aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Spörlein <uqs@FreeBSD.org>2014-01-31 19:59:03 +0000
committerUlrich Spörlein <uqs@FreeBSD.org>2014-01-31 19:59:03 +0000
commit3d011e300bd9608b1a158e0da873026a1a09517b (patch)
tree23b6a81a1df09aafea64657d4d56bc50e677df33
parent211d2d512b87f4d2be8961b75432e4f0d5206c9a (diff)
downloadsrc-3d011e300bd9608b1a158e0da873026a1a09517b.tar.gz
src-3d011e300bd9608b1a158e0da873026a1a09517b.zip
Import mdocml version 1.12.3
Notes
Notes: svn path=/vendor/mdocml/dist/; revision=261327
-rw-r--r--Makefile317
-rw-r--r--NEWS370
-rw-r--r--TODO184
-rw-r--r--apropos.155
-rw-r--r--apropos.c137
-rw-r--r--apropos_db.c22
-rw-r--r--arch.in5
-rw-r--r--catman.c10
-rw-r--r--cgi.c78
-rw-r--r--chars.c6
-rw-r--r--chars.in3
-rw-r--r--config.h.post18
-rw-r--r--demandoc.17
-rw-r--r--demandoc.c4
-rw-r--r--eqn.77
-rw-r--r--gmdiff35
-rw-r--r--html.c124
-rw-r--r--html.h4
-rw-r--r--index.sgml312
-rw-r--r--lib.in33
-rw-r--r--libman.h12
-rw-r--r--libmandoc.h22
-rw-r--r--libmdoc.h27
-rw-r--r--libroff.h4
-rw-r--r--main.c30
-rw-r--r--man.790
-rw-r--r--man.c268
-rw-r--r--man.cgi.75
-rw-r--r--man.h6
-rw-r--r--man_html.c90
-rw-r--r--man_macro.c179
-rw-r--r--man_term.c245
-rw-r--r--man_validate.c214
-rw-r--r--mandoc.122
-rw-r--r--mandoc.3100
-rw-r--r--mandoc.c363
-rw-r--r--mandoc.h37
-rw-r--r--mandoc_char.760
-rw-r--r--mandocdb.853
-rw-r--r--mandocdb.c383
-rw-r--r--mandocdb.h6
-rw-r--r--manpath.c22
-rw-r--r--manpath.h4
-rw-r--r--mdoc.7121
-rw-r--r--mdoc.c315
-rw-r--r--mdoc.h5
-rw-r--r--mdoc_argv.c129
-rw-r--r--mdoc_html.c73
-rw-r--r--mdoc_macro.c593
-rw-r--r--mdoc_man.c1373
-rw-r--r--mdoc_term.c314
-rw-r--r--mdoc_validate.c374
-rw-r--r--out.c42
-rw-r--r--preconv.17
-rw-r--r--preconv.c11
-rw-r--r--predefs.in4
-rw-r--r--read.c98
-rw-r--r--roff.7315
-rw-r--r--roff.c624
-rw-r--r--st.in24
-rw-r--r--tbl.3295
-rw-r--r--tbl.714
-rw-r--r--tbl.c40
-rw-r--r--tbl_data.c12
-rw-r--r--tbl_html.c20
-rw-r--r--tbl_layout.c154
-rw-r--r--tbl_term.c138
-rw-r--r--term.c211
-rw-r--r--term.h26
-rw-r--r--term_ascii.c5
-rw-r--r--test-betoh64.c18
-rw-r--r--test-mmap.c2
-rw-r--r--tree.c20
-rw-r--r--whatis.153
74 files changed, 6072 insertions, 3331 deletions
diff --git a/Makefile b/Makefile
index 304237b47827..20b9feaa022b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,19 +1,15 @@
.PHONY: clean install installwww
.SUFFIXES: .sgml .html .md5 .h .h.html
.SUFFIXES: .1 .3 .7 .8
-.SUFFIXES: .1.txt .3.txt .7.txt .8.txt
-.SUFFIXES: .1.pdf .3.pdf .7.pdf .8.pdf
-.SUFFIXES: .1.ps .3.ps .7.ps .8.ps
.SUFFIXES: .1.html .3.html .7.html .8.html
-.SUFFIXES: .1.xhtml .3.xhtml .7.xhtml .8.xhtml
# Specify this if you want to hard-code the operating system to appear
# in the lower-left hand corner of -mdoc manuals.
#
-# CFLAGS += -DOSNAME="\"OpenBSD 4.5\""
+# CFLAGS += -DOSNAME="\"OpenBSD 5.4\""
-VERSION = 1.12.1
-VDATE = 23 March 2012
+VERSION = 1.12.3
+VDATE = 31 December 2013
# IFF your system supports multi-byte functions (setlocale(), wcwidth(),
# putwchar()) AND has __STDC_ISO_10646__ (that is, wchar_t is simply a
@@ -29,12 +25,13 @@ CFLAGS += -DUSE_WCHAR
# variable.
#CFLAGS += -DUSE_MANPATH
-# If your system supports static binaries only, uncomment this. This
-# appears only to be BSD UNIX systems (Mac OS X has no support and Linux
-# requires -pthreads for static libdb).
+# If your system does not support static binaries, comment this,
+# for example on Mac OS X.
STATIC = -static
+# Linux requires -pthread to statically link with libdb.
+#STATIC += -pthread
-CFLAGS += -g -DHAVE_CONFIG_H -DVERSION="\"$(VERSION)\""
+CFLAGS += -g -DHAVE_CONFIG_H
CFLAGS += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings
PREFIX = /usr/local
WWWPREFIX = /var/www
@@ -64,6 +61,7 @@ DBLN = llib-lapropos.ln llib-lmandocdb.ln llib-lman.cgi.ln llib-lcatman.ln
all: mandoc preconv demandoc $(DBBIN)
SRCS = Makefile \
+ NEWS \
TODO \
apropos.1 \
apropos.c \
@@ -92,6 +90,7 @@ SRCS = Makefile \
eqn_term.c \
example.style.css \
external.png \
+ gmdiff \
html.c \
html.h \
index.css \
@@ -147,6 +146,7 @@ SRCS = Makefile \
st.c \
st.in \
style.css \
+ tbl.3 \
tbl.7 \
tbl.c \
tbl_data.c \
@@ -158,6 +158,7 @@ SRCS = Makefile \
term.h \
term_ascii.c \
term_ps.c \
+ test-betoh64.c \
test-fgetln.c \
test-getsubopt.c \
test-mmap.c \
@@ -173,10 +174,6 @@ LIBMAN_OBJS = man.o \
man_hash.o \
man_macro.o \
man_validate.o
-LIBMAN_LNS = man.ln \
- man_hash.ln \
- man_macro.ln \
- man_validate.ln
LIBMDOC_OBJS = arch.o \
att.o \
@@ -188,16 +185,6 @@ LIBMDOC_OBJS = arch.o \
mdoc_validate.o \
st.o \
vol.o
-LIBMDOC_LNS = arch.ln \
- att.ln \
- lib.ln \
- mdoc.ln \
- mdoc_argv.ln \
- mdoc_hash.ln \
- mdoc_macro.ln \
- mdoc_validate.ln \
- st.ln \
- vol.ln
LIBROFF_OBJS = eqn.o \
roff.o \
@@ -205,12 +192,6 @@ LIBROFF_OBJS = eqn.o \
tbl_data.o \
tbl_layout.o \
tbl_opts.o
-LIBROFF_LNS = eqn.ln \
- roff.ln \
- tbl.ln \
- tbl_data.ln \
- tbl_layout.ln \
- tbl_opts.ln
LIBMANDOC_OBJS = $(LIBMAN_OBJS) \
$(LIBMDOC_OBJS) \
@@ -219,52 +200,35 @@ LIBMANDOC_OBJS = $(LIBMAN_OBJS) \
mandoc.o \
msec.o \
read.o
-LIBMANDOC_LNS = $(LIBMAN_LNS) \
- $(LIBMDOC_LNS) \
- $(LIBROFF_LNS) \
- chars.ln \
- mandoc.ln \
- msec.ln \
- read.ln
COMPAT_OBJS = compat_fgetln.o \
compat_getsubopt.o \
compat_strlcat.o \
compat_strlcpy.o
-COMPAT_LNS = compat_fgetln.ln \
- compat_getsubopt.ln \
- compat_strlcat.ln \
- compat_strlcpy.ln
-
-arch.o arch.ln: arch.in
-att.o att.ln: att.in
-chars.o chars.ln: chars.in
-lib.o lib.ln: lib.in
-msec.o msec.ln: msec.in
-roff.o roff.ln: predefs.in
-st.o st.ln: st.in
-vol.o vol.ln: vol.in
-
-$(LIBMAN_OBJS) $(LIBMAN_LNS): libman.h
-$(LIBMDOC_OBJS) $(LIBMDOC_LNS): libmdoc.h
-$(LIBROFF_OBJS) $(LIBROFF_LNS): libroff.h
-$(LIBMANDOC_OBJS) $(LIBMANDOC_LNS): mandoc.h mdoc.h man.h libmandoc.h config.h
-
-$(COMPAT_OBJS) $(COMPAT_LNS): config.h
+
+arch.o: arch.in
+att.o: att.in
+chars.o: chars.in
+lib.o: lib.in
+msec.o: msec.in
+roff.o: predefs.in
+st.o: st.in
+vol.o: vol.in
+
+$(LIBMAN_OBJS): libman.h
+$(LIBMDOC_OBJS): libmdoc.h
+$(LIBROFF_OBJS): libroff.h
+$(LIBMANDOC_OBJS): mandoc.h mdoc.h man.h libmandoc.h config.h
+$(COMPAT_OBJS): config.h
MANDOC_HTML_OBJS = eqn_html.o \
html.o \
man_html.o \
mdoc_html.o \
tbl_html.o
-MANDOC_HTML_LNS = eqn_html.ln \
- html.ln \
- man_html.ln \
- mdoc_html.ln \
- tbl_html.ln
+$(MANDOC_HTML_OBJS): html.h
MANDOC_MAN_OBJS = mdoc_man.o
-MANDOC_MAN_LNS = mdoc_man.ln
MANDOC_TERM_OBJS = eqn_term.o \
man_term.o \
@@ -273,13 +237,7 @@ MANDOC_TERM_OBJS = eqn_term.o \
term_ascii.o \
term_ps.o \
tbl_term.o
-MANDOC_TERM_LNS = eqn_term.ln \
- man_term.ln \
- mdoc_term.ln \
- term.ln \
- term_ascii.ln \
- term_ps.ln \
- tbl_term.ln
+$(MANDOC_TERM_OBJS): term.h
MANDOC_OBJS = $(MANDOC_HTML_OBJS) \
$(MANDOC_MAN_OBJS) \
@@ -287,31 +245,16 @@ MANDOC_OBJS = $(MANDOC_HTML_OBJS) \
main.o \
out.o \
tree.o
-MANDOC_LNS = $(MANDOC_HTML_LNS) \
- $(MANDOC_MAN_LNS) \
- $(MANDOC_TERM_LNS) \
- main.ln \
- out.ln \
- tree.ln
-
-$(MANDOC_HTML_OBJS) $(MANDOC_HTML_LNS): html.h
-$(MANDOC_TERM_OBJS) $(MANDOC_TERM_LNS): term.h
-$(MANDOC_OBJS) $(MANDOC_LNS): main.h mandoc.h mdoc.h man.h config.h out.h
+$(MANDOC_OBJS): main.h mandoc.h mdoc.h man.h config.h out.h
MANDOCDB_OBJS = mandocdb.o manpath.o
-MANDOCDB_LNS = mandocdb.ln manpath.ln
-
-$(MANDOCDB_OBJS) $(MANDOCDB_LNS): mandocdb.h mandoc.h mdoc.h man.h config.h manpath.h
+$(MANDOCDB_OBJS): mandocdb.h mandoc.h mdoc.h man.h config.h manpath.h
PRECONV_OBJS = preconv.o
-PRECONV_LNS = preconv.ln
-
-$(PRECONV_OBJS) $(PRECONV_LNS): config.h
+$(PRECONV_OBJS): config.h
APROPOS_OBJS = apropos.o apropos_db.o manpath.o
-APROPOS_LNS = apropos.ln apropos_db.ln manpath.ln
-
-$(APROPOS_OBJS) $(APROPOS_LNS): config.h mandoc.h apropos_db.h manpath.h mandocdb.h
+$(APROPOS_OBJS): config.h mandoc.h apropos_db.h manpath.h mandocdb.h
CGI_OBJS = $(MANDOC_HTML_OBJS) \
$(MANDOC_MAN_OBJS) \
@@ -321,103 +264,30 @@ CGI_OBJS = $(MANDOC_HTML_OBJS) \
manpath.o \
out.o \
tree.o
-
-CGI_LNS = $(MANDOC_HTML_LNS) \
- $(MANDOC_MAN_LNS) \
- $(MANDOC_TERM_LNS) \
- cgi.ln \
- apropos_db.ln \
- manpath.ln \
- out.ln \
- tree.ln
-
-$(CGI_OBJS) $(CGI_LNS): main.h mdoc.h man.h out.h config.h mandoc.h apropos_db.h manpath.h mandocdb.h
+$(CGI_OBJS): main.h mdoc.h man.h out.h config.h mandoc.h apropos_db.h manpath.h mandocdb.h
CATMAN_OBJS = catman.o manpath.o
-CATMAN_LNS = catman.ln manpath.ln
-
-$(CATMAN_OBJS) $(CATMAN_LNS): config.h mandoc.h manpath.h mandocdb.h
+$(CATMAN_OBJS): config.h mandoc.h manpath.h mandocdb.h
DEMANDOC_OBJS = demandoc.o
-DEMANDOC_LNS = demandoc.ln
-
-$(DEMANDOC_OBJS) $(DEMANDOC_LNS): config.h
+$(DEMANDOC_OBJS): config.h
INDEX_MANS = apropos.1.html \
- apropos.1.xhtml \
- apropos.1.ps \
- apropos.1.pdf \
- apropos.1.txt \
catman.8.html \
- catman.8.xhtml \
- catman.8.ps \
- catman.8.pdf \
- catman.8.txt \
demandoc.1.html \
- demandoc.1.xhtml \
- demandoc.1.ps \
- demandoc.1.pdf \
- demandoc.1.txt \
mandoc.1.html \
- mandoc.1.xhtml \
- mandoc.1.ps \
- mandoc.1.pdf \
- mandoc.1.txt \
whatis.1.html \
- whatis.1.xhtml \
- whatis.1.ps \
- whatis.1.pdf \
- whatis.1.txt \
mandoc.3.html \
- mandoc.3.xhtml \
- mandoc.3.ps \
- mandoc.3.pdf \
- mandoc.3.txt \
+ tbl.3.html \
eqn.7.html \
- eqn.7.xhtml \
- eqn.7.ps \
- eqn.7.pdf \
- eqn.7.txt \
man.7.html \
- man.7.xhtml \
- man.7.ps \
- man.7.pdf \
- man.7.txt \
man.cgi.7.html \
- man.cgi.7.xhtml \
- man.cgi.7.ps \
- man.cgi.7.pdf \
- man.cgi.7.txt \
mandoc_char.7.html \
- mandoc_char.7.xhtml \
- mandoc_char.7.ps \
- mandoc_char.7.pdf \
- mandoc_char.7.txt \
mdoc.7.html \
- mdoc.7.xhtml \
- mdoc.7.ps \
- mdoc.7.pdf \
- mdoc.7.txt \
preconv.1.html \
- preconv.1.xhtml \
- preconv.1.ps \
- preconv.1.pdf \
- preconv.1.txt \
roff.7.html \
- roff.7.xhtml \
- roff.7.ps \
- roff.7.pdf \
- roff.7.txt \
tbl.7.html \
- tbl.7.xhtml \
- tbl.7.ps \
- tbl.7.pdf \
- tbl.7.txt \
- mandocdb.8.html \
- mandocdb.8.xhtml \
- mandocdb.8.ps \
- mandocdb.8.pdf \
- mandocdb.8.txt
+ mandocdb.8.html
$(INDEX_MANS): mandoc
@@ -430,38 +300,19 @@ INDEX_OBJS = $(INDEX_MANS) \
www: index.html
-lint: llib-lmandoc.ln llib-lpreconv.ln llib-ldemandoc.ln $(DBLN)
-
clean:
rm -f libmandoc.a $(LIBMANDOC_OBJS)
- rm -f llib-llibmandoc.ln $(LIBMANDOC_LNS)
rm -f mandocdb $(MANDOCDB_OBJS)
- rm -f llib-lmandocdb.ln $(MANDOCDB_LNS)
rm -f preconv $(PRECONV_OBJS)
- rm -f llib-lpreconv.ln $(PRECONV_LNS)
rm -f apropos whatis $(APROPOS_OBJS)
- rm -f llib-lapropos.ln $(APROPOS_LNS)
rm -f man.cgi $(CGI_OBJS)
- rm -f llib-lman.cgi.ln $(CGI_LNS)
rm -f catman $(CATMAN_OBJS)
- rm -f llib-lcatman.ln $(CATMAN_LNS)
rm -f demandoc $(DEMANDOC_OBJS)
- rm -f llib-ldemandoc.ln $(DEMANDOC_LNS)
rm -f mandoc $(MANDOC_OBJS)
- rm -f llib-lmandoc.ln $(MANDOC_LNS)
- rm -f config.h config.log $(COMPAT_OBJS) $(COMPAT_LNS)
- rm -f mdocml.tar.gz mdocml-win32.zip mdocml-win64.zip mdocml-macosx.zip
+ rm -f config.h config.log $(COMPAT_OBJS)
+ rm -f mdocml.tar.gz
rm -f index.html $(INDEX_OBJS)
- rm -rf test-fgetln.dSYM
- rm -rf test-strlcpy.dSYM
- rm -rf test-strlcat.dSYM
- rm -rf test-strptime.dSYM
- rm -rf test-mmap.dSYM
- rm -rf test-getsubopt.dSYM
- rm -rf apropos.dSYM
- rm -rf catman.dSYM
- rm -rf mandocdb.dSYM
- rm -rf whatis.dSYM
+ rm -rf *.dSYM
install: all
mkdir -p $(DESTDIR)$(BINDIR)
@@ -475,7 +326,7 @@ install: all
$(INSTALL_LIB) libmandoc.a $(DESTDIR)$(LIBDIR)
$(INSTALL_LIB) man.h mdoc.h mandoc.h $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_MAN) mandoc.1 preconv.1 demandoc.1 $(DESTDIR)$(MANDIR)/man1
- $(INSTALL_MAN) mandoc.3 $(DESTDIR)$(MANDIR)/man3
+ $(INSTALL_MAN) mandoc.3 tbl.3 $(DESTDIR)$(MANDIR)/man3
$(INSTALL_MAN) man.7 mdoc.7 roff.7 eqn.7 tbl.7 mandoc_char.7 $(DESTDIR)$(MANDIR)/man7
$(INSTALL_DATA) example.style.css $(DESTDIR)$(EXAMPLEDIR)
@@ -500,54 +351,30 @@ installwww: www
libmandoc.a: $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
$(AR) rs $@ $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
-llib-llibmandoc.ln: $(COMPAT_LNS) $(LIBMANDOC_LNS)
- $(LINT) $(LINTFLAGS) -Clibmandoc $(COMPAT_LNS) $(LIBMANDOC_LNS)
-
mandoc: $(MANDOC_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(MANDOC_OBJS) libmandoc.a
-llib-lmandoc.ln: $(MANDOC_LNS) llib-llibmandoc.ln
- $(LINT) $(LINTFLAGS) -Cmandoc $(MANDOC_LNS) llib-llibmandoc.ln
-
mandocdb: $(MANDOCDB_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(MANDOCDB_OBJS) libmandoc.a $(DBLIB)
-llib-lmandocdb.ln: $(MANDOCDB_LNS) llib-llibmandoc.ln
- $(LINT) $(LINTFLAGS) -Cmandocdb $(MANDOCDB_LNS) llib-llibmandoc.ln
-
preconv: $(PRECONV_OBJS)
$(CC) $(LDFLAGS) -o $@ $(PRECONV_OBJS)
-llib-lpreconv.ln: $(PRECONV_LNS) llib-llibmandoc.ln
- $(LINT) $(LINTFLAGS) -Cpreconv $(PRECONV_LNS) llib-llibmandoc.ln
-
whatis: apropos
cp -f apropos whatis
apropos: $(APROPOS_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(APROPOS_OBJS) libmandoc.a $(DBLIB)
-llib-lapropos.ln: $(APROPOS_LNS) llib-llibmandoc.ln
- $(LINT) $(LINTFLAGS) -Capropos $(APROPOS_LNS) llib-llibmandoc.ln
-
catman: $(CATMAN_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(CATMAN_OBJS) libmandoc.a $(DBLIB)
-llib-lcatman.ln: $(CATMAN_LNS) llib-llibmandoc.ln
- $(LINT) $(LINTFLAGS) -Ccatman $(CATMAN_LNS) llib-llibmandoc.ln
-
man.cgi: $(CGI_OBJS) libmandoc.a
$(CC) $(LDFLAGS) $(STATIC) -o $@ $(CGI_OBJS) libmandoc.a $(DBLIB)
-llib-lman.cgi.ln: $(CGI_LNS) llib-llibmandoc.ln
- $(LINT) $(LINTFLAGS) -Cman.cgi $(CGI_LNS) llib-llibmandoc.ln
-
demandoc: $(DEMANDOC_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(DEMANDOC_OBJS) libmandoc.a
-llib-ldemandoc.ln: $(DEMANDOC_LNS) llib-llibmandoc.ln
- $(LINT) $(LINTFLAGS) -Cdemandoc $(DEMANDOC_LNS) llib-llibmandoc.ln
-
mdocml.md5: mdocml.tar.gz
md5 mdocml.tar.gz >$@
@@ -557,67 +384,41 @@ mdocml.tar.gz: $(SRCS)
( cd .dist/ && tar zcf ../$@ ./ )
rm -rf .dist/
-mdocml-win32.zip: $(SRCS)
- mkdir -p .win32/mdocml-$(VERSION)/
- $(INSTALL_SOURCE) $(SRCS) .win32
- cp .win32/Makefile .win32/Makefile.old
- egrep -v -e DUSE_WCHAR -e ^DBBIN .win32/Makefile.old >.win32/Makefile
- ( cd .win32; \
- CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar CFLAGS='-DOSNAME=\"Windows\"' make; \
- make install PREFIX=mdocml-$(VERSION) ; \
- zip -r ../$@ mdocml-$(VERSION) )
- rm -rf .win32
-
-mdocml-win64.zip: $(SRCS)
- mkdir -p .win64/mdocml-$(VERSION)/
- $(INSTALL_SOURCE) $(SRCS) .win64
- cp .win64/Makefile .win64/Makefile.old
- egrep -v -e DUSE_WCHAR -e ^DBBIN .win64/Makefile.old >.win64/Makefile
- ( cd .win64; \
- CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-ar CFLAGS='-DOSNAME=\"Windows\"' make; \
- make install PREFIX=mdocml-$(VERSION) ; \
- zip -r ../$@ mdocml-$(VERSION) )
- rm -rf .win64
-
-mdocml-macosx.zip: $(SRCS)
- mkdir -p .macosx/mdocml-$(VERSION)/
- $(INSTALL_SOURCE) $(SRCS) .macosx
- ( cd .macosx; \
- CFLAGS="-arch i386 -arch x86_64 -arch ppc" LDFLAGS="-arch i386 -arch x86_64 -arch ppc" make; \
- make install PREFIX=mdocml-$(VERSION) ; \
- zip -r ../$@ mdocml-$(VERSION) )
- rm -rf .macosx
-
index.html: $(INDEX_OBJS)
config.h: config.h.pre config.h.post
rm -f config.log
( cat config.h.pre; \
echo; \
- if $(CC) $(CFLAGS) -Werror -o test-fgetln test-fgetln.c >> config.log 2>&1; then \
+ echo '#define VERSION "$(VERSION)"'; \
+ if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-fgetln test-fgetln.c >> config.log 2>&1; then \
echo '#define HAVE_FGETLN'; \
rm test-fgetln; \
fi; \
- if $(CC) $(CFLAGS) -Werror -o test-strptime test-strptime.c >> config.log 2>&1; then \
+ if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strptime test-strptime.c >> config.log 2>&1; then \
echo '#define HAVE_STRPTIME'; \
rm test-strptime; \
fi; \
- if $(CC) $(CFLAGS) -Werror -o test-getsubopt test-getsubopt.c >> config.log 2>&1; then \
+ if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-getsubopt test-getsubopt.c >> config.log 2>&1; then \
echo '#define HAVE_GETSUBOPT'; \
rm test-getsubopt; \
fi; \
- if $(CC) $(CFLAGS) -Werror -o test-strlcat test-strlcat.c >> config.log 2>&1; then \
+ if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strlcat test-strlcat.c >> config.log 2>&1; then \
echo '#define HAVE_STRLCAT'; \
rm test-strlcat; \
fi; \
- if $(CC) $(CFLAGS) -Werror -o test-mmap test-mmap.c >> config.log 2>&1; then \
+ if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-mmap test-mmap.c >> config.log 2>&1; then \
echo '#define HAVE_MMAP'; \
rm test-mmap; \
fi; \
- if $(CC) $(CFLAGS) -Werror -o test-strlcpy test-strlcpy.c >> config.log 2>&1; then \
+ if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strlcpy test-strlcpy.c >> config.log 2>&1; then \
echo '#define HAVE_STRLCPY'; \
rm test-strlcpy; \
fi; \
+ if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-betoh64 test-betoh64.c >> config.log 2>&1; then \
+ echo '#define HAVE_BETOH64'; \
+ rm test-betoh64; \
+ fi; \
echo; \
cat config.h.post \
) > $@
@@ -625,21 +426,9 @@ config.h: config.h.pre config.h.post
.h.h.html:
highlight -I $< >$@
-.1.1.txt .3.3.txt .7.7.txt .8.8.txt:
- ./mandoc -Tascii -Wall,stop $< | col -b >$@
-
.1.1.html .3.3.html .7.7.html .8.8.html:
./mandoc -Thtml -Wall,stop -Ostyle=style.css,man=%N.%S.html,includes=%I.html $< >$@
-.1.1.ps .3.3.ps .7.7.ps .8.8.ps:
- ./mandoc -Tps -Wall,stop $< >$@
-
-.1.1.xhtml .3.3.xhtml .7.7.xhtml .8.8.xhtml:
- ./mandoc -Txhtml -Wall,stop -Ostyle=style.css,man=%N.%S.xhtml,includes=%I.html $< >$@
-
-.1.1.pdf .3.3.pdf .7.7.pdf .8.8.pdf:
- ./mandoc -Tpdf -Wall,stop $< >$@
-
.sgml.html:
validate --warn $<
sed -e "s!@VERSION@!$(VERSION)!" -e "s!@VDATE@!$(VDATE)!" $< >$@
diff --git a/NEWS b/NEWS
new file mode 100644
index 000000000000..6f21a38dea3c
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,370 @@
+$Id: NEWS,v 1.3 2013/10/13 16:06:50 schwarze Exp $
+
+This file lists the most important changes in the mdocml.bsd.lv distribution.
+
+Changes in version 1.12.3, released on December 31, 2013
+
+ * In the mdoc(7) SYNOPSIS, line breaks and hanging indentation
+ now work correctly for .Fo/.Fa/.Fc and .Fn blocks.
+ Thanks to Franco Fichtner for doing part of the work.
+ * The mdoc(7) .Bk macro got some addititonal bugfixes.
+ * In mdoc(7) macro arguments, double quotes can now be quoted
+ by doubling them, just like in man(7).
+ Thanks to Tsugutomo ENAMI for the patch.
+ * At the end of man(7) macro lines, end-of-sentence spacing
+ now works. Thanks to Franco Fichtner for the patch.
+ * For backward compatibility, the man(7) parser now supports the
+ man-ext .UR/.UE (uniform resource identifier) block macros.
+ * The man(7) parser now handles closing blocks that are not open
+ more gracefully.
+ * The man(7) parser now ignores blank lines right after .SH and .SS.
+ * In the man(7) formatter, reset indentation when leaving a block,
+ not just when entering the next one.
+ * The roff(7) .nr request now supports incrementing and decrementing
+ number registers and stops parsing the number right before the
+ first non-digit character.
+ * The roff(7) parser now supports the alternative escape sequence
+ syntax \C'uXXXX' for Unicode characters.
+ * The roff(7) parser now parses and ignores the .fam (font family)
+ and .hw (hyphenation points) requests and the \d and \u escape
+ sequences.
+ * The roff(7) manual got a new ESCAPE SEQUENCE REFERENCE.
+
+Changes in version 1.12.2, released on Oktober 5, 2013
+
+ * The mdoc(7) to man(7) converter, to be called as mandoc -Tman,
+ is now fully functional.
+ * The mandoc(1) utility now supports the -Ios (default operating system)
+ input option, and the -Tutf8 output mode now actually works.
+ * The mandocdb(8) utility no longer truncates existing databases when
+ starting to build new ones, but only replaces them when the build
+ actually succeeds.
+ * The man(7) parser now supports the PD macro (paragraph distance),
+ and (for GNU man-ext compatibility only) EX (example block) and EE
+ (example end). Plus several bugfixes regarding indentation, line
+ breaks, and vertical spacing, and regarding RS following TP.
+ * The roff(7) parser now supports the \f(BI (bold+italic) font escape,
+ the \z (zero cursor advance) escape and the cc (change control
+ character) and it (input line trap) requests. Plus bugfixes regarding
+ the \t (tab) escape, nested escape sequences, and conditional requests.
+ * In mdoc(7), several bugs were fixed related to UTF-8 output of quoting
+ enclosures, delimiter handling, list indentation and horizontal and
+ vertical spacing, formatting of the Lk, %U, and %C macros, plus some
+ bugfixes related to the handling of syntax errors like badly nested
+ font blocks, stray Ta macros outside column lists, unterminated It Xo
+ blocks, and non-text children of Nm blocks.
+ * In tbl(7), the width of horizontal spans and the vertical spacing
+ around tables was corrected, and in man(7) files, a crash was fixed
+ that was triggered by some particular unclosed T{ macros.
+ * For mandoc developers, we now provide a tbl(3) library manual and
+ gmdiff, a very small, very simplistic groff-versus-mandoc output
+ comparison tool.
+ * Provide this NEWS file.
+
+Changes in version 1.12.1, released on March 23, 2012
+
+ * Significant work on apropos(1) and mandocdb(8). These tools are now
+ much more robust. A whatis(1) implementation is now handled as an
+ apropos(1) mode. These tools are also able to minimally handle
+ pre-formatted pages, that is, those already formatted by another
+ utility such as GNU troff.
+ * The man.cgi(7) script is also now available for wider testing.
+ It interfaces with mandocdb(8) manuals cached by catman(8).
+ HTML output is generated on-the-fly by libmandoc or internal
+ methods to convert pre-formatted pages.
+ * The mailing list archive for the discuss and tech lists are being
+ hosted by Gmane at gmane.comp.tools.mdocml.user and
+ gmane.comp.tools.mdocml.devel, respectively.
+
+Changes in version 1.12.0, released on October 8, 2011
+
+ * This version features a new, work-in-progress mandoc(1) output mode:
+ -Tman. This mode allows a system maintainer to distribute man(7)
+ media for older systems that may not natively support mdoc(7), such
+ as old Solaris systems.
+ * The -Ofragment option was added to mandoc(1)'s -Thtml and -Txhtml modes.
+ * While adding features, an apropos(1) utility has been merged from the
+ mandoc-tools sandbox. This interfaces with mandocdb(8) for semantic
+ search of manual content. apropos(1) is different from the traditional
+ apropos primarily in allowing keyword search (such as for functions,
+ utilities, etc.) and regular expressions. Note that the calling
+ syntax for apropos is likely to change as it settles down.
+ * In documentation news, the mdoc(7) and man(7) manuals have been
+ made considerably more readable by adding MACRO OVERVIEW sections, by
+ moving the gory details of the LANGUAGE SYNTAX to the roff(7) manual,
+ and by moving the very technical MACRO SYNTAX sections down to the
+ bottom of the page.
+ * Furthermore, for tbl(7), the -Tascii mode horizontal spacing of tables
+ was rewritten completely. It is now compatible with groff(1), both
+ with and without frames and rulers.
+ * Nesting of indented blocks is now supported in man(7), and several
+ bugs were fixed regarding indentation and alignment.
+ * The page headers in mdoc(7) are now nicer for very long titles.
+
+Changes in version 1.11.7, released on September 2, 2011
+
+ * Added demandoc(1) utility for stripping away macros and escapes.
+ This replaces the historical deroff(1) utility.
+ * Also improved the mdoc(7) and man(7) manuals.
+
+Changes in version 1.11.6, released on August 16, 2011
+
+ * Handling of tr macro in roff(7) implemented. This makes Perl
+ documentation much more readable. Hyphenation is also now enabled in
+ man(7) format documents. Many other general improvements have been
+ implemented.
+
+Changes in version 1.11.5, released on July 24, 2011
+
+ * Significant eqn(7) improvements. mdocml can now parse arbitrary eqn
+ input (although few GNU extensions are accepted, nor is mixing
+ low-level roff with eqn). See the eqn(7) manual for details.
+ For the time being, equations are rendered as simple in-line text.
+ The equation parser satisfies the language specified in the
+ Second Edition User's Guide:
+ http://www.kohala.com/start/troff/v7man/eqn/eqn2e.ps
+
+Changes in version 1.11.4, released on July 12, 2011
+
+ * Bug-fixes and clean-ups across all systems, especially in mandocdb(8)
+ and the man(7) parser. This release was significantly assisted by
+ participants in OpenBSD's c2k11. Thanks!
+
+Changes in version 1.11.3, released on May 26, 2011
+
+ * Introduce locale-encoding of output with the -Tlocale output option and
+ Unicode escaped-character input. See mandoc(1) and mandoc_char(7),
+ respectively, for details. This allows for non-ASCII characters (e.g.,
+ \[u5000]) to be rendered in the locale's encoding, if said environment
+ supports wide-character encoding (if it does not, -Tascii is used
+ instead). Locale support can be turned off at compile time by removing
+ -DUSE_WCHAR in the Makefile, in which case -Tlocale is always a synonym
+ for -Tascii.
+ * Furthermore, multibyte-encoded documents, such as those in UTF-8, may
+ be on-the-fly recoded into mandoc(1) input by using the newly-added
+ preconv(1) utility. Note: in the future, this feature may be
+ integrated into mandoc(1).
+
+Changes in version 1.11.2, released on May 12, 2011
+
+ * Corrected some installation issues in version 1.11.1.
+ * Further migration to libmandoc.
+ * Initial public release (this utility is very much under development)
+ of mandocdb(8). This utility produces keyword databases of manual
+ content, which features semantic querying of manual content.
+
+Changes in version 1.11.1, released on April 4, 2011
+
+ * The earlier libroff, libmdoc, and libman soup have been merged into
+ a single library, libmandoc, which manages all aspects of parsing
+ real manuals, from line-handling to tbl(7) parsing.
+ * As usual, many general fixes and improvements have also occurred.
+ In particular, a great deal of redundancy and superfluous code has
+ been removed with the merging of the backend libraries.
+ * see also the changes in 1.10.10
+
+Changes in version 1.10.10, March 20, 2011, NOT released
+
+ * Initial eqn(7) functionality is in place. For the time being,
+ this is limited to the recognition of equation blocks;
+ future version of mdocml will expand upon this framework.
+
+Changes in version 1.10.9, released on January 7, 2011
+
+ * Many back-end fixes have been implemented: argument handling (quoting),
+ man(7) improvements, error/warning classes, and many more.
+ * Initial tbl(7) functionality (see the "TS", "TE", and "T&" macros in
+ the roff(7) manual) has been merged from tbl.bsd.lv. Output is still
+ minimal, especially for -Thtml and -Txhtml, but manages to at least
+ display data. This means that mandoc(1) now has built-in support
+ for two troff preprocessors via libroff: soelim(1) and tbl(1).
+
+Changes in version 1.10.8, released on December 24, 2010
+
+ * Overhauled the -Thtml and -Txhtml output modes. They now display
+ readable output in arbitrary browsers, including text-based ones like
+ lynx(1). See HTML and XHTML manuals in the DOCUMENTATION section
+ for examples. Attention: available style-sheet classes have been
+ considerably changed! See the example.style.css file for details.
+ Lastly, libmdoc and libman have been cleaned up and reduced in size
+ and complexity.
+ * see also the changes in 1.10.7
+
+Changes in version 1.10.7, December 6, 2010, NOT released
+
+ Significant improvements merged from OpenBSD downstream, including:
+ * many new roff(7) components,
+ * in-line implementation of troff's soelim(1),
+ * broken-block handling,
+ * overhauled error classifications, and
+ * cleaned up handling of error conditions.
+
+Changes in version 1.10.6, released on September 27, 2010
+
+ * Calling conventions for mandoc(1) have changed: -W improved and -f
+ deprecated.
+ * Non-ASCII characters are also now uniformly discarded.
+ * Lots of documentation improvements.
+ * Many incremental fixes accomodating for groff's more interesting
+ productions.
+ * Lastly, pod2man(1) preambles are now fully accepted after some
+ considerable roff(7) and special character support.
+
+Changes in version 1.10.5, released on July 27, 2010
+
+ * Primarily a bug-fix and polish release, but including -Tpdf support
+ in mandoc(1) by way of "Summer of Code". Highlights:
+ * fix "Sm" and "Bd" handling
+ * fix end-of-sentence handling for embedded sentences
+ * polish man(7) documentation
+ * document all mdoc(7) macros
+ * polish mandoc(1) -Tps output
+ * lots of internal clean-ups in character escapes
+ * un-break literal contexts in man(7) documents
+ * improve -Thtml output for -man
+ * add mandoc(1) -Tpdf support
+
+Changes in version 1.10.4, released on July 12, 2010
+
+ * Lots of features developed during both "Summer of Code" and the
+ OpenBSD c2k10 hackathon:
+ * minimal "ds" roff(7) symbols are supported
+ * beautified SYNOPSIS section output
+ * acceptance of scope-block breakage in mdoc(7)
+ * clarify error message status
+ * many minor bug-fixes and formatting issues resolved
+ * see also changes in 1.10.3
+
+Changes in version 1.10.3, June 29, 2010, NOT released
+
+ * variable font-width and paper-size support in mandoc(1) -Tps output
+ * "Bk" mdoc(7) support
+
+Changes in version 1.10.2, released on June 19, 2010
+
+ * Small release featuring text-decoration in -Tps output,
+ a few minor relaxations of errors, and some optimisations.
+
+Changes in version 1.10.1, released on June 7, 2010
+
+ * This primarily focusses on the "Bl" and "It" macros described in
+ mdoc(7). Multi-line column support is now fully compatible with groff,
+ as are implicit list entries for columns.
+ * Removed manuals(7) in favour of http://manpages.bsd.lv.
+ * The way we handle the SYNOPSIS section (see the SYNOPSIS documentation
+ in MANUAL STRUCTURE) has also been considerably simplified compared
+ to groff's method.
+ * Furthermore, the -Owidth=width output option has been added to -Tascii,
+ see mandoc(1).
+ * Lastly, initial PostScript output has been added with the -Tps option
+ to mandoc(1). It's brutally simple at the moment: fixed-font, with no
+ font decorations.
+
+Changes in version 1.10.0, released on May 29, 2010
+
+ * Release consisting of the results from the m2k10 hackathon and up-merge
+ from OpenBSD. This requires a significant note of thanks to Ingo
+ Schwarze (OpenBSD) and Joerg Sonnenberger (NetBSD) for their hard work,
+ and again to Joerg for hosting m2k10. Highlights (mostly cribbed from
+ Ingo's m2k10 report) follow in no particular order:
+ * a libroff preprocessor in front of libmdoc and libman stripping out
+ roff(7) instructions;
+ * end-of-sentence (EOS) detection in free-form and macro lines;
+ * correct handling of tab-separated columnar lists in mdoc(7);
+ * improved main calling routines to optionally use mmap(3) for better
+ performance;
+ * cleaned up exiting when invoked as -Tlint or over multiple files
+ with -fign-errors;
+ * error and warning message handling re-written to be unified for
+ libroff, libmdoc, and libman;
+ * handling of badly-nested explicit-scoped macros;
+ * improved free-form text parsing in libman and libmdoc;
+ * significant GNU troff compatibility improvements in -Tascii,
+ largely in terms of spacing;
+ * a regression framework for making sure the many fragilities of GNU
+ troff aren't trampled in subsequent work;
+ * support for -Tascii breaking at hyphens encountered in free-form text;
+ * and many more minor fixes and improvements
+
+Changes in version 1.9.25, released on May 13, 2010
+
+ * Fixed handling of "\*(Ba" escape.
+ * Backed out -fno-ign-chars (pointless complexity).
+ * Fixed erroneous breaking of literal lines.
+ * Fixed SYNOPSIS breaking lines before non-initial macros.
+ * Changed default section ordering.
+ * Most importantly, the framework for end-of-sentence double-spacing is
+ in place, now implemented for the "end-of-sentence, end-of-line" rule.
+ * This is a stable roll-back point before the mandoc hackathon in Rostock!
+
+Changes in version 1.9.24, released on May 9, 2010
+
+ * Rolled back break-at-hyphen.
+ * -DUGLY is now the default (no feature splits!).
+ * Free-form text is not de-chunked any more: lines are passed
+ whole-sale into the front-end, including whitespace.
+ * Added mailing lists.
+
+Changes in version 1.9.23, released on April 7, 2010
+
+ * mdocml has been linked to the OpenBSD build.
+ * This version incorporates many small changes, mostly from patches
+ by OpenBSD, allowing crufty manuals to slip by with warnings instead
+ of erroring-out.
+ * Some subtle semantic issues, such as punctuation scope, have also
+ been fixed.
+ * Lastly, some issues with -Thtml have been fixed, which prompted an
+ update to the online manual pages style layout.
+
+Changes in version 1.9.22, released on March 31, 2010
+
+ * Adjusted merge of the significant work by Ingo Schwarze
+ in getting "Xo" blocks (block full implicit, e.g., "It"
+ for non-columnar lists) to work properly. This isn't
+ enabled by default: you must specify -DUGLY as a compiler
+ flag (see the Makefile for details).
+
+Changes in version 1.9.20, released on March 30, 2010
+
+ * More efforts to get roff instructions in man(7) documents under
+ control. Note that roff instructions embedded in line-scoped,
+ next-line macros (e.g. "B") are not supported.
+ * Leading punctuation for mdoc(7) macros, such as "Fl ( ( a",
+ are now correctly handled.
+
+Changes in version 1.9.18, released on March 27, 2010
+
+ * Many fixes (largely pertaining to scope)
+ and improvements (e.g., handling of apostrophe-control macros,
+ which fixes the strange "BR" seen in some macro output)
+ to handling roff instructions in man(7) documents.
+
+Changes in version 1.9.17, released on March 25, 2010
+
+ * Accept perlpod(1) standard preamble.
+ * Also accept (and discard) "de", "dei", "am", "ami", and "ig"
+ roff macro blocks.
+
+Changes in version 1.9.16, released on March 22, 2010
+
+ * Inspired by patches and bug reports by Ingo Schwarze,
+ allowed man(7) to accept non-printing elements to be nested
+ within next-line scopes, such as "br" within "B" or "TH",
+ which is valid roff.
+ * Longsoon architecture also noted and Makefile cleaned up.
+
+Changes in version 1.9.15, released on February 18, 2010
+
+ * Moved to our new BSD.lv home.
+ * XHTML is now an acceptable output mode for mandoc(1);
+ * "Xr" made more compatible with groff;
+ * "Vt" fixed when invoked in SYNOPSIS;
+ * "\\" escape removed;
+ * end-of-line white-space detected for all lines;
+ * subtle bug fixed in list display for some modes;
+ * compatibility layer checked in for compilation in diverse
+ UNIX systems;
+ * and column lengths handled correctly.
+
+For older releases, see the ChangeLog files
+in http://mdocml.bsd.lv/snapshots/ .
diff --git a/TODO b/TODO
index a8701361290c..26f42c23b417 100644
--- a/TODO
+++ b/TODO
@@ -1,25 +1,13 @@
************************************************************************
* Official mandoc TODO.
-* $Id: TODO,v 1.129 2012/03/04 23:53:37 schwarze Exp $
+* $Id: TODO,v 1.162 2013/12/25 14:40:34 schwarze Exp $
************************************************************************
************************************************************************
-* parser bugs
+* crashes
************************************************************************
-- ".\}" on its own line gets translated to bare ".\&"
- which forces pset() into man(7)
- and then triggers an unknown macro error
- reported by naddy@ Sun, 3 Jul 2011 21:52:24 +0200
-
-************************************************************************
-* formatter bugs
-************************************************************************
-
-- tbl(7): Horizontal and vertical lines are formatted badly:
- With the box option, there is too much white space at the end of cells.
- Horizontal lines from "=" lines are a bit too long.
- yuri dot pankov at gmail dot com Thu, 14 Apr 2011 05:45:26 +0400
+None known.
************************************************************************
* missing features
@@ -27,15 +15,11 @@
--- missing roff features ----------------------------------------------
-- The pod2man preamble wants \h'...' with quoted numerical arguments,
- see for example AUTHORS in MooseX::Getopt.3p, p5-MooseX-Getopt.
+- roff.c should treat \n(.H>23 and \n(.V>19 in the pod2man(1)
+ preamble as true, see for example AUTHORS in MooseX::Getopt.3p
reported by Andreas Voegele <mail at andreasvoegele dot com>
Tue, 22 Nov 2011 15:34:47 +0100 on ports@
-- .if n \{
- .br\}
- should cause an extra space to be raised.
-
- .ad (adjust margins)
.ad l -- adjust left margin only (flush left)
.ad r -- adjust right margin only (flush right)
@@ -45,19 +29,46 @@
.ad -- re-enable adjustment without changing the mode
Adjustment mode is ignored while in no-fill mode (.nf).
-- .it (line traps) occur in mysql(1), yasm_arch(7)
- generated by DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
- reported by brad@ Sat, 15 Jan 2011 15:48:18 -0500
+- .as (append to string)
+ found by jca@ in ratpoison(1) Sun, 30 Jun 2013 12:01:09 +0200
+
+- .ce (center N lines)
+ found by naddy@ in xloadimage(1)
+ found by Juan Francisco Cantero Hurtado <iam at juanfra dot info>
+ in lang/racket(1) Thu, 20 Jun 2013 03:19:11 +0200
+
+- .fc (field control)
+ found by naddy@ in xloadimage(1)
+
+- .ll (line length)
+ found by naddy@ in textproc/enchant(1) Sat, 12 Oct 2013 03:27:10 +0200
+
+- .nr third argument (auto-increment step size, requires \n+)
+ found by bentley@ in sbcl(1) Mon, 9 Dec 2013 18:36:57 -0700
- .ns (no-space mode) occurs in xine-config(1)
reported by brad@ Sat, 15 Jan 2011 15:45:23 -0500
-- xloadimage(1) wants .ti (temporary indent), rep by naddy@
-
- .ta (tab settings) occurs in ircbug(1) and probably gnats(1)
reported by brad@ Sat, 15 Jan 2011 15:50:51 -0500
-- \c (interrupted text) occurs in chat(8)
+- .ti (temporary indent)
+ found by naddy@ in xloadimage(1)
+ found by bentley@ in nmh(1) Mon, 23 Apr 2012 13:38:28 -0600
+
+- .while and .shift
+ found by jca@ in ratpoison(1) Sun, 30 Jun 2013 12:01:09 +0200
+
+- \c (interrupted text) should prevent the line break
+ even inside .Bd literal; that occurs in chat(8)
+ also found in cclive(1) - DocBook output
+
+- \h horizontal move
+ found in cclive(1) DocBook output
+ Anthony J. Bentley on discuss@ Sat, 21 Sep 2013 22:29:34 -0600
+
+- \n+ and \n- numerical register increment and decrement
+ found by bentley@ in sbcl(1) Mon, 9 Dec 2013 18:36:57 -0700
- using undefined strings or macros defines them to be empty
wl@ Mon, 14 Nov 2011 14:37:01 +0000
@@ -134,6 +145,8 @@
- groff an-ext.tmac macros (.UR, .UE) occur in xine(5)
reported by brad@ Sat, 15 Jan 2011 15:45:23 -0500
+ also occur in freeciv-client(6) freeciv-server(6) freeciv-modpack(6)
+ reported by bentley@ Tue, 30 Oct 2012 01:05:57 -0600
- -T[x]html doesn't stipulate non-collapsing spaces in literal mode
@@ -149,6 +162,18 @@
--- missing misc features ----------------------------------------------
+- italic correction (\/) in PostScript mode
+ Werner LEMBERG on groff at gnu dot org Sun, 10 Nov 2013 12:47:46
+
+- The whatis(1) utility looks for whole words in Nm.
+ If the file name of a page does not agree with the contents of any
+ of its Nm macros (e.g. pool(9)), add the file name as an Nm entry
+ to the mandoc.db as well, such that whatis(1) finds it.
+ If there is a page with a file name that does not appear as a substring
+ neither in Nm nor in Nd, the same fix would allow finding that page
+ with apropos(1) using the file name as a key, as well.
+ Issue reported by tedu@ Fri, 05 Jul 2013 21:15:23 -0400
+
- clean up escape sequence handling, creating three classes:
(1) fully implemented, or parsed and ignored without loss of content
(2) unimplemented, potentially causing loss of content
@@ -156,14 +181,6 @@
see textproc/mgdiff(1) for nice examples
(3) undefined, just output the character -> perhaps WARNING
-- The \t escape sequence is the same as a literal tab, see for example
- the ASCII table in hexdump(1) where
- .Bl -column \&000_nu \&001_so \&002_st \&003_et \&004_eo
- .It \&000\ nul\t001\ soh\t002\ stx\t003\ etx\t004\ eot\t005\ enq
- produces
- 000 nul 001 soh 002 stx 003 etx 004 eot 005 enq
- and the example in oldrdist(1)
-
- look at pages generated from reStructeredText, e.g. devel/mercurial hg(1)
These are a weird mixture of man(7) and custom autogenerated low-level
roff stuff. Figure out to what extent we can cope.
@@ -171,6 +188,9 @@
noted by stsp@ Sat, 24 Apr 2010 09:17:55 +0200
reminded by nicm@ Mon, 3 May 2010 09:52:41 +0100
+- look at pages generated from Texinfo source by yat2m, e.g. security/gnupg
+ First impression is not that bad.
+
- check compatibility with Plan9:
http://swtch.com/usr/local/plan9/tmac/tmac.an
http://swtch.com/plan9port/man/man7/man.html
@@ -183,14 +203,6 @@
- a column list with blank `Ta' cells triggers a spurrious
start-with-whitespace printing of a newline
-- double quotes inside double quotes are escaped by doubling them
- implement this in mdoc(7), too
- so far, we only have it in roff(7) and man(7)
- reminded by millert@ Thu, 09 Dec 2010 17:29:52 -0500
-
-- perl(1) SYNOPSIS looks bad; reported by deraadt@
- 1) man(7) seems to need SYNOPSIS .Nm blocks, too
-
- In .Bl -column,
.It Em Authentication<tab>Key Length
ought to render "Key Length" with emphasis, too,
@@ -210,9 +222,18 @@
of in_line() - put trailing punctuation out of scope.
Found in mount_nfs(8) and exports(5), search for "Appendix".
+- Trailing punctuation after .%T triggers EOS spacing, at least
+ outside .Rs (eek!). Simply setting ARGSFL_DELIM for .%T is not
+ the right solution, it sends mandoc into an endless loop.
+ reported by Nicolas Joly Sat, 17 Nov 2012 11:49:54 +0100
+
- in enclosures, mandoc sometimes fancies a bogus end of sentence
reminded by jmc@ Thu, 23 Sep 2010 18:13:39 +0059
+- formatting /usr/local/man/man1/latex2man.1 with groff and mandoc
+ reveals lots of bugs both in groff and mandoc...
+ reported by bentley@ Wed, 22 May 2013 23:49:30 -0600
+
************************************************************************
* formatting issues: gratuitous differences
************************************************************************
@@ -225,18 +246,6 @@
is just "o\bo".
see for example OpenBSD ksh(1)
-- The characters "|" and "\*(Ba" should never be bold,
- not even in the middle of a word, e.g. ".Cm b\*(Bac" in
- "mknod [-m mode] name b|c major minor"
- in OpenBSD ksh(1)
-
-- A bogus .Pp between two .It must not produce a double blank line,
- see between -R and -r in OpenBSD rm(1), before "update" in mount(8),
- or in DIAGNOSTICS in init(8), or before "is always true" in ksh(1).
- The same happens with .Pp just before .El, see bgpd.conf(5).
- Also have `It' complain if `Pp' is invoked at certain times (not
- -compact?).
-
- .Pp between two .It in .Bl -column should produce one,
not two blank lines, see e.g. login.conf(5).
reported by jmc@ Sun, 17 Apr 2011 14:04:58 +0059
@@ -250,6 +259,10 @@
in between, see for example tmux(1).
reported by nicm@ 13 Jan 2011 00:18:57 +0000
+- Trailing punctuation after .It should trigger EOS spacing.
+ reported by Nicolas Joly Sat, 17 Nov 2012 11:49:54 +0100
+ Probably, this should be fixed somewhere in termp_it_pre(), not sure.
+
- .Nx 1.0a
should be "NetBSD 1.0A", not "NetBSD 1.0a",
see OpenBSD ccdconfig(8).
@@ -265,68 +278,19 @@
as -width 7n, not -width 11n.
The same applies to .Bl -column column widths;
reported again by Nicolas Joly Thu, 1 Mar 2012 13:41:26 +0100 via wiz@ 5 Mar
+ reported again by Franco Fichtner Fri, 27 Sep 2013 21:02:28 +0200
+ An easy partial fix would be to just skip the first word if it starts
+ with a dot, including any following white space, when measuring.
- The \& zero-width character counts as output.
That is, when it is alone on a line between two .Pp,
we want three blank lines, not two as in mandoc.
-- When .Fn arguments exceed one output line, all but the first
- should be indented, see e.g. rpc(3);
- reported by jmc@ on discuss@ Fri, 29 Oct 2010 13:48:33 +0100
- reported again by Nicolas Joly via wiz@ Sun, 18 Sep 2011 18:24:40 +0200
- Also, we don't want to break the line within the argument of:
- .Fa "chtype tl"
-
-- .Ns should work when called at the end of an input line, see
- the following code in vi(1):
- .It Xo
- .Op Ar line
- .Cm a Ns Op Cm ppend Ns
- .Op Cm !\&
- .Xc
- The input text is appended after the specified line.
-
- Header lines of excessive length:
Port OpenBSD man_term.c rev. 1.25 to mdoc_term.c
and document it in mdoc(7) and man(7) COMPATIBILITY
found while talking to Chris Bennett
-- In man(7), the sequence
- .HP
- one line of regular text
- .SH
- should not produce two blank lines before the .SH,
- see for example named-checkconf(8).
-
-- In man(7), the sequence
- .SH HEADER
- <blank line>
- .PP
- regular text
- should not produce any blank lines between the header and the text,
- see for example rsync(1).
- Reported by naddy@ Mon, 28 Mar 2011 20:45:42 +0200
-
-- In man(7), the sequence
- regular text
- .IP
- .IP "tag"
- indented text
- should produce one, not four blank lines between the regular text
- and the tag, see for example rsync(1).
- Likewise,
- regular text
- .IP
- indented text
- should produce one, not two blank lines in between, and
- regular text
- .IP
- .RS
- .IP tag
- indented text
- should produce one, not three blank lines.
- Reported by naddy@ Mon, 28 Mar 2011 20:45:42 +0200
-
- trailing whitespace must be ignored even when followed by a font escape,
see for example
makes
@@ -335,12 +299,6 @@
in dig(1).
************************************************************************
-* error reporting issues
-************************************************************************
-
-- .TP directly followed by .RS gives an assertion.
-
-************************************************************************
* performance issues
************************************************************************
diff --git a/apropos.1 b/apropos.1
index 7dea132a461e..5adfeb6c3109 100644
--- a/apropos.1
+++ b/apropos.1
@@ -1,6 +1,6 @@
-.\" $Id: apropos.1,v 1.17 2012/03/24 01:46:25 kristaps Exp $
+.\" $Id: apropos.1,v 1.16.2.3 2013/10/05 01:25:20 schwarze Exp $
.\"
-.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2011 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
@@ -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: March 24 2012 $
+.Dd $Mdocdate: October 5 2013 $
.Dt APROPOS 1
.Os
.Sh NAME
@@ -23,8 +23,8 @@
.Sh SYNOPSIS
.Nm
.Op Fl C Ar file
-.Op Fl M Ar manpath
-.Op Fl m Ar manpath
+.Op Fl M Ar path
+.Op Fl m Ar path
.Op Fl S Ar arch
.Op Fl s Ar section
.Ar expression ...
@@ -44,11 +44,11 @@ searches for
databases in the default paths stipulated by
.Xr man 1 ,
parses terms as case-sensitive regular expressions
-over manual names and descriptions.
+.Pq the Li \&~ operator
+over manual names and descriptions
+.Pq the Li \&Nm No and Li \&Nd No macro keys .
Multiple terms imply pairwise
.Fl o .
-If standard output is a TTY, a result may be selected from a list and
-its manual displayed with the pager.
.Pp
Its arguments are as follows:
.Bl -tag -width Ds
@@ -58,13 +58,13 @@ Specify an alternative configuration
in
.Xr man.conf 5
format.
-.It Fl M Ar manpath
+.It Fl M Ar path
Use the colon-separated path instead of the default list of paths
searched for
.Xr mandocdb 8
databases.
Invalid paths, or paths without manual databases, are ignored.
-.It Fl m Ar manpath
+.It Fl m Ar path
Prepend the colon-separated paths to the list of paths searched
for
.Xr mandocdb 8
@@ -156,21 +156,13 @@ If an architecture is specified for the manual, it is displayed as
.Pp
.D1 title(cat/arch) \- description
.Pp
-If on a TTY, results are prefixed with a numeric identifier.
+Resulting manuals may be accessed as
.Pp
-.D1 [index] title(cat) \- description
+.Dl $ man \-s sec title
.Pp
-One may choose a manual be entering the index at the prompt.
-Valid choices are displayed using
-.Ev MANPAGER ,
-or failing that ,
-.Ev PAGER
-or just
-.Xr more 1 .
-Source pages are formatted with
-.Xr mandoc 1 ;
-preformatted pages with
-.Xr cat 1 .
+If an architecture is specified in the output, use
+.Pp
+.Dl $ man \-s sec \-S arch title
.Ss Macro Keys
Queries evaluate over a subset of
.Xr mdoc 7
@@ -248,14 +240,6 @@ Text production:
.El
.Sh ENVIRONMENT
.Bl -tag -width Ds
-.It Ev MANPAGER
-Default pager for manuals.
-If this is unset, falls back to
-.Ev Pager .
-.It Ev PAGER
-The second choice for a manual pager.
-If this is unset, use
-.Xr more 1 .
.It Ev MANPATH
Colon-separated paths modifying the default list of paths searched for
manual databases.
@@ -276,11 +260,11 @@ If none of these conditions are met, it overrides the default list.
.El
.Sh FILES
.Bl -tag -width "/etc/man.conf" -compact
-.It Pa whatis.db
+.It Pa mandoc.db
name of the
.Xr mandocdb 8
keyword database
-.It Pa whatis.index
+.It Pa mandoc.index
name of the
.Xr mandocdb 8
filename database
@@ -317,12 +301,11 @@ as variable names in the library category:
.Pp
.Dl $ apropos \-s 3 Va~^optind \-a Va~^optarg$
.Sh SEE ALSO
-.Xr more 1
+.Xr man 1 ,
.Xr re_format 7 ,
.Xr mandocdb 8
.Sh AUTHORS
The
.Nm
utility was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
diff --git a/apropos.c b/apropos.c
index 9c3cae96afa0..f5d1425f8615 100644
--- a/apropos.c
+++ b/apropos.c
@@ -1,4 +1,4 @@
-/* $Id: apropos.c,v 1.30 2012/03/24 02:18:51 kristaps Exp $ */
+/* $Id: apropos.c,v 1.27.2.1 2013/09/17 23:23:10 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -25,40 +25,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include "apropos_db.h"
#include "mandoc.h"
#include "manpath.h"
-#define SINGLETON(_res, _sz) \
- ((_sz) && (_res)[0].matched && \
- (1 == (_sz) || 0 == (_res)[1].matched))
-#define EMPTYSET(_res, _sz) \
- ((0 == (_sz)) || 0 == (_res)[0].matched)
-
static int cmp(const void *, const void *);
static void list(struct res *, size_t, void *);
-static void usage(void);
static char *progname;
int
main(int argc, char *argv[])
{
- int ch, rc, whatis, usecat;
+ int ch, rc, whatis;
struct res *res;
struct manpaths paths;
- const char *prog;
- pid_t pid;
- char path[PATH_MAX];
- int fds[2];
- size_t terms, ressz, sz;
+ size_t terms, ressz;
struct opts opts;
struct expr *e;
- char *defpaths, *auxpaths, *conf_file, *cp;
- extern int optind;
+ char *defpaths, *auxpaths;
+ char *conf_file;
extern char *optarg;
+ extern int optind;
progname = strrchr(argv[0], '/');
if (progname == NULL)
@@ -66,18 +55,16 @@ main(int argc, char *argv[])
else
++progname;
- whatis = 0 == strncmp(progname, "whatis", 6);
+ whatis = (0 == strncmp(progname, "whatis", 6));
memset(&paths, 0, sizeof(struct manpaths));
memset(&opts, 0, sizeof(struct opts));
- usecat = 0;
ressz = 0;
res = NULL;
auxpaths = defpaths = NULL;
conf_file = NULL;
e = NULL;
- path[0] = '\0';
while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
switch (ch) {
@@ -97,15 +84,14 @@ main(int argc, char *argv[])
opts.cat = optarg;
break;
default:
- usage();
- return(EXIT_FAILURE);
+ goto usage;
}
argc -= optind;
argv += optind;
- if (0 == argc)
- return(EXIT_SUCCESS);
+ if (0 == argc)
+ goto usage;
rc = 0;
@@ -123,63 +109,21 @@ main(int argc, char *argv[])
(paths.sz, paths.paths, &opts,
e, terms, NULL, &ressz, &res, list);
- terms = 1;
-
if (0 == rc) {
fprintf(stderr, "%s: Bad database\n", progname);
goto out;
- } else if ( ! isatty(STDOUT_FILENO) || EMPTYSET(res, ressz))
- goto out;
-
- if ( ! SINGLETON(res, ressz)) {
- printf("Which manpage would you like [1]? ");
- fflush(stdout);
- if (NULL != (cp = fgetln(stdin, &sz)) &&
- sz > 1 && '\n' == cp[--sz]) {
- if ((ch = atoi(cp)) <= 0)
- goto out;
- terms = (size_t)ch;
- }
}
- if (--terms < ressz && res[terms].matched) {
- chdir(paths.paths[res[terms].volume]);
- strlcpy(path, res[terms].file, PATH_MAX);
- usecat = RESTYPE_CAT == res[terms].type;
- }
out:
manpath_free(&paths);
resfree(res, ressz);
exprfree(e);
+ return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
- if ('\0' == path[0])
- return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
-
- if (-1 == pipe(fds)) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
-
- if (-1 == (pid = fork())) {
- perror(NULL);
- exit(EXIT_FAILURE);
- } else if (pid > 0) {
- dup2(fds[0], STDIN_FILENO);
- close(fds[1]);
- prog = NULL != getenv("MANPAGER") ?
- getenv("MANPAGER") :
- (NULL != getenv("PAGER") ?
- getenv("PAGER") : "more");
- execlp(prog, prog, (char *)NULL);
- perror(prog);
- return(EXIT_FAILURE);
- }
-
- dup2(fds[1], STDOUT_FILENO);
- close(fds[0]);
- prog = usecat ? "cat" : "mandoc";
- execlp(prog, prog, path, (char *)NULL);
- perror(prog);
+usage:
+ fprintf(stderr, "usage: %s [-C file] [-M path] [-m path] "
+ "[-S arch] [-s section]%s ...\n", progname,
+ whatis ? " name" : "\n expression");
return(EXIT_FAILURE);
}
@@ -191,49 +135,22 @@ list(struct res *res, size_t sz, void *arg)
qsort(res, sz, sizeof(struct res), cmp);
- if (EMPTYSET(res, sz) || SINGLETON(res, sz))
- return;
-
- if ( ! isatty(STDOUT_FILENO))
- for (i = 0; i < sz && res[i].matched; i++)
- printf("%s(%s%s%s) - %.70s\n",
- res[i].title, res[i].cat,
- *res[i].arch ? "/" : "",
- *res[i].arch ? res[i].arch : "",
- res[i].desc);
- else
- for (i = 0; i < sz && res[i].matched; i++)
- printf("[%zu] %s(%s%s%s) - %.70s\n", i + 1,
- res[i].title, res[i].cat,
- *res[i].arch ? "/" : "",
- *res[i].arch ? res[i].arch : "",
- res[i].desc);
+ for (i = 0; i < sz; i++) {
+ if ( ! res[i].matched)
+ continue;
+ printf("%s(%s%s%s) - %.70s\n",
+ res[i].title,
+ res[i].cat,
+ *res[i].arch ? "/" : "",
+ *res[i].arch ? res[i].arch : "",
+ res[i].desc);
+ }
}
static int
cmp(const void *p1, const void *p2)
{
- const struct res *r1 = p1;
- const struct res *r2 = p2;
-
- if (0 == r1->matched)
- return(1);
- else if (0 == r2->matched)
- return(1);
-
- return(strcasecmp(r1->title, r2->title));
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s "
- "[-C file] "
- "[-M manpath] "
- "[-m manpath] "
- "[-S arch] "
- "[-s section] "
- "expression ...\n",
- progname);
+ return(strcasecmp(((const struct res *)p1)->title,
+ ((const struct res *)p2)->title));
}
diff --git a/apropos_db.c b/apropos_db.c
index 8aea771da791..786fc7bd8fd4 100644
--- a/apropos_db.c
+++ b/apropos_db.c
@@ -1,4 +1,4 @@
-/* $Id: apropos_db.c,v 1.31 2012/03/24 01:46:25 kristaps Exp $ */
+/* $Id: apropos_db.c,v 1.32.2.3 2013/10/10 23:43:04 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -19,6 +19,8 @@
#include "config.h"
#endif
+#include <sys/param.h>
+
#include <assert.h>
#include <fcntl.h>
#include <regex.h>
@@ -28,12 +30,18 @@
#include <string.h>
#include <unistd.h>
-#if defined(__linux__)
+#if defined(__APPLE__)
+# include <libkern/OSByteOrder.h>
+#elif defined(__linux__)
# include <endian.h>
+#elif defined(__sun)
+# include <sys/byteorder.h>
+#else
+# include <sys/endian.h>
+#endif
+
+#if defined(__linux__) || defined(__sun)
# include <db_185.h>
-#elif defined(__APPLE__)
-# include <libkern/OSByteOrder.h>
-# include <db.h>
#else
# include <db.h>
#endif
@@ -411,11 +419,10 @@ apropos_search(int pathsz, char **paths, const struct opts *opts,
{
struct rectree tree;
struct mchars *mc;
- int i, rc;
+ int i;
memset(&tree, 0, sizeof(struct rectree));
- rc = 0;
mc = mchars_alloc();
*sz = 0;
*resp = NULL;
@@ -426,6 +433,7 @@ apropos_search(int pathsz, char **paths, const struct opts *opts,
*/
for (i = 0; i < pathsz; i++) {
+ assert('/' == paths[i][0]);
if (chdir(paths[i]))
continue;
if (single_search(&tree, opts, expr, terms, mc, i))
diff --git a/arch.in b/arch.in
index 5113446e468a..d0c445f308b2 100644
--- a/arch.in
+++ b/arch.in
@@ -1,4 +1,4 @@
-/* $Id: arch.in,v 1.12 2012/01/28 14:02:17 joerg Exp $ */
+/* $Id: arch.in,v 1.14 2013/09/16 22:12:57 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -38,9 +38,9 @@ LINE("arm", "ARM")
LINE("arm26", "ARM26")
LINE("arm32", "ARM32")
LINE("armish", "ARMISH")
+LINE("armv7", "ARMv7")
LINE("aviion", "AViiON")
LINE("atari", "ATARI")
-LINE("beagle", "Beagle")
LINE("bebox", "BeBox")
LINE("cats", "cats")
LINE("cesfic", "CESFIC")
@@ -81,6 +81,7 @@ LINE("netwinder", "NetWinder")
LINE("news68k", "NeWS68k")
LINE("newsmips", "NeWSMIPS")
LINE("next68k", "NeXT68k")
+LINE("octeon", "OCTEON")
LINE("ofppc", "OFPPC")
LINE("palm", "Palm")
LINE("pc532", "PC532")
diff --git a/catman.c b/catman.c
index 1d313ea6e00e..8767e5e3f6db 100644
--- a/catman.c
+++ b/catman.c
@@ -1,4 +1,4 @@
-/* $Id: catman.c,v 1.10 2012/01/03 15:17:20 kristaps Exp $ */
+/* $Id: catman.c,v 1.11.2.2 2013/10/11 00:06:48 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -31,7 +31,7 @@
#include <string.h>
#include <unistd.h>
-#ifdef __linux__
+#if defined(__linux__) || defined(__sun)
# include <db_185.h>
#else
# include <db.h>
@@ -212,9 +212,6 @@ indexhtml(char *src, size_t ssz, char *dst, size_t dsz)
const char *f;
char *d;
char fname[MAXPATHLEN];
- pid_t pid;
-
- pid = -1;
xstrlcpy(fname, dst, MAXPATHLEN);
xstrlcat(fname, "/", MAXPATHLEN);
@@ -380,7 +377,8 @@ manup(const struct manpaths *dirs, char *base)
char dst[MAXPATHLEN],
src[MAXPATHLEN];
const char *path;
- int i, c;
+ size_t i;
+ int c;
size_t sz;
FILE *f;
diff --git a/cgi.c b/cgi.c
index 2f5870ff8efd..64bde45ce2c7 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-/* $Id: cgi.c,v 1.42 2012/03/24 01:46:25 kristaps Exp $ */
+/* $Id: cgi.c,v 1.46 2013/10/11 00:06:48 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -18,7 +18,6 @@
#include "config.h"
#endif
-#include <sys/param.h>
#include <sys/wait.h>
#include <assert.h>
@@ -35,6 +34,13 @@
#include <string.h>
#include <unistd.h>
+#if defined(__sun)
+/* for stat() */
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
#include "apropos_db.h"
#include "mandoc.h"
#include "mdoc.h"
@@ -43,7 +49,7 @@
#include "manpath.h"
#include "mandocdb.h"
-#ifdef __linux__
+#if defined(__linux__) || defined(__sun)
# include <db_185.h>
#else
# include <db.h>
@@ -726,14 +732,14 @@ format(const struct req *req, const char *file)
struct man *man;
void *vp;
enum mandoclevel rc;
- char opts[MAXPATHLEN + 128];
+ char opts[PATH_MAX + 128];
if (-1 == (fd = open(file, O_RDONLY, 0))) {
resp_baddb();
return;
}
- mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
+ mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL, NULL);
rc = mparse_readfd(mp, fd, file);
close(fd);
@@ -743,7 +749,7 @@ format(const struct req *req, const char *file)
}
snprintf(opts, sizeof(opts), "fragment,"
- "man=%s/search.html?sec=%%S&expr=%%N,"
+ "man=%s/search.html?sec=%%S&expr=Nm~^%%N$,"
/*"includes=/cgi-bin/man.cgi/usr/include/%%I"*/,
progname);
@@ -777,7 +783,7 @@ pg_show(const struct req *req, char *path)
struct manpaths ps;
size_t sz;
char *sub;
- char file[MAXPATHLEN];
+ char file[PATH_MAX];
const char *cp;
int rc, catm;
unsigned int vol, rec, mr;
@@ -831,10 +837,10 @@ pg_show(const struct req *req, char *path)
goto out;
}
- sz = strlcpy(file, ps.paths[vol], MAXPATHLEN);
- assert(sz < MAXPATHLEN);
- strlcat(file, "/", MAXPATHLEN);
- strlcat(file, MANDOC_IDX, MAXPATHLEN);
+ sz = strlcpy(file, ps.paths[vol], PATH_MAX);
+ assert(sz < PATH_MAX);
+ strlcat(file, "/", PATH_MAX);
+ strlcat(file, MANDOC_IDX, PATH_MAX);
/* Open the index recno(3) database. */
@@ -863,8 +869,8 @@ pg_show(const struct req *req, char *path)
resp_baddb();
else {
file[(int)sz] = '\0';
- strlcat(file, "/", MAXPATHLEN);
- strlcat(file, cp, MAXPATHLEN);
+ strlcat(file, "/", PATH_MAX);
+ strlcat(file, cp, PATH_MAX);
if (catm)
catman(req, file);
else
@@ -973,7 +979,7 @@ int
main(void)
{
int i;
- char buf[MAXPATHLEN];
+ char buf[PATH_MAX];
DIR *cwd;
struct req req;
char *p, *path, *subpath;
@@ -1010,7 +1016,7 @@ main(void)
memset(&req, 0, sizeof(struct req));
- strlcpy(buf, ".", MAXPATHLEN);
+ strlcpy(buf, ".", PATH_MAX);
pathgen(cwd, buf, &req);
closedir(cwd);
@@ -1098,11 +1104,20 @@ static int
pathstop(DIR *dir)
{
struct dirent *d;
+#if defined(__sun)
+ struct stat sb;
+#endif
- while (NULL != (d = readdir(dir)))
+ while (NULL != (d = readdir(dir))) {
+#if defined(__sun)
+ stat(d->d_name, &sb);
+ if (S_IFREG & sb.st_mode)
+#else
if (DT_REG == d->d_type)
+#endif
if (0 == strcmp(d->d_name, "catman.conf"))
return(1);
+ }
return(0);
}
@@ -1119,9 +1134,12 @@ pathgen(DIR *dir, char *path, struct req *req)
DIR *cd;
int rc;
size_t sz, ssz;
+#if defined(__sun)
+ struct stat sb;
+#endif
- sz = strlcat(path, "/", MAXPATHLEN);
- if (sz >= MAXPATHLEN) {
+ sz = strlcat(path, "/", PATH_MAX);
+ if (sz >= PATH_MAX) {
fprintf(stderr, "%s: Path too long", path);
return;
}
@@ -1134,13 +1152,19 @@ pathgen(DIR *dir, char *path, struct req *req)
rc = 0;
while (0 == rc && NULL != (d = readdir(dir))) {
- if (DT_DIR != d->d_type || strcmp(d->d_name, "etc"))
+#if defined(__sun)
+ stat(d->d_name, &sb);
+ if (!(S_IFDIR & sb.st_mode)
+#else
+ if (DT_DIR != d->d_type
+#endif
+ || strcmp(d->d_name, "etc"))
continue;
path[(int)sz] = '\0';
- ssz = strlcat(path, d->d_name, MAXPATHLEN);
+ ssz = strlcat(path, d->d_name, PATH_MAX);
- if (ssz >= MAXPATHLEN) {
+ if (ssz >= PATH_MAX) {
fprintf(stderr, "%s: Path too long", path);
return;
} else if (NULL == (cd = opendir(path))) {
@@ -1183,13 +1207,19 @@ pathgen(DIR *dir, char *path, struct req *req)
rewinddir(dir);
while (NULL != (d = readdir(dir))) {
- if (DT_DIR != d->d_type || '.' == d->d_name[0])
+#if defined(__sun)
+ stat(d->d_name, &sb);
+ if (!(S_IFDIR & sb.st_mode)
+#else
+ if (DT_DIR != d->d_type
+#endif
+ || '.' == d->d_name[0])
continue;
path[(int)sz] = '\0';
- ssz = strlcat(path, d->d_name, MAXPATHLEN);
+ ssz = strlcat(path, d->d_name, PATH_MAX);
- if (ssz >= MAXPATHLEN) {
+ if (ssz >= PATH_MAX) {
fprintf(stderr, "%s: Path too long", path);
return;
} else if (NULL == (cd = opendir(path))) {
diff --git a/chars.c b/chars.c
index ce03347b5d83..3ad1f57471c6 100644
--- a/chars.c
+++ b/chars.c
@@ -1,4 +1,4 @@
-/* $Id: chars.c,v 1.52 2011/11/08 00:15:23 kristaps Exp $ */
+/* $Id: chars.c,v 1.54 2013/06/20 22:39:30 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -37,7 +37,7 @@ struct ln {
int unicode;
};
-#define LINES_MAX 328
+#define LINES_MAX 329
#define CHAR(in, ch, code) \
{ NULL, (in), (ch), (code) },
@@ -77,7 +77,7 @@ mchars_alloc(void)
*/
tab = mandoc_malloc(sizeof(struct mchars));
- htab = mandoc_calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln **));
+ htab = mandoc_calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln *));
for (i = 0; i < LINES_MAX; i++) {
hash = (int)lines[i].code[0] - PRINT_LO;
diff --git a/chars.in b/chars.in
index a4c45b3c43eb..cc6549e7e5be 100644
--- a/chars.in
+++ b/chars.in
@@ -1,4 +1,4 @@
-/* $Id: chars.in,v 1.42 2011/10/02 10:02:26 kristaps Exp $ */
+/* $Id: chars.in,v 1.43 2013/06/20 22:39:30 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -42,6 +42,7 @@ CHAR("&", "", 0)
CHAR("^", "", 0)
CHAR("|", "", 0)
CHAR("}", "", 0)
+CHAR("t", "", 0)
/* Accents. */
CHAR("a\"", "\"", 779)
diff --git a/config.h.post b/config.h.post
index 39da2b2f0699..9a33671b568e 100644
--- a/config.h.post
+++ b/config.h.post
@@ -15,14 +15,16 @@
# endif
#endif
-#if defined(__APPLE__)
-# define htobe32(x) OSSwapHostToBigInt32(x)
-# define betoh32(x) OSSwapBigToHostInt32(x)
-# define htobe64(x) OSSwapHostToBigInt64(x)
-# define betoh64(x) OSSwapBigToHostInt64(x)
-#elif defined(__linux__)
-# define betoh32(x) be32toh(x)
-# define betoh64(x) be64toh(x)
+#ifndef HAVE_BETOH64
+# if defined(__APPLE__)
+# define betoh64(x) OSSwapBigToHostInt64(x)
+# define htobe64(x) OSSwapHostToBigInt64(x)
+# elif defined(__sun)
+# define betoh64(x) BE_64(x)
+# define htobe64(x) BE_64(x)
+# else
+# define betoh64(x) be64toh(x)
+# endif
#endif
#ifndef HAVE_STRLCAT
diff --git a/demandoc.1 b/demandoc.1
index 845b9c14b55b..84571baf30aa 100644
--- a/demandoc.1
+++ b/demandoc.1
@@ -1,4 +1,4 @@
-.\" $Id: demandoc.1,v 1.6 2011/12/25 19:35:44 kristaps Exp $
+.\" $Id: demandoc.1,v 1.7 2013/07/13 19:41:16 schwarze Exp $
.\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -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: December 25 2011 $
+.Dd $Mdocdate: July 13 2013 $
.Dt DEMANDOC 1
.Os
.Sh NAME
@@ -105,5 +105,4 @@ documents.
The
.Nm
utility was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
diff --git a/demandoc.c b/demandoc.c
index 2474a358e233..aad42085b185 100644
--- a/demandoc.c
+++ b/demandoc.c
@@ -1,4 +1,4 @@
-/* $Id: demandoc.c,v 1.6 2011/09/01 22:25:53 kristaps Exp $ */
+/* $Id: demandoc.c,v 1.7 2012/05/31 22:27:14 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -76,7 +76,7 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
+ mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL, NULL);
assert(mp);
if (0 == argc)
diff --git a/eqn.7 b/eqn.7
index f86b9c496bb0..dcbad41cc15b 100644
--- a/eqn.7
+++ b/eqn.7
@@ -1,4 +1,4 @@
-.\" $Id: eqn.7,v 1.28 2011/09/25 18:37:09 schwarze Exp $
+.\" $Id: eqn.7,v 1.29 2013/07/13 19:41:16 schwarze Exp $
.\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -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: September 25 2011 $
+.Dd $Mdocdate: July 13 2013 $
.Dt EQN 7
.Os
.Sh NAME
@@ -276,5 +276,4 @@ was added in 2011.
This
.Nm
reference was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
diff --git a/gmdiff b/gmdiff
new file mode 100644
index 000000000000..a5bca9d31c9a
--- /dev/null
+++ b/gmdiff
@@ -0,0 +1,35 @@
+#!/bin/sh
+# Copyright (c) 2013 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.
+
+if [ `id -u` -eq 0 ]; then
+ echo "$0: do not run me as root"
+ exit 1
+fi
+
+if [ $# -eq 0 ]; then
+ echo "usage: $0 manual_source_file ..."
+ exit 1
+fi
+
+while [ -n "$1" ]; do
+ file=$1
+ shift
+ echo " ========== $file ========== "
+ tbl $file | groff -mandoc -Tascii -P -c 2>&1 > /tmp/groff.out
+ mandoc -Ios='OpenBSD ports' -Werror $file 2>&1 > /tmp/mandoc.out
+ diff -au /tmp/groff.out /tmp/mandoc.out 2>&1
+done
+
+exit 0
diff --git a/html.c b/html.c
index 326df035fc44..9d28b4270e4c 100644
--- a/html.c
+++ b/html.c
@@ -1,7 +1,7 @@
-/* $Id: html.c,v 1.150 2011/10/05 21:35:17 kristaps Exp $ */
+/* $Id: html.c,v 1.152 2013/08/08 20:07:47 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2012, 2013 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
@@ -235,6 +235,9 @@ print_metaf(struct html *h, enum mandoc_esc deco)
case (ESCAPE_FONTBOLD):
font = HTMLFONT_BOLD;
break;
+ case (ESCAPE_FONTBI):
+ font = HTMLFONT_BI;
+ break;
case (ESCAPE_FONT):
/* FALLTHROUGH */
case (ESCAPE_FONTROMAN):
@@ -253,17 +256,27 @@ print_metaf(struct html *h, enum mandoc_esc deco)
h->metal = h->metac;
h->metac = font;
- if (HTMLFONT_NONE != font)
- h->metaf = HTMLFONT_BOLD == font ?
- print_otag(h, TAG_B, 0, NULL) :
- print_otag(h, TAG_I, 0, NULL);
+ switch (font) {
+ case (HTMLFONT_ITALIC):
+ h->metaf = print_otag(h, TAG_I, 0, NULL);
+ break;
+ case (HTMLFONT_BOLD):
+ h->metaf = print_otag(h, TAG_B, 0, NULL);
+ break;
+ case (HTMLFONT_BI):
+ h->metaf = print_otag(h, TAG_B, 0, NULL);
+ print_otag(h, TAG_I, 0, NULL);
+ break;
+ default:
+ break;
+ }
}
int
html_strlen(const char *cp)
{
- int ssz, sz;
- const char *seq, *p;
+ size_t rsz;
+ int skip, sz;
/*
* Account for escaped sequences within string length
@@ -274,10 +287,21 @@ html_strlen(const char *cp)
*/
sz = 0;
- while (NULL != (p = strchr(cp, '\\'))) {
- sz += (int)(p - cp);
- ++cp;
- switch (mandoc_escape(&cp, &seq, &ssz)) {
+ skip = 0;
+ while (1) {
+ rsz = strcspn(cp, "\\");
+ if (rsz) {
+ cp += rsz;
+ if (skip) {
+ skip = 0;
+ rsz--;
+ }
+ sz += rsz;
+ }
+ if ('\0' == *cp)
+ break;
+ cp++;
+ switch (mandoc_escape(&cp, NULL, NULL)) {
case (ESCAPE_ERROR):
return(sz);
case (ESCAPE_UNICODE):
@@ -285,15 +309,19 @@ html_strlen(const char *cp)
case (ESCAPE_NUMBERED):
/* FALLTHROUGH */
case (ESCAPE_SPECIAL):
- sz++;
+ if (skip)
+ skip = 0;
+ else
+ sz++;
+ break;
+ case (ESCAPE_SKIPCHAR):
+ skip = 1;
break;
default:
break;
}
}
-
- assert(sz >= 0);
- return(sz + strlen(cp));
+ return(sz);
}
static int
@@ -308,6 +336,12 @@ print_encode(struct html *h, const char *p, int norecurse)
nospace = 0;
while ('\0' != *p) {
+ if (HTML_SKIPCHAR & h->flags && '\\' != *p) {
+ h->flags &= ~HTML_SKIPCHAR;
+ p++;
+ continue;
+ }
+
sz = strcspn(p, rejs);
fwrite(p, 1, sz, stdout);
@@ -338,6 +372,33 @@ print_encode(struct html *h, const char *p, int norecurse)
break;
switch (esc) {
+ case (ESCAPE_FONT):
+ /* FALLTHROUGH */
+ case (ESCAPE_FONTPREV):
+ /* FALLTHROUGH */
+ case (ESCAPE_FONTBOLD):
+ /* FALLTHROUGH */
+ case (ESCAPE_FONTITALIC):
+ /* FALLTHROUGH */
+ case (ESCAPE_FONTBI):
+ /* FALLTHROUGH */
+ case (ESCAPE_FONTROMAN):
+ if (0 == norecurse)
+ print_metaf(h, esc);
+ continue;
+ case (ESCAPE_SKIPCHAR):
+ h->flags |= HTML_SKIPCHAR;
+ continue;
+ default:
+ break;
+ }
+
+ if (h->flags & HTML_SKIPCHAR) {
+ h->flags &= ~HTML_SKIPCHAR;
+ continue;
+ }
+
+ switch (esc) {
case (ESCAPE_UNICODE):
/* Skip passed "u" header. */
c = mchars_num2uc(seq + 1, len - 1);
@@ -356,19 +417,6 @@ print_encode(struct html *h, const char *p, int norecurse)
else if (-1 == c && 1 == len)
putchar((int)*seq);
break;
- case (ESCAPE_FONT):
- /* FALLTHROUGH */
- case (ESCAPE_FONTPREV):
- /* FALLTHROUGH */
- case (ESCAPE_FONTBOLD):
- /* FALLTHROUGH */
- case (ESCAPE_FONTITALIC):
- /* FALLTHROUGH */
- case (ESCAPE_FONTROMAN):
- if (norecurse)
- break;
- print_metaf(h, esc);
- break;
case (ESCAPE_NOSPACE):
if ('\0' == *p)
nospace = 1;
@@ -511,10 +559,20 @@ print_text(struct html *h, const char *word)
}
assert(NULL == h->metaf);
- if (HTMLFONT_NONE != h->metac)
- h->metaf = HTMLFONT_BOLD == h->metac ?
- print_otag(h, TAG_B, 0, NULL) :
- print_otag(h, TAG_I, 0, NULL);
+ switch (h->metac) {
+ case (HTMLFONT_ITALIC):
+ h->metaf = print_otag(h, TAG_I, 0, NULL);
+ break;
+ case (HTMLFONT_BOLD):
+ h->metaf = print_otag(h, TAG_B, 0, NULL);
+ break;
+ case (HTMLFONT_BI):
+ h->metaf = print_otag(h, TAG_B, 0, NULL);
+ print_otag(h, TAG_I, 0, NULL);
+ break;
+ default:
+ break;
+ }
assert(word);
if ( ! print_encode(h, word, 0)) {
diff --git a/html.h b/html.h
index 60960702f19b..894cfc4cff47 100644
--- a/html.h
+++ b/html.h
@@ -1,4 +1,4 @@
-/* $Id: html.h,v 1.47 2011/10/05 21:35:17 kristaps Exp $ */
+/* $Id: html.h,v 1.49 2013/08/08 20:07:47 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -75,6 +75,7 @@ enum htmlfont {
HTMLFONT_NONE = 0,
HTMLFONT_BOLD,
HTMLFONT_ITALIC,
+ HTMLFONT_BI,
HTMLFONT_MAX
};
@@ -117,6 +118,7 @@ struct html {
#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 */
struct tagq tags; /* stack of open tags */
struct rofftbl tbl; /* current table */
struct tag *tblt; /* current open table scope */
diff --git a/index.sgml b/index.sgml
index 4386a9ebd955..83a43a737d73 100644
--- a/index.sgml
+++ b/index.sgml
@@ -7,6 +7,7 @@
</HEAD>
<BODY>
<P CLASS="head">
+ <A HREF="http://www.openbsd.org/"><IMG SRC="puffy.gif" ALT="Puffy" WIDTH="100" HEIGHT="91" STYLE="float: right"></A>
<B>mdocml</B> &#8211; UNIX manpage compiler, current version @VERSION@ (@VDATE@)
</P>
<P CLASS="subhead">
@@ -20,49 +21,47 @@
<P>
<SPAN CLASS="nm">mdocml</SPAN> is a suite of tools compiling <I><A HREF="mdoc.7.html">mdoc</A></I>, the roff macro
package of choice for BSD manual pages, and <I><A HREF="man.7.html">man</A></I>, the predominant historical package for
- UNIX manuals. The mission of <SPAN CLASS="nm">mdocml</SPAN> is to deprecate <A
- HREF="http://www.gnu.org/software/groff/" CLASS="external">groff</A>, the GNU troff implementation, for displaying <I>mdoc</I>
- pages whilst providing token support for <I>man</I>.
+ UNIX manuals.
+ It is small, ISO C, <A CLASS="external" HREF="http://www.isc.org/software/license">ISC</A>-licensed, and quite fast.
</P>
<P>
- Why? groff amounts to over 5 MB of source code, most of which is C++ and all of which is GPL. It runs slowly, produces
- uncertain output, and varies in operation from system to system. mdocml strives to fix this (respectively small, C, <A
- CLASS="external" HREF="http://www.isc.org/software/license">ISC</A>-licensed, fast and regular).
- </P>
- <P>
- <SPAN CLASS="nm">mdocml</SPAN> consists of the <A HREF="mandoc.3.html">libmandoc</A> validating compiler and <A
- HREF="mandoc.1.html">mandoc</A>, which interfaces with the compiler library to format output for UNIX terminals (with
+ The tool set features <A HREF="mandoc.1.html">mandoc</A>,
+ based on the <A HREF="mandoc.3.html">libmandoc</A> validating compiler,
+ to format output for UNIX terminals (with
support for wide-character locales), XHTML, HTML, PostScript, and PDF.
It also includes <A HREF="preconv.1.html">preconv</A>, for recoding multibyte manuals;
<A HREF="demandoc.1.html">demandoc</A>, for emitting only text parts of manuals;
<A HREF="mandocdb.8.html">mandocdb</A>, for indexing manuals; and
<A HREF="apropos.1.html">apropos</A>, <A HREF="whatis.1.html">whatis</A>, and
<A HREF="man.cgi.7.html">man.cgi</A> (via <A HREF="catman.8.html">catman</A>) for semantic search of manual content.
- It is a <A CLASS="external" HREF="http://bsd.lv/">BSD.lv</A> project.
</P>
<P>
- <I>Disambiguation</I>: <SPAN CLASS="nm">mdocml</SPAN> is often referred to by its installed binary, <Q>mandoc</Q>.
+ <SPAN CLASS="nm">mdocml</SPAN> has predominantly been developed on OpenBSD
+ and is both an <A CLASS="external" HREF="http://www.openbsd.org/">OpenBSD</A>
+ and a <A CLASS="external" HREF="http://bsd.lv/">BSD.lv</A> project.
+ We strive to support all interested free operating systems, in particular
+ <A CLASS="external" HREF="http://www.dragonflybsd.org/">DragonFly</A>,
+ <A CLASS="external" HREF="http://www.netbsd.org/">NetBSD</A>,
+ <A CLASS="external" HREF="http://www.freebsd.org/">FreeBSD</A>,
+ <A CLASS="external" HREF="http://www.minix3.org/">Minix 3</A>,
+ and <A CLASS="external" HREF="http://www.gnu.org/">GNU</A>/Linux,
+ as well as all systems running the <A CLASS="external" HREF="http://www.pkgsrc.org/">pkgsrc</A> portable package build system.
+ All of these projects have helped to make <SPAN CLASS="nm">mdocml</SPAN> better, by providing feedback and advice,
+ bug reports, and patches.
</P>
- <H2>
- <A NAME="sources">Sources</A>
- </H2>
<P>
- <SPAN CLASS="nm">mdocml</SPAN> is in plain-old ANSI C and should build and run on any modern system; however, you'll
- need <A HREF="http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html">libdb</A> to build <A
- HREF="apropos.1.html">apropos</A>, <A HREF="whatis.1.html">whatis</A>, <A HREF="man.cgi.7.html">man.cgi</A>, <A
- HREF="catman.8.html">catman</A>, and <A HREF="mandocdb.8.html">mandocdb</A> (this is installed by default on BSD UNIX
- systems &mdash; see the <I>Makefile</I> if you're running Linux). To build and install into <I>/usr/local/</I>, just
- run <CODE>make install</CODE>. Be careful: the <B>preconv</B>, <B>apropos</B>, and <B>whatis</B> binary names are
- usually taken by existing utilities.
+ <I>Disambiguation</I>: <SPAN CLASS="nm">mdocml</SPAN> is often referred to by its installed binary, <Q>mandoc</Q>.
</P>
<H2>
- <A NAME="binaries">Binaries</A>
+ <A NAME="sources">Sources</A>
</H2>
<P>
- Binary archives consist of pre-compiled binaries, manuals, and other necessary files.
- Universal (Mac OS X) binaries are compiled for the PCC, i386, and x86_64 architectures.
- Windows binaries are compiled with <A CLASS="external" HREF="http://www.mingw.org">MingW</A> for the 32-bit (i686) and
- 64-bit (x86_64) architectures.
+ <SPAN CLASS="nm">mdocml</SPAN> should build and run on any modern system with
+ <A HREF="http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html">libdb</A>
+ (this is installed by default on BSD UNIX systems &mdash; see the <I>Makefile</I> if you're running Linux).
+ To build and install into <I>/usr/local/</I>, just run <CODE>make install</CODE>.
+ Be careful: the <B>preconv</B>, <B>apropos</B>, and <B>whatis</B> installed binary names
+ may be taken by existing utilities.
</P>
<H2>
Downstream
@@ -70,8 +69,7 @@
<P>
Several systems come bundled with <SPAN CLASS="nm">mdocml</SPAN> utilities.
If your system does not appear below, the maintainers have not contacted me and it should not be considered
- <Q>official</Q>.
- Please <A HREF="#contact">contact us</A> if you plan on maintaining a downstream version!
+ <Q>official</Q>, so please <A HREF="#contact">contact us</A> if you plan on maintaining a downstream version!
</P>
<TABLE WIDTH="100%" SUMMARY="Downstream Sources">
<COL WIDTH="175">
@@ -80,37 +78,52 @@
<TR>
<TD>DragonFly BSD</TD>
<TD>
- <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/usr.bin/mandoc" CLASS="external">usr.bin/mandoc</A>
+ <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/contrib/mdocml" CLASS="external">contrib/mdocml</A> (1.12.3 sources)
+ <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/lib/libmandoc" CLASS="external">lib/libmandoc</A>
+ <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/usr.bin/mandoc" CLASS="external">usr.bin/mandoc</A> (build system)
</TD>
</TR>
<TR>
- <TD>FreeBSD</TD>
+ <TD>FreeBSD 10.0, -CURRENT</TD>
<TD>
- <A HREF="http://www.freebsd.org/cgi/cvsweb.cgi/ports/textproc/mdocml/" CLASS="external">ports/textproc/mdocml</A>
+ <A HREF="http://svnweb.freebsd.org/base/head/contrib/mdocml/" CLASS="external">contrib/mdocml</A> (1.12.1 sources)
+ <A HREF="http://svnweb.freebsd.org/base/head/usr.bin/mandoc/" CLASS="external">usr.bin/mandoc</A> (build system)
+ </TD>
+ </TR>
+ <TR>
+ <TD>FreeBSD 9.x, 8.x</TD>
+ <TD>
+ <A HREF="http://svnweb.freebsd.org/ports/head/textproc/mdocml/" CLASS="external">ports/textproc/mdocml</A> (1.12.2 port)
</TD>
</TR>
<TR>
<TD>NetBSD</TD>
<TD>
- <A HREF="http://cvsweb.netbsd.org/bsdweb.cgi/src/external/bsd/mdocml/" CLASS="external">src/external/bsd/mdocml</A>
+ <A HREF="http://cvsweb.netbsd.org/bsdweb.cgi/src/external/bsd/mdocml/" CLASS="external">src/external/bsd/mdocml</A> (1.12.1 sources plus patches and build system)
</TD>
</TR>
<TR>
<TD>OpenBSD</TD>
<TD>
- <A HREF="http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/mandoc/" CLASS="external">src/usr.bin/mandoc</A>
+ <A HREF="http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/mandoc/" CLASS="external">src/usr.bin/mandoc</A> (1.12.3 sources under active development and build system)
</TD>
</TR>
<TR>
<TD>pkgsrc</TD>
<TD>
- <A HREF="http://pkgsrc.se/textproc/mdocml" CLASS="external">textproc/mdocml</A>
+ <A HREF="http://pkgsrc.se/textproc/mdocml" CLASS="external">textproc/mdocml</A> (1.12.2 port)
</TD>
</TR>
<TR>
<TD>Minix3</TD>
<TD>
- <A HREF="http://git.minix3.org/?p=minix.git;a=tree;f=external/bsd/mdocml" CLASS="external">external/bsd/mdocml</A>
+ <A HREF="http://git.minix3.org/?p=minix.git;a=tree;f=external/bsd/mdocml" CLASS="external">external/bsd/mdocml</A> (1.10.9 sources and build system)
+ </TD>
+ </TR>
+ <TR>
+ <TD>Alpine Linux</TD>
+ <TD>
+ <A HREF="http://git.alpinelinux.org/cgit/aports/tree/main/mdocml" CLASS="external">aports/main/mdocml</A> (1.12.2 port)
</TD>
</TR>
</TBODY>
@@ -131,154 +144,119 @@
<TD VALIGN="top"><A HREF="apropos.1.html">apropos(1)</A></TD>
<TD VALIGN="top">
search the manual page database
- (<A HREF="apropos.1.txt">text</A> |
- <A HREF="apropos.1.xhtml">xhtml</A> |
- <A HREF="apropos.1.pdf">pdf</A> |
- <A HREF="apropos.1.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="demandoc.1.html">demandoc(1)</A></TD>
<TD VALIGN="top">
emit only text of UNIX manuals
- (<A HREF="demandoc.1.txt">text</A> |
- <A HREF="demandoc.1.xhtml">xhtml</A> |
- <A HREF="demandoc.1.pdf">pdf</A> |
- <A HREF="demandoc.1.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="mandoc.1.html">mandoc(1)</A></TD>
<TD VALIGN="top">
format and display UNIX manuals
- (<A HREF="mandoc.1.txt">text</A> |
- <A HREF="mandoc.1.xhtml">xhtml</A> |
- <A HREF="mandoc.1.pdf">pdf</A> |
- <A HREF="mandoc.1.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="preconv.1.html">preconv(1)</A></TD>
<TD VALIGN="top">
recode multibyte UNIX manuals
- (<A HREF="preconv.1.txt">text</A> |
- <A HREF="preconv.1.xhtml">xhtml</A> |
- <A HREF="preconv.1.pdf">pdf</A> |
- <A HREF="preconv.1.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="whatis.1.html">whatis(1)</A></TD>
<TD VALIGN="top">
search the manual page database
- (<A HREF="whatis.1.txt">text</A> |
- <A HREF="whatis.1.xhtml">xhtml</A> |
- <A HREF="whatis.1.pdf">pdf</A> |
- <A HREF="whatis.1.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="mandoc.3.html">mandoc(3)</A></TD>
<TD VALIGN="top">
mandoc macro compiler library
- (<A HREF="mandoc.3.txt">text</A> |
- <A HREF="mandoc.3.xhtml">xhtml</A> |
- <A HREF="mandoc.3.pdf">pdf</A> |
- <A HREF="mandoc.3.ps">ps</A>)
</TD>
</TR>
<TR>
- <TD VALIGN="top"><A HREF="man.7.html">man(7)</A></TD>
+ <TD VALIGN="top"><A HREF="tbl.3.html">tbl(3)</A></TD>
<TD VALIGN="top">
- man language reference
- (<A HREF="man.7.txt">text</A> |
- <A HREF="man.7.xhtml">xhtml</A> |
- <A HREF="man.7.pdf">pdf</A> |
- <A HREF="man.7.ps">ps</A>)
+ roff table parser library for mandoc
</TD>
</TR>
<TR>
- <TD VALIGN="top"><A HREF="man.cgi.7.html">man.cgi(7)</A></TD>
+ <TD VALIGN="top"><A HREF="eqn.7.html">eqn(7)</A></TD>
<TD VALIGN="top">
- cgi for manpage query and display
- (<A HREF="man.cgi.7.txt">text</A> |
- <A HREF="man.cgi.7.xhtml">xhtml</A> |
- <A HREF="man.cgi.7.pdf">pdf</A> |
- <A HREF="man.cgi.7.ps">ps</A>)
+ eqn-mandoc language reference
</TD>
</TR>
<TR>
- <TD VALIGN="top"><A HREF="eqn.7.html">eqn(7)</A></TD>
+ <TD VALIGN="top"><A HREF="man.7.html">man(7)</A></TD>
<TD VALIGN="top">
- eqn-mandoc language reference
- (<A HREF="eqn.7.txt">text</A> |
- <A HREF="eqn.7.xhtml">xhtml</A> |
- <A HREF="eqn.7.pdf">pdf</A> |
- <A HREF="eqn.7.ps">ps</A>)
+ man language reference
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN="top"><A HREF="man.cgi.7.html">man.cgi(7)</A></TD>
+ <TD VALIGN="top">
+ cgi for manpage query and display
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="mandoc_char.7.html">mandoc_char(7)</A></TD>
<TD VALIGN="top">
mandoc special characters
- (<A HREF="mandoc_char.7.txt">text</A> |
- <A HREF="mandoc_char.7.xhtml">xhtml</A> |
- <A HREF="mandoc_char.7.pdf">pdf</A> |
- <A HREF="mandoc_char.7.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="mdoc.7.html">mdoc(7)</A></TD>
<TD VALIGN="top">
mdoc language reference
- (<A HREF="mdoc.7.txt">text</A> |
- <A HREF="mdoc.7.xhtml">xhtml</A> |
- <A HREF="mdoc.7.pdf">pdf</A> |
- <A HREF="mdoc.7.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="roff.7.html">roff(7)</A></TD>
<TD VALIGN="top">
roff-mandoc language reference
- (<A HREF="roff.7.txt">text</A> |
- <A HREF="roff.7.xhtml">xhtml</A> |
- <A HREF="roff.7.pdf">pdf</A> |
- <A HREF="roff.7.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="tbl.7.html">tbl(7)</A></TD>
<TD VALIGN="top">
tbl-mandoc language reference
- (<A HREF="tbl.7.txt">text</A> |
- <A HREF="tbl.7.xhtml">xhtml</A> |
- <A HREF="tbl.7.pdf">pdf</A> |
- <A HREF="tbl.7.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="catman.8.html">catman(8)</A></TD>
<TD VALIGN="top">
update a man.cgi manpage cache
- (<A HREF="catman.8.txt">text</A> |
- <A HREF="catman.8.xhtml">xhtml</A> |
- <A HREF="catman.8.pdf">pdf</A> |
- <A HREF="catman.8.ps">ps</A>)
</TD>
</TR>
<TR>
<TD VALIGN="top"><A HREF="mandocdb.8.html">mandocdb(8)</A></TD>
<TD VALIGN="top">
index UNIX manuals
- (<A HREF="mandocdb.8.txt">text</A> |
- <A HREF="mandocdb.8.xhtml">xhtml</A> |
- <A HREF="mandocdb.8.pdf">pdf</A> |
- <A HREF="mandocdb.8.ps">ps</A>)
</TD>
</TR>
</TBODY>
</TABLE>
+ <H2>
+ <A NAME="links">Supplementary Information</A>
+ </H2>
+ <UL>
+ <LI>
+ <A HREF="http://manpages.bsd.lv/">Practical UNIX Manuals</A>: mdoc tutorial by Kristaps Dzonsons
+ </LI>
+ <LI>
+ <A HREF="http://www.openbsd.org/faq/ports/specialtopics.html#Mandoc" CLASS="external">OpenBSD porting guide</A>
+ chapter regarding manual pages
+ </LI>
+ <LI>
+ <A HREF="press.html">Publications and media coverage</A>
+ concerning mdocml and mandoc
+ </LI>
+ <LI>
+ <A HREF="http://manpages.bsd.lv/history.html">History of UNIX Manpages</A>: a comprehensive overview by Kristaps Dzonsons
+ </LI>
+ </UL>
<H1>
<A NAME="contact">Contact</A>
</H1>
@@ -326,38 +304,134 @@
<A NAME="news">News</A>
</H1>
<P CLASS="news">
- 23-03-2011: version 1.12.1
+ 31-12-2013: version 1.12.3
</P>
<P>
- Significant work on <A HREF="apropos.1.html">apropos</A> and <A HREF="mandocdb.8.html">mandocdb</A>. These tools are
- now much more robust.
- A <A HREF="whatis.1.html">whatis</A> implementation is now handled as an <A HREF="apropos.1.html">apropos</A> mode.
- These tools are also able to minimally handle pre-formatted pages, that is, those already formatted by another utility
- such as GNU troff.
+ In the <A HREF="mdoc.7.html">mdoc(7)</A> SYNOPSIS, line breaks and hanging indentation
+ now work correctly for .Fo/.Fa/.Fc and .Fn blocks.
+ Thanks to Franco Fichtner for doing part of the work.
</P>
<P>
- The <A HREF="man.cgi.7.html">man.cgi</A> script is also now available for wider testing. It interfaces with <A
- HREF="mandocdb.8.html">mandocdb</A> manuals cached by <A HREF="catman.8.html">catman</A>. HTML output is generated
- on-the-fly by <A HREF="mandoc.3.html">libmandoc</A> or internal methods to convert pre-formatted pages.
+ The <A HREF="mdoc.7.html">mdoc(7)</A> .Bk macro got some addititonal bugfixes.
</P>
<P>
- The mailing list archive for the discuss and tech lists are being hosted by <A CLASS="external"
- HREF="http://www.gmane.org">Gmane</A> at <A HREF="http://dir.gmane.org/gmane.comp.tools.mdocml.user"
- CLASS="external">gmane.comp.tools.mdocml.user</A> and <A HREF="http://dir.gmane.org/gmane.comp.tools.mdocml.devel"
- CLASS="external">gmane.comp.tools.mdocml.devel</A>, respectively.
+ In <A HREF="mdoc.7.html">mdoc(7)</A> macro arguments, double quotes can now be quoted
+ by doubling them, just like in <A HREF="man.7.html">man(7)</A>.
+ Thanks to Tsugutomo ENAMI for the patch.
</P>
<P>
- Lastly, I'm no longer providing binaries, as nobody has asked for them.
+ At the end of <A HREF="man.7.html">man(7)</A> macro lines, end-of-sentence spacing
+ now works. Thanks to Franco Fichtner for the patch.
</P>
<P>
- See <A HREF="http://mdocml.bsd.lv/cgi-bin/cvsweb/index.sgml?cvsroot=mdocml">cvsweb</A> for
- historical notes.
+ For backward compatibility, the <A HREF="man.7.html">man(7)</A> parser now supports the
+ man-ext .UR/.UE (uniform resource identifier) block macros.
</P>
+ <P>
+ The <A HREF="man.7.html">man(7)</A> parser now handles closing blocks that are not open
+ more gracefully.
+ </P>
+ <P>
+ The <A HREF="man.7.html">man(7)</A> parser now ignores blank lines right after .SH and .SS.
+ </P>
+ <P>
+ In the <A HREF="man.7.html">man(7)</A> formatter, reset indentation when leaving a block,
+ not just when entering the next one.
+ </P>
+ <P>
+ The <A HREF="roff.7.html">roff(7)</A> .nr request now supports incrementing and decrementing
+ number registers and stops parsing the number right before the first non-digit character.
+ </P>
+ <P>
+ The <A HREF="roff.7.html">roff(7)</A> parser now supports the alternative escape sequence
+ syntax \C'uXXXX' for Unicode characters.
+ </P>
+ <P>
+ The <A HREF="roff.7.html">roff(7)</A> parser now parses and ignores the .fam (font family)
+ and .hw (hyphenation points) requests and the \d and \u escape sequences.
+ </P>
+ <P>
+ The <A HREF="roff.7.html">roff(7)</A> manual got a new ESCAPE SEQUENCE REFERENCE.
+ </P>
+ <P CLASS="news">
+ 05-10-2013: version 1.12.2
+ </P>
+ <P>
+ The <A HREF="mdoc.7.html">mdoc(7)</A> to <A HREF="man.7.html">man(7)</A> converter,
+ to be called as <CODE>mandoc -Tman</CODE>, is now fully functional.
+ </P>
+ <P>
+ The <A HREF="mandoc.1.html">mandoc(1)</A> utility now supports the <CODE>-Ios</CODE> (default operating system)
+ input option, and the <CODE>-Tutf8</CODE> output mode now actually works.
+ </P>
+ <P>
+ The <A HREF="mandocdb.8.html">mandocdb(8)</A> utility no longer truncates existing databases when starting to build new ones,
+ but only replaces them when the build actually succeeds.
+ </P>
+ <P>
+ The <A HREF="man.7.html">man(7)</A> parser now supports the <EM>PD</EM> macro (paragraph distance),
+ and (for GNU man-ext compatibility only) <EM>EX</EM> (example block) and <EM>EE</EM> (example end).
+ Plus several bugfixes regarding indentation, line breaks, and vertical spacing,
+ and regarding <EM>RS</EM> following <EM>TP</EM>.
+ </P>
+ <P>
+ The <A HREF="roff.7.html">roff(7)</A> parser now supports the <EM>\f(BI</EM> (bold+italic) font escape,
+ the <EM>\z</EM> (zero cursor advance) escape and the <EM>cc</EM> (change control character)
+ and <EM>it</EM> (input line trap) requests.
+ Plus bugfixes regarding the <EM>\t</EM> (tab) escape, nested escape sequences, and conditional requests.
+ </P>
+ <P>
+ In <A HREF="mdoc.7.html">mdoc(7)</A>, several bugs were fixed related to UTF-8 output of quoting enclosures,
+ delimiter handling, list indentation and horizontal and vertical spacing,
+ formatting of the <EM>Lk</EM>, <EM>%U</EM>, and <EM>%C</EM> macros,
+ plus some bugfixes related to the handling of syntax errors like badly nested font blocks,
+ stray <EM>Ta</EM> macros outside column lists, unterminated <EM>It Xo</EM> blocks,
+ and non-text children of <EM>Nm</EM> blocks.
+ </P>
+ <P>
+ In <A HREF="tbl.7.html">tbl(7)</A>, the width of horizontal spans and the vertical spacing around tables was corrected,
+ and in <A HREF="man.7.html">man(7)</A> files, a crash was fixed that was triggered by some particular unclosed <EM>T{</EM> macros.
+ </P>
+ <P>
+ For mandoc developers, we now provide a <A HREF="tbl.3.html">tbl(3)</A> library manual and <CODE>gmdiff</CODE>,
+ a very small, very simplistic groff-versus-mandoc output comparison tool.
+ </P>
+ <H2>
+ <A>History</A>
+ </H2>
+ <UL>
+ <LI>
+ <A HREF="NEWS">Release notes</A> going back to release 1.9.15, February 18, 2010.
+ Briefly explaining the most important changes in each release in relatively easy terms.
+ Very many changes are not mentioned here.
+ </LI>
+ <LI>
+ <A HREF="history.html">Development history</A> going back to the beginning of the project, November 22, 2008.
+ One-line entries for important commits, releases, merges, hackathons and talks.
+ Makes it easy to find out who did what, and when, and when it became available where.
+ However, this is still incomplete, mentioning only a small fraction of all commits,
+ and to keep the size down, the individual entries are extremely terse and technical.
+ Feel free to look up more details and longer explanations about individual entries
+ in the ChangeLog or in CVS.
+ </LI>
+ <LI>
+ <A HREF="ChangeLog">CVS ChangeLog</A> going back to the beginning of the project.
+ Very technical information of varying quality, strictly chronological.
+ All commits are mentioned, but some messages neglect to mention some changes.
+ Partly terse, partly detailed and verbose. In any case, the ChangeLog is very long -
+ more than 25,000 lines, more than 700 kB.
+ </LI>
+ <LI>
+ <A HREF="/cgi-bin/cvsweb/?cvsroot=mdocml">CVS</A> web interface, going back to the beginning of the project.
+ Source code, diffs and commit messages for each source file. The real thing.
+ </LI>
+ </UL>
<P CLASS="foot">
<SMALL>
Copyright &#169; 2008&#8211;2011
<A CLASS="external" HREF="http://kristaps.bsd.lv">Kristaps Dzonsons</A>,
- $Date: 2012/03/24 02:07:32 $
+ &#169; 2013 Ingo Schwarze,
+ $Date: 2013/12/31 $
</SMALL>
</P>
</BODY>
diff --git a/lib.in b/lib.in
index 230a465ad3dd..334e093f727c 100644
--- a/lib.in
+++ b/lib.in
@@ -1,4 +1,4 @@
-/* $Id: lib.in,v 1.13 2012/01/28 23:46:28 joerg Exp $ */
+/* $Id: lib.in,v 1.17 2013/10/13 15:24:03 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -23,10 +23,12 @@
* Be sure to escape strings.
*/
-LINE("libarchive", "Reading and Writing Streaming Archives Library (libarchive, \\-larchive)")
+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("libbluetooth", "Bluetooth Library (libbluetooth, \\-lbluetooth)")
+LINE("libbsdxml", "eXpat XML parser library (libbsdxml, \\-lbsdxml)")
LINE("libbsm", "Basic Security Module User Library (libbsm, \\-lbsm)")
LINE("libc", "Standard C Library (libc, \\-lc)")
LINE("libc_r", "Reentrant C\\~Library (libc_r, \\-lc_r)")
@@ -37,17 +39,24 @@ LINE("libcipher", "FreeSec Crypt Library (libcipher, \\-lcipher)")
LINE("libcompat", "Compatibility Library (libcompat, \\-lcompat)")
LINE("libcrypt", "Crypt Library (libcrypt, \\-lcrypt)")
LINE("libcurses", "Curses Library (libcurses, \\-lcurses)")
+LINE("libdevattr", "Device attribute and event library (libdevattr, \\-ldevattr)")
LINE("libdevinfo", "Device and Resource Information Utility Library (libdevinfo, \\-ldevinfo)")
LINE("libdevstat", "Device Statistics Library (libdevstat, \\-ldevstat)")
LINE("libdisk", "Interface to Slice and Partition Labels Library (libdisk, \\-ldisk)")
+LINE("libdm", "Device Mapper Library (libdm, \\-ldm)")
LINE("libdwarf", "DWARF Access Library (libdwarf, \\-ldwarf)")
LINE("libedit", "Command Line Editor Library (libedit, \\-ledit)")
+LINE("libefi", "EFI Runtime Services Library (libefi, \\-lefi)")
LINE("libelf", "ELF Access Library (libelf, \\-lelf)")
LINE("libevent", "Event Notification Library (libevent, \\-levent)")
-LINE("libfetch", "File Transfer Library for URLs (libfetch, \\-lfetch)")
+LINE("libexecinfo", "Backtrace Information Library (libexecinfo, \\-lexecinfo)")
+LINE("libfetch", "File Transfer Library (libfetch, \\-lfetch)")
+LINE("libfsid", "Filesystem Identification Library (libfsid, \\-lfsid)")
+LINE("libftpio", "FTP Connection Management Library (libftpio, \\-lftpio)")
LINE("libform", "Curses Form Library (libform, \\-lform)")
-LINE("libgeom", "Userland API Library for kernel GEOM subsystem (libgeom, \\-lgeom)")
+LINE("libgeom", "Userland API Library for Kernel GEOM subsystem (libgeom, \\-lgeom)")
LINE("libgpib", "General-Purpose Instrument Bus (GPIB) library (libgpib, \\-lgpib)")
+LINE("libhammer", "HAMMER Filesystem Userland Library (libhammer, \\-lhammer)")
LINE("libi386", "i386 Architecture Library (libi386, \\-li386)")
LINE("libintl", "Internationalized Message Handling Library (libintl, \\-lintl)")
LINE("libipsec", "IPsec Policy Control Library (libipsec, \\-lipsec)")
@@ -55,37 +64,49 @@ LINE("libipx", "IPX Address Conversion Support Library (libipx, \\-lipx)")
LINE("libiscsi", "iSCSI protocol library (libiscsi, \\-liscsi)")
LINE("libisns", "Internet Storage Name Service Library (libisns, \\-lisns)")
LINE("libjail", "Jail Library (libjail, \\-ljail)")
-LINE("libkiconv", "Kernel side iconv library (libkiconv, \\-lkiconv)")
+LINE("libkcore", "Kernel Memory Core Access Library (libkcore, \\-lkcore)")
+LINE("libkiconv", "Kernel-side iconv Library (libkiconv, \\-lkiconv)")
LINE("libkse", "N:M Threading Library (libkse, \\-lkse)")
LINE("libkvm", "Kernel Data Access Library (libkvm, \\-lkvm)")
LINE("libm", "Math Library (libm, \\-lm)")
LINE("libm68k", "m68k Architecture Library (libm68k, \\-lm68k)")
LINE("libmagic", "Magic Number Recognition Library (libmagic, \\-lmagic)")
+LINE("libmandoc", "Mandoc Macro Compiler Library (libmandoc, \\-lmandoc)")
LINE("libmd", "Message Digest (MD4, MD5, etc.) Support Library (libmd, \\-lmd)")
LINE("libmemstat", "Kernel Memory Allocator Statistics Library (libmemstat, \\-lmemstat)")
LINE("libmenu", "Curses Menu Library (libmenu, \\-lmenu)")
+LINE("libmj", "Minimalist JSON library (libmj, \\-lmj)")
LINE("libnetgraph", "Netgraph User Library (libnetgraph, \\-lnetgraph)")
-LINE("libnetpgp", "Netpgp signing, verification, encryption and decryption (libnetpgp, \\-lnetpgp)")
+LINE("libnetpgp", "Netpgp Signing, Verification, Encryption and Decryption (libnetpgp, \\-lnetpgp)")
+LINE("libnetpgpverify", "Netpgp Verification (libnetpgpverify, \\-lnetpgpverify)")
+LINE("libnpf", "NPF Packet Filter Library (libnpf, \\-lnpf)")
LINE("libossaudio", "OSS Audio Emulation Library (libossaudio, \\-lossaudio)")
LINE("libpam", "Pluggable Authentication Module Library (libpam, \\-lpam)")
LINE("libpcap", "Capture Library (libpcap, \\-lpcap)")
LINE("libpci", "PCI Bus Access Library (libpci, \\-lpci)")
LINE("libpmc", "Performance Counters Library (libpmc, \\-lpmc)")
+LINE("libppath", "Property-List Paths Library (libppath, \\-lppath)")
LINE("libposix", "POSIX Compatibility Library (libposix, \\-lposix)")
+LINE("libposix1e", "POSIX.1e Security API Library (libposix1e, \\-lposix1e)")
LINE("libppath", "Property-List Paths Library (libppath, \\-lppath)")
LINE("libprop", "Property Container Object Library (libprop, \\-lprop)")
LINE("libpthread", "POSIX Threads Library (libpthread, \\-lpthread)")
LINE("libpuffs", "puffs Convenience Library (libpuffs, \\-lpuffs)")
LINE("libquota", "Disk Quota Access and Control Library (libquota, \\-lquota)")
+LINE("libradius", "RADIUS Client Library (libradius, \\-lradius)")
LINE("librefuse", "File System in Userspace Convenience Library (librefuse, \\-lrefuse)")
LINE("libresolv", "DNS Resolver Library (libresolv, \\-lresolv)")
LINE("librpcsec_gss", "RPC GSS-API Authentication Library (librpcsec_gss, \\-lrpcsec_gss)")
LINE("librpcsvc", "RPC Service Library (librpcsvc, \\-lrpcsvc)")
LINE("librt", "POSIX Real\\-time Library (librt, \\-lrt)")
+LINE("librumpclient", "Clientside Stubs for rump Kernel Remote Protocols (librumpclient, \\-lrumpclient)")
LINE("libsaslc", "Simple Authentication and Security Layer client library (libsaslc, \\-lsaslc)")
LINE("libsdp", "Bluetooth Service Discovery Protocol User Library (libsdp, \\-lsdp)")
LINE("libssp", "Buffer Overflow Protection Library (libssp, \\-lssp)")
+LINE("libstand", "Standalone Applications Library (libstand, \\-lstand)")
LINE("libSystem", "System Library (libSystem, \\-lSystem)")
+LINE("libtacplus", "TACACS+ Client Library (libtacplus, \\-ltacplus)")
+LINE("libtcplay", "TrueCrypt-compatible API library (libtcplay, \\-ltcplay)")
LINE("libtermcap", "Termcap Access Library (libtermcap, \\-ltermcap)")
LINE("libterminfo", "Terminal Information Library (libterminfo, \\-lterminfo)")
LINE("libthr", "1:1 Threading Library (libthr, \\-lthr)")
diff --git a/libman.h b/libman.h
index 4bc5128204f6..f2ba6a125630 100644
--- a/libman.h
+++ b/libman.h
@@ -1,4 +1,4 @@
-/* $Id: libman.h,v 1.55 2011/11/07 01:24:40 schwarze Exp $ */
+/* $Id: libman.h,v 1.56 2012/11/17 00:26:33 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -39,7 +39,7 @@ struct man {
struct roff *roff;
};
-#define MACRO_PROT_ARGS struct man *m, \
+#define MACRO_PROT_ARGS struct man *man, \
enum mant tok, \
int line, \
int ppos, \
@@ -61,10 +61,10 @@ extern const struct man_macro *const man_macros;
__BEGIN_DECLS
-#define man_pmsg(m, l, p, t) \
- mandoc_msg((t), (m)->parse, (l), (p), NULL)
-#define man_nmsg(m, n, t) \
- mandoc_msg((t), (m)->parse, (n)->line, (n)->pos, NULL)
+#define man_pmsg(man, l, p, t) \
+ mandoc_msg((t), (man)->parse, (l), (p), NULL)
+#define man_nmsg(man, n, t) \
+ mandoc_msg((t), (man)->parse, (n)->line, (n)->pos, NULL)
int man_word_alloc(struct man *, int, int, const char *);
int man_block_alloc(struct man *, int, int, enum mant);
int man_head_alloc(struct man *, int, int, enum mant);
diff --git a/libmandoc.h b/libmandoc.h
index de422884a214..3c005e106da9 100644
--- a/libmandoc.h
+++ b/libmandoc.h
@@ -1,6 +1,7 @@
-/* $Id: libmandoc.h,v 1.29 2011/12/02 01:37:14 schwarze Exp $ */
+/* $Id: libmandoc.h,v 1.35 2013/12/15 21:23:52 schwarze Exp $ */
/*
- * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,11 +30,6 @@ enum rofferr {
ROFF_ERR /* badness: puke and stop */
};
-enum regs {
- REG_nS = 0, /* nS register */
- REG__MAX
-};
-
__BEGIN_DECLS
struct roff;
@@ -47,12 +43,11 @@ void mandoc_vmsg(enum mandocerr, struct mparse *,
char *mandoc_getarg(struct mparse *, char **, int, int *);
char *mandoc_normdate(struct mparse *, char *, int, int);
int mandoc_eos(const char *, size_t, int);
-int mandoc_getcontrol(const char *, int *);
int mandoc_strntoi(const char *, size_t, int);
const char *mandoc_a2msec(const char*);
void mdoc_free(struct mdoc *);
-struct mdoc *mdoc_alloc(struct roff *, struct mparse *);
+struct mdoc *mdoc_alloc(struct roff *, struct mparse *, char *);
void mdoc_reset(struct mdoc *);
int mdoc_parseln(struct mdoc *, int, char *, int);
int mdoc_endparse(struct mdoc *);
@@ -68,15 +63,16 @@ int man_addspan(struct man *, const struct tbl_span *);
int man_addeqn(struct man *, const struct eqn *);
void roff_free(struct roff *);
-struct roff *roff_alloc(struct mparse *);
+struct roff *roff_alloc(enum mparset, struct mparse *);
void roff_reset(struct roff *);
enum rofferr roff_parseln(struct roff *, int,
char **, size_t *, int, int *);
void roff_endparse(struct roff *);
-int roff_regisset(const struct roff *, enum regs);
-unsigned int roff_regget(const struct roff *, enum regs);
-void roff_regunset(struct roff *, enum regs);
+void roff_setreg(struct roff *, const char *, int, char sign);
+int roff_getreg(const struct roff *, const char *);
char *roff_strdup(const struct roff *, const char *);
+int roff_getcontrol(const struct roff *,
+ const char *, int *);
#if 0
char roff_eqndelim(const struct roff *);
void roff_openeqn(struct roff *, const char *,
diff --git a/libmdoc.h b/libmdoc.h
index af1729268a44..3f14519d3b40 100644
--- a/libmdoc.h
+++ b/libmdoc.h
@@ -1,6 +1,7 @@
-/* $Id: libmdoc.h,v 1.78 2011/12/02 01:37:14 schwarze Exp $ */
+/* $Id: libmdoc.h,v 1.82 2013/10/21 23:47:58 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2013 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 +25,7 @@ enum mdoc_next {
struct mdoc {
struct mparse *parse; /* parse pointer */
+ char *defos; /* default argument for .Os */
int flags; /* parse flags */
#define MDOC_HALT (1 << 0) /* error in parse: halt */
#define MDOC_LITERAL (1 << 1) /* in a literal scope */
@@ -33,6 +35,8 @@ struct mdoc {
#define MDOC_PPHRASE (1 << 5) /* within a partial phrase */
#define MDOC_FREECOL (1 << 6) /* `It' invocation should close */
#define MDOC_SYNOPSIS (1 << 7) /* SYNOPSIS-style formatting */
+#define MDOC_KEEP (1 << 8) /* in a word keep */
+#define MDOC_SMOFF (1 << 9) /* spacing is off */
enum mdoc_next next; /* where to put the next node */
struct mdoc_node *last; /* the last node parsed */
struct mdoc_node *first; /* the first node parsed */
@@ -42,7 +46,7 @@ struct mdoc {
struct roff *roff;
};
-#define MACRO_PROT_ARGS struct mdoc *m, \
+#define MACRO_PROT_ARGS struct mdoc *mdoc, \
enum mdoct tok, \
int line, \
int ppos, \
@@ -56,8 +60,8 @@ struct mdoc_macro {
#define MDOC_PARSED (1 << 1)
#define MDOC_EXPLICIT (1 << 2)
#define MDOC_PROLOGUE (1 << 3)
-#define MDOC_IGNDELIM (1 << 4)
- /* Reserved words in arguments treated as text. */
+#define MDOC_IGNDELIM (1 << 4)
+#define MDOC_JOIN (1 << 5)
};
enum margserr {
@@ -99,13 +103,14 @@ extern const struct mdoc_macro *const mdoc_macros;
__BEGIN_DECLS
-#define mdoc_pmsg(m, l, p, t) \
- mandoc_msg((t), (m)->parse, (l), (p), NULL)
-#define mdoc_nmsg(m, n, t) \
- mandoc_msg((t), (m)->parse, (n)->line, (n)->pos, NULL)
+#define mdoc_pmsg(mdoc, l, p, t) \
+ mandoc_msg((t), (mdoc)->parse, (l), (p), NULL)
+#define mdoc_nmsg(mdoc, n, t) \
+ mandoc_msg((t), (mdoc)->parse, (n)->line, (n)->pos, NULL)
int mdoc_macro(MACRO_PROT_ARGS);
int mdoc_word_alloc(struct mdoc *,
int, int, const char *);
+void mdoc_word_append(struct mdoc *, const char *);
int mdoc_elem_alloc(struct mdoc *, int, int,
enum mdoct, struct mdoc_arg *);
int mdoc_block_alloc(struct mdoc *, int, int,
@@ -113,10 +118,10 @@ int mdoc_block_alloc(struct mdoc *, int, int,
int mdoc_head_alloc(struct mdoc *, int, int, enum mdoct);
int mdoc_tail_alloc(struct mdoc *, int, int, enum mdoct);
int mdoc_body_alloc(struct mdoc *, int, int, enum mdoct);
-int mdoc_endbody_alloc(struct mdoc *m, int line, int pos,
- enum mdoct tok, struct mdoc_node *body,
- enum mdoc_endbody end);
+int mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct,
+ struct mdoc_node *, enum mdoc_endbody);
void mdoc_node_delete(struct mdoc *, struct mdoc_node *);
+int mdoc_node_relink(struct mdoc *, struct mdoc_node *);
void mdoc_hash_init(void);
enum mdoct mdoc_hash_find(const char *);
const char *mdoc_a2att(const char *);
diff --git a/libroff.h b/libroff.h
index 0bdd5a360478..5b84c5fc4541 100644
--- a/libroff.h
+++ b/libroff.h
@@ -1,4 +1,4 @@
-/* $Id: libroff.h,v 1.27 2011/07/25 15:37:00 kristaps Exp $ */
+/* $Id: libroff.h,v 1.28 2013/05/31 21:37:17 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -31,7 +31,7 @@ struct tbl_node {
int pos; /* invocation column */
int line; /* invocation line */
enum tbl_part part;
- struct tbl opts;
+ struct tbl_opts opts;
struct tbl_row *first_row;
struct tbl_row *last_row;
struct tbl_span *first_span;
diff --git a/main.c b/main.c
index fec83fba513a..7e5c7a98aef2 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
-/* $Id: main.c,v 1.165 2011/10/06 22:29:12 kristaps Exp $ */
+/* $Id: main.c,v 1.167 2012/11/19 17:22:26 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 2012 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
@@ -85,6 +85,7 @@ main(int argc, char *argv[])
struct curparse curp;
enum mparset type;
enum mandoclevel rc;
+ char *defos;
progname = strrchr(argv[0], '/');
if (progname == NULL)
@@ -97,10 +98,24 @@ main(int argc, char *argv[])
type = MPARSE_AUTO;
curp.outtype = OUTT_ASCII;
curp.wlevel = MANDOCLEVEL_FATAL;
+ defos = NULL;
/* LINTED */
- while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
+ while (-1 != (c = getopt(argc, argv, "I:m:O:T:VW:")))
switch (c) {
+ case ('I'):
+ if (strncmp(optarg, "os=", 3)) {
+ fprintf(stderr, "-I%s: Bad argument\n",
+ optarg);
+ return((int)MANDOCLEVEL_BADARG);
+ }
+ if (defos) {
+ fprintf(stderr, "-I%s: Duplicate argument\n",
+ optarg);
+ return((int)MANDOCLEVEL_BADARG);
+ }
+ defos = mandoc_strdup(optarg + 3);
+ break;
case ('m'):
if ( ! moptions(&type, optarg))
return((int)MANDOCLEVEL_BADARG);
@@ -125,7 +140,7 @@ main(int argc, char *argv[])
/* NOTREACHED */
}
- curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp);
+ curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp, defos);
/*
* Conditionally start up the lookaside buffer before parsing.
@@ -152,6 +167,7 @@ main(int argc, char *argv[])
(*curp.outfree)(curp.outdata);
if (curp.mp)
mparse_free(curp.mp);
+ free(defos);
return((int)rc);
}
@@ -170,12 +186,12 @@ usage(void)
fprintf(stderr, "usage: %s "
"[-V] "
- "[-foption] "
+ "[-Ios=name] "
"[-mformat] "
"[-Ooption] "
"[-Toutput] "
- "[-Wlevel] "
- "[file...]\n",
+ "[-Wlevel]\n"
+ "\t [file ...]\n",
progname);
exit((int)MANDOCLEVEL_BADARG);
diff --git a/man.7 b/man.7
index 1715a7ca119b..f2f4d1d8c099 100644
--- a/man.7
+++ b/man.7
@@ -1,7 +1,7 @@
-.\" $Id: man.7,v 1.113 2012/01/03 15:16:24 kristaps Exp $
+.\" $Id: man.7,v 1.120 2013/09/16 22:58:57 schwarze Exp $
.\"
-.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2011, 2012 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: January 3 2012 $
+.Dd $Mdocdate: September 16 2013 $
.Dt MAN 7
.Os
.Sh NAME
@@ -253,6 +253,7 @@ in the alphabetical reference below.
.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 \&br Ta force output line break in text mode (no arguments)
.It Sx \&sp Ta force vertical space: Op Ar height
.It Sx fi , nf Ta fill mode and no-fill mode (no arguments)
@@ -272,10 +273,6 @@ in the alphabetical reference below.
.It Sx RB Ta alternate between roman and boldface fonts
.It Sx RI Ta alternate between roman and italic fonts
.El
-.Ss Semantic markup
-.Bl -column "PP, LP, P" description
-.It Sx OP Ta optional arguments
-.El
.Sh MACRO REFERENCE
This section is a canonical reference to all macros, arranged
alphabetically.
@@ -343,6 +340,18 @@ and
.Ss \&DT
Has no effect.
Included for compatibility.
+.Ss \&EE
+This is a non-standard GNU extension, included only for compatibility.
+In
+.Xr mandoc 1 ,
+it does the same as
+.Sx \&fi .
+.Ss \&EX
+This is a non-standard GNU extension, included only for compatibility.
+In
+.Xr mandoc 1 ,
+it does the same as
+.Sx \&nf .
.Ss \&HP
Begin a paragraph whose initial output line is left-justified, but
subsequent output lines are indented, with the following syntax:
@@ -353,8 +362,9 @@ subsequent output lines are indented, with the following syntax:
.Pp
The
.Cm width
-argument must conform to
-.Sx Scaling Widths .
+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
@@ -396,8 +406,9 @@ Begin an indented paragraph with the following syntax:
.Pp
The
.Cm width
-argument defines the width of the left margin and is defined by
-.Sx Scaling Widths .
+argument is a
+.Xr roff 7
+scaling width defining the left margin.
It's saved for later paragraph left-margins; if unspecified, the saved or
default width is used.
.Pp
@@ -443,7 +454,8 @@ and
.Sx \&TP .
.Ss \&OP
Optional command-line argument.
-This has the following syntax:
+This is a non-standard GNU extension, included only for compatibility.
+It has the following syntax:
.Bd -filled -offset indent
.Pf \. Sx \&OP
.Cm key Op Cm value
@@ -465,6 +477,36 @@ See also
.Sx \&PP ,
and
.Sx \&TP .
+.Ss \&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 Cm height
+.Ed
+.Pp
+The
+.Cm height
+argument is a
+.Xr roff 7
+scaling width.
+It defaults to
+.Cm 1v .
+If the unit is omitted,
+.Cm v
+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 ,
+and
+.Sx \&TP .
.Ss \&PP
Synonym for
.Sx \&LP .
@@ -529,8 +571,9 @@ This has the following syntax:
.Pp
The
.Cm width
-argument must conform to
-.Sx Scaling Widths .
+argument is a
+.Xr roff 7
+scaling width.
If not specified, the saved or default width is used.
.Pp
See also
@@ -595,8 +638,9 @@ The syntax is as follows:
.Pp
The
.Cm width
-argument must conform to
-.Sx Scaling Widths .
+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
@@ -609,7 +653,8 @@ and
.Sx \&PP .
.Ss \&UC
Sets the volume for the footer for compatibility with man pages from
-BSD releases.
+.Bx
+releases.
The optional first argument specifies which release it is from.
.Ss \&br
Breaks the current line.
@@ -653,10 +698,10 @@ Insert vertical spaces into output with the following syntax:
.Op Cm height
.Ed
.Pp
-Insert
+The
.Cm height
-spaces, which must conform to
-.Sx Scaling Widths .
+argument is a scaling width as described in
+.Xr roff 7 .
If 0, this is equivalent to the
.Sx \&br
macro.
@@ -904,8 +949,7 @@ utility written by Kristaps Dzonsons appeared in
This
.Nm
reference was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
.Sh CAVEATS
Do not use this language.
Use
diff --git a/man.c b/man.c
index 1bea5610e3d7..e6e1c2899209 100644
--- a/man.c
+++ b/man.c
@@ -1,4 +1,4 @@
-/* $Id: man.c,v 1.115 2012/01/03 15:16:24 kristaps Exp $ */
+/* $Id: man.c,v 1.121 2013/11/10 22:54:40 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -40,7 +40,8 @@ const char *const __man_macronames[MAN_MAX] = {
"RI", "na", "sp", "nf",
"fi", "RE", "RS", "DT",
"UC", "PD", "AT", "in",
- "ft", "OP"
+ "ft", "OP", "EX", "EE",
+ "UR", "UE"
};
const char * const *man_macronames = __man_macronames;
@@ -60,20 +61,20 @@ static int man_descope(struct man *, int, int);
const struct man_node *
-man_node(const struct man *m)
+man_node(const struct man *man)
{
- assert( ! (MAN_HALT & m->flags));
- return(m->first);
+ assert( ! (MAN_HALT & man->flags));
+ return(man->first);
}
const struct man_meta *
-man_meta(const struct man *m)
+man_meta(const struct man *man)
{
- assert( ! (MAN_HALT & m->flags));
- return(&m->meta);
+ assert( ! (MAN_HALT & man->flags));
+ return(&man->meta);
}
@@ -112,28 +113,28 @@ man_alloc(struct roff *roff, struct mparse *parse)
int
-man_endparse(struct man *m)
+man_endparse(struct man *man)
{
- assert( ! (MAN_HALT & m->flags));
- if (man_macroend(m))
+ assert( ! (MAN_HALT & man->flags));
+ if (man_macroend(man))
return(1);
- m->flags |= MAN_HALT;
+ man->flags |= MAN_HALT;
return(0);
}
int
-man_parseln(struct man *m, int ln, char *buf, int offs)
+man_parseln(struct man *man, int ln, char *buf, int offs)
{
- m->flags |= MAN_NEWLINE;
+ man->flags |= MAN_NEWLINE;
- assert( ! (MAN_HALT & m->flags));
+ assert( ! (MAN_HALT & man->flags));
- return (mandoc_getcontrol(buf, &offs) ?
- man_pmacro(m, ln, buf, offs) :
- man_ptext(m, ln, buf, offs));
+ return (roff_getcontrol(man->roff, buf, &offs) ?
+ man_pmacro(man, ln, buf, offs) :
+ man_ptext(man, ln, buf, offs));
}
@@ -157,16 +158,16 @@ man_free1(struct man *man)
static void
-man_alloc1(struct man *m)
+man_alloc1(struct man *man)
{
- memset(&m->meta, 0, sizeof(struct man_meta));
- m->flags = 0;
- m->last = mandoc_calloc(1, sizeof(struct man_node));
- m->first = m->last;
- m->last->type = MAN_ROOT;
- m->last->tok = MAN_MAX;
- m->next = MAN_NEXT_CHILD;
+ memset(&man->meta, 0, sizeof(struct man_meta));
+ man->flags = 0;
+ man->last = mandoc_calloc(1, sizeof(struct man_node));
+ man->first = man->last;
+ man->last->type = MAN_ROOT;
+ man->last->tok = MAN_MAX;
+ man->next = MAN_NEXT_CHILD;
}
@@ -234,7 +235,7 @@ man_node_append(struct man *man, struct man_node *p)
static struct man_node *
-man_node_alloc(struct man *m, int line, int pos,
+man_node_alloc(struct man *man, int line, int pos,
enum man_type type, enum mant tok)
{
struct man_node *p;
@@ -245,89 +246,89 @@ man_node_alloc(struct man *m, int line, int pos,
p->type = type;
p->tok = tok;
- if (MAN_NEWLINE & m->flags)
+ if (MAN_NEWLINE & man->flags)
p->flags |= MAN_LINE;
- m->flags &= ~MAN_NEWLINE;
+ man->flags &= ~MAN_NEWLINE;
return(p);
}
int
-man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
+man_elem_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
- p = man_node_alloc(m, line, pos, MAN_ELEM, tok);
- if ( ! man_node_append(m, p))
+ p = man_node_alloc(man, line, pos, MAN_ELEM, tok);
+ if ( ! man_node_append(man, p))
return(0);
- m->next = MAN_NEXT_CHILD;
+ man->next = MAN_NEXT_CHILD;
return(1);
}
int
-man_tail_alloc(struct man *m, int line, int pos, enum mant tok)
+man_tail_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
- p = man_node_alloc(m, line, pos, MAN_TAIL, tok);
- if ( ! man_node_append(m, p))
+ p = man_node_alloc(man, line, pos, MAN_TAIL, tok);
+ if ( ! man_node_append(man, p))
return(0);
- m->next = MAN_NEXT_CHILD;
+ man->next = MAN_NEXT_CHILD;
return(1);
}
int
-man_head_alloc(struct man *m, int line, int pos, enum mant tok)
+man_head_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
- p = man_node_alloc(m, line, pos, MAN_HEAD, tok);
- if ( ! man_node_append(m, p))
+ p = man_node_alloc(man, line, pos, MAN_HEAD, tok);
+ if ( ! man_node_append(man, p))
return(0);
- m->next = MAN_NEXT_CHILD;
+ man->next = MAN_NEXT_CHILD;
return(1);
}
int
-man_body_alloc(struct man *m, int line, int pos, enum mant tok)
+man_body_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
- p = man_node_alloc(m, line, pos, MAN_BODY, tok);
- if ( ! man_node_append(m, p))
+ p = man_node_alloc(man, line, pos, MAN_BODY, tok);
+ if ( ! man_node_append(man, p))
return(0);
- m->next = MAN_NEXT_CHILD;
+ man->next = MAN_NEXT_CHILD;
return(1);
}
int
-man_block_alloc(struct man *m, int line, int pos, enum mant tok)
+man_block_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
- p = man_node_alloc(m, line, pos, MAN_BLOCK, tok);
- if ( ! man_node_append(m, p))
+ p = man_node_alloc(man, line, pos, MAN_BLOCK, tok);
+ if ( ! man_node_append(man, p))
return(0);
- m->next = MAN_NEXT_CHILD;
+ man->next = MAN_NEXT_CHILD;
return(1);
}
int
-man_word_alloc(struct man *m, int line, int pos, const char *word)
+man_word_alloc(struct man *man, int line, int pos, const char *word)
{
struct man_node *n;
- n = man_node_alloc(m, line, pos, MAN_TEXT, MAN_MAX);
- n->string = roff_strdup(m->roff, word);
+ n = man_node_alloc(man, line, pos, MAN_TEXT, MAN_MAX);
+ n->string = roff_strdup(man->roff, word);
- if ( ! man_node_append(m, n))
+ if ( ! man_node_append(man, n))
return(0);
- m->next = MAN_NEXT_SIBLING;
+ man->next = MAN_NEXT_SIBLING;
return(1);
}
@@ -347,52 +348,52 @@ man_node_free(struct man_node *p)
void
-man_node_delete(struct man *m, struct man_node *p)
+man_node_delete(struct man *man, struct man_node *p)
{
while (p->child)
- man_node_delete(m, p->child);
+ man_node_delete(man, p->child);
- man_node_unlink(m, p);
+ man_node_unlink(man, p);
man_node_free(p);
}
int
-man_addeqn(struct man *m, const struct eqn *ep)
+man_addeqn(struct man *man, const struct eqn *ep)
{
struct man_node *n;
- assert( ! (MAN_HALT & m->flags));
+ assert( ! (MAN_HALT & man->flags));
- n = man_node_alloc(m, ep->ln, ep->pos, MAN_EQN, MAN_MAX);
+ n = man_node_alloc(man, ep->ln, ep->pos, MAN_EQN, MAN_MAX);
n->eqn = ep;
- if ( ! man_node_append(m, n))
+ if ( ! man_node_append(man, n))
return(0);
- m->next = MAN_NEXT_SIBLING;
- return(man_descope(m, ep->ln, ep->pos));
+ man->next = MAN_NEXT_SIBLING;
+ return(man_descope(man, ep->ln, ep->pos));
}
int
-man_addspan(struct man *m, const struct tbl_span *sp)
+man_addspan(struct man *man, const struct tbl_span *sp)
{
struct man_node *n;
- assert( ! (MAN_HALT & m->flags));
+ assert( ! (MAN_HALT & man->flags));
- n = man_node_alloc(m, sp->line, 0, MAN_TBL, MAN_MAX);
+ n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX);
n->span = sp;
- if ( ! man_node_append(m, n))
+ if ( ! man_node_append(man, n))
return(0);
- m->next = MAN_NEXT_SIBLING;
- return(man_descope(m, sp->line, 0));
+ man->next = MAN_NEXT_SIBLING;
+ return(man_descope(man, sp->line, 0));
}
static int
-man_descope(struct man *m, int line, int offs)
+man_descope(struct man *man, int line, int offs)
{
/*
* Co-ordinate what happens with having a next-line scope open:
@@ -400,44 +401,51 @@ man_descope(struct man *m, int line, int offs)
* out the block scope (also if applicable).
*/
- if (MAN_ELINE & m->flags) {
- m->flags &= ~MAN_ELINE;
- if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
+ if (MAN_ELINE & man->flags) {
+ man->flags &= ~MAN_ELINE;
+ if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
return(0);
}
- if ( ! (MAN_BLINE & m->flags))
+ if ( ! (MAN_BLINE & man->flags))
return(1);
- m->flags &= ~MAN_BLINE;
+ man->flags &= ~MAN_BLINE;
- if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
+ if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
return(0);
- return(man_body_alloc(m, line, offs, m->last->tok));
+ return(man_body_alloc(man, line, offs, man->last->tok));
}
static int
-man_ptext(struct man *m, int line, char *buf, int offs)
+man_ptext(struct man *man, int line, char *buf, int offs)
{
int i;
/* Literal free-form text whitespace is preserved. */
- if (MAN_LITERAL & m->flags) {
- if ( ! man_word_alloc(m, line, offs, buf + offs))
+ if (MAN_LITERAL & man->flags) {
+ if ( ! man_word_alloc(man, line, offs, buf + offs))
return(0);
- return(man_descope(m, line, offs));
+ return(man_descope(man, line, offs));
}
- /* Pump blank lines directly into the backend. */
-
for (i = offs; ' ' == buf[i]; i++)
/* Skip leading whitespace. */ ;
+ /*
+ * Blank lines are ignored right after headings
+ * but add a single vertical space elsewhere.
+ */
+
if ('\0' == buf[i]) {
/* Allocate a blank entry. */
- if ( ! man_word_alloc(m, line, offs, ""))
- return(0);
- return(man_descope(m, line, offs));
+ if (MAN_SH != man->last->tok &&
+ MAN_SS != man->last->tok) {
+ if ( ! man_elem_alloc(man, line, offs, MAN_sp))
+ return(0);
+ man->next = MAN_NEXT_SIBLING;
+ }
+ return(1);
}
/*
@@ -450,7 +458,7 @@ man_ptext(struct man *m, int line, char *buf, int offs)
if (' ' == buf[i - 1] || '\t' == buf[i - 1]) {
if (i > 1 && '\\' != buf[i - 2])
- man_pmsg(m, line, i - 1, MANDOCERR_EOLNSPACE);
+ man_pmsg(man, line, i - 1, MANDOCERR_EOLNSPACE);
for (--i; i && ' ' == buf[i]; i--)
/* Spin back to non-space. */ ;
@@ -461,7 +469,7 @@ man_ptext(struct man *m, int line, char *buf, int offs)
buf[i] = '\0';
}
- if ( ! man_word_alloc(m, line, offs, buf + offs))
+ if ( ! man_word_alloc(man, line, offs, buf + offs))
return(0);
/*
@@ -472,13 +480,13 @@ man_ptext(struct man *m, int line, char *buf, int offs)
assert(i);
if (mandoc_eos(buf, (size_t)i, 0))
- m->last->flags |= MAN_EOS;
+ man->last->flags |= MAN_EOS;
- return(man_descope(m, line, offs));
+ return(man_descope(man, line, offs));
}
static int
-man_pmacro(struct man *m, int ln, char *buf, int offs)
+man_pmacro(struct man *man, int ln, char *buf, int offs)
{
int i, ppos;
enum mant tok;
@@ -486,7 +494,7 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
struct man_node *n;
if ('"' == buf[offs]) {
- man_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
+ man_pmsg(man, ln, offs, MANDOCERR_BADCOMMENT);
return(1);
} else if ('\0' == buf[offs])
return(1);
@@ -508,7 +516,7 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
if (MAN_MAX == tok) {
- mandoc_vmsg(MANDOCERR_MACRO, m->parse, ln,
+ mandoc_vmsg(MANDOCERR_MACRO, man->parse, ln,
ppos, "%s", buf + ppos - 1);
return(1);
}
@@ -524,7 +532,7 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
*/
if ('\0' == buf[offs] && ' ' == buf[offs - 1])
- man_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
+ man_pmsg(man, ln, offs - 1, MANDOCERR_EOLNSPACE);
/*
* Remove prior ELINE macro, as it's being clobbered by a new
@@ -533,8 +541,8 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
*/
if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
- m->flags & MAN_ELINE) {
- n = m->last;
+ man->flags & MAN_ELINE) {
+ n = man->last;
assert(MAN_TEXT != n->type);
/* Remove repeated NSCOPED macros causing ELINE. */
@@ -542,20 +550,20 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
if (MAN_NSCOPED & man_macros[n->tok].flags)
n = n->parent;
- mandoc_vmsg(MANDOCERR_LINESCOPE, m->parse, n->line,
+ mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line,
n->pos, "%s breaks %s", man_macronames[tok],
man_macronames[n->tok]);
- man_node_delete(m, n);
- m->flags &= ~MAN_ELINE;
+ man_node_delete(man, n);
+ man->flags &= ~MAN_ELINE;
}
/*
* Remove prior BLINE macro that is being clobbered.
*/
- if ((m->flags & MAN_BLINE) &&
+ if ((man->flags & MAN_BLINE) &&
(MAN_BSCOPE & man_macros[tok].flags)) {
- n = m->last;
+ n = man->last;
/* Might be a text node like 8 in
* .TP 8
@@ -573,12 +581,12 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
assert(MAN_BLOCK == n->type);
assert(MAN_SCOPED & man_macros[n->tok].flags);
- mandoc_vmsg(MANDOCERR_LINESCOPE, m->parse, n->line,
+ mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line,
n->pos, "%s breaks %s", man_macronames[tok],
man_macronames[n->tok]);
- man_node_delete(m, n);
- m->flags &= ~MAN_BLINE;
+ man_node_delete(man, n);
+ man->flags &= ~MAN_BLINE;
}
/*
@@ -587,13 +595,13 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
* when they exit.
*/
- if (MAN_BLINE & m->flags)
- m->flags |= MAN_BPLINE;
+ if (MAN_BLINE & man->flags)
+ man->flags |= MAN_BPLINE;
/* Call to handler... */
assert(man_macros[tok].fp);
- if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &offs, buf))
+ if ( ! (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf))
goto err;
/*
@@ -601,19 +609,19 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
* above-parsed macro, so return.
*/
- if ( ! (MAN_BPLINE & m->flags)) {
- m->flags &= ~MAN_ILINE;
+ if ( ! (MAN_BPLINE & man->flags)) {
+ man->flags &= ~MAN_ILINE;
return(1);
}
- m->flags &= ~MAN_BPLINE;
+ man->flags &= ~MAN_BPLINE;
/*
* If we're in a block scope, then allow this macro to slip by
* without closing scope around it.
*/
- if (MAN_ILINE & m->flags) {
- m->flags &= ~MAN_ILINE;
+ if (MAN_ILINE & man->flags) {
+ man->flags &= ~MAN_ILINE;
return(1);
}
@@ -622,30 +630,30 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
* now, as the next line will close out the block scope.
*/
- if (MAN_ELINE & m->flags)
+ if (MAN_ELINE & man->flags)
return(1);
/* Close out the block scope opened in the prior line. */
- assert(MAN_BLINE & m->flags);
- m->flags &= ~MAN_BLINE;
+ assert(MAN_BLINE & man->flags);
+ man->flags &= ~MAN_BLINE;
- if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
+ if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX))
return(0);
- return(man_body_alloc(m, ln, ppos, m->last->tok));
+ return(man_body_alloc(man, ln, ppos, man->last->tok));
err: /* Error out. */
- m->flags |= MAN_HALT;
+ man->flags |= MAN_HALT;
return(0);
}
/*
- * Unlink a node from its context. If "m" is provided, the last parse
+ * Unlink a node from its context. If "man" is provided, the last parse
* point will also be adjusted accordingly.
*/
static void
-man_node_unlink(struct man *m, struct man_node *n)
+man_node_unlink(struct man *man, struct man_node *n)
{
/* Adjust siblings. */
@@ -665,26 +673,26 @@ man_node_unlink(struct man *m, struct man_node *n)
/* Adjust parse point, if applicable. */
- if (m && m->last == n) {
+ if (man && man->last == n) {
/*XXX: this can occur when bailing from validation. */
/*assert(NULL == n->next);*/
if (n->prev) {
- m->last = n->prev;
- m->next = MAN_NEXT_SIBLING;
+ man->last = n->prev;
+ man->next = MAN_NEXT_SIBLING;
} else {
- m->last = n->parent;
- m->next = MAN_NEXT_CHILD;
+ man->last = n->parent;
+ man->next = MAN_NEXT_CHILD;
}
}
- if (m && m->first == n)
- m->first = NULL;
+ if (man && man->first == n)
+ man->first = NULL;
}
const struct mparse *
-man_mparse(const struct man *m)
+man_mparse(const struct man *man)
{
- assert(m && m->parse);
- return(m->parse);
+ assert(man && man->parse);
+ return(man->parse);
}
diff --git a/man.cgi.7 b/man.cgi.7
index b7afd84b907a..ec927ca9b10f 100644
--- a/man.cgi.7
+++ b/man.cgi.7
@@ -1,4 +1,4 @@
-.Dd $Mdocdate: March 24 2012 $
+.Dd $Mdocdate: July 13 2013 $
.Dt MAN.CGI 7
.Os
.Sh NAME
@@ -114,8 +114,7 @@ However, the results may not be quite the same.
The
.Nm
utility was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
.Sh CAVEATS
If you're running in a jailed web-server, make sure the
.Pa /tmp
diff --git a/man.h b/man.h
index 4fc3934e6f6f..ef9480f2768c 100644
--- a/man.h
+++ b/man.h
@@ -1,4 +1,4 @@
-/* $Id: man.h,v 1.60 2012/01/03 15:16:24 kristaps Exp $ */
+/* $Id: man.h,v 1.62 2013/10/17 20:54:58 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -52,6 +52,10 @@ enum mant {
MAN_in,
MAN_ft,
MAN_OP,
+ MAN_EX,
+ MAN_EE,
+ MAN_UR,
+ MAN_UE,
MAN_MAX
};
diff --git a/man_html.c b/man_html.c
index a76ea2d70708..2c4e220a1181 100644
--- a/man_html.c
+++ b/man_html.c
@@ -1,6 +1,7 @@
-/* $Id: man_html.c,v 1.86 2012/01/03 15:16:24 kristaps Exp $ */
+/* $Id: man_html.c,v 1.90 2013/10/17 20:54:58 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2013 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,7 +38,7 @@
#define INDENT 5
-#define MAN_ARGS const struct man_meta *m, \
+#define MAN_ARGS const struct man_meta *man, \
const struct man_node *n, \
struct mhtml *mh, \
struct html *h
@@ -70,6 +71,7 @@ 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_UR_pre(MAN_ARGS);
static int man_alt_pre(MAN_ARGS);
static int man_br_pre(MAN_ARGS);
static int man_ign_pre(MAN_ARGS);
@@ -113,6 +115,10 @@ static const struct htmlman mans[MAN_MAX] = {
{ man_in_pre, NULL }, /* in */
{ man_ign_pre, NULL }, /* ft */
{ man_OP_pre, NULL }, /* OP */
+ { man_literal_pre, NULL }, /* EX */
+ { man_literal_pre, NULL }, /* EE */
+ { man_UR_pre, NULL }, /* UR */
+ { NULL, NULL }, /* UE */
};
/*
@@ -139,12 +145,12 @@ print_bvspace(struct html *h, const struct man_node *n)
}
void
-html_man(void *arg, const struct man *m)
+html_man(void *arg, const struct man *man)
{
struct mhtml mh;
memset(&mh, 0, sizeof(struct mhtml));
- print_man(man_meta(m), man_node(m), &mh, (struct html *)arg);
+ print_man(man_meta(man), man_node(man), &mh, (struct html *)arg);
putchar('\n');
}
@@ -160,14 +166,14 @@ print_man(MAN_ARGS)
print_gen_decls(h);
t = print_otag(h, TAG_HTML, 0, NULL);
tt = print_otag(h, TAG_HEAD, 0, NULL);
- print_man_head(m, n, mh, h);
+ print_man_head(man, n, mh, h);
print_tagq(h, tt);
print_otag(h, TAG_BODY, 0, NULL);
print_otag(h, TAG_DIV, 1, &tag);
} else
t = print_otag(h, TAG_DIV, 1, &tag);
- print_man_nodelist(m, n, mh, h);
+ print_man_nodelist(man, n, mh, h);
print_tagq(h, t);
}
@@ -178,9 +184,9 @@ print_man_head(MAN_ARGS)
{
print_gen_head(h);
- assert(m->title);
- assert(m->msec);
- bufcat_fmt(h, "%s(%s)", m->title, m->msec);
+ assert(man->title);
+ assert(man->msec);
+ bufcat_fmt(h, "%s(%s)", man->title, man->msec);
print_otag(h, TAG_TITLE, 0, NULL);
print_text(h, h->buf);
}
@@ -190,9 +196,9 @@ static void
print_man_nodelist(MAN_ARGS)
{
- print_man_node(m, n, mh, h);
+ print_man_node(man, n, mh, h);
if (n->next)
- print_man_nodelist(m, n->next, mh, h);
+ print_man_nodelist(man, n->next, mh, h);
}
@@ -207,7 +213,7 @@ print_man_node(MAN_ARGS)
switch (n->type) {
case (MAN_ROOT):
- man_root_pre(m, n, mh, h);
+ man_root_pre(man, n, mh, h);
break;
case (MAN_TEXT):
/*
@@ -258,25 +264,25 @@ print_man_node(MAN_ARGS)
t = h->tags.head;
}
if (mans[n->tok].pre)
- child = (*mans[n->tok].pre)(m, n, mh, h);
+ child = (*mans[n->tok].pre)(man, n, mh, h);
break;
}
if (child && n->child)
- print_man_nodelist(m, n->child, mh, h);
+ print_man_nodelist(man, n->child, mh, h);
/* This will automatically close out any font scope. */
print_stagq(h, t);
switch (n->type) {
case (MAN_ROOT):
- man_root_post(m, n, mh, h);
+ man_root_post(man, n, mh, h);
break;
case (MAN_EQN):
break;
default:
if (mans[n->tok].post)
- (*mans[n->tok].post)(m, n, mh, h);
+ (*mans[n->tok].post)(man, n, mh, h);
break;
}
}
@@ -304,12 +310,12 @@ man_root_pre(MAN_ARGS)
char b[BUFSIZ], title[BUFSIZ];
b[0] = 0;
- if (m->vol)
- (void)strlcat(b, m->vol, BUFSIZ);
+ if (man->vol)
+ (void)strlcat(b, man->vol, BUFSIZ);
- assert(m->title);
- assert(m->msec);
- snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
+ assert(man->title);
+ assert(man->msec);
+ snprintf(title, BUFSIZ - 1, "%s(%s)", man->title, man->msec);
PAIR_SUMMARY_INIT(&tag[0], "Document Header");
PAIR_CLASS_INIT(&tag[1], "head");
@@ -363,16 +369,16 @@ man_root_post(MAN_ARGS)
PAIR_CLASS_INIT(&tag[0], "foot-date");
print_otag(h, TAG_TD, 1, tag);
- assert(m->date);
- print_text(h, m->date);
+ assert(man->date);
+ print_text(h, man->date);
print_stagq(h, tt);
PAIR_CLASS_INIT(&tag[0], "foot-os");
PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
print_otag(h, TAG_TD, 2, tag);
- if (m->source)
- print_text(h, m->source);
+ if (man->source)
+ print_text(h, man->source);
print_tagq(h, t);
}
@@ -468,7 +474,7 @@ man_alt_pre(MAN_ARGS)
if (TAG_MAX != fp)
t = print_otag(h, fp, 0, NULL);
- print_man_node(m, nn, mh, h);
+ print_man_node(man, nn, mh, h);
if (t)
print_tagq(h, t);
@@ -543,14 +549,14 @@ man_IP_pre(MAN_ARGS)
/* For IP, only print the first header element. */
if (MAN_IP == n->tok && n->child)
- print_man_node(m, n->child, mh, h);
+ print_man_node(man, n->child, mh, h);
/* For TP, only print next-line header elements. */
if (MAN_TP == n->tok)
for (nn = n->child; nn; nn = nn->next)
if (nn->line > n->line)
- print_man_node(m, nn, mh, h);
+ print_man_node(man, nn, mh, h);
return(0);
}
@@ -638,7 +644,7 @@ static int
man_literal_pre(MAN_ARGS)
{
- if (MAN_nf != n->tok) {
+ if (MAN_fi == n->tok || MAN_EE == n->tok) {
print_otag(h, TAG_BR, 0, NULL);
mh->fl &= ~MANH_LITERAL;
} else
@@ -686,3 +692,27 @@ man_RS_pre(MAN_ARGS)
print_otag(h, TAG_DIV, 1, &tag);
return(1);
}
+
+/* ARGSUSED */
+static int
+man_UR_pre(MAN_ARGS)
+{
+ struct htmlpair tag[2];
+
+ n = n->child;
+ assert(MAN_HEAD == n->type);
+ if (n->nchild) {
+ assert(MAN_TEXT == n->child->type);
+ PAIR_CLASS_INIT(&tag[0], "link-ext");
+ PAIR_HREF_INIT(&tag[1], n->child->string);
+ print_otag(h, TAG_A, 2, tag);
+ }
+
+ assert(MAN_BODY == n->next->type);
+ if (n->next->nchild)
+ n = n->next;
+
+ print_man_nodelist(man, n->child, mh, h);
+
+ return(0);
+}
diff --git a/man_macro.c b/man_macro.c
index 4bbbc4fa7f16..479d0484c41f 100644
--- a/man_macro.c
+++ b/man_macro.c
@@ -1,6 +1,8 @@
-/* $Id: man_macro.c,v 1.71 2012/01/03 15:16:24 kristaps Exp $ */
+/* $Id: man_macro.c,v 1.79 2013/12/25 00:50:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -77,7 +79,7 @@ const struct man_macro __man_macros[MAN_MAX] = {
{ in_line_eoln, MAN_BSCOPE }, /* nf */
{ in_line_eoln, MAN_BSCOPE }, /* fi */
{ blk_close, 0 }, /* RE */
- { blk_exp, MAN_EXPLICIT }, /* RS */
+ { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* RS */
{ in_line_eoln, 0 }, /* DT */
{ in_line_eoln, 0 }, /* UC */
{ in_line_eoln, 0 }, /* PD */
@@ -85,6 +87,10 @@ const struct man_macro __man_macros[MAN_MAX] = {
{ in_line_eoln, 0 }, /* in */
{ in_line_eoln, 0 }, /* ft */
{ in_line_eoln, 0 }, /* OP */
+ { in_line_eoln, MAN_BSCOPE }, /* EX */
+ { in_line_eoln, MAN_BSCOPE }, /* EE */
+ { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */
+ { blk_close, 0 }, /* UE */
};
const struct man_macro * const man_macros = __man_macros;
@@ -94,7 +100,7 @@ const struct man_macro * const man_macros = __man_macros;
* Warn when "n" is an explicit non-roff macro.
*/
static void
-rew_warn(struct man *m, struct man_node *n, enum mandocerr er)
+rew_warn(struct man *man, struct man_node *n, enum mandocerr er)
{
if (er == MANDOCERR_MAX || MAN_BLOCK != n->type)
@@ -105,7 +111,7 @@ rew_warn(struct man *m, struct man_node *n, enum mandocerr er)
return;
assert(er < MANDOCERR_FATAL);
- man_nmsg(m, n, er);
+ man_nmsg(man, n, er);
}
@@ -114,33 +120,33 @@ rew_warn(struct man *m, struct man_node *n, enum mandocerr er)
* will be used if an explicit block scope is being closed out.
*/
int
-man_unscope(struct man *m, const struct man_node *to,
+man_unscope(struct man *man, const struct man_node *to,
enum mandocerr er)
{
struct man_node *n;
assert(to);
- m->next = MAN_NEXT_SIBLING;
+ man->next = MAN_NEXT_SIBLING;
/* LINTED */
- while (m->last != to) {
+ while (man->last != to) {
/*
* Save the parent here, because we may delete the
- * m->last node in the post-validation phase and reset
- * it to m->last->parent, causing a step in the closing
+ * man->last node in the post-validation phase and reset
+ * it to man->last->parent, causing a step in the closing
* out to be lost.
*/
- n = m->last->parent;
- rew_warn(m, m->last, er);
- if ( ! man_valid_post(m))
+ n = man->last->parent;
+ rew_warn(man, man->last, er);
+ if ( ! man_valid_post(man))
return(0);
- m->last = n;
- assert(m->last);
+ man->last = n;
+ assert(man->last);
}
- rew_warn(m, m->last, er);
- if ( ! man_valid_post(m))
+ rew_warn(man, man->last, er);
+ if ( ! man_valid_post(man))
return(0);
return(1);
@@ -183,8 +189,12 @@ rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
return(REW_NOHALT);
/* First: rewind to ourselves. */
- if (type == n->type && tok == n->tok)
- return(REW_REWIND);
+ if (type == n->type && tok == n->tok) {
+ if (MAN_EXPLICIT & man_macros[n->tok].flags)
+ return(REW_HALT);
+ else
+ return(REW_REWIND);
+ }
/*
* Next follow the implicit scope-smashings as defined by man.7:
@@ -200,6 +210,10 @@ rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
return(c);
break;
case (MAN_RS):
+ /* Preserve empty paragraphs before RS. */
+ if (0 == n->nchild && (MAN_P == n->tok ||
+ MAN_PP == n->tok || MAN_LP == n->tok))
+ return(REW_HALT);
/* Rewind to a subsection, if a block. */
if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
return(c);
@@ -230,13 +244,13 @@ rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
* scopes. When a scope is closed, it must be validated and actioned.
*/
static int
-rew_scope(enum man_type type, struct man *m, enum mant tok)
+rew_scope(enum man_type type, struct man *man, enum mant tok)
{
struct man_node *n;
enum rew c;
/* LINTED */
- for (n = m->last; n; n = n->parent) {
+ for (n = man->last; n; n = n->parent) {
/*
* Whether we should stop immediately (REW_HALT), stop
* and rewind until this point (REW_REWIND), or keep
@@ -255,7 +269,7 @@ rew_scope(enum man_type type, struct man *m, enum mant tok)
*/
assert(n);
- return(man_unscope(m, n, MANDOCERR_MAX));
+ return(man_unscope(man, n, MANDOCERR_MAX));
}
@@ -273,22 +287,24 @@ blk_close(MACRO_PROT_ARGS)
case (MAN_RE):
ntok = MAN_RS;
break;
+ case (MAN_UE):
+ ntok = MAN_UR;
+ break;
default:
abort();
/* NOTREACHED */
}
- for (nn = m->last->parent; nn; nn = nn->parent)
- if (ntok == nn->tok)
+ for (nn = man->last->parent; nn; nn = nn->parent)
+ if (ntok == nn->tok && MAN_BLOCK == nn->type)
break;
- if (NULL == nn)
- man_pmsg(m, line, ppos, MANDOCERR_NOSCOPE);
-
- if ( ! rew_scope(MAN_BODY, m, ntok))
- return(0);
- if ( ! rew_scope(MAN_BLOCK, m, ntok))
- return(0);
+ if (NULL == nn) {
+ man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE);
+ if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))
+ return(0);
+ } else
+ man_unscope(man, nn, MANDOCERR_MAX);
return(1);
}
@@ -298,34 +314,40 @@ blk_close(MACRO_PROT_ARGS)
int
blk_exp(MACRO_PROT_ARGS)
{
+ struct man_node *n;
int la;
char *p;
- /*
- * Close out prior scopes. "Regular" explicit macros cannot be
- * nested, but we allow roff macros to be placed just about
- * anywhere.
- */
+ /* Close out prior implicit scopes. */
- if ( ! man_block_alloc(m, line, ppos, tok))
+ if ( ! rew_scope(MAN_BLOCK, man, tok))
return(0);
- if ( ! man_head_alloc(m, line, ppos, tok))
+
+ if ( ! man_block_alloc(man, line, ppos, tok))
+ return(0);
+ if ( ! man_head_alloc(man, line, ppos, tok))
return(0);
for (;;) {
la = *pos;
- if ( ! man_args(m, line, pos, buf, &p))
+ if ( ! man_args(man, line, pos, buf, &p))
break;
- if ( ! man_word_alloc(m, line, la, p))
+ if ( ! man_word_alloc(man, line, la, p))
return(0);
}
- assert(m);
+ assert(man);
assert(tok != MAN_MAX);
- if ( ! rew_scope(MAN_HEAD, m, tok))
- return(0);
- return(man_body_alloc(m, line, ppos, tok));
+ for (n = man->last; n; n = n->parent) {
+ if (n->tok != tok)
+ continue;
+ assert(MAN_HEAD == n->type);
+ man_unscope(man, n, MANDOCERR_MAX);
+ break;
+ }
+
+ return(man_body_alloc(man, line, ppos, tok));
}
@@ -346,27 +368,27 @@ blk_imp(MACRO_PROT_ARGS)
/* Close out prior scopes. */
- if ( ! rew_scope(MAN_BODY, m, tok))
+ if ( ! rew_scope(MAN_BODY, man, tok))
return(0);
- if ( ! rew_scope(MAN_BLOCK, m, tok))
+ if ( ! rew_scope(MAN_BLOCK, man, tok))
return(0);
/* Allocate new block & head scope. */
- if ( ! man_block_alloc(m, line, ppos, tok))
+ if ( ! man_block_alloc(man, line, ppos, tok))
return(0);
- if ( ! man_head_alloc(m, line, ppos, tok))
+ if ( ! man_head_alloc(man, line, ppos, tok))
return(0);
- n = m->last;
+ n = man->last;
/* Add line arguments. */
for (;;) {
la = *pos;
- if ( ! man_args(m, line, pos, buf, &p))
+ if ( ! man_args(man, line, pos, buf, &p))
break;
- if ( ! man_word_alloc(m, line, la, p))
+ if ( ! man_word_alloc(man, line, la, p))
return(0);
}
@@ -375,17 +397,17 @@ blk_imp(MACRO_PROT_ARGS)
if (MAN_SCOPED & man_macros[tok].flags) {
/* If we're forcing scope (`TP'), keep it open. */
if (MAN_FSCOPED & man_macros[tok].flags) {
- m->flags |= MAN_BLINE;
+ man->flags |= MAN_BLINE;
return(1);
- } else if (n == m->last) {
- m->flags |= MAN_BLINE;
+ } else if (n == man->last) {
+ man->flags |= MAN_BLINE;
return(1);
}
}
- if ( ! rew_scope(MAN_HEAD, m, tok))
+ if ( ! rew_scope(MAN_HEAD, man, tok))
return(0);
- return(man_body_alloc(m, line, ppos, tok));
+ return(man_body_alloc(man, line, ppos, tok));
}
@@ -397,28 +419,37 @@ in_line_eoln(MACRO_PROT_ARGS)
char *p;
struct man_node *n;
- if ( ! man_elem_alloc(m, line, ppos, tok))
+ if ( ! man_elem_alloc(man, line, ppos, tok))
return(0);
- n = m->last;
+ n = man->last;
for (;;) {
la = *pos;
- if ( ! man_args(m, line, pos, buf, &p))
+ if ( ! man_args(man, line, pos, buf, &p))
break;
- if ( ! man_word_alloc(m, line, la, p))
+ if ( ! man_word_alloc(man, line, la, p))
return(0);
}
/*
+ * Append MAN_EOS in case the last snipped argument
+ * ends with a dot, e.g. `.IR syslog (3).'
+ */
+
+ if (n != man->last &&
+ mandoc_eos(man->last->string, strlen(man->last->string), 0))
+ man->last->flags |= MAN_EOS;
+
+ /*
* If no arguments are specified and this is MAN_SCOPED (i.e.,
* next-line scoped), then set our mode to indicate that we're
* waiting for terms to load into our context.
*/
- if (n == m->last && MAN_SCOPED & man_macros[tok].flags) {
+ if (n == man->last && MAN_SCOPED & man_macros[tok].flags) {
assert( ! (MAN_NSCOPED & man_macros[tok].flags));
- m->flags |= MAN_ELINE;
+ man->flags |= MAN_ELINE;
return(1);
}
@@ -426,11 +457,11 @@ in_line_eoln(MACRO_PROT_ARGS)
if (MAN_NSCOPED & man_macros[tok].flags) {
assert( ! (MAN_SCOPED & man_macros[tok].flags));
- m->flags |= MAN_ILINE;
+ man->flags |= MAN_ILINE;
}
- assert(MAN_ROOT != m->last->type);
- m->next = MAN_NEXT_SIBLING;
+ assert(MAN_ROOT != man->last->type);
+ man->next = MAN_NEXT_SIBLING;
/*
* Rewind our element scope. Note that when TH is pruned, we'll
@@ -438,22 +469,22 @@ in_line_eoln(MACRO_PROT_ARGS)
* its sibling.
*/
- for ( ; m->last; m->last = m->last->parent) {
- if (m->last == n)
+ for ( ; man->last; man->last = man->last->parent) {
+ if (man->last == n)
break;
- if (m->last->type == MAN_ROOT)
+ if (man->last->type == MAN_ROOT)
break;
- if ( ! man_valid_post(m))
+ if ( ! man_valid_post(man))
return(0);
}
- assert(m->last);
+ assert(man->last);
/*
* Same here regarding whether we're back at the root.
*/
- if (m->last->type != MAN_ROOT && ! man_valid_post(m))
+ if (man->last->type != MAN_ROOT && ! man_valid_post(man))
return(0);
return(1);
@@ -461,14 +492,14 @@ in_line_eoln(MACRO_PROT_ARGS)
int
-man_macroend(struct man *m)
+man_macroend(struct man *man)
{
- return(man_unscope(m, m->first, MANDOCERR_SCOPEEXIT));
+ return(man_unscope(man, man->first, MANDOCERR_SCOPEEXIT));
}
static int
-man_args(struct man *m, int line, int *pos, char *buf, char **v)
+man_args(struct man *man, int line, int *pos, char *buf, char **v)
{
char *start;
@@ -479,6 +510,6 @@ man_args(struct man *m, int line, int *pos, char *buf, char **v)
if ('\0' == *start)
return(0);
- *v = mandoc_getarg(m->parse, v, line, pos);
+ *v = mandoc_getarg(man->parse, v, line, pos);
return(1);
}
diff --git a/man_term.c b/man_term.c
index 69c5c95e442d..4bd62443b430 100644
--- a/man_term.c
+++ b/man_term.c
@@ -1,7 +1,7 @@
-/* $Id: man_term.c,v 1.127 2012/01/03 15:16:24 kristaps Exp $ */
+/* $Id: man_term.c,v 1.139 2013/12/22 23:34:13 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 2011, 2012, 2013 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
@@ -35,8 +35,6 @@
#define MAXMARGINS 64 /* maximum number of indented scopes */
-/* FIXME: have PD set the default vspace width. */
-
struct mtermp {
int fl;
#define MANT_LITERAL (1 << 0)
@@ -44,12 +42,13 @@ struct mtermp {
int lmargincur; /* index of current margin */
int lmarginsz; /* actual number of nested margins */
size_t offset; /* default offset to visible page */
+ int pardist; /* vert. space before par., unit: [v] */
};
#define DECL_ARGS struct termp *p, \
struct mtermp *mt, \
const struct man_node *n, \
- const struct man_meta *m
+ const struct man_meta *meta
struct termact {
int (*pre)(DECL_ARGS);
@@ -66,18 +65,20 @@ static void print_man_node(DECL_ARGS);
static void print_man_head(struct termp *, const void *);
static void print_man_foot(struct termp *, const void *);
static void print_bvspace(struct termp *,
- const struct man_node *);
+ const struct man_node *, int);
static int pre_B(DECL_ARGS);
static int pre_HP(DECL_ARGS);
static int pre_I(DECL_ARGS);
static int pre_IP(DECL_ARGS);
static int pre_OP(DECL_ARGS);
+static int pre_PD(DECL_ARGS);
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_TP(DECL_ARGS);
+static int pre_UR(DECL_ARGS);
static int pre_alternate(DECL_ARGS);
static int pre_ft(DECL_ARGS);
static int pre_ign(DECL_ARGS);
@@ -91,6 +92,7 @@ static void post_RS(DECL_ARGS);
static void post_SH(DECL_ARGS);
static void post_SS(DECL_ARGS);
static void post_TP(DECL_ARGS);
+static void post_UR(DECL_ARGS);
static const struct termact termacts[MAN_MAX] = {
{ pre_sp, NULL, MAN_NOTEXT }, /* br */
@@ -122,11 +124,15 @@ static const struct termact termacts[MAN_MAX] = {
{ pre_RS, post_RS, 0 }, /* RS */
{ pre_ign, NULL, 0 }, /* DT */
{ pre_ign, NULL, 0 }, /* UC */
- { pre_ign, NULL, 0 }, /* PD */
+ { pre_PD, NULL, MAN_NOTEXT }, /* PD */
{ pre_ign, NULL, 0 }, /* AT */
{ pre_in, NULL, MAN_NOTEXT }, /* in */
{ pre_ft, NULL, MAN_NOTEXT }, /* ft */
{ pre_OP, NULL, 0 }, /* OP */
+ { pre_literal, NULL, 0 }, /* EX */
+ { pre_literal, NULL, 0 }, /* EE */
+ { pre_UR, post_UR, 0 }, /* UR */
+ { NULL, NULL, 0 }, /* UE */
};
@@ -136,7 +142,7 @@ terminal_man(void *arg, const struct man *man)
{
struct termp *p;
const struct man_node *n;
- const struct man_meta *m;
+ const struct man_meta *meta;
struct mtermp mt;
p = (struct termp *)arg;
@@ -152,18 +158,19 @@ terminal_man(void *arg, const struct man *man)
p->symtab = mchars_alloc();
n = man_node(man);
- m = man_meta(man);
+ meta = man_meta(man);
- term_begin(p, print_man_head, print_man_foot, m);
+ term_begin(p, print_man_head, print_man_foot, meta);
p->flags |= TERMP_NOSPACE;
memset(&mt, 0, sizeof(struct mtermp));
mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
mt.offset = term_len(p, p->defindent);
+ mt.pardist = 1;
if (n->child)
- print_man_nodelist(p, &mt, n->child, m);
+ print_man_nodelist(p, &mt, n->child, meta);
term_end(p);
}
@@ -201,8 +208,9 @@ a2width(const struct termp *p, const char *cp)
* first, print it.
*/
static void
-print_bvspace(struct termp *p, const struct man_node *n)
+print_bvspace(struct termp *p, const struct man_node *n, int pardist)
{
+ int i;
term_newln(p);
@@ -214,7 +222,8 @@ print_bvspace(struct termp *p, const struct man_node *n)
if (NULL == n->prev)
return;
- term_vspace(p);
+ for (i = 0; i < pardist; i++)
+ term_vspace(p);
}
/* ARGSUSED */
@@ -243,7 +252,7 @@ pre_literal(DECL_ARGS)
term_newln(p);
- if (MAN_nf == n->tok)
+ if (MAN_nf == n->tok || MAN_EX == n->tok)
mt->fl |= MANT_LITERAL;
else
mt->fl &= ~MANT_LITERAL;
@@ -256,7 +265,8 @@ pre_literal(DECL_ARGS)
if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) {
p->offset = p->rmargin;
p->rmargin = p->maxrmargin;
- p->flags &= ~(TERMP_NOBREAK | TERMP_TWOSPACE);
+ p->trailspace = 0;
+ p->flags &= ~TERMP_NOBREAK;
p->flags |= TERMP_NOSPACE;
}
@@ -265,6 +275,21 @@ pre_literal(DECL_ARGS)
/* ARGSUSED */
static int
+pre_PD(DECL_ARGS)
+{
+
+ n = n->child;
+ if (0 == n) {
+ mt->pardist = 1;
+ return(0);
+ }
+ assert(MAN_TEXT == n->type);
+ mt->pardist = atoi(n->string);
+ return(0);
+}
+
+/* ARGSUSED */
+static int
pre_alternate(DECL_ARGS)
{
enum termfont font[2];
@@ -307,7 +332,7 @@ pre_alternate(DECL_ARGS)
term_fontrepl(p, font[i]);
if (savelit && NULL == nn->next)
mt->fl |= MANT_LITERAL;
- print_man_node(p, mt, nn, m);
+ print_man_node(p, mt, nn, meta);
if (nn->next)
p->flags |= TERMP_NOSPACE;
}
@@ -438,28 +463,54 @@ pre_in(DECL_ARGS)
static int
pre_sp(DECL_ARGS)
{
+ char *s;
size_t i, len;
+ int neg;
if ((NULL == n->prev && n->parent)) {
- if (MAN_SS == n->parent->tok)
- return(0);
- if (MAN_SH == n->parent->tok)
+ switch (n->parent->tok) {
+ case (MAN_SH):
+ /* FALLTHROUGH */
+ case (MAN_SS):
+ /* FALLTHROUGH */
+ case (MAN_PP):
+ /* FALLTHROUGH */
+ case (MAN_LP):
+ /* FALLTHROUGH */
+ case (MAN_P):
+ /* FALLTHROUGH */
return(0);
+ default:
+ break;
+ }
}
+ neg = 0;
switch (n->tok) {
case (MAN_br):
len = 0;
break;
default:
- len = n->child ? a2height(p, n->child->string) : 1;
+ if (NULL == n->child) {
+ len = 1;
+ break;
+ }
+ s = n->child->string;
+ if ('-' == *s) {
+ neg = 1;
+ s++;
+ }
+ len = a2height(p, s);
break;
}
if (0 == len)
term_newln(p);
- for (i = 0; i < len; i++)
- term_vspace(p);
+ else if (neg)
+ p->skipvsp += len;
+ else
+ for (i = 0; i < len; i++)
+ term_vspace(p);
return(0);
}
@@ -475,16 +526,19 @@ pre_HP(DECL_ARGS)
switch (n->type) {
case (MAN_BLOCK):
- print_bvspace(p, n);
+ print_bvspace(p, n, mt->pardist);
return(1);
case (MAN_BODY):
- p->flags |= TERMP_NOBREAK;
- p->flags |= TERMP_TWOSPACE;
break;
default:
return(0);
}
+ if ( ! (MANT_LITERAL & mt->fl)) {
+ p->flags |= TERMP_NOBREAK;
+ p->trailspace = 2;
+ }
+
len = mt->lmargin[mt->lmargincur];
ival = -1;
@@ -514,13 +568,10 @@ post_HP(DECL_ARGS)
{
switch (n->type) {
- case (MAN_BLOCK):
- term_flushln(p);
- break;
case (MAN_BODY):
- term_flushln(p);
+ term_newln(p);
p->flags &= ~TERMP_NOBREAK;
- p->flags &= ~TERMP_TWOSPACE;
+ p->trailspace = 0;
p->offset = mt->offset;
p->rmargin = p->maxrmargin;
break;
@@ -538,7 +589,7 @@ pre_PP(DECL_ARGS)
switch (n->type) {
case (MAN_BLOCK):
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
- print_bvspace(p, n);
+ print_bvspace(p, n, mt->pardist);
break;
default:
p->offset = mt->offset;
@@ -563,9 +614,10 @@ pre_IP(DECL_ARGS)
break;
case (MAN_HEAD):
p->flags |= TERMP_NOBREAK;
+ p->trailspace = 1;
break;
case (MAN_BLOCK):
- print_bvspace(p, n);
+ print_bvspace(p, n, mt->pardist);
/* FALLTHROUGH */
default:
return(1);
@@ -598,7 +650,7 @@ pre_IP(DECL_ARGS)
mt->fl &= ~MANT_LITERAL;
if (n->child)
- print_man_node(p, mt, n->child, m);
+ print_man_node(p, mt, n->child, meta);
if (savelit)
mt->fl |= MANT_LITERAL;
@@ -625,10 +677,12 @@ post_IP(DECL_ARGS)
case (MAN_HEAD):
term_flushln(p);
p->flags &= ~TERMP_NOBREAK;
+ p->trailspace = 0;
p->rmargin = p->maxrmargin;
break;
case (MAN_BODY):
term_newln(p);
+ p->offset = mt->offset;
break;
default:
break;
@@ -647,12 +701,13 @@ pre_TP(DECL_ARGS)
switch (n->type) {
case (MAN_HEAD):
p->flags |= TERMP_NOBREAK;
+ p->trailspace = 1;
break;
case (MAN_BODY):
p->flags |= TERMP_NOSPACE;
break;
case (MAN_BLOCK):
- print_bvspace(p, n);
+ print_bvspace(p, n, mt->pardist);
/* FALLTHROUGH */
default:
return(1);
@@ -683,7 +738,7 @@ pre_TP(DECL_ARGS)
/* Don't print same-line elements. */
for (nn = n->child; nn; nn = nn->next)
if (nn->line > n->line)
- print_man_node(p, mt, nn, m);
+ print_man_node(p, mt, nn, meta);
if (savelit)
mt->fl |= MANT_LITERAL;
@@ -694,6 +749,8 @@ pre_TP(DECL_ARGS)
case (MAN_BODY):
p->offset = mt->offset + len;
p->rmargin = p->maxrmargin;
+ p->trailspace = 0;
+ p->flags &= ~TERMP_NOBREAK;
break;
default:
break;
@@ -711,12 +768,10 @@ post_TP(DECL_ARGS)
switch (n->type) {
case (MAN_HEAD):
term_flushln(p);
- p->flags &= ~TERMP_NOBREAK;
- p->flags &= ~TERMP_TWOSPACE;
- p->rmargin = p->maxrmargin;
break;
case (MAN_BODY):
term_newln(p);
+ p->offset = mt->offset;
break;
default:
break;
@@ -728,6 +783,7 @@ post_TP(DECL_ARGS)
static int
pre_SS(DECL_ARGS)
{
+ int i;
switch (n->type) {
case (MAN_BLOCK):
@@ -740,11 +796,12 @@ pre_SS(DECL_ARGS)
break;
if (NULL == n->prev)
break;
- term_vspace(p);
+ for (i = 0; i < mt->pardist; i++)
+ term_vspace(p);
break;
case (MAN_HEAD):
term_fontrepl(p, TERMFONT_BOLD);
- p->offset = term_len(p, p->defindent/2);
+ p->offset = term_len(p, 3);
break;
case (MAN_BODY):
p->offset = mt->offset;
@@ -779,6 +836,7 @@ post_SS(DECL_ARGS)
static int
pre_SH(DECL_ARGS)
{
+ int i;
switch (n->type) {
case (MAN_BLOCK):
@@ -792,7 +850,8 @@ pre_SH(DECL_ARGS)
/* If the first macro, no vspae. */
if (NULL == n->prev)
break;
- term_vspace(p);
+ for (i = 0; i < mt->pardist; i++)
+ term_vspace(p);
break;
case (MAN_HEAD):
term_fontrepl(p, TERMFONT_BOLD);
@@ -890,6 +949,32 @@ post_RS(DECL_ARGS)
mt->lmargincur = mt->lmarginsz;
}
+/* ARGSUSED */
+static int
+pre_UR(DECL_ARGS)
+{
+
+ return (MAN_HEAD != n->type);
+}
+
+/* ARGSUSED */
+static void
+post_UR(DECL_ARGS)
+{
+
+ if (MAN_BLOCK != n->type)
+ return;
+
+ term_word(p, "<");
+ p->flags |= TERMP_NOSPACE;
+
+ if (NULL != n->child->child)
+ print_man_node(p, mt, n->child->child, meta);
+
+ p->flags |= TERMP_NOSPACE;
+ term_word(p, ">");
+}
+
static void
print_man_node(DECL_ARGS)
{
@@ -910,29 +995,8 @@ print_man_node(DECL_ARGS)
term_newln(p);
term_word(p, n->string);
+ goto out;
- /*
- * If we're in a literal context, make sure that words
- * togehter on the same line stay together. This is a
- * POST-printing call, so we check the NEXT word. Since
- * -man doesn't have nested macros, we don't need to be
- * more specific than this.
- */
- if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) &&
- (NULL == n->next ||
- n->next->line > n->line)) {
- rm = p->rmargin;
- rmax = p->maxrmargin;
- p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
- p->flags |= TERMP_NOSPACE;
- term_flushln(p);
- p->rmargin = rm;
- p->maxrmargin = rmax;
- }
-
- if (MAN_EOS & n->flags)
- p->flags |= TERMP_SENTENCE;
- return;
case (MAN_EQN):
term_eqn(p, n->eqn);
return;
@@ -954,16 +1018,41 @@ print_man_node(DECL_ARGS)
c = 1;
if (termacts[n->tok].pre)
- c = (*termacts[n->tok].pre)(p, mt, n, m);
+ c = (*termacts[n->tok].pre)(p, mt, n, meta);
if (c && n->child)
- print_man_nodelist(p, mt, n->child, m);
+ print_man_nodelist(p, mt, n->child, meta);
if (termacts[n->tok].post)
- (*termacts[n->tok].post)(p, mt, n, m);
+ (*termacts[n->tok].post)(p, mt, n, meta);
if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
term_fontrepl(p, TERMFONT_NONE);
+out:
+ /*
+ * If we're in a literal context, make sure that words
+ * together on the same line stay together. This is a
+ * POST-printing call, so we check the NEXT word. Since
+ * -man doesn't have nested macros, we don't need to be
+ * more specific than this.
+ */
+ if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) &&
+ (NULL == n->next || n->next->line > n->line)) {
+ rm = p->rmargin;
+ rmax = p->maxrmargin;
+ p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
+ p->flags |= TERMP_NOSPACE;
+ if (NULL != n->string && '\0' != *n->string)
+ term_flushln(p);
+ else
+ term_newln(p);
+ if (rm < rmax && n->parent->tok == MAN_HP) {
+ p->offset = rm;
+ p->rmargin = rmax;
+ } else
+ p->rmargin = rm;
+ p->maxrmargin = rmax;
+ }
if (MAN_EOS & n->flags)
p->flags |= TERMP_SENTENCE;
}
@@ -973,10 +1062,10 @@ static void
print_man_nodelist(DECL_ARGS)
{
- print_man_node(p, mt, n, m);
+ print_man_node(p, mt, n, meta);
if ( ! n->next)
return;
- print_man_nodelist(p, mt, n->next, m);
+ print_man_nodelist(p, mt, n->next, meta);
}
@@ -1016,6 +1105,7 @@ print_man_foot(struct termp *p, const void *arg)
/* Bottom left corner: manual source. */
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
+ p->trailspace = 1;
p->offset = 0;
p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2;
@@ -1038,6 +1128,7 @@ print_man_foot(struct termp *p, const void *arg)
p->flags &= ~TERMP_NOBREAK;
p->flags |= TERMP_NOSPACE;
+ p->trailspace = 0;
p->offset = p->rmargin;
p->rmargin = p->maxrmargin;
@@ -1051,24 +1142,25 @@ print_man_head(struct termp *p, const void *arg)
{
char buf[BUFSIZ], title[BUFSIZ];
size_t buflen, titlen;
- const struct man_meta *m;
+ const struct man_meta *meta;
- m = (const struct man_meta *)arg;
- assert(m->title);
- assert(m->msec);
+ meta = (const struct man_meta *)arg;
+ assert(meta->title);
+ assert(meta->msec);
- if (m->vol)
- strlcpy(buf, m->vol, BUFSIZ);
+ if (meta->vol)
+ strlcpy(buf, meta->vol, BUFSIZ);
else
buf[0] = '\0';
buflen = term_strlen(p, buf);
/* Top left corner: manual title and section. */
- snprintf(title, BUFSIZ, "%s(%s)", m->title, m->msec);
+ snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec);
titlen = term_strlen(p, title);
p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
+ p->trailspace = 1;
p->offset = 0;
p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
(p->maxrmargin -
@@ -1091,6 +1183,7 @@ print_man_head(struct termp *p, const void *arg)
/* Top right corner: title and section, again. */
p->flags &= ~TERMP_NOBREAK;
+ p->trailspace = 0;
if (p->rmargin + titlen <= p->maxrmargin) {
p->flags |= TERMP_NOSPACE;
p->offset = p->rmargin;
diff --git a/man_validate.c b/man_validate.c
index e40b089f53b8..da2e557ebb5e 100644
--- a/man_validate.c
+++ b/man_validate.c
@@ -1,7 +1,7 @@
-/* $Id: man_validate.c,v 1.80 2012/01/03 15:16:24 kristaps Exp $ */
+/* $Id: man_validate.c,v 1.86 2013/10/17 20:54:58 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012, 2013 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
@@ -35,7 +35,7 @@
#include "libman.h"
#include "libmandoc.h"
-#define CHKARGS struct man *m, struct man_node *n
+#define CHKARGS struct man *man, struct man_node *n
typedef int (*v_check)(CHKARGS);
@@ -49,12 +49,14 @@ static int check_eq2(CHKARGS);
static int check_le1(CHKARGS);
static int check_ge2(CHKARGS);
static int check_le5(CHKARGS);
+static int check_head1(CHKARGS);
static int check_par(CHKARGS);
static int check_part(CHKARGS);
static int check_root(CHKARGS);
static void check_text(CHKARGS);
static int post_AT(CHKARGS);
+static int post_IP(CHKARGS);
static int post_vs(CHKARGS);
static int post_fi(CHKARGS);
static int post_ft(CHKARGS);
@@ -70,6 +72,8 @@ static v_check posts_eq0[] = { check_eq0, NULL };
static v_check posts_eq2[] = { check_eq2, NULL };
static v_check posts_fi[] = { check_eq0, post_fi, NULL };
static v_check posts_ft[] = { post_ft, NULL };
+static v_check posts_ip[] = { post_IP, NULL };
+static v_check posts_le1[] = { check_le1, NULL };
static v_check posts_nf[] = { check_eq0, post_nf, NULL };
static v_check posts_par[] = { check_par, NULL };
static v_check posts_part[] = { check_part, NULL };
@@ -77,6 +81,7 @@ static v_check posts_sec[] = { post_sec, NULL };
static v_check posts_sp[] = { post_vs, check_le1, NULL };
static v_check posts_th[] = { check_ge2, check_le5, post_TH, NULL };
static v_check posts_uc[] = { post_UC, NULL };
+static v_check posts_ur[] = { check_head1, check_part, NULL };
static v_check pres_sec[] = { pre_sec, NULL };
static const struct man_valid man_valids[MAN_MAX] = {
@@ -88,7 +93,7 @@ static const struct man_valid man_valids[MAN_MAX] = {
{ NULL, posts_par }, /* LP */
{ NULL, posts_par }, /* PP */
{ NULL, posts_par }, /* P */
- { NULL, NULL }, /* IP */
+ { NULL, posts_ip }, /* IP */
{ NULL, NULL }, /* HP */
{ NULL, NULL }, /* SM */
{ NULL, NULL }, /* SB */
@@ -109,16 +114,20 @@ static const struct man_valid man_valids[MAN_MAX] = {
{ NULL, posts_part }, /* RS */
{ NULL, NULL }, /* DT */
{ NULL, posts_uc }, /* UC */
- { NULL, NULL }, /* PD */
+ { NULL, posts_le1 }, /* PD */
{ NULL, posts_at }, /* AT */
{ NULL, NULL }, /* in */
{ NULL, posts_ft }, /* ft */
{ NULL, posts_eq2 }, /* OP */
+ { NULL, posts_nf }, /* EX */
+ { NULL, posts_fi }, /* EE */
+ { NULL, posts_ur }, /* UR */
+ { NULL, NULL }, /* UE */
};
int
-man_valid_pre(struct man *m, struct man_node *n)
+man_valid_pre(struct man *man, struct man_node *n)
{
v_check *cp;
@@ -138,27 +147,27 @@ man_valid_pre(struct man *m, struct man_node *n)
if (NULL == (cp = man_valids[n->tok].pres))
return(1);
for ( ; *cp; cp++)
- if ( ! (*cp)(m, n))
+ if ( ! (*cp)(man, n))
return(0);
return(1);
}
int
-man_valid_post(struct man *m)
+man_valid_post(struct man *man)
{
v_check *cp;
- if (MAN_VALID & m->last->flags)
+ if (MAN_VALID & man->last->flags)
return(1);
- m->last->flags |= MAN_VALID;
+ man->last->flags |= MAN_VALID;
- switch (m->last->type) {
+ switch (man->last->type) {
case (MAN_TEXT):
- check_text(m, m->last);
+ check_text(man, man->last);
return(1);
case (MAN_ROOT):
- return(check_root(m, m->last));
+ return(check_root(man, man->last));
case (MAN_EQN):
/* FALLTHROUGH */
case (MAN_TBL):
@@ -167,10 +176,10 @@ man_valid_post(struct man *m)
break;
}
- if (NULL == (cp = man_valids[m->last->tok].posts))
+ if (NULL == (cp = man_valids[man->last->tok].posts))
return(1);
for ( ; *cp; cp++)
- if ( ! (*cp)(m, m->last))
+ if ( ! (*cp)(man, man->last))
return(0);
return(1);
@@ -181,29 +190,29 @@ static int
check_root(CHKARGS)
{
- if (MAN_BLINE & m->flags)
- man_nmsg(m, n, MANDOCERR_SCOPEEXIT);
- else if (MAN_ELINE & m->flags)
- man_nmsg(m, n, MANDOCERR_SCOPEEXIT);
+ if (MAN_BLINE & man->flags)
+ man_nmsg(man, n, MANDOCERR_SCOPEEXIT);
+ else if (MAN_ELINE & man->flags)
+ man_nmsg(man, n, MANDOCERR_SCOPEEXIT);
- m->flags &= ~MAN_BLINE;
- m->flags &= ~MAN_ELINE;
+ man->flags &= ~MAN_BLINE;
+ man->flags &= ~MAN_ELINE;
- if (NULL == m->first->child) {
- man_nmsg(m, n, MANDOCERR_NODOCBODY);
+ if (NULL == man->first->child) {
+ man_nmsg(man, n, MANDOCERR_NODOCBODY);
return(0);
- } else if (NULL == m->meta.title) {
- man_nmsg(m, n, MANDOCERR_NOTITLE);
+ } else if (NULL == man->meta.title) {
+ man_nmsg(man, n, MANDOCERR_NOTITLE);
/*
* If a title hasn't been set, do so now (by
* implication, date and section also aren't set).
*/
- m->meta.title = mandoc_strdup("unknown");
- m->meta.msec = mandoc_strdup("1");
- m->meta.date = mandoc_normdate
- (m->parse, NULL, n->line, n->pos);
+ man->meta.title = mandoc_strdup("unknown");
+ man->meta.msec = mandoc_strdup("1");
+ man->meta.date = mandoc_normdate
+ (man->parse, NULL, n->line, n->pos);
}
return(1);
@@ -214,12 +223,12 @@ check_text(CHKARGS)
{
char *cp, *p;
- if (MAN_LITERAL & m->flags)
+ if (MAN_LITERAL & man->flags)
return;
cp = n->string;
for (p = cp; NULL != (p = strchr(p, '\t')); p++)
- man_pmsg(m, n->line, (int)(p - cp), MANDOCERR_BADTAB);
+ man_pmsg(man, n->line, (int)(p - cp), MANDOCERR_BADTAB);
}
#define INEQ_DEFINE(x, ineq, name) \
@@ -228,7 +237,7 @@ check_##name(CHKARGS) \
{ \
if (n->nchild ineq (x)) \
return(1); \
- mandoc_vmsg(MANDOCERR_ARGCOUNT, m->parse, n->line, n->pos, \
+ mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line, n->pos, \
"line arguments %s %d (have %d)", \
#ineq, (x), n->nchild); \
return(1); \
@@ -241,6 +250,17 @@ INEQ_DEFINE(2, >=, ge2)
INEQ_DEFINE(5, <=, le5)
static int
+check_head1(CHKARGS)
+{
+
+ if (MAN_HEAD == n->type && 1 != n->nchild)
+ mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
+ n->pos, "line arguments eq 1 (have %d)", n->nchild);
+
+ return(1);
+}
+
+static int
post_ft(CHKARGS)
{
char *cp;
@@ -282,14 +302,14 @@ post_ft(CHKARGS)
if (0 == ok) {
mandoc_vmsg
- (MANDOCERR_BADFONT, m->parse,
+ (MANDOCERR_BADFONT, man->parse,
n->line, n->pos, "%s", cp);
*cp = '\0';
}
if (1 < n->nchild)
mandoc_vmsg
- (MANDOCERR_ARGCOUNT, m->parse, n->line,
+ (MANDOCERR_ARGCOUNT, man->parse, n->line,
n->pos, "want one child (have %d)",
n->nchild);
@@ -301,7 +321,7 @@ pre_sec(CHKARGS)
{
if (MAN_BLOCK == n->type)
- m->flags &= ~MAN_LITERAL;
+ man->flags &= ~MAN_LITERAL;
return(1);
}
@@ -312,7 +332,7 @@ post_sec(CHKARGS)
if ( ! (MAN_HEAD == n->type && 0 == n->nchild))
return(1);
- man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
+ man_nmsg(man, n, MANDOCERR_SYNTARGCOUNT);
return(0);
}
@@ -321,7 +341,7 @@ check_part(CHKARGS)
{
if (MAN_BODY == n->type && 0 == n->nchild)
- mandoc_msg(MANDOCERR_ARGCWARN, m->parse, n->line,
+ mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line,
n->pos, "want children (have none)");
return(1);
@@ -335,15 +355,15 @@ check_par(CHKARGS)
switch (n->type) {
case (MAN_BLOCK):
if (0 == n->body->nchild)
- man_node_delete(m, n);
+ man_node_delete(man, n);
break;
case (MAN_BODY):
if (0 == n->nchild)
- man_nmsg(m, n, MANDOCERR_IGNPAR);
+ man_nmsg(man, n, MANDOCERR_IGNPAR);
break;
case (MAN_HEAD):
if (n->nchild)
- man_nmsg(m, n, MANDOCERR_ARGSLOST);
+ man_nmsg(man, n, MANDOCERR_ARGSLOST);
break;
default:
break;
@@ -352,6 +372,24 @@ check_par(CHKARGS)
return(1);
}
+static int
+post_IP(CHKARGS)
+{
+
+ switch (n->type) {
+ case (MAN_BLOCK):
+ if (0 == n->head->nchild && 0 == n->body->nchild)
+ man_node_delete(man, n);
+ break;
+ case (MAN_BODY):
+ if (0 == n->parent->head->nchild && 0 == n->nchild)
+ man_nmsg(man, n, MANDOCERR_IGNPAR);
+ break;
+ default:
+ break;
+ }
+ return(1);
+}
static int
post_TH(CHKARGS)
@@ -359,21 +397,16 @@ post_TH(CHKARGS)
const char *p;
int line, pos;
- if (m->meta.title)
- free(m->meta.title);
- if (m->meta.vol)
- free(m->meta.vol);
- if (m->meta.source)
- free(m->meta.source);
- if (m->meta.msec)
- free(m->meta.msec);
- if (m->meta.date)
- free(m->meta.date);
+ free(man->meta.title);
+ free(man->meta.vol);
+ free(man->meta.source);
+ free(man->meta.msec);
+ free(man->meta.date);
line = n->line;
pos = n->pos;
- m->meta.title = m->meta.vol = m->meta.date =
- m->meta.msec = m->meta.source = NULL;
+ man->meta.title = man->meta.vol = man->meta.date =
+ man->meta.msec = man->meta.source = NULL;
/* ->TITLE<- MSEC DATE SOURCE VOL */
@@ -383,22 +416,22 @@ post_TH(CHKARGS)
/* Only warn about this once... */
if (isalpha((unsigned char)*p) &&
! isupper((unsigned char)*p)) {
- man_nmsg(m, n, MANDOCERR_UPPERCASE);
+ man_nmsg(man, n, MANDOCERR_UPPERCASE);
break;
}
}
- m->meta.title = mandoc_strdup(n->string);
+ man->meta.title = mandoc_strdup(n->string);
} else
- m->meta.title = mandoc_strdup("");
+ man->meta.title = mandoc_strdup("");
/* TITLE ->MSEC<- DATE SOURCE VOL */
if (n)
n = n->next;
if (n && n->string)
- m->meta.msec = mandoc_strdup(n->string);
+ man->meta.msec = mandoc_strdup(n->string);
else
- m->meta.msec = mandoc_strdup("");
+ man->meta.msec = mandoc_strdup("");
/* TITLE MSEC ->DATE<- SOURCE VOL */
@@ -406,30 +439,30 @@ post_TH(CHKARGS)
n = n->next;
if (n && n->string && '\0' != n->string[0]) {
pos = n->pos;
- m->meta.date = mandoc_normdate
- (m->parse, n->string, line, pos);
+ man->meta.date = mandoc_normdate
+ (man->parse, n->string, line, pos);
} else
- m->meta.date = mandoc_strdup("");
+ man->meta.date = mandoc_strdup("");
/* TITLE MSEC DATE ->SOURCE<- VOL */
if (n && (n = n->next))
- m->meta.source = mandoc_strdup(n->string);
+ man->meta.source = mandoc_strdup(n->string);
/* TITLE MSEC DATE SOURCE ->VOL<- */
/* If missing, use the default VOL name for MSEC. */
if (n && (n = n->next))
- m->meta.vol = mandoc_strdup(n->string);
- else if ('\0' != m->meta.msec[0] &&
- (NULL != (p = mandoc_a2msec(m->meta.msec))))
- m->meta.vol = mandoc_strdup(p);
+ man->meta.vol = mandoc_strdup(n->string);
+ else if ('\0' != man->meta.msec[0] &&
+ (NULL != (p = mandoc_a2msec(man->meta.msec))))
+ man->meta.vol = mandoc_strdup(p);
/*
* Remove the `TH' node after we've processed it for our
* meta-data.
*/
- man_node_delete(m, m->last);
+ man_node_delete(man, man->last);
return(1);
}
@@ -437,10 +470,10 @@ static int
post_nf(CHKARGS)
{
- if (MAN_LITERAL & m->flags)
- man_nmsg(m, n, MANDOCERR_SCOPEREP);
+ if (MAN_LITERAL & man->flags)
+ man_nmsg(man, n, MANDOCERR_SCOPEREP);
- m->flags |= MAN_LITERAL;
+ man->flags |= MAN_LITERAL;
return(1);
}
@@ -448,10 +481,10 @@ static int
post_fi(CHKARGS)
{
- if ( ! (MAN_LITERAL & m->flags))
- man_nmsg(m, n, MANDOCERR_WNOSCOPE);
+ if ( ! (MAN_LITERAL & man->flags))
+ man_nmsg(man, n, MANDOCERR_WNOSCOPE);
- m->flags &= ~MAN_LITERAL;
+ man->flags &= ~MAN_LITERAL;
return(1);
}
@@ -488,10 +521,8 @@ post_UC(CHKARGS)
p = bsd_versions[0];
}
- if (m->meta.source)
- free(m->meta.source);
-
- m->meta.source = mandoc_strdup(p);
+ free(man->meta.source);
+ man->meta.source = mandoc_strdup(p);
return(1);
}
@@ -528,10 +559,8 @@ post_AT(CHKARGS)
p = unix_versions[0];
}
- if (m->meta.source)
- free(m->meta.source);
-
- m->meta.source = mandoc_strdup(p);
+ free(man->meta.source);
+ man->meta.source = mandoc_strdup(p);
return(1);
}
@@ -539,12 +568,25 @@ static int
post_vs(CHKARGS)
{
- /*
- * Don't warn about this because it occurs in pod2man and would
- * cause considerable (unfixable) warnage.
- */
- if (NULL == n->prev && MAN_ROOT == n->parent->type)
- man_node_delete(m, n);
+ if (NULL != n->prev)
+ return(1);
+
+ switch (n->parent->tok) {
+ case (MAN_SH):
+ /* FALLTHROUGH */
+ case (MAN_SS):
+ man_nmsg(man, n, MANDOCERR_IGNPAR);
+ /* FALLTHROUGH */
+ case (MAN_MAX):
+ /*
+ * Don't warn about this because it occurs in pod2man
+ * and would cause considerable (unfixable) warnage.
+ */
+ man_node_delete(man, n);
+ break;
+ default:
+ break;
+ }
return(1);
}
diff --git a/mandoc.1 b/mandoc.1
index dbff0e31caa3..0657bc66c559 100644
--- a/mandoc.1
+++ b/mandoc.1
@@ -1,6 +1,7 @@
-.\" $Id: mandoc.1,v 1.100 2011/12/25 19:35:44 kristaps Exp $
+.\" $Id: mandoc.1,v 1.103 2013/07/13 19:41:16 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2012 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 +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: December 25 2011 $
+.Dd $Mdocdate: July 13 2013 $
.Dt MANDOC 1
.Os
.Sh NAME
@@ -23,6 +24,9 @@
.Sh SYNOPSIS
.Nm mandoc
.Op Fl V
+.Sm off
+.Op Fl I Cm os Li = Ar name
+.Sm on
.Op Fl m Ns Ar format
.Op Fl O Ns Ar option
.Op Fl T Ns Ar output
@@ -49,6 +53,15 @@ output.
.Pp
The arguments are as follows:
.Bl -tag -width Ds
+.Sm off
+.It Fl I Cm os Li = Ar name
+.Sm on
+Override the default operating system
+.Ar name
+for the
+.Xr mdoc 7
+.Sq \&Os
+macro.
.It Fl m Ns Ar format
Input format.
See
@@ -334,7 +347,7 @@ for font style specification and available command-line arguments.
Translate input format into
.Xr man 7
output format.
-This is useful for distributing manual sources to legancy systems
+This is useful for distributing manual sources to legacy systems
lacking
.Xr mdoc 7
formatters.
@@ -637,8 +650,7 @@ lists render similarly.
The
.Nm
utility was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
.Sh CAVEATS
In
.Fl T Ns Cm html
diff --git a/mandoc.3 b/mandoc.3
index 4d0b20d6507e..fe6503d5477e 100644
--- a/mandoc.3
+++ b/mandoc.3
@@ -1,4 +1,4 @@
-.\" $Id: mandoc.3,v 1.17 2012/01/13 15:27:14 joerg Exp $
+.\" $Id: mandoc.3,v 1.22 2013/10/06 17:01:52 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: January 13 2012 $
+.Dd $Mdocdate: October 6 2013 $
.Dt MANDOC 3
.Os
.Sh NAME
@@ -43,15 +43,15 @@
.Nm mparse_strlevel
.Nd mandoc macro compiler library
.Sh LIBRARY
-.Lb mandoc
+.Lb libmandoc
.Sh SYNOPSIS
.In man.h
.In mdoc.h
.In mandoc.h
.Ft "enum mandoc_esc"
.Fo mandoc_escape
-.Fa "const char **end"
-.Fa "const char **start"
+.Fa "const char const **end"
+.Fa "const char const **start"
.Fa "int *sz"
.Fc
.Ft "const struct man_meta *"
@@ -67,7 +67,7 @@
.Fa "const struct man *man"
.Fc
.Ft "struct mchars *"
-.Fn mchars_alloc
+.Fn mchars_alloc "void"
.Ft void
.Fn mchars_free "struct mchars *p"
.Ft char
@@ -86,7 +86,6 @@
.Fa "const struct mchars *p"
.Fa "const char *cp"
.Fa "size_t sz"
-.Ft "const char *"
.Fc
.Ft "const struct mdoc_meta *"
.Fo mdoc_meta
@@ -257,16 +256,32 @@ and
.Va sz
may be
.Dv NULL .
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa mandoc.c .
.It Fn man_meta
Obtain the meta-data of a successful parse.
This may only be used on a pointer returned by
.Fn mparse_result .
+Declared in
+.In man.h ,
+implemented in
+.Pa man.c .
.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_node
Obtain the root node of a successful parse.
This may only be used on a pointer returned by
.Fn mparse_result .
+Declared in
+.In man.h ,
+implemented in
+.Pa man.c .
.It Fn mchars_alloc
Allocate an
.Vt "struct mchars *"
@@ -276,33 +291,65 @@ See
for an overview of special characters.
The object must be freed with
.Fn mchars_free .
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa chars.c .
.It Fn mchars_free
Free an object created with
.Fn mchars_alloc .
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa chars.c .
.It Fn mchars_num2char
Convert a character index (e.g., the \eN\(aq\(aq escape) into a
printable ASCII character.
Returns \e0 (the nil character) if the input sequence is malformed.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa chars.c .
.It Fn mchars_num2uc
Convert a hexadecimal character index (e.g., the \e[uNNNN] escape) into
a Unicode codepoint.
Returns \e0 (the nil character) if the input sequence is malformed.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa chars.c .
.It Fn mchars_spec2cp
Convert a special character into a valid Unicode codepoint.
Returns \-1 on failure or a non-zero Unicode codepoint on success.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa chars.c .
.It Fn mchars_spec2str
Convert a special character into an ASCII string.
Returns
.Dv NULL
on failure.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa chars.c .
.It Fn mdoc_meta
Obtain the meta-data of a successful parse.
This may only be used on a pointer returned by
.Fn mparse_result .
+Declared in
+.In mdoc.h ,
+implemented in
+.Pa mdoc.c .
.It Fn mdoc_node
Obtain the root node of a successful parse.
This may only be used on a pointer returned by
.Fn mparse_result .
+Declared in
+.In mdoc.h ,
+implemented in
+.Pa mdoc.c .
.It Fn mparse_alloc
Allocate a parser.
The same parser may be used for multiple files so long as
@@ -310,18 +357,34 @@ The same parser may be used for multiple files so long as
is called between parses.
.Fn mparse_free
must be called to free the memory allocated by this function.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa read.c .
.It Fn mparse_free
Free all memory allocated by
.Fn mparse_alloc .
+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.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa read.c .
.It Fn mparse_readfd
Parse a file or file descriptor.
If
@@ -336,10 +399,18 @@ is assumed to be the name associated with
This may be called multiple times with different parameters; however,
.Fn mparse_reset
should be invoked between parses.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa read.c .
.It Fn mparse_reset
Reset a parser so that
.Fn mparse_readfd
may be used again.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa read.c .
.It Fn mparse_result
Obtain the result of a parse.
Only successful parses
@@ -350,10 +421,22 @@ returned less than MANDOCLEVEL_FATAL
.Pc
should invoke this function, in which case 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 .
.El
.Ss Variables
.Bl -ohang
@@ -596,5 +679,4 @@ levels of badly-nested blocks.
The
.Nm
library was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
diff --git a/mandoc.c b/mandoc.c
index 604bb67e6ae4..58e3aca34ba9 100644
--- a/mandoc.c
+++ b/mandoc.c
@@ -1,7 +1,7 @@
-/* $Id: mandoc.c,v 1.62 2011/12/03 16:08:51 schwarze Exp $ */
+/* $Id: mandoc.c,v 1.73 2013/12/26 02:55:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2012, 2013 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,83 +37,38 @@
static int a2time(time_t *, const char *, const char *);
static char *time2a(time_t);
-static int numescape(const char *);
-/*
- * Pass over recursive numerical expressions. This context of this
- * function is important: it's only called within character-terminating
- * escapes (e.g., \s[xxxyyy]), so all we need to do is handle initial
- * recursion: we don't care about what's in these blocks.
- * This returns the number of characters skipped or -1 if an error
- * occurs (the caller should bail).
- */
-static int
-numescape(const char *start)
-{
- int i;
- size_t sz;
- const char *cp;
- i = 0;
-
- /* The expression consists of a subexpression. */
-
- if ('\\' == start[i]) {
- cp = &start[++i];
- /*
- * Read past the end of the subexpression.
- * Bail immediately on errors.
- */
- if (ESCAPE_ERROR == mandoc_escape(&cp, NULL, NULL))
- return(-1);
- return(i + cp - &start[i]);
- }
-
- if ('(' != start[i++])
- return(0);
+enum mandoc_esc
+mandoc_escape(const char const **end, const char const **start, int *sz)
+{
+ const char *local_start;
+ int local_sz;
+ char term;
+ enum mandoc_esc gly;
/*
- * A parenthesised subexpression. Read until the closing
- * parenthesis, making sure to handle any nested subexpressions
- * that might ruin our parse.
+ * When the caller doesn't provide return storage,
+ * use local storage.
*/
- while (')' != start[i]) {
- sz = strcspn(&start[i], ")\\");
- i += (int)sz;
-
- if ('\0' == start[i])
- return(-1);
- else if ('\\' != start[i])
- continue;
-
- cp = &start[++i];
- if (ESCAPE_ERROR == mandoc_escape(&cp, NULL, NULL))
- return(-1);
- i += cp - &start[i];
- }
-
- /* Read past the terminating ')'. */
- return(++i);
-}
+ if (NULL == start)
+ start = &local_start;
+ if (NULL == sz)
+ sz = &local_sz;
-enum mandoc_esc
-mandoc_escape(const char **end, const char **start, int *sz)
-{
- char c, term, numeric;
- int i, lim, ssz, rlim;
- const char *cp, *rstart;
- enum mandoc_esc gly;
+ /*
+ * 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.
+ */
- cp = *end;
- rstart = cp;
- if (start)
- *start = rstart;
- i = lim = 0;
gly = ESCAPE_ERROR;
- term = numeric = '\0';
+ *start = ++*end;
+ *sz = 0;
+ term = '\0';
- switch ((c = cp[i++])) {
+ switch ((*start)[-1]) {
/*
* First the glyphs. There are several different forms of
* these, but each eventually returns a substring of the glyph
@@ -121,7 +76,7 @@ mandoc_escape(const char **end, const char **start, int *sz)
*/
case ('('):
gly = ESCAPE_SPECIAL;
- lim = 2;
+ *sz = 2;
break;
case ('['):
gly = ESCAPE_SPECIAL;
@@ -131,18 +86,39 @@ mandoc_escape(const char **end, const char **start, int *sz)
* Unicode codepoint. Here, however, only check whether
* it's not a zero-width escape.
*/
- if ('u' == cp[i] && ']' != cp[i + 1])
+ if ('u' == (*start)[0] && ']' != (*start)[1])
gly = ESCAPE_UNICODE;
term = ']';
break;
case ('C'):
- if ('\'' != cp[i])
+ if ('\'' != **start)
return(ESCAPE_ERROR);
- gly = ESCAPE_SPECIAL;
+ *start = ++*end;
+ if ('u' == (*start)[0] && '\'' != (*start)[1])
+ gly = ESCAPE_UNICODE;
+ else
+ gly = ESCAPE_SPECIAL;
term = '\'';
break;
/*
+ * Escapes taking no arguments at all.
+ */
+ case ('d'):
+ /* FALLTHROUGH */
+ case ('u'):
+ return(ESCAPE_IGNORE);
+
+ /*
+ * The \z escape is supposed to output the following
+ * character without advancing the cursor position.
+ * Since we are mostly dealing with terminal mode,
+ * let us just skip the next character.
+ */
+ case ('z'):
+ return(ESCAPE_SKIPCHAR);
+
+ /*
* Handle all triggers matching \X(xy, \Xx, and \X[xxxx], where
* 'X' is the trigger. These have opaque sub-strings.
*/
@@ -166,21 +142,17 @@ mandoc_escape(const char **end, const char **start, int *sz)
case ('f'):
if (ESCAPE_ERROR == gly)
gly = ESCAPE_FONT;
-
- rstart= &cp[i];
- if (start)
- *start = rstart;
-
- switch (cp[i++]) {
+ switch (**start) {
case ('('):
- lim = 2;
+ *start = ++*end;
+ *sz = 2;
break;
case ('['):
+ *start = ++*end;
term = ']';
break;
default:
- lim = 1;
- i--;
+ *sz = 1;
break;
}
break;
@@ -193,18 +165,23 @@ mandoc_escape(const char **end, const char **start, int *sz)
/* FALLTHROUGH */
case ('b'):
/* FALLTHROUGH */
+ case ('B'):
+ /* FALLTHROUGH */
case ('D'):
/* FALLTHROUGH */
case ('o'):
/* FALLTHROUGH */
case ('R'):
/* FALLTHROUGH */
+ case ('w'):
+ /* FALLTHROUGH */
case ('X'):
/* FALLTHROUGH */
case ('Z'):
- if ('\'' != cp[i++])
+ if ('\'' != **start)
return(ESCAPE_ERROR);
gly = ESCAPE_IGNORE;
+ *start = ++*end;
term = '\'';
break;
@@ -212,8 +189,6 @@ mandoc_escape(const char **end, const char **start, int *sz)
* These escapes are of the form \X'N', where 'X' is the trigger
* and 'N' resolves to a numerical expression.
*/
- case ('B'):
- /* FALLTHROUGH */
case ('h'):
/* FALLTHROUGH */
case ('H'):
@@ -221,20 +196,17 @@ mandoc_escape(const char **end, const char **start, int *sz)
case ('L'):
/* FALLTHROUGH */
case ('l'):
- gly = ESCAPE_NUMBERED;
/* FALLTHROUGH */
case ('S'):
/* FALLTHROUGH */
case ('v'):
/* FALLTHROUGH */
- case ('w'):
- /* FALLTHROUGH */
case ('x'):
- if (ESCAPE_ERROR == gly)
- gly = ESCAPE_IGNORE;
- if ('\'' != cp[i++])
+ if ('\'' != **start)
return(ESCAPE_ERROR);
- term = numeric = '\'';
+ gly = ESCAPE_IGNORE;
+ *start = ++*end;
+ term = '\'';
break;
/*
@@ -242,17 +214,17 @@ mandoc_escape(const char **end, const char **start, int *sz)
* XXX Do any other escapes need similar handling?
*/
case ('N'):
- if ('\0' == cp[i])
+ if ('\0' == **start)
return(ESCAPE_ERROR);
- *end = &cp[++i];
- if (isdigit((unsigned char)cp[i-1]))
+ (*end)++;
+ if (isdigit((unsigned char)**start)) {
+ *sz = 1;
return(ESCAPE_IGNORE);
+ }
+ (*start)++;
while (isdigit((unsigned char)**end))
(*end)++;
- if (start)
- *start = &cp[i];
- if (sz)
- *sz = *end - &cp[i];
+ *sz = *end - *start;
if ('\0' != **end)
(*end)++;
return(ESCAPE_NUMBERED);
@@ -263,122 +235,93 @@ mandoc_escape(const char **end, const char **start, int *sz)
case ('s'):
gly = ESCAPE_IGNORE;
- rstart = &cp[i];
- if (start)
- *start = rstart;
-
/* See +/- counts as a sign. */
- c = cp[i];
- if ('+' == c || '-' == c || ASCII_HYPH == c)
- ++i;
+ if ('+' == **end || '-' == **end || ASCII_HYPH == **end)
+ (*end)++;
- switch (cp[i++]) {
+ switch (**end) {
case ('('):
- lim = 2;
+ *start = ++*end;
+ *sz = 2;
break;
case ('['):
- term = numeric = ']';
+ *start = ++*end;
+ term = ']';
break;
case ('\''):
- term = numeric = '\'';
+ *start = ++*end;
+ term = '\'';
break;
default:
- lim = 1;
- i--;
+ *sz = 1;
break;
}
- /* See +/- counts as a sign. */
- c = cp[i];
- if ('+' == c || '-' == c || ASCII_HYPH == c)
- ++i;
-
break;
/*
* Anything else is assumed to be a glyph.
+ * In this case, pass back the character after the backslash.
*/
default:
gly = ESCAPE_SPECIAL;
- lim = 1;
- i--;
+ *start = --*end;
+ *sz = 1;
break;
}
assert(ESCAPE_ERROR != gly);
- rstart = &cp[i];
- if (start)
- *start = rstart;
-
/*
- * If a terminating block has been specified, we need to
- * handle the case of recursion, which could have their
- * own terminating blocks that mess up our parse. This, by the
- * way, means that the "start" and "size" values will be
- * effectively meaningless.
- */
-
- ssz = 0;
- if (numeric && -1 == (ssz = numescape(&cp[i])))
- return(ESCAPE_ERROR);
-
- i += ssz;
- rlim = -1;
-
- /*
- * We have a character terminator. Try to read up to that
- * character. If we can't (i.e., we hit the nil), then return
- * an error; if we can, calculate our length, read past the
- * terminating character, and exit.
+ * Read up to the terminating character,
+ * paying attention to nested escapes.
*/
if ('\0' != term) {
- *end = strchr(&cp[i], term);
- if ('\0' == *end)
+ while (**end != term) {
+ switch (**end) {
+ case ('\0'):
+ return(ESCAPE_ERROR);
+ case ('\\'):
+ (*end)++;
+ if (ESCAPE_ERROR ==
+ mandoc_escape(end, NULL, NULL))
+ return(ESCAPE_ERROR);
+ break;
+ default:
+ (*end)++;
+ break;
+ }
+ }
+ *sz = (*end)++ - *start;
+ } else {
+ assert(*sz > 0);
+ if ((size_t)*sz > strlen(*start))
return(ESCAPE_ERROR);
-
- rlim = *end - &cp[i];
- if (sz)
- *sz = rlim;
- (*end)++;
- goto out;
+ *end += *sz;
}
- assert(lim > 0);
-
- /*
- * We have a numeric limit. If the string is shorter than that,
- * stop and return an error. Else adjust our endpoint, length,
- * and return the current glyph.
- */
-
- if ((size_t)lim > strlen(&cp[i]))
- return(ESCAPE_ERROR);
-
- rlim = lim;
- if (sz)
- *sz = rlim;
-
- *end = &cp[i] + lim;
-
-out:
- assert(rlim >= 0 && rstart);
-
/* Run post-processors. */
switch (gly) {
case (ESCAPE_FONT):
- /*
- * Pretend that the constant-width font modes are the
- * same as the regular font modes.
- */
- if (2 == rlim && 'C' == *rstart)
- rstart++;
- else if (1 != rlim)
+ 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;
+ break;
+ }
+ } else if (1 != *sz)
break;
- switch (*rstart) {
+ switch (**start) {
case ('3'):
/* FALLTHROUGH */
case ('B'):
@@ -400,9 +343,7 @@ out:
}
break;
case (ESCAPE_SPECIAL):
- if (1 != rlim)
- break;
- if ('c' == *rstart)
+ if (1 == *sz && 'c' == **start)
gly = ESCAPE_NOSPACE;
break;
default:
@@ -484,10 +425,10 @@ mandoc_strdup(const char *ptr)
* 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.
- * Null-terminate the argument in place.
+ * NUL-terminate the argument in place.
* Collapse pairs of quotes inside quoted arguments.
* Advance the argument pointer to the next argument,
- * or to the null byte terminating the argument line.
+ * or to the NUL byte terminating the argument line.
*/
char *
mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
@@ -506,17 +447,35 @@ mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
pairs = 0;
white = 0;
for (cp = start; '\0' != *cp; cp++) {
- /* Move left after quoted quotes and escaped backslashes. */
+
+ /*
+ * Move the following text left
+ * after quoted quotes and after "\\" and "\t".
+ */
if (pairs)
cp[-pairs] = cp[0];
+
if ('\\' == cp[0]) {
- if ('\\' == cp[1]) {
- /* Poor man's copy mode. */
+ /*
+ * 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++;
- } else if (0 == quoted && ' ' == cp[1])
+ break;
+ case (' '):
/* Skip escaped blanks. */
- cp++;
+ if (0 == quoted)
+ cp++;
+ break;
+ default:
+ break;
+ }
} else if (0 == quoted) {
if (' ' == cp[0]) {
/* Unescaped blanks end unquoted args. */
@@ -540,7 +499,7 @@ mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
if (1 == quoted)
mandoc_msg(MANDOCERR_BADQUOTE, parse, ln, *pos, NULL);
- /* Null-terminate this argument and move to the next one. */
+ /* NUL-terminate this argument and move to the next one. */
if (pairs)
cp[-pairs] = '\0';
if ('\0' != *cp) {
@@ -678,32 +637,6 @@ mandoc_eos(const char *p, size_t sz, int enclosed)
}
/*
- * Find out whether a line is a macro line or not. If it is, adjust the
- * current position and return one; if it isn't, return zero and don't
- * change the current position.
- */
-int
-mandoc_getcontrol(const char *cp, int *ppos)
-{
- int pos;
-
- pos = *ppos;
-
- if ('\\' == cp[pos] && '.' == cp[pos + 1])
- pos += 2;
- else if ('.' == cp[pos] || '\'' == cp[pos])
- pos++;
- else
- return(0);
-
- while (' ' == cp[pos] || '\t' == cp[pos])
- pos++;
-
- *ppos = pos;
- return(1);
-}
-
-/*
* Convert a string to a long that may not be <0.
* If the string is invalid, or is less than 0, return -1.
*/
diff --git a/mandoc.h b/mandoc.h
index a37effc5f58e..5170b419b907 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -1,6 +1,7 @@
-/* $Id: mandoc.h,v 1.99 2012/02/16 20:51:31 joerg Exp $ */
+/* $Id: mandoc.h,v 1.111 2013/10/05 20:30:05 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -50,6 +51,7 @@ enum mandocerr {
MANDOCERR_NOTITLE, /* no title in document */
MANDOCERR_UPPERCASE, /* document title should be all caps */
MANDOCERR_BADMSEC, /* unknown manual section */
+ MANDOCERR_BADVOLARCH, /* unknown manual volume or arch */
MANDOCERR_NODATE, /* date missing, using today's date */
MANDOCERR_BADDATE, /* cannot parse date, using it verbatim */
MANDOCERR_PROLOGOOO, /* prologue macros out of order */
@@ -61,14 +63,14 @@ enum mandocerr {
MANDOCERR_SO, /* .so is fragile, better use ln(1) */
MANDOCERR_NAMESECFIRST, /* NAME section must come first */
MANDOCERR_BADNAMESEC, /* bad NAME section contents */
- MANDOCERR_NONAME, /* manual name not yet set */
MANDOCERR_SECOOO, /* sections out of conventional order */
MANDOCERR_SECREP, /* duplicate section name */
- MANDOCERR_SECMSEC, /* section not in conventional manual section */
+ MANDOCERR_SECMSEC, /* section header suited to sections ... */
/* related to macros and nesting */
MANDOCERR_MACROOBS, /* skipping obsolete macro */
MANDOCERR_IGNPAR, /* skipping paragraph macro */
+ MANDOCERR_MOVEPAR, /* moving paragraph macro out of list */
MANDOCERR_IGNNS, /* skipping no-space macro */
MANDOCERR_SCOPENEST, /* blocks badly nested */
MANDOCERR_CHILD, /* child violates parent syntax */
@@ -129,10 +131,12 @@ enum mandocerr {
MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
MANDOCERR_BADCHAR, /* skipping bad character */
MANDOCERR_NAMESC, /* escaped character not allowed in a name */
+ MANDOCERR_NONAME, /* manual name not yet set */
MANDOCERR_NOTEXT, /* skipping text before the first section header */
MANDOCERR_MACRO, /* skipping unknown macro */
MANDOCERR_REQUEST, /* NOT IMPLEMENTED: skipping request */
MANDOCERR_ARGCOUNT, /* argument count wrong */
+ MANDOCERR_STRAYTA, /* skipping column outside column list */
MANDOCERR_NOSCOPE, /* skipping end of block that is not open */
MANDOCERR_SCOPEBROKEN, /* missing end of block */
MANDOCERR_SCOPEEXIT, /* scope open on exit */
@@ -141,6 +145,7 @@ enum mandocerr {
MANDOCERR_NOARGS, /* macro requires line argument(s) */
MANDOCERR_NOBODY, /* macro requires body argument(s) */
MANDOCERR_NOARGV, /* macro requires argument(s) */
+ MANDOCERR_NUMERIC, /* request requires a numeric argument */
MANDOCERR_LISTTYPE, /* missing list type */
MANDOCERR_ARGSLOST, /* line argument(s) will be lost */
MANDOCERR_BODYLOST, /* body argument(s) will be lost */
@@ -160,7 +165,7 @@ enum mandocerr {
MANDOCERR_MAX
};
-struct tbl {
+struct tbl_opts {
char tab; /* cell-separator */
char decimal; /* decimal point */
int linesize;
@@ -175,20 +180,14 @@ struct tbl {
int cols; /* number of columns */
};
-enum tbl_headt {
- TBL_HEAD_DATA, /* plug in data from tbl_dat */
- TBL_HEAD_VERT, /* vertical spacer */
- TBL_HEAD_DVERT /* double-vertical spacer */
-};
-
/*
* The head of a table specifies all of its columns. When formatting a
* tbl_span, iterate over these and plug in data from the tbl_span when
* appropriate, using tbl_cell as a guide to placement.
*/
struct tbl_head {
- enum tbl_headt pos;
int ident; /* 0 <= unique id < cols */
+ int vert; /* width of preceding vertical line */
struct tbl_head *next;
struct tbl_head *prev;
};
@@ -203,8 +202,6 @@ enum tbl_cellt {
TBL_CELL_DOWN, /* ^ */
TBL_CELL_HORIZ, /* _, - */
TBL_CELL_DHORIZ, /* = */
- TBL_CELL_VERT, /* | */
- TBL_CELL_DVERT, /* || */
TBL_CELL_MAX
};
@@ -213,6 +210,7 @@ enum tbl_cellt {
*/
struct tbl_cell {
struct tbl_cell *next;
+ int vert; /* width of preceding vertical line */
enum tbl_cellt pos;
size_t spacing;
int flags;
@@ -266,7 +264,7 @@ enum tbl_spant {
* A row of data in a table.
*/
struct tbl_span {
- struct tbl *tbl;
+ struct tbl_opts *opts;
struct tbl_head *head;
struct tbl_row *layout; /* layout row */
struct tbl_dat *first;
@@ -382,11 +380,13 @@ enum mandoc_esc {
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_FONTPREV, /* previous font mode */
ESCAPE_NUMBERED, /* a numbered glyph */
ESCAPE_UNICODE, /* a unicode codepoint */
- ESCAPE_NOSPACE /* suppress space if the last on a line */
+ ESCAPE_NOSPACE, /* suppress space if the last on a line */
+ ESCAPE_SKIPCHAR /* skip the next character */
};
typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel,
@@ -400,7 +400,8 @@ struct man;
__BEGIN_DECLS
void *mandoc_calloc(size_t, size_t);
-enum mandoc_esc mandoc_escape(const char **, const char **, int *);
+enum mandoc_esc mandoc_escape(const char const **,
+ const char const **, int *);
void *mandoc_malloc(size_t);
void *mandoc_realloc(void *, size_t);
char *mandoc_strdup(const char *);
@@ -413,8 +414,8 @@ int mchars_spec2cp(const struct mchars *,
const char *, size_t);
const char *mchars_spec2str(const struct mchars *,
const char *, size_t, size_t *);
-struct mparse *mparse_alloc(enum mparset,
- enum mandoclevel, mandocmsg, void *);
+struct mparse *mparse_alloc(enum mparset, enum mandoclevel,
+ mandocmsg, void *, char *);
void mparse_free(struct mparse *);
void mparse_keep(struct mparse *);
enum mandoclevel mparse_readfd(struct mparse *, int, const char *);
diff --git a/mandoc_char.7 b/mandoc_char.7
index acc1b6100d4f..8d8356652ef5 100644
--- a/mandoc_char.7
+++ b/mandoc_char.7
@@ -1,4 +1,4 @@
-.\" $Id: mandoc_char.7,v 1.51 2011/11/23 10:09:30 kristaps Exp $
+.\" $Id: mandoc_char.7,v 1.56 2013/12/26 17:23:42 schwarze Exp $
.\"
.\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: November 23 2011 $
+.Dd $Mdocdate: December 26 2013 $
.Dt MANDOC_CHAR 7
.Os
.Sh NAME
@@ -98,26 +98,27 @@ in literal context, and when none of the following special cases apply,
just use the normal space character
.Pq Sq \ .
.Pp
-When filling text, lines may be broken between words, i.e. at space
+When filling text, output lines may be broken between words, i.e. at space
characters.
To prevent a line break between two particular words,
-use the non-breaking space escape sequence
-.Pq Sq \e~
+use the unpaddable non-breaking space escape sequence
+.Pq Sq \e\ \&
instead of the normal space character.
For example, the input string
-.Dq number\e~1
+.Dq number\e\ 1
will be kept together as
-.Dq number\~1
+.Dq number\ 1
on the same output line.
.Pp
On request and macro lines, the normal space character serves as an
argument delimiter.
-To include whitespace into arguments, quoting is usually the best choice.
-In some cases, using either the non-breaking
-.Pq Sq \e~
-or the breaking
+To include whitespace into arguments, quoting is usually the best choice;
+see the MACRO SYNTAX section in
+.Xr roff 7 .
+In some cases, using the non-breaking space escape sequence
.Pq Sq \e\ \&
-space escape sequence may be preferable.
+may be preferable.
+.Pp
To escape macro names and to protect whitespace at the end
of input lines, the zero-width space
.Pq Sq \e&
@@ -194,14 +195,13 @@ manual.
Spacing:
.Bl -column "Input" "Description" -offset indent -compact
.It Em Input Ta Em Description
-.It \e~ Ta non-breaking, non-collapsing space
-.It \e Ta breaking, non-collapsing n-width space
-.It \e^ Ta zero-width space
-.It \e% Ta zero-width space
+.It Sq \e\ \& Ta unpaddable non-breaking space
+.It \e~ Ta paddable non-breaking space
+.It \e0 Ta unpaddable, breaking digit-width space
+.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 space
-.It \e0 Ta breaking, non-collapsing digit-width space
-.It \ec Ta removes any trailing space (if applicable)
+.It \e% Ta zero-width space allowing hyphenation
.El
.Pp
Lines:
@@ -655,13 +655,18 @@ manual.
.It \e*(Ai Ta \*(Ai Ta ANSI standard name
.El
.Sh UNICODE CHARACTERS
-The escape sequence
+The escape sequences
.Pp
-.Dl \e[uXXXX]
+.Dl \e[uXXXX] and \eC'uXXXX'
.Pp
-is interpreted as a Unicode codepoint.
+are interpreted as Unicode codepoints.
The codepoint must be in the range above U+0080 and less than U+10FFFF.
-For compatibility, points must be zero-padded to four characters; if
+For compatibility, the hexadecimal digits
+.Sq A
+to
+.Sq F
+must be given as uppercase characters,
+and points must be zero-padded to four characters; if
greater than four characters, no zero padding is allowed.
Unicode surrogates are not allowed.
.\" .Pp
@@ -684,7 +689,7 @@ For example, do not use \eN'34', use \e(dq, or even the plain
.Sq \(dq
character where possible.
.Sh COMPATIBILITY
-This section documents compatibility between mandoc and other other
+This section documents compatibility between mandoc and other
troff implementations, at this time limited to GNU troff
.Pq Qq groff .
.Pp
@@ -728,12 +733,11 @@ known representation.
The
.Nm
manual page was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
.Sh CAVEATS
-The
+The predefined string
.Sq \e*(Ba
-escape mimics the behaviour of the
+mimics the behaviour of the
.Sq \&|
character in
.Xr mdoc 7 ;
diff --git a/mandocdb.8 b/mandocdb.8
index cb48359b3407..83b6a0102e2a 100644
--- a/mandocdb.8
+++ b/mandocdb.8
@@ -1,4 +1,4 @@
-.\" $Id: mandocdb.8,v 1.17 2011/12/25 21:00:23 schwarze Exp $
+.\" $Id: mandocdb.8,v 1.17.2.1 2013/09/18 01:04:07 schwarze Exp $
.\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -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: December 25 2011 $
+.Dd $Mdocdate: September 18 2013 $
.Dt MANDOCDB 8
.Os
.Sh NAME
@@ -125,7 +125,7 @@ is printed to stderr, omitted from the index, and the parse continues
with the next input file.
.Ss Index Database
The index database,
-.Pa whatis.index ,
+.Pa mandoc.index ,
is a
.Xr recno 3
database with record values consisting of
@@ -161,7 +161,7 @@ Each of the above is NUL-terminated.
If the record value is zero-length, it is unassigned.
.Ss Keyword Database
The keyword database,
-.Pa whatis.db ,
+.Pa mandoc.db ,
is a
.Xr btree 3
database of NUL-terminated keywords (record length is non-zero string
@@ -225,12 +225,12 @@ or
respectively, grows as a multiple of the index length and input size.
.Sh FILES
.Bl -tag -width Ds
-.It Pa whatis.db
+.It Pa mandoc.db
A
.Xr btree 3
keyword database mapping keywords to a type and file reference in
-.Pa whatis.index .
-.It Pa whatis.index
+.Pa mandoc.index .
+.It Pa mandoc.index
A
.Xr recno 3
database of indexed file-names.
@@ -285,9 +285,40 @@ arguments.
.Xr btree 3 ,
.Xr recno 3 ,
.Xr man.conf 5
-.Sh AUTHORS
+.Sh HISTORY
+A
+.Nm makewhatis
+utility first appeared in
+.Bx 2 .
+It was rewritten in
+.Xr perl 1
+for
+.Ox 2.7
+and in C for
+.Ox 5.1 .
+.Pp
The
+.Ar dir
+argument first appeared in
+.Nx 1.0 ;
+the options
+.Fl dtu
+in
+.Ox 2.7 ;
+and the options
+.Fl aCvW
+in
+.Ox 5.1 .
+.Sh AUTHORS
+.An -nosplit
+.An Bill Joy
+wrote the original
+.Bx
+.Nm makewhatis
+in February 1979,
+.An Marc Espie
+started the Perl version in 2000,
+and the current version of
.Nm
-utility was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+was written by
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
diff --git a/mandocdb.c b/mandocdb.c
index e621c1d2a211..a7491cafa6ab 100644
--- a/mandocdb.c
+++ b/mandocdb.c
@@ -1,7 +1,7 @@
-/* $Id: mandocdb.c,v 1.46 2012/03/23 06:52:17 kristaps Exp $ */
+/* $Id: mandocdb.c,v 1.49.2.10 2013/11/21 01:53:48 schwarze Exp $ */
/*
- * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011, 2012 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,7 +19,6 @@
#include "config.h"
#endif
-#include <sys/param.h>
#include <sys/types.h>
#include <assert.h>
@@ -28,18 +27,26 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
+#include <limits.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#if defined(__linux__)
+#if defined(__APPLE__)
+# include <libkern/OSByteOrder.h>
+#elif defined(__linux__)
# include <endian.h>
+#elif defined(__sun)
+# include <sys/byteorder.h>
+# include <sys/stat.h>
+#else
+# include <sys/endian.h>
+#endif
+
+#if defined(__linux__) || defined(__sun)
# include <db_185.h>
-#elif defined(__APPLE__)
-# include <libkern/OSByteOrder.h>
-# include <db.h>
#else
# include <db.h>
#endif
@@ -56,20 +63,11 @@
#define MANDOC_SRC 0x1
#define MANDOC_FORM 0x2
-#define WARNING(_f, _b, _fmt, _args...) \
- do if (warnings) { \
- fprintf(stderr, "%s: ", (_b)); \
- fprintf(stderr, (_fmt), ##_args); \
- if ('\0' != *(_f)) \
- fprintf(stderr, ": %s", (_f)); \
- fprintf(stderr, "\n"); \
- } while (/* CONSTCOND */ 0)
-
/* Access to the mandoc database on disk. */
struct mdb {
- char idxn[MAXPATHLEN]; /* index db filename */
- char dbn[MAXPATHLEN]; /* keyword db filename */
+ char idxn[PATH_MAX]; /* index db filename */
+ char dbn[PATH_MAX]; /* keyword db filename */
DB *idx; /* index recno database */
DB *db; /* keyword btree database */
};
@@ -133,17 +131,16 @@ static void hash_put(DB *, const struct buf *, uint64_t);
static void hash_reset(DB **);
static void index_merge(const struct of *, struct mparse *,
struct buf *, struct buf *, DB *,
- struct mdb *, struct recs *,
- const char *);
+ struct mdb *, struct recs *);
static void index_prune(const struct of *, struct mdb *,
- struct recs *, const char *);
-static void ofile_argbuild(int, char *[],
- struct of **, const char *);
+ struct recs *);
+static void ofile_argbuild(int, char *[], struct of **,
+ const char *);
static void ofile_dirbuild(const char *, const char *,
- const char *, int, struct of **, char *);
+ const char *, int, struct of **);
static void ofile_free(struct of *);
-static void pformatted(DB *, struct buf *, struct buf *,
- const struct of *, const char *);
+static void pformatted(DB *, struct buf *,
+ struct buf *, const struct of *);
static int pman_node(MAN_ARGS);
static void pmdoc_node(MDOC_ARGS);
static int pmdoc_head(MDOC_ARGS);
@@ -304,11 +301,12 @@ main(int argc, char *argv[])
struct recs recs;
enum op op; /* current operation */
const char *dir;
+ char *cp;
+ char pbuf[PATH_MAX];
int ch, i, flags;
- char dirbuf[MAXPATHLEN];
DB *hash; /* temporary keyword hashtable */
BTREEINFO info; /* btree configuration */
- size_t sz1, sz2;
+ size_t sz1, sz2, ipath;
struct buf buf, /* keyword buffer */
dbuf; /* description buffer */
struct of *of; /* list of files for processing */
@@ -396,7 +394,7 @@ main(int argc, char *argv[])
info.lorder = 4321;
info.flags = R_DUP;
- mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
+ mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL, NULL);
memset(&buf, 0, sizeof(struct buf));
memset(&dbuf, 0, sizeof(struct buf));
@@ -407,25 +405,31 @@ main(int argc, char *argv[])
dbuf.cp = mandoc_malloc(dbuf.size);
if (OP_TEST == op) {
- ofile_argbuild(argc, argv, &of, ".");
+ ofile_argbuild(argc, argv, &of, NULL);
if (NULL == of)
goto out;
- index_merge(of, mp, &dbuf, &buf,
- hash, &mdb, &recs, ".");
+ index_merge(of, mp, &dbuf, &buf, hash, &mdb, &recs);
goto out;
}
if (OP_UPDATE == op || OP_DELETE == op) {
- strlcat(mdb.dbn, dir, MAXPATHLEN);
- strlcat(mdb.dbn, "/", MAXPATHLEN);
- sz1 = strlcat(mdb.dbn, MANDOC_DB, MAXPATHLEN);
+ if (NULL == realpath(dir, pbuf)) {
+ perror(dir);
+ exit((int)MANDOCLEVEL_BADARG);
+ }
+ if (strlcat(pbuf, "/", PATH_MAX) >= PATH_MAX) {
+ fprintf(stderr, "%s: path too long\n", pbuf);
+ exit((int)MANDOCLEVEL_BADARG);
+ }
+
+ strlcat(mdb.dbn, pbuf, PATH_MAX);
+ sz1 = strlcat(mdb.dbn, MANDOC_DB, PATH_MAX);
- strlcat(mdb.idxn, dir, MAXPATHLEN);
- strlcat(mdb.idxn, "/", MAXPATHLEN);
- sz2 = strlcat(mdb.idxn, MANDOC_IDX, MAXPATHLEN);
+ strlcat(mdb.idxn, pbuf, PATH_MAX);
+ sz2 = strlcat(mdb.idxn, MANDOC_IDX, PATH_MAX);
- if (sz1 >= MAXPATHLEN || sz2 >= MAXPATHLEN) {
- fprintf(stderr, "%s: path too long\n", dir);
+ if (sz1 >= PATH_MAX || sz2 >= PATH_MAX) {
+ fprintf(stderr, "%s: path too long\n", mdb.idxn);
exit((int)MANDOCLEVEL_BADARG);
}
@@ -441,12 +445,12 @@ main(int argc, char *argv[])
exit((int)MANDOCLEVEL_SYSERR);
}
- ofile_argbuild(argc, argv, &of, dir);
+ ofile_argbuild(argc, argv, &of, pbuf);
if (NULL == of)
goto out;
- index_prune(of, &mdb, &recs, dir);
+ index_prune(of, &mdb, &recs);
/*
* Go to the root of the respective manual tree.
@@ -460,7 +464,7 @@ main(int argc, char *argv[])
exit((int)MANDOCLEVEL_SYSERR);
}
index_merge(of, mp, &dbuf, &buf, hash,
- &mdb, &recs, dir);
+ &mdb, &recs);
}
goto out;
@@ -475,48 +479,72 @@ main(int argc, char *argv[])
if (argc > 0) {
dirs.paths = mandoc_calloc(argc, sizeof(char *));
dirs.sz = argc;
- for (i = 0; i < argc; i++)
- dirs.paths[i] = mandoc_strdup(argv[i]);
+ for (i = 0; i < argc; i++) {
+ if (NULL == (cp = realpath(argv[i], pbuf))) {
+ perror(argv[i]);
+ goto out;
+ }
+ dirs.paths[i] = mandoc_strdup(cp);
+ }
} else
manpath_parse(&dirs, dir, NULL, NULL);
- for (i = 0; i < dirs.sz; i++) {
+ for (ipath = 0; ipath < dirs.sz; ipath++) {
+
/*
* Go to the root of the respective manual tree.
* This must work or no manuals may be found:
* They are indexed relative to the root.
*/
- if (-1 == chdir(dirs.paths[i])) {
- perror(dirs.paths[i]);
+ if (-1 == chdir(dirs.paths[ipath])) {
+ perror(dirs.paths[ipath]);
exit((int)MANDOCLEVEL_SYSERR);
}
- strlcpy(mdb.dbn, MANDOC_DB, MAXPATHLEN);
- strlcpy(mdb.idxn, MANDOC_IDX, MAXPATHLEN);
-
- flags = O_CREAT | O_TRUNC | O_RDWR;
- mdb.db = dbopen(mdb.dbn, flags, 0644, DB_BTREE, &info);
- mdb.idx = dbopen(mdb.idxn, flags, 0644, DB_RECNO, NULL);
+ /* Create a new database in two temporary files. */
- if (NULL == mdb.db) {
- perror(mdb.dbn);
- exit((int)MANDOCLEVEL_SYSERR);
- } else if (NULL == mdb.idx) {
- perror(mdb.idxn);
- exit((int)MANDOCLEVEL_SYSERR);
+ flags = O_CREAT | O_EXCL | O_RDWR;
+ while (NULL == mdb.db) {
+ strlcpy(mdb.dbn, MANDOC_DB, PATH_MAX);
+ strlcat(mdb.dbn, ".XXXXXXXXXX", PATH_MAX);
+ if (NULL == mktemp(mdb.dbn)) {
+ perror(mdb.dbn);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ mdb.db = dbopen(mdb.dbn, flags, 0644,
+ DB_BTREE, &info);
+ if (NULL == mdb.db && EEXIST != errno) {
+ perror(mdb.dbn);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ }
+ while (NULL == mdb.idx) {
+ strlcpy(mdb.idxn, MANDOC_IDX, PATH_MAX);
+ strlcat(mdb.idxn, ".XXXXXXXXXX", PATH_MAX);
+ if (NULL == mktemp(mdb.idxn)) {
+ perror(mdb.idxn);
+ unlink(mdb.dbn);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ mdb.idx = dbopen(mdb.idxn, flags, 0644,
+ DB_RECNO, NULL);
+ if (NULL == mdb.idx && EEXIST != errno) {
+ perror(mdb.idxn);
+ unlink(mdb.dbn);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
}
/*
* Search for manuals and fill the new database.
*/
- strlcpy(dirbuf, dirs.paths[i], MAXPATHLEN);
- ofile_dirbuild(".", "", "", 0, &of, dirbuf);
+ ofile_dirbuild(".", "", "", 0, &of);
if (NULL != of) {
index_merge(of, mp, &dbuf, &buf, hash,
- &mdb, &recs, dirs.paths[i]);
+ &mdb, &recs);
ofile_free(of);
of = NULL;
}
@@ -525,6 +553,26 @@ main(int argc, char *argv[])
(*mdb.idx->close)(mdb.idx);
mdb.db = NULL;
mdb.idx = NULL;
+
+ /*
+ * Replace the old database with the new one.
+ * This is not perfectly atomic,
+ * but i cannot think of a better way.
+ */
+
+ if (-1 == rename(mdb.dbn, MANDOC_DB)) {
+ perror(MANDOC_DB);
+ unlink(mdb.dbn);
+ unlink(mdb.idxn);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ if (-1 == rename(mdb.idxn, MANDOC_IDX)) {
+ perror(MANDOC_IDX);
+ unlink(MANDOC_DB);
+ unlink(MANDOC_IDX);
+ unlink(mdb.idxn);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
}
out:
@@ -547,7 +595,7 @@ out:
usage:
fprintf(stderr,
- "usage: %s [-av] [-C file] | dir ... | -t file ...\n"
+ "usage: %s [-avvv] [-C file] | dir ... | -t file ...\n"
" -d dir [file ...] | "
"-u dir [file ...]\n",
progname);
@@ -558,24 +606,24 @@ usage:
void
index_merge(const struct of *of, struct mparse *mp,
struct buf *dbuf, struct buf *buf, DB *hash,
- struct mdb *mdb, struct recs *recs,
- const char *basedir)
+ struct mdb *mdb, struct recs *recs)
{
recno_t rec;
int ch, skip;
DBT key, val;
DB *files; /* temporary file name table */
- char emptystring[1] = {'\0'};
struct mdoc *mdoc;
struct man *man;
- char *p;
const char *fn, *msec, *march, *mtitle;
+ char *p;
uint64_t mask;
size_t sv;
unsigned seq;
uint64_t vbuf[2];
char type;
+ static char emptystring[] = "";
+
if (warnings) {
files = NULL;
hash_reset(&files);
@@ -629,9 +677,13 @@ index_merge(const struct of *of, struct mparse *mp,
skip = 0;
assert(of->sec);
assert(msec);
- if (strcasecmp(msec, of->sec))
- WARNING(fn, basedir, "Section \"%s\" manual "
- "in \"%s\" directory", msec, of->sec);
+ if (warnings)
+ if (strcasecmp(msec, of->sec))
+ fprintf(stderr, "%s: "
+ "section \"%s\" manual "
+ "in \"%s\" directory\n",
+ fn, msec, of->sec);
+
/*
* Manual page directories exist for each kernel
* architecture as returned by machine(1).
@@ -649,10 +701,12 @@ index_merge(const struct of *of, struct mparse *mp,
assert(of->arch);
assert(march);
- if (strcasecmp(march, of->arch))
- WARNING(fn, basedir, "Architecture \"%s\" "
- "manual in \"%s\" directory",
- march, of->arch);
+ if (warnings)
+ if (strcasecmp(march, of->arch))
+ fprintf(stderr, "%s: "
+ "architecture \"%s\" manual "
+ "in \"%s\" directory\n",
+ fn, march, of->arch);
/*
* By default, skip a file if the title given
@@ -682,7 +736,7 @@ index_merge(const struct of *of, struct mparse *mp,
}
buf_appendb(buf, ")", 2);
for (p = buf->cp; '\0' != *p; p++)
- *p = tolower(*p);
+ *p = tolower((unsigned char)*p);
key.data = buf->cp;
key.size = buf->len;
val.data = NULL;
@@ -742,7 +796,7 @@ index_merge(const struct of *of, struct mparse *mp,
else if (man)
pman_node(hash, buf, dbuf, man_node(man));
else
- pformatted(hash, buf, dbuf, of, basedir);
+ pformatted(hash, buf, dbuf, of);
/* Test mode, do not access any database. */
@@ -789,6 +843,8 @@ index_merge(const struct of *of, struct mparse *mp,
}
if (ch < 0) {
perror("hash");
+ unlink(mdb->dbn);
+ unlink(mdb->idxn);
exit((int)MANDOCLEVEL_SYSERR);
}
@@ -807,7 +863,7 @@ index_merge(const struct of *of, struct mparse *mp,
val.size = dbuf->len;
if (verb)
- printf("%s: Adding to index: %s\n", basedir, fn);
+ printf("%s: adding to index\n", fn);
dbt_put(mdb->idx, mdb->idxn, &key, &val);
}
@@ -822,9 +878,9 @@ index_merge(const struct of *of, struct mparse *mp,
while (0 == (*files->seq)(files, &key, &val, seq)) {
seq = R_NEXT;
if (val.size)
- WARNING((char *)val.data, basedir,
- "Probably unreachable, title "
- "is %s", (char *)key.data);
+ fprintf(stderr, "%s: probably "
+ "unreachable, title is %s\n",
+ (char *)val.data, (char *)key.data);
}
(*files->close)(files);
}
@@ -837,8 +893,7 @@ index_merge(const struct of *of, struct mparse *mp,
* in `idx' (zeroing its value size).
*/
static void
-index_prune(const struct of *ofile, struct mdb *mdb,
- struct recs *recs, const char *basedir)
+index_prune(const struct of *ofile, struct mdb *mdb, struct recs *recs)
{
const struct of *of;
const char *fn;
@@ -913,8 +968,7 @@ index_prune(const struct of *ofile, struct mdb *mdb,
}
if (verb)
- printf("%s: Deleting from index: %s\n",
- basedir, fn);
+ printf("%s: deleting from index\n", fn);
val.size = 0;
ch = (*mdb->idx->put)(mdb->idx, &key, &val, R_CURSOR);
@@ -1474,15 +1528,16 @@ pman_node(MAN_ARGS)
* By necessity, this involves rather crude guesswork.
*/
static void
-pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
- const struct of *of, const char *basedir)
+pformatted(DB *hash, struct buf *buf,
+ struct buf *dbuf, const struct of *of)
{
FILE *stream;
char *line, *p, *title;
size_t len, plen, titlesz;
if (NULL == (stream = fopen(of->fname, "r"))) {
- WARNING(of->fname, basedir, "%s", strerror(errno));
+ if (warnings)
+ perror(of->fname);
return;
}
@@ -1537,6 +1592,7 @@ pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
title[(int)titlesz - 1] = ' ';
}
+
/*
* If no page content can be found, or the input line
* is already the next section header, or there is no
@@ -1545,8 +1601,9 @@ pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
*/
if (NULL == title || '\0' == *title) {
- WARNING(of->fname, basedir,
- "Cannot find NAME section");
+ if (warnings)
+ fprintf(stderr, "%s: cannot find NAME section\n",
+ of->fname);
buf_appendb(dbuf, buf->cp, buf->size);
hash_put(hash, buf, TYPE_Nd);
fclose(stream);
@@ -1567,8 +1624,9 @@ pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
for (p += 2; ' ' == *p || '\b' == *p; p++)
/* Skip to next word. */ ;
} else {
- WARNING(of->fname, basedir,
- "No dash in title line");
+ if (warnings)
+ fprintf(stderr, "%s: no dash in title line\n",
+ of->fname);
p = title;
}
@@ -1595,16 +1653,30 @@ pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
}
static void
-ofile_argbuild(int argc, char *argv[],
- struct of **of, const char *basedir)
+ofile_argbuild(int argc, char *argv[], struct of **of,
+ const char *basedir)
{
- char buf[MAXPATHLEN];
+ char buf[PATH_MAX];
+ char pbuf[PATH_MAX];
const char *sec, *arch, *title;
- char *p;
+ char *relpath, *p;
int i, src_form;
struct of *nof;
for (i = 0; i < argc; i++) {
+ if (NULL == (relpath = realpath(argv[i], pbuf))) {
+ perror(argv[i]);
+ continue;
+ }
+ if (NULL != basedir) {
+ if (strstr(pbuf, basedir) != pbuf) {
+ fprintf(stderr, "%s: file outside "
+ "base directory %s\n",
+ pbuf, basedir);
+ continue;
+ }
+ relpath = pbuf + strlen(basedir);
+ }
/*
* Try to infer the manual section, architecture and
@@ -1613,8 +1685,8 @@ ofile_argbuild(int argc, char *argv[],
* cat<section>[/<arch>]/<title>.0
*/
- if (strlcpy(buf, argv[i], sizeof(buf)) >= sizeof(buf)) {
- fprintf(stderr, "%s: Path too long\n", argv[i]);
+ if (strlcpy(buf, relpath, sizeof(buf)) >= sizeof(buf)) {
+ fprintf(stderr, "%s: path too long\n", relpath);
continue;
}
sec = arch = title = "";
@@ -1646,8 +1718,11 @@ ofile_argbuild(int argc, char *argv[],
break;
}
if ('\0' == *title) {
- WARNING(argv[i], basedir,
- "Cannot deduce title from filename");
+ if (warnings)
+ fprintf(stderr,
+ "%s: cannot deduce title "
+ "from filename\n",
+ relpath);
title = buf;
}
@@ -1656,7 +1731,7 @@ ofile_argbuild(int argc, char *argv[],
*/
nof = mandoc_calloc(1, sizeof(struct of));
- nof->fname = mandoc_strdup(argv[i]);
+ nof->fname = mandoc_strdup(relpath);
nof->sec = mandoc_strdup(sec);
nof->arch = mandoc_strdup(arch);
nof->title = mandoc_strdup(title);
@@ -1681,15 +1756,18 @@ ofile_argbuild(int argc, char *argv[],
* Recursively build up a list of files to parse.
* We use this instead of ftw() and so on because I don't want global
* variables hanging around.
- * This ignores the mandocdb.db and mandocdb.index files, but assumes that
+ * This ignores the mandoc.db and mandoc.index files, but assumes that
* everything else is a manual.
* Pass in a pointer to a NULL structure for the first invocation.
*/
static void
ofile_dirbuild(const char *dir, const char* psec, const char *parch,
- int p_src_form, struct of **of, char *basedir)
+ int p_src_form, struct of **of)
{
- char buf[MAXPATHLEN];
+ char buf[PATH_MAX];
+#if defined(__sun)
+ struct stat sb;
+#endif
size_t sz;
DIR *d;
const char *fn, *sec, *arch;
@@ -1699,7 +1777,8 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
int src_form;
if (NULL == (d = opendir(dir))) {
- WARNING("", dir, "%s", strerror(errno));
+ if (warnings)
+ perror(dir);
return;
}
@@ -1711,7 +1790,12 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
src_form = p_src_form;
+#if defined(__sun)
+ stat(dp->d_name, &sb);
+ if (S_IFDIR & sb.st_mode) {
+#else
if (DT_DIR == dp->d_type) {
+#endif
sec = psec;
arch = parch;
@@ -1729,7 +1813,9 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
src_form |= MANDOC_FORM;
sec = fn + 3;
} else {
- WARNING(fn, basedir, "Bad section");
+ if (warnings) fprintf(stderr,
+ "%s/%s: bad section\n",
+ dir, fn);
if (use_all)
sec = fn;
else
@@ -1737,45 +1823,53 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
}
} else if ('\0' == *arch) {
if (NULL != strchr(fn, '.')) {
- WARNING(fn, basedir, "Bad architecture");
+ if (warnings) fprintf(stderr,
+ "%s/%s: bad architecture\n",
+ dir, fn);
if (0 == use_all)
continue;
}
arch = fn;
} else {
- WARNING(fn, basedir, "Excessive subdirectory");
+ if (warnings) fprintf(stderr, "%s/%s: "
+ "excessive subdirectory\n", dir, fn);
if (0 == use_all)
continue;
}
buf[0] = '\0';
- strlcat(buf, dir, MAXPATHLEN);
- strlcat(buf, "/", MAXPATHLEN);
- strlcat(basedir, "/", MAXPATHLEN);
- strlcat(basedir, fn, MAXPATHLEN);
- sz = strlcat(buf, fn, MAXPATHLEN);
-
- if (MAXPATHLEN <= sz) {
- WARNING(fn, basedir, "Path too long");
+ strlcat(buf, dir, PATH_MAX);
+ strlcat(buf, "/", PATH_MAX);
+ sz = strlcat(buf, fn, PATH_MAX);
+
+ if (PATH_MAX <= sz) {
+ if (warnings) fprintf(stderr, "%s/%s: "
+ "path too long\n", dir, fn);
continue;
}
- ofile_dirbuild(buf, sec, arch,
- src_form, of, basedir);
-
- p = strrchr(basedir, '/');
- *p = '\0';
+ ofile_dirbuild(buf, sec, arch, src_form, of);
continue;
}
+#if defined(__sun)
+ if (0 == S_IFREG & sb.st_mode) {
+#else
if (DT_REG != dp->d_type) {
- WARNING(fn, basedir, "Not a regular file");
+#endif
+ if (warnings)
+ fprintf(stderr,
+ "%s/%s: not a regular file\n",
+ dir, fn);
continue;
}
if (!strcmp(MANDOC_DB, fn) || !strcmp(MANDOC_IDX, fn))
continue;
if ('\0' == *psec) {
- WARNING(fn, basedir, "File outside section");
+ if (warnings)
+ fprintf(stderr,
+ "%s/%s: file outside section\n",
+ dir, fn);
if (0 == use_all)
continue;
}
@@ -1788,14 +1882,20 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
suffix = strrchr(fn, '.');
if (NULL == suffix) {
- WARNING(fn, basedir, "No filename suffix");
+ if (warnings)
+ fprintf(stderr,
+ "%s/%s: no filename suffix\n",
+ dir, fn);
if (0 == use_all)
continue;
} else if ((MANDOC_SRC & src_form &&
strcmp(suffix + 1, psec)) ||
(MANDOC_FORM & src_form &&
strcmp(suffix + 1, "0"))) {
- WARNING(fn, basedir, "Wrong filename suffix");
+ if (warnings)
+ fprintf(stderr,
+ "%s/%s: wrong filename suffix\n",
+ dir, fn);
if (0 == use_all)
continue;
if ('0' == suffix[1])
@@ -1814,7 +1914,7 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
if (0 == use_all && MANDOC_FORM & src_form &&
'\0' != *psec) {
buf[0] = '\0';
- strlcat(buf, dir, MAXPATHLEN);
+ strlcat(buf, dir, PATH_MAX);
p = strrchr(buf, '/');
if ('\0' != *parch && NULL != p)
for (p--; p > buf; p--)
@@ -1826,18 +1926,22 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
p++;
if (0 == strncmp("cat", p, 3))
memcpy(p, "man", 3);
- strlcat(buf, "/", MAXPATHLEN);
- sz = strlcat(buf, fn, MAXPATHLEN);
- if (sz >= MAXPATHLEN) {
- WARNING(fn, basedir, "Path too long");
+ strlcat(buf, "/", PATH_MAX);
+ sz = strlcat(buf, fn, PATH_MAX);
+ if (sz >= PATH_MAX) {
+ if (warnings) fprintf(stderr,
+ "%s/%s: path too long\n",
+ dir, fn);
continue;
}
q = strrchr(buf, '.');
if (NULL != q && p < q++) {
*q = '\0';
- sz = strlcat(buf, psec, MAXPATHLEN);
- if (sz >= MAXPATHLEN) {
- WARNING(fn, basedir, "Path too long");
+ sz = strlcat(buf, psec, PATH_MAX);
+ if (sz >= PATH_MAX) {
+ if (warnings) fprintf(stderr,
+ "%s/%s: path too long\n",
+ dir, fn);
continue;
}
if (0 == access(buf, R_OK))
@@ -1848,12 +1952,13 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
buf[0] = '\0';
assert('.' == dir[0]);
if ('/' == dir[1]) {
- strlcat(buf, dir + 2, MAXPATHLEN);
- strlcat(buf, "/", MAXPATHLEN);
+ strlcat(buf, dir + 2, PATH_MAX);
+ strlcat(buf, "/", PATH_MAX);
}
- sz = strlcat(buf, fn, MAXPATHLEN);
- if (sz >= MAXPATHLEN) {
- WARNING(fn, basedir, "Path too long");
+ sz = strlcat(buf, fn, PATH_MAX);
+ if (sz >= PATH_MAX) {
+ if (warnings) fprintf(stderr,
+ "%s/%s: path too long\n", dir, fn);
continue;
}
diff --git a/mandocdb.h b/mandocdb.h
index bda0536e793f..1bfd686ffc67 100644
--- a/mandocdb.h
+++ b/mandocdb.h
@@ -1,4 +1,4 @@
-/* $Id: mandocdb.h,v 1.6 2012/03/23 02:52:33 kristaps Exp $ */
+/* $Id: mandocdb.h,v 1.6.2.1 2013/09/18 00:54:20 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -17,8 +17,8 @@
#ifndef MANDOCDB_H
#define MANDOCDB_H
-#define MANDOC_DB "mandocdb.db"
-#define MANDOC_IDX "mandocdb.index"
+#define MANDOC_DB "mandoc.db"
+#define MANDOC_IDX "mandoc.index"
#define TYPE_An 0x0000000000000001ULL
#define TYPE_Ar 0x0000000000000002ULL
diff --git a/manpath.c b/manpath.c
index b6d9574e3070..c33e0ecf469c 100644
--- a/manpath.c
+++ b/manpath.c
@@ -1,4 +1,4 @@
-/* $Id: manpath.c,v 1.8 2011/12/24 22:37:16 kristaps Exp $ */
+/* $Id: manpath.c,v 1.12 2013/11/21 01:49:18 schwarze Exp $ */
/*
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -19,8 +19,6 @@
#include "config.h"
#endif
-#include <sys/param.h>
-
#include <assert.h>
#include <ctype.h>
#include <limits.h>
@@ -42,7 +40,7 @@ manpath_parse(struct manpaths *dirs, const char *file,
char *defp, char *auxp)
{
#ifdef USE_MANPATH
- char cmd[(MAXPATHLEN * 3) + 20];
+ char cmd[(PATH_MAX * 3) + 20];
FILE *stream;
char *buf;
size_t sz, bsz;
@@ -74,7 +72,7 @@ manpath_parse(struct manpaths *dirs, const char *file,
do {
buf = mandoc_realloc(buf, bsz + 1024);
- sz = fread(buf + (int)bsz, 1, 1024, stream);
+ sz = fread(buf + bsz, 1, 1024, stream);
bsz += sz;
} while (sz > 0);
@@ -90,8 +88,8 @@ manpath_parse(struct manpaths *dirs, const char *file,
char *insert;
/* Always prepend -m. */
- manpath_parseline(dirs, auxp);
-
+ manpath_parseline(dirs, auxp);
+
/* If -M is given, it overrides everything else. */
if (NULL != defp) {
manpath_parseline(dirs, defp);
@@ -117,7 +115,7 @@ manpath_parse(struct manpaths *dirs, const char *file,
}
/* Append man.conf(5) to MANPATH. */
- if (':' == defp[(int)strlen(defp) - 1]) {
+ if (':' == defp[strlen(defp) - 1]) {
manpath_parseline(dirs, defp);
manpath_manconf(dirs, file);
return;
@@ -162,7 +160,7 @@ manpath_add(struct manpaths *dirs, const char *dir)
{
char buf[PATH_MAX];
char *cp;
- int i;
+ size_t i;
if (NULL == (cp = realpath(dir, buf)))
return;
@@ -173,7 +171,7 @@ manpath_add(struct manpaths *dirs, const char *dir)
dirs->paths = mandoc_realloc
(dirs->paths,
- ((size_t)dirs->sz + 1) * sizeof(char *));
+ (dirs->sz + 1) * sizeof(char *));
dirs->paths[dirs->sz++] = mandoc_strdup(cp);
}
@@ -181,7 +179,7 @@ manpath_add(struct manpaths *dirs, const char *dir)
void
manpath_free(struct manpaths *p)
{
- int i;
+ size_t i;
for (i = 0; i < p->sz; i++)
free(p->paths[i]);
@@ -211,7 +209,7 @@ manpath_manconf(struct manpaths *dirs, const char *file)
if (strncmp(MAN_CONF_KEY, p, keysz))
continue;
p += keysz;
- while (isspace(*p))
+ while (isspace((unsigned char)*p))
p++;
if ('\0' == *p)
continue;
diff --git a/manpath.h b/manpath.h
index 167ee01021ea..2fe1b36e15f2 100644
--- a/manpath.h
+++ b/manpath.h
@@ -1,4 +1,4 @@
-/* $Id: manpath.h,v 1.5 2011/12/13 20:56:46 kristaps Exp $ */
+/* $Id: manpath.h,v 1.6 2012/06/08 10:32:40 kristaps Exp $ */
/*
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -23,7 +23,7 @@
* databases.
*/
struct manpaths {
- int sz;
+ size_t sz;
char **paths;
};
diff --git a/mdoc.7 b/mdoc.7
index 44d927b56b82..165c76b95001 100644
--- a/mdoc.7
+++ b/mdoc.7
@@ -1,7 +1,7 @@
-.\" $Id: mdoc.7,v 1.214 2012/01/03 10:18:05 kristaps Exp $
+.\" $Id: mdoc.7,v 1.223 2013/12/25 14:09:32 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010, 2011, 2013 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: January 3 2012 $
+.Dd $Mdocdate: December 25 2013 $
.Dt MDOC 7
.Os
.Sh NAME
@@ -477,6 +477,7 @@ in the alphabetical
.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:
@@ -657,7 +658,7 @@ for all other author listings.
.Pp
Examples:
.Dl \&.An -nosplit
-.Dl \&.An Kristaps Dzonsons \&Aq kristaps@bsd.lv
+.Dl \&.An Kristaps Dzonsons \&Aq \&Mt kristaps@bsd.lv
.Ss \&Ao
Begin a block enclosed by angle brackets.
Does not have any head arguments.
@@ -711,7 +712,9 @@ for fixed strings to be passed verbatim as arguments, use
or
.Sx \&Cm .
.Ss \&At
-Formats an AT&T version.
+Formats an
+.At
+version.
Accepts one optional argument:
.Pp
.Bl -tag -width "v[1-7] | 32vX" -offset indent -compact
@@ -820,8 +823,8 @@ The most popular is the imaginary macro
which resolves to
.Sy 6n .
.It
-A width using the syntax described in
-.Sx Scaling Widths .
+A scaling width as described in
+.Xr roff 7 .
.It
An arbitrary string, which indents by the length of this string.
.El
@@ -926,8 +929,8 @@ The
.Fl width
and
.Fl offset
-arguments accept
-.Sx Scaling Widths
+arguments accept scaling widths as described in
+.Xr roff 7
or use the length of the given string.
The
.Fl offset
@@ -956,9 +959,9 @@ A columnated list.
The
.Fl width
argument has no effect; instead, each argument specifies the width
-of one column, using either the
-.Sx Scaling Widths
-syntax or the string length of the argument.
+of one column, using either the scaling width syntax described in
+.Xr roff 7
+or the string length of the argument.
If the first line of the body of a
.Fl column
list is not an
@@ -1089,7 +1092,9 @@ Examples:
See also
.Sx \&Bro .
.Ss \&Bsx
-Format the BSD/OS version provided as an argument, or a default value if
+Format the
+.Bsx
+version provided as an argument, or a default value if
no argument is provided.
.Pp
Examples:
@@ -1109,7 +1114,9 @@ and
Prints
.Dq is currently in beta test.
.Ss \&Bx
-Format the BSD version provided as an argument, or a default value if no
+Format the
+.Bx
+version provided as an argument, or a default value if no
argument is provided.
.Pp
Examples:
@@ -1401,11 +1408,16 @@ See also
.Sx \&Er
and
.Sx \&Ev
-for special-purpose constants and
+for special-purpose constants,
.Sx \&Va
-for variable symbols.
+for variable symbols, and
+.Sx \&Fd
+for listing preprocessor variable definitions in the
+.Em SYNOPSIS .
.Ss \&Dx
-Format the DragonFly BSD version provided as an argument, or a default
+Format the
+.Dx
+version provided as an argument, or a default
value if no argument is provided.
.Pp
Examples:
@@ -1562,15 +1574,32 @@ See also
End a function context started by
.Sx \&Fo .
.Ss \&Fd
-Historically used to document include files.
-This usage has been deprecated in favour of
+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 .
-Do not use this macro.
+.Pp
+Its syntax is as follows:
+.Bd -ragged -offset indent
+.Pf \. Sx \&Fd
+.Li # Ns Ar directive
+.Op Ar argument ...
+.Ed
+.Pp
+Examples:
+.Dl \&.Fd #define sa_handler __sigaction_u.__sa_handler
+.Dl \&.Fd #define SIO_MAXNFDS
+.Dl \&.Fd #ifdef FS_DEBUG
+.Dl \&.Ft void
+.Dl \&.Fn dbg_open \(dqconst char *\(dq
+.Dl \&.Fd #endif
.Pp
See also
-.Sx MANUAL STRUCTURE
+.Sx MANUAL STRUCTURE ,
+.Sx \&In ,
and
-.Sx \&In .
+.Sx \&Dv .
.Ss \&Fl
Command-line flag or option.
Used when listing arguments to command-line utilities.
@@ -1851,7 +1880,7 @@ section as described in
.Pp
Examples:
.Dl \&.Lb libz
-.Dl \&.Lb mdoc
+.Dl \&.Lb libmandoc
.Ss \&Li
Denotes text that should be in a
.Li literal
@@ -1902,6 +1931,7 @@ Its syntax is as follows:
.Pp
Examples:
.Dl \&.Mt discuss@manpages.bsd.lv
+.Dl \&.An Kristaps Dzonsons \&Aq \&Mt kristaps@bsd.lv
.Ss \&Nd
A one line description of the manual's content.
This may only be invoked in the
@@ -2083,7 +2113,7 @@ This macro is obsolete and not implemented in
.Xr mandoc 1 .
.Pp
Historical
-.Xr mdoc 7
+.Nm
packages described it as
.Dq "old function type (FORTRAN)" .
.Ss \&Ox
@@ -2347,20 +2377,26 @@ The following standards are recognised:
.St -p1003.1b-93
.It \-p1003.1c-95
.St -p1003.1c-95
+.It \-p1003.1d-99
+.St -p1003.1d-99
.It \-p1003.1g-2000
.St -p1003.1g-2000
.It \-p1003.1i-95
.St -p1003.1i-95
+.It \-p1003.1j-2000
+.St -p1003.1j-2000
+.It \-p1003.1q-2000
+.St -p1003.1q-2000
+.It \-p1003.2
+.St -p1003.2
.It \-p1003.2-92
.St -p1003.2-92
.It \-p1003.2a-92
.St -p1003.2a-92
-.It \-p1387.2-95
-.St -p1387.2-95
-.It \-p1003.2
-.St -p1003.2
.It \-p1387.2
.St -p1387.2
+.It \-p1387.2-95
+.St -p1387.2-95
.It \-isoC
.St -isoC
.It \-isoC-90
@@ -2407,6 +2443,8 @@ The following standards are recognised:
.St -xbd5
.It \-xcu5
.St -xcu5
+.It \-xsh4.2
+.St -xsh4.2
.It \-xsh5
.St -xsh5
.It \-xns5
@@ -2467,7 +2505,9 @@ Examples:
Prints out
.Dq currently under development.
.Ss \&Ux
-Format the UNIX name.
+Format the
+.Ux
+name.
Accepts no argument.
.Pp
Examples:
@@ -2532,20 +2572,14 @@ Link to another manual
.Pq Qq cross-reference .
Its syntax is as follows:
.Pp
-.D1 Pf \. Sx \&Xr Ar name section
+.D1 Pf \. Sx \&Xr Ar name Op section
.Pp
-The
+Cross reference the
.Ar name
and
.Ar section
-are the name and section of the linked manual.
-If
-.Ar section
-is followed by non-punctuation, an
-.Sx \&Ns
-is inserted into the token stream.
-This behaviour is for compatibility with
-GNU troff.
+number of another man page;
+omitting the section number is rarely useful.
.Pp
Examples:
.Dl \&.Xr mandoc 1
@@ -2569,8 +2603,8 @@ Its syntax is as follows:
.Pp
The
.Ar height
-argument must be formatted as described in
-.Sx Scaling Widths .
+argument is a scaling width as described in
+.Xr roff 7 .
If unspecified,
.Sx \&sp
asserts a single vertical space.
@@ -2964,7 +2998,7 @@ Manually switching the font using the
.Ql \ef
font escape sequences is never required.
.Sh COMPATIBILITY
-This section documents compatibility between mandoc and other other
+This section documents compatibility between mandoc and other
troff implementations, at this time limited to GNU troff
.Pq Qq groff .
The term
@@ -3168,5 +3202,4 @@ utility written by Kristaps Dzonsons appeared in
The
.Nm
reference was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
diff --git a/mdoc.c b/mdoc.c
index 81a4ffc96fd4..87b358797b45 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc.c,v 1.196 2011/09/30 00:13:28 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.206 2013/12/24 19:11:46 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012, 2013 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
@@ -104,20 +104,20 @@ static int mdoc_ptext(struct mdoc *, int, char *, int);
static int mdoc_pmacro(struct mdoc *, int, char *, int);
const struct mdoc_node *
-mdoc_node(const struct mdoc *m)
+mdoc_node(const struct mdoc *mdoc)
{
- assert( ! (MDOC_HALT & m->flags));
- return(m->first);
+ assert( ! (MDOC_HALT & mdoc->flags));
+ return(mdoc->first);
}
const struct mdoc_meta *
-mdoc_meta(const struct mdoc *m)
+mdoc_meta(const struct mdoc *mdoc)
{
- assert( ! (MDOC_HALT & m->flags));
- return(&m->meta);
+ assert( ! (MDOC_HALT & mdoc->flags));
+ return(&mdoc->meta);
}
@@ -197,13 +197,14 @@ mdoc_free(struct mdoc *mdoc)
* Allocate volatile and non-volatile parse resources.
*/
struct mdoc *
-mdoc_alloc(struct roff *roff, struct mparse *parse)
+mdoc_alloc(struct roff *roff, struct mparse *parse, char *defos)
{
struct mdoc *p;
p = mandoc_calloc(1, sizeof(struct mdoc));
p->parse = parse;
+ p->defos = defos;
p->roff = roff;
mdoc_hash_init();
@@ -217,61 +218,61 @@ mdoc_alloc(struct roff *roff, struct mparse *parse)
* through to macro_end() in macro.c.
*/
int
-mdoc_endparse(struct mdoc *m)
+mdoc_endparse(struct mdoc *mdoc)
{
- assert( ! (MDOC_HALT & m->flags));
- if (mdoc_macroend(m))
+ assert( ! (MDOC_HALT & mdoc->flags));
+ if (mdoc_macroend(mdoc))
return(1);
- m->flags |= MDOC_HALT;
+ mdoc->flags |= MDOC_HALT;
return(0);
}
int
-mdoc_addeqn(struct mdoc *m, const struct eqn *ep)
+mdoc_addeqn(struct mdoc *mdoc, const struct eqn *ep)
{
struct mdoc_node *n;
- assert( ! (MDOC_HALT & m->flags));
+ assert( ! (MDOC_HALT & mdoc->flags));
/* No text before an initial macro. */
- if (SEC_NONE == m->lastnamed) {
- mdoc_pmsg(m, ep->ln, ep->pos, MANDOCERR_NOTEXT);
+ if (SEC_NONE == mdoc->lastnamed) {
+ mdoc_pmsg(mdoc, ep->ln, ep->pos, MANDOCERR_NOTEXT);
return(1);
}
- n = node_alloc(m, ep->ln, ep->pos, MDOC_MAX, MDOC_EQN);
+ n = node_alloc(mdoc, ep->ln, ep->pos, MDOC_MAX, MDOC_EQN);
n->eqn = ep;
- if ( ! node_append(m, n))
+ if ( ! node_append(mdoc, n))
return(0);
- m->next = MDOC_NEXT_SIBLING;
+ mdoc->next = MDOC_NEXT_SIBLING;
return(1);
}
int
-mdoc_addspan(struct mdoc *m, const struct tbl_span *sp)
+mdoc_addspan(struct mdoc *mdoc, const struct tbl_span *sp)
{
struct mdoc_node *n;
- assert( ! (MDOC_HALT & m->flags));
+ assert( ! (MDOC_HALT & mdoc->flags));
/* No text before an initial macro. */
- if (SEC_NONE == m->lastnamed) {
- mdoc_pmsg(m, sp->line, 0, MANDOCERR_NOTEXT);
+ if (SEC_NONE == mdoc->lastnamed) {
+ mdoc_pmsg(mdoc, sp->line, 0, MANDOCERR_NOTEXT);
return(1);
}
- n = node_alloc(m, sp->line, 0, MDOC_MAX, MDOC_TBL);
+ n = node_alloc(mdoc, sp->line, 0, MDOC_MAX, MDOC_TBL);
n->span = sp;
- if ( ! node_append(m, n))
+ if ( ! node_append(mdoc, n))
return(0);
- m->next = MDOC_NEXT_SIBLING;
+ mdoc->next = MDOC_NEXT_SIBLING;
return(1);
}
@@ -281,12 +282,12 @@ mdoc_addspan(struct mdoc *m, const struct tbl_span *sp)
* the macro (mdoc_pmacro()) or text parser (mdoc_ptext()).
*/
int
-mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs)
+mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs)
{
- assert( ! (MDOC_HALT & m->flags));
+ assert( ! (MDOC_HALT & mdoc->flags));
- m->flags |= MDOC_NEWLINE;
+ mdoc->flags |= MDOC_NEWLINE;
/*
* Let the roff nS register switch SYNOPSIS mode early,
@@ -294,16 +295,14 @@ mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs)
* whether this mode is on or off.
* Note that this mode is also switched by the Sh macro.
*/
- if (roff_regisset(m->roff, REG_nS)) {
- if (roff_regget(m->roff, REG_nS))
- m->flags |= MDOC_SYNOPSIS;
- else
- m->flags &= ~MDOC_SYNOPSIS;
- }
+ if (roff_getreg(mdoc->roff, "nS"))
+ mdoc->flags |= MDOC_SYNOPSIS;
+ else
+ mdoc->flags &= ~MDOC_SYNOPSIS;
- return(mandoc_getcontrol(buf, &offs) ?
- mdoc_pmacro(m, ln, buf, offs) :
- mdoc_ptext(m, ln, buf, offs));
+ return(roff_getcontrol(mdoc->roff, buf, &offs) ?
+ mdoc_pmacro(mdoc, ln, buf, offs) :
+ mdoc_ptext(mdoc, ln, buf, offs));
}
int
@@ -314,31 +313,31 @@ mdoc_macro(MACRO_PROT_ARGS)
/* If we're in the body, deny prologue calls. */
if (MDOC_PROLOGUE & mdoc_macros[tok].flags &&
- MDOC_PBODY & m->flags) {
- mdoc_pmsg(m, line, ppos, MANDOCERR_BADBODY);
+ MDOC_PBODY & mdoc->flags) {
+ mdoc_pmsg(mdoc, line, ppos, MANDOCERR_BADBODY);
return(1);
}
/* If we're in the prologue, deny "body" macros. */
if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) &&
- ! (MDOC_PBODY & m->flags)) {
- mdoc_pmsg(m, line, ppos, MANDOCERR_BADPROLOG);
- if (NULL == m->meta.msec)
- m->meta.msec = mandoc_strdup("1");
- if (NULL == m->meta.title)
- m->meta.title = mandoc_strdup("UNKNOWN");
- if (NULL == m->meta.vol)
- m->meta.vol = mandoc_strdup("LOCAL");
- if (NULL == m->meta.os)
- m->meta.os = mandoc_strdup("LOCAL");
- if (NULL == m->meta.date)
- m->meta.date = mandoc_normdate
- (m->parse, NULL, line, ppos);
- m->flags |= MDOC_PBODY;
+ ! (MDOC_PBODY & mdoc->flags)) {
+ mdoc_pmsg(mdoc, line, ppos, MANDOCERR_BADPROLOG);
+ if (NULL == mdoc->meta.msec)
+ mdoc->meta.msec = mandoc_strdup("1");
+ if (NULL == mdoc->meta.title)
+ mdoc->meta.title = mandoc_strdup("UNKNOWN");
+ if (NULL == mdoc->meta.vol)
+ mdoc->meta.vol = mandoc_strdup("LOCAL");
+ if (NULL == mdoc->meta.os)
+ mdoc->meta.os = mandoc_strdup("LOCAL");
+ if (NULL == mdoc->meta.date)
+ mdoc->meta.date = mandoc_normdate
+ (mdoc->parse, NULL, line, ppos);
+ mdoc->flags |= MDOC_PBODY;
}
- return((*mdoc_macros[tok].fp)(m, tok, line, ppos, pos, buf));
+ return((*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf));
}
@@ -374,6 +373,8 @@ node_append(struct mdoc *mdoc, struct mdoc_node *p)
switch (p->type) {
case (MDOC_BODY):
+ if (ENDBODY_NOT != p->end)
+ break;
/* FALLTHROUGH */
case (MDOC_TAIL):
/* FALLTHROUGH */
@@ -424,97 +425,99 @@ node_append(struct mdoc *mdoc, struct mdoc_node *p)
static struct mdoc_node *
-node_alloc(struct mdoc *m, int line, int pos,
+node_alloc(struct mdoc *mdoc, int line, int pos,
enum mdoct tok, enum mdoc_type type)
{
struct mdoc_node *p;
p = mandoc_calloc(1, sizeof(struct mdoc_node));
- p->sec = m->lastsec;
+ p->sec = mdoc->lastsec;
p->line = line;
p->pos = pos;
+ p->lastline = line;
p->tok = tok;
p->type = type;
/* Flag analysis. */
- if (MDOC_SYNOPSIS & m->flags)
+ if (MDOC_SYNOPSIS & mdoc->flags)
p->flags |= MDOC_SYNPRETTY;
else
p->flags &= ~MDOC_SYNPRETTY;
- if (MDOC_NEWLINE & m->flags)
+ if (MDOC_NEWLINE & mdoc->flags)
p->flags |= MDOC_LINE;
- m->flags &= ~MDOC_NEWLINE;
+ mdoc->flags &= ~MDOC_NEWLINE;
return(p);
}
int
-mdoc_tail_alloc(struct mdoc *m, int line, int pos, enum mdoct tok)
+mdoc_tail_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
{
struct mdoc_node *p;
- p = node_alloc(m, line, pos, tok, MDOC_TAIL);
- if ( ! node_append(m, p))
+ p = node_alloc(mdoc, line, pos, tok, MDOC_TAIL);
+ if ( ! node_append(mdoc, p))
return(0);
- m->next = MDOC_NEXT_CHILD;
+ mdoc->next = MDOC_NEXT_CHILD;
return(1);
}
int
-mdoc_head_alloc(struct mdoc *m, int line, int pos, enum mdoct tok)
+mdoc_head_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
{
struct mdoc_node *p;
- assert(m->first);
- assert(m->last);
+ assert(mdoc->first);
+ assert(mdoc->last);
- p = node_alloc(m, line, pos, tok, MDOC_HEAD);
- if ( ! node_append(m, p))
+ p = node_alloc(mdoc, line, pos, tok, MDOC_HEAD);
+ if ( ! node_append(mdoc, p))
return(0);
- m->next = MDOC_NEXT_CHILD;
+ mdoc->next = MDOC_NEXT_CHILD;
return(1);
}
int
-mdoc_body_alloc(struct mdoc *m, int line, int pos, enum mdoct tok)
+mdoc_body_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
{
struct mdoc_node *p;
- p = node_alloc(m, line, pos, tok, MDOC_BODY);
- if ( ! node_append(m, p))
+ p = node_alloc(mdoc, line, pos, tok, MDOC_BODY);
+ if ( ! node_append(mdoc, p))
return(0);
- m->next = MDOC_NEXT_CHILD;
+ mdoc->next = MDOC_NEXT_CHILD;
return(1);
}
int
-mdoc_endbody_alloc(struct mdoc *m, int line, int pos, enum mdoct tok,
+mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok,
struct mdoc_node *body, enum mdoc_endbody end)
{
struct mdoc_node *p;
- p = node_alloc(m, line, pos, tok, MDOC_BODY);
+ p = node_alloc(mdoc, line, pos, tok, MDOC_BODY);
p->pending = body;
+ p->norm = body->norm;
p->end = end;
- if ( ! node_append(m, p))
+ if ( ! node_append(mdoc, p))
return(0);
- m->next = MDOC_NEXT_SIBLING;
+ mdoc->next = MDOC_NEXT_SIBLING;
return(1);
}
int
-mdoc_block_alloc(struct mdoc *m, int line, int pos,
+mdoc_block_alloc(struct mdoc *mdoc, int line, int pos,
enum mdoct tok, struct mdoc_arg *args)
{
struct mdoc_node *p;
- p = node_alloc(m, line, pos, tok, MDOC_BLOCK);
+ p = node_alloc(mdoc, line, pos, tok, MDOC_BLOCK);
p->args = args;
if (p->args)
(args->refcnt)++;
@@ -533,20 +536,20 @@ mdoc_block_alloc(struct mdoc *m, int line, int pos,
break;
}
- if ( ! node_append(m, p))
+ if ( ! node_append(mdoc, p))
return(0);
- m->next = MDOC_NEXT_CHILD;
+ mdoc->next = MDOC_NEXT_CHILD;
return(1);
}
int
-mdoc_elem_alloc(struct mdoc *m, int line, int pos,
+mdoc_elem_alloc(struct mdoc *mdoc, int line, int pos,
enum mdoct tok, struct mdoc_arg *args)
{
struct mdoc_node *p;
- p = node_alloc(m, line, pos, tok, MDOC_ELEM);
+ p = node_alloc(mdoc, line, pos, tok, MDOC_ELEM);
p->args = args;
if (p->args)
(args->refcnt)++;
@@ -559,27 +562,44 @@ mdoc_elem_alloc(struct mdoc *m, int line, int pos,
break;
}
- if ( ! node_append(m, p))
+ if ( ! node_append(mdoc, p))
return(0);
- m->next = MDOC_NEXT_CHILD;
+ mdoc->next = MDOC_NEXT_CHILD;
return(1);
}
int
-mdoc_word_alloc(struct mdoc *m, int line, int pos, const char *p)
+mdoc_word_alloc(struct mdoc *mdoc, int line, int pos, const char *p)
{
struct mdoc_node *n;
- n = node_alloc(m, line, pos, MDOC_MAX, MDOC_TEXT);
- n->string = roff_strdup(m->roff, p);
+ n = node_alloc(mdoc, line, pos, MDOC_MAX, MDOC_TEXT);
+ n->string = roff_strdup(mdoc->roff, p);
- if ( ! node_append(m, n))
+ if ( ! node_append(mdoc, n))
return(0);
- m->next = MDOC_NEXT_SIBLING;
+ mdoc->next = MDOC_NEXT_SIBLING;
return(1);
}
+void
+mdoc_word_append(struct mdoc *mdoc, const char *p)
+{
+ struct mdoc_node *n;
+ char *addstr, *newstr;
+
+ n = mdoc->last;
+ addstr = roff_strdup(mdoc->roff, p);
+ if (-1 == asprintf(&newstr, "%s %s", n->string, addstr)) {
+ perror(NULL);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ free(addstr);
+ free(n->string);
+ n->string = newstr;
+ mdoc->next = MDOC_NEXT_SIBLING;
+}
static void
mdoc_node_free(struct mdoc_node *p)
@@ -596,7 +616,7 @@ mdoc_node_free(struct mdoc_node *p)
static void
-mdoc_node_unlink(struct mdoc *m, struct mdoc_node *n)
+mdoc_node_unlink(struct mdoc *mdoc, struct mdoc_node *n)
{
/* Adjust siblings. */
@@ -618,35 +638,43 @@ mdoc_node_unlink(struct mdoc *m, struct mdoc_node *n)
/* Adjust parse point, if applicable. */
- if (m && m->last == n) {
+ if (mdoc && mdoc->last == n) {
if (n->prev) {
- m->last = n->prev;
- m->next = MDOC_NEXT_SIBLING;
+ mdoc->last = n->prev;
+ mdoc->next = MDOC_NEXT_SIBLING;
} else {
- m->last = n->parent;
- m->next = MDOC_NEXT_CHILD;
+ mdoc->last = n->parent;
+ mdoc->next = MDOC_NEXT_CHILD;
}
}
- if (m && m->first == n)
- m->first = NULL;
+ if (mdoc && mdoc->first == n)
+ mdoc->first = NULL;
}
void
-mdoc_node_delete(struct mdoc *m, struct mdoc_node *p)
+mdoc_node_delete(struct mdoc *mdoc, struct mdoc_node *p)
{
while (p->child) {
assert(p->nchild);
- mdoc_node_delete(m, p->child);
+ mdoc_node_delete(mdoc, p->child);
}
assert(0 == p->nchild);
- mdoc_node_unlink(m, p);
+ mdoc_node_unlink(mdoc, p);
mdoc_node_free(p);
}
+int
+mdoc_node_relink(struct mdoc *mdoc, struct mdoc_node *p)
+{
+
+ mdoc_node_unlink(mdoc, p);
+ return(node_append(mdoc, p));
+}
+
#if 0
/*
* Pre-treat a text line.
@@ -658,7 +686,7 @@ mdoc_node_delete(struct mdoc *m, struct mdoc_node *p)
* the end-of-line, i.e., will re-enter in the next roff parse.
*/
static int
-mdoc_preptext(struct mdoc *m, int line, char *buf, int offs)
+mdoc_preptext(struct mdoc *mdoc, int line, char *buf, int offs)
{
char *start, *end;
char delim;
@@ -666,12 +694,12 @@ mdoc_preptext(struct mdoc *m, int line, char *buf, int offs)
while ('\0' != buf[offs]) {
/* Mark starting position if eqn is set. */
start = NULL;
- if ('\0' != (delim = roff_eqndelim(m->roff)))
+ if ('\0' != (delim = roff_eqndelim(mdoc->roff)))
if (NULL != (start = strchr(buf + offs, delim)))
*start++ = '\0';
/* Parse text as normal. */
- if ( ! mdoc_ptext(m, line, buf, offs))
+ if ( ! mdoc_ptext(mdoc, line, buf, offs))
return(0);
/* Continue only if an equation exists. */
@@ -688,11 +716,11 @@ mdoc_preptext(struct mdoc *m, int line, char *buf, int offs)
}
/* Parse the equation itself. */
- roff_openeqn(m->roff, NULL, line, offs, buf);
+ roff_openeqn(mdoc->roff, NULL, line, offs, buf);
/* Process a finished equation? */
- if (roff_closeeqn(m->roff))
- if ( ! mdoc_addeqn(m, roff_eqn(m->roff)))
+ if (roff_closeeqn(mdoc->roff))
+ if ( ! mdoc_addeqn(mdoc, roff_eqn(mdoc->roff)))
return(0);
offs += (end - (buf + offs));
}
@@ -706,20 +734,20 @@ mdoc_preptext(struct mdoc *m, int line, char *buf, int offs)
* control character.
*/
static int
-mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
+mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
{
char *c, *ws, *end;
struct mdoc_node *n;
/* No text before an initial macro. */
- if (SEC_NONE == m->lastnamed) {
- mdoc_pmsg(m, line, offs, MANDOCERR_NOTEXT);
+ if (SEC_NONE == mdoc->lastnamed) {
+ mdoc_pmsg(mdoc, line, offs, MANDOCERR_NOTEXT);
return(1);
}
- assert(m->last);
- n = m->last;
+ assert(mdoc->last);
+ n = mdoc->last;
/*
* Divert directly to list processing if we're encountering a
@@ -731,8 +759,8 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
LIST_column == n->norm->Bl.type) {
/* `Bl' is open without any children. */
- m->flags |= MDOC_FREECOL;
- return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf));
+ mdoc->flags |= MDOC_FREECOL;
+ return(mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf));
}
if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
@@ -740,8 +768,8 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
MDOC_Bl == n->parent->tok &&
LIST_column == n->parent->norm->Bl.type) {
/* `Bl' has block-level `It' children. */
- m->flags |= MDOC_FREECOL;
- return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf));
+ mdoc->flags |= MDOC_FREECOL;
+ return(mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf));
}
/*
@@ -769,7 +797,7 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
* Strip trailing tabs in literal context only;
* outside, they affect the next line.
*/
- if (MDOC_LITERAL & m->flags)
+ if (MDOC_LITERAL & mdoc->flags)
continue;
break;
case '\\':
@@ -786,27 +814,28 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
*end = '\0';
if (ws)
- mdoc_pmsg(m, line, (int)(ws-buf), MANDOCERR_EOLNSPACE);
+ mdoc_pmsg(mdoc, line, (int)(ws-buf), MANDOCERR_EOLNSPACE);
- if ('\0' == buf[offs] && ! (MDOC_LITERAL & m->flags)) {
- mdoc_pmsg(m, line, (int)(c-buf), MANDOCERR_NOBLANKLN);
+ if ('\0' == buf[offs] && ! (MDOC_LITERAL & mdoc->flags)) {
+ mdoc_pmsg(mdoc, line, (int)(c-buf), MANDOCERR_NOBLANKLN);
/*
* Insert a `sp' in the case of a blank line. Technically,
* blank lines aren't allowed, but enough manuals assume this
* behaviour that we want to work around it.
*/
- if ( ! mdoc_elem_alloc(m, line, offs, MDOC_sp, NULL))
+ if ( ! mdoc_elem_alloc(mdoc, line, offs, MDOC_sp, NULL))
return(0);
- m->next = MDOC_NEXT_SIBLING;
- return(1);
+ mdoc->next = MDOC_NEXT_SIBLING;
+
+ return(mdoc_valid_post(mdoc));
}
- if ( ! mdoc_word_alloc(m, line, offs, buf+offs))
+ if ( ! mdoc_word_alloc(mdoc, line, offs, buf+offs))
return(0);
- if (MDOC_LITERAL & m->flags)
+ if (MDOC_LITERAL & mdoc->flags)
return(1);
/*
@@ -818,7 +847,7 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
assert(buf < end);
if (mandoc_eos(buf+offs, (size_t)(end-buf-offs), 0))
- m->last->flags |= MDOC_EOS;
+ mdoc->last->flags |= MDOC_EOS;
return(1);
}
@@ -829,7 +858,7 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
* character.
*/
static int
-mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
+mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
{
enum mdoct tok;
int i, sv;
@@ -839,7 +868,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
/* Empty post-control lines are ignored. */
if ('"' == buf[offs]) {
- mdoc_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
+ mdoc_pmsg(mdoc, ln, offs, MANDOCERR_BADCOMMENT);
return(1);
} else if ('\0' == buf[offs])
return(1);
@@ -861,7 +890,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
tok = (i > 1 || i < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
if (MDOC_MAX == tok) {
- mandoc_vmsg(MANDOCERR_MACRO, m->parse,
+ mandoc_vmsg(MANDOCERR_MACRO, mdoc->parse,
ln, sv, "%s", buf + sv - 1);
return(1);
}
@@ -882,21 +911,21 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
*/
if ('\0' == buf[offs] && ' ' == buf[offs - 1])
- mdoc_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
+ mdoc_pmsg(mdoc, ln, offs - 1, MANDOCERR_EOLNSPACE);
/*
* If an initial macro or a list invocation, divert directly
* into macro processing.
*/
- if (NULL == m->last || MDOC_It == tok || MDOC_El == tok) {
- if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf))
+ if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) {
+ if ( ! mdoc_macro(mdoc, tok, ln, sv, &offs, buf))
goto err;
return(1);
}
- n = m->last;
- assert(m->last);
+ n = mdoc->last;
+ assert(mdoc->last);
/*
* If the first macro of a `Bl -column', open an `It' block
@@ -905,8 +934,8 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
LIST_column == n->norm->Bl.type) {
- m->flags |= MDOC_FREECOL;
- if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
+ mdoc->flags |= MDOC_FREECOL;
+ if ( ! mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf))
goto err;
return(1);
}
@@ -921,22 +950,22 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
NULL != n->parent &&
MDOC_Bl == n->parent->tok &&
LIST_column == n->parent->norm->Bl.type) {
- m->flags |= MDOC_FREECOL;
- if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
+ mdoc->flags |= MDOC_FREECOL;
+ if ( ! mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf))
goto err;
return(1);
}
/* Normal processing of a macro. */
- if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf))
+ if ( ! mdoc_macro(mdoc, tok, ln, sv, &offs, buf))
goto err;
return(1);
err: /* Error out. */
- m->flags |= MDOC_HALT;
+ mdoc->flags |= MDOC_HALT;
return(0);
}
@@ -980,7 +1009,7 @@ mdoc_isdelim(const char *p)
if (0 == strcmp(p + 1, "."))
return(DELIM_CLOSE);
- if (0 == strcmp(p + 1, "*(Ba"))
+ if (0 == strcmp(p + 1, "fR|\\fP"))
return(DELIM_MIDDLE);
return(DELIM_NONE);
diff --git a/mdoc.h b/mdoc.h
index 9cee098e7fee..d0153b448061 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -1,4 +1,4 @@
-/* $Id: mdoc.h,v 1.122 2011/03/22 14:05:45 kristaps Exp $ */
+/* $Id: mdoc.h,v 1.125 2013/12/24 19:11:45 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -311,6 +311,7 @@ struct mdoc_bl {
int comp; /* -compact */
size_t ncols; /* -column arg count */
const char **cols; /* -column val ptr */
+ int count; /* -enum counter */
};
struct mdoc_bf {
@@ -350,6 +351,7 @@ struct mdoc_node {
int nchild; /* number children */
int line; /* parse line */
int pos; /* parse column */
+ int lastline; /* the node ends on this line */
enum mdoct tok; /* tok or MDOC__MAX if none */
int flags;
#define MDOC_VALID (1 << 0) /* has been validated */
@@ -362,6 +364,7 @@ struct mdoc_node {
enum mdoc_type type; /* AST node type */
enum mdoc_sec sec; /* current named section */
union mdoc_data *norm; /* normalised args */
+ const void *prev_font; /* before entering this node */
/* FIXME: these can be union'd to shave a few bytes. */
struct mdoc_arg *args; /* BLOCK/ELEM */
struct mdoc_node *pending; /* BLOCK */
diff --git a/mdoc_argv.c b/mdoc_argv.c
index 08386e09b14e..bb9bc6c339b7 100644
--- a/mdoc_argv.c
+++ b/mdoc_argv.c
@@ -1,6 +1,7 @@
-/* $Id: mdoc_argv.c,v 1.82 2012/03/23 05:50:24 kristaps Exp $ */
+/* $Id: mdoc_argv.c,v 1.89 2013/12/25 00:50:05 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2012 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,8 +43,7 @@ enum argsflag {
enum argvflag {
ARGV_NONE, /* no args to flag (e.g., -split) */
ARGV_SINGLE, /* one arg to flag (e.g., -file xxx) */
- ARGV_MULTI, /* multiple args (e.g., -column xxx yyy) */
- ARGV_OPT_SINGLE /* optional arg (e.g., -offset [xxx]) */
+ ARGV_MULTI /* multiple args (e.g., -column xxx yyy) */
};
struct mdocarg {
@@ -57,8 +57,6 @@ static enum margserr args(struct mdoc *, int, int *,
static int args_checkpunct(const char *, int);
static int argv_multi(struct mdoc *, int,
struct mdoc_argv *, int *, char *);
-static int argv_opt_single(struct mdoc *, int,
- struct mdoc_argv *, int *, char *);
static int argv_single(struct mdoc *, int,
struct mdoc_argv *, int *, char *);
@@ -69,7 +67,7 @@ static const enum argvflag argvflags[MDOC_ARG_MAX] = {
ARGV_NONE, /* MDOC_Unfilled */
ARGV_NONE, /* MDOC_Literal */
ARGV_SINGLE, /* MDOC_File */
- ARGV_OPT_SINGLE, /* MDOC_Offset */
+ ARGV_SINGLE, /* MDOC_Offset */
ARGV_NONE, /* MDOC_Bullet */
ARGV_NONE, /* MDOC_Dash */
ARGV_NONE, /* MDOC_Hyphen */
@@ -81,7 +79,7 @@ static const enum argvflag argvflags[MDOC_ARG_MAX] = {
ARGV_NONE, /* MDOC_Ohang */
ARGV_NONE, /* MDOC_Inset */
ARGV_MULTI, /* MDOC_Column */
- ARGV_OPT_SINGLE, /* MDOC_Width */
+ ARGV_SINGLE, /* MDOC_Width */
ARGV_NONE, /* MDOC_Compact */
ARGV_NONE, /* MDOC_Std */
ARGV_NONE, /* MDOC_Filled */
@@ -146,7 +144,7 @@ static const enum mdocargt args_Bl[] = {
};
static const struct mdocarg mdocargs[MDOC_MAX] = {
- { ARGSFL_NONE, NULL }, /* Ap */
+ { ARGSFL_DELIM, NULL }, /* Ap */
{ ARGSFL_NONE, NULL }, /* Dd */
{ ARGSFL_NONE, NULL }, /* Dt */
{ ARGSFL_NONE, NULL }, /* Os */
@@ -163,7 +161,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
{ ARGSFL_DELIM, NULL }, /* Ad */
{ ARGSFL_DELIM, args_An }, /* An */
{ ARGSFL_DELIM, NULL }, /* Ar */
- { ARGSFL_NONE, NULL }, /* Cd */
+ { ARGSFL_DELIM, NULL }, /* Cd */
{ ARGSFL_DELIM, NULL }, /* Cm */
{ ARGSFL_DELIM, NULL }, /* Dv */
{ ARGSFL_DELIM, NULL }, /* Er */
@@ -175,7 +173,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
{ ARGSFL_DELIM, NULL }, /* Fn */
{ ARGSFL_DELIM, NULL }, /* Ft */
{ ARGSFL_DELIM, NULL }, /* Ic */
- { ARGSFL_NONE, NULL }, /* In */
+ { ARGSFL_DELIM, NULL }, /* In */
{ ARGSFL_DELIM, NULL }, /* Li */
{ ARGSFL_NONE, NULL }, /* Nd */
{ ARGSFL_DELIM, NULL }, /* Nm */
@@ -243,7 +241,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
{ ARGSFL_DELIM, NULL }, /* Xc */
{ ARGSFL_NONE, NULL }, /* Xo */
{ ARGSFL_NONE, NULL }, /* Fo */
- { ARGSFL_NONE, NULL }, /* Fc */
+ { ARGSFL_DELIM, NULL }, /* Fc */
{ ARGSFL_NONE, NULL }, /* Oo */
{ ARGSFL_DELIM, NULL }, /* Oc */
{ ARGSFL_NONE, args_Bk }, /* Bk */
@@ -252,7 +250,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
{ ARGSFL_NONE, NULL }, /* Hf */
{ ARGSFL_NONE, NULL }, /* Fr */
{ ARGSFL_NONE, NULL }, /* Ud */
- { ARGSFL_NONE, NULL }, /* Lb */
+ { ARGSFL_DELIM, NULL }, /* Lb */
{ ARGSFL_NONE, NULL }, /* Lp */
{ ARGSFL_DELIM, NULL }, /* Lk */
{ ARGSFL_DELIM, NULL }, /* Mt */
@@ -262,7 +260,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
{ ARGSFL_NONE, NULL }, /* %C */
{ ARGSFL_NONE, NULL }, /* Es */
{ ARGSFL_NONE, NULL }, /* En */
- { ARGSFL_NONE, NULL }, /* Dx */
+ { ARGSFL_DELIM, NULL }, /* Dx */
{ ARGSFL_NONE, NULL }, /* %Q */
{ ARGSFL_NONE, NULL }, /* br */
{ ARGSFL_NONE, NULL }, /* sp */
@@ -277,7 +275,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
* one mandatory value, an optional single value, or no value.
*/
enum margverr
-mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
+mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok,
struct mdoc_arg **v, int *pos, char *buf)
{
char *p, sv;
@@ -344,15 +342,11 @@ mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
switch (argvflags[tmp.arg]) {
case (ARGV_SINGLE):
- if ( ! argv_single(m, line, &tmp, pos, buf))
+ if ( ! argv_single(mdoc, line, &tmp, pos, buf))
return(ARGV_ERROR);
break;
case (ARGV_MULTI):
- if ( ! argv_multi(m, line, &tmp, pos, buf))
- return(ARGV_ERROR);
- break;
- case (ARGV_OPT_SINGLE):
- if ( ! argv_opt_single(m, line, &tmp, pos, buf))
+ if ( ! argv_multi(mdoc, line, &tmp, pos, buf))
return(ARGV_ERROR);
break;
case (ARGV_NONE):
@@ -413,14 +407,14 @@ argn_free(struct mdoc_arg *p, int iarg)
}
enum margserr
-mdoc_zargs(struct mdoc *m, int line, int *pos, char *buf, char **v)
+mdoc_zargs(struct mdoc *mdoc, int line, int *pos, char *buf, char **v)
{
- return(args(m, line, pos, buf, ARGSFL_NONE, v));
+ return(args(mdoc, line, pos, buf, ARGSFL_NONE, v));
}
enum margserr
-mdoc_args(struct mdoc *m, int line, int *pos,
+mdoc_args(struct mdoc *mdoc, int line, int *pos,
char *buf, enum mdoct tok, char **v)
{
enum argsflag fl;
@@ -429,7 +423,7 @@ mdoc_args(struct mdoc *m, int line, int *pos,
fl = mdocargs[tok].flags;
if (MDOC_It != tok)
- return(args(m, line, pos, buf, fl, v));
+ return(args(mdoc, line, pos, buf, fl, v));
/*
* We know that we're in an `It', so it's reasonable to expect
@@ -438,35 +432,36 @@ mdoc_args(struct mdoc *m, int line, int *pos,
* safe fall-back into the default behaviour.
*/
- for (n = m->last; n; n = n->parent)
+ for (n = mdoc->last; n; n = n->parent)
if (MDOC_Bl == n->tok)
if (LIST_column == n->norm->Bl.type) {
fl = ARGSFL_TABSEP;
break;
}
- return(args(m, line, pos, buf, fl, v));
+ return(args(mdoc, line, pos, buf, fl, v));
}
static enum margserr
-args(struct mdoc *m, int line, int *pos,
+args(struct mdoc *mdoc, int line, int *pos,
char *buf, enum argsflag fl, char **v)
{
char *p, *pp;
+ int pairs;
enum margserr rc;
if ('\0' == buf[*pos]) {
- if (MDOC_PPHRASE & m->flags)
+ if (MDOC_PPHRASE & mdoc->flags)
return(ARGS_EOLN);
/*
* If we're not in a partial phrase and the flag for
* being a phrase literal is still set, the punctuation
* is unterminated.
*/
- if (MDOC_PHRASELIT & m->flags)
- mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
+ if (MDOC_PHRASELIT & mdoc->flags)
+ mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE);
- m->flags &= ~MDOC_PHRASELIT;
+ mdoc->flags &= ~MDOC_PHRASELIT;
return(ARGS_EOLN);
}
@@ -489,7 +484,7 @@ args(struct mdoc *m, int line, int *pos,
pp = NULL;
/* Scan ahead to unescaped `Ta'. */
- if ( ! (MDOC_PHRASELIT & m->flags))
+ if ( ! (MDOC_PHRASELIT & mdoc->flags))
for (pp = *v; ; pp++) {
if (NULL == (pp = strstr(pp, "Ta")))
break;
@@ -523,7 +518,7 @@ args(struct mdoc *m, int line, int *pos,
/* Whitespace check for eoln case... */
if ('\0' == *p && ' ' == *(p - 1))
- mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE);
+ mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE);
*pos += (int)(p - *v);
@@ -541,37 +536,48 @@ args(struct mdoc *m, int line, int *pos,
/* Skip ahead. */ ;
return(rc);
- }
+ }
- /*
+ /*
* Process a quoted literal. A quote begins with a double-quote
* and ends with a double-quote NOT preceded by a double-quote.
+ * NUL-terminate the literal in place.
+ * Collapse pairs of quotes inside quoted literals.
* Whitespace is NOT involved in literal termination.
*/
- if (MDOC_PHRASELIT & m->flags || '\"' == buf[*pos]) {
- if ( ! (MDOC_PHRASELIT & m->flags))
+ if (MDOC_PHRASELIT & mdoc->flags || '\"' == buf[*pos]) {
+ if ( ! (MDOC_PHRASELIT & mdoc->flags))
*v = &buf[++(*pos)];
- if (MDOC_PPHRASE & m->flags)
- m->flags |= MDOC_PHRASELIT;
+ if (MDOC_PPHRASE & mdoc->flags)
+ mdoc->flags |= MDOC_PHRASELIT;
+ pairs = 0;
for ( ; buf[*pos]; (*pos)++) {
+ /* Move following text left after quoted quotes. */
+ if (pairs)
+ buf[*pos - pairs] = buf[*pos];
if ('\"' != buf[*pos])
continue;
+ /* Unquoted quotes end quoted args. */
if ('\"' != buf[*pos + 1])
break;
+ /* Quoted quotes collapse. */
+ pairs++;
(*pos)++;
}
+ if (pairs)
+ buf[*pos - pairs] = '\0';
if ('\0' == buf[*pos]) {
- if (MDOC_PPHRASE & m->flags)
+ if (MDOC_PPHRASE & mdoc->flags)
return(ARGS_QWORD);
- mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
+ mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE);
return(ARGS_QWORD);
}
- m->flags &= ~MDOC_PHRASELIT;
+ mdoc->flags &= ~MDOC_PHRASELIT;
buf[(*pos)++] = '\0';
if ('\0' == buf[*pos])
@@ -581,13 +587,13 @@ args(struct mdoc *m, int line, int *pos,
(*pos)++;
if ('\0' == buf[*pos])
- mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE);
+ mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE);
return(ARGS_QWORD);
}
p = &buf[*pos];
- *v = mandoc_getarg(m->parse, &p, line, pos);
+ *v = mandoc_getarg(mdoc->parse, &p, line, pos);
return(ARGS_WORD);
}
@@ -643,7 +649,7 @@ args_checkpunct(const char *buf, int i)
}
static int
-argv_multi(struct mdoc *m, int line,
+argv_multi(struct mdoc *mdoc, int line,
struct mdoc_argv *v, int *pos, char *buf)
{
enum margserr ac;
@@ -652,7 +658,7 @@ argv_multi(struct mdoc *m, int line,
for (v->sz = 0; ; v->sz++) {
if ('-' == buf[*pos])
break;
- ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
+ ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p);
if (ARGS_ERROR == ac)
return(0);
else if (ARGS_EOLN == ac)
@@ -669,16 +675,13 @@ argv_multi(struct mdoc *m, int line,
}
static int
-argv_opt_single(struct mdoc *m, int line,
+argv_single(struct mdoc *mdoc, int line,
struct mdoc_argv *v, int *pos, char *buf)
{
enum margserr ac;
char *p;
- if ('-' == buf[*pos])
- return(1);
-
- ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
+ ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p);
if (ARGS_ERROR == ac)
return(0);
if (ARGS_EOLN == ac)
@@ -690,27 +693,3 @@ argv_opt_single(struct mdoc *m, int line,
return(1);
}
-
-static int
-argv_single(struct mdoc *m, int line,
- struct mdoc_argv *v, int *pos, char *buf)
-{
- int ppos;
- enum margserr ac;
- char *p;
-
- ppos = *pos;
-
- ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
- if (ARGS_EOLN == ac) {
- mdoc_pmsg(m, line, ppos, MANDOCERR_SYNTARGVCOUNT);
- return(0);
- } else if (ARGS_ERROR == ac)
- return(0);
-
- v->sz = 1;
- v->value = mandoc_malloc(sizeof(char *));
- v->value[0] = mandoc_strdup(p);
-
- return(1);
-}
diff --git a/mdoc_html.c b/mdoc_html.c
index 60ea6dc73830..a7aa722d94c4 100644
--- a/mdoc_html.c
+++ b/mdoc_html.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_html.c,v 1.182 2011/11/03 20:37:00 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.186 2013/12/24 20:45:27 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -35,7 +35,7 @@
#define INDENT 5
-#define MDOC_ARGS const struct mdoc_meta *m, \
+#define MDOC_ARGS const struct mdoc_meta *meta, \
const struct mdoc_node *n, \
struct html *h
@@ -260,10 +260,11 @@ static const char * const lists[LIST_MAX] = {
};
void
-html_mdoc(void *arg, const struct mdoc *m)
+html_mdoc(void *arg, const struct mdoc *mdoc)
{
- print_mdoc(mdoc_meta(m), mdoc_node(m), (struct html *)arg);
+ print_mdoc(mdoc_meta(mdoc), mdoc_node(mdoc),
+ (struct html *)arg);
putchar('\n');
}
@@ -361,14 +362,14 @@ print_mdoc(MDOC_ARGS)
print_gen_decls(h);
t = print_otag(h, TAG_HTML, 0, NULL);
tt = print_otag(h, TAG_HEAD, 0, NULL);
- print_mdoc_head(m, n, h);
+ print_mdoc_head(meta, n, h);
print_tagq(h, tt);
print_otag(h, TAG_BODY, 0, NULL);
print_otag(h, TAG_DIV, 1, &tag);
} else
t = print_otag(h, TAG_DIV, 1, &tag);
- print_mdoc_nodelist(m, n, h);
+ print_mdoc_nodelist(meta, n, h);
print_tagq(h, t);
}
@@ -380,10 +381,10 @@ print_mdoc_head(MDOC_ARGS)
print_gen_head(h);
bufinit(h);
- bufcat_fmt(h, "%s(%s)", m->title, m->msec);
+ bufcat_fmt(h, "%s(%s)", meta->title, meta->msec);
- if (m->arch)
- bufcat_fmt(h, " (%s)", m->arch);
+ if (meta->arch)
+ bufcat_fmt(h, " (%s)", meta->arch);
print_otag(h, TAG_TITLE, 0, NULL);
print_text(h, h->buf);
@@ -394,9 +395,9 @@ static void
print_mdoc_nodelist(MDOC_ARGS)
{
- print_mdoc_node(m, n, h);
+ print_mdoc_node(meta, n, h);
if (n->next)
- print_mdoc_nodelist(m, n->next, h);
+ print_mdoc_nodelist(meta, n->next, h);
}
@@ -411,7 +412,7 @@ print_mdoc_node(MDOC_ARGS)
switch (n->type) {
case (MDOC_ROOT):
- child = mdoc_root_pre(m, n, h);
+ child = mdoc_root_pre(meta, n, h);
break;
case (MDOC_TEXT):
/* No tables in this mode... */
@@ -454,36 +455,32 @@ print_mdoc_node(MDOC_ARGS)
assert(NULL == h->tblt);
if (mdocs[n->tok].pre && ENDBODY_NOT == n->end)
- child = (*mdocs[n->tok].pre)(m, n, h);
+ child = (*mdocs[n->tok].pre)(meta, n, h);
break;
}
if (HTML_KEEP & h->flags) {
- if (n->prev && n->prev->line != n->line) {
+ if (n->prev ? (n->prev->lastline != n->line) :
+ (n->parent && n->parent->line != n->line)) {
h->flags &= ~HTML_KEEP;
h->flags |= HTML_PREKEEP;
- } else if (NULL == n->prev) {
- if (n->parent && n->parent->line != n->line) {
- h->flags &= ~HTML_KEEP;
- h->flags |= HTML_PREKEEP;
- }
}
}
if (child && n->child)
- print_mdoc_nodelist(m, n->child, h);
+ print_mdoc_nodelist(meta, n->child, h);
print_stagq(h, t);
switch (n->type) {
case (MDOC_ROOT):
- mdoc_root_post(m, n, h);
+ mdoc_root_post(meta, n, h);
break;
case (MDOC_EQN):
break;
default:
if (mdocs[n->tok].post && ENDBODY_NOT == n->end)
- (*mdocs[n->tok].post)(m, n, h);
+ (*mdocs[n->tok].post)(meta, n, h);
break;
}
}
@@ -509,13 +506,13 @@ mdoc_root_post(MDOC_ARGS)
PAIR_CLASS_INIT(&tag[0], "foot-date");
print_otag(h, TAG_TD, 1, tag);
- print_text(h, m->date);
+ print_text(h, meta->date);
print_stagq(h, tt);
PAIR_CLASS_INIT(&tag[0], "foot-os");
PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
print_otag(h, TAG_TD, 2, tag);
- print_text(h, m->os);
+ print_text(h, meta->os);
print_tagq(h, t);
}
@@ -528,15 +525,15 @@ mdoc_root_pre(MDOC_ARGS)
struct tag *t, *tt;
char b[BUFSIZ], title[BUFSIZ];
- strlcpy(b, m->vol, BUFSIZ);
+ strlcpy(b, meta->vol, BUFSIZ);
- if (m->arch) {
+ if (meta->arch) {
strlcat(b, " (", BUFSIZ);
- strlcat(b, m->arch, BUFSIZ);
+ strlcat(b, meta->arch, BUFSIZ);
strlcat(b, ")", BUFSIZ);
}
- snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
+ snprintf(title, BUFSIZ - 1, "%s(%s)", meta->title, meta->msec);
PAIR_SUMMARY_INIT(&tag[0], "Document Header");
PAIR_CLASS_INIT(&tag[1], "head");
@@ -689,13 +686,13 @@ mdoc_nm_pre(MDOC_ARGS)
synopsis_pre(h, n);
PAIR_CLASS_INIT(&tag, "name");
print_otag(h, TAG_B, 1, &tag);
- if (NULL == n->child && m->name)
- print_text(h, m->name);
+ if (NULL == n->child && meta->name)
+ print_text(h, meta->name);
return(1);
case (MDOC_HEAD):
print_otag(h, TAG_TD, 0, NULL);
- if (NULL == n->child && m->name)
- print_text(h, m->name);
+ if (NULL == n->child && meta->name)
+ print_text(h, meta->name);
return(1);
case (MDOC_BODY):
print_otag(h, TAG_TD, 0, NULL);
@@ -712,8 +709,8 @@ mdoc_nm_pre(MDOC_ARGS)
if (MDOC_TEXT == n->type)
len += html_strlen(n->string);
- if (0 == len && m->name)
- len = html_strlen(m->name);
+ if (0 == len && meta->name)
+ len = html_strlen(meta->name);
SCALE_HS_INIT(&su, (double)len);
bufinit(h);
@@ -981,8 +978,6 @@ mdoc_bl_pre(MDOC_ARGS)
struct roffsu su;
char buf[BUFSIZ];
- bufinit(h);
-
if (MDOC_BODY == n->type) {
if (LIST_column == n->norm->Bl.type)
print_otag(h, TAG_TBODY, 0, NULL);
@@ -1001,6 +996,7 @@ mdoc_bl_pre(MDOC_ARGS)
*/
for (i = 0; i < (int)n->norm->Bl.ncols; i++) {
+ bufinit(h);
a2width(n->norm->Bl.cols[i], &su);
if (i < (int)n->norm->Bl.ncols - 1)
bufcat_su(h, "width", &su);
@@ -1014,6 +1010,7 @@ mdoc_bl_pre(MDOC_ARGS)
}
SCALE_VS_INIT(&su, 0);
+ bufinit(h);
bufcat_su(h, "margin-top", &su);
bufcat_su(h, "margin-bottom", &su);
PAIR_STYLE_INIT(&tag[0], h);
@@ -1225,7 +1222,7 @@ mdoc_bd_pre(MDOC_ARGS)
h->flags |= HTML_LITERAL;
for (nn = n->child; nn; nn = nn->next) {
- print_mdoc_node(m, nn, h);
+ 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
@@ -2273,7 +2270,7 @@ mdoc_quote_post(MDOC_ARGS)
case (MDOC_So):
/* FALLTHROUGH */
case (MDOC_Sq):
- print_text(h, "\\(aq");
+ print_text(h, "\\(cq");
break;
default:
abort();
diff --git a/mdoc_macro.c b/mdoc_macro.c
index 11d147399eef..2a63ca92e31d 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_macro.c,v 1.115 2012/01/05 00:43:51 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.125 2013/12/24 20:45:27 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 2012, 2013 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
@@ -51,8 +51,8 @@ static int in_line(MACRO_PROT_ARGS);
static int obsolete(MACRO_PROT_ARGS);
static int phrase_ta(MACRO_PROT_ARGS);
-static int dword(struct mdoc *, int, int,
- const char *, enum mdelim);
+static int dword(struct mdoc *, int, int, const char *,
+ enum mdelim, int);
static int append_delims(struct mdoc *,
int, int *, char *);
static enum mdoct lookup(enum mdoct, const char *);
@@ -70,128 +70,147 @@ static int rew_sub(enum mdoc_type, struct mdoc *,
enum mdoct, int, int);
const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
- { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */
{ in_line_eoln, MDOC_PROLOGUE }, /* Dd */
{ in_line_eoln, MDOC_PROLOGUE }, /* Dt */
{ in_line_eoln, MDOC_PROLOGUE }, /* Os */
- { blk_full, MDOC_PARSED }, /* Sh */
- { blk_full, MDOC_PARSED }, /* Ss */
- { in_line_eoln, 0 }, /* Pp */
- { blk_part_imp, MDOC_PARSED }, /* D1 */
- { blk_part_imp, MDOC_PARSED }, /* Dl */
+ { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Sh */
+ { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Ss */
+ { in_line_eoln, 0 }, /* Pp */
+ { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* D1 */
+ { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* Dl */
{ blk_full, MDOC_EXPLICIT }, /* Bd */
- { blk_exp_close, MDOC_EXPLICIT }, /* Ed */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ed */
{ blk_full, MDOC_EXPLICIT }, /* Bl */
- { blk_exp_close, MDOC_EXPLICIT }, /* El */
- { blk_full, MDOC_PARSED }, /* It */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* El */
+ { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
{ in_line_eoln, 0 }, /* Ex */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
- { in_line_eoln, 0 }, /* Fd */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
+ { in_line_eoln, 0 }, /* Fd */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
- { blk_full, 0 }, /* Nd */
- { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Li */
+ { blk_full, MDOC_JOIN }, /* Nd */
+ { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
{ blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
{ obsolete, 0 }, /* Ot */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
{ in_line_eoln, 0 }, /* Rv */
- { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
- { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
+ { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
- { in_line_eoln, 0 }, /* %A */
- { in_line_eoln, 0 }, /* %B */
- { in_line_eoln, 0 }, /* %D */
- { in_line_eoln, 0 }, /* %I */
- { in_line_eoln, 0 }, /* %J */
+ { in_line_eoln, MDOC_JOIN }, /* %A */
+ { in_line_eoln, MDOC_JOIN }, /* %B */
+ { in_line_eoln, MDOC_JOIN }, /* %D */
+ { in_line_eoln, MDOC_JOIN }, /* %I */
+ { in_line_eoln, MDOC_JOIN }, /* %J */
{ in_line_eoln, 0 }, /* %N */
- { in_line_eoln, 0 }, /* %O */
+ { in_line_eoln, MDOC_JOIN }, /* %O */
{ in_line_eoln, 0 }, /* %P */
- { in_line_eoln, 0 }, /* %R */
- { in_line_eoln, 0 }, /* %T */
+ { in_line_eoln, MDOC_JOIN }, /* %R */
+ { in_line_eoln, MDOC_JOIN }, /* %T */
{ in_line_eoln, 0 }, /* %V */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
- { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
- { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Ac */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Ao */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Aq */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
- { blk_full, MDOC_EXPLICIT }, /* Bf */
- { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
- { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Bc */
+ { blk_full, MDOC_EXPLICIT }, /* Bf */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Bo */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Bq */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
{ in_line_eoln, 0 }, /* Db */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
- { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
- { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
- { blk_exp_close, MDOC_EXPLICIT }, /* Ef */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Dc */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Do */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Dq */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ec */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ef */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Em */
{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
- { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* No */
- { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Ns */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_IGNDELIM | MDOC_JOIN }, /* No */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Pc */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
- { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
- { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
- { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
- { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
- { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
- { blk_exp_close, MDOC_EXPLICIT }, /* Re */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Po */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Pq */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Qc */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ql */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Qo */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Qq */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Re */
{ blk_full, MDOC_EXPLICIT }, /* Rs */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
- { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
- { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Sc */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* So */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sq */
{ in_line_eoln, 0 }, /* Sm */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sx */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sy */
{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
- { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ux */
{ blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
{ blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
- { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
- { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
+ { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Fc */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Oo */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Oc */
{ blk_full, MDOC_EXPLICIT }, /* Bk */
- { blk_exp_close, MDOC_EXPLICIT }, /* Ek */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ek */
{ in_line_eoln, 0 }, /* Bt */
{ in_line_eoln, 0 }, /* Hf */
{ obsolete, 0 }, /* Fr */
{ in_line_eoln, 0 }, /* Ud */
{ in_line, 0 }, /* Lb */
- { in_line_eoln, 0 }, /* Lp */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
- { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
- { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
- { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
- { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
- { in_line_eoln, 0 }, /* %C */
+ { in_line_eoln, 0 }, /* Lp */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Brq */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Bro */
+ { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+ MDOC_EXPLICIT | MDOC_JOIN }, /* Brc */
+ { in_line_eoln, MDOC_JOIN }, /* %C */
{ obsolete, 0 }, /* Es */
{ obsolete, 0 }, /* En */
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
- { in_line_eoln, 0 }, /* %Q */
+ { in_line_eoln, MDOC_JOIN }, /* %Q */
{ in_line_eoln, 0 }, /* br */
{ in_line_eoln, 0 }, /* sp */
{ in_line_eoln, 0 }, /* %U */
- { phrase_ta, MDOC_CALLABLE | MDOC_PARSED }, /* Ta */
+ { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
};
const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
@@ -203,22 +222,23 @@ const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
* are errors.
*/
int
-mdoc_macroend(struct mdoc *m)
+mdoc_macroend(struct mdoc *mdoc)
{
struct mdoc_node *n;
/* Scan for open explicit scopes. */
- n = MDOC_VALID & m->last->flags ? m->last->parent : m->last;
+ n = MDOC_VALID & mdoc->last->flags ?
+ mdoc->last->parent : mdoc->last;
for ( ; n; n = n->parent)
if (MDOC_BLOCK == n->type &&
MDOC_EXPLICIT & mdoc_macros[n->tok].flags)
- mdoc_nmsg(m, n, MANDOCERR_SCOPEEXIT);
+ mdoc_nmsg(mdoc, n, MANDOCERR_SCOPEEXIT);
/* Rewind to the first. */
- return(rew_last(m, m->first));
+ return(rew_last(mdoc, mdoc->first));
}
@@ -263,8 +283,8 @@ rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
while (mdoc->last != to) {
/*
* Save the parent here, because we may delete the
- * m->last node in the post-validation phase and reset
- * it to m->last->parent, causing a step in the closing
+ * mdoc->last node in the post-validation phase and reset
+ * it to mdoc->last->parent, causing a step in the closing
* out to be lost.
*/
np = mdoc->last->parent;
@@ -460,7 +480,7 @@ rew_elem(struct mdoc *mdoc, enum mdoct tok)
*/
static int
make_pending(struct mdoc_node *broken, enum mdoct tok,
- struct mdoc *m, int line, int ppos)
+ struct mdoc *mdoc, int line, int ppos)
{
struct mdoc_node *breaker;
@@ -515,7 +535,7 @@ make_pending(struct mdoc_node *broken, enum mdoct tok,
taker->pending = broken->pending;
}
broken->pending = breaker;
- mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos,
+ mandoc_vmsg(MANDOCERR_SCOPENEST, mdoc->parse, line, ppos,
"%s breaks %s", mdoc_macronames[tok],
mdoc_macronames[broken->tok]);
return(1);
@@ -530,41 +550,46 @@ make_pending(struct mdoc_node *broken, enum mdoct tok,
static int
-rew_sub(enum mdoc_type t, struct mdoc *m,
+rew_sub(enum mdoc_type t, struct mdoc *mdoc,
enum mdoct tok, int line, int ppos)
{
struct mdoc_node *n;
- n = m->last;
+ n = mdoc->last;
while (n) {
switch (rew_dohalt(tok, t, n)) {
case (REWIND_NONE):
return(1);
case (REWIND_THIS):
+ n->lastline = line -
+ (MDOC_NEWLINE & mdoc->flags &&
+ ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
break;
case (REWIND_FORCE):
- mandoc_vmsg(MANDOCERR_SCOPEBROKEN, m->parse,
+ mandoc_vmsg(MANDOCERR_SCOPEBROKEN, mdoc->parse,
line, ppos, "%s breaks %s",
mdoc_macronames[tok],
mdoc_macronames[n->tok]);
/* FALLTHROUGH */
case (REWIND_MORE):
+ n->lastline = line -
+ (MDOC_NEWLINE & mdoc->flags ? 1 : 0);
n = n->parent;
continue;
case (REWIND_LATER):
- if (make_pending(n, tok, m, line, ppos) ||
+ if (make_pending(n, tok, mdoc, line, ppos) ||
MDOC_BLOCK != t)
return(1);
/* FALLTHROUGH */
case (REWIND_ERROR):
- mdoc_pmsg(m, line, ppos, MANDOCERR_NOSCOPE);
+ mdoc_pmsg(mdoc, line, ppos, MANDOCERR_NOSCOPE);
return(1);
}
break;
}
assert(n);
- if ( ! rew_last(m, n))
+ if ( ! rew_last(mdoc, n))
return(0);
/*
@@ -572,10 +597,10 @@ rew_sub(enum mdoc_type t, struct mdoc *m,
* Now that the current block ends, close the enclosing block, too.
*/
while (NULL != (n = n->pending)) {
- if ( ! rew_last(m, n))
+ if ( ! rew_last(mdoc, n))
return(0);
if (MDOC_HEAD == n->type &&
- ! mdoc_body_alloc(m, n->line, n->pos, n->tok))
+ ! mdoc_body_alloc(mdoc, n->line, n->pos, n->tok))
return(0);
}
@@ -587,18 +612,26 @@ rew_sub(enum mdoc_type t, struct mdoc *m,
* Punctuation consists of those tokens found in mdoc_isdelim().
*/
static int
-dword(struct mdoc *m, int line,
- int col, const char *p, enum mdelim d)
+dword(struct mdoc *mdoc, int line, int col, const char *p,
+ enum mdelim d, int may_append)
{
if (DELIM_MAX == d)
d = mdoc_isdelim(p);
- if ( ! mdoc_word_alloc(m, line, col, p))
+ if (may_append &&
+ ! ((MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF) & mdoc->flags) &&
+ DELIM_NONE == d && MDOC_TEXT == mdoc->last->type &&
+ DELIM_NONE == mdoc_isdelim(mdoc->last->string)) {
+ mdoc_word_append(mdoc, p);
+ return(1);
+ }
+
+ if ( ! mdoc_word_alloc(mdoc, line, col, p))
return(0);
if (DELIM_OPEN == d)
- m->last->flags |= MDOC_DELIMO;
+ mdoc->last->flags |= MDOC_DELIMO;
/*
* Closing delimiters only suppress the preceding space
@@ -610,15 +643,16 @@ dword(struct mdoc *m, int line,
* and solve this in the code related to `No'!
*/
- else if (DELIM_CLOSE == d && m->last->prev &&
- m->last->prev->tok != MDOC_No)
- m->last->flags |= MDOC_DELIMC;
+ else if (DELIM_CLOSE == d && mdoc->last->prev &&
+ mdoc->last->prev->tok != MDOC_No &&
+ mdoc->last->parent->tok != MDOC_Fd)
+ mdoc->last->flags |= MDOC_DELIMC;
return(1);
}
static int
-append_delims(struct mdoc *m, int line, int *pos, char *buf)
+append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
{
int la;
enum margserr ac;
@@ -629,14 +663,14 @@ append_delims(struct mdoc *m, int line, int *pos, char *buf)
for (;;) {
la = *pos;
- ac = mdoc_zargs(m, line, pos, buf, &p);
+ ac = mdoc_zargs(mdoc, line, pos, buf, &p);
if (ARGS_ERROR == ac)
return(0);
else if (ARGS_EOLN == ac)
break;
- dword(m, line, la, p, DELIM_MAX);
+ dword(mdoc, line, la, p, DELIM_MAX, 1);
/*
* If we encounter end-of-sentence symbols, then trigger
@@ -650,7 +684,7 @@ append_delims(struct mdoc *m, int line, int *pos, char *buf)
* example, `. ;' shouldn't propagate the double-space.
*/
if (mandoc_eos(p, strlen(p), 0))
- m->last->flags |= MDOC_EOS;
+ mdoc->last->flags |= MDOC_EOS;
}
return(1);
@@ -672,12 +706,14 @@ blk_exp_close(MACRO_PROT_ARGS)
enum mdoct atok, ntok;
char *p;
- nl = MDOC_NEWLINE & m->flags;
+ nl = MDOC_NEWLINE & mdoc->flags;
switch (tok) {
case (MDOC_Ec):
maxargs = 1;
break;
+ case (MDOC_Ek):
+ mdoc->flags &= ~MDOC_KEEP;
default:
maxargs = 0;
break;
@@ -689,7 +725,7 @@ blk_exp_close(MACRO_PROT_ARGS)
*/
atok = rew_alt(tok);
body = later = NULL;
- for (n = m->last; n; n = n->parent) {
+ for (n = mdoc->last; n; n = n->parent) {
if (MDOC_VALID & n->flags)
continue;
@@ -718,13 +754,13 @@ blk_exp_close(MACRO_PROT_ARGS)
* postpone closing out the current block
* until the rew_sub() closing out the sub-block.
*/
- make_pending(later, tok, m, line, ppos);
+ make_pending(later, tok, mdoc, line, ppos);
/*
* Mark the place where the formatting - but not
* the scope - of the current block ends.
*/
- if ( ! mdoc_endbody_alloc(m, line, ppos,
+ if ( ! mdoc_endbody_alloc(mdoc, line, ppos,
atok, body, ENDBODY_SPACE))
return(0);
break;
@@ -738,37 +774,37 @@ blk_exp_close(MACRO_PROT_ARGS)
if (later &&
MDOC_EXPLICIT & mdoc_macros[later->tok].flags)
continue;
- if (MDOC_CALLABLE & mdoc_macros[n->tok].flags)
+ if (MDOC_It != n->tok)
later = n;
}
if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
/* FIXME: do this in validate */
if (buf[*pos])
- mdoc_pmsg(m, line, ppos, MANDOCERR_ARGSLOST);
+ mdoc_pmsg(mdoc, line, ppos, MANDOCERR_ARGSLOST);
- if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
- return(rew_sub(MDOC_BLOCK, m, tok, line, ppos));
+ return(rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos));
}
- if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
if (NULL == later && maxargs > 0)
- if ( ! mdoc_tail_alloc(m, line, ppos, rew_alt(tok)))
+ if ( ! mdoc_tail_alloc(mdoc, line, ppos, rew_alt(tok)))
return(0);
for (flushed = j = 0; ; j++) {
lastarg = *pos;
if (j == maxargs && ! flushed) {
- if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
return(0);
flushed = 1;
}
- ac = mdoc_args(m, line, pos, buf, tok, &p);
+ ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ARGS_ERROR == ac)
return(0);
@@ -780,27 +816,31 @@ blk_exp_close(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! dword(m, line, lastarg, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, lastarg, p, DELIM_MAX,
+ MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
continue;
}
if ( ! flushed) {
- if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
return(0);
flushed = 1;
}
- if ( ! mdoc_macro(m, ntok, line, lastarg, pos, buf))
+
+ mdoc->flags &= ~MDOC_NEWLINE;
+
+ if ( ! mdoc_macro(mdoc, ntok, line, lastarg, pos, buf))
return(0);
break;
}
- if ( ! flushed && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
+ if ( ! flushed && ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
return(0);
if ( ! nl)
return(1);
- return(append_delims(m, line, pos, buf));
+ return(append_delims(mdoc, line, pos, buf));
}
@@ -815,7 +855,7 @@ in_line(MACRO_PROT_ARGS)
struct mdoc_arg *arg;
char *p;
- nl = MDOC_NEWLINE & m->flags;
+ nl = MDOC_NEWLINE & mdoc->flags;
/*
* Whether we allow ignored elements (those without content,
@@ -843,7 +883,7 @@ in_line(MACRO_PROT_ARGS)
for (arg = NULL;; ) {
la = *pos;
- av = mdoc_argv(m, line, tok, &arg, pos, buf);
+ av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
if (ARGV_WORD == av) {
*pos = la;
@@ -860,7 +900,7 @@ in_line(MACRO_PROT_ARGS)
for (cnt = scope = 0;; ) {
la = *pos;
- ac = mdoc_args(m, line, pos, buf, tok, &p);
+ ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ARGS_ERROR == ac)
return(0);
@@ -879,23 +919,25 @@ in_line(MACRO_PROT_ARGS)
*/
if (MDOC_MAX != ntok) {
- if (scope && ! rew_elem(m, tok))
+ if (scope && ! rew_elem(mdoc, tok))
return(0);
if (nc && 0 == cnt) {
- if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
+ if ( ! mdoc_elem_alloc(mdoc, line,
+ ppos, tok, arg))
return(0);
- if ( ! rew_last(m, m->last))
+ if ( ! rew_last(mdoc, mdoc->last))
return(0);
} else if ( ! nc && 0 == cnt) {
mdoc_argv_free(arg);
- mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY);
+ mdoc_pmsg(mdoc, line, ppos,
+ MANDOCERR_MACROEMPTY);
}
- if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
+ if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
return(0);
if ( ! nl)
return(1);
- return(append_delims(m, line, pos, buf));
+ return(append_delims(mdoc, line, pos, buf));
}
/*
@@ -917,7 +959,8 @@ in_line(MACRO_PROT_ARGS)
*/
if (0 == cnt && (nc || MDOC_Li == tok) &&
DELIM_CLOSE == d && ! scope) {
- if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
+ if ( ! mdoc_elem_alloc(mdoc, line,
+ ppos, tok, arg))
return(0);
if (MDOC_Ar == tok || MDOC_Li == tok ||
MDOC_Fl == tok)
@@ -928,11 +971,11 @@ in_line(MACRO_PROT_ARGS)
* Close out our scope, if one is open, before
* any punctuation.
*/
- if (scope && ! rew_elem(m, tok))
+ if (scope && ! rew_elem(mdoc, tok))
return(0);
scope = 0;
} else if ( ! scope) {
- if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
+ if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
return(0);
scope = 1;
}
@@ -940,7 +983,8 @@ in_line(MACRO_PROT_ARGS)
if (DELIM_NONE == d)
cnt++;
- if ( ! dword(m, line, la, p, d))
+ if ( ! dword(mdoc, line, la, p, d,
+ MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
/*
@@ -949,13 +993,13 @@ in_line(MACRO_PROT_ARGS)
* having to parse out spaces.
*/
if (scope && MDOC_Fl == tok) {
- if ( ! rew_elem(m, tok))
+ if ( ! rew_elem(mdoc, tok))
return(0);
scope = 0;
}
}
- if (scope && ! rew_elem(m, tok))
+ if (scope && ! rew_elem(mdoc, tok))
return(0);
/*
@@ -965,18 +1009,18 @@ in_line(MACRO_PROT_ARGS)
*/
if (nc && 0 == cnt) {
- if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
+ if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
return(0);
- if ( ! rew_last(m, m->last))
+ if ( ! rew_last(mdoc, mdoc->last))
return(0);
} else if ( ! nc && 0 == cnt) {
mdoc_argv_free(arg);
- mdoc_pmsg(m, line, ppos, MANDOCERR_MACROEMPTY);
+ mdoc_pmsg(mdoc, line, ppos, MANDOCERR_MACROEMPTY);
}
if ( ! nl)
return(1);
- return(append_delims(m, line, pos, buf));
+ return(append_delims(mdoc, line, pos, buf));
}
@@ -994,14 +1038,14 @@ blk_full(MACRO_PROT_ARGS)
enum margverr av;
char *p;
- nl = MDOC_NEWLINE & m->flags;
+ nl = MDOC_NEWLINE & mdoc->flags;
/* Close out prior implicit scope. */
if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
- if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
- if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
return(0);
}
@@ -1016,7 +1060,7 @@ blk_full(MACRO_PROT_ARGS)
for (arg = NULL;; ) {
la = *pos;
- av = mdoc_argv(m, line, tok, &arg, pos, buf);
+ av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
if (ARGV_WORD == av) {
*pos = la;
@@ -1032,7 +1076,7 @@ blk_full(MACRO_PROT_ARGS)
return(0);
}
- if ( ! mdoc_block_alloc(m, line, ppos, tok, arg))
+ if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, arg))
return(0);
head = body = NULL;
@@ -1042,8 +1086,8 @@ blk_full(MACRO_PROT_ARGS)
* parsed, even though `It' macros in general are parsed.
*/
nparsed = MDOC_It == tok &&
- MDOC_Bl == m->last->parent->tok &&
- LIST_diag == m->last->parent->norm->Bl.type;
+ MDOC_Bl == mdoc->last->parent->tok &&
+ LIST_diag == mdoc->last->parent->norm->Bl.type;
/*
* The `Nd' macro has all arguments in its body: it's a hybrid
@@ -1051,15 +1095,18 @@ blk_full(MACRO_PROT_ARGS)
*/
if (MDOC_Nd == tok) {
- if ( ! mdoc_head_alloc(m, line, ppos, tok))
+ if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
- head = m->last;
- if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
+ head = mdoc->last;
+ if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
return(0);
- if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
- body = m->last;
- }
+ body = mdoc->last;
+ }
+
+ if (MDOC_Bk == tok)
+ mdoc->flags |= MDOC_KEEP;
ac = ARGS_ERROR;
@@ -1067,7 +1114,7 @@ blk_full(MACRO_PROT_ARGS)
la = *pos;
/* Initialise last-phrase-type with ARGS_PEND. */
lac = ARGS_ERROR == ac ? ARGS_PEND : ac;
- ac = mdoc_args(m, line, pos, buf, tok, &p);
+ ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ARGS_PUNCT == ac)
break;
@@ -1085,11 +1132,11 @@ blk_full(MACRO_PROT_ARGS)
* reopen our scope if the last parse was a
* phrase or partial phrase.
*/
- if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
- if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
- body = m->last;
+ body = mdoc->last;
break;
}
@@ -1104,7 +1151,7 @@ blk_full(MACRO_PROT_ARGS)
ARGS_PPHRASE != ac &&
ARGS_QWORD != ac &&
DELIM_OPEN == mdoc_isdelim(p)) {
- if ( ! dword(m, line, la, p, DELIM_OPEN))
+ if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
return(0);
continue;
}
@@ -1112,9 +1159,9 @@ blk_full(MACRO_PROT_ARGS)
/* Open a head if one hasn't been opened. */
if (NULL == head) {
- if ( ! mdoc_head_alloc(m, line, ppos, tok))
+ if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
- head = m->last;
+ head = mdoc->last;
}
if (ARGS_PHRASE == ac ||
@@ -1126,14 +1173,14 @@ blk_full(MACRO_PROT_ARGS)
*/
mtt = body ? MDOC_BODY : MDOC_HEAD;
- if ( ! rew_sub(mtt, m, tok, line, ppos))
+ if ( ! rew_sub(mtt, mdoc, tok, line, ppos))
return(0);
/* Then allocate our body context. */
- if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
- body = m->last;
+ body = mdoc->last;
/*
* Process phrases: set whether we're in a
@@ -1142,14 +1189,14 @@ blk_full(MACRO_PROT_ARGS)
*/
if (ARGS_PPHRASE == ac)
- m->flags |= MDOC_PPHRASE;
+ mdoc->flags |= MDOC_PPHRASE;
if (ARGS_PEND == ac && ARGS_PPHRASE == lac)
- m->flags |= MDOC_PPHRASE;
+ mdoc->flags |= MDOC_PPHRASE;
- if ( ! phrase(m, line, la, buf))
+ if ( ! phrase(mdoc, line, la, buf))
return(0);
- m->flags &= ~MDOC_PPHRASE;
+ mdoc->flags &= ~MDOC_PPHRASE;
continue;
}
@@ -1157,23 +1204,24 @@ blk_full(MACRO_PROT_ARGS)
MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! dword(m, line, la, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+ MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
continue;
}
- if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
+ if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
return(0);
break;
}
if (NULL == head) {
- if ( ! mdoc_head_alloc(m, line, ppos, tok))
+ if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
- head = m->last;
+ head = mdoc->last;
}
- if (nl && ! append_delims(m, line, pos, buf))
+ if (nl && ! append_delims(mdoc, line, pos, buf))
return(0);
/* If we've already opened our body, exit now. */
@@ -1187,7 +1235,7 @@ blk_full(MACRO_PROT_ARGS)
* head to body until the rew_sub() call closing out that
* sub-block.
*/
- for (n = m->last; n && n != head; n = n->parent) {
+ for (n = mdoc->last; n && n != head; n = n->parent) {
if (MDOC_BLOCK == n->type &&
MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
! (MDOC_VALID & n->flags)) {
@@ -1198,21 +1246,21 @@ blk_full(MACRO_PROT_ARGS)
/* Close out scopes to remain in a consistent state. */
- if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
return(0);
- if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
out:
- if ( ! (MDOC_FREECOL & m->flags))
+ if ( ! (MDOC_FREECOL & mdoc->flags))
return(1);
- if ( ! rew_sub(MDOC_BODY, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
- if ( ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
return(0);
- m->flags &= ~MDOC_FREECOL;
+ mdoc->flags &= ~MDOC_FREECOL;
return(1);
}
@@ -1228,7 +1276,7 @@ blk_part_imp(MACRO_PROT_ARGS)
struct mdoc_node *body; /* saved body context */
struct mdoc_node *n;
- nl = MDOC_NEWLINE & m->flags;
+ nl = MDOC_NEWLINE & mdoc->flags;
/*
* A macro that spans to the end of the line. This is generally
@@ -1239,14 +1287,14 @@ blk_part_imp(MACRO_PROT_ARGS)
* or more closing punctuation nodes.
*/
- if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
+ if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
return(0);
- blk = m->last;
+ blk = mdoc->last;
- if ( ! mdoc_head_alloc(m, line, ppos, tok))
+ if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
- if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
return(0);
/*
@@ -1257,7 +1305,7 @@ blk_part_imp(MACRO_PROT_ARGS)
for (body = NULL; ; ) {
la = *pos;
- ac = mdoc_args(m, line, pos, buf, tok, &p);
+ ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ARGS_ERROR == ac)
return(0);
@@ -1268,26 +1316,27 @@ blk_part_imp(MACRO_PROT_ARGS)
if (NULL == body && ARGS_QWORD != ac &&
DELIM_OPEN == mdoc_isdelim(p)) {
- if ( ! dword(m, line, la, p, DELIM_OPEN))
+ if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
return(0);
continue;
- }
+ }
if (NULL == body) {
- if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
- body = m->last;
+ body = mdoc->last;
}
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! dword(m, line, la, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+ MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
continue;
}
- if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
+ if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
return(0);
break;
}
@@ -1295,9 +1344,9 @@ blk_part_imp(MACRO_PROT_ARGS)
/* Clean-ups to leave in a consistent state. */
if (NULL == body) {
- if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
- body = m->last;
+ body = mdoc->last;
}
for (n = body->child; n && n->next; n = n->next)
@@ -1324,12 +1373,13 @@ blk_part_imp(MACRO_PROT_ARGS)
* postpone closing out the current block
* until the rew_sub() call closing out the sub-block.
*/
- for (n = m->last; n && n != body && n != blk->parent; n = n->parent) {
+ for (n = mdoc->last; n && n != body && n != blk->parent;
+ n = n->parent) {
if (MDOC_BLOCK == n->type &&
MDOC_EXPLICIT & mdoc_macros[n->tok].flags &&
! (MDOC_VALID & n->flags)) {
- make_pending(n, tok, m, line, ppos);
- if ( ! mdoc_endbody_alloc(m, line, ppos,
+ make_pending(n, tok, mdoc, line, ppos);
+ if ( ! mdoc_endbody_alloc(mdoc, line, ppos,
tok, body, ENDBODY_NOSPACE))
return(0);
return(1);
@@ -1343,22 +1393,29 @@ blk_part_imp(MACRO_PROT_ARGS)
* crufty use of `Op' breakage.
*/
if (n != body)
- mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos,
+ mandoc_vmsg(MANDOCERR_SCOPENEST, mdoc->parse, line, ppos,
"%s broken", mdoc_macronames[tok]);
- if (n && ! rew_sub(MDOC_BODY, m, tok, line, ppos))
+ if (n && ! rew_sub(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
/* Standard appending of delimiters. */
- if (nl && ! append_delims(m, line, pos, buf))
+ if (nl && ! append_delims(mdoc, line, pos, buf))
return(0);
/* Rewind scope, if applicable. */
- if (n && ! rew_sub(MDOC_BLOCK, m, tok, line, ppos))
+ if (n && ! rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos))
return(0);
+ /* Move trailing .Ns out of scope. */
+
+ for (n = body->child; n && n->next; n = n->next)
+ /* Do nothing. */ ;
+ if (n && MDOC_Ns == n->tok)
+ mdoc_node_relink(mdoc, n);
+
return(1);
}
@@ -1373,7 +1430,7 @@ blk_part_exp(MACRO_PROT_ARGS)
char *p;
enum mdoct ntok;
- nl = MDOC_NEWLINE & m->flags;
+ nl = MDOC_NEWLINE & mdoc->flags;
/*
* The opening of an explicit macro having zero or more leading
@@ -1381,12 +1438,12 @@ blk_part_exp(MACRO_PROT_ARGS)
* case of `Eo'); and a body that may be empty.
*/
- if ( ! mdoc_block_alloc(m, line, ppos, tok, NULL))
+ if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
return(0);
for (head = body = NULL; ; ) {
la = *pos;
- ac = mdoc_args(m, line, pos, buf, tok, &p);
+ ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ARGS_ERROR == ac)
return(0);
@@ -1400,16 +1457,16 @@ blk_part_exp(MACRO_PROT_ARGS)
if (NULL == head && ARGS_QWORD != ac &&
DELIM_OPEN == mdoc_isdelim(p)) {
assert(NULL == body);
- if ( ! dword(m, line, la, p, DELIM_OPEN))
+ if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
return(0);
continue;
- }
+ }
if (NULL == head) {
assert(NULL == body);
- if ( ! mdoc_head_alloc(m, line, ppos, tok))
+ if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
- head = m->last;
+ head = mdoc->last;
}
/*
@@ -1421,14 +1478,14 @@ blk_part_exp(MACRO_PROT_ARGS)
assert(head);
/* No check whether it's a macro! */
if (MDOC_Eo == tok)
- if ( ! dword(m, line, la, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, la, p, DELIM_MAX, 0))
return(0);
- if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
return(0);
- if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
- body = m->last;
+ body = mdoc->last;
if (MDOC_Eo == tok)
continue;
@@ -1439,12 +1496,13 @@ blk_part_exp(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! dword(m, line, la, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+ MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
continue;
}
- if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
+ if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
return(0);
break;
}
@@ -1452,13 +1510,13 @@ blk_part_exp(MACRO_PROT_ARGS)
/* Clean-up to leave in a consistent state. */
if (NULL == head)
- if ( ! mdoc_head_alloc(m, line, ppos, tok))
+ if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
if (NULL == body) {
- if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
+ if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
return(0);
- if ( ! mdoc_body_alloc(m, line, ppos, tok))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
}
@@ -1466,7 +1524,7 @@ blk_part_exp(MACRO_PROT_ARGS)
if ( ! nl)
return(1);
- return(append_delims(m, line, pos, buf));
+ return(append_delims(mdoc, line, pos, buf));
}
@@ -1481,7 +1539,7 @@ in_line_argn(MACRO_PROT_ARGS)
char *p;
enum mdoct ntok;
- nl = MDOC_NEWLINE & m->flags;
+ nl = MDOC_NEWLINE & mdoc->flags;
/*
* A line macro that has a fixed number of arguments (maxargs).
@@ -1513,7 +1571,7 @@ in_line_argn(MACRO_PROT_ARGS)
for (arg = NULL; ; ) {
la = *pos;
- av = mdoc_argv(m, line, tok, &arg, pos, buf);
+ av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
if (ARGV_WORD == av) {
*pos = la;
@@ -1531,7 +1589,7 @@ in_line_argn(MACRO_PROT_ARGS)
for (flushed = j = 0; ; ) {
la = *pos;
- ac = mdoc_args(m, line, pos, buf, tok, &p);
+ ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ARGS_ERROR == ac)
return(0);
@@ -1543,15 +1601,15 @@ in_line_argn(MACRO_PROT_ARGS)
if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
ARGS_QWORD != ac && 0 == j &&
DELIM_OPEN == mdoc_isdelim(p)) {
- if ( ! dword(m, line, la, p, DELIM_OPEN))
+ if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
return(0);
continue;
} else if (0 == j)
- if ( ! mdoc_elem_alloc(m, line, la, tok, arg))
+ if ( ! mdoc_elem_alloc(mdoc, line, la, tok, arg))
return(0);
if (j == maxargs && ! flushed) {
- if ( ! rew_elem(m, tok))
+ if ( ! rew_elem(mdoc, tok))
return(0);
flushed = 1;
}
@@ -1559,10 +1617,10 @@ in_line_argn(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX != ntok) {
- if ( ! flushed && ! rew_elem(m, tok))
+ if ( ! flushed && ! rew_elem(mdoc, tok))
return(0);
flushed = 1;
- if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
+ if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
return(0);
j++;
break;
@@ -1572,26 +1630,27 @@ in_line_argn(MACRO_PROT_ARGS)
ARGS_QWORD != ac &&
! flushed &&
DELIM_NONE != mdoc_isdelim(p)) {
- if ( ! rew_elem(m, tok))
+ if ( ! rew_elem(mdoc, tok))
return(0);
flushed = 1;
}
- if ( ! dword(m, line, la, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+ MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
j++;
}
- if (0 == j && ! mdoc_elem_alloc(m, line, la, tok, arg))
+ if (0 == j && ! mdoc_elem_alloc(mdoc, line, la, tok, arg))
return(0);
/* Close out in a consistent state. */
- if ( ! flushed && ! rew_elem(m, tok))
+ if ( ! flushed && ! rew_elem(mdoc, tok))
return(0);
if ( ! nl)
return(1);
- return(append_delims(m, line, pos, buf));
+ return(append_delims(mdoc, line, pos, buf));
}
@@ -1608,13 +1667,13 @@ in_line_eoln(MACRO_PROT_ARGS)
assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
if (tok == MDOC_Pp)
- rew_sub(MDOC_BLOCK, m, MDOC_Nm, line, ppos);
+ rew_sub(MDOC_BLOCK, mdoc, MDOC_Nm, line, ppos);
/* Parse macro arguments. */
for (arg = NULL; ; ) {
la = *pos;
- av = mdoc_argv(m, line, tok, &arg, pos, buf);
+ av = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
if (ARGV_WORD == av) {
*pos = la;
@@ -1631,14 +1690,14 @@ in_line_eoln(MACRO_PROT_ARGS)
/* Open element scope. */
- if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg))
+ if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
return(0);
/* Parse argument terms. */
for (;;) {
la = *pos;
- ac = mdoc_args(m, line, pos, buf, tok, &p);
+ ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ARGS_ERROR == ac)
return(0);
@@ -1648,19 +1707,20 @@ in_line_eoln(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! dword(m, line, la, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+ MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
continue;
}
- if ( ! rew_elem(m, tok))
+ if ( ! rew_elem(mdoc, tok))
return(0);
- return(mdoc_macro(m, ntok, line, la, pos, buf));
+ return(mdoc_macro(mdoc, ntok, line, la, pos, buf));
}
/* Close out (no delimiters). */
- return(rew_elem(m, tok));
+ return(rew_elem(mdoc, tok));
}
@@ -1670,15 +1730,15 @@ ctx_synopsis(MACRO_PROT_ARGS)
{
int nl;
- nl = MDOC_NEWLINE & m->flags;
+ nl = MDOC_NEWLINE & mdoc->flags;
/* If we're not in the SYNOPSIS, go straight to in-line. */
- if ( ! (MDOC_SYNOPSIS & m->flags))
- return(in_line(m, tok, line, ppos, pos, buf));
+ if ( ! (MDOC_SYNOPSIS & mdoc->flags))
+ return(in_line(mdoc, tok, line, ppos, pos, buf));
/* If we're a nested call, same place. */
if ( ! nl)
- return(in_line(m, tok, line, ppos, pos, buf));
+ return(in_line(mdoc, tok, line, ppos, pos, buf));
/*
* XXX: this will open a block scope; however, if later we end
@@ -1686,9 +1746,9 @@ ctx_synopsis(MACRO_PROT_ARGS)
* the formatting. Be careful.
*/
if (MDOC_Nm == tok)
- return(blk_full(m, tok, line, ppos, pos, buf));
+ return(blk_full(mdoc, tok, line, ppos, pos, buf));
assert(MDOC_Vt == tok);
- return(blk_part_imp(m, tok, line, ppos, pos, buf));
+ return(blk_part_imp(mdoc, tok, line, ppos, pos, buf));
}
@@ -1697,7 +1757,7 @@ static int
obsolete(MACRO_PROT_ARGS)
{
- mdoc_pmsg(m, line, ppos, MANDOCERR_MACROOBS);
+ mdoc_pmsg(mdoc, line, ppos, MANDOCERR_MACROOBS);
return(1);
}
@@ -1708,7 +1768,7 @@ obsolete(MACRO_PROT_ARGS)
* macro is encountered.
*/
static int
-phrase(struct mdoc *m, int line, int ppos, char *buf)
+phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
{
int la, pos;
enum margserr ac;
@@ -1718,7 +1778,7 @@ phrase(struct mdoc *m, int line, int ppos, char *buf)
for (pos = ppos; ; ) {
la = pos;
- ac = mdoc_zargs(m, line, &pos, buf, &p);
+ ac = mdoc_zargs(mdoc, line, &pos, buf, &p);
if (ARGS_ERROR == ac)
return(0);
@@ -1728,14 +1788,14 @@ phrase(struct mdoc *m, int line, int ppos, char *buf)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
if (MDOC_MAX == ntok) {
- if ( ! dword(m, line, la, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, la, p, DELIM_MAX, 1))
return(0);
continue;
}
- if ( ! mdoc_macro(m, ntok, line, la, &pos, buf))
+ if ( ! mdoc_macro(mdoc, ntok, line, la, &pos, buf))
return(0);
- return(append_delims(m, line, &pos, buf));
+ return(append_delims(mdoc, line, &pos, buf));
}
return(1);
@@ -1746,24 +1806,30 @@ phrase(struct mdoc *m, int line, int ppos, char *buf)
static int
phrase_ta(MACRO_PROT_ARGS)
{
+ struct mdoc_node *n;
int la;
enum mdoct ntok;
enum margserr ac;
char *p;
- /*
- * FIXME: this is overly restrictive: if the `Ta' is unexpected,
- * it should simply error out with ARGSLOST.
- */
+ /* Make sure we are in a column list or ignore this macro. */
+ n = mdoc->last;
+ while (NULL != n && MDOC_Bl != n->tok)
+ n = n->parent;
+ if (NULL == n || LIST_column != n->norm->Bl.type) {
+ mdoc_pmsg(mdoc, line, ppos, MANDOCERR_STRAYTA);
+ return(1);
+ }
- if ( ! rew_sub(MDOC_BODY, m, MDOC_It, line, ppos))
+ /* Advance to the next column. */
+ if ( ! rew_sub(MDOC_BODY, mdoc, MDOC_It, line, ppos))
return(0);
- if ( ! mdoc_body_alloc(m, line, ppos, MDOC_It))
+ if ( ! mdoc_body_alloc(mdoc, line, ppos, MDOC_It))
return(0);
for (;;) {
la = *pos;
- ac = mdoc_zargs(m, line, pos, buf, &p);
+ ac = mdoc_zargs(mdoc, line, pos, buf, &p);
if (ARGS_ERROR == ac)
return(0);
@@ -1773,14 +1839,15 @@ phrase_ta(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
if (MDOC_MAX == ntok) {
- if ( ! dword(m, line, la, p, DELIM_MAX))
+ if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+ MDOC_JOIN & mdoc_macros[tok].flags))
return(0);
continue;
}
- if ( ! mdoc_macro(m, ntok, line, la, pos, buf))
+ if ( ! mdoc_macro(mdoc, ntok, line, la, pos, buf))
return(0);
- return(append_delims(m, line, pos, buf));
+ return(append_delims(mdoc, line, pos, buf));
}
return(1);
diff --git a/mdoc_man.c b/mdoc_man.c
index 9d7d2ca23861..6ee8b3abf45e 100644
--- a/mdoc_man.c
+++ b/mdoc_man.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc_man.c,v 1.9 2011/10/24 21:47:59 schwarze Exp $ */
+/* $Id: mdoc_man.c,v 1.57 2013/12/25 22:00:45 schwarze Exp $ */
/*
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2012, 2013 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,22 +18,18 @@
#include "config.h"
#endif
+#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "mandoc.h"
+#include "out.h"
#include "man.h"
#include "mdoc.h"
#include "main.h"
-#define DECL_ARGS const struct mdoc_meta *m, \
- const struct mdoc_node *n, \
- struct mman *mm
-
-struct mman {
- int need_space; /* next word needs prior ws */
- int need_nl; /* next word needs prior nl */
-};
+#define DECL_ARGS const struct mdoc_meta *meta, \
+ const struct mdoc_node *n
struct manact {
int (*cond)(DECL_ARGS); /* DON'T run actions */
@@ -45,29 +41,74 @@ struct manact {
static int cond_body(DECL_ARGS);
static int cond_head(DECL_ARGS);
+static void font_push(char);
+static void font_pop(void);
+static void mid_it(void);
+static void post__t(DECL_ARGS);
static void post_bd(DECL_ARGS);
+static void post_bf(DECL_ARGS);
+static void post_bk(DECL_ARGS);
+static void post_bl(DECL_ARGS);
static void post_dl(DECL_ARGS);
static void post_enc(DECL_ARGS);
+static void post_eo(DECL_ARGS);
+static void post_fa(DECL_ARGS);
+static void post_fd(DECL_ARGS);
+static void post_fl(DECL_ARGS);
+static void post_fn(DECL_ARGS);
+static void post_fo(DECL_ARGS);
+static void post_font(DECL_ARGS);
+static void post_in(DECL_ARGS);
+static void post_it(DECL_ARGS);
+static void post_lb(DECL_ARGS);
static void post_nm(DECL_ARGS);
static void post_percent(DECL_ARGS);
static void post_pf(DECL_ARGS);
static void post_sect(DECL_ARGS);
static void post_sp(DECL_ARGS);
+static void post_vt(DECL_ARGS);
+static int pre__t(DECL_ARGS);
+static int pre_an(DECL_ARGS);
static int pre_ap(DECL_ARGS);
static int pre_bd(DECL_ARGS);
+static int pre_bf(DECL_ARGS);
+static int pre_bk(DECL_ARGS);
+static int pre_bl(DECL_ARGS);
static int pre_br(DECL_ARGS);
static int pre_bx(DECL_ARGS);
static int pre_dl(DECL_ARGS);
static int pre_enc(DECL_ARGS);
+static int pre_em(DECL_ARGS);
+static int pre_fa(DECL_ARGS);
+static int pre_fd(DECL_ARGS);
+static int pre_fl(DECL_ARGS);
+static int pre_fn(DECL_ARGS);
+static int pre_fo(DECL_ARGS);
+static int pre_ft(DECL_ARGS);
+static int pre_in(DECL_ARGS);
static int pre_it(DECL_ARGS);
+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 int pre_ns(DECL_ARGS);
static int pre_pp(DECL_ARGS);
+static int pre_rs(DECL_ARGS);
+static int pre_sm(DECL_ARGS);
static int pre_sp(DECL_ARGS);
static int pre_sect(DECL_ARGS);
+static int pre_sy(DECL_ARGS);
+static void pre_syn(const struct mdoc_node *);
+static int pre_vt(DECL_ARGS);
static int pre_ux(DECL_ARGS);
static int pre_xr(DECL_ARGS);
-static void print_word(struct mman *, const char *);
+static void print_word(const char *);
+static void print_line(const char *, int);
+static void print_block(const char *, int);
+static void print_offs(const char *);
+static void print_width(const char *,
+ const struct mdoc_node *, size_t);
+static void print_count(int *);
static void print_node(DECL_ARGS);
static const struct manact manacts[MDOC_MAX + 1] = {
@@ -82,74 +123,74 @@ static const struct manact manacts[MDOC_MAX + 1] = {
{ cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
{ cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
{ NULL, NULL, NULL, NULL, NULL }, /* Ed */
- { NULL, NULL, NULL, NULL, NULL }, /* Bl */
+ { cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */
{ NULL, NULL, NULL, NULL, NULL }, /* El */
- { NULL, pre_it, NULL, NULL, NULL }, /* _It */
- { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ad */
- { NULL, NULL, NULL, NULL, NULL }, /* _An */
- { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
- { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cd */
- { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
- { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Dv */
- { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Er */
- { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Ev */
+ { NULL, pre_it, post_it, NULL, NULL }, /* It */
+ { NULL, pre_em, post_font, NULL, NULL }, /* Ad */
+ { NULL, pre_an, NULL, NULL, NULL }, /* An */
+ { NULL, pre_em, post_font, NULL, NULL }, /* Ar */
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Cd */
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Cm */
+ { NULL, pre_li, post_font, NULL, NULL }, /* Dv */
+ { NULL, pre_li, post_font, NULL, NULL }, /* Er */
+ { NULL, pre_li, post_font, NULL, NULL }, /* Ev */
{ NULL, pre_enc, post_enc, "The \\fB",
"\\fP\nutility exits 0 on success, and >0 if an error occurs."
}, /* Ex */
- { NULL, NULL, NULL, NULL, NULL }, /* _Fa */
- { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
- { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
- { NULL, NULL, NULL, NULL, NULL }, /* _Fn */
- { NULL, NULL, NULL, NULL, NULL }, /* _Ft */
- { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */
- { NULL, NULL, NULL, NULL, NULL }, /* _In */
- { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Li */
+ { NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */
+ { NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */
+ { NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */
+ { NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */
+ { NULL, pre_ft, post_font, NULL, NULL }, /* Ft */
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Ic */
+ { NULL, pre_in, post_in, NULL, NULL }, /* In */
+ { NULL, pre_li, post_font, NULL, NULL }, /* Li */
{ cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
{ NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
{ NULL, NULL, NULL, NULL, NULL }, /* Ot */
- { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Pa */
+ { NULL, pre_em, post_font, NULL, NULL }, /* Pa */
{ NULL, pre_enc, post_enc, "The \\fB",
"\\fP\nfunction returns the value 0 if successful;\n"
"otherwise the value -1 is returned and the global\n"
"variable \\fIerrno\\fP is set to indicate the error."
}, /* Rv */
{ NULL, NULL, NULL, NULL, NULL }, /* St */
- { NULL, NULL, NULL, NULL, NULL }, /* _Va */
- { NULL, NULL, NULL, NULL, NULL }, /* _Vt */
+ { NULL, pre_em, post_font, NULL, NULL }, /* Va */
+ { NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
{ NULL, pre_xr, NULL, NULL, NULL }, /* Xr */
- { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
- { NULL, NULL, NULL, NULL, NULL }, /* _%B */
- { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
- { NULL, NULL, NULL, NULL, NULL }, /* _%I */
- { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
- { NULL, NULL, NULL, NULL, NULL }, /* _%N */
- { NULL, NULL, NULL, NULL, NULL }, /* _%O */
- { NULL, NULL, NULL, NULL, NULL }, /* _%P */
- { NULL, NULL, NULL, NULL, NULL }, /* _%R */
- { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
- { NULL, NULL, NULL, NULL, NULL }, /* _%V */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %A */
+ { NULL, pre_em, post_percent, NULL, NULL }, /* %B */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %D */
+ { NULL, pre_em, post_percent, NULL, NULL }, /* %I */
+ { NULL, pre_em, post_percent, NULL, NULL }, /* %J */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %N */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %O */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %P */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %R */
+ { NULL, pre__t, post__t, NULL, NULL }, /* %T */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %V */
{ NULL, NULL, NULL, NULL, NULL }, /* Ac */
{ cond_body, pre_enc, post_enc, "<", ">" }, /* Ao */
{ cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
{ NULL, NULL, NULL, NULL, NULL }, /* At */
{ NULL, NULL, NULL, NULL, NULL }, /* Bc */
- { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
+ { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
{ NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */
{ NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
{ NULL, NULL, NULL, NULL, NULL }, /* Db */
{ NULL, NULL, NULL, NULL, NULL }, /* Dc */
- { cond_body, pre_enc, post_enc, "``", "''" }, /* Do */
- { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
- { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
- { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
- { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */
- { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
+ { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
+ { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
+ { NULL, NULL, NULL, NULL, NULL }, /* Ec */
+ { NULL, NULL, NULL, NULL, NULL }, /* Ef */
+ { NULL, pre_em, post_font, NULL, NULL }, /* Em */
+ { NULL, NULL, post_eo, NULL, NULL }, /* Eo */
{ NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */
- { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ms */
- { NULL, NULL, NULL, NULL, NULL }, /* No */
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
+ { NULL, pre_no, NULL, NULL, NULL }, /* No */
{ NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
{ NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */
{ NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */
@@ -158,91 +199,324 @@ static const struct manact manacts[MDOC_MAX + 1] = {
{ cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
{ cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
{ NULL, NULL, NULL, NULL, NULL }, /* Qc */
- { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
{ cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
{ cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
{ NULL, NULL, NULL, NULL, NULL }, /* Re */
- { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
+ { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
{ NULL, NULL, NULL, NULL, NULL }, /* Sc */
- { cond_body, pre_enc, post_enc, "`", "'" }, /* So */
- { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
- { NULL, NULL, NULL, NULL, NULL }, /* _Sm */
- { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */
- { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */
- { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Tn */
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */
+ { NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
+ { NULL, pre_em, post_font, NULL, NULL }, /* Sx */
+ { NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
+ { NULL, pre_li, post_font, NULL, NULL }, /* Tn */
{ NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */
- { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
- { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
- { NULL, NULL, NULL, NULL, NULL }, /* _Fo */
- { NULL, NULL, NULL, NULL, NULL }, /* _Fc */
+ { NULL, NULL, NULL, NULL, NULL }, /* Xc */
+ { NULL, NULL, NULL, NULL, NULL }, /* Xo */
+ { NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
+ { NULL, NULL, NULL, NULL, NULL }, /* Fc */
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
{ NULL, NULL, NULL, NULL, NULL }, /* Oc */
- { NULL, NULL, NULL, NULL, NULL }, /* _Bk */
- { NULL, NULL, NULL, NULL, NULL }, /* _Ek */
+ { NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
+ { NULL, NULL, NULL, NULL, NULL }, /* Ek */
{ NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */
{ NULL, NULL, NULL, NULL, NULL }, /* Hf */
{ NULL, NULL, NULL, NULL, NULL }, /* Fr */
{ NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */
- { NULL, NULL, NULL, NULL, NULL }, /* _Lb */
+ { NULL, NULL, post_lb, NULL, NULL }, /* Lb */
{ NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
- { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
- { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
+ { NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
+ { NULL, pre_em, post_font, NULL, NULL }, /* Mt */
{ cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
{ cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
{ NULL, NULL, NULL, NULL, NULL }, /* Brc */
- { NULL, NULL, NULL, NULL, NULL }, /* _%C */
- { NULL, NULL, NULL, NULL, NULL }, /* _Es */
- { NULL, NULL, NULL, NULL, NULL }, /* _En */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %C */
+ { NULL, NULL, NULL, NULL, NULL }, /* Es */
+ { NULL, NULL, NULL, NULL, NULL }, /* En */
{ NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */
- { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %Q */
{ NULL, pre_br, NULL, NULL, NULL }, /* br */
{ NULL, pre_sp, post_sp, NULL, NULL }, /* sp */
- { NULL, NULL, NULL, NULL, NULL }, /* _%U */
- { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
+ { NULL, NULL, post_percent, NULL, NULL }, /* %U */
+ { NULL, NULL, NULL, NULL, NULL }, /* Ta */
{ NULL, NULL, NULL, NULL, NULL }, /* ROOT */
};
+static int outflags;
+#define MMAN_spc (1 << 0) /* blank character before next word */
+#define MMAN_spc_force (1 << 1) /* even before trailing punctuation */
+#define MMAN_nl (1 << 2) /* break man(7) code line */
+#define MMAN_br (1 << 3) /* break output line */
+#define MMAN_sp (1 << 4) /* insert a blank output line */
+#define MMAN_PP (1 << 5) /* reset indentation etc. */
+#define MMAN_Sm (1 << 6) /* horizontal spacing mode */
+#define MMAN_Bk (1 << 7) /* word keep mode */
+#define MMAN_Bk_susp (1 << 8) /* suspend this (after a macro) */
+#define MMAN_An_split (1 << 9) /* author mode is "split" */
+#define MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */
+#define MMAN_PD (1 << 11) /* inter-paragraph spacing disabled */
+#define MMAN_nbrword (1 << 12) /* do not break the next word */
+
+#define BL_STACK_MAX 32
+
+static size_t Bl_stack[BL_STACK_MAX]; /* offsets [chars] */
+static int Bl_stack_post[BL_STACK_MAX]; /* add final .RE */
+static int Bl_stack_len; /* number of nested Bl blocks */
+static int TPremain; /* characters before tag is full */
+
+static struct {
+ char *head;
+ char *tail;
+ size_t size;
+} fontqueue;
+
+static void
+font_push(char newfont)
+{
+
+ if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) {
+ fontqueue.size += 8;
+ fontqueue.head = mandoc_realloc(fontqueue.head,
+ fontqueue.size);
+ }
+ *fontqueue.tail = newfont;
+ print_word("");
+ printf("\\f");
+ putchar(newfont);
+ outflags &= ~MMAN_spc;
+}
+
+static void
+font_pop(void)
+{
+
+ if (fontqueue.tail > fontqueue.head)
+ fontqueue.tail--;
+ outflags &= ~MMAN_spc;
+ print_word("");
+ printf("\\f");
+ putchar(*fontqueue.tail);
+}
+
static void
-print_word(struct mman *mm, const char *s)
+print_word(const char *s)
{
- if (mm->need_nl) {
+ if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) {
/*
* If we need a newline, print it now and start afresh.
*/
- putchar('\n');
- mm->need_space = 0;
- mm->need_nl = 0;
- } else if (mm->need_space && '\0' != s[0])
+ if (MMAN_PP & outflags) {
+ if (MMAN_sp & outflags) {
+ if (MMAN_PD & outflags) {
+ printf("\n.PD");
+ outflags &= ~MMAN_PD;
+ }
+ } else if ( ! (MMAN_PD & outflags)) {
+ printf("\n.PD 0");
+ outflags |= MMAN_PD;
+ }
+ printf("\n.PP\n");
+ } else if (MMAN_sp & outflags)
+ printf("\n.sp\n");
+ else if (MMAN_br & outflags)
+ printf("\n.br\n");
+ else if (MMAN_nl & outflags)
+ putchar('\n');
+ outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc);
+ if (1 == TPremain)
+ printf(".br\n");
+ TPremain = 0;
+ } else if (MMAN_spc & outflags) {
/*
- * If we need a space, only print it before
- * (1) a nonzero length word;
- * (2) a word that is non-punctuation; and
- * (3) if punctuation, non-terminating puncutation.
+ * If we need a space, only print it if
+ * (1) it is forced by `No' or
+ * (2) what follows is not terminating punctuation or
+ * (3) what follows is longer than one character.
*/
- if (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1])
+ if (MMAN_spc_force & outflags || '\0' == s[0] ||
+ NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
+ if (MMAN_Bk & outflags &&
+ ! (MMAN_Bk_susp & outflags))
+ putchar('\\');
putchar(' ');
+ if (TPremain)
+ TPremain--;
+ }
+ }
/*
* Reassign needing space if we're not following opening
* punctuation.
*/
- mm->need_space =
- ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
+ if (MMAN_Sm & outflags && ('\0' == s[0] ||
+ (('(' != s[0] && '[' != s[0]) || '\0' != s[1])))
+ outflags |= MMAN_spc;
+ else
+ outflags &= ~MMAN_spc;
+ outflags &= ~(MMAN_spc_force | MMAN_Bk_susp);
for ( ; *s; s++) {
switch (*s) {
case (ASCII_NBRSP):
- printf("\\~");
+ printf("\\ ");
break;
case (ASCII_HYPH):
putchar('-');
break;
+ case (' '):
+ if (MMAN_nbrword & outflags) {
+ printf("\\ ");
+ break;
+ }
+ /* FALLTHROUGH */
default:
putchar((unsigned char)*s);
break;
}
+ if (TPremain)
+ TPremain--;
+ }
+ outflags &= ~MMAN_nbrword;
+}
+
+static void
+print_line(const char *s, int newflags)
+{
+
+ outflags &= ~MMAN_br;
+ outflags |= MMAN_nl;
+ print_word(s);
+ outflags |= newflags;
+}
+
+static void
+print_block(const char *s, int newflags)
+{
+
+ outflags &= ~MMAN_PP;
+ if (MMAN_sp & outflags) {
+ outflags &= ~(MMAN_sp | MMAN_br);
+ if (MMAN_PD & outflags) {
+ print_line(".PD", 0);
+ outflags &= ~MMAN_PD;
+ }
+ } else if (! (MMAN_PD & outflags))
+ print_line(".PD 0", MMAN_PD);
+ outflags |= MMAN_nl;
+ print_word(s);
+ outflags |= MMAN_Bk_susp | newflags;
+}
+
+static void
+print_offs(const char *v)
+{
+ char buf[24];
+ struct roffsu su;
+ size_t sz;
+
+ print_line(".RS", MMAN_Bk_susp);
+
+ /* Convert v into a number (of characters). */
+ if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
+ sz = 0;
+ else if (0 == strcmp(v, "indent"))
+ sz = 6;
+ else if (0 == strcmp(v, "indent-two"))
+ sz = 12;
+ else if (a2roffsu(v, &su, SCALE_MAX)) {
+ if (SCALE_EN == su.unit)
+ sz = su.scale;
+ else {
+ /*
+ * XXX
+ * If we are inside an enclosing list,
+ * there is no easy way to add the two
+ * indentations because they are provided
+ * in terms of different units.
+ */
+ print_word(v);
+ outflags |= MMAN_nl;
+ return;
+ }
+ } else
+ sz = strlen(v);
+
+ /*
+ * We are inside an enclosing list.
+ * Add the two indentations.
+ */
+ if (Bl_stack_len)
+ sz += Bl_stack[Bl_stack_len - 1];
+
+ snprintf(buf, sizeof(buf), "%zun", sz);
+ print_word(buf);
+ outflags |= MMAN_nl;
+}
+
+/*
+ * Set up the indentation for a list item; used from pre_it().
+ */
+void
+print_width(const char *v, const struct mdoc_node *child, size_t defsz)
+{
+ char buf[24];
+ struct roffsu su;
+ size_t sz, chsz;
+ int numeric, remain;
+
+ numeric = 1;
+ remain = 0;
+
+ /* Convert v into a number (of characters). */
+ if (NULL == v)
+ sz = defsz;
+ else if (a2roffsu(v, &su, SCALE_MAX)) {
+ if (SCALE_EN == su.unit)
+ sz = su.scale;
+ else {
+ sz = 0;
+ numeric = 0;
+ }
+ } else
+ sz = strlen(v);
+
+ /* XXX Rough estimation, might have multiple parts. */
+ chsz = (NULL != child && MDOC_TEXT == child->type) ?
+ strlen(child->string) : 0;
+
+ /* Maybe we are inside an enclosing list? */
+ mid_it();
+
+ /*
+ * Save our own indentation,
+ * such that child lists can use it.
+ */
+ Bl_stack[Bl_stack_len++] = sz + 2;
+
+ /* Set up the current list. */
+ if (defsz && chsz > sz)
+ print_block(".HP", 0);
+ else {
+ print_block(".TP", 0);
+ remain = sz + 2;
}
+ if (numeric) {
+ snprintf(buf, sizeof(buf), "%zun", sz + 2);
+ print_word(buf);
+ } else
+ print_word(v);
+ TPremain = remain;
+}
+
+void
+print_count(int *count)
+{
+ char buf[12];
+
+ snprintf(buf, sizeof(buf), "%d.", ++*count);
+ print_word(buf);
}
void
@@ -261,37 +535,42 @@ man_man(void *arg, const struct man *man)
void
man_mdoc(void *arg, const struct mdoc *mdoc)
{
- const struct mdoc_meta *m;
+ const struct mdoc_meta *meta;
const struct mdoc_node *n;
- struct mman mm;
- m = mdoc_meta(mdoc);
+ meta = mdoc_meta(mdoc);
n = mdoc_node(mdoc);
- printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
- m->title, m->msec, m->date, m->os, m->vol);
+ printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
+ meta->title, meta->msec, meta->date,
+ meta->os, meta->vol);
- memset(&mm, 0, sizeof(struct mman));
+ /* Disable hyphenation and if nroff, disable justification. */
+ printf(".nh\n.if n .ad l");
- mm.need_nl = 1;
- print_node(m, n, &mm);
+ outflags = MMAN_nl | MMAN_Sm;
+ if (0 == fontqueue.size) {
+ fontqueue.size = 8;
+ fontqueue.head = fontqueue.tail = mandoc_malloc(8);
+ *fontqueue.tail = 'R';
+ }
+ print_node(meta, n);
putchar('\n');
}
static void
print_node(DECL_ARGS)
{
- const struct mdoc_node *prev, *sub;
+ const struct mdoc_node *sub;
const struct manact *act;
int cond, do_sub;
-
+
/*
* Break the line if we were parsed subsequent the current node.
* This makes the page structure be more consistent.
*/
- prev = n->prev ? n->prev : n->parent;
- if (prev && prev->line < n->line)
- mm->need_nl = 1;
+ if (MMAN_spc & outflags && MDOC_LINE & n->flags)
+ outflags |= MMAN_nl;
act = NULL;
cond = 0;
@@ -302,21 +581,22 @@ print_node(DECL_ARGS)
* Make sure that we don't happen to start with a
* control character at the start of a line.
*/
- if (mm->need_nl && ('.' == *n->string ||
+ if (MMAN_nl & outflags && ('.' == *n->string ||
'\'' == *n->string)) {
- print_word(mm, "\\&");
- mm->need_space = 0;
+ print_word("");
+ printf("\\&");
+ outflags &= ~MMAN_spc;
}
- print_word(mm, n->string);
+ print_word(n->string);
} else {
/*
* Conditionally run the pre-node action handler for a
* node.
*/
act = manacts + n->tok;
- cond = NULL == act->cond || (*act->cond)(m, n, mm);
+ cond = NULL == act->cond || (*act->cond)(meta, n);
if (cond && act->pre)
- do_sub = (*act->pre)(m, n, mm);
+ do_sub = (*act->pre)(meta, n);
}
/*
@@ -326,13 +606,13 @@ print_node(DECL_ARGS)
*/
if (do_sub)
for (sub = n->child; sub; sub = sub->next)
- print_node(m, sub, mm);
+ print_node(meta, sub);
/*
* Lastly, conditionally run the post-node handler.
*/
if (cond && act->post)
- (*act->post)(m, n, mm);
+ (*act->post)(meta, n);
}
static int
@@ -349,10 +629,6 @@ cond_body(DECL_ARGS)
return(MDOC_BODY == n->type);
}
-/*
- * Output a font encoding before a node, e.g., \fR.
- * This obviously has no trailing space.
- */
static int
pre_enc(DECL_ARGS)
{
@@ -361,14 +637,11 @@ pre_enc(DECL_ARGS)
prefix = manacts[n->tok].prefix;
if (NULL == prefix)
return(1);
- print_word(mm, prefix);
- mm->need_space = 0;
+ print_word(prefix);
+ outflags &= ~MMAN_spc;
return(1);
}
-/*
- * Output a font encoding subsequent a node, e.g., \fP.
- */
static void
post_enc(DECL_ARGS)
{
@@ -377,28 +650,62 @@ post_enc(DECL_ARGS)
suffix = manacts[n->tok].suffix;
if (NULL == suffix)
return;
- mm->need_space = 0;
- print_word(mm, suffix);
+ outflags &= ~MMAN_spc;
+ print_word(suffix);
+}
+
+static void
+post_font(DECL_ARGS)
+{
+
+ font_pop();
}
-/*
- * Used in listings (percent = %A, e.g.).
- * FIXME: this is incomplete.
- * It doesn't print a nice ", and" for lists.
- */
static void
post_percent(DECL_ARGS)
{
- post_enc(m, n, mm);
- if (n->next)
- print_word(mm, ",");
- else {
- print_word(mm, ".");
- mm->need_nl = 1;
+ if (pre_em == manacts[n->tok].pre)
+ font_pop();
+ if (n->next) {
+ print_word(",");
+ if (n->prev && n->prev->tok == n->tok &&
+ n->next->tok == n->tok)
+ print_word("and");
+ } else {
+ print_word(".");
+ outflags |= MMAN_nl;
}
}
+static int
+pre__t(DECL_ARGS)
+{
+
+ if (n->parent && MDOC_Rs == n->parent->tok &&
+ n->parent->norm->Rs.quote_T) {
+ print_word("");
+ putchar('\"');
+ outflags &= ~MMAN_spc;
+ } else
+ font_push('I');
+ return(1);
+}
+
+static void
+post__t(DECL_ARGS)
+{
+
+ if (n->parent && MDOC_Rs == n->parent->tok &&
+ n->parent->norm->Rs.quote_T) {
+ outflags &= ~MMAN_spc;
+ print_word("");
+ putchar('\"');
+ } else
+ font_pop();
+ post_percent(meta, n);
+}
+
/*
* Print before a section header.
*/
@@ -406,12 +713,13 @@ static int
pre_sect(DECL_ARGS)
{
- if (MDOC_HEAD != n->type)
- return(1);
- mm->need_nl = 1;
- print_word(mm, manacts[n->tok].prefix);
- print_word(mm, "\"");
- mm->need_space = 0;
+ if (MDOC_HEAD == n->type) {
+ outflags |= MMAN_sp;
+ print_block(manacts[n->tok].prefix, 0);
+ print_word("");
+ putchar('\"');
+ outflags &= ~MMAN_spc;
+ }
return(1);
}
@@ -424,18 +732,84 @@ post_sect(DECL_ARGS)
if (MDOC_HEAD != n->type)
return;
- mm->need_space = 0;
- print_word(mm, "\"");
- mm->need_nl = 1;
+ outflags &= ~MMAN_spc;
+ print_word("");
+ putchar('\"');
+ outflags |= MMAN_nl;
+ if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec)
+ outflags &= ~(MMAN_An_split | MMAN_An_nosplit);
+}
+
+/* See mdoc_term.c, synopsis_pre() for comments. */
+static void
+pre_syn(const struct mdoc_node *n)
+{
+
+ if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
+ return;
+
+ if (n->prev->tok == n->tok &&
+ MDOC_Ft != n->tok &&
+ MDOC_Fo != n->tok &&
+ MDOC_Fn != n->tok) {
+ outflags |= MMAN_br;
+ return;
+ }
+
+ switch (n->prev->tok) {
+ case (MDOC_Fd):
+ /* FALLTHROUGH */
+ case (MDOC_Fn):
+ /* FALLTHROUGH */
+ case (MDOC_Fo):
+ /* FALLTHROUGH */
+ case (MDOC_In):
+ /* FALLTHROUGH */
+ case (MDOC_Vt):
+ outflags |= MMAN_sp;
+ break;
+ case (MDOC_Ft):
+ if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
+ outflags |= MMAN_sp;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ outflags |= MMAN_br;
+ break;
+ }
+}
+
+static int
+pre_an(DECL_ARGS)
+{
+
+ switch (n->norm->An.auth) {
+ case (AUTH_split):
+ outflags &= ~MMAN_An_nosplit;
+ outflags |= MMAN_An_split;
+ return(0);
+ case (AUTH_nosplit):
+ outflags &= ~MMAN_An_split;
+ outflags |= MMAN_An_nosplit;
+ return(0);
+ default:
+ if (MMAN_An_split & outflags)
+ outflags |= MMAN_br;
+ else if (SEC_AUTHORS == n->sec &&
+ ! (MMAN_An_nosplit & outflags))
+ outflags |= MMAN_An_split;
+ return(1);
+ }
}
static int
pre_ap(DECL_ARGS)
{
- mm->need_space = 0;
- print_word(mm, "'");
- mm->need_space = 0;
+ outflags &= ~MMAN_spc;
+ print_word("'");
+ outflags &= ~MMAN_spc;
return(0);
}
@@ -443,12 +817,14 @@ static int
pre_bd(DECL_ARGS)
{
+ outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br);
+
if (DISP_unfilled == n->norm->Bd.type ||
- DISP_literal == n->norm->Bd.type) {
- mm->need_nl = 1;
- print_word(mm, ".nf");
- }
- mm->need_nl = 1;
+ DISP_literal == n->norm->Bd.type)
+ print_line(".nf", 0);
+ if (0 == n->norm->Bd.comp && NULL != n->parent->prev)
+ outflags |= MMAN_sp;
+ print_offs(n->norm->Bd.offs);
return(1);
}
@@ -456,21 +832,143 @@ static void
post_bd(DECL_ARGS)
{
+ /* Close out this display. */
+ print_line(".RE", MMAN_nl);
if (DISP_unfilled == n->norm->Bd.type ||
- DISP_literal == n->norm->Bd.type) {
- mm->need_nl = 1;
- print_word(mm, ".fi");
+ DISP_literal == n->norm->Bd.type)
+ print_line(".fi", MMAN_nl);
+
+ /* Maybe we are inside an enclosing list? */
+ if (NULL != n->parent->next)
+ mid_it();
+}
+
+static int
+pre_bf(DECL_ARGS)
+{
+
+ switch (n->type) {
+ case (MDOC_BLOCK):
+ return(1);
+ case (MDOC_BODY):
+ break;
+ default:
+ return(0);
+ }
+ switch (n->norm->Bf.font) {
+ case (FONT_Em):
+ font_push('I');
+ break;
+ case (FONT_Sy):
+ font_push('B');
+ break;
+ default:
+ font_push('R');
+ break;
}
- mm->need_nl = 1;
+ return(1);
+}
+
+static void
+post_bf(DECL_ARGS)
+{
+
+ if (MDOC_BODY == n->type)
+ font_pop();
+}
+
+static int
+pre_bk(DECL_ARGS)
+{
+
+ switch (n->type) {
+ case (MDOC_BLOCK):
+ return(1);
+ case (MDOC_BODY):
+ outflags |= MMAN_Bk;
+ return(1);
+ default:
+ return(0);
+ }
+}
+
+static void
+post_bk(DECL_ARGS)
+{
+
+ if (MDOC_BODY == n->type)
+ outflags &= ~MMAN_Bk;
+}
+
+static int
+pre_bl(DECL_ARGS)
+{
+ size_t icol;
+
+ /*
+ * print_offs() will increase the -offset to account for
+ * a possible enclosing .It, but any enclosed .It blocks
+ * just nest and do not add up their indentation.
+ */
+ if (n->norm->Bl.offs) {
+ print_offs(n->norm->Bl.offs);
+ Bl_stack[Bl_stack_len++] = 0;
+ }
+
+ switch (n->norm->Bl.type) {
+ case (LIST_enum):
+ n->norm->Bl.count = 0;
+ return(1);
+ case (LIST_column):
+ break;
+ default:
+ return(1);
+ }
+
+ print_line(".TS", MMAN_nl);
+ for (icol = 0; icol < n->norm->Bl.ncols; icol++)
+ print_word("l");
+ print_word(".");
+ outflags |= MMAN_nl;
+ return(1);
+}
+
+static void
+post_bl(DECL_ARGS)
+{
+
+ switch (n->norm->Bl.type) {
+ case (LIST_column):
+ print_line(".TE", 0);
+ break;
+ case (LIST_enum):
+ n->norm->Bl.count = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (n->norm->Bl.offs) {
+ print_line(".RE", MMAN_nl);
+ assert(Bl_stack_len);
+ Bl_stack_len--;
+ assert(0 == Bl_stack[Bl_stack_len]);
+ } else {
+ outflags |= MMAN_PP | MMAN_nl;
+ outflags &= ~(MMAN_sp | MMAN_br);
+ }
+
+ /* Maybe we are inside an enclosing list? */
+ if (NULL != n->parent->next)
+ mid_it();
+
}
static int
pre_br(DECL_ARGS)
{
- mm->need_nl = 1;
- print_word(mm, ".br");
- mm->need_nl = 1;
+ outflags |= MMAN_br;
return(0);
}
@@ -480,17 +978,17 @@ pre_bx(DECL_ARGS)
n = n->child;
if (n) {
- print_word(mm, n->string);
- mm->need_space = 0;
+ print_word(n->string);
+ outflags &= ~MMAN_spc;
n = n->next;
}
- print_word(mm, "BSD");
+ print_word("BSD");
if (NULL == n)
return(0);
- mm->need_space = 0;
- print_word(mm, "-");
- mm->need_space = 0;
- print_word(mm, n->string);
+ outflags &= ~MMAN_spc;
+ print_word("-");
+ outflags &= ~MMAN_spc;
+ print_word(n->string);
return(0);
}
@@ -498,9 +996,7 @@ static int
pre_dl(DECL_ARGS)
{
- mm->need_nl = 1;
- print_word(mm, ".RS 6n");
- mm->need_nl = 1;
+ print_offs("6n");
return(1);
}
@@ -508,9 +1004,213 @@ static void
post_dl(DECL_ARGS)
{
- mm->need_nl = 1;
- print_word(mm, ".RE");
- mm->need_nl = 1;
+ print_line(".RE", MMAN_nl);
+
+ /* Maybe we are inside an enclosing list? */
+ if (NULL != n->parent->next)
+ mid_it();
+}
+
+static int
+pre_em(DECL_ARGS)
+{
+
+ font_push('I');
+ return(1);
+}
+
+static void
+post_eo(DECL_ARGS)
+{
+
+ if (MDOC_HEAD == n->type || MDOC_BODY == n->type)
+ outflags &= ~MMAN_spc;
+}
+
+static int
+pre_fa(DECL_ARGS)
+{
+ int am_Fa;
+
+ am_Fa = MDOC_Fa == n->tok;
+
+ if (am_Fa)
+ n = n->child;
+
+ while (NULL != n) {
+ font_push('I');
+ if (am_Fa || MDOC_SYNPRETTY & n->flags)
+ outflags |= MMAN_nbrword;
+ print_node(meta, n);
+ font_pop();
+ if (NULL != (n = n->next))
+ print_word(",");
+ }
+ return(0);
+}
+
+static void
+post_fa(DECL_ARGS)
+{
+
+ if (NULL != n->next && MDOC_Fa == n->next->tok)
+ print_word(",");
+}
+
+static int
+pre_fd(DECL_ARGS)
+{
+
+ pre_syn(n);
+ font_push('B');
+ return(1);
+}
+
+static void
+post_fd(DECL_ARGS)
+{
+
+ font_pop();
+ outflags |= MMAN_br;
+}
+
+static int
+pre_fl(DECL_ARGS)
+{
+
+ font_push('B');
+ print_word("\\-");
+ outflags &= ~MMAN_spc;
+ return(1);
+}
+
+static void
+post_fl(DECL_ARGS)
+{
+
+ font_pop();
+ if (0 == n->nchild && NULL != n->next &&
+ n->next->line == n->line)
+ outflags &= ~MMAN_spc;
+}
+
+static int
+pre_fn(DECL_ARGS)
+{
+
+ pre_syn(n);
+
+ n = n->child;
+ if (NULL == n)
+ return(0);
+
+ if (MDOC_SYNPRETTY & n->flags)
+ print_block(".HP 4n", MMAN_nl);
+
+ font_push('B');
+ print_node(meta, n);
+ font_pop();
+ outflags &= ~MMAN_spc;
+ print_word("(");
+ outflags &= ~MMAN_spc;
+
+ n = n->next;
+ if (NULL != n)
+ pre_fa(meta, n);
+ return(0);
+}
+
+static void
+post_fn(DECL_ARGS)
+{
+
+ print_word(")");
+ if (MDOC_SYNPRETTY & n->flags) {
+ print_word(";");
+ outflags |= MMAN_PP;
+ }
+}
+
+static int
+pre_fo(DECL_ARGS)
+{
+
+ switch (n->type) {
+ case (MDOC_BLOCK):
+ pre_syn(n);
+ break;
+ case (MDOC_HEAD):
+ if (MDOC_SYNPRETTY & n->flags)
+ print_block(".HP 4n", MMAN_nl);
+ font_push('B');
+ break;
+ case (MDOC_BODY):
+ outflags &= ~MMAN_spc;
+ print_word("(");
+ outflags &= ~MMAN_spc;
+ break;
+ default:
+ break;
+ }
+ return(1);
+}
+
+static void
+post_fo(DECL_ARGS)
+{
+
+ switch (n->type) {
+ case (MDOC_HEAD):
+ font_pop();
+ break;
+ case (MDOC_BODY):
+ post_fn(meta, n);
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+pre_ft(DECL_ARGS)
+{
+
+ pre_syn(n);
+ font_push('I');
+ return(1);
+}
+
+static int
+pre_in(DECL_ARGS)
+{
+
+ if (MDOC_SYNPRETTY & n->flags) {
+ pre_syn(n);
+ font_push('B');
+ print_word("#include <");
+ outflags &= ~MMAN_spc;
+ } else {
+ print_word("<");
+ outflags &= ~MMAN_spc;
+ font_push('I');
+ }
+ return(1);
+}
+
+static void
+post_in(DECL_ARGS)
+{
+
+ if (MDOC_SYNPRETTY & n->flags) {
+ outflags &= ~MMAN_spc;
+ print_word(">");
+ font_pop();
+ outflags |= MMAN_br;
+ } else {
+ font_pop();
+ outflags &= ~MMAN_spc;
+ print_word(">");
+ }
}
static int
@@ -518,36 +1218,221 @@ pre_it(DECL_ARGS)
{
const struct mdoc_node *bln;
- if (MDOC_HEAD == n->type) {
- mm->need_nl = 1;
- print_word(mm, ".TP");
- bln = n->parent->parent->prev;
+ switch (n->type) {
+ case (MDOC_HEAD):
+ outflags |= MMAN_PP | MMAN_nl;
+ bln = n->parent->parent;
+ if (0 == bln->norm->Bl.comp ||
+ (NULL == n->parent->prev &&
+ NULL == bln->parent->prev))
+ outflags |= MMAN_sp;
+ outflags &= ~MMAN_br;
switch (bln->norm->Bl.type) {
+ case (LIST_item):
+ return(0);
+ case (LIST_inset):
+ /* FALLTHROUGH */
+ case (LIST_diag):
+ /* FALLTHROUGH */
+ case (LIST_ohang):
+ if (bln->norm->Bl.type == LIST_diag)
+ print_line(".B \"", 0);
+ else
+ print_line(".R \"", 0);
+ outflags &= ~MMAN_spc;
+ return(1);
case (LIST_bullet):
- print_word(mm, "4n");
- mm->need_nl = 1;
- print_word(mm, "\\fBo\\fP");
+ /* FALLTHROUGH */
+ case (LIST_dash):
+ /* FALLTHROUGH */
+ case (LIST_hyphen):
+ print_width(bln->norm->Bl.width, NULL, 0);
+ TPremain = 0;
+ outflags |= MMAN_nl;
+ font_push('B');
+ if (LIST_bullet == bln->norm->Bl.type)
+ print_word("o");
+ else
+ print_word("-");
+ font_pop();
+ break;
+ case (LIST_enum):
+ print_width(bln->norm->Bl.width, NULL, 0);
+ TPremain = 0;
+ outflags |= MMAN_nl;
+ print_count(&bln->norm->Bl.count);
+ break;
+ case (LIST_hang):
+ print_width(bln->norm->Bl.width, n->child, 6);
+ TPremain = 0;
+ break;
+ case (LIST_tag):
+ print_width(bln->norm->Bl.width, n->child, 0);
+ putchar('\n');
+ outflags &= ~MMAN_spc;
+ return(1);
+ default:
+ return(1);
+ }
+ outflags |= MMAN_nl;
+ default:
+ break;
+ }
+ return(1);
+}
+
+/*
+ * This function is called after closing out an indented block.
+ * If we are inside an enclosing list, restore its indentation.
+ */
+static void
+mid_it(void)
+{
+ char buf[24];
+
+ /* Nothing to do outside a list. */
+ if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1])
+ return;
+
+ /* The indentation has already been set up. */
+ if (Bl_stack_post[Bl_stack_len - 1])
+ return;
+
+ /* Restore the indentation of the enclosing list. */
+ print_line(".RS", MMAN_Bk_susp);
+ snprintf(buf, sizeof(buf), "%zun", Bl_stack[Bl_stack_len - 1]);
+ print_word(buf);
+
+ /* Remeber to close out this .RS block later. */
+ Bl_stack_post[Bl_stack_len - 1] = 1;
+}
+
+static void
+post_it(DECL_ARGS)
+{
+ const struct mdoc_node *bln;
+
+ bln = n->parent->parent;
+
+ switch (n->type) {
+ case (MDOC_HEAD):
+ switch (bln->norm->Bl.type) {
+ case (LIST_diag):
+ outflags &= ~MMAN_spc;
+ print_word("\\ ");
+ break;
+ case (LIST_ohang):
+ outflags |= MMAN_br;
+ break;
+ default:
+ break;
+ }
+ break;
+ case (MDOC_BODY):
+ switch (bln->norm->Bl.type) {
+ case (LIST_bullet):
+ /* FALLTHROUGH */
+ case (LIST_dash):
+ /* FALLTHROUGH */
+ case (LIST_hyphen):
+ /* FALLTHROUGH */
+ case (LIST_enum):
+ /* FALLTHROUGH */
+ case (LIST_hang):
+ /* FALLTHROUGH */
+ case (LIST_tag):
+ assert(Bl_stack_len);
+ Bl_stack[--Bl_stack_len] = 0;
+
+ /*
+ * Our indentation had to be restored
+ * after a child display or child list.
+ * Close out that indentation block now.
+ */
+ if (Bl_stack_post[Bl_stack_len]) {
+ print_line(".RE", MMAN_nl);
+ Bl_stack_post[Bl_stack_len] = 0;
+ }
+ break;
+ case (LIST_column):
+ if (NULL != n->next) {
+ putchar('\t');
+ outflags &= ~MMAN_spc;
+ }
break;
default:
- if (bln->norm->Bl.width)
- print_word(mm, bln->norm->Bl.width);
break;
}
- mm->need_nl = 1;
+ break;
+ default:
+ break;
}
+}
+
+static void
+post_lb(DECL_ARGS)
+{
+
+ if (SEC_LIBRARY == n->sec)
+ outflags |= MMAN_br;
+}
+
+static int
+pre_lk(DECL_ARGS)
+{
+ const struct mdoc_node *link, *descr;
+
+ if (NULL == (link = n->child))
+ return(0);
+
+ if (NULL != (descr = link->next)) {
+ font_push('I');
+ while (NULL != descr) {
+ print_word(descr->string);
+ descr = descr->next;
+ }
+ print_word(":");
+ font_pop();
+ }
+
+ font_push('B');
+ print_word(link->string);
+ font_pop();
+ return(0);
+}
+
+static int
+pre_li(DECL_ARGS)
+{
+
+ font_push('R');
return(1);
}
static int
pre_nm(DECL_ARGS)
{
+ char *name;
+ if (MDOC_BLOCK == n->type) {
+ outflags |= MMAN_Bk;
+ pre_syn(n);
+ }
if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
return(1);
- print_word(mm, "\\fB");
- mm->need_space = 0;
+ name = n->child ? n->child->string : meta->name;
+ if (NULL == name)
+ return(0);
+ if (MDOC_HEAD == n->type) {
+ if (NULL == n->parent->prev)
+ outflags |= MMAN_sp;
+ print_block(".HP", 0);
+ printf(" %zun", strlen(name) + 1);
+ outflags |= MMAN_nl;
+ }
+ font_push('B');
if (NULL == n->child)
- print_word(mm, m->name);
+ print_word(meta->name);
return(1);
}
@@ -555,17 +1440,33 @@ static void
post_nm(DECL_ARGS)
{
- if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
- return;
- mm->need_space = 0;
- print_word(mm, "\\fP");
+ switch (n->type) {
+ case (MDOC_BLOCK):
+ outflags &= ~MMAN_Bk;
+ break;
+ case (MDOC_HEAD):
+ /* FALLTHROUGH */
+ case (MDOC_ELEM):
+ font_pop();
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+pre_no(DECL_ARGS)
+{
+
+ outflags |= MMAN_spc_force;
+ return(1);
}
static int
pre_ns(DECL_ARGS)
{
- mm->need_space = 0;
+ outflags &= ~MMAN_spc;
return(0);
}
@@ -573,28 +1474,52 @@ static void
post_pf(DECL_ARGS)
{
- mm->need_space = 0;
+ outflags &= ~MMAN_spc;
}
static int
pre_pp(DECL_ARGS)
{
- mm->need_nl = 1;
- if (MDOC_It == n->parent->tok)
- print_word(mm, ".sp");
- else
- print_word(mm, ".PP");
- mm->need_nl = 1;
+ if (MDOC_It != n->parent->tok)
+ outflags |= MMAN_PP;
+ outflags |= MMAN_sp | MMAN_nl;
+ outflags &= ~MMAN_br;
+ return(0);
+}
+
+static int
+pre_rs(DECL_ARGS)
+{
+
+ if (SEC_SEE_ALSO == n->sec) {
+ outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
+ outflags &= ~MMAN_br;
+ }
return(1);
}
static int
+pre_sm(DECL_ARGS)
+{
+
+ assert(n->child && MDOC_TEXT == n->child->type);
+ if (0 == strcmp("on", n->child->string))
+ outflags |= MMAN_Sm | MMAN_spc;
+ else
+ outflags &= ~MMAN_Sm;
+ return(0);
+}
+
+static int
pre_sp(DECL_ARGS)
{
- mm->need_nl = 1;
- print_word(mm, ".sp");
+ if (MMAN_PP & outflags) {
+ outflags &= ~MMAN_PP;
+ print_line(".PP", 0);
+ } else
+ print_line(".sp", 0);
return(1);
}
@@ -602,7 +1527,43 @@ static void
post_sp(DECL_ARGS)
{
- mm->need_nl = 1;
+ outflags |= MMAN_nl;
+}
+
+static int
+pre_sy(DECL_ARGS)
+{
+
+ font_push('B');
+ return(1);
+}
+
+static int
+pre_vt(DECL_ARGS)
+{
+
+ if (MDOC_SYNPRETTY & n->flags) {
+ switch (n->type) {
+ case (MDOC_BLOCK):
+ pre_syn(n);
+ return(1);
+ case (MDOC_BODY):
+ break;
+ default:
+ return(0);
+ }
+ }
+ font_push('I');
+ return(1);
+}
+
+static void
+post_vt(DECL_ARGS)
+{
+
+ if (MDOC_SYNPRETTY & n->flags && MDOC_BODY != n->type)
+ return;
+ font_pop();
}
static int
@@ -612,14 +1573,14 @@ pre_xr(DECL_ARGS)
n = n->child;
if (NULL == n)
return(0);
- print_node(m, n, mm);
+ print_node(meta, n);
n = n->next;
if (NULL == n)
return(0);
- mm->need_space = 0;
- print_word(mm, "(");
- print_node(m, n, mm);
- print_word(mm, ")");
+ outflags &= ~MMAN_spc;
+ print_word("(");
+ print_node(meta, n);
+ print_word(")");
return(0);
}
@@ -627,11 +1588,11 @@ static int
pre_ux(DECL_ARGS)
{
- print_word(mm, manacts[n->tok].prefix);
+ print_word(manacts[n->tok].prefix);
if (NULL == n->child)
return(0);
- mm->need_space = 0;
- print_word(mm, "\\~");
- mm->need_space = 0;
+ outflags &= ~MMAN_spc;
+ print_word("\\ ");
+ outflags &= ~MMAN_spc;
return(1);
}
diff --git a/mdoc_term.c b/mdoc_term.c
index 533356644448..268fcae00665 100644
--- a/mdoc_term.c
+++ b/mdoc_term.c
@@ -1,7 +1,8 @@
-/* $Id: mdoc_term.c,v 1.238 2011/11/13 13:15:14 schwarze Exp $ */
+/* $Id: mdoc_term.c,v 1.258 2013/12/25 21:24:12 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -41,8 +42,8 @@ struct termpair {
#define DECL_ARGS struct termp *p, \
struct termpair *pair, \
- const struct mdoc_meta *m, \
- const struct mdoc_node *n
+ const struct mdoc_meta *meta, \
+ struct mdoc_node *n
struct termact {
int (*pre)(DECL_ARGS);
@@ -69,7 +70,7 @@ static void termp_an_post(DECL_ARGS);
static void termp_bd_post(DECL_ARGS);
static void termp_bk_post(DECL_ARGS);
static void termp_bl_post(DECL_ARGS);
-static void termp_d1_post(DECL_ARGS);
+static void termp_fd_post(DECL_ARGS);
static void termp_fo_post(DECL_ARGS);
static void termp_in_post(DECL_ARGS);
static void termp_it_post(DECL_ARGS);
@@ -100,7 +101,6 @@ static int termp_fl_pre(DECL_ARGS);
static int termp_fn_pre(DECL_ARGS);
static int termp_fo_pre(DECL_ARGS);
static int termp_ft_pre(DECL_ARGS);
-static int termp_igndelim_pre(DECL_ARGS);
static int termp_in_pre(DECL_ARGS);
static int termp_it_pre(DECL_ARGS);
static int termp_li_pre(DECL_ARGS);
@@ -129,8 +129,8 @@ static const struct termact termacts[MDOC_MAX] = {
{ termp_sh_pre, termp_sh_post }, /* Sh */
{ termp_ss_pre, termp_ss_post }, /* Ss */
{ termp_sp_pre, NULL }, /* Pp */
- { termp_d1_pre, termp_d1_post }, /* D1 */
- { termp_d1_pre, termp_d1_post }, /* Dl */
+ { termp_d1_pre, termp_bl_post }, /* D1 */
+ { termp_d1_pre, termp_bl_post }, /* Dl */
{ termp_bd_pre, termp_bd_post }, /* Bd */
{ NULL, NULL }, /* Ed */
{ termp_bl_pre, termp_bl_post }, /* Bl */
@@ -146,7 +146,7 @@ static const struct termact termacts[MDOC_MAX] = {
{ NULL, NULL }, /* Ev */
{ termp_ex_pre, NULL }, /* Ex */
{ termp_fa_pre, NULL }, /* Fa */
- { termp_fd_pre, NULL }, /* Fd */
+ { termp_fd_pre, termp_fd_post }, /* Fd */
{ termp_fl_pre, NULL }, /* Fl */
{ termp_fn_pre, NULL }, /* Fn */
{ termp_ft_pre, NULL }, /* Ft */
@@ -194,12 +194,12 @@ static const struct termact termacts[MDOC_MAX] = {
{ termp_quote_pre, termp_quote_post }, /* Eo */
{ termp_xx_pre, NULL }, /* Fx */
{ termp_bold_pre, NULL }, /* Ms */
- { termp_igndelim_pre, NULL }, /* No */
+ { NULL, NULL }, /* No */
{ termp_ns_pre, NULL }, /* Ns */
{ termp_xx_pre, NULL }, /* Nx */
{ termp_xx_pre, NULL }, /* Ox */
{ NULL, NULL }, /* Pc */
- { termp_igndelim_pre, termp_pf_post }, /* Pf */
+ { NULL, termp_pf_post }, /* Pf */
{ termp_quote_pre, termp_quote_post }, /* Po */
{ termp_quote_pre, termp_quote_post }, /* Pq */
{ NULL, NULL }, /* Qc */
@@ -242,7 +242,7 @@ static const struct termact termacts[MDOC_MAX] = {
{ NULL, termp____post }, /* %Q */
{ termp_sp_pre, NULL }, /* br */
{ termp_sp_pre, NULL }, /* sp */
- { termp_under_pre, termp____post }, /* %U */
+ { NULL, termp____post }, /* %U */
{ NULL, NULL }, /* Ta */
};
@@ -251,7 +251,7 @@ void
terminal_mdoc(void *arg, const struct mdoc *mdoc)
{
const struct mdoc_node *n;
- const struct mdoc_meta *m;
+ const struct mdoc_meta *meta;
struct termp *p;
p = (struct termp *)arg;
@@ -267,12 +267,12 @@ terminal_mdoc(void *arg, const struct mdoc *mdoc)
p->symtab = mchars_alloc();
n = mdoc_node(mdoc);
- m = mdoc_meta(mdoc);
+ meta = mdoc_meta(mdoc);
- term_begin(p, print_mdoc_head, print_mdoc_foot, m);
+ term_begin(p, print_mdoc_head, print_mdoc_foot, meta);
if (n->child)
- print_mdoc_nodelist(p, NULL, m, n->child);
+ print_mdoc_nodelist(p, NULL, meta, n->child);
term_end(p);
}
@@ -282,9 +282,9 @@ static void
print_mdoc_nodelist(DECL_ARGS)
{
- print_mdoc_node(p, pair, m, n);
+ print_mdoc_node(p, pair, meta, n);
if (n->next)
- print_mdoc_nodelist(p, pair, m, n->next);
+ print_mdoc_nodelist(p, pair, meta, n->next);
}
@@ -293,14 +293,13 @@ static void
print_mdoc_node(DECL_ARGS)
{
int chld;
- const void *font;
struct termpair npair;
size_t offset, rmargin;
chld = 1;
offset = p->offset;
rmargin = p->rmargin;
- font = term_fontq(p);
+ n->prev_font = term_fontq(p);
memset(&npair, 0, sizeof(struct termpair));
npair.ppair = pair;
@@ -308,34 +307,17 @@ print_mdoc_node(DECL_ARGS)
/*
* Keeps only work until the end of a line. If a keep was
* invoked in a prior line, revert it to PREKEEP.
- *
- * Also let SYNPRETTY sections behave as if they were wrapped
- * in a `Bk' block.
*/
- if (TERMP_KEEP & p->flags || MDOC_SYNPRETTY & n->flags) {
- if (n->prev && n->prev->line != n->line) {
+ if (TERMP_KEEP & p->flags) {
+ if (n->prev ? (n->prev->lastline != n->line) :
+ (n->parent && n->parent->line != n->line)) {
p->flags &= ~TERMP_KEEP;
p->flags |= TERMP_PREKEEP;
- } else if (NULL == n->prev) {
- if (n->parent && n->parent->line != n->line) {
- p->flags &= ~TERMP_KEEP;
- p->flags |= TERMP_PREKEEP;
- }
}
}
/*
- * Since SYNPRETTY sections aren't "turned off" with `Ek',
- * we have to intuit whether we should disable formatting.
- */
-
- if ( ! (MDOC_SYNPRETTY & n->flags) &&
- ((n->prev && MDOC_SYNPRETTY & n->prev->flags) ||
- (n->parent && MDOC_SYNPRETTY & n->parent->flags)))
- p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
-
- /*
* After the keep flags have been set up, we may now
* produce output. Note that some pre-handlers do so.
*/
@@ -359,14 +341,15 @@ print_mdoc_node(DECL_ARGS)
default:
if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
chld = (*termacts[n->tok].pre)
- (p, &npair, m, n);
+ (p, &npair, meta, n);
break;
}
if (chld && n->child)
- print_mdoc_nodelist(p, &npair, m, n->child);
+ print_mdoc_nodelist(p, &npair, meta, n->child);
- term_fontpopq(p, font);
+ term_fontpopq(p,
+ (ENDBODY_NOT == n->end ? n : n->pending)->prev_font);
switch (n->type) {
case (MDOC_TEXT):
@@ -378,7 +361,7 @@ print_mdoc_node(DECL_ARGS)
default:
if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags)
break;
- (void)(*termacts[n->tok].post)(p, &npair, m, n);
+ (void)(*termacts[n->tok].post)(p, &npair, meta, n);
/*
* Explicit end tokens not only call the post
@@ -409,9 +392,9 @@ print_mdoc_node(DECL_ARGS)
static void
print_mdoc_foot(struct termp *p, const void *arg)
{
- const struct mdoc_meta *m;
+ const struct mdoc_meta *meta;
- m = (const struct mdoc_meta *)arg;
+ meta = (const struct mdoc_meta *)arg;
term_fontrepl(p, TERMFONT_NONE);
@@ -427,25 +410,27 @@ print_mdoc_foot(struct termp *p, const void *arg)
p->offset = 0;
p->rmargin = (p->maxrmargin -
- term_strlen(p, m->date) + term_len(p, 1)) / 2;
+ term_strlen(p, meta->date) + term_len(p, 1)) / 2;
+ p->trailspace = 1;
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
- term_word(p, m->os);
+ term_word(p, meta->os);
term_flushln(p);
p->offset = p->rmargin;
- p->rmargin = p->maxrmargin - term_strlen(p, m->os);
+ p->rmargin = p->maxrmargin - term_strlen(p, meta->os);
p->flags |= TERMP_NOSPACE;
- term_word(p, m->date);
+ term_word(p, meta->date);
term_flushln(p);
p->offset = p->rmargin;
p->rmargin = p->maxrmargin;
+ p->trailspace = 0;
p->flags &= ~TERMP_NOBREAK;
p->flags |= TERMP_NOSPACE;
- term_word(p, m->os);
+ term_word(p, meta->os);
term_flushln(p);
p->offset = 0;
@@ -459,9 +444,9 @@ print_mdoc_head(struct termp *p, const void *arg)
{
char buf[BUFSIZ], title[BUFSIZ];
size_t buflen, titlen;
- const struct mdoc_meta *m;
+ const struct mdoc_meta *meta;
- m = (const struct mdoc_meta *)arg;
+ meta = (const struct mdoc_meta *)arg;
/*
* The header is strange. It has three components, which are
@@ -479,20 +464,21 @@ print_mdoc_head(struct termp *p, const void *arg)
p->offset = 0;
p->rmargin = p->maxrmargin;
- assert(m->vol);
- strlcpy(buf, m->vol, BUFSIZ);
+ assert(meta->vol);
+ strlcpy(buf, meta->vol, BUFSIZ);
buflen = term_strlen(p, buf);
- if (m->arch) {
+ if (meta->arch) {
strlcat(buf, " (", BUFSIZ);
- strlcat(buf, m->arch, BUFSIZ);
+ strlcat(buf, meta->arch, BUFSIZ);
strlcat(buf, ")", BUFSIZ);
}
- snprintf(title, BUFSIZ, "%s(%s)", m->title, m->msec);
+ snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec);
titlen = term_strlen(p, title);
p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
+ p->trailspace = 1;
p->offset = 0;
p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
(p->maxrmargin -
@@ -511,6 +497,7 @@ print_mdoc_head(struct termp *p, const void *arg)
term_flushln(p);
p->flags &= ~TERMP_NOBREAK;
+ p->trailspace = 0;
if (p->rmargin + titlen <= p->maxrmargin) {
p->flags |= TERMP_NOSPACE;
p->offset = p->rmargin;
@@ -727,12 +714,10 @@ termp_it_pre(DECL_ARGS)
case (LIST_dash):
/* FALLTHROUGH */
case (LIST_hyphen):
- if (width < term_len(p, 4))
- width = term_len(p, 4);
- break;
+ /* FALLTHROUGH */
case (LIST_enum):
- if (width < term_len(p, 5))
- width = term_len(p, 5);
+ if (width < term_len(p, 2))
+ width = term_len(p, 2);
break;
case (LIST_hang):
if (0 == width)
@@ -787,20 +772,26 @@ termp_it_pre(DECL_ARGS)
*/
switch (type) {
+ case (LIST_enum):
+ /*
+ * Weird special case.
+ * Very narrow enum lists actually hang.
+ */
+ if (width == term_len(p, 2))
+ p->flags |= TERMP_HANG;
+ /* FALLTHROUGH */
case (LIST_bullet):
/* FALLTHROUGH */
case (LIST_dash):
/* FALLTHROUGH */
- case (LIST_enum):
- /* FALLTHROUGH */
case (LIST_hyphen):
- if (MDOC_HEAD == n->type)
- p->flags |= TERMP_NOBREAK;
+ if (MDOC_HEAD != n->type)
+ break;
+ p->flags |= TERMP_NOBREAK;
+ p->trailspace = 1;
break;
case (LIST_hang):
- if (MDOC_HEAD == n->type)
- p->flags |= TERMP_NOBREAK;
- else
+ if (MDOC_HEAD != n->type)
break;
/*
@@ -812,16 +803,18 @@ termp_it_pre(DECL_ARGS)
if (n->next->child &&
(MDOC_Bl == n->next->child->tok ||
MDOC_Bd == n->next->child->tok))
- p->flags &= ~TERMP_NOBREAK;
- else
- p->flags |= TERMP_HANG;
+ break;
+
+ p->flags |= TERMP_NOBREAK | TERMP_HANG;
+ p->trailspace = 1;
break;
case (LIST_tag):
- if (MDOC_HEAD == n->type)
- p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE;
-
if (MDOC_HEAD != n->type)
break;
+
+ p->flags |= TERMP_NOBREAK;
+ p->trailspace = 2;
+
if (NULL == n->next || NULL == n->next->child)
p->flags |= TERMP_DANGLE;
break;
@@ -829,15 +822,20 @@ termp_it_pre(DECL_ARGS)
if (MDOC_HEAD == n->type)
break;
- if (NULL == n->next)
+ if (NULL == n->next) {
p->flags &= ~TERMP_NOBREAK;
- else
+ p->trailspace = 0;
+ } else {
p->flags |= TERMP_NOBREAK;
+ p->trailspace = 1;
+ }
break;
case (LIST_diag):
- if (MDOC_HEAD == n->type)
- p->flags |= TERMP_NOBREAK;
+ if (MDOC_HEAD != n->type)
+ break;
+ p->flags |= TERMP_NOBREAK;
+ p->trailspace = 1;
break;
default:
break;
@@ -989,8 +987,8 @@ termp_it_post(DECL_ARGS)
p->flags &= ~TERMP_DANGLE;
p->flags &= ~TERMP_NOBREAK;
- p->flags &= ~TERMP_TWOSPACE;
p->flags &= ~TERMP_HANG;
+ p->trailspace = 0;
}
@@ -999,22 +997,25 @@ static int
termp_nm_pre(DECL_ARGS)
{
- if (MDOC_BLOCK == n->type)
+ if (MDOC_BLOCK == n->type) {
+ p->flags |= TERMP_PREKEEP;
return(1);
+ }
if (MDOC_BODY == n->type) {
if (NULL == n->child)
return(0);
p->flags |= TERMP_NOSPACE;
p->offset += term_len(p, 1) +
- (NULL == n->prev->child ? term_strlen(p, m->name) :
+ (NULL == n->prev->child ?
+ term_strlen(p, meta->name) :
MDOC_TEXT == n->prev->child->type ?
- term_strlen(p, n->prev->child->string) :
+ term_strlen(p, n->prev->child->string) :
term_len(p, 5));
return(1);
}
- if (NULL == n->child && NULL == m->name)
+ if (NULL == n->child && NULL == meta->name)
return(0);
if (MDOC_HEAD == n->type)
@@ -1022,9 +1023,10 @@ termp_nm_pre(DECL_ARGS)
if (MDOC_HEAD == n->type && n->next->child) {
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
+ p->trailspace = 1;
p->rmargin = p->offset + term_len(p, 1);
if (NULL == n->child) {
- p->rmargin += term_strlen(p, m->name);
+ p->rmargin += term_strlen(p, meta->name);
} else if (MDOC_TEXT == n->child->type) {
p->rmargin += term_strlen(p, n->child->string);
if (n->child->next)
@@ -1037,7 +1039,7 @@ termp_nm_pre(DECL_ARGS)
term_fontpush(p, TERMFONT_BOLD);
if (NULL == n->child)
- term_word(p, m->name);
+ term_word(p, meta->name);
return(1);
}
@@ -1047,9 +1049,12 @@ static void
termp_nm_post(DECL_ARGS)
{
- if (MDOC_HEAD == n->type && n->next->child) {
+ if (MDOC_BLOCK == n->type) {
+ p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
+ } else if (MDOC_HEAD == n->type && n->next->child) {
term_flushln(p);
p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
+ p->trailspace = 0;
} else if (MDOC_BODY == n->type && n->child)
term_flushln(p);
}
@@ -1375,14 +1380,14 @@ termp_vt_pre(DECL_ARGS)
if (MDOC_ELEM == n->type) {
synopsis_pre(p, n);
- return(termp_under_pre(p, pair, m, n));
+ return(termp_under_pre(p, pair, meta, n));
} else if (MDOC_BLOCK == n->type) {
synopsis_pre(p, n);
return(1);
} else if (MDOC_HEAD == n->type)
return(0);
- return(termp_under_pre(p, pair, m, n));
+ return(termp_under_pre(p, pair, meta, n));
}
@@ -1402,7 +1407,16 @@ termp_fd_pre(DECL_ARGS)
{
synopsis_pre(p, n);
- return(termp_bold_pre(p, pair, m, n));
+ return(termp_bold_pre(p, pair, meta, n));
+}
+
+
+/* ARGSUSED */
+static void
+termp_fd_post(DECL_ARGS)
+{
+
+ term_newln(p);
}
@@ -1425,6 +1439,8 @@ termp_sh_pre(DECL_ARGS)
break;
case (MDOC_BODY):
p->offset = term_len(p, p->defindent);
+ if (SEC_AUTHORS == n->sec)
+ p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT);
break;
default:
break;
@@ -1498,17 +1514,6 @@ termp_d1_pre(DECL_ARGS)
/* ARGSUSED */
-static void
-termp_d1_post(DECL_ARGS)
-{
-
- if (MDOC_BLOCK != n->type)
- return;
- term_newln(p);
-}
-
-
-/* ARGSUSED */
static int
termp_ft_pre(DECL_ARGS)
{
@@ -1524,6 +1529,7 @@ termp_ft_pre(DECL_ARGS)
static int
termp_fn_pre(DECL_ARGS)
{
+ size_t rmargin = 0;
int pretty;
pretty = MDOC_SYNPRETTY & n->flags;
@@ -1533,11 +1539,24 @@ termp_fn_pre(DECL_ARGS)
if (NULL == (n = n->child))
return(0);
+ if (pretty) {
+ rmargin = p->rmargin;
+ p->rmargin = p->offset + term_len(p, 4);
+ p->flags |= TERMP_NOBREAK | TERMP_HANG;
+ }
+
assert(MDOC_TEXT == n->type);
term_fontpush(p, TERMFONT_BOLD);
term_word(p, n->string);
term_fontpop(p);
+ if (pretty) {
+ term_flushln(p);
+ p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
+ p->offset = p->rmargin;
+ p->rmargin = rmargin;
+ }
+
p->flags |= TERMP_NOSPACE;
term_word(p, "(");
p->flags |= TERMP_NOSPACE;
@@ -1545,6 +1564,8 @@ termp_fn_pre(DECL_ARGS)
for (n = n->next; n; n = n->next) {
assert(MDOC_TEXT == n->type);
term_fontpush(p, TERMFONT_UNDER);
+ if (pretty)
+ p->flags |= TERMP_NBRWORD;
term_word(p, n->string);
term_fontpop(p);
@@ -1560,6 +1581,7 @@ termp_fn_pre(DECL_ARGS)
if (pretty) {
p->flags |= TERMP_NOSPACE;
term_word(p, ";");
+ term_flushln(p);
}
return(0);
@@ -1579,20 +1601,16 @@ termp_fa_pre(DECL_ARGS)
for (nn = n->child; nn; nn = nn->next) {
term_fontpush(p, TERMFONT_UNDER);
+ p->flags |= TERMP_NBRWORD;
term_word(p, nn->string);
term_fontpop(p);
- if (nn->next) {
+ if (nn->next || (n->next && n->next->tok == MDOC_Fa)) {
p->flags |= TERMP_NOSPACE;
term_word(p, ",");
}
}
- if (n->child && n->next && n->next->tok == MDOC_Fa) {
- p->flags |= TERMP_NOSPACE;
- term_word(p, ",");
- }
-
return(0);
}
@@ -1602,7 +1620,7 @@ static int
termp_bd_pre(DECL_ARGS)
{
size_t tabwidth, rm, rmax;
- const struct mdoc_node *nn;
+ struct mdoc_node *nn;
if (MDOC_BLOCK == n->type) {
print_bvspace(p, n, n);
@@ -1634,7 +1652,7 @@ termp_bd_pre(DECL_ARGS)
p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
for (nn = n->child; nn; nn = nn->next) {
- print_mdoc_node(p, pair, m, nn);
+ 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
@@ -1751,7 +1769,8 @@ termp_xx_pre(DECL_ARGS)
pp = "UNIX";
break;
default:
- break;
+ abort();
+ /* NOTREACHED */
}
term_word(p, pp);
@@ -1766,16 +1785,6 @@ termp_xx_pre(DECL_ARGS)
/* ARGSUSED */
-static int
-termp_igndelim_pre(DECL_ARGS)
-{
-
- p->flags |= TERMP_IGNDELIM;
- return(1);
-}
-
-
-/* ARGSUSED */
static void
termp_pf_post(DECL_ARGS)
{
@@ -1923,7 +1932,7 @@ termp_quote_pre(DECL_ARGS)
case (MDOC_Do):
/* FALLTHROUGH */
case (MDOC_Dq):
- term_word(p, "``");
+ term_word(p, "\\(lq");
break;
case (MDOC_Eo):
break;
@@ -1944,7 +1953,7 @@ termp_quote_pre(DECL_ARGS)
case (MDOC_So):
/* FALLTHROUGH */
case (MDOC_Sq):
- term_word(p, "`");
+ term_word(p, "\\(oq");
break;
default:
abort();
@@ -1989,7 +1998,7 @@ termp_quote_post(DECL_ARGS)
case (MDOC_Do):
/* FALLTHROUGH */
case (MDOC_Dq):
- term_word(p, "''");
+ term_word(p, "\\(rq");
break;
case (MDOC_Eo):
break;
@@ -2010,7 +2019,7 @@ termp_quote_post(DECL_ARGS)
case (MDOC_So):
/* FALLTHROUGH */
case (MDOC_Sq):
- term_word(p, "'");
+ term_word(p, "\\(cq");
break;
default:
abort();
@@ -2023,16 +2032,31 @@ termp_quote_post(DECL_ARGS)
static int
termp_fo_pre(DECL_ARGS)
{
+ size_t rmargin = 0;
+ int pretty;
+
+ pretty = MDOC_SYNPRETTY & n->flags;
if (MDOC_BLOCK == n->type) {
synopsis_pre(p, n);
return(1);
} else if (MDOC_BODY == n->type) {
+ if (pretty) {
+ rmargin = p->rmargin;
+ p->rmargin = p->offset + term_len(p, 4);
+ p->flags |= TERMP_NOBREAK | TERMP_HANG;
+ }
p->flags |= TERMP_NOSPACE;
term_word(p, "(");
p->flags |= TERMP_NOSPACE;
+ if (pretty) {
+ term_flushln(p);
+ p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
+ p->offset = p->rmargin;
+ p->rmargin = rmargin;
+ }
return(1);
- }
+ }
if (NULL == n->child)
return(0);
@@ -2060,6 +2084,7 @@ termp_fo_post(DECL_ARGS)
if (MDOC_SYNPRETTY & n->flags) {
p->flags |= TERMP_NOSPACE;
term_word(p, ";");
+ term_flushln(p);
}
}
@@ -2071,7 +2096,7 @@ termp_bf_pre(DECL_ARGS)
if (MDOC_HEAD == n->type)
return(0);
- else if (MDOC_BLOCK != n->type)
+ else if (MDOC_BODY != n->type)
return(1);
if (FONT_Em == n->norm->Bf.font)
@@ -2157,25 +2182,24 @@ termp_li_pre(DECL_ARGS)
static int
termp_lk_pre(DECL_ARGS)
{
- const struct mdoc_node *nn, *sv;
-
- term_fontpush(p, TERMFONT_UNDER);
+ const struct mdoc_node *link, *descr;
- nn = sv = n->child;
-
- if (NULL == nn || NULL == nn->next)
- return(1);
-
- for (nn = nn->next; nn; nn = nn->next)
- term_word(p, nn->string);
-
- term_fontpop(p);
+ if (NULL == (link = n->child))
+ return(0);
- p->flags |= TERMP_NOSPACE;
- term_word(p, ":");
+ if (NULL != (descr = link->next)) {
+ term_fontpush(p, TERMFONT_UNDER);
+ while (NULL != descr) {
+ term_word(p, descr->string);
+ descr = descr->next;
+ }
+ p->flags |= TERMP_NOSPACE;
+ term_word(p, ":");
+ term_fontpop(p);
+ }
term_fontpush(p, TERMFONT_BOLD);
- term_word(p, sv->string);
+ term_word(p, link->string);
term_fontpop(p);
return(0);
@@ -2225,9 +2249,9 @@ termp__t_post(DECL_ARGS)
*/
if (n->parent && MDOC_Rs == n->parent->tok &&
n->parent->norm->Rs.quote_T)
- termp_quote_post(p, pair, m, n);
+ termp_quote_post(p, pair, meta, n);
- termp____post(p, pair, m, n);
+ termp____post(p, pair, meta, n);
}
/* ARGSUSED */
@@ -2241,7 +2265,7 @@ termp__t_pre(DECL_ARGS)
*/
if (n->parent && MDOC_Rs == n->parent->tok &&
n->parent->norm->Rs.quote_T)
- return(termp_quote_pre(p, pair, m, n));
+ return(termp_quote_pre(p, pair, meta, n));
term_fontpush(p, TERMFONT_UNDER);
return(1);
diff --git a/mdoc_validate.c b/mdoc_validate.c
index 060ccdadec38..4cfd620448f1 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -1,7 +1,7 @@
-/* $Id: mdoc_validate.c,v 1.182 2012/03/23 05:50:25 kristaps Exp $ */
+/* $Id: mdoc_validate.c,v 1.198 2013/12/15 21:23:52 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 2011, 2012, 2013 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,7 +19,7 @@
#include "config.h"
#endif
-#ifndef OSNAME
+#ifndef OSNAME
#include <sys/utsname.h>
#endif
@@ -97,17 +97,19 @@ static int post_bl_block_width(POST_ARGS);
static int post_bl_block_tag(POST_ARGS);
static int post_bl_head(POST_ARGS);
static int post_bx(POST_ARGS);
+static int post_defaults(POST_ARGS);
static int post_dd(POST_ARGS);
static int post_dt(POST_ARGS);
-static int post_defaults(POST_ARGS);
-static int post_literal(POST_ARGS);
static int post_eoln(POST_ARGS);
+static int post_hyph(POST_ARGS);
+static int post_ignpar(POST_ARGS);
static int post_it(POST_ARGS);
static int post_lb(POST_ARGS);
+static int post_literal(POST_ARGS);
static int post_nm(POST_ARGS);
static int post_ns(POST_ARGS);
static int post_os(POST_ARGS);
-static int post_ignpar(POST_ARGS);
+static int post_par(POST_ARGS);
static int post_prol(POST_ARGS);
static int post_root(POST_ARGS);
static int post_rs(POST_ARGS);
@@ -141,27 +143,30 @@ static v_post posts_bx[] = { post_bx, NULL };
static v_post posts_bool[] = { ebool, NULL };
static v_post posts_eoln[] = { post_eoln, NULL };
static v_post posts_defaults[] = { post_defaults, NULL };
+static v_post posts_d1[] = { bwarn_ge1, post_hyph, NULL };
static v_post posts_dd[] = { post_dd, post_prol, NULL };
static v_post posts_dl[] = { post_literal, bwarn_ge1, NULL };
static v_post posts_dt[] = { post_dt, post_prol, NULL };
static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
+static v_post posts_hyph[] = { post_hyph, NULL };
+static v_post posts_hyphtext[] = { ewarn_ge1, post_hyph, NULL };
static v_post posts_it[] = { post_it, NULL };
static v_post posts_lb[] = { post_lb, NULL };
-static v_post posts_nd[] = { berr_ge1, NULL };
+static v_post posts_nd[] = { berr_ge1, post_hyph, NULL };
static v_post posts_nm[] = { post_nm, NULL };
static v_post posts_notext[] = { ewarn_eq0, NULL };
static v_post posts_ns[] = { post_ns, NULL };
static v_post posts_os[] = { post_os, post_prol, NULL };
+static v_post posts_pp[] = { post_par, ewarn_eq0, NULL };
static v_post posts_rs[] = { post_rs, NULL };
-static v_post posts_sh[] = { post_ignpar, hwarn_ge1, post_sh, NULL };
-static v_post posts_sp[] = { ewarn_le1, NULL };
-static v_post posts_ss[] = { post_ignpar, hwarn_ge1, NULL };
+static v_post posts_sh[] = { post_ignpar,hwarn_ge1,post_sh,post_hyph,NULL };
+static v_post posts_sp[] = { post_par, ewarn_le1, NULL };
+static v_post posts_ss[] = { post_ignpar, hwarn_ge1, post_hyph, NULL };
static v_post posts_st[] = { post_st, NULL };
static v_post posts_std[] = { post_std, NULL };
static v_post posts_text[] = { ewarn_ge1, NULL };
static v_post posts_text1[] = { ewarn_eq1, NULL };
static v_post posts_vt[] = { post_vt, NULL };
-static v_post posts_wline[] = { bwarn_ge1, NULL };
static v_pre pres_an[] = { pre_an, NULL };
static v_pre pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL };
static v_pre pres_bl[] = { pre_bl, pre_par, NULL };
@@ -169,8 +174,6 @@ static v_pre pres_d1[] = { pre_display, NULL };
static v_pre pres_dl[] = { pre_literal, pre_display, NULL };
static v_pre pres_dd[] = { pre_dd, NULL };
static v_pre pres_dt[] = { pre_dt, NULL };
-static v_pre pres_er[] = { NULL, NULL };
-static v_pre pres_fd[] = { NULL, NULL };
static v_pre pres_it[] = { pre_it, pre_par, NULL };
static v_pre pres_os[] = { pre_os, NULL };
static v_pre pres_pp[] = { pre_par, NULL };
@@ -185,8 +188,8 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
{ pres_os, posts_os }, /* Os */
{ pres_sh, posts_sh }, /* Sh */
{ pres_ss, posts_ss }, /* Ss */
- { pres_pp, posts_notext }, /* Pp */
- { pres_d1, posts_wline }, /* D1 */
+ { pres_pp, posts_pp }, /* Pp */
+ { pres_d1, posts_d1 }, /* D1 */
{ pres_dl, posts_dl }, /* Dl */
{ pres_bd, posts_bd }, /* Bd */
{ NULL, NULL }, /* Ed */
@@ -199,11 +202,11 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Cd */
{ NULL, NULL }, /* Cm */
{ NULL, NULL }, /* Dv */
- { pres_er, NULL }, /* Er */
+ { NULL, NULL }, /* Er */
{ NULL, NULL }, /* Ev */
{ pres_std, posts_std }, /* Ex */
{ NULL, NULL }, /* Fa */
- { pres_fd, posts_text }, /* Fd */
+ { NULL, posts_text }, /* Fd */
{ NULL, NULL }, /* Fl */
{ NULL, NULL }, /* Fn */
{ NULL, NULL }, /* Ft */
@@ -221,15 +224,15 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, posts_vt }, /* Vt */
{ NULL, posts_text }, /* Xr */
{ NULL, posts_text }, /* %A */
- { NULL, posts_text }, /* %B */ /* FIXME: can be used outside Rs/Re. */
+ { NULL, posts_hyphtext }, /* %B */ /* FIXME: can be used outside Rs/Re. */
{ NULL, posts_text }, /* %D */
{ NULL, posts_text }, /* %I */
{ NULL, posts_text }, /* %J */
- { NULL, posts_text }, /* %N */
- { NULL, posts_text }, /* %O */
+ { NULL, posts_hyphtext }, /* %N */
+ { NULL, posts_hyphtext }, /* %O */
{ NULL, posts_text }, /* %P */
- { NULL, posts_text }, /* %R */
- { NULL, posts_text }, /* %T */ /* FIXME: can be used outside Rs/Re. */
+ { NULL, posts_hyphtext }, /* %R */
+ { NULL, posts_hyphtext }, /* %T */ /* FIXME: can be used outside Rs/Re. */
{ NULL, posts_text }, /* %V */
{ NULL, NULL }, /* Ac */
{ NULL, NULL }, /* Ao */
@@ -269,7 +272,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* So */
{ NULL, NULL }, /* Sq */
{ NULL, posts_bool }, /* Sm */
- { NULL, NULL }, /* Sx */
+ { NULL, posts_hyph }, /* Sx */
{ NULL, NULL }, /* Sy */
{ NULL, NULL }, /* Tn */
{ NULL, NULL }, /* Ux */
@@ -286,7 +289,7 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Fr */
{ NULL, posts_eoln }, /* Ud */
{ NULL, posts_lb }, /* Lb */
- { NULL, posts_notext }, /* Lp */
+ { pres_pp, posts_pp }, /* Lp */
{ NULL, NULL }, /* Lk */
{ NULL, posts_defaults }, /* Mt */
{ NULL, NULL }, /* Brq */
@@ -297,8 +300,8 @@ static const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* En */
{ NULL, NULL }, /* Dx */
{ NULL, posts_text }, /* %Q */
- { NULL, posts_notext }, /* br */
- { pres_pp, posts_sp }, /* sp */
+ { NULL, posts_pp }, /* br */
+ { NULL, posts_sp }, /* sp */
{ NULL, posts_text1 }, /* %U */
{ NULL, NULL }, /* Ta */
};
@@ -314,12 +317,12 @@ static const enum mdoct rsord[RSORD_MAX] = {
MDOC__R,
MDOC__N,
MDOC__V,
+ MDOC__U,
MDOC__P,
MDOC__Q,
- MDOC__D,
- MDOC__O,
MDOC__C,
- MDOC__U
+ MDOC__D,
+ MDOC__O
};
static const char * const secnames[SEC__MAX] = {
@@ -414,29 +417,29 @@ mdoc_valid_post(struct mdoc *mdoc)
}
static int
-check_count(struct mdoc *m, enum mdoc_type type,
+check_count(struct mdoc *mdoc, enum mdoc_type type,
enum check_lvl lvl, enum check_ineq ineq, int val)
{
const char *p;
enum mandocerr t;
- if (m->last->type != type)
+ if (mdoc->last->type != type)
return(1);
switch (ineq) {
case (CHECK_LT):
p = "less than ";
- if (m->last->nchild < val)
+ if (mdoc->last->nchild < val)
return(1);
break;
case (CHECK_GT):
p = "more than ";
- if (m->last->nchild > val)
+ if (mdoc->last->nchild > val)
return(1);
break;
case (CHECK_EQ):
p = "";
- if (val == m->last->nchild)
+ if (val == mdoc->last->nchild)
return(1);
break;
default:
@@ -445,9 +448,9 @@ check_count(struct mdoc *m, enum mdoc_type type,
}
t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;
- mandoc_vmsg(t, m->parse, m->last->line, m->last->pos,
+ mandoc_vmsg(t, mdoc->parse, mdoc->last->line, mdoc->last->pos,
"want %s%d children (have %d)",
- p, val, m->last->nchild);
+ p, val, mdoc->last->nchild);
return(1);
}
@@ -513,7 +516,7 @@ hwarn_le1(POST_ARGS)
}
static void
-check_args(struct mdoc *m, struct mdoc_node *n)
+check_args(struct mdoc *mdoc, struct mdoc_node *n)
{
int i;
@@ -522,34 +525,34 @@ check_args(struct mdoc *m, struct mdoc_node *n)
assert(n->args->argc);
for (i = 0; i < (int)n->args->argc; i++)
- check_argv(m, n, &n->args->argv[i]);
+ check_argv(mdoc, n, &n->args->argv[i]);
}
static void
-check_argv(struct mdoc *m, struct mdoc_node *n, struct mdoc_argv *v)
+check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v)
{
int i;
for (i = 0; i < (int)v->sz; i++)
- check_text(m, v->line, v->pos, v->value[i]);
+ check_text(mdoc, v->line, v->pos, v->value[i]);
/* FIXME: move to post_std(). */
if (MDOC_Std == v->arg)
- if ( ! (v->sz || m->meta.name))
- mdoc_nmsg(m, n, MANDOCERR_NONAME);
+ if ( ! (v->sz || mdoc->meta.name))
+ mdoc_nmsg(mdoc, n, MANDOCERR_NONAME);
}
static void
-check_text(struct mdoc *m, int ln, int pos, char *p)
+check_text(struct mdoc *mdoc, int ln, int pos, char *p)
{
char *cp;
- if (MDOC_LITERAL & m->flags)
+ if (MDOC_LITERAL & mdoc->flags)
return;
for (cp = p; NULL != (p = strchr(p, '\t')); p++)
- mdoc_pmsg(m, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
+ mdoc_pmsg(mdoc, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
}
static int
@@ -733,14 +736,14 @@ pre_bl(PRE_ARGS)
/*
* Validate the width field. Some list types don't need width
* types and should be warned about them. Others should have it
- * and must also be warned.
+ * and must also be warned. Yet others have a default and need
+ * no warning.
*/
switch (n->norm->Bl.type) {
case (LIST_tag):
- if (n->norm->Bl.width)
- break;
- mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG);
+ if (NULL == n->norm->Bl.width)
+ mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG);
break;
case (LIST_column):
/* FALLTHROUGH */
@@ -754,6 +757,18 @@ pre_bl(PRE_ARGS)
if (n->norm->Bl.width)
mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV);
break;
+ case (LIST_bullet):
+ /* FALLTHROUGH */
+ case (LIST_dash):
+ /* FALLTHROUGH */
+ case (LIST_hyphen):
+ if (NULL == n->norm->Bl.width)
+ n->norm->Bl.width = "2n";
+ break;
+ case (LIST_enum):
+ if (NULL == n->norm->Bl.width)
+ n->norm->Bl.width = "3n";
+ break;
default:
break;
}
@@ -874,8 +889,6 @@ pre_sh(PRE_ARGS)
if (MDOC_BLOCK != n->type)
return(1);
-
- roff_regunset(mdoc->roff, REG_nS);
return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
}
@@ -1111,24 +1124,29 @@ post_nm(POST_ARGS)
char buf[BUFSIZ];
int c;
- /* If no child specified, make sure we have the meta name. */
-
- if (NULL == mdoc->last->child && NULL == mdoc->meta.name) {
- mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
- return(1);
- } else if (mdoc->meta.name)
+ if (NULL != mdoc->meta.name)
return(1);
- /* If no meta name, set it from the child. */
+ /* Try to use our children for setting the meta name. */
- buf[0] = '\0';
- if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) {
+ if (NULL != mdoc->last->child) {
+ buf[0] = '\0';
+ c = concat(buf, mdoc->last->child, BUFSIZ);
+ } else
+ c = 0;
+
+ switch (c) {
+ case (-1):
mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM);
return(0);
+ case (0):
+ mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
+ mdoc->meta.name = mandoc_strdup("UNKNOWN");
+ break;
+ default:
+ mdoc->meta.name = mandoc_strdup(buf);
+ break;
}
-
- assert(c);
- mdoc->meta.name = mandoc_strdup(buf);
return(1);
}
@@ -1334,7 +1352,7 @@ post_it(POST_ARGS)
static int
post_bl_block(POST_ARGS)
{
- struct mdoc_node *n;
+ struct mdoc_node *n, *ni, *nc;
/*
* These are fairly complicated, so we've broken them into two
@@ -1350,13 +1368,42 @@ post_bl_block(POST_ARGS)
NULL == n->norm->Bl.width) {
if ( ! post_bl_block_tag(mdoc))
return(0);
+ assert(n->norm->Bl.width);
} else if (NULL != n->norm->Bl.width) {
if ( ! post_bl_block_width(mdoc))
return(0);
- } else
- return(1);
+ assert(n->norm->Bl.width);
+ }
- assert(n->norm->Bl.width);
+ for (ni = n->body->child; ni; ni = ni->next) {
+ if (NULL == ni->body)
+ continue;
+ nc = ni->body->last;
+ while (NULL != nc) {
+ switch (nc->tok) {
+ case (MDOC_Pp):
+ /* FALLTHROUGH */
+ case (MDOC_Lp):
+ /* FALLTHROUGH */
+ case (MDOC_br):
+ break;
+ default:
+ nc = NULL;
+ continue;
+ }
+ if (NULL == ni->next) {
+ mdoc_nmsg(mdoc, nc, MANDOCERR_MOVEPAR);
+ if ( ! mdoc_node_relink(mdoc, nc))
+ return(0);
+ } else if (0 == n->norm->Bl.comp &&
+ LIST_column != n->norm->Bl.type) {
+ mdoc_nmsg(mdoc, nc, MANDOCERR_IGNPAR);
+ mdoc_node_delete(mdoc, nc);
+ } else
+ break;
+ nc = ni->body->last;
+ }
+ }
return(1);
}
@@ -1544,32 +1591,71 @@ post_bl_head(POST_ARGS)
static int
post_bl(POST_ARGS)
{
- struct mdoc_node *n;
+ struct mdoc_node *nparent, *nprev; /* of the Bl block */
+ struct mdoc_node *nblock, *nbody; /* of the Bl */
+ struct mdoc_node *nchild, *nnext; /* of the Bl body */
- if (MDOC_HEAD == mdoc->last->type)
- return(post_bl_head(mdoc));
- if (MDOC_BLOCK == mdoc->last->type)
+ nbody = mdoc->last;
+ switch (nbody->type) {
+ case (MDOC_BLOCK):
return(post_bl_block(mdoc));
- if (MDOC_BODY != mdoc->last->type)
+ case (MDOC_HEAD):
+ return(post_bl_head(mdoc));
+ case (MDOC_BODY):
+ break;
+ default:
return(1);
+ }
- for (n = mdoc->last->child; n; n = n->next) {
- switch (n->tok) {
- case (MDOC_Lp):
- /* FALLTHROUGH */
- case (MDOC_Pp):
- mdoc_nmsg(mdoc, n, MANDOCERR_CHILD);
- /* FALLTHROUGH */
- case (MDOC_It):
- /* FALLTHROUGH */
- case (MDOC_Sm):
+ nchild = nbody->child;
+ while (NULL != nchild) {
+ if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) {
+ nchild = nchild->next;
continue;
- default:
- break;
}
- mdoc_nmsg(mdoc, n, MANDOCERR_SYNTCHILD);
- return(0);
+ mdoc_nmsg(mdoc, nchild, MANDOCERR_CHILD);
+
+ /*
+ * Move the node out of the Bl block.
+ * First, collect all required node pointers.
+ */
+
+ nblock = nbody->parent;
+ nprev = nblock->prev;
+ nparent = nblock->parent;
+ nnext = nchild->next;
+
+ /*
+ * Unlink this child.
+ */
+
+ assert(NULL == nchild->prev);
+ if (0 == --nbody->nchild) {
+ nbody->child = NULL;
+ nbody->last = NULL;
+ assert(NULL == nnext);
+ } else {
+ nbody->child = nnext;
+ nnext->prev = NULL;
+ }
+
+ /*
+ * Relink this child.
+ */
+
+ nchild->parent = nparent;
+ nchild->prev = nprev;
+ nchild->next = nblock;
+
+ nblock->prev = nchild;
+ nparent->nchild++;
+ if (NULL == nprev)
+ nparent->child = nchild;
+ else
+ nprev->next = nchild;
+
+ nchild = nnext;
}
return(1);
@@ -1588,10 +1674,16 @@ ebool(struct mdoc *mdoc)
assert(MDOC_TEXT == mdoc->last->child->type);
- if (0 == strcmp(mdoc->last->child->string, "on"))
+ if (0 == strcmp(mdoc->last->child->string, "on")) {
+ if (MDOC_Sm == mdoc->last->tok)
+ mdoc->flags &= ~MDOC_SMOFF;
return(1);
- if (0 == strcmp(mdoc->last->child->string, "off"))
+ }
+ if (0 == strcmp(mdoc->last->child->string, "off")) {
+ if (MDOC_Sm == mdoc->last->tok)
+ mdoc->flags |= MDOC_SMOFF;
return(1);
+ }
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL);
return(1);
@@ -1771,6 +1863,47 @@ post_rs(POST_ARGS)
return(1);
}
+/*
+ * For some arguments of some macros,
+ * convert all breakable hyphens into ASCII_HYPH.
+ */
+static int
+post_hyph(POST_ARGS)
+{
+ struct mdoc_node *n, *nch;
+ char *cp;
+
+ n = mdoc->last;
+ switch (n->type) {
+ case (MDOC_HEAD):
+ if (MDOC_Sh == n->tok || MDOC_Ss == n->tok)
+ break;
+ return(1);
+ case (MDOC_BODY):
+ if (MDOC_D1 == n->tok || MDOC_Nd == n->tok)
+ break;
+ return(1);
+ case (MDOC_ELEM):
+ break;
+ default:
+ return(1);
+ }
+
+ for (nch = n->child; nch; nch = nch->next) {
+ if (MDOC_TEXT != nch->type)
+ continue;
+ cp = nch->string;
+ if (3 > strnlen(cp, 3))
+ continue;
+ while ('\0' != *(++cp))
+ if ('-' == *cp &&
+ isalpha((unsigned char)cp[-1]) &&
+ isalpha((unsigned char)cp[1]))
+ *cp = ASCII_HYPH;
+ }
+ return(1);
+}
+
static int
post_ns(POST_ARGS)
{
@@ -1857,10 +1990,13 @@ post_sh_head(POST_ARGS)
/* The SYNOPSIS gets special attention in other areas. */
- if (SEC_SYNOPSIS == sec)
+ if (SEC_SYNOPSIS == sec) {
+ roff_setreg(mdoc->roff, "nS", 1, '=');
mdoc->flags |= MDOC_SYNOPSIS;
- else
+ } else {
+ roff_setreg(mdoc->roff, "nS", 0, '=');
mdoc->flags &= ~MDOC_SYNOPSIS;
+ }
/* Mark our last section. */
@@ -1916,7 +2052,8 @@ post_sh_head(POST_ARGS)
break;
if (*mdoc->meta.msec == '9')
break;
- mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECMSEC);
+ mandoc_msg(MANDOCERR_SECMSEC, mdoc->parse,
+ mdoc->last->line, mdoc->last->pos, buf);
break;
default:
break;
@@ -1962,7 +2099,9 @@ pre_par(PRE_ARGS)
* block: `Lp', `Pp', or non-compact `Bd' or `Bl'.
*/
- if (MDOC_Pp != mdoc->last->tok && MDOC_Lp != mdoc->last->tok)
+ if (MDOC_Pp != mdoc->last->tok &&
+ MDOC_Lp != mdoc->last->tok &&
+ MDOC_br != mdoc->last->tok)
return(1);
if (MDOC_Bl == n->tok && n->norm->Bl.comp)
return(1);
@@ -1977,6 +2116,32 @@ pre_par(PRE_ARGS)
}
static int
+post_par(POST_ARGS)
+{
+
+ if (MDOC_ELEM != mdoc->last->type &&
+ MDOC_BLOCK != mdoc->last->type)
+ return(1);
+
+ if (NULL == mdoc->last->prev) {
+ if (MDOC_Sh != mdoc->last->parent->tok &&
+ MDOC_Ss != mdoc->last->parent->tok)
+ return(1);
+ } else {
+ if (MDOC_Pp != mdoc->last->prev->tok &&
+ MDOC_Lp != mdoc->last->prev->tok &&
+ (MDOC_br != mdoc->last->tok ||
+ (MDOC_sp != mdoc->last->prev->tok &&
+ MDOC_br != mdoc->last->prev->tok)))
+ return(1);
+ }
+
+ mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR);
+ mdoc_node_delete(mdoc, mdoc->last);
+ return(1);
+}
+
+static int
pre_literal(PRE_ARGS)
{
@@ -2129,9 +2294,9 @@ post_dt(POST_ARGS)
free(mdoc->meta.vol);
mdoc->meta.vol = mandoc_strdup(cp);
} else {
- /* FIXME: warn about bad arch. */
cp = mdoc_a2arch(nn->string);
if (NULL == cp) {
+ mdoc_nmsg(mdoc, nn, MANDOCERR_BADVOLARCH);
free(mdoc->meta.vol);
mdoc->meta.vol = mandoc_strdup(nn->string);
} else
@@ -2192,14 +2357,15 @@ post_os(POST_ARGS)
n = mdoc->last;
/*
- * Set the operating system by way of the `Os' macro. Note that
- * if an argument isn't provided and -DOSNAME="\"foo\"" is
- * provided during compilation, this value will be used instead
- * of filling in "sysname release" from uname().
+ * Set the operating system by way of the `Os' macro.
+ * The order of precedence is:
+ * 1. the argument of the `Os' macro, unless empty
+ * 2. the -Ios=foo command line argument, if provided
+ * 3. -DOSNAME="\"foo\"", if provided during compilation
+ * 4. "sysname release" from uname(3)
*/
- if (mdoc->meta.os)
- free(mdoc->meta.os);
+ free(mdoc->meta.os);
buf[0] = '\0';
if (-1 == (c = concat(buf, n->child, BUFSIZ))) {
@@ -2209,11 +2375,11 @@ post_os(POST_ARGS)
assert(c);
- /* XXX: yes, these can all be dynamically-adjusted buffers, but
- * it's really not worth the extra hackery.
- */
-
if ('\0' == buf[0]) {
+ if (mdoc->defos) {
+ mdoc->meta.os = mandoc_strdup(mdoc->defos);
+ return(1);
+ }
#ifdef OSNAME
if (strlcat(buf, OSNAME, BUFSIZ) >= BUFSIZ) {
mdoc_nmsg(mdoc, n, MANDOCERR_MEM);
diff --git a/out.c b/out.c
index 8dbd68ac11ad..c93166497789 100644
--- a/out.c
+++ b/out.c
@@ -1,4 +1,4 @@
-/* $Id: out.c,v 1.43 2011/09/20 23:05:49 schwarze Exp $ */
+/* $Id: out.c,v 1.46 2013/10/05 20:30:05 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -32,11 +32,11 @@
#include "out.h"
static void tblcalc_data(struct rofftbl *, struct roffcol *,
- const struct tbl *, const struct tbl_dat *);
+ const struct tbl_opts *, const struct tbl_dat *);
static void tblcalc_literal(struct rofftbl *, struct roffcol *,
const struct tbl_dat *);
static void tblcalc_number(struct rofftbl *, struct roffcol *,
- const struct tbl *, const struct tbl_dat *);
+ const struct tbl_opts *, const struct tbl_dat *);
/*
* Convert a `scaling unit' to a consistent form, or fail. Scaling
@@ -142,7 +142,6 @@ void
tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
{
const struct tbl_dat *dp;
- const struct tbl_head *hp;
struct roffcol *col;
int spans;
@@ -154,9 +153,7 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
assert(NULL == tbl->cols);
tbl->cols = mandoc_calloc
- ((size_t)sp->tbl->cols, sizeof(struct roffcol));
-
- hp = sp->head;
+ ((size_t)sp->opts->cols, sizeof(struct roffcol));
for ( ; sp; sp = sp->next) {
if (TBL_SPAN_DATA != sp->pos)
@@ -175,33 +172,14 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
continue;
assert(dp->layout);
col = &tbl->cols[dp->layout->head->ident];
- tblcalc_data(tbl, col, sp->tbl, dp);
- }
- }
-
- /*
- * Calculate width of the spanners. These get one space for a
- * vertical line, two for a double-vertical line.
- */
-
- for ( ; hp; hp = hp->next) {
- col = &tbl->cols[hp->ident];
- switch (hp->pos) {
- case (TBL_HEAD_VERT):
- col->width = (*tbl->len)(1, tbl->arg);
- break;
- case (TBL_HEAD_DVERT):
- col->width = (*tbl->len)(2, tbl->arg);
- break;
- default:
- break;
+ tblcalc_data(tbl, col, sp->opts, dp);
}
}
}
static void
tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
- const struct tbl *tp, const struct tbl_dat *dp)
+ const struct tbl_opts *opts, const struct tbl_dat *dp)
{
size_t sz;
@@ -225,7 +203,7 @@ tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
tblcalc_literal(tbl, col, dp);
break;
case (TBL_CELL_NUMBER):
- tblcalc_number(tbl, col, tp, dp);
+ tblcalc_number(tbl, col, opts, dp);
break;
case (TBL_CELL_DOWN):
break;
@@ -251,7 +229,7 @@ tblcalc_literal(struct rofftbl *tbl, struct roffcol *col,
static void
tblcalc_number(struct rofftbl *tbl, struct roffcol *col,
- const struct tbl *tp, const struct tbl_dat *dp)
+ const struct tbl_opts *opts, const struct tbl_dat *dp)
{
int i;
size_t sz, psz, ssz, d;
@@ -273,12 +251,12 @@ tblcalc_number(struct rofftbl *tbl, struct roffcol *col,
/* FIXME: TBL_DATA_HORIZ et al.? */
- buf[0] = tp->decimal;
+ buf[0] = opts->decimal;
buf[1] = '\0';
psz = (*tbl->slen)(buf, tbl->arg);
- if (NULL != (cp = strrchr(str, tp->decimal))) {
+ if (NULL != (cp = strrchr(str, opts->decimal))) {
buf[1] = '\0';
for (ssz = 0, i = 0; cp != &str[i]; i++) {
buf[0] = str[i];
diff --git a/preconv.1 b/preconv.1
index c4cb8c5738fd..8daee30854d9 100644
--- a/preconv.1
+++ b/preconv.1
@@ -1,4 +1,4 @@
-.\" $Id: preconv.1,v 1.6 2011/12/25 19:35:44 kristaps Exp $
+.\" $Id: preconv.1,v 1.7 2013/07/13 19:41:16 schwarze Exp $
.\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -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: December 25 2011 $
+.Dd $Mdocdate: July 13 2013 $
.Dt PRECONV 1
.Os
.Sh NAME
@@ -150,8 +150,7 @@ utility appeared in May 2011.
The
.Nm
utility was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
.\" .Sh CAVEATS
.\" .Sh BUGS
.\" .Sh SECURITY CONSIDERATIONS
diff --git a/preconv.c b/preconv.c
index a0b2d6415e99..7595887dd26f 100644
--- a/preconv.c
+++ b/preconv.c
@@ -1,4 +1,4 @@
-/* $Id: preconv.c,v 1.5 2011/07/24 18:15:14 kristaps Exp $ */
+/* $Id: preconv.c,v 1.6 2013/06/02 03:52:21 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -32,13 +32,9 @@
/*
* The read_whole_file() and resize_buf() functions are copied from
- * read.c, including all dependency code (MAP_FILE, etc.).
+ * read.c, including all dependency code.
*/
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-
enum enc {
ENC_UTF_8, /* UTF-8 */
ENC_US_ASCII, /* US-ASCII */
@@ -271,8 +267,7 @@ read_whole_file(const char *f, int fd,
if (S_ISREG(st.st_mode)) {
*with_mmap = 1;
fb->sz = (size_t)st.st_size;
- fb->buf = mmap(NULL, fb->sz, PROT_READ,
- MAP_FILE|MAP_SHARED, fd, 0);
+ fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
if (fb->buf != MAP_FAILED)
return(1);
}
diff --git a/predefs.in b/predefs.in
index 70074bb617b5..d1690e356808 100644
--- a/predefs.in
+++ b/predefs.in
@@ -1,4 +1,4 @@
-/* $Id: predefs.in,v 1.3 2011/07/31 11:36:49 schwarze Exp $ */
+/* $Id: predefs.in,v 1.4 2012/07/18 10:39:19 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -26,7 +26,7 @@
*/
PREDEF("Am", "&")
-PREDEF("Ba", "|")
+PREDEF("Ba", "\\fR|\\fP")
PREDEF("Ge", "\\(>=")
PREDEF("Gt", ">")
PREDEF("If", "infinity")
diff --git a/read.c b/read.c
index 5b14e357d2bd..511ba7dc466d 100644
--- a/read.c
+++ b/read.c
@@ -1,7 +1,7 @@
-/* $Id: read.c,v 1.28 2012/02/16 20:51:31 joerg Exp $ */
+/* $Id: read.c,v 1.39 2013/09/16 00:25:07 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 2012, 2013 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
@@ -40,10 +40,6 @@
#include "man.h"
#include "main.h"
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-
#define REPARSE_LIMIT 1000
struct buf {
@@ -66,14 +62,16 @@ struct mparse {
void *arg; /* argument to mmsg */
const char *file;
struct buf *secondary;
+ char *defos; /* default operating system */
};
static void resize_buf(struct buf *, size_t);
static void mparse_buf_r(struct mparse *, struct buf, int);
-static void mparse_readfd_r(struct mparse *, int, const char *, int);
static void pset(const char *, int, struct mparse *);
static int read_whole_file(const char *, 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,
@@ -94,6 +92,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"no title in document",
"document title should be all caps",
"unknown manual section",
+ "unknown manual volume or arch",
"date missing, using today's date",
"cannot parse date, using it verbatim",
"prologue macros out of order",
@@ -105,14 +104,14 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
".so is fragile, better use ln(1)",
"NAME section must come first",
"bad NAME section contents",
- "manual name not yet set",
"sections out of conventional order",
"duplicate section name",
- "section not in conventional manual section",
+ "section header suited to sections 2, 3, and 9 only",
/* related to macros and nesting */
"skipping obsolete macro",
"skipping paragraph macro",
+ "moving paragraph macro out of list",
"skipping no-space macro",
"blocks badly nested",
"child violates parent syntax",
@@ -173,10 +172,12 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"input stack limit exceeded, infinite loop?",
"skipping bad character",
"escaped character not allowed in a name",
+ "manual name not yet set",
"skipping text before the first section header",
"skipping unknown macro",
"NOT IMPLEMENTED, please use groff: skipping request",
"argument count wrong",
+ "skipping column outside column list",
"skipping end of block that is not open",
"missing end of block",
"scope open on exit",
@@ -184,6 +185,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"macro requires line argument(s)",
"macro requires body argument(s)",
"macro requires argument(s)",
+ "request requires a numeric argument",
"missing list type",
"line argument(s) will be lost",
"body argument(s) will be lost",
@@ -247,7 +249,8 @@ pset(const char *buf, int pos, struct mparse *curp)
switch (curp->inttype) {
case (MPARSE_MDOC):
if (NULL == curp->pmdoc)
- curp->pmdoc = mdoc_alloc(curp->roff, curp);
+ curp->pmdoc = mdoc_alloc(curp->roff, curp,
+ curp->defos);
assert(curp->pmdoc);
curp->mdoc = curp->pmdoc;
return;
@@ -263,7 +266,8 @@ pset(const char *buf, int pos, struct mparse *curp)
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
if (NULL == curp->pmdoc)
- curp->pmdoc = mdoc_alloc(curp->roff, curp);
+ curp->pmdoc = mdoc_alloc(curp->roff, curp,
+ curp->defos);
assert(curp->pmdoc);
curp->mdoc = curp->pmdoc;
return;
@@ -322,6 +326,15 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
break;
}
+ /*
+ * Make sure we have space for at least
+ * one backslash and one other character
+ * and the trailing NUL byte.
+ */
+
+ if (pos + 2 >= (int)ln.sz)
+ resize_buf(&ln, 256);
+
/*
* Warn about bogus characters. If you're using
* non-ASCII encoding, you're screwing your
@@ -338,8 +351,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
mandoc_msg(MANDOCERR_BADCHAR, curp,
curp->line, pos, NULL);
i++;
- if (pos >= (int)ln.sz)
- resize_buf(&ln, 256);
ln.buf[pos++] = '?';
continue;
}
@@ -347,8 +358,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
/* Trailing backslash = a plain char. */
if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
- if (pos >= (int)ln.sz)
- resize_buf(&ln, 256);
ln.buf[pos++] = blk.buf[i++];
continue;
}
@@ -390,10 +399,20 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
break;
}
- /* Some other escape sequence, copy & cont. */
+ /* Catch escaped bogus characters. */
- if (pos + 1 >= (int)ln.sz)
- resize_buf(&ln, 256);
+ c = (unsigned char) blk.buf[i+1];
+
+ if ( ! (isascii(c) &&
+ (isgraph(c) || isblank(c)))) {
+ mandoc_msg(MANDOCERR_BADCHAR, curp,
+ curp->line, pos, NULL);
+ i += 2;
+ ln.buf[pos++] = '?';
+ continue;
+ }
+
+ /* Some other escape sequence, copy & cont. */
ln.buf[pos++] = blk.buf[i++];
ln.buf[pos++] = blk.buf[i++];
@@ -469,7 +488,7 @@ rerun:
*/
if (curp->secondary)
curp->secondary->sz -= pos + 1;
- mparse_readfd_r(curp, -1, ln.buf + of, 1);
+ mparse_readfd(curp, -1, ln.buf + of);
if (MANDOCLEVEL_FATAL <= curp->file_status)
break;
pos = 0;
@@ -575,8 +594,7 @@ read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
}
*with_mmap = 1;
fb->sz = (size_t)st.st_size;
- fb->buf = mmap(NULL, fb->sz, PROT_READ,
- MAP_FILE|MAP_SHARED, fd, 0);
+ fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
if (fb->buf != MAP_FAILED)
return(1);
}
@@ -643,19 +661,25 @@ mparse_end(struct mparse *curp)
}
static void
-mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file,
- int re)
+mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
{
const char *svfile;
+ static int recursion_depth;
+
+ if (64 < recursion_depth) {
+ mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, 0, NULL);
+ return;
+ }
/* Line number is per-file. */
svfile = curp->file;
curp->file = file;
curp->line = 1;
+ recursion_depth++;
mparse_buf_r(curp, blk, 1);
- if (0 == re && MANDOCLEVEL_FATAL > curp->file_status)
+ if (0 == --recursion_depth && MANDOCLEVEL_FATAL > curp->file_status)
mparse_end(curp);
curp->file = svfile;
@@ -670,12 +694,12 @@ mparse_readmem(struct mparse *curp, const void *buf, size_t len,
blk.buf = UNCONST(buf);
blk.sz = len;
- mparse_parse_buffer(curp, blk, file, 0);
+ mparse_parse_buffer(curp, blk, file);
return(curp->file_status);
}
-static void
-mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
+enum mandoclevel
+mparse_readfd(struct mparse *curp, int fd, const char *file)
{
struct buf blk;
int with_mmap;
@@ -684,7 +708,7 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
if (-1 == (fd = open(file, O_RDONLY, 0))) {
perror(file);
curp->file_status = MANDOCLEVEL_SYSERR;
- return;
+ goto out;
}
/*
* Run for each opened file; may be called more than once for
@@ -695,10 +719,10 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
if ( ! read_whole_file(file, fd, &blk, &with_mmap)) {
curp->file_status = MANDOCLEVEL_SYSERR;
- return;
+ goto out;
}
- mparse_parse_buffer(curp, blk, file, re);
+ mparse_parse_buffer(curp, blk, file);
#ifdef HAVE_MMAP
if (with_mmap)
@@ -709,18 +733,13 @@ mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
if (STDIN_FILENO != fd && -1 == close(fd))
perror(file);
-}
-
-enum mandoclevel
-mparse_readfd(struct mparse *curp, int fd, const char *file)
-{
-
- mparse_readfd_r(curp, fd, file, 0);
+out:
return(curp->file_status);
}
struct mparse *
-mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void *arg)
+mparse_alloc(enum mparset inttype, enum mandoclevel wlevel,
+ mandocmsg mmsg, void *arg, char *defos)
{
struct mparse *curp;
@@ -732,8 +751,9 @@ mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void
curp->mmsg = mmsg;
curp->arg = arg;
curp->inttype = inttype;
+ curp->defos = defos;
- curp->roff = roff_alloc(curp);
+ curp->roff = roff_alloc(inttype, curp);
return(curp);
}
diff --git a/roff.7 b/roff.7
index dd32a45b2908..48e16dd905bd 100644
--- a/roff.7
+++ b/roff.7
@@ -1,7 +1,7 @@
-.\" $Id: roff.7,v 1.37 2011/12/11 00:38:11 schwarze Exp $
+.\" $Id: roff.7,v 1.46 2013/12/26 02:43:18 schwarze Exp $
.\"
-.\" Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2010, 2011, 2013 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: December 11 2011 $
+.Dd $Mdocdate: December 26 2013 $
.Dt ROFF 7
.Os
.Sh NAME
@@ -32,7 +32,7 @@ and
manual formatting languages are based on it,
many real-world manuals use small numbers of
.Nm
-requests intermixed with their
+requests and escape sequences intermixed with their
.Xr mdoc 7
or
.Xr man 7
@@ -41,8 +41,8 @@ To properly format such manuals, the
.Xr mandoc 1
utility supports a tiny subset of
.Nm
-requests.
-Only these requests supported by
+requests and escapes.
+Only these requests and escapes supported by
.Xr mandoc 1
are documented in the present manual,
together with the basic language syntax shared by
@@ -83,9 +83,9 @@ depends on the respective processing context.
.Nm
documents may contain only graphable 7-bit ASCII characters, the space
character, and, in certain circumstances, the tab character.
-The back-space character
+The backslash character
.Sq \e
-indicates the start of an escape sequence for
+indicates the start of an escape sequence, used for example for
.Sx Comments ,
.Sx Special Characters ,
.Sx Predefined Strings ,
@@ -93,6 +93,9 @@ and
user-defined strings defined using the
.Sx ds
request.
+For a listing of escape sequences, consult the
+.Sx ESCAPE SEQUENCE REFERENCE
+below.
.Ss Comments
Text following an escaped double-quote
.Sq \e\(dq ,
@@ -146,12 +149,19 @@ respectively) may be used instead.
The indicator or numerical representative may be preceded by C
(constant-width), which is ignored.
.Pp
+The two-character indicator
+.Sq BI
+requests a font that is both bold and italic.
+It may not be portable to old roff implementations.
+.Pp
Examples:
.Bl -tag -width Ds -offset indent -compact
.It Li \efBbold\efR
-Write in bold, then switch to regular font mode.
+Write in \fBbold\fP, then switch to regular font mode.
.It Li \efIitalic\efP
-Write in italic, then return to previous font mode.
+Write in \fIitalic\fP, then return to previous font mode.
+.It Li \ef(BIbold italic\efP
+Write in \f(BIbold italic\fP, then return to previous font mode.
.El
.Pp
Text decoration is
@@ -417,6 +427,18 @@ The syntax of this request is the same as that of
It is currently ignored by
.Xr mandoc 1 ,
as are its children.
+.Ss \&cc
+Changes the control character.
+Its syntax is as follows:
+.Bd -literal -offset indent
+.Pf . Cm \&cc Op Ar c
+.Ed
+.Pp
+If
+.Ar c
+is not specified, the control character is reset to
+.Sq \&. .
+Trailing characters are ignored.
.Ss \&de
Define a
.Nm
@@ -619,6 +641,15 @@ Begin an equation block.
See
.Xr eqn 7
for a description of the equation language.
+.Ss \&fam
+Change the font family.
+This line-scoped request is intended to have one argument specifying
+the font family to be selected.
+It is a groff extension, and currently, it is ignored including its
+arguments, and the number of arguments is not checked.
+.Ss \&hw
+Specify hyphenation points in words.
+This line-scoped request is currently ignored.
.Ss \&hy
Set automatic hyphenation mode.
This line-scoped request is currently ignored.
@@ -786,19 +817,22 @@ the name of the request, macro or string to be undefined.
Currently, it is ignored including its arguments,
and the number of arguments is not checked.
.Ss \&nr
-Define a register.
+Define or change a register.
A register is an arbitrary string value that defines some sort of state,
which influences parsing and/or formatting.
Its syntax is as follows:
.Pp
-.D1 Pf \. Cm \&nr Ar name Ar value
+.D1 Pf \. Cm \&nr Ar name Oo +|- Oc Ns Ar value
.Pp
The
.Ar value
may, at the moment, only be an integer.
-So far, only the following register
+If it is prefixed by a sign, the register will be
+incremented or decremented instead of assigned to.
+.Pp
+The following register
.Ar name
-is recognised:
+is handled specially:
.Bl -tag -width Ds
.It Cm nS
If set to a positive integer value, certain
@@ -895,8 +929,251 @@ Begin a table, which formats input in aligned rows and columns.
See
.Xr tbl 7
for a description of the tbl language.
+.Sh ESCAPE SEQUENCE REFERENCE
+The
+.Xr mandoc 1
+.Nm
+parser recognises the following escape sequences.
+Note that the
+.Nm
+language defines more escape sequences not implemented in
+.Xr mandoc 1 .
+In
+.Xr mdoc 7
+and
+.Xr man 7
+documents, using escape sequences is discouraged except for those
+described in the
+.Sx LANGUAGE SYNTAX
+section above.
+.Pp
+A backslash followed by any character not listed here
+simply prints that character itself.
+.Ss \e<newline>
+A backslash at the end of an input line can be used to continue the
+logical input line on the next physical input line, joining the text
+on both lines together as if it were on a single input line.
+.Ss \e<space>
+The escape sequence backslash-space
+.Pq Sq \e\ \&
+is an unpaddable space-sized non-breaking space character; see
+.Sx Whitespace .
+.Ss \e\(dq
+The rest of the input line is treated as
+.Sx Comments .
+.Ss \e%
+Hyphenation allowed at this point of the word; ignored by
+.Xr mandoc 1 .
+.Ss \e&
+Non-printing zero-width character; see
+.Sx Whitespace .
+.Ss \e\(aq
+Acute accent special character; use
+.Sq \e(aa
+instead.
+.Ss \e( Ns Ar cc
+.Sx Special Characters
+with two-letter names, see
+.Xr mandoc_char 7 .
+.Ss \e*[ Ns Ar name ]
+Interpolate the string with the
+.Ar name ;
+see
+.Sx Predefined Strings
+and
+.Sx ds .
+For short names, there are variants
+.No \e* Ns Ar c
+and
+.No \e*( Ns Ar cc .
+.Ss \e-
+Special character
+.Dq mathematical minus sign .
+.Ss \e[ Ns Ar name ]
+.Sx Special Characters
+with names of arbitrary length, see
+.Xr mandoc_char 7 .
+.Ss \e^
+One-twelfth em half-narrow space character, effectively zero-width in
+.Xr mandoc 1 .
+.Ss \e`
+Grave accent special character; use
+.Sq \e(ga
+instead.
+.Ss \e{
+Begin conditional input; see
+.Sx if .
+.Ss \e\(ba
+One-sixth em narrow space character, effectively zero-width in
+.Xr mandoc 1 .
+.Ss \e}
+End conditional input; see
+.Sx if .
+.Ss \e~
+Paddable non-breaking space character.
+.Ss \e0
+Digit width space character.
+.Ss \eA\(aq Ns Ar string Ns \(aq
+Anchor definition; ignored by
+.Xr mandoc 1 .
+.Ss \eB\(aq Ns Ar string Ns \(aq
+Test whether
+.Ar string
+is a numerical expession; ignored by
+.Xr mandoc 1 .
+.Ss \eb\(aq Ns Ar string Ns \(aq
+Bracket building function; ignored by
+.Xr mandoc 1 .
+.Ss \eC\(aq Ns Ar name Ns \(aq
+.Sx Special Characters
+with names of arbitrary length.
+.Ss \ec
+Interrupt text processing to insert requests or macros; ignored by
+.Xr mandoc 1 .
+.Ss \eD\(aq Ns Ar string Ns \(aq
+Draw graphics function; ignored by
+.Xr mandoc 1 .
+.Ss \ed
+Move down by half a line; ignored by
+.Xr mandoc 1 .
+.Ss \ee
+Backslash special character.
+.Ss \eF[ Ns Ar name ]
+Switch font family (groff extension); ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eF Ns Ar c
+and
+.No \eF( Ns Ar cc .
+.Ss \ef[ Ns Ar name ]
+Switch to the font
+.Ar name ,
+see
+.Sx Text Decoration .
+For short names, there are variants
+.No \ef Ns Ar c
+and
+.No \ef( Ns Ar cc .
+.Ss \eg[ Ns Ar name ]
+Interpolate the format of a number register; ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eg Ns Ar c
+and
+.No \eg( Ns Ar cc .
+.Ss \eH\(aq Ns Oo +|- Oc Ns Ar number Ns \(aq
+Set the height of the current font; ignored by
+.Xr mandoc 1 .
+.Ss \eh\(aq Ns Ar number Ns \(aq
+Horizontal motion; ignored by
+.Xr mandoc 1 .
+.Ss \ek[ Ns Ar name ]
+Mark horizontal input place in register; ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \ek Ns Ar c
+and
+.No \ek( Ns Ar cc .
+.Ss \eL\(aq Ns Ar number Ns Oo Ar c Oc Ns \(aq
+Vertical line drawing function; ignored by
+.Xr mandoc 1 .
+.Ss \el\(aq Ns Ar number Ns Oo Ar c Oc Ns \(aq
+Horizontal line drawing function; ignored by
+.Xr mandoc 1 .
+.Ss \eM[ Ns Ar name ]
+Set fill (background) color (groff extension); ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eM Ns Ar c
+and
+.No \eM( Ns Ar cc .
+.Ss \em[ Ns Ar name ]
+Set glyph drawing color (groff extension); ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \em Ns Ar c
+and
+.No \em( Ns Ar cc .
+.Ss \eN\(aq Ns Ar number Ns \(aq
+Character
+.Ar number
+on the current font.
+.Ss \en[ Ns Ar name ]
+Interpolate the number register
+.Ar name .
+For short names, there are variants
+.No \en Ns Ar c
+and
+.No \en( Ns Ar cc .
+.Ss \eo\(aq Ns Ar string Ns \(aq
+Overstrike
+.Ar string ;
+ignored by
+.Xr mandoc 1 .
+.Ss \eR\(aq Ns Ar name Oo +|- Oc Ns Ar number Ns \(aq
+Set number register; ignored by
+.Xr mandoc 1 .
+.Ss \eS\(aq Ns Ar number Ns \(aq
+Slant output; ignored by
+.Xr mandoc 1 .
+.Ss \es\(aq Ns Oo +|- Oc Ns Ar number Ns \(aq
+Change point size; ignored by
+.Xr mandoc 1 .
+Alternative forms
+.No \es Ns Oo +|- Oc Ns Ar n ,
+.No \es Ns Oo +|- Oc Ns \(aq Ns Ar number Ns \(aq ,
+.No \es Ns [ Oo +|- Oc Ns Ar number ] ,
+and
+.No \es Ns Oo +|- Oc Ns [ Ar number Ns ]
+are also parsed and ignored.
+.Ss \et
+Horizontal tab; ignored by
+.Xr mandoc 1 .
+.Ss \eu
+Move up by half a line; ignored by
+.Xr mandoc 1 .
+.Ss \eV[ Ns Ar name ]
+Interpolate an environment variable; ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eV Ns Ar c
+and
+.No \eV( Ns Ar cc .
+.Ss \ev\(aq Ns Ar number Ns \(aq
+Vertical motion; ignored by
+.Xr mandoc 1 .
+.Ss \ew\(aq Ns Ar string Ns \(aq
+Interpolate the width of the
+.Ar string ;
+ignored by
+.Xr mandoc 1 .
+.Ss \eX\(aq Ns Ar string Ns \(aq
+Output
+.Ar string
+as device control function; ignored in nroff mode and by
+.Xr mandoc 1 .
+.Ss \ex\(aq Ns Ar number Ns \(aq
+Extra line space function; ignored by
+.Xr mandoc 1 .
+.Ss \eY[ Ns Ar name ]
+Output a string as a device control function; ignored in nroff mode and by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eY Ns Ar c
+and
+.No \eY( Ns Ar cc .
+.Ss \eZ\(aq Ns Ar string Ns \(aq
+Print
+.Ar string
+with zero width and height; ignored by
+.Xr mandoc 1 .
+.Ss \ez
+Output the next character without advancing the cursor position;
+approximated in
+.Xr mandoc 1
+by simply skipping the next character.
.Sh COMPATIBILITY
-This section documents compatibility between mandoc and other other
+This section documents compatibility between mandoc and other
.Nm
implementations, at this time limited to GNU troff
.Pq Qq groff .
@@ -982,8 +1259,6 @@ In 1989, James Clarke re-implemented troff in C++, naming it groff.
This
.Nm
reference was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv ;
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
and
-.An Ingo Schwarze ,
-.Mt schwarze@openbsd.org .
+.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
diff --git a/roff.c b/roff.c
index b479cc298cff..e33216c40970 100644
--- a/roff.c
+++ b/roff.c
@@ -1,7 +1,7 @@
-/* $Id: roff.c,v 1.172 2011/10/24 21:41:45 schwarze Exp $ */
+/* $Id: roff.c,v 1.188 2013/12/25 00:50:05 schwarze Exp $ */
/*
- * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 2011, 2012, 2013 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
@@ -21,6 +21,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -39,11 +40,14 @@ enum rofft {
ROFF_am,
ROFF_ami,
ROFF_am1,
+ ROFF_cc,
ROFF_de,
ROFF_dei,
ROFF_de1,
ROFF_ds,
ROFF_el,
+ ROFF_fam,
+ ROFF_hw,
ROFF_hy,
ROFF_ie,
ROFF_if,
@@ -58,6 +62,8 @@ enum rofft {
ROFF_so,
ROFF_ta,
ROFF_tr,
+ ROFF_Dd,
+ ROFF_TH,
ROFF_TS,
ROFF_TE,
ROFF_T_,
@@ -70,18 +76,8 @@ enum rofft {
};
enum roffrule {
- ROFFRULE_ALLOW,
- ROFFRULE_DENY
-};
-
-/*
- * A single register entity. If "set" is zero, the value of the
- * register should be the default one, which is per-register.
- * Registers are assumed to be unsigned ints for now.
- */
-struct reg {
- int set; /* whether set or not */
- unsigned int u; /* unsigned integer */
+ ROFFRULE_DENY,
+ ROFFRULE_ALLOW
};
/*
@@ -101,12 +97,23 @@ struct roffkv {
struct roffkv *next; /* next in list */
};
+/*
+ * A single number register as part of a singly-linked list.
+ */
+struct roffreg {
+ struct roffstr key;
+ int val;
+ struct roffreg *next;
+};
+
struct roff {
+ enum mparset parsetype; /* requested parse type */
struct mparse *parse; /* parse point */
struct roffnode *last; /* leaf of stack */
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */
+ char control; /* control character */
int rstackpos; /* position in rstack */
- struct reg regs[REG__MAX];
+ struct roffreg *regtab; /* number registers */
struct roffkv *strtab; /* user-defined strings & macros */
struct roffkv *xmbtab; /* multi-byte trans table (`tr') */
struct roffstr *xtab; /* single-byte trans table (`tr') */
@@ -169,6 +176,7 @@ static enum rofferr roff_block(ROFF_ARGS);
static enum rofferr roff_block_text(ROFF_ARGS);
static enum rofferr roff_block_sub(ROFF_ARGS);
static enum rofferr roff_cblock(ROFF_ARGS);
+static enum rofferr roff_cc(ROFF_ARGS);
static enum rofferr roff_ccond(ROFF_ARGS);
static enum rofferr roff_cond(ROFF_ARGS);
static enum rofferr roff_cond_text(ROFF_ARGS);
@@ -176,16 +184,22 @@ static enum rofferr roff_cond_sub(ROFF_ARGS);
static enum rofferr roff_ds(ROFF_ARGS);
static enum roffrule roff_evalcond(const char *, int *);
static void roff_free1(struct roff *);
+static void roff_freereg(struct roffreg *);
static void roff_freestr(struct roffkv *);
static char *roff_getname(struct roff *, char **, int, int);
+static int roff_getnum(const char *, int *, int *);
+static int roff_getop(const char *, int *, char *);
+static int roff_getregn(const struct roff *,
+ const char *, size_t);
static const char *roff_getstrn(const struct roff *,
const char *, size_t);
+static enum rofferr roff_it(ROFF_ARGS);
static enum rofferr roff_line_ignore(ROFF_ARGS);
static enum rofferr roff_nr(ROFF_ARGS);
static void roff_openeqn(struct roff *, const char *,
int, int, const char *);
static enum rofft roff_parse(struct roff *, const char *, int *);
-static enum rofferr roff_parsetext(char *);
+static enum rofferr roff_parsetext(char **, size_t *, int, int *);
static enum rofferr roff_res(struct roff *,
char **, size_t *, int, int);
static enum rofferr roff_rm(ROFF_ARGS);
@@ -195,6 +209,8 @@ static void roff_setstrn(struct roffkv **, const char *,
size_t, const char *, size_t, int);
static enum rofferr roff_so(ROFF_ARGS);
static enum rofferr roff_tr(ROFF_ARGS);
+static enum rofferr roff_Dd(ROFF_ARGS);
+static enum rofferr roff_TH(ROFF_ARGS);
static enum rofferr roff_TE(ROFF_ARGS);
static enum rofferr roff_TS(ROFF_ARGS);
static enum rofferr roff_EQ(ROFF_ARGS);
@@ -215,16 +231,19 @@ static struct roffmac roffs[ROFF_MAX] = {
{ "am", roff_block, roff_block_text, roff_block_sub, 0, NULL },
{ "ami", roff_block, roff_block_text, roff_block_sub, 0, NULL },
{ "am1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+ { "cc", roff_cc, NULL, NULL, 0, NULL },
{ "de", roff_block, roff_block_text, roff_block_sub, 0, NULL },
{ "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL },
{ "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
{ "ds", roff_ds, NULL, NULL, 0, NULL },
{ "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
+ { "fam", roff_line_ignore, NULL, NULL, 0, NULL },
+ { "hw", roff_line_ignore, NULL, NULL, 0, NULL },
{ "hy", roff_line_ignore, NULL, NULL, 0, NULL },
{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
{ "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
{ "ig", roff_block, roff_block_text, roff_block_sub, 0, NULL },
- { "it", roff_line_ignore, NULL, NULL, 0, NULL },
+ { "it", roff_it, NULL, NULL, 0, NULL },
{ "ne", roff_line_ignore, NULL, NULL, 0, NULL },
{ "nh", roff_line_ignore, NULL, NULL, 0, NULL },
{ "nr", roff_nr, NULL, NULL, 0, NULL },
@@ -234,6 +253,8 @@ static struct roffmac roffs[ROFF_MAX] = {
{ "so", roff_so, NULL, NULL, 0, NULL },
{ "ta", roff_line_ignore, NULL, NULL, 0, NULL },
{ "tr", roff_tr, NULL, NULL, 0, NULL },
+ { "Dd", roff_Dd, NULL, NULL, 0, NULL },
+ { "TH", roff_TH, NULL, NULL, 0, NULL },
{ "TS", roff_TS, NULL, NULL, 0, NULL },
{ "TE", roff_TE, NULL, NULL, 0, NULL },
{ "T&", roff_T_, NULL, NULL, 0, NULL },
@@ -244,6 +265,37 @@ static struct roffmac roffs[ROFF_MAX] = {
{ NULL, roff_userdef, NULL, NULL, 0, NULL },
};
+const char *const __mdoc_reserved[] = {
+ "Ac", "Ad", "An", "Ao", "Ap", "Aq", "Ar", "At",
+ "Bc", "Bd", "Bf", "Bk", "Bl", "Bo", "Bq",
+ "Brc", "Bro", "Brq", "Bsx", "Bt", "Bx",
+ "Cd", "Cm", "Db", "Dc", "Dd", "Dl", "Do", "Dq",
+ "Ds", "Dt", "Dv", "Dx", "D1",
+ "Ec", "Ed", "Ef", "Ek", "El", "Em", "em",
+ "En", "Eo", "Eq", "Er", "Es", "Ev", "Ex",
+ "Fa", "Fc", "Fd", "Fl", "Fn", "Fo", "Fr", "Ft", "Fx",
+ "Hf", "Ic", "In", "It", "Lb", "Li", "Lk", "Lp", "LP",
+ "Me", "Ms", "Mt", "Nd", "Nm", "No", "Ns", "Nx",
+ "Oc", "Oo", "Op", "Os", "Ot", "Ox",
+ "Pa", "Pc", "Pf", "Po", "Pp", "PP", "pp", "Pq",
+ "Qc", "Ql", "Qo", "Qq", "Or", "Rd", "Re", "Rs", "Rv",
+ "Sc", "Sf", "Sh", "SH", "Sm", "So", "Sq",
+ "Ss", "St", "Sx", "Sy",
+ "Ta", "Tn", "Ud", "Ux", "Va", "Vt", "Xc", "Xo", "Xr",
+ "%A", "%B", "%D", "%I", "%J", "%N", "%O",
+ "%P", "%Q", "%R", "%T", "%U", "%V",
+ NULL
+};
+
+const char *const __man_reserved[] = {
+ "AT", "B", "BI", "BR", "BT", "DE", "DS", "DT",
+ "EE", "EN", "EQ", "EX", "HF", "HP", "I", "IB", "IP", "IR",
+ "LP", "ME", "MT", "OP", "P", "PD", "PP", "PT",
+ "R", "RB", "RE", "RI", "RS", "SB", "SH", "SM", "SS", "SY",
+ "TE", "TH", "TP", "TQ", "TS", "T&", "UC", "UE", "UR", "YS",
+ NULL
+};
+
/* Array of injected predefined strings. */
#define PREDEFS_MAX 38
static const struct predef predefs[PREDEFS_MAX] = {
@@ -253,6 +305,9 @@ static const struct predef predefs[PREDEFS_MAX] = {
/* See roffhash_find() */
#define ROFF_HASH(p) (p[0] - ASCII_LO)
+static int roffit_lines; /* number of lines to delay */
+static char *roffit_macro; /* nil-terminated macro line */
+
static void
roffhash_init(void)
{
@@ -351,13 +406,13 @@ roffnode_push(struct roff *r, enum rofft tok, const char *name,
static void
roff_free1(struct roff *r)
{
- struct tbl_node *t;
+ struct tbl_node *tbl;
struct eqn_node *e;
int i;
- while (NULL != (t = r->first_tbl)) {
- r->first_tbl = t->next;
- tbl_free(t);
+ while (NULL != (tbl = r->first_tbl)) {
+ r->first_tbl = tbl->next;
+ tbl_free(tbl);
}
r->first_tbl = r->last_tbl = r->tbl = NULL;
@@ -377,6 +432,10 @@ roff_free1(struct roff *r)
r->strtab = r->xmbtab = NULL;
+ roff_freereg(r->regtab);
+
+ r->regtab = NULL;
+
if (r->xtab)
for (i = 0; i < 128; i++)
free(r->xtab[i].p);
@@ -392,7 +451,7 @@ roff_reset(struct roff *r)
roff_free1(r);
- memset(&r->regs, 0, sizeof(struct reg) * REG__MAX);
+ r->control = 0;
for (i = 0; i < PREDEFS_MAX; i++)
roff_setstr(r, predefs[i].name, predefs[i].str, 0);
@@ -409,12 +468,13 @@ roff_free(struct roff *r)
struct roff *
-roff_alloc(struct mparse *parse)
+roff_alloc(enum mparset type, struct mparse *parse)
{
struct roff *r;
int i;
r = mandoc_calloc(1, sizeof(struct roff));
+ r->parsetype = type;
r->parse = parse;
r->rstackpos = -1;
@@ -427,22 +487,23 @@ roff_alloc(struct mparse *parse)
}
/*
- * Pre-filter each and every line for reserved words (one beginning with
- * `\*', e.g., `\*(ab'). These must be handled before the actual line
- * is processed.
- * This also checks the syntax of regular escapes.
+ * In the current line, expand user-defined strings ("\*")
+ * and references to number registers ("\n").
+ * Also check the syntax of other escape sequences.
*/
static enum rofferr
roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
{
- enum mandoc_esc esc;
+ char ubuf[12]; /* buffer to print the number */
const char *stesc; /* start of an escape sequence ('\\') */
const char *stnam; /* start of the name, after "[(*" */
const char *cp; /* end of the name, e.g. before ']' */
const char *res; /* the string to be substituted */
- int i, maxl, expand_count;
- size_t nsz;
- char *n;
+ char *nbuf; /* new buffer to copy bufp to */
+ size_t nsz; /* size of the new buffer */
+ size_t maxl; /* expected length of the escape name */
+ size_t naml; /* actual length of the escape name */
+ int expand_count; /* to avoid infinite loops */
expand_count = 0;
@@ -452,7 +513,7 @@ again:
stesc = cp++;
/*
- * The second character must be an asterisk.
+ * The second character must be an asterisk or an n.
* If it isn't, skip it anyway: It is escaped,
* so it can't start another escape sequence.
*/
@@ -460,12 +521,16 @@ again:
if ('\0' == *cp)
return(ROFF_CONT);
- if ('*' != *cp) {
- res = cp;
- esc = mandoc_escape(&cp, NULL, NULL);
- if (ESCAPE_ERROR != esc)
+ switch (*cp) {
+ case ('*'):
+ res = NULL;
+ break;
+ case ('n'):
+ res = ubuf;
+ break;
+ default:
+ if (ESCAPE_ERROR != mandoc_escape(&cp, NULL, NULL))
continue;
- cp = res;
mandoc_msg
(MANDOCERR_BADESCAPE, r->parse,
ln, (int)(stesc - *bufp), NULL);
@@ -476,7 +541,7 @@ again:
/*
* The third character decides the length
- * of the name of the string.
+ * of the name of the string or register.
* Save a pointer to the name.
*/
@@ -499,7 +564,7 @@ again:
/* Advance to the end of the name. */
- for (i = 0; 0 == maxl || i < maxl; i++, cp++) {
+ for (naml = 0; 0 == maxl || naml < maxl; naml++, cp++) {
if ('\0' == *cp) {
mandoc_msg
(MANDOCERR_BADESCAPE,
@@ -516,7 +581,11 @@ again:
* undefined, resume searching for escapes.
*/
- res = roff_getstrn(r, stnam, (size_t)i);
+ if (NULL == res)
+ res = roff_getstrn(r, stnam, naml);
+ else
+ snprintf(ubuf, sizeof(ubuf), "%d",
+ roff_getregn(r, stnam, naml));
if (NULL == res) {
mandoc_msg
@@ -530,15 +599,15 @@ again:
pos = stesc - *bufp;
nsz = *szp + strlen(res) + 1;
- n = mandoc_malloc(nsz);
+ nbuf = mandoc_malloc(nsz);
- strlcpy(n, *bufp, (size_t)(stesc - *bufp + 1));
- strlcat(n, res, nsz);
- strlcat(n, cp + (maxl ? 0 : 1), nsz);
+ strlcpy(nbuf, *bufp, (size_t)(stesc - *bufp + 1));
+ strlcat(nbuf, res, nsz);
+ strlcat(nbuf, cp + (maxl ? 0 : 1), nsz);
free(*bufp);
- *bufp = n;
+ *bufp = nbuf;
*szp = nsz;
if (EXPAND_LIMIT >= ++expand_count)
@@ -552,16 +621,20 @@ again:
}
/*
- * Process text streams: convert all breakable hyphens into ASCII_HYPH.
+ * Process text streams:
+ * Convert all breakable hyphens into ASCII_HYPH.
+ * Decrement and spring input line trap.
*/
static enum rofferr
-roff_parsetext(char *p)
+roff_parsetext(char **bufp, size_t *szp, int pos, int *offs)
{
size_t sz;
const char *start;
+ char *p;
+ int isz;
enum mandoc_esc esc;
- start = p;
+ start = p = *bufp + pos;
while ('\0' != *p) {
sz = strcspn(p, "-\\");
@@ -574,7 +647,7 @@ roff_parsetext(char *p)
/* Skip over escapes. */
p++;
esc = mandoc_escape
- ((const char **)&p, NULL, NULL);
+ ((const char const **)&p, NULL, NULL);
if (ESCAPE_ERROR == esc)
break;
continue;
@@ -589,6 +662,22 @@ roff_parsetext(char *p)
p++;
}
+ /* Spring the input line trap. */
+ if (1 == roffit_lines) {
+ isz = asprintf(&p, "%s\n.%s", *bufp, roffit_macro);
+ if (-1 == isz) {
+ perror(NULL);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ free(*bufp);
+ *bufp = p;
+ *szp = isz + 1;
+ *offs = 0;
+ free(roffit_macro);
+ roffit_lines = 0;
+ return(ROFF_REPARSE);
+ } else if (1 < roffit_lines)
+ --roffit_lines;
return(ROFF_CONT);
}
@@ -611,7 +700,7 @@ roff_parseln(struct roff *r, int ln, char **bufp,
assert(ROFF_CONT == e);
ppos = pos;
- ctl = mandoc_getcontrol(*bufp, &pos);
+ ctl = roff_getcontrol(r, *bufp, &pos);
/*
* First, if a scope is open and we're not a macro, pass the
@@ -629,19 +718,14 @@ roff_parseln(struct roff *r, int ln, char **bufp,
assert(ROFF_IGN == e || ROFF_CONT == e);
if (ROFF_CONT != e)
return(e);
- if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
- if (r->tbl)
- return(tbl_read(r->tbl, ln, *bufp, pos));
- return(roff_parsetext(*bufp + pos));
- } else if ( ! ctl) {
- if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
+ }
+ if (r->eqn)
+ return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
+ if ( ! ctl) {
if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, pos));
- return(roff_parsetext(*bufp + pos));
- } else if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
+ return(roff_parsetext(bufp, szp, pos, offs));
+ }
/*
* If a scope is open, go to the child handler for that macro,
@@ -778,7 +862,7 @@ roffnode_cleanscope(struct roff *r)
{
while (r->last) {
- if (--r->last->endspan < 0)
+ if (--r->last->endspan != 0)
break;
roffnode_pop(r);
}
@@ -984,57 +1068,45 @@ roff_cond_sub(ROFF_ARGS)
rr = r->last->rule;
roffnode_cleanscope(r);
+ t = roff_parse(r, *bufp, &pos);
/*
- * If the macro is unknown, first check if it contains a closing
- * delimiter `\}'. If it does, close out our scope and return
- * the currently-scoped rule (ignore or continue). Else, drop
- * into the currently-scoped rule.
+ * Fully handle known macros when they are structurally
+ * required or when the conditional evaluated to true.
*/
- if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) {
- ep = &(*bufp)[pos];
- for ( ; NULL != (ep = strchr(ep, '\\')); ep++) {
- ep++;
- if ('}' != *ep)
- continue;
-
- /*
- * Make the \} go away.
- * This is a little haphazard, as it's not quite
- * clear how nroff does this.
- * If we're at the end of line, then just chop
- * off the \} and resize the buffer.
- * If we aren't, then conver it to spaces.
- */
+ if ((ROFF_MAX != t) &&
+ (ROFF_ccond == t || ROFFRULE_ALLOW == rr ||
+ ROFFMAC_STRUCT & roffs[t].flags)) {
+ assert(roffs[t].proc);
+ return((*roffs[t].proc)(r, t, bufp, szp,
+ ln, ppos, pos, offs));
+ }
- if ('\0' == *(ep + 1)) {
- *--ep = '\0';
- *szp -= 2;
- } else
- *(ep - 1) = *ep = ' ';
+ /* Always check for the closing delimiter `\}'. */
- roff_ccond(r, ROFF_ccond, bufp, szp,
- ln, pos, pos + 2, offs);
- break;
- }
- return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
- }
+ ep = &(*bufp)[pos];
+ while (NULL != (ep = strchr(ep, '\\'))) {
+ if ('}' != *(++ep))
+ continue;
- /*
- * A denied conditional must evaluate its children if and only
- * if they're either structurally required (such as loops and
- * conditionals) or a closing macro.
- */
+ /*
+ * If we're at the end of line, then just chop
+ * off the \} and resize the buffer.
+ * If we aren't, then convert it to spaces.
+ */
- if (ROFFRULE_DENY == rr)
- if ( ! (ROFFMAC_STRUCT & roffs[t].flags))
- if (ROFF_ccond != t)
- return(ROFF_IGN);
+ if ('\0' == *(ep + 1)) {
+ *--ep = '\0';
+ *szp -= 2;
+ } else
+ *(ep - 1) = *ep = ' ';
- assert(roffs[t].proc);
- return((*roffs[t].proc)(r, t, bufp, szp,
- ln, ppos, pos, offs));
+ roff_ccond(r, ROFF_ccond, bufp, szp,
+ ln, pos, pos + 2, offs);
+ break;
+ }
+ return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
}
/* ARGSUSED */
@@ -1059,9 +1131,61 @@ roff_cond_text(ROFF_ARGS)
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
}
+static int
+roff_getnum(const char *v, int *pos, int *res)
+{
+ int p, n;
+
+ p = *pos;
+ n = v[p] == '-';
+ if (n)
+ p++;
+
+ for (*res = 0; isdigit((unsigned char)v[p]); p++)
+ *res += 10 * *res + v[p] - '0';
+ if (p == *pos + n)
+ return 0;
+
+ if (n)
+ *res = -*res;
+
+ *pos = p;
+ return 1;
+}
+
+static int
+roff_getop(const char *v, int *pos, char *res)
+{
+ int e;
+
+ *res = v[*pos];
+ e = v[*pos + 1] == '=';
+
+ switch (*res) {
+ case '=':
+ break;
+ case '>':
+ if (e)
+ *res = 'g';
+ break;
+ case '<':
+ if (e)
+ *res = 'l';
+ break;
+ default:
+ return(0);
+ }
+
+ *pos += 1 + e;
+
+ return(*res);
+}
+
static enum roffrule
roff_evalcond(const char *v, int *pos)
{
+ int not, lh, rh;
+ char op;
switch (v[*pos]) {
case ('n'):
@@ -1074,13 +1198,47 @@ roff_evalcond(const char *v, int *pos)
case ('t'):
(*pos)++;
return(ROFFRULE_DENY);
+ case ('!'):
+ (*pos)++;
+ not = 1;
+ break;
default:
+ not = 0;
break;
}
- while (v[*pos] && ' ' != v[*pos])
- (*pos)++;
- return(ROFFRULE_DENY);
+ if (!roff_getnum(v, pos, &lh))
+ return ROFFRULE_DENY;
+ if (!roff_getop(v, pos, &op)) {
+ if (lh < 0)
+ lh = 0;
+ goto out;
+ }
+ if (!roff_getnum(v, pos, &rh))
+ return ROFFRULE_DENY;
+ switch (op) {
+ case 'g':
+ lh = lh >= rh;
+ break;
+ case 'l':
+ lh = lh <= rh;
+ break;
+ case '=':
+ lh = lh == rh;
+ break;
+ case '>':
+ lh = lh > rh;
+ break;
+ case '<':
+ lh = lh < rh;
+ break;
+ default:
+ return ROFFRULE_DENY;
+ }
+out:
+ if (not)
+ lh = !lh;
+ return lh ? ROFFRULE_ALLOW : ROFFRULE_DENY;
}
/* ARGSUSED */
@@ -1088,9 +1246,6 @@ static enum rofferr
roff_line_ignore(ROFF_ARGS)
{
- if (ROFF_it == tok)
- mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos, "it");
-
return(ROFF_IGN);
}
@@ -1098,8 +1253,8 @@ roff_line_ignore(ROFF_ARGS)
static enum rofferr
roff_cond(ROFF_ARGS)
{
- int sv;
- enum roffrule rule;
+
+ roffnode_push(r, tok, NULL, ln, ppos);
/*
* An `.el' has no conditional body: it will consume the value
@@ -1109,31 +1264,11 @@ roff_cond(ROFF_ARGS)
* If we're not an `el', however, then evaluate the conditional.
*/
- rule = ROFF_el == tok ?
+ r->last->rule = ROFF_el == tok ?
(r->rstackpos < 0 ?
ROFFRULE_DENY : r->rstack[r->rstackpos--]) :
roff_evalcond(*bufp, &pos);
- sv = pos;
- while (' ' == (*bufp)[pos])
- pos++;
-
- /*
- * Roff is weird. If we have just white-space after the
- * conditional, it's considered the BODY and we exit without
- * really doing anything. Warn about this. It's probably
- * wrong.
- */
-
- if ('\0' == (*bufp)[pos] && sv != pos) {
- mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL);
- return(ROFF_IGN);
- }
-
- roffnode_push(r, tok, NULL, ln, ppos);
-
- r->last->rule = rule;
-
/*
* An if-else will put the NEGATION of the current evaluated
* conditional into the stack of rules.
@@ -1156,28 +1291,39 @@ roff_cond(ROFF_ARGS)
r->last->rule = ROFFRULE_DENY;
/*
- * Determine scope. If we're invoked with "\{" trailing the
- * conditional, then we're in a multiline scope. Else our scope
- * expires on the next line.
+ * Determine scope.
+ * If there is nothing on the line after the conditional,
+ * not even whitespace, use next-line scope.
*/
- r->last->endspan = 1;
+ if ('\0' == (*bufp)[pos]) {
+ r->last->endspan = 2;
+ goto out;
+ }
+
+ while (' ' == (*bufp)[pos])
+ pos++;
+
+ /* An opening brace requests multiline scope. */
if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) {
r->last->endspan = -1;
pos += 2;
+ goto out;
}
/*
- * If there are no arguments on the line, the next-line scope is
- * assumed.
+ * Anything else following the conditional causes
+ * single-line scope. Warn if the scope contains
+ * nothing but trailing whitespace.
*/
if ('\0' == (*bufp)[pos])
- return(ROFF_IGN);
+ mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL);
- /* Otherwise re-run the roff parser after recalculating. */
+ r->last->endspan = 1;
+out:
*offs = pos;
return(ROFF_RERUN);
}
@@ -1213,25 +1359,71 @@ roff_ds(ROFF_ARGS)
return(ROFF_IGN);
}
+void
+roff_setreg(struct roff *r, const char *name, int val, char sign)
+{
+ struct roffreg *reg;
+
+ /* Search for an existing register with the same name. */
+ reg = r->regtab;
+
+ while (reg && strcmp(name, reg->key.p))
+ reg = reg->next;
+
+ if (NULL == reg) {
+ /* Create a new register. */
+ reg = mandoc_malloc(sizeof(struct roffreg));
+ reg->key.p = mandoc_strdup(name);
+ reg->key.sz = strlen(name);
+ reg->val = 0;
+ reg->next = r->regtab;
+ r->regtab = reg;
+ }
+
+ if ('+' == sign)
+ reg->val += val;
+ else if ('-' == sign)
+ reg->val -= val;
+ else
+ reg->val = val;
+}
+
int
-roff_regisset(const struct roff *r, enum regs reg)
+roff_getreg(const struct roff *r, const char *name)
{
+ struct roffreg *reg;
+
+ for (reg = r->regtab; reg; reg = reg->next)
+ if (0 == strcmp(name, reg->key.p))
+ return(reg->val);
- return(r->regs[(int)reg].set);
+ return(0);
}
-unsigned int
-roff_regget(const struct roff *r, enum regs reg)
+static int
+roff_getregn(const struct roff *r, const char *name, size_t len)
{
+ struct roffreg *reg;
- return(r->regs[(int)reg].u);
+ for (reg = r->regtab; reg; reg = reg->next)
+ if (len == reg->key.sz &&
+ 0 == strncmp(name, reg->key.p, len))
+ return(reg->val);
+
+ return(0);
}
-void
-roff_regunset(struct roff *r, enum regs reg)
+static void
+roff_freereg(struct roffreg *reg)
{
+ struct roffreg *old_reg;
- r->regs[(int)reg].set = 0;
+ while (NULL != reg) {
+ free(reg->key.p);
+ old_reg = reg;
+ reg = reg->next;
+ free(old_reg);
+ }
}
/* ARGSUSED */
@@ -1240,18 +1432,21 @@ roff_nr(ROFF_ARGS)
{
const char *key;
char *val;
+ size_t sz;
int iv;
+ char sign;
val = *bufp + pos;
key = roff_getname(r, &val, ln, pos);
- if (0 == strcmp(key, "nS")) {
- r->regs[(int)REG_nS].set = 1;
- if ((iv = mandoc_strntoi(val, strlen(val), 10)) >= 0)
- r->regs[(int)REG_nS].u = (unsigned)iv;
- else
- r->regs[(int)REG_nS].u = 0u;
- }
+ sign = *val;
+ if ('+' == sign || '-' == sign)
+ val++;
+
+ sz = strspn(val, "0123456789");
+ iv = sz ? mandoc_strntoi(val, sz, 10) : 0;
+
+ roff_setreg(r, key, iv, sign);
return(ROFF_IGN);
}
@@ -1274,6 +1469,57 @@ roff_rm(ROFF_ARGS)
/* ARGSUSED */
static enum rofferr
+roff_it(ROFF_ARGS)
+{
+ char *cp;
+ size_t len;
+ int iv;
+
+ /* Parse the number of lines. */
+ cp = *bufp + pos;
+ len = strcspn(cp, " \t");
+ cp[len] = '\0';
+ if ((iv = mandoc_strntoi(cp, len, 10)) <= 0) {
+ mandoc_msg(MANDOCERR_NUMERIC, r->parse,
+ ln, ppos, *bufp + 1);
+ return(ROFF_IGN);
+ }
+ cp += len + 1;
+
+ /* Arm the input line trap. */
+ roffit_lines = iv;
+ roffit_macro = mandoc_strdup(cp);
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_Dd(ROFF_ARGS)
+{
+ const char *const *cp;
+
+ if (MPARSE_MDOC != r->parsetype)
+ for (cp = __mdoc_reserved; *cp; cp++)
+ roff_setstr(r, *cp, NULL, 0);
+
+ return(ROFF_CONT);
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_TH(ROFF_ARGS)
+{
+ const char *const *cp;
+
+ if (MPARSE_MDOC != r->parsetype)
+ for (cp = __man_reserved; *cp; cp++)
+ roff_setstr(r, *cp, NULL, 0);
+
+ return(ROFF_CONT);
+}
+
+/* ARGSUSED */
+static enum rofferr
roff_TE(ROFF_ARGS)
{
@@ -1352,21 +1598,38 @@ roff_EN(ROFF_ARGS)
static enum rofferr
roff_TS(ROFF_ARGS)
{
- struct tbl_node *t;
+ struct tbl_node *tbl;
if (r->tbl) {
mandoc_msg(MANDOCERR_SCOPEBROKEN, r->parse, ln, ppos, NULL);
tbl_end(&r->tbl);
}
- t = tbl_alloc(ppos, ln, r->parse);
+ tbl = tbl_alloc(ppos, ln, r->parse);
if (r->last_tbl)
- r->last_tbl->next = t;
+ r->last_tbl->next = tbl;
else
- r->first_tbl = r->last_tbl = t;
+ r->first_tbl = r->last_tbl = tbl;
+
+ r->tbl = r->last_tbl = tbl;
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_cc(ROFF_ARGS)
+{
+ const char *p;
+
+ p = *bufp + pos;
+
+ if ('\0' == *p || '.' == (r->control = *p++))
+ r->control = 0;
+
+ if ('\0' != *p)
+ mandoc_msg(MANDOCERR_ARGCOUNT, r->parse, ln, ppos, NULL);
- r->tbl = r->last_tbl = t;
return(ROFF_IGN);
}
@@ -1470,7 +1733,7 @@ roff_userdef(ROFF_ARGS)
/*
* Collect pointers to macro argument strings
- * and null-terminate them.
+ * and NUL-terminate them.
*/
cp = *bufp + pos;
for (i = 0; i < 9; i++)
@@ -1766,3 +2029,38 @@ roff_strdup(const struct roff *r, const char *p)
res[(int)ssz] = '\0';
return(res);
}
+
+/*
+ * Find out whether a line is a macro line or not.
+ * If it is, adjust the current position and return one; if it isn't,
+ * return zero and don't change the current position.
+ * If the control character has been set with `.cc', then let that grain
+ * precedence.
+ * This is slighly contrary to groff, where using the non-breaking
+ * control character when `cc' has been invoked will cause the
+ * non-breaking macro contents to be printed verbatim.
+ */
+int
+roff_getcontrol(const struct roff *r, const char *cp, int *ppos)
+{
+ int pos;
+
+ pos = *ppos;
+
+ if (0 != r->control && cp[pos] == r->control)
+ pos++;
+ else if (0 != r->control)
+ return(0);
+ else if ('\\' == cp[pos] && '.' == cp[pos + 1])
+ pos += 2;
+ else if ('.' == cp[pos] || '\'' == cp[pos])
+ pos++;
+ else
+ return(0);
+
+ while (' ' == cp[pos] || '\t' == cp[pos])
+ pos++;
+
+ *ppos = pos;
+ return(1);
+}
diff --git a/st.in b/st.in
index 3ba41dd359d3..c52ddab9ba1c 100644
--- a/st.in
+++ b/st.in
@@ -1,4 +1,4 @@
-/* $Id: st.in,v 1.19 2012/02/26 21:47:09 schwarze Exp $ */
+/* $Id: st.in,v 1.22 2013/12/25 14:09:32 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -35,16 +35,19 @@ LINE("-p1003.1-2001", "IEEE Std 1003.1-2001 (\\(lqPOSIX.1\\(rq)")
LINE("-p1003.1-2004", "IEEE Std 1003.1-2004 (\\(lqPOSIX.1\\(rq)")
LINE("-p1003.1-2008", "IEEE Std 1003.1-2008 (\\(lqPOSIX.1\\(rq)")
LINE("-p1003.1", "IEEE Std 1003.1 (\\(lqPOSIX.1\\(rq)")
-LINE("-p1003.1b", "IEEE Std 1003.1b (\\(lqPOSIX.1\\(rq)")
-LINE("-p1003.1b-93", "IEEE Std 1003.1b-1993 (\\(lqPOSIX.1\\(rq)")
-LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(lqPOSIX.1\\(rq)")
-LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(lqPOSIX.1\\(rq)")
-LINE("-p1003.1i-95", "IEEE Std 1003.1i-1995 (\\(lqPOSIX.1\\(rq)")
+LINE("-p1003.1b", "IEEE Std 1003.1b (\\(lqPOSIX.1b\\(rq)")
+LINE("-p1003.1b-93", "IEEE Std 1003.1b-1993 (\\(lqPOSIX.1b\\(rq)")
+LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(lqPOSIX.1c\\(rq)")
+LINE("-p1003.1d-99", "IEEE Std 1003.1d-1999 (\\(lqPOSIX.1d\\(rq)")
+LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(lqPOSIX.1g\\(rq)")
+LINE("-p1003.1i-95", "IEEE Std 1003.1i-1995 (\\(lqPOSIX.1i\\(rq)")
+LINE("-p1003.1j-2000", "IEEE Std 1003.1j-2000 (\\(lqPOSIX.1j\\(rq)")
+LINE("-p1003.1q-2000", "IEEE Std 1003.1q-2000 (\\(lqPOSIX.1q\\(rq)")
+LINE("-p1003.2", "IEEE Std 1003.2 (\\(lqPOSIX.2\\(rq)")
LINE("-p1003.2-92", "IEEE Std 1003.2-1992 (\\(lqPOSIX.2\\(rq)")
LINE("-p1003.2a-92", "IEEE Std 1003.2a-1992 (\\(lqPOSIX.2\\(rq)")
-LINE("-p1387.2-95", "IEEE Std 1387.2-1995 (\\(lqPOSIX.7.2\\(rq)")
-LINE("-p1003.2", "IEEE Std 1003.2 (\\(lqPOSIX.2\\(rq)")
LINE("-p1387.2", "IEEE Std 1387.2 (\\(lqPOSIX.7.2\\(rq)")
+LINE("-p1387.2-95", "IEEE Std 1387.2-1995 (\\(lqPOSIX.7.2\\(rq)")
LINE("-isoC", "ISO/IEC 9899:1990 (\\(lqISO\\~C90\\(rq)")
LINE("-isoC-90", "ISO/IEC 9899:1990 (\\(lqISO\\~C90\\(rq)")
LINE("-isoC-amd1", "ISO/IEC 9899/AMD1:1995 (\\(lqISO\\~C90, Amendment 1\\(rq)")
@@ -68,11 +71,12 @@ LINE("-xpg4.2", "X/Open Portability Guide Issue\\~4, Version\\~2 (\\(lqXPG4.2\\
LINE("-xpg4.3", "X/Open Portability Guide Issue\\~4, Version\\~3 (\\(lqXPG4.3\\(rq)")
LINE("-xbd5", "X/Open Base Definitions Issue\\~5 (\\(lqXBD5\\(rq)")
LINE("-xcu5", "X/Open Commands and Utilities Issue\\~5 (\\(lqXCU5\\(rq)")
+LINE("-xsh4.2", "X/Open System Interfaces and Headers Issue\\~4, Version\\~2 (\\(lqXSH4.2\\(rq)")
LINE("-xsh5", "X/Open System Interfaces and Headers Issue\\~5 (\\(lqXSH5\\(rq)")
LINE("-xns5", "X/Open Networking Services Issue\\~5 (\\(lqXNS5\\(rq)")
LINE("-xns5.2", "X/Open Networking Services Issue\\~5.2 (\\(lqXNS5.2\\(rq)")
LINE("-xns5.2d2.0", "X/Open Networking Services Issue\\~5.2 Draft\\~2.0 (\\(lqXNS5.2D2.0\\(rq)")
LINE("-xcurses4.2", "X/Open Curses Issue\\~4, Version\\~2 (\\(lqXCURSES4.2\\(rq)")
-LINE("-susv2", "Version\\~2 of the Single UNIX Specification")
-LINE("-susv3", "Version\\~3 of the Single UNIX Specification")
+LINE("-susv2", "Version\\~2 of the Single UNIX Specification (\\(lqSUSv2\\(rq)")
+LINE("-susv3", "Version\\~3 of the Single UNIX Specification (\\(lqSUSv3\\(rq)")
LINE("-svid4", "System\\~V Interface Definition, Fourth Edition (\\(lqSVID4\\(rq)")
diff --git a/tbl.3 b/tbl.3
new file mode 100644
index 000000000000..05e423fe548e
--- /dev/null
+++ b/tbl.3
@@ -0,0 +1,295 @@
+.\" $Id: tbl.3,v 1.1 2013/06/01 05:44:39 schwarze Exp $
+.\"
+.\" Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: June 1 2013 $
+.Dt TBL 3
+.Os
+.Sh NAME
+.Nm tbl_alloc ,
+.Nm tbl_read ,
+.Nm tbl_restart ,
+.Nm tbl_span ,
+.Nm tbl_end ,
+.Nm tbl_free
+.Nd roff table parser library for mandoc
+.Sh SYNOPSIS
+.In mandoc.h
+.In libmandoc.h
+.In libroff.h
+.Ft struct tbl_node *
+.Fo tbl_alloc
+.Fa "int pos"
+.Fa "int line"
+.Fa "struct mparse *parse"
+.Fc
+.Ft enum rofferr
+.Fo tbl_read
+.Fa "struct tbl_node *tbl"
+.Fa "int ln"
+.Fa "const char *p"
+.Fa "int offs"
+.Fc
+.Ft void
+.Fo tbl_restart
+.Fa "int line"
+.Fa "int pos"
+.Fa "struct tbl_node *tbl"
+.Fc
+.Ft const struct tbl_span *
+.Fo tbl_span
+.Fa "struct tbl_node *tbl"
+.Fc
+.Ft void
+.Fo tbl_end
+.Fa "struct tbl_node **tblp"
+.Fc
+.Ft void
+.Fo tbl_free
+.Fa "struct tbl_node *tbl"
+.Fc
+.Sh DESCRIPTION
+This library is tightly integrated into the
+.Xr mandoc 1
+utility and not designed for stand-alone use.
+The present manual is intended as a reference for developers working on
+.Xr mandoc 1 .
+.Ss Data structures
+Unless otherwise noted, all of the following data structures are defined in
+.In mandoc.h
+and are deleted in
+.Fn tbl_free .
+.Bl -tag -width Ds
+.It Vt struct tbl_node
+This structure describes a complete table.
+It is defined in
+.In libroff.h ,
+created in
+.Fn tbl_alloc ,
+and stored in the members
+.Va first_tbl ,
+.Va last_tbl ,
+and
+.Va tbl
+of
+.Vt struct roff Bq Pa roff.c .
+.It Vt struct tbl_opts
+This structure describes the options of one table.
+It is used as a substructure of
+.Vt struct tbl_node
+and thus created and deleted together with it.
+It is filled in
+.Fn tbl_options .
+.It Vt struct tbl_head
+This structure describes one layout column in a table,
+in particular the vertical line to its left.
+It is allocated and filled in
+.Fn cell_alloc Bq Pa tbl_layout.c
+and referenced from the
+.Va first_head
+and
+.Va last_head
+members of
+.Vt struct tbl_node .
+.It Vt struct tbl_row
+This structure describes one layout line in a table
+by maintaining a list of all the cells in that line.
+It is allocated and filled in
+.Fn row Bq Pa tbl_layout.c
+and referenced from the
+.Va layout
+member of
+.Vt struct tbl_node .
+.It Vt struct tbl_cell
+This structure describes one layout cell in a table,
+in particular its alignment, membership in spans, and
+usage for lines.
+It is allocated and filled in
+.Fn cell_alloc Bq Pa tbl_layout.c
+and referenced from the
+.Va first
+and
+.Va last
+members of
+.Vt struct tbl_row .
+.It Vt struct tbl_span
+This structure describes one data line in a table
+by maintaining a list of all data cells in that line
+or by specifying that it is a horizontal line.
+It is allocated and filled in
+.Fn newspan Bq Pa tbl_data.c
+which is called from
+.Fn tbl_data
+and referenced from the
+.Va first_span ,
+.Va current_span ,
+and
+.Va last_span
+members of
+.Vt struct tbl_node ,
+and from the
+.Va span
+members of
+.Vt struct man_node
+and
+.Vt struct mdoc_node
+from
+.In man.h
+and
+.In mdoc.h .
+.It Vt struct tbl_dat
+This structure describes one data cell in a table by specifying
+whether it contains a line or data, whether it spans additional
+layout cells, and by storing the data.
+It is allocated and filled in
+.Fn data
+and referenced from the
+.Va first
+and
+.Va last
+members of
+.Vt struct tbl_span .
+.El
+.Ss Interface functions
+The following functions are implemented in
+.Pa tbl.c ,
+and all callers in
+.Pa roff.c .
+.Bl -tag -width Ds
+.It Fn tbl_alloc
+Allocates, initializes, and returns a new
+.Vt struct tbl_node .
+Called from
+.Fn roff_TS .
+.It Fn tbl_read
+Dispatches to
+.Fn tbl_option ,
+.Fn tbl_layout ,
+.Fn tbl_cdata ,
+and
+.Fn tbl_data ,
+see below.
+Called from
+.Fn roff_parseln .
+.It Fn tbl_restart
+Resets the
+.Va part
+member of
+.Vt struct tbl_node
+to
+.Dv TBL_PART_LAYOUT .
+Called from
+.Fn roff_T_ .
+.It Fn tbl_span
+On the first call, return the first
+.Vt struct tbl_span ;
+for later calls, return the next one or
+.Dv NULL .
+Called from
+.Fn roff_span .
+.It Fn tbl_end
+Flags the last span as
+.Dv TBL_SPAN_LAST
+and clears the pointer passed as an argment.
+Called from
+.Fn roff_TE
+and
+.Fn roff_endparse .
+.It Fn tbl_free
+Frees the specified
+.Vt struct tbl_node
+and all the tbl_row, tbl_cell, tbl_span, tbl_dat and tbl_head structures
+referenced from it.
+Called from
+.Fn roff_free
+and
+.Fn roff_reset .
+.El
+.Ss Private functions
+.Bl -tag -width Ds
+.It Ft int Fn tbl_options "struct tbl_node *tbl" "int ln" "const char *p"
+Parses the options line into
+.Vt struct tbl_opts .
+Implemented in
+.Pa tbl_opts.c ,
+called from
+.Fn tbl_read .
+.It Ft int Fn tbl_layout "struct tbl_node *tbl" "int ln" "const char *p"
+Allocates and fills one
+.Vt struct tbl_head
+for each layout column, one
+.Vt struct tbl_row
+for each layout line, and one
+.Vt struct tbl_cell
+for each layout cell.
+Implemented in
+.Pa tbl_layout.c ,
+called from
+.Fn tbl_read .
+.It Ft int Fn tbl_data "struct tbl_node *tbl" "int ln" "const char *p"
+Allocates one
+.Vt struct tbl_span
+for each data line and calls
+.Fn data
+on that line.
+Implemented in
+.Pa tbl_data.c ,
+called from
+.Fn tbl_read .
+.It Ft int Fn tbl_cdata "struct tbl_node *tbl" "int ln" "const char *p"
+Continues parsing a data line:
+When finding
+.Sq T} ,
+switches back to
+.Dv TBL_PART_DATA
+mode and calls
+.Fn data
+if there are more data cells on the line.
+Otherwise, appends the data to the current data cell.
+Implemented in
+.Pa tbl_data.c ,
+called from
+.Fn tbl_read .
+.It Xo
+.Ft int
+.Fo data
+.Fa "struct tbl_node *tbl"
+.Fa "struct tbl_span *dp"
+.Fa "int ln"
+.Fa "const char *p"
+.Fa "int *pos"
+.Fc
+.Xc
+Parses one data cell into one
+.Vt struct tbl_dat .
+Implemented in
+.Pa tbl_data.c ,
+called from
+.Fn tbl_data
+and
+.Fn tbl_cdata .
+.El
+.Sh SEE ALSO
+.Xr mandoc 1 ,
+.Xr mandoc 3 ,
+.Xr tbl 7
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm tbl
+library was written by
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
+with contributions from
+.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
diff --git a/tbl.7 b/tbl.7
index ea3d2ba3a8b6..d4c829bfddf5 100644
--- a/tbl.7
+++ b/tbl.7
@@ -1,4 +1,4 @@
-.\" $Id: tbl.7,v 1.16 2011/09/03 00:29:21 kristaps Exp $
+.\" $Id: tbl.7,v 1.18 2013/09/16 22:39:19 schwarze Exp $
.\"
.\" Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -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: September 3 2011 $
+.Dd $Mdocdate: September 16 2013 $
.Dt TBL 7
.Os
.Sh NAME
@@ -69,13 +69,6 @@ c5 c5 c5.
4:5:6
.TE
.Ed
-.Pp
-The
-.Nm
-implementation in
-.Xr mandoc 1
-is
-.Ud
.Sh TABLE STRUCTURE
Tables are enclosed by the
.Sq TS
@@ -344,5 +337,4 @@ utility.
This
.Nm
reference was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
diff --git a/tbl.c b/tbl.c
index b3d651be07ad..b244ac80acfa 100644
--- a/tbl.c
+++ b/tbl.c
@@ -1,4 +1,4 @@
-/* $Id: tbl.c,v 1.26 2011/07/25 15:37:00 kristaps Exp $ */
+/* $Id: tbl.c,v 1.27 2013/05/31 22:08:09 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -72,21 +72,21 @@ tbl_read(struct tbl_node *tbl, int ln, const char *p, int offs)
struct tbl_node *
tbl_alloc(int pos, int line, struct mparse *parse)
{
- struct tbl_node *p;
-
- p = mandoc_calloc(1, sizeof(struct tbl_node));
- p->line = line;
- p->pos = pos;
- p->parse = parse;
- p->part = TBL_PART_OPTS;
- p->opts.tab = '\t';
- p->opts.linesize = 12;
- p->opts.decimal = '.';
- return(p);
+ struct tbl_node *tbl;
+
+ tbl = mandoc_calloc(1, sizeof(struct tbl_node));
+ tbl->line = line;
+ tbl->pos = pos;
+ tbl->parse = parse;
+ tbl->part = TBL_PART_OPTS;
+ tbl->opts.tab = '\t';
+ tbl->opts.linesize = 12;
+ tbl->opts.decimal = '.';
+ return(tbl);
}
void
-tbl_free(struct tbl_node *p)
+tbl_free(struct tbl_node *tbl)
{
struct tbl_row *rp;
struct tbl_cell *cp;
@@ -94,8 +94,8 @@ tbl_free(struct tbl_node *p)
struct tbl_dat *dp;
struct tbl_head *hp;
- while (NULL != (rp = p->first_row)) {
- p->first_row = rp->next;
+ while (NULL != (rp = tbl->first_row)) {
+ tbl->first_row = rp->next;
while (rp->first) {
cp = rp->first;
rp->first = cp->next;
@@ -104,8 +104,8 @@ tbl_free(struct tbl_node *p)
free(rp);
}
- while (NULL != (sp = p->first_span)) {
- p->first_span = sp->next;
+ while (NULL != (sp = tbl->first_span)) {
+ tbl->first_span = sp->next;
while (sp->first) {
dp = sp->first;
sp->first = dp->next;
@@ -116,12 +116,12 @@ tbl_free(struct tbl_node *p)
free(sp);
}
- while (NULL != (hp = p->first_head)) {
- p->first_head = hp->next;
+ while (NULL != (hp = tbl->first_head)) {
+ tbl->first_head = hp->next;
free(hp);
}
- free(p);
+ free(tbl);
}
void
diff --git a/tbl_data.c b/tbl_data.c
index 129695d8bb96..7413aa2d83dd 100644
--- a/tbl_data.c
+++ b/tbl_data.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_data.c,v 1.24 2011/03/20 16:02:05 kristaps Exp $ */
+/* $Id: tbl_data.c,v 1.27 2013/06/01 04:56:50 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -49,13 +49,11 @@ data(struct tbl_node *tbl, struct tbl_span *dp,
cp = dp->layout->first;
/*
- * Skip over spanners and vertical lines to data formats, since
+ * Skip over spanners, since
* we want to match data with data layout cells in the header.
*/
- while (cp && (TBL_CELL_VERT == cp->pos ||
- TBL_CELL_DVERT == cp->pos ||
- TBL_CELL_SPAN == cp->pos))
+ while (cp && TBL_CELL_SPAN == cp->pos)
cp = cp->next;
/*
@@ -104,7 +102,7 @@ data(struct tbl_node *tbl, struct tbl_span *dp,
if (*pos - sv == 2 && 'T' == p[sv] && '{' == p[sv + 1]) {
tbl->part = TBL_PART_CDATA;
- return(0);
+ return(1);
}
assert(*pos - sv >= 0);
@@ -187,7 +185,7 @@ newspan(struct tbl_node *tbl, int line, struct tbl_row *rp)
dp = mandoc_calloc(1, sizeof(struct tbl_span));
dp->line = line;
- dp->tbl = &tbl->opts;
+ dp->opts = &tbl->opts;
dp->layout = rp;
dp->head = tbl->first_head;
diff --git a/tbl_html.c b/tbl_html.c
index 8e7dc05de0db..6b8ced716b11 100644
--- a/tbl_html.c
+++ b/tbl_html.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_html.c,v 1.9 2011/09/18 14:14:15 schwarze Exp $ */
+/* $Id: tbl_html.c,v 1.10 2012/05/27 17:54:54 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -119,20 +119,12 @@ print_tbl(struct html *h, const struct tbl_span *sp)
print_stagq(h, tt);
print_otag(h, TAG_TD, 0, NULL);
- switch (hp->pos) {
- case (TBL_HEAD_VERT):
- /* FALLTHROUGH */
- case (TBL_HEAD_DVERT):
- continue;
- case (TBL_HEAD_DATA):
- if (NULL == dp)
- break;
- if (TBL_CELL_DOWN != dp->layout->pos)
- if (dp->string)
- print_text(h, dp->string);
- dp = dp->next;
+ if (NULL == dp)
break;
- }
+ if (TBL_CELL_DOWN != dp->layout->pos)
+ if (dp->string)
+ print_text(h, dp->string);
+ dp = dp->next;
}
break;
}
diff --git a/tbl_layout.c b/tbl_layout.c
index 7601f146cad6..6cce977fa2e7 100644
--- a/tbl_layout.c
+++ b/tbl_layout.c
@@ -1,6 +1,7 @@
-/* $Id: tbl_layout.c,v 1.22 2011/09/18 14:14:15 schwarze Exp $ */
+/* $Id: tbl_layout.c,v 1.23 2012/05/27 17:54:54 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2012 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
@@ -51,8 +52,7 @@ static const struct tbl_phrase keys[KEYS_MAX] = {
{ '^', TBL_CELL_DOWN },
{ '-', TBL_CELL_HORIZ },
{ '_', TBL_CELL_HORIZ },
- { '=', TBL_CELL_DHORIZ },
- { '|', TBL_CELL_VERT }
+ { '=', TBL_CELL_DHORIZ }
};
static int mods(struct tbl_node *, struct tbl_cell *,
@@ -60,10 +60,8 @@ static int mods(struct tbl_node *, struct tbl_cell *,
static int cell(struct tbl_node *, struct tbl_row *,
int, const char *, int *);
static void row(struct tbl_node *, int, const char *, int *);
-static struct tbl_cell *cell_alloc(struct tbl_node *,
- struct tbl_row *, enum tbl_cellt);
-static void head_adjust(const struct tbl_cell *,
- struct tbl_head *);
+static struct tbl_cell *cell_alloc(struct tbl_node *, struct tbl_row *,
+ enum tbl_cellt, int vert);
static int
mods(struct tbl_node *tbl, struct tbl_cell *cp,
@@ -80,10 +78,6 @@ mods(struct tbl_node *tbl, struct tbl_cell *cp,
case (TBL_CELL_HORIZ):
/* FALLTHROUGH */
case (TBL_CELL_DHORIZ):
- /* FALLTHROUGH */
- case (TBL_CELL_VERT):
- /* FALLTHROUGH */
- case (TBL_CELL_DVERT):
return(1);
default:
break;
@@ -214,10 +208,17 @@ static int
cell(struct tbl_node *tbl, struct tbl_row *rp,
int ln, const char *p, int *pos)
{
- int i;
+ int vert, i;
enum tbl_cellt c;
- /* Parse the column position (`r', `R', `|', ...). */
+ /* Handle vertical lines. */
+
+ for (vert = 0; '|' == p[*pos]; ++*pos)
+ vert++;
+ while (' ' == p[*pos])
+ (*pos)++;
+
+ /* Parse the column position (`c', `l', `r', ...). */
for (i = 0; i < KEYS_MAX; i++)
if (tolower((unsigned char)p[*pos]) == keys[i].name)
@@ -246,8 +247,6 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
return(0);
} else if (rp->last)
switch (rp->last->pos) {
- case (TBL_CELL_VERT):
- case (TBL_CELL_DVERT):
case (TBL_CELL_HORIZ):
case (TBL_CELL_DHORIZ):
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
@@ -270,25 +269,16 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
(*pos)++;
- /* Extra check for the double-vertical. */
-
- if (TBL_CELL_VERT == c && '|' == p[*pos]) {
- (*pos)++;
- c = TBL_CELL_DVERT;
- }
-
/* Disallow adjacent spacers. */
- if (rp->last && (TBL_CELL_VERT == c || TBL_CELL_DVERT == c) &&
- (TBL_CELL_VERT == rp->last->pos ||
- TBL_CELL_DVERT == rp->last->pos)) {
+ if (vert > 2) {
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos - 1, NULL);
return(0);
}
/* Allocate cell then parse its modifiers. */
- return(mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos));
+ return(mods(tbl, cell_alloc(tbl, rp, c, vert), ln, p, pos));
}
@@ -308,11 +298,11 @@ row: /*
*/
rp = mandoc_calloc(1, sizeof(struct tbl_row));
- if (tbl->last_row) {
+ if (tbl->last_row)
tbl->last_row->next = rp;
- tbl->last_row = rp;
- } else
- tbl->last_row = tbl->first_row = rp;
+ else
+ tbl->first_row = rp;
+ tbl->last_row = rp;
cell:
while (isspace((unsigned char)p[*pos]))
@@ -357,7 +347,8 @@ tbl_layout(struct tbl_node *tbl, int ln, const char *p)
}
static struct tbl_cell *
-cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
+cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos,
+ int vert)
{
struct tbl_cell *p, *pp;
struct tbl_head *h, *hp;
@@ -365,108 +356,35 @@ cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
p = mandoc_calloc(1, sizeof(struct tbl_cell));
if (NULL != (pp = rp->last)) {
- rp->last->next = p;
- rp->last = p;
- } else
- rp->last = rp->first = p;
+ pp->next = p;
+ h = pp->head->next;
+ } else {
+ rp->first = p;
+ h = tbl->first_head;
+ }
+ rp->last = p;
p->pos = pos;
+ p->vert = vert;
- /*
- * This is a little bit complicated. Here we determine the
- * header the corresponds to a cell. We add headers dynamically
- * when need be or re-use them, otherwise. As an example, given
- * the following:
- *
- * 1 c || l
- * 2 | c | l
- * 3 l l
- * 3 || c | l |.
- *
- * We first add the new headers (as there are none) in (1); then
- * in (2) we insert the first spanner (as it doesn't match up
- * with the header); then we re-use the prior data headers,
- * skipping over the spanners; then we re-use everything and add
- * a last spanner. Note that VERT headers are made into DVERT
- * ones.
- */
-
- h = pp ? pp->head->next : tbl->first_head;
+ /* Re-use header. */
if (h) {
- /* Re-use data header. */
- if (TBL_HEAD_DATA == h->pos &&
- (TBL_CELL_VERT != p->pos &&
- TBL_CELL_DVERT != p->pos)) {
- p->head = h;
- return(p);
- }
-
- /* Re-use spanner header. */
- if (TBL_HEAD_DATA != h->pos &&
- (TBL_CELL_VERT == p->pos ||
- TBL_CELL_DVERT == p->pos)) {
- head_adjust(p, h);
- p->head = h;
- return(p);
- }
-
- /* Right-shift headers with a new spanner. */
- if (TBL_HEAD_DATA == h->pos &&
- (TBL_CELL_VERT == p->pos ||
- TBL_CELL_DVERT == p->pos)) {
- hp = mandoc_calloc(1, sizeof(struct tbl_head));
- hp->ident = tbl->opts.cols++;
- hp->prev = h->prev;
- if (h->prev)
- h->prev->next = hp;
- if (h == tbl->first_head)
- tbl->first_head = hp;
- h->prev = hp;
- hp->next = h;
- head_adjust(p, hp);
- p->head = hp;
- return(p);
- }
-
- if (NULL != (h = h->next)) {
- head_adjust(p, h);
- p->head = h;
- return(p);
- }
-
- /* Fall through to default case... */
+ p->head = h;
+ return(p);
}
hp = mandoc_calloc(1, sizeof(struct tbl_head));
hp->ident = tbl->opts.cols++;
+ hp->vert = vert;
if (tbl->last_head) {
hp->prev = tbl->last_head;
tbl->last_head->next = hp;
- tbl->last_head = hp;
} else
- tbl->last_head = tbl->first_head = hp;
+ tbl->first_head = hp;
+ tbl->last_head = hp;
- head_adjust(p, hp);
p->head = hp;
return(p);
}
-
-static void
-head_adjust(const struct tbl_cell *cellp, struct tbl_head *head)
-{
- if (TBL_CELL_VERT != cellp->pos &&
- TBL_CELL_DVERT != cellp->pos) {
- head->pos = TBL_HEAD_DATA;
- return;
- }
-
- if (TBL_CELL_VERT == cellp->pos)
- if (TBL_HEAD_DVERT != head->pos)
- head->pos = TBL_HEAD_VERT;
-
- if (TBL_CELL_DVERT == cellp->pos)
- head->pos = TBL_HEAD_DVERT;
-}
-
diff --git a/tbl_term.c b/tbl_term.c
index f1928f02cb20..e8411ffeceaa 100644
--- a/tbl_term.c
+++ b/tbl_term.c
@@ -1,7 +1,7 @@
-/* $Id: tbl_term.c,v 1.21 2011/09/20 23:05:49 schwarze Exp $ */
+/* $Id: tbl_term.c,v 1.25 2013/05/31 21:37:17 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2012 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
@@ -31,14 +31,14 @@
static size_t term_tbl_len(size_t, void *);
static size_t term_tbl_strlen(const char *, void *);
static void tbl_char(struct termp *, char, size_t);
-static void tbl_data(struct termp *, const struct tbl *,
+static void tbl_data(struct termp *, const struct tbl_opts *,
const struct tbl_dat *,
const struct roffcol *);
static size_t tbl_rulewidth(struct termp *, const struct tbl_head *);
static void tbl_hframe(struct termp *, const struct tbl_span *, int);
static void tbl_literal(struct termp *, const struct tbl_dat *,
const struct roffcol *);
-static void tbl_number(struct termp *, const struct tbl *,
+static void tbl_number(struct termp *, const struct tbl_opts *,
const struct tbl_dat *,
const struct roffcol *);
static void tbl_hrule(struct termp *, const struct tbl_span *);
@@ -96,16 +96,16 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
/* Horizontal frame at the start of boxed tables. */
if (TBL_SPAN_FIRST & sp->flags) {
- if (TBL_OPT_DBOX & sp->tbl->opts)
+ if (TBL_OPT_DBOX & sp->opts->opts)
tbl_hframe(tp, sp, 1);
- if (TBL_OPT_DBOX & sp->tbl->opts ||
- TBL_OPT_BOX & sp->tbl->opts)
+ if (TBL_OPT_DBOX & sp->opts->opts ||
+ TBL_OPT_BOX & sp->opts->opts)
tbl_hframe(tp, sp, 0);
}
/* Vertical frame at the start of each row. */
- if (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts)
+ if (TBL_OPT_BOX & sp->opts->opts || TBL_OPT_DBOX & sp->opts->opts)
term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
TBL_SPAN_DHORIZ == sp->pos ? "+" : "|");
@@ -126,49 +126,23 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
dp = sp->first;
spans = 0;
for (hp = sp->head; hp; hp = hp->next) {
+
/*
* If the current data header is invoked during
* a spanner ("spans" > 0), don't emit anything
* at all.
*/
- switch (hp->pos) {
- case (TBL_HEAD_VERT):
- /* FALLTHROUGH */
- case (TBL_HEAD_DVERT):
- if (spans <= 0)
- tbl_vrule(tp, hp);
- continue;
- case (TBL_HEAD_DATA):
- break;
- }
if (--spans >= 0)
continue;
- /*
- * All cells get a leading blank, except the
- * first one and those after double rulers.
- */
+ /* Separate columns. */
- if (hp->prev && TBL_HEAD_DVERT != hp->prev->pos)
- tbl_char(tp, ASCII_NBRSP, 1);
+ if (NULL != hp->prev)
+ tbl_vrule(tp, hp);
col = &tp->tbl.cols[hp->ident];
- tbl_data(tp, sp->tbl, dp, col);
-
- /* No trailing blanks. */
-
- if (NULL == hp->next)
- break;
-
- /*
- * Add another blank between cells,
- * or two when there is no vertical ruler.
- */
-
- tbl_char(tp, ASCII_NBRSP,
- TBL_HEAD_VERT == hp->next->pos ||
- TBL_HEAD_DVERT == hp->next->pos ? 1 : 2);
+ tbl_data(tp, sp->opts, dp, col);
/*
* Go to the next data cell and assign the
@@ -185,7 +159,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
/* Vertical frame at the end of each row. */
- if (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts)
+ if (TBL_OPT_BOX & sp->opts->opts || TBL_OPT_DBOX & sp->opts->opts)
term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
TBL_SPAN_DHORIZ == sp->pos ? "+" : " |");
term_flushln(tp);
@@ -196,11 +170,15 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
*/
if (TBL_SPAN_LAST & sp->flags) {
- if (TBL_OPT_DBOX & sp->tbl->opts ||
- TBL_OPT_BOX & sp->tbl->opts)
+ if (TBL_OPT_DBOX & sp->opts->opts ||
+ TBL_OPT_BOX & sp->opts->opts) {
tbl_hframe(tp, sp, 0);
- if (TBL_OPT_DBOX & sp->tbl->opts)
+ tp->skipvsp = 1;
+ }
+ if (TBL_OPT_DBOX & sp->opts->opts) {
tbl_hframe(tp, sp, 1);
+ tp->skipvsp = 2;
+ }
assert(tp->tbl.cols);
free(tp->tbl.cols);
tp->tbl.cols = NULL;
@@ -222,17 +200,14 @@ tbl_rulewidth(struct termp *tp, const struct tbl_head *hp)
size_t width;
width = tp->tbl.cols[hp->ident].width;
- if (TBL_HEAD_DATA == hp->pos) {
- /* Account for leading blanks. */
- if (hp->prev && TBL_HEAD_DVERT != hp->prev->pos)
- width++;
- /* Account for trailing blanks. */
- width++;
- if (hp->next &&
- TBL_HEAD_VERT != hp->next->pos &&
- TBL_HEAD_DVERT != hp->next->pos)
- width++;
- }
+
+ /* Account for leading blanks. */
+ if (hp->prev)
+ width += 2 - hp->vert;
+
+ /* Account for trailing blank. */
+ width++;
+
return(width);
}
@@ -250,10 +225,11 @@ tbl_hrule(struct termp *tp, const struct tbl_span *sp)
if (TBL_SPAN_DHORIZ == sp->pos)
c = '=';
- for (hp = sp->head; hp; hp = hp->next)
- tbl_char(tp,
- TBL_HEAD_DATA == hp->pos ? c : '+',
- tbl_rulewidth(tp, hp));
+ for (hp = sp->head; hp; hp = hp->next) {
+ if (hp->prev && hp->vert)
+ tbl_char(tp, '+', hp->vert);
+ tbl_char(tp, c, tbl_rulewidth(tp, hp));
+ }
}
/*
@@ -268,16 +244,17 @@ tbl_hframe(struct termp *tp, const struct tbl_span *sp, int outer)
const struct tbl_head *hp;
term_word(tp, "+");
- for (hp = sp->head; hp; hp = hp->next)
- tbl_char(tp,
- outer || TBL_HEAD_DATA == hp->pos ? '-' : '+',
- tbl_rulewidth(tp, hp));
+ for (hp = sp->head; hp; hp = hp->next) {
+ if (hp->prev && hp->vert)
+ tbl_char(tp, (outer ? '-' : '+'), hp->vert);
+ tbl_char(tp, '-', tbl_rulewidth(tp, hp));
+ }
term_word(tp, "+");
term_flushln(tp);
}
static void
-tbl_data(struct termp *tp, const struct tbl *tbl,
+tbl_data(struct termp *tp, const struct tbl_opts *opts,
const struct tbl_dat *dp,
const struct roffcol *col)
{
@@ -323,7 +300,7 @@ tbl_data(struct termp *tp, const struct tbl *tbl,
tbl_literal(tp, dp, col);
break;
case (TBL_CELL_NUMBER):
- tbl_number(tp, tbl, dp, col);
+ tbl_number(tp, opts, dp, col);
break;
case (TBL_CELL_DOWN):
tbl_char(tp, ASCII_NBRSP, col->width);
@@ -338,16 +315,11 @@ static void
tbl_vrule(struct termp *tp, const struct tbl_head *hp)
{
- switch (hp->pos) {
- case (TBL_HEAD_VERT):
- term_word(tp, "|");
- break;
- case (TBL_HEAD_DVERT):
- term_word(tp, "||");
- break;
- default:
- break;
- }
+ tbl_char(tp, ASCII_NBRSP, 1);
+ if (0 < hp->vert)
+ tbl_char(tp, '|', hp->vert);
+ if (2 > hp->vert)
+ tbl_char(tp, ASCII_NBRSP, 2 - hp->vert);
}
static void
@@ -369,11 +341,19 @@ static void
tbl_literal(struct termp *tp, const struct tbl_dat *dp,
const struct roffcol *col)
{
- size_t len, padl, padr;
+ struct tbl_head *hp;
+ size_t width, len, padl, padr;
+ int spans;
assert(dp->string);
len = term_strlen(tp, dp->string);
- padr = col->width > len ? col->width - len : 0;
+
+ hp = dp->layout->head->next;
+ width = col->width;
+ for (spans = dp->spans; spans--; hp = hp->next)
+ width += tp->tbl.cols[hp->ident].width + 3;
+
+ padr = width > len ? width - len : 0;
padl = 0;
switch (dp->layout->pos) {
@@ -401,7 +381,7 @@ tbl_literal(struct termp *tp, const struct tbl_dat *dp,
}
static void
-tbl_number(struct termp *tp, const struct tbl *tbl,
+tbl_number(struct termp *tp, const struct tbl_opts *opts,
const struct tbl_dat *dp,
const struct roffcol *col)
{
@@ -419,12 +399,12 @@ tbl_number(struct termp *tp, const struct tbl *tbl,
sz = term_strlen(tp, dp->string);
- buf[0] = tbl->decimal;
+ buf[0] = opts->decimal;
buf[1] = '\0';
psz = term_strlen(tp, buf);
- if (NULL != (cp = strrchr(dp->string, tbl->decimal))) {
+ if (NULL != (cp = strrchr(dp->string, opts->decimal))) {
buf[1] = '\0';
for (ssz = 0, i = 0; cp != &dp->string[i]; i++) {
buf[0] = dp->string[i];
diff --git a/term.c b/term.c
index 4ca15ed6fa58..e7b95578752d 100644
--- a/term.c
+++ b/term.c
@@ -1,7 +1,7 @@
-/* $Id: term.c,v 1.201 2011/09/21 09:57:13 schwarze Exp $ */
+/* $Id: term.c,v 1.214 2013/12/25 00:39:31 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 2012, 2013 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,7 +33,8 @@
#include "term.h"
#include "main.h"
-static void adjbuf(struct termp *p, int);
+static size_t cond_width(const struct termp *, int, int *);
+static void adjbuf(struct termp *p, size_t);
static void bufferc(struct termp *, char);
static void encode(struct termp *, const char *, size_t);
static void encode1(struct termp *, int);
@@ -82,9 +83,8 @@ term_end(struct termp *p)
* - TERMP_NOBREAK: this is the most important and is used when making
* columns. In short: don't print a newline and instead expect the
* next call to do the padding up to the start of the next column.
- *
- * - TERMP_TWOSPACE: make sure there is room for at least two space
- * characters of padding. Otherwise, rather break the line.
+ * p->trailspace may be set to 0, 1, or 2, depending on how many
+ * space characters are required at the end of the column.
*
* - TERMP_DANGLE: don't newline when TERMP_NOBREAK is specified and
* the line is overrun, and don't pad-right if it's underrun.
@@ -104,14 +104,15 @@ term_end(struct termp *p)
void
term_flushln(struct termp *p)
{
- int i; /* current input position in p->buf */
+ size_t i; /* current input position in p->buf */
+ int ntab; /* number of tabs to prepend */
size_t vis; /* current visual position on output */
size_t vbl; /* number of blanks to prepend to output */
size_t vend; /* end of word visual position on output */
size_t bp; /* visual right border position */
size_t dv; /* temporary for visual pos calculations */
- int j; /* temporary loop index for p->buf */
- int jhy; /* last hyph before overflow w/r/t j */
+ size_t j; /* temporary loop index for p->buf */
+ size_t jhy; /* last hyph before overflow w/r/t j */
size_t maxvis; /* output position of visible boundary */
size_t mmax; /* used in calculating bp */
@@ -119,7 +120,12 @@ term_flushln(struct termp *p)
* First, establish the maximum columns of "visible" content.
* This is usually the difference between the right-margin and
* an indentation, but can be, for tagged lists or columns, a
- * small set of values.
+ * small set of values.
+ *
+ * The following unsigned-signed subtractions look strange,
+ * but they are actually correct. If the int p->overstep
+ * is negative, it gets sign extended. Subtracting that
+ * very large size_t effectively adds a small number to dv.
*/
assert (p->rmargin >= p->offset);
dv = p->rmargin - p->offset;
@@ -143,10 +149,12 @@ term_flushln(struct termp *p)
* Handle literal tab characters: collapse all
* subsequent tabs into a single huge set of spaces.
*/
+ ntab = 0;
while (i < p->col && '\t' == p->buf[i]) {
vend = (vis / p->tabwidth + 1) * p->tabwidth;
vbl += vend - vis;
vis = vend;
+ ntab++;
i++;
}
@@ -158,7 +166,7 @@ term_flushln(struct termp *p)
*/
for (j = i, jhy = 0; j < p->col; j++) {
- if ((j && ' ' == p->buf[j]) || '\t' == p->buf[j])
+ if (' ' == p->buf[j] || '\t' == p->buf[j])
break;
/* Back over the the last printed character. */
@@ -191,7 +199,16 @@ term_flushln(struct termp *p)
} else
vbl = p->offset;
- /* Remove the p->overstep width. */
+ /* use pending tabs on the new line */
+
+ if (0 < ntab)
+ vbl += ntab * p->tabwidth;
+
+ /*
+ * Remove the p->overstep width.
+ * Again, if p->overstep is negative,
+ * sign extension does the right thing.
+ */
bp += (size_t)p->overstep;
p->overstep = 0;
@@ -207,7 +224,7 @@ term_flushln(struct termp *p)
j = i;
while (' ' == p->buf[i])
i++;
- dv = (size_t)(i - j) * (*p->width)(p, ' ');
+ dv = (i - j) * (*p->width)(p, ' ');
vbl += dv;
vend += dv;
break;
@@ -260,20 +277,17 @@ term_flushln(struct termp *p)
}
if (TERMP_HANG & p->flags) {
- /* We need one blank after the tag. */
- p->overstep = (int)(vis - maxvis + (*p->width)(p, ' '));
+ p->overstep = (int)(vis - maxvis +
+ p->trailspace * (*p->width)(p, ' '));
/*
- * Behave exactly the same way as groff:
* If we have overstepped the margin, temporarily move
* it to the right and flag the rest of the line to be
* shorter.
- * If we landed right at the margin, be happy.
- * If we are one step before the margin, temporarily
- * move it one step LEFT and flag the rest of the line
- * to be longer.
+ * If there is a request to keep the columns together,
+ * allow negative overstep when the column is not full.
*/
- if (p->overstep < -1)
+ if (p->trailspace && p->overstep < 0)
p->overstep = 0;
return;
@@ -281,8 +295,7 @@ term_flushln(struct termp *p)
return;
/* If the column was overrun, break the line. */
- if (maxvis <= vis +
- ((TERMP_TWOSPACE & p->flags) ? (*p->width)(p, ' ') : 0)) {
+ if (maxvis < vis + p->trailspace * (*p->width)(p, ' ')) {
(*p->endline)(p);
p->viscol = 0;
}
@@ -316,7 +329,10 @@ term_vspace(struct termp *p)
term_newln(p);
p->viscol = 0;
- (*p->endline)(p);
+ if (0 < p->skipvsp)
+ p->skipvsp--;
+ else
+ (*p->endline)(p);
}
void
@@ -369,7 +385,7 @@ void
term_fontpopq(struct termp *p, const void *key)
{
- while (p->fonti >= 0 && key != &p->fontq[p->fonti])
+ while (p->fonti >= 0 && key < (void *)(p->fontq + p->fonti))
p->fonti--;
assert(p->fonti >= 0);
}
@@ -391,6 +407,7 @@ term_fontpop(struct termp *p)
void
term_word(struct termp *p, const char *word)
{
+ const char nbrsp[2] = { ASCII_NBRSP, 0 };
const char *seq, *cp;
char c;
int sz, uc;
@@ -399,29 +416,42 @@ term_word(struct termp *p, const char *word)
if ( ! (TERMP_NOSPACE & p->flags)) {
if ( ! (TERMP_KEEP & p->flags)) {
- if (TERMP_PREKEEP & p->flags)
- p->flags |= TERMP_KEEP;
bufferc(p, ' ');
if (TERMP_SENTENCE & p->flags)
bufferc(p, ' ');
} else
bufferc(p, ASCII_NBRSP);
}
+ if (TERMP_PREKEEP & p->flags)
+ p->flags |= TERMP_KEEP;
if ( ! (p->flags & TERMP_NONOSPACE))
p->flags &= ~TERMP_NOSPACE;
else
p->flags |= TERMP_NOSPACE;
- p->flags &= ~(TERMP_SENTENCE | TERMP_IGNDELIM);
+ p->flags &= ~TERMP_SENTENCE;
while ('\0' != *word) {
- if ((ssz = strcspn(word, "\\")) > 0)
+ if ('\\' != *word) {
+ if (TERMP_SKIPCHAR & p->flags) {
+ p->flags &= ~TERMP_SKIPCHAR;
+ word++;
+ continue;
+ }
+ if (TERMP_NBRWORD & p->flags) {
+ if (' ' == *word) {
+ encode(p, nbrsp, 1);
+ word++;
+ continue;
+ }
+ ssz = strcspn(word, "\\ ");
+ } else
+ ssz = strcspn(word, "\\");
encode(p, word, ssz);
-
- word += (int)ssz;
- if ('\\' != *word)
+ word += (int)ssz;
continue;
+ }
word++;
esc = mandoc_escape(&word, &seq, &sz);
@@ -468,6 +498,9 @@ term_word(struct termp *p, const char *word)
case (ESCAPE_FONTITALIC):
term_fontrepl(p, TERMFONT_UNDER);
break;
+ case (ESCAPE_FONTBI):
+ term_fontrepl(p, TERMFONT_BI);
+ break;
case (ESCAPE_FONT):
/* FALLTHROUGH */
case (ESCAPE_FONTROMAN):
@@ -477,17 +510,23 @@ term_word(struct termp *p, const char *word)
term_fontlast(p);
break;
case (ESCAPE_NOSPACE):
- if ('\0' == *word)
+ if (TERMP_SKIPCHAR & p->flags)
+ p->flags &= ~TERMP_SKIPCHAR;
+ else if ('\0' == *word)
p->flags |= TERMP_NOSPACE;
break;
+ case (ESCAPE_SKIPCHAR):
+ p->flags |= TERMP_SKIPCHAR;
+ break;
default:
break;
}
}
+ p->flags &= ~TERMP_NBRWORD;
}
static void
-adjbuf(struct termp *p, int sz)
+adjbuf(struct termp *p, size_t sz)
{
if (0 == p->maxcols)
@@ -495,8 +534,7 @@ adjbuf(struct termp *p, int sz)
while (sz >= p->maxcols)
p->maxcols <<= 2;
- p->buf = mandoc_realloc
- (p->buf, sizeof(int) * (size_t)p->maxcols);
+ p->buf = mandoc_realloc(p->buf, sizeof(int) * p->maxcols);
}
static void
@@ -519,31 +557,39 @@ encode1(struct termp *p, int c)
{
enum termfont f;
- if (p->col + 4 >= p->maxcols)
- adjbuf(p, p->col + 4);
+ if (TERMP_SKIPCHAR & p->flags) {
+ p->flags &= ~TERMP_SKIPCHAR;
+ return;
+ }
+
+ if (p->col + 6 >= p->maxcols)
+ adjbuf(p, p->col + 6);
f = term_fonttop(p);
- if (TERMFONT_NONE == f) {
- p->buf[p->col++] = c;
- return;
- } else if (TERMFONT_UNDER == f) {
+ if (TERMFONT_UNDER == f || TERMFONT_BI == f) {
p->buf[p->col++] = '_';
- } else
- p->buf[p->col++] = c;
-
- p->buf[p->col++] = 8;
+ p->buf[p->col++] = 8;
+ }
+ if (TERMFONT_BOLD == f || TERMFONT_BI == f) {
+ if (ASCII_HYPH == c)
+ p->buf[p->col++] = '-';
+ else
+ p->buf[p->col++] = c;
+ p->buf[p->col++] = 8;
+ }
p->buf[p->col++] = c;
}
static void
encode(struct termp *p, const char *word, size_t sz)
{
- enum termfont f;
- int i, len;
+ size_t i;
- /* LINTED */
- len = sz;
+ if (TERMP_SKIPCHAR & p->flags) {
+ p->flags &= ~TERMP_SKIPCHAR;
+ return;
+ }
/*
* Encode and buffer a string of characters. If the current
@@ -551,35 +597,25 @@ encode(struct termp *p, const char *word, size_t sz)
* character by character.
*/
- if (TERMFONT_NONE == (f = term_fonttop(p))) {
- if (p->col + len >= p->maxcols)
- adjbuf(p, p->col + len);
- for (i = 0; i < len; i++)
+ if (TERMFONT_NONE == term_fonttop(p)) {
+ if (p->col + sz >= p->maxcols)
+ adjbuf(p, p->col + sz);
+ for (i = 0; i < sz; i++)
p->buf[p->col++] = word[i];
return;
}
/* Pre-buffer, assuming worst-case. */
- if (p->col + 1 + (len * 3) >= p->maxcols)
- adjbuf(p, p->col + 1 + (len * 3));
-
- for (i = 0; i < len; i++) {
- if (ASCII_HYPH != word[i] &&
- ! isgraph((unsigned char)word[i])) {
- p->buf[p->col++] = word[i];
- continue;
- }
+ if (p->col + 1 + (sz * 5) >= p->maxcols)
+ adjbuf(p, p->col + 1 + (sz * 5));
- if (TERMFONT_UNDER == f)
- p->buf[p->col++] = '_';
- else if (ASCII_HYPH == word[i])
- p->buf[p->col++] = '-';
+ for (i = 0; i < sz; i++) {
+ if (ASCII_HYPH == word[i] ||
+ isgraph((unsigned char)word[i]))
+ encode1(p, word[i]);
else
p->buf[p->col++] = word[i];
-
- p->buf[p->col++] = 8;
- p->buf[p->col++] = word[i];
}
}
@@ -590,12 +626,22 @@ term_len(const struct termp *p, size_t sz)
return((*p->width)(p, ' ') * sz);
}
+static size_t
+cond_width(const struct termp *p, int c, int *skip)
+{
+
+ if (*skip) {
+ (*skip) = 0;
+ return(0);
+ } else
+ return((*p->width)(p, c));
+}
size_t
term_strlen(const struct termp *p, const char *cp)
{
size_t sz, rsz, i;
- int ssz, c;
+ int ssz, skip, c;
const char *seq, *rhs;
enum mandoc_esc esc;
static const char rej[] = { '\\', ASCII_HYPH, ASCII_NBRSP, '\0' };
@@ -607,10 +653,11 @@ term_strlen(const struct termp *p, const char *cp)
*/
sz = 0;
+ skip = 0;
while ('\0' != *cp) {
rsz = strcspn(cp, rej);
for (i = 0; i < rsz; i++)
- sz += (*p->width)(p, *cp++);
+ sz += cond_width(p, *cp++, &skip);
c = 0;
switch (*cp) {
@@ -627,14 +674,14 @@ term_strlen(const struct termp *p, const char *cp)
(seq + 1, ssz - 1);
if ('\0' == c)
break;
- sz += (*p->width)(p, c);
+ sz += cond_width(p, c, &skip);
continue;
case (ESCAPE_SPECIAL):
c = mchars_spec2cp
(p->symtab, seq, ssz);
if (c <= 0)
break;
- sz += (*p->width)(p, c);
+ sz += cond_width(p, c, &skip);
continue;
default:
break;
@@ -644,12 +691,12 @@ term_strlen(const struct termp *p, const char *cp)
switch (esc) {
case (ESCAPE_UNICODE):
- sz += (*p->width)(p, '?');
+ sz += cond_width(p, '?', &skip);
break;
case (ESCAPE_NUMBERED):
c = mchars_num2char(seq, ssz);
if ('\0' != c)
- sz += (*p->width)(p, c);
+ sz += cond_width(p, c, &skip);
break;
case (ESCAPE_SPECIAL):
rhs = mchars_spec2str
@@ -661,6 +708,9 @@ term_strlen(const struct termp *p, const char *cp)
rhs = seq;
rsz = ssz;
break;
+ case (ESCAPE_SKIPCHAR):
+ skip = 1;
+ break;
default:
break;
}
@@ -668,15 +718,20 @@ term_strlen(const struct termp *p, const char *cp)
if (NULL == rhs)
break;
+ if (skip) {
+ skip = 0;
+ break;
+ }
+
for (i = 0; i < rsz; i++)
sz += (*p->width)(p, *rhs++);
break;
case (ASCII_NBRSP):
- sz += (*p->width)(p, ' ');
+ sz += cond_width(p, ' ', &skip);
cp++;
break;
case (ASCII_HYPH):
- sz += (*p->width)(p, '-');
+ sz += cond_width(p, '-', &skip);
cp++;
break;
default:
diff --git a/term.h b/term.h
index 56d076e54a83..8cad4be83831 100644
--- a/term.h
+++ b/term.h
@@ -1,6 +1,7 @@
-/* $Id: term.h,v 1.90 2011/12/04 23:10:52 schwarze Exp $ */
+/* $Id: term.h,v 1.97 2013/12/25 00:39:31 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011, 2012, 2013 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 +38,7 @@ enum termfont {
TERMFONT_NONE = 0,
TERMFONT_BOLD,
TERMFONT_UNDER,
+ TERMFONT_BI,
TERMFONT__MAX
};
@@ -57,26 +59,28 @@ struct termp {
size_t defrmargin; /* Right margin of the device. */
size_t rmargin; /* Current right margin. */
size_t maxrmargin; /* Max right margin. */
- int maxcols; /* Max size of buf. */
+ size_t maxcols; /* Max size of buf. */
size_t offset; /* Margin offest. */
size_t tabwidth; /* Distance of tab positions. */
- int col; /* Bytes in buf. */
+ size_t col; /* Bytes in buf. */
size_t viscol; /* Chars on current line. */
+ size_t trailspace; /* See termp_flushln(). */
int overstep; /* See termp_flushln(). */
+ int skipvsp; /* Vertical space to skip. */
int flags;
#define TERMP_SENTENCE (1 << 1) /* Space before a sentence. */
#define TERMP_NOSPACE (1 << 2) /* No space before words. */
-#define TERMP_NOBREAK (1 << 4) /* See term_flushln(). */
-#define TERMP_IGNDELIM (1 << 6) /* Delims like regulars. */
-#define TERMP_NONOSPACE (1 << 7) /* No space (no autounset). */
-#define TERMP_DANGLE (1 << 8) /* See term_flushln(). */
-#define TERMP_HANG (1 << 9) /* See term_flushln(). */
-#define TERMP_TWOSPACE (1 << 10) /* See term_flushln(). */
+#define TERMP_NONOSPACE (1 << 3) /* No space (no autounset). */
+#define TERMP_NBRWORD (1 << 4) /* Make next word nonbreaking. */
+#define TERMP_KEEP (1 << 5) /* Keep words together. */
+#define TERMP_PREKEEP (1 << 6) /* ...starting with the next one. */
+#define TERMP_SKIPCHAR (1 << 7) /* Skip the next character. */
+#define TERMP_NOBREAK (1 << 8) /* See term_flushln(). */
+#define TERMP_DANGLE (1 << 9) /* See term_flushln(). */
+#define TERMP_HANG (1 << 10) /* See term_flushln(). */
#define TERMP_NOSPLIT (1 << 11) /* See termp_an_pre/post(). */
#define TERMP_SPLIT (1 << 12) /* See termp_an_pre/post(). */
#define TERMP_ANPREC (1 << 13) /* See termp_an_pre(). */
-#define TERMP_KEEP (1 << 14) /* Keep words together. */
-#define TERMP_PREKEEP (1 << 15) /* ...starting with the next one. */
int *buf; /* Output buffer. */
enum termenc enc; /* Type of encoding. */
struct mchars *symtab; /* Encoded-symbol table. */
diff --git a/term_ascii.c b/term_ascii.c
index 2f114786f6af..cb7ac294059e 100644
--- a/term_ascii.c
+++ b/term_ascii.c
@@ -1,4 +1,4 @@
-/* $Id: term_ascii.c,v 1.20 2011/12/04 23:10:52 schwarze Exp $ */
+/* $Id: term_ascii.c,v 1.21 2013/06/01 14:27:20 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -73,7 +73,6 @@ ascii_init(enum termenc enc, char *outopts)
struct termp *p;
p = mandoc_calloc(1, sizeof(struct termp));
- p->enc = enc;
p->tabwidth = 5;
p->defrmargin = 78;
@@ -93,7 +92,7 @@ ascii_init(enum termenc enc, char *outopts)
if (TERMENC_ASCII != enc) {
v = TERMENC_LOCALE == enc ?
setlocale(LC_ALL, "") :
- setlocale(LC_CTYPE, "UTF-8");
+ setlocale(LC_CTYPE, "en_US.UTF-8");
if (NULL != v && MB_CUR_MAX > 1) {
p->enc = enc;
p->advance = locale_advance;
diff --git a/test-betoh64.c b/test-betoh64.c
new file mode 100644
index 000000000000..d33f4017843a
--- /dev/null
+++ b/test-betoh64.c
@@ -0,0 +1,18 @@
+#include <sys/types.h>
+
+#if defined(__linux__)
+# include <endian.h>
+#elif defined(__APPLE__)
+# include <libkern/OSByteOrder.h>
+#else
+# include <sys/endian.h>
+#endif
+
+int
+main(int argc, char **argv)
+{
+ u_int64_t hostorder;
+ u_int64_t bigendian = 1;
+ hostorder = betoh64(bigendian);
+ return 0;
+}
diff --git a/test-mmap.c b/test-mmap.c
index db8fd8732e4d..1e0f94229eb1 100644
--- a/test-mmap.c
+++ b/test-mmap.c
@@ -5,6 +5,6 @@ int
main(int argc, char **argv)
{
- mmap(0, 0, PROT_READ, MAP_FILE|MAP_SHARED, -1, 0);
+ mmap(0, 0, PROT_READ, MAP_SHARED, -1, 0);
return 0;
}
diff --git a/tree.c b/tree.c
index 1430c737e00e..fdb70e1b9338 100644
--- a/tree.c
+++ b/tree.c
@@ -1,6 +1,7 @@
-/* $Id: tree.c,v 1.47 2011/09/18 14:14:15 schwarze Exp $ */
+/* $Id: tree.c,v 1.50 2013/12/24 19:11:46 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2013 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
@@ -58,13 +59,11 @@ print_mdoc(const struct mdoc_node *n, int indent)
{
const char *p, *t;
int i, j;
- size_t argc, sz;
- char **params;
+ size_t argc;
struct mdoc_argv *argv;
argv = NULL;
- argc = sz = 0;
- params = NULL;
+ argc = 0;
t = p = NULL;
switch (n->type) {
@@ -161,11 +160,14 @@ print_mdoc(const struct mdoc_node *n, int indent)
if (argv[i].sz > 0)
printf(" ]");
}
-
- for (i = 0; i < (int)sz; i++)
- printf(" [%s]", params[i]);
- printf(" %d:%d\n", n->line, n->pos);
+ putchar(' ');
+ if (MDOC_LINE & n->flags)
+ putchar('*');
+ printf("%d:%d", n->line, n->pos);
+ if (n->lastline != n->line)
+ printf("-%d", n->lastline);
+ putchar('\n');
}
if (n->child)
diff --git a/whatis.1 b/whatis.1
index 500b0b6c34d4..b8071a450d84 100644
--- a/whatis.1
+++ b/whatis.1
@@ -1,6 +1,6 @@
-.\" $Id: whatis.1,v 1.8 2012/03/24 01:54:43 kristaps Exp $
+.\" $Id: whatis.1,v 1.7.2.2 2013/10/05 01:25:20 schwarze Exp $
.\"
-.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2011 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
@@ -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: March 24 2012 $
+.Dd $Mdocdate: October 5 2013 $
.Dt WHATIS 1
.Os
.Sh NAME
@@ -23,8 +23,8 @@
.Sh SYNOPSIS
.Nm
.Op Fl C Ar file
-.Op Fl M Ar manpath
-.Op Fl m Ar manpath
+.Op Fl M Ar path
+.Op Fl m Ar path
.Op Fl S Ar arch
.Op Fl s Ar section
.Ar name ...
@@ -47,8 +47,6 @@ searches for
.Xr mandocdb 8
databases in the default paths stipulated by
.Xr man 1 .
-If standard output is a TTY, a result may be selected from a list and
-its manual displayed with the pager.
.Pp
The options are as follows:
.Bl -tag -width Ds
@@ -58,16 +56,16 @@ Specify an alternative configuration
in
.Xr man.conf 5
format.
-.It Fl M Ar manpath
+.It Fl M Ar path
Use the colon-separated
-.Ar manpath
+.Ar path
instead of the default list of paths searched for
.Xr mandocdb 8
databases.
Invalid paths, or paths without manual databases, are ignored.
-.It Fl m Ar manpath
+.It Fl m Ar path
Prepend the colon-separated
-.Ar manpath
+.Ar path
to the list of paths searched for
.Xr mandocdb 8
databases.
@@ -97,21 +95,13 @@ If an architecture is specified for the manual, it is displayed as
.Pp
.D1 title(cat/arch) \- description
.Pp
-If on a TTY, results are prefixed with a numeric identifier.
+Resulting manuals may be accessed as
.Pp
-.D1 [index] title(cat) \- description
+.Dl $ man \-s sec title
.Pp
-One may choose a manual be entering the index at the prompt.
-Valid choices are displayed using
-.Ev MANPAGER ,
-or failing that ,
-.Ev PAGER
-or just
-.Xr more 1 .
-Source pages are formatted with
-.Xr mandoc 1 ;
-preformatted pages with
-.Xr cat 1 .
+If an architecture is specified in the output, use
+.Pp
+.Dl $ man \-s sec \-S arch title
.Pp
.Nm
is identical to running
@@ -121,14 +111,6 @@ as follows:
.Dl $ apropos -- -i 'Nm~[[:<:]]term[[:>:]]'
.Sh ENVIRONMENT
.Bl -tag -width Ds
-.It Ev MANPAGER
-Default pager for manuals.
-If this is unset, falls back to
-.Ev Pager .
-.It Ev PAGER
-The second choice for a manual pager.
-If this is unset, use
-.Xr more 1 .
.It Ev MANPATH
Colon-separated paths modifying the default list of paths searched for
manual databases.
@@ -149,11 +131,11 @@ If none of these conditions are met, it overrides the default list.
.El
.Sh FILES
.Bl -tag -width "/etc/man.conf" -compact
-.It Pa whatis.db
+.It Pa mandoc.db
name of the
.Xr mandocdb 8
keyword database
-.It Pa whatis.index
+.It Pa mandoc.index
name of the
.Xr mandocdb 8
filename database
@@ -186,5 +168,4 @@ wrote the original
.Nm
in 1979.
The current version was written by
-.An Kristaps Dzonsons ,
-.Mt kristaps@bsd.lv .
+.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .