Merge ^head r294090 through r294168.

This commit is contained in:
Dimitry Andric 2016-01-16 17:33:09 +00:00
commit 7aa11cde7e
192 changed files with 8498 additions and 7706 deletions

View File

@ -121,6 +121,10 @@ OLD_FILES+=usr/lib/clang/3.7.1/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_
OLD_DIRS+=usr/lib/clang/3.7.1/lib/freebsd OLD_DIRS+=usr/lib/clang/3.7.1/lib/freebsd
OLD_DIRS+=usr/lib/clang/3.7.1/lib OLD_DIRS+=usr/lib/clang/3.7.1/lib
OLD_DIRS+=usr/lib/clang/3.7.1 OLD_DIRS+=usr/lib/clang/3.7.1
# 20160116: Update mandoc to cvs snapshot 20160116
OLD_FILES+=/usr/share/mdocml/example.style.css
OLD_FILES+=/usr/share/mdocml/style.css
OLD_DIRS+=/usr/share/mdocml
# 20151225: new clang import which bumps version from 3.7.0 to 3.7.1. # 20151225: new clang import which bumps version from 3.7.0 to 3.7.1.
OLD_FILES+=usr/lib/clang/3.7.0/include/sanitizer/allocator_interface.h OLD_FILES+=usr/lib/clang/3.7.0/include/sanitizer/allocator_interface.h
OLD_FILES+=usr/lib/clang/3.7.0/include/sanitizer/asan_interface.h OLD_FILES+=usr/lib/clang/3.7.0/include/sanitizer/asan_interface.h

View File

@ -1,4 +1,4 @@
$Id: INSTALL,v 1.10 2015/03/09 21:00:14 schwarze Exp $ $Id: INSTALL,v 1.13 2015/11/07 14:01:16 schwarze Exp $
About mdocml, the portable mandoc distribution About mdocml, the portable mandoc distribution
---------------------------------------------- ----------------------------------------------
@ -42,6 +42,8 @@ generates. If anything looks wrong or different from what you
wish, read the file "configure.local.example", create and edit wish, read the file "configure.local.example", create and edit
a file "configure.local", and re-run "./configure" until the a file "configure.local", and re-run "./configure" until the
result seems right to you. result seems right to you.
On Solaris 10 and earlier, you may have to run "ksh ./configure"
because the native /bin/sh lacks some POSIX features.
3. Run "make". 3. Run "make".
Any POSIX-compatible make, in particular both BSD make and GNU make, Any POSIX-compatible make, in particular both BSD make and GNU make,
@ -82,9 +84,10 @@ manual page source.
Understanding mandoc dependencies Understanding mandoc dependencies
--------------------------------- ---------------------------------
The mandoc(1), man(1), and demandoc(1) utilities have no external The mandoc(1), man(1), and demandoc(1) utilities only depend
dependencies, but makewhatis(8) and apropos(1) depend on the on the zlib library for decompressing gzipped manual pages,
following software: but makewhatis(8) and apropos(1) depend on the following
additional software:
1. The SQLite database system, see <http://sqlite.org/>. 1. The SQLite database system, see <http://sqlite.org/>.
The recommended version of SQLite is 3.8.4.3 or newer. The mandoc The recommended version of SQLite is 3.8.4.3 or newer. The mandoc
@ -107,6 +110,11 @@ If you run into that problem, set "HAVE_FTS=0" in configure.local.
If your system does not have it, the bundled compatibility version If your system does not have it, the bundled compatibility version
will be used, so you probably need not worry about it. will be used, so you probably need not worry about it.
One of the chief design goals of the mandoc toolbox is to make
sure that nothing related to documentation requires C++.
Consequently, linking mandoc against any kind of C++ program
would defeat the purpose and is not supported.
Checking autoconfiguration quality Checking autoconfiguration quality
---------------------------------- ----------------------------------

View File

@ -1,4 +1,4 @@
$Id: LICENSE,v 1.7 2015/02/16 14:56:22 schwarze Exp $ $Id: LICENSE,v 1.11 2015/11/07 17:58:55 schwarze Exp $
With the exceptions noted below, all code and documentation With the exceptions noted below, all code and documentation
contained in the mdocml toolkit is protected by the Copyright contained in the mdocml toolkit is protected by the Copyright
@ -8,10 +8,12 @@ Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org> Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org>
Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de> Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org> Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
Copyright (c) 1998, 2004, 2010 Todd C. Miller <Todd.Miller@courtesan.com> Copyright (c) 1998, 2004, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
Copyright (c) 2004 Ted Unangst <tedu@openbsd.org> Copyright (c) 2004 Ted Unangst <tedu@openbsd.org>
Copyright (c) 1994 Christos Zoulas <christos@netbsd.org>
Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org> Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
See the individual source files for information about who contributed See the individual source files for information about who contributed
@ -35,13 +37,16 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
The following files included from outside sources are protected by The following files included from outside sources are protected by
other people's Copyright and are distributed under a 3-clause BSD other people's Copyright and are distributed under various 2-clause
license; see these individual files for details. and 3-clause BSD licenses; see these individual files for details.
compat_fts.c, compat_fts.h, soelim.c, soelim.1:
Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
compat_err.c, compat_fts.c, compat_fts.h,
compat_getsubopt.c, compat_strcasestr.c, compat_strsep.c, compat_getsubopt.c, compat_strcasestr.c, compat_strsep.c,
man.1: man.1:
Copyright (c) 1989,1990,1993,1994 The Regents of the University of California Copyright (c) 1989,1990,1993,1994 The Regents of the University of California
compat_fgetln.c: compat_stringlist.c, compat_stringlist.h:
Copyright (c) 1998 The NetBSD Foundation, Inc. Copyright (c) 1994 Christos Zoulas <christos@netbsd.org>

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.457 2015/03/13 12:35:32 schwarze Exp $ # $Id: Makefile,v 1.480 2015/11/07 21:53:14 schwarze Exp $
# #
# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> # Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
# Copyright (c) 2011, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> # Copyright (c) 2011, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -20,36 +20,49 @@ VERSION = 1.13.3
# === LIST OF FILES ==================================================== # === LIST OF FILES ====================================================
TESTSRCS = test-dirent-namlen.c \ TESTSRCS = test-dirent-namlen.c \
test-fgetln.c \ test-err.c \
test-fts.c \ test-fts.c \
test-getline.c \
test-getsubopt.c \ test-getsubopt.c \
test-isblank.c \
test-mkdtemp.c \
test-mmap.c \ test-mmap.c \
test-ohash.c \ test-ohash.c \
test-pledge.c \
test-progname.c \
test-reallocarray.c \ test-reallocarray.c \
test-sqlite3.c \ test-sqlite3.c \
test-sqlite3_errstr.c \ test-sqlite3_errstr.c \
test-strcasestr.c \ test-strcasestr.c \
test-stringlist.c \
test-strlcat.c \ test-strlcat.c \
test-strlcpy.c \ test-strlcpy.c \
test-strptime.c \ test-strptime.c \
test-strsep.c \ test-strsep.c \
test-strtonum.c \ test-strtonum.c \
test-vasprintf.c \
test-wchar.c test-wchar.c
SRCS = att.c \ SRCS = att.c \
cgi.c \ cgi.c \
chars.c \ chars.c \
compat_fgetln.c \ compat_err.c \
compat_fts.c \ compat_fts.c \
compat_getline.c \
compat_getsubopt.c \ compat_getsubopt.c \
compat_isblank.c \
compat_mkdtemp.c \
compat_ohash.c \ compat_ohash.c \
compat_progname.c \
compat_reallocarray.c \ compat_reallocarray.c \
compat_sqlite3_errstr.c \ compat_sqlite3_errstr.c \
compat_strcasestr.c \ compat_strcasestr.c \
compat_stringlist.c \
compat_strlcat.c \ compat_strlcat.c \
compat_strlcpy.c \ compat_strlcpy.c \
compat_strsep.c \ compat_strsep.c \
compat_strtonum.c \ compat_strtonum.c \
compat_vasprintf.c \
demandoc.c \ demandoc.c \
eqn.c \ eqn.c \
eqn_html.c \ eqn_html.c \
@ -65,6 +78,7 @@ SRCS = att.c \
man_validate.c \ man_validate.c \
mandoc.c \ mandoc.c \
mandoc_aux.c \ mandoc_aux.c \
mandoc_ohash.c \
mandocdb.c \ mandocdb.c \
manpage.c \ manpage.c \
manpath.c \ manpath.c \
@ -76,6 +90,7 @@ SRCS = att.c \
mdoc_html.c \ mdoc_html.c \
mdoc_macro.c \ mdoc_macro.c \
mdoc_man.c \ mdoc_man.c \
mdoc_state.c \
mdoc_term.c \ mdoc_term.c \
mdoc_validate.c \ mdoc_validate.c \
msec.c \ msec.c \
@ -83,7 +98,9 @@ SRCS = att.c \
preconv.c \ preconv.c \
read.c \ read.c \
roff.c \ roff.c \
soelim.c \
st.c \ st.c \
tag.c \
tbl.c \ tbl.c \
tbl_data.c \ tbl_data.c \
tbl_html.c \ tbl_html.c \
@ -93,8 +110,7 @@ SRCS = att.c \
term.c \ term.c \
term_ascii.c \ term_ascii.c \
term_ps.c \ term_ps.c \
tree.c \ tree.c
$(TESTSRCS)
DISTFILES = INSTALL \ DISTFILES = INSTALL \
LICENSE \ LICENSE \
@ -104,14 +120,13 @@ DISTFILES = INSTALL \
TODO \ TODO \
apropos.1 \ apropos.1 \
cgi.h.example \ cgi.h.example \
chars.in \
compat_fts.h \ compat_fts.h \
compat_ohash.h \ compat_ohash.h \
compat_stringlist.h \
configure \ configure \
configure.local.example \ configure.local.example \
demandoc.1 \ demandoc.1 \
eqn.7 \ eqn.7 \
example.style.css \
gmdiff \ gmdiff \
html.h \ html.h \
lib.in \ lib.in \
@ -121,13 +136,15 @@ DISTFILES = INSTALL \
libroff.h \ libroff.h \
main.h \ main.h \
makewhatis.8 \ makewhatis.8 \
man-cgi.css \
man.1 \ man.1 \
man.7 \ man.7 \
man.cgi.8 \ man.cgi.8 \
man.conf.5 \
man.h \ man.h \
manconf.h \
mandoc.1 \ mandoc.1 \
mandoc.3 \ mandoc.3 \
mandoc.css \
mandoc.db.5 \ mandoc.db.5 \
mandoc.h \ mandoc.h \
mandoc_aux.h \ mandoc_aux.h \
@ -136,7 +153,7 @@ DISTFILES = INSTALL \
mandoc_headers.3 \ mandoc_headers.3 \
mandoc_html.3 \ mandoc_html.3 \
mandoc_malloc.3 \ mandoc_malloc.3 \
manpath.h \ mandoc_ohash.h \
mansearch.3 \ mansearch.3 \
mansearch.h \ mansearch.h \
mchars_alloc.3 \ mchars_alloc.3 \
@ -146,12 +163,15 @@ DISTFILES = INSTALL \
out.h \ out.h \
predefs.in \ predefs.in \
roff.7 \ roff.7 \
roff.h \
soelim.1 \
st.in \ st.in \
style.css \ tag.h \
tbl.3 \ tbl.3 \
tbl.7 \ tbl.7 \
term.h \ term.h \
$(SRCS) $(SRCS) \
$(TESTSRCS)
LIBMAN_OBJS = man.o \ LIBMAN_OBJS = man.o \
man_hash.o \ man_hash.o \
@ -164,6 +184,7 @@ LIBMDOC_OBJS = att.o \
mdoc_argv.o \ mdoc_argv.o \
mdoc_hash.o \ mdoc_hash.o \
mdoc_macro.o \ mdoc_macro.o \
mdoc_state.o \
mdoc_validate.o \ mdoc_validate.o \
st.o st.o
@ -180,21 +201,27 @@ LIBMANDOC_OBJS = $(LIBMAN_OBJS) \
chars.o \ chars.o \
mandoc.o \ mandoc.o \
mandoc_aux.o \ mandoc_aux.o \
mandoc_ohash.o \
msec.o \ msec.o \
preconv.o \ preconv.o \
read.o read.o
COMPAT_OBJS = compat_fgetln.o \ COMPAT_OBJS = compat_err.o \
compat_fts.o \ compat_fts.o \
compat_getline.o \
compat_getsubopt.o \ compat_getsubopt.o \
compat_isblank.o \
compat_mkdtemp.o \
compat_ohash.o \ compat_ohash.o \
compat_progname.o \
compat_reallocarray.o \ compat_reallocarray.o \
compat_sqlite3_errstr.o \ compat_sqlite3_errstr.o \
compat_strcasestr.o \ compat_strcasestr.o \
compat_strlcat.o \ compat_strlcat.o \
compat_strlcpy.o \ compat_strlcpy.o \
compat_strsep.o \ compat_strsep.o \
compat_strtonum.o compat_strtonum.o \
compat_vasprintf.o
MANDOC_HTML_OBJS = eqn_html.o \ MANDOC_HTML_OBJS = eqn_html.o \
html.o \ html.o \
@ -218,6 +245,7 @@ BASE_OBJS = $(MANDOC_HTML_OBJS) \
main.o \ main.o \
manpath.o \ manpath.o \
out.o \ out.o \
tag.o \
tree.o tree.o
MAIN_OBJS = $(BASE_OBJS) MAIN_OBJS = $(BASE_OBJS)
@ -236,10 +264,18 @@ MANPAGE_OBJS = manpage.o mansearch.o mansearch_const.o manpath.o
DEMANDOC_OBJS = demandoc.o DEMANDOC_OBJS = demandoc.o
SOELIM_OBJS = soelim.o \
compat_err.o \
compat_getline.o \
compat_progname.o \
compat_reallocarray.o \
compat_stringlist.o
WWW_MANS = apropos.1.html \ WWW_MANS = apropos.1.html \
demandoc.1.html \ demandoc.1.html \
man.1.html \ man.1.html \
mandoc.1.html \ mandoc.1.html \
soelim.1.html \
mandoc.3.html \ mandoc.3.html \
mandoc_escape.3.html \ mandoc_escape.3.html \
mandoc_headers.3.html \ mandoc_headers.3.html \
@ -248,6 +284,7 @@ WWW_MANS = apropos.1.html \
mansearch.3.html \ mansearch.3.html \
mchars_alloc.3.html \ mchars_alloc.3.html \
tbl.3.html \ tbl.3.html \
man.conf.5.html \
mandoc.db.5.html \ mandoc.db.5.html \
eqn.7.html \ eqn.7.html \
man.7.html \ man.7.html \
@ -258,11 +295,12 @@ WWW_MANS = apropos.1.html \
makewhatis.8.html \ makewhatis.8.html \
man.cgi.8.html \ man.cgi.8.html \
man.h.html \ man.h.html \
manconf.h.html \
mandoc.h.html \ mandoc.h.html \
mandoc_aux.h.html \ mandoc_aux.h.html \
manpath.h.html \
mansearch.h.html \ mansearch.h.html \
mdoc.h.html mdoc.h.html \
roff.h.html
WWW_OBJS = mdocml.tar.gz \ WWW_OBJS = mdocml.tar.gz \
mdocml.sha256 mdocml.sha256
@ -275,7 +313,7 @@ include Makefile.local
all: base-build $(BUILD_TARGETS) Makefile.local all: base-build $(BUILD_TARGETS) Makefile.local
base-build: mandoc demandoc base-build: mandoc demandoc soelim
cgi-build: man.cgi cgi-build: man.cgi
@ -301,33 +339,36 @@ clean:
rm -f man.cgi $(CGI_OBJS) rm -f man.cgi $(CGI_OBJS)
rm -f manpage $(MANPAGE_OBJS) rm -f manpage $(MANPAGE_OBJS)
rm -f demandoc $(DEMANDOC_OBJS) rm -f demandoc $(DEMANDOC_OBJS)
rm -f soelim $(SOELIM_OBJS)
rm -f $(WWW_MANS) $(WWW_OBJS) rm -f $(WWW_MANS) $(WWW_OBJS)
rm -rf *.dSYM rm -rf *.dSYM
base-install: base-build base-install: base-build
mkdir -p $(DESTDIR)$(BINDIR) mkdir -p $(DESTDIR)$(BINDIR)
mkdir -p $(DESTDIR)$(EXAMPLEDIR)
mkdir -p $(DESTDIR)$(LIBDIR) mkdir -p $(DESTDIR)$(LIBDIR)
mkdir -p $(DESTDIR)$(INCLUDEDIR) mkdir -p $(DESTDIR)$(INCLUDEDIR)
mkdir -p $(DESTDIR)$(MANDIR)/man1 mkdir -p $(DESTDIR)$(MANDIR)/man1
mkdir -p $(DESTDIR)$(MANDIR)/man3 mkdir -p $(DESTDIR)$(MANDIR)/man3
mkdir -p $(DESTDIR)$(MANDIR)/man5
mkdir -p $(DESTDIR)$(MANDIR)/man7 mkdir -p $(DESTDIR)$(MANDIR)/man7
$(INSTALL_PROGRAM) mandoc demandoc $(DESTDIR)$(BINDIR) $(INSTALL_PROGRAM) mandoc demandoc $(DESTDIR)$(BINDIR)
$(INSTALL_PROGRAM) soelim $(DESTDIR)$(BINDIR)/$(BINM_SOELIM)
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_MAN) ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_MAN)
$(INSTALL_LIB) libmandoc.a $(DESTDIR)$(LIBDIR) $(INSTALL_LIB) libmandoc.a $(DESTDIR)$(LIBDIR)
$(INSTALL_LIB) man.h mandoc.h mandoc_aux.h mdoc.h \ $(INSTALL_LIB) man.h mandoc.h mandoc_aux.h mdoc.h roff.h \
$(DESTDIR)$(INCLUDEDIR) $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_MAN) mandoc.1 demandoc.1 $(DESTDIR)$(MANDIR)/man1 $(INSTALL_MAN) mandoc.1 demandoc.1 $(DESTDIR)$(MANDIR)/man1
$(INSTALL_MAN) soelim.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_SOELIM).1
$(INSTALL_MAN) man.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_MAN).1 $(INSTALL_MAN) man.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_MAN).1
$(INSTALL_MAN) mandoc.3 mandoc_escape.3 mandoc_malloc.3 \ $(INSTALL_MAN) mandoc.3 mandoc_escape.3 mandoc_malloc.3 \
mchars_alloc.3 tbl.3 $(DESTDIR)$(MANDIR)/man3 mchars_alloc.3 tbl.3 $(DESTDIR)$(MANDIR)/man3
$(INSTALL_MAN) man.conf.5 $(DESTDIR)$(MANDIR)/man5/${MANM_MANCONF}.5
$(INSTALL_MAN) man.7 $(DESTDIR)$(MANDIR)/man7/${MANM_MAN}.7 $(INSTALL_MAN) man.7 $(DESTDIR)$(MANDIR)/man7/${MANM_MAN}.7
$(INSTALL_MAN) mdoc.7 $(DESTDIR)$(MANDIR)/man7/${MANM_MDOC}.7 $(INSTALL_MAN) mdoc.7 $(DESTDIR)$(MANDIR)/man7/${MANM_MDOC}.7
$(INSTALL_MAN) roff.7 $(DESTDIR)$(MANDIR)/man7/${MANM_ROFF}.7 $(INSTALL_MAN) roff.7 $(DESTDIR)$(MANDIR)/man7/${MANM_ROFF}.7
$(INSTALL_MAN) eqn.7 $(DESTDIR)$(MANDIR)/man7/${MANM_EQN}.7 $(INSTALL_MAN) eqn.7 $(DESTDIR)$(MANDIR)/man7/${MANM_EQN}.7
$(INSTALL_MAN) tbl.7 $(DESTDIR)$(MANDIR)/man7/${MANM_TBL}.7 $(INSTALL_MAN) tbl.7 $(DESTDIR)$(MANDIR)/man7/${MANM_TBL}.7
$(INSTALL_MAN) mandoc_char.7 $(DESTDIR)$(MANDIR)/man7 $(INSTALL_MAN) mandoc_char.7 $(DESTDIR)$(MANDIR)/man7
$(INSTALL_DATA) example.style.css $(DESTDIR)$(EXAMPLEDIR)
db-install: base-build db-install: base-build
mkdir -p $(DESTDIR)$(BINDIR) mkdir -p $(DESTDIR)$(BINDIR)
@ -354,8 +395,7 @@ cgi-install: cgi-build
mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1 mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1
mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8 mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8
$(INSTALL_PROGRAM) man.cgi $(DESTDIR)$(CGIBINDIR) $(INSTALL_PROGRAM) man.cgi $(DESTDIR)$(CGIBINDIR)
$(INSTALL_DATA) example.style.css $(DESTDIR)$(HTDOCDIR)/man.css $(INSTALL_DATA) mandoc.css $(DESTDIR)$(HTDOCDIR)
$(INSTALL_DATA) man-cgi.css $(DESTDIR)$(HTDOCDIR)
$(INSTALL_MAN) apropos.1 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1/ $(INSTALL_MAN) apropos.1 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1/
$(INSTALL_MAN) man.cgi.8 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8/ $(INSTALL_MAN) man.cgi.8 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8/
@ -376,13 +416,16 @@ man.cgi: $(CGI_OBJS) libmandoc.a
$(CC) $(LDFLAGS) $(STATIC) -o $@ $(CGI_OBJS) libmandoc.a $(DBLIB) $(CC) $(LDFLAGS) $(STATIC) -o $@ $(CGI_OBJS) libmandoc.a $(DBLIB)
demandoc: $(DEMANDOC_OBJS) libmandoc.a demandoc: $(DEMANDOC_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(DEMANDOC_OBJS) libmandoc.a $(CC) $(LDFLAGS) -o $@ $(DEMANDOC_OBJS) libmandoc.a $(DBLIB)
soelim: $(SOELIM_OBJS)
$(CC) $(LDFLAGS) -o $@ $(SOELIM_OBJS)
# --- maintainer targets --- # --- maintainer targets ---
www-install: www www-install: www
mkdir -p $(HTDOCDIR)/snapshots mkdir -p $(HTDOCDIR)/snapshots
$(INSTALL_DATA) $(WWW_MANS) style.css $(HTDOCDIR) $(INSTALL_DATA) $(WWW_MANS) mandoc.css $(HTDOCDIR)
$(INSTALL_DATA) $(WWW_OBJS) $(HTDOCDIR)/snapshots $(INSTALL_DATA) $(WWW_OBJS) $(HTDOCDIR)/snapshots
$(INSTALL_DATA) mdocml.tar.gz \ $(INSTALL_DATA) mdocml.tar.gz \
$(HTDOCDIR)/snapshots/mdocml-$(VERSION).tar.gz $(HTDOCDIR)/snapshots/mdocml-$(VERSION).tar.gz
@ -416,4 +459,4 @@ mdocml.tar.gz: $(DISTFILES)
.1.1.html .3.3.html .5.5.html .7.7.html .8.8.html: mandoc .1.1.html .3.3.html .5.5.html .7.7.html .8.8.html: mandoc
./mandoc -Thtml -Wall,stop \ ./mandoc -Thtml -Wall,stop \
-Ostyle=style.css,man=%N.%S.html,includes=%I.html $< > $@ -Ostyle=mandoc.css,man=%N.%S.html,includes=%I.html $< > $@

View File

@ -1,51 +1,61 @@
att.o: att.c config.h mdoc.h libmdoc.h att.o: att.c config.h roff.h mdoc.h libmdoc.h
cgi.o: cgi.c config.h mandoc.h mandoc_aux.h main.h manpath.h mansearch.h cgi.h cgi.o: cgi.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h main.h manconf.h mansearch.h cgi.h
chars.o: chars.c config.h mandoc.h mandoc_aux.h libmandoc.h chars.in chars.o: chars.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h libmandoc.h
compat_fgetln.o: compat_fgetln.c config.h compat_err.o: compat_err.c config.h
compat_fts.o: compat_fts.c config.h compat_fts.h compat_fts.o: compat_fts.c config.h compat_fts.h
compat_getline.o: compat_getline.c config.h
compat_getsubopt.o: compat_getsubopt.c config.h compat_getsubopt.o: compat_getsubopt.c config.h
compat_isblank.o: compat_isblank.c config.h
compat_mkdtemp.o: compat_mkdtemp.c config.h
compat_ohash.o: compat_ohash.c config.h compat_ohash.h compat_ohash.o: compat_ohash.c config.h compat_ohash.h
compat_progname.o: compat_progname.c config.h
compat_reallocarray.o: compat_reallocarray.c config.h compat_reallocarray.o: compat_reallocarray.c config.h
compat_sqlite3_errstr.o: compat_sqlite3_errstr.c config.h compat_sqlite3_errstr.o: compat_sqlite3_errstr.c config.h
compat_strcasestr.o: compat_strcasestr.c config.h compat_strcasestr.o: compat_strcasestr.c config.h
compat_stringlist.o: compat_stringlist.c config.h compat_stringlist.h
compat_strlcat.o: compat_strlcat.c config.h compat_strlcat.o: compat_strlcat.c config.h
compat_strlcpy.o: compat_strlcpy.c config.h compat_strlcpy.o: compat_strlcpy.c config.h
compat_strsep.o: compat_strsep.c config.h compat_strsep.o: compat_strsep.c config.h
compat_strtonum.o: compat_strtonum.c config.h compat_strtonum.o: compat_strtonum.c config.h
demandoc.o: demandoc.c config.h man.h mdoc.h mandoc.h compat_vasprintf.o: compat_vasprintf.c config.h
demandoc.o: demandoc.c config.h roff.h man.h mdoc.h mandoc.h
eqn.o: eqn.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h eqn.o: eqn.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
eqn_html.o: eqn_html.c config.h mandoc.h out.h html.h eqn_html.o: eqn_html.c config.h mandoc.h out.h html.h
eqn_term.o: eqn_term.c config.h mandoc.h out.h term.h eqn_term.o: eqn_term.c config.h mandoc.h out.h term.h
html.o: html.c config.h mandoc.h mandoc_aux.h out.h html.h main.h html.o: html.c config.h mandoc.h mandoc_aux.h out.h html.h manconf.h main.h
lib.o: lib.c config.h mdoc.h libmdoc.h lib.in lib.o: lib.c config.h roff.h mdoc.h libmdoc.h lib.in
main.o: main.c config.h mandoc.h mandoc_aux.h main.h mdoc.h man.h manpath.h mansearch.h main.o: main.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h tag.h main.h manconf.h mansearch.h
man.o: man.c config.h man.h mandoc.h mandoc_aux.h libman.h libmandoc.h man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
man_hash.o: man_hash.c config.h man.h libman.h man_hash.o: man_hash.c config.h roff.h man.h libman.h
man_html.o: man_html.c config.h mandoc_aux.h man.h out.h html.h main.h man_html.o: man_html.c config.h mandoc_aux.h roff.h man.h out.h html.h main.h
man_macro.o: man_macro.c config.h man.h mandoc.h libmandoc.h libman.h man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
man_term.o: man_term.c config.h mandoc.h mandoc_aux.h out.h man.h term.h main.h man_term.o: man_term.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h term.h main.h
man_validate.o: man_validate.c config.h man.h mandoc.h mandoc_aux.h libman.h libmandoc.h man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
mandoc.o: mandoc.c config.h mandoc.h mandoc_aux.h libmandoc.h mandoc.o: mandoc.c config.h mandoc.h mandoc_aux.h libmandoc.h
mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h
mandocdb.o: mandocdb.c config.h compat_fts.h compat_ohash.h mdoc.h man.h mandoc.h mandoc_aux.h manpath.h mansearch.h mandoc_ohash.o: mandoc_ohash.c mandoc_aux.h mandoc_ohash.h compat_ohash.h
manpage.o: manpage.c config.h manpath.h mansearch.h mandocdb.o: mandocdb.c config.h compat_fts.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h mdoc.h man.h manconf.h mansearch.h
manpath.o: manpath.c config.h mandoc_aux.h manpath.h manpage.o: manpage.c config.h manconf.h mansearch.h
mansearch.o: mansearch.c config.h compat_ohash.h mandoc.h mandoc_aux.h manpath.h mansearch.h manpath.o: manpath.c config.h mandoc_aux.h manconf.h
mansearch.o: mansearch.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h manconf.h mansearch.h
mansearch_const.o: mansearch_const.c config.h mansearch.h mansearch_const.o: mansearch_const.c config.h mansearch.h
mdoc.o: mdoc.c config.h mdoc.h mandoc.h mandoc_aux.h libmdoc.h libmandoc.h mdoc.o: mdoc.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
mdoc_argv.o: mdoc_argv.c config.h mdoc.h mandoc.h mandoc_aux.h libmdoc.h libmandoc.h mdoc_argv.o: mdoc_argv.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h
mdoc_hash.o: mdoc_hash.c config.h mdoc.h libmdoc.h mdoc_hash.o: mdoc_hash.c config.h roff.h mdoc.h libmdoc.h
mdoc_html.o: mdoc_html.c config.h mandoc_aux.h mdoc.h out.h html.h main.h mdoc_html.o: mdoc_html.c config.h mandoc_aux.h roff.h mdoc.h out.h html.h main.h
mdoc_macro.o: mdoc_macro.c config.h mdoc.h mandoc.h libmdoc.h libmandoc.h mdoc_macro.o: mdoc_macro.c config.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
mdoc_man.o: mdoc_man.c config.h mandoc.h mandoc_aux.h out.h man.h mdoc.h main.h mdoc_man.o: mdoc_man.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h out.h main.h
mdoc_term.o: mdoc_term.c config.h mandoc.h mandoc_aux.h out.h term.h mdoc.h main.h mdoc_state.o: mdoc_state.c mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h
mdoc_validate.o: mdoc_validate.c config.h mdoc.h mandoc.h mandoc_aux.h libmdoc.h libmandoc.h mdoc_term.o: mdoc_term.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h out.h term.h tag.h main.h
mdoc_validate.o: mdoc_validate.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
msec.o: msec.c config.h mandoc.h libmandoc.h msec.in msec.o: msec.c config.h mandoc.h libmandoc.h msec.in
out.o: out.c config.h mandoc_aux.h mandoc.h out.h out.o: out.c config.h mandoc_aux.h mandoc.h out.h
preconv.o: preconv.c config.h mandoc.h libmandoc.h preconv.o: preconv.c config.h mandoc.h libmandoc.h
read.o: read.c config.h mandoc.h mandoc_aux.h libmandoc.h mdoc.h man.h read.o: read.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h libmandoc.h roff_int.h
roff.o: roff.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h predefs.in roff.o: roff.c config.h mandoc.h mandoc_aux.h roff.h libmandoc.h roff_int.h libroff.h predefs.in
st.o: st.c config.h mdoc.h libmdoc.h st.in soelim.o: soelim.c config.h compat_stringlist.h
st.o: st.c config.h roff.h mdoc.h libmdoc.h st.in
tag.o: tag.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h tag.h
tbl.o: tbl.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h tbl.o: tbl.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
tbl_data.o: tbl_data.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h tbl_data.o: tbl_data.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
tbl_html.o: tbl_html.c config.h mandoc.h out.h html.h tbl_html.o: tbl_html.c config.h mandoc.h out.h html.h
@ -53,22 +63,6 @@ tbl_layout.o: tbl_layout.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
tbl_opts.o: tbl_opts.c config.h mandoc.h libmandoc.h libroff.h tbl_opts.o: tbl_opts.c config.h mandoc.h libmandoc.h libroff.h
tbl_term.o: tbl_term.c config.h mandoc.h out.h term.h tbl_term.o: tbl_term.c config.h mandoc.h out.h term.h
term.o: term.c config.h mandoc.h mandoc_aux.h out.h term.h main.h term.o: term.c config.h mandoc.h mandoc_aux.h out.h term.h main.h
term_ascii.o: term_ascii.c config.h mandoc.h mandoc_aux.h out.h term.h main.h term_ascii.o: term_ascii.c config.h mandoc.h mandoc_aux.h out.h term.h manconf.h main.h
term_ps.o: term_ps.c config.h mandoc_aux.h out.h term.h main.h term_ps.o: term_ps.c config.h mandoc_aux.h out.h term.h manconf.h main.h
tree.o: tree.c config.h mandoc.h mdoc.h man.h main.h tree.o: tree.c config.h mandoc.h roff.h mdoc.h man.h main.h
test-dirent-namlen.o: test-dirent-namlen.c
test-fgetln.o: test-fgetln.c
test-fts.o: test-fts.c
test-getsubopt.o: test-getsubopt.c
test-mmap.o: test-mmap.c
test-ohash.o: test-ohash.c
test-reallocarray.o: test-reallocarray.c
test-sqlite3.o: test-sqlite3.c
test-sqlite3_errstr.o: test-sqlite3_errstr.c
test-strcasestr.o: test-strcasestr.c
test-strlcat.o: test-strlcat.c
test-strlcpy.o: test-strlcpy.c
test-strptime.o: test-strptime.c
test-strsep.o: test-strsep.c
test-strtonum.o: test-strtonum.c
test-wchar.o: test-wchar.c

View File

@ -1,4 +1,4 @@
$Id: NEWS,v 1.9 2015/03/13 12:35:32 schwarze Exp $ $Id: NEWS,v 1.10 2015/11/05 16:58:20 schwarze Exp $
This file lists the most important changes in the mdocml.bsd.lv distribution. This file lists the most important changes in the mdocml.bsd.lv distribution.
@ -93,7 +93,7 @@ Changes in version 1.13.3, released on March 13, 2015
* roff(7): Three minor fixes with respect to evaluation of conditionals. * roff(7): Three minor fixes with respect to evaluation of conditionals.
* roff(7): Let .it accept numerical expressions, not just constants. * roff(7): Let .it accept numerical expressions, not just constants.
* mandoc_char(7): Correct some character names and renderings. * mandoc_char(7): Correct some character names and renderings.
* If earlier files set a non-zero exit status, never reset it to zero. * If earlier files set a non-zero exit status, never reset it to zero.
--- THANKS TO --- --- THANKS TO ---
* Jonathan Gray (OpenBSD) for yet more testing with afl (the American * Jonathan Gray (OpenBSD) for yet more testing with afl (the American
Fuzzy Lop security fuzzer), again resulting in many bug reports. Fuzzy Lop security fuzzer), again resulting in many bug reports.

View File

@ -1,6 +1,6 @@
************************************************************************ ************************************************************************
* Official mandoc TODO. * Official mandoc TODO.
* $Id: TODO,v 1.202 2015/03/11 13:11:22 schwarze Exp $ * $Id: TODO,v 1.216 2016/01/08 01:37:32 schwarze Exp $
************************************************************************ ************************************************************************
Many issues are annotated for difficulty as follows: Many issues are annotated for difficulty as follows:
@ -66,6 +66,7 @@ are mere guesses, and some may be wrong.
loc * exist * algo * size * imp ** loc * exist * algo * size * imp **
- .ns (no-space mode) occurs in xine-config(1) - .ns (no-space mode) occurs in xine-config(1)
when implementing this, also let .TH set it
reported by brad@ Sat, 15 Jan 2011 15:45:23 -0500 reported by brad@ Sat, 15 Jan 2011 15:45:23 -0500
loc *** exist *** algo *** size ** imp * loc *** exist *** algo *** size ** imp *
@ -105,6 +106,19 @@ are mere guesses, and some may be wrong.
needed for Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100 needed for Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100
loc ** exist *** algo *** size * imp *** loc ** exist *** algo *** size * imp ***
- \\ in high-level macro arguments
Currently, \\ is expanded in two situations:
1) macro and string definition (roff.c setstrn())
2) macro argument parsing (mandoc.c mandoc_getarg())
For user defined macros, the second happens in time because of ROFF_REPARSE.
But for standard high-level macros, it only happens after entering the
high level parsers, which is too late because the code doesn't get
back to roff.c roff_res() from that point. Because this requires
distinguishing requests, user-defined macros and standard macros
on the roff_res() level, it is hard to solve without the parser reorg.
Found by naddy@ in devel/cutils cobfusc(1) Mon, 16 Feb 2015 19:10:52 +0100
loc *** exist *** algo *** size ** imp *
- using undefined strings or macros defines them to be empty - using undefined strings or macros defines them to be empty
wl@ Mon, 14 Nov 2011 14:37:01 +0000 wl@ Mon, 14 Nov 2011 14:37:01 +0000
loc * exist * algo * size * imp * loc * exist * algo * size * imp *
@ -194,6 +208,26 @@ are mere guesses, and some may be wrong.
--- missing tbl features ----------------------------------------------- --- missing tbl features -----------------------------------------------
- horizontal lines in the layout still consume data cells
and can be mixed with actual data on the same table line
synaptics(4) found by tedu@ Mon, 17 Aug 2015 21:17:42 -0400
loc ** exist ** algo ** size ** imp ***
- the "w" layout option is ignored
synaptics(4) found by tedu@ Mon, 17 Aug 2015 21:17:42 -0400
loc * exist * algo * size * imp **
- the "s" layout column specifier is used for placement of data
into columns, but ignored during column width calculations
synaptics(4) found by tedu@ Mon, 17 Aug 2015 21:17:42 -0400
loc * exist ** algo *** size * imp **
- support mdoc(7) and man(7) macros inside tbl(7) code;
probably requires the parser reorg and letting tbl(7)
use roff_node such that macro sets can mix;
informed by bapt@ that FreeBSD needs this.
loc *** exist ** algo *** size ** imp ***
- look at the POSIX manuals in the books/man-pages-posix port, - look at the POSIX manuals in the books/man-pages-posix port,
they use some unsupported tbl(7) features. they use some unsupported tbl(7) features.
loc * exist ** algo ** size ** imp *** loc * exist ** algo ** size ** imp ***
@ -203,13 +237,13 @@ are mere guesses, and some may be wrong.
suggested by bentley@ Tue, 14 Oct 2014 04:10:55 -0600 suggested by bentley@ Tue, 14 Oct 2014 04:10:55 -0600
loc * exist ** algo * size * imp ** loc * exist ** algo * size * imp **
- allow standalone `.' to be interpreted as an end-of-layout
delimiter instead of being thrown away as a no-op roff line
reported by Yuri Pankov, Wed 18 May 2011 11:34:59 CEST
loc ** exist ** algo ** size * imp **
--- missing eqn features ----------------------------------------------- --- missing eqn features -----------------------------------------------
- In a matrix, break the output line after each matrix line.
Found in the discussion at CDBUG 2015.
Suggested by Avi Weinstock.
loc * exist * algo * size * imp **
- The "size" keyword is parsed, but ignored by the formatter. - The "size" keyword is parsed, but ignored by the formatter.
loc * exist * algo * size * imp * loc * exist * algo * size * imp *
@ -227,13 +261,9 @@ are mere guesses, and some may be wrong.
Werner LEMBERG on groff at gnu dot org Sun, 10 Nov 2013 12:47:46 Werner LEMBERG on groff at gnu dot org Sun, 10 Nov 2013 12:47:46
loc ** exist ** algo * size * imp * loc ** exist ** algo * size * imp *
- When makewhatis(8) encounters a FATAL parse error, - change the default PAGER to more -Es and use the pager
it silently treats the file as formatted, which makes no sense even for apropos title line output; req by bapt@
at all for paths like man1/foo.1 - and which also contradicts loc * exist * algo * size * imp ***
what the manual says at the end of the description.
The end result will be ENOENT for file names returned
by mansearch() in manpage.file.
loc * exist * algo * size * imp **
- makewhatis(8) for preformatted pages: - makewhatis(8) for preformatted pages:
parse the section number from the header line parse the section number from the header line
@ -255,11 +285,13 @@ are mere guesses, and some may be wrong.
- kettenis wants base roff, ms, and me Fri, 1 Jan 2010 22:13:15 +0100 (CET) - kettenis wants base roff, ms, and me Fri, 1 Jan 2010 22:13:15 +0100 (CET)
loc ** exist ** algo ** size *** imp * loc ** exist ** algo ** size *** imp *
--- compatibility checks ----------------------------------------------- - Vsevolod Stakhov (FreeBSD) needs either a markdown output formatter
for mandoc -mdoc or a markdown to mdoc converter because they
have to maintain manuals needed both in markdown and mdoc format.
Look at the libsoldout (markdown -> whatever)
loc * exist * algo * size ** imp **
- write a configure check for [[:<:]] support and provide some --- compatibility checks -----------------------------------------------
fallback for whatis(1) when it doesn't work;
Svyatoslav Mishyn Wed, 17 Dec 2014 11:07:10 +0200
- is .Bk implemented correctly in modern groff? - is .Bk implemented correctly in modern groff?
sobrado@ Tue, 19 Apr 2011 22:12:55 +0200 sobrado@ Tue, 19 Apr 2011 22:12:55 +0200
@ -293,6 +325,9 @@ are mere guesses, and some may be wrong.
http://swtch.com/plan9port/man/man7/man.html http://swtch.com/plan9port/man/man7/man.html
"Anthony J. Bentley" <anthonyjbentley@gmail.com> 28 Dec 2010 21:58:40 -0700 "Anthony J. Bentley" <anthonyjbentley@gmail.com> 28 Dec 2010 21:58:40 -0700
- check compatibility with COHERENT troff:
http://www.nesssoftware.com/home/mwc/source.php
- check compatibility with the man(7) formatter - check compatibility with the man(7) formatter
https://raw.githubusercontent.com/rofl0r/hardcore-utils/master/man.c https://raw.githubusercontent.com/rofl0r/hardcore-utils/master/man.c
@ -381,6 +416,12 @@ are mere guesses, and some may be wrong.
see also matthew@ Fri, 18 Jul 2014 19:25:12 -0700 see also matthew@ Fri, 18 Jul 2014 19:25:12 -0700
loc * exist * algo ** size * imp *** loc * exist * algo ** size * imp ***
- .Bf at the beginning of a paragraph inserts a bogus 1ex horizontal
space, see for example random(3). Introduced in
http://mdocml.bsd.lv/cgi-bin/cvsweb/mdoc_html.c.diff?r1=1.91&r2=1.92
reported by deraadt@ Mon, 28 Sep 2015 20:14:13 -0600 (MDT)
loc ** exist ** algo ** size * imp *
- jsg on icb, Nov 3, 2014: - jsg on icb, Nov 3, 2014:
try to guess Xr in man(7) for hyperlinking try to guess Xr in man(7) for hyperlinking
@ -394,6 +435,10 @@ are mere guesses, and some may be wrong.
- consider whether <var> can be used for Ar Dv Er Ev Fa Va. - consider whether <var> can be used for Ar Dv Er Ev Fa Va.
from bentley@ Wed, 13 Aug 2014 09:17:55 -0600 from bentley@ Wed, 13 Aug 2014 09:17:55 -0600
- generate <img> tags in HTML
idea from florian@ Tue, 7 Apr 2015 00:26:28 +0000
may be possible to implement with .Lk img://something.png alt_text
- check https://github.com/trentm/mdocml - check https://github.com/trentm/mdocml
************************************************************************ ************************************************************************
@ -466,6 +511,10 @@ are mere guesses, and some may be wrong.
found while talking to Chris Bennett found while talking to Chris Bennett
loc * exist * algo * size * imp * loc * exist * algo * size * imp *
- Sequences of multiple man(7) paragraphs (.PP, .IP) interspersed
with .ps and .nf/.fi produce execessive blank lines, see libJudy
and graphics/dcmtk. The parser reorg may help with this.
- trailing whitespace must be ignored even when followed by a font escape, - trailing whitespace must be ignored even when followed by a font escape,
see for example see for example
makes makes
@ -474,10 +523,32 @@ are mere guesses, and some may be wrong.
in dig(1). in dig(1).
loc ** exist ** algo ** size * imp ** loc ** exist ** algo ** size * imp **
************************************************************************
* portability
************************************************************************
- systems having UTF-8 but not en_US.UTF-8
call locale(1) from ./configure, select a UTF-8-locale,
and use that for test-wchar.c and term_ascii.c
to Markus Waldeck Sat, 18 Jul 2015 01:55:37 +0200
loc * exist * algo * size * imp *
************************************************************************ ************************************************************************
* warning issues * warning issues
************************************************************************ ************************************************************************
- provide a way in mandoc(1) to warn about broken .Xr links;
probably cannot be on by default in -Tlint because it needs
to access the manpath and mandoc.db(3) after parsing.
asked for by jmc@ Fri, 4 Dec 2015 22:39:40 +0000
- Report errors in -O suboption parsing.
loc * exist * algo * size * imp **
- warn when .Sh or .Ss contain other macros
Steffen Nurpmeso, savannah.gnu.org/bugs/index.php?45034
loc * exist * algo * size * imp **
- check that MANDOCERR_BADTAB is thrown in the right cases, - check that MANDOCERR_BADTAB is thrown in the right cases,
i.e. when finding a literal tab character in fill mode, i.e. when finding a literal tab character in fill mode,
and possibly change the wording of the warning message and possibly change the wording of the warning message
@ -557,11 +628,6 @@ Several areas can be cleaned up to make mandoc even faster. These are
* structural issues * structural issues
************************************************************************ ************************************************************************
- Improve -O suboption parsing. Do it in the main program such that
errors can be reported. Pay attention to distinguishing the
mandoc(1) and apropos(1) styles of both options.
loc ** exist * algo ** size ** imp ***
- Use libz directly instead of forking gunzip(1). - Use libz directly instead of forking gunzip(1).
Suggested by bapt at FreeBSD among others. Suggested by bapt at FreeBSD among others.

View File

@ -1,4 +1,4 @@
.\" $Id: apropos.1,v 1.37 2015/02/16 16:23:54 schwarze Exp $ .\" $Id: apropos.1,v 1.39 2015/04/03 08:46:17 schwarze Exp $
.\" .\"
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: February 16 2015 $ .Dd $Mdocdate: April 3 2015 $
.Dt APROPOS 1 .Dt APROPOS 1
.Os .Os
.Sh NAME .Sh NAME
@ -210,7 +210,7 @@ This has syntax
.Sm off .Sm off
.Oo .Oo
.Op Ar key Op , Ar key ... .Op Ar key Op , Ar key ...
.Pq Cm = | ~ .Pq Cm = | \(ti
.Oc .Oc
.Ar val , .Ar val ,
.Sm on .Sm on
@ -227,7 +227,7 @@ for a list of available keys.
Operator Operator
.Cm = .Cm =
evaluates a substring, while evaluates a substring, while
.Cm ~ .Cm \(ti
evaluates a regular expression. evaluates a regular expression.
.It Fl i Ar term .It Fl i Ar term
If If
@ -365,7 +365,8 @@ Specifies the pagination program to use when
.Ev MANPAGER .Ev MANPAGER
is not defined. is not defined.
If neither PAGER nor MANPAGER is defined, If neither PAGER nor MANPAGER is defined,
.Pa /usr/bin/more Fl s .Xr more 1
.Fl s
will be used. will be used.
.El .El
.Sh FILES .Sh FILES
@ -398,7 +399,7 @@ as well:
.Pp .Pp
Search in names and descriptions using a regular expression: Search in names and descriptions using a regular expression:
.Pp .Pp
.Dl $ apropos '~set.?[ug]id' .Dl $ apropos \(aq\(tiset.?[ug]id\(aq
.Pp .Pp
Search for manuals in the library section mentioning both the Search for manuals in the library section mentioning both the
.Qq optind .Qq optind
@ -413,15 +414,15 @@ Do exactly the same as calling
with the argument with the argument
.Qq ssh : .Qq ssh :
.Pp .Pp
.Dl $ apropos \-\- \-i 'Nm~[[:<:]]ssh[[:>:]]' .Dl $ apropos \-\- \-i \(aqNm\(ti[[:<:]]ssh[[:>:]]\(aq
.Pp .Pp
The following two invocations are equivalent: The following two invocations are equivalent:
.Pp .Pp
.D1 Li $ apropos -S Ar arch Li -s Ar section expression .D1 Li $ apropos -S Ar arch Li -s Ar section expression
.Bd -ragged -offset indent .Bd -ragged -offset indent
.Li $ apropos \e( Ar expression Li \e) .Li $ apropos \e( Ar expression Li \e)
.Li -a arch~^( Ns Ar arch Ns Li |any)$ .Li -a arch\(ti^( Ns Ar arch Ns Li |any)$
.Li -a sec~^ Ns Ar section Ns Li $ .Li -a sec\(ti^ Ns Ar section Ns Li $
.Ed .Ed
.Sh SEE ALSO .Sh SEE ALSO
.Xr man 1 , .Xr man 1 ,

View File

@ -1,4 +1,4 @@
/* $Id: att.c,v 1.13 2014/11/28 18:57:31 schwarze Exp $ */ /* $Id: att.c,v 1.15 2015/10/06 18:32:19 schwarze Exp $ */
/* /*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -19,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include "roff.h"
#include "mdoc.h" #include "mdoc.h"
#include "libmdoc.h" #include "libmdoc.h"
@ -45,5 +46,5 @@ mdoc_a2att(const char *p)
LINE("V.3", "AT&T System\\~V Release\\~3 UNIX"); LINE("V.3", "AT&T System\\~V Release\\~3 UNIX");
LINE("V.4", "AT&T System\\~V Release\\~4 UNIX"); LINE("V.4", "AT&T System\\~V Release\\~4 UNIX");
return(NULL); return NULL;
} }

View File

@ -1,15 +1,15 @@
/* $Id: cgi.c,v 1.104 2015/02/10 08:05:30 schwarze Exp $ */ /* $Id: cgi.c,v 1.116 2016/01/04 12:36:26 schwarze Exp $ */
/* /*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@usta.de> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@usta.de>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -30,10 +30,13 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "mandoc.h"
#include "roff.h"
#include "mdoc.h"
#include "man.h"
#include "main.h" #include "main.h"
#include "manpath.h" #include "manconf.h"
#include "mansearch.h" #include "mansearch.h"
#include "cgi.h" #include "cgi.h"
@ -60,9 +63,6 @@ static void html_print(const char *);
static void html_putchar(char); static void html_putchar(char);
static int http_decode(char *); static int http_decode(char *);
static void http_parse(struct req *, const char *); static void http_parse(struct req *, const char *);
static void http_print(const char *);
static void http_putchar(char);
static void http_printquery(const struct req *, const char *);
static void pathgen(struct req *); static void pathgen(struct req *);
static void pg_error_badrequest(const char *); static void pg_error_badrequest(const char *);
static void pg_error_internal(void); static void pg_error_internal(void);
@ -74,6 +74,7 @@ static void pg_searchres(const struct req *,
static void pg_show(struct req *, const char *); static void pg_show(struct req *, const char *);
static void resp_begin_html(int, const char *); static void resp_begin_html(int, const char *);
static void resp_begin_http(int, const char *); static void resp_begin_http(int, const char *);
static void resp_copy(const char *);
static void resp_end_html(void); static void resp_end_html(void);
static void resp_searchform(const struct req *); static void resp_searchform(const struct req *);
static void resp_show(const struct req *, const char *); static void resp_show(const struct req *, const char *);
@ -145,40 +146,6 @@ html_putchar(char c)
} }
} }
static void
http_printquery(const struct req *req, const char *sep)
{
if (NULL != req->q.query) {
printf("query=");
http_print(req->q.query);
}
if (0 == req->q.equal)
printf("%sapropos=1", sep);
if (NULL != req->q.sec) {
printf("%ssec=", sep);
http_print(req->q.sec);
}
if (NULL != req->q.arch) {
printf("%sarch=", sep);
http_print(req->q.arch);
}
if (strcmp(req->q.manpath, req->p[0])) {
printf("%smanpath=", sep);
http_print(req->q.manpath);
}
}
static void
http_print(const char *p)
{
if (NULL == p)
return;
while ('\0' != *p)
http_putchar(*p++);
}
/* /*
* Call through to html_putchar(). * Call through to html_putchar().
* Accepts NULL strings. * Accepts NULL strings.
@ -299,20 +266,6 @@ http_parse(struct req *req, const char *qs)
} }
} }
static void
http_putchar(char c)
{
if (isalnum((unsigned char)c)) {
putchar((unsigned char)c);
return;
} else if (' ' == c) {
putchar('+');
return;
}
printf("%%%.2x", c);
}
/* /*
* HTTP-decode a string. The standard explanation is that this turns * HTTP-decode a string. The standard explanation is that this turns
* "%4e+foo" into "n foo" in the regular way. This is done in-place * "%4e+foo" into "n foo" in the regular way. This is done in-place
@ -331,13 +284,13 @@ http_decode(char *p)
for ( ; '\0' != *p; p++, q++) { for ( ; '\0' != *p; p++, q++) {
if ('%' == *p) { if ('%' == *p) {
if ('\0' == (hex[0] = *(p + 1))) if ('\0' == (hex[0] = *(p + 1)))
return(0); return 0;
if ('\0' == (hex[1] = *(p + 2))) if ('\0' == (hex[1] = *(p + 2)))
return(0); return 0;
if (1 != sscanf(hex, "%x", &c)) if (1 != sscanf(hex, "%x", &c))
return(0); return 0;
if ('\0' == c) if ('\0' == c)
return(0); return 0;
*q = (char)c; *q = (char)c;
p += 2; p += 2;
@ -346,7 +299,7 @@ http_decode(char *p)
} }
*q = '\0'; *q = '\0';
return(1); return 1;
} }
static void static void
@ -364,6 +317,20 @@ resp_begin_http(int code, const char *msg)
fflush(stdout); fflush(stdout);
} }
static void
resp_copy(const char *filename)
{
char buf[4096];
ssize_t sz;
int fd;
if ((fd = open(filename, O_RDONLY)) != -1) {
fflush(stdout);
while ((sz = read(fd, buf, sizeof(buf))) > 0)
write(STDOUT_FILENO, buf, sz);
}
}
static void static void
resp_begin_html(int code, const char *msg) resp_begin_html(int code, const char *msg)
{ {
@ -374,21 +341,23 @@ resp_begin_html(int code, const char *msg)
"<HTML>\n" "<HTML>\n"
"<HEAD>\n" "<HEAD>\n"
"<META CHARSET=\"UTF-8\" />\n" "<META CHARSET=\"UTF-8\" />\n"
"<LINK REL=\"stylesheet\" HREF=\"%s/man-cgi.css\"" "<LINK REL=\"stylesheet\" HREF=\"%s/mandoc.css\""
" TYPE=\"text/css\" media=\"all\">\n"
"<LINK REL=\"stylesheet\" HREF=\"%s/man.css\""
" TYPE=\"text/css\" media=\"all\">\n" " TYPE=\"text/css\" media=\"all\">\n"
"<TITLE>%s</TITLE>\n" "<TITLE>%s</TITLE>\n"
"</HEAD>\n" "</HEAD>\n"
"<BODY>\n" "<BODY>\n"
"<!-- Begin page content. //-->\n", "<!-- Begin page content. //-->\n",
CSS_DIR, CSS_DIR, CUSTOMIZE_TITLE); CSS_DIR, CUSTOMIZE_TITLE);
resp_copy(MAN_DIR "/header.html");
} }
static void static void
resp_end_html(void) resp_end_html(void)
{ {
resp_copy(MAN_DIR "/footer.html");
puts("</BODY>\n" puts("</BODY>\n"
"</HTML>"); "</HTML>");
} }
@ -398,7 +367,6 @@ resp_searchform(const struct req *req)
{ {
int i; int i;
puts(CUSTOMIZE_BEGIN);
puts("<!-- Begin search form. //-->"); puts("<!-- Begin search form. //-->");
printf("<DIV ID=\"mancgi\">\n" printf("<DIV ID=\"mancgi\">\n"
"<FORM ACTION=\"%s\" METHOD=\"get\">\n" "<FORM ACTION=\"%s\" METHOD=\"get\">\n"
@ -498,10 +466,10 @@ validate_urifrag(const char *frag)
if ( ! (isalnum((unsigned char)*frag) || if ( ! (isalnum((unsigned char)*frag) ||
'-' == *frag || '.' == *frag || '-' == *frag || '.' == *frag ||
'/' == *frag || '_' == *frag)) '/' == *frag || '_' == *frag))
return(0); return 0;
frag++; frag++;
} }
return(1); return 1;
} }
static int static int
@ -510,13 +478,13 @@ validate_manpath(const struct req *req, const char* manpath)
size_t i; size_t i;
if ( ! strcmp(manpath, "mandoc")) if ( ! strcmp(manpath, "mandoc"))
return(1); return 1;
for (i = 0; i < req->psz; i++) for (i = 0; i < req->psz; i++)
if ( ! strcmp(manpath, req->p[i])) if ( ! strcmp(manpath, req->p[i]))
return(1); return 1;
return(0); return 0;
} }
static int static int
@ -526,8 +494,8 @@ validate_filename(const char *file)
if ('.' == file[0] && '/' == file[1]) if ('.' == file[0] && '/' == file[1])
file += 2; file += 2;
return ( ! (strstr(file, "../") || strstr(file, "/..") || return ! (strstr(file, "../") || strstr(file, "/..") ||
(strncmp(file, "man", 3) && strncmp(file, "cat", 3)))); (strncmp(file, "man", 3) && strncmp(file, "cat", 3)));
} }
static void static void
@ -604,9 +572,8 @@ pg_searchres(const struct req *req, struct manpage *r, size_t sz)
* without any delay. * without any delay.
*/ */
printf("Status: 303 See Other\r\n"); printf("Status: 303 See Other\r\n");
printf("Location: http://%s%s/%s/%s?", printf("Location: http://%s%s/%s/%s",
HTTP_HOST, scriptname, req->q.manpath, r[0].file); HTTP_HOST, scriptname, req->q.manpath, r[0].file);
http_printquery(req, "&");
printf("\r\n" printf("\r\n"
"Content-Type: text/html; charset=utf-8\r\n" "Content-Type: text/html; charset=utf-8\r\n"
"\r\n"); "\r\n");
@ -621,9 +588,8 @@ pg_searchres(const struct req *req, struct manpage *r, size_t sz)
for (i = 0; i < sz; i++) { for (i = 0; i < sz; i++) {
printf("<TR>\n" printf("<TR>\n"
"<TD CLASS=\"title\">\n" "<TD CLASS=\"title\">\n"
"<A HREF=\"%s/%s/%s?", "<A HREF=\"%s/%s/%s",
scriptname, req->q.manpath, r[i].file); scriptname, req->q.manpath, r[i].file);
http_printquery(req, "&amp;");
printf("\">"); printf("\">");
html_print(r[i].names); html_print(r[i].names);
printf("</A>\n" printf("</A>\n"
@ -685,12 +651,13 @@ static void
catman(const struct req *req, const char *file) catman(const struct req *req, const char *file)
{ {
FILE *f; FILE *f;
size_t len;
int i;
char *p; char *p;
size_t sz;
ssize_t len;
int i;
int italic, bold; int italic, bold;
if (NULL == (f = fopen(file, "r"))) { if ((f = fopen(file, "r")) == NULL) {
puts("<P>You specified an invalid manual file.</P>"); puts("<P>You specified an invalid manual file.</P>");
return; return;
} }
@ -698,9 +665,12 @@ catman(const struct req *req, const char *file)
puts("<DIV CLASS=\"catman\">\n" puts("<DIV CLASS=\"catman\">\n"
"<PRE>"); "<PRE>");
while (NULL != (p = fgetln(f, &len))) { p = NULL;
sz = 0;
while ((len = getline(&p, &sz, f)) != -1) {
bold = italic = 0; bold = italic = 0;
for (i = 0; i < (int)len - 1; i++) { for (i = 0; i < len - 1; i++) {
/* /*
* This means that the catpage is out of state. * This means that the catpage is out of state.
* Ignore it and keep going (although the * Ignore it and keep going (although the
@ -725,7 +695,7 @@ catman(const struct req *req, const char *file)
italic = bold = 0; italic = bold = 0;
html_putchar(p[i]); html_putchar(p[i]);
continue; continue;
} else if (i + 2 >= (int)len) } else if (i + 2 >= len)
continue; continue;
/* Italic mode. */ /* Italic mode. */
@ -801,11 +771,12 @@ catman(const struct req *req, const char *file)
if (bold) if (bold)
printf("</B>"); printf("</B>");
if (i == (int)len - 1 && '\n' != p[i]) if (i == len - 1 && p[i] != '\n')
html_putchar(p[i]); html_putchar(p[i]);
putchar('\n'); putchar('\n');
} }
free(p);
puts("</PRE>\n" puts("</PRE>\n"
"</DIV>"); "</DIV>");
@ -816,12 +787,10 @@ catman(const struct req *req, const char *file)
static void static void
format(const struct req *req, const char *file) format(const struct req *req, const char *file)
{ {
struct manoutput conf;
struct mparse *mp; struct mparse *mp;
struct mchars *mchars; struct roff_man *man;
struct mdoc *mdoc;
struct man *man;
void *vp; void *vp;
char *opts;
int fd; int fd;
int usepath; int usepath;
@ -830,42 +799,45 @@ format(const struct req *req, const char *file)
return; return;
} }
mchars = mchars_alloc(); mchars_alloc();
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, req->q.manpath);
mchars, req->q.manpath);
mparse_readfd(mp, fd, file); mparse_readfd(mp, fd, file);
close(fd); close(fd);
memset(&conf, 0, sizeof(conf));
conf.fragment = 1;
usepath = strcmp(req->q.manpath, req->p[0]); usepath = strcmp(req->q.manpath, req->p[0]);
mandoc_asprintf(&opts, mandoc_asprintf(&conf.man, "%s?query=%%N&sec=%%S%s%s%s%s",
"fragment,man=%s?query=%%N&sec=%%S%s%s%s%s",
scriptname, scriptname,
req->q.arch ? "&arch=" : "", req->q.arch ? "&arch=" : "",
req->q.arch ? req->q.arch : "", req->q.arch ? req->q.arch : "",
usepath ? "&manpath=" : "", usepath ? "&manpath=" : "",
usepath ? req->q.manpath : ""); usepath ? req->q.manpath : "");
mparse_result(mp, &mdoc, &man, NULL); mparse_result(mp, &man, NULL);
if (NULL == man && NULL == mdoc) { if (man == NULL) {
fprintf(stderr, "fatal mandoc error: %s/%s\n", fprintf(stderr, "fatal mandoc error: %s/%s\n",
req->q.manpath, file); req->q.manpath, file);
pg_error_internal(); pg_error_internal();
mparse_free(mp); mparse_free(mp);
mchars_free(mchars); mchars_free();
return; return;
} }
vp = html_alloc(mchars, opts); vp = html_alloc(&conf);
if (NULL != mdoc) if (man->macroset == MACROSET_MDOC) {
html_mdoc(vp, mdoc); mdoc_validate(man);
else html_mdoc(vp, man);
} else {
man_validate(man);
html_man(vp, man); html_man(vp, man);
}
html_free(vp); html_free(vp);
mparse_free(mp); mparse_free(mp);
mchars_free(mchars); mchars_free();
free(opts); free(conf.man);
} }
static void static void
@ -1030,7 +1002,7 @@ main(void)
if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) { if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) {
fprintf(stderr, "setitimer: %s\n", strerror(errno)); fprintf(stderr, "setitimer: %s\n", strerror(errno));
pg_error_internal(); pg_error_internal();
return(EXIT_FAILURE); return EXIT_FAILURE;
} }
/* Scan our run-time environment. */ /* Scan our run-time environment. */
@ -1042,7 +1014,7 @@ main(void)
fprintf(stderr, "unsafe SCRIPT_NAME \"%s\"\n", fprintf(stderr, "unsafe SCRIPT_NAME \"%s\"\n",
scriptname); scriptname);
pg_error_internal(); pg_error_internal();
return(EXIT_FAILURE); return EXIT_FAILURE;
} }
/* /*
@ -1055,7 +1027,7 @@ main(void)
fprintf(stderr, "MAN_DIR: %s: %s\n", fprintf(stderr, "MAN_DIR: %s: %s\n",
MAN_DIR, strerror(errno)); MAN_DIR, strerror(errno));
pg_error_internal(); pg_error_internal();
return(EXIT_FAILURE); return EXIT_FAILURE;
} }
memset(&req, 0, sizeof(struct req)); memset(&req, 0, sizeof(struct req));
@ -1071,13 +1043,13 @@ main(void)
else if ( ! validate_manpath(&req, req.q.manpath)) { else if ( ! validate_manpath(&req, req.q.manpath)) {
pg_error_badrequest( pg_error_badrequest(
"You specified an invalid manpath."); "You specified an invalid manpath.");
return(EXIT_FAILURE); return EXIT_FAILURE;
} }
if ( ! (NULL == req.q.arch || validate_urifrag(req.q.arch))) { if ( ! (NULL == req.q.arch || validate_urifrag(req.q.arch))) {
pg_error_badrequest( pg_error_badrequest(
"You specified an invalid architecture."); "You specified an invalid architecture.");
return(EXIT_FAILURE); return EXIT_FAILURE;
} }
/* Dispatch to the three different pages. */ /* Dispatch to the three different pages. */
@ -1102,7 +1074,7 @@ main(void)
for (i = 0; i < (int)req.psz; i++) for (i = 0; i < (int)req.psz; i++)
free(req.p[i]); free(req.p[i]);
free(req.p); free(req.p);
return(EXIT_SUCCESS); return EXIT_SUCCESS;
} }
/* /*
@ -1114,6 +1086,7 @@ pathgen(struct req *req)
FILE *fp; FILE *fp;
char *dp; char *dp;
size_t dpsz; size_t dpsz;
ssize_t len;
if (NULL == (fp = fopen("manpath.conf", "r"))) { if (NULL == (fp = fopen("manpath.conf", "r"))) {
fprintf(stderr, "%s/manpath.conf: %s\n", fprintf(stderr, "%s/manpath.conf: %s\n",
@ -1122,12 +1095,14 @@ pathgen(struct req *req)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
while (NULL != (dp = fgetln(fp, &dpsz))) { dp = NULL;
if ('\n' == dp[dpsz - 1]) dpsz = 0;
dpsz--;
while ((len = getline(&dp, &dpsz, fp)) != -1) {
if (dp[len - 1] == '\n')
dp[--len] = '\0';
req->p = mandoc_realloc(req->p, req->p = mandoc_realloc(req->p,
(req->psz + 1) * sizeof(char *)); (req->psz + 1) * sizeof(char *));
dp = mandoc_strndup(dp, dpsz);
if ( ! validate_urifrag(dp)) { if ( ! validate_urifrag(dp)) {
fprintf(stderr, "%s/manpath.conf contains " fprintf(stderr, "%s/manpath.conf contains "
"unsafe path \"%s\"\n", MAN_DIR, dp); "unsafe path \"%s\"\n", MAN_DIR, dp);
@ -1141,7 +1116,10 @@ pathgen(struct req *req)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
req->p[req->psz++] = dp; req->p[req->psz++] = dp;
dp = NULL;
dpsz = 0;
} }
free(dp);
if ( req->p == NULL ) { if ( req->p == NULL ) {
fprintf(stderr, "%s/manpath.conf is empty\n", MAN_DIR); fprintf(stderr, "%s/manpath.conf is empty\n", MAN_DIR);

View File

@ -4,6 +4,4 @@
#define MAN_DIR "/var/www/man" #define MAN_DIR "/var/www/man"
#define CSS_DIR "" #define CSS_DIR ""
#define CUSTOMIZE_TITLE "Manual pages with mandoc" #define CUSTOMIZE_TITLE "Manual pages with mandoc"
#define CUSTOMIZE_BEGIN "<H2>\nManual pages with " \
"<A HREF=\"http://mdocml.bsd.lv/\">mandoc</A>\n</H2>"
#define COMPAT_OLDURI Yes #define COMPAT_OLDURI Yes

View File

@ -1,7 +1,7 @@
/* $Id: chars.c,v 1.66 2015/02/17 20:37:16 schwarze Exp $ */ /* $Id: chars.c,v 1.68 2015/10/13 22:59:54 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011, 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -21,90 +21,429 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "mandoc.h" #include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "mandoc_ohash.h"
#include "libmandoc.h" #include "libmandoc.h"
#define PRINT_HI 126
#define PRINT_LO 32
struct ln { struct ln {
struct ln *next; const char roffcode[16];
const char *code;
const char *ascii; const char *ascii;
int unicode; int unicode;
}; };
#define LINES_MAX 332 /* Special break control characters. */
static const char ascii_nbrsp[2] = { ASCII_NBRSP, '\0' };
static const char ascii_break[2] = { ASCII_BREAK, '\0' };
#define CHAR(in, ch, code) \ static struct ln lines[] = {
{ NULL, (in), (ch), (code) },
#define CHAR_TBL_START static struct ln lines[LINES_MAX] = { /* Spacing. */
#define CHAR_TBL_END }; { " ", ascii_nbrsp, 0x00a0 },
{ "~", ascii_nbrsp, 0x00a0 },
{ "0", " ", 0x2002 },
{ "|", "", 0 },
{ "^", "", 0 },
{ "&", "", 0 },
{ "%", "", 0 },
{ ":", ascii_break, 0 },
/* XXX The following three do not really belong here. */
{ "t", "", 0 },
{ "c", "", 0 },
{ "}", "", 0 },
#include "chars.in" /* Lines. */
{ "ba", "|", 0x007c },
{ "br", "|", 0x2502 },
{ "ul", "_", 0x005f },
{ "rn", "-", 0x203e },
{ "bb", "|", 0x00a6 },
{ "sl", "/", 0x002f },
{ "rs", "\\", 0x005c },
struct mchars { /* Text markers. */
struct ln **htab; { "ci", "O", 0x25cb },
{ "bu", "+\bo", 0x2022 },
{ "dd", "|\b=", 0x2021 },
{ "dg", "|\b-", 0x2020 },
{ "lz", "<>", 0x25ca },
{ "sq", "[]", 0x25a1 },
{ "ps", "<par>", 0x00b6 },
{ "sc", "<sec>", 0x00a7 },
{ "lh", "<=", 0x261c },
{ "rh", "=>", 0x261e },
{ "at", "@", 0x0040 },
{ "sh", "#", 0x0023 },
{ "CR", "_|", 0x21b5 },
{ "OK", "\\/", 0x2713 },
/* Legal symbols. */
{ "co", "(C)", 0x00a9 },
{ "rg", "(R)", 0x00ae },
{ "tm", "tm", 0x2122 },
/* Punctuation. */
{ "em", "--", 0x2014 },
{ "en", "-", 0x2013 },
{ "hy", "-", 0x2010 },
{ "e", "\\", 0x005c },
{ ".", ".", 0x002e },
{ "r!", "!", 0x00a1 },
{ "r?", "?", 0x00bf },
/* Quotes. */
{ "Bq", ",,", 0x201e },
{ "bq", ",", 0x201a },
{ "lq", "\"", 0x201c },
{ "rq", "\"", 0x201d },
{ "Lq", "``", 0x201c },
{ "Rq", "''", 0x201d },
{ "oq", "`", 0x2018 },
{ "cq", "\'", 0x2019 },
{ "aq", "\'", 0x0027 },
{ "dq", "\"", 0x0022 },
{ "Fo", "<<", 0x00ab },
{ "Fc", ">>", 0x00bb },
{ "fo", "<", 0x2039 },
{ "fc", ">", 0x203a },
/* Brackets. */
{ "lB", "[", 0x005b },
{ "rB", "]", 0x005d },
{ "lC", "{", 0x007b },
{ "rC", "}", 0x007d },
{ "la", "<", 0x27e8 },
{ "ra", ">", 0x27e9 },
{ "bv", "|", 0x23aa },
{ "braceex", "|", 0x23aa },
{ "bracketlefttp", "|", 0x23a1 },
{ "bracketleftbt", "|", 0x23a3 },
{ "bracketleftex", "|", 0x23a2 },
{ "bracketrighttp", "|", 0x23a4 },
{ "bracketrightbt", "|", 0x23a6 },
{ "bracketrightex", "|", 0x23a5 },
{ "lt", ",-", 0x23a7 },
{ "bracelefttp", ",-", 0x23a7 },
{ "lk", "{", 0x23a8 },
{ "braceleftmid", "{", 0x23a8 },
{ "lb", "`-", 0x23a9 },
{ "braceleftbt", "`-", 0x23a9 },
{ "braceleftex", "|", 0x23aa },
{ "rt", "-.", 0x23ab },
{ "bracerighttp", "-.", 0x23ab },
{ "rk", "}", 0x23ac },
{ "bracerightmid", "}", 0x23ac },
{ "rb", "-\'", 0x23ad },
{ "bracerightbt", "-\'", 0x23ad },
{ "bracerightex", "|", 0x23aa },
{ "parenlefttp", "/", 0x239b },
{ "parenleftbt", "\\", 0x239d },
{ "parenleftex", "|", 0x239c },
{ "parenrighttp", "\\", 0x239e },
{ "parenrightbt", "/", 0x23a0 },
{ "parenrightex", "|", 0x239f },
/* Arrows and lines. */
{ "<-", "<-", 0x2190 },
{ "->", "->", 0x2192 },
{ "<>", "<->", 0x2194 },
{ "da", "|\bv", 0x2193 },
{ "ua", "|\b^", 0x2191 },
{ "va", "^v", 0x2195 },
{ "lA", "<=", 0x21d0 },
{ "rA", "=>", 0x21d2 },
{ "hA", "<=>", 0x21d4 },
{ "uA", "=\b^", 0x21d1 },
{ "dA", "=\bv", 0x21d3 },
{ "vA", "^=v", 0x21d5 },
/* Logic. */
{ "AN", "^", 0x2227 },
{ "OR", "v", 0x2228 },
{ "no", "~", 0x00ac },
{ "tno", "~", 0x00ac },
{ "te", "3", 0x2203 },
{ "fa", "-\bV", 0x2200 },
{ "st", "-)", 0x220b },
{ "tf", ".:.", 0x2234 },
{ "3d", ".:.", 0x2234 },
{ "or", "|", 0x007c },
/* Mathematicals. */
{ "pl", "+", 0x002b },
{ "mi", "-", 0x2212 },
{ "-", "-", 0x002d },
{ "-+", "-+", 0x2213 },
{ "+-", "+-", 0x00b1 },
{ "t+-", "+-", 0x00b1 },
{ "pc", ".", 0x00b7 },
{ "md", ".", 0x22c5 },
{ "mu", "x", 0x00d7 },
{ "tmu", "x", 0x00d7 },
{ "c*", "O\bx", 0x2297 },
{ "c+", "O\b+", 0x2295 },
{ "di", "-:-", 0x00f7 },
{ "tdi", "-:-", 0x00f7 },
{ "f/", "/", 0x2044 },
{ "**", "*", 0x2217 },
{ "<=", "<=", 0x2264 },
{ ">=", ">=", 0x2265 },
{ "<<", "<<", 0x226a },
{ ">>", ">>", 0x226b },
{ "eq", "=", 0x003d },
{ "!=", "!=", 0x2260 },
{ "==", "==", 0x2261 },
{ "ne", "!==", 0x2262 },
{ "ap", "~", 0x223c },
{ "|=", "-~", 0x2243 },
{ "=~", "=~", 0x2245 },
{ "~~", "~~", 0x2248 },
{ "~=", "~=", 0x2248 },
{ "pt", "oc", 0x221d },
{ "es", "{}", 0x2205 },
{ "mo", "E", 0x2208 },
{ "nm", "!E", 0x2209 },
{ "sb", "(=", 0x2282 },
{ "nb", "(!=", 0x2284 },
{ "sp", "=)", 0x2283 },
{ "nc", "!=)", 0x2285 },
{ "ib", "(=\b_", 0x2286 },
{ "ip", "=\b_)", 0x2287 },
{ "ca", "(^)", 0x2229 },
{ "cu", "U", 0x222a },
{ "/_", "_\b/", 0x2220 },
{ "pp", "_\b|", 0x22a5 },
{ "is", "'\b,\bI", 0x222b },
{ "integral", "'\b,\bI", 0x222b },
{ "sum", "E", 0x2211 },
{ "product", "TT", 0x220f },
{ "coproduct", "U", 0x2210 },
{ "gr", "V", 0x2207 },
{ "sr", "\\/", 0x221a },
{ "sqrt", "\\/", 0x221a },
{ "lc", "|~", 0x2308 },
{ "rc", "~|", 0x2309 },
{ "lf", "|_", 0x230a },
{ "rf", "_|", 0x230b },
{ "if", "oo", 0x221e },
{ "Ah", "N", 0x2135 },
{ "Im", "I", 0x2111 },
{ "Re", "R", 0x211c },
{ "pd", "a", 0x2202 },
{ "-h", "/h", 0x210f },
{ "12", "1/2", 0x00bd },
{ "14", "1/4", 0x00bc },
{ "34", "3/4", 0x00be },
/* Ligatures. */
{ "ff", "ff", 0xfb00 },
{ "fi", "fi", 0xfb01 },
{ "fl", "fl", 0xfb02 },
{ "Fi", "ffi", 0xfb03 },
{ "Fl", "ffl", 0xfb04 },
{ "AE", "AE", 0x00c6 },
{ "ae", "ae", 0x00e6 },
{ "OE", "OE", 0x0152 },
{ "oe", "oe", 0x0153 },
{ "ss", "ss", 0x00df },
{ "IJ", "IJ", 0x0132 },
{ "ij", "ij", 0x0133 },
/* Accents. */
{ "a\"", "\"", 0x02dd },
{ "a-", "-", 0x00af },
{ "a.", ".", 0x02d9 },
{ "a^", "^", 0x005e },
{ "aa", "\'", 0x00b4 },
{ "\'", "\'", 0x00b4 },
{ "ga", "`", 0x0060 },
{ "`", "`", 0x0060 },
{ "ab", "'\b`", 0x02d8 },
{ "ac", ",", 0x00b8 },
{ "ad", "\"", 0x00a8 },
{ "ah", "v", 0x02c7 },
{ "ao", "o", 0x02da },
{ "a~", "~", 0x007e },
{ "ho", ",", 0x02db },
{ "ha", "^", 0x005e },
{ "ti", "~", 0x007e },
/* Accented letters. */
{ "'A", "'\bA", 0x00c1 },
{ "'E", "'\bE", 0x00c9 },
{ "'I", "'\bI", 0x00cd },
{ "'O", "'\bO", 0x00d3 },
{ "'U", "'\bU", 0x00da },
{ "'a", "'\ba", 0x00e1 },
{ "'e", "'\be", 0x00e9 },
{ "'i", "'\bi", 0x00ed },
{ "'o", "'\bo", 0x00f3 },
{ "'u", "'\bu", 0x00fa },
{ "`A", "`\bA", 0x00c0 },
{ "`E", "`\bE", 0x00c8 },
{ "`I", "`\bI", 0x00cc },
{ "`O", "`\bO", 0x00d2 },
{ "`U", "`\bU", 0x00d9 },
{ "`a", "`\ba", 0x00e0 },
{ "`e", "`\be", 0x00e8 },
{ "`i", "`\bi", 0x00ec },
{ "`o", "`\bo", 0x00f2 },
{ "`u", "`\bu", 0x00f9 },
{ "~A", "~\bA", 0x00c3 },
{ "~N", "~\bN", 0x00d1 },
{ "~O", "~\bO", 0x00d5 },
{ "~a", "~\ba", 0x00e3 },
{ "~n", "~\bn", 0x00f1 },
{ "~o", "~\bo", 0x00f5 },
{ ":A", "\"\bA", 0x00c4 },
{ ":E", "\"\bE", 0x00cb },
{ ":I", "\"\bI", 0x00cf },
{ ":O", "\"\bO", 0x00d6 },
{ ":U", "\"\bU", 0x00dc },
{ ":a", "\"\ba", 0x00e4 },
{ ":e", "\"\be", 0x00eb },
{ ":i", "\"\bi", 0x00ef },
{ ":o", "\"\bo", 0x00f6 },
{ ":u", "\"\bu", 0x00fc },
{ ":y", "\"\by", 0x00ff },
{ "^A", "^\bA", 0x00c2 },
{ "^E", "^\bE", 0x00ca },
{ "^I", "^\bI", 0x00ce },
{ "^O", "^\bO", 0x00d4 },
{ "^U", "^\bU", 0x00db },
{ "^a", "^\ba", 0x00e2 },
{ "^e", "^\be", 0x00ea },
{ "^i", "^\bi", 0x00ee },
{ "^o", "^\bo", 0x00f4 },
{ "^u", "^\bu", 0x00fb },
{ ",C", ",\bC", 0x00c7 },
{ ",c", ",\bc", 0x00e7 },
{ "/L", "/\bL", 0x0141 },
{ "/l", "/\bl", 0x0142 },
{ "/O", "/\bO", 0x00d8 },
{ "/o", "/\bo", 0x00f8 },
{ "oA", "o\bA", 0x00c5 },
{ "oa", "o\ba", 0x00e5 },
/* Special letters. */
{ "-D", "-\bD", 0x00d0 },
{ "Sd", "d", 0x00f0 },
{ "TP", "Th", 0x00de },
{ "Tp", "th", 0x00fe },
{ ".i", "i", 0x0131 },
{ ".j", "j", 0x0237 },
/* Currency. */
{ "Do", "$", 0x0024 },
{ "ct", "/\bc", 0x00a2 },
{ "Eu", "EUR", 0x20ac },
{ "eu", "EUR", 0x20ac },
{ "Ye", "=\bY", 0x00a5 },
{ "Po", "GBP", 0x00a3 },
{ "Cs", "o\bx", 0x00a4 },
{ "Fn", ",\bf", 0x0192 },
/* Units. */
{ "de", "<deg>", 0x00b0 },
{ "%0", "%o", 0x2030 },
{ "fm", "\'", 0x2032 },
{ "sd", "''", 0x2033 },
{ "mc", ",\bu", 0x00b5 },
/* Greek characters. */
{ "*A", "A", 0x0391 },
{ "*B", "B", 0x0392 },
{ "*G", "G", 0x0393 },
{ "*D", "_\b/_\b\\", 0x0394 },
{ "*E", "E", 0x0395 },
{ "*Z", "Z", 0x0396 },
{ "*Y", "H", 0x0397 },
{ "*H", "-\bO", 0x0398 },
{ "*I", "I", 0x0399 },
{ "*K", "K", 0x039a },
{ "*L", "/\\", 0x039b },
{ "*M", "M", 0x039c },
{ "*N", "N", 0x039d },
{ "*C", "_\bH", 0x039e },
{ "*O", "O", 0x039f },
{ "*P", "TT", 0x03a0 },
{ "*R", "P", 0x03a1 },
{ "*S", "S", 0x03a3 },
{ "*T", "T", 0x03a4 },
{ "*U", "Y", 0x03a5 },
{ "*F", "I\bO", 0x03a6 },
{ "*X", "X", 0x03a7 },
{ "*Q", "I\bY", 0x03a8 },
{ "*W", "_\bO", 0x03a9 },
{ "*a", "a", 0x03b1 },
{ "*b", "B", 0x03b2 },
{ "*g", "y", 0x03b3 },
{ "*d", "d", 0x03b4 },
{ "*e", "e", 0x03b5 },
{ "*z", ",\bC", 0x03b6 },
{ "*y", "n", 0x03b7 },
{ "*h", "-\b0", 0x03b8 },
{ "*i", "i", 0x03b9 },
{ "*k", "k", 0x03ba },
{ "*l", ">\b\\", 0x03bb },
{ "*m", ",\bu", 0x03bc },
{ "*n", "v", 0x03bd },
{ "*c", ",\bE", 0x03be },
{ "*o", "o", 0x03bf },
{ "*p", "-\bn", 0x03c0 },
{ "*r", "p", 0x03c1 },
{ "*s", "-\bo", 0x03c3 },
{ "*t", "~\bt", 0x03c4 },
{ "*u", "u", 0x03c5 },
{ "*f", "|\bo", 0x03d5 },
{ "*x", "x", 0x03c7 },
{ "*q", "|\bu", 0x03c8 },
{ "*w", "w", 0x03c9 },
{ "+h", "-\b0", 0x03d1 },
{ "+f", "|\bo", 0x03c6 },
{ "+p", "-\bw", 0x03d6 },
{ "+e", "e", 0x03f5 },
{ "ts", "s", 0x03c2 },
}; };
static const struct ln *find(const struct mchars *, static struct ohash mchars;
const char *, size_t);
void void
mchars_free(struct mchars *arg) mchars_free(void)
{ {
free(arg->htab); ohash_delete(&mchars);
free(arg);
} }
struct mchars * void
mchars_alloc(void) mchars_alloc(void)
{ {
struct mchars *tab; size_t i;
struct ln **htab; unsigned int slot;
struct ln *pp;
int i, hash;
/* mandoc_ohash_init(&mchars, 9, offsetof(struct ln, roffcode));
* Constructs a very basic chaining hashtable. The hash routine for (i = 0; i < sizeof(lines)/sizeof(lines[0]); i++) {
* is simply the integral value of the first character. slot = ohash_qlookup(&mchars, lines[i].roffcode);
* Subsequent entries are chained in the order they're processed. assert(ohash_find(&mchars, slot) == NULL);
*/ ohash_insert(&mchars, slot, lines + i);
tab = mandoc_malloc(sizeof(struct mchars));
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;
if (NULL == (pp = htab[hash])) {
htab[hash] = &lines[i];
continue;
}
for ( ; pp->next; pp = pp->next)
/* Scan ahead. */ ;
pp->next = &lines[i];
} }
tab->htab = htab;
return(tab);
} }
int int
mchars_spec2cp(const struct mchars *arg, const char *p, size_t sz) mchars_spec2cp(const char *p, size_t sz)
{ {
const struct ln *ln; const struct ln *ln;
const char *end;
ln = find(arg, p, sz); end = p + sz;
return(ln != NULL ? ln->unicode : sz == 1 ? (unsigned char)*p : -1); ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end));
return ln != NULL ? ln->unicode : sz == 1 ? (unsigned char)*p : -1;
} }
int int
@ -113,7 +452,7 @@ mchars_num2char(const char *p, size_t sz)
int i; int i;
i = mandoc_strntoi(p, sz, 10); i = mandoc_strntoi(p, sz, 10);
return(i >= 0 && i < 256 ? i : -1); return i >= 0 && i < 256 ? i : -1;
} }
int int
@ -123,53 +462,33 @@ mchars_num2uc(const char *p, size_t sz)
i = mandoc_strntoi(p, sz, 16); i = mandoc_strntoi(p, sz, 16);
assert(i >= 0 && i <= 0x10FFFF); assert(i >= 0 && i <= 0x10FFFF);
return(i); return i;
} }
const char * const char *
mchars_spec2str(const struct mchars *arg, mchars_spec2str(const char *p, size_t sz, size_t *rsz)
const char *p, size_t sz, size_t *rsz)
{ {
const struct ln *ln; const struct ln *ln;
const char *end;
ln = find(arg, p, sz); end = p + sz;
ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end));
if (ln == NULL) { if (ln == NULL) {
*rsz = 1; *rsz = 1;
return(sz == 1 ? p : NULL); return sz == 1 ? p : NULL;
} }
*rsz = strlen(ln->ascii); *rsz = strlen(ln->ascii);
return(ln->ascii); return ln->ascii;
} }
const char * const char *
mchars_uc2str(int uc) mchars_uc2str(int uc)
{ {
int i; size_t i;
for (i = 0; i < LINES_MAX; i++) for (i = 0; i < sizeof(lines)/sizeof(lines[0]); i++)
if (uc == lines[i].unicode) if (uc == lines[i].unicode)
return(lines[i].ascii); return lines[i].ascii;
return("<?>"); return "<?>";
}
static const struct ln *
find(const struct mchars *tab, const char *p, size_t sz)
{
const struct ln *pp;
int hash;
assert(p);
if (0 == sz || p[0] < PRINT_LO || p[0] > PRINT_HI)
return(NULL);
hash = (int)p[0] - PRINT_LO;
for (pp = tab->htab[hash]; pp; pp = pp->next)
if (0 == strncmp(pp->code, p, sz) &&
'\0' == pp->code[(int)sz])
return(pp);
return(NULL);
} }

View File

@ -1,404 +0,0 @@
/* $Id: chars.in,v 1.52 2015/02/17 20:37:16 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 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.
*/
/*
* The ASCII translation tables.
*
* The left-hand side corresponds to the input sequence (\x, \(xx, \*(xx
* and so on) whose length is listed second element. The right-hand
* side is what's produced by the front-end, with the fourth element
* being its length.
*
* XXX - C-escape strings!
* XXX - update LINES_MAX if adding more!
*/
/* Special break control characters. */
static const char ascii_nbrsp[2] = { ASCII_NBRSP, '\0' };
static const char ascii_break[2] = { ASCII_BREAK, '\0' };
CHAR_TBL_START
/* Spacing. */
CHAR(" ", ascii_nbrsp, 160)
CHAR("~", ascii_nbrsp, 160)
CHAR("0", " ", 8194)
CHAR("|", "", 0)
CHAR("^", "", 0)
CHAR("&", "", 0)
CHAR("%", "", 0)
CHAR(":", ascii_break, 0)
/* XXX The following three do not really belong into this file. */
CHAR("t", "", 0)
CHAR("c", "", 0)
CHAR("}", "", 0)
/* Accents. */
CHAR("a\"", "\"", 733)
CHAR("a-", "-", 175)
CHAR("a.", ".", 729)
CHAR("a^", "^", 94)
CHAR("\'", "\'", 180)
CHAR("aa", "\'", 180)
CHAR("ga", "`", 96)
CHAR("`", "`", 96)
CHAR("ab", "'\b`", 728)
CHAR("ac", ",", 184)
CHAR("ad", "\"", 168)
CHAR("ah", "v", 711)
CHAR("ao", "o", 730)
CHAR("a~", "~", 126)
CHAR("ho", ",", 731)
CHAR("ha", "^", 94)
CHAR("ti", "~", 126)
/* Quotes. */
CHAR("Bq", ",,", 8222)
CHAR("bq", ",", 8218)
CHAR("lq", "\"", 8220)
CHAR("rq", "\"", 8221)
CHAR("Lq", "``", 8220)
CHAR("Rq", "''", 8221)
CHAR("oq", "`", 8216)
CHAR("cq", "\'", 8217)
CHAR("aq", "\'", 39)
CHAR("dq", "\"", 34)
CHAR("Fo", "<<", 171)
CHAR("Fc", ">>", 187)
CHAR("fo", "<", 8249)
CHAR("fc", ">", 8250)
/* Brackets. */
CHAR("lB", "[", 91)
CHAR("rB", "]", 93)
CHAR("lC", "{", 123)
CHAR("rC", "}", 125)
CHAR("la", "<", 10216)
CHAR("ra", ">", 10217)
CHAR("bv", "|", 9130)
CHAR("braceex", "|", 9130)
CHAR("bracketlefttp", "|", 9121)
CHAR("bracketleftbt", "|", 9123)
CHAR("bracketleftex", "|", 9122)
CHAR("bracketrighttp", "|", 9124)
CHAR("bracketrightbt", "|", 9126)
CHAR("bracketrightex", "|", 9125)
CHAR("lt", ",-", 9127)
CHAR("bracelefttp", ",-", 9127)
CHAR("lk", "{", 9128)
CHAR("braceleftmid", "{", 9128)
CHAR("lb", "`-", 9129)
CHAR("braceleftbt", "`-", 9129)
CHAR("braceleftex", "|", 9130)
CHAR("rt", "-.", 9131)
CHAR("bracerighttp", "-.", 9131)
CHAR("rk", "}", 9132)
CHAR("bracerightmid", "}", 9132)
CHAR("rb", "-\'", 9133)
CHAR("bracerightbt", "-\'", 9133)
CHAR("bracerightex", "|", 9130)
CHAR("parenlefttp", "/", 9115)
CHAR("parenleftbt", "\\", 9117)
CHAR("parenleftex", "|", 9116)
CHAR("parenrighttp", "\\", 9118)
CHAR("parenrightbt", "/", 9120)
CHAR("parenrightex", "|", 9119)
/* Greek characters. */
CHAR("*A", "A", 913)
CHAR("*B", "B", 914)
CHAR("*G", "G", 915)
CHAR("*D", "_\b/_\b\\", 916)
CHAR("*E", "E", 917)
CHAR("*Z", "Z", 918)
CHAR("*Y", "H", 919)
CHAR("*H", "-\bO", 920)
CHAR("*I", "I", 921)
CHAR("*K", "K", 922)
CHAR("*L", "/\\", 923)
CHAR("*M", "M", 924)
CHAR("*N", "N", 925)
CHAR("*C", "_\bH", 926)
CHAR("*O", "O", 927)
CHAR("*P", "TT", 928)
CHAR("*R", "P", 929)
CHAR("*S", "S", 931)
CHAR("*T", "T", 932)
CHAR("*U", "Y", 933)
CHAR("*F", "I\bO", 934)
CHAR("*X", "X", 935)
CHAR("*Q", "I\bY", 936)
CHAR("*W", "_\bO", 937)
CHAR("*a", "a", 945)
CHAR("*b", "B", 946)
CHAR("*g", "y", 947)
CHAR("*d", "d", 948)
CHAR("*e", "e", 949)
CHAR("*z", ",\bC", 950)
CHAR("*y", "n", 951)
CHAR("*h", "-\b0", 952)
CHAR("*i", "i", 953)
CHAR("*k", "k", 954)
CHAR("*l", ">\b\\", 955)
CHAR("*m", ",\bu", 956)
CHAR("*n", "v", 957)
CHAR("*c", ",\bE", 958)
CHAR("*o", "o", 959)
CHAR("*p", "-\bn", 960)
CHAR("*r", "p", 961)
CHAR("*s", "-\bo", 963)
CHAR("*t", "~\bt", 964)
CHAR("*u", "u", 965)
CHAR("*f", "|\bo", 981)
CHAR("*x", "x", 967)
CHAR("*q", "|\bu", 968)
CHAR("*w", "w", 969)
CHAR("+h", "-\b0", 977)
CHAR("+f", "|\bo", 966)
CHAR("+p", "-\bw", 982)
CHAR("+e", "e", 1013)
CHAR("ts", "s", 962)
/* Accented letters. */
CHAR(",C", ",\bC", 199)
CHAR(",c", ",\bc", 231)
CHAR("/L", "/\bL", 321)
CHAR("/O", "/\bO", 216)
CHAR("/l", "/\bl", 322)
CHAR("/o", "/\bo", 248)
CHAR("oA", "o\bA", 197)
CHAR("oa", "o\ba", 229)
CHAR(":A", "\"\bA", 196)
CHAR(":E", "\"\bE", 203)
CHAR(":I", "\"\bI", 207)
CHAR(":O", "\"\bO", 214)
CHAR(":U", "\"\bU", 220)
CHAR(":a", "\"\ba", 228)
CHAR(":e", "\"\be", 235)
CHAR(":i", "\"\bi", 239)
CHAR(":o", "\"\bo", 246)
CHAR(":u", "\"\bu", 252)
CHAR(":y", "\"\by", 255)
CHAR("'A", "'\bA", 193)
CHAR("'E", "'\bE", 201)
CHAR("'I", "'\bI", 205)
CHAR("'O", "'\bO", 211)
CHAR("'U", "'\bU", 218)
CHAR("'a", "'\ba", 225)
CHAR("'e", "'\be", 233)
CHAR("'i", "'\bi", 237)
CHAR("'o", "'\bo", 243)
CHAR("'u", "'\bu", 250)
CHAR("^A", "^\bA", 194)
CHAR("^E", "^\bE", 202)
CHAR("^I", "^\bI", 206)
CHAR("^O", "^\bO", 212)
CHAR("^U", "^\bU", 219)
CHAR("^a", "^\ba", 226)
CHAR("^e", "^\be", 234)
CHAR("^i", "^\bi", 238)
CHAR("^o", "^\bo", 244)
CHAR("^u", "^\bu", 251)
CHAR("`A", "`\bA", 192)
CHAR("`E", "`\bE", 200)
CHAR("`I", "`\bI", 204)
CHAR("`O", "`\bO", 210)
CHAR("`U", "`\bU", 217)
CHAR("`a", "`\ba", 224)
CHAR("`e", "`\be", 232)
CHAR("`i", "`\bi", 236)
CHAR("`o", "`\bo", 242)
CHAR("`u", "`\bu", 249)
CHAR("~A", "~\bA", 195)
CHAR("~N", "~\bN", 209)
CHAR("~O", "~\bO", 213)
CHAR("~a", "~\ba", 227)
CHAR("~n", "~\bn", 241)
CHAR("~o", "~\bo", 245)
/* Arrows and lines. */
CHAR("<-", "<-", 8592)
CHAR("->", "->", 8594)
CHAR("<>", "<->", 8596)
CHAR("da", "|\bv", 8595)
CHAR("ua", "|\b^", 8593)
CHAR("va", "^v", 8597)
CHAR("lA", "<=", 8656)
CHAR("rA", "=>", 8658)
CHAR("hA", "<=>", 8660)
CHAR("dA", "=\bv", 8659)
CHAR("uA", "=\b^", 8657)
CHAR("vA", "^=v", 8661)
/* Logic. */
CHAR("AN", "^", 8743)
CHAR("OR", "v", 8744)
CHAR("no", "~", 172)
CHAR("tno", "~", 172)
CHAR("te", "3", 8707)
CHAR("fa", "-\bV", 8704)
CHAR("st", "-)", 8715)
CHAR("tf", ".:.", 8756)
CHAR("3d", ".:.", 8756)
CHAR("or", "|", 124)
/* Mathematicals. */
CHAR("pl", "+", 43)
CHAR("mi", "-", 8722)
CHAR("-", "-", 45)
CHAR("-+", "-+", 8723)
CHAR("+-", "+-", 177)
CHAR("t+-", "+-", 177)
CHAR("pc", ".", 183)
CHAR("md", ".", 8901)
CHAR("mu", "x", 215)
CHAR("tmu", "x", 215)
CHAR("c*", "O\bx", 8855)
CHAR("c+", "O\b+", 8853)
CHAR("di", "-:-", 247)
CHAR("tdi", "-:-", 247)
CHAR("f/", "/", 8260)
CHAR("**", "*", 8727)
CHAR("<=", "<=", 8804)
CHAR(">=", ">=", 8805)
CHAR("<<", "<<", 8810)
CHAR(">>", ">>", 8811)
CHAR("eq", "=", 61)
CHAR("!=", "!=", 8800)
CHAR("==", "==", 8801)
CHAR("ne", "!==", 8802)
CHAR("=~", "=~", 8773)
CHAR("|=", "-~", 8771)
CHAR("ap", "~", 8764)
CHAR("~~", "~~", 8776)
CHAR("~=", "~=", 8776)
CHAR("pt", "oc", 8733)
CHAR("es", "{}", 8709)
CHAR("mo", "E", 8712)
CHAR("nm", "!E", 8713)
CHAR("sb", "(=", 8834)
CHAR("nb", "(!=", 8836)
CHAR("sp", "=)", 8835)
CHAR("nc", "!=)", 8837)
CHAR("ib", "(=\b_", 8838)
CHAR("ip", "=\b_)", 8839)
CHAR("ca", "(^)", 8745)
CHAR("cu", "U", 8746)
CHAR("/_", "_\b/", 8736)
CHAR("pp", "_\b|", 8869)
CHAR("is", "'\b,\bI", 8747)
CHAR("integral", "'\b,\bI", 8747)
CHAR("sum", "E", 8721)
CHAR("product", "TT", 8719)
CHAR("coproduct", "U", 8720)
CHAR("gr", "V", 8711)
CHAR("sr", "\\/", 8730)
CHAR("sqrt", "\\/", 8730)
CHAR("lc", "|~", 8968)
CHAR("rc", "~|", 8969)
CHAR("lf", "|_", 8970)
CHAR("rf", "_|", 8971)
CHAR("if", "oo", 8734)
CHAR("Ah", "N", 8501)
CHAR("Im", "I", 8465)
CHAR("Re", "R", 8476)
CHAR("pd", "a", 8706)
CHAR("-h", "/h", 8463)
CHAR("12", "1/2", 189)
CHAR("14", "1/4", 188)
CHAR("34", "3/4", 190)
/* Ligatures. */
CHAR("ff", "ff", 64256)
CHAR("fi", "fi", 64257)
CHAR("fl", "fl", 64258)
CHAR("Fi", "ffi", 64259)
CHAR("Fl", "ffl", 64260)
CHAR("AE", "AE", 198)
CHAR("ae", "ae", 230)
CHAR("OE", "OE", 338)
CHAR("oe", "oe", 339)
CHAR("ss", "ss", 223)
CHAR("IJ", "IJ", 306)
CHAR("ij", "ij", 307)
/* Special letters. */
CHAR("-D", "-\bD", 208)
CHAR("Sd", "d", 240)
CHAR("TP", "Th", 222)
CHAR("Tp", "th", 254)
CHAR(".i", "i", 305)
CHAR(".j", "j", 567)
/* Currency. */
CHAR("Do", "$", 36)
CHAR("ct", "/\bc", 162)
CHAR("Eu", "EUR", 8364)
CHAR("eu", "EUR", 8364)
CHAR("Ye", "=\bY", 165)
CHAR("Po", "GBP", 163)
CHAR("Cs", "o\bx", 164)
CHAR("Fn", ",\bf", 402)
/* Lines. */
CHAR("ba", "|", 124)
CHAR("br", "|", 9474)
CHAR("ul", "_", 95)
CHAR("rn", "-", 8254)
CHAR("bb", "|", 166)
CHAR("sl", "/", 47)
CHAR("rs", "\\", 92)
/* Text markers. */
CHAR("ci", "O", 9675)
CHAR("bu", "+\bo", 8226)
CHAR("dd", "|\b=", 8225)
CHAR("dg", "|\b-", 8224)
CHAR("lz", "<>", 9674)
CHAR("sq", "[]", 9633)
CHAR("ps", "<par>", 182)
CHAR("sc", "<sec>", 167)
CHAR("lh", "<=", 9756)
CHAR("rh", "=>", 9758)
CHAR("at", "@", 64)
CHAR("sh", "#", 35)
CHAR("CR", "_|", 8629)
CHAR("OK", "\\/", 10003)
/* Legal symbols. */
CHAR("co", "(C)", 169)
CHAR("rg", "(R)", 174)
CHAR("tm", "tm", 8482)
/* Punctuation. */
CHAR(".", ".", 46)
CHAR("r!", "!", 161)
CHAR("r?", "?", 191)
CHAR("em", "--", 8212)
CHAR("en", "-", 8211)
CHAR("hy", "-", 8208)
CHAR("e", "\\", 92)
/* Units. */
CHAR("de", "<deg>", 176)
CHAR("%0", "%o", 8240)
CHAR("fm", "\'", 8242)
CHAR("sd", "''", 8243)
CHAR("mc", ",\bu", 181)
CHAR_TBL_END

112
contrib/mdocml/compat_err.c Normal file
View File

@ -0,0 +1,112 @@
#include "config.h"
#if HAVE_ERR
int dummy;
#else
/* $Id: compat_err.c,v 1.4 2015/11/26 07:42:11 schwarze Exp $ */
/*
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void vwarni(const char *, va_list);
static void vwarnxi(const char *, va_list);
static void
vwarnxi(const char *fmt, va_list ap)
{
fprintf(stderr, "%s: ", getprogname());
if (fmt != NULL)
vfprintf(stderr, fmt, ap);
}
static void
vwarni(const char *fmt, va_list ap)
{
int sverrno;
sverrno = errno;
vwarnxi(fmt, ap);
if (fmt != NULL)
fputs(": ", stderr);
fprintf(stderr, "%s\n", strerror(sverrno));
}
void
err(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarni(fmt, ap);
va_end(ap);
exit(eval);
}
void
errx(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnxi(fmt, ap);
va_end(ap);
fputc('\n', stderr);
exit(eval);
}
void
warn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarni(fmt, ap);
va_end(ap);
}
void
warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnxi(fmt, ap);
va_end(ap);
fputc('\n', stderr);
}
#endif

View File

@ -1,94 +0,0 @@
#include "config.h"
#if HAVE_FGETLN
int dummy;
#else
/* $NetBSD: fgetln.c,v 1.3 2006/09/25 07:18:17 lukem Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *
fgetln(fp, len)
FILE *fp;
size_t *len;
{
static char *buf = NULL;
static size_t bufsiz = 0;
char *ptr;
if (buf == NULL) {
bufsiz = BUFSIZ;
if ((buf = malloc(bufsiz)) == NULL)
return NULL;
}
if (fgets(buf, bufsiz, fp) == NULL)
return NULL;
*len = 0;
while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
size_t nbufsiz = bufsiz + BUFSIZ;
char *nbuf = realloc(buf, nbufsiz);
if (nbuf == NULL) {
int oerrno = errno;
free(buf);
errno = oerrno;
buf = NULL;
return NULL;
} else
buf = nbuf;
*len = bufsiz;
if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL)
return buf;
bufsiz = nbufsiz;
}
*len = (ptr - buf) + 1;
return buf;
}
#endif

View File

@ -6,7 +6,7 @@ int dummy;
#else #else
/* $Id: compat_fts.c,v 1.8 2015/02/07 07:53:01 schwarze Exp $ */ /* $Id: compat_fts.c,v 1.9 2015/03/18 19:29:48 schwarze Exp $ */
/* $OpenBSD: fts.c,v 1.50 2015/01/16 16:48:51 deraadt Exp $ */ /* $OpenBSD: fts.c,v 1.50 2015/01/16 16:48:51 deraadt Exp $ */
/*- /*-
@ -60,7 +60,6 @@ static size_t fts_maxarglen(char * const *);
static void fts_padjust(FTS *, FTSENT *); static void fts_padjust(FTS *, FTSENT *);
static int fts_palloc(FTS *, size_t); static int fts_palloc(FTS *, size_t);
static unsigned short fts_stat(FTS *, FTSENT *); static unsigned short fts_stat(FTS *, FTSENT *);
static int fts_safe_changedir(FTS *, FTSENT *, int, const char *);
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
#ifndef O_DIRECTORY #ifndef O_DIRECTORY
@ -74,8 +73,6 @@ static int fts_safe_changedir(FTS *, FTSENT *, int, const char *);
#define ISSET(opt) (sp->fts_options & (opt)) #define ISSET(opt) (sp->fts_options & (opt))
#define SET(opt) (sp->fts_options |= (opt)) #define SET(opt) (sp->fts_options |= (opt))
#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
FTS * FTS *
fts_open(char * const *argv, int options, void *dummy) fts_open(char * const *argv, int options, void *dummy)
{ {
@ -146,17 +143,6 @@ fts_open(char * const *argv, int options, void *dummy)
sp->fts_cur->fts_link = root; sp->fts_cur->fts_link = root;
sp->fts_cur->fts_info = FTS_INIT; sp->fts_cur->fts_info = FTS_INIT;
/*
* If using chdir(2), grab a file descriptor pointing to dot to ensure
* that we can get back here; this could be avoided for some paths,
* but almost certainly not worth the effort. Slashes, symbolic links,
* and ".." are all fairly nasty problems. Note, if we can't get the
* descriptor we run anyway, just more slowly.
*/
if (!ISSET(FTS_NOCHDIR) &&
(sp->fts_rfd = open(".", O_RDONLY | O_CLOEXEC)) < 0)
SET(FTS_NOCHDIR);
if (nitems == 0) if (nitems == 0)
free(parent); free(parent);
@ -197,7 +183,6 @@ int
fts_close(FTS *sp) fts_close(FTS *sp)
{ {
FTSENT *freep, *p; FTSENT *freep, *p;
int rfd, error = 0;
/* /*
* This still works if we haven't read anything -- the dummy structure * This still works if we haven't read anything -- the dummy structure
@ -213,25 +198,13 @@ fts_close(FTS *sp)
free(p); free(p);
} }
/* Stash the original directory fd if needed. */
rfd = ISSET(FTS_NOCHDIR) ? -1 : sp->fts_rfd;
/* Free up child linked list, sort array, path buffer, stream ptr.*/ /* Free up child linked list, sort array, path buffer, stream ptr.*/
if (sp->fts_child) if (sp->fts_child)
fts_lfree(sp->fts_child); fts_lfree(sp->fts_child);
free(sp->fts_path); free(sp->fts_path);
free(sp); free(sp);
/* Return to original directory, checking for error. */ return (0);
if (rfd != -1) {
int saved_errno;
error = fchdir(rfd);
saved_errno = errno;
(void)close(rfd);
errno = saved_errno;
}
return (error);
} }
/* /*
@ -274,25 +247,11 @@ fts_read(FTS *sp)
} }
/* /*
* Cd to the subdirectory.
*
* If have already read and now fail to chdir, whack the list
* to make the names come out right, and set the parent errno
* so the application will eventually get an error condition.
* Set the FTS_DONTCHDIR flag so that when we logically change
* directories back to the parent we don't do a chdir.
*
* If haven't read do so. If the read fails, fts_build sets * If haven't read do so. If the read fails, fts_build sets
* FTS_STOP or the fts_info field of the node. * FTS_STOP or the fts_info field of the node.
*/ */
if (sp->fts_child) { if (sp->fts_child) {
if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { /* nothing */
p->fts_errno = errno;
p->fts_flags |= FTS_DONTCHDIR;
for (p = sp->fts_child; p; p = p->fts_link)
p->fts_accpath =
p->fts_parent->fts_accpath;
}
} else if ((sp->fts_child = fts_build(sp)) == NULL) { } else if ((sp->fts_child = fts_build(sp)) == NULL) {
if (ISSET(FTS_STOP)) if (ISSET(FTS_STOP))
return (NULL); return (NULL);
@ -313,10 +272,6 @@ next: tmp = p;
* the root of the tree), and load the paths for the next root. * the root of the tree), and load the paths for the next root.
*/ */
if (p->fts_level == FTS_ROOTLEVEL) { if (p->fts_level == FTS_ROOTLEVEL) {
if (FCHDIR(sp, sp->fts_rfd)) {
SET(FTS_STOP);
return (NULL);
}
fts_load(sp, p); fts_load(sp, p);
return (sp->fts_cur = p); return (sp->fts_cur = p);
} }
@ -352,23 +307,6 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
/* NUL terminate the pathname. */ /* NUL terminate the pathname. */
sp->fts_path[p->fts_pathlen] = '\0'; sp->fts_path[p->fts_pathlen] = '\0';
/*
* Return to the parent directory. If at a root node or came through
* a symlink, go back through the file descriptor. Otherwise, cd up
* one directory.
*/
if (p->fts_level == FTS_ROOTLEVEL) {
if (FCHDIR(sp, sp->fts_rfd)) {
SET(FTS_STOP);
sp->fts_cur = p;
return (NULL);
}
} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
SET(FTS_STOP);
sp->fts_cur = p;
return (NULL);
}
p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
return (sp->fts_cur = p); return (sp->fts_cur = p);
} }
@ -414,7 +352,7 @@ fts_build(FTS *sp)
DIR *dirp; DIR *dirp;
void *oldaddr; void *oldaddr;
size_t dlen, len, maxlen; size_t dlen, len, maxlen;
int nitems, cderrno, descend, level, doadjust; int nitems, level, doadjust;
int saved_errno; int saved_errno;
char *cp; char *cp;
@ -431,32 +369,6 @@ fts_build(FTS *sp)
return (NULL); return (NULL);
} }
/*
* If we're going to need to stat anything or we want to descend
* and stay in the directory, chdir. If this fails we keep going,
* but set a flag so we don't chdir after the post-order visit.
* We won't be able to stat anything, but we can still return the
* names themselves. Note, that since fts_read won't be able to
* chdir into the directory, it will have to return different path
* names than before, i.e. "a/b" instead of "b". Since the node
* has already been visited in pre-order, have to wait until the
* post-order visit to return the error. There is a special case
* here, if there was nothing to stat then it's not an error to
* not be able to stat. This is all fairly nasty. If a program
* needed sorted entries or stat information, they had better be
* checking FTS_NS on the returned nodes.
*/
cderrno = 0;
if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
cur->fts_errno = errno;
cur->fts_flags |= FTS_DONTCHDIR;
descend = 0;
cderrno = errno;
(void)closedir(dirp);
dirp = NULL;
} else
descend = 1;
/* /*
* Figure out the max file name length that can be stored in the * Figure out the max file name length that can be stored in the
* current path -- the inner loop allocates more path as necessary. * current path -- the inner loop allocates more path as necessary.
@ -468,10 +380,8 @@ fts_build(FTS *sp)
* each new name into the path. * each new name into the path.
*/ */
len = NAPPEND(cur); len = NAPPEND(cur);
if (ISSET(FTS_NOCHDIR)) { cp = sp->fts_path + len;
cp = sp->fts_path + len; *cp++ = '/';
*cp++ = '/';
}
len++; len++;
maxlen = sp->fts_pathlen - len; maxlen = sp->fts_pathlen - len;
@ -518,8 +428,7 @@ mem1: saved_errno = errno;
/* Did realloc() change the pointer? */ /* Did realloc() change the pointer? */
if (oldaddr != sp->fts_path) { if (oldaddr != sp->fts_path) {
doadjust = 1; doadjust = 1;
if (ISSET(FTS_NOCHDIR)) cp = sp->fts_path + len;
cp = sp->fts_path + len;
} }
maxlen = sp->fts_pathlen - len; maxlen = sp->fts_pathlen - len;
} }
@ -542,20 +451,11 @@ mem1: saved_errno = errno;
return (NULL); return (NULL);
} }
if (cderrno) { /* Build a file name for fts_stat to stat. */
p->fts_info = FTS_NS; p->fts_accpath = p->fts_path;
p->fts_errno = cderrno; memmove(cp, p->fts_name, p->fts_namelen + 1);
p->fts_accpath = cur->fts_accpath; /* Stat it. */
} else { p->fts_info = fts_stat(sp, p);
/* Build a file name for fts_stat to stat. */
if (ISSET(FTS_NOCHDIR)) {
p->fts_accpath = p->fts_path;
memmove(cp, p->fts_name, p->fts_namelen + 1);
} else
p->fts_accpath = p->fts_name;
/* Stat it. */
p->fts_info = fts_stat(sp, p);
}
/* We walk in directory order so "ls -f" doesn't get upset. */ /* We walk in directory order so "ls -f" doesn't get upset. */
p->fts_link = NULL; p->fts_link = NULL;
@ -581,26 +481,9 @@ mem1: saved_errno = errno;
* If not changing directories, reset the path back to original * If not changing directories, reset the path back to original
* state. * state.
*/ */
if (ISSET(FTS_NOCHDIR)) { if (len == sp->fts_pathlen || nitems == 0)
if (len == sp->fts_pathlen || nitems == 0) --cp;
--cp; *cp = '\0';
*cp = '\0';
}
/*
* If descended after called from fts_children or after called from
* fts_read and nothing found, get back. At the root level we use
* the saved fd; if one of fts_open()'s arguments is a relative path
* to an empty directory, we wind up here with no other way back. If
* can't get back, we're done.
*/
if (descend && !nitems &&
(cur->fts_level == FTS_ROOTLEVEL ? FCHDIR(sp, sp->fts_rfd) :
fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
cur->fts_info = FTS_ERR;
SET(FTS_STOP);
return (NULL);
}
/* If didn't find anything, return NULL. */ /* If didn't find anything, return NULL. */
if (!nitems) { if (!nitems) {
@ -771,38 +654,4 @@ fts_maxarglen(char * const *argv)
return (max + 1); return (max + 1);
} }
/*
* Change to dir specified by fd or p->fts_accpath without getting
* tricked by someone changing the world out from underneath us.
* Assumes p->fts_dev and p->fts_ino are filled in.
*/
static int
fts_safe_changedir(FTS *sp, FTSENT *p, int fd, const char *path)
{
int ret, oerrno, newfd;
struct stat sb;
newfd = fd;
if (ISSET(FTS_NOCHDIR))
return (0);
if (fd < 0 && (newfd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC)) < 0)
return (-1);
if (fstat(newfd, &sb)) {
ret = -1;
goto bail;
}
if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
errno = ENOENT; /* disinformation */
ret = -1;
goto bail;
}
ret = fchdir(newfd);
bail:
oerrno = errno;
if (fd < 0)
(void)close(newfd);
errno = oerrno;
return (ret);
}
#endif #endif

View File

@ -40,13 +40,12 @@ typedef struct {
struct _ftsent *fts_child; /* linked list of children */ struct _ftsent *fts_child; /* linked list of children */
dev_t fts_dev; /* starting device # */ dev_t fts_dev; /* starting device # */
char *fts_path; /* path for this descent */ char *fts_path; /* path for this descent */
int fts_rfd; /* fd for root */
size_t fts_pathlen; /* sizeof(path) */ size_t fts_pathlen; /* sizeof(path) */
#define FTS_NOCHDIR 0x0004 /* don't change directories */ #define FTS_NOCHDIR 0x0004 /* don't change directories */
#define FTS_PHYSICAL 0x0010 /* physical walk */ #define FTS_PHYSICAL 0x0010 /* physical walk */
#define FTS_XDEV 0x0040 /* don't cross devices */ #define FTS_XDEV 0x0040 /* don't cross devices */
#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ #define FTS_OPTIONMASK 0x0054 /* valid user option mask */
#define FTS_STOP 0x2000 /* (private) unrecoverable error */ #define FTS_STOP 0x2000 /* (private) unrecoverable error */
int fts_options; /* fts_open options, global flags */ int fts_options; /* fts_open options, global flags */
@ -85,9 +84,6 @@ typedef struct _ftsent {
#define FTS_SL 12 /* symbolic link */ #define FTS_SL 12 /* symbolic link */
unsigned short fts_info; /* user flags for FTSENT structure */ unsigned short fts_info; /* user flags for FTSENT structure */
#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */
unsigned short fts_flags; /* private flags for FTSENT structure */
#define FTS_NOINSTR 3 /* no instructions */ #define FTS_NOINSTR 3 /* no instructions */
#define FTS_SKIP 4 /* discard node */ #define FTS_SKIP 4 /* discard node */
unsigned short fts_instr; /* fts_set() instructions */ unsigned short fts_instr; /* fts_set() instructions */
@ -96,11 +92,10 @@ typedef struct _ftsent {
char fts_name[1]; /* file name */ char fts_name[1]; /* file name */
} FTSENT; } FTSENT;
__BEGIN_DECLS
int fts_close(FTS *); int fts_close(FTS *);
FTS *fts_open(char * const *, int, void *); FTS *fts_open(char * const *, int, void *);
FTSENT *fts_read(FTS *); FTSENT *fts_read(FTS *);
int fts_set(FTS *, FTSENT *, int); int fts_set(FTS *, FTSENT *, int);
__END_DECLS
#endif /* !_FTS_H_ */ #endif /* !_FTS_H_ */

View File

@ -0,0 +1,68 @@
#include "config.h"
#if HAVE_GETLINE
int dummy;
#else
/* $Id: compat_getline.c,v 1.1 2015/11/07 20:52:52 schwarze Exp $ */
/*
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
ssize_t
getline(char **buf, size_t *bufsz, FILE *fp)
{
char *nbuf;
size_t nbufsz, pos;
int c;
if (buf == NULL || bufsz == NULL) {
errno = EINVAL;
return -1;
}
if (*buf == NULL)
*bufsz = 0;
else
**buf = '\0';
pos = 0;
for (;;) {
if (pos + 1 >= *bufsz) {
nbufsz = *bufsz ? *bufsz * 2 : BUFSIZ;
if ((nbuf = realloc(*buf, nbufsz)) == NULL)
return -1;
*buf = nbuf;
*bufsz = nbufsz;
}
if ((c = fgetc(fp)) == EOF) {
(*buf)[pos] = '\0';
return pos > 0 && feof(fp) ? (ssize_t)pos : -1;
}
(*buf)[pos++] = c;
(*buf)[pos] = '\0';
if (c == '\n')
return pos;
}
}
#endif

View File

@ -0,0 +1,33 @@
#include "config.h"
#if HAVE_ISBLANK
int dummy;
#else
/* $Id: compat_isblank.c,v 1.2 2015/10/06 18:32:19 schwarze Exp $ */
/*
* Copyright (c) 2015 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.
*/
int
isblank(int c)
{
return c == ' ' || c == '\t';
}
#endif

View File

@ -0,0 +1,61 @@
#include "config.h"
#if HAVE_MKDTEMP
int dummy;
#else
/* $Id: compat_mkdtemp.c,v 1.2 2015/10/06 18:32:19 schwarze Exp $ */
/*
* Copyright (c) 2015 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.
*
* The algorithm of this function is inspired by OpenBSD mkdtemp(3)
* by Theo de Raadt and Todd Miller, but the code differs.
*/
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
char *
mkdtemp(char *path)
{
char *start, *cp;
unsigned int tries;
start = strchr(path, '\0');
while (start > path && start[-1] == 'X')
start--;
for (tries = INT_MAX; tries; tries--) {
if (mktemp(path) == NULL) {
errno = EEXIST;
return NULL;
}
if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR) == 0)
return path;
if (errno != EEXIST)
return NULL;
for (cp = start; *cp != '\0'; cp++)
*cp = 'X';
}
errno = EEXIST;
return NULL;
}
#endif

View File

@ -49,7 +49,6 @@ struct ohash {
* a hashing table index (opaque) to be used in find/insert/remove. * a hashing table index (opaque) to be used in find/insert/remove.
* The keys are stored at a known position in the client data. * The keys are stored at a known position in the client data.
*/ */
__BEGIN_DECLS
void ohash_init(struct ohash *, unsigned, struct ohash_info *); void ohash_init(struct ohash *, unsigned, struct ohash_info *);
void ohash_delete(struct ohash *); void ohash_delete(struct ohash *);
@ -69,5 +68,5 @@ uint32_t ohash_interval(const char *, const char **);
unsigned int ohash_qlookupi(struct ohash *, const char *, const char **); unsigned int ohash_qlookupi(struct ohash *, const char *, const char **);
unsigned int ohash_qlookup(struct ohash *, const char *); unsigned int ohash_qlookup(struct ohash *, const char *);
__END_DECLS
#endif #endif

View File

@ -0,0 +1,42 @@
#include "config.h"
#if HAVE_PROGNAME
int dummy;
#else
/* $Id: compat_progname.c,v 1.1 2015/11/06 16:30:33 schwarze Exp $ */
/*
* Copyright (c) 2015 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.
*/
static const char *progname;
void
setprogname(const char *name)
{
progname = name;
}
const char *
getprogname(void)
{
return progname;
}
#endif

View File

@ -10,7 +10,7 @@ const char *
sqlite3_errstr(int rc) sqlite3_errstr(int rc)
{ {
return(rc ? "unknown error" : "not an error"); return rc ? "unknown error" : "not an error";
} }
#endif #endif

View File

@ -0,0 +1,119 @@
#include "config.h"
#if HAVE_STRINGLIST
int dummy;
#else
/* $Id: compat_stringlist.c,v 1.6 2015/11/07 14:22:29 schwarze Exp $ */
/*
* Copyright (c) 1994 Christos Zoulas <christos@netbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if HAVE_ERR
#include <err.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "compat_stringlist.h"
#define _SL_CHUNKSIZE 20
/*
* sl_init(): Initialize a string list
*/
StringList *
sl_init(void)
{
StringList *sl;
sl = malloc(sizeof(StringList));
if (sl == NULL)
err(1, "stringlist");
sl->sl_cur = 0;
sl->sl_max = _SL_CHUNKSIZE;
sl->sl_str = reallocarray(NULL, sl->sl_max, sizeof(char *));
if (sl->sl_str == NULL)
err(1, "stringlist");
return sl;
}
/*
* sl_add(): Add an item to the string list
*/
int
sl_add(StringList *sl, char *name)
{
if (sl->sl_cur == sl->sl_max - 1) {
sl->sl_max += _SL_CHUNKSIZE;
sl->sl_str = reallocarray(sl->sl_str,
sl->sl_max, sizeof(char *));
if (sl->sl_str == NULL)
return (-1);
}
sl->sl_str[sl->sl_cur++] = name;
return (0);
}
/*
* sl_free(): Free a stringlist
*/
void
sl_free(StringList *sl, int all)
{
size_t i;
if (sl == NULL)
return;
if (sl->sl_str) {
if (all)
for (i = 0; i < sl->sl_cur; i++)
free(sl->sl_str[i]);
free(sl->sl_str);
}
free(sl);
}
/*
* sl_find(): Find a name in the string list
*/
char *
sl_find(StringList *sl, const char *name)
{
size_t i;
for (i = 0; i < sl->sl_cur; i++)
if (strcmp(sl->sl_str[i], name) == 0)
return sl->sl_str[i];
return NULL;
}
#endif

View File

@ -0,0 +1,45 @@
/* $Id: compat_stringlist.h,v 1.4 2015/11/07 14:01:16 schwarze Exp $ */
/* $NetBSD: stringlist.h,v 1.2 1997/01/17 06:11:36 lukem Exp $ */
/*
* Copyright (c) 1994 Christos Zoulas <christos@netbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
/*
* Simple string list
*/
typedef struct _stringlist {
char **sl_str;
size_t sl_max;
size_t sl_cur;
} StringList;
StringList *sl_init(void);
int sl_add(StringList *, char *);
void sl_free(StringList *, int);
char *sl_find(StringList *, const char *);

View File

@ -0,0 +1,56 @@
#include "config.h"
#if HAVE_VASPRINTF
int dummy;
#else
/* $Id: compat_vasprintf.c,v 1.3 2015/10/06 18:32:19 schwarze Exp $ */
/*
* Copyright (c) 2015 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.
*
* This fallback implementation is not efficient:
* It does the formatting twice.
* Short of fiddling with the unknown internals of the system's
* printf(3) or completely reimplementing printf(3), i can't think
* of another portable solution.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
int
vasprintf(char **ret, const char *format, va_list ap)
{
char buf[2];
va_list ap2;
int sz;
va_copy(ap2, ap);
sz = vsnprintf(buf, sizeof(buf), format, ap2);
va_end(ap2);
if (sz != -1 && (*ret = malloc(sz + 1)) != NULL) {
if (vsnprintf(*ret, sz + 1, format, ap) == sz)
return sz;
free(*ret);
}
*ret = NULL;
return -1;
}
#endif

View File

@ -1,3 +1,7 @@
#ifdef __cplusplus
#error "Do not use C++. See the INSTALL file."
#endif
#ifndef MANDOC_CONFIG_H #ifndef MANDOC_CONFIG_H
#define MANDOC_CONFIG_H #define MANDOC_CONFIG_H
@ -6,19 +10,30 @@
#endif #endif
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h>
#define MAN_CONF_FILE "/etc/man.conf"
#define HAVE_DIRENT_NAMLEN 1 #define HAVE_DIRENT_NAMLEN 1
#define HAVE_FGETLN 1 #define HAVE_ERR 1
#define HAVE_FTS 1 #define HAVE_FTS 1
#define HAVE_GETLINE 1
#define HAVE_GETSUBOPT 1 #define HAVE_GETSUBOPT 1
#define HAVE_ISBLANK 1
#define HAVE_MKDTEMP 1
#define HAVE_MMAP 1 #define HAVE_MMAP 1
#define HAVE_PLEDGE 0
#define HAVE_PROGNAME 1
#define HAVE_REALLOCARRAY 1 #define HAVE_REALLOCARRAY 1
#define HAVE_REWB_BSD 0
#define HAVE_REWB_SYSV 0
#define HAVE_STRCASESTR 1 #define HAVE_STRCASESTR 1
#define HAVE_STRINGLIST 1
#define HAVE_STRLCAT 1 #define HAVE_STRLCAT 1
#define HAVE_STRLCPY 1 #define HAVE_STRLCPY 1
#define HAVE_STRPTIME 1 #define HAVE_STRPTIME 1
#define HAVE_STRSEP 1 #define HAVE_STRSEP 1
#define HAVE_STRTONUM 1 #define HAVE_STRTONUM 1
#define HAVE_VASPRINTF 1
#define HAVE_WCHAR 1 #define HAVE_WCHAR 1
#define HAVE_SQLITE3 1 #define HAVE_SQLITE3 1
#define HAVE_SQLITE3_ERRSTR 0 #define HAVE_SQLITE3_ERRSTR 0
@ -26,26 +41,12 @@
#define HAVE_MANPATH 1 #define HAVE_MANPATH 1
#define BINM_APROPOS "apropos" #define BINM_APROPOS "apropos"
#define BINM_MAN "man"
#define BINM_WHATIS "whatis"
#define BINM_MAKEWHATIS "makewhatis" #define BINM_MAKEWHATIS "makewhatis"
#define BINM_MAN "man"
#define BINM_SOELIM "soelim"
#define BINM_WHATIS "whatis"
#if !defined(__BEGIN_DECLS) extern ssize_t getline(char **, size_t *, FILE *);
# ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# else
# define __BEGIN_DECLS
# endif
#endif
#if !defined(__END_DECLS)
# ifdef __cplusplus
# define __END_DECLS }
# else
# define __END_DECLS
# endif
#endif
extern void *reallocarray(void *, size_t, size_t);
extern const char *sqlite3_errstr(int); extern const char *sqlite3_errstr(int);
#endif /* MANDOC_CONFIG_H */ #endif /* MANDOC_CONFIG_H */

210
contrib/mdocml/config.log Normal file
View File

@ -0,0 +1,210 @@
configure.local: no (fully automatic configuration)
dirent-namlen: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-dirent-namlen test-dirent-namlen.c
dirent-namlen: cc succeeded
dirent-namlen: yes
err: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-err test-err.c
err: cc succeeded
test-err: 1. warnx
test-err: 2. warn: No error: 0
test-err: 3. err: No error: 0
err: yes
fts: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-fts test-fts.c
fts: cc succeeded
fts: yes
getline: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-getline test-getline.c
test-getline.c:12:9: error: implicit declaration of function 'getline' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
return getline(&line, &linesz, stdin) != -1;
^
1 error generated.
getline: cc failed with 1
getsubopt: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-getsubopt test-getsubopt.c
getsubopt: cc succeeded
getsubopt: yes
isblank: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-isblank test-isblank.c
isblank: cc succeeded
isblank: yes
mkdtemp: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-mkdtemp test-mkdtemp.c
mkdtemp: cc succeeded
mkdtemp: yes
mmap: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-mmap test-mmap.c
mmap: cc succeeded
mmap: yes
pledge: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-pledge test-pledge.c
test-pledge.c:6:11: error: implicit declaration of function 'pledge' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
return !!pledge("stdio", NULL);
^
1 error generated.
pledge: cc failed with 1
progname: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-progname test-progname.c
progname: cc succeeded
progname: yes
reallocarray: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-reallocarray test-reallocarray.c
reallocarray: cc succeeded
reallocarray: yes
rewb-bsd: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-rewb-bsd test-rewb-bsd.c
test-rewb-bsd.c:11:42: error: use of undeclared identifier 'NULL'
if (regexec(&re, "the word is here", 0, NULL, 0))
^
test-rewb-bsd.c:13:35: error: use of undeclared identifier 'NULL'
if (regexec(&re, "same word", 0, NULL, 0))
^
test-rewb-bsd.c:15:36: error: use of undeclared identifier 'NULL'
if (regexec(&re, "word again", 0, NULL, 0))
^
test-rewb-bsd.c:17:30: error: use of undeclared identifier 'NULL'
if (regexec(&re, "word", 0, NULL, 0))
^
test-rewb-bsd.c:19:31: error: use of undeclared identifier 'NULL'
if (regexec(&re, "wordy", 0, NULL, 0) != REG_NOMATCH)
^
test-rewb-bsd.c:21:31: error: use of undeclared identifier 'NULL'
if (regexec(&re, "sword", 0, NULL, 0) != REG_NOMATCH)
^
test-rewb-bsd.c:23:34: error: use of undeclared identifier 'NULL'
if (regexec(&re, "reworded", 0, NULL, 0) != REG_NOMATCH)
^
7 errors generated.
rewb-bsd: cc failed with 1
rewb-sysv: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-rewb-sysv test-rewb-sysv.c
test-rewb-sysv.c:11:42: error: use of undeclared identifier 'NULL'
if (regexec(&re, "the word is here", 0, NULL, 0))
^
test-rewb-sysv.c:13:35: error: use of undeclared identifier 'NULL'
if (regexec(&re, "same word", 0, NULL, 0))
^
test-rewb-sysv.c:15:36: error: use of undeclared identifier 'NULL'
if (regexec(&re, "word again", 0, NULL, 0))
^
test-rewb-sysv.c:17:30: error: use of undeclared identifier 'NULL'
if (regexec(&re, "word", 0, NULL, 0))
^
test-rewb-sysv.c:19:31: error: use of undeclared identifier 'NULL'
if (regexec(&re, "wordy", 0, NULL, 0) != REG_NOMATCH)
^
test-rewb-sysv.c:21:31: error: use of undeclared identifier 'NULL'
if (regexec(&re, "sword", 0, NULL, 0) != REG_NOMATCH)
^
test-rewb-sysv.c:23:34: error: use of undeclared identifier 'NULL'
if (regexec(&re, "reworded", 0, NULL, 0) != REG_NOMATCH)
^
7 errors generated.
rewb-sysv: cc failed with 1
strcasestr: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-strcasestr test-strcasestr.c
strcasestr: cc succeeded
strcasestr: yes
stringlist: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-stringlist test-stringlist.c
test-stringlist.c:26:26: error: use of undeclared identifier 'NULL'
if ((sl = sl_init()) == NULL)
^
1 error generated.
stringlist: cc failed with 1
strlcat: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-strlcat test-strlcat.c
strlcat: cc succeeded
strlcat: yes
strlcpy: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-strlcpy test-strlcpy.c
strlcpy: cc succeeded
strlcpy: yes
strptime: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-strptime test-strptime.c
strptime: cc succeeded
strptime: yes
strsep: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-strsep test-strsep.c
strsep: cc succeeded
strsep: yes
strtonum: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-strtonum test-strtonum.c
strtonum: cc succeeded
strtonum: yes
vasprintf: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-vasprintf test-vasprintf.c
vasprintf: cc succeeded
vasprintf: yes
wchar: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-wchar test-wchar.c
wchar: cc succeeded
*wchar: yes
sqlite3: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -lsqlite3 -o test-sqlite3 test-sqlite3.c
test-sqlite3.c:20:10: fatal error: 'sqlite3.h' file not found
#include <sqlite3.h>
^
1 error generated.
sqlite3: cc failed with 1
sqlite3: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -I/usr/local/include -L/usr/local/lib -lsqlite3 -o test-sqlite3 test-sqlite3.c
sqlite3: cc succeeded
sqlite3: yes
sqlite3_errstr: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -L/usr/local/lib -lsqlite3 -o test-sqlite3_errstr test-sqlite3_errstr.c
test-sqlite3_errstr.c:2:10: fatal error: 'sqlite3.h' file not found
#include <sqlite3.h>
^
1 error generated.
sqlite3_errstr: cc failed with 1
ohash: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -o test-ohash test-ohash.c
test-ohash.c:4:10: fatal error: 'ohash.h' file not found
#include <ohash.h>
^
1 error generated.
ohash: cc failed with 1
ohash: testing...
cc -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -Wno-unused -Werror -lutil -o test-ohash test-ohash.c
test-ohash.c:4:10: fatal error: 'ohash.h' file not found
#include <ohash.h>
^
1 error generated.
ohash: cc failed with 1
DBLIB="-L/usr/local/lib -lsqlite3 -lz"
/usr/share/man:/usr/local/man:/usr/share/openssl/man:/usr/local/lib/perl5/site_perl/man:/usr/local/lib/perl5/5.20/perl/man:/usr/local/share/xpdf/man
manpath: yes
config.h: written
Makefile.local: written

View File

@ -16,8 +16,8 @@
set -e set -e
[ -e config.log ] && mv config.log config.log.old [ -w config.log ] && mv config.log config.log.old
[ -e config.h ] && mv config.h config.h.old [ -w config.h ] && mv config.h config.h.old
# Output file descriptor usage: # Output file descriptor usage:
# 1 (stdout): config.h, Makefile.local # 1 (stdout): config.h, Makefile.local
@ -31,6 +31,7 @@ echo "config.log: writing..."
# Initialize all variables here, # Initialize all variables here,
# such that nothing can leak in from the environment. # such that nothing can leak in from the environment.
MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
OSNAME= OSNAME=
CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make -f -` CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make -f -`
@ -42,17 +43,26 @@ BUILD_DB=1
BUILD_CGI=0 BUILD_CGI=0
HAVE_DIRENT_NAMLEN= HAVE_DIRENT_NAMLEN=
HAVE_FGETLN= HAVE_ERR=
HAVE_FTS= HAVE_FTS=
HAVE_GETLINE=
HAVE_GETSUBOPT= HAVE_GETSUBOPT=
HAVE_ISBLANK=
HAVE_MKDTEMP=
HAVE_MMAP= HAVE_MMAP=
HAVE_PLEDGE=
HAVE_PROGNAME=
HAVE_REALLOCARRAY= HAVE_REALLOCARRAY=
HAVE_REWB_BSD=
HAVE_REWB_SYSV=
HAVE_STRCASESTR= HAVE_STRCASESTR=
HAVE_STRINGLIST=
HAVE_STRLCAT= HAVE_STRLCAT=
HAVE_STRLCPY= HAVE_STRLCPY=
HAVE_STRPTIME= HAVE_STRPTIME=
HAVE_STRSEP= HAVE_STRSEP=
HAVE_STRTONUM= HAVE_STRTONUM=
HAVE_VASPRINTF=
HAVE_WCHAR= HAVE_WCHAR=
HAVE_SQLITE3= HAVE_SQLITE3=
@ -66,7 +76,6 @@ SBINDIR=
INCLUDEDIR= INCLUDEDIR=
LIBDIR= LIBDIR=
MANDIR= MANDIR=
EXAMPLEDIR=
HOMEBREWDIR= HOMEBREWDIR=
WWWPREFIX="/var/www" WWWPREFIX="/var/www"
@ -74,10 +83,12 @@ HTDOCDIR=
CGIBINDIR= CGIBINDIR=
BINM_APROPOS="apropos" BINM_APROPOS="apropos"
BINM_MAN="man"
BINM_WHATIS="whatis"
BINM_MAKEWHATIS="makewhatis" BINM_MAKEWHATIS="makewhatis"
BINM_MAN="man"
BINM_SOELIM="soelim"
BINM_WHATIS="whatis"
MANM_MAN="man" MANM_MAN="man"
MANM_MANCONF="man.conf"
MANM_MDOC="mdoc" MANM_MDOC="mdoc"
MANM_ROFF="roff" MANM_ROFF="roff"
MANM_EQN="eqn" MANM_EQN="eqn"
@ -91,7 +102,7 @@ INSTALL_DATA=
# --- manual settings from configure.local ----------------------------- # --- manual settings from configure.local -----------------------------
if [ -e ./configure.local ]; then if [ -r ./configure.local ]; then
echo "configure.local: reading..." 1>&2 echo "configure.local: reading..." 1>&2
echo "configure.local: reading..." 1>&3 echo "configure.local: reading..." 1>&3
cat ./configure.local 1>&3 cat ./configure.local 1>&3
@ -164,17 +175,26 @@ runtest() {
# --- library functions --- # --- library functions ---
runtest dirent-namlen DIRENT_NAMLEN || true runtest dirent-namlen DIRENT_NAMLEN || true
runtest fgetln FGETLN || true runtest err ERR || true
runtest fts FTS || true runtest fts FTS || true
runtest getline GETLINE || true
runtest getsubopt GETSUBOPT || true runtest getsubopt GETSUBOPT || true
runtest isblank ISBLANK || true
runtest mkdtemp MKDTEMP || true
runtest mmap MMAP || true runtest mmap MMAP || true
runtest pledge PLEDGE || true
runtest progname PROGNAME || true
runtest reallocarray REALLOCARRAY || true runtest reallocarray REALLOCARRAY || true
runtest rewb-bsd REWB_BSD || true
runtest rewb-sysv REWB_SYSV || true
runtest strcasestr STRCASESTR || true runtest strcasestr STRCASESTR || true
runtest stringlist STRINGLIST || true
runtest strlcat STRLCAT || true runtest strlcat STRLCAT || true
runtest strlcpy STRLCPY || true runtest strlcpy STRLCPY || true
runtest strptime STRPTIME || true runtest strptime STRPTIME || true
runtest strsep STRSEP || true runtest strsep STRSEP || true
runtest strtonum STRTONUM || true runtest strtonum STRTONUM || true
runtest vasprintf VASPRINTF || true
runtest wchar WCHAR || true runtest wchar WCHAR || true
# --- sqlite3 --- # --- sqlite3 ---
@ -228,9 +248,9 @@ fi
# --- DBLIB --- # --- DBLIB ---
if [ ${BUILD_DB} -eq 0 ]; then if [ ${BUILD_DB} -eq 0 ]; then
DBLIB= DBLIB="-lz"
elif [ -z "${DBLIB}" ]; then elif [ -z "${DBLIB}" ]; then
DBLIB="${DETECTLIB}" DBLIB="${DETECTLIB} -lz"
echo "DBLIB=\"${DBLIB}\"" 1>&2 echo "DBLIB=\"${DBLIB}\"" 1>&2
echo "DBLIB=\"${DBLIB}\"" 1>&3 echo "DBLIB=\"${DBLIB}\"" 1>&3
echo 1>&3 echo 1>&3
@ -256,6 +276,10 @@ fi
exec > config.h exec > config.h
cat << __HEREDOC__ cat << __HEREDOC__
#ifdef __cplusplus
#error "Do not use C++. See the INSTALL file."
#endif
#ifndef MANDOC_CONFIG_H #ifndef MANDOC_CONFIG_H
#define MANDOC_CONFIG_H #define MANDOC_CONFIG_H
@ -265,28 +289,40 @@ cat << __HEREDOC__
__HEREDOC__ __HEREDOC__
[ ${HAVE_FGETLN} -eq 0 -o ${HAVE_REALLOCARRAY} -eq 0 -o \ [ ${HAVE_GETLINE} -eq 0 -o ${HAVE_REALLOCARRAY} -eq 0 -o \
${HAVE_STRLCAT} -eq 0 -o ${HAVE_STRLCPY} -eq 0 ] \ ${HAVE_STRLCAT} -eq 0 -o ${HAVE_STRLCPY} -eq 0 ] \
&& echo "#include <sys/types.h>" && echo "#include <sys/types.h>"
[ ${HAVE_FGETLN} -eq 0 ] && echo "#include <stdio.h>" [ ${HAVE_VASPRINTF} -eq 0 ] && echo "#include <stdarg.h>"
[ ${HAVE_GETLINE} -eq 0 ] && echo "#include <stdio.h>"
echo echo
echo "#define MAN_CONF_FILE \"/etc/${MANM_MANCONF}\""
echo "#define MANPATH_DEFAULT \"${MANPATH_DEFAULT}\""
[ -n "${OSNAME}" ] && echo "#define OSNAME \"${OSNAME}\"" [ -n "${OSNAME}" ] && echo "#define OSNAME \"${OSNAME}\""
[ -n "${HOMEBREWDIR}" ] && echo "#define HOMEBREWDIR \"${HOMEBREWDIR}\"" [ -n "${HOMEBREWDIR}" ] && echo "#define HOMEBREWDIR \"${HOMEBREWDIR}\""
cat << __HEREDOC__ cat << __HEREDOC__
#define HAVE_DIRENT_NAMLEN ${HAVE_DIRENT_NAMLEN} #define HAVE_DIRENT_NAMLEN ${HAVE_DIRENT_NAMLEN}
#define HAVE_FGETLN ${HAVE_FGETLN} #define HAVE_ERR ${HAVE_ERR}
#define HAVE_FTS ${HAVE_FTS} #define HAVE_FTS ${HAVE_FTS}
#define HAVE_GETLINE ${HAVE_GETLINE}
#define HAVE_GETSUBOPT ${HAVE_GETSUBOPT} #define HAVE_GETSUBOPT ${HAVE_GETSUBOPT}
#define HAVE_ISBLANK ${HAVE_ISBLANK}
#define HAVE_MKDTEMP ${HAVE_MKDTEMP}
#define HAVE_MMAP ${HAVE_MMAP} #define HAVE_MMAP ${HAVE_MMAP}
#define HAVE_PLEDGE ${HAVE_PLEDGE}
#define HAVE_PROGNAME ${HAVE_PROGNAME}
#define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY} #define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY}
#define HAVE_REWB_BSD ${HAVE_REWB_BSD}
#define HAVE_REWB_SYSV ${HAVE_REWB_SYSV}
#define HAVE_STRCASESTR ${HAVE_STRCASESTR} #define HAVE_STRCASESTR ${HAVE_STRCASESTR}
#define HAVE_STRINGLIST ${HAVE_STRINGLIST}
#define HAVE_STRLCAT ${HAVE_STRLCAT} #define HAVE_STRLCAT ${HAVE_STRLCAT}
#define HAVE_STRLCPY ${HAVE_STRLCPY} #define HAVE_STRLCPY ${HAVE_STRLCPY}
#define HAVE_STRPTIME ${HAVE_STRPTIME} #define HAVE_STRPTIME ${HAVE_STRPTIME}
#define HAVE_STRSEP ${HAVE_STRSEP} #define HAVE_STRSEP ${HAVE_STRSEP}
#define HAVE_STRTONUM ${HAVE_STRTONUM} #define HAVE_STRTONUM ${HAVE_STRTONUM}
#define HAVE_VASPRINTF ${HAVE_VASPRINTF}
#define HAVE_WCHAR ${HAVE_WCHAR} #define HAVE_WCHAR ${HAVE_WCHAR}
#define HAVE_SQLITE3 ${HAVE_SQLITE3} #define HAVE_SQLITE3 ${HAVE_SQLITE3}
#define HAVE_SQLITE3_ERRSTR ${HAVE_SQLITE3_ERRSTR} #define HAVE_SQLITE3_ERRSTR ${HAVE_SQLITE3_ERRSTR}
@ -294,33 +330,37 @@ cat << __HEREDOC__
#define HAVE_MANPATH ${HAVE_MANPATH} #define HAVE_MANPATH ${HAVE_MANPATH}
#define BINM_APROPOS "${BINM_APROPOS}" #define BINM_APROPOS "${BINM_APROPOS}"
#define BINM_MAN "${BINM_MAN}"
#define BINM_WHATIS "${BINM_WHATIS}"
#define BINM_MAKEWHATIS "${BINM_MAKEWHATIS}" #define BINM_MAKEWHATIS "${BINM_MAKEWHATIS}"
#define BINM_MAN "${BINM_MAN}"
#if !defined(__BEGIN_DECLS) #define BINM_SOELIM "${BINM_SOELIM}"
# ifdef __cplusplus #define BINM_WHATIS "${BINM_WHATIS}"
# define __BEGIN_DECLS extern "C" {
# else
# define __BEGIN_DECLS
# endif
#endif
#if !defined(__END_DECLS)
# ifdef __cplusplus
# define __END_DECLS }
# else
# define __END_DECLS
# endif
#endif
__HEREDOC__ __HEREDOC__
[ ${HAVE_FGETLN} -eq 0 ] && \ if [ ${HAVE_ERR} -eq 0 ]; then
echo "extern char *fgetln(FILE *, size_t *);" echo "extern void err(int, const char *, ...);"
echo "extern void errx(int, const char *, ...);"
echo "extern void warn(const char *, ...);"
echo "extern void warnx(const char *, ...);"
fi
[ ${HAVE_GETLINE} -eq 0 ] && \
echo "extern ssize_t getline(char **, size_t *, FILE *);"
[ ${HAVE_GETSUBOPT} -eq 0 ] && \ [ ${HAVE_GETSUBOPT} -eq 0 ] && \
echo "extern int getsubopt(char **, char * const *, char **);" echo "extern int getsubopt(char **, char * const *, char **);"
[ ${HAVE_ISBLANK} -eq 0 ] && \
echo "extern int isblank(int);"
[ ${HAVE_MKDTEMP} -eq 0 ] && \
echo "extern char *mkdtemp(char *);"
if [ ${HAVE_PROGNAME} -eq 0 ]; then
echo "extern const char *getprogname(void);"
echo "extern void setprogname(const char *);"
fi
[ ${HAVE_REALLOCARRAY} -eq 0 ] && \ [ ${HAVE_REALLOCARRAY} -eq 0 ] && \
echo "extern void *reallocarray(void *, size_t, size_t);" echo "extern void *reallocarray(void *, size_t, size_t);"
@ -342,6 +382,9 @@ __HEREDOC__
[ ${HAVE_STRTONUM} -eq 0 ] && \ [ ${HAVE_STRTONUM} -eq 0 ] && \
echo "extern long long strtonum(const char *, long long, long long, const char **);" echo "extern long long strtonum(const char *, long long, long long, const char **);"
[ ${HAVE_VASPRINTF} -eq 0 ] && \
echo "extern int vasprintf(char **, const char *, va_list);"
echo echo
echo "#endif /* MANDOC_CONFIG_H */" echo "#endif /* MANDOC_CONFIG_H */"
@ -357,7 +400,6 @@ exec > Makefile.local
[ -z "${INCLUDEDIR}" ] && INCLUDEDIR="${PREFIX}/include/mandoc" [ -z "${INCLUDEDIR}" ] && INCLUDEDIR="${PREFIX}/include/mandoc"
[ -z "${LIBDIR}" ] && LIBDIR="${PREFIX}/lib/mandoc" [ -z "${LIBDIR}" ] && LIBDIR="${PREFIX}/lib/mandoc"
[ -z "${MANDIR}" ] && MANDIR="${PREFIX}/man" [ -z "${MANDIR}" ] && MANDIR="${PREFIX}/man"
[ -z "${EXAMPLEDIR}" ] && EXAMPLEDIR="${PREFIX}/share/examples/mandoc"
[ -z "${HTDOCDIR}" ] && HTDOCDIR="${WWWPREFIX}/htdocs" [ -z "${HTDOCDIR}" ] && HTDOCDIR="${WWWPREFIX}/htdocs"
[ -z "${CGIBINDIR}" ] && CGIBINDIR="${WWWPREFIX}/cgi-bin" [ -z "${CGIBINDIR}" ] && CGIBINDIR="${WWWPREFIX}/cgi-bin"
@ -382,6 +424,7 @@ INSTALL_TARGETS="base-install"
cat << __HEREDOC__ cat << __HEREDOC__
BUILD_TARGETS = ${BUILD_TARGETS} BUILD_TARGETS = ${BUILD_TARGETS}
INSTALL_TARGETS = ${INSTALL_TARGETS} INSTALL_TARGETS = ${INSTALL_TARGETS}
CC = ${CC}
CFLAGS = ${CFLAGS} CFLAGS = ${CFLAGS}
DBLIB = ${DBLIB} DBLIB = ${DBLIB}
STATIC = ${STATIC} STATIC = ${STATIC}
@ -391,15 +434,16 @@ SBINDIR = ${SBINDIR}
INCLUDEDIR = ${INCLUDEDIR} INCLUDEDIR = ${INCLUDEDIR}
LIBDIR = ${LIBDIR} LIBDIR = ${LIBDIR}
MANDIR = ${MANDIR} MANDIR = ${MANDIR}
EXAMPLEDIR = ${EXAMPLEDIR}
WWWPREFIX = ${WWWPREFIX} WWWPREFIX = ${WWWPREFIX}
HTDOCDIR = ${HTDOCDIR} HTDOCDIR = ${HTDOCDIR}
CGIBINDIR = ${CGIBINDIR} CGIBINDIR = ${CGIBINDIR}
BINM_APROPOS = ${BINM_APROPOS} BINM_APROPOS = ${BINM_APROPOS}
BINM_MAN = ${BINM_MAN}
BINM_WHATIS = ${BINM_WHATIS}
BINM_MAKEWHATIS = ${BINM_MAKEWHATIS} BINM_MAKEWHATIS = ${BINM_MAKEWHATIS}
BINM_MAN = ${BINM_MAN}
BINM_SOELIM = ${BINM_SOELIM}
BINM_WHATIS = ${BINM_WHATIS}
MANM_MAN = ${MANM_MAN} MANM_MAN = ${MANM_MAN}
MANM_MANCONF = ${MANM_MANCONF}
MANM_MDOC = ${MANM_MDOC} MANM_MDOC = ${MANM_MDOC}
MANM_ROFF = ${MANM_ROFF} MANM_ROFF = ${MANM_ROFF}
MANM_EQN = ${MANM_EQN} MANM_EQN = ${MANM_EQN}

View File

@ -1,4 +1,4 @@
# $Id: configure.local.example,v 1.6 2015/02/16 14:56:22 schwarze Exp $ # $Id: configure.local.example,v 1.10 2015/11/07 13:14:21 schwarze Exp $
# #
# Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> # Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
# #
@ -48,6 +48,13 @@ HAVE_WCHAR=1
HAVE_WCHAR=0 HAVE_WCHAR=0
# When man(1) or apropos(1) is called without -m and -M options,
# MANPATH is not set in the environment, man.conf(5) is not available
# and manpath(1) not used, manuals are searched for in the following
# directory trees by default.
MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
# In manual pages written in the mdoc(7) language, the operating system # In manual pages written in the mdoc(7) language, the operating system
# version is displayed in the page footer line. If an operating system # version is displayed in the page footer line. If an operating system
# is specified as an argument to the .Os macro, that is always used. # is specified as an argument to the .Os macro, that is always used.
@ -72,7 +79,6 @@ SBINDIR="${PREFIX}/sbin"
INCLUDEDIR="${PREFIX}/include/mandoc" INCLUDEDIR="${PREFIX}/include/mandoc"
LIBDIR="${PREFIX}/lib/mandoc" LIBDIR="${PREFIX}/lib/mandoc"
MANDIR="${PREFIX}/man" MANDIR="${PREFIX}/man"
EXAMPLEDIR="${PREFIX}/share/examples/mandoc"
# The man(1) utility needs to know where the manuals reside. # The man(1) utility needs to know where the manuals reside.
# We know of two ways to tell it: via manpath(1) or man.conf(5). # We know of two ways to tell it: via manpath(1) or man.conf(5).
@ -89,6 +95,11 @@ HAVE_MANPATH=1
# man(1), makewhatis(8), and apropos(1) will not work properly. # man(1), makewhatis(8), and apropos(1) will not work properly.
HAVE_MANPATH=0 HAVE_MANPATH=0
# Some distributions may want to avoid naming conflicts
# with the configuration files of other man(1) implementations.
# This changes the name of the installed section 5 manual page as well.
MANM_MANCONF="mandoc.conf" # default is "man.conf"
# Some distributions may want to avoid naming conflicts among manuals. # Some distributions may want to avoid naming conflicts among manuals.
# If you want to change the names of installed section 7 manual pages, # If you want to change the names of installed section 7 manual pages,
# the following alternative names are suggested. # the following alternative names are suggested.
@ -103,13 +114,14 @@ MANM_EQN="mandoc_eqn" # default is "eqn"
MANM_TBL="mandoc_tbl" # default is "tbl" MANM_TBL="mandoc_tbl" # default is "tbl"
# Some distributions may want to avoid naming conflicts # Some distributions may want to avoid naming conflicts
# with another man(1) utility. # with other man(1) and soelim(1) utilities.
# If you want to change the name of the binary program, # If you want to change the names of binary programs,
# the following alternative name is suggested. # the following alternative names are suggested.
# Using a different name is possible as well. # Using different names is possible as well.
# This changes the name of the installed section 1 manual page as well. # This changes the names of the installed section 1 manual pages as well.
BINM_MAN=mman # default is "man" BINM_MAN=mman # default is "man"
BINM_SOELIM=msoelim # default is "soelim"
# It is possible to change the utility program used for installation # It is possible to change the utility program used for installation
# and the modes files are installed with. The defaults are: # and the modes files are installed with. The defaults are:

View File

@ -1,4 +1,4 @@
/* $Id: demandoc.c,v 1.15 2015/02/10 08:05:30 schwarze Exp $ */ /* $Id: demandoc.c,v 1.26 2016/01/08 02:53:13 schwarze Exp $ */
/* /*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -26,14 +26,15 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "roff.h"
#include "man.h" #include "man.h"
#include "mdoc.h" #include "mdoc.h"
#include "mandoc.h" #include "mandoc.h"
static void pline(int, int *, int *, int); static void pline(int, int *, int *, int);
static void pman(const struct man_node *, int *, int *, int); static void pman(const struct roff_node *, int *, int *, int);
static void pmandoc(struct mparse *, int, const char *, int); static void pmandoc(struct mparse *, int, const char *, int);
static void pmdoc(const struct mdoc_node *, int *, int *, int); static void pmdoc(const struct roff_node *, int *, int *, int);
static void pstring(const char *, int, int *, int); static void pstring(const char *, int, int *, int);
static void usage(void); static void usage(void);
@ -43,7 +44,6 @@ int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct mparse *mp; struct mparse *mp;
struct mchars *mchars;
int ch, fd, i, list; int ch, fd, i, list;
extern int optind; extern int optind;
@ -72,14 +72,14 @@ main(int argc, char *argv[])
break; break;
default: default:
usage(); usage();
return((int)MANDOCLEVEL_BADARG); return (int)MANDOCLEVEL_BADARG;
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
mchars = mchars_alloc(); mchars_alloc();
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, mchars, NULL); mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, NULL);
assert(mp); assert(mp);
if (argc < 1) if (argc < 1)
@ -87,7 +87,7 @@ main(int argc, char *argv[])
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
mparse_reset(mp); mparse_reset(mp);
if (mparse_open(mp, &fd, argv[i]) != MANDOCLEVEL_OK) { if ((fd = mparse_open(mp, argv[i])) == -1) {
perror(argv[i]); perror(argv[i]);
continue; continue;
} }
@ -95,8 +95,8 @@ main(int argc, char *argv[])
} }
mparse_free(mp); mparse_free(mp);
mchars_free(mchars); mchars_free();
return((int)MANDOCLEVEL_OK); return (int)MANDOCLEVEL_OK;
} }
static void static void
@ -109,21 +109,24 @@ usage(void)
static void static void
pmandoc(struct mparse *mp, int fd, const char *fn, int list) pmandoc(struct mparse *mp, int fd, const char *fn, int list)
{ {
struct mdoc *mdoc; struct roff_man *man;
struct man *man;
int line, col; int line, col;
mparse_readfd(mp, fd, fn); mparse_readfd(mp, fd, fn);
mparse_result(mp, &mdoc, &man, NULL); close(fd);
mparse_result(mp, &man, NULL);
line = 1; line = 1;
col = 0; col = 0;
if (mdoc) if (man == NULL)
pmdoc(mdoc_node(mdoc), &line, &col, list);
else if (man)
pman(man_node(man), &line, &col, list);
else
return; return;
if (man->macroset == MACROSET_MDOC) {
mdoc_validate(man);
pmdoc(man->first->child, &line, &col, list);
} else {
man_validate(man);
pman(man->first->child, &line, &col, list);
}
if ( ! list) if ( ! list)
putchar('\n'); putchar('\n');
@ -233,13 +236,13 @@ pline(int line, int *linep, int *col, int list)
} }
static void static void
pmdoc(const struct mdoc_node *p, int *line, int *col, int list) pmdoc(const struct roff_node *p, int *line, int *col, int list)
{ {
for ( ; p; p = p->next) { for ( ; p; p = p->next) {
if (MDOC_LINE & p->flags) if (MDOC_LINE & p->flags)
pline(p->line, line, col, list); pline(p->line, line, col, list);
if (MDOC_TEXT == p->type) if (ROFFT_TEXT == p->type)
pstring(p->string, p->pos, col, list); pstring(p->string, p->pos, col, list);
if (p->child) if (p->child)
pmdoc(p->child, line, col, list); pmdoc(p->child, line, col, list);
@ -247,13 +250,13 @@ pmdoc(const struct mdoc_node *p, int *line, int *col, int list)
} }
static void static void
pman(const struct man_node *p, int *line, int *col, int list) pman(const struct roff_node *p, int *line, int *col, int list)
{ {
for ( ; p; p = p->next) { for ( ; p; p = p->next) {
if (MAN_LINE & p->flags) if (MAN_LINE & p->flags)
pline(p->line, line, col, list); pline(p->line, line, col, list);
if (MAN_TEXT == p->type) if (ROFFT_TEXT == p->type)
pstring(p->string, p->pos, col, list); pstring(p->string, p->pos, col, list);
if (p->child) if (p->child)
pman(p->child, line, col, list); pman(p->child, line, col, list);

View File

@ -1,4 +1,4 @@
.\" $Id: eqn.7,v 1.34 2015/03/09 20:17:23 schwarze Exp $ .\" $Id: eqn.7,v 1.35 2015/03/30 16:06:14 schwarze Exp $
.\" .\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: March 9 2015 $ .Dd $Mdocdate: March 30 2015 $
.Dt EQN 7 .Dt EQN 7
.Os .Os
.Sh NAME .Sh NAME
@ -146,7 +146,7 @@ is used as the delimiter for the value
.Ar val . .Ar val .
This allows for arbitrary enclosure of terms (not just quotes), such as This allows for arbitrary enclosure of terms (not just quotes), such as
.Pp .Pp
.D1 Cm define Ar foo 'bar baz' .D1 Cm define Ar foo \(aqbar baz\(aq
.D1 Cm define Ar foo cbar bazc .D1 Cm define Ar foo cbar bazc
.Pp .Pp
It is an error to have an empty It is an error to have an empty
@ -166,8 +166,8 @@ created.
Definitions can create arbitrary strings, for example, the following is Definitions can create arbitrary strings, for example, the following is
a legal construction. a legal construction.
.Bd -literal -offset indent .Bd -literal -offset indent
define foo 'define' define foo \(aqdefine\(aq
foo bar 'baz' foo bar \(aqbaz\(aq
.Ed .Ed
.Pp .Pp
Self-referencing definitions will raise an error. Self-referencing definitions will raise an error.

View File

@ -1,4 +1,4 @@
/* $Id: eqn.c,v 1.58 2015/03/04 12:19:49 schwarze Exp $ */ /* $Id: eqn.c,v 1.61 2016/01/08 00:50:45 schwarze Exp $ */
/* /*
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -302,10 +302,10 @@ eqn_read(struct eqn_node **epp, int ln,
while (' ' == *p || '\t' == *p) while (' ' == *p || '\t' == *p)
p++; p++;
if ('\0' == *p) if ('\0' == *p)
return(er); return er;
mandoc_vmsg(MANDOCERR_ARG_SKIP, ep->parse, mandoc_vmsg(MANDOCERR_ARG_SKIP, ep->parse,
ln, pos, "EN %s", p); ln, pos, "EN %s", p);
return(er); return er;
} }
/* /*
@ -324,7 +324,7 @@ eqn_read(struct eqn_node **epp, int ln,
ep->sz += sz; ep->sz += sz;
strlcat(ep->data, p + pos, ep->sz + 1); strlcat(ep->data, p + pos, ep->sz + 1);
strlcat(ep->data, " ", ep->sz + 1); strlcat(ep->data, " ", ep->sz + 1);
return(ROFF_IGN); return ROFF_IGN;
} }
struct eqn_node * struct eqn_node *
@ -339,7 +339,7 @@ eqn_alloc(int pos, int line, struct mparse *parse)
p->eqn.pos = pos; p->eqn.pos = pos;
p->gsize = EQN_DEFSIZE; p->gsize = EQN_DEFSIZE;
return(p); return p;
} }
/* /*
@ -353,9 +353,9 @@ eqn_def_find(struct eqn_node *ep, const char *key, size_t sz)
for (i = 0; i < (int)ep->defsz; i++) for (i = 0; i < (int)ep->defsz; i++)
if (ep->defs[i].keysz && STRNEQ(ep->defs[i].key, if (ep->defs[i].keysz && STRNEQ(ep->defs[i].key,
ep->defs[i].keysz, key, sz)) ep->defs[i].keysz, key, sz))
return(&ep->defs[i]); return &ep->defs[i];
return(NULL); return NULL;
} }
/* /*
@ -382,7 +382,7 @@ eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl)
if (lim >= EQN_NEST_MAX) { if (lim >= EQN_NEST_MAX) {
mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse, mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse,
ep->eqn.ln, ep->eqn.pos, NULL); ep->eqn.ln, ep->eqn.pos, NULL);
return(NULL); return NULL;
} }
ep->cur = ep->rew; ep->cur = ep->rew;
@ -390,7 +390,7 @@ eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl)
q = 0; q = 0;
if ('\0' == *start) if ('\0' == *start)
return(NULL); return NULL;
if (quote == *start) { if (quote == *start) {
ep->cur++; ep->cur++;
@ -432,7 +432,7 @@ eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl)
/* Quotes aren't expanded for values. */ /* Quotes aren't expanded for values. */
if (q || ! repl) if (q || ! repl)
return(start); return start;
if (NULL != (def = eqn_def_find(ep, start, *sz))) { if (NULL != (def = eqn_def_find(ep, start, *sz))) {
diff = def->valsz - *sz; diff = def->valsz - *sz;
@ -448,10 +448,11 @@ eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl)
memmove(start + *sz + diff, start + *sz, memmove(start + *sz + diff, start + *sz,
(strlen(start) - *sz) + 1); (strlen(start) - *sz) + 1);
memcpy(start, def->val, def->valsz); memcpy(start, def->val, def->valsz);
lim++;
goto again; goto again;
} }
return(start); return start;
} }
/* /*
@ -462,7 +463,7 @@ static const char *
eqn_nexttok(struct eqn_node *ep, size_t *sz) eqn_nexttok(struct eqn_node *ep, size_t *sz)
{ {
return(eqn_next(ep, '"', sz, 1)); return eqn_next(ep, '"', sz, 1);
} }
/* /*
@ -472,7 +473,7 @@ static const char *
eqn_nextrawtok(struct eqn_node *ep, size_t *sz) eqn_nextrawtok(struct eqn_node *ep, size_t *sz)
{ {
return(eqn_next(ep, '"', sz, 0)); return eqn_next(ep, '"', sz, 0);
} }
/* /*
@ -498,12 +499,12 @@ eqn_tok_parse(struct eqn_node *ep, char **p)
quoted = ep->data[ep->cur] == '"'; quoted = ep->data[ep->cur] == '"';
if (NULL == (start = eqn_nexttok(ep, &sz))) if (NULL == (start = eqn_nexttok(ep, &sz)))
return(EQN_TOK_EOF); return EQN_TOK_EOF;
if (quoted) { if (quoted) {
if (p != NULL) if (p != NULL)
*p = mandoc_strndup(start, sz); *p = mandoc_strndup(start, sz);
return(EQN_TOK__MAX); return EQN_TOK__MAX;
} }
for (i = 0; i < EQN_TOK__MAX; i++) { for (i = 0; i < EQN_TOK__MAX; i++) {
@ -516,7 +517,7 @@ eqn_tok_parse(struct eqn_node *ep, char **p)
if (i == EQN_TOK__MAX && NULL != p) if (i == EQN_TOK__MAX && NULL != p)
*p = mandoc_strndup(start, sz); *p = mandoc_strndup(start, sz);
return(i); return i;
} }
static void static void
@ -557,7 +558,7 @@ eqn_box_alloc(struct eqn_node *ep, struct eqn_box *parent)
parent->first = bp; parent->first = bp;
parent->last = bp; parent->last = bp;
return(bp); return bp;
} }
/* /*
@ -587,7 +588,7 @@ eqn_box_makebinary(struct eqn_node *ep,
newb->first = newb->last = b; newb->first = newb->last = b;
newb->first->next = NULL; newb->first->next = NULL;
b->parent = newb; b->parent = newb;
return(newb); return newb;
} }
/* /*
@ -712,7 +713,7 @@ eqn_parse(struct eqn_node *ep, struct eqn_box *parent)
*/ */
if (ep->data == NULL) if (ep->data == NULL)
return(ROFF_IGN); return ROFF_IGN;
next_tok: next_tok:
tok = eqn_tok_parse(ep, &p); tok = eqn_tok_parse(ep, &p);
@ -986,7 +987,7 @@ eqn_parse(struct eqn_node *ep, struct eqn_box *parent)
parent->right = mandoc_strndup(start, sz); parent->right = mandoc_strndup(start, sz);
} }
parent = parent->parent; parent = parent->parent;
if (EQN_TOK_BRACE_CLOSE == tok && parent && if (tok == EQN_TOK_BRACE_CLOSE &&
(parent->type == EQN_PILE || (parent->type == EQN_PILE ||
parent->type == EQN_MATRIX)) parent->type == EQN_MATRIX))
parent = parent->parent; parent = parent->parent;
@ -1060,7 +1061,7 @@ eqn_parse(struct eqn_node *ep, struct eqn_box *parent)
* End of file! * End of file!
* TODO: make sure we're not in an open subexpression. * TODO: make sure we're not in an open subexpression.
*/ */
return(ROFF_EQN); return ROFF_EQN;
default: default:
assert(tok == EQN_TOK__MAX); assert(tok == EQN_TOK__MAX);
assert(NULL != p); assert(NULL != p);
@ -1104,7 +1105,7 @@ eqn_end(struct eqn_node **epp)
ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box)); ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box));
ep->eqn.root->expectargs = UINT_MAX; ep->eqn.root->expectargs = UINT_MAX;
return(eqn_parse(ep, ep->eqn.root)); return eqn_parse(ep, ep->eqn.root);
} }
void void

View File

@ -1,114 +0,0 @@
/* $Id: example.style.css,v 1.55 2015/02/10 08:05:30 schwarze Exp $ */
/*
* This is an example style-sheet provided for mandoc(1) and the -Thtml
* or -Txhtml output mode.
* It mimics the appearance of the legacy man.cgi output.
* See mdoc(7) and man(7) for macro explanations.
*/
div.mandoc { min-width: 102ex;
width: 102ex;
font-family: monospace; } /* This is the outer node of all mandoc -T[x]html documents. */
div.mandoc h1 { margin-bottom: 0ex; font-size: inherit; margin-left: -4ex; } /* Section header (Sh, SH). */
div.mandoc h2 { margin-bottom: 0ex; font-size: inherit; margin-left: -2ex; } /* Sub-section header (Ss, SS). */
div.mandoc table { width: 100%; margin-top: 0ex; margin-bottom: 0ex; } /* All tables. */
div.mandoc td { vertical-align: top; } /* All table cells. */
div.mandoc p { } /* Paragraph: Pp, Lp. */
div.mandoc blockquote { margin-left: 5ex; margin-top: 0ex; margin-bottom: 0ex; } /* D1, Dl. */
div.mandoc div.section { margin-bottom: 2ex; margin-left: 5ex; } /* Sections (Sh, SH). */
div.mandoc div.subsection { } /* Sub-sections (Ss, SS). */
div.mandoc table.synopsis { } /* SYNOPSIS section table. */
div.mandoc table.foot { } /* Document footer. */
div.mandoc td.foot-date { width: 50%; } /* Document footer: date. */
div.mandoc td.foot-os { width: 50%;
text-align: right; } /* Document footer: OS/source. */
div.mandoc table.head { } /* Document header. */
div.mandoc td.head-ltitle { width: 10%; } /* Document header: left-title. */
div.mandoc td.head-vol { width: 80%;
text-align: center; } /* Document header: volume. */
div.mandoc td.head-rtitle { width: 10%;
text-align: right; } /* Document header: right-title. */
div.mandoc .display { } /* All Bd, D1, Dl. */
div.mandoc .list { } /* All Bl. */
div.mandoc i { } /* Italic: BI, IB, I, (implicit). */
div.mandoc b { } /* Bold: SB, BI, IB, BR, RB, B, (implicit). */
div.mandoc small { } /* Small: SB, SM. */
div.mandoc .emph { font-style: italic; font-weight: normal; } /* Emphasis: Em, Bl -emphasis. */
div.mandoc .symb { font-style: normal; font-weight: bold; } /* Symbolic: Sy, Ms, Bf -symbolic. */
div.mandoc .lit { font-style: normal; font-weight: normal; font-family: monospace; } /* Literal: Dl, Li, Ql, Bf -literal, Bl -literal, Bl -unfilled. */
div.mandoc i.addr { font-weight: normal; } /* Address (Ad). */
div.mandoc i.arg { font-weight: normal; } /* Command argument (Ar). */
div.mandoc span.author { } /* Author name (An). */
div.mandoc b.cmd { font-style: normal; } /* Command (Cm). */
div.mandoc b.config { font-style: normal; } /* Config statement (Cd). */
div.mandoc span.define { } /* Defines (Dv). */
div.mandoc span.desc { } /* Nd. After em-dash. */
div.mandoc b.diag { font-style: normal; } /* Diagnostic (Bl -diag). */
div.mandoc span.env { } /* Environment variables (Ev). */
div.mandoc span.errno { } /* Error string (Er). */
div.mandoc i.farg { font-weight: normal; } /* Function argument (Fa, Fn). */
div.mandoc i.file { font-weight: normal; } /* File (Pa). */
div.mandoc b.flag { font-style: normal; } /* Flag (Fl, Cm). */
div.mandoc b.fname { font-style: normal; } /* Function name (Fa, Fn, Rv). */
div.mandoc i.ftype { font-weight: normal; } /* Function types (Ft, Fn). */
div.mandoc b.includes { font-style: normal; } /* Header includes (In). */
div.mandoc span.lib { } /* Library (Lb). */
div.mandoc i.link-sec { font-weight: normal; } /* Section links (Sx). */
div.mandoc b.macro { font-style: normal; } /* Macro-ish thing (Fd). */
div.mandoc b.name { font-style: normal; } /* Name of utility (Nm). */
div.mandoc span.opt { } /* Options (Op, Oo/Oc). */
div.mandoc span.ref { } /* Citations (Rs). */
div.mandoc span.ref-auth { } /* Reference author (%A). */
div.mandoc i.ref-book { font-weight: normal; } /* Reference book (%B). */
div.mandoc span.ref-city { } /* Reference city (%C). */
div.mandoc span.ref-date { } /* Reference date (%D). */
div.mandoc i.ref-issue { font-weight: normal; } /* Reference issuer/publisher (%I). */
div.mandoc i.ref-jrnl { font-weight: normal; } /* Reference journal (%J). */
div.mandoc span.ref-num { } /* Reference number (%N). */
div.mandoc span.ref-opt { } /* Reference optionals (%O). */
div.mandoc span.ref-page { } /* Reference page (%P). */
div.mandoc span.ref-corp { } /* Reference corporate/foreign author (%Q). */
div.mandoc span.ref-rep { } /* Reference report (%R). */
div.mandoc span.ref-title { text-decoration: underline; } /* Reference title (%T). */
div.mandoc span.ref-vol { } /* Reference volume (%V). */
div.mandoc span.type { font-style: italic; font-weight: normal; } /* Variable types (Vt). */
div.mandoc span.unix { } /* Unices (Ux, Ox, Nx, Fx, Bx, Bsx, Dx). */
div.mandoc b.utility { font-style: normal; } /* Name of utility (Ex). */
div.mandoc b.var { font-style: normal; } /* Variables (Rv). */
div.mandoc a.link-ext { } /* Off-site link (Lk). */
div.mandoc a.link-includes { } /* Include-file link (In). */
div.mandoc a.link-mail { } /* Mailto links (Mt). */
div.mandoc a.link-man { } /* Manual links (Xr). */
div.mandoc a.link-ref { } /* Reference section links (%Q). */
div.mandoc a.link-sec { } /* Section links (Sx). */
div.mandoc dl.list-diag { } /* Formatting for lists. See mdoc(7). */
div.mandoc dt.list-diag { }
div.mandoc dd.list-diag { }
div.mandoc dl.list-hang { }
div.mandoc dt.list-hang { }
div.mandoc dd.list-hang { }
div.mandoc dl.list-inset { }
div.mandoc dt.list-inset { }
div.mandoc dd.list-inset { }
div.mandoc dl.list-ohang { }
div.mandoc dt.list-ohang { }
div.mandoc dd.list-ohang { margin-left: 0ex; }
div.mandoc dl.list-tag { }
div.mandoc dt.list-tag { }
div.mandoc dd.list-tag { }
div.mandoc table.list-col { }
div.mandoc tr.list-col { }
div.mandoc td.list-col { }
div.mandoc ul.list-bul { list-style-type: disc; padding-left: 1em; }
div.mandoc li.list-bul { }
div.mandoc ul.list-dash { list-style-type: none; padding-left: 0em; }
div.mandoc li.list-dash:before { content: "\2014 "; }
div.mandoc ul.list-hyph { list-style-type: none; padding-left: 0em; }
div.mandoc li.list-hyph:before { content: "\2013 "; }
div.mandoc ul.list-item { list-style-type: none; padding-left: 0em; }
div.mandoc li.list-item { }
div.mandoc ol.list-enum { padding-left: 2em; }
div.mandoc li.list-enum { }
div.mandoc span.eqn { } /* Equation modes. See eqn(7). */
div.mandoc table.tbl { } /* Table modes. See tbl(7). */
div.mandoc div.spacer { margin: 1em 0; }

View File

@ -40,7 +40,8 @@ while [ -n "$1" ]; do
shift shift
echo " ========== $file ========== " echo " ========== $file ========== "
tbl $file | $EQN | $ROFF -mandoc 2> /tmp/roff.err > /tmp/roff.out tbl $file | $EQN | $ROFF -mandoc 2> /tmp/roff.err > /tmp/roff.out
mandoc -Ios='OpenBSD ports' $MOPT $file 2> /tmp/mandoc.err > /tmp/mandoc.out ${MANDOC:=mandoc} -Ios='OpenBSD ports' $MOPT $file \
2> /tmp/mandoc.err > /tmp/mandoc.out
for i in roff mandoc; do for i in roff mandoc; do
[[ -s /tmp/$i.err ]] && echo "$i errors:" && cat /tmp/$i.err [[ -s /tmp/$i.err ]] && echo "$i errors:" && cat /tmp/$i.err
done done

View File

@ -1,4 +1,4 @@
/* $Id: html.c,v 1.185 2015/01/21 20:33:25 schwarze Exp $ */ /* $Id: html.c,v 1.192 2016/01/04 12:45:29 schwarze Exp $ */
/* /*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
@ -7,9 +7,9 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -32,6 +32,7 @@
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "out.h" #include "out.h"
#include "html.h" #include "html.h"
#include "manconf.h"
#include "main.h" #include "main.h"
struct htmldata { struct htmldata {
@ -129,42 +130,20 @@ static void print_attr(struct html *, const char *, const char *);
void * void *
html_alloc(const struct mchars *mchars, char *outopts) html_alloc(const struct manoutput *outopts)
{ {
struct html *h; struct html *h;
const char *toks[5];
char *v;
toks[0] = "style";
toks[1] = "man";
toks[2] = "includes";
toks[3] = "fragment";
toks[4] = NULL;
h = mandoc_calloc(1, sizeof(struct html)); h = mandoc_calloc(1, sizeof(struct html));
h->tags.head = NULL; h->tags.head = NULL;
h->symtab = mchars; h->style = outopts->style;
h->base_man = outopts->man;
h->base_includes = outopts->includes;
if (outopts->fragment)
h->oflags |= HTML_FRAGMENT;
while (outopts && *outopts) return h;
switch (getsubopt(&outopts, UNCONST(toks), &v)) {
case 0:
h->style = v;
break;
case 1:
h->base_man = v;
break;
case 2:
h->base_includes = v;
break;
case 3:
h->oflags |= HTML_FRAGMENT;
break;
default:
break;
}
return(h);
} }
void void
@ -237,13 +216,11 @@ print_metaf(struct html *h, enum mandoc_esc deco)
font = HTMLFONT_BI; font = HTMLFONT_BI;
break; break;
case ESCAPE_FONT: case ESCAPE_FONT:
/* FALLTHROUGH */
case ESCAPE_FONTROMAN: case ESCAPE_FONTROMAN:
font = HTMLFONT_NONE; font = HTMLFONT_NONE;
break; break;
default: default:
abort(); abort();
/* NOTREACHED */
} }
if (h->metaf) { if (h->metaf) {
@ -301,13 +278,10 @@ html_strlen(const char *cp)
cp++; cp++;
switch (mandoc_escape(&cp, NULL, NULL)) { switch (mandoc_escape(&cp, NULL, NULL)) {
case ESCAPE_ERROR: case ESCAPE_ERROR:
return(sz); return sz;
case ESCAPE_UNICODE: case ESCAPE_UNICODE:
/* FALLTHROUGH */
case ESCAPE_NUMBERED: case ESCAPE_NUMBERED:
/* FALLTHROUGH */
case ESCAPE_SPECIAL: case ESCAPE_SPECIAL:
/* FALLTHROUGH */
case ESCAPE_OVERSTRIKE: case ESCAPE_OVERSTRIKE:
if (skip) if (skip)
skip = 0; skip = 0;
@ -321,7 +295,7 @@ html_strlen(const char *cp)
break; break;
} }
} }
return(sz); return sz;
} }
static int static int
@ -342,17 +316,17 @@ print_escape(char c)
printf("&quot;"); printf("&quot;");
break; break;
case ASCII_NBRSP: case ASCII_NBRSP:
putchar('-'); printf("&nbsp;");
break; break;
case ASCII_HYPH: case ASCII_HYPH:
putchar('-'); putchar('-');
/* FALLTHROUGH */ break;
case ASCII_BREAK: case ASCII_BREAK:
break; break;
default: default:
return(0); return 0;
} }
return(1); return 1;
} }
static int static int
@ -391,15 +365,10 @@ print_encode(struct html *h, const char *p, int norecurse)
switch (esc) { switch (esc) {
case ESCAPE_FONT: case ESCAPE_FONT:
/* FALLTHROUGH */
case ESCAPE_FONTPREV: case ESCAPE_FONTPREV:
/* FALLTHROUGH */
case ESCAPE_FONTBOLD: case ESCAPE_FONTBOLD:
/* FALLTHROUGH */
case ESCAPE_FONTITALIC: case ESCAPE_FONTITALIC:
/* FALLTHROUGH */
case ESCAPE_FONTBI: case ESCAPE_FONTBI:
/* FALLTHROUGH */
case ESCAPE_FONTROMAN: case ESCAPE_FONTROMAN:
if (0 == norecurse) if (0 == norecurse)
print_metaf(h, esc); print_metaf(h, esc);
@ -427,7 +396,7 @@ print_encode(struct html *h, const char *p, int norecurse)
continue; continue;
break; break;
case ESCAPE_SPECIAL: case ESCAPE_SPECIAL:
c = mchars_spec2cp(h->symtab, seq, len); c = mchars_spec2cp(seq, len);
if (c <= 0) if (c <= 0)
continue; continue;
break; break;
@ -452,7 +421,7 @@ print_encode(struct html *h, const char *p, int norecurse)
putchar(c); putchar(c);
} }
return(nospace); return nospace;
} }
static void static void
@ -514,7 +483,7 @@ print_otag(struct html *h, enum htmltag tag,
if ((HTML_AUTOCLOSE | HTML_CLRLINE) & htmltags[tag].flags) if ((HTML_AUTOCLOSE | HTML_CLRLINE) & htmltags[tag].flags)
putchar('\n'); putchar('\n');
return(t); return t;
} }
static void static void
@ -751,8 +720,8 @@ void
bufcat_id(struct html *h, const char *src) bufcat_id(struct html *h, const char *src)
{ {
/* Cf. <http://www.w3.org/TR/html4/types.html#h-6.2>. */ /* Cf. <http://www.w3.org/TR/html5/dom.html#the-id-attribute>. */
while ('\0' != *src) for (; '\0' != *src; src++)
bufcat_fmt(h, "%.2x", *src++); bufncat(h, *src == ' ' ? "_" : src, 1);
} }

View File

@ -1,4 +1,4 @@
/* $Id: html.h,v 1.70 2014/12/02 10:08:06 schwarze Exp $ */ /* $Id: html.h,v 1.72 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -130,7 +130,6 @@ struct html {
struct tagq tags; /* stack of open tags */ struct tagq tags; /* stack of open tags */
struct rofftbl tbl; /* current table */ struct rofftbl tbl; /* current table */
struct tag *tblt; /* current open table scope */ struct tag *tblt; /* current open table scope */
const struct mchars *symtab; /* character table */
char *base_man; /* base for manpage href */ char *base_man; /* base for manpage href */
char *base_includes; /* base for include href */ char *base_includes; /* base for include href */
char *style; /* style-sheet URI */ char *style; /* style-sheet URI */
@ -143,7 +142,6 @@ struct html {
#define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */ #define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */
}; };
__BEGIN_DECLS
struct tbl_span; struct tbl_span;
struct eqn; struct eqn;
@ -176,5 +174,3 @@ void buffmt_man(struct html *,
void buffmt_includes(struct html *, const char *); void buffmt_includes(struct html *, const char *);
int html_strlen(const char *); int html_strlen(const char *);
__END_DECLS

View File

@ -1,4 +1,4 @@
/* $Id: lib.c,v 1.11 2014/08/10 23:54:41 schwarze Exp $ */ /* $Id: lib.c,v 1.13 2015/10/06 18:32:19 schwarze Exp $ */
/* /*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -20,6 +20,7 @@
#include <string.h> #include <string.h>
#include "roff.h"
#include "mdoc.h" #include "mdoc.h"
#include "libmdoc.h" #include "libmdoc.h"
@ -32,5 +33,5 @@ mdoc_a2lib(const char *p)
#include "lib.in" #include "lib.in"
return(NULL); return NULL;
} }

View File

@ -1,44 +1,23 @@
/* $Id: libman.h,v 1.67 2014/12/28 14:42:27 schwarze Exp $ */ /* $Id: libman.h,v 1.79 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
enum man_next { #define MACRO_PROT_ARGS struct roff_man *man, \
MAN_NEXT_SIBLING = 0, int tok, \
MAN_NEXT_CHILD
};
struct man {
struct mparse *parse; /* parse pointer */
const char *defos; /* default OS argument for .TH */
int quick; /* abort parse early */
int flags; /* parse flags */
#define MAN_ELINE (1 << 1) /* Next-line element scope. */
#define MAN_BLINE (1 << 2) /* Next-line block scope. */
#define MAN_LITERAL (1 << 4) /* Literal input. */
#define MAN_NEWLINE (1 << 6) /* first macro/text in a line */
enum man_next next; /* where to put the next node */
struct man_node *last; /* the last parsed node */
struct man_node *first; /* the first parsed node */
struct man_meta meta; /* document meta-data */
struct roff *roff;
};
#define MACRO_PROT_ARGS struct man *man, \
enum mant tok, \
int line, \ int line, \
int ppos, \ int ppos, \
int *pos, \ int *pos, \
@ -47,30 +26,16 @@ struct man {
struct man_macro { struct man_macro {
void (*fp)(MACRO_PROT_ARGS); void (*fp)(MACRO_PROT_ARGS);
int flags; int flags;
#define MAN_SCOPED (1 << 0) #define MAN_SCOPED (1 << 0) /* Optional next-line scope. */
#define MAN_EXPLICIT (1 << 1) /* See blk_imp(). */ #define MAN_NSCOPED (1 << 1) /* Allowed in next-line element scope. */
#define MAN_FSCOPED (1 << 2) /* See blk_imp(). */ #define MAN_BSCOPE (1 << 2) /* Break next-line block scope. */
#define MAN_NSCOPED (1 << 3) /* See in_line_eoln(). */ #define MAN_JOIN (1 << 3) /* Join arguments together. */
#define MAN_NOCLOSE (1 << 4) /* See blk_exp(). */
#define MAN_BSCOPE (1 << 5) /* Break BLINE scope. */
#define MAN_JOIN (1 << 6) /* Join arguments together. */
}; };
extern const struct man_macro *const man_macros; extern const struct man_macro *const man_macros;
__BEGIN_DECLS
void man_word_alloc(struct man *, int, int, const char *); int man_hash_find(const char *);
void man_word_append(struct man *, const char *); void man_node_validate(struct roff_man *);
void man_block_alloc(struct man *, int, int, enum mant); void man_state(struct roff_man *, struct roff_node *);
void man_head_alloc(struct man *, int, int, enum mant); void man_unscope(struct roff_man *, const struct roff_node *);
void man_body_alloc(struct man *, int, int, enum mant);
void man_elem_alloc(struct man *, int, int, enum mant);
void man_node_delete(struct man *, struct man_node *);
void man_hash_init(void);
enum mant man_hash_find(const char *);
void man_macroend(struct man *);
void man_valid_post(struct man *);
void man_unscope(struct man *, const struct man_node *);
__END_DECLS

View File

@ -1,15 +1,15 @@
/* $Id: libmandoc.h,v 1.55 2015/01/15 04:26:39 schwarze Exp $ */ /* $Id: libmandoc.h,v 1.62 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -32,15 +32,13 @@ struct buf {
size_t sz; size_t sz;
}; };
__BEGIN_DECLS
struct mparse; struct mparse;
struct mchars;
struct tbl_span; struct tbl_span;
struct eqn; struct eqn;
struct roff; struct roff;
struct mdoc; struct roff_man;
struct man; struct roff_node;
void mandoc_msg(enum mandocerr, struct mparse *, void mandoc_msg(enum mandocerr, struct mparse *,
int, int, const char *); int, int, const char *);
@ -55,31 +53,25 @@ int mandoc_eos(const char *, size_t);
int mandoc_strntoi(const char *, size_t, int); int mandoc_strntoi(const char *, size_t, int);
const char *mandoc_a2msec(const char*); const char *mandoc_a2msec(const char*);
void mdoc_free(struct mdoc *); void mdoc_hash_init(void);
struct mdoc *mdoc_alloc(struct roff *, struct mparse *, int mdoc_parseln(struct roff_man *, int, char *, int);
const char *, int); void mdoc_endparse(struct roff_man *);
void mdoc_reset(struct mdoc *);
int mdoc_parseln(struct mdoc *, int, char *, int);
void mdoc_endparse(struct mdoc *);
void mdoc_addspan(struct mdoc *, const struct tbl_span *);
void mdoc_addeqn(struct mdoc *, const struct eqn *);
void man_free(struct man *); void man_hash_init(void);
struct man *man_alloc(struct roff *, struct mparse *, int man_parseln(struct roff_man *, int, char *, int);
const char *, int); void man_endparse(struct roff_man *);
void man_reset(struct man *);
int man_parseln(struct man *, int, char *, int);
void man_endparse(struct man *);
void man_addspan(struct man *, const struct tbl_span *);
void man_addeqn(struct man *, const struct eqn *);
int preconv_cue(const struct buf *, size_t); int preconv_cue(const struct buf *, size_t);
int preconv_encode(struct buf *, size_t *, int preconv_encode(struct buf *, size_t *,
struct buf *, size_t *, int *); struct buf *, size_t *, int *);
void roff_free(struct roff *); void roff_free(struct roff *);
struct roff *roff_alloc(struct mparse *, const struct mchars *, int); struct roff *roff_alloc(struct mparse *, int);
void roff_reset(struct roff *); void roff_reset(struct roff *);
void roff_man_free(struct roff_man *);
struct roff_man *roff_man_alloc(struct roff *, struct mparse *,
const char *, int);
void roff_man_reset(struct roff_man *);
enum rofferr roff_parseln(struct roff *, int, struct buf *, int *); enum rofferr roff_parseln(struct roff *, int, struct buf *, int *);
void roff_endparse(struct roff *); void roff_endparse(struct roff *);
void roff_setreg(struct roff *, const char *, int, char sign); void roff_setreg(struct roff *, const char *, int, char sign);
@ -91,5 +83,3 @@ int roff_getformat(const struct roff *);
const struct tbl_span *roff_span(const struct roff *); const struct tbl_span *roff_span(const struct roff *);
const struct eqn *roff_eqn(const struct roff *); const struct eqn *roff_eqn(const struct roff *);
__END_DECLS

View File

@ -1,53 +1,23 @@
/* $Id: libmdoc.h,v 1.97 2015/02/02 04:26:44 schwarze Exp $ */ /* $Id: libmdoc.h,v 1.108 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
enum mdoc_next { #define MACRO_PROT_ARGS struct roff_man *mdoc, \
MDOC_NEXT_SIBLING = 0, int tok, \
MDOC_NEXT_CHILD
};
struct mdoc {
struct mparse *parse; /* parse pointer */
const char *defos; /* default argument for .Os */
int quick; /* abort parse early */
int flags; /* parse flags */
#define MDOC_LITERAL (1 << 1) /* in a literal scope */
#define MDOC_PBODY (1 << 2) /* in the document body */
#define MDOC_NEWLINE (1 << 3) /* first macro/text in a line */
#define MDOC_PHRASELIT (1 << 4) /* literal within a partila phrase */
#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 */
#define MDOC_NODELIMC (1 << 10) /* disable closing delimiter handling */
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 */
struct mdoc_node *last_es; /* the most recent Es node */
struct mdoc_meta meta; /* document meta-data */
enum mdoc_sec lastnamed;
enum mdoc_sec lastsec;
struct roff *roff;
};
#define MACRO_PROT_ARGS struct mdoc *mdoc, \
enum mdoct tok, \
int line, \ int line, \
int ppos, \ int ppos, \
int *pos, \ int *pos, \
@ -70,9 +40,7 @@ enum margserr {
ARGS_WORD, /* normal word */ ARGS_WORD, /* normal word */
ARGS_PUNCT, /* series of punctuation */ ARGS_PUNCT, /* series of punctuation */
ARGS_QWORD, /* quoted word */ ARGS_QWORD, /* quoted word */
ARGS_PHRASE, /* Ta'd phrase (-column) */ ARGS_PHRASE /* Bl -column phrase */
ARGS_PPHRASE, /* tabbed phrase (-column) */
ARGS_PEND /* last phrase (-column) */
}; };
/* /*
@ -94,36 +62,27 @@ enum mdelim {
extern const struct mdoc_macro *const mdoc_macros; extern const struct mdoc_macro *const mdoc_macros;
__BEGIN_DECLS
void mdoc_macro(MACRO_PROT_ARGS); void mdoc_macro(MACRO_PROT_ARGS);
void mdoc_word_alloc(struct mdoc *, int, int, const char *); void mdoc_elem_alloc(struct roff_man *, int, int,
void mdoc_word_append(struct mdoc *, const char *); int, struct mdoc_arg *);
void mdoc_elem_alloc(struct mdoc *, int, int, struct roff_node *mdoc_block_alloc(struct roff_man *, int, int,
enum mdoct, struct mdoc_arg *); int, struct mdoc_arg *);
struct mdoc_node *mdoc_block_alloc(struct mdoc *, int, int, void mdoc_tail_alloc(struct roff_man *, int, int, int);
enum mdoct, struct mdoc_arg *); struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int, int,
struct mdoc_node *mdoc_head_alloc(struct mdoc *, int, int, enum mdoct); struct roff_node *, enum mdoc_endbody);
void mdoc_tail_alloc(struct mdoc *, int, int, enum mdoct); void mdoc_node_relink(struct roff_man *, struct roff_node *);
struct mdoc_node *mdoc_body_alloc(struct mdoc *, int, int, enum mdoct); void mdoc_node_validate(struct roff_man *);
struct mdoc_node *mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct, void mdoc_state(struct roff_man *, struct roff_node *);
struct mdoc_node *, enum mdoc_endbody); void mdoc_state_reset(struct roff_man *);
void mdoc_node_delete(struct mdoc *, struct mdoc_node *); int mdoc_hash_find(const char *);
void mdoc_node_relink(struct mdoc *, struct mdoc_node *); const char *mdoc_a2arch(const char *);
void mdoc_hash_init(void);
enum mdoct mdoc_hash_find(const char *);
const char *mdoc_a2att(const char *); const char *mdoc_a2att(const char *);
const char *mdoc_a2lib(const char *); const char *mdoc_a2lib(const char *);
enum roff_sec mdoc_a2sec(const char *);
const char *mdoc_a2st(const char *); const char *mdoc_a2st(const char *);
const char *mdoc_a2arch(const char *); void mdoc_argv(struct roff_man *, int, int,
void mdoc_valid_pre(struct mdoc *, struct mdoc_node *);
void mdoc_valid_post(struct mdoc *);
void mdoc_argv(struct mdoc *, int, enum mdoct,
struct mdoc_arg **, int *, char *); struct mdoc_arg **, int *, char *);
void mdoc_argv_free(struct mdoc_arg *); enum margserr mdoc_args(struct roff_man *, int,
enum margserr mdoc_args(struct mdoc *, int, int *, char *, int, char **);
int *, char *, enum mdoct, char **);
void mdoc_macroend(struct mdoc *);
enum mdelim mdoc_isdelim(const char *); enum mdelim mdoc_isdelim(const char *);
__END_DECLS

View File

@ -1,4 +1,4 @@
/* $Id: libroff.h,v 1.38 2015/01/30 04:11:50 schwarze Exp $ */ /* $Id: libroff.h,v 1.39 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -60,7 +60,6 @@ struct eqn_def {
size_t valsz; size_t valsz;
}; };
__BEGIN_DECLS
struct tbl_node *tbl_alloc(int, int, struct mparse *); struct tbl_node *tbl_alloc(int, int, struct mparse *);
void tbl_restart(int, int, struct tbl_node *); void tbl_restart(int, int, struct tbl_node *);
@ -78,5 +77,3 @@ enum rofferr eqn_end(struct eqn_node **);
void eqn_free(struct eqn_node *); void eqn_free(struct eqn_node *);
enum rofferr eqn_read(struct eqn_node **, int, enum rofferr eqn_read(struct eqn_node **, int,
const char *, int, int *); const char *, int, int *);
__END_DECLS

View File

@ -1,16 +1,16 @@
/* $Id: main.c,v 1.225 2015/03/10 13:50:03 schwarze Exp $ */ /* $Id: main.c,v 1.262 2016/01/08 02:53:13 schwarze Exp $ */
/* /*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010-2012, 2014-2016 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org> * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -24,21 +24,27 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <glob.h> #include <glob.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "main.h" #include "mandoc.h"
#include "roff.h"
#include "mdoc.h" #include "mdoc.h"
#include "man.h" #include "man.h"
#include "manpath.h" #include "tag.h"
#include "main.h"
#include "manconf.h"
#include "mansearch.h" #include "mansearch.h"
#if !defined(__GNUC__) || (__GNUC__ < 2) #if !defined(__GNUC__) || (__GNUC__ < 2)
@ -56,10 +62,6 @@ enum outmode {
OUTMODE_ONE OUTMODE_ONE
}; };
typedef void (*out_mdoc)(void *, const struct mdoc *);
typedef void (*out_man)(void *, const struct man *);
typedef void (*out_free)(void *);
enum outt { enum outt {
OUTT_ASCII = 0, /* -Tascii */ OUTT_ASCII = 0, /* -Tascii */
OUTT_LOCALE, /* -Tlocale */ OUTT_LOCALE, /* -Tlocale */
@ -74,15 +76,11 @@ enum outt {
struct curparse { struct curparse {
struct mparse *mp; struct mparse *mp;
struct mchars *mchars; /* character table */
enum mandoclevel wlevel; /* ignore messages below this */ enum mandoclevel wlevel; /* ignore messages below this */
int wstop; /* stop after a file with a warning */ int wstop; /* stop after a file with a warning */
enum outt outtype; /* which output to use */ enum outt outtype; /* which output to use */
out_mdoc outmdoc; /* mdoc output ptr */
out_man outman; /* man output ptr */
out_free outfree; /* free output ptr */
void *outdata; /* data for output */ void *outdata; /* data for output */
char outopts[BUFSIZ]; /* buf of output opts */ struct manoutput *outopts; /* output options */
}; };
static int fs_lookup(const struct manpaths *, static int fs_lookup(const struct manpaths *,
@ -99,10 +97,9 @@ int mandocdb(int, char**);
static int moptions(int *, char *); static int moptions(int *, char *);
static void mmsg(enum mandocerr, enum mandoclevel, static void mmsg(enum mandocerr, enum mandoclevel,
const char *, int, int, const char *); const char *, int, int, const char *);
static void parse(struct curparse *, int, static void parse(struct curparse *, int, const char *);
const char *, enum mandoclevel *); static void passthrough(const char *, int, int);
static enum mandoclevel passthrough(const char *, int, int); static pid_t spawn_pager(struct tag_files *);
static pid_t spawn_pager(void);
static int toptions(struct curparse *, char *); static int toptions(struct curparse *, char *);
static void usage(enum argmode) __attribute__((noreturn)); static void usage(enum argmode) __attribute__((noreturn));
static int woptions(struct curparse *, char *); static int woptions(struct curparse *, char *);
@ -110,46 +107,60 @@ static int woptions(struct curparse *, char *);
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9}; static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
static char help_arg[] = "help"; static char help_arg[] = "help";
static char *help_argv[] = {help_arg, NULL}; static char *help_argv[] = {help_arg, NULL};
static const char *progname; static enum mandoclevel rc;
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct manconf conf;
struct curparse curp; struct curparse curp;
struct mansearch search; struct mansearch search;
struct manpaths paths; struct tag_files *tag_files;
const char *progname;
char *auxpaths; char *auxpaths;
char *defos; char *defos;
unsigned char *uc; unsigned char *uc;
struct manpage *res, *resp; struct manpage *res, *resp;
char *conf_file, *defpaths; char *conf_file, *defpaths;
size_t isec, i, sz; size_t isec, i, sz;
int prio, best_prio, synopsis_only; int prio, best_prio;
char sec; char sec;
enum mandoclevel rc, rctmp;
enum outmode outmode; enum outmode outmode;
int fd; int fd;
int show_usage; int show_usage;
int options; int options;
int use_pager;
int status, signum;
int c; int c;
pid_t pager_pid; /* 0: don't use; 1: not yet spawned. */ pid_t pager_pid, tc_pgid, man_pgid, pid;
#if HAVE_PROGNAME
progname = getprogname();
#else
if (argc < 1) if (argc < 1)
progname = "mandoc"; progname = mandoc_strdup("mandoc");
else if ((progname = strrchr(argv[0], '/')) == NULL) else if ((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0]; progname = argv[0];
else else
++progname; ++progname;
setprogname(progname);
#endif
#if HAVE_SQLITE3 #if HAVE_SQLITE3
if (strcmp(progname, BINM_MAKEWHATIS) == 0) if (strncmp(progname, "mandocdb", 8) == 0 ||
return(mandocdb(argc, argv)); strcmp(progname, BINM_MAKEWHATIS) == 0)
return mandocdb(argc, argv);
#endif
#if HAVE_PLEDGE
if (pledge("stdio rpath tmppath tty proc exec flock", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
#endif #endif
/* Search options. */ /* Search options. */
memset(&paths, 0, sizeof(struct manpaths)); memset(&conf, 0, sizeof(conf));
conf_file = defpaths = NULL; conf_file = defpaths = NULL;
auxpaths = NULL; auxpaths = NULL;
@ -172,12 +183,13 @@ main(int argc, char *argv[])
memset(&curp, 0, sizeof(struct curparse)); memset(&curp, 0, sizeof(struct curparse));
curp.outtype = OUTT_LOCALE; curp.outtype = OUTT_LOCALE;
curp.wlevel = MANDOCLEVEL_BADARG; curp.wlevel = MANDOCLEVEL_BADARG;
curp.outopts = &conf.output;
options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1; options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1;
defos = NULL; defos = NULL;
pager_pid = 1; use_pager = 1;
tag_files = NULL;
show_usage = 0; show_usage = 0;
synopsis_only = 0;
outmode = OUTMODE_DEF; outmode = OUTMODE_DEF;
while (-1 != (c = getopt(argc, argv, while (-1 != (c = getopt(argc, argv,
@ -190,29 +202,24 @@ main(int argc, char *argv[])
conf_file = optarg; conf_file = optarg;
break; break;
case 'c': case 'c':
pager_pid = 0; use_pager = 0;
break; break;
case 'f': case 'f':
search.argmode = ARG_WORD; search.argmode = ARG_WORD;
break; break;
case 'h': case 'h':
(void)strlcat(curp.outopts, "synopsis,", BUFSIZ); conf.output.synopsisonly = 1;
synopsis_only = 1; use_pager = 0;
pager_pid = 0;
outmode = OUTMODE_ALL; outmode = OUTMODE_ALL;
break; break;
case 'I': case 'I':
if (strncmp(optarg, "os=", 3)) { if (strncmp(optarg, "os=", 3)) {
fprintf(stderr, warnx("-I %s: Bad argument", optarg);
"%s: -I %s: Bad argument\n", return (int)MANDOCLEVEL_BADARG;
progname, optarg);
return((int)MANDOCLEVEL_BADARG);
} }
if (defos) { if (defos) {
fprintf(stderr, warnx("-I %s: Duplicate argument", optarg);
"%s: -I %s: Duplicate argument\n", return (int)MANDOCLEVEL_BADARG;
progname, optarg);
return((int)MANDOCLEVEL_BADARG);
} }
defos = mandoc_strdup(optarg + 3); defos = mandoc_strdup(optarg + 3);
break; break;
@ -221,7 +228,7 @@ main(int argc, char *argv[])
break; break;
case 'K': case 'K':
if ( ! koptions(&options, optarg)) if ( ! koptions(&options, optarg))
return((int)MANDOCLEVEL_BADARG); return (int)MANDOCLEVEL_BADARG;
break; break;
case 'k': case 'k':
search.argmode = ARG_EXPR; search.argmode = ARG_EXPR;
@ -238,8 +245,9 @@ main(int argc, char *argv[])
break; break;
case 'O': case 'O':
search.outkey = optarg; search.outkey = optarg;
(void)strlcat(curp.outopts, optarg, BUFSIZ); while (optarg != NULL)
(void)strlcat(curp.outopts, ",", BUFSIZ); manconf_output(&conf.output,
strsep(&optarg, ","));
break; break;
case 'S': case 'S':
search.arch = optarg; search.arch = optarg;
@ -249,11 +257,11 @@ main(int argc, char *argv[])
break; break;
case 'T': case 'T':
if ( ! toptions(&curp, optarg)) if ( ! toptions(&curp, optarg))
return((int)MANDOCLEVEL_BADARG); return (int)MANDOCLEVEL_BADARG;
break; break;
case 'W': case 'W':
if ( ! woptions(&curp, optarg)) if ( ! woptions(&curp, optarg))
return((int)MANDOCLEVEL_BADARG); return (int)MANDOCLEVEL_BADARG;
break; break;
case 'w': case 'w':
outmode = OUTMODE_FLN; outmode = OUTMODE_FLN;
@ -273,7 +281,7 @@ main(int argc, char *argv[])
switch (search.argmode) { switch (search.argmode) {
case ARG_FILE: case ARG_FILE:
outmode = OUTMODE_ALL; outmode = OUTMODE_ALL;
pager_pid = 0; use_pager = 0;
break; break;
case ARG_NAME: case ARG_NAME:
outmode = OUTMODE_ONE; outmode = OUTMODE_ONE;
@ -284,6 +292,17 @@ main(int argc, char *argv[])
} }
} }
if (outmode == OUTMODE_FLN ||
outmode == OUTMODE_LST ||
!isatty(STDOUT_FILENO))
use_pager = 0;
#if HAVE_PLEDGE
if (!use_pager)
if (pledge("stdio rpath flock", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
#endif
/* Parse arguments. */ /* Parse arguments. */
if (argc > 0) { if (argc > 0) {
@ -334,22 +353,28 @@ main(int argc, char *argv[])
/* Access the mandoc database. */ /* Access the mandoc database. */
manpath_parse(&paths, conf_file, defpaths, auxpaths); manconf_parse(&conf, conf_file, defpaths, auxpaths);
#if HAVE_SQLITE3 #if HAVE_SQLITE3
mansearch_setup(1); mansearch_setup(1);
if( ! mansearch(&search, &paths, argc, argv, &res, &sz)) if ( ! mansearch(&search, &conf.manpath,
argc, argv, &res, &sz))
usage(search.argmode); usage(search.argmode);
#else #else
if (search.argmode != ARG_NAME) { if (search.argmode != ARG_NAME) {
fputs("mandoc: database support not compiled in\n", fputs("mandoc: database support not compiled in\n",
stderr); stderr);
return((int)MANDOCLEVEL_BADARG); return (int)MANDOCLEVEL_BADARG;
} }
sz = 0; sz = 0;
#endif #endif
if (sz == 0 && search.argmode == ARG_NAME) if (sz == 0) {
fs_search(&search, &paths, argc, argv, &res, &sz); if (search.argmode == ARG_NAME)
fs_search(&search, &conf.manpath,
argc, argv, &res, &sz);
else
warnx("nothing appropriate");
}
if (sz == 0) { if (sz == 0) {
rc = MANDOCLEVEL_BADARG; rc = MANDOCLEVEL_BADARG;
@ -404,12 +429,21 @@ main(int argc, char *argv[])
/* mandoc(1) */ /* mandoc(1) */
if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths)) #if HAVE_PLEDGE
return((int)MANDOCLEVEL_BADARG); if (use_pager) {
if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
} else {
if (pledge("stdio rpath", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
}
#endif
curp.mchars = mchars_alloc(); if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths))
curp.mp = mparse_alloc(options, curp.wlevel, mmsg, return (int)MANDOCLEVEL_BADARG;
curp.mchars, defos);
mchars_alloc();
curp.mp = mparse_alloc(options, curp.wlevel, mmsg, defos);
/* /*
* Conditionally start up the lookaside buffer before parsing. * Conditionally start up the lookaside buffer before parsing.
@ -418,41 +452,33 @@ main(int argc, char *argv[])
mparse_keep(curp.mp); mparse_keep(curp.mp);
if (argc < 1) { if (argc < 1) {
if (pager_pid == 1 && isatty(STDOUT_FILENO)) if (use_pager)
pager_pid = spawn_pager(); tag_files = tag_init();
parse(&curp, STDIN_FILENO, "<stdin>", &rc); parse(&curp, STDIN_FILENO, "<stdin>");
} }
while (argc > 0) { while (argc > 0) {
rctmp = mparse_open(curp.mp, &fd, fd = mparse_open(curp.mp, resp != NULL ? resp->file : *argv);
resp != NULL ? resp->file : *argv);
if (rc < rctmp)
rc = rctmp;
if (fd != -1) { if (fd != -1) {
if (pager_pid == 1 && isatty(STDOUT_FILENO)) if (use_pager) {
pager_pid = spawn_pager(); tag_files = tag_init();
use_pager = 0;
if (resp == NULL)
parse(&curp, fd, *argv, &rc);
else if (resp->form & FORM_SRC) {
/* For .so only; ignore failure. */
chdir(paths.paths[resp->ipath]);
parse(&curp, fd, resp->file, &rc);
} else {
rctmp = passthrough(resp->file, fd,
synopsis_only);
if (rc < rctmp)
rc = rctmp;
} }
rctmp = mparse_wait(curp.mp); if (resp == NULL)
if (rc < rctmp) parse(&curp, fd, *argv);
rc = rctmp; else if (resp->form & FORM_SRC) {
/* For .so only; ignore failure. */
chdir(conf.manpath.paths[resp->ipath]);
parse(&curp, fd, resp->file);
} else
passthrough(resp->file, fd,
conf.output.synopsisonly);
if (argc > 1 && curp.outtype <= OUTT_UTF8) if (argc > 1 && curp.outtype <= OUTT_UTF8)
ascii_sepline(curp.outdata); ascii_sepline(curp.outdata);
} } else if (rc < MANDOCLEVEL_ERROR)
rc = MANDOCLEVEL_ERROR;
if (MANDOCLEVEL_OK != rc && curp.wstop) if (MANDOCLEVEL_OK != rc && curp.wstop)
break; break;
@ -465,14 +491,30 @@ main(int argc, char *argv[])
mparse_reset(curp.mp); mparse_reset(curp.mp);
} }
if (curp.outfree) if (curp.outdata != NULL) {
(*curp.outfree)(curp.outdata); switch (curp.outtype) {
case OUTT_HTML:
html_free(curp.outdata);
break;
case OUTT_UTF8:
case OUTT_LOCALE:
case OUTT_ASCII:
ascii_free(curp.outdata);
break;
case OUTT_PDF:
case OUTT_PS:
pspdf_free(curp.outdata);
break;
default:
break;
}
}
mparse_free(curp.mp); mparse_free(curp.mp);
mchars_free(curp.mchars); mchars_free();
out: out:
if (search.argmode != ARG_FILE) { if (search.argmode != ARG_FILE) {
manpath_free(&paths); manconf_free(&conf);
#if HAVE_SQLITE3 #if HAVE_SQLITE3
mansearch_free(res, sz); mansearch_free(res, sz);
mansearch_setup(0); mansearch_setup(0);
@ -482,17 +524,63 @@ main(int argc, char *argv[])
free(defos); free(defos);
/* /*
* If a pager is attached, flush the pipe leading to it * When using a pager, finish writing both temporary files,
* and signal end of file such that the user can browse * fork it, wait for the user to close it, and clean up.
* to the end. Then wait for the user to close the pager.
*/ */
if (pager_pid != 0 && pager_pid != 1) { if (tag_files != NULL) {
fclose(stdout); fclose(stdout);
waitpid(pager_pid, NULL, 0); tag_write();
man_pgid = getpgid(0);
tag_files->tcpgid = man_pgid == getpid() ?
getpgid(getppid()) : man_pgid;
pager_pid = 0;
signum = SIGSTOP;
for (;;) {
/* Stop here until moved to the foreground. */
tc_pgid = tcgetpgrp(STDIN_FILENO);
if (tc_pgid != man_pgid) {
if (tc_pgid == pager_pid) {
(void)tcsetpgrp(STDIN_FILENO,
man_pgid);
if (signum == SIGTTIN)
continue;
} else
tag_files->tcpgid = tc_pgid;
kill(0, signum);
continue;
}
/* Once in the foreground, activate the pager. */
if (pager_pid) {
(void)tcsetpgrp(STDIN_FILENO, pager_pid);
kill(pager_pid, SIGCONT);
} else
pager_pid = spawn_pager(tag_files);
/* Wait for the pager to stop or exit. */
while ((pid = waitpid(pager_pid, &status,
WUNTRACED)) == -1 && errno == EINTR)
continue;
if (pid == -1) {
warn("wait");
rc = MANDOCLEVEL_SYSERR;
break;
}
if (!WIFSTOPPED(status))
break;
signum = WSTOPSIG(status);
}
tag_unlink();
} }
return((int)rc); return (int)rc;
} }
static void static void
@ -501,9 +589,9 @@ usage(enum argmode argmode)
switch (argmode) { switch (argmode) {
case ARG_FILE: case ARG_FILE:
fputs("usage: mandoc [-acfhkl] [-Ios=name] " fputs("usage: mandoc [-acfhkl] [-I os=name] "
"[-Kencoding] [-mformat] [-Ooption]\n" "[-K encoding] [-mformat] [-O option]\n"
"\t [-Toutput] [-Wlevel] [file ...]\n", stderr); "\t [-T output] [-W level] [file ...]\n", stderr);
break; break;
case ARG_NAME: case ARG_NAME:
fputs("usage: man [-acfhklw] [-C file] [-I os=name] " fputs("usage: man [-acfhklw] [-C file] [-I os=name] "
@ -559,26 +647,23 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
free(file); free(file);
} }
mandoc_asprintf(&file, "%s/man%s/%s.*", mandoc_asprintf(&file, "%s/man%s/%s.[01-9]*",
paths->paths[ipath], sec, name); paths->paths[ipath], sec, name);
globres = glob(file, 0, NULL, &globinfo); globres = glob(file, 0, NULL, &globinfo);
if (globres != 0 && globres != GLOB_NOMATCH) if (globres != 0 && globres != GLOB_NOMATCH)
fprintf(stderr, "%s: %s: glob: %s\n", warn("%s: glob", file);
progname, file, strerror(errno));
free(file); free(file);
if (globres == 0) if (globres == 0)
file = mandoc_strdup(*globinfo.gl_pathv); file = mandoc_strdup(*globinfo.gl_pathv);
globfree(&globinfo); globfree(&globinfo);
if (globres != 0) if (globres != 0)
return(0); return 0;
found: found:
#if HAVE_SQLITE3 #if HAVE_SQLITE3
fprintf(stderr, "%s: outdated mandoc.db lacks %s(%s) entry,\n" warnx("outdated mandoc.db lacks %s(%s) entry, run makewhatis %s",
" consider running # makewhatis %s\n", name, sec, paths->paths[ipath]);
progname, name, sec, paths->paths[ipath]);
#endif #endif
*res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage)); *res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage));
page = *res + (*ressz - 1); page = *res + (*ressz - 1);
page->file = file; page->file = file;
@ -588,7 +673,7 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
page->bits = NAME_FILE & NAME_MASK; page->bits = NAME_FILE & NAME_MASK;
page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10;
page->form = form; page->form = form;
return(1); return 1;
} }
static void static void
@ -619,9 +704,7 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
return; return;
} }
if (*ressz == lastsz) if (*ressz == lastsz)
fprintf(stderr, warnx("No entry for %s in the manual.", *argv);
"%s: No entry for %s in the manual.\n",
progname, *argv);
lastsz = *ressz; lastsz = *ressz;
argv++; argv++;
argc--; argc--;
@ -629,111 +712,112 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
} }
static void static void
parse(struct curparse *curp, int fd, const char *file, parse(struct curparse *curp, int fd, const char *file)
enum mandoclevel *level)
{ {
enum mandoclevel rc; enum mandoclevel rctmp;
struct mdoc *mdoc; struct roff_man *man;
struct man *man;
/* Begin by parsing the file itself. */ /* Begin by parsing the file itself. */
assert(file); assert(file);
assert(fd >= -1); assert(fd > 0);
rc = mparse_readfd(curp->mp, fd, file); rctmp = mparse_readfd(curp->mp, fd, file);
if (fd != STDIN_FILENO)
close(fd);
if (rc < rctmp)
rc = rctmp;
/* /*
* With -Wstop and warnings or errors of at least the requested * With -Wstop and warnings or errors of at least the requested
* level, do not produce output. * level, do not produce output.
*/ */
if (MANDOCLEVEL_OK != rc && curp->wstop) if (rctmp != MANDOCLEVEL_OK && curp->wstop)
goto cleanup; return;
/* If unset, allocate output dev now (if applicable). */ /* If unset, allocate output dev now (if applicable). */
if ( ! (curp->outman && curp->outmdoc)) { if (curp->outdata == NULL) {
switch (curp->outtype) { switch (curp->outtype) {
case OUTT_HTML: case OUTT_HTML:
curp->outdata = html_alloc(curp->mchars, curp->outdata = html_alloc(curp->outopts);
curp->outopts);
curp->outfree = html_free;
break; break;
case OUTT_UTF8: case OUTT_UTF8:
curp->outdata = utf8_alloc(curp->mchars, curp->outdata = utf8_alloc(curp->outopts);
curp->outopts);
curp->outfree = ascii_free;
break; break;
case OUTT_LOCALE: case OUTT_LOCALE:
curp->outdata = locale_alloc(curp->mchars, curp->outdata = locale_alloc(curp->outopts);
curp->outopts);
curp->outfree = ascii_free;
break; break;
case OUTT_ASCII: case OUTT_ASCII:
curp->outdata = ascii_alloc(curp->mchars, curp->outdata = ascii_alloc(curp->outopts);
curp->outopts);
curp->outfree = ascii_free;
break; break;
case OUTT_PDF: case OUTT_PDF:
curp->outdata = pdf_alloc(curp->mchars, curp->outdata = pdf_alloc(curp->outopts);
curp->outopts);
curp->outfree = pspdf_free;
break; break;
case OUTT_PS: case OUTT_PS:
curp->outdata = ps_alloc(curp->mchars, curp->outdata = ps_alloc(curp->outopts);
curp->outopts);
curp->outfree = pspdf_free;
break;
default:
break;
}
switch (curp->outtype) {
case OUTT_HTML:
curp->outman = html_man;
curp->outmdoc = html_mdoc;
break;
case OUTT_TREE:
curp->outman = tree_man;
curp->outmdoc = tree_mdoc;
break;
case OUTT_MAN:
curp->outmdoc = man_mdoc;
curp->outman = man_man;
break;
case OUTT_PDF:
/* FALLTHROUGH */
case OUTT_ASCII:
/* FALLTHROUGH */
case OUTT_UTF8:
/* FALLTHROUGH */
case OUTT_LOCALE:
/* FALLTHROUGH */
case OUTT_PS:
curp->outman = terminal_man;
curp->outmdoc = terminal_mdoc;
break; break;
default: default:
break; break;
} }
} }
mparse_result(curp->mp, &mdoc, &man, NULL); mparse_result(curp->mp, &man, NULL);
/* Execute the out device, if it exists. */ /* Execute the out device, if it exists. */
if (man && curp->outman) if (man == NULL)
(*curp->outman)(curp->outdata, man); return;
if (mdoc && curp->outmdoc) if (man->macroset == MACROSET_MDOC) {
(*curp->outmdoc)(curp->outdata, mdoc); mdoc_validate(man);
switch (curp->outtype) {
cleanup: case OUTT_HTML:
if (*level < rc) html_mdoc(curp->outdata, man);
*level = rc; break;
case OUTT_TREE:
tree_mdoc(curp->outdata, man);
break;
case OUTT_MAN:
man_mdoc(curp->outdata, man);
break;
case OUTT_PDF:
case OUTT_ASCII:
case OUTT_UTF8:
case OUTT_LOCALE:
case OUTT_PS:
terminal_mdoc(curp->outdata, man);
break;
default:
break;
}
}
if (man->macroset == MACROSET_MAN) {
man_validate(man);
switch (curp->outtype) {
case OUTT_HTML:
html_man(curp->outdata, man);
break;
case OUTT_TREE:
tree_man(curp->outdata, man);
break;
case OUTT_MAN:
man_man(curp->outdata, man);
break;
case OUTT_PDF:
case OUTT_ASCII:
case OUTT_UTF8:
case OUTT_LOCALE:
case OUTT_PS:
terminal_man(curp->outdata, man);
break;
default:
break;
}
}
} }
static enum mandoclevel static void
passthrough(const char *file, int fd, int synopsis_only) passthrough(const char *file, int fd, int synopsis_only)
{ {
const char synb[] = "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS"; const char synb[] = "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS";
@ -741,12 +825,12 @@ passthrough(const char *file, int fd, int synopsis_only)
FILE *stream; FILE *stream;
const char *syscall; const char *syscall;
char *line; char *line, *cp;
size_t len, off; size_t linesz;
ssize_t nw;
int print; int print;
fflush(stdout); line = NULL;
linesz = 0;
if ((stream = fdopen(fd, "r")) == NULL) { if ((stream = fdopen(fd, "r")) == NULL) {
close(fd); close(fd);
@ -755,48 +839,44 @@ passthrough(const char *file, int fd, int synopsis_only)
} }
print = 0; print = 0;
while ((line = fgetln(stream, &len)) != NULL) { while (getline(&line, &linesz, stream) != -1) {
cp = line;
if (synopsis_only) { if (synopsis_only) {
if (print) { if (print) {
if ( ! isspace((unsigned char)*line)) if ( ! isspace((unsigned char)*cp))
goto done; goto done;
while (len && while (isspace((unsigned char)*cp))
isspace((unsigned char)*line)) { cp++;
line++;
len--;
}
} else { } else {
if ((len == sizeof(synb) && if (strcmp(cp, synb) == 0 ||
! strncmp(line, synb, len - 1)) || strcmp(cp, synr) == 0)
(len == sizeof(synr) &&
! strncmp(line, synr, len - 1)))
print = 1; print = 1;
continue; continue;
} }
} }
for (off = 0; off < len; off += nw) if (fputs(cp, stdout)) {
if ((nw = write(STDOUT_FILENO, line + off, fclose(stream);
len - off)) == -1 || nw == 0) { syscall = "fputs";
fclose(stream); goto fail;
syscall = "write"; }
goto fail;
}
} }
if (ferror(stream)) { if (ferror(stream)) {
fclose(stream); fclose(stream);
syscall = "fgetln"; syscall = "getline";
goto fail; goto fail;
} }
done: done:
free(line);
fclose(stream); fclose(stream);
return(MANDOCLEVEL_OK); return;
fail: fail:
fprintf(stderr, "%s: %s: SYSERR: %s: %s", free(line);
progname, file, syscall, strerror(errno)); warn("%s: SYSERR: %s", file, syscall);
return(MANDOCLEVEL_SYSERR); if (rc < MANDOCLEVEL_SYSERR)
rc = MANDOCLEVEL_SYSERR;
} }
static int static int
@ -812,11 +892,10 @@ koptions(int *options, char *arg)
} else if ( ! strcmp(arg, "us-ascii")) { } else if ( ! strcmp(arg, "us-ascii")) {
*options &= ~(MPARSE_UTF8 | MPARSE_LATIN1); *options &= ~(MPARSE_UTF8 | MPARSE_LATIN1);
} else { } else {
fprintf(stderr, "%s: -K %s: Bad argument\n", warnx("-K %s: Bad argument", arg);
progname, arg); return 0;
return(0);
} }
return(1); return 1;
} }
static int static int
@ -832,12 +911,11 @@ moptions(int *options, char *arg)
else if (0 == strcmp(arg, "an")) else if (0 == strcmp(arg, "an"))
*options |= MPARSE_MAN; *options |= MPARSE_MAN;
else { else {
fprintf(stderr, "%s: -m %s: Bad argument\n", warnx("-m %s: Bad argument", arg);
progname, arg); return 0;
return(0);
} }
return(1); return 1;
} }
static int static int
@ -866,12 +944,11 @@ toptions(struct curparse *curp, char *arg)
else if (0 == strcmp(arg, "pdf")) else if (0 == strcmp(arg, "pdf"))
curp->outtype = OUTT_PDF; curp->outtype = OUTT_PDF;
else { else {
fprintf(stderr, "%s: -T %s: Bad argument\n", warnx("-T %s: Bad argument", arg);
progname, arg); return 0;
return(0);
} }
return(1); return 1;
} }
static int static int
@ -895,7 +972,6 @@ woptions(struct curparse *curp, char *arg)
curp->wstop = 1; curp->wstop = 1;
break; break;
case 1: case 1:
/* FALLTHROUGH */
case 2: case 2:
curp->wlevel = MANDOCLEVEL_WARNING; curp->wlevel = MANDOCLEVEL_WARNING;
break; break;
@ -909,13 +985,12 @@ woptions(struct curparse *curp, char *arg)
curp->wlevel = MANDOCLEVEL_BADARG; curp->wlevel = MANDOCLEVEL_BADARG;
break; break;
default: default:
fprintf(stderr, "%s: -W %s: Bad argument\n", warnx("-W %s: Bad argument", o);
progname, o); return 0;
return(0);
} }
} }
return(1); return 1;
} }
static void static void
@ -924,7 +999,7 @@ mmsg(enum mandocerr t, enum mandoclevel lvl,
{ {
const char *mparse_msg; const char *mparse_msg;
fprintf(stderr, "%s: %s:", progname, file); fprintf(stderr, "%s: %s:", getprogname(), file);
if (line) if (line)
fprintf(stderr, "%d:%d:", line, col + 1); fprintf(stderr, "%d:%d:", line, col + 1);
@ -941,55 +1016,21 @@ mmsg(enum mandocerr t, enum mandoclevel lvl,
} }
static pid_t static pid_t
spawn_pager(void) spawn_pager(struct tag_files *tag_files)
{ {
#define MAX_PAGER_ARGS 16 #define MAX_PAGER_ARGS 16
char *argv[MAX_PAGER_ARGS]; char *argv[MAX_PAGER_ARGS];
const char *pager; const char *pager;
char *cp; char *cp;
int fildes[2]; size_t cmdlen;
int argc; int argc;
pid_t pager_pid; pid_t pager_pid;
if (pipe(fildes) == -1) {
fprintf(stderr, "%s: pipe: %s\n",
progname, strerror(errno));
return(0);
}
switch (pager_pid = fork()) {
case -1:
fprintf(stderr, "%s: fork: %s\n",
progname, strerror(errno));
exit((int)MANDOCLEVEL_SYSERR);
case 0:
break;
default:
close(fildes[0]);
if (dup2(fildes[1], STDOUT_FILENO) == -1) {
fprintf(stderr, "%s: dup output: %s\n",
progname, strerror(errno));
exit((int)MANDOCLEVEL_SYSERR);
}
close(fildes[1]);
return(pager_pid);
}
/* The child process becomes the pager. */
close(fildes[1]);
if (dup2(fildes[0], STDIN_FILENO) == -1) {
fprintf(stderr, "%s: dup input: %s\n",
progname, strerror(errno));
exit((int)MANDOCLEVEL_SYSERR);
}
close(fildes[0]);
pager = getenv("MANPAGER"); pager = getenv("MANPAGER");
if (pager == NULL || *pager == '\0') if (pager == NULL || *pager == '\0')
pager = getenv("PAGER"); pager = getenv("PAGER");
if (pager == NULL || *pager == '\0') if (pager == NULL || *pager == '\0')
pager = "/usr/bin/more -s"; pager = "more -s";
cp = mandoc_strdup(pager); cp = mandoc_strdup(pager);
/* /*
@ -998,7 +1039,7 @@ spawn_pager(void)
*/ */
argc = 0; argc = 0;
while (argc + 1 < MAX_PAGER_ARGS) { while (argc + 4 < MAX_PAGER_ARGS) {
argv[argc++] = cp; argv[argc++] = cp;
cp = strchr(cp, ' '); cp = strchr(cp, ' ');
if (cp == NULL) if (cp == NULL)
@ -1009,12 +1050,43 @@ spawn_pager(void)
if (*cp == '\0') if (*cp == '\0')
break; break;
} }
/* For more(1) and less(1), use the tag file. */
if ((cmdlen = strlen(argv[0])) >= 4) {
cp = argv[0] + cmdlen - 4;
if (strcmp(cp, "less") == 0 || strcmp(cp, "more") == 0) {
argv[argc++] = mandoc_strdup("-T");
argv[argc++] = tag_files->tfn;
}
}
argv[argc++] = tag_files->ofn;
argv[argc] = NULL; argv[argc] = NULL;
/* Hand over to the pager. */ switch (pager_pid = fork()) {
case -1:
err((int)MANDOCLEVEL_SYSERR, "fork");
case 0:
/* Set pgrp in both parent and child to avoid racing exec. */
(void)setpgid(0, 0);
break;
default:
(void)setpgid(pager_pid, 0);
(void)tcsetpgrp(STDIN_FILENO, pager_pid);
#if HAVE_PLEDGE
if (pledge("stdio rpath tmppath tty proc", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
#endif
tag_files->pager_pid = pager_pid;
return pager_pid;
}
/* The child process becomes the pager. */
if (dup2(tag_files->ofd, STDOUT_FILENO) == -1)
err((int)MANDOCLEVEL_SYSERR, "pager stdout");
close(tag_files->ofd);
close(tag_files->tfd);
execvp(argv[0], argv); execvp(argv[0], argv);
fprintf(stderr, "%s: exec: %s\n", err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]);
progname, strerror(errno));
exit((int)MANDOCLEVEL_SYSERR);
} }

View File

@ -1,15 +1,15 @@
/* $Id: main.h,v 1.20 2014/12/31 16:52:40 schwarze Exp $ */ /* $Id: main.h,v 1.24 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -18,11 +18,8 @@
#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a)) #define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
__BEGIN_DECLS struct roff_man;
struct manoutput;
struct mchars;
struct mdoc;
struct man;
/* /*
* Definitions for main.c-visible output device functions, e.g., -Thtml * Definitions for main.c-visible output device functions, e.g., -Thtml
@ -31,28 +28,26 @@ struct man;
* terminal output routines with different character settings. * terminal output routines with different character settings.
*/ */
void *html_alloc(const struct mchars *, char *); void *html_alloc(const struct manoutput *);
void html_mdoc(void *, const struct mdoc *); void html_mdoc(void *, const struct roff_man *);
void html_man(void *, const struct man *); void html_man(void *, const struct roff_man *);
void html_free(void *); void html_free(void *);
void tree_mdoc(void *, const struct mdoc *); void tree_mdoc(void *, const struct roff_man *);
void tree_man(void *, const struct man *); void tree_man(void *, const struct roff_man *);
void man_mdoc(void *, const struct mdoc *); void man_mdoc(void *, const struct roff_man *);
void man_man(void *, const struct man *); void man_man(void *, const struct roff_man *);
void *locale_alloc(const struct mchars *, char *); void *locale_alloc(const struct manoutput *);
void *utf8_alloc(const struct mchars *, char *); void *utf8_alloc(const struct manoutput *);
void *ascii_alloc(const struct mchars *, char *); void *ascii_alloc(const struct manoutput *);
void ascii_free(void *); void ascii_free(void *);
void ascii_sepline(void *); void ascii_sepline(void *);
void *pdf_alloc(const struct mchars *, char *); void *pdf_alloc(const struct manoutput *);
void *ps_alloc(const struct mchars *, char *); void *ps_alloc(const struct manoutput *);
void pspdf_free(void *); void pspdf_free(void *);
void terminal_mdoc(void *, const struct mdoc *); void terminal_mdoc(void *, const struct roff_man *);
void terminal_man(void *, const struct man *); void terminal_man(void *, const struct roff_man *);
__END_DECLS

View File

@ -1,4 +1,4 @@
.\" $Id: man.1,v 1.13 2015/02/16 16:23:54 schwarze Exp $ .\" $Id: man.1,v 1.16 2015/09/21 09:59:02 schwarze Exp $
.\" .\"
.\" Copyright (c) 1989, 1990, 1993 .\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved. .\" The Regents of the University of California. All rights reserved.
@ -31,7 +31,7 @@
.\" .\"
.\" @(#)man.1 8.2 (Berkeley) 1/2/94 .\" @(#)man.1 8.2 (Berkeley) 1/2/94
.\" .\"
.Dd $Mdocdate: February 16 2015 $ .Dd $Mdocdate: September 21 2015 $
.Dt MAN 1 .Dt MAN 1
.Os .Os
.Sh NAME .Sh NAME
@ -173,12 +173,6 @@ must be a colon
separated list of directories. separated list of directories.
This search path may also be set using the environment variable This search path may also be set using the environment variable
.Ev MANPATH . .Ev MANPATH .
The subdirectories to be searched, and their search order,
are specified by the
.Dq _subdir
line in the
.Nm
configuration file.
.It Fl m Ar path .It Fl m Ar path
Augment the list of standard directories which Augment the list of standard directories which
.Nm .Nm
@ -194,12 +188,6 @@ the directories specified using the
option or the option or the
.Ev MANPATH .Ev MANPATH
environment variable. environment variable.
The subdirectories to be searched, and their search order,
are specified by the
.Dq _subdir
line in the
.Nm
configuration file.
.It Fl O Ar option Ns = Ns Ar value .It Fl O Ar option Ns = Ns Ar value
Comma-separated output options. Comma-separated output options.
For each output format, the available options are described in the For each output format, the available options are described in the
@ -360,6 +348,13 @@ Any non-empty value of the environment variable
.Ev MANPAGER .Ev MANPAGER
will be used instead of the standard pagination program, will be used instead of the standard pagination program,
.Xr more 1 . .Xr more 1 .
If
.Xr less 1
is used, the interactive
.Ic :t
command can be used to go to the definitions of various terms, for
example command line options, command modifiers, internal commands,
and environment variables.
.It Ev MANPATH .It Ev MANPATH
The standard search path used by The standard search path used by
.Nm .Nm
@ -370,18 +365,13 @@ variable.
The format of the path is a colon The format of the path is a colon
.Pq Ql \&: .Pq Ql \&:
separated list of directories. separated list of directories.
The subdirectories to be searched, as well as their search order,
are specified by the
.Dq _subdir
line in the
.Nm
configuration file.
.It Ev PAGER .It Ev PAGER
Specifies the pagination program to use when Specifies the pagination program to use when
.Ev MANPAGER .Ev MANPAGER
is not defined. is not defined.
If neither PAGER nor MANPAGER is defined, If neither PAGER nor MANPAGER is defined,
.Pa /usr/bin/more Fl s .Xr more 1
.Fl s
will be used. will be used.
.El .El
.Sh FILES .Sh FILES

View File

@ -1,4 +1,4 @@
/* $Id: man.c,v 1.149 2015/01/30 21:28:46 schwarze Exp $ */ /* $Id: man.c,v 1.166 2015/10/22 21:54:23 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -8,9 +8,9 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -27,11 +27,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "man.h"
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "libman.h" #include "mandoc.h"
#include "roff.h"
#include "man.h"
#include "libmandoc.h" #include "libmandoc.h"
#include "roff_int.h"
#include "libman.h"
const char *const __man_macronames[MAN_MAX] = { const char *const __man_macronames[MAN_MAX] = {
"br", "TH", "SH", "SS", "br", "TH", "SH", "SS",
@ -48,306 +50,25 @@ const char *const __man_macronames[MAN_MAX] = {
const char * const *man_macronames = __man_macronames; const char * const *man_macronames = __man_macronames;
static void man_alloc1(struct man *); static void man_descope(struct roff_man *, int, int);
static void man_breakscope(struct man *, enum mant); static int man_ptext(struct roff_man *, int, char *, int);
static void man_descope(struct man *, int, int); static int man_pmacro(struct roff_man *, int, char *, int);
static void man_free1(struct man *);
static struct man_node *man_node_alloc(struct man *, int, int,
enum man_type, enum mant);
static void man_node_append(struct man *, struct man_node *);
static void man_node_free(struct man_node *);
static void man_node_unlink(struct man *,
struct man_node *);
static int man_ptext(struct man *, int, char *, int);
static int man_pmacro(struct man *, int, char *, int);
const struct man_node *
man_node(const struct man *man)
{
return(man->first);
}
const struct man_meta *
man_meta(const struct man *man)
{
return(&man->meta);
}
void
man_reset(struct man *man)
{
man_free1(man);
man_alloc1(man);
}
void
man_free(struct man *man)
{
man_free1(man);
free(man);
}
struct man *
man_alloc(struct roff *roff, struct mparse *parse,
const char *defos, int quick)
{
struct man *p;
p = mandoc_calloc(1, sizeof(struct man));
man_hash_init();
p->parse = parse;
p->defos = defos;
p->quick = quick;
p->roff = roff;
man_alloc1(p);
return(p);
}
void
man_endparse(struct man *man)
{
man_macroend(man);
}
int int
man_parseln(struct man *man, int ln, char *buf, int offs) man_parseln(struct roff_man *man, int ln, char *buf, int offs)
{ {
if (man->last->type != MAN_EQN || ln > man->last->line) if (man->last->type != ROFFT_EQN || ln > man->last->line)
man->flags |= MAN_NEWLINE; man->flags |= MAN_NEWLINE;
return (roff_getcontrol(man->roff, buf, &offs) ? return roff_getcontrol(man->roff, buf, &offs) ?
man_pmacro(man, ln, buf, offs) : man_pmacro(man, ln, buf, offs) :
man_ptext(man, ln, buf, offs)); man_ptext(man, ln, buf, offs);
} }
static void static void
man_free1(struct man *man) man_descope(struct roff_man *man, int line, int offs)
{
if (man->first)
man_node_delete(man, man->first);
free(man->meta.title);
free(man->meta.source);
free(man->meta.date);
free(man->meta.vol);
free(man->meta.msec);
}
static void
man_alloc1(struct man *man)
{
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;
}
static void
man_node_append(struct man *man, struct man_node *p)
{
assert(man->last);
assert(man->first);
assert(p->type != MAN_ROOT);
switch (man->next) {
case MAN_NEXT_SIBLING:
man->last->next = p;
p->prev = man->last;
p->parent = man->last->parent;
break;
case MAN_NEXT_CHILD:
man->last->child = p;
p->parent = man->last;
break;
default:
abort();
/* NOTREACHED */
}
assert(p->parent);
p->parent->nchild++;
switch (p->type) {
case MAN_BLOCK:
if (p->tok == MAN_SH || p->tok == MAN_SS)
man->flags &= ~MAN_LITERAL;
break;
case MAN_HEAD:
assert(p->parent->type == MAN_BLOCK);
p->parent->head = p;
break;
case MAN_BODY:
assert(p->parent->type == MAN_BLOCK);
p->parent->body = p;
break;
default:
break;
}
man->last = p;
switch (p->type) {
case MAN_TBL:
/* FALLTHROUGH */
case MAN_TEXT:
man_valid_post(man);
break;
default:
break;
}
}
static struct man_node *
man_node_alloc(struct man *man, int line, int pos,
enum man_type type, enum mant tok)
{
struct man_node *p;
p = mandoc_calloc(1, sizeof(struct man_node));
p->line = line;
p->pos = pos;
p->type = type;
p->tok = tok;
if (man->flags & MAN_NEWLINE)
p->flags |= MAN_LINE;
man->flags &= ~MAN_NEWLINE;
return(p);
}
void
man_elem_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
p = man_node_alloc(man, line, pos, MAN_ELEM, tok);
man_node_append(man, p);
man->next = MAN_NEXT_CHILD;
}
void
man_head_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
p = man_node_alloc(man, line, pos, MAN_HEAD, tok);
man_node_append(man, p);
man->next = MAN_NEXT_CHILD;
}
void
man_body_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
p = man_node_alloc(man, line, pos, MAN_BODY, tok);
man_node_append(man, p);
man->next = MAN_NEXT_CHILD;
}
void
man_block_alloc(struct man *man, int line, int pos, enum mant tok)
{
struct man_node *p;
p = man_node_alloc(man, line, pos, MAN_BLOCK, tok);
man_node_append(man, p);
man->next = MAN_NEXT_CHILD;
}
void
man_word_alloc(struct man *man, int line, int pos, const char *word)
{
struct man_node *n;
n = man_node_alloc(man, line, pos, MAN_TEXT, MAN_MAX);
n->string = roff_strdup(man->roff, word);
man_node_append(man, n);
man->next = MAN_NEXT_SIBLING;
}
void
man_word_append(struct man *man, const char *word)
{
struct man_node *n;
char *addstr, *newstr;
n = man->last;
addstr = roff_strdup(man->roff, word);
mandoc_asprintf(&newstr, "%s %s", n->string, addstr);
free(addstr);
free(n->string);
n->string = newstr;
man->next = MAN_NEXT_SIBLING;
}
/*
* Free all of the resources held by a node. This does NOT unlink a
* node from its context; for that, see man_node_unlink().
*/
static void
man_node_free(struct man_node *p)
{
free(p->string);
free(p);
}
void
man_node_delete(struct man *man, struct man_node *p)
{
while (p->child)
man_node_delete(man, p->child);
man_node_unlink(man, p);
man_node_free(p);
}
void
man_addeqn(struct man *man, const struct eqn *ep)
{
struct man_node *n;
n = man_node_alloc(man, ep->ln, ep->pos, MAN_EQN, MAN_MAX);
n->eqn = ep;
if (ep->ln > man->last->line)
n->flags |= MAN_LINE;
man_node_append(man, n);
man->next = MAN_NEXT_SIBLING;
man_descope(man, ep->ln, ep->pos);
}
void
man_addspan(struct man *man, const struct tbl_span *sp)
{
struct man_node *n;
man_breakscope(man, MAN_MAX);
n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX);
n->span = sp;
man_node_append(man, n);
man->next = MAN_NEXT_SIBLING;
man_descope(man, sp->line, 0);
}
static void
man_descope(struct man *man, int line, int offs)
{ {
/* /*
* Co-ordinate what happens with having a next-line scope open: * Co-ordinate what happens with having a next-line scope open:
@ -363,20 +84,20 @@ man_descope(struct man *man, int line, int offs)
return; return;
man->flags &= ~MAN_BLINE; man->flags &= ~MAN_BLINE;
man_unscope(man, man->last->parent); man_unscope(man, man->last->parent);
man_body_alloc(man, line, offs, man->last->tok); roff_body_alloc(man, line, offs, man->last->tok);
} }
static int static int
man_ptext(struct man *man, int line, char *buf, int offs) man_ptext(struct roff_man *man, int line, char *buf, int offs)
{ {
int i; int i;
/* Literal free-form text whitespace is preserved. */ /* Literal free-form text whitespace is preserved. */
if (man->flags & MAN_LITERAL) { if (man->flags & MAN_LITERAL) {
man_word_alloc(man, line, offs, buf + offs); roff_word_alloc(man, line, offs, buf + offs);
man_descope(man, line, offs); man_descope(man, line, offs);
return(1); return 1;
} }
for (i = offs; buf[i] == ' '; i++) for (i = offs; buf[i] == ' '; i++)
@ -391,10 +112,10 @@ man_ptext(struct man *man, int line, char *buf, int offs)
/* Allocate a blank entry. */ /* Allocate a blank entry. */
if (man->last->tok != MAN_SH && if (man->last->tok != MAN_SH &&
man->last->tok != MAN_SS) { man->last->tok != MAN_SS) {
man_elem_alloc(man, line, offs, MAN_sp); roff_elem_alloc(man, line, offs, MAN_sp);
man->next = MAN_NEXT_SIBLING; man->next = ROFF_NEXT_SIBLING;
} }
return(1); return 1;
} }
/* /*
@ -418,7 +139,7 @@ man_ptext(struct man *man, int line, char *buf, int offs)
buf[i] = '\0'; buf[i] = '\0';
} }
man_word_alloc(man, line, offs, buf + offs); roff_word_alloc(man, line, offs, buf + offs);
/* /*
* End-of-sentence check. If the last character is an unescaped * End-of-sentence check. If the last character is an unescaped
@ -431,15 +152,15 @@ man_ptext(struct man *man, int line, char *buf, int offs)
man->last->flags |= MAN_EOS; man->last->flags |= MAN_EOS;
man_descope(man, line, offs); man_descope(man, line, offs);
return(1); return 1;
} }
static int static int
man_pmacro(struct man *man, int ln, char *buf, int offs) man_pmacro(struct roff_man *man, int ln, char *buf, int offs)
{ {
struct man_node *n; struct roff_node *n;
const char *cp; const char *cp;
enum mant tok; int tok;
int i, ppos; int i, ppos;
int bline; int bline;
char mac[5]; char mac[5];
@ -457,12 +178,12 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
mac[i] = '\0'; mac[i] = '\0';
tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX; tok = (i > 0 && i < 4) ? man_hash_find(mac) : TOKEN_NONE;
if (tok == MAN_MAX) { if (tok == TOKEN_NONE) {
mandoc_msg(MANDOCERR_MACRO, man->parse, mandoc_msg(MANDOCERR_MACRO, man->parse,
ln, ppos, buf + ppos - 1); ln, ppos, buf + ppos - 1);
return(1); return 1;
} }
/* Skip a leading escape sequence or tab. */ /* Skip a leading escape sequence or tab. */
@ -511,9 +232,9 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
if (man->quick && tok == MAN_SH) { if (man->quick && tok == MAN_SH) {
n = man->last; n = man->last;
if (n->type == MAN_BODY && if (n->type == ROFFT_BODY &&
strcmp(n->prev->child->string, "NAME")) strcmp(n->prev->child->string, "NAME"))
return(2); return 2;
} }
/* /*
@ -524,20 +245,20 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
if ( ! bline || man->flags & MAN_ELINE || if ( ! bline || man->flags & MAN_ELINE ||
man_macros[tok].flags & MAN_NSCOPED) man_macros[tok].flags & MAN_NSCOPED)
return(1); return 1;
assert(man->flags & MAN_BLINE); assert(man->flags & MAN_BLINE);
man->flags &= ~MAN_BLINE; man->flags &= ~MAN_BLINE;
man_unscope(man, man->last->parent); man_unscope(man, man->last->parent);
man_body_alloc(man, ln, ppos, man->last->tok); roff_body_alloc(man, ln, ppos, man->last->tok);
return(1); return 1;
} }
void void
man_breakscope(struct man *man, enum mant tok) man_breakscope(struct roff_man *man, int tok)
{ {
struct man_node *n; struct roff_node *n;
/* /*
* An element next line scope is open, * An element next line scope is open,
@ -545,142 +266,104 @@ man_breakscope(struct man *man, enum mant tok)
* Delete the element that is being broken. * Delete the element that is being broken.
*/ */
if (man->flags & MAN_ELINE && (tok == MAN_MAX || if (man->flags & MAN_ELINE && (tok == TOKEN_NONE ||
! (man_macros[tok].flags & MAN_NSCOPED))) { ! (man_macros[tok].flags & MAN_NSCOPED))) {
n = man->last; n = man->last;
assert(n->type != MAN_TEXT); assert(n->type != ROFFT_TEXT);
if (man_macros[n->tok].flags & MAN_NSCOPED) if (man_macros[n->tok].flags & MAN_NSCOPED)
n = n->parent; n = n->parent;
mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
n->line, n->pos, "%s breaks %s", n->line, n->pos, "%s breaks %s",
tok == MAN_MAX ? "TS" : man_macronames[tok], tok == TOKEN_NONE ? "TS" : man_macronames[tok],
man_macronames[n->tok]); man_macronames[n->tok]);
man_node_delete(man, n); roff_node_delete(man, n);
man->flags &= ~MAN_ELINE; man->flags &= ~MAN_ELINE;
} }
/*
* Weird special case:
* Switching fill mode closes section headers.
*/
if (man->flags & MAN_BLINE &&
(tok == MAN_nf || tok == MAN_fi) &&
(man->last->tok == MAN_SH || man->last->tok == MAN_SS)) {
n = man->last;
man_unscope(man, n);
roff_body_alloc(man, n->line, n->pos, n->tok);
man->flags &= ~MAN_BLINE;
}
/* /*
* A block header next line scope is open, * A block header next line scope is open,
* and the new macro is not allowed inside block headers. * and the new macro is not allowed inside block headers.
* Delete the block that is being broken. * Delete the block that is being broken.
*/ */
if (man->flags & MAN_BLINE && (tok == MAN_MAX || if (man->flags & MAN_BLINE && (tok == TOKEN_NONE ||
man_macros[tok].flags & MAN_BSCOPE)) { man_macros[tok].flags & MAN_BSCOPE)) {
n = man->last; n = man->last;
if (n->type == MAN_TEXT) if (n->type == ROFFT_TEXT)
n = n->parent; n = n->parent;
if ( ! (man_macros[n->tok].flags & MAN_BSCOPE)) if ( ! (man_macros[n->tok].flags & MAN_BSCOPE))
n = n->parent; n = n->parent;
assert(n->type == MAN_HEAD); assert(n->type == ROFFT_HEAD);
n = n->parent; n = n->parent;
assert(n->type == MAN_BLOCK); assert(n->type == ROFFT_BLOCK);
assert(man_macros[n->tok].flags & MAN_SCOPED); assert(man_macros[n->tok].flags & MAN_SCOPED);
mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
n->line, n->pos, "%s breaks %s", n->line, n->pos, "%s breaks %s",
tok == MAN_MAX ? "TS" : man_macronames[tok], tok == TOKEN_NONE ? "TS" : man_macronames[tok],
man_macronames[n->tok]); man_macronames[n->tok]);
man_node_delete(man, n); roff_node_delete(man, n);
man->flags &= ~MAN_BLINE; man->flags &= ~MAN_BLINE;
} }
} }
/*
* 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 *man, struct man_node *n)
{
/* Adjust siblings. */
if (n->prev)
n->prev->next = n->next;
if (n->next)
n->next->prev = n->prev;
/* Adjust parent. */
if (n->parent) {
n->parent->nchild--;
if (n->parent->child == n)
n->parent->child = n->prev ? n->prev : n->next;
}
/* Adjust parse point, if applicable. */
if (man && man->last == n) {
/*XXX: this can occur when bailing from validation. */
/*assert(NULL == n->next);*/
if (n->prev) {
man->last = n->prev;
man->next = MAN_NEXT_SIBLING;
} else {
man->last = n->parent;
man->next = MAN_NEXT_CHILD;
}
}
if (man && man->first == n)
man->first = NULL;
}
const struct mparse * const struct mparse *
man_mparse(const struct man *man) man_mparse(const struct roff_man *man)
{ {
assert(man && man->parse); assert(man && man->parse);
return(man->parse); return man->parse;
} }
void void
man_deroff(char **dest, const struct man_node *n) man_state(struct roff_man *man, struct roff_node *n)
{ {
char *cp;
size_t sz;
if (n->type != MAN_TEXT) { switch(n->tok) {
for (n = n->child; n; n = n->next) case MAN_nf:
man_deroff(dest, n); case MAN_EX:
return; if (man->flags & MAN_LITERAL && ! (n->flags & MAN_VALID))
mandoc_msg(MANDOCERR_NF_SKIP, man->parse,
n->line, n->pos, "nf");
man->flags |= MAN_LITERAL;
break;
case MAN_fi:
case MAN_EE:
if ( ! (man->flags & MAN_LITERAL) &&
! (n->flags & MAN_VALID))
mandoc_msg(MANDOCERR_FI_SKIP, man->parse,
n->line, n->pos, "fi");
man->flags &= ~MAN_LITERAL;
break;
default:
break;
} }
man->last->flags |= MAN_VALID;
/* Skip leading whitespace and escape sequences. */ }
cp = n->string; void
while ('\0' != *cp) { man_validate(struct roff_man *man)
if ('\\' == *cp) { {
cp++;
mandoc_escape((const char **)&cp, NULL, NULL); man->last = man->first;
} else if (isspace((unsigned char)*cp)) man_node_validate(man);
cp++; man->flags &= ~MAN_LITERAL;
else
break;
}
/* Skip trailing whitespace. */
for (sz = strlen(cp); sz; sz--)
if (0 == isspace((unsigned char)cp[sz-1]))
break;
/* Skip empty strings. */
if (0 == sz)
return;
if (NULL == *dest) {
*dest = mandoc_strndup(cp, sz);
return;
}
mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp);
free(*dest);
*dest = cp;
} }

View File

@ -1,4 +1,4 @@
.\" $Id: man.cgi.8,v 1.11 2014/09/14 19:44:28 schwarze Exp $ .\" $Id: man.cgi.8,v 1.13 2015/11/05 20:55:41 schwarze Exp $
.\" .\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\" .\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: September 14 2014 $ .Dd $Mdocdate: November 5 2015 $
.Dt MAN.CGI 8 .Dt MAN.CGI 8
.Os .Os
.Sh NAME .Sh NAME
@ -161,6 +161,9 @@ database inside each manpath.
Configure your web server to execute CGI programs located in Configure your web server to execute CGI programs located in
.Pa /cgi-bin . .Pa /cgi-bin .
When using When using
.Ox
.Xr httpd 8
or
.Xr nginx 8 , .Xr nginx 8 ,
the the
.Xr slowcgi 8 .Xr slowcgi 8
@ -187,14 +190,8 @@ and to be specified without a trailing slash.
When not specified, the CSS files When not specified, the CSS files
are assumed to be in the document root. are assumed to be in the document root.
This is used in generated HTML code. This is used in generated HTML code.
.It Ev CUSTOMIZE_BEGIN
A HTML string to be inserted right after opening the
.Aq BODY
element.
.It Ev CUSTOMIZE_TITLE .It Ev CUSTOMIZE_TITLE
An ASCII string to be used for the HTML An ASCII string to be used for the HTML <TITLE> element.
.Aq TITLE
element.
.It Ev HTTP_HOST .It Ev HTTP_HOST
The FQDN of the (possibly virtual) host the HTTP server is running on. The FQDN of the (possibly virtual) host the HTTP server is running on.
This is used for This is used for
@ -349,15 +346,10 @@ Can be overridden by
The path to the server document root relative to the server root. The path to the server document root relative to the server root.
This is part of the web server configuration and not specific to This is part of the web server configuration and not specific to
.Nm . .Nm .
.It Pa /htdocs/man-cgi.css .It Pa /htdocs/mandoc.css
A style sheet for general
.Nm
styling, referenced from each generated HTML page.
.It Pa /htdocs/man.css
A style sheet for A style sheet for
.Xr mandoc 1 .Xr mandoc 1
HTML styling, referenced from each generated HTML page after HTML styling, referenced from each generated HTML page.
.Pa man-cgi.css .
.It Pa /man .It Pa /man
Default Default
.Nm .Nm
@ -376,6 +368,12 @@ or any character not contained in the
.Sx Restricted character set , .Sx Restricted character set ,
.Nm .Nm
reports an internal server error and exits without doing anything. reports an internal server error and exits without doing anything.
.It Pa /man/header.html
An optional file containing static HTML code to be inserted right
after opening the <BODY> element.
.It Pa /man/footer.html
An optional file containing static HTML code to be inserted right
before closing the <BODY> element.
.It Pa /man/OpenBSD-current/man1/mandoc.1 .It Pa /man/OpenBSD-current/man1/mandoc.1
An example An example
.Xr mdoc 7 .Xr mdoc 7

131
contrib/mdocml/man.conf.5 Normal file
View File

@ -0,0 +1,131 @@
.\" $Id: man.conf.5,v 1.3 2015/03/27 21:33:20 schwarze Exp $
.\"
.\" Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: March 27 2015 $
.Dt MAN.CONF 5
.Os
.Sh NAME
.Nm man.conf
.Nd configuration file for man
.Sh DESCRIPTION
This is the configuration file
for the
.Xr man 1 ,
.Xr apropos 1 ,
and
.Xr makewhatis 8
utilities.
Its presence, and all directives, are optional.
.Pp
This file is an ASCII text file.
Leading whitespace on lines, lines starting with
.Sq # ,
and blank lines are ignored.
Words are separated by whitespace.
The first word on each line is the name of a configuration directive.
.Pp
The following directives are supported:
.Bl -tag -width Ds
.It Ic manpath Ar path
Override the default search
.Ar path
for
.Xr man 1 ,
.Xr apropos 1 ,
and
.Xr makewhatis 8 .
It can be used multiple times to specify multiple paths,
with the order determining the manual page search order.
.Pp
Each path is a tree containing subdirectories
whose names consist of the strings
.Sq man
and/or
.Sq cat
followed by the names of sections, usually single digits.
The former are supposed to contain unformatted manual pages in
.Xr mdoc 7
and/or
.Xr man 7
format; file names should end with the name of the section
preceded by a dot.
The latter should contain preformatted manual pages;
file names should end with
.Ql .0 .
.Pp
Creating a
.Xr mandoc.db 5
database with
.Xr makewhatis 8
in each directory configured with
.Ic manpath
is recommended and necessary for
.Xr apropos 1
to work, but not strictly required for
.Xr man 1 .
.It Ic output Ar option Op Ar value
Configure the default value of an output option.
These directives are overridden by the
.Fl O
command line options of the same names.
For details, see the
.Xr mandoc 1
manual.
.Pp
.Bl -column fragment integer "ascii, utf8" -compact
.It Ar option Ta Ar value Ta used by Fl T Ta purpose
.It Ta Ta Ta
.It Ic fragment Ta none Ta Cm html Ta print only body
.It Ic includes Ta string Ta Cm html Ta path to header files
.It Ic indent Ta integer Ta Cm ascii , utf8 Ta left margin
.It Ic man Ta string Ta Cm html Ta path for Xr links
.It Ic paper Ta string Ta Cm ps , pdf Ta paper size
.It Ic style Ta string Ta Cm html Ta CSS file
.It Ic width Ta integer Ta Cm ascii , utf8 Ta right margin
.El
.It Ic _whatdb Ar path Ns Cm /whatis.db
This directive provides the same functionality as
.Ic manpath ,
but using a historic and misleading syntax.
It is kept for backward compatibility for now,
but will eventually be removed.
.El
.Sh FILES
.Pa /etc/man.conf
.Sh EXAMPLES
The following configuration file reproduces the defaults:
installing it is equivalent to not having a
.Nm
file at all.
.Bd -literal -offset indent
manpath /usr/share/man
manpath /usr/X11R6/man
manpath /usr/local/man
.Ed
.Sh SEE ALSO
.Xr apropos 1 ,
.Xr man 1 ,
.Xr makewhatis 8
.Sh HISTORY
A relatively complicated
.Nm
file format first appeared in
.Bx 4.3 Reno .
For
.Ox 5.8 ,
it was redesigned from scratch, aiming for simplicity.
.Sh AUTHORS
.An Ingo Schwarze Aq Mt schwarze@openbsd.org

View File

@ -1,116 +1,66 @@
/* $Id: man.h,v 1.69 2015/01/24 02:41:49 schwarze Exp $ */ /* $Id: man.h,v 1.77 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
enum mant { #define MAN_br 0
MAN_br = 0, #define MAN_TH 1
MAN_TH, #define MAN_SH 2
MAN_SH, #define MAN_SS 3
MAN_SS, #define MAN_TP 4
MAN_TP, #define MAN_LP 5
MAN_LP, #define MAN_PP 6
MAN_PP, #define MAN_P 7
MAN_P, #define MAN_IP 8
MAN_IP, #define MAN_HP 9
MAN_HP, #define MAN_SM 10
MAN_SM, #define MAN_SB 11
MAN_SB, #define MAN_BI 12
MAN_BI, #define MAN_IB 13
MAN_IB, #define MAN_BR 14
MAN_BR, #define MAN_RB 15
MAN_RB, #define MAN_R 16
MAN_R, #define MAN_B 17
MAN_B, #define MAN_I 18
MAN_I, #define MAN_IR 19
MAN_IR, #define MAN_RI 20
MAN_RI, #define MAN_sp 21
MAN_sp, #define MAN_nf 22
MAN_nf, #define MAN_fi 23
MAN_fi, #define MAN_RE 24
MAN_RE, #define MAN_RS 25
MAN_RS, #define MAN_DT 26
MAN_DT, #define MAN_UC 27
MAN_UC, #define MAN_PD 28
MAN_PD, #define MAN_AT 29
MAN_AT, #define MAN_in 30
MAN_in, #define MAN_ft 31
MAN_ft, #define MAN_OP 32
MAN_OP, #define MAN_EX 33
MAN_EX, #define MAN_EE 34
MAN_EE, #define MAN_UR 35
MAN_UR, #define MAN_UE 36
MAN_UE, #define MAN_ll 37
MAN_ll, #define MAN_MAX 38
MAN_MAX
};
enum man_type { /* Names of macros. */
MAN_TEXT,
MAN_ELEM,
MAN_ROOT,
MAN_BLOCK,
MAN_HEAD,
MAN_BODY,
MAN_TBL,
MAN_EQN
};
struct man_meta {
char *msec; /* `TH' section (1, 3p, etc.) */
char *date; /* `TH' normalised date */
char *vol; /* `TH' volume */
char *title; /* `TH' title (e.g., FOO) */
char *source; /* `TH' source (e.g., GNU) */
int hasbody; /* document is not empty */
};
struct man_node {
struct man_node *parent; /* parent AST node */
struct man_node *child; /* first child AST node */
struct man_node *next; /* sibling AST node */
struct man_node *prev; /* prior sibling AST node */
int nchild; /* number children */
int line;
int pos;
enum mant tok; /* tok or MAN__MAX if none */
int flags;
#define MAN_VALID (1 << 0) /* has been validated */
#define MAN_EOS (1 << 2) /* at sentence boundary */
#define MAN_LINE (1 << 3) /* first macro/text on line */
enum man_type type; /* AST node type */
char *string; /* TEXT node argument */
struct man_node *head; /* BLOCK node HEAD ptr */
struct man_node *tail; /* BLOCK node TAIL ptr */
struct man_node *body; /* BLOCK node BODY ptr */
const struct tbl_span *span; /* TBL */
const struct eqn *eqn; /* EQN */
int aux; /* decoded node data, type-dependent */
};
/* Names of macros. Index is enum mant. */
extern const char *const *man_macronames; extern const char *const *man_macronames;
__BEGIN_DECLS
struct man; struct roff_man;
const struct man_node *man_node(const struct man *); const struct mparse *man_mparse(const struct roff_man *);
const struct man_meta *man_meta(const struct man *); void man_validate(struct roff_man *);
const struct mparse *man_mparse(const struct man *);
void man_deroff(char **, const struct man_node *);
__END_DECLS

View File

@ -1,6 +1,7 @@
/* $Id: man_hash.c,v 1.29 2014/12/01 08:05:52 schwarze Exp $ */ /* $Id: man_hash.c,v 1.34 2015/10/06 18:32:19 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -23,6 +24,7 @@
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include "roff.h"
#include "man.h" #include "man.h"
#include "libman.h" #include "libman.h"
@ -46,18 +48,15 @@
static unsigned char table[26 * HASH_DEPTH]; static unsigned char table[26 * HASH_DEPTH];
/*
* XXX - this hash has global scope, so if intended for use as a library
* with multiple callers, it will need re-invocation protection.
*/
void void
man_hash_init(void) man_hash_init(void)
{ {
int i, j, x; int i, j, x;
memset(table, UCHAR_MAX, sizeof(table)); if (*table != '\0')
return;
assert(MAN_MAX < UCHAR_MAX); memset(table, UCHAR_MAX, sizeof(table));
for (i = 0; i < (int)MAN_MAX; i++) { for (i = 0; i < (int)MAN_MAX; i++) {
x = man_macronames[i][0]; x = man_macronames[i][0];
@ -76,27 +75,27 @@ man_hash_init(void)
} }
} }
enum mant int
man_hash_find(const char *tmp) man_hash_find(const char *tmp)
{ {
int x, y, i; int x, y, i;
enum mant tok; int tok;
if ('\0' == (x = tmp[0])) if ('\0' == (x = tmp[0]))
return(MAN_MAX); return TOKEN_NONE;
if ( ! (isalpha((unsigned char)x))) if ( ! (isalpha((unsigned char)x)))
return(MAN_MAX); return TOKEN_NONE;
HASH_ROW(x); HASH_ROW(x);
for (i = 0; i < HASH_DEPTH; i++) { for (i = 0; i < HASH_DEPTH; i++) {
if (UCHAR_MAX == (y = table[x + i])) if (UCHAR_MAX == (y = table[x + i]))
return(MAN_MAX); return TOKEN_NONE;
tok = (enum mant)y; tok = y;
if (0 == strcmp(tmp, man_macronames[tok])) if (0 == strcmp(tmp, man_macronames[tok]))
return(tok); return tok;
} }
return(MAN_MAX); return TOKEN_NONE;
} }

View File

@ -1,4 +1,4 @@
/* $Id: man_html.c,v 1.112 2015/03/03 21:11:34 schwarze Exp $ */ /* $Id: man_html.c,v 1.120 2016/01/08 17:48:09 schwarze Exp $ */
/* /*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -7,9 +7,9 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -26,6 +26,7 @@
#include <string.h> #include <string.h>
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "roff.h"
#include "man.h" #include "man.h"
#include "out.h" #include "out.h"
#include "html.h" #include "html.h"
@ -36,8 +37,8 @@
#define INDENT 5 #define INDENT 5
#define MAN_ARGS const struct man_meta *man, \ #define MAN_ARGS const struct roff_meta *man, \
const struct man_node *n, \ const struct roff_node *n, \
struct mhtml *mh, \ struct mhtml *mh, \
struct html *h struct html *h
@ -52,12 +53,11 @@ struct htmlman {
}; };
static void print_bvspace(struct html *, static void print_bvspace(struct html *,
const struct man_node *); const struct roff_node *);
static void print_man(MAN_ARGS);
static void print_man_head(MAN_ARGS); static void print_man_head(MAN_ARGS);
static void print_man_nodelist(MAN_ARGS); static void print_man_nodelist(MAN_ARGS);
static void print_man_node(MAN_ARGS); static void print_man_node(MAN_ARGS);
static int a2width(const struct man_node *, static int a2width(const struct roff_node *,
struct roffsu *); struct roffsu *);
static int man_B_pre(MAN_ARGS); static int man_B_pre(MAN_ARGS);
static int man_HP_pre(MAN_ARGS); static int man_HP_pre(MAN_ARGS);
@ -129,14 +129,14 @@ static const struct htmlman mans[MAN_MAX] = {
* first, print it. * first, print it.
*/ */
static void static void
print_bvspace(struct html *h, const struct man_node *n) print_bvspace(struct html *h, const struct roff_node *n)
{ {
if (n->body && n->body->child) if (n->body && n->body->child)
if (MAN_TBL == n->body->child->type) if (n->body->child->type == ROFFT_TBL)
return; return;
if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok) if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS)
if (NULL == n->prev) if (NULL == n->prev)
return; return;
@ -144,36 +144,31 @@ print_bvspace(struct html *h, const struct man_node *n)
} }
void void
html_man(void *arg, const struct man *man) html_man(void *arg, const struct roff_man *man)
{ {
struct mhtml mh; struct mhtml mh;
memset(&mh, 0, sizeof(struct mhtml));
print_man(man_meta(man), man_node(man), &mh, (struct html *)arg);
putchar('\n');
}
static void
print_man(MAN_ARGS)
{
struct tag *t, *tt;
struct htmlpair tag; struct htmlpair tag;
struct html *h;
struct tag *t, *tt;
memset(&mh, 0, sizeof(mh));
PAIR_CLASS_INIT(&tag, "mandoc"); PAIR_CLASS_INIT(&tag, "mandoc");
h = (struct html *)arg;
if ( ! (HTML_FRAGMENT & h->oflags)) { if ( ! (HTML_FRAGMENT & h->oflags)) {
print_gen_decls(h); print_gen_decls(h);
t = print_otag(h, TAG_HTML, 0, NULL); t = print_otag(h, TAG_HTML, 0, NULL);
tt = print_otag(h, TAG_HEAD, 0, NULL); tt = print_otag(h, TAG_HEAD, 0, NULL);
print_man_head(man, n, mh, h); print_man_head(&man->meta, man->first, &mh, h);
print_tagq(h, tt); print_tagq(h, tt);
print_otag(h, TAG_BODY, 0, NULL); print_otag(h, TAG_BODY, 0, NULL);
print_otag(h, TAG_DIV, 1, &tag); print_otag(h, TAG_DIV, 1, &tag);
} else } else
t = print_otag(h, TAG_DIV, 1, &tag); t = print_otag(h, TAG_DIV, 1, &tag);
print_man_nodelist(man, n, mh, h); print_man_nodelist(&man->meta, man->first, &mh, h);
print_tagq(h, t); print_tagq(h, t);
putchar('\n');
} }
static void static void
@ -208,10 +203,10 @@ print_man_node(MAN_ARGS)
t = h->tags.head; t = h->tags.head;
switch (n->type) { switch (n->type) {
case MAN_ROOT: case ROFFT_ROOT:
man_root_pre(man, n, mh, h); man_root_pre(man, n, mh, h);
break; break;
case MAN_TEXT: case ROFFT_TEXT:
if ('\0' == *n->string) { if ('\0' == *n->string) {
print_paragraph(h); print_paragraph(h);
return; return;
@ -222,12 +217,12 @@ print_man_node(MAN_ARGS)
print_otag(h, TAG_BR, 0, NULL); print_otag(h, TAG_BR, 0, NULL);
print_text(h, n->string); print_text(h, n->string);
return; return;
case MAN_EQN: case ROFFT_EQN:
if (n->flags & MAN_LINE) if (n->flags & MAN_LINE)
putchar('\n'); putchar('\n');
print_eqn(h, n->eqn); print_eqn(h, n->eqn);
break; break;
case MAN_TBL: case ROFFT_TBL:
/* /*
* This will take care of initialising all of the table * This will take care of initialising all of the table
* state data for the first table, then tearing it down * state data for the first table, then tearing it down
@ -266,10 +261,10 @@ print_man_node(MAN_ARGS)
print_stagq(h, t); print_stagq(h, t);
switch (n->type) { switch (n->type) {
case MAN_ROOT: case ROFFT_ROOT:
man_root_post(man, n, mh, h); man_root_post(man, n, mh, h);
break; break;
case MAN_EQN: case ROFFT_EQN:
break; break;
default: default:
if (mans[n->tok].post) if (mans[n->tok].post)
@ -279,15 +274,15 @@ print_man_node(MAN_ARGS)
} }
static int static int
a2width(const struct man_node *n, struct roffsu *su) a2width(const struct roff_node *n, struct roffsu *su)
{ {
if (MAN_TEXT != n->type) if (n->type != ROFFT_TEXT)
return(0); return 0;
if (a2roffsu(n->string, su, SCALE_EN)) if (a2roffsu(n->string, su, SCALE_EN))
return(1); return 1;
return(0); return 0;
} }
static void static void
@ -347,8 +342,8 @@ man_root_post(MAN_ARGS)
PAIR_CLASS_INIT(&tag, "foot-os"); PAIR_CLASS_INIT(&tag, "foot-os");
print_otag(h, TAG_TD, 1, &tag); print_otag(h, TAG_TD, 1, &tag);
if (man->source) if (man->os)
print_text(h, man->source); print_text(h, man->os);
print_tagq(h, t); print_tagq(h, t);
} }
@ -376,7 +371,7 @@ man_br_pre(MAN_ARGS)
/* So the div isn't empty: */ /* So the div isn't empty: */
print_text(h, "\\~"); print_text(h, "\\~");
return(0); return 0;
} }
static int static int
@ -384,22 +379,22 @@ man_SH_pre(MAN_ARGS)
{ {
struct htmlpair tag; struct htmlpair tag;
if (MAN_BLOCK == n->type) { if (n->type == ROFFT_BLOCK) {
mh->fl &= ~MANH_LITERAL; mh->fl &= ~MANH_LITERAL;
PAIR_CLASS_INIT(&tag, "section"); PAIR_CLASS_INIT(&tag, "section");
print_otag(h, TAG_DIV, 1, &tag); print_otag(h, TAG_DIV, 1, &tag);
return(1); return 1;
} else if (MAN_BODY == n->type) } else if (n->type == ROFFT_BODY)
return(1); return 1;
print_otag(h, TAG_H1, 0, NULL); print_otag(h, TAG_H1, 0, NULL);
return(1); return 1;
} }
static int static int
man_alt_pre(MAN_ARGS) man_alt_pre(MAN_ARGS)
{ {
const struct man_node *nn; const struct roff_node *nn;
int i, savelit; int i, savelit;
enum htmltag fp; enum htmltag fp;
struct tag *t; struct tag *t;
@ -432,7 +427,6 @@ man_alt_pre(MAN_ARGS)
break; break;
default: default:
abort(); abort();
/* NOTREACHED */
} }
if (i) if (i)
@ -450,7 +444,7 @@ man_alt_pre(MAN_ARGS)
if (savelit) if (savelit)
mh->fl |= MANH_LITERAL; mh->fl |= MANH_LITERAL;
return(0); return 0;
} }
static int static int
@ -460,7 +454,7 @@ man_SM_pre(MAN_ARGS)
print_otag(h, TAG_SMALL, 0, NULL); print_otag(h, TAG_SMALL, 0, NULL);
if (MAN_SB == n->tok) if (MAN_SB == n->tok)
print_otag(h, TAG_B, 0, NULL); print_otag(h, TAG_B, 0, NULL);
return(1); return 1;
} }
static int static int
@ -468,41 +462,41 @@ man_SS_pre(MAN_ARGS)
{ {
struct htmlpair tag; struct htmlpair tag;
if (MAN_BLOCK == n->type) { if (n->type == ROFFT_BLOCK) {
mh->fl &= ~MANH_LITERAL; mh->fl &= ~MANH_LITERAL;
PAIR_CLASS_INIT(&tag, "subsection"); PAIR_CLASS_INIT(&tag, "subsection");
print_otag(h, TAG_DIV, 1, &tag); print_otag(h, TAG_DIV, 1, &tag);
return(1); return 1;
} else if (MAN_BODY == n->type) } else if (n->type == ROFFT_BODY)
return(1); return 1;
print_otag(h, TAG_H2, 0, NULL); print_otag(h, TAG_H2, 0, NULL);
return(1); return 1;
} }
static int static int
man_PP_pre(MAN_ARGS) man_PP_pre(MAN_ARGS)
{ {
if (MAN_HEAD == n->type) if (n->type == ROFFT_HEAD)
return(0); return 0;
else if (MAN_BLOCK == n->type) else if (n->type == ROFFT_BLOCK)
print_bvspace(h, n); print_bvspace(h, n);
return(1); return 1;
} }
static int static int
man_IP_pre(MAN_ARGS) man_IP_pre(MAN_ARGS)
{ {
const struct man_node *nn; const struct roff_node *nn;
if (MAN_BODY == n->type) { if (n->type == ROFFT_BODY) {
print_otag(h, TAG_DD, 0, NULL); print_otag(h, TAG_DD, 0, NULL);
return(1); return 1;
} else if (MAN_HEAD != n->type) { } else if (n->type != ROFFT_HEAD) {
print_otag(h, TAG_DL, 0, NULL); print_otag(h, TAG_DL, 0, NULL);
return(1); return 1;
} }
/* FIXME: width specification. */ /* FIXME: width specification. */
@ -526,7 +520,7 @@ man_IP_pre(MAN_ARGS)
} }
} }
return(0); return 0;
} }
static int static int
@ -534,12 +528,12 @@ man_HP_pre(MAN_ARGS)
{ {
struct htmlpair tag[2]; struct htmlpair tag[2];
struct roffsu su; struct roffsu su;
const struct man_node *np; const struct roff_node *np;
if (MAN_HEAD == n->type) if (n->type == ROFFT_HEAD)
return(0); return 0;
else if (MAN_BLOCK != n->type) else if (n->type != ROFFT_BLOCK)
return(1); return 1;
np = n->head->child; np = n->head->child;
@ -555,7 +549,7 @@ man_HP_pre(MAN_ARGS)
PAIR_STYLE_INIT(&tag[0], h); PAIR_STYLE_INIT(&tag[0], h);
PAIR_CLASS_INIT(&tag[1], "spacer"); PAIR_CLASS_INIT(&tag[1], "spacer");
print_otag(h, TAG_DIV, 2, tag); print_otag(h, TAG_DIV, 2, tag);
return(1); return 1;
} }
static int static int
@ -584,7 +578,7 @@ man_OP_pre(MAN_ARGS)
print_stagq(h, tt); print_stagq(h, tt);
h->flags |= HTML_NOSPACE; h->flags |= HTML_NOSPACE;
print_text(h, "]"); print_text(h, "]");
return(0); return 0;
} }
static int static int
@ -592,7 +586,7 @@ man_B_pre(MAN_ARGS)
{ {
print_otag(h, TAG_B, 0, NULL); print_otag(h, TAG_B, 0, NULL);
return(1); return 1;
} }
static int static int
@ -600,7 +594,7 @@ man_I_pre(MAN_ARGS)
{ {
print_otag(h, TAG_I, 0, NULL); print_otag(h, TAG_I, 0, NULL);
return(1); return 1;
} }
static int static int
@ -613,7 +607,7 @@ man_literal_pre(MAN_ARGS)
} else } else
mh->fl |= MANH_LITERAL; mh->fl |= MANH_LITERAL;
return(0); return 0;
} }
static int static int
@ -621,14 +615,14 @@ man_in_pre(MAN_ARGS)
{ {
print_otag(h, TAG_BR, 0, NULL); print_otag(h, TAG_BR, 0, NULL);
return(0); return 0;
} }
static int static int
man_ign_pre(MAN_ARGS) man_ign_pre(MAN_ARGS)
{ {
return(0); return 0;
} }
static int static int
@ -637,10 +631,10 @@ man_RS_pre(MAN_ARGS)
struct htmlpair tag; struct htmlpair tag;
struct roffsu su; struct roffsu su;
if (MAN_HEAD == n->type) if (n->type == ROFFT_HEAD)
return(0); return 0;
else if (MAN_BODY == n->type) else if (n->type == ROFFT_BODY)
return(1); return 1;
SCALE_HS_INIT(&su, INDENT); SCALE_HS_INIT(&su, INDENT);
if (n->head->child) if (n->head->child)
@ -650,7 +644,7 @@ man_RS_pre(MAN_ARGS)
bufcat_su(h, "margin-left", &su); bufcat_su(h, "margin-left", &su);
PAIR_STYLE_INIT(&tag, h); PAIR_STYLE_INIT(&tag, h);
print_otag(h, TAG_DIV, 1, &tag); print_otag(h, TAG_DIV, 1, &tag);
return(1); return 1;
} }
static int static int
@ -659,19 +653,19 @@ man_UR_pre(MAN_ARGS)
struct htmlpair tag[2]; struct htmlpair tag[2];
n = n->child; n = n->child;
assert(MAN_HEAD == n->type); assert(n->type == ROFFT_HEAD);
if (n->nchild) { if (n->child != NULL) {
assert(MAN_TEXT == n->child->type); assert(n->child->type == ROFFT_TEXT);
PAIR_CLASS_INIT(&tag[0], "link-ext"); PAIR_CLASS_INIT(&tag[0], "link-ext");
PAIR_HREF_INIT(&tag[1], n->child->string); PAIR_HREF_INIT(&tag[1], n->child->string);
print_otag(h, TAG_A, 2, tag); print_otag(h, TAG_A, 2, tag);
} }
assert(MAN_BODY == n->next->type); assert(n->next->type == ROFFT_BODY);
if (n->next->nchild) if (n->next->child != NULL)
n = n->next; n = n->next;
print_man_nodelist(man, n->child, mh, h); print_man_nodelist(man, n->child, mh, h);
return(0); return 0;
} }

View File

@ -1,4 +1,4 @@
/* $Id: man_macro.c,v 1.98 2015/02/06 11:54:36 schwarze Exp $ */ /* $Id: man_macro.c,v 1.114 2016/01/08 17:48:09 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2012, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2012, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -8,9 +8,9 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -25,37 +25,27 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "man.h"
#include "mandoc.h" #include "mandoc.h"
#include "roff.h"
#include "man.h"
#include "libmandoc.h" #include "libmandoc.h"
#include "roff_int.h"
#include "libman.h" #include "libman.h"
enum rew {
REW_REWIND,
REW_NOHALT,
REW_HALT
};
static void blk_close(MACRO_PROT_ARGS); static void blk_close(MACRO_PROT_ARGS);
static void blk_exp(MACRO_PROT_ARGS); static void blk_exp(MACRO_PROT_ARGS);
static void blk_imp(MACRO_PROT_ARGS); static void blk_imp(MACRO_PROT_ARGS);
static void in_line_eoln(MACRO_PROT_ARGS); static void in_line_eoln(MACRO_PROT_ARGS);
static int man_args(struct man *, int, static int man_args(struct roff_man *, int,
int *, char *, char **); int *, char *, char **);
static void rew_scope(struct roff_man *, int);
static void rew_scope(enum man_type,
struct man *, enum mant);
static enum rew rew_dohalt(enum mant, enum man_type,
const struct man_node *);
static enum rew rew_block(enum mant, enum man_type,
const struct man_node *);
const struct man_macro __man_macros[MAN_MAX] = { const struct man_macro __man_macros[MAN_MAX] = {
{ in_line_eoln, MAN_NSCOPED }, /* br */ { in_line_eoln, MAN_NSCOPED }, /* br */
{ in_line_eoln, MAN_BSCOPE }, /* TH */ { in_line_eoln, MAN_BSCOPE }, /* TH */
{ blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */ { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */
{ blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */ { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */
{ blk_imp, MAN_BSCOPE | MAN_SCOPED | MAN_FSCOPED }, /* TP */ { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* TP */
{ blk_imp, MAN_BSCOPE }, /* LP */ { blk_imp, MAN_BSCOPE }, /* LP */
{ blk_imp, MAN_BSCOPE }, /* PP */ { blk_imp, MAN_BSCOPE }, /* PP */
{ blk_imp, MAN_BSCOPE }, /* P */ { blk_imp, MAN_BSCOPE }, /* P */
@ -73,20 +63,20 @@ const struct man_macro __man_macros[MAN_MAX] = {
{ in_line_eoln, 0 }, /* IR */ { in_line_eoln, 0 }, /* IR */
{ in_line_eoln, 0 }, /* RI */ { in_line_eoln, 0 }, /* RI */
{ in_line_eoln, MAN_NSCOPED }, /* sp */ { in_line_eoln, MAN_NSCOPED }, /* sp */
{ in_line_eoln, MAN_BSCOPE }, /* nf */ { in_line_eoln, MAN_NSCOPED }, /* nf */
{ in_line_eoln, MAN_BSCOPE }, /* fi */ { in_line_eoln, MAN_NSCOPED }, /* fi */
{ blk_close, MAN_BSCOPE }, /* RE */ { blk_close, MAN_BSCOPE }, /* RE */
{ blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* RS */ { blk_exp, MAN_BSCOPE }, /* RS */
{ in_line_eoln, 0 }, /* DT */ { in_line_eoln, 0 }, /* DT */
{ in_line_eoln, 0 }, /* UC */ { in_line_eoln, 0 }, /* UC */
{ in_line_eoln, 0 }, /* PD */ { in_line_eoln, MAN_NSCOPED }, /* PD */
{ in_line_eoln, 0 }, /* AT */ { in_line_eoln, 0 }, /* AT */
{ in_line_eoln, 0 }, /* in */ { in_line_eoln, 0 }, /* in */
{ in_line_eoln, 0 }, /* ft */ { in_line_eoln, 0 }, /* ft */
{ in_line_eoln, 0 }, /* OP */ { in_line_eoln, 0 }, /* OP */
{ in_line_eoln, MAN_BSCOPE }, /* EX */ { in_line_eoln, MAN_BSCOPE }, /* EX */
{ in_line_eoln, MAN_BSCOPE }, /* EE */ { in_line_eoln, MAN_BSCOPE }, /* EE */
{ blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */ { blk_exp, MAN_BSCOPE }, /* UR */
{ blk_close, MAN_BSCOPE }, /* UE */ { blk_close, MAN_BSCOPE }, /* UE */
{ in_line_eoln, 0 }, /* ll */ { in_line_eoln, 0 }, /* ll */
}; };
@ -95,9 +85,9 @@ const struct man_macro * const man_macros = __man_macros;
void void
man_unscope(struct man *man, const struct man_node *to) man_unscope(struct roff_man *man, const struct roff_node *to)
{ {
struct man_node *n; struct roff_node *n;
to = to->parent; to = to->parent;
n = man->last; n = man->last;
@ -115,17 +105,17 @@ man_unscope(struct man *man, const struct man_node *to)
if (man->flags & MAN_ELINE) if (man->flags & MAN_ELINE)
man->flags &= ~MAN_ELINE; man->flags &= ~MAN_ELINE;
else { else {
assert(n->type == MAN_HEAD); assert(n->type == ROFFT_HEAD);
n = n->parent; n = n->parent;
man->flags &= ~MAN_BLINE; man->flags &= ~MAN_BLINE;
} }
man->last = n; man->last = n;
n = n->parent; n = n->parent;
man_node_delete(man, man->last); roff_node_delete(man, man->last);
continue; continue;
} }
if (n->type == MAN_BLOCK && if (n->type == ROFFT_BLOCK &&
man_macros[n->tok].flags & MAN_EXPLICIT) man_macros[n->tok].fp == blk_exp)
mandoc_msg(MANDOCERR_BLK_NOEND, mandoc_msg(MANDOCERR_BLK_NOEND,
man->parse, n->line, n->pos, man->parse, n->line, n->pos,
man_macronames[n->tok]); man_macronames[n->tok]);
@ -140,7 +130,7 @@ man_unscope(struct man *man, const struct man_node *to)
man->last = n; man->last = n;
n = n->parent; n = n->parent;
man_valid_post(man); man->last->flags |= MAN_VALID;
} }
/* /*
@ -151,90 +141,7 @@ man_unscope(struct man *man, const struct man_node *to)
*/ */
man->next = (man->last == to) ? man->next = (man->last == to) ?
MAN_NEXT_CHILD : MAN_NEXT_SIBLING; ROFF_NEXT_CHILD : ROFF_NEXT_SIBLING;
}
static enum rew
rew_block(enum mant ntok, enum man_type type, const struct man_node *n)
{
if (type == MAN_BLOCK && ntok == n->parent->tok &&
n->parent->type == MAN_BODY)
return(REW_REWIND);
return(ntok == n->tok ? REW_HALT : REW_NOHALT);
}
/*
* There are three scope levels: scoped to the root (all), scoped to the
* section (all less sections), and scoped to subsections (all less
* sections and subsections).
*/
static enum rew
rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
{
enum rew c;
/* We cannot progress beyond the root ever. */
if (MAN_ROOT == n->type)
return(REW_HALT);
assert(n->parent);
/* Normal nodes shouldn't go to the level of the root. */
if (MAN_ROOT == n->parent->type)
return(REW_REWIND);
/* Already-validated nodes should be closed out. */
if (MAN_VALID & n->flags)
return(REW_NOHALT);
/* First: rewind to ourselves. */
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:
* section, sub-section, etc.
*/
switch (tok) {
case MAN_SH:
break;
case MAN_SS:
/* Rewind to a section, if a block. */
if (REW_NOHALT != (c = rew_block(MAN_SH, type, 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);
/* Rewind to a section, if a block. */
if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
return(c);
break;
default:
/* Rewind to an offsetter, if a block. */
if (REW_NOHALT != (c = rew_block(MAN_RS, type, n)))
return(c);
/* Rewind to a subsection, if a block. */
if (REW_NOHALT != (c = rew_block(MAN_SS, type, n)))
return(c);
/* Rewind to a section, if a block. */
if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
return(c);
break;
}
return(REW_NOHALT);
} }
/* /*
@ -243,30 +150,40 @@ 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. * scopes. When a scope is closed, it must be validated and actioned.
*/ */
static void static void
rew_scope(enum man_type type, struct man *man, enum mant tok) rew_scope(struct roff_man *man, int tok)
{ {
struct man_node *n; struct roff_node *n;
enum rew c;
for (n = man->last; n; n = n->parent) { /* Preserve empty paragraphs before RS. */
/*
* Whether we should stop immediately (REW_HALT), stop n = man->last;
* and rewind until this point (REW_REWIND), or keep if (tok == MAN_RS && n->child == NULL &&
* rewinding (REW_NOHALT). (n->tok == MAN_P || n->tok == MAN_PP || n->tok == MAN_LP))
*/ return;
c = rew_dohalt(tok, type, n);
if (REW_HALT == c) for (;;) {
if (n->type == ROFFT_ROOT)
return; return;
if (REW_REWIND == c) if (n->flags & MAN_VALID) {
break; n = n->parent;
continue;
}
if (n->type != ROFFT_BLOCK) {
if (n->parent->type == ROFFT_ROOT) {
man_unscope(man, n);
return;
} else {
n = n->parent;
continue;
}
}
if (tok != MAN_SH && (n->tok == MAN_SH ||
(tok != MAN_SS && (n->tok == MAN_SS ||
man_macros[n->tok].fp == blk_exp))))
return;
man_unscope(man, n);
n = man->last;
} }
/*
* Rewind until the current point. Warn if we're a roff
* instruction that's mowing over explicit scopes.
*/
man_unscope(man, n);
} }
@ -276,8 +193,8 @@ rew_scope(enum man_type type, struct man *man, enum mant tok)
void void
blk_close(MACRO_PROT_ARGS) blk_close(MACRO_PROT_ARGS)
{ {
enum mant ntok; int ntok;
const struct man_node *nn; const struct roff_node *nn;
char *p; char *p;
int nrew, target; int nrew, target;
@ -288,7 +205,7 @@ blk_close(MACRO_PROT_ARGS)
if ( ! man_args(man, line, pos, buf, &p)) if ( ! man_args(man, line, pos, buf, &p))
break; break;
for (nn = man->last->parent; nn; nn = nn->parent) for (nn = man->last->parent; nn; nn = nn->parent)
if (nn->tok == ntok && nn->type == MAN_BLOCK) if (nn->tok == ntok && nn->type == ROFFT_BLOCK)
nrew++; nrew++;
target = strtol(p, &p, 10); target = strtol(p, &p, 10);
if (*p != '\0') if (*p != '\0')
@ -308,17 +225,16 @@ blk_close(MACRO_PROT_ARGS)
break; break;
default: default:
abort(); abort();
/* NOTREACHED */
} }
for (nn = man->last->parent; nn; nn = nn->parent) for (nn = man->last->parent; nn; nn = nn->parent)
if (nn->tok == ntok && nn->type == MAN_BLOCK && ! --nrew) if (nn->tok == ntok && nn->type == ROFFT_BLOCK && ! --nrew)
break; break;
if (nn == NULL) { if (nn == NULL) {
mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse, mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
line, ppos, man_macronames[tok]); line, ppos, man_macronames[tok]);
rew_scope(MAN_BLOCK, man, MAN_PP); rew_scope(man, MAN_PP);
} else { } else {
line = man->last->line; line = man->last->line;
ppos = man->last->pos; ppos = man->last->pos;
@ -337,18 +253,17 @@ blk_close(MACRO_PROT_ARGS)
void void
blk_exp(MACRO_PROT_ARGS) blk_exp(MACRO_PROT_ARGS)
{ {
struct man_node *head; struct roff_node *head;
char *p; char *p;
int la; int la;
rew_scope(MAN_BLOCK, man, tok); rew_scope(man, tok);
man_block_alloc(man, line, ppos, tok); roff_block_alloc(man, line, ppos, tok);
man_head_alloc(man, line, ppos, tok); head = roff_head_alloc(man, line, ppos, tok);
head = man->last;
la = *pos; la = *pos;
if (man_args(man, line, pos, buf, &p)) if (man_args(man, line, pos, buf, &p))
man_word_alloc(man, line, la, p); roff_word_alloc(man, line, la, p);
if (buf[*pos] != '\0') if (buf[*pos] != '\0')
mandoc_vmsg(MANDOCERR_ARG_EXCESS, mandoc_vmsg(MANDOCERR_ARG_EXCESS,
@ -356,12 +271,12 @@ blk_exp(MACRO_PROT_ARGS)
man_macronames[tok], buf + *pos); man_macronames[tok], buf + *pos);
man_unscope(man, head); man_unscope(man, head);
man_body_alloc(man, line, ppos, tok); roff_body_alloc(man, line, ppos, tok);
} }
/* /*
* Parse an implicit-block macro. These contain a MAN_HEAD and a * Parse an implicit-block macro. These contain a ROFFT_HEAD and a
* MAN_BODY contained within a MAN_BLOCK. Rules for closing out other * ROFFT_BODY contained within a ROFFT_BLOCK. Rules for closing out other
* scopes, such as `SH' closing out an `SS', are defined in the rew * scopes, such as `SH' closing out an `SS', are defined in the rew
* routines. * routines.
*/ */
@ -370,13 +285,13 @@ blk_imp(MACRO_PROT_ARGS)
{ {
int la; int la;
char *p; char *p;
struct man_node *n; struct roff_node *n;
rew_scope(MAN_BODY, man, tok); rew_scope(man, tok);
rew_scope(MAN_BLOCK, man, tok); n = roff_block_alloc(man, line, ppos, tok);
man_block_alloc(man, line, ppos, tok); if (n->tok == MAN_SH || n->tok == MAN_SS)
man_head_alloc(man, line, ppos, tok); man->flags &= ~MAN_LITERAL;
n = man->last; n = roff_head_alloc(man, line, ppos, tok);
/* Add line arguments. */ /* Add line arguments. */
@ -384,23 +299,25 @@ blk_imp(MACRO_PROT_ARGS)
la = *pos; la = *pos;
if ( ! man_args(man, line, pos, buf, &p)) if ( ! man_args(man, line, pos, buf, &p))
break; break;
man_word_alloc(man, line, la, p); roff_word_alloc(man, line, la, p);
} }
/* Close out head and open body (unless MAN_SCOPE). */ /*
* For macros having optional next-line scope,
* keep the head open if there were no arguments.
* For `TP', always keep the head open.
*/
if (man_macros[tok].flags & MAN_SCOPED) { if (man_macros[tok].flags & MAN_SCOPED &&
/* If we're forcing scope (`TP'), keep it open. */ (tok == MAN_TP || n == man->last)) {
if (man_macros[tok].flags & MAN_FSCOPED) { man->flags |= MAN_BLINE;
man->flags |= MAN_BLINE; return;
return;
} else if (n == man->last) {
man->flags |= MAN_BLINE;
return;
}
} }
rew_scope(MAN_HEAD, man, tok);
man_body_alloc(man, line, ppos, tok); /* Close out the head and open the body. */
man_unscope(man, n);
roff_body_alloc(man, line, ppos, tok);
} }
void void
@ -408,9 +325,9 @@ in_line_eoln(MACRO_PROT_ARGS)
{ {
int la; int la;
char *p; char *p;
struct man_node *n; struct roff_node *n;
man_elem_alloc(man, line, ppos, tok); roff_elem_alloc(man, line, ppos, tok);
n = man->last; n = man->last;
for (;;) { for (;;) {
@ -432,10 +349,10 @@ in_line_eoln(MACRO_PROT_ARGS)
if ( ! man_args(man, line, pos, buf, &p)) if ( ! man_args(man, line, pos, buf, &p))
break; break;
if (man_macros[tok].flags & MAN_JOIN && if (man_macros[tok].flags & MAN_JOIN &&
man->last->type == MAN_TEXT) man->last->type == ROFFT_TEXT)
man_word_append(man, p); roff_word_append(man, p);
else else
man_word_alloc(man, line, la, p); roff_word_alloc(man, line, la, p);
} }
/* /*
@ -459,43 +376,28 @@ in_line_eoln(MACRO_PROT_ARGS)
return; return;
} }
assert(man->last->type != MAN_ROOT); assert(man->last->type != ROFFT_ROOT);
man->next = MAN_NEXT_SIBLING; man->next = ROFF_NEXT_SIBLING;
/* /* Rewind our element scope. */
* Rewind our element scope. Note that when TH is pruned, we'll
* be back at the root, so make sure that we don't clobber as
* its sibling.
*/
for ( ; man->last; man->last = man->last->parent) { for ( ; man->last; man->last = man->last->parent) {
man_state(man, man->last);
if (man->last == n) if (man->last == n)
break; break;
if (man->last->type == MAN_ROOT)
break;
man_valid_post(man);
} }
assert(man->last);
/*
* Same here regarding whether we're back at the root.
*/
if (man->last->type != MAN_ROOT)
man_valid_post(man);
} }
void void
man_macroend(struct man *man) man_endparse(struct roff_man *man)
{ {
man_unscope(man, man->first); man_unscope(man, man->first);
man->flags &= ~MAN_LITERAL;
} }
static int static int
man_args(struct man *man, int line, int *pos, char *buf, char **v) man_args(struct roff_man *man, int line, int *pos, char *buf, char **v)
{ {
char *start; char *start;
@ -504,8 +406,8 @@ man_args(struct man *man, int line, int *pos, char *buf, char **v)
assert(' ' != *start); assert(' ' != *start);
if ('\0' == *start) if ('\0' == *start)
return(0); return 0;
*v = mandoc_getarg(man->parse, v, line, pos); *v = mandoc_getarg(man->parse, v, line, pos);
return(1); return 1;
} }

View File

@ -1,4 +1,4 @@
/* $Id: man_term.c,v 1.169 2015/03/06 15:48:52 schwarze Exp $ */ /* $Id: man_term.c,v 1.187 2016/01/08 17:48:09 schwarze Exp $ */
/* /*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
@ -7,9 +7,9 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -26,10 +26,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "out.h" #include "mandoc.h"
#include "roff.h"
#include "man.h" #include "man.h"
#include "out.h"
#include "term.h" #include "term.h"
#include "main.h" #include "main.h"
@ -47,8 +48,8 @@ struct mtermp {
#define DECL_ARGS struct termp *p, \ #define DECL_ARGS struct termp *p, \
struct mtermp *mt, \ struct mtermp *mt, \
struct man_node *n, \ struct roff_node *n, \
const struct man_meta *meta const struct roff_meta *meta
struct termact { struct termact {
int (*pre)(DECL_ARGS); int (*pre)(DECL_ARGS);
@ -59,10 +60,12 @@ struct termact {
static void print_man_nodelist(DECL_ARGS); static void print_man_nodelist(DECL_ARGS);
static void print_man_node(DECL_ARGS); static void print_man_node(DECL_ARGS);
static void print_man_head(struct termp *, const void *); static void print_man_head(struct termp *,
static void print_man_foot(struct termp *, const void *); const struct roff_meta *);
static void print_man_foot(struct termp *,
const struct roff_meta *);
static void print_bvspace(struct termp *, static void print_bvspace(struct termp *,
const struct man_node *, int); const struct roff_node *, int);
static int pre_B(DECL_ARGS); static int pre_B(DECL_ARGS);
static int pre_HP(DECL_ARGS); static int pre_HP(DECL_ARGS);
@ -135,36 +138,32 @@ static const struct termact termacts[MAN_MAX] = {
void void
terminal_man(void *arg, const struct man *man) terminal_man(void *arg, const struct roff_man *man)
{ {
struct termp *p; struct termp *p;
const struct man_meta *meta; struct roff_node *n;
struct man_node *n;
struct mtermp mt; struct mtermp mt;
p = (struct termp *)arg; p = (struct termp *)arg;
p->overstep = 0; p->overstep = 0;
p->rmargin = p->maxrmargin = p->defrmargin; p->rmargin = p->maxrmargin = p->defrmargin;
p->tabwidth = term_len(p, 5); p->tabwidth = term_len(p, 5);
n = man_node(man)->child;
meta = man_meta(man);
memset(&mt, 0, sizeof(struct mtermp)); memset(&mt, 0, sizeof(struct mtermp));
mt.lmargin[mt.lmargincur] = term_len(p, p->defindent); mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
mt.offset = term_len(p, p->defindent); mt.offset = term_len(p, p->defindent);
mt.pardist = 1; mt.pardist = 1;
n = man->first->child;
if (p->synopsisonly) { if (p->synopsisonly) {
while (n != NULL) { while (n != NULL) {
if (n->tok == MAN_SH && if (n->tok == MAN_SH &&
n->child->child->type == MAN_TEXT && n->child->child->type == ROFFT_TEXT &&
!strcmp(n->child->child->string, "SYNOPSIS")) { !strcmp(n->child->child->string, "SYNOPSIS")) {
if (n->child->next->child != NULL) if (n->child->next->child != NULL)
print_man_nodelist(p, &mt, print_man_nodelist(p, &mt,
n->child->next->child, meta); n->child->next->child,
&man->meta);
term_newln(p); term_newln(p);
break; break;
} }
@ -173,10 +172,10 @@ terminal_man(void *arg, const struct man *man)
} else { } else {
if (p->defindent == 0) if (p->defindent == 0)
p->defindent = 7; p->defindent = 7;
term_begin(p, print_man_head, print_man_foot, meta); term_begin(p, print_man_head, print_man_foot, &man->meta);
p->flags |= TERMP_NOSPACE; p->flags |= TERMP_NOSPACE;
if (n != NULL) if (n != NULL)
print_man_nodelist(p, &mt, n, meta); print_man_nodelist(p, &mt, n, &man->meta);
term_end(p); term_end(p);
} }
} }
@ -190,17 +189,17 @@ terminal_man(void *arg, const struct man *man)
* first, print it. * first, print it.
*/ */
static void static void
print_bvspace(struct termp *p, const struct man_node *n, int pardist) print_bvspace(struct termp *p, const struct roff_node *n, int pardist)
{ {
int i; int i;
term_newln(p); term_newln(p);
if (n->body && n->body->child) if (n->body && n->body->child)
if (MAN_TBL == n->body->child->type) if (n->body->child->type == ROFFT_TBL)
return; return;
if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok) if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS)
if (NULL == n->prev) if (NULL == n->prev)
return; return;
@ -213,15 +212,15 @@ static int
pre_ign(DECL_ARGS) pre_ign(DECL_ARGS)
{ {
return(0); return 0;
} }
static int static int
pre_ll(DECL_ARGS) pre_ll(DECL_ARGS)
{ {
term_setwidth(p, n->nchild ? n->child->string : NULL); term_setwidth(p, n->child != NULL ? n->child->string : NULL);
return(0); return 0;
} }
static int static int
@ -229,7 +228,7 @@ pre_I(DECL_ARGS)
{ {
term_fontrepl(p, TERMFONT_UNDER); term_fontrepl(p, TERMFONT_UNDER);
return(1); return 1;
} }
static int static int
@ -256,7 +255,7 @@ pre_literal(DECL_ARGS)
p->flags |= TERMP_NOSPACE; p->flags |= TERMP_NOSPACE;
} }
return(0); return 0;
} }
static int static int
@ -267,19 +266,19 @@ pre_PD(DECL_ARGS)
n = n->child; n = n->child;
if (n == NULL) { if (n == NULL) {
mt->pardist = 1; mt->pardist = 1;
return(0); return 0;
} }
assert(MAN_TEXT == n->type); assert(n->type == ROFFT_TEXT);
if (a2roffsu(n->string, &su, SCALE_VS)) if (a2roffsu(n->string, &su, SCALE_VS))
mt->pardist = term_vspan(p, &su); mt->pardist = term_vspan(p, &su);
return(0); return 0;
} }
static int static int
pre_alternate(DECL_ARGS) pre_alternate(DECL_ARGS)
{ {
enum termfont font[2]; enum termfont font[2];
struct man_node *nn; struct roff_node *nn;
int savelit, i; int savelit, i;
switch (n->tok) { switch (n->tok) {
@ -318,12 +317,15 @@ pre_alternate(DECL_ARGS)
term_fontrepl(p, font[i]); term_fontrepl(p, font[i]);
if (savelit && NULL == nn->next) if (savelit && NULL == nn->next)
mt->fl |= MANT_LITERAL; mt->fl |= MANT_LITERAL;
print_man_node(p, mt, nn, meta); assert(nn->type == ROFFT_TEXT);
term_word(p, nn->string);
if (nn->flags & MAN_EOS)
p->flags |= TERMP_SENTENCE;
if (nn->next) if (nn->next)
p->flags |= TERMP_NOSPACE; p->flags |= TERMP_NOSPACE;
} }
return(0); return 0;
} }
static int static int
@ -331,7 +333,7 @@ pre_B(DECL_ARGS)
{ {
term_fontrepl(p, TERMFONT_BOLD); term_fontrepl(p, TERMFONT_BOLD);
return(1); return 1;
} }
static int static int
@ -353,7 +355,7 @@ pre_OP(DECL_ARGS)
term_fontrepl(p, TERMFONT_NONE); term_fontrepl(p, TERMFONT_NONE);
p->flags |= TERMP_NOSPACE; p->flags |= TERMP_NOSPACE;
term_word(p, "]"); term_word(p, "]");
return(0); return 0;
} }
static int static int
@ -363,20 +365,17 @@ pre_ft(DECL_ARGS)
if (NULL == n->child) { if (NULL == n->child) {
term_fontlast(p); term_fontlast(p);
return(0); return 0;
} }
cp = n->child->string; cp = n->child->string;
switch (*cp) { switch (*cp) {
case '4': case '4':
/* FALLTHROUGH */
case '3': case '3':
/* FALLTHROUGH */
case 'B': case 'B':
term_fontrepl(p, TERMFONT_BOLD); term_fontrepl(p, TERMFONT_BOLD);
break; break;
case '2': case '2':
/* FALLTHROUGH */
case 'I': case 'I':
term_fontrepl(p, TERMFONT_UNDER); term_fontrepl(p, TERMFONT_UNDER);
break; break;
@ -384,16 +383,14 @@ pre_ft(DECL_ARGS)
term_fontlast(p); term_fontlast(p);
break; break;
case '1': case '1':
/* FALLTHROUGH */
case 'C': case 'C':
/* FALLTHROUGH */
case 'R': case 'R':
term_fontrepl(p, TERMFONT_NONE); term_fontrepl(p, TERMFONT_NONE);
break; break;
default: default:
break; break;
} }
return(0); return 0;
} }
static int static int
@ -408,7 +405,7 @@ pre_in(DECL_ARGS)
if (NULL == n->child) { if (NULL == n->child) {
p->offset = mt->offset; p->offset = mt->offset;
return(0); return 0;
} }
cp = n->child->string; cp = n->child->string;
@ -422,9 +419,9 @@ pre_in(DECL_ARGS)
cp--; cp--;
if ( ! a2roffsu(++cp, &su, SCALE_EN)) if ( ! a2roffsu(++cp, &su, SCALE_EN))
return(0); return 0;
v = term_hspan(p, &su); v = (term_hspan(p, &su) + 11) / 24;
if (less < 0) if (less < 0)
p->offset -= p->offset > v ? v : p->offset; p->offset -= p->offset > v ? v : p->offset;
@ -435,7 +432,7 @@ pre_in(DECL_ARGS)
if (p->offset > SHRT_MAX) if (p->offset > SHRT_MAX)
p->offset = term_len(p, p->defindent); p->offset = term_len(p, p->defindent);
return(0); return 0;
} }
static int static int
@ -447,16 +444,11 @@ pre_sp(DECL_ARGS)
if ((NULL == n->prev && n->parent)) { if ((NULL == n->prev && n->parent)) {
switch (n->parent->tok) { switch (n->parent->tok) {
case MAN_SH: case MAN_SH:
/* FALLTHROUGH */
case MAN_SS: case MAN_SS:
/* FALLTHROUGH */
case MAN_PP: case MAN_PP:
/* FALLTHROUGH */
case MAN_LP: case MAN_LP:
/* FALLTHROUGH */
case MAN_P: case MAN_P:
/* FALLTHROUGH */ return 0;
return(0);
default: default:
break; break;
} }
@ -480,24 +472,35 @@ pre_sp(DECL_ARGS)
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
term_vspace(p); term_vspace(p);
return(0); /*
* Handle an explicit break request in the same way
* as an overflowing line.
*/
if (p->flags & TERMP_BRIND) {
p->offset = p->rmargin;
p->rmargin = p->maxrmargin;
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
}
return 0;
} }
static int static int
pre_HP(DECL_ARGS) pre_HP(DECL_ARGS)
{ {
struct roffsu su; struct roffsu su;
const struct man_node *nn; const struct roff_node *nn;
int len; int len;
switch (n->type) { switch (n->type) {
case MAN_BLOCK: case ROFFT_BLOCK:
print_bvspace(p, n, mt->pardist); print_bvspace(p, n, mt->pardist);
return(1); return 1;
case MAN_BODY: case ROFFT_BODY:
break; break;
default: default:
return(0); return 0;
} }
if ( ! (MANT_LITERAL & mt->fl)) { if ( ! (MANT_LITERAL & mt->fl)) {
@ -509,7 +512,7 @@ pre_HP(DECL_ARGS)
if ((nn = n->parent->head->child) != NULL && if ((nn = n->parent->head->child) != NULL &&
a2roffsu(nn->string, &su, SCALE_EN)) { a2roffsu(nn->string, &su, SCALE_EN)) {
len = term_hspan(p, &su); len = term_hspan(p, &su) / 24;
if (len < 0 && (size_t)(-len) > mt->offset) if (len < 0 && (size_t)(-len) > mt->offset)
len = -mt->offset; len = -mt->offset;
else if (len > SHRT_MAX) else if (len > SHRT_MAX)
@ -520,7 +523,7 @@ pre_HP(DECL_ARGS)
p->offset = mt->offset; p->offset = mt->offset;
p->rmargin = mt->offset + len; p->rmargin = mt->offset + len;
return(1); return 1;
} }
static void static void
@ -528,8 +531,19 @@ post_HP(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_BODY: case ROFFT_BODY:
term_newln(p); term_newln(p);
/*
* Compatibility with a groff bug.
* The .HP macro uses the undocumented .tag request
* which causes a line break and cancels no-space
* mode even if there isn't any output.
*/
if (n->child == NULL)
term_vspace(p);
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
p->trailspace = 0; p->trailspace = 0;
p->offset = mt->offset; p->offset = mt->offset;
@ -545,7 +559,7 @@ pre_PP(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_BLOCK: case ROFFT_BLOCK:
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
print_bvspace(p, n, mt->pardist); print_bvspace(p, n, mt->pardist);
break; break;
@ -554,36 +568,36 @@ pre_PP(DECL_ARGS)
break; break;
} }
return(MAN_HEAD != n->type); return n->type != ROFFT_HEAD;
} }
static int static int
pre_IP(DECL_ARGS) pre_IP(DECL_ARGS)
{ {
struct roffsu su; struct roffsu su;
const struct man_node *nn; const struct roff_node *nn;
int len, savelit; int len, savelit;
switch (n->type) { switch (n->type) {
case MAN_BODY: case ROFFT_BODY:
p->flags |= TERMP_NOSPACE; p->flags |= TERMP_NOSPACE;
break; break;
case MAN_HEAD: case ROFFT_HEAD:
p->flags |= TERMP_NOBREAK; p->flags |= TERMP_NOBREAK;
p->trailspace = 1; p->trailspace = 1;
break; break;
case MAN_BLOCK: case ROFFT_BLOCK:
print_bvspace(p, n, mt->pardist); print_bvspace(p, n, mt->pardist);
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
return(1); return 1;
} }
/* Calculate the offset from the optional second argument. */ /* Calculate the offset from the optional second argument. */
if ((nn = n->parent->head->child) != NULL && if ((nn = n->parent->head->child) != NULL &&
(nn = nn->next) != NULL && (nn = nn->next) != NULL &&
a2roffsu(nn->string, &su, SCALE_EN)) { a2roffsu(nn->string, &su, SCALE_EN)) {
len = term_hspan(p, &su); len = term_hspan(p, &su) / 24;
if (len < 0 && (size_t)(-len) > mt->offset) if (len < 0 && (size_t)(-len) > mt->offset)
len = -mt->offset; len = -mt->offset;
else if (len > SHRT_MAX) else if (len > SHRT_MAX)
@ -593,7 +607,7 @@ pre_IP(DECL_ARGS)
len = mt->lmargin[mt->lmargincur]; len = mt->lmargin[mt->lmargincur];
switch (n->type) { switch (n->type) {
case MAN_HEAD: case ROFFT_HEAD:
p->offset = mt->offset; p->offset = mt->offset;
p->rmargin = mt->offset + len; p->rmargin = mt->offset + len;
@ -606,8 +620,8 @@ pre_IP(DECL_ARGS)
if (savelit) if (savelit)
mt->fl |= MANT_LITERAL; mt->fl |= MANT_LITERAL;
return(0); return 0;
case MAN_BODY: case ROFFT_BODY:
p->offset = mt->offset + len; p->offset = mt->offset + len;
p->rmargin = p->maxrmargin; p->rmargin = p->maxrmargin;
break; break;
@ -615,7 +629,7 @@ pre_IP(DECL_ARGS)
break; break;
} }
return(1); return 1;
} }
static void static void
@ -623,13 +637,13 @@ post_IP(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_HEAD: case ROFFT_HEAD:
term_flushln(p); term_flushln(p);
p->flags &= ~TERMP_NOBREAK; p->flags &= ~TERMP_NOBREAK;
p->trailspace = 0; p->trailspace = 0;
p->rmargin = p->maxrmargin; p->rmargin = p->maxrmargin;
break; break;
case MAN_BODY: case ROFFT_BODY:
term_newln(p); term_newln(p);
p->offset = mt->offset; p->offset = mt->offset;
break; break;
@ -642,22 +656,22 @@ static int
pre_TP(DECL_ARGS) pre_TP(DECL_ARGS)
{ {
struct roffsu su; struct roffsu su;
struct man_node *nn; struct roff_node *nn;
int len, savelit; int len, savelit;
switch (n->type) { switch (n->type) {
case MAN_HEAD: case ROFFT_HEAD:
p->flags |= TERMP_NOBREAK; p->flags |= TERMP_NOBREAK | TERMP_BRTRSP;
p->trailspace = 1; p->trailspace = 1;
break; break;
case MAN_BODY: case ROFFT_BODY:
p->flags |= TERMP_NOSPACE; p->flags |= TERMP_NOSPACE;
break; break;
case MAN_BLOCK: case ROFFT_BLOCK:
print_bvspace(p, n, mt->pardist); print_bvspace(p, n, mt->pardist);
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
return(1); return 1;
} }
/* Calculate offset. */ /* Calculate offset. */
@ -665,7 +679,7 @@ pre_TP(DECL_ARGS)
if ((nn = n->parent->head->child) != NULL && if ((nn = n->parent->head->child) != NULL &&
nn->string != NULL && ! (MAN_LINE & nn->flags) && nn->string != NULL && ! (MAN_LINE & nn->flags) &&
a2roffsu(nn->string, &su, SCALE_EN)) { a2roffsu(nn->string, &su, SCALE_EN)) {
len = term_hspan(p, &su); len = term_hspan(p, &su) / 24;
if (len < 0 && (size_t)(-len) > mt->offset) if (len < 0 && (size_t)(-len) > mt->offset)
len = -mt->offset; len = -mt->offset;
else if (len > SHRT_MAX) else if (len > SHRT_MAX)
@ -675,7 +689,7 @@ pre_TP(DECL_ARGS)
len = mt->lmargin[mt->lmargincur]; len = mt->lmargin[mt->lmargincur];
switch (n->type) { switch (n->type) {
case MAN_HEAD: case ROFFT_HEAD:
p->offset = mt->offset; p->offset = mt->offset;
p->rmargin = mt->offset + len; p->rmargin = mt->offset + len;
@ -694,18 +708,18 @@ pre_TP(DECL_ARGS)
if (savelit) if (savelit)
mt->fl |= MANT_LITERAL; mt->fl |= MANT_LITERAL;
return(0); return 0;
case MAN_BODY: case ROFFT_BODY:
p->offset = mt->offset + len; p->offset = mt->offset + len;
p->rmargin = p->maxrmargin; p->rmargin = p->maxrmargin;
p->trailspace = 0; p->trailspace = 0;
p->flags &= ~TERMP_NOBREAK; p->flags &= ~(TERMP_NOBREAK | TERMP_BRTRSP);
break; break;
default: default:
break; break;
} }
return(1); return 1;
} }
static void static void
@ -713,10 +727,10 @@ post_TP(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_HEAD: case ROFFT_HEAD:
term_flushln(p); term_flushln(p);
break; break;
case MAN_BODY: case ROFFT_BODY:
term_newln(p); term_newln(p);
p->offset = mt->offset; p->offset = mt->offset;
break; break;
@ -731,7 +745,7 @@ pre_SS(DECL_ARGS)
int i; int i;
switch (n->type) { switch (n->type) {
case MAN_BLOCK: case ROFFT_BLOCK:
mt->fl &= ~MANT_LITERAL; mt->fl &= ~MANT_LITERAL;
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
mt->offset = term_len(p, p->defindent); mt->offset = term_len(p, p->defindent);
@ -743,25 +757,32 @@ pre_SS(DECL_ARGS)
do { do {
n = n->prev; n = n->prev;
} while (n != NULL && termacts[n->tok].flags & MAN_NOTEXT); } while (n != NULL && n->tok != TOKEN_NONE &&
termacts[n->tok].flags & MAN_NOTEXT);
if (n == NULL || (n->tok == MAN_SS && n->body->child == NULL)) if (n == NULL || (n->tok == MAN_SS && n->body->child == NULL))
break; break;
for (i = 0; i < mt->pardist; i++) for (i = 0; i < mt->pardist; i++)
term_vspace(p); term_vspace(p);
break; break;
case MAN_HEAD: case ROFFT_HEAD:
term_fontrepl(p, TERMFONT_BOLD); term_fontrepl(p, TERMFONT_BOLD);
p->offset = term_len(p, 3); p->offset = term_len(p, 3);
p->rmargin = mt->offset;
p->trailspace = mt->offset;
p->flags |= TERMP_NOBREAK | TERMP_BRIND;
break; break;
case MAN_BODY: case ROFFT_BODY:
p->offset = mt->offset; p->offset = mt->offset;
p->rmargin = p->maxrmargin;
p->trailspace = 0;
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
break; break;
default: default:
break; break;
} }
return(1); return 1;
} }
static void static void
@ -769,10 +790,10 @@ post_SS(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_HEAD: case ROFFT_HEAD:
term_newln(p); term_newln(p);
break; break;
case MAN_BODY: case ROFFT_BODY:
term_newln(p); term_newln(p);
break; break;
default: default:
@ -786,7 +807,7 @@ pre_SH(DECL_ARGS)
int i; int i;
switch (n->type) { switch (n->type) {
case MAN_BLOCK: case ROFFT_BLOCK:
mt->fl &= ~MANT_LITERAL; mt->fl &= ~MANT_LITERAL;
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
mt->offset = term_len(p, p->defindent); mt->offset = term_len(p, p->defindent);
@ -805,18 +826,24 @@ pre_SH(DECL_ARGS)
for (i = 0; i < mt->pardist; i++) for (i = 0; i < mt->pardist; i++)
term_vspace(p); term_vspace(p);
break; break;
case MAN_HEAD: case ROFFT_HEAD:
term_fontrepl(p, TERMFONT_BOLD); term_fontrepl(p, TERMFONT_BOLD);
p->offset = 0; p->offset = 0;
p->rmargin = mt->offset;
p->trailspace = mt->offset;
p->flags |= TERMP_NOBREAK | TERMP_BRIND;
break; break;
case MAN_BODY: case ROFFT_BODY:
p->offset = mt->offset; p->offset = mt->offset;
p->rmargin = p->maxrmargin;
p->trailspace = 0;
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
break; break;
default: default:
break; break;
} }
return(1); return 1;
} }
static void static void
@ -824,10 +851,10 @@ post_SH(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_HEAD: case ROFFT_HEAD:
term_newln(p); term_newln(p);
break; break;
case MAN_BODY: case ROFFT_BODY:
term_newln(p); term_newln(p);
break; break;
default: default:
@ -841,19 +868,21 @@ pre_RS(DECL_ARGS)
struct roffsu su; struct roffsu su;
switch (n->type) { switch (n->type) {
case MAN_BLOCK: case ROFFT_BLOCK:
term_newln(p); term_newln(p);
return(1); return 1;
case MAN_HEAD: case ROFFT_HEAD:
return(0); return 0;
default: default:
break; break;
} }
n = n->parent->head; n = n->parent->head;
n->aux = SHRT_MAX + 1; n->aux = SHRT_MAX + 1;
if (n->child != NULL && a2roffsu(n->child->string, &su, SCALE_EN)) if (n->child == NULL)
n->aux = term_hspan(p, &su); n->aux = mt->lmargin[mt->lmargincur];
else if (a2roffsu(n->child->string, &su, SCALE_EN))
n->aux = term_hspan(p, &su) / 24;
if (n->aux < 0 && (size_t)(-n->aux) > mt->offset) if (n->aux < 0 && (size_t)(-n->aux) > mt->offset)
n->aux = -mt->offset; n->aux = -mt->offset;
else if (n->aux > SHRT_MAX) else if (n->aux > SHRT_MAX)
@ -866,8 +895,8 @@ pre_RS(DECL_ARGS)
if (++mt->lmarginsz < MAXMARGINS) if (++mt->lmarginsz < MAXMARGINS)
mt->lmargincur = mt->lmarginsz; mt->lmargincur = mt->lmarginsz;
mt->lmargin[mt->lmargincur] = mt->lmargin[mt->lmargincur - 1]; mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
return(1); return 1;
} }
static void static void
@ -875,9 +904,9 @@ post_RS(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_BLOCK: case ROFFT_BLOCK:
return; return;
case MAN_HEAD: case ROFFT_HEAD:
return; return;
default: default:
term_newln(p); term_newln(p);
@ -895,14 +924,14 @@ static int
pre_UR(DECL_ARGS) pre_UR(DECL_ARGS)
{ {
return (MAN_HEAD != n->type); return n->type != ROFFT_HEAD;
} }
static void static void
post_UR(DECL_ARGS) post_UR(DECL_ARGS)
{ {
if (MAN_BLOCK != n->type) if (n->type != ROFFT_BLOCK)
return; return;
term_word(p, "<"); term_word(p, "<");
@ -922,7 +951,7 @@ print_man_node(DECL_ARGS)
int c; int c;
switch (n->type) { switch (n->type) {
case MAN_TEXT: case ROFFT_TEXT:
/* /*
* If we have a blank line, output a vertical space. * If we have a blank line, output a vertical space.
* If we have a space as the first character, break * If we have a space as the first character, break
@ -937,14 +966,14 @@ print_man_node(DECL_ARGS)
term_word(p, n->string); term_word(p, n->string);
goto out; goto out;
case MAN_EQN: case ROFFT_EQN:
if ( ! (n->flags & MAN_LINE)) if ( ! (n->flags & MAN_LINE))
p->flags |= TERMP_NOSPACE; p->flags |= TERMP_NOSPACE;
term_eqn(p, n->eqn); term_eqn(p, n->eqn);
if (n->next != NULL && ! (n->next->flags & MAN_LINE)) if (n->next != NULL && ! (n->next->flags & MAN_LINE))
p->flags |= TERMP_NOSPACE; p->flags |= TERMP_NOSPACE;
return; return;
case MAN_TBL: case ROFFT_TBL:
if (p->tbl.cols == NULL) if (p->tbl.cols == NULL)
term_vspace(p); term_vspace(p);
term_tbl(p, n->span); term_tbl(p, n->span);
@ -1010,13 +1039,11 @@ print_man_nodelist(DECL_ARGS)
} }
static void static void
print_man_foot(struct termp *p, const void *arg) print_man_foot(struct termp *p, const struct roff_meta *meta)
{ {
const struct man_meta *meta;
char *title; char *title;
size_t datelen, titlen; size_t datelen, titlen;
meta = (const struct man_meta *)arg;
assert(meta->title); assert(meta->title);
assert(meta->msec); assert(meta->msec);
assert(meta->date); assert(meta->date);
@ -1028,8 +1055,8 @@ print_man_foot(struct termp *p, const void *arg)
/* /*
* Temporary, undocumented option to imitate mdoc(7) output. * Temporary, undocumented option to imitate mdoc(7) output.
* In the bottom right corner, use the source instead of * In the bottom right corner, use the operating system
* the title. * instead of the title.
*/ */
if ( ! p->mdocstyle) { if ( ! p->mdocstyle) {
@ -1039,14 +1066,14 @@ print_man_foot(struct termp *p, const void *arg)
} }
mandoc_asprintf(&title, "%s(%s)", mandoc_asprintf(&title, "%s(%s)",
meta->title, meta->msec); meta->title, meta->msec);
} else if (meta->source) { } else if (meta->os) {
title = mandoc_strdup(meta->source); title = mandoc_strdup(meta->os);
} else { } else {
title = mandoc_strdup(""); title = mandoc_strdup("");
} }
datelen = term_strlen(p, meta->date); datelen = term_strlen(p, meta->date);
/* Bottom left corner: manual source. */ /* Bottom left corner: operating system. */
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK; p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
p->trailspace = 1; p->trailspace = 1;
@ -1054,8 +1081,8 @@ print_man_foot(struct termp *p, const void *arg)
p->rmargin = p->maxrmargin > datelen ? p->rmargin = p->maxrmargin > datelen ?
(p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0; (p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0;
if (meta->source) if (meta->os)
term_word(p, meta->source); term_word(p, meta->os);
term_flushln(p); term_flushln(p);
/* At the bottom in the middle: manual date. */ /* At the bottom in the middle: manual date. */
@ -1082,14 +1109,12 @@ print_man_foot(struct termp *p, const void *arg)
} }
static void static void
print_man_head(struct termp *p, const void *arg) print_man_head(struct termp *p, const struct roff_meta *meta)
{ {
const struct man_meta *meta;
const char *volume; const char *volume;
char *title; char *title;
size_t vollen, titlen; size_t vollen, titlen;
meta = (const struct man_meta *)arg;
assert(meta->title); assert(meta->title);
assert(meta->msec); assert(meta->msec);

View File

@ -1,15 +1,15 @@
/* $OpenBSD$ */ /* $OpenBSD$ */
/* /*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -28,13 +28,15 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "man.h"
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "libman.h" #include "mandoc.h"
#include "roff.h"
#include "man.h"
#include "libmandoc.h" #include "libmandoc.h"
#include "roff_int.h"
#include "libman.h"
#define CHKARGS struct man *man, struct man_node *n #define CHKARGS struct roff_man *man, struct roff_node *n
typedef void (*v_check)(CHKARGS); typedef void (*v_check)(CHKARGS);
@ -46,9 +48,7 @@ static void check_text(CHKARGS);
static void post_AT(CHKARGS); static void post_AT(CHKARGS);
static void post_IP(CHKARGS); static void post_IP(CHKARGS);
static void post_vs(CHKARGS); static void post_vs(CHKARGS);
static void post_fi(CHKARGS);
static void post_ft(CHKARGS); static void post_ft(CHKARGS);
static void post_nf(CHKARGS);
static void post_OP(CHKARGS); static void post_OP(CHKARGS);
static void post_TH(CHKARGS); static void post_TH(CHKARGS);
static void post_UC(CHKARGS); static void post_UC(CHKARGS);
@ -77,8 +77,8 @@ static v_check man_valids[MAN_MAX] = {
NULL, /* IR */ NULL, /* IR */
NULL, /* RI */ NULL, /* RI */
post_vs, /* sp */ post_vs, /* sp */
post_nf, /* nf */ NULL, /* nf */
post_fi, /* fi */ NULL, /* fi */
NULL, /* RE */ NULL, /* RE */
check_part, /* RS */ check_part, /* RS */
NULL, /* DT */ NULL, /* DT */
@ -88,8 +88,8 @@ static v_check man_valids[MAN_MAX] = {
NULL, /* in */ NULL, /* in */
post_ft, /* ft */ post_ft, /* ft */
post_OP, /* OP */ post_OP, /* OP */
post_nf, /* EX */ NULL, /* EX */
post_fi, /* EE */ NULL, /* EE */
post_UR, /* UR */ post_UR, /* UR */
NULL, /* UE */ NULL, /* UE */
NULL, /* ll */ NULL, /* ll */
@ -97,31 +97,39 @@ static v_check man_valids[MAN_MAX] = {
void void
man_valid_post(struct man *man) man_node_validate(struct roff_man *man)
{ {
struct man_node *n; struct roff_node *n;
v_check *cp; v_check *cp;
n = man->last; n = man->last;
if (n->flags & MAN_VALID) man->last = man->last->child;
return; while (man->last != NULL) {
n->flags |= MAN_VALID; man_node_validate(man);
if (man->last == n)
man->last = man->last->child;
else
man->last = man->last->next;
}
man->last = n;
man->next = ROFF_NEXT_SIBLING;
switch (n->type) { switch (n->type) {
case MAN_TEXT: case ROFFT_TEXT:
check_text(man, n); check_text(man, n);
break; break;
case MAN_ROOT: case ROFFT_ROOT:
check_root(man, n); check_root(man, n);
break; break;
case MAN_EQN: case ROFFT_EQN:
/* FALLTHROUGH */ case ROFFT_TBL:
case MAN_TBL:
break; break;
default: default:
cp = man_valids + n->tok; cp = man_valids + n->tok;
if (*cp) if (*cp)
(*cp)(man, n); (*cp)(man, n);
if (man->last == n)
man_state(man, n);
break; break;
} }
} }
@ -172,10 +180,10 @@ static void
post_OP(CHKARGS) post_OP(CHKARGS)
{ {
if (n->nchild == 0) if (n->child == NULL)
mandoc_msg(MANDOCERR_OP_EMPTY, man->parse, mandoc_msg(MANDOCERR_OP_EMPTY, man->parse,
n->line, n->pos, "OP"); n->line, n->pos, "OP");
else if (n->nchild > 2) { else if (n->child->next != NULL && n->child->next->next != NULL) {
n = n->child->next->next; n = n->child->next->next;
mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse, mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse,
n->line, n->pos, "OP ... %s", n->string); n->line, n->pos, "OP ... %s", n->string);
@ -186,7 +194,7 @@ static void
post_UR(CHKARGS) post_UR(CHKARGS)
{ {
if (n->type == MAN_HEAD && n->child == NULL) if (n->type == ROFFT_HEAD && n->child == NULL)
mandoc_vmsg(MANDOCERR_UR_NOHEAD, man->parse, mandoc_vmsg(MANDOCERR_UR_NOHEAD, man->parse,
n->line, n->pos, "UR"); n->line, n->pos, "UR");
check_part(man, n); check_part(man, n);
@ -198,24 +206,18 @@ post_ft(CHKARGS)
char *cp; char *cp;
int ok; int ok;
if (0 == n->nchild) if (n->child == NULL)
return; return;
ok = 0; ok = 0;
cp = n->child->string; cp = n->child->string;
switch (*cp) { switch (*cp) {
case '1': case '1':
/* FALLTHROUGH */
case '2': case '2':
/* FALLTHROUGH */
case '3': case '3':
/* FALLTHROUGH */
case '4': case '4':
/* FALLTHROUGH */
case 'I': case 'I':
/* FALLTHROUGH */
case 'P': case 'P':
/* FALLTHROUGH */
case 'R': case 'R':
if ('\0' == cp[1]) if ('\0' == cp[1])
ok = 1; ok = 1;
@ -243,7 +245,7 @@ static void
check_part(CHKARGS) check_part(CHKARGS)
{ {
if (n->type == MAN_BODY && n->child == NULL) if (n->type == ROFFT_BODY && n->child == NULL)
mandoc_msg(MANDOCERR_BLK_EMPTY, man->parse, mandoc_msg(MANDOCERR_BLK_EMPTY, man->parse,
n->line, n->pos, man_macronames[n->tok]); n->line, n->pos, man_macronames[n->tok]);
} }
@ -253,23 +255,23 @@ check_par(CHKARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_BLOCK: case ROFFT_BLOCK:
if (0 == n->body->nchild) if (n->body->child == NULL)
man_node_delete(man, n); roff_node_delete(man, n);
break; break;
case MAN_BODY: case ROFFT_BODY:
if (0 == n->nchild) if (n->child == NULL)
mandoc_vmsg(MANDOCERR_PAR_SKIP, mandoc_vmsg(MANDOCERR_PAR_SKIP,
man->parse, n->line, n->pos, man->parse, n->line, n->pos,
"%s empty", man_macronames[n->tok]); "%s empty", man_macronames[n->tok]);
break; break;
case MAN_HEAD: case ROFFT_HEAD:
if (n->nchild) if (n->child != NULL)
mandoc_vmsg(MANDOCERR_ARG_SKIP, mandoc_vmsg(MANDOCERR_ARG_SKIP,
man->parse, n->line, n->pos, man->parse, n->line, n->pos,
"%s %s%s", man_macronames[n->tok], "%s %s%s", man_macronames[n->tok],
n->child->string, n->child->string,
n->nchild > 1 ? " ..." : ""); n->child->next != NULL ? " ..." : "");
break; break;
default: default:
break; break;
@ -281,12 +283,12 @@ post_IP(CHKARGS)
{ {
switch (n->type) { switch (n->type) {
case MAN_BLOCK: case ROFFT_BLOCK:
if (0 == n->head->nchild && 0 == n->body->nchild) if (n->head->child == NULL && n->body->child == NULL)
man_node_delete(man, n); roff_node_delete(man, n);
break; break;
case MAN_BODY: case ROFFT_BODY:
if (0 == n->parent->head->nchild && 0 == n->nchild) if (n->parent->head->child == NULL && n->child == NULL)
mandoc_vmsg(MANDOCERR_PAR_SKIP, mandoc_vmsg(MANDOCERR_PAR_SKIP,
man->parse, n->line, n->pos, man->parse, n->line, n->pos,
"%s empty", man_macronames[n->tok]); "%s empty", man_macronames[n->tok]);
@ -299,21 +301,21 @@ post_IP(CHKARGS)
static void static void
post_TH(CHKARGS) post_TH(CHKARGS)
{ {
struct man_node *nb; struct roff_node *nb;
const char *p; const char *p;
free(man->meta.title); free(man->meta.title);
free(man->meta.vol); free(man->meta.vol);
free(man->meta.source); free(man->meta.os);
free(man->meta.msec); free(man->meta.msec);
free(man->meta.date); free(man->meta.date);
man->meta.title = man->meta.vol = man->meta.date = man->meta.title = man->meta.vol = man->meta.date =
man->meta.msec = man->meta.source = NULL; man->meta.msec = man->meta.os = NULL;
nb = n; nb = n;
/* ->TITLE<- MSEC DATE SOURCE VOL */ /* ->TITLE<- MSEC DATE OS VOL */
n = n->child; n = n->child;
if (n && n->string) { if (n && n->string) {
@ -335,7 +337,7 @@ post_TH(CHKARGS)
nb->line, nb->pos, "TH"); nb->line, nb->pos, "TH");
} }
/* TITLE ->MSEC<- DATE SOURCE VOL */ /* TITLE ->MSEC<- DATE OS VOL */
if (n) if (n)
n = n->next; n = n->next;
@ -347,7 +349,7 @@ post_TH(CHKARGS)
nb->line, nb->pos, "TH %s", man->meta.title); nb->line, nb->pos, "TH %s", man->meta.title);
} }
/* TITLE MSEC ->DATE<- SOURCE VOL */ /* TITLE MSEC ->DATE<- OS VOL */
if (n) if (n)
n = n->next; n = n->next;
@ -363,14 +365,14 @@ post_TH(CHKARGS)
n ? n->pos : nb->pos, "TH"); n ? n->pos : nb->pos, "TH");
} }
/* TITLE MSEC DATE ->SOURCE<- VOL */ /* TITLE MSEC DATE ->OS<- VOL */
if (n && (n = n->next)) if (n && (n = n->next))
man->meta.source = mandoc_strdup(n->string); man->meta.os = mandoc_strdup(n->string);
else if (man->defos != NULL) else if (man->defos != NULL)
man->meta.source = mandoc_strdup(man->defos); man->meta.os = mandoc_strdup(man->defos);
/* TITLE MSEC DATE SOURCE ->VOL<- */ /* TITLE MSEC DATE OS ->VOL<- */
/* If missing, use the default VOL name for MSEC. */ /* If missing, use the default VOL name for MSEC. */
if (n && (n = n->next)) if (n && (n = n->next))
@ -387,29 +389,7 @@ post_TH(CHKARGS)
* Remove the `TH' node after we've processed it for our * Remove the `TH' node after we've processed it for our
* meta-data. * meta-data.
*/ */
man_node_delete(man, man->last); roff_node_delete(man, man->last);
}
static void
post_nf(CHKARGS)
{
if (man->flags & MAN_LITERAL)
mandoc_msg(MANDOCERR_NF_SKIP, man->parse,
n->line, n->pos, "nf");
man->flags |= MAN_LITERAL;
}
static void
post_fi(CHKARGS)
{
if ( ! (MAN_LITERAL & man->flags))
mandoc_msg(MANDOCERR_FI_SKIP, man->parse,
n->line, n->pos, "fi");
man->flags &= ~MAN_LITERAL;
} }
static void static void
@ -427,7 +407,7 @@ post_UC(CHKARGS)
n = n->child; n = n->child;
if (NULL == n || MAN_TEXT != n->type) if (n == NULL || n->type != ROFFT_TEXT)
p = bsd_versions[0]; p = bsd_versions[0];
else { else {
s = n->string; s = n->string;
@ -445,8 +425,8 @@ post_UC(CHKARGS)
p = bsd_versions[0]; p = bsd_versions[0];
} }
free(man->meta.source); free(man->meta.os);
man->meta.source = mandoc_strdup(p); man->meta.os = mandoc_strdup(p);
} }
static void static void
@ -459,12 +439,12 @@ post_AT(CHKARGS)
"System V Release 2", "System V Release 2",
}; };
struct roff_node *nn;
const char *p, *s; const char *p, *s;
struct man_node *nn;
n = n->child; n = n->child;
if (NULL == n || MAN_TEXT != n->type) if (n == NULL || n->type != ROFFT_TEXT)
p = unix_versions[0]; p = unix_versions[0];
else { else {
s = n->string; s = n->string;
@ -474,7 +454,9 @@ post_AT(CHKARGS)
p = unix_versions[1]; p = unix_versions[1];
else if (0 == strcmp(s, "5")) { else if (0 == strcmp(s, "5")) {
nn = n->next; nn = n->next;
if (nn && MAN_TEXT == nn->type && nn->string[0]) if (nn != NULL &&
nn->type == ROFFT_TEXT &&
nn->string[0] != '\0')
p = unix_versions[3]; p = unix_versions[3];
else else
p = unix_versions[2]; p = unix_versions[2];
@ -482,8 +464,8 @@ post_AT(CHKARGS)
p = unix_versions[0]; p = unix_versions[0];
} }
free(man->meta.source); free(man->meta.os);
man->meta.source = mandoc_strdup(p); man->meta.os = mandoc_strdup(p);
} }
static void static void
@ -495,18 +477,17 @@ post_vs(CHKARGS)
switch (n->parent->tok) { switch (n->parent->tok) {
case MAN_SH: case MAN_SH:
/* FALLTHROUGH */
case MAN_SS: case MAN_SS:
mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos, mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos,
"%s after %s", man_macronames[n->tok], "%s after %s", man_macronames[n->tok],
man_macronames[n->parent->tok]); man_macronames[n->parent->tok]);
/* FALLTHROUGH */ /* FALLTHROUGH */
case MAN_MAX: case TOKEN_NONE:
/* /*
* Don't warn about this because it occurs in pod2man * Don't warn about this because it occurs in pod2man
* and would cause considerable (unfixable) warnage. * and would cause considerable (unfixable) warnage.
*/ */
man_node_delete(man, n); roff_node_delete(man, n);
break; break;
default: default:
break; break;

48
contrib/mdocml/manconf.h Normal file
View File

@ -0,0 +1,48 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
* 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* List of unique, absolute paths to manual trees. */
struct manpaths {
char **paths;
size_t sz;
};
/* Data from -O options and man.conf(5) output directives. */
struct manoutput {
char *includes;
char *man;
char *paper;
char *style;
size_t indent;
size_t width;
int fragment;
int mdoc;
int synopsisonly;
};
struct manconf {
struct manoutput output;
struct manpaths manpath;
};
void manconf_parse(struct manconf *, const char *, char *, char *);
void manconf_output(struct manoutput *, const char *);
void manconf_free(struct manconf *);

View File

@ -1,4 +1,4 @@
.\" $Id: mandoc.1,v 1.155 2015/02/23 13:31:03 schwarze Exp $ .\" $Id: mandoc.1,v 1.164 2015/11/05 17:47:51 schwarze Exp $
.\" .\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: February 23 2015 $ .Dd $Mdocdate: November 5 2015 $
.Dt MANDOC 1 .Dt MANDOC 1
.Os .Os
.Sh NAME .Sh NAME
@ -24,14 +24,12 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm mandoc .Nm mandoc
.Op Fl acfhkl .Op Fl acfhkl
.Sm off .Op Fl I Cm os Ns = Ns Ar name
.Op Fl I Cm os Li = Ar name .Op Fl K Ar encoding
.Sm on
.Op Fl K Ns Ar encoding
.Op Fl m Ns Ar format .Op Fl m Ns Ar format
.Op Fl O Ns Ar option .Op Fl O Ar option
.Op Fl T Ns Ar output .Op Fl T Ar output
.Op Fl W Ns Ar level .Op Fl W Ar level
.Op Ar .Op Ar
.Sh DESCRIPTION .Sh DESCRIPTION
The The
@ -49,7 +47,7 @@ or
text from stdin, implying text from stdin, implying
.Fl m Ns Cm andoc , .Fl m Ns Cm andoc ,
and produces and produces
.Fl T Ns Cm locale .Fl T Cm locale
output. output.
.Pp .Pp
The options are as follows: The options are as follows:
@ -77,9 +75,7 @@ This overrides any earlier
and and
.Fl l .Fl l
options. options.
.Sm off .It Fl I Cm os Ns = Ns Ar name
.It Fl I Cm os Li = Ar name
.Sm on
Override the default operating system Override the default operating system
.Ar name .Ar name
for the for the
@ -93,7 +89,7 @@ macro.
Display only the SYNOPSIS lines. Display only the SYNOPSIS lines.
Implies Implies
.Fl c . .Fl c .
.It Fl K Ns Ar encoding .It Fl K Ar encoding
Specify the input encoding. Specify the input encoding.
The supported The supported
.Ar encoding .Ar encoding
@ -141,16 +137,16 @@ See
for available formats. for available formats.
Defaults to Defaults to
.Fl m Ns Cm andoc . .Fl m Ns Cm andoc .
.It Fl O Ns Ar option .It Fl O Ar option
Comma-separated output options. Comma-separated output options.
.It Fl T Ns Ar output .It Fl T Ar output
Output format. Output format.
See See
.Sx Output Formats .Sx Output Formats
for available formats. for available formats.
Defaults to Defaults to
.Fl T Ns Cm locale . .Fl T Cm locale .
.It Fl W Ns Ar level .It Fl W Ar level
Specify the minimum message Specify the minimum message
.Ar level .Ar level
to be reported on the standard error output and to affect the exit status. to be reported on the standard error output and to affect the exit status.
@ -174,7 +170,7 @@ and
for details. for details.
.Pp .Pp
The special option The special option
.Fl W Ns Cm stop .Fl W Cm stop
tells tells
.Nm .Nm
to exit after parsing a file that causes warnings or errors of at least to exit after parsing a file that causes warnings or errors of at least
@ -185,7 +181,7 @@ If both a
and and
.Cm stop .Cm stop
are requested, they can be joined with a comma, for example are requested, they can be joined with a comma, for example
.Fl W Ns Cm error , Ns Cm stop . .Fl W Cm error , Ns Cm stop .
.It Ar file .It Ar file
Read input from zero or more files. Read input from zero or more files.
If unspecified, reads from stdin. If unspecified, reads from stdin.
@ -254,54 +250,56 @@ The
utility accepts the following utility accepts the following
.Fl T .Fl T
arguments, which correspond to output modes: arguments, which correspond to output modes:
.Bl -tag -width "-Tlocale" .Bl -tag -width "-T locale"
.It Fl T Ns Cm ascii .It Fl T Cm ascii
Produce 7-bit ASCII output. Produce 7-bit ASCII output.
See See
.Sx ASCII Output . .Sx ASCII Output .
.It Fl T Ns Cm html .It Fl T Cm html
Produce HTML5, CSS1, and MathML output. Produce HTML5, CSS1, and MathML output.
See See
.Sx HTML Output . .Sx HTML Output .
.It Fl T Ns Cm lint .It Fl T Cm lint
Parse only: produce no output. Parse only: produce no output.
Implies Implies
.Fl W Ns Cm warning . .Fl W Cm warning .
.It Fl T Ns Cm locale .It Fl T Cm locale
Encode output using the current locale. Encode output using the current locale.
This is the default. This is the default.
See See
.Sx Locale Output . .Sx Locale Output .
.It Fl T Ns Cm man .It Fl T Cm man
Produce Produce
.Xr man 7 .Xr man 7
format output. format output.
See See
.Sx Man Output . .Sx Man Output .
.It Fl T Ns Cm pdf .It Fl T Cm pdf
Produce PDF output. Produce PDF output.
See See
.Sx PDF Output . .Sx PDF Output .
.It Fl T Ns Cm ps .It Fl T Cm ps
Produce PostScript output. Produce PostScript output.
See See
.Sx PostScript Output . .Sx PostScript Output .
.It Fl T Ns Cm tree .It Fl T Cm tree
Produce an indented parse tree. Produce an indented parse tree.
.It Fl T Ns Cm utf8 See
.Sx Syntax tree output .
.It Fl T Cm utf8
Encode output in the UTF\-8 multi-byte format. Encode output in the UTF\-8 multi-byte format.
See See
.Sx UTF\-8 Output . .Sx UTF\-8 Output .
.It Fl T Ns Cm xhtml .It Fl T Cm xhtml
This is a synonym for This is a synonym for
.Fl T Ns Cm html . .Fl T Cm html .
.El .El
.Pp .Pp
If multiple input files are specified, these will be processed by the If multiple input files are specified, these will be processed by the
corresponding filter in-order. corresponding filter in-order.
.Ss ASCII Output .Ss ASCII Output
Output produced by Output produced by
.Fl T Ns Cm ascii .Fl T Cm ascii
is rendered in standard 7-bit ASCII documented in is rendered in standard 7-bit ASCII documented in
.Xr ascii 7 . .Xr ascii 7 .
.Pp .Pp
@ -343,7 +341,7 @@ which will normalise to \(>=58.
.El .El
.Ss HTML Output .Ss HTML Output
Output produced by Output produced by
.Fl T Ns Cm html .Fl T Cm html
conforms to HTML5 using optional self-closing tags. conforms to HTML5 using optional self-closing tags.
Default styles use only CSS1. Default styles use only CSS1.
Equations rendered from Equations rendered from
@ -351,11 +349,11 @@ Equations rendered from
blocks use MathML. blocks use MathML.
.Pp .Pp
The The
.Pa example.style.css .Pa mandoc.css
file documents style-sheet classes available for customising output. file documents style-sheet classes available for customising output.
If a style-sheet is not specified with If a style-sheet is not specified with
.Fl O Ns Ar style , .Fl O Cm style ,
.Fl T Ns Cm html .Fl T Cm html
defaults to simple output (via an embedded style-sheet) defaults to simple output (via an embedded style-sheet)
readable in any graphical or text-based web readable in any graphical or text-based web
browser. browser.
@ -411,13 +409,13 @@ relative URI.
.El .El
.Ss Locale Output .Ss Locale Output
Locale-depending output encoding is triggered with Locale-depending output encoding is triggered with
.Fl T Ns Cm locale . .Fl T Cm locale .
This is the default. This is the default.
.Pp .Pp
This option is not available on all systems: systems without locale This option is not available on all systems: systems without locale
support, or those whose internal representation is not natively UCS-4, support, or those whose internal representation is not natively UCS-4,
will fall back to will fall back to
.Fl T Ns Cm ascii . .Fl T Cm ascii .
See See
.Sx ASCII Output .Sx ASCII Output
for font style specification and available command-line arguments. for font style specification and available command-line arguments.
@ -447,7 +445,7 @@ level controls which
are displayed before copying the input to the output. are displayed before copying the input to the output.
.Ss PDF Output .Ss PDF Output
PDF-1.1 output may be generated by PDF-1.1 output may be generated by
.Fl T Ns Cm pdf . .Fl T Cm pdf .
See See
.Sx PostScript Output .Sx PostScript Output
for for
@ -457,7 +455,7 @@ arguments and defaults.
PostScript PostScript
.Qq Adobe-3.0 .Qq Adobe-3.0
Level-2 pages may be generated by Level-2 pages may be generated by
.Fl T Ns Cm ps . .Fl T Cm ps .
Output pages default to letter sized and are rendered in the Times font Output pages default to letter sized and are rendered in the Times font
family, 11-point. family, 11-point.
Margins are calculated as 1/9 the page length and width. Margins are calculated as 1/9 the page length and width.
@ -489,11 +487,50 @@ is used.
.El .El
.Ss UTF\-8 Output .Ss UTF\-8 Output
Use Use
.Fl T Ns Cm utf8 .Fl T Cm utf8
to force a UTF\-8 locale. to force a UTF\-8 locale.
See See
.Sx Locale Output .Sx Locale Output
for details and options. for details and options.
.Ss Syntax tree output
Use
.Fl T Cm tree
to show a human readable representation of the syntax tree.
It is useful for debugging the source code of manual pages.
The exact format is subject to change, so don't write parsers for it.
Each output line shows one syntax tree node.
Child nodes are indented with respect to their parent node.
The columns are:
.Pp
.Bl -enum -compact
.It
For macro nodes, the macro name; for text and
.Xr tbl 7
nodes, the content.
There is a special format for
.Xr eqn 7
nodes.
.It
Node type (text, elem, block, head, body, body-end, tail, tbl, eqn).
.It
Flags:
.Bl -dash -compact
.It
An opening parenthesis if the node is an opening delimiter.
.It
An asterisk if the node starts a new input line.
.It
The input line number (starting at one).
.It
A colon.
.It
The input column number (starting at one).
.It
A closing parenthesis if the node is a closing delimiter.
.It
A full stop if the node ends a sentence.
.El
.El
.Sh ENVIRONMENT .Sh ENVIRONMENT
.Bl -tag -width MANPAGER .Bl -tag -width MANPAGER
.It Ev MANPAGER .It Ev MANPAGER
@ -506,7 +543,8 @@ Specifies the pagination program to use when
.Ev MANPAGER .Ev MANPAGER
is not defined. is not defined.
If neither PAGER nor MANPAGER is defined, If neither PAGER nor MANPAGER is defined,
.Pa /usr/bin/more Fl s .Xr more 1
.Fl s
will be used. will be used.
.El .El
.Sh EXIT STATUS .Sh EXIT STATUS
@ -525,21 +563,21 @@ they were lower than the requested
.Ar level . .Ar level .
.It 2 .It 2
At least one warning occurred, but no error, and At least one warning occurred, but no error, and
.Fl W Ns Cm warning .Fl W Cm warning
was specified. was specified.
.It 3 .It 3
At least one parsing error occurred, At least one parsing error occurred,
but no unsupported feature was encountered, and but no unsupported feature was encountered, and
.Fl W Ns Cm error .Fl W Cm error
or or
.Fl W Ns Cm warning .Fl W Cm warning
was specified. was specified.
.It 4 .It 4
At least one unsupported feature was encountered, and At least one unsupported feature was encountered, and
.Fl W Ns Cm unsupp , .Fl W Cm unsupp ,
.Fl W Ns Cm error .Fl W Cm error
or or
.Fl W Ns Cm warning .Fl W Cm warning
was specified. was specified.
.It 5 .It 5
Invalid command line arguments were specified. Invalid command line arguments were specified.
@ -553,28 +591,28 @@ to exit at once, possibly in the middle of parsing or formatting a file.
.El .El
.Pp .Pp
Note that selecting Note that selecting
.Fl T Ns Cm lint .Fl T Cm lint
output mode implies output mode implies
.Fl W Ns Cm warning . .Fl W Cm warning .
.Sh EXAMPLES .Sh EXAMPLES
To page manuals to the terminal: To page manuals to the terminal:
.Pp .Pp
.Dl $ mandoc \-Wall,stop mandoc.1 2\*(Gt&1 | less .Dl $ mandoc \-W all,stop mandoc.1 2\*(Gt&1 | less
.Dl $ mandoc mandoc.1 mdoc.3 mdoc.7 | less .Dl $ mandoc mandoc.1 mdoc.3 mdoc.7 | less
.Pp .Pp
To produce HTML manuals with To produce HTML manuals with
.Ar style.css .Pa mandoc.css
as the style-sheet: as the style-sheet:
.Pp .Pp
.Dl $ mandoc \-Thtml -Ostyle=style.css mdoc.7 \*(Gt mdoc.7.html .Dl $ mandoc \-T html -O style=mandoc.css mdoc.7 \*(Gt mdoc.7.html
.Pp .Pp
To check over a large set of manuals: To check over a large set of manuals:
.Pp .Pp
.Dl $ mandoc \-Tlint `find /usr/src -name \e*\e.[1-9]` .Dl $ mandoc \-T lint \(gafind /usr/src -name \e*\e.[1-9]\(ga
.Pp .Pp
To produce a series of PostScript manuals for A4 paper: To produce a series of PostScript manuals for A4 paper:
.Pp .Pp
.Dl $ mandoc \-Tps \-Opaper=a4 mdoc.7 man.7 \*(Gt manuals.ps .Dl $ mandoc \-T ps \-O paper=a4 mdoc.7 man.7 \*(Gt manuals.ps
.Pp .Pp
Convert a modern Convert a modern
.Xr mdoc 7 .Xr mdoc 7
@ -584,7 +622,7 @@ format, for use on systems lacking an
.Xr mdoc 7 .Xr mdoc 7
parser: parser:
.Pp .Pp
.Dl $ mandoc \-Tman foo.mdoc \*(Gt foo.man .Dl $ mandoc \-T man foo.mdoc \*(Gt foo.man
.Sh DIAGNOSTICS .Sh DIAGNOSTICS
Messages displayed by Messages displayed by
.Nm .Nm
@ -651,7 +689,7 @@ levels except those about non-existent or unreadable input files
are hidden unless their level, or a lower level, is requested using a are hidden unless their level, or a lower level, is requested using a
.Fl W .Fl W
option or option or
.Fl T Ns Cm lint .Fl T Cm lint
output mode. output mode.
.Ss Warnings related to the document prologue .Ss Warnings related to the document prologue
.Bl -ohang .Bl -ohang
@ -817,7 +855,7 @@ In the SEE ALSO section, an
macro with a lower section number follows one with a higher number, macro with a lower section number follows one with a higher number,
or two or two
.Ic \&Xr .Ic \&Xr
macros refering to the same section are out of alphabetical order. macros referring to the same section are out of alphabetical order.
.It Sy "unusual Xr punctuation" .It Sy "unusual Xr punctuation"
.Pq mdoc .Pq mdoc
In the SEE ALSO section, punctuation between two In the SEE ALSO section, punctuation between two
@ -937,13 +975,6 @@ list block contains text or macros before the first
.Ic \&It .Ic \&It
macro. macro.
The offending children are moved before the beginning of the list. The offending children are moved before the beginning of the list.
.It Sy ".Vt block has child macro"
.Pq mdoc
The
.Ic \&Vt
macro supports plain text arguments only.
Formatting may be ugly and semantic searching
for the affected content might not work.
.It Sy "fill mode already enabled, skipping" .It Sy "fill mode already enabled, skipping"
.Pq man .Pq man
A A
@ -1569,6 +1600,13 @@ By requesting the inclusion of a sensitive file, a malicious document
might otherwise trick a privileged user into inadvertently displaying might otherwise trick a privileged user into inadvertently displaying
the file on the screen, revealing the file content to bystanders. the file on the screen, revealing the file content to bystanders.
The argument is ignored including the file name following it. The argument is ignored including the file name following it.
.It Sy "skipping display without arguments"
.Pq mdoc
A
.Ic \&Bd
block macro does not have any arguments.
The block is discarded, and the block content is displayed in
whatever mode was active before the block.
.It Sy "missing list type, using -item" .It Sy "missing list type, using -item"
.Pq mdoc .Pq mdoc
A A
@ -1767,6 +1805,7 @@ as if they were a text line.
.Xr roff 7 , .Xr roff 7 ,
.Xr tbl 7 .Xr tbl 7
.Sh AUTHORS .Sh AUTHORS
.An -nosplit
The The
.Nm .Nm
utility was written by utility was written by
@ -1775,10 +1814,10 @@ and is maintained by
.An Ingo Schwarze Aq Mt schwarze@openbsd.org . .An Ingo Schwarze Aq Mt schwarze@openbsd.org .
.Sh BUGS .Sh BUGS
In In
.Fl T Ns Cm html , .Fl T Cm html ,
the maximum size of an element attribute is determined by the maximum size of an element attribute is determined by
.Dv BUFSIZ , .Dv BUFSIZ ,
which is usually 1024 bytes. which is usually 1024 bytes.
Be aware of this when setting long link Be aware of this when setting long link
formats such as formats such as
.Fl O Ns Cm style Ns = Ns Ar really/long/link . .Fl O Cm style Ns = Ns Ar really/long/link .

View File

@ -1,7 +1,7 @@
.\" $Id: mandoc.3,v 1.31 2015/01/15 04:26:40 schwarze Exp $ .\" $Id: mandoc.3,v 1.36 2016/01/08 17:48:09 schwarze Exp $
.\" .\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
.\" .\"
.\" Permission to use, copy, modify, and distribute this software for any .\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above .\" 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 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: January 15 2015 $ .Dd $Mdocdate: January 8 2016 $
.Dt MANDOC 3 .Dt MANDOC 3
.Os .Os
.Sh NAME .Sh NAME
@ -37,7 +37,6 @@
.Nm mparse_result , .Nm mparse_result ,
.Nm mparse_strerror , .Nm mparse_strerror ,
.Nm mparse_strlevel .Nm mparse_strlevel
.Nm mparse_wait ,
.Nd mandoc macro compiler library .Nd mandoc macro compiler library
.Sh SYNOPSIS .Sh SYNOPSIS
.In sys/types.h .In sys/types.h
@ -51,7 +50,6 @@
.Fa "int options" .Fa "int options"
.Fa "enum mandoclevel wlevel" .Fa "enum mandoclevel wlevel"
.Fa "mandocmsg mmsg" .Fa "mandocmsg mmsg"
.Fa "const struct mchars *mchars"
.Fa "char *defos" .Fa "char *defos"
.Fc .Fc
.Ft void .Ft void
@ -75,10 +73,9 @@
.Fo mparse_keep .Fo mparse_keep
.Fa "struct mparse *parse" .Fa "struct mparse *parse"
.Fc .Fc
.Ft "enum mandoclevel" .Ft int
.Fo mparse_open .Fo mparse_open
.Fa "struct mparse *parse" .Fa "struct mparse *parse"
.Fa "int *fd"
.Fa "const char *fname" .Fa "const char *fname"
.Fc .Fc
.Ft "enum mandoclevel" .Ft "enum mandoclevel"
@ -106,10 +103,6 @@
.Fo mparse_strlevel .Fo mparse_strlevel
.Fa "enum mandoclevel" .Fa "enum mandoclevel"
.Fc .Fc
.Ft "enum mandoclevel"
.Fo mparse_wait
.Fa "struct mparse *parse"
.Fc
.In sys/types.h .In sys/types.h
.In mandoc.h .In mandoc.h
.In mdoc.h .In mdoc.h
@ -183,6 +176,9 @@ or
parse it with parse it with
.Fn mparse_readfd ; .Fn mparse_readfd ;
.It .It
close it with
.Xr close 2 ;
.It
retrieve the syntax tree with retrieve the syntax tree with
.Fn mparse_result ; .Fn mparse_result ;
.It .It
@ -215,12 +211,6 @@ An error or warning message during parsing.
A classification of an A classification of an
.Vt "enum mandocerr" .Vt "enum mandocerr"
as regards system operation. as regards system operation.
.It Vt "struct mchars"
An opaque pointer to a a character table.
Created with
.Xr mchars_alloc 3
and freed with
.Xr mchars_free 3 .
.It Vt "struct mparse" .It Vt "struct mparse"
An opaque pointer to a running parse sequence. An opaque pointer to a running parse sequence.
Created with Created with
@ -345,9 +335,6 @@ A callback function to handle errors and warnings.
See See
.Pa main.c .Pa main.c
for an example. for an example.
.It Ar mchars
An opaque pointer to a a character table obtained from
.Xr mchars_alloc 3 .
.It Ar defos .It Ar defos
A default string for the A default string for the
.Xr mdoc 7 .Xr mdoc 7
@ -392,23 +379,15 @@ Declared in
implemented in implemented in
.Pa read.c . .Pa read.c .
.It Fn mparse_open .It Fn mparse_open
If the Open the file for reading.
If that fails and
.Fa fname .Fa fname
ends in does not already end in
.Pa .gz , .Ql .gz ,
open with try again after appending
.Xr gunzip 1 ; .Ql .gz .
otherwise, with Save the information whether the file is zipped or not.
.Xr open 2 . Return a file descriptor open for reading or -1 on failure.
If
.Xr open 2
fails, append
.Pa .gz
and try with
.Xr gunzip 1 .
Return a file descriptor open for reading in
.Fa fd ,
or -1 on failure.
It can be passed to It can be passed to
.Fn mparse_readfd .Fn mparse_readfd
or used directly. or used directly.
@ -423,10 +402,9 @@ or
.Fn mparse_open . .Fn mparse_open .
Pass the associated filename in Pass the associated filename in
.Va fname . .Va fname .
Calls
.Fn mparse_wait
before returning.
This function may be called multiple times with different parameters; however, This function may be called multiple times with different parameters; however,
.Xr close 2
and
.Fn mparse_reset .Fn mparse_reset
should be invoked between parses. should be invoked between parses.
Declared in Declared in
@ -460,28 +438,6 @@ Declared in
.In mandoc.h , .In mandoc.h ,
implemented in implemented in
.Pa read.c . .Pa read.c .
.It Fn mparse_wait
Bury a
.Xr gunzip 1
child process that was spawned with
.Fn mparse_open .
To be called after the parse sequence is complete.
Not needed after
.Fn mparse_readfd ,
but does no harm in that case, either.
Returns
.Dv MANDOCLEVEL_OK
on success and
.Dv MANDOCLEVEL_SYSERR
on failure, that is, when
.Xr wait 2
fails, or when
.Xr gunzip 1
died from a signal or exited with non-zero status.
Declared in
.In mandoc.h ,
implemented in
.Pa read.c .
.El .El
.Ss Variables .Ss Variables
.Bl -ohang .Bl -ohang
@ -601,7 +557,7 @@ and
fields), its position in the tree (the fields), its position in the tree (the
.Va parent , .Va parent ,
.Va child , .Va child ,
.Va nchild , .Va last ,
.Va next .Va next
and and
.Va prev .Va prev

View File

@ -1,4 +1,4 @@
/* $Id: mandoc.c,v 1.92 2015/02/20 23:55:10 schwarze Exp $ */ /* $Id: mandoc.c,v 1.98 2015/11/12 22:44:27 schwarze Exp $ */
/* /*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
@ -32,8 +32,6 @@
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "libmandoc.h" #include "libmandoc.h"
#define DATESIZE 32
static int a2time(time_t *, const char *, const char *); static int a2time(time_t *, const char *, const char *);
static char *time2a(time_t); static char *time2a(time_t);
@ -83,7 +81,7 @@ mandoc_escape(const char **end, const char **start, int *sz)
break; break;
case 'C': case 'C':
if ('\'' != **start) if ('\'' != **start)
return(ESCAPE_ERROR); return ESCAPE_ERROR;
*start = ++*end; *start = ++*end;
gly = ESCAPE_SPECIAL; gly = ESCAPE_SPECIAL;
term = '\''; term = '\'';
@ -93,9 +91,10 @@ mandoc_escape(const char **end, const char **start, int *sz)
* Escapes taking no arguments at all. * Escapes taking no arguments at all.
*/ */
case 'd': case 'd':
/* FALLTHROUGH */
case 'u': case 'u':
return(ESCAPE_IGNORE); case ',':
case '/':
return ESCAPE_IGNORE;
/* /*
* The \z escape is supposed to output the following * The \z escape is supposed to output the following
@ -104,26 +103,19 @@ mandoc_escape(const char **end, const char **start, int *sz)
* let us just skip the next character. * let us just skip the next character.
*/ */
case 'z': case 'z':
return(ESCAPE_SKIPCHAR); return ESCAPE_SKIPCHAR;
/* /*
* Handle all triggers matching \X(xy, \Xx, and \X[xxxx], where * Handle all triggers matching \X(xy, \Xx, and \X[xxxx], where
* 'X' is the trigger. These have opaque sub-strings. * 'X' is the trigger. These have opaque sub-strings.
*/ */
case 'F': case 'F':
/* FALLTHROUGH */
case 'g': case 'g':
/* FALLTHROUGH */
case 'k': case 'k':
/* FALLTHROUGH */
case 'M': case 'M':
/* FALLTHROUGH */
case 'm': case 'm':
/* FALLTHROUGH */
case 'n': case 'n':
/* FALLTHROUGH */
case 'V': case 'V':
/* FALLTHROUGH */
case 'Y': case 'Y':
gly = ESCAPE_IGNORE; gly = ESCAPE_IGNORE;
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -151,21 +143,16 @@ mandoc_escape(const char **end, const char **start, int *sz)
* The \B and \w escapes are handled in roff.c, roff_res(). * The \B and \w escapes are handled in roff.c, roff_res().
*/ */
case 'A': case 'A':
/* FALLTHROUGH */
case 'b': case 'b':
/* FALLTHROUGH */
case 'D': case 'D':
/* FALLTHROUGH */
case 'R': case 'R':
/* FALLTHROUGH */
case 'X': case 'X':
/* FALLTHROUGH */
case 'Z': case 'Z':
gly = ESCAPE_IGNORE; gly = ESCAPE_IGNORE;
/* FALLTHROUGH */ /* FALLTHROUGH */
case 'o': case 'o':
if (**start == '\0') if (**start == '\0')
return(ESCAPE_ERROR); return ESCAPE_ERROR;
if (gly == ESCAPE_ERROR) if (gly == ESCAPE_ERROR)
gly = ESCAPE_OVERSTRIKE; gly = ESCAPE_OVERSTRIKE;
term = **start; term = **start;
@ -177,22 +164,16 @@ mandoc_escape(const char **end, const char **start, int *sz)
* and 'N' resolves to a numerical expression. * and 'N' resolves to a numerical expression.
*/ */
case 'h': case 'h':
/* FALLTHROUGH */
case 'H': case 'H':
/* FALLTHROUGH */
case 'L': case 'L':
/* FALLTHROUGH */
case 'l': case 'l':
/* FALLTHROUGH */
case 'S': case 'S':
/* FALLTHROUGH */
case 'v': case 'v':
/* FALLTHROUGH */
case 'x': case 'x':
if (strchr(" %&()*+-./0123456789:<=>", **start)) { if (strchr(" %&()*+-./0123456789:<=>", **start)) {
if ('\0' != **start) if ('\0' != **start)
++*end; ++*end;
return(ESCAPE_ERROR); return ESCAPE_ERROR;
} }
gly = ESCAPE_IGNORE; gly = ESCAPE_IGNORE;
term = **start; term = **start;
@ -205,11 +186,11 @@ mandoc_escape(const char **end, const char **start, int *sz)
*/ */
case 'N': case 'N':
if ('\0' == **start) if ('\0' == **start)
return(ESCAPE_ERROR); return ESCAPE_ERROR;
(*end)++; (*end)++;
if (isdigit((unsigned char)**start)) { if (isdigit((unsigned char)**start)) {
*sz = 1; *sz = 1;
return(ESCAPE_IGNORE); return ESCAPE_IGNORE;
} }
(*start)++; (*start)++;
while (isdigit((unsigned char)**end)) while (isdigit((unsigned char)**end))
@ -217,7 +198,7 @@ mandoc_escape(const char **end, const char **start, int *sz)
*sz = *end - *start; *sz = *end - *start;
if ('\0' != **end) if ('\0' != **end)
(*end)++; (*end)++;
return(ESCAPE_NUMBERED); return ESCAPE_NUMBERED;
/* /*
* Sizes get a special category of their own. * Sizes get a special category of their own.
@ -243,9 +224,7 @@ mandoc_escape(const char **end, const char **start, int *sz)
term = '\''; term = '\'';
break; break;
case '3': case '3':
/* FALLTHROUGH */
case '2': case '2':
/* FALLTHROUGH */
case '1': case '1':
*sz = (*end)[-1] == 's' && *sz = (*end)[-1] == 's' &&
isdigit((unsigned char)(*end)[1]) ? 2 : 1; isdigit((unsigned char)(*end)[1]) ? 2 : 1;
@ -279,12 +258,12 @@ mandoc_escape(const char **end, const char **start, int *sz)
while (**end != term) { while (**end != term) {
switch (**end) { switch (**end) {
case '\0': case '\0':
return(ESCAPE_ERROR); return ESCAPE_ERROR;
case '\\': case '\\':
(*end)++; (*end)++;
if (ESCAPE_ERROR == if (ESCAPE_ERROR ==
mandoc_escape(end, NULL, NULL)) mandoc_escape(end, NULL, NULL))
return(ESCAPE_ERROR); return ESCAPE_ERROR;
break; break;
default: default:
(*end)++; (*end)++;
@ -295,7 +274,7 @@ mandoc_escape(const char **end, const char **start, int *sz)
} else { } else {
assert(*sz > 0); assert(*sz > 0);
if ((size_t)*sz > strlen(*start)) if ((size_t)*sz > strlen(*start))
return(ESCAPE_ERROR); return ESCAPE_ERROR;
*end += *sz; *end += *sz;
} }
@ -321,12 +300,10 @@ mandoc_escape(const char **end, const char **start, int *sz)
switch (**start) { switch (**start) {
case '3': case '3':
/* FALLTHROUGH */
case 'B': case 'B':
gly = ESCAPE_FONTBOLD; gly = ESCAPE_FONTBOLD;
break; break;
case '2': case '2':
/* FALLTHROUGH */
case 'I': case 'I':
gly = ESCAPE_FONTITALIC; gly = ESCAPE_FONTITALIC;
break; break;
@ -334,7 +311,6 @@ mandoc_escape(const char **end, const char **start, int *sz)
gly = ESCAPE_FONTPREV; gly = ESCAPE_FONTPREV;
break; break;
case '1': case '1':
/* FALLTHROUGH */
case 'R': case 'R':
gly = ESCAPE_FONTROMAN; gly = ESCAPE_FONTROMAN;
break; break;
@ -355,6 +331,9 @@ mandoc_escape(const char **end, const char **start, int *sz)
break; break;
if (*sz == 6 && (*start)[1] == '0') if (*sz == 6 && (*start)[1] == '0')
break; break;
if (*sz == 5 && (*start)[1] == 'D' &&
strchr("89ABCDEF", (*start)[2]) != NULL)
break;
if ((int)strspn(*start + 1, "0123456789ABCDEFabcdef") if ((int)strspn(*start + 1, "0123456789ABCDEFabcdef")
+ 1 == *sz) + 1 == *sz)
gly = ESCAPE_UNICODE; gly = ESCAPE_UNICODE;
@ -363,7 +342,7 @@ mandoc_escape(const char **end, const char **start, int *sz)
break; break;
} }
return(gly); return gly;
} }
/* /*
@ -458,7 +437,7 @@ mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
if ('\0' == *cp && (white || ' ' == cp[-1])) if ('\0' == *cp && (white || ' ' == cp[-1]))
mandoc_msg(MANDOCERR_SPACE_EOL, parse, ln, *pos, NULL); mandoc_msg(MANDOCERR_SPACE_EOL, parse, ln, *pos, NULL);
return(start); return start;
} }
static int static int
@ -475,10 +454,10 @@ a2time(time_t *t, const char *fmt, const char *p)
#endif #endif
if (NULL != pp && '\0' == *pp) { if (NULL != pp && '\0' == *pp) {
*t = mktime(&tm); *t = mktime(&tm);
return(1); return 1;
} }
return(0); return 0;
} }
static char * static char *
@ -491,7 +470,7 @@ time2a(time_t t)
tm = localtime(&t); tm = localtime(&t);
if (tm == NULL) if (tm == NULL)
return(NULL); return NULL;
/* /*
* Reserve space: * Reserve space:
@ -499,45 +478,61 @@ time2a(time_t t)
* up to 2 characters for the day + comma + blank * up to 2 characters for the day + comma + blank
* 4 characters for the year and a terminating '\0' * 4 characters for the year and a terminating '\0'
*/ */
p = buf = mandoc_malloc(10 + 4 + 4 + 1); p = buf = mandoc_malloc(10 + 4 + 4 + 1);
if (0 == (ssz = strftime(p, 10 + 1, "%B ", tm))) if ((ssz = strftime(p, 10 + 1, "%B ", tm)) == 0)
goto fail; goto fail;
p += (int)ssz; p += (int)ssz;
if (-1 == (isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday))) /*
* The output format is just "%d" here, not "%2d" or "%02d".
* That's also the reason why we can't just format the
* date as a whole with "%B %e, %Y" or "%B %d, %Y".
* Besides, the present approach is less prone to buffer
* overflows, in case anybody should ever introduce the bug
* of looking at LC_TIME.
*/
if ((isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday)) == -1)
goto fail; goto fail;
p += isz; p += isz;
if (0 == strftime(p, 4 + 1, "%Y", tm)) if (strftime(p, 4 + 1, "%Y", tm) == 0)
goto fail; goto fail;
return(buf); return buf;
fail: fail:
free(buf); free(buf);
return(NULL); return NULL;
} }
char * char *
mandoc_normdate(struct mparse *parse, char *in, int ln, int pos) mandoc_normdate(struct mparse *parse, char *in, int ln, int pos)
{ {
char *out;
time_t t; time_t t;
if (NULL == in || '\0' == *in || /* No date specified: use today's date. */
0 == strcmp(in, "$" "Mdocdate$")) {
if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0) {
mandoc_msg(MANDOCERR_DATE_MISSING, parse, ln, pos, NULL); mandoc_msg(MANDOCERR_DATE_MISSING, parse, ln, pos, NULL);
time(&t); return time2a(time(NULL));
} }
else if (a2time(&t, "%Y-%m-%d", in))
t = 0; /* Valid mdoc(7) date format. */
else if (!a2time(&t, "$" "Mdocdate: %b %d %Y $", in) &&
!a2time(&t, "%b %d, %Y", in)) { if (a2time(&t, "$" "Mdocdate: %b %d %Y $", in) ||
a2time(&t, "%b %d, %Y", in))
return time2a(t);
/* Do not warn about the legacy man(7) format. */
if ( ! a2time(&t, "%Y-%m-%d", in))
mandoc_msg(MANDOCERR_DATE_BAD, parse, ln, pos, in); mandoc_msg(MANDOCERR_DATE_BAD, parse, ln, pos, in);
t = 0;
} /* Use any non-mdoc(7) date verbatim. */
out = t ? time2a(t) : NULL;
return(out ? out : mandoc_strdup(in)); return mandoc_strdup(in);
} }
int int
@ -547,7 +542,7 @@ mandoc_eos(const char *p, size_t sz)
int enclosed, found; int enclosed, found;
if (0 == sz) if (0 == sz)
return(0); return 0;
/* /*
* End-of-sentence recognition must include situations where * End-of-sentence recognition must include situations where
@ -559,28 +554,24 @@ mandoc_eos(const char *p, size_t sz)
for (q = p + (int)sz - 1; q >= p; q--) { for (q = p + (int)sz - 1; q >= p; q--) {
switch (*q) { switch (*q) {
case '\"': case '\"':
/* FALLTHROUGH */
case '\'': case '\'':
/* FALLTHROUGH */
case ']': case ']':
/* FALLTHROUGH */
case ')': case ')':
if (0 == found) if (0 == found)
enclosed = 1; enclosed = 1;
break; break;
case '.': case '.':
/* FALLTHROUGH */
case '!': case '!':
/* FALLTHROUGH */
case '?': case '?':
found = 1; found = 1;
break; break;
default: default:
return(found && (!enclosed || isalnum((unsigned char)*q))); return found &&
(!enclosed || isalnum((unsigned char)*q));
} }
} }
return(found && !enclosed); return found && !enclosed;
} }
/* /*
@ -595,7 +586,7 @@ mandoc_strntoi(const char *p, size_t sz, int base)
long v; long v;
if (sz > 31) if (sz > 31)
return(-1); return -1;
memcpy(buf, p, sz); memcpy(buf, p, sz);
buf[(int)sz] = '\0'; buf[(int)sz] = '\0';
@ -604,12 +595,12 @@ mandoc_strntoi(const char *p, size_t sz, int base)
v = strtol(buf, &ep, base); v = strtol(buf, &ep, base);
if (buf[0] == '\0' || *ep != '\0') if (buf[0] == '\0' || *ep != '\0')
return(-1); return -1;
if (v > INT_MAX) if (v > INT_MAX)
v = INT_MAX; v = INT_MAX;
if (v < INT_MIN) if (v < INT_MIN)
v = INT_MIN; v = INT_MIN;
return((int)v); return (int)v;
} }

View File

@ -1,4 +1,4 @@
/* $Id: style.css,v 1.31 2015/02/10 08:05:30 schwarze Exp $ */ /* $Id: mandoc.css,v 1.1 2015/11/05 17:47:51 schwarze Exp $ */
/* /*
* This is an example style-sheet provided for mandoc(1) and the -Thtml * This is an example style-sheet provided for mandoc(1) and the -Thtml
@ -11,6 +11,19 @@
html { max-width: 880px; margin-left: 1em; } html { max-width: 880px; margin-left: 1em; }
body { font-size: smaller; font-family: Helvetica,Arial,sans-serif; } body { font-size: smaller; font-family: Helvetica,Arial,sans-serif; }
body > div { padding-left: 2em;
padding-top: 1em; }
body > div.mandoc,
body > div#mancgi { padding-left: 0em;
padding-top: 0em; }
body > div.results { font-size: smaller; }
#mancgi fieldset { text-align: center;
border: thin solid silver;
border-radius: 1em;
font-size: small; }
#mancgi input[name=expr] { width: 25%; }
.results td.title { vertical-align: top;
padding-right: 1em; }
h1 { margin-bottom: 1ex; font-size: 110%; margin-left: -4ex; } /* Section header (Sh, SH). */ h1 { margin-bottom: 1ex; font-size: 110%; margin-left: -4ex; } /* Section header (Sh, SH). */
h2 { margin-bottom: 1ex; font-size: 105%; margin-left: -2ex; } /* Sub-section header (Ss, SS). */ h2 { margin-bottom: 1ex; font-size: 105%; margin-left: -2ex; } /* Sub-section header (Ss, SS). */
table { width: 100%; margin-top: 0ex; margin-bottom: 0ex; } /* All tables. */ table { width: 100%; margin-top: 0ex; margin-bottom: 0ex; } /* All tables. */

View File

@ -1,15 +1,15 @@
/* $Id: mandoc.h,v 1.201 2015/02/23 13:31:04 schwarze Exp $ */ /* $Id: mandoc.h,v 1.209 2016/01/08 02:53:13 schwarze Exp $ */
/* /*
* Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -86,7 +86,6 @@ enum mandocerr {
MANDOCERR_BLK_NEST, /* blocks badly nested: macro ... */ MANDOCERR_BLK_NEST, /* blocks badly nested: macro ... */
MANDOCERR_BD_NEST, /* nested displays are not portable: macro ... */ MANDOCERR_BD_NEST, /* nested displays are not portable: macro ... */
MANDOCERR_BL_MOVE, /* moving content out of list: macro */ MANDOCERR_BL_MOVE, /* moving content out of list: macro */
MANDOCERR_VT_CHILD, /* .Vt block has child macro: macro */
MANDOCERR_FI_SKIP, /* fill mode already enabled, skipping: fi */ MANDOCERR_FI_SKIP, /* fill mode already enabled, skipping: fi */
MANDOCERR_NF_SKIP, /* fill mode already disabled, skipping: nf */ MANDOCERR_NF_SKIP, /* fill mode already disabled, skipping: nf */
MANDOCERR_BLK_LINE, /* line scope broken: macro breaks macro */ MANDOCERR_BLK_LINE, /* line scope broken: macro breaks macro */
@ -173,6 +172,7 @@ enum mandocerr {
/* related to request and macro arguments */ /* related to request and macro arguments */
MANDOCERR_NAMESC, /* escaped character not allowed in a name: name */ MANDOCERR_NAMESC, /* escaped character not allowed in a name: name */
MANDOCERR_BD_FILE, /* NOT IMPLEMENTED: Bd -file */ MANDOCERR_BD_FILE, /* NOT IMPLEMENTED: Bd -file */
MANDOCERR_BD_NOARG, /* skipping display without arguments: Bd */
MANDOCERR_BL_NOTYPE, /* missing list type, using -item: Bl */ MANDOCERR_BL_NOTYPE, /* missing list type, using -item: Bl */
MANDOCERR_NM_NONAME, /* missing manual name, using "": Nm */ MANDOCERR_NM_NONAME, /* missing manual name, using "": Nm */
MANDOCERR_OS_UNAME, /* uname(3) system call failed, using UNKNOWN */ MANDOCERR_OS_UNAME, /* uname(3) system call failed, using UNKNOWN */
@ -408,37 +408,28 @@ enum mandoc_esc {
typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel, typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel,
const char *, int, int, const char *); const char *, int, int, const char *);
__BEGIN_DECLS
struct mparse; struct mparse;
struct mchars; struct roff_man;
struct mdoc;
struct man;
enum mandoc_esc mandoc_escape(const char **, const char **, int *); enum mandoc_esc mandoc_escape(const char **, const char **, int *);
struct mchars *mchars_alloc(void); void mchars_alloc(void);
void mchars_free(struct mchars *); void mchars_free(void);
int mchars_num2char(const char *, size_t); int mchars_num2char(const char *, size_t);
const char *mchars_uc2str(int); const char *mchars_uc2str(int);
int mchars_num2uc(const char *, size_t); int mchars_num2uc(const char *, size_t);
int mchars_spec2cp(const struct mchars *, int mchars_spec2cp(const char *, size_t);
const char *, size_t); const char *mchars_spec2str(const char *, size_t, size_t *);
const char *mchars_spec2str(const struct mchars *, struct mparse *mparse_alloc(int, enum mandoclevel, mandocmsg, const char *);
const char *, size_t, size_t *);
struct mparse *mparse_alloc(int, enum mandoclevel, mandocmsg,
const struct mchars *, const char *);
void mparse_free(struct mparse *); void mparse_free(struct mparse *);
void mparse_keep(struct mparse *); void mparse_keep(struct mparse *);
enum mandoclevel mparse_open(struct mparse *, int *, const char *); int mparse_open(struct mparse *, const char *);
enum mandoclevel mparse_readfd(struct mparse *, int, const char *); enum mandoclevel mparse_readfd(struct mparse *, int, const char *);
enum mandoclevel mparse_readmem(struct mparse *, void *, size_t, enum mandoclevel mparse_readmem(struct mparse *, void *, size_t,
const char *); const char *);
void mparse_reset(struct mparse *); void mparse_reset(struct mparse *);
void mparse_result(struct mparse *, void mparse_result(struct mparse *,
struct mdoc **, struct man **, char **); struct roff_man **, char **);
const char *mparse_getkeep(const struct mparse *); const char *mparse_getkeep(const struct mparse *);
const char *mparse_strerror(enum mandocerr); const char *mparse_strerror(enum mandocerr);
const char *mparse_strlevel(enum mandoclevel); const char *mparse_strlevel(enum mandoclevel);
enum mandoclevel mparse_wait(struct mparse *);
__END_DECLS

View File

@ -1,4 +1,4 @@
/* $Id: mandoc_aux.c,v 1.4 2014/08/10 23:54:41 schwarze Exp $ */ /* $Id: mandoc_aux.c,v 1.9 2015/11/07 14:22:29 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -19,6 +19,9 @@
#include <sys/types.h> #include <sys/types.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -27,6 +30,7 @@
#include "mandoc.h" #include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
int int
mandoc_asprintf(char **dest, const char *fmt, ...) mandoc_asprintf(char **dest, const char *fmt, ...)
{ {
@ -37,11 +41,9 @@ mandoc_asprintf(char **dest, const char *fmt, ...)
ret = vasprintf(dest, fmt, ap); ret = vasprintf(dest, fmt, ap);
va_end(ap); va_end(ap);
if (-1 == ret) { if (ret == -1)
perror(NULL); err((int)MANDOCLEVEL_SYSERR, NULL);
exit((int)MANDOCLEVEL_SYSERR); return ret;
}
return(ret);
} }
void * void *
@ -50,11 +52,9 @@ mandoc_calloc(size_t num, size_t size)
void *ptr; void *ptr;
ptr = calloc(num, size); ptr = calloc(num, size);
if (NULL == ptr) { if (ptr == NULL)
perror(NULL); err((int)MANDOCLEVEL_SYSERR, NULL);
exit((int)MANDOCLEVEL_SYSERR); return ptr;
}
return(ptr);
} }
void * void *
@ -63,11 +63,9 @@ mandoc_malloc(size_t size)
void *ptr; void *ptr;
ptr = malloc(size); ptr = malloc(size);
if (NULL == ptr) { if (ptr == NULL)
perror(NULL); err((int)MANDOCLEVEL_SYSERR, NULL);
exit((int)MANDOCLEVEL_SYSERR); return ptr;
}
return(ptr);
} }
void * void *
@ -75,11 +73,9 @@ mandoc_realloc(void *ptr, size_t size)
{ {
ptr = realloc(ptr, size); ptr = realloc(ptr, size);
if (NULL == ptr) { if (ptr == NULL)
perror(NULL); err((int)MANDOCLEVEL_SYSERR, NULL);
exit((int)MANDOCLEVEL_SYSERR); return ptr;
}
return(ptr);
} }
void * void *
@ -87,11 +83,9 @@ mandoc_reallocarray(void *ptr, size_t num, size_t size)
{ {
ptr = reallocarray(ptr, num, size); ptr = reallocarray(ptr, num, size);
if (NULL == ptr) { if (ptr == NULL)
perror(NULL); err((int)MANDOCLEVEL_SYSERR, NULL);
exit((int)MANDOCLEVEL_SYSERR); return ptr;
}
return(ptr);
} }
char * char *
@ -100,11 +94,9 @@ mandoc_strdup(const char *ptr)
char *p; char *p;
p = strdup(ptr); p = strdup(ptr);
if (NULL == p) { if (p == NULL)
perror(NULL); err((int)MANDOCLEVEL_SYSERR, NULL);
exit((int)MANDOCLEVEL_SYSERR); return p;
}
return(p);
} }
char * char *
@ -115,5 +107,5 @@ mandoc_strndup(const char *ptr, size_t sz)
p = mandoc_malloc(sz + 1); p = mandoc_malloc(sz + 1);
memcpy(p, ptr, sz); memcpy(p, ptr, sz);
p[(int)sz] = '\0'; p[(int)sz] = '\0';
return(p); return p;
} }

View File

@ -1,4 +1,4 @@
/* $Id: mandoc_aux.h,v 1.3 2014/12/01 04:05:32 schwarze Exp $ */ /* $Id: mandoc_aux.h,v 1.4 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -16,8 +16,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
__BEGIN_DECLS
int mandoc_asprintf(char **, const char *, ...); int mandoc_asprintf(char **, const char *, ...);
void *mandoc_calloc(size_t, size_t); void *mandoc_calloc(size_t, size_t);
void *mandoc_malloc(size_t); void *mandoc_malloc(size_t);
@ -25,5 +23,3 @@ void *mandoc_realloc(void *, size_t);
void *mandoc_reallocarray(void *, size_t, size_t); void *mandoc_reallocarray(void *, size_t, size_t);
char *mandoc_strdup(const char *); char *mandoc_strdup(const char *);
char *mandoc_strndup(const char *, size_t); char *mandoc_strndup(const char *, size_t);
__END_DECLS

View File

@ -1,8 +1,8 @@
.\" $Id: mandoc_char.7,v 1.59 2015/01/20 19:39:34 schwarze Exp $ .\" $Id: mandoc_char.7,v 1.63 2015/09/02 15:38:35 schwarze Exp $
.\" .\"
.\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org> .\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2011, 2013, 2015 Ingo Schwarze <schwarze@openbsd.org>
.\" .\"
.\" Permission to use, copy, modify, and distribute this software for any .\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above .\" purpose with or without fee is hereby granted, provided that the above
@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: January 20 2015 $ .Dd $Mdocdate: September 2 2015 $
.Dt MANDOC_CHAR 7 .Dt MANDOC_CHAR 7
.Os .Os
.Sh NAME .Sh NAME
@ -49,7 +49,7 @@ names; instead, provide ASCII transcriptions of the names.
.Ss Dashes and Hyphens .Ss Dashes and Hyphens
In typography there are different types of dashes of various width: In typography there are different types of dashes of various width:
the hyphen (-), the hyphen (-),
the minus sign (\-), the minus sign (\(mi),
the en-dash (\(en), the en-dash (\(en),
and the em-dash (\(em). and the em-dash (\(em).
.Pp .Pp
@ -64,10 +64,10 @@ lorry-driver
.Pp .Pp
The mathematical minus sign is used for negative numbers or subtraction. The mathematical minus sign is used for negative numbers or subtraction.
It should be written as It should be written as
.Sq \e- : .Sq \e(mi :
.Bd -unfilled -offset indent .Bd -unfilled -offset indent
a = 3 \e- 1; a = 3 \e(mi 1;
b = \e-2; b = \e(mi2;
.Ed .Ed
.Pp .Pp
The en-dash is used to separate the two elements of a range, The en-dash is used to separate the two elements of a range,
@ -142,6 +142,28 @@ Note that on text lines, literal double-quote characters can be used
verbatim. verbatim.
All other quote-like characters can be used verbatim as well, All other quote-like characters can be used verbatim as well,
even on request and macro lines. even on request and macro lines.
.Ss Accents
In output modes supporting such special output characters, for example
.Fl T Cm pdf ,
some
.Xr roff 7
formatters convert the following ASCII input characters to the
following Unicode special output characters:
.Bl -column x(ga U+2018 -offset indent
.It \(ga Ta U+2018 Ta left single quotation mark
.It \(aq Ta U+2019 Ta right single quotation mark
.It \(ti Ta U+02DC Ta small tilde
.El
.Pp
In prose, this automatic substitution is often desirable;
but when these characters have to be displayed as plain ASCII
characters, for example in source code samples, they require
escaping to render as follows:
.Bl -column x(ga U+2018 -offset indent
.It \e(ga Ta U+0060 Ta grave accent
.It \e(aq Ta U+0027 Ta apostrophe
.It \e(ti Ta U+007E Ta tilde
.El
.Ss Periods .Ss Periods
The period The period
.Pq Sq \&. .Pq Sq \&.
@ -196,7 +218,7 @@ Spacing:
.Bl -column "Input" "Description" -offset indent -compact .Bl -column "Input" "Description" -offset indent -compact
.It Em Input Ta Em Description .It Em Input Ta Em Description
.It Sq \e\ \& Ta unpaddable non-breaking space .It Sq \e\ \& Ta unpaddable non-breaking space
.It \e~ Ta paddable non-breaking space .It \e\(ti Ta paddable non-breaking space
.It \e0 Ta unpaddable, breaking digit-width 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-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 one-twelfth \e(em half-narrow space, zero width in nroff
@ -371,9 +393,9 @@ Mathematical:
.It \e(ne Ta \(ne Ta not equivalent .It \e(ne Ta \(ne Ta not equivalent
.It \e(ap Ta \(ap Ta tilde operator .It \e(ap Ta \(ap Ta tilde operator
.It \e(|= Ta \(|= Ta asymptotically equal .It \e(|= Ta \(|= Ta asymptotically equal
.It \e(=~ Ta \(=~ Ta approximately equal .It \e(=\(ti Ta \(=~ Ta approximately equal
.It \e(~~ Ta \(~~ Ta almost equal .It \e(\(ti\(ti Ta \(~~ Ta almost equal
.It \e(~= Ta \(~= Ta almost equal .It \e(\(ti= Ta \(~= Ta almost equal
.It \e(pt Ta \(pt Ta proportionate .It \e(pt Ta \(pt Ta proportionate
.It \e(es Ta \(es Ta empty set .It \e(es Ta \(es Ta empty set
.It \e(mo Ta \(mo Ta element .It \e(mo Ta \(mo Ta element
@ -436,15 +458,15 @@ Accents:
.It \e(a. Ta \(a. Ta dotted .It \e(a. Ta \(a. Ta dotted
.It \e(a^ Ta \(a^ Ta circumflex .It \e(a^ Ta \(a^ Ta circumflex
.It \e(aa Ta \(aa Ta acute .It \e(aa Ta \(aa Ta acute
.It \e' Ta \' Ta acute .It \e\(aq Ta \' Ta acute
.It \e(ga Ta \(ga Ta grave .It \e(ga Ta \(ga Ta grave
.It \e` Ta \` Ta grave .It \e\(ga Ta \` Ta grave
.It \e(ab Ta \(ab Ta breve .It \e(ab Ta \(ab Ta breve
.It \e(ac Ta \(ac Ta cedilla .It \e(ac Ta \(ac Ta cedilla
.It \e(ad Ta \(ad Ta dieresis .It \e(ad Ta \(ad Ta dieresis
.It \e(ah Ta \(ah Ta caron .It \e(ah Ta \(ah Ta caron
.It \e(ao Ta \(ao Ta ring .It \e(ao Ta \(ao Ta ring
.It \e(a~ Ta \(a~ Ta tilde .It \e(a\(ti Ta \(a~ Ta tilde
.It \e(ho Ta \(ho Ta ogonek .It \e(ho Ta \(ho Ta ogonek
.It \e(ha Ta \(ha Ta hat (text) .It \e(ha Ta \(ha Ta hat (text)
.It \e(ti Ta \(ti Ta tilde (text) .It \e(ti Ta \(ti Ta tilde (text)
@ -453,32 +475,32 @@ Accents:
Accented letters: Accented letters:
.Bl -column "Input" "Rendered" "Description" -offset indent -compact .Bl -column "Input" "Rendered" "Description" -offset indent -compact
.It Em Input Ta Em Rendered Ta Em Description .It Em Input Ta Em Rendered Ta Em Description
.It \e('A Ta \('A Ta acute A .It \e(\(aqA Ta \('A Ta acute A
.It \e('E Ta \('E Ta acute E .It \e(\(aqE Ta \('E Ta acute E
.It \e('I Ta \('I Ta acute I .It \e(\(aqI Ta \('I Ta acute I
.It \e('O Ta \('O Ta acute O .It \e(\(aqO Ta \('O Ta acute O
.It \e('U Ta \('U Ta acute U .It \e(\(aqU Ta \('U Ta acute U
.It \e('a Ta \('a Ta acute a .It \e(\(aqa Ta \('a Ta acute a
.It \e('e Ta \('e Ta acute e .It \e(\(aqe Ta \('e Ta acute e
.It \e('i Ta \('i Ta acute i .It \e(\(aqi Ta \('i Ta acute i
.It \e('o Ta \('o Ta acute o .It \e(\(aqo Ta \('o Ta acute o
.It \e('u Ta \('u Ta acute u .It \e(\(aqu Ta \('u Ta acute u
.It \e(`A Ta \(`A Ta grave A .It \e(\(gaA Ta \(`A Ta grave A
.It \e(`E Ta \(`E Ta grave E .It \e(\(gaE Ta \(`E Ta grave E
.It \e(`I Ta \(`I Ta grave I .It \e(\(gaI Ta \(`I Ta grave I
.It \e(`O Ta \(`O Ta grave O .It \e(\(gaO Ta \(`O Ta grave O
.It \e(`U Ta \(`U Ta grave U .It \e(\(gaU Ta \(`U Ta grave U
.It \e(`a Ta \(`a Ta grave a .It \e(\(gaa Ta \(`a Ta grave a
.It \e(`e Ta \(`e Ta grave e .It \e(\(gae Ta \(`e Ta grave e
.It \e(`i Ta \(`i Ta grave i .It \e(\(gai Ta \(`i Ta grave i
.It \e(`o Ta \(`i Ta grave o .It \e(\(gao Ta \(`i Ta grave o
.It \e(`u Ta \(`u Ta grave u .It \e(\(gau Ta \(`u Ta grave u
.It \e(~A Ta \(~A Ta tilde A .It \e(\(tiA Ta \(~A Ta tilde A
.It \e(~N Ta \(~N Ta tilde N .It \e(\(tiN Ta \(~N Ta tilde N
.It \e(~O Ta \(~O Ta tilde O .It \e(\(tiO Ta \(~O Ta tilde O
.It \e(~a Ta \(~a Ta tilde a .It \e(\(tia Ta \(~a Ta tilde a
.It \e(~n Ta \(~n Ta tilde n .It \e(\(tin Ta \(~n Ta tilde n
.It \e(~o Ta \(~o Ta tilde o .It \e(\(tio Ta \(~o Ta tilde o
.It \e(:A Ta \(:A Ta dieresis A .It \e(:A Ta \(:A Ta dieresis A
.It \e(:E Ta \(:E Ta dieresis E .It \e(:E Ta \(:E Ta dieresis E
.It \e(:I Ta \(:I Ta dieresis I .It \e(:I Ta \(:I Ta dieresis I
@ -657,7 +679,7 @@ manual.
.Sh UNICODE CHARACTERS .Sh UNICODE CHARACTERS
The escape sequences The escape sequences
.Pp .Pp
.Dl \e[uXXXX] and \eC'uXXXX' .Dl \e[uXXXX] and \eC\(aquXXXX\(aq
.Pp .Pp
are interpreted as Unicode codepoints. are interpreted as Unicode codepoints.
The codepoint must be in the range above U+0080 and less than U+10FFFF. The codepoint must be in the range above U+0080 and less than U+10FFFF.
@ -669,10 +691,6 @@ must be given as uppercase characters,
and points must be zero-padded to four characters; if and points must be zero-padded to four characters; if
greater than four characters, no zero padding is allowed. greater than four characters, no zero padding is allowed.
Unicode surrogates are not allowed. Unicode surrogates are not allowed.
.\" .Pp
.\" Unicode glyphs attenuate to the
.\" .Sq \&?
.\" character if invalid or not rendered by current output media.
.Sh NUMBERED CHARACTERS .Sh NUMBERED CHARACTERS
For backward compatibility with existing manuals, For backward compatibility with existing manuals,
.Xr mandoc 1 .Xr mandoc 1
@ -685,7 +703,7 @@ escape sequence, inserting the character
from the current character set into the output. from the current character set into the output.
Of course, this is inherently non-portable and is already marked Of course, this is inherently non-portable and is already marked
as deprecated in the Heirloom roff manual. as deprecated in the Heirloom roff manual.
For example, do not use \eN'34', use \e(dq, or even the plain For example, do not use \eN\(aq34\(aq, use \e(dq, or even the plain
.Sq \(dq .Sq \(dq
character where possible. character where possible.
.Sh COMPATIBILITY .Sh COMPATIBILITY
@ -702,14 +720,14 @@ In
.Fl T Ns Cm ascii , .Fl T Ns Cm ascii ,
the the
\e(ss, \e(nm, \e(nb, \e(nc, \e(ib, \e(ip, \e(pp, \e[sum], \e[product], \e(ss, \e(nm, \e(nb, \e(nc, \e(ib, \e(ip, \e(pp, \e[sum], \e[product],
\e[coproduct], \e(gr, \e(\-h, and \e(a. special characters render \e[coproduct], \e(gr, \e(-h, and \e(a. special characters render
differently between mandoc and groff. differently between mandoc and groff.
.It .It
In In
.Fl T Ns Cm html .Fl T Ns Cm html
and and
.Fl T Ns Cm xhtml , .Fl T Ns Cm xhtml ,
the \e(~=, \e(nb, and \e(nc special characters render differently the \e(\(ti=, \e(nb, and \e(nc special characters render differently
between mandoc and groff. between mandoc and groff.
.It .It
The The

View File

@ -54,7 +54,6 @@ require inclusion of the header where that type is defined.
Each of the following headers can be included without including Each of the following headers can be included without including
any other mandoc header. any other mandoc header.
These headers should be included before any other mandoc headers. These headers should be included before any other mandoc headers.
Afterwards, any other mandoc headers can be included as needed.
.Bl -tag -width Ds .Bl -tag -width Ds
.It Qq Pa mandoc_aux.h .It Qq Pa mandoc_aux.h
Requires Requires
@ -99,14 +98,10 @@ and the functions
described in described in
.Xr mandoc 3 . .Xr mandoc 3 .
.Pp .Pp
Uses the opaque types Uses the opaque type
.Vt struct mparse .Vt struct mparse
from from
.Pa read.c .Pa read.c
and
.Vt struct mchars
from
.Pa chars.c
for function prototypes. for function prototypes.
Uses the types Uses the types
.Vt struct mdoc .Vt struct mdoc
@ -117,23 +112,45 @@ and
from from
.Pa libman.h .Pa libman.h
as opaque types for function prototypes. as opaque types for function prototypes.
.It Qq Pa roff.h
Provides
.Vt enum mdoc_endbody ,
.Vt enum roff_sec ,
.Vt enum roff_type ,
.Vt struct roff_meta ,
and
.Vt struct roff_node .
.Pp
Uses pointers to the types
.Vt struct mdoc_arg
and
.Vt union mdoc_data
from
.Qq Pa mdoc.h
as opaque struct members.
.El
.Pp
The following two require
.Qq Pa roff.h
but no other mandoc headers.
Afterwards, any other mandoc headers can be included as needed.
.Bl -tag -width Ds
.It Qq Pa mdoc.h .It Qq Pa mdoc.h
Requires Requires
.In sys/types.h .In sys/types.h
for for
.Vt size_t . .Vt size_t
and
.Qq Pa roff.h
for
.Vt enum roff_type .
.Pp .Pp
Provides Provides
.Vt enum mdoct ,
.Vt enum mdocargt , .Vt enum mdocargt ,
.Vt enum mdoc_type ,
.Vt enum mdoc_sec ,
.Vt enum mdoc_endbody ,
.Vt enum mdoc_disp , .Vt enum mdoc_disp ,
.Vt enum mdoc_list , .Vt enum mdoc_list ,
.Vt enum mdoc_auth , .Vt enum mdoc_auth ,
.Vt enum mdoc_font , .Vt enum mdoc_font ,
.Vt struct mdoc_meta ,
.Vt struct mdoc_argv , .Vt struct mdoc_argv ,
.Vt struct mdoc_arg , .Vt struct mdoc_arg ,
.Vt struct mdoc_bd , .Vt struct mdoc_bd ,
@ -141,7 +158,6 @@ Provides
.Vt struct mdoc_an , .Vt struct mdoc_an ,
.Vt struct mdoc_bf , .Vt struct mdoc_bf ,
.Vt struct mdoc_rs , .Vt struct mdoc_rs ,
.Vt struct mdoc_node ,
and the functions and the functions
.Fn mdoc_* .Fn mdoc_*
described in described in
@ -163,12 +179,12 @@ When this header is included, the same file should not include
or or
.Pa libroff.h . .Pa libroff.h .
.It Qq Pa man.h .It Qq Pa man.h
Provides Requires
.Vt enum mant , .Qq Pa roff.h
.Vt enum man_type , for
.Vt struct man_meta , .Vt enum roff_type .
.Vt struct man_node , .Pp
and the functions Provides the functions
.Fn man_* .Fn man_*
described in described in
.Xr mandoc 3 . .Xr mandoc 3 .
@ -204,11 +220,16 @@ are included, the same file should not include any formatter headers.
Requires Requires
.In sys/types.h .In sys/types.h
for for
.Vt size_t .Vt size_t ,
and
.Qq Pa mandoc.h .Qq Pa mandoc.h
for for
.Vt enum mandocerr . .Vt enum mandocerr ,
and
.Qq Pa roff.h
for
.Vt struct roff_meta
and
.Vt struct roff_node .
.Pp .Pp
Provides Provides
.Vt enum rofferr , .Vt enum rofferr ,
@ -243,8 +264,7 @@ as opaque types for function prototypes.
Requires Requires
.Qq Pa mdoc.h .Qq Pa mdoc.h
for for
.Vt enum mdoct , .Vt enum mdoc_*
.Vt enum mdoc_* ,
and and
.Vt struct mdoc_* . .Vt struct mdoc_* .
.Pp .Pp
@ -274,11 +294,11 @@ or
.Pa libroff.h . .Pa libroff.h .
.It Qq Pa libman.h .It Qq Pa libman.h
Requires Requires
.Qq Pa man.h .Qq Pa roff.h
for for
.Vt enum mant .Vt struct roff_meta
and and
.Vt struct man_node. .Vt struct roff_node .
.Pp .Pp
Provides Provides
.Vt enum man_next , .Vt enum man_next ,
@ -366,8 +386,6 @@ from
as an opaque type for function prototypes. as an opaque type for function prototypes.
.Pp .Pp
When this header is included, the same file should not include When this header is included, the same file should not include
.Pa manpath.h
or
.Pa mansearch.h . .Pa mansearch.h .
.It Qq Pa term.h .It Qq Pa term.h
Requires Requires
@ -389,11 +407,7 @@ Provides
.Vt struct termp , .Vt struct termp ,
and many terminal formatting functions. and many terminal formatting functions.
.Pp .Pp
Uses the opaque types Uses the opaque type
.Vt struct mchars
from
.Pa chars.c
and
.Vt struct termp_ps .Vt struct termp_ps
from from
.Pa term_ps.c . .Pa term_ps.c .
@ -403,11 +417,14 @@ and
.Vt struct eqn .Vt struct eqn
from from
.Pa mandoc.h .Pa mandoc.h
and
.Vt struct roff_meta
from
.Qq Pa roff.h
as opaque types for function prototypes. as opaque types for function prototypes.
.Pp .Pp
When this header is included, the same file should not include When this header is included, the same file should not include
.Pa html.h , .Pa html.h
.Pa manpath.h
or or
.Pa mansearch.h . .Pa mansearch.h .
.It Qq Pa html.h .It Qq Pa html.h
@ -435,23 +452,13 @@ Provides
.Vt struct html , .Vt struct html ,
and many HTML formatting functions. and many HTML formatting functions.
.Pp .Pp
Uses the opaque type
.Vt struct mchars
from
.Pa chars.c .
.Pp
When this header is included, the same file should not include When this header is included, the same file should not include
.Pa term.h , .Pa term.h
.Pa manpath.h
or or
.Pa mansearch.h . .Pa mansearch.h .
.It Qq Pa main.h .It Qq Pa main.h
Provides the top level steering functions for all formatters. Provides the top level steering functions for all formatters.
.Pp .Pp
Uses the opaque type
.Vt struct mchars
from
.Pa chars.c .
Uses the types Uses the types
.Vt struct mdoc .Vt struct mdoc
from from
@ -461,25 +468,21 @@ and
from from
.Pa libman.h .Pa libman.h
as opaque types for function prototypes. as opaque types for function prototypes.
.It Qq Pa manpath.h .It Qq Pa manconf.h
Requires Requires
.In sys/types.h .In sys/types.h
for for
.Vt size_t . .Vt size_t .
.Pp .Pp
Provides Provides
.Vt struct manpaths .Vt struct manconf ,
.Vt struct manpaths ,
.Vt struct manoutput ,
and the functions and the functions
.Fn manpath_manconf , .Fn manconf_parse ,
.Fn manpath_parse , .Fn manconf_output ,
and and
.Fn manpath_free . .Fn manconf_free .
.Pp
When this header is included, the same file should not include
.Pa out.h ,
.Pa term.h ,
or
.Pa html.h .
.It Qq Pa mansearch.h .It Qq Pa mansearch.h
Requires Requires
.In sys/types.h .In sys/types.h
@ -503,7 +506,7 @@ and
Uses Uses
.Vt struct manpaths .Vt struct manpaths
from from
.Pa manpath.h .Pa manconf.h
as an opaque type for function prototypes. as an opaque type for function prototypes.
.Pp .Pp
When this header is included, the same file should not include When this header is included, the same file should not include

View File

@ -0,0 +1,63 @@
/* $Id: mandoc_ohash.c,v 1.2 2015/10/19 18:58:47 schwarze Exp $ */
/*
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include "mandoc_aux.h"
#include "mandoc_ohash.h"
static void *hash_alloc(size_t, void *);
static void *hash_calloc(size_t, size_t, void *);
static void hash_free(void *, void *);
void
mandoc_ohash_init(struct ohash *h, unsigned int sz, ptrdiff_t ko)
{
struct ohash_info info;
info.alloc = hash_alloc;
info.calloc = hash_calloc;
info.free = hash_free;
info.data = NULL;
info.key_offset = ko;
ohash_init(h, sz, &info);
}
static void *
hash_alloc(size_t sz, void *arg)
{
return mandoc_malloc(sz);
}
static void *
hash_calloc(size_t n, size_t sz, void *arg)
{
return mandoc_calloc(n, sz);
}
static void
hash_free(void *p, void *arg)
{
free(p);
}

View File

@ -0,0 +1,23 @@
/* $Id: mandoc_ohash.h,v 1.2 2015/11/07 14:01:16 schwarze Exp $ */
/*
* Copyright (c) 2015 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 HAVE_OHASH
#include <ohash.h>
#else
#include "compat_ohash.h"
#endif
void mandoc_ohash_init(struct ohash *, unsigned int, ptrdiff_t);

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $Id: manpage.c,v 1.10 2015/02/10 08:05:30 schwarze Exp $ */ /* $Id: manpage.c,v 1.13 2015/11/07 17:58:55 schwarze Exp $ */
/* /*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
@ -28,7 +28,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "manpath.h" #include "manconf.h"
#include "mansearch.h" #include "mansearch.h"
static void show(const char *, const char *); static void show(const char *, const char *);
@ -37,13 +37,14 @@ int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int ch, term; int ch, term;
size_t i, sz, len; size_t i, sz, linesz;
ssize_t len;
struct mansearch search; struct mansearch search;
struct manpage *res; struct manpage *res;
char *conf_file, *defpaths, *auxpaths, *cp; char *conf_file, *defpaths, *auxpaths, *line;
char buf[PATH_MAX]; char buf[PATH_MAX];
const char *cmd; const char *cmd;
struct manpaths paths; struct manconf conf;
char *progname; char *progname;
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
@ -57,7 +58,7 @@ main(int argc, char *argv[])
++progname; ++progname;
auxpaths = defpaths = conf_file = NULL; auxpaths = defpaths = conf_file = NULL;
memset(&paths, 0, sizeof(struct manpaths)); memset(&conf, 0, sizeof(conf));
memset(&search, 0, sizeof(struct mansearch)); memset(&search, 0, sizeof(struct mansearch));
while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:"))) while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
@ -90,21 +91,21 @@ main(int argc, char *argv[])
search.outkey = "Nd"; search.outkey = "Nd";
search.argmode = ARG_EXPR; search.argmode = ARG_EXPR;
manpath_parse(&paths, conf_file, defpaths, auxpaths); manconf_parse(&conf, conf_file, defpaths, auxpaths);
ch = mansearch(&search, &paths, argc, argv, &res, &sz); ch = mansearch(&search, &conf.manpath, argc, argv, &res, &sz);
manpath_free(&paths); manconf_free(&conf);
if (0 == ch) if (0 == ch)
goto usage; goto usage;
if (0 == sz) { if (0 == sz) {
free(res); free(res);
return(EXIT_FAILURE); return EXIT_FAILURE;
} else if (1 == sz && term) { } else if (1 == sz && term) {
i = 1; i = 1;
goto show; goto show;
} else if (NULL == res) } else if (NULL == res)
return(EXIT_FAILURE); return EXIT_FAILURE;
for (i = 0; i < sz; i++) { for (i = 0; i < sz; i++) {
printf("%6zu %s: %s\n", printf("%6zu %s: %s\n",
@ -117,25 +118,29 @@ main(int argc, char *argv[])
for (i = 0; i < sz; i++) for (i = 0; i < sz; i++)
free(res[i].file); free(res[i].file);
free(res); free(res);
return(EXIT_SUCCESS); return EXIT_SUCCESS;
} }
i = 1; i = 1;
printf("Enter a choice [1]: "); printf("Enter a choice [1]: ");
fflush(stdout); fflush(stdout);
if (NULL != (cp = fgetln(stdin, &len))) line = NULL;
if ('\n' == cp[--len] && len > 0) { linesz = 0;
cp[len] = '\0'; if ((len = getline(&line, &linesz, stdin)) != -1) {
if ((i = atoi(cp)) < 1 || i > sz) if ('\n' == line[--len] && len > 0) {
line[len] = '\0';
if ((i = atoi(line)) < 1 || i > sz)
i = 0; i = 0;
} }
}
free(line);
if (0 == i) { if (0 == i) {
for (i = 0; i < sz; i++) for (i = 0; i < sz; i++)
free(res[i].file); free(res[i].file);
free(res); free(res);
return(EXIT_SUCCESS); return EXIT_SUCCESS;
} }
show: show:
cmd = res[i - 1].form ? "mandoc" : "cat"; cmd = res[i - 1].form ? "mandoc" : "cat";
@ -154,7 +159,7 @@ main(int argc, char *argv[])
"[-s section] " "[-s section] "
"expr ...\n", "expr ...\n",
progname); progname);
return(EXIT_FAILURE); return EXIT_FAILURE;
} }
static void static void

View File

@ -1,15 +1,15 @@
/* $Id: manpath.c,v 1.19 2014/11/27 00:30:40 schwarze Exp $ */ /* $Id: manpath.c,v 1.29 2015/11/07 17:58:55 schwarze Exp $ */
/* /*
* Copyright (c) 2011, 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -20,24 +20,27 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <assert.h>
#include <ctype.h> #include <ctype.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <limits.h> #include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "manpath.h" #include "manconf.h"
#define MAN_CONF_FILE "/etc/man.conf"
#define MAN_CONF_KEY "_whatdb"
#if !HAVE_MANPATH
static void manconf_file(struct manconf *, const char *);
#endif
static void manpath_add(struct manpaths *, const char *, int); static void manpath_add(struct manpaths *, const char *, int);
static void manpath_parseline(struct manpaths *, char *, int); static void manpath_parseline(struct manpaths *, char *, int);
void void
manpath_parse(struct manpaths *dirs, const char *file, manconf_parse(struct manconf *conf, const char *file,
char *defp, char *auxp) char *defp, char *auxp)
{ {
#if HAVE_MANPATH #if HAVE_MANPATH
@ -80,7 +83,7 @@ manpath_parse(struct manpaths *dirs, const char *file,
if ( ! ferror(stream) && feof(stream) && if ( ! ferror(stream) && feof(stream) &&
bsz && '\n' == buf[bsz - 1]) { bsz && '\n' == buf[bsz - 1]) {
buf[bsz - 1] = '\0'; buf[bsz - 1] = '\0';
manpath_parseline(dirs, buf, 1); manpath_parseline(&conf->manpath, buf, 1);
} }
free(buf); free(buf);
@ -89,11 +92,11 @@ manpath_parse(struct manpaths *dirs, const char *file,
char *insert; char *insert;
/* Always prepend -m. */ /* Always prepend -m. */
manpath_parseline(dirs, auxp, 1); manpath_parseline(&conf->manpath, auxp, 1);
/* If -M is given, it overrides everything else. */ /* If -M is given, it overrides everything else. */
if (NULL != defp) { if (NULL != defp) {
manpath_parseline(dirs, defp, 1); manpath_parseline(&conf->manpath, defp, 1);
return; return;
} }
@ -104,21 +107,21 @@ manpath_parse(struct manpaths *dirs, const char *file,
/* No MANPATH; use man.conf(5) only. */ /* No MANPATH; use man.conf(5) only. */
if (NULL == defp || '\0' == defp[0]) { if (NULL == defp || '\0' == defp[0]) {
manpath_manconf(dirs, file); manconf_file(conf, file);
return; return;
} }
/* Prepend man.conf(5) to MANPATH. */ /* Prepend man.conf(5) to MANPATH. */
if (':' == defp[0]) { if (':' == defp[0]) {
manpath_manconf(dirs, file); manconf_file(conf, file);
manpath_parseline(dirs, defp, 0); manpath_parseline(&conf->manpath, defp, 0);
return; return;
} }
/* Append man.conf(5) to MANPATH. */ /* Append man.conf(5) to MANPATH. */
if (':' == defp[strlen(defp) - 1]) { if (':' == defp[strlen(defp) - 1]) {
manpath_parseline(dirs, defp, 0); manpath_parseline(&conf->manpath, defp, 0);
manpath_manconf(dirs, file); manconf_file(conf, file);
return; return;
} }
@ -126,14 +129,14 @@ manpath_parse(struct manpaths *dirs, const char *file,
insert = strstr(defp, "::"); insert = strstr(defp, "::");
if (NULL != insert) { if (NULL != insert) {
*insert++ = '\0'; *insert++ = '\0';
manpath_parseline(dirs, defp, 0); manpath_parseline(&conf->manpath, defp, 0);
manpath_manconf(dirs, file); manconf_file(conf, file);
manpath_parseline(dirs, insert + 1, 0); manpath_parseline(&conf->manpath, insert + 1, 0);
return; return;
} }
/* MANPATH overrides man.conf(5) completely. */ /* MANPATH overrides man.conf(5) completely. */
manpath_parseline(dirs, defp, 0); manpath_parseline(&conf->manpath, defp, 0);
#endif #endif
} }
@ -165,10 +168,8 @@ manpath_add(struct manpaths *dirs, const char *dir, int complain)
size_t i; size_t i;
if (NULL == (cp = realpath(dir, buf))) { if (NULL == (cp = realpath(dir, buf))) {
if (complain) { if (complain)
fputs("manpath: ", stderr); warn("manpath: %s", dir);
perror(dir);
}
return; return;
} }
@ -177,10 +178,8 @@ manpath_add(struct manpaths *dirs, const char *dir, int complain)
return; return;
if (stat(cp, &sb) == -1) { if (stat(cp, &sb) == -1) {
if (complain) { if (complain)
fputs("manpath: ", stderr); warn("manpath: %s", dir);
perror(dir);
}
return; return;
} }
@ -191,47 +190,147 @@ manpath_add(struct manpaths *dirs, const char *dir, int complain)
} }
void void
manpath_free(struct manpaths *p) manconf_free(struct manconf *conf)
{ {
size_t i; size_t i;
for (i = 0; i < p->sz; i++) for (i = 0; i < conf->manpath.sz; i++)
free(p->paths[i]); free(conf->manpath.paths[i]);
free(p->paths); free(conf->manpath.paths);
free(conf->output.includes);
free(conf->output.man);
free(conf->output.paper);
free(conf->output.style);
} }
#if !HAVE_MANPATH
static void
manconf_file(struct manconf *conf, const char *file)
{
const char *const toks[] = { "manpath", "output", "_whatdb" };
char manpath_default[] = MANPATH_DEFAULT;
FILE *stream;
char *line, *cp, *ep;
size_t linesz, tok, toklen;
ssize_t linelen;
if ((stream = fopen(file, "r")) == NULL)
goto out;
line = NULL;
linesz = 0;
while ((linelen = getline(&line, &linesz, stream)) != -1) {
cp = line;
ep = cp + linelen;
if (ep[-1] != '\n')
break;
*--ep = '\0';
while (isspace((unsigned char)*cp))
cp++;
if (*cp == '#')
continue;
for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
toklen = strlen(toks[tok]);
if (cp + toklen < ep &&
isspace((unsigned char)cp[toklen]) &&
strncmp(cp, toks[tok], toklen) == 0) {
cp += toklen;
while (isspace((unsigned char)*cp))
cp++;
break;
}
}
switch (tok) {
case 2: /* _whatdb */
while (ep > cp && ep[-1] != '/')
ep--;
if (ep == cp)
continue;
*ep = '\0';
/* FALLTHROUGH */
case 0: /* manpath */
manpath_add(&conf->manpath, cp, 0);
*manpath_default = '\0';
break;
case 1: /* output */
manconf_output(&conf->output, cp);
break;
default:
break;
}
}
free(line);
fclose(stream);
out:
if (*manpath_default != '\0')
manpath_parseline(&conf->manpath, manpath_default, 0);
}
#endif
void void
manpath_manconf(struct manpaths *dirs, const char *file) manconf_output(struct manoutput *conf, const char *cp)
{ {
FILE *stream; const char *const toks[] = {
char *p, *q; "includes", "man", "paper", "style",
size_t len, keysz; "indent", "width", "fragment", "mdoc"
};
keysz = strlen(MAN_CONF_KEY); size_t len, tok;
assert(keysz > 0);
if (NULL == (stream = fopen(file, "r"))) for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
return; len = strlen(toks[tok]);
if ( ! strncmp(cp, toks[tok], len) &&
while (NULL != (p = fgetln(stream, &len))) { strchr(" = ", cp[len]) != NULL) {
if (0 == len || '\n' != p[--len]) cp += len;
if (*cp == '=')
cp++;
while (isspace((unsigned char)*cp))
cp++;
break; break;
p[len] = '\0'; }
while (isspace((unsigned char)*p))
p++;
if (strncmp(MAN_CONF_KEY, p, keysz))
continue;
p += keysz;
while (isspace((unsigned char)*p))
p++;
if ('\0' == *p)
continue;
if (NULL == (q = strrchr(p, '/')))
continue;
*q = '\0';
manpath_add(dirs, p, 0);
} }
fclose(stream); if (tok < 6 && *cp == '\0')
return;
switch (tok) {
case 0:
if (conf->includes == NULL)
conf->includes = mandoc_strdup(cp);
break;
case 1:
if (conf->man == NULL)
conf->man = mandoc_strdup(cp);
break;
case 2:
if (conf->paper == NULL)
conf->paper = mandoc_strdup(cp);
break;
case 3:
if (conf->style == NULL)
conf->style = mandoc_strdup(cp);
break;
case 4:
if (conf->indent == 0)
conf->indent = strtonum(cp, 0, 1000, NULL);
break;
case 5:
if (conf->width == 0)
conf->width = strtonum(cp, 58, 1000, NULL);
break;
case 6:
conf->fragment = 1;
break;
case 7:
conf->mdoc = 1;
break;
default:
break;
}
} }

View File

@ -1,4 +1,4 @@
.\" $Id: mansearch.3,v 1.3 2014/12/12 21:44:33 schwarze Exp $ .\" $Id: mansearch.3,v 1.4 2015/03/27 17:37:25 schwarze Exp $
.\" .\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\" .\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: December 12 2014 $ .Dd $Mdocdate: March 27 2015 $
.Dt MANSEARCH 3 .Dt MANSEARCH 3
.Os .Os
.Sh NAME .Sh NAME
@ -23,7 +23,7 @@
.Nd search manual page databases .Nd search manual page databases
.Sh SYNOPSIS .Sh SYNOPSIS
.In stdint.h .In stdint.h
.In manpath.h .In manconf.h
.In mansearch.h .In mansearch.h
.Ft int .Ft int
.Fo mansearch_setup .Fo mansearch_setup
@ -53,7 +53,7 @@ Search options, defined in
.In mansearch.h . .In mansearch.h .
.It Fa "const struct manpaths *paths" .It Fa "const struct manpaths *paths"
Directories to be searched, defined in Directories to be searched, defined in
.In manpath.h . .In manconf.h .
.It Fa "int argc" , "char *argv[]" .It Fa "int argc" , "char *argv[]"
Search criteria, usually taken from the command line. Search criteria, usually taken from the command line.
.El .El

View File

@ -1,4 +1,4 @@
/* $Id: mansearch.c,v 1.55 2015/03/11 13:11:22 schwarze Exp $ */ /* $Id: mansearch.c,v 1.64 2016/01/08 15:02:54 schwarze Exp $ */
/* /*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -7,9 +7,9 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -21,6 +21,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <assert.h> #include <assert.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <getopt.h> #include <getopt.h>
@ -34,11 +37,6 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#if HAVE_OHASH
#include <ohash.h>
#else
#include "compat_ohash.h"
#endif
#include <sqlite3.h> #include <sqlite3.h>
#ifndef SQLITE_DETERMINISTIC #ifndef SQLITE_DETERMINISTIC
#define SQLITE_DETERMINISTIC 0 #define SQLITE_DETERMINISTIC 0
@ -46,7 +44,8 @@
#include "mandoc.h" #include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "manpath.h" #include "mandoc_ohash.h"
#include "manconf.h"
#include "mansearch.h" #include "mansearch.h"
extern int mansearch_keymax; extern int mansearch_keymax;
@ -55,17 +54,17 @@ extern const char *const mansearch_keynames[];
#define SQL_BIND_TEXT(_db, _s, _i, _v) \ #define SQL_BIND_TEXT(_db, _s, _i, _v) \
do { if (SQLITE_OK != sqlite3_bind_text \ do { if (SQLITE_OK != sqlite3_bind_text \
((_s), (_i)++, (_v), -1, SQLITE_STATIC)) \ ((_s), (_i)++, (_v), -1, SQLITE_STATIC)) \
fprintf(stderr, "%s\n", sqlite3_errmsg((_db))); \ errx((int)MANDOCLEVEL_SYSERR, "%s", sqlite3_errmsg((_db))); \
} while (0) } while (0)
#define SQL_BIND_INT64(_db, _s, _i, _v) \ #define SQL_BIND_INT64(_db, _s, _i, _v) \
do { if (SQLITE_OK != sqlite3_bind_int64 \ do { if (SQLITE_OK != sqlite3_bind_int64 \
((_s), (_i)++, (_v))) \ ((_s), (_i)++, (_v))) \
fprintf(stderr, "%s\n", sqlite3_errmsg((_db))); \ errx((int)MANDOCLEVEL_SYSERR, "%s", sqlite3_errmsg((_db))); \
} while (0) } while (0)
#define SQL_BIND_BLOB(_db, _s, _i, _v) \ #define SQL_BIND_BLOB(_db, _s, _i, _v) \
do { if (SQLITE_OK != sqlite3_bind_blob \ do { if (SQLITE_OK != sqlite3_bind_blob \
((_s), (_i)++, (&_v), sizeof(_v), SQLITE_STATIC)) \ ((_s), (_i)++, (&_v), sizeof(_v), SQLITE_STATIC)) \
fprintf(stderr, "%s\n", sqlite3_errmsg((_db))); \ errx((int)MANDOCLEVEL_SYSERR, "%s", sqlite3_errmsg((_db))); \
} while (0) } while (0)
struct expr { struct expr {
@ -92,9 +91,6 @@ static void buildnames(const struct mansearch *,
const char *, int form); const char *, int form);
static char *buildoutput(sqlite3 *, sqlite3_stmt *, static char *buildoutput(sqlite3 *, sqlite3_stmt *,
uint64_t, uint64_t); uint64_t, uint64_t);
static void *hash_alloc(size_t, void *);
static void hash_free(void *, void *);
static void *hash_calloc(size_t, size_t, void *);
static struct expr *exprcomp(const struct mansearch *, static struct expr *exprcomp(const struct mansearch *,
int, char *[]); int, char *[]);
static void exprfree(struct expr *); static void exprfree(struct expr *);
@ -120,8 +116,8 @@ mansearch_setup(int start)
if (start) { if (start) {
if (NULL != pagecache) { if (NULL != pagecache) {
fprintf(stderr, "pagecache already enabled\n"); warnx("pagecache already enabled");
return((int)MANDOCLEVEL_BADARG); return (int)MANDOCLEVEL_BADARG;
} }
pagecache = mmap(NULL, PC_PAGESIZE * PC_NUMPAGES, pagecache = mmap(NULL, PC_PAGESIZE * PC_NUMPAGES,
@ -129,32 +125,32 @@ mansearch_setup(int start)
MAP_SHARED | MAP_ANON, -1, 0); MAP_SHARED | MAP_ANON, -1, 0);
if (MAP_FAILED == pagecache) { if (MAP_FAILED == pagecache) {
perror("mmap"); warn("mmap");
pagecache = NULL; pagecache = NULL;
return((int)MANDOCLEVEL_SYSERR); return (int)MANDOCLEVEL_SYSERR;
} }
c = sqlite3_config(SQLITE_CONFIG_PAGECACHE, c = sqlite3_config(SQLITE_CONFIG_PAGECACHE,
pagecache, PC_PAGESIZE, PC_NUMPAGES); pagecache, PC_PAGESIZE, PC_NUMPAGES);
if (SQLITE_OK == c) if (SQLITE_OK == c)
return((int)MANDOCLEVEL_OK); return (int)MANDOCLEVEL_OK;
fprintf(stderr, "pagecache: %s\n", sqlite3_errstr(c)); warnx("pagecache: %s", sqlite3_errstr(c));
} else if (NULL == pagecache) { } else if (NULL == pagecache) {
fprintf(stderr, "pagecache missing\n"); warnx("pagecache missing");
return((int)MANDOCLEVEL_BADARG); return (int)MANDOCLEVEL_BADARG;
} }
if (-1 == munmap(pagecache, PC_PAGESIZE * PC_NUMPAGES)) { if (-1 == munmap(pagecache, PC_PAGESIZE * PC_NUMPAGES)) {
perror("munmap"); warn("munmap");
pagecache = NULL; pagecache = NULL;
return((int)MANDOCLEVEL_SYSERR); return (int)MANDOCLEVEL_SYSERR;
} }
pagecache = NULL; pagecache = NULL;
return((int)MANDOCLEVEL_OK); return (int)MANDOCLEVEL_OK;
} }
int int
@ -163,7 +159,6 @@ mansearch(const struct mansearch *search,
int argc, char *argv[], int argc, char *argv[],
struct manpage **res, size_t *sz) struct manpage **res, size_t *sz)
{ {
int fd, rc, c, indexbit;
int64_t pageid; int64_t pageid;
uint64_t outbit, iterbit; uint64_t outbit, iterbit;
char buf[PATH_MAX]; char buf[PATH_MAX];
@ -173,27 +168,18 @@ mansearch(const struct mansearch *search,
sqlite3 *db; sqlite3 *db;
sqlite3_stmt *s, *s2; sqlite3_stmt *s, *s2;
struct match *mp; struct match *mp;
struct ohash_info info;
struct ohash htab; struct ohash htab;
unsigned int idx; unsigned int idx;
size_t i, j, cur, maxres; size_t i, j, cur, maxres;
int c, chdir_status, getcwd_status, indexbit;
info.calloc = hash_calloc; if (argc == 0 || (e = exprcomp(search, argc, argv)) == NULL) {
info.alloc = hash_alloc; *sz = 0;
info.free = hash_free; return 0;
info.key_offset = offsetof(struct match, pageid); }
*sz = cur = maxres = 0; cur = maxres = 0;
sql = NULL;
*res = NULL; *res = NULL;
fd = -1;
e = NULL;
rc = 0;
if (0 == argc)
goto out;
if (NULL == (e = exprcomp(search, argc, argv)))
goto out;
if (NULL != search->outkey) { if (NULL != search->outkey) {
outbit = TYPE_Nd; outbit = TYPE_Nd;
@ -210,19 +196,18 @@ mansearch(const struct mansearch *search,
outbit = 0; outbit = 0;
/* /*
* Save a descriptor to the current working directory. * Remember the original working directory, if possible.
* Since pathnames in the "paths" variable might be relative, * This will be needed if the second or a later directory
* and we'll be chdir()ing into them, we need to keep a handle * is given as a relative path.
* on our current directory from which to start the chdir(). * Do not error out if the current directory is not
* searchable: Maybe it won't be needed after all.
*/ */
if (NULL == getcwd(buf, PATH_MAX)) { if (getcwd(buf, PATH_MAX) == NULL) {
perror("getcwd"); getcwd_status = 0;
goto out; (void)strlcpy(buf, strerror(errno), sizeof(buf));
} else if (-1 == (fd = open(buf, O_RDONLY, 0))) { } else
perror(buf); getcwd_status = 1;
goto out;
}
sql = sql_statement(e); sql = sql_statement(e);
@ -234,22 +219,28 @@ mansearch(const struct mansearch *search,
* scan it for our match expression. * scan it for our match expression.
*/ */
chdir_status = 0;
for (i = 0; i < paths->sz; i++) { for (i = 0; i < paths->sz; i++) {
if (-1 == fchdir(fd)) { if (chdir_status && paths->paths[i][0] != '/') {
perror(buf); if ( ! getcwd_status) {
free(*res); warnx("%s: getcwd: %s", paths->paths[i], buf);
break; continue;
} else if (-1 == chdir(paths->paths[i])) { } else if (chdir(buf) == -1) {
perror(paths->paths[i]); warn("%s", buf);
continue;
}
}
if (chdir(paths->paths[i]) == -1) {
warn("%s", paths->paths[i]);
continue; continue;
} }
chdir_status = 1;
c = sqlite3_open_v2(MANDOC_DB, &db, c = sqlite3_open_v2(MANDOC_DB, &db,
SQLITE_OPEN_READONLY, NULL); SQLITE_OPEN_READONLY, NULL);
if (SQLITE_OK != c) { if (SQLITE_OK != c) {
fprintf(stderr, "%s/%s: %s\n", warn("%s/%s", paths->paths[i], MANDOC_DB);
paths->paths[i], MANDOC_DB, strerror(errno));
sqlite3_close(db); sqlite3_close(db);
continue; continue;
} }
@ -271,7 +262,8 @@ mansearch(const struct mansearch *search,
j = 1; j = 1;
c = sqlite3_prepare_v2(db, sql, -1, &s, NULL); c = sqlite3_prepare_v2(db, sql, -1, &s, NULL);
if (SQLITE_OK != c) if (SQLITE_OK != c)
fprintf(stderr, "%s\n", sqlite3_errmsg(db)); errx((int)MANDOCLEVEL_SYSERR,
"%s", sqlite3_errmsg(db));
for (ep = e; NULL != ep; ep = ep->next) { for (ep = e; NULL != ep; ep = ep->next) {
if (NULL == ep->substr) { if (NULL == ep->substr) {
@ -282,8 +274,7 @@ mansearch(const struct mansearch *search,
SQL_BIND_INT64(db, s, j, ep->bits); SQL_BIND_INT64(db, s, j, ep->bits);
} }
memset(&htab, 0, sizeof(struct ohash)); mandoc_ohash_init(&htab, 4, offsetof(struct match, pageid));
ohash_init(&htab, 4, &info);
/* /*
* Hash each entry on its [unique] document identifier. * Hash each entry on its [unique] document identifier.
@ -313,7 +304,7 @@ mansearch(const struct mansearch *search,
} }
if (SQLITE_DONE != c) if (SQLITE_DONE != c)
fprintf(stderr, "%s\n", sqlite3_errmsg(db)); warnx("%s", sqlite3_errmsg(db));
sqlite3_finalize(s); sqlite3_finalize(s);
@ -322,14 +313,16 @@ mansearch(const struct mansearch *search,
"WHERE pageid=? ORDER BY sec, arch, name", "WHERE pageid=? ORDER BY sec, arch, name",
-1, &s, NULL); -1, &s, NULL);
if (SQLITE_OK != c) if (SQLITE_OK != c)
fprintf(stderr, "%s\n", sqlite3_errmsg(db)); errx((int)MANDOCLEVEL_SYSERR,
"%s", sqlite3_errmsg(db));
c = sqlite3_prepare_v2(db, c = sqlite3_prepare_v2(db,
"SELECT bits, key, pageid FROM keys " "SELECT bits, key, pageid FROM keys "
"WHERE pageid=? AND bits & ?", "WHERE pageid=? AND bits & ?",
-1, &s2, NULL); -1, &s2, NULL);
if (SQLITE_OK != c) if (SQLITE_OK != c)
fprintf(stderr, "%s\n", sqlite3_errmsg(db)); errx((int)MANDOCLEVEL_SYSERR,
"%s", sqlite3_errmsg(db));
for (mp = ohash_first(&htab, &idx); for (mp = ohash_first(&htab, &idx);
NULL != mp; NULL != mp;
@ -370,17 +363,12 @@ mansearch(const struct mansearch *search,
break; break;
} }
qsort(*res, cur, sizeof(struct manpage), manpage_compare); qsort(*res, cur, sizeof(struct manpage), manpage_compare);
rc = 1; if (chdir_status && getcwd_status && chdir(buf) == -1)
out: warn("%s", buf);
if (-1 != fd) {
if (-1 == fchdir(fd))
perror(buf);
close(fd);
}
exprfree(e); exprfree(e);
free(sql); free(sql);
*sz = cur; *sz = cur;
return(rc); return 1;
} }
void void
@ -404,9 +392,9 @@ manpage_compare(const void *vp1, const void *vp2)
mp1 = vp1; mp1 = vp1;
mp2 = vp2; mp2 = vp2;
return( (diff = mp2->bits - mp1->bits) ? diff : return (diff = mp2->bits - mp1->bits) ? diff :
(diff = mp1->sec - mp2->sec) ? diff : (diff = mp1->sec - mp2->sec) ? diff :
strcasecmp(mp1->names, mp2->names)); strcasecmp(mp1->names, mp2->names);
} }
static void static void
@ -515,7 +503,7 @@ buildnames(const struct mansearch *search, struct manpage *mpage,
globfree(&globinfo); globfree(&globinfo);
} }
if (c != SQLITE_DONE) if (c != SQLITE_DONE)
fprintf(stderr, "%s\n", sqlite3_errmsg(db)); warnx("%s", sqlite3_errmsg(db));
sqlite3_reset(s); sqlite3_reset(s);
/* If none of the files is usable, use the first name. */ /* If none of the files is usable, use the first name. */
@ -565,9 +553,9 @@ buildoutput(sqlite3 *db, sqlite3_stmt *s, uint64_t pageid, uint64_t outbit)
output = newoutput; output = newoutput;
} }
if (SQLITE_DONE != c) if (SQLITE_DONE != c)
fprintf(stderr, "%s\n", sqlite3_errmsg(db)); warnx("%s", sqlite3_errmsg(db));
sqlite3_reset(s); sqlite3_reset(s);
return(output); return output;
} }
/* /*
@ -662,7 +650,7 @@ sql_statement(const struct expr *e)
needop = 1; needop = 1;
} }
return(sql); return sql;
} }
/* /*
@ -745,12 +733,12 @@ exprcomp(const struct mansearch *search, int argc, char *argv[])
toopen = logic = igncase = 0; toopen = logic = igncase = 0;
} }
if ( ! (toopen || logic || igncase || toclose)) if ( ! (toopen || logic || igncase || toclose))
return(first); return first;
fail: fail:
if (NULL != first) if (NULL != first)
exprfree(first); exprfree(first);
return(NULL); return NULL;
} }
static struct expr * static struct expr *
@ -763,7 +751,7 @@ exprterm(const struct mansearch *search, char *buf, int cs)
int i, irc; int i, irc;
if ('\0' == *buf) if ('\0' == *buf)
return(NULL); return NULL;
e = mandoc_calloc(1, sizeof(struct expr)); e = mandoc_calloc(1, sizeof(struct expr));
@ -771,7 +759,7 @@ exprterm(const struct mansearch *search, char *buf, int cs)
e->bits = TYPE_Nm; e->bits = TYPE_Nm;
e->substr = buf; e->substr = buf;
e->equal = 1; e->equal = 1;
return(e); return e;
} }
/* /*
@ -783,7 +771,14 @@ exprterm(const struct mansearch *search, char *buf, int cs)
if (search->argmode == ARG_WORD) { if (search->argmode == ARG_WORD) {
e->bits = TYPE_Nm; e->bits = TYPE_Nm;
e->substr = NULL; e->substr = NULL;
#if HAVE_REWB_BSD
mandoc_asprintf(&val, "[[:<:]]%s[[:>:]]", buf); mandoc_asprintf(&val, "[[:<:]]%s[[:>:]]", buf);
#elif HAVE_REWB_SYSV
mandoc_asprintf(&val, "\\<%s\\>", buf);
#else
mandoc_asprintf(&val,
"(^|[^a-zA-Z01-9_])%s([^a-zA-Z01-9_]|$)", buf);
#endif
cs = 0; cs = 0;
} else if ((val = strpbrk(buf, "=~")) == NULL) { } else if ((val = strpbrk(buf, "=~")) == NULL) {
e->bits = TYPE_Nm | TYPE_Nd; e->bits = TYPE_Nm | TYPE_Nd;
@ -807,14 +802,14 @@ exprterm(const struct mansearch *search, char *buf, int cs)
free(val); free(val);
if (irc) { if (irc) {
regerror(irc, &e->regexp, errbuf, sizeof(errbuf)); regerror(irc, &e->regexp, errbuf, sizeof(errbuf));
fprintf(stderr, "regcomp: %s\n", errbuf); warnx("regcomp: %s", errbuf);
free(e); free(e);
return(NULL); return NULL;
} }
} }
if (e->bits) if (e->bits)
return(e); return e;
/* /*
* Parse out all possible fields. * Parse out all possible fields.
@ -836,13 +831,13 @@ exprterm(const struct mansearch *search, char *buf, int cs)
if (i == mansearch_keymax) { if (i == mansearch_keymax) {
if (strcasecmp(key, "any")) { if (strcasecmp(key, "any")) {
free(e); free(e);
return(NULL); return NULL;
} }
e->bits |= ~0ULL; e->bits |= ~0ULL;
} }
} }
return(e); return e;
} }
static void static void
@ -856,24 +851,3 @@ exprfree(struct expr *p)
p = pp; p = pp;
} }
} }
static void *
hash_calloc(size_t nmemb, size_t sz, void *arg)
{
return(mandoc_calloc(nmemb, sz));
}
static void *
hash_alloc(size_t sz, void *arg)
{
return(mandoc_malloc(sz));
}
static void
hash_free(void *p, void *arg)
{
free(p);
}

View File

@ -1,4 +1,4 @@
/* $Id: mansearch.h,v 1.23 2014/12/01 08:05:52 schwarze Exp $ */ /* $Id: mansearch.h,v 1.24 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -95,7 +95,6 @@ struct mansearch {
int firstmatch; /* first matching database only */ int firstmatch; /* first matching database only */
}; };
__BEGIN_DECLS
struct manpaths; struct manpaths;
@ -107,5 +106,3 @@ int mansearch(const struct mansearch *cfg, /* options */
struct manpage **res, /* results */ struct manpage **res, /* results */
size_t *ressz); /* results returned */ size_t *ressz); /* results returned */
void mansearch_free(struct manpage *, size_t); void mansearch_free(struct manpage *, size_t);
__END_DECLS

View File

@ -1,4 +1,4 @@
.\" $Id: mchars_alloc.3,v 1.2 2014/10/26 18:07:28 schwarze Exp $ .\" $Id: mchars_alloc.3,v 1.3 2015/10/13 22:59:54 schwarze Exp $
.\" .\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\" .\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: October 26 2014 $ .Dd $Mdocdate: October 13 2015 $
.Dt MCHARS_ALLOC 3 .Dt MCHARS_ALLOC 3
.Os .Os
.Sh NAME .Sh NAME
@ -25,17 +25,13 @@
.Nm mchars_spec2cp , .Nm mchars_spec2cp ,
.Nm mchars_spec2str .Nm mchars_spec2str
.Nd character table for mandoc .Nd character table for mandoc
.Sh LIBRARY
.Lb libmandoc
.Sh SYNOPSIS .Sh SYNOPSIS
.In sys/types.h .In sys/types.h
.In mandoc.h .In mandoc.h
.Ft "struct mchars *"
.Fn mchars_alloc "void"
.Ft void .Ft void
.Fo mchars_free .Fn mchars_alloc void
.Fa "struct mchars *table" .Ft void
.Fc .Fn mchars_free void
.Ft char .Ft char
.Fo mchars_num2char .Fo mchars_num2char
.Fa "const char *decimal" .Fa "const char *decimal"
@ -48,13 +44,11 @@
.Fc .Fc
.Ft int .Ft int
.Fo mchars_spec2cp .Fo mchars_spec2cp
.Fa "const struct mchars *table"
.Fa "const char *name" .Fa "const char *name"
.Fa "size_t sz" .Fa "size_t sz"
.Fc .Fc
.Ft "const char *" .Ft "const char *"
.Fo mchars_spec2str .Fo mchars_spec2str
.Fa "const struct mchars *table"
.Fa "const char *name" .Fa "const char *name"
.Fa "size_t sz" .Fa "size_t sz"
.Fa "size_t *rsz" .Fa "size_t *rsz"
@ -135,9 +129,9 @@ escape sequences.
.Pp .Pp
The function The function
.Fn mchars_alloc .Fn mchars_alloc
allocates an opaque initializes a static
.Vt "struct mchars *" .Vt "struct ohash"
table object for subsequent use by the following two lookup functions. object for subsequent use by the following two lookup functions.
When no longer needed, this object can be destroyed with When no longer needed, this object can be destroyed with
.Fn mchars_free . .Fn mchars_free .
.Pp .Pp
@ -149,9 +143,7 @@ special character
.Fa name .Fa name
consisting of consisting of
.Fa sz .Fa sz
characters in the characters and returns the corresponding Unicode codepoint.
.Fa table
and returns the corresponding Unicode codepoint.
If the If the
.Ar name .Ar name
is not recognized, \-1 is returned. is not recognized, \-1 is returned.
@ -175,9 +167,7 @@ special character
.Fa name .Fa name
consisting of consisting of
.Fa sz .Fa sz
characters in the characters and returns an ASCII string representation.
.Fa table
and returns an ASCII string representation.
The length of the representation is returned in The length of the representation is returned in
.Fa rsz . .Fa rsz .
In many cases, the meaning of such ASCII representations In many cases, the meaning of such ASCII representations
@ -215,6 +205,7 @@ These funtions are implemented in the file
.Sh SEE ALSO .Sh SEE ALSO
.Xr mandoc 1 , .Xr mandoc 1 ,
.Xr mandoc_escape 3 , .Xr mandoc_escape 3 ,
.Xr ohash_init 3 ,
.Xr mandoc_char 7 , .Xr mandoc_char 7 ,
.Xr roff 7 .Xr roff 7
.Sh HISTORY .Sh HISTORY

View File

@ -1,4 +1,4 @@
.\" $Id: mdoc.7,v 1.252 2015/02/23 13:31:04 schwarze Exp $ .\" $Id: mdoc.7,v 1.257 2015/11/05 12:06:45 schwarze Exp $
.\" .\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010, 2011, 2013 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2010, 2011, 2013 Ingo Schwarze <schwarze@openbsd.org>
@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: February 23 2015 $ .Dd $Mdocdate: November 5 2015 $
.Dt MDOC 7 .Dt MDOC 7
.Os .Os
.Sh NAME .Sh NAME
@ -304,6 +304,11 @@ Print verbose information.
\&.El \&.El
.Ed .Ed
.Pp .Pp
List the options in alphabetical order,
uppercase before lowercase for each letter and
with no regard to whether an option takes an argument.
Put digits in ascending order before all letter options.
.Pp
Manuals not documenting a command won't include the above fragment. Manuals not documenting a command won't include the above fragment.
.Pp .Pp
Since the Since the
@ -1622,7 +1627,7 @@ See also
A function name. A function name.
Its syntax is as follows: Its syntax is as follows:
.Bd -ragged -offset indent .Bd -ragged -offset indent
.Pf \. Ns Sx \&Fn .Pf . Sx \&Fn
.Op Ar functype .Op Ar functype
.Ar funcname .Ar funcname
.Op Oo Ar argtype Oc Ar argname .Op Oo Ar argtype Oc Ar argname
@ -2093,7 +2098,7 @@ It is suggested to leave it unspecified, in which case
.Xr mandoc 1 .Xr mandoc 1
uses its uses its
.Fl Ios .Fl Ios
argument, or, if that isn't specified either, argument or, if that isn't specified either,
.Fa sysname .Fa sysname
and and
.Fa release .Fa release
@ -2155,19 +2160,23 @@ See also
Close parenthesised context opened by Close parenthesised context opened by
.Sx \&Po . .Sx \&Po .
.Ss \&Pf .Ss \&Pf
Removes the space between its argument Removes the space between its argument and the following macro.
.Pq Dq prefix
and the following macro.
Its syntax is as follows: Its syntax is as follows:
.Pp .Pp
.D1 .Pf Ar prefix macro arguments ... .D1 .Pf Ar prefix macro arguments ...
.Pp .Pp
This is equivalent to: This is equivalent to:
.Pp .Pp
.D1 .No Ar prefix No \&Ns Ar macro arguments ... .D1 .No \e& Ns Ar prefix No \&Ns Ar macro arguments ...
.Pp
The
.Ar prefix
argument is not parsed for macro names or delimiters,
but used verbatim as if it were escaped.
.Pp .Pp
Examples: Examples:
.Dl ".Pf $ Ar variable_name" .Dl ".Pf $ Ar variable_name"
.Dl ".Pf . Ar macro_name"
.Dl ".Pf 0x Ar hex_digits" .Dl ".Pf 0x Ar hex_digits"
.Pp .Pp
See also See also
@ -2267,7 +2276,7 @@ Examples:
\&.%A J. D. Ullman \&.%A J. D. Ullman
\&.%B Introduction to Automata Theory, Languages, and Computation \&.%B Introduction to Automata Theory, Languages, and Computation
\&.%I Addison-Wesley \&.%I Addison-Wesley
\&.%C Reading, Massachusettes \&.%C Reading, Massachusetts
\&.%D 1979 \&.%D 1979
\&.Re \&.Re
.Ed .Ed

View File

@ -1,4 +1,4 @@
/* $Id: mdoc.c,v 1.238 2015/02/12 13:00:52 schwarze Exp $ */ /* $Id: mdoc.c,v 1.256 2015/10/30 19:04:16 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
@ -7,9 +7,9 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -27,13 +27,16 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "mdoc.h"
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "libmdoc.h" #include "mandoc.h"
#include "roff.h"
#include "mdoc.h"
#include "libmandoc.h" #include "libmandoc.h"
#include "roff_int.h"
#include "libmdoc.h"
const char *const __mdoc_macronames[MDOC_MAX + 1] = { const char *const __mdoc_macronames[MDOC_MAX + 1] = {
"text",
"Ap", "Dd", "Dt", "Os", "Ap", "Dd", "Dt", "Os",
"Sh", "Ss", "Pp", "D1", "Sh", "Ss", "Pp", "D1",
"Dl", "Bd", "Ed", "Bl", "Dl", "Bd", "Ed", "Bl",
@ -64,8 +67,8 @@ const char *const __mdoc_macronames[MDOC_MAX + 1] = {
"Lk", "Mt", "Brq", "Bro", "Lk", "Mt", "Brq", "Bro",
"Brc", "%C", "Es", "En", "Brc", "%C", "Es", "En",
"Dx", "%Q", "br", "sp", "Dx", "%Q", "br", "sp",
"%U", "Ta", "ll", "text", "%U", "Ta", "ll",
}; };
const char *const __mdoc_argnames[MDOC_ARG_MAX] = { const char *const __mdoc_argnames[MDOC_ARG_MAX] = {
"split", "nosplit", "ragged", "split", "nosplit", "ragged",
@ -79,157 +82,22 @@ const char *const __mdoc_argnames[MDOC_ARG_MAX] = {
"symbolic", "nested", "centered" "symbolic", "nested", "centered"
}; };
const char * const *mdoc_macronames = __mdoc_macronames; const char * const *mdoc_macronames = __mdoc_macronames + 1;
const char * const *mdoc_argnames = __mdoc_argnames; const char * const *mdoc_argnames = __mdoc_argnames;
static void mdoc_node_free(struct mdoc_node *); static int mdoc_ptext(struct roff_man *, int, char *, int);
static void mdoc_node_unlink(struct mdoc *, static int mdoc_pmacro(struct roff_man *, int, char *, int);
struct mdoc_node *);
static void mdoc_free1(struct mdoc *);
static void mdoc_alloc1(struct mdoc *);
static struct mdoc_node *node_alloc(struct mdoc *, int, int,
enum mdoct, enum mdoc_type);
static void node_append(struct mdoc *, struct mdoc_node *);
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 *mdoc)
{
return(mdoc->first);
}
const struct mdoc_meta *
mdoc_meta(const struct mdoc *mdoc)
{
return(&mdoc->meta);
}
/*
* Frees volatile resources (parse tree, meta-data, fields).
*/
static void
mdoc_free1(struct mdoc *mdoc)
{
if (mdoc->first)
mdoc_node_delete(mdoc, mdoc->first);
free(mdoc->meta.msec);
free(mdoc->meta.vol);
free(mdoc->meta.arch);
free(mdoc->meta.date);
free(mdoc->meta.title);
free(mdoc->meta.os);
free(mdoc->meta.name);
}
/*
* Allocate all volatile resources (parse tree, meta-data, fields).
*/
static void
mdoc_alloc1(struct mdoc *mdoc)
{
memset(&mdoc->meta, 0, sizeof(struct mdoc_meta));
mdoc->flags = 0;
mdoc->lastnamed = mdoc->lastsec = SEC_NONE;
mdoc->last = mandoc_calloc(1, sizeof(struct mdoc_node));
mdoc->first = mdoc->last;
mdoc->last->type = MDOC_ROOT;
mdoc->last->tok = MDOC_MAX;
mdoc->next = MDOC_NEXT_CHILD;
}
/*
* Free up volatile resources (see mdoc_free1()) then re-initialises the
* data with mdoc_alloc1(). After invocation, parse data has been reset
* and the parser is ready for re-invocation on a new tree; however,
* cross-parse non-volatile data is kept intact.
*/
void
mdoc_reset(struct mdoc *mdoc)
{
mdoc_free1(mdoc);
mdoc_alloc1(mdoc);
}
/*
* Completely free up all volatile and non-volatile parse resources.
* After invocation, the pointer is no longer usable.
*/
void
mdoc_free(struct mdoc *mdoc)
{
mdoc_free1(mdoc);
free(mdoc);
}
/*
* Allocate volatile and non-volatile parse resources.
*/
struct mdoc *
mdoc_alloc(struct roff *roff, struct mparse *parse,
const char *defos, int quick)
{
struct mdoc *p;
p = mandoc_calloc(1, sizeof(struct mdoc));
p->parse = parse;
p->defos = defos;
p->quick = quick;
p->roff = roff;
mdoc_hash_init();
mdoc_alloc1(p);
return(p);
}
void
mdoc_endparse(struct mdoc *mdoc)
{
mdoc_macroend(mdoc);
}
void
mdoc_addeqn(struct mdoc *mdoc, const struct eqn *ep)
{
struct mdoc_node *n;
n = node_alloc(mdoc, ep->ln, ep->pos, MDOC_MAX, MDOC_EQN);
n->eqn = ep;
if (ep->ln > mdoc->last->line)
n->flags |= MDOC_LINE;
node_append(mdoc, n);
mdoc->next = MDOC_NEXT_SIBLING;
}
void
mdoc_addspan(struct mdoc *mdoc, const struct tbl_span *sp)
{
struct mdoc_node *n;
n = node_alloc(mdoc, sp->line, 0, MDOC_MAX, MDOC_TBL);
n->span = sp;
node_append(mdoc, n);
mdoc->next = MDOC_NEXT_SIBLING;
}
/* /*
* Main parse routine. Parses a single line -- really just hands off to * Main parse routine. Parses a single line -- really just hands off to
* the macro (mdoc_pmacro()) or text parser (mdoc_ptext()). * the macro (mdoc_pmacro()) or text parser (mdoc_ptext()).
*/ */
int int
mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs) mdoc_parseln(struct roff_man *mdoc, int ln, char *buf, int offs)
{ {
if (mdoc->last->type != MDOC_EQN || ln > mdoc->last->line) if (mdoc->last->type != ROFFT_EQN || ln > mdoc->last->line)
mdoc->flags |= MDOC_NEWLINE; mdoc->flags |= MDOC_NEWLINE;
/* /*
@ -243,231 +111,80 @@ mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs)
else else
mdoc->flags &= ~MDOC_SYNOPSIS; mdoc->flags &= ~MDOC_SYNOPSIS;
return(roff_getcontrol(mdoc->roff, buf, &offs) ? return roff_getcontrol(mdoc->roff, buf, &offs) ?
mdoc_pmacro(mdoc, ln, buf, offs) : mdoc_pmacro(mdoc, ln, buf, offs) :
mdoc_ptext(mdoc, ln, buf, offs)); mdoc_ptext(mdoc, ln, buf, offs);
} }
void void
mdoc_macro(MACRO_PROT_ARGS) mdoc_macro(MACRO_PROT_ARGS)
{ {
assert(tok < MDOC_MAX); assert(tok > TOKEN_NONE && tok < MDOC_MAX);
if (mdoc->flags & MDOC_PBODY) {
if (tok == MDOC_Dt) {
mandoc_vmsg(MANDOCERR_DT_LATE,
mdoc->parse, line, ppos,
"Dt %s", buf + *pos);
return;
}
} else if ( ! (mdoc_macros[tok].flags & MDOC_PROLOGUE)) {
if (mdoc->meta.title == NULL) {
mandoc_vmsg(MANDOCERR_DT_NOTITLE,
mdoc->parse, line, ppos, "%s %s",
mdoc_macronames[tok], buf + *pos);
mdoc->meta.title = mandoc_strdup("UNTITLED");
}
if (NULL == mdoc->meta.vol)
mdoc->meta.vol = mandoc_strdup("LOCAL");
mdoc->flags |= MDOC_PBODY;
}
(*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf); (*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf);
} }
static void
node_append(struct mdoc *mdoc, struct mdoc_node *p)
{
assert(mdoc->last);
assert(mdoc->first);
assert(MDOC_ROOT != p->type);
switch (mdoc->next) {
case MDOC_NEXT_SIBLING:
mdoc->last->next = p;
p->prev = mdoc->last;
p->parent = mdoc->last->parent;
break;
case MDOC_NEXT_CHILD:
mdoc->last->child = p;
p->parent = mdoc->last;
break;
default:
abort();
/* NOTREACHED */
}
p->parent->nchild++;
/*
* Copy over the normalised-data pointer of our parent. Not
* everybody has one, but copying a null pointer is fine.
*/
switch (p->type) {
case MDOC_BODY:
if (ENDBODY_NOT != p->end)
break;
/* FALLTHROUGH */
case MDOC_TAIL:
/* FALLTHROUGH */
case MDOC_HEAD:
p->norm = p->parent->norm;
break;
default:
break;
}
mdoc_valid_pre(mdoc, p);
switch (p->type) {
case MDOC_HEAD:
assert(MDOC_BLOCK == p->parent->type);
p->parent->head = p;
break;
case MDOC_TAIL:
assert(MDOC_BLOCK == p->parent->type);
p->parent->tail = p;
break;
case MDOC_BODY:
if (p->end)
break;
assert(MDOC_BLOCK == p->parent->type);
p->parent->body = p;
break;
default:
break;
}
mdoc->last = p;
switch (p->type) {
case MDOC_TBL:
/* FALLTHROUGH */
case MDOC_TEXT:
mdoc_valid_post(mdoc);
break;
default:
break;
}
}
static struct mdoc_node *
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 = mdoc->lastsec;
p->line = line;
p->pos = pos;
p->tok = tok;
p->type = type;
/* Flag analysis. */
if (MDOC_SYNOPSIS & mdoc->flags)
p->flags |= MDOC_SYNPRETTY;
else
p->flags &= ~MDOC_SYNPRETTY;
if (MDOC_NEWLINE & mdoc->flags)
p->flags |= MDOC_LINE;
mdoc->flags &= ~MDOC_NEWLINE;
return(p);
}
void void
mdoc_tail_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok) mdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, int tok)
{ {
struct mdoc_node *p; struct roff_node *p;
p = node_alloc(mdoc, line, pos, tok, MDOC_TAIL); p = roff_node_alloc(mdoc, line, pos, ROFFT_TAIL, tok);
node_append(mdoc, p); roff_node_append(mdoc, p);
mdoc->next = MDOC_NEXT_CHILD; mdoc->next = ROFF_NEXT_CHILD;
} }
struct mdoc_node * struct roff_node *
mdoc_head_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok) mdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos, int tok,
struct roff_node *body, enum mdoc_endbody end)
{ {
struct mdoc_node *p; struct roff_node *p;
assert(mdoc->first);
assert(mdoc->last);
p = node_alloc(mdoc, line, pos, tok, MDOC_HEAD);
node_append(mdoc, p);
mdoc->next = MDOC_NEXT_CHILD;
return(p);
}
struct mdoc_node *
mdoc_body_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
{
struct mdoc_node *p;
p = node_alloc(mdoc, line, pos, tok, MDOC_BODY);
node_append(mdoc, p);
mdoc->next = MDOC_NEXT_CHILD;
return(p);
}
struct mdoc_node *
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;
body->flags |= MDOC_ENDED; body->flags |= MDOC_ENDED;
body->parent->flags |= MDOC_ENDED; body->parent->flags |= MDOC_ENDED;
p = node_alloc(mdoc, line, pos, tok, MDOC_BODY); p = roff_node_alloc(mdoc, line, pos, ROFFT_BODY, tok);
p->body = body; p->body = body;
p->norm = body->norm; p->norm = body->norm;
p->end = end; p->end = end;
node_append(mdoc, p); roff_node_append(mdoc, p);
mdoc->next = MDOC_NEXT_SIBLING; mdoc->next = ROFF_NEXT_SIBLING;
return(p); return p;
} }
struct mdoc_node * struct roff_node *
mdoc_block_alloc(struct mdoc *mdoc, int line, int pos, mdoc_block_alloc(struct roff_man *mdoc, int line, int pos,
enum mdoct tok, struct mdoc_arg *args) int tok, struct mdoc_arg *args)
{ {
struct mdoc_node *p; struct roff_node *p;
p = node_alloc(mdoc, line, pos, tok, MDOC_BLOCK); p = roff_node_alloc(mdoc, line, pos, ROFFT_BLOCK, tok);
p->args = args; p->args = args;
if (p->args) if (p->args)
(args->refcnt)++; (args->refcnt)++;
switch (tok) { switch (tok) {
case MDOC_Bd: case MDOC_Bd:
/* FALLTHROUGH */
case MDOC_Bf: case MDOC_Bf:
/* FALLTHROUGH */
case MDOC_Bl: case MDOC_Bl:
/* FALLTHROUGH */
case MDOC_En: case MDOC_En:
/* FALLTHROUGH */
case MDOC_Rs: case MDOC_Rs:
p->norm = mandoc_calloc(1, sizeof(union mdoc_data)); p->norm = mandoc_calloc(1, sizeof(union mdoc_data));
break; break;
default: default:
break; break;
} }
node_append(mdoc, p); roff_node_append(mdoc, p);
mdoc->next = MDOC_NEXT_CHILD; mdoc->next = ROFF_NEXT_CHILD;
return(p); return p;
} }
void void
mdoc_elem_alloc(struct mdoc *mdoc, int line, int pos, mdoc_elem_alloc(struct roff_man *mdoc, int line, int pos,
enum mdoct tok, struct mdoc_arg *args) int tok, struct mdoc_arg *args)
{ {
struct mdoc_node *p; struct roff_node *p;
p = node_alloc(mdoc, line, pos, tok, MDOC_ELEM); p = roff_node_alloc(mdoc, line, pos, ROFFT_ELEM, tok);
p->args = args; p->args = args;
if (p->args) if (p->args)
(args->refcnt)++; (args->refcnt)++;
@ -479,106 +196,17 @@ mdoc_elem_alloc(struct mdoc *mdoc, int line, int pos,
default: default:
break; break;
} }
node_append(mdoc, p); roff_node_append(mdoc, p);
mdoc->next = MDOC_NEXT_CHILD; mdoc->next = ROFF_NEXT_CHILD;
} }
void void
mdoc_word_alloc(struct mdoc *mdoc, int line, int pos, const char *p) mdoc_node_relink(struct roff_man *mdoc, struct roff_node *p)
{
struct mdoc_node *n;
n = node_alloc(mdoc, line, pos, MDOC_MAX, MDOC_TEXT);
n->string = roff_strdup(mdoc->roff, p);
node_append(mdoc, n);
mdoc->next = MDOC_NEXT_SIBLING;
}
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);
mandoc_asprintf(&newstr, "%s %s", n->string, addstr);
free(addstr);
free(n->string);
n->string = newstr;
mdoc->next = MDOC_NEXT_SIBLING;
}
static void
mdoc_node_free(struct mdoc_node *p)
{ {
if (MDOC_BLOCK == p->type || MDOC_ELEM == p->type) roff_node_unlink(mdoc, p);
free(p->norm); p->prev = p->next = NULL;
if (p->string) roff_node_append(mdoc, p);
free(p->string);
if (p->args)
mdoc_argv_free(p->args);
free(p);
}
static void
mdoc_node_unlink(struct mdoc *mdoc, struct mdoc_node *n)
{
/* Adjust siblings. */
if (n->prev)
n->prev->next = n->next;
if (n->next)
n->next->prev = n->prev;
/* Adjust parent. */
if (n->parent) {
n->parent->nchild--;
if (n->parent->child == n)
n->parent->child = n->prev ? n->prev : n->next;
if (n->parent->last == n)
n->parent->last = n->prev ? n->prev : NULL;
}
/* Adjust parse point, if applicable. */
if (mdoc && mdoc->last == n) {
if (n->prev) {
mdoc->last = n->prev;
mdoc->next = MDOC_NEXT_SIBLING;
} else {
mdoc->last = n->parent;
mdoc->next = MDOC_NEXT_CHILD;
}
}
if (mdoc && mdoc->first == n)
mdoc->first = NULL;
}
void
mdoc_node_delete(struct mdoc *mdoc, struct mdoc_node *p)
{
while (p->child) {
assert(p->nchild);
mdoc_node_delete(mdoc, p->child);
}
assert(0 == p->nchild);
mdoc_node_unlink(mdoc, p);
mdoc_node_free(p);
}
void
mdoc_node_relink(struct mdoc *mdoc, struct mdoc_node *p)
{
mdoc_node_unlink(mdoc, p);
node_append(mdoc, p);
} }
/* /*
@ -586,37 +214,37 @@ mdoc_node_relink(struct mdoc *mdoc, struct mdoc_node *p)
* control character. * control character.
*/ */
static int static int
mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs) mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
{ {
struct roff_node *n;
char *c, *ws, *end; char *c, *ws, *end;
struct mdoc_node *n;
assert(mdoc->last); assert(mdoc->last);
n = mdoc->last; n = mdoc->last;
/* /*
* Divert directly to list processing if we're encountering a * Divert directly to list processing if we're encountering a
* columnar MDOC_BLOCK with or without a prior MDOC_BLOCK entry * columnar ROFFT_BLOCK with or without a prior ROFFT_BLOCK entry
* (a MDOC_BODY means it's already open, in which case we should * (a ROFFT_BODY means it's already open, in which case we should
* process within its context in the normal way). * process within its context in the normal way).
*/ */
if (n->tok == MDOC_Bl && n->type == MDOC_BODY && if (n->tok == MDOC_Bl && n->type == ROFFT_BODY &&
n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) { n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) {
/* `Bl' is open without any children. */ /* `Bl' is open without any children. */
mdoc->flags |= MDOC_FREECOL; mdoc->flags |= MDOC_FREECOL;
mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf); mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
return(1); return 1;
} }
if (MDOC_It == n->tok && MDOC_BLOCK == n->type && if (n->tok == MDOC_It && n->type == ROFFT_BLOCK &&
NULL != n->parent && NULL != n->parent &&
MDOC_Bl == n->parent->tok && MDOC_Bl == n->parent->tok &&
LIST_column == n->parent->norm->Bl.type) { LIST_column == n->parent->norm->Bl.type) {
/* `Bl' has block-level `It' children. */ /* `Bl' has block-level `It' children. */
mdoc->flags |= MDOC_FREECOL; mdoc->flags |= MDOC_FREECOL;
mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf); mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
return(1); return 1;
} }
/* /*
@ -673,16 +301,16 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
* blank lines aren't allowed, but enough manuals assume this * blank lines aren't allowed, but enough manuals assume this
* behaviour that we want to work around it. * behaviour that we want to work around it.
*/ */
mdoc_elem_alloc(mdoc, line, offs, MDOC_sp, NULL); roff_elem_alloc(mdoc, line, offs, MDOC_sp);
mdoc->next = MDOC_NEXT_SIBLING; mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;
mdoc_valid_post(mdoc); mdoc->next = ROFF_NEXT_SIBLING;
return(1); return 1;
} }
mdoc_word_alloc(mdoc, line, offs, buf+offs); roff_word_alloc(mdoc, line, offs, buf+offs);
if (mdoc->flags & MDOC_LITERAL) if (mdoc->flags & MDOC_LITERAL)
return(1); return 1;
/* /*
* End-of-sentence check. If the last character is an unescaped * End-of-sentence check. If the last character is an unescaped
@ -694,7 +322,7 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
if (mandoc_eos(buf+offs, (size_t)(end-buf-offs))) if (mandoc_eos(buf+offs, (size_t)(end-buf-offs)))
mdoc->last->flags |= MDOC_EOS; mdoc->last->flags |= MDOC_EOS;
return(1); return 1;
} }
/* /*
@ -702,11 +330,11 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
* character. * character.
*/ */
static int static int
mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs) mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs)
{ {
struct mdoc_node *n; struct roff_node *n;
const char *cp; const char *cp;
enum mdoct tok; int tok;
int i, sv; int i, sv;
char mac[5]; char mac[5];
@ -723,12 +351,12 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
mac[i] = '\0'; mac[i] = '\0';
tok = (i > 1 && i < 4) ? mdoc_hash_find(mac) : MDOC_MAX; tok = (i > 1 && i < 4) ? mdoc_hash_find(mac) : TOKEN_NONE;
if (tok == MDOC_MAX) { if (tok == TOKEN_NONE) {
mandoc_msg(MANDOCERR_MACRO, mdoc->parse, mandoc_msg(MANDOCERR_MACRO, mdoc->parse,
ln, sv, buf + sv - 1); ln, sv, buf + sv - 1);
return(1); return 1;
} }
/* Skip a leading escape sequence or tab. */ /* Skip a leading escape sequence or tab. */
@ -767,7 +395,7 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) { if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) {
mdoc_macro(mdoc, tok, ln, sv, &offs, buf); mdoc_macro(mdoc, tok, ln, sv, &offs, buf);
return(1); return 1;
} }
n = mdoc->last; n = mdoc->last;
@ -778,11 +406,11 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
* context around the parsed macro. * context around the parsed macro.
*/ */
if (n->tok == MDOC_Bl && n->type == MDOC_BODY && if (n->tok == MDOC_Bl && n->type == ROFFT_BODY &&
n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) { n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) {
mdoc->flags |= MDOC_FREECOL; mdoc->flags |= MDOC_FREECOL;
mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf); mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
return(1); return 1;
} }
/* /*
@ -791,13 +419,13 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
* then open an `It' block context around the parsed macro. * then open an `It' block context around the parsed macro.
*/ */
if (MDOC_It == n->tok && MDOC_BLOCK == n->type && if (n->tok == MDOC_It && n->type == ROFFT_BLOCK &&
NULL != n->parent && NULL != n->parent &&
MDOC_Bl == n->parent->tok && MDOC_Bl == n->parent->tok &&
LIST_column == n->parent->norm->Bl.type) { LIST_column == n->parent->norm->Bl.type) {
mdoc->flags |= MDOC_FREECOL; mdoc->flags |= MDOC_FREECOL;
mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf); mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
return(1); return 1;
} }
/* Normal processing of a macro. */ /* Normal processing of a macro. */
@ -808,9 +436,9 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
if (mdoc->quick && MDOC_Sh == tok && if (mdoc->quick && MDOC_Sh == tok &&
SEC_NAME != mdoc->last->sec) SEC_NAME != mdoc->last->sec)
return(2); return 2;
return(1); return 1;
} }
enum mdelim enum mdelim
@ -818,82 +446,44 @@ mdoc_isdelim(const char *p)
{ {
if ('\0' == p[0]) if ('\0' == p[0])
return(DELIM_NONE); return DELIM_NONE;
if ('\0' == p[1]) if ('\0' == p[1])
switch (p[0]) { switch (p[0]) {
case '(': case '(':
/* FALLTHROUGH */
case '[': case '[':
return(DELIM_OPEN); return DELIM_OPEN;
case '|': case '|':
return(DELIM_MIDDLE); return DELIM_MIDDLE;
case '.': case '.':
/* FALLTHROUGH */
case ',': case ',':
/* FALLTHROUGH */
case ';': case ';':
/* FALLTHROUGH */
case ':': case ':':
/* FALLTHROUGH */
case '?': case '?':
/* FALLTHROUGH */
case '!': case '!':
/* FALLTHROUGH */
case ')': case ')':
/* FALLTHROUGH */
case ']': case ']':
return(DELIM_CLOSE); return DELIM_CLOSE;
default: default:
return(DELIM_NONE); return DELIM_NONE;
} }
if ('\\' != p[0]) if ('\\' != p[0])
return(DELIM_NONE); return DELIM_NONE;
if (0 == strcmp(p + 1, ".")) if (0 == strcmp(p + 1, "."))
return(DELIM_CLOSE); return DELIM_CLOSE;
if (0 == strcmp(p + 1, "fR|\\fP")) if (0 == strcmp(p + 1, "fR|\\fP"))
return(DELIM_MIDDLE); return DELIM_MIDDLE;
return(DELIM_NONE); return DELIM_NONE;
} }
void void
mdoc_deroff(char **dest, const struct mdoc_node *n) mdoc_validate(struct roff_man *mdoc)
{ {
char *cp;
size_t sz;
if (MDOC_TEXT != n->type) { mdoc->last = mdoc->first;
for (n = n->child; n; n = n->next) mdoc_node_validate(mdoc);
mdoc_deroff(dest, n); mdoc_state_reset(mdoc);
return;
}
/* Skip leading whitespace. */
for (cp = n->string; '\0' != *cp; cp++)
if (0 == isspace((unsigned char)*cp))
break;
/* Skip trailing whitespace. */
for (sz = strlen(cp); sz; sz--)
if (0 == isspace((unsigned char)cp[sz-1]))
break;
/* Skip empty strings. */
if (0 == sz)
return;
if (NULL == *dest) {
*dest = mandoc_strndup(cp, sz);
return;
}
mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp);
free(*dest);
*dest = cp;
} }

View File

@ -1,4 +1,4 @@
/* $Id: mdoc.h,v 1.136 2015/02/12 12:24:33 schwarze Exp $ */ /* $Id: mdoc.h,v 1.144 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -7,141 +7,139 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
enum mdoct { #define MDOC_Ap 0
MDOC_Ap = 0, #define MDOC_Dd 1
MDOC_Dd, #define MDOC_Dt 2
MDOC_Dt, #define MDOC_Os 3
MDOC_Os, #define MDOC_Sh 4
MDOC_Sh, #define MDOC_Ss 5
MDOC_Ss, #define MDOC_Pp 6
MDOC_Pp, #define MDOC_D1 7
MDOC_D1, #define MDOC_Dl 8
MDOC_Dl, #define MDOC_Bd 9
MDOC_Bd, #define MDOC_Ed 10
MDOC_Ed, #define MDOC_Bl 11
MDOC_Bl, #define MDOC_El 12
MDOC_El, #define MDOC_It 13
MDOC_It, #define MDOC_Ad 14
MDOC_Ad, #define MDOC_An 15
MDOC_An, #define MDOC_Ar 16
MDOC_Ar, #define MDOC_Cd 17
MDOC_Cd, #define MDOC_Cm 18
MDOC_Cm, #define MDOC_Dv 19
MDOC_Dv, #define MDOC_Er 20
MDOC_Er, #define MDOC_Ev 21
MDOC_Ev, #define MDOC_Ex 22
MDOC_Ex, #define MDOC_Fa 23
MDOC_Fa, #define MDOC_Fd 24
MDOC_Fd, #define MDOC_Fl 25
MDOC_Fl, #define MDOC_Fn 26
MDOC_Fn, #define MDOC_Ft 27
MDOC_Ft, #define MDOC_Ic 28
MDOC_Ic, #define MDOC_In 29
MDOC_In, #define MDOC_Li 30
MDOC_Li, #define MDOC_Nd 31
MDOC_Nd, #define MDOC_Nm 32
MDOC_Nm, #define MDOC_Op 33
MDOC_Op, #define MDOC_Ot 34
MDOC_Ot, #define MDOC_Pa 35
MDOC_Pa, #define MDOC_Rv 36
MDOC_Rv, #define MDOC_St 37
MDOC_St, #define MDOC_Va 38
MDOC_Va, #define MDOC_Vt 39
MDOC_Vt, #define MDOC_Xr 40
MDOC_Xr, #define MDOC__A 41
MDOC__A, #define MDOC__B 42
MDOC__B, #define MDOC__D 43
MDOC__D, #define MDOC__I 44
MDOC__I, #define MDOC__J 45
MDOC__J, #define MDOC__N 46
MDOC__N, #define MDOC__O 47
MDOC__O, #define MDOC__P 48
MDOC__P, #define MDOC__R 49
MDOC__R, #define MDOC__T 50
MDOC__T, #define MDOC__V 51
MDOC__V, #define MDOC_Ac 52
MDOC_Ac, #define MDOC_Ao 53
MDOC_Ao, #define MDOC_Aq 54
MDOC_Aq, #define MDOC_At 55
MDOC_At, #define MDOC_Bc 56
MDOC_Bc, #define MDOC_Bf 57
MDOC_Bf, #define MDOC_Bo 58
MDOC_Bo, #define MDOC_Bq 59
MDOC_Bq, #define MDOC_Bsx 60
MDOC_Bsx, #define MDOC_Bx 61
MDOC_Bx, #define MDOC_Db 62
MDOC_Db, #define MDOC_Dc 63
MDOC_Dc, #define MDOC_Do 64
MDOC_Do, #define MDOC_Dq 65
MDOC_Dq, #define MDOC_Ec 66
MDOC_Ec, #define MDOC_Ef 67
MDOC_Ef, #define MDOC_Em 68
MDOC_Em, #define MDOC_Eo 69
MDOC_Eo, #define MDOC_Fx 70
MDOC_Fx, #define MDOC_Ms 71
MDOC_Ms, #define MDOC_No 72
MDOC_No, #define MDOC_Ns 73
MDOC_Ns, #define MDOC_Nx 74
MDOC_Nx, #define MDOC_Ox 75
MDOC_Ox, #define MDOC_Pc 76
MDOC_Pc, #define MDOC_Pf 77
MDOC_Pf, #define MDOC_Po 78
MDOC_Po, #define MDOC_Pq 79
MDOC_Pq, #define MDOC_Qc 80
MDOC_Qc, #define MDOC_Ql 81
MDOC_Ql, #define MDOC_Qo 82
MDOC_Qo, #define MDOC_Qq 83
MDOC_Qq, #define MDOC_Re 84
MDOC_Re, #define MDOC_Rs 85
MDOC_Rs, #define MDOC_Sc 86
MDOC_Sc, #define MDOC_So 87
MDOC_So, #define MDOC_Sq 88
MDOC_Sq, #define MDOC_Sm 89
MDOC_Sm, #define MDOC_Sx 90
MDOC_Sx, #define MDOC_Sy 91
MDOC_Sy, #define MDOC_Tn 92
MDOC_Tn, #define MDOC_Ux 93
MDOC_Ux, #define MDOC_Xc 94
MDOC_Xc, #define MDOC_Xo 95
MDOC_Xo, #define MDOC_Fo 96
MDOC_Fo, #define MDOC_Fc 97
MDOC_Fc, #define MDOC_Oo 98
MDOC_Oo, #define MDOC_Oc 99
MDOC_Oc, #define MDOC_Bk 100
MDOC_Bk, #define MDOC_Ek 101
MDOC_Ek, #define MDOC_Bt 102
MDOC_Bt, #define MDOC_Hf 103
MDOC_Hf, #define MDOC_Fr 104
MDOC_Fr, #define MDOC_Ud 105
MDOC_Ud, #define MDOC_Lb 106
MDOC_Lb, #define MDOC_Lp 107
MDOC_Lp, #define MDOC_Lk 108
MDOC_Lk, #define MDOC_Mt 109
MDOC_Mt, #define MDOC_Brq 110
MDOC_Brq, #define MDOC_Bro 111
MDOC_Bro, #define MDOC_Brc 112
MDOC_Brc, #define MDOC__C 113
MDOC__C, #define MDOC_Es 114
MDOC_Es, #define MDOC_En 115
MDOC_En, #define MDOC_Dx 116
MDOC_Dx, #define MDOC__Q 117
MDOC__Q, #define MDOC_br 118
MDOC_br, #define MDOC_sp 119
MDOC_sp, #define MDOC__U 120
MDOC__U, #define MDOC_Ta 121
MDOC_Ta, #define MDOC_ll 122
MDOC_ll, #define MDOC_MAX 123
MDOC_MAX
};
enum mdocargt { enum mdocargt {
MDOC_Split, /* -split */ MDOC_Split, /* -split */
@ -174,61 +172,6 @@ enum mdocargt {
MDOC_ARG_MAX MDOC_ARG_MAX
}; };
enum mdoc_type {
MDOC_TEXT,
MDOC_ELEM,
MDOC_HEAD,
MDOC_TAIL,
MDOC_BODY,
MDOC_BLOCK,
MDOC_TBL,
MDOC_EQN,
MDOC_ROOT
};
/*
* Section (named/unnamed) of `Sh'. Note that these appear in the
* conventional order imposed by mdoc.7. In the case of SEC_NONE, no
* section has been invoked (this shouldn't happen). SEC_CUSTOM refers
* to other sections.
*/
enum mdoc_sec {
SEC_NONE = 0,
SEC_NAME, /* NAME */
SEC_LIBRARY, /* LIBRARY */
SEC_SYNOPSIS, /* SYNOPSIS */
SEC_DESCRIPTION, /* DESCRIPTION */
SEC_CONTEXT, /* CONTEXT */
SEC_IMPLEMENTATION, /* IMPLEMENTATION NOTES */
SEC_RETURN_VALUES, /* RETURN VALUES */
SEC_ENVIRONMENT, /* ENVIRONMENT */
SEC_FILES, /* FILES */
SEC_EXIT_STATUS, /* EXIT STATUS */
SEC_EXAMPLES, /* EXAMPLES */
SEC_DIAGNOSTICS, /* DIAGNOSTICS */
SEC_COMPATIBILITY, /* COMPATIBILITY */
SEC_ERRORS, /* ERRORS */
SEC_SEE_ALSO, /* SEE ALSO */
SEC_STANDARDS, /* STANDARDS */
SEC_HISTORY, /* HISTORY */
SEC_AUTHORS, /* AUTHORS */
SEC_CAVEATS, /* CAVEATS */
SEC_BUGS, /* BUGS */
SEC_SECURITY, /* SECURITY */
SEC_CUSTOM,
SEC__MAX
};
struct mdoc_meta {
char *msec; /* `Dt' section (1, 3p, etc.) */
char *vol; /* `Dt' volume (implied) */
char *arch; /* `Dt' arch (i386, etc.) */
char *date; /* `Dd' normalised date */
char *title; /* `Dt' title (FOO, etc.) */
char *os; /* `Os' system (OpenBSD, etc.) */
char *name; /* leading `Nm' name */
};
/* /*
* An argument to a macro (multiple values = `-column xxx yyy'). * An argument to a macro (multiple values = `-column xxx yyy').
*/ */
@ -251,16 +194,6 @@ struct mdoc_arg {
unsigned int refcnt; unsigned int refcnt;
}; };
/*
* Indicates that a BODY's formatting has ended, but the scope is still
* open. Used for syntax-broken blocks.
*/
enum mdoc_endbody {
ENDBODY_NOT = 0,
ENDBODY_SPACE, /* is broken: append a space */
ENDBODY_NOSPACE /* is broken: don't append a space */
};
enum mdoc_list { enum mdoc_list {
LIST__NONE = 0, LIST__NONE = 0,
LIST_bullet, /* -bullet */ LIST_bullet, /* -bullet */
@ -337,59 +270,15 @@ union mdoc_data {
struct mdoc_bd Bd; struct mdoc_bd Bd;
struct mdoc_bf Bf; struct mdoc_bf Bf;
struct mdoc_bl Bl; struct mdoc_bl Bl;
struct mdoc_node *Es; struct roff_node *Es;
struct mdoc_rs Rs; struct mdoc_rs Rs;
}; };
/* /* Names of macros. */
* Single node in tree-linked AST.
*/
struct mdoc_node {
struct mdoc_node *parent; /* parent AST node */
struct mdoc_node *child; /* first child AST node */
struct mdoc_node *last; /* last child AST node */
struct mdoc_node *next; /* sibling AST node */
struct mdoc_node *prev; /* prior sibling AST node */
int nchild; /* number children */
int line; /* parse line */
int pos; /* parse column */
enum mdoct tok; /* tok or MDOC__MAX if none */
int flags;
#define MDOC_VALID (1 << 0) /* has been validated */
#define MDOC_ENDED (1 << 1) /* gone past body end mark */
#define MDOC_EOS (1 << 2) /* at sentence boundary */
#define MDOC_LINE (1 << 3) /* first macro/text on line */
#define MDOC_SYNPRETTY (1 << 4) /* SYNOPSIS-style formatting */
#define MDOC_BROKEN (1 << 5) /* must validate parent when ending */
#define MDOC_DELIMO (1 << 6)
#define MDOC_DELIMC (1 << 7)
enum mdoc_type type; /* AST node type */
enum mdoc_sec sec; /* current named section */
union mdoc_data *norm; /* normalised args */
int 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 *head; /* BLOCK */
struct mdoc_node *body; /* BLOCK/ENDBODY */
struct mdoc_node *tail; /* BLOCK */
char *string; /* TEXT */
const struct tbl_span *span; /* TBL */
const struct eqn *eqn; /* EQN */
enum mdoc_endbody end; /* BODY */
};
/* Names of macros. Index is enum mdoct. */
extern const char *const *mdoc_macronames; extern const char *const *mdoc_macronames;
/* Names of macro args. Index is enum mdocargt. */ /* Names of macro args. Index is enum mdocargt. */
extern const char *const *mdoc_argnames; extern const char *const *mdoc_argnames;
__BEGIN_DECLS
struct mdoc; void mdoc_validate(struct roff_man *);
const struct mdoc_node *mdoc_node(const struct mdoc *);
const struct mdoc_meta *mdoc_meta(const struct mdoc *);
void mdoc_deroff(char **, const struct mdoc_node *);
__END_DECLS

View File

@ -1,15 +1,15 @@
/* $Id: mdoc_argv.c,v 1.100 2015/02/04 18:59:45 schwarze Exp $ */ /* $Id: mdoc_argv.c,v 1.107 2015/10/17 00:21:07 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2012, 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -24,11 +24,12 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "mdoc.h"
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "libmdoc.h" #include "mandoc.h"
#include "roff.h"
#include "mdoc.h"
#include "libmandoc.h" #include "libmandoc.h"
#include "libmdoc.h"
#define MULTI_STEP 5 /* pre-allocate argument values */ #define MULTI_STEP 5 /* pre-allocate argument values */
#define DELIMSZ 6 /* max possible size of a delimiter */ #define DELIMSZ 6 /* max possible size of a delimiter */
@ -51,12 +52,12 @@ struct mdocarg {
}; };
static void argn_free(struct mdoc_arg *, int); static void argn_free(struct mdoc_arg *, int);
static enum margserr args(struct mdoc *, int, int *, static enum margserr args(struct roff_man *, int, int *,
char *, enum argsflag, char **); char *, enum argsflag, char **);
static int args_checkpunct(const char *, int); static int args_checkpunct(const char *, int);
static void argv_multi(struct mdoc *, int, static void argv_multi(struct roff_man *, int,
struct mdoc_argv *, int *, char *); struct mdoc_argv *, int *, char *);
static void argv_single(struct mdoc *, int, static void argv_single(struct roff_man *, int,
struct mdoc_argv *, int *, char *); struct mdoc_argv *, int *, char *);
static const enum argvflag argvflags[MDOC_ARG_MAX] = { static const enum argvflag argvflags[MDOC_ARG_MAX] = {
@ -275,7 +276,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
* Some flags take no argument, some one, some multiple. * Some flags take no argument, some one, some multiple.
*/ */
void void
mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok, mdoc_argv(struct roff_man *mdoc, int line, int tok,
struct mdoc_arg **reta, int *pos, char *buf) struct mdoc_arg **reta, int *pos, char *buf)
{ {
struct mdoc_argv tmpv; struct mdoc_argv tmpv;
@ -412,18 +413,18 @@ argn_free(struct mdoc_arg *p, int iarg)
} }
enum margserr enum margserr
mdoc_args(struct mdoc *mdoc, int line, int *pos, mdoc_args(struct roff_man *mdoc, int line, int *pos,
char *buf, enum mdoct tok, char **v) char *buf, int tok, char **v)
{ {
struct mdoc_node *n; struct roff_node *n;
char *v_local; char *v_local;
enum argsflag fl; enum argsflag fl;
if (v == NULL) if (v == NULL)
v = &v_local; v = &v_local;
fl = tok == MDOC_MAX ? ARGSFL_NONE : mdocargs[tok].flags; fl = tok == TOKEN_NONE ? ARGSFL_NONE : mdocargs[tok].flags;
if (tok != MDOC_It) if (tok != MDOC_It)
return(args(mdoc, 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 * We know that we're in an `It', so it's reasonable to expect
@ -439,105 +440,82 @@ mdoc_args(struct mdoc *mdoc, int line, int *pos,
break; break;
} }
return(args(mdoc, line, pos, buf, fl, v)); return args(mdoc, line, pos, buf, fl, v);
} }
static enum margserr static enum margserr
args(struct mdoc *mdoc, int line, int *pos, args(struct roff_man *mdoc, int line, int *pos,
char *buf, enum argsflag fl, char **v) char *buf, enum argsflag fl, char **v)
{ {
char *p, *pp; char *p;
int pairs; int pairs;
enum margserr rc;
if ('\0' == buf[*pos]) { if (buf[*pos] == '\0') {
if (MDOC_PPHRASE & mdoc->flags) if (mdoc->flags & MDOC_PHRASELIT &&
return(ARGS_EOLN); ! (mdoc->flags & MDOC_PHRASE)) {
/*
* 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 & mdoc->flags)
mandoc_msg(MANDOCERR_ARG_QUOTE, mandoc_msg(MANDOCERR_ARG_QUOTE,
mdoc->parse, line, *pos, NULL); mdoc->parse, line, *pos, NULL);
mdoc->flags &= ~MDOC_PHRASELIT;
mdoc->flags &= ~MDOC_PHRASELIT; }
return(ARGS_EOLN); return ARGS_EOLN;
} }
*v = &buf[*pos]; *v = buf + *pos;
if (ARGSFL_DELIM == fl) if (fl == ARGSFL_DELIM && args_checkpunct(buf, *pos))
if (args_checkpunct(buf, *pos)) return ARGS_PUNCT;
return(ARGS_PUNCT);
/* /*
* First handle TABSEP items, restricted to `Bl -column'. This * Tabs in `It' lines in `Bl -column' can't be escaped.
* ignores conventional token parsing and instead uses tabs or * Phrases are reparsed for `Ta' and other macros later.
* `Ta' macros to separate phrases. Phrases are parsed again
* for arguments at a later phase.
*/ */
if (ARGSFL_TABSEP == fl) { if (fl == ARGSFL_TABSEP) {
/* Scan ahead to tab (can't be escaped). */ if ((p = strchr(*v, '\t')) != NULL) {
p = strchr(*v, '\t');
pp = NULL;
/* Scan ahead to unescaped `Ta'. */ /*
if ( ! (MDOC_PHRASELIT & mdoc->flags)) * Words right before and right after
for (pp = *v; ; pp++) { * tab characters are not parsed,
if (NULL == (pp = strstr(pp, "Ta"))) * unless there is a blank in between.
break; */
if (pp > *v && ' ' != *(pp - 1))
continue;
if (' ' == *(pp + 2) || '\0' == *(pp + 2))
break;
}
/* By default, assume a phrase. */ if (p[-1] != ' ')
rc = ARGS_PHRASE; mdoc->flags |= MDOC_PHRASEQL;
if (p[1] != ' ')
mdoc->flags |= MDOC_PHRASEQN;
/* /*
* Adjust new-buffer position to be beyond delimiter * One or more blanks after a tab cause
* mark (e.g., Ta -> end + 2). * one leading blank in the next column.
*/ * So skip all but one of them.
if (p && pp) { */
*pos += pp < p ? 2 : 1;
rc = pp < p ? ARGS_PHRASE : ARGS_PPHRASE; *pos += (int)(p - *v) + 1;
p = pp < p ? pp : p; while (buf[*pos] == ' ' && buf[*pos + 1] == ' ')
} else if (p && ! pp) { (*pos)++;
rc = ARGS_PPHRASE;
*pos += 1; /*
} else if (pp && ! p) { * A tab at the end of an input line
p = pp; * switches to the next column.
*pos += 2; */
if (buf[*pos] == '\0' || buf[*pos + 1] == '\0')
mdoc->flags |= MDOC_PHRASEQN;
} else { } else {
rc = ARGS_PEND; p = strchr(*v, '\0');
p = strchr(*v, 0); if (p[-1] == ' ')
mandoc_msg(MANDOCERR_SPACE_EOL,
mdoc->parse, line, *pos, NULL);
*pos += (int)(p - *v);
} }
/* Whitespace check for eoln case... */ /* Skip any trailing blank characters. */
if ('\0' == *p && ' ' == *(p - 1)) while (p > *v && p[-1] == ' ' &&
mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse, (p - 1 == *v || p[-2] != '\\'))
line, *pos, NULL); p--;
*p = '\0';
*pos += (int)(p - *v); return ARGS_PHRASE;
/* Strip delimiter's preceding whitespace. */
pp = p - 1;
while (pp > *v && ' ' == *pp) {
if (pp > *v && '\\' == *(pp - 1))
break;
pp--;
}
*(pp + 1) = 0;
/* Strip delimiter's proceeding whitespace. */
for (pp = &buf[*pos]; ' ' == *pp; pp++, (*pos)++)
/* Skip ahead. */ ;
return(rc);
} }
/* /*
@ -548,11 +526,11 @@ args(struct mdoc *mdoc, int line, int *pos,
* Whitespace is NOT involved in literal termination. * Whitespace is NOT involved in literal termination.
*/ */
if (MDOC_PHRASELIT & mdoc->flags || '\"' == buf[*pos]) { if (mdoc->flags & MDOC_PHRASELIT || buf[*pos] == '\"') {
if ( ! (MDOC_PHRASELIT & mdoc->flags)) if ( ! (mdoc->flags & MDOC_PHRASELIT))
*v = &buf[++(*pos)]; *v = &buf[++(*pos)];
if (MDOC_PPHRASE & mdoc->flags) if (mdoc->flags & MDOC_PHRASE)
mdoc->flags |= MDOC_PHRASELIT; mdoc->flags |= MDOC_PHRASELIT;
pairs = 0; pairs = 0;
@ -572,19 +550,18 @@ args(struct mdoc *mdoc, int line, int *pos,
if (pairs) if (pairs)
buf[*pos - pairs] = '\0'; buf[*pos - pairs] = '\0';
if ('\0' == buf[*pos]) { if (buf[*pos] == '\0') {
if (MDOC_PPHRASE & mdoc->flags) if ( ! (mdoc->flags & MDOC_PHRASE))
return(ARGS_QWORD); mandoc_msg(MANDOCERR_ARG_QUOTE,
mandoc_msg(MANDOCERR_ARG_QUOTE, mdoc->parse, line, *pos, NULL);
mdoc->parse, line, *pos, NULL); return ARGS_QWORD;
return(ARGS_QWORD);
} }
mdoc->flags &= ~MDOC_PHRASELIT; mdoc->flags &= ~MDOC_PHRASELIT;
buf[(*pos)++] = '\0'; buf[(*pos)++] = '\0';
if ('\0' == buf[*pos]) if ('\0' == buf[*pos])
return(ARGS_QWORD); return ARGS_QWORD;
while (' ' == buf[*pos]) while (' ' == buf[*pos])
(*pos)++; (*pos)++;
@ -593,13 +570,22 @@ args(struct mdoc *mdoc, int line, int *pos,
mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse, mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse,
line, *pos, NULL); line, *pos, NULL);
return(ARGS_QWORD); return ARGS_QWORD;
} }
p = &buf[*pos]; p = &buf[*pos];
*v = mandoc_getarg(mdoc->parse, &p, line, pos); *v = mandoc_getarg(mdoc->parse, &p, line, pos);
return(ARGS_WORD); /*
* After parsing the last word in this phrase,
* tell lookup() whether or not to interpret it.
*/
if (*p == '\0' && mdoc->flags & MDOC_PHRASEQL) {
mdoc->flags &= ~MDOC_PHRASEQL;
mdoc->flags |= MDOC_PHRASEQF;
}
return ARGS_WORD;
} }
/* /*
@ -621,11 +607,11 @@ args_checkpunct(const char *buf, int i)
dbuf[j] = buf[i]; dbuf[j] = buf[i];
if (DELIMSZ == j) if (DELIMSZ == j)
return(0); return 0;
dbuf[j] = '\0'; dbuf[j] = '\0';
if (DELIM_CLOSE != mdoc_isdelim(dbuf)) if (DELIM_CLOSE != mdoc_isdelim(dbuf))
return(0); return 0;
while (' ' == buf[i]) while (' ' == buf[i])
i++; i++;
@ -638,22 +624,22 @@ args_checkpunct(const char *buf, int i)
dbuf[j++] = buf[i++]; dbuf[j++] = buf[i++];
if (DELIMSZ == j) if (DELIMSZ == j)
return(0); return 0;
dbuf[j] = '\0'; dbuf[j] = '\0';
d = mdoc_isdelim(dbuf); d = mdoc_isdelim(dbuf);
if (DELIM_NONE == d || DELIM_OPEN == d) if (DELIM_NONE == d || DELIM_OPEN == d)
return(0); return 0;
while (' ' == buf[i]) while (' ' == buf[i])
i++; i++;
} }
return('\0' == buf[i]); return '\0' == buf[i];
} }
static void static void
argv_multi(struct mdoc *mdoc, int line, argv_multi(struct roff_man *mdoc, int line,
struct mdoc_argv *v, int *pos, char *buf) struct mdoc_argv *v, int *pos, char *buf)
{ {
enum margserr ac; enum margserr ac;
@ -675,7 +661,7 @@ argv_multi(struct mdoc *mdoc, int line,
} }
static void static void
argv_single(struct mdoc *mdoc, int line, argv_single(struct roff_man *mdoc, int line,
struct mdoc_argv *v, int *pos, char *buf) struct mdoc_argv *v, int *pos, char *buf)
{ {
enum margserr ac; enum margserr ac;

View File

@ -1,6 +1,7 @@
/* $Id: mdoc_hash.c,v 1.21 2014/08/10 23:54:41 schwarze Exp $ */ /* $Id: mdoc_hash.c,v 1.26 2015/10/06 18:32:19 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -25,22 +26,22 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "roff.h"
#include "mdoc.h" #include "mdoc.h"
#include "libmdoc.h" #include "libmdoc.h"
static unsigned char table[27 * 12]; static unsigned char table[27 * 12];
/*
* XXX - this hash has global scope, so if intended for use as a library
* with multiple callers, it will need re-invocation protection.
*/
void void
mdoc_hash_init(void) mdoc_hash_init(void)
{ {
int i, j, major; int i, j, major;
const char *p; const char *p;
if (*table != '\0')
return;
memset(table, UCHAR_MAX, sizeof(table)); memset(table, UCHAR_MAX, sizeof(table));
for (i = 0; i < (int)MDOC_MAX; i++) { for (i = 0; i < (int)MDOC_MAX; i++) {
@ -61,32 +62,32 @@ mdoc_hash_init(void)
} }
} }
enum mdoct int
mdoc_hash_find(const char *p) mdoc_hash_find(const char *p)
{ {
int major, i, j; int major, i, j;
if (0 == p[0]) if (0 == p[0])
return(MDOC_MAX); return TOKEN_NONE;
if ( ! isalpha((unsigned char)p[0]) && '%' != p[0]) if ( ! isalpha((unsigned char)p[0]) && '%' != p[0])
return(MDOC_MAX); return TOKEN_NONE;
if (isalpha((unsigned char)p[1])) if (isalpha((unsigned char)p[1]))
major = 12 * (tolower((unsigned char)p[1]) - 97); major = 12 * (tolower((unsigned char)p[1]) - 97);
else if ('1' == p[1]) else if ('1' == p[1])
major = 12 * 26; major = 12 * 26;
else else
return(MDOC_MAX); return TOKEN_NONE;
if (p[2] && p[3]) if (p[2] && p[3])
return(MDOC_MAX); return TOKEN_NONE;
for (j = 0; j < 12; j++) { for (j = 0; j < 12; j++) {
if (UCHAR_MAX == (i = table[major + j])) if (UCHAR_MAX == (i = table[major + j]))
break; break;
if (0 == strcmp(p, mdoc_macronames[i])) if (0 == strcmp(p, mdoc_macronames[i]))
return((enum mdoct)i); return i;
} }
return(MDOC_MAX); return TOKEN_NONE;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $Id: mdoc_macro.c,v 1.183 2015/02/12 12:24:33 schwarze Exp $ */ /* $Id: mdoc_macro.c,v 1.206 2015/10/20 02:01:32 schwarze Exp $ */
/* /*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
@ -7,9 +7,9 @@
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -26,10 +26,12 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "mdoc.h"
#include "mandoc.h" #include "mandoc.h"
#include "libmdoc.h" #include "roff.h"
#include "mdoc.h"
#include "libmandoc.h" #include "libmandoc.h"
#include "roff_int.h"
#include "libmdoc.h"
static void blk_full(MACRO_PROT_ARGS); static void blk_full(MACRO_PROT_ARGS);
static void blk_exp_close(MACRO_PROT_ARGS); static void blk_exp_close(MACRO_PROT_ARGS);
@ -41,18 +43,19 @@ static void in_line_argn(MACRO_PROT_ARGS);
static void in_line(MACRO_PROT_ARGS); static void in_line(MACRO_PROT_ARGS);
static void phrase_ta(MACRO_PROT_ARGS); static void phrase_ta(MACRO_PROT_ARGS);
static void dword(struct mdoc *, int, int, const char *, static void append_delims(struct roff_man *, int, int *, char *);
enum mdelim, int); static void dword(struct roff_man *, int, int, const char *,
static void append_delims(struct mdoc *, int, int *, char *); enum mdelim, int);
static enum mdoct lookup(struct mdoc *, enum mdoct, static int find_pending(struct roff_man *, int, int, int,
int, int, const char *); struct roff_node *);
static int lookup(struct roff_man *, int, int, int, const char *);
static int macro_or_word(MACRO_PROT_ARGS, int); static int macro_or_word(MACRO_PROT_ARGS, int);
static int parse_rest(struct mdoc *, enum mdoct, static int parse_rest(struct roff_man *, int, int, int *, char *);
int, int *, char *); static int rew_alt(int);
static enum mdoct rew_alt(enum mdoct); static void rew_elem(struct roff_man *, int);
static void rew_elem(struct mdoc *, enum mdoct); static void rew_last(struct roff_man *, const struct roff_node *);
static void rew_last(struct mdoc *, const struct mdoc_node *); static void rew_pending(struct roff_man *,
static void rew_pending(struct mdoc *, const struct mdoc_node *); const struct roff_node *);
const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */
@ -207,9 +210,9 @@ const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
* are errors. * are errors.
*/ */
void void
mdoc_macroend(struct mdoc *mdoc) mdoc_endparse(struct roff_man *mdoc)
{ {
struct mdoc_node *n; struct roff_node *n;
/* Scan for open explicit scopes. */ /* Scan for open explicit scopes. */
@ -217,7 +220,7 @@ mdoc_macroend(struct mdoc *mdoc)
mdoc->last->parent : mdoc->last; mdoc->last->parent : mdoc->last;
for ( ; n; n = n->parent) for ( ; n; n = n->parent)
if (n->type == MDOC_BLOCK && if (n->type == ROFFT_BLOCK &&
mdoc_macros[n->tok].flags & MDOC_EXPLICIT) mdoc_macros[n->tok].flags & MDOC_EXPLICIT)
mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse, mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse,
n->line, n->pos, mdoc_macronames[n->tok]); n->line, n->pos, mdoc_macronames[n->tok]);
@ -225,86 +228,87 @@ mdoc_macroend(struct mdoc *mdoc)
/* Rewind to the first. */ /* Rewind to the first. */
rew_last(mdoc, mdoc->first); rew_last(mdoc, mdoc->first);
mdoc_state_reset(mdoc);
} }
/* /*
* Look up the macro at *p called by "from", * Look up the macro at *p called by "from",
* or as a line macro if from == MDOC_MAX. * or as a line macro if from == TOKEN_NONE.
*/ */
static enum mdoct static int
lookup(struct mdoc *mdoc, enum mdoct from, int line, int ppos, const char *p) lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p)
{ {
enum mdoct res; int res;
if (from == MDOC_MAX || mdoc_macros[from].flags & MDOC_PARSED) { if (mdoc->flags & MDOC_PHRASEQF) {
mdoc->flags &= ~MDOC_PHRASEQF;
return TOKEN_NONE;
}
if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) {
res = mdoc_hash_find(p); res = mdoc_hash_find(p);
if (res != MDOC_MAX) { if (res != TOKEN_NONE) {
if (mdoc_macros[res].flags & MDOC_CALLABLE) if (mdoc_macros[res].flags & MDOC_CALLABLE)
return(res); return res;
if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll) if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll)
mandoc_msg(MANDOCERR_MACRO_CALL, mandoc_msg(MANDOCERR_MACRO_CALL,
mdoc->parse, line, ppos, p); mdoc->parse, line, ppos, p);
} }
} }
return(MDOC_MAX); return TOKEN_NONE;
} }
/* /*
* Rewind up to and including a specific node. * Rewind up to and including a specific node.
*/ */
static void static void
rew_last(struct mdoc *mdoc, const struct mdoc_node *to) rew_last(struct roff_man *mdoc, const struct roff_node *to)
{ {
struct mdoc_node *n, *np;
assert(to); if (to->flags & MDOC_VALID)
mdoc->next = MDOC_NEXT_SIBLING; return;
while (mdoc->last != to) { while (mdoc->last != to) {
/* mdoc_state(mdoc, mdoc->last);
* Save the parent here, because we may delete the mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;
* mdoc->last node in the post-validation phase and reset mdoc->last = mdoc->last->parent;
* it to mdoc->last->parent, causing a step in the closing
* out to be lost.
*/
np = mdoc->last->parent;
mdoc_valid_post(mdoc);
n = mdoc->last;
mdoc->last = np;
assert(mdoc->last);
mdoc->last->last = n;
} }
mdoc_valid_post(mdoc); mdoc_state(mdoc, mdoc->last);
mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;
mdoc->next = ROFF_NEXT_SIBLING;
} }
/* /*
* Rewind up to a specific block, including all blocks that broke it. * Rewind up to a specific block, including all blocks that broke it.
*/ */
static void static void
rew_pending(struct mdoc *mdoc, const struct mdoc_node *n) rew_pending(struct roff_man *mdoc, const struct roff_node *n)
{ {
for (;;) { for (;;) {
rew_last(mdoc, n); rew_last(mdoc, n);
switch (n->type) { if (mdoc->last == n) {
case MDOC_HEAD: switch (n->type) {
mdoc_body_alloc(mdoc, n->line, n->pos, n->tok); case ROFFT_HEAD:
return; roff_body_alloc(mdoc, n->line, n->pos,
case MDOC_BLOCK: n->tok);
break; return;
default: case ROFFT_BLOCK:
return; break;
} default:
return;
if ( ! (n->flags & MDOC_BROKEN)) }
return; if ( ! (n->flags & MDOC_BROKEN))
return;
} else
n = mdoc->last;
for (;;) { for (;;) {
if ((n = n->parent) == NULL) if ((n = n->parent) == NULL)
return; return;
if (n->type == MDOC_BLOCK || if (n->type == ROFFT_BLOCK ||
n->type == MDOC_HEAD) { n->type == ROFFT_HEAD) {
if (n->flags & MDOC_ENDED) if (n->flags & MDOC_ENDED)
break; break;
else else
@ -318,67 +322,104 @@ rew_pending(struct mdoc *mdoc, const struct mdoc_node *n)
* For a block closing macro, return the corresponding opening one. * For a block closing macro, return the corresponding opening one.
* Otherwise, return the macro itself. * Otherwise, return the macro itself.
*/ */
static enum mdoct static int
rew_alt(enum mdoct tok) rew_alt(int tok)
{ {
switch (tok) { switch (tok) {
case MDOC_Ac: case MDOC_Ac:
return(MDOC_Ao); return MDOC_Ao;
case MDOC_Bc: case MDOC_Bc:
return(MDOC_Bo); return MDOC_Bo;
case MDOC_Brc: case MDOC_Brc:
return(MDOC_Bro); return MDOC_Bro;
case MDOC_Dc: case MDOC_Dc:
return(MDOC_Do); return MDOC_Do;
case MDOC_Ec: case MDOC_Ec:
return(MDOC_Eo); return MDOC_Eo;
case MDOC_Ed: case MDOC_Ed:
return(MDOC_Bd); return MDOC_Bd;
case MDOC_Ef: case MDOC_Ef:
return(MDOC_Bf); return MDOC_Bf;
case MDOC_Ek: case MDOC_Ek:
return(MDOC_Bk); return MDOC_Bk;
case MDOC_El: case MDOC_El:
return(MDOC_Bl); return MDOC_Bl;
case MDOC_Fc: case MDOC_Fc:
return(MDOC_Fo); return MDOC_Fo;
case MDOC_Oc: case MDOC_Oc:
return(MDOC_Oo); return MDOC_Oo;
case MDOC_Pc: case MDOC_Pc:
return(MDOC_Po); return MDOC_Po;
case MDOC_Qc: case MDOC_Qc:
return(MDOC_Qo); return MDOC_Qo;
case MDOC_Re: case MDOC_Re:
return(MDOC_Rs); return MDOC_Rs;
case MDOC_Sc: case MDOC_Sc:
return(MDOC_So); return MDOC_So;
case MDOC_Xc: case MDOC_Xc:
return(MDOC_Xo); return MDOC_Xo;
default: default:
return(tok); return tok;
} }
/* NOTREACHED */
} }
static void static void
rew_elem(struct mdoc *mdoc, enum mdoct tok) rew_elem(struct roff_man *mdoc, int tok)
{ {
struct mdoc_node *n; struct roff_node *n;
n = mdoc->last; n = mdoc->last;
if (MDOC_ELEM != n->type) if (n->type != ROFFT_ELEM)
n = n->parent; n = n->parent;
assert(MDOC_ELEM == n->type); assert(n->type == ROFFT_ELEM);
assert(tok == n->tok); assert(tok == n->tok);
rew_last(mdoc, n); rew_last(mdoc, n);
} }
/*
* If there is an open sub-block of the target requiring
* explicit close-out, postpone closing out the target until
* the rew_pending() call closing out the sub-block.
*/
static int
find_pending(struct roff_man *mdoc, int tok, int line, int ppos,
struct roff_node *target)
{
struct roff_node *n;
int irc;
irc = 0;
for (n = mdoc->last; n != NULL && n != target; n = n->parent) {
if (n->flags & MDOC_ENDED) {
if ( ! (n->flags & MDOC_VALID))
n->flags |= MDOC_BROKEN;
continue;
}
if (n->type == ROFFT_BLOCK &&
mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {
irc = 1;
n->flags = MDOC_BROKEN;
if (target->type == ROFFT_HEAD)
target->flags = MDOC_ENDED;
else if ( ! (target->flags & MDOC_ENDED)) {
mandoc_vmsg(MANDOCERR_BLK_NEST,
mdoc->parse, line, ppos,
"%s breaks %s", mdoc_macronames[tok],
mdoc_macronames[n->tok]);
mdoc_endbody_alloc(mdoc, line, ppos,
tok, target, ENDBODY_NOSPACE);
}
}
}
return irc;
}
/* /*
* Allocate a word and check whether it's punctuation or not. * Allocate a word and check whether it's punctuation or not.
* Punctuation consists of those tokens found in mdoc_isdelim(). * Punctuation consists of those tokens found in mdoc_isdelim().
*/ */
static void static void
dword(struct mdoc *mdoc, int line, int col, const char *p, dword(struct roff_man *mdoc, int line, int col, const char *p,
enum mdelim d, int may_append) enum mdelim d, int may_append)
{ {
@ -387,13 +428,13 @@ dword(struct mdoc *mdoc, int line, int col, const char *p,
if (may_append && if (may_append &&
! (mdoc->flags & (MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF)) && ! (mdoc->flags & (MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF)) &&
d == DELIM_NONE && mdoc->last->type == MDOC_TEXT && d == DELIM_NONE && mdoc->last->type == ROFFT_TEXT &&
mdoc_isdelim(mdoc->last->string) == DELIM_NONE) { mdoc_isdelim(mdoc->last->string) == DELIM_NONE) {
mdoc_word_append(mdoc, p); roff_word_append(mdoc, p);
return; return;
} }
mdoc_word_alloc(mdoc, line, col, p); roff_word_alloc(mdoc, line, col, p);
/* /*
* If the word consists of a bare delimiter, * If the word consists of a bare delimiter,
@ -412,7 +453,7 @@ dword(struct mdoc *mdoc, int line, int col, const char *p,
} }
static void static void
append_delims(struct mdoc *mdoc, int line, int *pos, char *buf) append_delims(struct roff_man *mdoc, int line, int *pos, char *buf)
{ {
char *p; char *p;
int la; int la;
@ -422,7 +463,8 @@ append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
for (;;) { for (;;) {
la = *pos; la = *pos;
if (mdoc_args(mdoc, line, pos, buf, MDOC_MAX, &p) == ARGS_EOLN) if (mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p) ==
ARGS_EOLN)
break; break;
dword(mdoc, line, la, p, DELIM_MAX, 1); dword(mdoc, line, la, p, DELIM_MAX, 1);
@ -452,26 +494,26 @@ static int
macro_or_word(MACRO_PROT_ARGS, int parsed) macro_or_word(MACRO_PROT_ARGS, int parsed)
{ {
char *p; char *p;
enum mdoct ntok; int ntok;
p = buf + ppos; p = buf + ppos;
ntok = MDOC_MAX; ntok = TOKEN_NONE;
if (*p == '"') if (*p == '"')
p++; p++;
else if (parsed && ! (mdoc->flags & MDOC_PHRASELIT)) else if (parsed && ! (mdoc->flags & MDOC_PHRASELIT))
ntok = lookup(mdoc, tok, line, ppos, p); ntok = lookup(mdoc, tok, line, ppos, p);
if (ntok == MDOC_MAX) { if (ntok == TOKEN_NONE) {
dword(mdoc, line, ppos, p, DELIM_MAX, tok == MDOC_MAX || dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE ||
mdoc_macros[tok].flags & MDOC_JOIN); mdoc_macros[tok].flags & MDOC_JOIN);
return(0); return 0;
} else { } else {
if (mdoc_macros[tok].fp == in_line_eoln) if (mdoc_macros[tok].fp == in_line_eoln)
rew_elem(mdoc, tok); rew_elem(mdoc, tok);
mdoc_macro(mdoc, ntok, line, ppos, pos, buf); mdoc_macro(mdoc, ntok, line, ppos, pos, buf);
if (tok == MDOC_MAX) if (tok == TOKEN_NONE)
append_delims(mdoc, line, pos, buf); append_delims(mdoc, line, pos, buf);
return(1); return 1;
} }
} }
@ -481,15 +523,16 @@ macro_or_word(MACRO_PROT_ARGS, int parsed)
static void static void
blk_exp_close(MACRO_PROT_ARGS) blk_exp_close(MACRO_PROT_ARGS)
{ {
struct mdoc_node *body; /* Our own body. */ struct roff_node *body; /* Our own body. */
struct mdoc_node *endbody; /* Our own end marker. */ struct roff_node *endbody; /* Our own end marker. */
struct mdoc_node *itblk; /* An It block starting later. */ struct roff_node *itblk; /* An It block starting later. */
struct mdoc_node *later; /* A sub-block starting later. */ struct roff_node *later; /* A sub-block starting later. */
struct mdoc_node *n; /* Search back to our block. */ struct roff_node *n; /* Search back to our block. */
struct roff_node *target; /* For find_pending(). */
int j, lastarg, maxargs, nl; int j, lastarg, maxargs, nl, pending;
enum margserr ac; enum margserr ac;
enum mdoct atok, ntok; int atok, ntok;
char *p; char *p;
nl = MDOC_NEWLINE & mdoc->flags; nl = MDOC_NEWLINE & mdoc->flags;
@ -522,13 +565,13 @@ blk_exp_close(MACRO_PROT_ARGS)
/* Remember the start of our own body. */ /* Remember the start of our own body. */
if (n->type == MDOC_BODY && atok == n->tok) { if (n->type == ROFFT_BODY && atok == n->tok) {
if (n->end == ENDBODY_NOT) if (n->end == ENDBODY_NOT)
body = n; body = n;
continue; continue;
} }
if (n->type != MDOC_BLOCK || n->tok == MDOC_Nm) if (n->type != ROFFT_BLOCK || n->tok == MDOC_Nm)
continue; continue;
if (n->tok == MDOC_It) { if (n->tok == MDOC_It) {
@ -575,7 +618,7 @@ blk_exp_close(MACRO_PROT_ARGS)
*/ */
if (maxargs) if (maxargs)
mdoc->next = MDOC_NEXT_CHILD; mdoc->next = ROFF_NEXT_CHILD;
break; break;
} }
@ -596,12 +639,14 @@ blk_exp_close(MACRO_PROT_ARGS)
if (body == NULL) { if (body == NULL) {
mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse, mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse,
line, ppos, mdoc_macronames[tok]); line, ppos, mdoc_macronames[tok]);
if (later != NULL)
later->flags &= ~MDOC_BROKEN;
if (maxargs && endbody == NULL) { if (maxargs && endbody == NULL) {
/* /*
* Stray .Ec without previous .Eo: * Stray .Ec without previous .Eo:
* Break the output line, keep the arguments. * Break the output line, keep the arguments.
*/ */
mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL); roff_elem_alloc(mdoc, line, ppos, MDOC_br);
rew_elem(mdoc, MDOC_br); rew_elem(mdoc, MDOC_br);
} }
} else if (endbody == NULL) { } else if (endbody == NULL) {
@ -623,38 +668,47 @@ blk_exp_close(MACRO_PROT_ARGS)
if (endbody != NULL) if (endbody != NULL)
n = endbody; n = endbody;
ntok = TOKEN_NONE;
for (j = 0; ; j++) { for (j = 0; ; j++) {
lastarg = *pos; lastarg = *pos;
if (j == maxargs && n != NULL) { if (j == maxargs && n != NULL)
rew_pending(mdoc, n); rew_last(mdoc, n);
n = NULL;
}
ac = mdoc_args(mdoc, line, pos, buf, tok, &p); ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ac == ARGS_PUNCT || ac == ARGS_EOLN) if (ac == ARGS_PUNCT || ac == ARGS_EOLN)
break; break;
ntok = ac == ARGS_QWORD ? MDOC_MAX : ntok = ac == ARGS_QWORD ? TOKEN_NONE :
lookup(mdoc, tok, line, lastarg, p); lookup(mdoc, tok, line, lastarg, p);
if (ntok == MDOC_MAX) { if (ntok == TOKEN_NONE) {
dword(mdoc, line, lastarg, p, DELIM_MAX, dword(mdoc, line, lastarg, p, DELIM_MAX,
MDOC_JOIN & mdoc_macros[tok].flags); MDOC_JOIN & mdoc_macros[tok].flags);
continue; continue;
} }
if (n != NULL) { if (n != NULL)
rew_pending(mdoc, n); rew_last(mdoc, n);
n = NULL;
}
mdoc->flags &= ~MDOC_NEWLINE; mdoc->flags &= ~MDOC_NEWLINE;
mdoc_macro(mdoc, ntok, line, lastarg, pos, buf); mdoc_macro(mdoc, ntok, line, lastarg, pos, buf);
break; break;
} }
if (n != NULL) if (n != NULL) {
rew_pending(mdoc, n); if (ntok != TOKEN_NONE && n->flags & MDOC_BROKEN) {
target = n;
do
target = target->parent;
while ( ! (target->flags & MDOC_ENDED));
pending = find_pending(mdoc, ntok, line, ppos,
target);
} else
pending = 0;
if ( ! pending)
rew_pending(mdoc, n);
}
if (nl) if (nl)
append_delims(mdoc, line, pos, buf); append_delims(mdoc, line, pos, buf);
} }
@ -663,7 +717,7 @@ static void
in_line(MACRO_PROT_ARGS) in_line(MACRO_PROT_ARGS)
{ {
int la, scope, cnt, firstarg, mayopen, nc, nl; int la, scope, cnt, firstarg, mayopen, nc, nl;
enum mdoct ntok; int ntok;
enum margserr ac; enum margserr ac;
enum mdelim d; enum mdelim d;
struct mdoc_arg *arg; struct mdoc_arg *arg;
@ -678,15 +732,10 @@ in_line(MACRO_PROT_ARGS)
switch (tok) { switch (tok) {
case MDOC_An: case MDOC_An:
/* FALLTHROUGH */
case MDOC_Ar: case MDOC_Ar:
/* FALLTHROUGH */
case MDOC_Fl: case MDOC_Fl:
/* FALLTHROUGH */
case MDOC_Mt: case MDOC_Mt:
/* FALLTHROUGH */
case MDOC_Nm: case MDOC_Nm:
/* FALLTHROUGH */
case MDOC_Pa: case MDOC_Pa:
nc = 1; nc = 1;
break; break;
@ -730,7 +779,7 @@ in_line(MACRO_PROT_ARGS)
} }
ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ? ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ?
MDOC_MAX : lookup(mdoc, tok, line, la, p); TOKEN_NONE : lookup(mdoc, tok, line, la, p);
/* /*
* In this case, we've located a submacro and must * In this case, we've located a submacro and must
@ -739,7 +788,7 @@ in_line(MACRO_PROT_ARGS)
* or raise a warning. * or raise a warning.
*/ */
if (ntok != MDOC_MAX) { if (ntok != TOKEN_NONE) {
if (scope) if (scope)
rew_elem(mdoc, tok); rew_elem(mdoc, tok);
if (nc && ! cnt) { if (nc && ! cnt) {
@ -847,10 +896,10 @@ blk_full(MACRO_PROT_ARGS)
{ {
int la, nl, parsed; int la, nl, parsed;
struct mdoc_arg *arg; struct mdoc_arg *arg;
struct mdoc_node *blk; /* Our own or a broken block. */ struct roff_node *blk; /* Our own or a broken block. */
struct mdoc_node *head; /* Our own head. */ struct roff_node *head; /* Our own head. */
struct mdoc_node *body; /* Our own body. */ struct roff_node *body; /* Our own body. */
struct mdoc_node *n; struct roff_node *n;
enum margserr ac, lac; enum margserr ac, lac;
char *p; char *p;
@ -873,7 +922,7 @@ blk_full(MACRO_PROT_ARGS)
n->flags |= MDOC_BROKEN; n->flags |= MDOC_BROKEN;
continue; continue;
} }
if (n->type != MDOC_BLOCK) if (n->type != ROFFT_BLOCK)
continue; continue;
if (tok == MDOC_It && n->tok == MDOC_Bl) { if (tok == MDOC_It && n->tok == MDOC_Bl) {
@ -890,7 +939,6 @@ blk_full(MACRO_PROT_ARGS)
if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {
switch (tok) { switch (tok) {
case MDOC_Sh: case MDOC_Sh:
/* FALLTHROUGH */
case MDOC_Ss: case MDOC_Ss:
mandoc_vmsg(MANDOCERR_BLK_BROKEN, mandoc_vmsg(MANDOCERR_BLK_BROKEN,
mdoc->parse, line, ppos, mdoc->parse, line, ppos,
@ -938,7 +986,7 @@ blk_full(MACRO_PROT_ARGS)
if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) { if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) {
mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse, mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse,
line, ppos, "It %s", buf + *pos); line, ppos, "It %s", buf + *pos);
mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL); roff_elem_alloc(mdoc, line, ppos, MDOC_br);
rew_elem(mdoc, MDOC_br); rew_elem(mdoc, MDOC_br);
return; return;
} }
@ -972,34 +1020,47 @@ blk_full(MACRO_PROT_ARGS)
*/ */
if (tok == MDOC_Nd) { if (tok == MDOC_Nd) {
head = mdoc_head_alloc(mdoc, line, ppos, tok); head = roff_head_alloc(mdoc, line, ppos, tok);
rew_last(mdoc, head); rew_last(mdoc, head);
body = mdoc_body_alloc(mdoc, line, ppos, tok); body = roff_body_alloc(mdoc, line, ppos, tok);
} }
if (tok == MDOC_Bk) if (tok == MDOC_Bk)
mdoc->flags |= MDOC_KEEP; mdoc->flags |= MDOC_KEEP;
ac = ARGS_PEND; ac = ARGS_EOLN;
for (;;) { for (;;) {
/*
* If we are right after a tab character,
* do not parse the first word for macros.
*/
if (mdoc->flags & MDOC_PHRASEQN) {
mdoc->flags &= ~MDOC_PHRASEQN;
mdoc->flags |= MDOC_PHRASEQF;
}
la = *pos; la = *pos;
lac = ac; lac = ac;
ac = mdoc_args(mdoc, line, pos, buf, tok, &p); ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
if (ac == ARGS_EOLN) { if (ac == ARGS_EOLN) {
if (lac != ARGS_PPHRASE && lac != ARGS_PHRASE) if (lac != ARGS_PHRASE ||
! (mdoc->flags & MDOC_PHRASEQF))
break; break;
/* /*
* This is necessary: if the last token on a * This line ends in a tab; start the next
* line is a `Ta' or tab, then we'll get * column now, with a leading blank.
* ARGS_EOLN, so we must be smart enough to
* reopen our scope if the last parse was a
* phrase or partial phrase.
*/ */
if (body != NULL) if (body != NULL)
rew_last(mdoc, body); rew_last(mdoc, body);
body = mdoc_body_alloc(mdoc, line, ppos, tok); body = roff_body_alloc(mdoc, line, ppos, tok);
roff_word_alloc(mdoc, line, ppos, "\\&");
break; break;
} }
if (tok == MDOC_Bd || tok == MDOC_Bk) { if (tok == MDOC_Bd || tok == MDOC_Bk) {
mandoc_vmsg(MANDOCERR_ARG_EXCESS, mandoc_vmsg(MANDOCERR_ARG_EXCESS,
mdoc->parse, line, la, "%s ... %s", mdoc->parse, line, la, "%s ... %s",
@ -1016,13 +1077,11 @@ blk_full(MACRO_PROT_ARGS)
/* /*
* Emit leading punctuation (i.e., punctuation before * Emit leading punctuation (i.e., punctuation before
* the MDOC_HEAD) for non-phrase types. * the ROFFT_HEAD) for non-phrase types.
*/ */
if (head == NULL && if (head == NULL &&
ac != ARGS_PEND &&
ac != ARGS_PHRASE && ac != ARGS_PHRASE &&
ac != ARGS_PPHRASE &&
ac != ARGS_QWORD && ac != ARGS_QWORD &&
mdoc_isdelim(p) == DELIM_OPEN) { mdoc_isdelim(p) == DELIM_OPEN) {
dword(mdoc, line, la, p, DELIM_OPEN, 0); dword(mdoc, line, la, p, DELIM_OPEN, 0);
@ -1032,11 +1091,9 @@ blk_full(MACRO_PROT_ARGS)
/* Open a head if one hasn't been opened. */ /* Open a head if one hasn't been opened. */
if (head == NULL) if (head == NULL)
head = mdoc_head_alloc(mdoc, line, ppos, tok); head = roff_head_alloc(mdoc, line, ppos, tok);
if (ac == ARGS_PHRASE || if (ac == ARGS_PHRASE) {
ac == ARGS_PEND ||
ac == ARGS_PPHRASE) {
/* /*
* If we haven't opened a body yet, rewind the * If we haven't opened a body yet, rewind the
@ -1044,20 +1101,18 @@ blk_full(MACRO_PROT_ARGS)
*/ */
rew_last(mdoc, body == NULL ? head : body); rew_last(mdoc, body == NULL ? head : body);
body = mdoc_body_alloc(mdoc, line, ppos, tok); body = roff_body_alloc(mdoc, line, ppos, tok);
/* /* Process to the tab or to the end of the line. */
* Process phrases: set whether we're in a
* partial-phrase (this effects line handling)
* then call down into the phrase parser.
*/
if (ac == ARGS_PPHRASE) mdoc->flags |= MDOC_PHRASE;
mdoc->flags |= MDOC_PPHRASE; parse_rest(mdoc, TOKEN_NONE, line, &la, buf);
if (ac == ARGS_PEND && lac == ARGS_PPHRASE) mdoc->flags &= ~MDOC_PHRASE;
mdoc->flags |= MDOC_PPHRASE;
parse_rest(mdoc, MDOC_MAX, line, &la, buf); /* There may have been `Ta' macros. */
mdoc->flags &= ~MDOC_PPHRASE;
while (body->next != NULL)
body = body->next;
continue; continue;
} }
@ -1068,37 +1123,18 @@ blk_full(MACRO_PROT_ARGS)
if (blk->flags & MDOC_VALID) if (blk->flags & MDOC_VALID)
return; return;
if (head == NULL) if (head == NULL)
head = mdoc_head_alloc(mdoc, line, ppos, tok); head = roff_head_alloc(mdoc, line, ppos, tok);
if (nl && tok != MDOC_Bd && tok != MDOC_Bl && tok != MDOC_Rs) if (nl && tok != MDOC_Bd && tok != MDOC_Bl && tok != MDOC_Rs)
append_delims(mdoc, line, pos, buf); append_delims(mdoc, line, pos, buf);
if (body != NULL) if (body != NULL)
goto out; goto out;
if (find_pending(mdoc, tok, line, ppos, head))
/*
* If there is an open (i.e., unvalidated) sub-block requiring
* explicit close-out, postpone switching the current block from
* head to body until the rew_pending() call closing out that
* sub-block.
*/
for (n = mdoc->last; n && n != head; n = n->parent) {
if (n->flags & MDOC_ENDED) {
if ( ! (n->flags & MDOC_VALID))
n->flags |= MDOC_BROKEN;
continue;
}
if (n->type == MDOC_BLOCK &&
mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {
n->flags = MDOC_BROKEN;
head->flags = MDOC_ENDED;
}
}
if (head->flags & MDOC_ENDED)
return; return;
/* Close out scopes to remain in a consistent state. */ /* Close out scopes to remain in a consistent state. */
rew_last(mdoc, head); rew_last(mdoc, head);
body = mdoc_body_alloc(mdoc, line, ppos, tok); body = roff_body_alloc(mdoc, line, ppos, tok);
out: out:
if (mdoc->flags & MDOC_FREECOL) { if (mdoc->flags & MDOC_FREECOL) {
rew_last(mdoc, body); rew_last(mdoc, body);
@ -1113,9 +1149,9 @@ blk_part_imp(MACRO_PROT_ARGS)
int la, nl; int la, nl;
enum margserr ac; enum margserr ac;
char *p; char *p;
struct mdoc_node *blk; /* saved block context */ struct roff_node *blk; /* saved block context */
struct mdoc_node *body; /* saved body context */ struct roff_node *body; /* saved body context */
struct mdoc_node *n; struct roff_node *n;
nl = MDOC_NEWLINE & mdoc->flags; nl = MDOC_NEWLINE & mdoc->flags;
@ -1129,7 +1165,7 @@ blk_part_imp(MACRO_PROT_ARGS)
*/ */
blk = mdoc_block_alloc(mdoc, line, ppos, tok, NULL); blk = mdoc_block_alloc(mdoc, line, ppos, tok, NULL);
rew_last(mdoc, mdoc_head_alloc(mdoc, line, ppos, tok)); rew_last(mdoc, roff_head_alloc(mdoc, line, ppos, tok));
/* /*
* Open the body scope "on-demand", that is, after we've * Open the body scope "on-demand", that is, after we've
@ -1150,42 +1186,15 @@ blk_part_imp(MACRO_PROT_ARGS)
} }
if (body == NULL) if (body == NULL)
body = mdoc_body_alloc(mdoc, line, ppos, tok); body = roff_body_alloc(mdoc, line, ppos, tok);
if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))
break; break;
} }
if (body == NULL) if (body == NULL)
body = mdoc_body_alloc(mdoc, line, ppos, tok); body = roff_body_alloc(mdoc, line, ppos, tok);
/* if (find_pending(mdoc, tok, line, ppos, body))
* If there is an open sub-block requiring explicit close-out,
* postpone closing out the current block until the
* rew_pending() call closing out the sub-block.
*/
for (n = mdoc->last; n && n != body && n != blk->parent;
n = n->parent) {
if (n->flags & MDOC_ENDED) {
if ( ! (n->flags & MDOC_VALID))
n->flags |= MDOC_BROKEN;
continue;
}
if (n->type == MDOC_BLOCK &&
mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {
n->flags |= MDOC_BROKEN;
if ( ! (body->flags & MDOC_ENDED)) {
mandoc_vmsg(MANDOCERR_BLK_NEST,
mdoc->parse, line, ppos,
"%s breaks %s", mdoc_macronames[tok],
mdoc_macronames[n->tok]);
mdoc_endbody_alloc(mdoc, line, ppos,
tok, body, ENDBODY_NOSPACE);
}
}
}
assert(n == body);
if (body->flags & MDOC_ENDED)
return; return;
rew_last(mdoc, body); rew_last(mdoc, body);
@ -1206,7 +1215,7 @@ blk_part_exp(MACRO_PROT_ARGS)
{ {
int la, nl; int la, nl;
enum margserr ac; enum margserr ac;
struct mdoc_node *head; /* keep track of head */ struct roff_node *head; /* keep track of head */
char *p; char *p;
nl = MDOC_NEWLINE & mdoc->flags; nl = MDOC_NEWLINE & mdoc->flags;
@ -1217,7 +1226,7 @@ blk_part_exp(MACRO_PROT_ARGS)
* case of `Eo'); and a body that may be empty. * case of `Eo'); and a body that may be empty.
*/ */
mdoc_block_alloc(mdoc, line, ppos, tok, NULL); roff_block_alloc(mdoc, line, ppos, tok);
head = NULL; head = NULL;
for (;;) { for (;;) {
la = *pos; la = *pos;
@ -1234,11 +1243,11 @@ blk_part_exp(MACRO_PROT_ARGS)
} }
if (head == NULL) { if (head == NULL) {
head = mdoc_head_alloc(mdoc, line, ppos, tok); head = roff_head_alloc(mdoc, line, ppos, tok);
if (tok == MDOC_Eo) /* Not parsed. */ if (tok == MDOC_Eo) /* Not parsed. */
dword(mdoc, line, la, p, DELIM_MAX, 0); dword(mdoc, line, la, p, DELIM_MAX, 0);
rew_last(mdoc, head); rew_last(mdoc, head);
mdoc_body_alloc(mdoc, line, ppos, tok); roff_body_alloc(mdoc, line, ppos, tok);
if (tok == MDOC_Eo) if (tok == MDOC_Eo)
continue; continue;
} }
@ -1250,8 +1259,8 @@ blk_part_exp(MACRO_PROT_ARGS)
/* Clean-up to leave in a consistent state. */ /* Clean-up to leave in a consistent state. */
if (head == NULL) { if (head == NULL) {
rew_last(mdoc, mdoc_head_alloc(mdoc, line, ppos, tok)); rew_last(mdoc, roff_head_alloc(mdoc, line, ppos, tok));
mdoc_body_alloc(mdoc, line, ppos, tok); roff_body_alloc(mdoc, line, ppos, tok);
} }
if (nl) if (nl)
append_delims(mdoc, line, pos, buf); append_delims(mdoc, line, pos, buf);
@ -1263,7 +1272,7 @@ in_line_argn(MACRO_PROT_ARGS)
struct mdoc_arg *arg; struct mdoc_arg *arg;
char *p; char *p;
enum margserr ac; enum margserr ac;
enum mdoct ntok; int ntok;
int state; /* arg#; -1: not yet open; -2: closed */ int state; /* arg#; -1: not yet open; -2: closed */
int la, maxargs, nl; int la, maxargs, nl;
@ -1279,16 +1288,12 @@ in_line_argn(MACRO_PROT_ARGS)
switch (tok) { switch (tok) {
case MDOC_Ap: case MDOC_Ap:
/* FALLTHROUGH */
case MDOC_Ns: case MDOC_Ns:
/* FALLTHROUGH */
case MDOC_Ux: case MDOC_Ux:
maxargs = 0; maxargs = 0;
break; break;
case MDOC_Bx: case MDOC_Bx:
/* FALLTHROUGH */
case MDOC_Es: case MDOC_Es:
/* FALLTHROUGH */
case MDOC_Xr: case MDOC_Xr:
maxargs = 2; maxargs = 2;
break; break;
@ -1332,9 +1337,9 @@ in_line_argn(MACRO_PROT_ARGS)
} }
ntok = (ac == ARGS_QWORD || (tok == MDOC_Pf && state == 0)) ? ntok = (ac == ARGS_QWORD || (tok == MDOC_Pf && state == 0)) ?
MDOC_MAX : lookup(mdoc, tok, line, la, p); TOKEN_NONE : lookup(mdoc, tok, line, la, p);
if (ntok != MDOC_MAX) { if (ntok != TOKEN_NONE) {
if (state >= 0) { if (state >= 0) {
rew_elem(mdoc, tok); rew_elem(mdoc, tok);
state = -2; state = -2;
@ -1377,16 +1382,16 @@ in_line_argn(MACRO_PROT_ARGS)
static void static void
in_line_eoln(MACRO_PROT_ARGS) in_line_eoln(MACRO_PROT_ARGS)
{ {
struct mdoc_node *n; struct roff_node *n;
struct mdoc_arg *arg; struct mdoc_arg *arg;
if ((tok == MDOC_Pp || tok == MDOC_Lp) && if ((tok == MDOC_Pp || tok == MDOC_Lp) &&
! (mdoc->flags & MDOC_SYNOPSIS)) { ! (mdoc->flags & MDOC_SYNOPSIS)) {
n = mdoc->last; n = mdoc->last;
if (mdoc->next == MDOC_NEXT_SIBLING) if (mdoc->next == ROFF_NEXT_SIBLING)
n = n->parent; n = n->parent;
if (n->tok == MDOC_Nm) if (n->tok == MDOC_Nm)
rew_last(mdoc, mdoc->last->parent); rew_last(mdoc, n->parent);
} }
if (buf[*pos] == '\0' && if (buf[*pos] == '\0' &&
@ -1409,16 +1414,16 @@ in_line_eoln(MACRO_PROT_ARGS)
* or until the next macro, call that macro, and return 1. * or until the next macro, call that macro, and return 1.
*/ */
static int static int
parse_rest(struct mdoc *mdoc, enum mdoct tok, int line, int *pos, char *buf) parse_rest(struct roff_man *mdoc, int tok, int line, int *pos, char *buf)
{ {
int la; int la;
for (;;) { for (;;) {
la = *pos; la = *pos;
if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN) if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN)
return(0); return 0;
if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))
return(1); return 1;
} }
} }
@ -1444,7 +1449,7 @@ ctx_synopsis(MACRO_PROT_ARGS)
static void static void
phrase_ta(MACRO_PROT_ARGS) phrase_ta(MACRO_PROT_ARGS)
{ {
struct mdoc_node *body, *n; struct roff_node *body, *n;
/* Make sure we are in a column list or ignore this macro. */ /* Make sure we are in a column list or ignore this macro. */
@ -1452,7 +1457,7 @@ phrase_ta(MACRO_PROT_ARGS)
for (n = mdoc->last; n != NULL; n = n->parent) { for (n = mdoc->last; n != NULL; n = n->parent) {
if (n->flags & MDOC_ENDED) if (n->flags & MDOC_ENDED)
continue; continue;
if (n->tok == MDOC_It && n->type == MDOC_BODY) if (n->tok == MDOC_It && n->type == ROFFT_BODY)
body = n; body = n;
if (n->tok == MDOC_Bl) if (n->tok == MDOC_Bl)
break; break;
@ -1467,6 +1472,6 @@ phrase_ta(MACRO_PROT_ARGS)
/* Advance to the next column. */ /* Advance to the next column. */
rew_last(mdoc, body); rew_last(mdoc, body);
mdoc_body_alloc(mdoc, line, ppos, MDOC_It); roff_body_alloc(mdoc, line, ppos, MDOC_It);
parse_rest(mdoc, MDOC_MAX, line, pos, buf); parse_rest(mdoc, TOKEN_NONE, line, pos, buf);
} }

View File

@ -1,6 +1,6 @@
/* $Id: mdoc_man.c,v 1.88 2015/02/17 20:37:17 schwarze Exp $ */ /* $Id: mdoc_man.c,v 1.96 2016/01/08 17:48:09 schwarze Exp $ */
/* /*
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -22,14 +22,15 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "out.h" #include "mandoc.h"
#include "man.h" #include "roff.h"
#include "mdoc.h" #include "mdoc.h"
#include "man.h"
#include "out.h"
#include "main.h" #include "main.h"
#define DECL_ARGS const struct mdoc_meta *meta, struct mdoc_node *n #define DECL_ARGS const struct roff_meta *meta, struct roff_node *n
struct manact { struct manact {
int (*cond)(DECL_ARGS); /* DON'T run actions */ int (*cond)(DECL_ARGS); /* DON'T run actions */
@ -107,7 +108,7 @@ static int pre_sm(DECL_ARGS);
static int pre_sp(DECL_ARGS); static int pre_sp(DECL_ARGS);
static int pre_sect(DECL_ARGS); static int pre_sect(DECL_ARGS);
static int pre_sy(DECL_ARGS); static int pre_sy(DECL_ARGS);
static void pre_syn(const struct mdoc_node *); static void pre_syn(const struct roff_node *);
static int pre_vt(DECL_ARGS); static int pre_vt(DECL_ARGS);
static int pre_ux(DECL_ARGS); static int pre_ux(DECL_ARGS);
static int pre_xr(DECL_ARGS); static int pre_xr(DECL_ARGS);
@ -116,7 +117,7 @@ static void print_line(const char *, int);
static void print_block(const char *, int); static void print_block(const char *, int);
static void print_offs(const char *, int); static void print_offs(const char *, int);
static void print_width(const struct mdoc_bl *, static void print_width(const struct mdoc_bl *,
const struct mdoc_node *); const struct roff_node *);
static void print_count(int *); static void print_count(int *);
static void print_node(DECL_ARGS); static void print_node(DECL_ARGS);
@ -467,7 +468,7 @@ print_offs(const char *v, int keywords)
* Set up the indentation for a list item; used from pre_it(). * Set up the indentation for a list item; used from pre_it().
*/ */
static void static void
print_width(const struct mdoc_bl *bl, const struct mdoc_node *child) print_width(const struct mdoc_bl *bl, const struct roff_node *child)
{ {
char buf[24]; char buf[24];
struct roffsu su; struct roffsu su;
@ -492,7 +493,7 @@ print_width(const struct mdoc_bl *bl, const struct mdoc_node *child)
/* XXX Rough estimation, might have multiple parts. */ /* XXX Rough estimation, might have multiple parts. */
if (bl->type == LIST_enum) if (bl->type == LIST_enum)
chsz = (bl->count > 8) + 1; chsz = (bl->count > 8) + 1;
else if (child != NULL && child->type == MDOC_TEXT) else if (child != NULL && child->type == ROFFT_TEXT)
chsz = strlen(child->string); chsz = strlen(child->string);
else else
chsz = 0; chsz = 0;
@ -531,7 +532,7 @@ print_count(int *count)
} }
void void
man_man(void *arg, const struct man *man) man_man(void *arg, const struct roff_man *man)
{ {
/* /*
@ -544,18 +545,14 @@ man_man(void *arg, const struct man *man)
} }
void void
man_mdoc(void *arg, const struct mdoc *mdoc) man_mdoc(void *arg, const struct roff_man *mdoc)
{ {
const struct mdoc_meta *meta; struct roff_node *n;
struct mdoc_node *n;
meta = mdoc_meta(mdoc);
n = mdoc_node(mdoc)->child;
printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
meta->title, mdoc->meta.title,
(meta->msec == NULL ? "" : meta->msec), (mdoc->meta.msec == NULL ? "" : mdoc->meta.msec),
meta->date, meta->os, meta->vol); mdoc->meta.date, mdoc->meta.os, mdoc->meta.vol);
/* Disable hyphenation and if nroff, disable justification. */ /* Disable hyphenation and if nroff, disable justification. */
printf(".nh\n.if n .ad l"); printf(".nh\n.if n .ad l");
@ -566,10 +563,8 @@ man_mdoc(void *arg, const struct mdoc *mdoc)
fontqueue.head = fontqueue.tail = mandoc_malloc(8); fontqueue.head = fontqueue.tail = mandoc_malloc(8);
*fontqueue.tail = 'R'; *fontqueue.tail = 'R';
} }
while (n != NULL) { for (n = mdoc->first->child; n != NULL; n = n->next)
print_node(meta, n); print_node(&mdoc->meta, n);
n = n->next;
}
putchar('\n'); putchar('\n');
} }
@ -577,7 +572,7 @@ static void
print_node(DECL_ARGS) print_node(DECL_ARGS)
{ {
const struct manact *act; const struct manact *act;
struct mdoc_node *sub; struct roff_node *sub;
int cond, do_sub; int cond, do_sub;
/* /*
@ -592,7 +587,7 @@ print_node(DECL_ARGS)
do_sub = 1; do_sub = 1;
n->flags &= ~MDOC_ENDED; n->flags &= ~MDOC_ENDED;
if (MDOC_TEXT == n->type) { if (n->type == ROFFT_TEXT) {
/* /*
* Make sure that we don't happen to start with a * Make sure that we don't happen to start with a
* control character at the start of a line. * control character at the start of a line.
@ -615,7 +610,8 @@ print_node(DECL_ARGS)
*/ */
act = manacts + n->tok; act = manacts + n->tok;
cond = act->cond == NULL || (*act->cond)(meta, n); cond = act->cond == NULL || (*act->cond)(meta, n);
if (cond && act->pre && (n->end == ENDBODY_NOT || n->nchild)) if (cond && act->pre != NULL &&
(n->end == ENDBODY_NOT || n->child != NULL))
do_sub = (*act->pre)(meta, n); do_sub = (*act->pre)(meta, n);
} }
@ -648,14 +644,14 @@ static int
cond_head(DECL_ARGS) cond_head(DECL_ARGS)
{ {
return(MDOC_HEAD == n->type); return n->type == ROFFT_HEAD;
} }
static int static int
cond_body(DECL_ARGS) cond_body(DECL_ARGS)
{ {
return(MDOC_BODY == n->type); return n->type == ROFFT_BODY;
} }
static int static int
@ -665,10 +661,10 @@ pre_enc(DECL_ARGS)
prefix = manacts[n->tok].prefix; prefix = manacts[n->tok].prefix;
if (NULL == prefix) if (NULL == prefix)
return(1); return 1;
print_word(prefix); print_word(prefix);
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(1); return 1;
} }
static void static void
@ -686,37 +682,36 @@ post_enc(DECL_ARGS)
static int static int
pre_ex(DECL_ARGS) pre_ex(DECL_ARGS)
{ {
int nchild; struct roff_node *nch;
outflags |= MMAN_br | MMAN_nl; outflags |= MMAN_br | MMAN_nl;
print_word("The"); print_word("The");
nchild = n->nchild; for (nch = n->child; nch != NULL; nch = nch->next) {
for (n = n->child; n; n = n->next) {
font_push('B'); font_push('B');
print_word(n->string); print_word(nch->string);
font_pop(); font_pop();
if (n->next == NULL) if (nch->next == NULL)
continue; continue;
if (nchild > 2) { if (nch->prev != NULL || nch->next->next != NULL) {
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word(","); print_word(",");
} }
if (n->next->next == NULL) if (nch->next->next == NULL)
print_word("and"); print_word("and");
} }
if (nchild > 1) if (n->child != NULL && n->child->next != NULL)
print_word("utilities exit\\~0"); print_word("utilities exit\\~0");
else else
print_word("utility exits\\~0"); print_word("utility exits\\~0");
print_word("on success, and\\~>0 if an error occurs."); print_word("on success, and\\~>0 if an error occurs.");
outflags |= MMAN_nl; outflags |= MMAN_nl;
return(0); return 0;
} }
static void static void
@ -754,7 +749,7 @@ pre__t(DECL_ARGS)
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
} else } else
font_push('I'); font_push('I');
return(1); return 1;
} }
static void static void
@ -778,14 +773,14 @@ static int
pre_sect(DECL_ARGS) pre_sect(DECL_ARGS)
{ {
if (MDOC_HEAD == n->type) { if (n->type == ROFFT_HEAD) {
outflags |= MMAN_sp; outflags |= MMAN_sp;
print_block(manacts[n->tok].prefix, 0); print_block(manacts[n->tok].prefix, 0);
print_word(""); print_word("");
putchar('\"'); putchar('\"');
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
} }
return(1); return 1;
} }
/* /*
@ -795,7 +790,7 @@ static void
post_sect(DECL_ARGS) post_sect(DECL_ARGS)
{ {
if (MDOC_HEAD != n->type) if (n->type != ROFFT_HEAD)
return; return;
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word(""); print_word("");
@ -807,7 +802,7 @@ post_sect(DECL_ARGS)
/* See mdoc_term.c, synopsis_pre() for comments. */ /* See mdoc_term.c, synopsis_pre() for comments. */
static void static void
pre_syn(const struct mdoc_node *n) pre_syn(const struct roff_node *n)
{ {
if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags)) if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
@ -823,13 +818,9 @@ pre_syn(const struct mdoc_node *n)
switch (n->prev->tok) { switch (n->prev->tok) {
case MDOC_Fd: case MDOC_Fd:
/* FALLTHROUGH */
case MDOC_Fn: case MDOC_Fn:
/* FALLTHROUGH */
case MDOC_Fo: case MDOC_Fo:
/* FALLTHROUGH */
case MDOC_In: case MDOC_In:
/* FALLTHROUGH */
case MDOC_Vt: case MDOC_Vt:
outflags |= MMAN_sp; outflags |= MMAN_sp;
break; break;
@ -853,18 +844,18 @@ pre_an(DECL_ARGS)
case AUTH_split: case AUTH_split:
outflags &= ~MMAN_An_nosplit; outflags &= ~MMAN_An_nosplit;
outflags |= MMAN_An_split; outflags |= MMAN_An_split;
return(0); return 0;
case AUTH_nosplit: case AUTH_nosplit:
outflags &= ~MMAN_An_split; outflags &= ~MMAN_An_split;
outflags |= MMAN_An_nosplit; outflags |= MMAN_An_nosplit;
return(0); return 0;
default: default:
if (MMAN_An_split & outflags) if (MMAN_An_split & outflags)
outflags |= MMAN_br; outflags |= MMAN_br;
else if (SEC_AUTHORS == n->sec && else if (SEC_AUTHORS == n->sec &&
! (MMAN_An_nosplit & outflags)) ! (MMAN_An_nosplit & outflags))
outflags |= MMAN_An_split; outflags |= MMAN_An_split;
return(1); return 1;
} }
} }
@ -875,17 +866,17 @@ pre_ap(DECL_ARGS)
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word("'"); print_word("'");
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(0); return 0;
} }
static int static int
pre_aq(DECL_ARGS) pre_aq(DECL_ARGS)
{ {
print_word(n->nchild == 1 && print_word(n->child != NULL && n->child->next == NULL &&
n->child->tok == MDOC_Mt ? "<" : "\\(la"); n->child->tok == MDOC_Mt ? "<" : "\\(la");
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(1); return 1;
} }
static void static void
@ -893,7 +884,7 @@ post_aq(DECL_ARGS)
{ {
outflags &= ~(MMAN_spc | MMAN_nl); outflags &= ~(MMAN_spc | MMAN_nl);
print_word(n->nchild == 1 && print_word(n->child != NULL && n->child->next == NULL &&
n->child->tok == MDOC_Mt ? ">" : "\\(ra"); n->child->tok == MDOC_Mt ? ">" : "\\(ra");
} }
@ -909,7 +900,7 @@ pre_bd(DECL_ARGS)
if (0 == n->norm->Bd.comp && NULL != n->parent->prev) if (0 == n->norm->Bd.comp && NULL != n->parent->prev)
outflags |= MMAN_sp; outflags |= MMAN_sp;
print_offs(n->norm->Bd.offs, 1); print_offs(n->norm->Bd.offs, 1);
return(1); return 1;
} }
static void static void
@ -932,12 +923,12 @@ pre_bf(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MDOC_BLOCK: case ROFFT_BLOCK:
return(1); return 1;
case MDOC_BODY: case ROFFT_BODY:
break; break;
default: default:
return(0); return 0;
} }
switch (n->norm->Bf.font) { switch (n->norm->Bf.font) {
case FONT_Em: case FONT_Em:
@ -950,14 +941,14 @@ pre_bf(DECL_ARGS)
font_push('R'); font_push('R');
break; break;
} }
return(1); return 1;
} }
static void static void
post_bf(DECL_ARGS) post_bf(DECL_ARGS)
{ {
if (MDOC_BODY == n->type) if (n->type == ROFFT_BODY)
font_pop(); font_pop();
} }
@ -966,13 +957,13 @@ pre_bk(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MDOC_BLOCK: case ROFFT_BLOCK:
return(1); return 1;
case MDOC_BODY: case ROFFT_BODY:
outflags |= MMAN_Bk; outflags |= MMAN_Bk;
return(1); return 1;
default: default:
return(0); return 0;
} }
} }
@ -980,7 +971,7 @@ static void
post_bk(DECL_ARGS) post_bk(DECL_ARGS)
{ {
if (MDOC_BODY == n->type) if (n->type == ROFFT_BODY)
outflags &= ~MMAN_Bk; outflags &= ~MMAN_Bk;
} }
@ -1002,21 +993,21 @@ pre_bl(DECL_ARGS)
switch (n->norm->Bl.type) { switch (n->norm->Bl.type) {
case LIST_enum: case LIST_enum:
n->norm->Bl.count = 0; n->norm->Bl.count = 0;
return(1); return 1;
case LIST_column: case LIST_column:
break; break;
default: default:
return(1); return 1;
} }
if (n->nchild) { if (n->child != NULL) {
print_line(".TS", MMAN_nl); print_line(".TS", MMAN_nl);
for (icol = 0; icol < n->norm->Bl.ncols; icol++) for (icol = 0; icol < n->norm->Bl.ncols; icol++)
print_word("l"); print_word("l");
print_word("."); print_word(".");
} }
outflags |= MMAN_nl; outflags |= MMAN_nl;
return(1); return 1;
} }
static void static void
@ -1025,7 +1016,7 @@ post_bl(DECL_ARGS)
switch (n->norm->Bl.type) { switch (n->norm->Bl.type) {
case LIST_column: case LIST_column:
if (n->nchild) if (n->child != NULL)
print_line(".TE", 0); print_line(".TE", 0);
break; break;
case LIST_enum: case LIST_enum:
@ -1056,7 +1047,7 @@ pre_br(DECL_ARGS)
{ {
outflags |= MMAN_br; outflags |= MMAN_br;
return(0); return 0;
} }
static int static int
@ -1071,12 +1062,12 @@ pre_bx(DECL_ARGS)
} }
print_word("BSD"); print_word("BSD");
if (NULL == n) if (NULL == n)
return(0); return 0;
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word("-"); print_word("-");
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word(n->string); print_word(n->string);
return(0); return 0;
} }
static int static int
@ -1084,7 +1075,7 @@ pre_dl(DECL_ARGS)
{ {
print_offs("6n", 0); print_offs("6n", 0);
return(1); return 1;
} }
static void static void
@ -1103,7 +1094,7 @@ pre_em(DECL_ARGS)
{ {
font_push('I'); font_push('I');
return(1); return 1;
} }
static int static int
@ -1112,11 +1103,11 @@ pre_en(DECL_ARGS)
if (NULL == n->norm->Es || if (NULL == n->norm->Es ||
NULL == n->norm->Es->child) NULL == n->norm->Es->child)
return(1); return 1;
print_word(n->norm->Es->child->string); print_word(n->norm->Es->child->string);
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(1); return 1;
} }
static void static void
@ -1146,7 +1137,7 @@ pre_eo(DECL_ARGS)
n->parent->head->child != NULL && (n->child != NULL || n->parent->head->child != NULL && (n->child != NULL ||
(n->parent->tail != NULL && n->parent->tail->child != NULL))) (n->parent->tail != NULL && n->parent->tail->child != NULL)))
outflags &= ~(MMAN_spc | MMAN_nl); outflags &= ~(MMAN_spc | MMAN_nl);
return(1); return 1;
} }
static void static void
@ -1189,7 +1180,7 @@ pre_fa(DECL_ARGS)
if (NULL != (n = n->next)) if (NULL != (n = n->next))
print_word(","); print_word(",");
} }
return(0); return 0;
} }
static void static void
@ -1206,7 +1197,7 @@ pre_fd(DECL_ARGS)
pre_syn(n); pre_syn(n);
font_push('B'); font_push('B');
return(1); return 1;
} }
static void static void
@ -1223,9 +1214,9 @@ pre_fl(DECL_ARGS)
font_push('B'); font_push('B');
print_word("\\-"); print_word("\\-");
if (n->nchild) if (n->child != NULL)
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(1); return 1;
} }
static void static void
@ -1233,9 +1224,9 @@ post_fl(DECL_ARGS)
{ {
font_pop(); font_pop();
if ( ! (n->nchild || if (!(n->child != NULL ||
n->next == NULL || n->next == NULL ||
n->next->type == MDOC_TEXT || n->next->type == ROFFT_TEXT ||
n->next->flags & MDOC_LINE)) n->next->flags & MDOC_LINE))
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
} }
@ -1248,7 +1239,7 @@ pre_fn(DECL_ARGS)
n = n->child; n = n->child;
if (NULL == n) if (NULL == n)
return(0); return 0;
if (MDOC_SYNPRETTY & n->flags) if (MDOC_SYNPRETTY & n->flags)
print_block(".HP 4n", MMAN_nl); print_block(".HP 4n", MMAN_nl);
@ -1263,7 +1254,7 @@ pre_fn(DECL_ARGS)
n = n->next; n = n->next;
if (NULL != n) if (NULL != n)
pre_fa(meta, n); pre_fa(meta, n);
return(0); return 0;
} }
static void static void
@ -1282,17 +1273,17 @@ pre_fo(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MDOC_BLOCK: case ROFFT_BLOCK:
pre_syn(n); pre_syn(n);
break; break;
case MDOC_HEAD: case ROFFT_HEAD:
if (n->child == NULL) if (n->child == NULL)
return(0); return 0;
if (MDOC_SYNPRETTY & n->flags) if (MDOC_SYNPRETTY & n->flags)
print_block(".HP 4n", MMAN_nl); print_block(".HP 4n", MMAN_nl);
font_push('B'); font_push('B');
break; break;
case MDOC_BODY: case ROFFT_BODY:
outflags &= ~(MMAN_spc | MMAN_nl); outflags &= ~(MMAN_spc | MMAN_nl);
print_word("("); print_word("(");
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
@ -1300,7 +1291,7 @@ pre_fo(DECL_ARGS)
default: default:
break; break;
} }
return(1); return 1;
} }
static void static void
@ -1308,11 +1299,11 @@ post_fo(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MDOC_HEAD: case ROFFT_HEAD:
if (n->child != NULL) if (n->child != NULL)
font_pop(); font_pop();
break; break;
case MDOC_BODY: case ROFFT_BODY:
post_fn(meta, n); post_fn(meta, n);
break; break;
default: default:
@ -1326,7 +1317,7 @@ pre_ft(DECL_ARGS)
pre_syn(n); pre_syn(n);
font_push('I'); font_push('I');
return(1); return 1;
} }
static int static int
@ -1343,7 +1334,7 @@ pre_in(DECL_ARGS)
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
font_push('I'); font_push('I');
} }
return(1); return 1;
} }
static void static void
@ -1365,10 +1356,10 @@ post_in(DECL_ARGS)
static int static int
pre_it(DECL_ARGS) pre_it(DECL_ARGS)
{ {
const struct mdoc_node *bln; const struct roff_node *bln;
switch (n->type) { switch (n->type) {
case MDOC_HEAD: case ROFFT_HEAD:
outflags |= MMAN_PP | MMAN_nl; outflags |= MMAN_PP | MMAN_nl;
bln = n->parent->parent; bln = n->parent->parent;
if (0 == bln->norm->Bl.comp || if (0 == bln->norm->Bl.comp ||
@ -1378,22 +1369,18 @@ pre_it(DECL_ARGS)
outflags &= ~MMAN_br; outflags &= ~MMAN_br;
switch (bln->norm->Bl.type) { switch (bln->norm->Bl.type) {
case LIST_item: case LIST_item:
return(0); return 0;
case LIST_inset: case LIST_inset:
/* FALLTHROUGH */
case LIST_diag: case LIST_diag:
/* FALLTHROUGH */
case LIST_ohang: case LIST_ohang:
if (bln->norm->Bl.type == LIST_diag) if (bln->norm->Bl.type == LIST_diag)
print_line(".B \"", 0); print_line(".B \"", 0);
else else
print_line(".R \"", 0); print_line(".R \"", 0);
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(1); return 1;
case LIST_bullet: case LIST_bullet:
/* FALLTHROUGH */
case LIST_dash: case LIST_dash:
/* FALLTHROUGH */
case LIST_hyphen: case LIST_hyphen:
print_width(&bln->norm->Bl, NULL); print_width(&bln->norm->Bl, NULL);
TPremain = 0; TPremain = 0;
@ -1405,31 +1392,31 @@ pre_it(DECL_ARGS)
print_word("-"); print_word("-");
font_pop(); font_pop();
outflags |= MMAN_nl; outflags |= MMAN_nl;
return(0); return 0;
case LIST_enum: case LIST_enum:
print_width(&bln->norm->Bl, NULL); print_width(&bln->norm->Bl, NULL);
TPremain = 0; TPremain = 0;
outflags |= MMAN_nl; outflags |= MMAN_nl;
print_count(&bln->norm->Bl.count); print_count(&bln->norm->Bl.count);
outflags |= MMAN_nl; outflags |= MMAN_nl;
return(0); return 0;
case LIST_hang: case LIST_hang:
print_width(&bln->norm->Bl, n->child); print_width(&bln->norm->Bl, n->child);
TPremain = 0; TPremain = 0;
outflags |= MMAN_nl; outflags |= MMAN_nl;
return(1); return 1;
case LIST_tag: case LIST_tag:
print_width(&bln->norm->Bl, n->child); print_width(&bln->norm->Bl, n->child);
putchar('\n'); putchar('\n');
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(1); return 1;
default: default:
return(1); return 1;
} }
default: default:
break; break;
} }
return(1); return 1;
} }
/* /*
@ -1462,12 +1449,12 @@ mid_it(void)
static void static void
post_it(DECL_ARGS) post_it(DECL_ARGS)
{ {
const struct mdoc_node *bln; const struct roff_node *bln;
bln = n->parent->parent; bln = n->parent->parent;
switch (n->type) { switch (n->type) {
case MDOC_HEAD: case ROFFT_HEAD:
switch (bln->norm->Bl.type) { switch (bln->norm->Bl.type) {
case LIST_diag: case LIST_diag:
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
@ -1480,18 +1467,13 @@ post_it(DECL_ARGS)
break; break;
} }
break; break;
case MDOC_BODY: case ROFFT_BODY:
switch (bln->norm->Bl.type) { switch (bln->norm->Bl.type) {
case LIST_bullet: case LIST_bullet:
/* FALLTHROUGH */
case LIST_dash: case LIST_dash:
/* FALLTHROUGH */
case LIST_hyphen: case LIST_hyphen:
/* FALLTHROUGH */
case LIST_enum: case LIST_enum:
/* FALLTHROUGH */
case LIST_hang: case LIST_hang:
/* FALLTHROUGH */
case LIST_tag: case LIST_tag:
assert(Bl_stack_len); assert(Bl_stack_len);
Bl_stack[--Bl_stack_len] = 0; Bl_stack[--Bl_stack_len] = 0;
@ -1532,10 +1514,10 @@ post_lb(DECL_ARGS)
static int static int
pre_lk(DECL_ARGS) pre_lk(DECL_ARGS)
{ {
const struct mdoc_node *link, *descr; const struct roff_node *link, *descr;
if (NULL == (link = n->child)) if (NULL == (link = n->child))
return(0); return 0;
if (NULL != (descr = link->next)) { if (NULL != (descr = link->next)) {
font_push('I'); font_push('I');
@ -1550,7 +1532,7 @@ pre_lk(DECL_ARGS)
font_push('B'); font_push('B');
print_word(link->string); print_word(link->string);
font_pop(); font_pop();
return(0); return 0;
} }
static int static int
@ -1558,7 +1540,7 @@ pre_ll(DECL_ARGS)
{ {
print_line(".ll", 0); print_line(".ll", 0);
return(1); return 1;
} }
static int static int
@ -1566,7 +1548,7 @@ pre_li(DECL_ARGS)
{ {
font_push('R'); font_push('R');
return(1); return 1;
} }
static int static int
@ -1574,16 +1556,16 @@ pre_nm(DECL_ARGS)
{ {
char *name; char *name;
if (MDOC_BLOCK == n->type) { if (n->type == ROFFT_BLOCK) {
outflags |= MMAN_Bk; outflags |= MMAN_Bk;
pre_syn(n); pre_syn(n);
} }
if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) if (n->type != ROFFT_ELEM && n->type != ROFFT_HEAD)
return(1); return 1;
name = n->child ? n->child->string : meta->name; name = n->child ? n->child->string : meta->name;
if (NULL == name) if (NULL == name)
return(0); return 0;
if (MDOC_HEAD == n->type) { if (n->type == ROFFT_HEAD) {
if (NULL == n->parent->prev) if (NULL == n->parent->prev)
outflags |= MMAN_sp; outflags |= MMAN_sp;
print_block(".HP", 0); print_block(".HP", 0);
@ -1593,7 +1575,7 @@ pre_nm(DECL_ARGS)
font_push('B'); font_push('B');
if (NULL == n->child) if (NULL == n->child)
print_word(meta->name); print_word(meta->name);
return(1); return 1;
} }
static void static void
@ -1601,12 +1583,11 @@ post_nm(DECL_ARGS)
{ {
switch (n->type) { switch (n->type) {
case MDOC_BLOCK: case ROFFT_BLOCK:
outflags &= ~MMAN_Bk; outflags &= ~MMAN_Bk;
break; break;
case MDOC_HEAD: case ROFFT_HEAD:
/* FALLTHROUGH */ case ROFFT_ELEM:
case MDOC_ELEM:
if (n->child != NULL || meta->name != NULL) if (n->child != NULL || meta->name != NULL)
font_pop(); font_pop();
break; break;
@ -1620,7 +1601,7 @@ pre_no(DECL_ARGS)
{ {
outflags |= MMAN_spc_force; outflags |= MMAN_spc_force;
return(1); return 1;
} }
static int static int
@ -1628,7 +1609,7 @@ pre_ns(DECL_ARGS)
{ {
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(0); return 0;
} }
static void static void
@ -1647,7 +1628,7 @@ pre_pp(DECL_ARGS)
outflags |= MMAN_PP; outflags |= MMAN_PP;
outflags |= MMAN_sp | MMAN_nl; outflags |= MMAN_sp | MMAN_nl;
outflags &= ~MMAN_br; outflags &= ~MMAN_br;
return(0); return 0;
} }
static int static int
@ -1658,40 +1639,39 @@ pre_rs(DECL_ARGS)
outflags |= MMAN_PP | MMAN_sp | MMAN_nl; outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
outflags &= ~MMAN_br; outflags &= ~MMAN_br;
} }
return(1); return 1;
} }
static int static int
pre_rv(DECL_ARGS) pre_rv(DECL_ARGS)
{ {
int nchild; struct roff_node *nch;
outflags |= MMAN_br | MMAN_nl; outflags |= MMAN_br | MMAN_nl;
nchild = n->nchild; if (n->child != NULL) {
if (nchild > 0) {
print_word("The"); print_word("The");
for (n = n->child; n; n = n->next) { for (nch = n->child; nch != NULL; nch = nch->next) {
font_push('B'); font_push('B');
print_word(n->string); print_word(nch->string);
font_pop(); font_pop();
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word("()"); print_word("()");
if (n->next == NULL) if (nch->next == NULL)
continue; continue;
if (nchild > 2) { if (nch->prev != NULL || nch->next->next != NULL) {
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word(","); print_word(",");
} }
if (n->next->next == NULL) if (nch->next->next == NULL)
print_word("and"); print_word("and");
} }
if (nchild > 1) if (n->child != NULL && n->child->next != NULL)
print_word("functions return"); print_word("functions return");
else else
print_word("function returns"); print_word("function returns");
@ -1710,14 +1690,14 @@ pre_rv(DECL_ARGS)
print_word("is set to indicate the error."); print_word("is set to indicate the error.");
outflags |= MMAN_nl; outflags |= MMAN_nl;
return(0); return 0;
} }
static int static int
pre_skip(DECL_ARGS) pre_skip(DECL_ARGS)
{ {
return(0); return 0;
} }
static int static int
@ -1734,7 +1714,7 @@ pre_sm(DECL_ARGS)
if (MMAN_Sm & outflags) if (MMAN_Sm & outflags)
outflags |= MMAN_spc; outflags |= MMAN_spc;
return(0); return 0;
} }
static int static int
@ -1746,7 +1726,7 @@ pre_sp(DECL_ARGS)
print_line(".PP", 0); print_line(".PP", 0);
} else } else
print_line(".sp", 0); print_line(".sp", 0);
return(1); return 1;
} }
static void static void
@ -1761,7 +1741,7 @@ pre_sy(DECL_ARGS)
{ {
font_push('B'); font_push('B');
return(1); return 1;
} }
static int static int
@ -1770,24 +1750,24 @@ pre_vt(DECL_ARGS)
if (MDOC_SYNPRETTY & n->flags) { if (MDOC_SYNPRETTY & n->flags) {
switch (n->type) { switch (n->type) {
case MDOC_BLOCK: case ROFFT_BLOCK:
pre_syn(n); pre_syn(n);
return(1); return 1;
case MDOC_BODY: case ROFFT_BODY:
break; break;
default: default:
return(0); return 0;
} }
} }
font_push('I'); font_push('I');
return(1); return 1;
} }
static void static void
post_vt(DECL_ARGS) post_vt(DECL_ARGS)
{ {
if (MDOC_SYNPRETTY & n->flags && MDOC_BODY != n->type) if (n->flags & MDOC_SYNPRETTY && n->type != ROFFT_BODY)
return; return;
font_pop(); font_pop();
} }
@ -1798,16 +1778,16 @@ pre_xr(DECL_ARGS)
n = n->child; n = n->child;
if (NULL == n) if (NULL == n)
return(0); return 0;
print_node(meta, n); print_node(meta, n);
n = n->next; n = n->next;
if (NULL == n) if (NULL == n)
return(0); return 0;
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word("("); print_word("(");
print_node(meta, n); print_node(meta, n);
print_word(")"); print_word(")");
return(0); return 0;
} }
static int static int
@ -1816,9 +1796,9 @@ pre_ux(DECL_ARGS)
print_word(manacts[n->tok].prefix); print_word(manacts[n->tok].prefix);
if (NULL == n->child) if (NULL == n->child)
return(0); return 0;
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
print_word("\\ "); print_word("\\ ");
outflags &= ~MMAN_spc; outflags &= ~MMAN_spc;
return(1); return 1;
} }

292
contrib/mdocml/mdoc_state.c Normal file
View File

@ -0,0 +1,292 @@
/* $Id: mdoc_state.c,v 1.3 2015/10/30 18:53:54 schwarze Exp $ */
/*
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "mandoc.h"
#include "roff.h"
#include "mdoc.h"
#include "libmandoc.h"
#include "libmdoc.h"
#define STATE_ARGS struct roff_man *mdoc, struct roff_node *n
typedef void (*state_handler)(STATE_ARGS);
static void state_bd(STATE_ARGS);
static void state_bl(STATE_ARGS);
static void state_dl(STATE_ARGS);
static void state_sh(STATE_ARGS);
static void state_sm(STATE_ARGS);
static const state_handler state_handlers[MDOC_MAX] = {
NULL, /* Ap */
NULL, /* Dd */
NULL, /* Dt */
NULL, /* Os */
state_sh, /* Sh */
NULL, /* Ss */
NULL, /* Pp */
NULL, /* D1 */
state_dl, /* Dl */
state_bd, /* Bd */
NULL, /* Ed */
state_bl, /* Bl */
NULL, /* El */
NULL, /* It */
NULL, /* Ad */
NULL, /* An */
NULL, /* Ar */
NULL, /* Cd */
NULL, /* Cm */
NULL, /* Dv */
NULL, /* Er */
NULL, /* Ev */
NULL, /* Ex */
NULL, /* Fa */
NULL, /* Fd */
NULL, /* Fl */
NULL, /* Fn */
NULL, /* Ft */
NULL, /* Ic */
NULL, /* In */
NULL, /* Li */
NULL, /* Nd */
NULL, /* Nm */
NULL, /* Op */
NULL, /* Ot */
NULL, /* Pa */
NULL, /* Rv */
NULL, /* St */
NULL, /* Va */
NULL, /* Vt */
NULL, /* Xr */
NULL, /* %A */
NULL, /* %B */
NULL, /* %D */
NULL, /* %I */
NULL, /* %J */
NULL, /* %N */
NULL, /* %O */
NULL, /* %P */
NULL, /* %R */
NULL, /* %T */
NULL, /* %V */
NULL, /* Ac */
NULL, /* Ao */
NULL, /* Aq */
NULL, /* At */
NULL, /* Bc */
NULL, /* Bf */
NULL, /* Bo */
NULL, /* Bq */
NULL, /* Bsx */
NULL, /* Bx */
NULL, /* Db */
NULL, /* Dc */
NULL, /* Do */
NULL, /* Dq */
NULL, /* Ec */
NULL, /* Ef */
NULL, /* Em */
NULL, /* Eo */
NULL, /* Fx */
NULL, /* Ms */
NULL, /* No */
NULL, /* Ns */
NULL, /* Nx */
NULL, /* Ox */
NULL, /* Pc */
NULL, /* Pf */
NULL, /* Po */
NULL, /* Pq */
NULL, /* Qc */
NULL, /* Ql */
NULL, /* Qo */
NULL, /* Qq */
NULL, /* Re */
NULL, /* Rs */
NULL, /* Sc */
NULL, /* So */
NULL, /* Sq */
state_sm, /* Sm */
NULL, /* Sx */
NULL, /* Sy */
NULL, /* Tn */
NULL, /* Ux */
NULL, /* Xc */
NULL, /* Xo */
NULL, /* Fo */
NULL, /* Fc */
NULL, /* Oo */
NULL, /* Oc */
NULL, /* Bk */
NULL, /* Ek */
NULL, /* Bt */
NULL, /* Hf */
NULL, /* Fr */
NULL, /* Ud */
NULL, /* Lb */
NULL, /* Lp */
NULL, /* Lk */
NULL, /* Mt */
NULL, /* Brq */
NULL, /* Bro */
NULL, /* Brc */
NULL, /* %C */
NULL, /* Es */
NULL, /* En */
NULL, /* Dx */
NULL, /* %Q */
NULL, /* br */
NULL, /* sp */
NULL, /* %U */
NULL, /* Ta */
NULL, /* ll */
};
void
mdoc_state(struct roff_man *mdoc, struct roff_node *n)
{
state_handler handler;
if (n->tok == TOKEN_NONE)
return;
if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE))
mdoc->flags |= MDOC_PBODY;
handler = state_handlers[n->tok];
if (*handler)
(*handler)(mdoc, n);
}
void
mdoc_state_reset(struct roff_man *mdoc)
{
roff_setreg(mdoc->roff, "nS", 0, '=');
mdoc->flags = 0;
}
static void
state_bd(STATE_ARGS)
{
enum mdocargt arg;
if (n->type != ROFFT_HEAD &&
(n->type != ROFFT_BODY || n->end != ENDBODY_NOT))
return;
if (n->parent->args == NULL)
return;
arg = n->parent->args->argv[0].arg;
if (arg != MDOC_Literal && arg != MDOC_Unfilled)
return;
state_dl(mdoc, n);
}
static void
state_bl(STATE_ARGS)
{
if (n->type != ROFFT_HEAD || n->parent->args == NULL)
return;
switch(n->parent->args->argv[0].arg) {
case MDOC_Diag:
n->norm->Bl.type = LIST_diag;
break;
case MDOC_Column:
n->norm->Bl.type = LIST_column;
break;
default:
break;
}
}
static void
state_dl(STATE_ARGS)
{
switch (n->type) {
case ROFFT_HEAD:
mdoc->flags |= MDOC_LITERAL;
break;
case ROFFT_BODY:
mdoc->flags &= ~MDOC_LITERAL;
break;
default:
break;
}
}
static void
state_sh(STATE_ARGS)
{
struct roff_node *nch;
char *secname;
if (n->type != ROFFT_HEAD)
return;
if ( ! (n->flags & MDOC_VALID)) {
secname = NULL;
deroff(&secname, n);
/*
* Set the section attribute for the BLOCK, HEAD,
* and HEAD children; the latter can only be TEXT
* nodes, so no recursion is needed. For other
* nodes, including the .Sh BODY, this is done
* when allocating the node data structures, but
* for .Sh BLOCK and HEAD, the section is still
* unknown at that time.
*/
n->sec = n->parent->sec = secname == NULL ?
SEC_CUSTOM : mdoc_a2sec(secname);
for (nch = n->child; nch != NULL; nch = nch->next)
nch->sec = n->sec;
free(secname);
}
if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) {
roff_setreg(mdoc->roff, "nS", 1, '=');
mdoc->flags |= MDOC_SYNOPSIS;
} else {
roff_setreg(mdoc->roff, "nS", 0, '=');
mdoc->flags &= ~MDOC_SYNOPSIS;
}
}
static void
state_sm(STATE_ARGS)
{
if (n->child == NULL)
mdoc->flags ^= MDOC_SMOFF;
else if ( ! strcmp(n->child->string, "on"))
mdoc->flags &= ~MDOC_SMOFF;
else if ( ! strcmp(n->child->string, "off"))
mdoc->flags |= MDOC_SMOFF;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $Id: msec.c,v 1.14 2014/12/21 14:14:35 schwarze Exp $ */ /* $Id: msec.c,v 1.15 2015/10/06 18:32:19 schwarze Exp $ */
/* /*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -32,5 +32,5 @@ mandoc_a2msec(const char *p)
#include "msec.in" #include "msec.in"
return(NULL); return NULL;
} }

View File

@ -1,4 +1,4 @@
/* $Id: out.c,v 1.59 2015/01/30 04:11:50 schwarze Exp $ */ /* $Id: out.c,v 1.62 2015/10/12 00:08:16 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -51,7 +51,7 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
dst->unit = def == SCALE_MAX ? SCALE_BU : def; dst->unit = def == SCALE_MAX ? SCALE_BU : def;
dst->scale = strtod(src, &endptr); dst->scale = strtod(src, &endptr);
if (endptr == src) if (endptr == src)
return(0); return 0;
switch (*endptr++) { switch (*endptr++) {
case 'c': case 'c':
@ -89,12 +89,12 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
if (SCALE_MAX == def) if (SCALE_MAX == def)
return(0); return 0;
dst->unit = def; dst->unit = def;
break; break;
} }
return(*endptr == '\0' ? 2 : 1); return *endptr == '\0' ? 2 : 1;
} }
/* /*
@ -240,18 +240,14 @@ tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
switch (dp->layout->pos) { switch (dp->layout->pos) {
case TBL_CELL_HORIZ: case TBL_CELL_HORIZ:
/* FALLTHROUGH */
case TBL_CELL_DHORIZ: case TBL_CELL_DHORIZ:
sz = (*tbl->len)(1, tbl->arg); sz = (*tbl->len)(1, tbl->arg);
if (col->width < sz) if (col->width < sz)
col->width = sz; col->width = sz;
break; break;
case TBL_CELL_LONG: case TBL_CELL_LONG:
/* FALLTHROUGH */
case TBL_CELL_CENTRE: case TBL_CELL_CENTRE:
/* FALLTHROUGH */
case TBL_CELL_LEFT: case TBL_CELL_LEFT:
/* FALLTHROUGH */
case TBL_CELL_RIGHT: case TBL_CELL_RIGHT:
tblcalc_literal(tbl, col, dp); tblcalc_literal(tbl, col, dp);
break; break;
@ -262,7 +258,6 @@ tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
break; break;
default: default:
abort(); abort();
/* NOTREACHED */
} }
} }

View File

@ -1,4 +1,4 @@
/* $Id: out.h,v 1.26 2014/12/01 08:05:52 schwarze Exp $ */ /* $Id: out.h,v 1.27 2015/11/07 14:01:16 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -60,12 +60,9 @@ struct rofftbl {
(p)->scale = (v); } \ (p)->scale = (v); } \
while (/* CONSTCOND */ 0) while (/* CONSTCOND */ 0)
__BEGIN_DECLS
struct tbl_span; struct tbl_span;
int a2roffsu(const char *, struct roffsu *, enum roffscale); int a2roffsu(const char *, struct roffsu *, enum roffscale);
void tblcalc(struct rofftbl *tbl, void tblcalc(struct rofftbl *tbl,
const struct tbl_span *, size_t); const struct tbl_span *, size_t);
__END_DECLS

View File

@ -1,4 +1,4 @@
/* $Id: preconv.c,v 1.14 2015/03/06 09:24:59 kristaps Exp $ */ /* $Id: preconv.c,v 1.15 2015/10/06 18:32:19 schwarze Exp $ */
/* /*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@ -92,17 +92,17 @@ preconv_encode(struct buf *ib, size_t *ii, struct buf *ob, size_t *oi,
*oi += snprintf(ob->buf + *oi, 11, "\\[u%.4X]", accum); *oi += snprintf(ob->buf + *oi, 11, "\\[u%.4X]", accum);
*ii = (char *)cu - ib->buf; *ii = (char *)cu - ib->buf;
*filenc &= ~MPARSE_LATIN1; *filenc &= ~MPARSE_LATIN1;
return(1); return 1;
latin: latin:
if ( ! (*filenc & MPARSE_LATIN1)) if ( ! (*filenc & MPARSE_LATIN1))
return(0); return 0;
*oi += snprintf(ob->buf + *oi, 11, *oi += snprintf(ob->buf + *oi, 11,
"\\[u%.4X]", (unsigned char)ib->buf[(*ii)++]); "\\[u%.4X]", (unsigned char)ib->buf[(*ii)++]);
*filenc &= ~MPARSE_UTF8; *filenc &= ~MPARSE_UTF8;
return(1); return 1;
} }
int int
@ -123,7 +123,7 @@ preconv_cue(const struct buf *b, size_t offset)
if ((sz = (size_t)(eoln - ln)) < 10 || if ((sz = (size_t)(eoln - ln)) < 10 ||
memcmp(ln, ".\\\" -*-", 7) || memcmp(eoln - 3, "-*-", 3)) memcmp(ln, ".\\\" -*-", 7) || memcmp(eoln - 3, "-*-", 3))
return(MPARSE_UTF8 | MPARSE_LATIN1); return MPARSE_UTF8 | MPARSE_LATIN1;
/* Move after the header and adjust for the trailer. */ /* Move after the header and adjust for the trailer. */
@ -162,15 +162,15 @@ preconv_cue(const struct buf *b, size_t offset)
sz--; sz--;
} }
if (0 == sz) if (0 == sz)
return(0); return 0;
/* Check us against known encodings. */ /* Check us against known encodings. */
if (phsz > 4 && !strncasecmp(ln, "utf-8", 5)) if (phsz > 4 && !strncasecmp(ln, "utf-8", 5))
return(MPARSE_UTF8); return MPARSE_UTF8;
if (phsz > 10 && !strncasecmp(ln, "iso-latin-1", 11)) if (phsz > 10 && !strncasecmp(ln, "iso-latin-1", 11))
return(MPARSE_LATIN1); return MPARSE_LATIN1;
return(0); return 0;
} }
return(MPARSE_UTF8 | MPARSE_LATIN1); return MPARSE_UTF8 | MPARSE_LATIN1;
} }

View File

@ -1,16 +1,16 @@
/* $Id: read.c,v 1.131 2015/03/11 13:05:20 schwarze Exp $ */ /* $Id: read.c,v 1.148 2016/01/08 02:53:13 schwarze Exp $ */
/* /*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org> * Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies. * copyright notice and this permission notice appear in all copies.
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@ -23,12 +23,13 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#include <sys/wait.h>
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #if HAVE_ERR
#include <err.h> #include <err.h>
#endif
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
@ -38,21 +39,19 @@
#include <unistd.h> #include <unistd.h>
#include <zlib.h> #include <zlib.h>
#include "mandoc.h"
#include "mandoc_aux.h" #include "mandoc_aux.h"
#include "libmandoc.h" #include "mandoc.h"
#include "roff.h"
#include "mdoc.h" #include "mdoc.h"
#include "man.h" #include "man.h"
#include "libmandoc.h"
#include "roff_int.h"
#define REPARSE_LIMIT 1000 #define REPARSE_LIMIT 1000
struct mparse { struct mparse {
struct man *pman; /* persistent man parser */ struct roff_man *man; /* man parser */
struct mdoc *pmdoc; /* persistent mdoc parser */
struct man *man; /* man parser */
struct mdoc *mdoc; /* mdoc parser */
struct roff *roff; /* roff parser (!NULL) */ struct roff *roff; /* roff parser (!NULL) */
const struct mchars *mchars; /* character table */
char *sodest; /* filename pointed to by .so */ char *sodest; /* filename pointed to by .so */
const char *file; /* filename of current input file */ const char *file; /* filename of current input file */
struct buf *primary; /* buffer currently being parsed */ struct buf *primary; /* buffer currently being parsed */
@ -62,10 +61,10 @@ struct mparse {
enum mandoclevel file_status; /* status of current parse */ enum mandoclevel file_status; /* status of current parse */
enum mandoclevel wlevel; /* ignore messages below this */ enum mandoclevel wlevel; /* ignore messages below this */
int options; /* parser options */ int options; /* parser options */
int gzip; /* current input file is gzipped */
int filenc; /* encoding of the current file */ int filenc; /* encoding of the current file */
int reparse_count; /* finite interp. stack */ int reparse_count; /* finite interp. stack */
int line; /* line number in the file */ int line; /* line number in the file */
pid_t child; /* the gunzip(1) process */
}; };
static void choose_parser(struct mparse *); static void choose_parser(struct mparse *);
@ -132,7 +131,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"blocks badly nested", "blocks badly nested",
"nested displays are not portable", "nested displays are not portable",
"moving content out of list", "moving content out of list",
".Vt block has child macro",
"fill mode already enabled, skipping", "fill mode already enabled, skipping",
"fill mode already disabled, skipping", "fill mode already disabled, skipping",
"line scope broken", "line scope broken",
@ -219,6 +217,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
/* related to request and macro arguments */ /* related to request and macro arguments */
"escaped character not allowed in a name", "escaped character not allowed in a name",
"NOT IMPLEMENTED: Bd -file", "NOT IMPLEMENTED: Bd -file",
"skipping display without arguments",
"missing list type, using -item", "missing list type, using -item",
"missing manual name, using \"\"", "missing manual name, using \"\"",
"uname(3) system call failed, using UNKNOWN", "uname(3) system call failed, using UNKNOWN",
@ -292,24 +291,22 @@ choose_parser(struct mparse *curp)
} }
} }
if (format == MPARSE_MDOC) { if (curp->man == NULL) {
if (NULL == curp->pmdoc) curp->man = roff_man_alloc(curp->roff, curp, curp->defos,
curp->pmdoc = mdoc_alloc( curp->options & MPARSE_QUICK ? 1 : 0);
curp->roff, curp, curp->defos, curp->man->macroset = MACROSET_MAN;
MPARSE_QUICK & curp->options ? 1 : 0); curp->man->first->tok = TOKEN_NONE;
assert(curp->pmdoc);
curp->mdoc = curp->pmdoc;
return;
} }
/* Fall back to man(7) as a last resort. */ if (format == MPARSE_MDOC) {
mdoc_hash_init();
if (NULL == curp->pman) curp->man->macroset = MACROSET_MDOC;
curp->pman = man_alloc( curp->man->first->tok = TOKEN_NONE;
curp->roff, curp, curp->defos, } else {
MPARSE_QUICK & curp->options ? 1 : 0); man_hash_init();
assert(curp->pman); curp->man->macroset = MACROSET_MAN;
curp->man = curp->pman; curp->man->first->tok = TOKEN_NONE;
}
} }
/* /*
@ -331,7 +328,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
int of; int of;
int lnn; /* line number in the real file */ int lnn; /* line number in the real file */
int fd; int fd;
pid_t save_child;
unsigned char c; unsigned char c;
memset(&ln, 0, sizeof(ln)); memset(&ln, 0, sizeof(ln));
@ -543,10 +539,9 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
if (curp->secondary) if (curp->secondary)
curp->secondary->sz -= pos + 1; curp->secondary->sz -= pos + 1;
save_file = curp->file; save_file = curp->file;
save_child = curp->child; if ((fd = mparse_open(curp, ln.buf + of)) != -1) {
if (mparse_open(curp, &fd, ln.buf + of) ==
MANDOCLEVEL_OK) {
mparse_readfd(curp, fd, ln.buf + of); mparse_readfd(curp, fd, ln.buf + of);
close(fd);
curp->file = save_file; curp->file = save_file;
} else { } else {
curp->file = save_file; curp->file = save_file;
@ -561,7 +556,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
of = 0; of = 0;
mparse_buf_r(curp, ln, of, 0); mparse_buf_r(curp, ln, of, 0);
} }
curp->child = save_child;
pos = 0; pos = 0;
continue; continue;
default: default:
@ -575,7 +569,8 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
* parsers with each one. * parsers with each one.
*/ */
if ( ! (curp->man || curp->mdoc)) if (curp->man == NULL ||
curp->man->macroset == MACROSET_NONE)
choose_parser(curp); choose_parser(curp);
/* /*
@ -587,19 +582,13 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
* Do the same for ROFF_EQN. * Do the same for ROFF_EQN.
*/ */
if (rr == ROFF_TBL) { if (rr == ROFF_TBL)
while ((span = roff_span(curp->roff)) != NULL) while ((span = roff_span(curp->roff)) != NULL)
if (curp->man == NULL) roff_addtbl(curp->man, span);
mdoc_addspan(curp->mdoc, span); else if (rr == ROFF_EQN)
else roff_addeqn(curp->man, roff_eqn(curp->roff));
man_addspan(curp->man, span); else if ((curp->man->macroset == MACROSET_MDOC ?
} else if (rr == ROFF_EQN) { mdoc_parseln(curp->man, curp->line, ln.buf, of) :
if (curp->man == NULL)
mdoc_addeqn(curp->mdoc, roff_eqn(curp->roff));
else
man_addeqn(curp->man, roff_eqn(curp->roff));
} else if ((curp->man == NULL ?
mdoc_parseln(curp->mdoc, curp->line, ln.buf, of) :
man_parseln(curp->man, curp->line, ln.buf, of)) == 2) man_parseln(curp->man, curp->line, ln.buf, of)) == 2)
break; break;
@ -620,15 +609,15 @@ static int
read_whole_file(struct mparse *curp, const char *file, int fd, read_whole_file(struct mparse *curp, const char *file, int fd,
struct buf *fb, int *with_mmap) struct buf *fb, int *with_mmap)
{ {
gzFile gz;
size_t off; size_t off;
ssize_t ssz; ssize_t ssz;
#if HAVE_MMAP #if HAVE_MMAP
struct stat st; struct stat st;
if (-1 == fstat(fd, &st)) {
perror(file); if (fstat(fd, &st) == -1)
exit((int)MANDOCLEVEL_SYSERR); err((int)MANDOCLEVEL_SYSERR, "%s", file);
}
/* /*
* If we're a regular file, try just reading in the whole entry * If we're a regular file, try just reading in the whole entry
@ -637,19 +626,25 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
* concerned that this is going to tank any machines. * concerned that this is going to tank any machines.
*/ */
if (S_ISREG(st.st_mode)) { if (curp->gzip == 0 && S_ISREG(st.st_mode)) {
if (st.st_size > 0x7fffffff) { if (st.st_size > 0x7fffffff) {
mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL); mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL);
return(0); return 0;
} }
*with_mmap = 1; *with_mmap = 1;
fb->sz = (size_t)st.st_size; fb->sz = (size_t)st.st_size;
fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0); fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
if (fb->buf != MAP_FAILED) if (fb->buf != MAP_FAILED)
return(1); return 1;
} }
#endif #endif
if (curp->gzip) {
if ((gz = gzdopen(fd, "rb")) == NULL)
err((int)MANDOCLEVEL_SYSERR, "%s", file);
} else
gz = NULL;
/* /*
* If this isn't a regular file (like, say, stdin), then we must * If this isn't a regular file (like, say, stdin), then we must
* go the old way and just read things in bit by bit. * go the old way and just read things in bit by bit.
@ -668,43 +663,35 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
} }
resize_buf(fb, 65536); resize_buf(fb, 65536);
} }
ssz = read(fd, fb->buf + (int)off, fb->sz - off); ssz = curp->gzip ?
gzread(gz, fb->buf + (int)off, fb->sz - off) :
read(fd, fb->buf + (int)off, fb->sz - off);
if (ssz == 0) { if (ssz == 0) {
fb->sz = off; fb->sz = off;
return(1); return 1;
}
if (ssz == -1) {
perror(file);
exit((int)MANDOCLEVEL_SYSERR);
} }
if (ssz == -1)
err((int)MANDOCLEVEL_SYSERR, "%s", file);
off += (size_t)ssz; off += (size_t)ssz;
} }
free(fb->buf); free(fb->buf);
fb->buf = NULL; fb->buf = NULL;
return(0); return 0;
} }
static void static void
mparse_end(struct mparse *curp) mparse_end(struct mparse *curp)
{ {
if (curp->mdoc == NULL && if (curp->man == NULL && curp->sodest == NULL)
curp->man == NULL && curp->man = roff_man_alloc(curp->roff, curp, curp->defos,
curp->sodest == NULL) { curp->options & MPARSE_QUICK ? 1 : 0);
if (curp->options & MPARSE_MDOC) if (curp->man->macroset == MACROSET_NONE)
curp->mdoc = curp->pmdoc; curp->man->macroset = MACROSET_MAN;
else { if (curp->man->macroset == MACROSET_MDOC)
if (curp->pman == NULL) mdoc_endparse(curp->man);
curp->pman = man_alloc( else
curp->roff, curp, curp->defos,
curp->options & MPARSE_QUICK ? 1 : 0);
curp->man = curp->pman;
}
}
if (curp->mdoc)
mdoc_endparse(curp->mdoc);
if (curp->man)
man_endparse(curp->man); man_endparse(curp->man);
roff_endparse(curp->roff); roff_endparse(curp->roff);
} }
@ -759,7 +746,7 @@ mparse_readmem(struct mparse *curp, void *buf, size_t len,
blk.sz = len; blk.sz = len;
mparse_parse_buffer(curp, blk, file); mparse_parse_buffer(curp, blk, file);
return(curp->file_status); return curp->file_status;
} }
/* /*
@ -786,126 +773,48 @@ mparse_readfd(struct mparse *curp, int fd, const char *file)
#endif #endif
free(blk.buf); free(blk.buf);
} }
return curp->file_status;
if (fd != STDIN_FILENO && close(fd) == -1)
perror(file);
mparse_wait(curp);
return(curp->file_status);
} }
/* int
* hack to avoid depending on gnuzip(1) waiting for upstream proper mparse_open(struct mparse *curp, const char *file)
* support
*/
static int
gunzip(const char *file)
{ {
gzFile gz;
char buf[8192];
int r;
gz = gzopen(file, "r");
if (gz == NULL)
err(EXIT_FAILURE, "cannot open %s", file);
while ((r = gzread(gz, buf, sizeof(buf))) > 0)
fwrite(buf, 1, r, stdout);
gzclose(gz);
return (EXIT_SUCCESS);
}
enum mandoclevel
mparse_open(struct mparse *curp, int *fd, const char *file)
{
int pfd[2];
int save_errno;
char *cp; char *cp;
int fd;
curp->file = file; curp->file = file;
cp = strrchr(file, '.');
curp->gzip = (cp != NULL && ! strcmp(cp + 1, "gz"));
/* Unless zipped, try to just open the file. */ /* First try to use the filename as it is. */
if ((cp = strrchr(file, '.')) == NULL || if ((fd = open(file, O_RDONLY)) != -1)
strcmp(cp + 1, "gz")) { return fd;
curp->child = 0;
if ((*fd = open(file, O_RDONLY)) != -1)
return(MANDOCLEVEL_OK);
/* Open failed; try to append ".gz". */ /*
* If that doesn't work and the filename doesn't
* already end in .gz, try appending .gz.
*/
if ( ! curp->gzip) {
mandoc_asprintf(&cp, "%s.gz", file); mandoc_asprintf(&cp, "%s.gz", file);
file = cp; fd = open(file, O_RDONLY);
} else
cp = NULL;
/* Before forking, make sure the file can be read. */
save_errno = errno;
if (access(file, R_OK) == -1) {
if (cp != NULL)
errno = save_errno;
free(cp); free(cp);
*fd = -1; if (fd != -1) {
curp->child = 0; curp->gzip = 1;
mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno)); return fd;
return(MANDOCLEVEL_ERROR);
}
/* Run gunzip(1). */
if (pipe(pfd) == -1) {
perror("pipe");
exit((int)MANDOCLEVEL_SYSERR);
}
switch (curp->child = fork()) {
case -1:
perror("fork");
exit((int)MANDOCLEVEL_SYSERR);
case 0:
close(pfd[0]);
if (dup2(pfd[1], STDOUT_FILENO) == -1) {
perror("dup");
exit((int)MANDOCLEVEL_SYSERR);
} }
exit(gunzip(file));
default:
close(pfd[1]);
*fd = pfd[0];
return(MANDOCLEVEL_OK);
} }
}
enum mandoclevel /* Neither worked, give up. */
mparse_wait(struct mparse *curp)
{
int status;
if (curp->child == 0) mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno));
return(MANDOCLEVEL_OK); return -1;
if (waitpid(curp->child, &status, 0) == -1) {
perror("wait");
exit((int)MANDOCLEVEL_SYSERR);
}
curp->child = 0;
if (WIFSIGNALED(status)) {
mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
"gunzip died from signal %d", WTERMSIG(status));
return(MANDOCLEVEL_ERROR);
}
if (WEXITSTATUS(status)) {
mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
"gunzip failed with code %d", WEXITSTATUS(status));
return(MANDOCLEVEL_ERROR);
}
return(MANDOCLEVEL_OK);
} }
struct mparse * struct mparse *
mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg, mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
const struct mchars *mchars, const char *defos) const char *defos)
{ {
struct mparse *curp; struct mparse *curp;
@ -916,18 +825,18 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
curp->mmsg = mmsg; curp->mmsg = mmsg;
curp->defos = defos; curp->defos = defos;
curp->mchars = mchars; curp->roff = roff_alloc(curp, options);
curp->roff = roff_alloc(curp, curp->mchars, options); curp->man = roff_man_alloc( curp->roff, curp, curp->defos,
if (curp->options & MPARSE_MDOC) curp->options & MPARSE_QUICK ? 1 : 0);
curp->pmdoc = mdoc_alloc( if (curp->options & MPARSE_MDOC) {
curp->roff, curp, curp->defos, mdoc_hash_init();
curp->options & MPARSE_QUICK ? 1 : 0); curp->man->macroset = MACROSET_MDOC;
if (curp->options & MPARSE_MAN) } else if (curp->options & MPARSE_MAN) {
curp->pman = man_alloc( man_hash_init();
curp->roff, curp, curp->defos, curp->man->macroset = MACROSET_MAN;
curp->options & MPARSE_QUICK ? 1 : 0); }
curp->man->first->tok = TOKEN_NONE;
return(curp); return curp;
} }
void void
@ -936,16 +845,12 @@ mparse_reset(struct mparse *curp)
roff_reset(curp->roff); roff_reset(curp->roff);
if (curp->mdoc) if (curp->man != NULL)
mdoc_reset(curp->mdoc); roff_man_reset(curp->man);
if (curp->man)
man_reset(curp->man);
if (curp->secondary) if (curp->secondary)
curp->secondary->sz = 0; curp->secondary->sz = 0;
curp->file_status = MANDOCLEVEL_OK; curp->file_status = MANDOCLEVEL_OK;
curp->mdoc = NULL;
curp->man = NULL;
free(curp->sodest); free(curp->sodest);
curp->sodest = NULL; curp->sodest = NULL;
@ -955,10 +860,7 @@ void
mparse_free(struct mparse *curp) mparse_free(struct mparse *curp)
{ {
if (curp->pmdoc) roff_man_free(curp->man);
mdoc_free(curp->pmdoc);
if (curp->pman)
man_free(curp->pman);
if (curp->roff) if (curp->roff)
roff_free(curp->roff); roff_free(curp->roff);
if (curp->secondary) if (curp->secondary)
@ -970,17 +872,14 @@ mparse_free(struct mparse *curp)
} }
void void
mparse_result(struct mparse *curp, mparse_result(struct mparse *curp, struct roff_man **man,
struct mdoc **mdoc, struct man **man, char **sodest) char **sodest)
{ {
if (sodest && NULL != (*sodest = curp->sodest)) { if (sodest && NULL != (*sodest = curp->sodest)) {
*mdoc = NULL;
*man = NULL; *man = NULL;
return; return;
} }
if (mdoc)
*mdoc = curp->mdoc;
if (man) if (man)
*man = curp->man; *man = curp->man;
} }
@ -1023,13 +922,13 @@ const char *
mparse_strerror(enum mandocerr er) mparse_strerror(enum mandocerr er)
{ {
return(mandocerrs[er]); return mandocerrs[er];
} }
const char * const char *
mparse_strlevel(enum mandoclevel lvl) mparse_strlevel(enum mandoclevel lvl)
{ {
return(mandoclevels[lvl]); return mandoclevels[lvl];
} }
void void
@ -1045,5 +944,5 @@ mparse_getkeep(const struct mparse *p)
{ {
assert(p->secondary); assert(p->secondary);
return(p->secondary->sz ? p->secondary->buf : NULL); return p->secondary->sz ? p->secondary->buf : NULL;
} }

View File

@ -1,7 +1,7 @@
.\" $Id: roff.7,v 1.70 2015/02/17 17:16:52 schwarze Exp $ .\" $Id: roff.7,v 1.75 2015/09/24 18:41:22 schwarze Exp $
.\" .\"
.\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010, 2011, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> .\" Copyright (c) 2010, 2011, 2013-2015 Ingo Schwarze <schwarze@openbsd.org>
.\" .\"
.\" Permission to use, copy, modify, and distribute this software for any .\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above .\" 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 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: February 17 2015 $ .Dd $Mdocdate: September 24 2015 $
.Dt ROFF 7 .Dt ROFF 7
.Os .Os
.Sh NAME .Sh NAME
@ -665,6 +665,8 @@ produces
.D1 \efI\e^XtFree\e^\efP. .D1 \efI\e^XtFree\e^\efP.
.Pp .Pp
in the input stream, and thus in the output: \fI\^XtFree\^\fP. in the input stream, and thus in the output: \fI\^XtFree\^\fP.
Each occurrence of \e\e$* is replaced with all the arguments,
joined together with single blank characters.
.Pp .Pp
Since macros and user-defined strings share a common string table, Since macros and user-defined strings share a common string table,
defining a macro defining a macro
@ -1057,8 +1059,6 @@ If the first character of COND is
.Pq string defined , .Pq string defined ,
.Sq e .Sq e
.Pq even page , .Pq even page ,
.Sq r
.Pq register accessed ,
.Sq t .Sq t
.Pq troff mode , .Pq troff mode ,
or or
@ -1066,6 +1066,11 @@ or
.Pq vroff mode , .Pq vroff mode ,
COND evaluates to false. COND evaluates to false.
.It .It
If the first character of COND is
.Sq r ,
it evaluates to true if the rest of COND is the name of an existing
number register; otherwise, it evaluates to false.
.It
If COND starts with a parenthesis or with an optionally signed If COND starts with a parenthesis or with an optionally signed
integer number, it is evaluated according to the rules of integer number, it is evaluated according to the rules of
.Sx Numerical expressions .Sx Numerical expressions
@ -1337,7 +1342,7 @@ Currently unsupported.
Temporarily turn off line numbering. Temporarily turn off line numbering.
Currently unsupported. Currently unsupported.
.Ss \&nop .Ss \&nop
Exexute the rest of the input line as a request or macro line. Execute the rest of the input line as a request or macro line.
Currently unsupported. Currently unsupported.
.Ss \&nr .Ss \&nr
Define or change a register. Define or change a register.
@ -1579,7 +1584,7 @@ Set tab stops.
Takes an arbitrary number of arguments. Takes an arbitrary number of arguments.
Currently unsupported. Currently unsupported.
.Ss \&tc .Ss \&tc
Change tab repetion character. Change tab repetition character.
Currently unsupported. Currently unsupported.
.Ss \&TE .Ss \&TE
End a table context. End a table context.
@ -1679,7 +1684,7 @@ Notify on change of string or macro.
This is a Heirloom extension and currently ignored. This is a Heirloom extension and currently ignored.
.Ss \&watchlength .Ss \&watchlength
On change, report the contents of macros and strings On change, report the contents of macros and strings
up to the sepcified length. up to the specified length.
This is a Heirloom extension and currently ignored. This is a Heirloom extension and currently ignored.
.Ss \&watchn .Ss \&watchn
Notify on change of register. Notify on change of register.
@ -1774,7 +1779,7 @@ minimum (not available in C)
maximum (not available in C) maximum (not available in C)
.El .El
.Pp .Pp
There is no concept of precendence; evaluation proceeds from left to right, There is no concept of precedence; evaluation proceeds from left to right,
except when subexpressions are enclosed in parantheses. except when subexpressions are enclosed in parantheses.
Inside parentheses, whitespace is ignored. Inside parentheses, whitespace is ignored.
.Sh ESCAPE SEQUENCE REFERENCE .Sh ESCAPE SEQUENCE REFERENCE
@ -1834,9 +1839,15 @@ For short names, there are variants
.No \e* Ns Ar c .No \e* Ns Ar c
and and
.No \e*( Ns Ar cc . .No \e*( Ns Ar cc .
.Ss \e,
Left italic correction (groff extension); ignored by
.Xr mandoc 1 .
.Ss \e- .Ss \e-
Special character Special character
.Dq mathematical minus sign . .Dq mathematical minus sign .
.Ss \e/
Right italic correction (groff extension); ignored by
.Xr mandoc 1 .
.Ss \e[ Ns Ar name ] .Ss \e[ Ns Ar name ]
.Sx Special Characters .Sx Special Characters
with names of arbitrary length, see with names of arbitrary length, see
@ -2028,10 +2039,7 @@ Print
with zero width and height; ignored by with zero width and height; ignored by
.Xr mandoc 1 . .Xr mandoc 1 .
.Ss \ez .Ss \ez
Output the next character without advancing the cursor position; Output the next character without advancing the cursor position.
approximated in
.Xr mandoc 1
by simply skipping the next character.
.Sh COMPATIBILITY .Sh COMPATIBILITY
The The
.Xr mandoc 1 .Xr mandoc 1

File diff suppressed because it is too large Load Diff

164
contrib/mdocml/roff.h Normal file
View File

@ -0,0 +1,164 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct mdoc_arg;
union mdoc_data;
enum roff_macroset {
MACROSET_NONE = 0,
MACROSET_MDOC,
MACROSET_MAN
};
enum roff_sec {
SEC_NONE = 0,
SEC_NAME,
SEC_LIBRARY,
SEC_SYNOPSIS,
SEC_DESCRIPTION,
SEC_CONTEXT,
SEC_IMPLEMENTATION, /* IMPLEMENTATION NOTES */
SEC_RETURN_VALUES,
SEC_ENVIRONMENT,
SEC_FILES,
SEC_EXIT_STATUS,
SEC_EXAMPLES,
SEC_DIAGNOSTICS,
SEC_COMPATIBILITY,
SEC_ERRORS,
SEC_SEE_ALSO,
SEC_STANDARDS,
SEC_HISTORY,
SEC_AUTHORS,
SEC_CAVEATS,
SEC_BUGS,
SEC_SECURITY,
SEC_CUSTOM,
SEC__MAX
};
enum roff_type {
ROFFT_ROOT,
ROFFT_BLOCK,
ROFFT_HEAD,
ROFFT_BODY,
ROFFT_TAIL,
ROFFT_ELEM,
ROFFT_TEXT,
ROFFT_TBL,
ROFFT_EQN
};
enum roff_next {
ROFF_NEXT_SIBLING = 0,
ROFF_NEXT_CHILD
};
/*
* Indicates that a BODY's formatting has ended, but
* the scope is still open. Used for badly nested blocks.
*/
enum mdoc_endbody {
ENDBODY_NOT = 0,
ENDBODY_SPACE, /* Is broken: append a space. */
ENDBODY_NOSPACE /* Is broken: don't append a space. */
};
struct roff_node {
struct roff_node *parent; /* Parent AST node. */
struct roff_node *child; /* First child AST node. */
struct roff_node *last; /* Last child AST node. */
struct roff_node *next; /* Sibling AST node. */
struct roff_node *prev; /* Prior sibling AST node. */
struct roff_node *head; /* BLOCK */
struct roff_node *body; /* BLOCK/ENDBODY */
struct roff_node *tail; /* BLOCK */
struct mdoc_arg *args; /* BLOCK/ELEM */
union mdoc_data *norm; /* Normalized arguments. */
char *string; /* TEXT */
const struct tbl_span *span; /* TBL */
const struct eqn *eqn; /* EQN */
int line; /* Input file line number. */
int pos; /* Input file column number. */
int tok; /* Request or macro ID. */
#define TOKEN_NONE (-1) /* No request or macro. */
int flags;
#define MDOC_VALID (1 << 0) /* Has been validated. */
#define MDOC_ENDED (1 << 1) /* Gone past body end mark. */
#define MDOC_EOS (1 << 2) /* At sentence boundary. */
#define MDOC_LINE (1 << 3) /* First macro/text on line. */
#define MDOC_SYNPRETTY (1 << 4) /* SYNOPSIS-style formatting. */
#define MDOC_BROKEN (1 << 5) /* Must validate parent when ending. */
#define MDOC_DELIMO (1 << 6)
#define MDOC_DELIMC (1 << 7)
#define MAN_VALID MDOC_VALID
#define MAN_EOS MDOC_EOS
#define MAN_LINE MDOC_LINE
int prev_font; /* Before entering this node. */
int aux; /* Decoded node data, type-dependent. */
enum roff_type type; /* AST node type. */
enum roff_sec sec; /* Current named section. */
enum mdoc_endbody end; /* BODY */
};
struct roff_meta {
char *msec; /* Manual section, usually a digit. */
char *vol; /* Manual volume title. */
char *os; /* Operating system. */
char *arch; /* Machine architecture. */
char *title; /* Manual title, usually CAPS. */
char *name; /* Leading manual name. */
char *date; /* Normalized date. */
int hasbody; /* Document is not empty. */
};
struct roff_man {
struct roff_meta meta; /* Document meta-data. */
struct mparse *parse; /* Parse pointer. */
struct roff *roff; /* Roff parser state data. */
const char *defos; /* Default operating system. */
struct roff_node *first; /* The first node parsed. */
struct roff_node *last; /* The last node parsed. */
struct roff_node *last_es; /* The most recent Es node. */
int quick; /* Abort parse early. */
int flags; /* Parse flags. */
#define MDOC_LITERAL (1 << 1) /* In a literal scope. */
#define MDOC_PBODY (1 << 2) /* In the document body. */
#define MDOC_NEWLINE (1 << 3) /* First macro/text in a line. */
#define MDOC_PHRASE (1 << 4) /* In a Bl -column phrase. */
#define MDOC_PHRASELIT (1 << 5) /* Literal within a 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. */
#define MDOC_NODELIMC (1 << 10) /* Disable closing delimiter handling. */
#define MAN_ELINE (1 << 11) /* Next-line element scope. */
#define MAN_BLINE (1 << 12) /* Next-line block scope. */
#define MDOC_PHRASEQF (1 << 13) /* Quote first word encountered. */
#define MDOC_PHRASEQL (1 << 14) /* Quote last word of this phrase. */
#define MDOC_PHRASEQN (1 << 15) /* Quote first word of the next phrase. */
#define MAN_LITERAL MDOC_LITERAL
#define MAN_NEWLINE MDOC_NEWLINE
enum roff_macroset macroset; /* Kind of high-level macros used. */
enum roff_sec lastsec; /* Last section seen. */
enum roff_sec lastnamed; /* Last standard section seen. */
enum roff_next next; /* Where to put the next node. */
};
void deroff(char **, const struct roff_node *);

41
contrib/mdocml/roff_int.h Normal file
View File

@ -0,0 +1,41 @@
/* $Id: roff_int.h,v 1.7 2015/11/07 14:01:16 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct roff_node *roff_node_alloc(struct roff_man *, int, int,
enum roff_type, int);
void roff_node_append(struct roff_man *, struct roff_node *);
void roff_word_alloc(struct roff_man *, int, int, const char *);
void roff_word_append(struct roff_man *, const char *);
void roff_elem_alloc(struct roff_man *, int, int, int);
struct roff_node *roff_block_alloc(struct roff_man *, int, int, int);
struct roff_node *roff_head_alloc(struct roff_man *, int, int, int);
struct roff_node *roff_body_alloc(struct roff_man *, int, int, int);
void roff_addeqn(struct roff_man *, const struct eqn *);
void roff_addtbl(struct roff_man *, const struct tbl_span *);
void roff_node_unlink(struct roff_man *, struct roff_node *);
void roff_node_free(struct roff_node *);
void roff_node_delete(struct roff_man *, struct roff_node *);
/*
* Functions called from roff.c need to be declared here,
* not in libmdoc.h or libman.h, even if they are specific
* to either the mdoc(7) or the man(7) parser.
*/
void man_breakscope(struct roff_man *, int);
void mdoc_argv_free(struct mdoc_arg *);

86
contrib/mdocml/soelim.1 Normal file
View File

@ -0,0 +1,86 @@
.\" $Id: soelim.1,v 1.3 2015/05/20 22:59:12 schwarze Exp $
.\"
.\" Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd $Mdocdate: May 20 2015 $
.Dt SOELIM 1
.Os
.Sh NAME
.Nm soelim
.Nd interpret .so requests in manpages
.Sh SYNOPSIS
.Nm
.Op Fl Crtv
.Op Fl I Ar dir
.Op Ar files ...
.Sh DESCRIPTION
.Nm
reads
.Ar files
lines by lines.
.Pp
If a line starts by:
.Dq .so anotherfile
it replace the line by processing
.Dq anotherfile .
Otherwise the line is printed to stdout.
.Bl -tag -width "-I dir"
.It Fl C
Recognise
.Em .so
when not followed by a space character.
.It Fl r
Compatibility with GNU groff's
.Xr soelim 1
(does nothing).
.It Fl t
Compatibility with GNU groff's
.Xr soelim 1
(does nothing).
.It Fl v
Compatibility with GNU groff's
.Xr soelim 1
(does nothing).
.It Fl I Ar dir
This option specify directories where
.Nm
searches for files (both those on the command line and those named in
.Dq .so
directive.)
This options may be specified multiple times. The directories will be searched
in the order specified.
.El
.Pp
The files are always searched first in the current directory.
.Pp
A file specified with an absolute path will be opened directly without
performing a search.
.Sh SEE ALSO
.Xr mandoc 1
.Sh AUTHORS
This version of the
.Nm
utility was written by
.An Baptiste Daroussin Aq Mt bapt@freebsd.org .

182
contrib/mdocml/soelim.c Normal file
View File

@ -0,0 +1,182 @@
/* $Id: soelim.c,v 1.5 2015/11/07 14:22:29 schwarze Exp $ */
/*
* Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <sys/types.h>
#include <ctype.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_STRINGLIST
#include <stringlist.h>
#else
#include "compat_stringlist.h"
#endif
#include <unistd.h>
#define C_OPTION 0x1
static StringList *includes;
static void
usage(void)
{
fprintf(stderr, "usage: soelim [-Crtv] [-I dir] [files]\n");
exit(EXIT_FAILURE);
}
static FILE *
soelim_fopen(const char *name)
{
FILE *f;
char path[PATH_MAX];
size_t i;
if (strcmp(name, "-") == 0)
return (stdin);
if ((f = fopen(name, "r")) != NULL)
return (f);
if (*name == '/') {
warn("can't open '%s'", name);
return (NULL);
}
for (i = 0; i < includes->sl_cur; i++) {
snprintf(path, sizeof(path), "%s/%s", includes->sl_str[i],
name);
if ((f = fopen(path, "r")) != NULL)
return (f);
}
warn("can't open '%s'", name);
return (f);
}
static int
soelim_file(FILE *f, int flag)
{
char *line = NULL;
char *walk, *cp;
size_t linecap = 0;
ssize_t linelen;
if (f == NULL)
return (1);
while ((linelen = getline(&line, &linecap, f)) > 0) {
if (strncmp(line, ".so", 3) != 0) {
printf("%s", line);
continue;
}
walk = line + 3;
if (!isspace(*walk) && ((flag & C_OPTION) == 0)) {
printf("%s", line);
continue;
}
while (isspace(*walk))
walk++;
cp = walk;
while (*cp != '\0' && !isspace(*cp))
cp++;
*cp = 0;
if (cp < line + linelen)
cp++;
if (*walk == '\0') {
printf("%s", line);
continue;
}
if (soelim_file(soelim_fopen(walk), flag) == 1) {
free(line);
return (1);
}
if (*cp != '\0')
printf("%s", cp);
}
free(line);
fclose(f);
return (0);
}
int
main(int argc, char **argv)
{
int ch, i;
int ret = 0;
int flags = 0;
includes = sl_init();
if (includes == NULL)
err(EXIT_FAILURE, "sl_init()");
while ((ch = getopt(argc, argv, "CrtvI:")) != -1) {
switch (ch) {
case 'C':
flags |= C_OPTION;
break;
case 'r':
case 'v':
case 't':
/* stub compatibility with groff's soelim */
break;
case 'I':
sl_add(includes, optarg);
break;
default:
sl_free(includes, 0);
usage();
}
}
argc -= optind;
argv += optind;
if (argc == 0)
ret = soelim_file(stdin, flags);
for (i = 0; i < argc; i++)
ret = soelim_file(soelim_fopen(argv[i]), flags);
sl_free(includes, 0);
return (ret);
}

View File

@ -1,4 +1,4 @@
/* $Id: st.c,v 1.11 2014/08/10 23:54:41 schwarze Exp $ */ /* $Id: st.c,v 1.13 2015/10/06 18:32:20 schwarze Exp $ */
/* /*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -20,6 +20,7 @@
#include <string.h> #include <string.h>
#include "roff.h"
#include "mdoc.h" #include "mdoc.h"
#include "libmdoc.h" #include "libmdoc.h"
@ -32,5 +33,5 @@ mdoc_a2st(const char *p)
#include "st.in" #include "st.in"
return(NULL); return NULL;
} }

192
contrib/mdocml/tag.c Normal file
View File

@ -0,0 +1,192 @@
/* $Id: tag.c,v 1.11 2015/11/20 21:59:54 schwarze Exp $ */
/*
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
#include <sys/types.h>
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mandoc_aux.h"
#include "mandoc_ohash.h"
#include "tag.h"
struct tag_entry {
size_t line;
int prio;
char s[];
};
static void tag_signal(int);
static struct ohash tag_data;
static struct tag_files tag_files;
/*
* Prepare for using a pager.
* Not all pagers are capable of using a tag file,
* but for simplicity, create it anyway.
*/
struct tag_files *
tag_init(void)
{
struct sigaction sa;
int ofd;
ofd = -1;
tag_files.tfd = -1;
tag_files.tcpgid = -1;
/* Save the original standard output for use by the pager. */
if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1)
goto fail;
/* Create both temporary output files. */
(void)strlcpy(tag_files.ofn, "/tmp/man.XXXXXXXXXX",
sizeof(tag_files.ofn));
(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
sizeof(tag_files.tfn));
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sa.sa_handler = tag_signal;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
if ((ofd = mkstemp(tag_files.ofn)) == -1)
goto fail;
if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1)
goto fail;
if (dup2(ofd, STDOUT_FILENO) == -1)
goto fail;
close(ofd);
/*
* Set up the ohash table to collect output line numbers
* where various marked-up terms are documented.
*/
mandoc_ohash_init(&tag_data, 4, offsetof(struct tag_entry, s));
return &tag_files;
fail:
tag_unlink();
if (ofd != -1)
close(ofd);
if (tag_files.ofd != -1)
close(tag_files.ofd);
if (tag_files.tfd != -1)
close(tag_files.tfd);
*tag_files.ofn = '\0';
*tag_files.tfn = '\0';
tag_files.ofd = -1;
tag_files.tfd = -1;
return NULL;
}
/*
* Set the line number where a term is defined,
* unless it is already defined at a higher priority.
*/
void
tag_put(const char *s, int prio, size_t line)
{
struct tag_entry *entry;
size_t len;
unsigned int slot;
if (tag_files.tfd <= 0 || strchr(s, ' ') != NULL)
return;
slot = ohash_qlookup(&tag_data, s);
entry = ohash_find(&tag_data, slot);
if (entry == NULL) {
len = strlen(s) + 1;
entry = mandoc_malloc(sizeof(*entry) + len);
memcpy(entry->s, s, len);
ohash_insert(&tag_data, slot, entry);
} else if (entry->prio <= prio)
return;
entry->line = line;
entry->prio = prio;
}
/*
* Write out the tags file using the previously collected
* information and clear the ohash table while going along.
*/
void
tag_write(void)
{
FILE *stream;
struct tag_entry *entry;
unsigned int slot;
if (tag_files.tfd <= 0)
return;
stream = fdopen(tag_files.tfd, "w");
entry = ohash_first(&tag_data, &slot);
while (entry != NULL) {
if (stream != NULL)
fprintf(stream, "%s %s %zu\n",
entry->s, tag_files.ofn, entry->line);
free(entry);
entry = ohash_next(&tag_data, &slot);
}
ohash_delete(&tag_data);
if (stream != NULL)
fclose(stream);
}
void
tag_unlink(void)
{
pid_t tc_pgid;
if (tag_files.tcpgid != -1) {
tc_pgid = tcgetpgrp(STDIN_FILENO);
if (tc_pgid == tag_files.pager_pid ||
tc_pgid == getpgid(0) ||
getpgid(tc_pgid) == -1)
(void)tcsetpgrp(STDIN_FILENO, tag_files.tcpgid);
}
if (*tag_files.ofn != '\0')
unlink(tag_files.ofn);
if (*tag_files.tfn != '\0')
unlink(tag_files.tfn);
}
static void
tag_signal(int signum)
{
struct sigaction sa;
tag_unlink();
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_DFL;
sigaction(signum, &sa, NULL);
kill(getpid(), signum);
/* NOTREACHED */
_exit(1);
}

31
contrib/mdocml/tag.h Normal file
View File

@ -0,0 +1,31 @@
/* $Id: tag.h,v 1.7 2015/11/20 21:59:54 schwarze Exp $ */
/*
* Copyright (c) 2015 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.
*/
struct tag_files {
char ofn[20];
char tfn[20];
int ofd;
int tfd;
pid_t tcpgid;
pid_t pager_pid;
};
struct tag_files *tag_init(void);
void tag_put(const char *, int, size_t);
void tag_write(void);
void tag_unlink(void);

View File

@ -1,4 +1,4 @@
/* $Id: tbl.c,v 1.39 2015/01/30 17:32:16 schwarze Exp $ */ /* $Id: tbl.c,v 1.40 2015/10/06 18:32:20 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -66,7 +66,7 @@ tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
if (*cp == ';') { if (*cp == ';') {
tbl_option(tbl, ln, p, &pos); tbl_option(tbl, ln, p, &pos);
if (p[pos] == '\0') if (p[pos] == '\0')
return(ROFF_IGN); return ROFF_IGN;
} }
} }
@ -75,15 +75,15 @@ tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
switch (tbl->part) { switch (tbl->part) {
case TBL_PART_LAYOUT: case TBL_PART_LAYOUT:
tbl_layout(tbl, ln, p, pos); tbl_layout(tbl, ln, p, pos);
return(ROFF_IGN); return ROFF_IGN;
case TBL_PART_CDATA: case TBL_PART_CDATA:
return(tbl_cdata(tbl, ln, p, pos) ? ROFF_TBL : ROFF_IGN); return tbl_cdata(tbl, ln, p, pos) ? ROFF_TBL : ROFF_IGN;
default: default:
break; break;
} }
tbl_data(tbl, ln, p, pos); tbl_data(tbl, ln, p, pos);
return(ROFF_TBL); return ROFF_TBL;
} }
struct tbl_node * struct tbl_node *
@ -98,7 +98,7 @@ tbl_alloc(int pos, int line, struct mparse *parse)
tbl->part = TBL_PART_OPTS; tbl->part = TBL_PART_OPTS;
tbl->opts.tab = '\t'; tbl->opts.tab = '\t';
tbl->opts.decimal = '.'; tbl->opts.decimal = '.';
return(tbl); return tbl;
} }
void void
@ -155,7 +155,7 @@ tbl_span(struct tbl_node *tbl)
: tbl->first_span; : tbl->first_span;
if (span) if (span)
tbl->current_span = span; tbl->current_span = span;
return(span); return span;
} }
int int
@ -177,7 +177,7 @@ tbl_end(struct tbl_node **tblp)
if (sp == NULL) { if (sp == NULL) {
mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->parse, mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->parse,
tbl->line, tbl->pos, NULL); tbl->line, tbl->pos, NULL);
return(0); return 0;
} }
return(1); return 1;
} }

View File

@ -1,4 +1,4 @@
/* $Id: tbl_data.c,v 1.39 2015/01/30 17:32:16 schwarze Exp $ */ /* $Id: tbl_data.c,v 1.41 2015/10/06 18:32:20 schwarze Exp $ */
/* /*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -132,11 +132,12 @@ tbl_cdata(struct tbl_node *tbl, int ln, const char *p, int pos)
if (p[pos] == tbl->opts.tab) { if (p[pos] == tbl->opts.tab) {
tbl->part = TBL_PART_DATA; tbl->part = TBL_PART_DATA;
pos++; pos++;
getdata(tbl, tbl->last_span, ln, p, &pos); while (p[pos] != '\0')
return(1); getdata(tbl, tbl->last_span, ln, p, &pos);
return 1;
} else if (p[pos] == '\0') { } else if (p[pos] == '\0') {
tbl->part = TBL_PART_DATA; tbl->part = TBL_PART_DATA;
return(1); return 1;
} }
/* Fallthrough: T} is part of a word. */ /* Fallthrough: T} is part of a word. */
@ -156,7 +157,7 @@ tbl_cdata(struct tbl_node *tbl, int ln, const char *p, int pos)
mandoc_msg(MANDOCERR_TBLDATA_SPAN, tbl->parse, mandoc_msg(MANDOCERR_TBLDATA_SPAN, tbl->parse,
ln, pos, dat->string); ln, pos, dat->string);
return(0); return 0;
} }
static struct tbl_span * static struct tbl_span *
@ -177,7 +178,7 @@ newspan(struct tbl_node *tbl, int line, struct tbl_row *rp)
dp->prev->next = dp; dp->prev->next = dp;
tbl->last_span = dp; tbl->last_span = dp;
return(dp); return dp;
} }
void void

Some files were not shown because too many files have changed in this diff Show More