Import CVS version of mandoc as of 20141201
This commit is contained in:
parent
52c0e9552d
commit
81bffeeaab
93
INSTALL
93
INSTALL
@ -1,4 +1,4 @@
|
||||
$Id: INSTALL,v 1.2 2014/08/10 17:22:26 schwarze Exp $
|
||||
$Id: INSTALL,v 1.5 2014/08/18 13:27:47 kristaps Exp $
|
||||
|
||||
About mdocml, the portable mandoc distribution
|
||||
----------------------------------------------
|
||||
@ -34,19 +34,52 @@ latest bundled and ported versions of mandoc for various operating
|
||||
systems is maintained at <http://mdocml.bsd.lv/ports.html>.
|
||||
|
||||
If mandoc is installed, you can check the version by running "mandoc -V".
|
||||
The version contained in this distribution tarball is listed near
|
||||
the beginning of the file "Makefile".
|
||||
You can find the version contained in this distribution tarball
|
||||
by running "./configure".
|
||||
|
||||
Regarding how packages and ports are maintained for your operating
|
||||
system, please consult your operating system documentation.
|
||||
To install mandoc manually, the following steps are needed:
|
||||
|
||||
1. Decide whether you want to build the base tools mandoc(1),
|
||||
preconv(1) and demandoc(1) only or whether you also want to build the
|
||||
database tools apropos(1) and makewhatis(8). For the latter,
|
||||
the following dependencies are required:
|
||||
1. If you want to build the CGI program, man.cgi(8), too, run the
|
||||
command "echo BUILD_CGI=1 > configure.local". Then run "cp
|
||||
cgi.h.examples cgi.h" and edit cgi.h as desired.
|
||||
|
||||
1.1. The SQLite database system, see <http://sqlite.org/>.
|
||||
2. Run "./configure".
|
||||
This script attempts autoconfiguration of mandoc for your system.
|
||||
Read both its standard output and the file "Makefile.local" it
|
||||
generates. If anything looks wrong or different from what you
|
||||
wish, read the file "configure.local.example", create and edit
|
||||
a file "configure.local", and re-run "./configure" until the
|
||||
result seems right to you.
|
||||
|
||||
3. Run "make".
|
||||
Any POSIX-compatible make, in particular both BSD make and GNU make,
|
||||
should work. If the build fails, look at "configure.local.example"
|
||||
and go back to step 2.
|
||||
|
||||
4. Run "make -n install" and check whether everything will be
|
||||
installed to the intended places. Otherwise, put some *DIR variables
|
||||
into "configure.local" and go back to step 2.
|
||||
|
||||
5. Run "sudo make install". If you intend to build a binary
|
||||
package using some kind of fake root mechanism, you may need a
|
||||
command like "make DESTDIR=... install". Read the *-install targets
|
||||
in the "Makefile" to understand how DESTDIR is used.
|
||||
|
||||
6. To set up a man.cgi(8) server, read its manual page.
|
||||
|
||||
7. To use mandoc(1) as your man(1) formatter, read the "Deployment"
|
||||
section below.
|
||||
|
||||
|
||||
Understanding mandoc dependencies
|
||||
---------------------------------
|
||||
The mandoc(1), preconv(1), and demandoc(1) utilities have no external
|
||||
dependencies. However, makewhatis(8) and apropos(1) depend on the
|
||||
following software:
|
||||
|
||||
1. The SQLite database system, see <http://sqlite.org/>.
|
||||
The recommended version of SQLite is 3.8.4.3 or newer. The mandoc
|
||||
toolset is known to work with version 3.7.5 or newer. Versions
|
||||
older than 3.8.3 may not achieve full performance due to the
|
||||
@ -57,47 +90,16 @@ problems, apropos(1) is fully usable with SQLite 3.7.5. Versions
|
||||
older than 3.7.5 may or may not work, they have not been tested.
|
||||
|
||||
1.2. The fts(3) directory traversion functions.
|
||||
A compatibility version will be bundled for 1.13.2 but is not available
|
||||
yet. If you want apropos(1) and makewhatis(8) but do not have fts(3),
|
||||
please stay with mandoc 1.12.3 for now and upgrade first to 1.12.4,
|
||||
then to 1.13.2 when these versionns are released. Be careful: the
|
||||
If your system does not have them, the bundled compatibility version
|
||||
will be used, so you need not worry in that case. But be careful: the
|
||||
glibc version of fts(3) is known to be broken on 32bit platforms,
|
||||
see <https://sourceware.org/bugzilla/show_bug.cgi?id=15838>.
|
||||
If you run into that problem, set "HAVE_FTS=0" in configure.local.
|
||||
|
||||
1.3. Marc Espie's ohash(3) library.
|
||||
If your system does not have it, the bundled compatibility version
|
||||
will be used, so you probably need not worry about it.
|
||||
|
||||
2. If you choose to build the database tools, too, decide whether
|
||||
you also want to build the CGI program, man.cgi(8).
|
||||
|
||||
3. Read the beginning of the file "Makefile" from "USER SETTINGS"
|
||||
to "END OF USER SETTINGS" and edit it as required. In particular,
|
||||
disable "BUILD_TARGETS += db-build" if you do not want database
|
||||
support or enable "BUILD_TARGETS += cgi-build" if you do want
|
||||
the CGI program.
|
||||
|
||||
4. Run "make". No separate "./configure" or "make depend" steps
|
||||
are needed. The former is run automatically by "make". The latter
|
||||
is a maintainer target. If you merely want to build the released
|
||||
version as opposed to doing active development, there is no need
|
||||
to regenerate the dependency specifications. Any POSIX-compatible
|
||||
make, in particular both BSD make and GNU make, should work.
|
||||
|
||||
5. Run "make -n install" and check whether everything will be
|
||||
installed to the intended places. Otherwise, edit the *DIR variables
|
||||
in the Makefile until it is.
|
||||
|
||||
6. Run "sudo make install". If you intend to build a binary
|
||||
package using some kind of fake root mechanism, you may need a
|
||||
command like "make DESTDIR=... install". Read the *-install targets
|
||||
in the "Makefile" to understand how DESTDIR is used.
|
||||
|
||||
7. To set up a man.cgi(8) server, read its manual page.
|
||||
|
||||
8. To use mandoc(1) as your man(1) formatter, read the "Deployment"
|
||||
section below.
|
||||
|
||||
|
||||
Checking autoconfiguration quality
|
||||
----------------------------------
|
||||
@ -130,9 +132,9 @@ please report whatever is missing on your platform.
|
||||
The following steps can be used to manually check the automatic
|
||||
configuration on your platform:
|
||||
|
||||
1. Run "make clean".
|
||||
1. Run "make distclean".
|
||||
|
||||
2. Run "make config.h"
|
||||
2. Run "./configure"
|
||||
|
||||
3. Read the file "config.log". It shows the compiler commands used
|
||||
to test the libraries installed on your system and the standard
|
||||
@ -140,8 +142,7 @@ output and standard error output these commands produce. Watch out
|
||||
for unexpected failures. Those are most likely to happen if headers
|
||||
or libraries are installed in unusual places or interfaces defined
|
||||
in unusual headers. You can also look at the file "config.h" and
|
||||
check that no expected "#define HAVE_*" lines are missing. The
|
||||
list of tests run can be found in the file "configure".
|
||||
check that no "#define HAVE_*" differ from your expectations.
|
||||
|
||||
|
||||
Deployment
|
||||
|
8
LICENSE
8
LICENSE
@ -1,4 +1,4 @@
|
||||
$Id: LICENSE,v 1.2 2014/04/23 21:06:41 schwarze Exp $
|
||||
$Id: LICENSE,v 1.4 2014/08/21 00:42:38 schwarze Exp $
|
||||
|
||||
With the exceptions noted below, all code and documentation
|
||||
contained in the mdocml toolkit is protected by the Copyright
|
||||
@ -37,8 +37,10 @@ The following files included from outside sources are protected by
|
||||
other people's Copyright and are distributed under a 3-clause BSD
|
||||
license; see these individual files for details.
|
||||
|
||||
compat_getsubopt.c, compat_strcasestr.c, compat_strsep.c:
|
||||
Copyright (c) 1990, 1993 The Regents of the University of California
|
||||
compat_fts.c, compat_fts.h,
|
||||
compat_getsubopt.c, compat_strcasestr.c, compat_strsep.c,
|
||||
man.1:
|
||||
Copyright (c) 1989,1990,1993,1994 The Regents of the University of California
|
||||
|
||||
compat_fgetln.c:
|
||||
Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
194
Makefile
194
Makefile
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.435 2014/08/10 02:45:04 schwarze Exp $
|
||||
# $Id: Makefile,v 1.448 2014/11/28 18:57:31 schwarze Exp $
|
||||
#
|
||||
# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
# Copyright (c) 2011, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,126 +15,31 @@
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
VERSION = 1.13.1
|
||||
|
||||
# === USER SETTINGS ====================================================
|
||||
|
||||
# --- user settings relevant for all builds ----------------------------
|
||||
|
||||
# Specify this if you want to hard-code the operating system to appear
|
||||
# in the lower-left hand corner of -mdoc manuals.
|
||||
#
|
||||
# CFLAGS += -DOSNAME="\"OpenBSD 5.5\""
|
||||
|
||||
# IFF your system supports multi-byte functions (setlocale(), wcwidth(),
|
||||
# putwchar()) AND has __STDC_ISO_10646__ (that is, wchar_t is simply a
|
||||
# UCS-4 value) should you define USE_WCHAR. If you define it and your
|
||||
# system DOESN'T support this, -Tlocale will produce garbage.
|
||||
# If you don't define it, -Tlocale is a synonym for -Tacsii.
|
||||
#
|
||||
CFLAGS += -DUSE_WCHAR
|
||||
|
||||
CFLAGS += -g -DHAVE_CONFIG_H
|
||||
CFLAGS += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings
|
||||
PREFIX = /usr/local
|
||||
BINDIR = $(PREFIX)/bin
|
||||
INCLUDEDIR = $(PREFIX)/include/mandoc
|
||||
LIBDIR = $(PREFIX)/lib/mandoc
|
||||
MANDIR = $(PREFIX)/man
|
||||
EXAMPLEDIR = $(PREFIX)/share/examples/mandoc
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = $(INSTALL) -m 0555
|
||||
INSTALL_DATA = $(INSTALL) -m 0444
|
||||
INSTALL_LIB = $(INSTALL) -m 0444
|
||||
INSTALL_SOURCE = $(INSTALL) -m 0644
|
||||
INSTALL_MAN = $(INSTALL_DATA)
|
||||
|
||||
# --- user settings related to database support ------------------------
|
||||
|
||||
# Building apropos(1) and makewhatis(8) requires both SQLite3 and fts(3).
|
||||
# To avoid those dependencies, comment the following line.
|
||||
# Be careful: the fts(3) implementation in glibc is broken on 32bit
|
||||
# machines, see: https://sourceware.org/bugzilla/show_bug.cgi?id=15838
|
||||
#
|
||||
BUILD_TARGETS += db-build
|
||||
|
||||
# The remaining settings in this section
|
||||
# are only relevant if db-build is enabled.
|
||||
# Otherwise, they have no effect either way.
|
||||
|
||||
# If your system has manpath(1), uncomment this. This is most any
|
||||
# system that's not OpenBSD or NetBSD. If uncommented, apropos(1)
|
||||
# and makewhatis(8) will use manpath(1) to get the MANPATH variable.
|
||||
#
|
||||
#CFLAGS += -DUSE_MANPATH
|
||||
|
||||
# On some systems, SQLite3 may be installed below /usr/local.
|
||||
# In that case, uncomment the following two lines.
|
||||
#
|
||||
#CFLAGS += -I/usr/local/include
|
||||
#DBLIB += -L/usr/local/lib
|
||||
|
||||
# OpenBSD has the ohash functions in libutil.
|
||||
# Comment the following line if your system doesn't.
|
||||
#
|
||||
DBLIB += -lutil
|
||||
|
||||
SBINDIR = $(PREFIX)/sbin
|
||||
|
||||
# --- user settings related to man.cgi ---------------------------------
|
||||
|
||||
# To build man.cgi, copy cgi.h.example to cgi.h, edit it,
|
||||
# and enable the following line.
|
||||
# Obviously, this requires that db-build is enabled, too.
|
||||
#
|
||||
#BUILD_TARGETS += cgi-build
|
||||
|
||||
# The remaining settings in this section
|
||||
# are only relevant if cgi-build is enabled.
|
||||
# Otherwise, they have no effect either way.
|
||||
|
||||
# If your system does not support static binaries, comment this,
|
||||
# for example on Mac OS X.
|
||||
#
|
||||
STATIC = -static
|
||||
|
||||
# Linux requires -pthread for statical linking.
|
||||
#
|
||||
#STATIC += -pthread
|
||||
|
||||
WWWPREFIX = /var/www
|
||||
HTDOCDIR = $(WWWPREFIX)/htdocs
|
||||
CGIBINDIR = $(WWWPREFIX)/cgi-bin
|
||||
|
||||
# === END OF USER SETTINGS =============================================
|
||||
|
||||
INSTALL_TARGETS = $(BUILD_TARGETS:-build=-install)
|
||||
|
||||
BASEBIN = mandoc preconv demandoc
|
||||
DBBIN = apropos makewhatis
|
||||
BASEBIN = mandoc demandoc
|
||||
DBBIN = makewhatis
|
||||
CGIBIN = man.cgi
|
||||
|
||||
DBLIB += -lsqlite3
|
||||
|
||||
TESTSRCS = test-fgetln.c \
|
||||
TESTSRCS = test-dirent-namlen.c \
|
||||
test-fgetln.c \
|
||||
test-fts.c \
|
||||
test-getsubopt.c \
|
||||
test-mmap.c \
|
||||
test-ohash.c \
|
||||
test-reallocarray.c \
|
||||
test-sqlite3.c \
|
||||
test-sqlite3_errstr.c \
|
||||
test-strcasestr.c \
|
||||
test-strlcat.c \
|
||||
test-strlcpy.c \
|
||||
test-strptime.c \
|
||||
test-strsep.c
|
||||
test-strsep.c \
|
||||
test-wchar.c
|
||||
|
||||
SRCS = apropos.c \
|
||||
arch.c \
|
||||
att.c \
|
||||
SRCS = att.c \
|
||||
cgi.c \
|
||||
chars.c \
|
||||
compat_fgetln.c \
|
||||
compat_fts.c \
|
||||
compat_getsubopt.c \
|
||||
compat_ohash.c \
|
||||
compat_reallocarray.c \
|
||||
@ -187,7 +92,6 @@ SRCS = apropos.c \
|
||||
term_ascii.c \
|
||||
term_ps.c \
|
||||
tree.c \
|
||||
vol.c \
|
||||
$(TESTSRCS)
|
||||
|
||||
DISTFILES = INSTALL \
|
||||
@ -197,14 +101,12 @@ DISTFILES = INSTALL \
|
||||
NEWS \
|
||||
TODO \
|
||||
apropos.1 \
|
||||
arch.in \
|
||||
att.in \
|
||||
cgi.h.example \
|
||||
chars.in \
|
||||
compat_fts.h \
|
||||
compat_ohash.h \
|
||||
config.h.post \
|
||||
config.h.pre \
|
||||
configure \
|
||||
configure.local.example \
|
||||
demandoc.1 \
|
||||
eqn.7 \
|
||||
example.style.css \
|
||||
@ -218,6 +120,7 @@ DISTFILES = INSTALL \
|
||||
main.h \
|
||||
makewhatis.8 \
|
||||
man-cgi.css \
|
||||
man.1 \
|
||||
man.7 \
|
||||
man.cgi.8 \
|
||||
man.h \
|
||||
@ -238,7 +141,6 @@ DISTFILES = INSTALL \
|
||||
mdoc.h \
|
||||
msec.in \
|
||||
out.h \
|
||||
preconv.1 \
|
||||
predefs.in \
|
||||
roff.7 \
|
||||
st.in \
|
||||
@ -246,7 +148,6 @@ DISTFILES = INSTALL \
|
||||
tbl.3 \
|
||||
tbl.7 \
|
||||
term.h \
|
||||
vol.in \
|
||||
$(SRCS)
|
||||
|
||||
LIBMAN_OBJS = man.o \
|
||||
@ -254,16 +155,14 @@ LIBMAN_OBJS = man.o \
|
||||
man_macro.o \
|
||||
man_validate.o
|
||||
|
||||
LIBMDOC_OBJS = arch.o \
|
||||
att.o \
|
||||
LIBMDOC_OBJS = att.o \
|
||||
lib.o \
|
||||
mdoc.o \
|
||||
mdoc_argv.o \
|
||||
mdoc_hash.o \
|
||||
mdoc_macro.o \
|
||||
mdoc_validate.o \
|
||||
st.o \
|
||||
vol.o
|
||||
st.o
|
||||
|
||||
LIBROFF_OBJS = eqn.o \
|
||||
roff.o \
|
||||
@ -279,9 +178,11 @@ LIBMANDOC_OBJS = $(LIBMAN_OBJS) \
|
||||
mandoc.o \
|
||||
mandoc_aux.o \
|
||||
msec.o \
|
||||
preconv.o \
|
||||
read.o
|
||||
|
||||
COMPAT_OBJS = compat_fgetln.o \
|
||||
compat_fts.o \
|
||||
compat_getsubopt.o \
|
||||
compat_ohash.o \
|
||||
compat_reallocarray.o \
|
||||
@ -314,11 +215,11 @@ MANDOC_OBJS = $(MANDOC_HTML_OBJS) \
|
||||
out.o \
|
||||
tree.o
|
||||
|
||||
MAN_OBJS = $(MANDOC_OBJS)
|
||||
|
||||
MAKEWHATIS_OBJS = mandocdb.o mansearch_const.o manpath.o
|
||||
|
||||
PRECONV_OBJS = preconv.o
|
||||
|
||||
APROPOS_OBJS = apropos.o mansearch.o mansearch_const.o manpath.o
|
||||
APROPOS_OBJS = mansearch.o mansearch_const.o manpath.o
|
||||
|
||||
CGI_OBJS = $(MANDOC_HTML_OBJS) \
|
||||
cgi.o \
|
||||
@ -332,8 +233,8 @@ DEMANDOC_OBJS = demandoc.o
|
||||
|
||||
WWW_MANS = apropos.1.html \
|
||||
demandoc.1.html \
|
||||
man.1.html \
|
||||
mandoc.1.html \
|
||||
preconv.1.html \
|
||||
mandoc.3.html \
|
||||
mandoc_escape.3.html \
|
||||
mandoc_html.3.html \
|
||||
@ -360,9 +261,13 @@ WWW_MANS = apropos.1.html \
|
||||
WWW_OBJS = mdocml.tar.gz \
|
||||
mdocml.sha256
|
||||
|
||||
include Makefile.local
|
||||
|
||||
INSTALL_TARGETS = $(BUILD_TARGETS:-build=-install)
|
||||
|
||||
# === DEPENDENCY HANDLING ==============================================
|
||||
|
||||
all: base-build $(BUILD_TARGETS)
|
||||
all: base-build $(BUILD_TARGETS) Makefile.local
|
||||
|
||||
base-build: $(BASEBIN)
|
||||
|
||||
@ -374,20 +279,22 @@ install: base-install $(INSTALL_TARGETS)
|
||||
|
||||
www: $(WWW_OBJS) $(WWW_MANS)
|
||||
|
||||
$(WWW_MANS): mandoc
|
||||
|
||||
include Makefile.depend
|
||||
|
||||
# === TARGETS CONTAINING SHELL COMMANDS ================================
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile.local config.h config.h.old config.log config.log.old
|
||||
|
||||
clean:
|
||||
rm -f libmandoc.a $(LIBMANDOC_OBJS)
|
||||
rm -f apropos $(APROPOS_OBJS)
|
||||
rm -f libmandoc.a $(LIBMANDOC_OBJS) $(COMPAT_OBJS)
|
||||
rm -f mandoc $(MANDOC_OBJS) $(APROPOS_OBJS)
|
||||
rm -f makewhatis $(MAKEWHATIS_OBJS)
|
||||
rm -f preconv $(PRECONV_OBJS)
|
||||
rm -f man.cgi $(CGI_OBJS)
|
||||
rm -f manpage $(MANPAGE_OBJS)
|
||||
rm -f demandoc $(DEMANDOC_OBJS)
|
||||
rm -f mandoc $(MANDOC_OBJS)
|
||||
rm -f config.h config.log $(COMPAT_OBJS)
|
||||
rm -f $(WWW_MANS) $(WWW_OBJS)
|
||||
rm -rf *.dSYM
|
||||
|
||||
@ -403,7 +310,8 @@ base-install: base-build
|
||||
$(INSTALL_LIB) libmandoc.a $(DESTDIR)$(LIBDIR)
|
||||
$(INSTALL_LIB) man.h mandoc.h mandoc_aux.h mdoc.h \
|
||||
$(DESTDIR)$(INCLUDEDIR)
|
||||
$(INSTALL_MAN) mandoc.1 preconv.1 demandoc.1 $(DESTDIR)$(MANDIR)/man1
|
||||
$(INSTALL_MAN) man.1 mandoc.1 demandoc.1 \
|
||||
$(DESTDIR)$(MANDIR)/man1
|
||||
$(INSTALL_MAN) mandoc.3 mandoc_escape.3 mandoc_malloc.3 \
|
||||
mchars_alloc.3 tbl.3 $(DESTDIR)$(MANDIR)/man3
|
||||
$(INSTALL_MAN) man.7 mdoc.7 roff.7 eqn.7 tbl.7 mandoc_char.7 \
|
||||
@ -417,8 +325,8 @@ db-install: db-build
|
||||
mkdir -p $(DESTDIR)$(MANDIR)/man3
|
||||
mkdir -p $(DESTDIR)$(MANDIR)/man5
|
||||
mkdir -p $(DESTDIR)$(MANDIR)/man8
|
||||
$(INSTALL_PROGRAM) apropos $(DESTDIR)$(BINDIR)
|
||||
ln -f $(DESTDIR)$(BINDIR)/apropos $(DESTDIR)$(BINDIR)/whatis
|
||||
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/apropos
|
||||
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/whatis
|
||||
$(INSTALL_PROGRAM) makewhatis $(DESTDIR)$(SBINDIR)
|
||||
$(INSTALL_MAN) apropos.1 $(DESTDIR)$(MANDIR)/man1
|
||||
ln -f $(DESTDIR)$(MANDIR)/man1/apropos.1 \
|
||||
@ -447,30 +355,29 @@ www-install: www
|
||||
$(INSTALL_DATA) mdocml.sha256 \
|
||||
$(DESTDIR)$(HTDOCDIR)/snapshots/mdocml-$(VERSION).sha256
|
||||
|
||||
Makefile.local config.h: configure ${TESTSRCS}
|
||||
@echo "$@ is out of date; please run ./configure"
|
||||
@exit 1
|
||||
|
||||
depend: config.h
|
||||
mkdep -f Makefile.depend $(CFLAGS) $(SRCS)
|
||||
perl -e 'undef $$/; $$_ = <>; s|/usr/include/\S+||g; \
|
||||
s|\\\n||g; s| +| |g; print;' Makefile.depend > Makefile.tmp
|
||||
s|\\\n||g; s| +| |g; s| $$||mg; print;' \
|
||||
Makefile.depend > Makefile.tmp
|
||||
mv Makefile.tmp Makefile.depend
|
||||
|
||||
libmandoc.a: $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
|
||||
$(AR) rs $@ $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
|
||||
|
||||
mandoc: $(MANDOC_OBJS) libmandoc.a
|
||||
$(CC) $(LDFLAGS) -o $@ $(MANDOC_OBJS) libmandoc.a
|
||||
mandoc: $(MAN_OBJS) libmandoc.a
|
||||
$(CC) $(LDFLAGS) -o $@ $(MAN_OBJS) libmandoc.a $(DBLIB)
|
||||
|
||||
makewhatis: $(MAKEWHATIS_OBJS) libmandoc.a
|
||||
$(CC) $(LDFLAGS) -o $@ $(MAKEWHATIS_OBJS) libmandoc.a $(DBLIB)
|
||||
|
||||
preconv: $(PRECONV_OBJS)
|
||||
$(CC) $(LDFLAGS) -o $@ $(PRECONV_OBJS)
|
||||
|
||||
manpage: $(MANPAGE_OBJS) libmandoc.a
|
||||
$(CC) $(LDFLAGS) -o $@ $(MANPAGE_OBJS) libmandoc.a $(DBLIB)
|
||||
|
||||
apropos: $(APROPOS_OBJS) libmandoc.a
|
||||
$(CC) $(LDFLAGS) -o $@ $(APROPOS_OBJS) libmandoc.a $(DBLIB)
|
||||
|
||||
man.cgi: $(CGI_OBJS) libmandoc.a
|
||||
$(CC) $(LDFLAGS) $(STATIC) -o $@ $(CGI_OBJS) libmandoc.a $(DBLIB)
|
||||
|
||||
@ -482,18 +389,13 @@ mdocml.sha256: mdocml.tar.gz
|
||||
|
||||
mdocml.tar.gz: $(DISTFILES)
|
||||
mkdir -p .dist/mdocml-$(VERSION)/
|
||||
$(INSTALL_SOURCE) $(DISTFILES) .dist/mdocml-$(VERSION)
|
||||
$(INSTALL) -m 0644 $(DISTFILES) .dist/mdocml-$(VERSION)
|
||||
chmod 755 .dist/mdocml-$(VERSION)/configure
|
||||
( cd .dist/ && tar zcf ../$@ mdocml-$(VERSION) )
|
||||
rm -rf .dist/
|
||||
|
||||
config.h: configure config.h.pre config.h.post $(TESTSRCS)
|
||||
rm -f config.log
|
||||
CC="$(CC)" CFLAGS="$(CFLAGS)" DBLIB="$(DBLIB)" \
|
||||
VERSION="$(VERSION)" ./configure
|
||||
|
||||
.PHONY: base-install cgi-install db-install install www-install
|
||||
.PHONY: clean depend
|
||||
.PHONY: clean distclean depend
|
||||
.SUFFIXES: .1 .3 .5 .7 .8 .h
|
||||
.SUFFIXES: .1.html .3.html .5.html .7.html .8.html .h.html
|
||||
|
||||
|
@ -1,24 +1,23 @@
|
||||
apropos.o: apropos.c config.h manpath.h mansearch.h
|
||||
arch.o: arch.c config.h mdoc.h libmdoc.h arch.in
|
||||
att.o: att.c config.h mdoc.h libmdoc.h att.in
|
||||
att.o: att.c config.h mdoc.h libmdoc.h
|
||||
cgi.o: cgi.c config.h mandoc.h mandoc_aux.h main.h manpath.h mansearch.h cgi.h
|
||||
chars.o: chars.c config.h mandoc.h mandoc_aux.h libmandoc.h chars.in
|
||||
compat_fgetln.o: compat_fgetln.c config.h
|
||||
compat_getsubopt.o: compat_getsubopt.c config.h
|
||||
compat_ohash.o: compat_ohash.c config.h
|
||||
compat_reallocarray.o: compat_reallocarray.c config.h
|
||||
compat_sqlite3_errstr.o: compat_sqlite3_errstr.c config.h
|
||||
compat_strcasestr.o: compat_strcasestr.c config.h
|
||||
compat_strlcat.o: compat_strlcat.c config.h
|
||||
compat_strlcpy.o: compat_strlcpy.c config.h
|
||||
compat_strsep.o: compat_strsep.c config.h
|
||||
compat_fgetln.o: compat_fgetln.c config.h
|
||||
compat_fts.o: compat_fts.c config.h compat_fts.h
|
||||
compat_getsubopt.o: compat_getsubopt.c config.h
|
||||
compat_ohash.o: compat_ohash.c config.h compat_ohash.h
|
||||
compat_reallocarray.o: compat_reallocarray.c config.h
|
||||
compat_sqlite3_errstr.o: compat_sqlite3_errstr.c config.h
|
||||
compat_strcasestr.o: compat_strcasestr.c config.h
|
||||
compat_strlcat.o: compat_strlcat.c config.h
|
||||
compat_strlcpy.o: compat_strlcpy.c config.h
|
||||
compat_strsep.o: compat_strsep.c config.h
|
||||
demandoc.o: demandoc.c config.h man.h mdoc.h mandoc.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_term.o: eqn_term.c config.h mandoc.h out.h term.h
|
||||
html.o: html.c config.h mandoc.h mandoc_aux.h libmandoc.h out.h html.h main.h
|
||||
lib.o: lib.c config.h mdoc.h libmdoc.h lib.in
|
||||
main.o: main.c config.h mandoc.h mandoc_aux.h main.h mdoc.h man.h
|
||||
main.o: main.c config.h mandoc.h mandoc_aux.h main.h mdoc.h man.h manpath.h mansearch.h
|
||||
man.o: man.c config.h man.h mandoc.h mandoc_aux.h libman.h libmandoc.h
|
||||
man_hash.o: man_hash.c config.h man.h mandoc.h libman.h
|
||||
man_html.o: man_html.c config.h mandoc.h mandoc_aux.h out.h html.h man.h main.h
|
||||
@ -27,10 +26,10 @@ man_term.o: man_term.c config.h mandoc.h mandoc_aux.h out.h man.h term.h main.h
|
||||
man_validate.o: man_validate.c config.h man.h mandoc.h mandoc_aux.h libman.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
|
||||
mandocdb.o: mandocdb.c config.h mdoc.h man.h mandoc.h mandoc_aux.h manpath.h mansearch.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
|
||||
manpage.o: manpage.c config.h manpath.h mansearch.h
|
||||
manpath.o: manpath.c config.h mandoc_aux.h manpath.h
|
||||
mansearch.o: mansearch.c config.h mandoc.h mandoc_aux.h manpath.h mansearch.h
|
||||
mansearch.o: mansearch.c config.h compat_ohash.h mandoc.h mandoc_aux.h manpath.h mansearch.h
|
||||
mansearch_const.o: mansearch_const.c config.h manpath.h mansearch.h
|
||||
mdoc.o: mdoc.c config.h mdoc.h mandoc.h mandoc_aux.h libmdoc.h libmandoc.h
|
||||
mdoc_argv.o: mdoc_argv.c config.h mdoc.h mandoc.h mandoc_aux.h libmdoc.h libmandoc.h
|
||||
@ -42,9 +41,9 @@ mdoc_term.o: mdoc_term.c config.h mandoc.h mandoc_aux.h out.h term.h mdoc.h main
|
||||
mdoc_validate.o: mdoc_validate.c config.h mdoc.h mandoc.h mandoc_aux.h libmdoc.h libmandoc.h
|
||||
msec.o: msec.c config.h mandoc.h libmandoc.h msec.in
|
||||
out.o: out.c config.h mandoc_aux.h mandoc.h out.h
|
||||
preconv.o: preconv.c config.h
|
||||
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 main.h
|
||||
roff.o: roff.c config.h mandoc.h mandoc_aux.h libroff.h libmandoc.h predefs.in
|
||||
roff.o: roff.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h predefs.in
|
||||
st.o: st.c config.h mdoc.h libmdoc.h st.in
|
||||
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
|
||||
@ -56,15 +55,18 @@ 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_ps.o: term_ps.c config.h mandoc.h mandoc_aux.h out.h main.h term.h
|
||||
tree.o: tree.c config.h mandoc.h mdoc.h man.h main.h
|
||||
vol.o: vol.c config.h mdoc.h libmdoc.h vol.in
|
||||
test-fgetln.o: test-fgetln.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_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-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-wchar.o: test-wchar.c
|
||||
|
5
NEWS
5
NEWS
@ -1,4 +1,4 @@
|
||||
$Id: NEWS,v 1.5 2014/08/10 16:32:57 schwarze Exp $
|
||||
$Id: NEWS,v 1.6 2014/08/11 01:39:00 schwarze Exp $
|
||||
|
||||
This file lists the most important changes in the mdocml.bsd.lv distribution.
|
||||
|
||||
@ -7,9 +7,6 @@ Changes in version 1.13.1, released on August 10, 2014
|
||||
--- MAJOR NEW FEATURES ---
|
||||
* A complete apropos(1)/makewhatis(8)/man.cgi(8) suite
|
||||
based on SQLite3 is now included.
|
||||
CAVEAT: This also requires a working fts(3) implementation.
|
||||
If your system lacks that *and* you want apropos(1)/makewhatis(8),
|
||||
stay with 1.12.3 for now, then go to 1.12.4 and 1.13.2.
|
||||
* The roff(7) parser now provides an almost complete implementation
|
||||
of numerical expressions.
|
||||
* Warning and error messages have been improved in many ways.
|
||||
|
176
TODO
176
TODO
@ -1,8 +1,37 @@
|
||||
************************************************************************
|
||||
* Official mandoc TODO.
|
||||
* $Id: TODO,v 1.176 2014/08/09 14:24:53 schwarze Exp $
|
||||
* $Id: TODO,v 1.189 2014/11/26 21:40:17 schwarze Exp $
|
||||
************************************************************************
|
||||
|
||||
Many issues are annotated for difficulty as follows:
|
||||
|
||||
- loc = locality of the issue
|
||||
* single file issue, affects file only, or very few
|
||||
** single module issue, affects several files of one module
|
||||
*** cross-module issue, significantly impacts multiple modules
|
||||
and may require substantial changes to internal interfaces
|
||||
- exist = difficulty of the existing code in this area
|
||||
* affected code is straightforward and easy to read and change
|
||||
** affected code is somewhat complex, but once you understand
|
||||
the design, not particularly difficult to understand
|
||||
*** affected code uses a special, exceptionally tricky design
|
||||
- algo = difficulty of the new algorithm to be written
|
||||
* the required logic and code is straightforward
|
||||
** the required logic is somewhat complex and needs a careful design
|
||||
*** the required logic is exceptionally tricky,
|
||||
maybe an approach to solve that is not even known yet
|
||||
- size = the amount of code to be written or changed
|
||||
* a small number of lines (at most 100, usually much less)
|
||||
** a considerable amount of code (several dozen to a few hundred)
|
||||
*** a large amount of code (many hundreds, maybe thousands)
|
||||
- imp = importance of the issue
|
||||
* mostly for completeness
|
||||
** would be nice to have
|
||||
*** issue causes considerable inconvenience
|
||||
|
||||
Obviously, as the issues have not been solved yet, these annotations
|
||||
are mere guesses, and some may be wrong.
|
||||
|
||||
************************************************************************
|
||||
* crashes
|
||||
************************************************************************
|
||||
@ -10,6 +39,7 @@
|
||||
- The abort() in bufcat(), html.c, can be triggered via buffmt_includes()
|
||||
by running -Thtml -Oincludes on a file containing a long .In argument.
|
||||
Fixing this will probably require reworking the whole bufcat() concept.
|
||||
loc ** exist * algo * size ** imp **
|
||||
|
||||
************************************************************************
|
||||
* missing features
|
||||
@ -25,49 +55,62 @@
|
||||
.na -- temporarily disable adjustment without changing the mode
|
||||
.ad -- re-enable adjustment without changing the mode
|
||||
Adjustment mode is ignored while in no-fill mode (.nf).
|
||||
loc *** exist *** algo ** size ** imp ** (parser reorg would help)
|
||||
|
||||
- .fc (field control)
|
||||
found by naddy@ in xloadimage(1)
|
||||
loc ** exist *** algo * size * imp *
|
||||
|
||||
- .nr third argument (auto-increment step size, requires \n+)
|
||||
found by bentley@ in sbcl(1) Mon, 9 Dec 2013 18:36:57 -0700
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- .ns (no-space mode) occurs in xine-config(1)
|
||||
reported by brad@ Sat, 15 Jan 2011 15:45:23 -0500
|
||||
loc *** exist *** algo *** size ** imp *
|
||||
|
||||
- .ta (tab settings) occurs in ircbug(1) and probably gnats(1)
|
||||
reported by brad@ Sat, 15 Jan 2011 15:50:51 -0500
|
||||
also Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100
|
||||
loc ** exist *** algo ** size ** imp **
|
||||
|
||||
- .ti (temporary indent)
|
||||
found by naddy@ in xloadimage(1)
|
||||
found by bentley@ in nmh(1) Mon, 23 Apr 2012 13:38:28 -0600
|
||||
loc ** exist ** algo ** size * imp ** (parser reorg helps a lot)
|
||||
|
||||
- .while and .shift
|
||||
found by jca@ in ratpoison(1) Sun, 30 Jun 2013 12:01:09 +0200
|
||||
loc * exist ** algo ** size ** imp **
|
||||
|
||||
- \c (interrupted text) should prevent the line break
|
||||
even inside .Bd literal; that occurs in chat(8)
|
||||
also found in cclive(1) - DocBook output
|
||||
loc ** exist *** algo ** size * imp *
|
||||
|
||||
- \h horizontal move
|
||||
found in cclive(1) DocBook output
|
||||
Anthony J. Bentley on discuss@ Sat, 21 Sep 2013 22:29:34 -0600
|
||||
loc ** exist ** algo ** size * imp ** (parser reorg helps a lot)
|
||||
|
||||
- \n+ and \n- numerical register increment and decrement
|
||||
found by bentley@ in sbcl(1) Mon, 9 Dec 2013 18:36:57 -0700
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- \w'' width measurements
|
||||
- \w'' improve width measurements
|
||||
would not be very useful without an expression parser, see below
|
||||
needed for Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100
|
||||
loc ** exist *** algo *** size * imp ***
|
||||
|
||||
- using undefined strings or macros defines them to be empty
|
||||
wl@ Mon, 14 Nov 2011 14:37:01 +0000
|
||||
loc * exist * algo * size * imp *
|
||||
|
||||
--- missing mdoc features ----------------------------------------------
|
||||
|
||||
- fix bad block nesting involving multiple identical explicit blocks
|
||||
see the OpenBSD mdoc_macro.c 1.47 commit message
|
||||
loc * exist *** algo *** size * imp **
|
||||
|
||||
- .Bl -column .Xo support is missing
|
||||
ultimate goal:
|
||||
@ -75,10 +118,12 @@
|
||||
lib/libc/compat-43/sigvec.3
|
||||
lib/libc/gen/signal.3
|
||||
lib/libc/sys/sigaction.2
|
||||
loc * exist *** algo *** size * imp **
|
||||
|
||||
- edge case: decide how to deal with blk_full bad nesting, e.g.
|
||||
.Sh .Nm .Bk .Nm .Ek .Sh found by jmc@ in ssh-keygen(1)
|
||||
from jmc@ Wed, 14 Jul 2010 18:10:32 +0100
|
||||
loc * exist *** algo *** size ** imp **
|
||||
|
||||
- \\ is now implemented correctly
|
||||
* when defining strings and macros using .ds and .de
|
||||
@ -92,18 +137,22 @@
|
||||
we don't have either.
|
||||
Besides, groff has bug causing text right *before* .Bd -centered
|
||||
to be centered as well.
|
||||
loc *** exist *** algo ** size ** imp ** (parser reorg would help)
|
||||
|
||||
- .Bd -filled should not be the same as .Bd -ragged, but align both
|
||||
the left and right margin. In groff, it is implemented in terms
|
||||
of .ad b, which we don't have either. Found in cksum(1).
|
||||
loc *** exist *** algo ** size ** imp ** (parser reorg would help)
|
||||
|
||||
- implement blank `Bl -column', such as
|
||||
.Bl -column
|
||||
.It foo Ta bar
|
||||
.El
|
||||
loc * exist *** algo *** size * imp *
|
||||
|
||||
- explicitly disallow nested `Bl -column', which would clobber internal
|
||||
flags defined for struct mdoc_macro
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- In .Bl -column .It, the end of the line probably has to be regarded
|
||||
as an implicit .Ta, if there could be one, see the following mildly
|
||||
@ -114,6 +163,7 @@
|
||||
Default search path.
|
||||
reported by Michal Mazurek <akfaew at jasminek dot net>
|
||||
via jmc@ Thu, 7 Apr 2011 16:00:53 +0059
|
||||
loc * exist *** algo ** size * imp **
|
||||
|
||||
- inside `.Bl -column' phrases, punctuation is handled like normal
|
||||
text, e.g. `.Bl -column .It Fl x . Ta ...' should give "-x -."
|
||||
@ -123,11 +173,14 @@
|
||||
but should give "ab ."
|
||||
|
||||
- set a meaningful default if no `Bl' list type is assigned
|
||||
loc * exist * algo * size * imp ** (already done?)
|
||||
|
||||
- have a blank `It' head for `Bl -tag' not puke
|
||||
loc * exist * algo * size * imp ** (already done?)
|
||||
|
||||
- check whether it is correct that `D1' uses INDENT+1;
|
||||
does it need its own constant?
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- prohibit `Nm' from having non-text HEAD children
|
||||
(e.g., NetBSD mDNSShared/dns-sd.1)
|
||||
@ -138,6 +191,7 @@
|
||||
that one uses NOMBRE because it is spanish...
|
||||
deraadt tends to think that section-dependent macro behaviour
|
||||
is a bad idea in the first place, so this may be irrelevant
|
||||
loc ** exist ** algo ** size * imp **
|
||||
|
||||
- When there is free text in the SYNOPSIS and that free text contains
|
||||
the .Nm macro, groff somehow understands to treat the .Nm as an in-line
|
||||
@ -146,6 +200,7 @@
|
||||
should be, needs investigation.
|
||||
uqs@ Thu, 2 Jun 2011 11:03:51 +0200
|
||||
uqs@ Thu, 2 Jun 2011 11:33:35 +0200
|
||||
loc * exist ** algo *** size * imp **
|
||||
|
||||
--- missing man features -----------------------------------------------
|
||||
|
||||
@ -155,18 +210,36 @@
|
||||
|
||||
- look at the POSIX manuals in the books/man-pages-posix port,
|
||||
they use some unsupported tbl(7) features.
|
||||
loc * exist ** algo ** size ** imp ***
|
||||
|
||||
- investigate tbl(1) errors in sox(1)
|
||||
see also naddy@ Sat, 16 Oct 2010 23:51:57 +0200
|
||||
- use Unicode U+2500 to U+256C for table borders
|
||||
in tbl(7) -Tutf-8 output
|
||||
suggested by bentley@ Tue, 14 Oct 2014 04:10:55 -0600
|
||||
loc * exist ** algo * size * imp **
|
||||
|
||||
- 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 -----------------------------------------------
|
||||
|
||||
- The "size" keyword is parsed, but ignored by the formatter.
|
||||
loc * exist * algo * size * imp *
|
||||
|
||||
- The spacing characters `~', `^', and tab are currently ignored,
|
||||
see User's Guide (Second Edition) page 2 section 4.
|
||||
loc * exist * algo ** size * imp **
|
||||
|
||||
- Mark and lineup are parsed and ignored,
|
||||
see User's Guide (Second Edition) page 5 section 15.
|
||||
loc ** exist ** algo ** size ** imp **
|
||||
|
||||
--- missing misc features ----------------------------------------------
|
||||
|
||||
- italic correction (\/) in PostScript mode
|
||||
Werner LEMBERG on groff at gnu dot org Sun, 10 Nov 2013 12:47:46
|
||||
loc ** exist ** algo * size * imp *
|
||||
|
||||
- When makewhatis(8) encounters a FATAL parse error,
|
||||
it silently treats the file as formatted, which makes no sense
|
||||
@ -174,13 +247,16 @@
|
||||
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:
|
||||
parse the section number from the header line
|
||||
and compare to the section number from the directory name
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- Does makewhatis(8) detect missing NAME sections, missing names,
|
||||
and missing descriptions in all the file formats?
|
||||
loc * exist * algo * size * imp ***
|
||||
|
||||
- clean up escape sequence handling, creating three classes:
|
||||
(1) fully implemented, or parsed and ignored without loss of content
|
||||
@ -188,8 +264,10 @@
|
||||
or serious mangling of formatting (e.g. \n) -> ERROR
|
||||
see textproc/mgdiff(1) for nice examples
|
||||
(3) undefined, just output the character -> perhaps WARNING
|
||||
loc *** exist ** algo ** size ** imp *** (parser reorg helps)
|
||||
|
||||
- kettenis wants base roff, ms, and me Fri, 1 Jan 2010 22:13:15 +0100 (CET)
|
||||
loc ** exist ** algo ** size *** imp *
|
||||
|
||||
--- compatibility checks -----------------------------------------------
|
||||
|
||||
@ -199,6 +277,10 @@
|
||||
- compare output to Heirloom roff, Solaris roff, and
|
||||
http://repo.or.cz/w/neatroff.git http://litcave.rudi.ir/
|
||||
|
||||
- look at AT&T DWB http://www2.research.att.com/sw/download
|
||||
Carsten Kunze <carsten dot kunze at arcor dot de> has patches
|
||||
Mon, 4 Aug 2014 17:01:28 +0200
|
||||
|
||||
- look at pages generated from reStructeredText, e.g. devel/mercurial hg(1)
|
||||
These are a weird mixture of man(7) and custom autogenerated low-level
|
||||
roff stuff. Figure out to what extent we can cope.
|
||||
@ -224,6 +306,11 @@
|
||||
- check compatibility with the man(7) formatter
|
||||
https://raw.githubusercontent.com/rofl0r/hardcore-utils/master/man.c
|
||||
|
||||
- check compatibility with
|
||||
http://ikiwiki.info/plugins/contrib/mandoc/
|
||||
https://github.com/schmonz/ikiwiki/compare/mandoc
|
||||
Amitai Schlair Mon, 19 May 2014 14:05:53 -0400
|
||||
|
||||
************************************************************************
|
||||
* formatting issues: ugly output
|
||||
************************************************************************
|
||||
@ -236,10 +323,12 @@
|
||||
ought to render "Key Length" with emphasis, too,
|
||||
see OpenBSD iked.conf(5).
|
||||
reported again Nicolas Joly via wiz@ Wed, 12 Oct 2011 00:20:00 +0200
|
||||
loc * exist *** algo *** size ** imp ***
|
||||
|
||||
- empty phrases in .Bl column produce too few blanks
|
||||
try e.g. .Bl -column It Ta Ta
|
||||
reported by millert Fri, 02 Apr 2010 16:13:46 -0400
|
||||
loc * exist *** algo *** size * imp **
|
||||
|
||||
- .%T can have trailing punctuation. Currently, it puts the trailing
|
||||
punctuation into a trailing MDOC_TEXT element inside its own scope.
|
||||
@ -249,11 +338,13 @@
|
||||
slurp all arguments into one single text element - and one feature
|
||||
of in_line() - put trailing punctuation out of scope.
|
||||
Found in mount_nfs(8) and exports(5), search for "Appendix".
|
||||
loc ** exist ** algo *** size * imp **
|
||||
|
||||
- Trailing punctuation after .%T triggers EOS spacing, at least
|
||||
outside .Rs (eek!). Simply setting ARGSFL_DELIM for .%T is not
|
||||
the right solution, it sends mandoc into an endless loop.
|
||||
reported by Nicolas Joly Sat, 17 Nov 2012 11:49:54 +0100
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- global variables in the SYNOPSIS of section 3 pages
|
||||
.Vt vs .Vt/.Va vs .Ft/.Va vs .Ft/.Fa ...
|
||||
@ -261,6 +352,7 @@
|
||||
|
||||
- in enclosures, mandoc sometimes fancies a bogus end of sentence
|
||||
reminded by jmc@ Thu, 23 Sep 2010 18:13:39 +0059
|
||||
loc * exist ** algo *** size * imp ***
|
||||
|
||||
- formatting /usr/local/man/man1/latex2man.1 with groff and mandoc
|
||||
reveals lots of bugs both in groff and mandoc...
|
||||
@ -273,6 +365,10 @@
|
||||
Search the text "Routing tables".
|
||||
Also check what PostScript mode does when fixing this.
|
||||
reported by juanfra@ Wed, 04 Jun 2014 21:44:58 +0200
|
||||
instructions from juanfra@ Wed, 11 Jun 2014 02:21:01 +0200
|
||||
add a new <</Type /Font>> block to the PDF files with /BaseFont /Courier
|
||||
and change the /Name from /F0 to the new font (/F5 (?)).
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
--- HTML issues --------------------------------------------------------
|
||||
|
||||
@ -280,6 +376,20 @@
|
||||
hints are easy to find on the web, e.g.
|
||||
http://stackoverflow.com/questions/1713048/
|
||||
see also matthew@ Fri, 18 Jul 2014 19:25:12 -0700
|
||||
loc * exist * algo ** size * imp ***
|
||||
|
||||
- jsg on icb, Nov 3, 2014:
|
||||
try to guess Xr in man(7) for hyperlinking
|
||||
|
||||
- The tables used to render the three-part page headers actually force
|
||||
the width of the <body> to the max-width given for <html>.
|
||||
Not yet sure how to fix that...
|
||||
Observed by an Anonymous Coward on undeadly.org:
|
||||
http://undeadly.org/cgi?action=article&sid=20140925064244&pid=1
|
||||
loc * exist * algo ** size * imp ***
|
||||
|
||||
- consider whether <var> can be used for Ar Dv Er Ev Fa Va.
|
||||
from bentley@ Wed, 13 Aug 2014 09:17:55 -0600
|
||||
|
||||
- check https://github.com/trentm/mdocml
|
||||
|
||||
@ -287,42 +397,57 @@
|
||||
* formatting issues: gratuitous differences
|
||||
************************************************************************
|
||||
|
||||
- .Fn reopens a new scope after punctuation in mandoc,
|
||||
but closes its scope for good in groff.
|
||||
Do we want to change mandoc or groff?
|
||||
Steffen Nurpmeso Sat, 08 Nov 2014 13:34:59 +0100
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- .Rv (and probably .Ex) print different text if an `Nm' has been named
|
||||
or not (run a manual without `Nm blah' to see this). I'm not sure
|
||||
that this exists in the wild, but it's still an error.
|
||||
loc * exist * algo * size * imp * (already done?)
|
||||
|
||||
- In .Bl -bullet, the groff bullet is "+\b+\bo\bo", the mandoc bullet
|
||||
is just "o\bo".
|
||||
is just "o\bo". The problem is to not break ps/pdf when fixing.
|
||||
see for example OpenBSD ksh(1)
|
||||
loc ** exist ** algo ** size * imp **
|
||||
|
||||
- In .Bl -enum -width 0n, groff continues one the same line after
|
||||
the number, mandoc breaks the line.
|
||||
mail to kristaps@ Mon, 20 Jul 2009 02:21:39 +0200
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- .Pp between two .It in .Bl -column should produce one,
|
||||
not two blank lines, see e.g. login.conf(5).
|
||||
reported by jmc@ Sun, 17 Apr 2011 14:04:58 +0059
|
||||
reported again by sthen@ Wed, 18 Jan 2012 02:09:39 +0000 (UTC)
|
||||
loc * exist *** algo ** size * imp **
|
||||
|
||||
- If the *first* line after .It is .Pp, break the line right after
|
||||
the tag, do not pad with space characters before breaking.
|
||||
See the description of the a, c, and i commands in sed(1).
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- If the first line after .It is .D1, do not assert a blank line
|
||||
in between, see for example tmux(1).
|
||||
reported by nicm@ 13 Jan 2011 00:18:57 +0000
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- Trailing punctuation after .It should trigger EOS spacing.
|
||||
reported by Nicolas Joly Sat, 17 Nov 2012 11:49:54 +0100
|
||||
Probably, this should be fixed somewhere in termp_it_pre(), not sure.
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- .Nx 1.0a
|
||||
should be "NetBSD 1.0A", not "NetBSD 1.0a",
|
||||
see OpenBSD ccdconfig(8).
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- In .Bl -tag, if a tag exceeds the right margin and must be continued
|
||||
on the next line, it must be indented by -width, not width+1;
|
||||
see "rule block|pass" in OpenBSD ifconfig(8).
|
||||
loc * exist *** algo ** size * imp **
|
||||
|
||||
- When the -width string contains macros, the macros must be rendered
|
||||
before measuring the width, for example
|
||||
@ -332,17 +457,21 @@
|
||||
The same applies to .Bl -column column widths;
|
||||
reported again by Nicolas Joly Thu, 1 Mar 2012 13:41:26 +0100 via wiz@ 5 Mar
|
||||
reported again by Franco Fichtner Fri, 27 Sep 2013 21:02:28 +0200
|
||||
loc *** exist *** algo *** size ** imp ***
|
||||
An easy partial fix would be to just skip the first word if it starts
|
||||
with a dot, including any following white space, when measuring.
|
||||
loc * exist * algo * size * imp ***
|
||||
|
||||
- The \& zero-width character counts as output.
|
||||
That is, when it is alone on a line between two .Pp,
|
||||
we want three blank lines, not two as in mandoc.
|
||||
loc ** exist ** algo ** size * imp **
|
||||
|
||||
- Header lines of excessive length:
|
||||
Port OpenBSD man_term.c rev. 1.25 to mdoc_term.c
|
||||
and document it in mdoc(7) and man(7) COMPATIBILITY
|
||||
found while talking to Chris Bennett
|
||||
loc * exist * algo * size * imp *
|
||||
|
||||
- trailing whitespace must be ignored even when followed by a font escape,
|
||||
see for example
|
||||
@ -350,6 +479,7 @@
|
||||
\fBdig \fR
|
||||
operate in batch mode
|
||||
in dig(1).
|
||||
loc ** exist ** algo ** size * imp **
|
||||
|
||||
************************************************************************
|
||||
* warning issues
|
||||
@ -361,17 +491,29 @@
|
||||
to refer to fill mode, not literal mode
|
||||
See the mail from Werner LEMBERG on the groff list,
|
||||
Fri, 14 Feb 2014 18:54:42 +0100 (CET)
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- warn about attempts to call non-callable macros
|
||||
Steffen Nurpmeso Tue, 11 Nov 2014 22:55:16 +0100
|
||||
Note that formatting is inconsistent in groff.
|
||||
.Fn Po prints "Po()", .Ar Sh prints "file ..." and no "Sh".
|
||||
Relatively hard because the relevant code is scattered
|
||||
all over mdoc_macro.c and all subtly different.
|
||||
loc ** exist ** algo ** size ** imp **
|
||||
|
||||
- warn about "new sentence, new line"
|
||||
loc ** exist ** algo *** size * imp **
|
||||
|
||||
- mandoc_special does not really check the escape sequence,
|
||||
but just the overall format
|
||||
loc ** exist ** algo *** size ** imp **
|
||||
|
||||
- integrate mdoclint into mandoc ("end-of-line whitespace" thread)
|
||||
from jmc@ Mon, 13 Jul 2009 17:12:09 +0100
|
||||
from kristaps@ Mon, 13 Jul 2009 18:34:53 +0200
|
||||
from jmc@ Mon, 13 Jul 2009 17:45:37 +0059
|
||||
from kristaps@ Mon, 13 Jul 2009 19:02:03 +0200
|
||||
(mostly done, check what remains)
|
||||
|
||||
- -Tlint parser errors and warnings to stdout
|
||||
to tech@mdocml, naddy@ Wed, 28 Sep 2011 11:21:46 +0200
|
||||
@ -395,6 +537,9 @@
|
||||
|
||||
- mention /usr/share/misc/mdoc.template in mdoc(7)?
|
||||
|
||||
- Is all the content from http://www.std.com/obi/BSD/doc/usd/28.tbl/tbl
|
||||
covered in tbl(7)?
|
||||
|
||||
************************************************************************
|
||||
* performance issues
|
||||
************************************************************************
|
||||
@ -413,11 +558,15 @@ Several areas can be cleaned up to make mandoc even faster. These are
|
||||
|
||||
- instead of re-initialising the roff predefined-strings set before each
|
||||
parse, create a read-only version the first time and copy it
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
************************************************************************
|
||||
* structural issues
|
||||
************************************************************************
|
||||
|
||||
- Use libz directly instead of forking gunzip(1).
|
||||
Suggested by bapt at FreeBSD among others.
|
||||
|
||||
- We use the input line number at several places to distinguish
|
||||
same-line from different-line input. That plainly doesn't work
|
||||
with user-defined macros, leading to random breakage.
|
||||
@ -430,8 +579,25 @@ Several areas can be cleaned up to make mandoc even faster. These are
|
||||
Update both mdoc(7) and man(7) documentation.
|
||||
Triggered by Tim van der Molen Tue, 22 Feb 2011 20:30:45 +0100
|
||||
|
||||
- struct mparse refactoring
|
||||
Steffen Nurpmeso Thu, 04 Sep 2014 12:50:00 +0200
|
||||
|
||||
- Consider creating some views that will make the database more
|
||||
readable from the sqlite3 shell. Consider using them to
|
||||
abstract from the database structure, too.
|
||||
suggested by espie@ Sat, 19 Apr 2014 14:52:57 +0200
|
||||
|
||||
************************************************************************
|
||||
* CGI issues
|
||||
************************************************************************
|
||||
|
||||
- Enable HTTP compression by detecting gzip encoding and filtering
|
||||
output through libz.
|
||||
- Sandbox (see OpenSSH).
|
||||
- Enable caching support via HTTP 304 and If-Modified-Since.
|
||||
- Allow for cgi.h to be overridden by CGI environment variables.
|
||||
Otherwise, binary distributions will inherit the compile-time
|
||||
behaviour, which is not optimal.
|
||||
- Have Mac OSX systems automatically disable -static compilation of the
|
||||
CGI: -static isn't supported.
|
||||
|
||||
|
133
apropos.1
133
apropos.1
@ -1,4 +1,4 @@
|
||||
.\" $Id: apropos.1,v 1.29 2014/04/24 00:28:19 schwarze Exp $
|
||||
.\" $Id: apropos.1,v 1.36 2014/10/25 01:03:52 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: April 24 2014 $
|
||||
.Dd $Mdocdate: October 25 2014 $
|
||||
.Dt APROPOS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -24,6 +24,7 @@
|
||||
.Nd search manual page databases
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl acfhklVw
|
||||
.Op Fl C Ar file
|
||||
.Op Fl M Ar path
|
||||
.Op Fl m Ar path
|
||||
@ -41,7 +42,7 @@ utilities query manual page databases generated by
|
||||
evaluating
|
||||
.Ar expression
|
||||
for each file in each database.
|
||||
By default, it displays the names, section numbers, and description lines
|
||||
By default, they display the names, section numbers, and description lines
|
||||
of all matching manuals.
|
||||
.Pp
|
||||
By default,
|
||||
@ -56,17 +57,82 @@ over manual names and descriptions
|
||||
.Pq the Li \&Nm No and Li \&Nd No macro keys .
|
||||
Multiple terms imply pairwise
|
||||
.Fl o .
|
||||
.Nm whatis
|
||||
maps terms only to case-sensitive manual names.
|
||||
.Pp
|
||||
Its arguments are as follows:
|
||||
.Nm whatis
|
||||
is a synonym for
|
||||
.Nm
|
||||
.Fl f .
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Instead of showing only the title lines, show the complete manual pages,
|
||||
just like
|
||||
.Xr man 1
|
||||
.Fl a
|
||||
would.
|
||||
If the standard output is a terminal device and
|
||||
.Fl c
|
||||
is not specified, use
|
||||
.Xr more 1
|
||||
to paginate them.
|
||||
In
|
||||
.Fl a
|
||||
mode, the options
|
||||
.Fl IKOTW
|
||||
described in the
|
||||
.Xr mandoc 1
|
||||
manual are also available.
|
||||
.It Fl C Ar file
|
||||
Specify an alternative configuration
|
||||
.Ar file
|
||||
in
|
||||
.Xr man.conf 5
|
||||
format.
|
||||
.It Fl c
|
||||
In
|
||||
.Fl a
|
||||
mode, copy the formatted manual pages to the standard output without using
|
||||
.Xr more 1
|
||||
to paginate them.
|
||||
.It Fl f
|
||||
Search for all words in
|
||||
.Ar expression
|
||||
in manual page names only.
|
||||
The search is case insensitive and matches whole words only.
|
||||
In this mode, macro keys, comparison operators, and logical operators
|
||||
are not available.
|
||||
This overrides any earlier
|
||||
.Fl k
|
||||
and
|
||||
.Fl l
|
||||
options.
|
||||
.It Fl h
|
||||
Instead of showing the title lines, show the SYNOPSIS sections, just like
|
||||
.Xr man 1
|
||||
.Fl h
|
||||
would.
|
||||
.It Fl k
|
||||
Support the full
|
||||
.Ar expression
|
||||
syntax.
|
||||
This overrides any earlier
|
||||
.Fl f
|
||||
and
|
||||
.Fl l
|
||||
options.
|
||||
It is the default for
|
||||
.Nm .
|
||||
.It Fl l
|
||||
An alias for
|
||||
.Xr mandoc 1
|
||||
.Fl a .
|
||||
This overrides any earlier
|
||||
.Fl f ,
|
||||
.Fl k ,
|
||||
and
|
||||
.Fl w
|
||||
options.
|
||||
.It Fl M Ar path
|
||||
Use the colon-separated path instead of the default list of paths
|
||||
searched for
|
||||
@ -96,6 +162,14 @@ By default, pages from all sections are shown.
|
||||
See
|
||||
.Xr man 1
|
||||
for a listing of sections.
|
||||
.It Fl V
|
||||
Print version and exit.
|
||||
.It Fl w
|
||||
Instead of showing title lines, show the pathnames of the matching
|
||||
manual pages, just like
|
||||
.Xr man 1
|
||||
.Fl w
|
||||
would.
|
||||
.El
|
||||
.Pp
|
||||
An
|
||||
@ -165,11 +239,6 @@ is evaluated case-insensitively.
|
||||
Has no effect on substring terms.
|
||||
.El
|
||||
.Pp
|
||||
.Nm whatis
|
||||
considers an
|
||||
.Ar expression
|
||||
to consist of an opaque keyword.
|
||||
.Pp
|
||||
Results are sorted by manual sections and names, with output formatted as
|
||||
.Pp
|
||||
.D1 name[, name...](sec) \- description
|
||||
@ -270,7 +339,12 @@ Text production:
|
||||
.It Li \&Dx Ta Dx No version reference
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width MANPATH
|
||||
.Bl -tag -width MANPAGER
|
||||
.It Ev MANPAGER
|
||||
Any non-empty value of the environment variable
|
||||
.Ev MANPAGER
|
||||
will be used instead of the standard pagination program,
|
||||
.Xr more 1 .
|
||||
.It Ev MANPATH
|
||||
The standard search path used by
|
||||
.Xr man 1
|
||||
@ -288,6 +362,13 @@ or if it contains two adjacent colons,
|
||||
the standard search path is inserted between the colons.
|
||||
If none of these conditions are met, it overrides the
|
||||
standard search path.
|
||||
.It Ev PAGER
|
||||
Specifies the pagination program to use when
|
||||
.Ev MANPAGER
|
||||
is not defined.
|
||||
If neither PAGER nor MANPAGER is defined,
|
||||
.Pa /usr/bin/more Fl s
|
||||
will be used.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/etc/man.conf" -compact
|
||||
@ -349,11 +430,19 @@ The following two invocations are equivalent:
|
||||
.Xr re_format 7 ,
|
||||
.Xr makewhatis 8
|
||||
.Sh HISTORY
|
||||
An
|
||||
Part of the functionality of
|
||||
.Nm whatis
|
||||
was already provided by the former
|
||||
.Nm manwhere
|
||||
utility in
|
||||
.Bx 1 .
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
and
|
||||
.Nm whatis
|
||||
utilities first appeared in
|
||||
.Bx 2 .
|
||||
It was rewritten from scratch for
|
||||
They were rewritten from scratch for
|
||||
.Ox 5.6 .
|
||||
.Pp
|
||||
The
|
||||
@ -373,13 +462,23 @@ and
|
||||
and
|
||||
.Fl s
|
||||
in
|
||||
.Ox 4.5 .
|
||||
.Ox 4.5
|
||||
for
|
||||
.Nm
|
||||
and in
|
||||
.Ox 5.6
|
||||
for
|
||||
.Nm whatis .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
.An Bill Joy
|
||||
wrote the original
|
||||
wrote
|
||||
.Nm manwhere
|
||||
in 1977 and the original
|
||||
.Bx
|
||||
.Nm
|
||||
and
|
||||
.Nm whatis
|
||||
in February 1979.
|
||||
The current version was written by
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
|
||||
|
123
apropos.c
123
apropos.c
@ -1,123 +0,0 @@
|
||||
/* $Id: apropos.c,v 1.39 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* 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.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "manpath.h"
|
||||
#include "mansearch.h"
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, whatis;
|
||||
struct mansearch search;
|
||||
size_t i, sz;
|
||||
struct manpage *res;
|
||||
struct manpaths paths;
|
||||
char *defpaths, *auxpaths;
|
||||
char *conf_file;
|
||||
char *progname;
|
||||
const char *outkey;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname == NULL)
|
||||
progname = argv[0];
|
||||
else
|
||||
++progname;
|
||||
|
||||
whatis = (0 == strncmp(progname, "whatis", 6));
|
||||
|
||||
memset(&paths, 0, sizeof(struct manpaths));
|
||||
memset(&search, 0, sizeof(struct mansearch));
|
||||
|
||||
auxpaths = defpaths = NULL;
|
||||
conf_file = NULL;
|
||||
outkey = "Nd";
|
||||
|
||||
while (-1 != (ch = getopt(argc, argv, "C:M:m:O:S:s:")))
|
||||
switch (ch) {
|
||||
case 'C':
|
||||
conf_file = optarg;
|
||||
break;
|
||||
case 'M':
|
||||
defpaths = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
auxpaths = optarg;
|
||||
break;
|
||||
case 'O':
|
||||
outkey = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
search.arch = optarg;
|
||||
break;
|
||||
case 's':
|
||||
search.sec = optarg;
|
||||
break;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (0 == argc)
|
||||
goto usage;
|
||||
|
||||
search.deftype = whatis ? TYPE_Nm : TYPE_Nm | TYPE_Nd;
|
||||
search.flags = whatis ? MANSEARCH_WHATIS : 0;
|
||||
|
||||
manpath_parse(&paths, conf_file, defpaths, auxpaths);
|
||||
mansearch_setup(1);
|
||||
ch = mansearch(&search, &paths, argc, argv, outkey, &res, &sz);
|
||||
manpath_free(&paths);
|
||||
|
||||
if (0 == ch)
|
||||
goto usage;
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
printf("%s - %s\n", res[i].names,
|
||||
NULL == res[i].output ? "" : res[i].output);
|
||||
free(res[i].file);
|
||||
free(res[i].names);
|
||||
free(res[i].output);
|
||||
}
|
||||
|
||||
free(res);
|
||||
mansearch_setup(0);
|
||||
return(sz ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
usage:
|
||||
fprintf(stderr, "usage: %s [-C file] [-M path] [-m path] "
|
||||
"[-O outkey] "
|
||||
"[-S arch] [-s section]%s ...\n", progname,
|
||||
whatis ? " name" : "\n expression");
|
||||
return(EXIT_FAILURE);
|
||||
}
|
112
arch.in
112
arch.in
@ -1,112 +0,0 @@
|
||||
/* $Id: arch.in,v 1.15 2014/04/27 22:42:15 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 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 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 file defines the architecture token of the .Dt prologue macro.
|
||||
* All architectures that your system supports (or the manuals of your
|
||||
* system) should be included here. The right-hand-side is the
|
||||
* formatted output.
|
||||
*
|
||||
* Be sure to escape strings.
|
||||
*
|
||||
* REMEMBER TO ADD NEW ARCHITECTURES TO MDOC.7!
|
||||
*/
|
||||
|
||||
LINE("acorn26", "Acorn26")
|
||||
LINE("acorn32", "Acorn32")
|
||||
LINE("algor", "Algor")
|
||||
LINE("alpha", "Alpha")
|
||||
LINE("amd64", "AMD64")
|
||||
LINE("amiga", "Amiga")
|
||||
LINE("amigappc", "AmigaPPC")
|
||||
LINE("arc", "ARC")
|
||||
LINE("arm", "ARM")
|
||||
LINE("arm26", "ARM26")
|
||||
LINE("arm32", "ARM32")
|
||||
LINE("armish", "ARMISH")
|
||||
LINE("armv7", "ARMv7")
|
||||
LINE("aviion", "AViiON")
|
||||
LINE("atari", "ATARI")
|
||||
LINE("bebox", "BeBox")
|
||||
LINE("cats", "cats")
|
||||
LINE("cesfic", "CESFIC")
|
||||
LINE("cobalt", "Cobalt")
|
||||
LINE("dreamcast", "Dreamcast")
|
||||
LINE("emips", "EMIPS")
|
||||
LINE("evbarm", "evbARM")
|
||||
LINE("evbmips", "evbMIPS")
|
||||
LINE("evbppc", "evbPPC")
|
||||
LINE("evbsh3", "evbSH3")
|
||||
LINE("ews4800mips", "EWS4800MIPS")
|
||||
LINE("hp300", "HP300")
|
||||
LINE("hp700", "HP700")
|
||||
LINE("hpcarm", "HPCARM")
|
||||
LINE("hpcmips", "HPCMIPS")
|
||||
LINE("hpcsh", "HPCSH")
|
||||
LINE("hppa", "HPPA")
|
||||
LINE("hppa64", "HPPA64")
|
||||
LINE("ia64", "ia64")
|
||||
LINE("i386", "i386")
|
||||
LINE("ibmnws", "IBMNWS")
|
||||
LINE("iyonix", "Iyonix")
|
||||
LINE("landisk", "LANDISK")
|
||||
LINE("loongson", "Loongson")
|
||||
LINE("luna68k", "LUNA68K")
|
||||
LINE("luna88k", "LUNA88K")
|
||||
LINE("m68k", "m68k")
|
||||
LINE("mac68k", "Mac68k")
|
||||
LINE("macppc", "MacPPC")
|
||||
LINE("mips", "MIPS")
|
||||
LINE("mips64", "MIPS64")
|
||||
LINE("mipsco", "MIPSCo")
|
||||
LINE("mmeye", "mmEye")
|
||||
LINE("mvme68k", "MVME68k")
|
||||
LINE("mvme88k", "MVME88k")
|
||||
LINE("mvmeppc", "MVMEPPC")
|
||||
LINE("netwinder", "NetWinder")
|
||||
LINE("news68k", "NeWS68k")
|
||||
LINE("newsmips", "NeWSMIPS")
|
||||
LINE("next68k", "NeXT68k")
|
||||
LINE("octeon", "OCTEON")
|
||||
LINE("ofppc", "OFPPC")
|
||||
LINE("palm", "Palm")
|
||||
LINE("pc532", "PC532")
|
||||
LINE("playstation2", "PlayStation2")
|
||||
LINE("pmax", "PMAX")
|
||||
LINE("pmppc", "pmPPC")
|
||||
LINE("powerpc", "PowerPC")
|
||||
LINE("prep", "PReP")
|
||||
LINE("rs6000", "RS6000")
|
||||
LINE("sandpoint", "Sandpoint")
|
||||
LINE("sbmips", "SBMIPS")
|
||||
LINE("sgi", "SGI")
|
||||
LINE("sgimips", "SGIMIPS")
|
||||
LINE("sh3", "SH3")
|
||||
LINE("shark", "Shark")
|
||||
LINE("socppc", "SOCPPC")
|
||||
LINE("solbourne", "Solbourne")
|
||||
LINE("sparc", "SPARC")
|
||||
LINE("sparc64", "SPARC64")
|
||||
LINE("sun2", "Sun2")
|
||||
LINE("sun3", "Sun3")
|
||||
LINE("tahoe", "Tahoe")
|
||||
LINE("vax", "VAX")
|
||||
LINE("x68k", "X68k")
|
||||
LINE("x86", "x86")
|
||||
LINE("x86_64", "x86_64")
|
||||
LINE("xen", "Xen")
|
||||
LINE("zaurus", "Zaurus")
|
22
att.c
22
att.c
@ -1,4 +1,4 @@
|
||||
/* $Id: att.c,v 1.11 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/* $Id: att.c,v 1.13 2014/11/28 18:57:31 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,24 +14,36 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mdoc.h"
|
||||
#include "libmdoc.h"
|
||||
|
||||
#define LINE(x, y) \
|
||||
if (0 == strcmp(p, x)) return(y);
|
||||
if (0 == strcmp(p, x)) return(y)
|
||||
|
||||
|
||||
const char *
|
||||
mdoc_a2att(const char *p)
|
||||
{
|
||||
|
||||
#include "att.in"
|
||||
LINE("v1", "Version\\~1 AT&T UNIX");
|
||||
LINE("v2", "Version\\~2 AT&T UNIX");
|
||||
LINE("v3", "Version\\~3 AT&T UNIX");
|
||||
LINE("v4", "Version\\~4 AT&T UNIX");
|
||||
LINE("v5", "Version\\~5 AT&T UNIX");
|
||||
LINE("v6", "Version\\~6 AT&T UNIX");
|
||||
LINE("v7", "Version\\~7 AT&T UNIX");
|
||||
LINE("32v", "Version\\~32V AT&T UNIX");
|
||||
LINE("III", "AT&T System\\~III UNIX");
|
||||
LINE("V", "AT&T System\\~V UNIX");
|
||||
LINE("V.1", "AT&T System\\~V Release\\~1 UNIX");
|
||||
LINE("V.2", "AT&T System\\~V Release\\~2 UNIX");
|
||||
LINE("V.3", "AT&T System\\~V Release\\~3 UNIX");
|
||||
LINE("V.4", "AT&T System\\~V Release\\~4 UNIX");
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
40
att.in
40
att.in
@ -1,40 +0,0 @@
|
||||
/* $Id: att.in,v 1.8 2011/07/31 17:30:33 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 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 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 file defines the AT&T versions of the .At macro. This probably
|
||||
* isn't going to change. The right-hand side is the formatted string.
|
||||
*
|
||||
* Be sure to escape strings.
|
||||
* The non-breaking blanks prevent ending an output line right before
|
||||
* a number. Groff prevent line breaks at the same places.
|
||||
*/
|
||||
|
||||
LINE("v1", "Version\\~1 AT&T UNIX")
|
||||
LINE("v2", "Version\\~2 AT&T UNIX")
|
||||
LINE("v3", "Version\\~3 AT&T UNIX")
|
||||
LINE("v4", "Version\\~4 AT&T UNIX")
|
||||
LINE("v5", "Version\\~5 AT&T UNIX")
|
||||
LINE("v6", "Version\\~6 AT&T UNIX")
|
||||
LINE("v7", "Version\\~7 AT&T UNIX")
|
||||
LINE("32v", "Version\\~32V AT&T UNIX")
|
||||
LINE("III", "AT&T System\\~III UNIX")
|
||||
LINE("V", "AT&T System\\~V UNIX")
|
||||
LINE("V.1", "AT&T System\\~V Release\\~1 UNIX")
|
||||
LINE("V.2", "AT&T System\\~V Release\\~2 UNIX")
|
||||
LINE("V.3", "AT&T System\\~V Release\\~3 UNIX")
|
||||
LINE("V.4", "AT&T System\\~V Release\\~4 UNIX")
|
133
cgi.c
133
cgi.c
@ -1,4 +1,4 @@
|
||||
/* $Id: cgi.c,v 1.92 2014/08/05 15:29:30 schwarze Exp $ */
|
||||
/* $Id: cgi.c,v 1.102 2014/11/26 17:55:27 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@usta.de>
|
||||
@ -15,9 +15,10 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@ -91,14 +92,14 @@ static const char *const sec_names[] = {
|
||||
"All Sections",
|
||||
"1 - General Commands",
|
||||
"2 - System Calls",
|
||||
"3 - Subroutines",
|
||||
"3p - Perl Subroutines",
|
||||
"4 - Special Files",
|
||||
"3 - Library Functions",
|
||||
"3p - Perl Library",
|
||||
"4 - Device Drivers",
|
||||
"5 - File Formats",
|
||||
"6 - Games",
|
||||
"7 - Macros and Conventions",
|
||||
"8 - Maintenance Commands",
|
||||
"9 - Kernel Interface"
|
||||
"7 - Miscellaneous Information",
|
||||
"8 - System Manager\'s Manual",
|
||||
"9 - Kernel Developer\'s Manual"
|
||||
};
|
||||
static const int sec_MAX = sizeof(sec_names) / sizeof(char *);
|
||||
|
||||
@ -162,8 +163,7 @@ http_printquery(const struct req *req, const char *sep)
|
||||
printf("%sarch=", sep);
|
||||
http_print(req->q.arch);
|
||||
}
|
||||
if (NULL != req->q.manpath &&
|
||||
strcmp(req->q.manpath, req->p[0])) {
|
||||
if (strcmp(req->q.manpath, req->p[0])) {
|
||||
printf("%smanpath=", sep);
|
||||
http_print(req->q.manpath);
|
||||
}
|
||||
@ -297,11 +297,6 @@ http_parse(struct req *req, const char *qs)
|
||||
if (*qs != '\0')
|
||||
qs++;
|
||||
}
|
||||
|
||||
/* Fall back to the default manpath. */
|
||||
|
||||
if (req->q.manpath == NULL)
|
||||
req->q.manpath = mandoc_strdup(req->p[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -375,13 +370,10 @@ resp_begin_html(int code, const char *msg)
|
||||
|
||||
resp_begin_http(code, msg);
|
||||
|
||||
printf("<!DOCTYPE HTML PUBLIC "
|
||||
" \"-//W3C//DTD HTML 4.01//EN\""
|
||||
" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
|
||||
printf("<!DOCTYPE html>\n"
|
||||
"<HTML>\n"
|
||||
"<HEAD>\n"
|
||||
"<META HTTP-EQUIV=\"Content-Type\""
|
||||
" CONTENT=\"text/html; charset=utf-8\">\n"
|
||||
"<META CHARSET=\"UTF-8\" />\n"
|
||||
"<LINK REL=\"stylesheet\" HREF=\"%s/man-cgi.css\""
|
||||
" TYPE=\"text/css\" media=\"all\">\n"
|
||||
"<LINK REL=\"stylesheet\" HREF=\"%s/man.css\""
|
||||
@ -471,8 +463,7 @@ resp_searchform(const struct req *req)
|
||||
puts("<SELECT NAME=\"manpath\">");
|
||||
for (i = 0; i < (int)req->psz; i++) {
|
||||
printf("<OPTION ");
|
||||
if (NULL == req->q.manpath ? 0 == i :
|
||||
0 == strcmp(req->q.manpath, req->p[i]))
|
||||
if (strcmp(req->q.manpath, req->p[i]) == 0)
|
||||
printf("SELECTED=\"selected\" ");
|
||||
printf("VALUE=\"");
|
||||
html_print(req->p[i]);
|
||||
@ -826,6 +817,7 @@ static void
|
||||
format(const struct req *req, const char *file)
|
||||
{
|
||||
struct mparse *mp;
|
||||
struct mchars *mchars;
|
||||
struct mdoc *mdoc;
|
||||
struct man *man;
|
||||
void *vp;
|
||||
@ -839,8 +831,9 @@ format(const struct req *req, const char *file)
|
||||
return;
|
||||
}
|
||||
|
||||
mchars = mchars_alloc();
|
||||
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_FATAL, NULL,
|
||||
req->q.manpath);
|
||||
mchars, req->q.manpath);
|
||||
rc = mparse_readfd(mp, fd, file);
|
||||
close(fd);
|
||||
|
||||
@ -866,10 +859,11 @@ format(const struct req *req, const char *file)
|
||||
req->q.manpath, file);
|
||||
pg_error_internal();
|
||||
mparse_free(mp);
|
||||
mchars_free(mchars);
|
||||
return;
|
||||
}
|
||||
|
||||
vp = html_alloc(opts);
|
||||
vp = html_alloc(mchars, opts);
|
||||
|
||||
if (NULL != mdoc)
|
||||
html_mdoc(vp, mdoc);
|
||||
@ -878,6 +872,7 @@ format(const struct req *req, const char *file)
|
||||
|
||||
html_free(vp);
|
||||
mparse_free(mp);
|
||||
mchars_free(mchars);
|
||||
free(opts);
|
||||
}
|
||||
|
||||
@ -953,10 +948,10 @@ pg_search(const struct req *req)
|
||||
struct mansearch search;
|
||||
struct manpaths paths;
|
||||
struct manpage *res;
|
||||
char **cp;
|
||||
const char *ep, *start;
|
||||
char **argv;
|
||||
char *query, *rp, *wp;
|
||||
size_t ressz;
|
||||
int i, sz;
|
||||
int argc;
|
||||
|
||||
/*
|
||||
* Begin by chdir()ing into the root of the manpath.
|
||||
@ -973,54 +968,54 @@ pg_search(const struct req *req)
|
||||
|
||||
search.arch = req->q.arch;
|
||||
search.sec = req->q.sec;
|
||||
search.deftype = req->q.equal ? TYPE_Nm : (TYPE_Nm | TYPE_Nd);
|
||||
search.flags = req->q.equal ? MANSEARCH_MAN : 0;
|
||||
search.outkey = "Nd";
|
||||
search.argmode = req->q.equal ? ARG_NAME : ARG_EXPR;
|
||||
search.firstmatch = 1;
|
||||
|
||||
paths.sz = 1;
|
||||
paths.paths = mandoc_malloc(sizeof(char *));
|
||||
paths.paths[0] = mandoc_strdup(".");
|
||||
|
||||
/*
|
||||
* Poor man's tokenisation: just break apart by spaces.
|
||||
* Yes, this is half-ass. But it works for now.
|
||||
* Break apart at spaces with backslash-escaping.
|
||||
*/
|
||||
|
||||
ep = req->q.query;
|
||||
while (ep && isspace((unsigned char)*ep))
|
||||
ep++;
|
||||
|
||||
sz = 0;
|
||||
cp = NULL;
|
||||
while (ep && '\0' != *ep) {
|
||||
cp = mandoc_reallocarray(cp, sz + 1, sizeof(char *));
|
||||
start = ep;
|
||||
while ('\0' != *ep && ! isspace((unsigned char)*ep))
|
||||
ep++;
|
||||
cp[sz] = mandoc_malloc((ep - start) + 1);
|
||||
memcpy(cp[sz], start, ep - start);
|
||||
cp[sz++][ep - start] = '\0';
|
||||
while (isspace((unsigned char)*ep))
|
||||
ep++;
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
rp = query = mandoc_strdup(req->q.query);
|
||||
for (;;) {
|
||||
while (isspace((unsigned char)*rp))
|
||||
rp++;
|
||||
if (*rp == '\0')
|
||||
break;
|
||||
argv = mandoc_reallocarray(argv, argc + 1, sizeof(char *));
|
||||
argv[argc++] = wp = rp;
|
||||
for (;;) {
|
||||
if (isspace((unsigned char)*rp)) {
|
||||
*wp = '\0';
|
||||
rp++;
|
||||
break;
|
||||
}
|
||||
if (rp[0] == '\\' && rp[1] != '\0')
|
||||
rp++;
|
||||
if (wp != rp)
|
||||
*wp = *rp;
|
||||
if (*rp == '\0')
|
||||
break;
|
||||
wp++;
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == mansearch(&search, &paths, sz, cp, "Nd", &res, &ressz))
|
||||
if (0 == mansearch(&search, &paths, argc, argv, &res, &ressz))
|
||||
pg_noresult(req, "You entered an invalid query.");
|
||||
else if (0 == ressz)
|
||||
pg_noresult(req, "No results found.");
|
||||
else
|
||||
pg_searchres(req, res, ressz);
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
free(cp[i]);
|
||||
free(cp);
|
||||
|
||||
for (i = 0; i < (int)ressz; i++) {
|
||||
free(res[i].file);
|
||||
free(res[i].names);
|
||||
free(res[i].output);
|
||||
}
|
||||
free(res);
|
||||
|
||||
free(query);
|
||||
mansearch_free(res, ressz);
|
||||
free(paths.paths[0]);
|
||||
free(paths.paths);
|
||||
}
|
||||
@ -1029,10 +1024,23 @@ int
|
||||
main(void)
|
||||
{
|
||||
struct req req;
|
||||
struct itimerval itimer;
|
||||
const char *path;
|
||||
const char *querystring;
|
||||
int i;
|
||||
|
||||
/* Poor man's ReDoS mitigation. */
|
||||
|
||||
itimer.it_value.tv_sec = 2;
|
||||
itimer.it_value.tv_usec = 0;
|
||||
itimer.it_interval.tv_sec = 2;
|
||||
itimer.it_interval.tv_usec = 0;
|
||||
if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) {
|
||||
fprintf(stderr, "setitimer: %s\n", strerror(errno));
|
||||
pg_error_internal();
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Scan our run-time environment. */
|
||||
|
||||
if (NULL == (scriptname = getenv("SCRIPT_NAME")))
|
||||
@ -1066,8 +1074,9 @@ main(void)
|
||||
if (NULL != (querystring = getenv("QUERY_STRING")))
|
||||
http_parse(&req, querystring);
|
||||
|
||||
if ( ! (NULL == req.q.manpath ||
|
||||
validate_manpath(&req, req.q.manpath))) {
|
||||
if (req.q.manpath == NULL)
|
||||
req.q.manpath = mandoc_strdup(req.p[0]);
|
||||
else if ( ! validate_manpath(&req, req.q.manpath)) {
|
||||
pg_error_badrequest(
|
||||
"You specified an invalid manpath.");
|
||||
return(EXIT_FAILURE);
|
||||
|
53
chars.c
53
chars.c
@ -1,7 +1,7 @@
|
||||
/* $Id: chars.c,v 1.58 2014/07/23 15:00:08 schwarze Exp $ */
|
||||
/* $Id: chars.c,v 1.65 2014/10/29 00:17:43 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011, 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
|
||||
@ -15,9 +15,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@ -104,20 +104,16 @@ mchars_spec2cp(const struct mchars *arg, const char *p, size_t sz)
|
||||
const struct ln *ln;
|
||||
|
||||
ln = find(arg, p, sz);
|
||||
if (NULL == ln)
|
||||
return(-1);
|
||||
return(ln->unicode);
|
||||
return(ln != NULL ? ln->unicode : sz == 1 ? (unsigned char)*p : -1);
|
||||
}
|
||||
|
||||
char
|
||||
int
|
||||
mchars_num2char(const char *p, size_t sz)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((i = mandoc_strntoi(p, sz, 10)) < 0)
|
||||
return('\0');
|
||||
|
||||
return(i > 0 && i < 256 && isprint(i) ? i : '\0');
|
||||
i = mandoc_strntoi(p, sz, 10);
|
||||
return(i >= 0 && i < 256 ? i : -1);
|
||||
}
|
||||
|
||||
int
|
||||
@ -125,21 +121,9 @@ mchars_num2uc(const char *p, size_t sz)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((i = mandoc_strntoi(p, sz, 16)) < 0)
|
||||
return('\0');
|
||||
|
||||
/*
|
||||
* Security warning:
|
||||
* Never extend the range of accepted characters
|
||||
* to overlap with the ASCII range, 0x00-0x7F
|
||||
* without re-auditing the callers of this function.
|
||||
* Some callers might relay on the fact that we never
|
||||
* return ASCII characters for their escaping decisions.
|
||||
*
|
||||
* XXX Code is missing here to exclude bogus ranges.
|
||||
*/
|
||||
|
||||
return(i > 0x80 && i <= 0x10FFFF ? i : '\0');
|
||||
i = mandoc_strntoi(p, sz, 16);
|
||||
assert(i >= 0 && i <= 0x10FFFF);
|
||||
return(i);
|
||||
}
|
||||
|
||||
const char *
|
||||
@ -149,15 +133,26 @@ mchars_spec2str(const struct mchars *arg,
|
||||
const struct ln *ln;
|
||||
|
||||
ln = find(arg, p, sz);
|
||||
if (NULL == ln) {
|
||||
if (ln == NULL) {
|
||||
*rsz = 1;
|
||||
return(NULL);
|
||||
return(sz == 1 ? p : NULL);
|
||||
}
|
||||
|
||||
*rsz = strlen(ln->ascii);
|
||||
return(ln->ascii);
|
||||
}
|
||||
|
||||
const char *
|
||||
mchars_uc2str(int uc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < LINES_MAX; i++)
|
||||
if (uc == lines[i].unicode)
|
||||
return(lines[i].ascii);
|
||||
return("<?>");
|
||||
}
|
||||
|
||||
static const struct ln *
|
||||
find(const struct mchars *tab, const char *p, size_t sz)
|
||||
{
|
||||
|
230
chars.in
230
chars.in
@ -1,4 +1,4 @@
|
||||
/* $Id: chars.in,v 1.46 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/* $Id: chars.in,v 1.49 2014/11/06 22:28:36 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -57,7 +57,7 @@ CHAR("\'", "\'", 180)
|
||||
CHAR("aa", "\'", 180)
|
||||
CHAR("ga", "`", 96)
|
||||
CHAR("`", "`", 96)
|
||||
CHAR("ab", "`", 728)
|
||||
CHAR("ab", "'\b`", 728)
|
||||
CHAR("ac", ",", 184)
|
||||
CHAR("ad", "\"", 168)
|
||||
CHAR("ah", "v", 711)
|
||||
@ -86,8 +86,8 @@ CHAR("lB", "[", 91)
|
||||
CHAR("rB", "]", 93)
|
||||
CHAR("lC", "{", 123)
|
||||
CHAR("rC", "}", 125)
|
||||
CHAR("la", "<", 60)
|
||||
CHAR("ra", ">", 62)
|
||||
CHAR("la", "<", 10216)
|
||||
CHAR("ra", ">", 10217)
|
||||
CHAR("bv", "|", 9130)
|
||||
CHAR("braceex", "|", 9130)
|
||||
CHAR("bracketlefttp", "|", 9121)
|
||||
@ -100,7 +100,7 @@ CHAR("lt", ",-", 9127)
|
||||
CHAR("bracelefttp", ",-", 9127)
|
||||
CHAR("lk", "{", 9128)
|
||||
CHAR("braceleftmid", "{", 9128)
|
||||
CHAR("lb", ",-", 9129)
|
||||
CHAR("lb", "`-", 9129)
|
||||
CHAR("braceleftbp", "`-", 9129)
|
||||
CHAR("braceleftex", "|", 9130)
|
||||
CHAR("rt", "-.", 9131)
|
||||
@ -120,127 +120,127 @@ CHAR("parenrightex", "|", 9119)
|
||||
/* Greek characters. */
|
||||
CHAR("*A", "A", 913)
|
||||
CHAR("*B", "B", 914)
|
||||
CHAR("*G", "|", 915)
|
||||
CHAR("*D", "/\\", 916)
|
||||
CHAR("*G", "G", 915)
|
||||
CHAR("*D", "_\b/_\b\\", 916)
|
||||
CHAR("*E", "E", 917)
|
||||
CHAR("*Z", "Z", 918)
|
||||
CHAR("*Y", "H", 919)
|
||||
CHAR("*H", "O", 920)
|
||||
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", "H", 926)
|
||||
CHAR("*C", "_\bH", 926)
|
||||
CHAR("*O", "O", 927)
|
||||
CHAR("*P", "TT", 928)
|
||||
CHAR("*R", "P", 929)
|
||||
CHAR("*S", ">", 931)
|
||||
CHAR("*S", "S", 931)
|
||||
CHAR("*T", "T", 932)
|
||||
CHAR("*U", "Y", 933)
|
||||
CHAR("*F", "O_", 934)
|
||||
CHAR("*F", "I\bO", 934)
|
||||
CHAR("*X", "X", 935)
|
||||
CHAR("*Q", "Y", 936)
|
||||
CHAR("*W", "O", 937)
|
||||
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", "C", 950)
|
||||
CHAR("*z", ",\bC", 950)
|
||||
CHAR("*y", "n", 951)
|
||||
CHAR("*h", "0", 952)
|
||||
CHAR("*h", "-\b0", 952)
|
||||
CHAR("*i", "i", 953)
|
||||
CHAR("*k", "k", 954)
|
||||
CHAR("*l", "\\", 955)
|
||||
CHAR("*m", "u", 956)
|
||||
CHAR("*l", ">\b\\", 955)
|
||||
CHAR("*m", ",\bu", 956)
|
||||
CHAR("*n", "v", 957)
|
||||
CHAR("*c", "E", 958)
|
||||
CHAR("*c", ",\bE", 958)
|
||||
CHAR("*o", "o", 959)
|
||||
CHAR("*p", "n", 960)
|
||||
CHAR("*p", "-\bn", 960)
|
||||
CHAR("*r", "p", 961)
|
||||
CHAR("*s", "o", 963)
|
||||
CHAR("*t", "t", 964)
|
||||
CHAR("*s", "-\bo", 963)
|
||||
CHAR("*t", "~\bt", 964)
|
||||
CHAR("*u", "u", 965)
|
||||
CHAR("*f", "o", 981)
|
||||
CHAR("*f", "|\bo", 981)
|
||||
CHAR("*x", "x", 967)
|
||||
CHAR("*q", "u", 968)
|
||||
CHAR("*q", "|\bu", 968)
|
||||
CHAR("*w", "w", 969)
|
||||
CHAR("+h", "0", 977)
|
||||
CHAR("+f", "o", 966)
|
||||
CHAR("+p", "w", 982)
|
||||
CHAR("+h", "-\b0", 977)
|
||||
CHAR("+f", "|\bo", 966)
|
||||
CHAR("+p", "-\bw", 982)
|
||||
CHAR("+e", "e", 1013)
|
||||
CHAR("ts", "s", 962)
|
||||
|
||||
/* Accented letters. */
|
||||
CHAR(",C", "C", 199)
|
||||
CHAR(",c", "c", 231)
|
||||
CHAR("/L", "L", 321)
|
||||
CHAR("/O", "O", 216)
|
||||
CHAR("/l", "l", 322)
|
||||
CHAR("/o", "o", 248)
|
||||
CHAR("oA", "A", 197)
|
||||
CHAR("oa", "a", 229)
|
||||
CHAR(":A", "A", 196)
|
||||
CHAR(":E", "E", 203)
|
||||
CHAR(":I", "I", 207)
|
||||
CHAR(":O", "O", 214)
|
||||
CHAR(":U", "U", 220)
|
||||
CHAR(":a", "a", 228)
|
||||
CHAR(":e", "e", 235)
|
||||
CHAR(":i", "i", 239)
|
||||
CHAR(":o", "o", 246)
|
||||
CHAR(":u", "u", 252)
|
||||
CHAR(":y", "y", 255)
|
||||
CHAR("\'A", "A", 193)
|
||||
CHAR("\'E", "E", 201)
|
||||
CHAR("\'I", "I", 205)
|
||||
CHAR("\'O", "O", 211)
|
||||
CHAR("\'U", "U", 218)
|
||||
CHAR("\'a", "a", 225)
|
||||
CHAR("\'e", "e", 233)
|
||||
CHAR("\'i", "i", 237)
|
||||
CHAR("\'o", "o", 243)
|
||||
CHAR("\'u", "u", 250)
|
||||
CHAR("^A", "A", 194)
|
||||
CHAR("^E", "E", 202)
|
||||
CHAR("^I", "I", 206)
|
||||
CHAR("^O", "O", 212)
|
||||
CHAR("^U", "U", 219)
|
||||
CHAR("^a", "a", 226)
|
||||
CHAR("^e", "e", 234)
|
||||
CHAR("^i", "i", 238)
|
||||
CHAR("^o", "o", 244)
|
||||
CHAR("^u", "u", 251)
|
||||
CHAR("`A", "A", 192)
|
||||
CHAR("`E", "E", 200)
|
||||
CHAR("`I", "I", 204)
|
||||
CHAR("`O", "O", 210)
|
||||
CHAR("`U", "U", 217)
|
||||
CHAR("`a", "a", 224)
|
||||
CHAR("`e", "e", 232)
|
||||
CHAR("`i", "i", 236)
|
||||
CHAR("`o", "o", 242)
|
||||
CHAR("`u", "u", 249)
|
||||
CHAR("~A", "A", 195)
|
||||
CHAR("~N", "N", 209)
|
||||
CHAR("~O", "O", 213)
|
||||
CHAR("~a", "a", 227)
|
||||
CHAR("~n", "n", 241)
|
||||
CHAR("~o", "o", 245)
|
||||
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", "v", 8595)
|
||||
CHAR("ua", "^", 8593)
|
||||
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", "v", 8659)
|
||||
CHAR("uA", "^", 8657)
|
||||
CHAR("dA", "=\bv", 8659)
|
||||
CHAR("uA", "=\b^", 8657)
|
||||
CHAR("vA", "^=v", 8661)
|
||||
|
||||
/* Logic. */
|
||||
@ -249,7 +249,7 @@ CHAR("OR", "v", 8744)
|
||||
CHAR("no", "~", 172)
|
||||
CHAR("tno", "~", 172)
|
||||
CHAR("te", "3", 8707)
|
||||
CHAR("fa", "V", 8704)
|
||||
CHAR("fa", "-\bV", 8704)
|
||||
CHAR("st", "-)", 8715)
|
||||
CHAR("tf", ".:.", 8756)
|
||||
CHAR("3d", ".:.", 8756)
|
||||
@ -266,8 +266,8 @@ CHAR("pc", ".", 183)
|
||||
CHAR("md", ".", 8901)
|
||||
CHAR("mu", "x", 215)
|
||||
CHAR("tmu", "x", 215)
|
||||
CHAR("c*", "x", 8855)
|
||||
CHAR("c+", "+", 8853)
|
||||
CHAR("c*", "O\bx", 8855)
|
||||
CHAR("c+", "O\b+", 8853)
|
||||
CHAR("di", "-:-", 247)
|
||||
CHAR("tdi", "-:-", 247)
|
||||
CHAR("f/", "/", 8260)
|
||||
@ -293,14 +293,14 @@ CHAR("sb", "(=", 8834)
|
||||
CHAR("nb", "(!=", 8836)
|
||||
CHAR("sp", "=)", 8835)
|
||||
CHAR("nc", "!=)", 8837)
|
||||
CHAR("ib", "(=", 8838)
|
||||
CHAR("ip", "=)", 8839)
|
||||
CHAR("ib", "(=\b_", 8838)
|
||||
CHAR("ip", "=\b_)", 8839)
|
||||
CHAR("ca", "(^)", 8745)
|
||||
CHAR("cu", "U", 8746)
|
||||
CHAR("/_", "/_", 8736)
|
||||
CHAR("pp", "_|_", 8869)
|
||||
CHAR("is", "I", 8747)
|
||||
CHAR("integral", "I", 8747)
|
||||
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)
|
||||
@ -336,22 +336,22 @@ CHAR("IJ", "IJ", 306)
|
||||
CHAR("ij", "ij", 307)
|
||||
|
||||
/* Special letters. */
|
||||
CHAR("-D", "D", 208)
|
||||
CHAR("Sd", "o", 240)
|
||||
CHAR("TP", "b", 222)
|
||||
CHAR("Tp", "b", 254)
|
||||
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", "c", 162)
|
||||
CHAR("ct", "/\bc", 162)
|
||||
CHAR("Eu", "EUR", 8364)
|
||||
CHAR("eu", "EUR", 8364)
|
||||
CHAR("Ye", "Y", 165)
|
||||
CHAR("Po", "L", 163)
|
||||
CHAR("Cs", "x", 164)
|
||||
CHAR("Fn", "f", 402)
|
||||
CHAR("Ye", "=\bY", 165)
|
||||
CHAR("Po", "GBP", 163)
|
||||
CHAR("Cs", "o\bx", 164)
|
||||
CHAR("Fn", ",\bf", 402)
|
||||
|
||||
/* Lines. */
|
||||
CHAR("ba", "|", 124)
|
||||
@ -363,14 +363,14 @@ CHAR("sl", "/", 47)
|
||||
CHAR("rs", "\\", 92)
|
||||
|
||||
/* Text markers. */
|
||||
CHAR("ci", "o", 9675)
|
||||
CHAR("bu", "o", 8226)
|
||||
CHAR("dd", "=", 8225)
|
||||
CHAR("dg", "-", 8224)
|
||||
CHAR("ci", "O", 9675)
|
||||
CHAR("bu", "+\bo", 8226)
|
||||
CHAR("dd", "|\b=", 8225)
|
||||
CHAR("dg", "|\b-", 8224)
|
||||
CHAR("lz", "<>", 9674)
|
||||
CHAR("sq", "[]", 9633)
|
||||
CHAR("ps", "9|", 182)
|
||||
CHAR("sc", "S", 167)
|
||||
CHAR("ps", "<par>", 182)
|
||||
CHAR("sc", "<sec>", 167)
|
||||
CHAR("lh", "<=", 9756)
|
||||
CHAR("rh", "=>", 9758)
|
||||
CHAR("at", "@", 64)
|
||||
@ -385,18 +385,18 @@ CHAR("tm", "tm", 8482)
|
||||
|
||||
/* Punctuation. */
|
||||
CHAR(".", ".", 46)
|
||||
CHAR("r!", "i", 161)
|
||||
CHAR("r?", "c", 191)
|
||||
CHAR("r!", "!", 161)
|
||||
CHAR("r?", "?", 191)
|
||||
CHAR("em", "--", 8212)
|
||||
CHAR("en", "-", 8211)
|
||||
CHAR("hy", "-", 8208)
|
||||
CHAR("e", "\\", 92)
|
||||
|
||||
/* Units. */
|
||||
CHAR("de", "o", 176)
|
||||
CHAR("de", "<deg>", 176)
|
||||
CHAR("%0", "%o", 8240)
|
||||
CHAR("fm", "\'", 8242)
|
||||
CHAR("sd", "\"", 8243)
|
||||
CHAR("mc", "mu", 181)
|
||||
CHAR("sd", "''", 8243)
|
||||
CHAR("mc", ",\bu", 181)
|
||||
|
||||
CHAR_TBL_END
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FGETLN
|
||||
#if HAVE_FGETLN
|
||||
|
||||
int dummy;
|
||||
|
||||
@ -41,6 +39,9 @@ int dummy;
|
||||
* 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>
|
||||
|
826
compat_fts.c
Normal file
826
compat_fts.c
Normal file
@ -0,0 +1,826 @@
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_FTS
|
||||
|
||||
int dummy;
|
||||
|
||||
#else
|
||||
|
||||
/* $Id: compat_fts.c,v 1.4 2014/08/17 20:45:59 schwarze Exp $ */
|
||||
/* $OpenBSD: fts.c,v 1.46 2014/05/25 17:47:04 tedu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* 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 <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "compat_fts.h"
|
||||
|
||||
static FTSENT *fts_alloc(FTS *, const char *, size_t);
|
||||
static FTSENT *fts_build(FTS *);
|
||||
static void fts_lfree(FTSENT *);
|
||||
static void fts_load(FTS *, FTSENT *);
|
||||
static size_t fts_maxarglen(char * const *);
|
||||
static void fts_padjust(FTS *, FTSENT *);
|
||||
static int fts_palloc(FTS *, size_t);
|
||||
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 CLR(opt) (sp->fts_options &= ~(opt))
|
||||
#define ISSET(opt) (sp->fts_options & (opt))
|
||||
#define SET(opt) (sp->fts_options |= (opt))
|
||||
|
||||
#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
|
||||
|
||||
FTS *
|
||||
fts_open(char * const *argv, int options, void *dummy)
|
||||
{
|
||||
FTS *sp;
|
||||
FTSENT *p, *root;
|
||||
int nitems;
|
||||
FTSENT *parent, *tmp;
|
||||
size_t len;
|
||||
|
||||
/* Options check. */
|
||||
if (options & ~FTS_OPTIONMASK) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Allocate/initialize the stream */
|
||||
if ((sp = calloc(1, sizeof(FTS))) == NULL)
|
||||
return (NULL);
|
||||
sp->fts_options = options;
|
||||
|
||||
/*
|
||||
* Start out with 1K of path space, and enough, in any case,
|
||||
* to hold the user's paths.
|
||||
*/
|
||||
if (fts_palloc(sp, MAX(fts_maxarglen(argv), PATH_MAX)))
|
||||
goto mem1;
|
||||
|
||||
/* Allocate/initialize root's parent. */
|
||||
if ((parent = fts_alloc(sp, "", 0)) == NULL)
|
||||
goto mem2;
|
||||
parent->fts_level = FTS_ROOTPARENTLEVEL;
|
||||
|
||||
/* Allocate/initialize root(s). */
|
||||
for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
|
||||
/* Don't allow zero-length paths. */
|
||||
if ((len = strlen(*argv)) == 0) {
|
||||
errno = ENOENT;
|
||||
goto mem3;
|
||||
}
|
||||
|
||||
if ((p = fts_alloc(sp, *argv, len)) == NULL)
|
||||
goto mem3;
|
||||
p->fts_level = FTS_ROOTLEVEL;
|
||||
p->fts_parent = parent;
|
||||
p->fts_accpath = p->fts_name;
|
||||
p->fts_info = fts_stat(sp, p);
|
||||
|
||||
/* Command-line "." and ".." are real directories. */
|
||||
if (p->fts_info == FTS_DOT)
|
||||
p->fts_info = FTS_D;
|
||||
|
||||
p->fts_link = NULL;
|
||||
if (root == NULL)
|
||||
tmp = root = p;
|
||||
else {
|
||||
tmp->fts_link = p;
|
||||
tmp = p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a dummy pointer and make fts_read think that we've just
|
||||
* finished the node before the root(s); set p->fts_info to FTS_INIT
|
||||
* so that everything about the "current" node is ignored.
|
||||
*/
|
||||
if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
|
||||
goto mem3;
|
||||
sp->fts_cur->fts_link = root;
|
||||
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, 0)) < 0)
|
||||
SET(FTS_NOCHDIR);
|
||||
|
||||
if (nitems == 0)
|
||||
free(parent);
|
||||
|
||||
return (sp);
|
||||
|
||||
mem3: fts_lfree(root);
|
||||
free(parent);
|
||||
mem2: free(sp->fts_path);
|
||||
mem1: free(sp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
fts_load(FTS *sp, FTSENT *p)
|
||||
{
|
||||
size_t len;
|
||||
char *cp;
|
||||
|
||||
/*
|
||||
* Load the stream structure for the next traversal. Since we don't
|
||||
* actually enter the directory until after the preorder visit, set
|
||||
* the fts_accpath field specially so the chdir gets done to the right
|
||||
* place and the user can access the first node. From fts_open it's
|
||||
* known that the path will fit.
|
||||
*/
|
||||
len = p->fts_pathlen = p->fts_namelen;
|
||||
memmove(sp->fts_path, p->fts_name, len + 1);
|
||||
if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
|
||||
len = strlen(++cp);
|
||||
memmove(p->fts_name, cp, len + 1);
|
||||
p->fts_namelen = len;
|
||||
}
|
||||
p->fts_accpath = p->fts_path = sp->fts_path;
|
||||
sp->fts_dev = p->fts_dev;
|
||||
}
|
||||
|
||||
int
|
||||
fts_close(FTS *sp)
|
||||
{
|
||||
FTSENT *freep, *p;
|
||||
int rfd, error = 0;
|
||||
|
||||
/*
|
||||
* This still works if we haven't read anything -- the dummy structure
|
||||
* points to the root list, so we step through to the end of the root
|
||||
* list which has a valid parent pointer.
|
||||
*/
|
||||
if (sp->fts_cur) {
|
||||
for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
|
||||
freep = p;
|
||||
p = p->fts_link ? p->fts_link : p->fts_parent;
|
||||
free(freep);
|
||||
}
|
||||
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.*/
|
||||
if (sp->fts_child)
|
||||
fts_lfree(sp->fts_child);
|
||||
free(sp->fts_path);
|
||||
free(sp);
|
||||
|
||||
/* Return to original directory, checking for error. */
|
||||
if (rfd != -1) {
|
||||
int saved_errno;
|
||||
error = fchdir(rfd);
|
||||
saved_errno = errno;
|
||||
(void)close(rfd);
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case of "/" at the end of the path so that slashes aren't
|
||||
* appended which would cause paths to be written as "....//foo".
|
||||
*/
|
||||
#define NAPPEND(p) \
|
||||
(p->fts_path[p->fts_pathlen - 1] == '/' \
|
||||
? p->fts_pathlen - 1 : p->fts_pathlen)
|
||||
|
||||
FTSENT *
|
||||
fts_read(FTS *sp)
|
||||
{
|
||||
FTSENT *p, *tmp;
|
||||
int instr;
|
||||
char *t;
|
||||
|
||||
/* If finished or unrecoverable error, return NULL. */
|
||||
if (sp->fts_cur == NULL || ISSET(FTS_STOP))
|
||||
return (NULL);
|
||||
|
||||
/* Set current node pointer. */
|
||||
p = sp->fts_cur;
|
||||
|
||||
/* Save and zero out user instructions. */
|
||||
instr = p->fts_instr;
|
||||
p->fts_instr = FTS_NOINSTR;
|
||||
|
||||
/* Directory in pre-order. */
|
||||
if (p->fts_info == FTS_D) {
|
||||
/* If skipped or crossed mount point, do post-order visit. */
|
||||
if (instr == FTS_SKIP ||
|
||||
(ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
|
||||
if (sp->fts_child) {
|
||||
fts_lfree(sp->fts_child);
|
||||
sp->fts_child = NULL;
|
||||
}
|
||||
p->fts_info = FTS_DP;
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* FTS_STOP or the fts_info field of the node.
|
||||
*/
|
||||
if (sp->fts_child) {
|
||||
if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
|
||||
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) {
|
||||
if (ISSET(FTS_STOP))
|
||||
return (NULL);
|
||||
return (p);
|
||||
}
|
||||
p = sp->fts_child;
|
||||
sp->fts_child = NULL;
|
||||
goto name;
|
||||
}
|
||||
|
||||
/* Move to the next node on this level. */
|
||||
next: tmp = p;
|
||||
if ((p = p->fts_link)) {
|
||||
free(tmp);
|
||||
|
||||
/*
|
||||
* If reached the top, return to the original directory (or
|
||||
* the root of the tree), and load the paths for the next root.
|
||||
*/
|
||||
if (p->fts_level == FTS_ROOTLEVEL) {
|
||||
if (FCHDIR(sp, sp->fts_rfd)) {
|
||||
SET(FTS_STOP);
|
||||
return (NULL);
|
||||
}
|
||||
fts_load(sp, p);
|
||||
return (sp->fts_cur = p);
|
||||
}
|
||||
|
||||
/*
|
||||
* User may have called fts_set on the node. If skipped,
|
||||
* ignore. If followed, get a file descriptor so we can
|
||||
* get back if necessary.
|
||||
*/
|
||||
if (p->fts_instr == FTS_SKIP)
|
||||
goto next;
|
||||
|
||||
name: t = sp->fts_path + NAPPEND(p->fts_parent);
|
||||
*t++ = '/';
|
||||
memmove(t, p->fts_name, p->fts_namelen + 1);
|
||||
return (sp->fts_cur = p);
|
||||
}
|
||||
|
||||
/* Move up to the parent node. */
|
||||
p = tmp->fts_parent;
|
||||
free(tmp);
|
||||
|
||||
if (p->fts_level == FTS_ROOTPARENTLEVEL) {
|
||||
/*
|
||||
* Done; free everything up and set errno to 0 so the user
|
||||
* can distinguish between error and EOF.
|
||||
*/
|
||||
free(p);
|
||||
errno = 0;
|
||||
return (sp->fts_cur = NULL);
|
||||
}
|
||||
|
||||
/* NUL terminate the pathname. */
|
||||
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;
|
||||
return (sp->fts_cur = p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fts_set takes the stream as an argument although it's not used in this
|
||||
* implementation; it would be necessary if anyone wanted to add global
|
||||
* semantics to fts using fts_set. An error return is allowed for similar
|
||||
* reasons.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
fts_set(FTS *sp, FTSENT *p, int instr)
|
||||
{
|
||||
if (instr && instr != FTS_NOINSTR && instr != FTS_SKIP) {
|
||||
errno = EINVAL;
|
||||
return (1);
|
||||
}
|
||||
p->fts_instr = instr;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the tricky part -- do not casually change *anything* in here. The
|
||||
* idea is to build the linked list of entries that are used by fts_children
|
||||
* and fts_read. There are lots of special cases.
|
||||
*
|
||||
* The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
|
||||
* set and it's a physical walk (so that symbolic links can't be directories),
|
||||
* we can do things quickly. First, if it's a 4.4BSD file system, the type
|
||||
* of the file is in the directory entry. Otherwise, we assume that the number
|
||||
* of subdirectories in a node is equal to the number of links to the parent.
|
||||
* The former skips all stat calls. The latter skips stat calls in any leaf
|
||||
* directories and for any files after the subdirectories in the directory have
|
||||
* been found, cutting the stat calls by about 2/3.
|
||||
*/
|
||||
static FTSENT *
|
||||
fts_build(FTS *sp)
|
||||
{
|
||||
struct dirent *dp;
|
||||
FTSENT *p, *head;
|
||||
FTSENT *cur, *tail;
|
||||
DIR *dirp;
|
||||
void *oldaddr;
|
||||
size_t dlen, len, maxlen;
|
||||
int nitems, cderrno, descend, level, nlinks, nostat, doadjust;
|
||||
int saved_errno;
|
||||
char *cp;
|
||||
|
||||
/* Set current node pointer. */
|
||||
cur = sp->fts_cur;
|
||||
|
||||
/*
|
||||
* Open the directory for reading. If this fails, we're done.
|
||||
* If being called from fts_read, set the fts_info field.
|
||||
*/
|
||||
if ((dirp = opendir(cur->fts_accpath)) == NULL) {
|
||||
cur->fts_info = FTS_DNR;
|
||||
cur->fts_errno = errno;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nlinks is the number of possible entries of type directory in the
|
||||
* directory if we're cheating on stat calls, 0 if we're not doing
|
||||
* any stat calls at all, -1 if we're doing stats on everything.
|
||||
*/
|
||||
nlinks = -1;
|
||||
nostat = 0;
|
||||
|
||||
/*
|
||||
* 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)) {
|
||||
if (nlinks)
|
||||
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
|
||||
* current path -- the inner loop allocates more path as necessary.
|
||||
* We really wouldn't have to do the maxlen calculations here, we
|
||||
* could do them in fts_read before returning the path, but it's a
|
||||
* lot easier here since the length is part of the dirent structure.
|
||||
*
|
||||
* If not changing directories set a pointer so that can just append
|
||||
* each new name into the path.
|
||||
*/
|
||||
len = NAPPEND(cur);
|
||||
if (ISSET(FTS_NOCHDIR)) {
|
||||
cp = sp->fts_path + len;
|
||||
*cp++ = '/';
|
||||
}
|
||||
len++;
|
||||
maxlen = sp->fts_pathlen - len;
|
||||
|
||||
/*
|
||||
* fts_level is signed so we must prevent it from wrapping
|
||||
* around to FTS_ROOTLEVEL and FTS_ROOTPARENTLEVEL.
|
||||
*/
|
||||
level = cur->fts_level;
|
||||
if (level < FTS_MAXLEVEL)
|
||||
level++;
|
||||
|
||||
/* Read the directory, attaching each entry to the `link' pointer. */
|
||||
doadjust = 0;
|
||||
for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
|
||||
if (ISDOT(dp->d_name))
|
||||
continue;
|
||||
|
||||
#if HAVE_DIRENT_NAMLEN
|
||||
dlen = dp->d_namlen;
|
||||
#else
|
||||
dlen = strlen(dp->d_name);
|
||||
#endif
|
||||
|
||||
if (!(p = fts_alloc(sp, dp->d_name, dlen)))
|
||||
goto mem1;
|
||||
if (dlen >= maxlen) { /* include space for NUL */
|
||||
oldaddr = sp->fts_path;
|
||||
if (fts_palloc(sp, dlen + len + 1)) {
|
||||
/*
|
||||
* No more memory for path or structures. Save
|
||||
* errno, free up the current structure and the
|
||||
* structures already allocated.
|
||||
*/
|
||||
mem1: saved_errno = errno;
|
||||
if (p)
|
||||
free(p);
|
||||
fts_lfree(head);
|
||||
(void)closedir(dirp);
|
||||
cur->fts_info = FTS_ERR;
|
||||
SET(FTS_STOP);
|
||||
errno = saved_errno;
|
||||
return (NULL);
|
||||
}
|
||||
/* Did realloc() change the pointer? */
|
||||
if (oldaddr != sp->fts_path) {
|
||||
doadjust = 1;
|
||||
if (ISSET(FTS_NOCHDIR))
|
||||
cp = sp->fts_path + len;
|
||||
}
|
||||
maxlen = sp->fts_pathlen - len;
|
||||
}
|
||||
|
||||
p->fts_level = level;
|
||||
p->fts_parent = sp->fts_cur;
|
||||
p->fts_pathlen = len + dlen;
|
||||
if (p->fts_pathlen < len) {
|
||||
/*
|
||||
* If we wrap, free up the current structure and
|
||||
* the structures already allocated, then error
|
||||
* out with ENAMETOOLONG.
|
||||
*/
|
||||
free(p);
|
||||
fts_lfree(head);
|
||||
(void)closedir(dirp);
|
||||
cur->fts_info = FTS_ERR;
|
||||
SET(FTS_STOP);
|
||||
errno = ENAMETOOLONG;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (cderrno) {
|
||||
if (nlinks) {
|
||||
p->fts_info = FTS_NS;
|
||||
p->fts_errno = cderrno;
|
||||
} else
|
||||
p->fts_info = FTS_NSOK;
|
||||
p->fts_accpath = cur->fts_accpath;
|
||||
} else if (nlinks == 0
|
||||
#ifdef DT_DIR
|
||||
|| (nostat &&
|
||||
dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
|
||||
#endif
|
||||
) {
|
||||
p->fts_accpath =
|
||||
ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
|
||||
p->fts_info = FTS_NSOK;
|
||||
} else {
|
||||
/* 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);
|
||||
|
||||
/* Decrement link count if applicable. */
|
||||
if (nlinks > 0 && (p->fts_info == FTS_D ||
|
||||
p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
|
||||
--nlinks;
|
||||
}
|
||||
|
||||
/* We walk in directory order so "ls -f" doesn't get upset. */
|
||||
p->fts_link = NULL;
|
||||
if (head == NULL)
|
||||
head = tail = p;
|
||||
else {
|
||||
tail->fts_link = p;
|
||||
tail = p;
|
||||
}
|
||||
++nitems;
|
||||
}
|
||||
if (dirp)
|
||||
(void)closedir(dirp);
|
||||
|
||||
/*
|
||||
* If realloc() changed the address of the path, adjust the
|
||||
* addresses for the rest of the tree and the dir list.
|
||||
*/
|
||||
if (doadjust)
|
||||
fts_padjust(sp, head);
|
||||
|
||||
/*
|
||||
* If not changing directories, reset the path back to original
|
||||
* state.
|
||||
*/
|
||||
if (ISSET(FTS_NOCHDIR)) {
|
||||
if (len == sp->fts_pathlen || nitems == 0)
|
||||
--cp;
|
||||
*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 (!nitems) {
|
||||
cur->fts_info = FTS_DP;
|
||||
return (NULL);
|
||||
}
|
||||
return (head);
|
||||
}
|
||||
|
||||
static unsigned short
|
||||
fts_stat(FTS *sp, FTSENT *p)
|
||||
{
|
||||
FTSENT *t;
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
struct stat *sbp;
|
||||
|
||||
/* If user needs stat info, stat buffer already allocated. */
|
||||
sbp = p->fts_statp;
|
||||
|
||||
if (lstat(p->fts_accpath, sbp)) {
|
||||
p->fts_errno = errno;
|
||||
memset(sbp, 0, sizeof(struct stat));
|
||||
return (FTS_NS);
|
||||
}
|
||||
|
||||
if (S_ISDIR(sbp->st_mode)) {
|
||||
/*
|
||||
* Set the device/inode. Used to find cycles and check for
|
||||
* crossing mount points. Also remember the link count, used
|
||||
* in fts_build to limit the number of stat calls. It is
|
||||
* understood that these fields are only referenced if fts_info
|
||||
* is set to FTS_D.
|
||||
*/
|
||||
dev = p->fts_dev = sbp->st_dev;
|
||||
ino = p->fts_ino = sbp->st_ino;
|
||||
p->fts_nlink = sbp->st_nlink;
|
||||
|
||||
if (ISDOT(p->fts_name))
|
||||
return (FTS_DOT);
|
||||
|
||||
/*
|
||||
* Cycle detection is done by brute force when the directory
|
||||
* is first encountered. If the tree gets deep enough or the
|
||||
* number of symbolic links to directories is high enough,
|
||||
* something faster might be worthwhile.
|
||||
*/
|
||||
for (t = p->fts_parent;
|
||||
t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
|
||||
if (ino == t->fts_ino && dev == t->fts_dev) {
|
||||
p->fts_cycle = t;
|
||||
return (FTS_DC);
|
||||
}
|
||||
return (FTS_D);
|
||||
}
|
||||
if (S_ISLNK(sbp->st_mode))
|
||||
return (FTS_SL);
|
||||
if (S_ISREG(sbp->st_mode))
|
||||
return (FTS_F);
|
||||
return (FTS_DEFAULT);
|
||||
}
|
||||
|
||||
static FTSENT *
|
||||
fts_alloc(FTS *sp, const char *name, size_t namelen)
|
||||
{
|
||||
FTSENT *p;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(FTSENT) + namelen;
|
||||
if ((p = calloc(1, len)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
p->fts_path = sp->fts_path;
|
||||
p->fts_namelen = namelen;
|
||||
p->fts_instr = FTS_NOINSTR;
|
||||
p->fts_statp = malloc(sizeof(struct stat));
|
||||
if (p->fts_statp == NULL) {
|
||||
free(p);
|
||||
return (NULL);
|
||||
}
|
||||
memcpy(p->fts_name, name, namelen);
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void
|
||||
fts_lfree(FTSENT *head)
|
||||
{
|
||||
FTSENT *p;
|
||||
|
||||
/* Free a linked list of structures. */
|
||||
while ((p = head)) {
|
||||
head = head->fts_link;
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow essentially unlimited paths; find, rm, ls should all work on any tree.
|
||||
* Most systems will allow creation of paths much longer than PATH_MAX, even
|
||||
* though the kernel won't resolve them. Add the size (not just what's needed)
|
||||
* plus 256 bytes so don't realloc the path 2 bytes at a time.
|
||||
*/
|
||||
static int
|
||||
fts_palloc(FTS *sp, size_t more)
|
||||
{
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* Check for possible wraparound.
|
||||
*/
|
||||
more += 256;
|
||||
if (sp->fts_pathlen + more < sp->fts_pathlen) {
|
||||
if (sp->fts_path)
|
||||
free(sp->fts_path);
|
||||
sp->fts_path = NULL;
|
||||
errno = ENAMETOOLONG;
|
||||
return (1);
|
||||
}
|
||||
sp->fts_pathlen += more;
|
||||
p = realloc(sp->fts_path, sp->fts_pathlen);
|
||||
if (p == NULL) {
|
||||
if (sp->fts_path)
|
||||
free(sp->fts_path);
|
||||
sp->fts_path = NULL;
|
||||
return (1);
|
||||
}
|
||||
sp->fts_path = p;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* When the path is realloc'd, have to fix all of the pointers in structures
|
||||
* already returned.
|
||||
*/
|
||||
static void
|
||||
fts_padjust(FTS *sp, FTSENT *head)
|
||||
{
|
||||
FTSENT *p;
|
||||
char *addr = sp->fts_path;
|
||||
|
||||
#define ADJUST(p) { \
|
||||
if ((p)->fts_accpath != (p)->fts_name) { \
|
||||
(p)->fts_accpath = \
|
||||
(char *)addr + ((p)->fts_accpath - (p)->fts_path); \
|
||||
} \
|
||||
(p)->fts_path = addr; \
|
||||
}
|
||||
/* Adjust the current set of children. */
|
||||
for (p = sp->fts_child; p; p = p->fts_link)
|
||||
ADJUST(p);
|
||||
|
||||
/* Adjust the rest of the tree, including the current level. */
|
||||
for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
|
||||
ADJUST(p);
|
||||
p = p->fts_link ? p->fts_link : p->fts_parent;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
fts_maxarglen(char * const *argv)
|
||||
{
|
||||
size_t len, max;
|
||||
|
||||
for (max = 0; *argv; ++argv)
|
||||
if ((len = strlen(*argv)) > max)
|
||||
max = len;
|
||||
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, 0)) < 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
|
106
compat_fts.h
Normal file
106
compat_fts.h
Normal file
@ -0,0 +1,106 @@
|
||||
/* $OpenBSD: fts.h,v 1.14 2012/12/05 23:19:57 deraadt Exp $ */
|
||||
/* $NetBSD: fts.h,v 1.7 2012/03/01 16:18:51 hans Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 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.
|
||||
*
|
||||
* @(#)fts.h 8.3 (Berkeley) 8/14/94
|
||||
*/
|
||||
|
||||
#ifndef _FTS_H_
|
||||
#define _FTS_H_
|
||||
|
||||
typedef struct {
|
||||
struct _ftsent *fts_cur; /* current node */
|
||||
struct _ftsent *fts_child; /* linked list of children */
|
||||
dev_t fts_dev; /* starting device # */
|
||||
char *fts_path; /* path for this descent */
|
||||
int fts_rfd; /* fd for root */
|
||||
size_t fts_pathlen; /* sizeof(path) */
|
||||
|
||||
#define FTS_NOCHDIR 0x0004 /* don't change directories */
|
||||
#define FTS_PHYSICAL 0x0010 /* physical walk */
|
||||
#define FTS_XDEV 0x0040 /* don't cross devices */
|
||||
#define FTS_OPTIONMASK 0x00ff /* valid user option mask */
|
||||
|
||||
#define FTS_STOP 0x2000 /* (private) unrecoverable error */
|
||||
int fts_options; /* fts_open options, global flags */
|
||||
} FTS;
|
||||
|
||||
typedef struct _ftsent {
|
||||
struct _ftsent *fts_cycle; /* cycle node */
|
||||
struct _ftsent *fts_parent; /* parent directory */
|
||||
struct _ftsent *fts_link; /* next file in directory */
|
||||
char *fts_accpath; /* access path */
|
||||
char *fts_path; /* root path */
|
||||
int fts_errno; /* errno for this node */
|
||||
size_t fts_pathlen; /* strlen(fts_path) */
|
||||
size_t fts_namelen; /* strlen(fts_name) */
|
||||
|
||||
ino_t fts_ino; /* inode */
|
||||
dev_t fts_dev; /* device */
|
||||
nlink_t fts_nlink; /* link count */
|
||||
|
||||
#define FTS_ROOTPARENTLEVEL -1
|
||||
#define FTS_ROOTLEVEL 0
|
||||
#define FTS_MAXLEVEL 0x7fffffff
|
||||
int fts_level; /* depth (-1 to N) */
|
||||
|
||||
#define FTS_D 1 /* preorder directory */
|
||||
#define FTS_DC 2 /* directory that causes cycles */
|
||||
#define FTS_DEFAULT 3 /* none of the above */
|
||||
#define FTS_DNR 4 /* unreadable directory */
|
||||
#define FTS_DOT 5 /* dot or dot-dot */
|
||||
#define FTS_DP 6 /* postorder directory */
|
||||
#define FTS_ERR 7 /* error; errno is set */
|
||||
#define FTS_F 8 /* regular file */
|
||||
#define FTS_INIT 9 /* initialized only */
|
||||
#define FTS_NS 10 /* stat(2) failed */
|
||||
#define FTS_NSOK 11 /* no stat(2) requested */
|
||||
#define FTS_SL 12 /* symbolic link */
|
||||
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_SKIP 4 /* discard node */
|
||||
unsigned short fts_instr; /* fts_set() instructions */
|
||||
|
||||
struct stat *fts_statp; /* stat(2) information */
|
||||
char fts_name[1]; /* file name */
|
||||
} FTSENT;
|
||||
|
||||
__BEGIN_DECLS
|
||||
int fts_close(FTS *);
|
||||
FTS *fts_open(char * const *, int, void *);
|
||||
FTSENT *fts_read(FTS *);
|
||||
int fts_set(FTS *, FTSENT *, int);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_FTS_H_ */
|
@ -1,13 +1,12 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETSUBOPT
|
||||
#if HAVE_GETSUBOPT
|
||||
|
||||
int dummy;
|
||||
|
||||
#else
|
||||
|
||||
/* $Id: compat_getsubopt.c,v 1.5 2014/08/17 20:53:50 schwarze Exp $ */
|
||||
/* $OpenBSD: getsubopt.c,v 1.4 2005/08/08 08:05:36 espie Exp $ */
|
||||
|
||||
/*-
|
||||
@ -43,18 +42,11 @@ int dummy;
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* The SVID interface to getsubopt provides no way of figuring out which
|
||||
* part of the suboptions list wasn't matched. This makes error messages
|
||||
* tricky... The extern variable suboptarg is a pointer to the token
|
||||
* which didn't match.
|
||||
*/
|
||||
char *suboptarg;
|
||||
|
||||
int
|
||||
getsubopt(char **optionp, char * const *tokens, char **valuep)
|
||||
{
|
||||
int cnt;
|
||||
char *suboptarg;
|
||||
char *p;
|
||||
|
||||
suboptarg = *valuep = NULL;
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OHASH
|
||||
#if HAVE_OHASH
|
||||
|
||||
int dummy;
|
||||
|
||||
@ -25,6 +23,8 @@ int dummy;
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_REALLOCARRAY
|
||||
#if HAVE_REALLOCARRAY
|
||||
|
||||
int dummy;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SQLITE3_ERRSTR
|
||||
#if HAVE_SQLITE3_ERRSTR
|
||||
|
||||
int dummy;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRCASESTR
|
||||
#if HAVE_STRCASESTR
|
||||
|
||||
int dummy;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRLCAT
|
||||
#if HAVE_STRLCAT
|
||||
|
||||
int dummy;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRLCPY
|
||||
#if HAVE_STRLCPY
|
||||
|
||||
int dummy;
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRSEP
|
||||
#if HAVE_STRSEP
|
||||
|
||||
int dummy;
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
#if !defined(__BEGIN_DECLS)
|
||||
# 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
|
||||
|
||||
#ifndef HAVE_FGETLN
|
||||
extern char *fgetln(FILE *, size_t *);
|
||||
#endif
|
||||
#ifndef HAVE_GETSUBOPT
|
||||
extern int getsubopt(char **, char * const *, char **);
|
||||
extern char *suboptarg;
|
||||
#endif
|
||||
#ifndef HAVE_REALLOCARRAY
|
||||
extern void *reallocarray(void *, size_t, size_t);
|
||||
#endif
|
||||
#ifndef HAVE_SQLITE3_ERRSTR
|
||||
extern const char *sqlite3_errstr(int);
|
||||
#endif
|
||||
#ifndef HAVE_STRCASESTR
|
||||
extern char *strcasestr(const char *, const char *);
|
||||
#endif
|
||||
#ifndef HAVE_STRLCAT
|
||||
extern size_t strlcat(char *, const char *, size_t);
|
||||
#endif
|
||||
#ifndef HAVE_STRLCPY
|
||||
extern size_t strlcpy(char *, const char *, size_t);
|
||||
#endif
|
||||
#ifndef HAVE_STRSEP
|
||||
extern char *strsep(char **, const char *);
|
||||
#endif
|
||||
|
||||
#endif /* MANDOC_CONFIG_H */
|
@ -1,9 +0,0 @@
|
||||
#ifndef MANDOC_CONFIG_H
|
||||
#define MANDOC_CONFIG_H
|
||||
|
||||
#if defined(__linux__) || defined(__MINT__)
|
||||
# define _GNU_SOURCE /* getsubopt(), strcasestr(), strptime() */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
390
configure
vendored
390
configure
vendored
@ -14,36 +14,380 @@
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
echo "/* RUNNING ./CONFIGURE - SHOULD BE USED ONLY VIA MAKE, READ INSTALL */"
|
||||
|
||||
set -e
|
||||
exec > config.h 2> config.log
|
||||
|
||||
CFLAGS="${CFLAGS} -Wno-unused -Werror"
|
||||
[ -e config.log ] && mv config.log config.log.old
|
||||
[ -e config.h ] && mv config.h config.h.old
|
||||
|
||||
runtest() {
|
||||
echo ${CC} ${CFLAGS} ${3} -o test-${1} test-${1}.c 1>&2
|
||||
${CC} ${CFLAGS} ${3} -o "test-${1}" "test-${1}.c" 1>&2 || return 0
|
||||
"./test-${1}" && echo "#define HAVE_${2}" \
|
||||
|| echo FAILURE: test-${1} returned $? 1>&2
|
||||
rm "test-${1}"
|
||||
# Output file descriptor usage:
|
||||
# 1 (stdout): config.h, Makefile.local
|
||||
# 2 (stderr): original stderr, usually to the console
|
||||
# 3: config.log
|
||||
|
||||
exec 3> config.log
|
||||
echo "config.log: writing..."
|
||||
|
||||
# --- default settings -------------------------------------------------
|
||||
# Initialize all variables here,
|
||||
# such that nothing can leak in from the environment.
|
||||
|
||||
VERSION="1.13.1"
|
||||
echo "VERSION=\"${VERSION}\"" 1>&2
|
||||
echo "VERSION=\"${VERSION}\"" 1>&3
|
||||
|
||||
OSNAME=
|
||||
|
||||
CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make -f -`
|
||||
CFLAGS="-g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings"
|
||||
DBLIB=
|
||||
STATIC="-static"
|
||||
|
||||
BUILD_DB=1
|
||||
BUILD_CGI=0
|
||||
|
||||
HAVE_DIRENT_NAMLEN=
|
||||
HAVE_FGETLN=
|
||||
HAVE_FTS=
|
||||
HAVE_GETSUBOPT=
|
||||
HAVE_MMAP=
|
||||
HAVE_REALLOCARRAY=
|
||||
HAVE_STRCASESTR=
|
||||
HAVE_STRLCAT=
|
||||
HAVE_STRLCPY=
|
||||
HAVE_STRPTIME=
|
||||
HAVE_STRSEP=
|
||||
HAVE_WCHAR=
|
||||
|
||||
HAVE_SQLITE3=
|
||||
HAVE_SQLITE3_ERRSTR=
|
||||
HAVE_OHASH=
|
||||
HAVE_MANPATH=
|
||||
|
||||
PREFIX="/usr/local"
|
||||
BINDIR=
|
||||
SBINDIR=
|
||||
INCLUDEDIR=
|
||||
LIBDIR=
|
||||
MANDIR=
|
||||
EXAMPLEDIR=
|
||||
|
||||
WWWPREFIX="/var/www"
|
||||
HTDOCDIR=
|
||||
CGIBINDIR=
|
||||
|
||||
INSTALL="install"
|
||||
INSTALL_PROGRAM=
|
||||
INSTALL_LIB=
|
||||
INSTALL_MAN=
|
||||
INSTALL_DATA=
|
||||
|
||||
# --- manual settings from configure.local -----------------------------
|
||||
|
||||
if [ -e ./configure.local ]; then
|
||||
echo "configure.local: reading..." 1>&2
|
||||
echo "configure.local: reading..." 1>&3
|
||||
cat ./configure.local 1>&3
|
||||
. ./configure.local
|
||||
else
|
||||
echo "configure.local: no (fully automatic configuration)" 1>&2
|
||||
echo "configure.local: no (fully automatic configuration)" 1>&3
|
||||
fi
|
||||
echo 1>&3
|
||||
|
||||
# --- tests for config.h ----------------------------------------------
|
||||
|
||||
COMP="${CC} ${CFLAGS} -Wno-unused -Werror"
|
||||
|
||||
# Check whether this HAVE_ setting is manually overridden.
|
||||
# If yes, use the override, if no, do not decide anything yet.
|
||||
# Arguments: lower-case test name, manual value
|
||||
ismanual() {
|
||||
[ -z "${2}" ] && return 1
|
||||
echo "${1}: manual (${2})" 1>&2
|
||||
echo "${1}: manual (${2})" 1>&3
|
||||
echo 1>&3
|
||||
return 0
|
||||
}
|
||||
|
||||
cat config.h.pre
|
||||
# Run a single autoconfiguration test.
|
||||
# In case of success, enable the feature.
|
||||
# In case of failure, do not decide anything yet.
|
||||
# Arguments: lower-case test name, upper-case test name, additional CFLAGS
|
||||
singletest() {
|
||||
cat 1>&3 << __HEREDOC__
|
||||
${1}: testing...
|
||||
${COMP} ${3} -o test-${1} test-${1}.c
|
||||
__HEREDOC__
|
||||
|
||||
if ${COMP} ${3} -o "test-${1}" "test-${1}.c" 1>&3 2>&3; then
|
||||
echo "${1}: ${CC} succeeded" 1>&3
|
||||
else
|
||||
echo "${1}: ${CC} failed with $?" 1>&3
|
||||
echo 1>&3
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ./test-${1} 1>&3 2>&3; then
|
||||
echo "${1}: yes" 1>&2
|
||||
echo "${1}: yes" 1>&3
|
||||
echo 1>&3
|
||||
eval HAVE_${2}=1
|
||||
rm "test-${1}"
|
||||
return 0
|
||||
else
|
||||
echo "${1}: execution failed with $?" 1>&3
|
||||
echo 1>&3
|
||||
rm "test-${1}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run a complete autoconfiguration test, including the check for
|
||||
# a manual override and disabling the feature on failure.
|
||||
# Arguments: lower case name, upper case name, additional CFLAGS
|
||||
runtest() {
|
||||
eval _manual=\${HAVE_${2}}
|
||||
ismanual "${1}" "${_manual}" && return 0
|
||||
singletest "${1}" "${2}" "${3}" && return 0
|
||||
echo "${1}: no" 1>&2
|
||||
eval HAVE_${2}=0
|
||||
return 1
|
||||
}
|
||||
|
||||
# --- library functions ---
|
||||
runtest dirent-namlen DIRENT_NAMLEN || true
|
||||
runtest fgetln FGETLN || true
|
||||
runtest fts FTS || true
|
||||
runtest getsubopt GETSUBOPT || true
|
||||
runtest mmap MMAP || true
|
||||
runtest reallocarray REALLOCARRAY || true
|
||||
runtest strcasestr STRCASESTR || true
|
||||
runtest strlcat STRLCAT || true
|
||||
runtest strlcpy STRLCPY || true
|
||||
runtest strptime STRPTIME || true
|
||||
runtest strsep STRSEP || true
|
||||
runtest wchar WCHAR || true
|
||||
|
||||
# --- sqlite3 ---
|
||||
DETECTLIB=
|
||||
if [ ${BUILD_DB} -eq 0 ]; then
|
||||
echo "BUILD_DB=0 (manual)" 1>&2
|
||||
echo "BUILD_DB=0 (manual)" 1>&3
|
||||
echo 1>&3
|
||||
HAVE_SQLITE3=0
|
||||
elif ismanual sqlite3 "${HAVE_SQLITE3}"; then
|
||||
DETECTLIB="-lsqlite3"
|
||||
elif [ -n "${DBLIB}" ]; then
|
||||
runtest sqlite3 SQLITE3 "${DBLIB}" || true
|
||||
elif singletest sqlite3 SQLITE3 "-lsqlite3"; then
|
||||
DETECTLIB="-lsqlite3"
|
||||
elif runtest sqlite3 SQLITE3 \
|
||||
"-I/usr/local/include -L/usr/local/lib -lsqlite3"; then
|
||||
DETECTLIB="-L/usr/local/lib -lsqlite3"
|
||||
CFLAGS="${CFLAGS} -I/usr/local/include"
|
||||
fi
|
||||
if [ ${BUILD_DB} -gt 0 -a ${HAVE_SQLITE3} -eq 0 ]; then
|
||||
echo "BUILD_DB=0 (no sqlite3)" 1>&2
|
||||
echo "BUILD_DB=0 (no sqlite3)" 1>&3
|
||||
echo 1>&3
|
||||
BUILD_DB=0
|
||||
fi
|
||||
|
||||
# --- sqlite3_errstr ---
|
||||
if [ ${BUILD_DB} -eq 0 ]; then
|
||||
HAVE_SQLITE3_ERRSTR=1
|
||||
elif ismanual sqlite3_errstr "${HAVE_SQLITE3_ERRSTR}"; then
|
||||
:
|
||||
elif [ -n "${DBLIB}" ]; then
|
||||
runtest sqlite3_errstr SQLITE3_ERRSTR "${DBLIB}" || true
|
||||
else
|
||||
runtest sqlite3_errstr SQLITE3_ERRSTR "${DETECTLIB}" || true
|
||||
fi
|
||||
|
||||
# --- ohash ---
|
||||
if [ ${BUILD_DB} -eq 0 ]; then
|
||||
HAVE_OHASH=1
|
||||
elif ismanual ohash "${HAVE_OHASH}"; then
|
||||
:
|
||||
elif [ -n "${DBLIB}" ]; then
|
||||
runtest ohash OHASH "${DBLIB}" || true
|
||||
elif singletest ohash OHASH; then
|
||||
:
|
||||
elif runtest ohash OHASH "-lutil"; then
|
||||
DETECTLIB="${DETECTLIB} -lutil"
|
||||
fi
|
||||
|
||||
# --- DBLIB ---
|
||||
if [ ${BUILD_DB} -eq 0 ]; then
|
||||
DBLIB=
|
||||
elif [ -z "${DBLIB}" ]; then
|
||||
DBLIB="${DETECTLIB}"
|
||||
echo "DBLIB=\"${DBLIB}\"" 1>&2
|
||||
echo "DBLIB=\"${DBLIB}\"" 1>&3
|
||||
echo 1>&3
|
||||
fi
|
||||
|
||||
# --- manpath ---
|
||||
if [ ${BUILD_DB} -eq 0 ]; then
|
||||
HAVE_MANPATH=0
|
||||
elif ismanual manpath "${HAVE_MANPATH}"; then
|
||||
:
|
||||
elif manpath 1>&3 2>&3; then
|
||||
echo "manpath: yes" 1>&2
|
||||
echo "manpath: yes" 1>&3
|
||||
echo 1>&3
|
||||
HAVE_MANPATH=1
|
||||
else
|
||||
echo "manpath: no" 1>&2
|
||||
echo "manpath: no" 1>&3
|
||||
echo 1>&3
|
||||
HAVE_MANPATH=0
|
||||
fi
|
||||
|
||||
# --- write config.h ---
|
||||
|
||||
exec > config.h
|
||||
|
||||
cat << __HEREDOC__
|
||||
#ifndef MANDOC_CONFIG_H
|
||||
#define MANDOC_CONFIG_H
|
||||
|
||||
#if defined(__linux__) || defined(__MINT__)
|
||||
#define _GNU_SOURCE /* See test-*.c what needs this. */
|
||||
#endif
|
||||
|
||||
__HEREDOC__
|
||||
|
||||
[ ${HAVE_FGETLN} -eq 0 -o ${HAVE_REALLOCARRAY} -eq 0 -o \
|
||||
${HAVE_STRLCAT} -eq 0 -o ${HAVE_STRLCPY} -eq 0 ] \
|
||||
&& echo "#include <sys/types.h>"
|
||||
[ ${HAVE_FGETLN} -eq 0 ] && echo "#include <stdio.h>"
|
||||
|
||||
echo
|
||||
echo "#define VERSION \"${VERSION}\""
|
||||
runtest fgetln FGETLN
|
||||
runtest getsubopt GETSUBOPT
|
||||
runtest mmap MMAP
|
||||
runtest ohash OHASH "${DBLIB}"
|
||||
runtest reallocarray REALLOCARRAY
|
||||
runtest sqlite3_errstr SQLITE3_ERRSTR "${DBLIB}"
|
||||
runtest strcasestr STRCASESTR
|
||||
runtest strlcat STRLCAT
|
||||
runtest strlcpy STRLCPY
|
||||
runtest strptime STRPTIME
|
||||
runtest strsep STRSEP
|
||||
[ -n "${OSNAME}" ] && echo "#define OSNAME \"${OSNAME}\""
|
||||
|
||||
cat << __HEREDOC__
|
||||
#define HAVE_DIRENT_NAMLEN ${HAVE_DIRENT_NAMLEN}
|
||||
#define HAVE_FGETLN ${HAVE_FGETLN}
|
||||
#define HAVE_FTS ${HAVE_FTS}
|
||||
#define HAVE_GETSUBOPT ${HAVE_GETSUBOPT}
|
||||
#define HAVE_MMAP ${HAVE_MMAP}
|
||||
#define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY}
|
||||
#define HAVE_STRCASESTR ${HAVE_STRCASESTR}
|
||||
#define HAVE_STRLCAT ${HAVE_STRLCAT}
|
||||
#define HAVE_STRLCPY ${HAVE_STRLCPY}
|
||||
#define HAVE_STRPTIME ${HAVE_STRPTIME}
|
||||
#define HAVE_STRSEP ${HAVE_STRSEP}
|
||||
#define HAVE_WCHAR ${HAVE_WCHAR}
|
||||
#define HAVE_SQLITE3 ${HAVE_SQLITE3}
|
||||
#define HAVE_SQLITE3_ERRSTR ${HAVE_SQLITE3_ERRSTR}
|
||||
#define HAVE_OHASH ${HAVE_OHASH}
|
||||
#define HAVE_MANPATH ${HAVE_MANPATH}
|
||||
|
||||
#if !defined(__BEGIN_DECLS)
|
||||
# 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
|
||||
|
||||
__HEREDOC__
|
||||
|
||||
[ ${HAVE_FGETLN} -eq 0 ] && \
|
||||
echo "extern char *fgetln(FILE *, size_t *);"
|
||||
|
||||
[ ${HAVE_GETSUBOPT} -eq 0 ] && \
|
||||
echo "extern int getsubopt(char **, char * const *, char **);"
|
||||
|
||||
[ ${HAVE_REALLOCARRAY} -eq 0 ] && \
|
||||
echo "extern void *reallocarray(void *, size_t, size_t);"
|
||||
|
||||
[ ${BUILD_DB} -gt 0 -a ${HAVE_SQLITE3_ERRSTR} -eq 0 ] &&
|
||||
echo "extern const char *sqlite3_errstr(int);"
|
||||
|
||||
[ ${HAVE_STRCASESTR} -eq 0 ] && \
|
||||
echo "extern char *strcasestr(const char *, const char *);"
|
||||
|
||||
[ ${HAVE_STRLCAT} -eq 0 ] && \
|
||||
echo "extern size_t strlcat(char *, const char *, size_t);"
|
||||
|
||||
[ ${HAVE_STRLCPY} -eq 0 ] && \
|
||||
echo "extern size_t strlcpy(char *, const char *, size_t);"
|
||||
|
||||
[ ${HAVE_STRSEP} -eq 0 ] && \
|
||||
echo "extern char *strsep(char **, const char *);"
|
||||
|
||||
echo
|
||||
cat config.h.post
|
||||
echo "#endif /* MANDOC_CONFIG_H */"
|
||||
|
||||
echo "config.h: written" 1>&2
|
||||
echo "config.h: written" 1>&3
|
||||
|
||||
# --- tests for Makefile.local -----------------------------------------
|
||||
|
||||
exec > Makefile.local
|
||||
|
||||
[ -z "${BINDIR}" ] && BINDIR="${PREFIX}/bin"
|
||||
[ -z "${SBINDIR}" ] && SBINDIR="${PREFIX}/sbin"
|
||||
[ -z "${INCLUDEDIR}" ] && INCLUDEDIR="${PREFIX}/include/mandoc"
|
||||
[ -z "${LIBDIR}" ] && LIBDIR="${PREFIX}/lib/mandoc"
|
||||
[ -z "${MANDIR}" ] && MANDIR="${PREFIX}/man"
|
||||
[ -z "${EXAMPLEDIR}" ] && EXAMPLEDIR="${PREFIX}/share/examples/mandoc"
|
||||
|
||||
[ -z "${HTDOCDIR}" ] && HTDOCDIR="${WWWPREFIX}/htdocs"
|
||||
[ -z "${CGIBINDIR}" ] && CGIBINDIR="${WWWPREFIX}/cgi-bin"
|
||||
|
||||
[ -z "${INSTALL_PROGRAM}" ] && INSTALL_PROGRAM="${INSTALL} -m 0555"
|
||||
[ -z "${INSTALL_LIB}" ] && INSTALL_LIB="${INSTALL} -m 0444"
|
||||
[ -z "${INSTALL_MAN}" ] && INSTALL_MAN="${INSTALL} -m 0444"
|
||||
[ -z "${INSTALL_DATA}" ] && INSTALL_DATA="${INSTALL} -m 0444"
|
||||
|
||||
if [ ${BUILD_DB} -eq 0 -a ${BUILD_CGI} -gt 0 ]; then
|
||||
echo "BUILD_CGI=0 (no BUILD_DB)" 1>&2
|
||||
echo "BUILD_CGI=0 (no BUILD_DB)" 1>&3
|
||||
BUILD_CGI=0
|
||||
fi
|
||||
|
||||
BUILD_TARGETS="base-build"
|
||||
[ ${BUILD_DB} -gt 0 ] && BUILD_TARGETS="${BUILD_TARGETS} db-build"
|
||||
[ ${BUILD_CGI} -gt 0 ] && BUILD_TARGETS="${BUILD_TARGETS} cgi-build"
|
||||
|
||||
cat << __HEREDOC__
|
||||
VERSION = ${VERSION}
|
||||
BUILD_TARGETS = ${BUILD_TARGETS}
|
||||
CFLAGS = ${CFLAGS}
|
||||
DBLIB = ${DBLIB}
|
||||
STATIC = ${STATIC}
|
||||
PREFIX = ${PREFIX}
|
||||
BINDIR = ${BINDIR}
|
||||
SBINDIR = ${SBINDIR}
|
||||
INCLUDEDIR = ${INCLUDEDIR}
|
||||
LIBDIR = ${LIBDIR}
|
||||
MANDIR = ${MANDIR}
|
||||
EXAMPLEDIR = ${EXAMPLEDIR}
|
||||
WWWPREFIX = ${WWWPREFIX}
|
||||
HTDOCDIR = ${HTDOCDIR}
|
||||
CGIBINDIR = ${CGIBINDIR}
|
||||
INSTALL = ${INSTALL}
|
||||
INSTALL_PROGRAM = ${INSTALL_PROGRAM}
|
||||
INSTALL_LIB = ${INSTALL_LIB}
|
||||
INSTALL_MAN = ${INSTALL_MAN}
|
||||
INSTALL_DATA = ${INSTALL_DATA}
|
||||
__HEREDOC__
|
||||
|
||||
[ ${BUILD_DB} -gt 0 ] && \
|
||||
echo "MAN_OBJS = \$(MANDOC_OBJS) \$(APROPOS_OBJS)"
|
||||
|
||||
echo "Makefile.local: written" 1>&2
|
||||
echo "Makefile.local: written" 1>&3
|
||||
|
||||
exit 0
|
||||
|
189
configure.local.example
Normal file
189
configure.local.example
Normal file
@ -0,0 +1,189 @@
|
||||
# $Id: configure.local.example,v 1.1 2014/08/16 19:00:01 schwarze Exp $
|
||||
#
|
||||
# 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.
|
||||
|
||||
# For all settings documented in this file, there are reasonable
|
||||
# defaults and/or the ./configure script attempts autodetection.
|
||||
# Consequently, you only need to create a file ./configure.local
|
||||
# and put any of these settings into it if ./configure autodetection
|
||||
# fails or if you want to make different choices for other reasons.
|
||||
|
||||
# If autodetection fails, please tell <tech@mdocml.bsd.lv>.
|
||||
|
||||
# We recommend that you write ./configure.local from scratch and
|
||||
# only put the lines there you need. This file contains examples.
|
||||
# It is not intended as a template to be copied as a whole.
|
||||
|
||||
# --- user settings relevant for all builds ----------------------------
|
||||
|
||||
# For -Tutf8 and -Tlocale operation, mandoc(1) requires <locale.h>
|
||||
# providing setlocale(3) and <wchar.h> providing wcwidth(3) and
|
||||
# putwchar(3) with a wchar_t storing UCS-4 values. Theoretically,
|
||||
# the latter should be tested with the __STDC_ISO_10646__ feature
|
||||
# macro. In practice, many <wchar.h> headers do not provide that
|
||||
# macro even though they treat wchar_t as UCS-4. So the automatic
|
||||
# test only checks that wchar_t is wide enough, that is, at least
|
||||
# four bytes.
|
||||
|
||||
# The following line forces multi-byte support.
|
||||
# If your C library does not treat wchar_t as UCS-4, the UTF-8 output
|
||||
# mode will print garbage.
|
||||
|
||||
HAVE_WCHAR=1
|
||||
|
||||
# The following line disables multi-byte support.
|
||||
# The output modes -Tutf8 and -Tlocale will be the same as -Tascii.
|
||||
|
||||
HAVE_WCHAR=0
|
||||
|
||||
# In manual pages written in the mdoc(7) language, the operating system
|
||||
# version is displayed in the page footer line. If an operating system
|
||||
# is specified as an argument to the .Os macro, that is always used.
|
||||
# If the .Os macro has no argument and an operation system is specified
|
||||
# with the mandoc(1) -Ios= command line option, that is used.
|
||||
# Otherwise, the uname(3) library function is called at runtime to find
|
||||
# the name of the operating system.
|
||||
# If you do not want uname(3) to be called but instead want a fixed
|
||||
# string to be used, use the following line:
|
||||
|
||||
OSNAME="OpenBSD 5.5"
|
||||
|
||||
# The following installation directories are used.
|
||||
# It is possible to set only one or a few of these variables,
|
||||
# there is no need to copy the whole block.
|
||||
# Even if you set PREFIX to something else, the other variables
|
||||
# pick it up without copying them all over.
|
||||
|
||||
PREFIX="/usr/local"
|
||||
BINDIR="${PREFIX}/bin"
|
||||
SBINDIR="${PREFIX}/sbin"
|
||||
INCLUDEDIR="${PREFIX}/include/mandoc"
|
||||
LIBDIR="${PREFIX}/lib/mandoc"
|
||||
MANDIR="${PREFIX}/man"
|
||||
EXAMPLEDIR="${PREFIX}/share/examples/mandoc"
|
||||
|
||||
# It is possible to change the utility program used for installation
|
||||
# and the modes files are installed with. The defaults are:
|
||||
|
||||
INSTALL="install"
|
||||
INSTALL_PROGRAM="${INSTALL} -m 0555"
|
||||
INSTALL_LIB="${INSTALL} -m 0444"
|
||||
INSTALL_MAN="${INSTALL} -m 0444"
|
||||
INSTALL_DATA="${INSTALL} -m 0444"
|
||||
|
||||
# --- user settings related to database support ------------------------
|
||||
|
||||
# By default, building makewhatis(8) and apropos(1) is enabled.
|
||||
# To disable it, for example to avoid the dependency on SQLite3,
|
||||
# use the following line. It that case, the remaining settings
|
||||
# in this section are irrelevant.
|
||||
|
||||
BUILD_DB=0
|
||||
|
||||
# Two libraries are needed: SQLite3 and ohash(3).
|
||||
# Autoconfiguration tries the following linker flags to find them.
|
||||
# If none of these work, add a working DBLIB line to configure.local,
|
||||
# disabling autodetection for library directories.
|
||||
|
||||
DBLIB="-lsqlite3"
|
||||
DBLIB="-lsqlite3 -lutil"
|
||||
DBLIB="-L/usr/local/lib -lsqlite3"
|
||||
|
||||
# When library autodetection decides to use -L/usr/local/lib,
|
||||
# -I/usr/local/include is automatically added to CFLAGS.
|
||||
# If you manually set DBLIB to something including -L/usr/local/lib,
|
||||
# chances are you will also need the following line:
|
||||
|
||||
CFLAGS="${CFLAGS} -I/usr/local/include"
|
||||
|
||||
# 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).
|
||||
# The latter is used by OpenBSD and NetBSD, the former by most
|
||||
# other systems.
|
||||
|
||||
# Force usage of manpath(1).
|
||||
# If it is not installed or not operational,
|
||||
# makewhatis(8) and apropos(1) will not work properly.
|
||||
|
||||
HAVE_MANPATH=1
|
||||
|
||||
# Force usage of man.conf(5).
|
||||
# If it does not exist or contains no valid configuration,
|
||||
# makewhatis(8) and apropos(1) will not work properly.
|
||||
|
||||
HAVE_MANPATH=0
|
||||
|
||||
# --- user settings related man.cgi ------------------------------------
|
||||
|
||||
# By default, building man.cgi(8) is disabled. To enable it, copy
|
||||
# cgi.h.example to cgi.h, edit it, and use the following line.
|
||||
# Obviously, this requires that BUILD_DB is enabled, too.
|
||||
|
||||
BUILD_CGI=1
|
||||
|
||||
# The remaining settings in this section are only relevant if BUILD_CGI
|
||||
# is enabled. Otherwise, they have no effect either way.
|
||||
|
||||
# By default, man.cgi(8) is linked statically.
|
||||
# Some systems do not support static linking, for example Mac OS X.
|
||||
# In that case, use the following line:
|
||||
|
||||
STATIC=
|
||||
|
||||
# Some systems, for example Linux, require -pthread for static linking:
|
||||
|
||||
STATIC="-static -pthread"
|
||||
|
||||
# Some directories.
|
||||
# This works just like PREFIX, see above.
|
||||
|
||||
WWWPREFIX="/var/www"
|
||||
HTDOCDIR="${WWWPREFIX}/htdocs"
|
||||
CGIBINDIR="${WWWPREFIX}/cgi-bin"
|
||||
|
||||
# --- settings that rarely need to be touched --------------------------
|
||||
|
||||
# Do not set these variables unless you really need to.
|
||||
|
||||
# You can manually override the compiler to be used.
|
||||
# But that's rarely useful because ./configure asks your make(1)
|
||||
# which compiler to use, and that answer will hardly be wrong.
|
||||
|
||||
CC=cc
|
||||
|
||||
# The default compiler flags are:
|
||||
|
||||
CFLAGS="-g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings"
|
||||
|
||||
# In rare cases, it may be required to skip individual automatic tests.
|
||||
# Each of the following variables can be set to 0 (test will not be run
|
||||
# and will be regarded as failed) or 1 (test will not be run and will
|
||||
# be regarded as successful).
|
||||
|
||||
HAVE_DIRENT_NAMLEN=0
|
||||
HAVE_FGETLN=0
|
||||
HAVE_FTS=0
|
||||
HAVE_GETSUBOPT=0
|
||||
HAVE_MMAP=0
|
||||
HAVE_REALLOCARRAY=0
|
||||
HAVE_STRCASESTR=0
|
||||
HAVE_STRLCAT=0
|
||||
HAVE_STRLCPY=0
|
||||
HAVE_STRPTIME=0
|
||||
HAVE_STRSEP=0
|
||||
|
||||
HAVE_SQLITE3=0
|
||||
HAVE_SQLITE3_ERRSTR=0
|
||||
HAVE_OHASH=0
|
@ -1,4 +1,4 @@
|
||||
.\" $Id: demandoc.1,v 1.7 2013/07/13 19:41:16 schwarze Exp $
|
||||
.\" $Id: demandoc.1,v 1.8 2014/09/12 00:10:26 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\"
|
||||
@ -14,7 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: July 13 2013 $
|
||||
.Dd $Mdocdate: September 12 2014 $
|
||||
.Dt DEMANDOC 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -92,7 +92,7 @@ This is accomplished as follows (assuming British spelling):
|
||||
.Dl $ demandoc -w file.1 | spell -b
|
||||
.Sh SEE ALSO
|
||||
.Xr mandoc 1 ,
|
||||
.Xr man 7
|
||||
.Xr man 7 ,
|
||||
.Xr mdoc 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
|
11
demandoc.c
11
demandoc.c
@ -1,4 +1,4 @@
|
||||
/* $Id: demandoc.c,v 1.10 2014/03/19 22:20:43 schwarze Exp $ */
|
||||
/* $Id: demandoc.c,v 1.12 2014/10/28 17:36:19 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,9 +14,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@ -43,6 +43,7 @@ int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct mparse *mp;
|
||||
struct mchars *mchars;
|
||||
int ch, i, list;
|
||||
extern int optind;
|
||||
|
||||
@ -76,7 +77,8 @@ main(int argc, char *argv[])
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_FATAL, NULL, NULL);
|
||||
mchars = mchars_alloc();
|
||||
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_FATAL, NULL, mchars, NULL);
|
||||
assert(mp);
|
||||
|
||||
if (0 == argc)
|
||||
@ -88,6 +90,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
mparse_free(mp);
|
||||
mchars_free(mchars);
|
||||
return((int)MANDOCLEVEL_OK);
|
||||
}
|
||||
|
||||
|
250
eqn.7
250
eqn.7
@ -1,6 +1,7 @@
|
||||
.\" $Id: eqn.7,v 1.29 2013/07/13 19:41:16 schwarze Exp $
|
||||
.\" $Id: eqn.7,v 1.31 2014/10/12 11:57:38 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 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
|
||||
@ -14,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: July 13 2013 $
|
||||
.Dd $Mdocdate: October 12 2014 $
|
||||
.Dt EQN 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -37,7 +38,9 @@ This manual describes the
|
||||
.Nm
|
||||
language accepted by the
|
||||
.Xr mandoc 1
|
||||
utility, which corresponds to the Second Edition eqn specification (see
|
||||
utility, which corresponds to the Second Edition
|
||||
.Nm
|
||||
specification (see
|
||||
.Sx SEE ALSO
|
||||
for references).
|
||||
.Pp
|
||||
@ -77,6 +80,7 @@ box : text
|
||||
| \*qgsize\*q text
|
||||
| \*qset\*q text text
|
||||
| \*qundef\*q text
|
||||
| \*qsqrt\*q box
|
||||
| box pos box
|
||||
| box mark
|
||||
| \*qmatrix\*q \*q{\*q [col \*q{\*q list \*q}\*q ]*
|
||||
@ -98,8 +102,19 @@ space : [\e^~ \et]
|
||||
.Pp
|
||||
White-space consists of the space, tab, circumflex, and tilde
|
||||
characters.
|
||||
It is required to delimit tokens consisting of alphabetic characters
|
||||
and it is ignored at other places.
|
||||
Braces and quotes also delimit tokens.
|
||||
If within a quoted string, these space characters are retained.
|
||||
Quoted strings are also not scanned for replacement definitions.
|
||||
Quoted strings are also not scanned for keywords, glyph names,
|
||||
and expansion of definitions.
|
||||
To print a literal quote character, it can be prepended with a
|
||||
backslash or expressed with the \e(dq escape sequence.
|
||||
.Pp
|
||||
Subequations can be enclosed in braces to pass them as arguments
|
||||
to operation keywords, overriding standard operation precedence.
|
||||
Braces can be nested.
|
||||
To set a brace verbatim, it needs to be enclosed in quotes.
|
||||
.Pp
|
||||
The following text terms are translated into a rendered glyph, if
|
||||
available: alpha, beta, chi, delta, epsilon, eta, gamma, iota, kappa,
|
||||
@ -110,9 +125,12 @@ int (integral), sum (summation), grad (gradient), del (vector
|
||||
differential), times (multiply), cdot (centre-dot), nothing (zero-width
|
||||
space), approx (approximately equals), prime (prime), half (one-half),
|
||||
partial (partial differential), inf (infinity), >> (much greater), <<
|
||||
(much less), \-> (left arrow), <\- (right arrow), += (plus-minus), !=
|
||||
(much less), \-> (left arrow), <\- (right arrow), +\- (plus-minus), !=
|
||||
(not equal), == (equivalence), <= (less-than-equal), and >=
|
||||
(more-than-equal).
|
||||
The character escape sequences documented in
|
||||
.Xr mandoc_char 7
|
||||
can be used, too.
|
||||
.Pp
|
||||
The following control statements are available:
|
||||
.Bl -tag -width Ds
|
||||
@ -120,7 +138,7 @@ The following control statements are available:
|
||||
Replace all occurrences of a key with a value.
|
||||
Its syntax is as follows:
|
||||
.Pp
|
||||
.D1 define Ar key cvalc
|
||||
.D1 Cm define Ar key cvalc
|
||||
.Pp
|
||||
The first character of the value string,
|
||||
.Ar c ,
|
||||
@ -128,8 +146,8 @@ is used as the delimiter for the value
|
||||
.Ar val .
|
||||
This allows for arbitrary enclosure of terms (not just quotes), such as
|
||||
.Pp
|
||||
.D1 define Ar foo 'bar baz'
|
||||
.D1 define Ar foo cbar bazc
|
||||
.D1 Cm define Ar foo 'bar baz'
|
||||
.D1 Cm define Ar foo cbar bazc
|
||||
.Pp
|
||||
It is an error to have an empty
|
||||
.Ar key
|
||||
@ -164,24 +182,26 @@ is discarded.
|
||||
Set the default font of subsequent output.
|
||||
Its syntax is as follows:
|
||||
.Pp
|
||||
.D1 gfont Ar font
|
||||
.D1 Cm gfont Ar font
|
||||
.Pp
|
||||
In mandoc, this value is discarded.
|
||||
.It Cm gsize
|
||||
Set the default size of subsequent output.
|
||||
Its syntax is as follows:
|
||||
.Pp
|
||||
.D1 gsize Ar size
|
||||
.D1 Cm gsize Oo +|\- Oc Ns Ar size
|
||||
.Pp
|
||||
The
|
||||
.Ar size
|
||||
value should be an integer.
|
||||
If prepended by a sign,
|
||||
the font size is changed relative to the current size.
|
||||
.It Cm set
|
||||
Set an equation mode.
|
||||
In mandoc, both arguments are thrown away.
|
||||
Its syntax is as follows:
|
||||
.Pp
|
||||
.D1 set Ar key val
|
||||
.D1 Cm set Ar key val
|
||||
.Pp
|
||||
The
|
||||
.Ar key
|
||||
@ -193,7 +213,7 @@ This statement is a GNU extension.
|
||||
Unset a previously-defined key.
|
||||
Its syntax is as follows:
|
||||
.Pp
|
||||
.D1 define Ar key
|
||||
.D1 Cm define Ar key
|
||||
.Pp
|
||||
Once invoked, the definition for
|
||||
.Ar key
|
||||
@ -203,6 +223,207 @@ The
|
||||
is not expanded for replacements.
|
||||
This statement is a GNU extension.
|
||||
.El
|
||||
.Pp
|
||||
Operation keywords have the following semantics:
|
||||
.Bl -tag -width Ds
|
||||
.It Cm above
|
||||
See
|
||||
.Cm pile .
|
||||
.It Cm bar
|
||||
Draw a line over the preceding box.
|
||||
.It Cm bold
|
||||
Set the following box using bold font.
|
||||
.It Cm ccol
|
||||
Like
|
||||
.Cm cpile ,
|
||||
but for use in
|
||||
.Cm matrix .
|
||||
.It Cm cpile
|
||||
Like
|
||||
.Cm pile ,
|
||||
but with slightly increased vertical spacing.
|
||||
.It Cm dot
|
||||
Set a single dot over the preceding box.
|
||||
.It Cm dotdot
|
||||
Set two dots (dieresis) over the preceding box.
|
||||
.It Cm dyad
|
||||
Set a dyad symbol (left-right arrow) over the preceding box.
|
||||
.It Cm fat
|
||||
A synonym for
|
||||
.Cm bold .
|
||||
.It Cm font
|
||||
Set the second argument using the font specified by the first argument;
|
||||
currently not recognized by the
|
||||
.Xr mandoc 1
|
||||
.Nm
|
||||
parser.
|
||||
.It Cm from
|
||||
Set the following box below the preceding box,
|
||||
using a slightly smaller font.
|
||||
Used for sums, integrals, limits, and the like.
|
||||
.It Cm hat
|
||||
Set a hat (circumflex) over the preceding box.
|
||||
.It Cm italic
|
||||
Set the following box using italic font.
|
||||
.It Cm lcol
|
||||
Like
|
||||
.Cm lpile ,
|
||||
but for use in
|
||||
.Cm matrix .
|
||||
.It Cm left
|
||||
Set the first argument as a big left delimiter before the second argument.
|
||||
As an optional third argument,
|
||||
.Cm right
|
||||
can follow.
|
||||
In that case, the fourth argument is set as a big right delimiter after
|
||||
the second argument.
|
||||
.It Cm lpile
|
||||
Like
|
||||
.Cm cpile ,
|
||||
but subequations are left-justified.
|
||||
.It Cm matrix
|
||||
Followed by a list of columns enclosed in braces.
|
||||
All columns need to have the same number of subequations.
|
||||
The columns are set as a matrix.
|
||||
The difference compared to multiple subsequent
|
||||
.Cm pile
|
||||
operators is that in a
|
||||
.Cm matrix ,
|
||||
corresponding subequations in all columns line up horizontally,
|
||||
while each
|
||||
.Cm pile
|
||||
does vertical spacing independently.
|
||||
.It Cm over
|
||||
Set a fraction.
|
||||
The preceding box is the numerator, the following box is the denominator.
|
||||
.It Cm pile
|
||||
Followed by a list of subequations enclosed in braces,
|
||||
the subequations being separated by
|
||||
.Cm above
|
||||
keywords.
|
||||
Sets the subequations one above the other, each of them centered.
|
||||
Typically used to represent vectors in coordinate representation.
|
||||
.It Cm rcol
|
||||
Like
|
||||
.Cm rpile ,
|
||||
but for use in
|
||||
.Cm matrix .
|
||||
.It Cm right
|
||||
See
|
||||
.Cm left ;
|
||||
.Cm right
|
||||
cannot be used without
|
||||
.Cm left .
|
||||
To set a big right delimiter without a big left delimiter, the following
|
||||
construction can be used:
|
||||
.Pp
|
||||
.D1 Cm left No \(dq\(dq Ar box Cm right Ar delimiter
|
||||
.It Cm roman
|
||||
Set the following box using the default font.
|
||||
.It Cm rpile
|
||||
Like
|
||||
.Cm cpile ,
|
||||
but subequations are right-justified.
|
||||
.It Cm size
|
||||
Set the second argument with the font size specified by the first
|
||||
argument; currently ignored by
|
||||
.Xr mandoc 1 .
|
||||
By prepending a plus or minus sign to the first argument,
|
||||
the font size can be selected relative to the current size.
|
||||
.It Cm sqrt
|
||||
Set the square root of the following box.
|
||||
.It Cm sub
|
||||
Set the following box as a subscript to the preceding box.
|
||||
.It Cm sup
|
||||
Set the following box as a superscript to the preceding box.
|
||||
As a special case, if a
|
||||
.Cm sup
|
||||
clause immediately follows a
|
||||
.Cm sub
|
||||
clause as in
|
||||
.Pp
|
||||
.D1 Ar mainbox Cm sub Ar subbox Cm sup Ar supbox
|
||||
.Pp
|
||||
both are set with respect to the same
|
||||
.Ar mainbox ,
|
||||
that is,
|
||||
.Ar supbox
|
||||
is set above
|
||||
.Ar subbox .
|
||||
.It Cm tilde
|
||||
Set a tilde over the preceding box.
|
||||
.It Cm to
|
||||
Set the following box above the preceding box,
|
||||
using a slightly smaller font.
|
||||
Used for sums and integrals and the like.
|
||||
As a special case, if a
|
||||
.Cm to
|
||||
clause immediately follows a
|
||||
.Cm from
|
||||
clause as in
|
||||
.Pp
|
||||
.D1 Ar mainbox Cm from Ar frombox Cm to Ar tobox
|
||||
.Pp
|
||||
both are set below and above the same
|
||||
.Ar mainbox .
|
||||
.It Cm under
|
||||
Underline the preceding box.
|
||||
.It Cm vec
|
||||
Set a vector symbol (right arrow) over the preceding box.
|
||||
.El
|
||||
.Pp
|
||||
The binary operations
|
||||
.Cm from ,
|
||||
.Cm to ,
|
||||
.Cm sub ,
|
||||
and
|
||||
.Cm sup
|
||||
group to the right, that is,
|
||||
.Pp
|
||||
.D1 Ar mainbox Cm sup Ar supbox Cm sub Ar subbox
|
||||
.Pp
|
||||
is the same as
|
||||
.Pp
|
||||
.D1 Ar mainbox Cm sup Brq Ar supbox Cm sub Ar subbox
|
||||
.Pp
|
||||
and different from
|
||||
.Pp
|
||||
.D1 Bro Ar mainbox Cm sup Ar supbox Brc Cm sub Ar subbox .
|
||||
.Pp
|
||||
By contrast,
|
||||
.Cm over
|
||||
groups to the left.
|
||||
.Pp
|
||||
In the following list, earlier operations bind more tightly than
|
||||
later operations:
|
||||
.Pp
|
||||
.Bl -enum -compact
|
||||
.It
|
||||
.Cm dyad ,
|
||||
.Cm vec ,
|
||||
.Cm under ,
|
||||
.Cm bar ,
|
||||
.Cm tilde ,
|
||||
.Cm hat ,
|
||||
.Cm dot ,
|
||||
.Cm dotdot
|
||||
.It
|
||||
.Cm fat ,
|
||||
.Cm roman ,
|
||||
.Cm italic ,
|
||||
.Cm bold ,
|
||||
.Cm size
|
||||
.It
|
||||
.Cm sub ,
|
||||
.Cm sup
|
||||
.It
|
||||
.Cm sqrt
|
||||
.It
|
||||
.Cm over
|
||||
.It
|
||||
.Cm from ,
|
||||
.Cm to
|
||||
.El
|
||||
.Sh COMPATIBILITY
|
||||
This section documents the compatibility of mandoc
|
||||
.Nm
|
||||
@ -236,6 +457,11 @@ The
|
||||
and
|
||||
.Cm down Ar n
|
||||
commands are also ignored.
|
||||
.It
|
||||
Inline equations and the
|
||||
.Cm delim
|
||||
control statement are not yet implemented in
|
||||
.Xr mandoc 1 .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mandoc 1 ,
|
||||
|
189
eqn_html.c
189
eqn_html.c
@ -1,6 +1,6 @@
|
||||
/* $Id: eqn_html.c,v 1.3 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/* $Id: eqn_html.c,v 1.10 2014/10/12 19:31:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -14,9 +14,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -27,16 +27,153 @@
|
||||
#include "out.h"
|
||||
#include "html.h"
|
||||
|
||||
static const enum htmltag fontmap[EQNFONT__MAX] = {
|
||||
TAG_SPAN, /* EQNFONT_NONE */
|
||||
TAG_SPAN, /* EQNFONT_ROMAN */
|
||||
TAG_B, /* EQNFONT_BOLD */
|
||||
TAG_B, /* EQNFONT_FAT */
|
||||
TAG_I /* EQNFONT_ITALIC */
|
||||
};
|
||||
static void
|
||||
eqn_box(struct html *p, const struct eqn_box *bp)
|
||||
{
|
||||
struct tag *post, *row, *cell, *t;
|
||||
struct htmlpair tag[2];
|
||||
const struct eqn_box *child, *parent;
|
||||
size_t i, j, rows;
|
||||
|
||||
static void eqn_box(struct html *, const struct eqn_box *);
|
||||
if (NULL == bp)
|
||||
return;
|
||||
|
||||
post = NULL;
|
||||
|
||||
/*
|
||||
* Special handling for a matrix, which is presented to us in
|
||||
* column order, but must be printed in row-order.
|
||||
*/
|
||||
if (EQN_MATRIX == bp->type) {
|
||||
if (NULL == bp->first)
|
||||
goto out;
|
||||
if (EQN_LIST != bp->first->type) {
|
||||
eqn_box(p, bp->first);
|
||||
goto out;
|
||||
}
|
||||
if (NULL == (parent = bp->first->first))
|
||||
goto out;
|
||||
/* Estimate the number of rows, first. */
|
||||
if (NULL == (child = parent->first))
|
||||
goto out;
|
||||
for (rows = 0; NULL != child; rows++)
|
||||
child = child->next;
|
||||
/* Print row-by-row. */
|
||||
post = print_otag(p, TAG_MTABLE, 0, NULL);
|
||||
for (i = 0; i < rows; i++) {
|
||||
parent = bp->first->first;
|
||||
row = print_otag(p, TAG_MTR, 0, NULL);
|
||||
while (NULL != parent) {
|
||||
child = parent->first;
|
||||
for (j = 0; j < i; j++) {
|
||||
if (NULL == child)
|
||||
break;
|
||||
child = child->next;
|
||||
}
|
||||
cell = print_otag
|
||||
(p, TAG_MTD, 0, NULL);
|
||||
/*
|
||||
* If we have no data for this
|
||||
* particular cell, then print a
|
||||
* placeholder and continue--don't puke.
|
||||
*/
|
||||
if (NULL != child)
|
||||
eqn_box(p, child->first);
|
||||
print_tagq(p, cell);
|
||||
parent = parent->next;
|
||||
}
|
||||
print_tagq(p, row);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (bp->pos) {
|
||||
case (EQNPOS_TO):
|
||||
post = print_otag(p, TAG_MOVER, 0, NULL);
|
||||
break;
|
||||
case (EQNPOS_SUP):
|
||||
post = print_otag(p, TAG_MSUP, 0, NULL);
|
||||
break;
|
||||
case (EQNPOS_FROM):
|
||||
post = print_otag(p, TAG_MUNDER, 0, NULL);
|
||||
break;
|
||||
case (EQNPOS_SUB):
|
||||
post = print_otag(p, TAG_MSUB, 0, NULL);
|
||||
break;
|
||||
case (EQNPOS_OVER):
|
||||
post = print_otag(p, TAG_MFRAC, 0, NULL);
|
||||
break;
|
||||
case (EQNPOS_FROMTO):
|
||||
post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
|
||||
break;
|
||||
case (EQNPOS_SUBSUP):
|
||||
post = print_otag(p, TAG_MSUBSUP, 0, NULL);
|
||||
break;
|
||||
case (EQNPOS_SQRT):
|
||||
post = print_otag(p, TAG_MSQRT, 0, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bp->top || bp->bottom) {
|
||||
assert(NULL == post);
|
||||
if (bp->top && NULL == bp->bottom)
|
||||
post = print_otag(p, TAG_MOVER, 0, NULL);
|
||||
else if (bp->top && bp->bottom)
|
||||
post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
|
||||
else if (bp->bottom)
|
||||
post = print_otag(p, TAG_MUNDER, 0, NULL);
|
||||
}
|
||||
|
||||
if (EQN_PILE == bp->type) {
|
||||
assert(NULL == post);
|
||||
if (bp->first != NULL && bp->first->type == EQN_LIST)
|
||||
post = print_otag(p, TAG_MTABLE, 0, NULL);
|
||||
} else if (bp->type == EQN_LIST &&
|
||||
bp->parent && bp->parent->type == EQN_PILE) {
|
||||
assert(NULL == post);
|
||||
post = print_otag(p, TAG_MTR, 0, NULL);
|
||||
print_otag(p, TAG_MTD, 0, NULL);
|
||||
}
|
||||
|
||||
if (NULL != bp->text) {
|
||||
assert(NULL == post);
|
||||
post = print_otag(p, TAG_MI, 0, NULL);
|
||||
print_text(p, bp->text);
|
||||
} else if (NULL == post) {
|
||||
if (NULL != bp->left || NULL != bp->right) {
|
||||
PAIR_INIT(&tag[0], ATTR_OPEN,
|
||||
NULL == bp->left ? "" : bp->left);
|
||||
PAIR_INIT(&tag[1], ATTR_CLOSE,
|
||||
NULL == bp->right ? "" : bp->right);
|
||||
post = print_otag(p, TAG_MFENCED, 2, tag);
|
||||
}
|
||||
if (NULL == post)
|
||||
post = print_otag(p, TAG_MROW, 0, NULL);
|
||||
else
|
||||
print_otag(p, TAG_MROW, 0, NULL);
|
||||
}
|
||||
|
||||
eqn_box(p, bp->first);
|
||||
|
||||
out:
|
||||
if (NULL != bp->bottom) {
|
||||
t = print_otag(p, TAG_MO, 0, NULL);
|
||||
print_text(p, bp->bottom);
|
||||
print_tagq(p, t);
|
||||
}
|
||||
if (NULL != bp->top) {
|
||||
t = print_otag(p, TAG_MO, 0, NULL);
|
||||
print_text(p, bp->top);
|
||||
print_tagq(p, t);
|
||||
}
|
||||
|
||||
if (NULL != post)
|
||||
print_tagq(p, post);
|
||||
|
||||
eqn_box(p, bp->next);
|
||||
}
|
||||
|
||||
void
|
||||
print_eqn(struct html *p, const struct eqn *ep)
|
||||
@ -45,7 +182,7 @@ print_eqn(struct html *p, const struct eqn *ep)
|
||||
struct tag *t;
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "eqn");
|
||||
t = print_otag(p, TAG_SPAN, 1, &tag);
|
||||
t = print_otag(p, TAG_MATH, 1, &tag);
|
||||
|
||||
p->flags |= HTML_NONOSPACE;
|
||||
eqn_box(p, ep->root);
|
||||
@ -53,29 +190,3 @@ print_eqn(struct html *p, const struct eqn *ep)
|
||||
|
||||
print_tagq(p, t);
|
||||
}
|
||||
|
||||
static void
|
||||
eqn_box(struct html *p, const struct eqn_box *bp)
|
||||
{
|
||||
struct tag *t;
|
||||
|
||||
t = EQNFONT_NONE == bp->font ? NULL :
|
||||
print_otag(p, fontmap[(int)bp->font], 0, NULL);
|
||||
|
||||
if (bp->left)
|
||||
print_text(p, bp->left);
|
||||
|
||||
if (bp->text)
|
||||
print_text(p, bp->text);
|
||||
|
||||
if (bp->first)
|
||||
eqn_box(p, bp->first);
|
||||
|
||||
if (NULL != t)
|
||||
print_tagq(p, t);
|
||||
if (bp->right)
|
||||
print_text(p, bp->right);
|
||||
|
||||
if (bp->next)
|
||||
eqn_box(p, bp->next);
|
||||
}
|
||||
|
87
eqn_term.c
87
eqn_term.c
@ -1,6 +1,7 @@
|
||||
/* $Id: eqn_term.c,v 1.5 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/* $Id: eqn_term.c,v 1.7 2014/10/12 14:49:39 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
@ -14,9 +15,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -42,36 +43,82 @@ void
|
||||
term_eqn(struct termp *p, const struct eqn *ep)
|
||||
{
|
||||
|
||||
p->flags |= TERMP_NONOSPACE;
|
||||
eqn_box(p, ep->root);
|
||||
term_word(p, " ");
|
||||
p->flags &= ~TERMP_NONOSPACE;
|
||||
p->flags &= ~TERMP_NOSPACE;
|
||||
}
|
||||
|
||||
static void
|
||||
eqn_box(struct termp *p, const struct eqn_box *bp)
|
||||
{
|
||||
const struct eqn_box *child;
|
||||
|
||||
if (EQNFONT_NONE != bp->font)
|
||||
if (bp->type == EQN_LIST ||
|
||||
(bp->type == EQN_PILE && (bp->prev || bp->next)) ||
|
||||
(bp->parent != NULL && bp->parent->pos == EQNPOS_SQRT)) {
|
||||
if (bp->parent->type == EQN_SUBEXPR && bp->prev != NULL)
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, bp->left != NULL ? bp->left : "(");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
}
|
||||
if (bp->font != EQNFONT_NONE)
|
||||
term_fontpush(p, fontmap[(int)bp->font]);
|
||||
if (bp->left)
|
||||
term_word(p, bp->left);
|
||||
if (EQN_SUBEXPR == bp->type)
|
||||
term_word(p, "(");
|
||||
|
||||
if (bp->text)
|
||||
if (bp->text != NULL)
|
||||
term_word(p, bp->text);
|
||||
|
||||
if (bp->first)
|
||||
if (bp->pos == EQNPOS_SQRT) {
|
||||
term_word(p, "sqrt");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
eqn_box(p, bp->first);
|
||||
} else if (bp->type == EQN_SUBEXPR) {
|
||||
child = bp->first;
|
||||
eqn_box(p, child);
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, bp->pos == EQNPOS_OVER ? "/" :
|
||||
(bp->pos == EQNPOS_SUP ||
|
||||
bp->pos == EQNPOS_TO) ? "^" : "_");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
child = child->next;
|
||||
eqn_box(p, child);
|
||||
if (bp->pos == EQNPOS_FROMTO ||
|
||||
bp->pos == EQNPOS_SUBSUP) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, "^");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
child = child->next;
|
||||
eqn_box(p, child);
|
||||
}
|
||||
} else {
|
||||
child = bp->first;
|
||||
if (bp->type == EQN_MATRIX && child->type == EQN_LIST)
|
||||
child = child->first;
|
||||
while (child != NULL) {
|
||||
eqn_box(p,
|
||||
bp->type == EQN_PILE &&
|
||||
child->type == EQN_LIST &&
|
||||
child->args == 1 ?
|
||||
child->first : child);
|
||||
child = child->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (EQN_SUBEXPR == bp->type)
|
||||
term_word(p, ")");
|
||||
if (bp->right)
|
||||
term_word(p, bp->right);
|
||||
if (EQNFONT_NONE != bp->font)
|
||||
if (bp->font != EQNFONT_NONE)
|
||||
term_fontpop(p);
|
||||
if (bp->type == EQN_LIST ||
|
||||
(bp->type == EQN_PILE && (bp->prev || bp->next)) ||
|
||||
(bp->parent != NULL && bp->parent->pos == EQNPOS_SQRT)) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, bp->right != NULL ? bp->right : ")");
|
||||
if (bp->parent->type == EQN_SUBEXPR && bp->next != NULL)
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
}
|
||||
|
||||
if (bp->next)
|
||||
eqn_box(p, bp->next);
|
||||
if (bp->top != NULL) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, bp->top);
|
||||
}
|
||||
if (bp->bottom != NULL) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, "_");
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: example.style.css,v 1.49 2011/12/15 12:18:57 kristaps Exp $ */
|
||||
/* $Id: example.style.css,v 1.53 2014/09/27 11:16:24 kristaps Exp $ */
|
||||
/*
|
||||
* This is an example style-sheet provided for mandoc(1) and the -Thtml
|
||||
* or -Txhtml output mode.
|
||||
@ -20,11 +20,11 @@ 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 td.foot-os { width: 50%; } /* 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 td.head-vol { width: 80%; } /* Document header: volume. */
|
||||
div.mandoc td.head-rtitle { width: 10%; } /* Document header: right-title. */
|
||||
div.mandoc .display { } /* All Bd, D1, Dl. */
|
||||
div.mandoc .list { } /* All Bl. */
|
||||
div.mandoc i { } /* Italic: BI, IB, I, (implicit). */
|
||||
@ -108,3 +108,4 @@ 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; }
|
||||
|
159
html.c
159
html.c
@ -1,6 +1,6 @@
|
||||
/* $Id: html.c,v 1.159 2014/07/23 15:00:08 schwarze Exp $ */
|
||||
/* $Id: html.c,v 1.181 2014/10/29 00:17:43 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -70,17 +68,31 @@ static const struct htmldata htmltags[TAG_MAX] = {
|
||||
{"dt", HTML_CLRLINE}, /* TAG_DT */
|
||||
{"dd", HTML_CLRLINE}, /* TAG_DD */
|
||||
{"blockquote", HTML_CLRLINE}, /* TAG_BLOCKQUOTE */
|
||||
{"p", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_P */
|
||||
{"pre", HTML_CLRLINE }, /* TAG_PRE */
|
||||
{"b", 0 }, /* TAG_B */
|
||||
{"i", 0 }, /* TAG_I */
|
||||
{"code", 0 }, /* TAG_CODE */
|
||||
{"small", 0 }, /* TAG_SMALL */
|
||||
{"style", HTML_CLRLINE}, /* TAG_STYLE */
|
||||
{"math", HTML_CLRLINE}, /* TAG_MATH */
|
||||
{"mrow", 0}, /* TAG_MROW */
|
||||
{"mi", 0}, /* TAG_MI */
|
||||
{"mo", 0}, /* TAG_MO */
|
||||
{"msup", 0}, /* TAG_MSUP */
|
||||
{"msub", 0}, /* TAG_MSUB */
|
||||
{"msubsup", 0}, /* TAG_MSUBSUP */
|
||||
{"mfrac", 0}, /* TAG_MFRAC */
|
||||
{"msqrt", 0}, /* TAG_MSQRT */
|
||||
{"mfenced", 0}, /* TAG_MFENCED */
|
||||
{"mtable", 0}, /* TAG_MTABLE */
|
||||
{"mtr", 0}, /* TAG_MTR */
|
||||
{"mtd", 0}, /* TAG_MTD */
|
||||
{"munderover", 0}, /* TAG_MUNDEROVER */
|
||||
{"munder", 0}, /* TAG_MUNDER*/
|
||||
{"mover", 0}, /* TAG_MOVER*/
|
||||
};
|
||||
|
||||
static const char *const htmlattrs[ATTR_MAX] = {
|
||||
"http-equiv", /* ATTR_HTTPEQUIV */
|
||||
"content", /* ATTR_CONTENT */
|
||||
"name", /* ATTR_NAME */
|
||||
"rel", /* ATTR_REL */
|
||||
"href", /* ATTR_HREF */
|
||||
@ -88,11 +100,12 @@ static const char *const htmlattrs[ATTR_MAX] = {
|
||||
"media", /* ATTR_MEDIA */
|
||||
"class", /* ATTR_CLASS */
|
||||
"style", /* ATTR_STYLE */
|
||||
"width", /* ATTR_WIDTH */
|
||||
"id", /* ATTR_ID */
|
||||
"summary", /* ATTR_SUMMARY */
|
||||
"align", /* ATTR_ALIGN */
|
||||
"colspan", /* ATTR_COLSPAN */
|
||||
"charset", /* ATTR_CHARSET */
|
||||
"open", /* ATTR_OPEN */
|
||||
"close", /* ATTR_CLOSE */
|
||||
"mathvariant", /* ATTR_MATHVARIANT */
|
||||
};
|
||||
|
||||
static const char *const roffscales[SCALE_MAX] = {
|
||||
@ -114,11 +127,10 @@ static int print_escape(char);
|
||||
static int print_encode(struct html *, const char *, int);
|
||||
static void print_metaf(struct html *, enum mandoc_esc);
|
||||
static void print_attr(struct html *, const char *, const char *);
|
||||
static void *ml_alloc(char *, enum htmltype);
|
||||
|
||||
|
||||
static void *
|
||||
ml_alloc(char *outopts, enum htmltype type)
|
||||
void *
|
||||
html_alloc(const struct mchars *mchars, char *outopts)
|
||||
{
|
||||
struct html *h;
|
||||
const char *toks[5];
|
||||
@ -132,9 +144,8 @@ ml_alloc(char *outopts, enum htmltype type)
|
||||
|
||||
h = mandoc_calloc(1, sizeof(struct html));
|
||||
|
||||
h->type = type;
|
||||
h->tags.head = NULL;
|
||||
h->symtab = mchars_alloc();
|
||||
h->symtab = mchars;
|
||||
|
||||
while (outopts && *outopts)
|
||||
switch (getsubopt(&outopts, UNCONST(toks), &v)) {
|
||||
@ -157,20 +168,6 @@ ml_alloc(char *outopts, enum htmltype type)
|
||||
return(h);
|
||||
}
|
||||
|
||||
void *
|
||||
html_alloc(char *outopts)
|
||||
{
|
||||
|
||||
return(ml_alloc(outopts, HTML_HTML_4_01_STRICT));
|
||||
}
|
||||
|
||||
void *
|
||||
xhtml_alloc(char *outopts)
|
||||
{
|
||||
|
||||
return(ml_alloc(outopts, HTML_XHTML_1_0_STRICT));
|
||||
}
|
||||
|
||||
void
|
||||
html_free(void *p)
|
||||
{
|
||||
@ -184,9 +181,6 @@ html_free(void *p)
|
||||
free(tag);
|
||||
}
|
||||
|
||||
if (h->symtab)
|
||||
mchars_free(h->symtab);
|
||||
|
||||
free(h);
|
||||
}
|
||||
|
||||
@ -194,18 +188,23 @@ void
|
||||
print_gen_head(struct html *h)
|
||||
{
|
||||
struct htmlpair tag[4];
|
||||
struct tag *t;
|
||||
|
||||
tag[0].key = ATTR_HTTPEQUIV;
|
||||
tag[0].val = "Content-Type";
|
||||
tag[1].key = ATTR_CONTENT;
|
||||
tag[1].val = "text/html; charset=utf-8";
|
||||
print_otag(h, TAG_META, 2, tag);
|
||||
tag[0].key = ATTR_CHARSET;
|
||||
tag[0].val = "utf-8";
|
||||
print_otag(h, TAG_META, 1, tag);
|
||||
|
||||
tag[0].key = ATTR_NAME;
|
||||
tag[0].val = "resource-type";
|
||||
tag[1].key = ATTR_CONTENT;
|
||||
tag[1].val = "document";
|
||||
print_otag(h, TAG_META, 2, tag);
|
||||
/*
|
||||
* Print a default style-sheet.
|
||||
*/
|
||||
t = print_otag(h, TAG_STYLE, 0, NULL);
|
||||
print_text(h, "table.head, table.foot { width: 100%; }\n"
|
||||
"td.head-rtitle, td.foot-os { text-align: right; }\n"
|
||||
"td.head-vol { text-align: center; }\n"
|
||||
"table.foot td { width: 50%; }\n"
|
||||
"table.head td { width: 33%; }\n"
|
||||
"div.spacer { margin: 1em 0; }\n");
|
||||
print_tagq(h, t);
|
||||
|
||||
if (h->style) {
|
||||
tag[0].key = ATTR_REL;
|
||||
@ -420,29 +419,31 @@ print_encode(struct html *h, const char *p, int norecurse)
|
||||
case ESCAPE_UNICODE:
|
||||
/* Skip past "u" header. */
|
||||
c = mchars_num2uc(seq + 1, len - 1);
|
||||
if ('\0' != c)
|
||||
printf("&#x%x;", c);
|
||||
break;
|
||||
case ESCAPE_NUMBERED:
|
||||
c = mchars_num2char(seq, len);
|
||||
if ( ! ('\0' == c || print_escape(c)))
|
||||
putchar(c);
|
||||
if (c < 0)
|
||||
continue;
|
||||
break;
|
||||
case ESCAPE_SPECIAL:
|
||||
c = mchars_spec2cp(h->symtab, seq, len);
|
||||
if (c > 0)
|
||||
printf("&#%d;", c);
|
||||
else if (-1 == c && 1 == len &&
|
||||
!print_escape(*seq))
|
||||
putchar((int)*seq);
|
||||
if (c <= 0)
|
||||
continue;
|
||||
break;
|
||||
case ESCAPE_NOSPACE:
|
||||
if ('\0' == *p)
|
||||
nospace = 1;
|
||||
break;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if ((c < 0x20 && c != 0x09) ||
|
||||
(c > 0x7E && c < 0xA0))
|
||||
c = 0xFFFD;
|
||||
if (c > 0x7E)
|
||||
printf("&#%d;", c);
|
||||
else if ( ! print_escape(c))
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
return(nospace);
|
||||
@ -495,24 +496,10 @@ print_otag(struct html *h, enum htmltag tag,
|
||||
for (i = 0; i < sz; i++)
|
||||
print_attr(h, htmlattrs[p[i].key], p[i].val);
|
||||
|
||||
/* Add non-overridable attributes. */
|
||||
|
||||
if (TAG_HTML == tag && HTML_XHTML_1_0_STRICT == h->type) {
|
||||
print_attr(h, "xmlns", "http://www.w3.org/1999/xhtml");
|
||||
print_attr(h, "xml:lang", "en");
|
||||
print_attr(h, "lang", "en");
|
||||
}
|
||||
|
||||
/* Accommodate for XML "well-formed" singleton escaping. */
|
||||
/* Accommodate for "well-formed" singleton escaping. */
|
||||
|
||||
if (HTML_AUTOCLOSE & htmltags[tag].flags)
|
||||
switch (h->type) {
|
||||
case HTML_XHTML_1_0_STRICT:
|
||||
putchar('/');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
putchar('/');
|
||||
|
||||
putchar('>');
|
||||
|
||||
@ -538,26 +525,8 @@ print_ctag(struct html *h, enum htmltag tag)
|
||||
void
|
||||
print_gen_decls(struct html *h)
|
||||
{
|
||||
const char *doctype;
|
||||
const char *dtd;
|
||||
const char *name;
|
||||
|
||||
switch (h->type) {
|
||||
case HTML_HTML_4_01_STRICT:
|
||||
name = "HTML";
|
||||
doctype = "-//W3C//DTD HTML 4.01//EN";
|
||||
dtd = "http://www.w3.org/TR/html4/strict.dtd";
|
||||
break;
|
||||
default:
|
||||
puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
name = "html";
|
||||
doctype = "-//W3C//DTD XHTML 1.0 Strict//EN";
|
||||
dtd = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("<!DOCTYPE %s PUBLIC \"%s\" \"%s\">\n",
|
||||
name, doctype, dtd);
|
||||
puts("<!DOCTYPE html>");
|
||||
}
|
||||
|
||||
void
|
||||
@ -649,6 +618,18 @@ print_stagq(struct html *h, const struct tag *suntil)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_paragraph(struct html *h)
|
||||
{
|
||||
struct tag *t;
|
||||
struct htmlpair tag;
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "spacer");
|
||||
t = print_otag(h, TAG_DIV, 1, &tag);
|
||||
print_tagq(h, t);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bufinit(struct html *h)
|
||||
{
|
||||
@ -761,6 +742,8 @@ bufcat_su(struct html *h, const char *p, const struct roffsu *su)
|
||||
v = su->scale;
|
||||
if (SCALE_MM == su->unit && 0.0 == (v /= 100.0))
|
||||
v = 1.0;
|
||||
else if (SCALE_BU == su->unit)
|
||||
v /= 24.0;
|
||||
|
||||
bufcat_fmt(h, "%s: %.2f%s;", p, v, roffscales[su->unit]);
|
||||
}
|
||||
|
43
html.h
43
html.h
@ -1,6 +1,6 @@
|
||||
/* $Id: html.h,v 1.51 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/* $Id: html.h,v 1.67 2014/10/28 17:36:19 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -44,18 +44,32 @@ enum htmltag {
|
||||
TAG_DT,
|
||||
TAG_DD,
|
||||
TAG_BLOCKQUOTE,
|
||||
TAG_P,
|
||||
TAG_PRE,
|
||||
TAG_B,
|
||||
TAG_I,
|
||||
TAG_CODE,
|
||||
TAG_SMALL,
|
||||
TAG_STYLE,
|
||||
TAG_MATH,
|
||||
TAG_MROW,
|
||||
TAG_MI,
|
||||
TAG_MO,
|
||||
TAG_MSUP,
|
||||
TAG_MSUB,
|
||||
TAG_MSUBSUP,
|
||||
TAG_MFRAC,
|
||||
TAG_MSQRT,
|
||||
TAG_MFENCED,
|
||||
TAG_MTABLE,
|
||||
TAG_MTR,
|
||||
TAG_MTD,
|
||||
TAG_MUNDEROVER,
|
||||
TAG_MUNDER,
|
||||
TAG_MOVER,
|
||||
TAG_MAX
|
||||
};
|
||||
|
||||
enum htmlattr {
|
||||
ATTR_HTTPEQUIV,
|
||||
ATTR_CONTENT,
|
||||
ATTR_NAME,
|
||||
ATTR_REL,
|
||||
ATTR_HREF,
|
||||
@ -63,11 +77,12 @@ enum htmlattr {
|
||||
ATTR_MEDIA,
|
||||
ATTR_CLASS,
|
||||
ATTR_STYLE,
|
||||
ATTR_WIDTH,
|
||||
ATTR_ID,
|
||||
ATTR_SUMMARY,
|
||||
ATTR_ALIGN,
|
||||
ATTR_COLSPAN,
|
||||
ATTR_CHARSET,
|
||||
ATTR_OPEN,
|
||||
ATTR_CLOSE,
|
||||
ATTR_MATHVARIANT,
|
||||
ATTR_MAX
|
||||
};
|
||||
|
||||
@ -103,12 +118,6 @@ struct htmlpair {
|
||||
#define PAIR_CLASS_INIT(p, v) PAIR_INIT(p, ATTR_CLASS, v)
|
||||
#define PAIR_HREF_INIT(p, v) PAIR_INIT(p, ATTR_HREF, v)
|
||||
#define PAIR_STYLE_INIT(p, h) PAIR_INIT(p, ATTR_STYLE, (h)->buf)
|
||||
#define PAIR_SUMMARY_INIT(p, v) PAIR_INIT(p, ATTR_SUMMARY, v)
|
||||
|
||||
enum htmltype {
|
||||
HTML_HTML_4_01_STRICT,
|
||||
HTML_XHTML_1_0_STRICT
|
||||
};
|
||||
|
||||
struct html {
|
||||
int flags;
|
||||
@ -119,10 +128,12 @@ struct html {
|
||||
#define HTML_NONOSPACE (1 << 4) /* never add spaces */
|
||||
#define HTML_LITERAL (1 << 5) /* literal (e.g., <PRE>) context */
|
||||
#define HTML_SKIPCHAR (1 << 6) /* skip the next character */
|
||||
#define HTML_NOSPLIT (1 << 7) /* do not break line before .An */
|
||||
#define HTML_SPLIT (1 << 8) /* break line before .An */
|
||||
struct tagq tags; /* stack of open tags */
|
||||
struct rofftbl tbl; /* current table */
|
||||
struct tag *tblt; /* current open table scope */
|
||||
struct mchars *symtab; /* character-escapes */
|
||||
const struct mchars *symtab; /* character table */
|
||||
char *base_man; /* base for manpage href */
|
||||
char *base_includes; /* base for include href */
|
||||
char *style; /* style-sheet URI */
|
||||
@ -131,7 +142,6 @@ struct html {
|
||||
struct tag *metaf; /* current open font scope */
|
||||
enum htmlfont metal; /* last used font */
|
||||
enum htmlfont metac; /* current font mode */
|
||||
enum htmltype type; /* output media type */
|
||||
int oflags; /* output options */
|
||||
#define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */
|
||||
};
|
||||
@ -146,6 +156,7 @@ void print_text(struct html *, const char *);
|
||||
void print_tblclose(struct html *);
|
||||
void print_tbl(struct html *, const struct tbl_span *);
|
||||
void print_eqn(struct html *, const struct eqn *);
|
||||
void print_paragraph(struct html *);
|
||||
|
||||
#if __GNUC__ - 0 >= 4
|
||||
__attribute__((__format__ (__printf__, 2, 3)))
|
||||
|
6
lib.c
6
lib.c
@ -1,4 +1,4 @@
|
||||
/* $Id: lib.c,v 1.10 2014/03/23 11:25:26 schwarze Exp $ */
|
||||
/* $Id: lib.c,v 1.11 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,9 +14,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
24
libman.h
24
libman.h
@ -1,6 +1,7 @@
|
||||
/* $Id: libman.h,v 1.63 2014/08/01 21:24:17 schwarze Exp $ */
|
||||
/* $Id: libman.h,v 1.65 2014/11/28 05:51:32 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
|
||||
@ -45,7 +46,7 @@ struct man {
|
||||
char *buf
|
||||
|
||||
struct man_macro {
|
||||
int (*fp)(MACRO_PROT_ARGS);
|
||||
void (*fp)(MACRO_PROT_ARGS);
|
||||
int flags;
|
||||
#define MAN_SCOPED (1 << 0)
|
||||
#define MAN_EXPLICIT (1 << 1) /* See blk_imp(). */
|
||||
@ -53,24 +54,25 @@ struct man_macro {
|
||||
#define MAN_NSCOPED (1 << 3) /* See in_line_eoln(). */
|
||||
#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;
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int man_word_alloc(struct man *, int, int, const char *);
|
||||
int man_block_alloc(struct man *, int, int, enum mant);
|
||||
int man_head_alloc(struct man *, int, int, enum mant);
|
||||
int man_tail_alloc(struct man *, int, int, enum mant);
|
||||
int man_body_alloc(struct man *, int, int, enum mant);
|
||||
int man_elem_alloc(struct man *, int, int, enum mant);
|
||||
void man_word_alloc(struct man *, int, int, const char *);
|
||||
void man_word_append(struct man *, const char *);
|
||||
void man_block_alloc(struct man *, int, int, enum mant);
|
||||
void man_head_alloc(struct man *, int, int, enum mant);
|
||||
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 *);
|
||||
int man_macroend(struct man *);
|
||||
int man_valid_post(struct man *);
|
||||
int man_unscope(struct man *, const struct man_node *);
|
||||
void man_macroend(struct man *);
|
||||
void man_valid_post(struct man *);
|
||||
void man_unscope(struct man *, const struct man_node *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
31
libmandoc.h
31
libmandoc.h
@ -1,4 +1,4 @@
|
||||
/* $Id: libmandoc.h,v 1.42 2014/07/09 11:31:43 schwarze Exp $ */
|
||||
/* $Id: libmandoc.h,v 1.49 2014/11/28 06:27:05 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -30,6 +30,11 @@ enum rofferr {
|
||||
ROFF_ERR /* badness: puke and stop */
|
||||
};
|
||||
|
||||
struct buf {
|
||||
char *buf;
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
struct roff;
|
||||
@ -55,34 +60,32 @@ struct mdoc *mdoc_alloc(struct roff *, struct mparse *,
|
||||
void mdoc_reset(struct mdoc *);
|
||||
int mdoc_parseln(struct mdoc *, int, char *, int);
|
||||
int mdoc_endparse(struct mdoc *);
|
||||
int mdoc_addspan(struct mdoc *, const struct tbl_span *);
|
||||
int mdoc_addeqn(struct mdoc *, const struct eqn *);
|
||||
void mdoc_addspan(struct mdoc *, const struct tbl_span *);
|
||||
void mdoc_addeqn(struct mdoc *, const struct eqn *);
|
||||
|
||||
void man_free(struct man *);
|
||||
struct man *man_alloc(struct roff *, struct mparse *, int);
|
||||
void man_reset(struct man *);
|
||||
int man_parseln(struct man *, int, char *, int);
|
||||
int man_endparse(struct man *);
|
||||
int man_addspan(struct man *, const struct tbl_span *);
|
||||
int man_addeqn(struct man *, const struct eqn *);
|
||||
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_encode(struct buf *, size_t *,
|
||||
struct buf *, size_t *, int *);
|
||||
|
||||
void roff_free(struct roff *);
|
||||
struct roff *roff_alloc(struct mparse *, int);
|
||||
struct roff *roff_alloc(struct mparse *, const struct mchars *, int);
|
||||
void roff_reset(struct roff *);
|
||||
enum rofferr roff_parseln(struct roff *, int,
|
||||
char **, size_t *, int, int *);
|
||||
enum rofferr roff_parseln(struct roff *, int, struct buf *, int *);
|
||||
void roff_endparse(struct roff *);
|
||||
void roff_setreg(struct roff *, const char *, int, char sign);
|
||||
int roff_getreg(const struct roff *, const char *);
|
||||
char *roff_strdup(const struct roff *, const char *);
|
||||
int roff_getcontrol(const struct roff *,
|
||||
const char *, int *);
|
||||
#if 0
|
||||
char roff_eqndelim(const struct roff *);
|
||||
void roff_openeqn(struct roff *, const char *,
|
||||
int, int, const char *);
|
||||
int roff_closeeqn(struct roff *);
|
||||
#endif
|
||||
int roff_getformat(const struct roff *);
|
||||
|
||||
const struct tbl_span *roff_span(const struct roff *);
|
||||
const struct eqn *roff_eqn(const struct roff *);
|
||||
|
44
libmdoc.h
44
libmdoc.h
@ -1,7 +1,7 @@
|
||||
/* $Id: libmdoc.h,v 1.88 2014/08/01 17:40:34 schwarze Exp $ */
|
||||
/* $Id: libmdoc.h,v 1.95 2014/11/29 03:37:44 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013, 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
|
||||
@ -37,6 +37,7 @@ struct mdoc {
|
||||
#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 */
|
||||
@ -55,7 +56,7 @@ struct mdoc {
|
||||
char *buf
|
||||
|
||||
struct mdoc_macro {
|
||||
int (*fp)(MACRO_PROT_ARGS);
|
||||
void (*fp)(MACRO_PROT_ARGS);
|
||||
int flags;
|
||||
#define MDOC_CALLABLE (1 << 0)
|
||||
#define MDOC_PARSED (1 << 1)
|
||||
@ -76,13 +77,6 @@ enum margserr {
|
||||
ARGS_PEND /* last phrase (-column) */
|
||||
};
|
||||
|
||||
enum margverr {
|
||||
ARGV_ERROR,
|
||||
ARGV_EOLN, /* end of line */
|
||||
ARGV_ARG, /* valid argument */
|
||||
ARGV_WORD /* normal word (or bad argument---same thing) */
|
||||
};
|
||||
|
||||
/*
|
||||
* A punctuation delimiter is opening, closing, or "middle mark"
|
||||
* punctuation. These govern spacing.
|
||||
@ -104,38 +98,34 @@ extern const struct mdoc_macro *const mdoc_macros;
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int mdoc_macro(MACRO_PROT_ARGS);
|
||||
int mdoc_word_alloc(struct mdoc *,
|
||||
int, int, const char *);
|
||||
void mdoc_macro(MACRO_PROT_ARGS);
|
||||
void mdoc_word_alloc(struct mdoc *, int, int, const char *);
|
||||
void mdoc_word_append(struct mdoc *, const char *);
|
||||
int mdoc_elem_alloc(struct mdoc *, int, int,
|
||||
void mdoc_elem_alloc(struct mdoc *, int, int,
|
||||
enum mdoct, struct mdoc_arg *);
|
||||
int mdoc_block_alloc(struct mdoc *, int, int,
|
||||
struct mdoc_node *mdoc_block_alloc(struct mdoc *, int, int,
|
||||
enum mdoct, struct mdoc_arg *);
|
||||
int mdoc_head_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
int mdoc_tail_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
int mdoc_body_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
int mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct,
|
||||
struct mdoc_node *mdoc_head_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
void mdoc_tail_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
struct mdoc_node *mdoc_body_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
void mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct,
|
||||
struct mdoc_node *, enum mdoc_endbody);
|
||||
void mdoc_node_delete(struct mdoc *, struct mdoc_node *);
|
||||
int mdoc_node_relink(struct mdoc *, struct mdoc_node *);
|
||||
void mdoc_node_relink(struct mdoc *, struct mdoc_node *);
|
||||
void mdoc_hash_init(void);
|
||||
enum mdoct mdoc_hash_find(const char *);
|
||||
const char *mdoc_a2att(const char *);
|
||||
const char *mdoc_a2lib(const char *);
|
||||
const char *mdoc_a2st(const char *);
|
||||
const char *mdoc_a2arch(const char *);
|
||||
const char *mdoc_a2vol(const char *);
|
||||
int mdoc_valid_pre(struct mdoc *, struct mdoc_node *);
|
||||
int mdoc_valid_post(struct mdoc *);
|
||||
enum margverr mdoc_argv(struct mdoc *, int, enum mdoct,
|
||||
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 *);
|
||||
void mdoc_argv_free(struct mdoc_arg *);
|
||||
enum margserr mdoc_args(struct mdoc *, int,
|
||||
int *, char *, enum mdoct, char **);
|
||||
enum margserr mdoc_zargs(struct mdoc *, int,
|
||||
int *, char *, char **);
|
||||
int mdoc_macroend(struct mdoc *);
|
||||
void mdoc_macroend(struct mdoc *);
|
||||
enum mdelim mdoc_isdelim(const char *);
|
||||
|
||||
__END_DECLS
|
||||
|
28
libroff.h
28
libroff.h
@ -1,6 +1,7 @@
|
||||
/* $Id: libroff.h,v 1.29 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/* $Id: libroff.h,v 1.31 2014/10/25 14:35:37 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
|
||||
@ -43,16 +44,19 @@ struct tbl_node {
|
||||
};
|
||||
|
||||
struct eqn_node {
|
||||
struct eqn_def *defs;
|
||||
size_t defsz;
|
||||
char *data;
|
||||
size_t rew;
|
||||
size_t cur;
|
||||
size_t sz;
|
||||
int gsize;
|
||||
struct eqn eqn;
|
||||
struct mparse *parse;
|
||||
struct eqn_node *next;
|
||||
struct eqn eqn; /* syntax tree of this equation */
|
||||
struct mparse *parse; /* main parser, for error reporting */
|
||||
struct eqn_node *next; /* singly linked list of equations */
|
||||
struct eqn_def *defs; /* array of definitions */
|
||||
char *data; /* source code of this equation */
|
||||
size_t defsz; /* number of definitions */
|
||||
size_t sz; /* length of the source code */
|
||||
size_t cur; /* parse point in the source code */
|
||||
size_t rew; /* beginning of the current token */
|
||||
int gsize; /* default point size */
|
||||
int delim; /* in-line delimiters enabled */
|
||||
char odelim; /* in-line opening delimiter */
|
||||
char cdelim; /* in-line closing delimiter */
|
||||
};
|
||||
|
||||
struct eqn_def {
|
||||
@ -73,7 +77,7 @@ int tbl_data(struct tbl_node *, int, const char *);
|
||||
int tbl_cdata(struct tbl_node *, int, const char *);
|
||||
const struct tbl_span *tbl_span(struct tbl_node *);
|
||||
void tbl_end(struct tbl_node **);
|
||||
struct eqn_node *eqn_alloc(const char *, int, int, struct mparse *);
|
||||
struct eqn_node *eqn_alloc(int, int, struct mparse *);
|
||||
enum rofferr eqn_end(struct eqn_node **);
|
||||
void eqn_free(struct eqn_node *);
|
||||
enum rofferr eqn_read(struct eqn_node **, int,
|
||||
|
539
main.c
539
main.c
@ -1,6 +1,6 @@
|
||||
/* $Id: main.c,v 1.177 2014/06/21 22:24:01 schwarze Exp $ */
|
||||
/* $Id: main.c,v 1.200 2014/11/26 21:40:17 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
|
||||
*
|
||||
@ -16,11 +16,14 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@ -32,6 +35,8 @@
|
||||
#include "main.h"
|
||||
#include "mdoc.h"
|
||||
#include "man.h"
|
||||
#include "manpath.h"
|
||||
#include "mansearch.h"
|
||||
|
||||
#if !defined(__GNUC__) || (__GNUC__ < 2)
|
||||
# if !defined(lint)
|
||||
@ -39,6 +44,15 @@
|
||||
# endif
|
||||
#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
|
||||
|
||||
enum outmode {
|
||||
OUTMODE_DEF = 0,
|
||||
OUTMODE_FLN,
|
||||
OUTMODE_LST,
|
||||
OUTMODE_ALL,
|
||||
OUTMODE_INT,
|
||||
OUTMODE_ONE
|
||||
};
|
||||
|
||||
typedef void (*out_mdoc)(void *, const struct mdoc *);
|
||||
typedef void (*out_man)(void *, const struct man *);
|
||||
typedef void (*out_free)(void *);
|
||||
@ -50,7 +64,6 @@ enum outt {
|
||||
OUTT_TREE, /* -Ttree */
|
||||
OUTT_MAN, /* -Tman */
|
||||
OUTT_HTML, /* -Thtml */
|
||||
OUTT_XHTML, /* -Txhtml */
|
||||
OUTT_LINT, /* -Tlint */
|
||||
OUTT_PS, /* -Tps */
|
||||
OUTT_PDF /* -Tpdf */
|
||||
@ -58,6 +71,7 @@ enum outt {
|
||||
|
||||
struct curparse {
|
||||
struct mparse *mp;
|
||||
struct mchars *mchars; /* character table */
|
||||
enum mandoclevel wlevel; /* ignore messages below this */
|
||||
int wstop; /* stop after a file with a warning */
|
||||
enum outt outtype; /* which output to use */
|
||||
@ -68,27 +82,45 @@ struct curparse {
|
||||
char outopts[BUFSIZ]; /* buf of output opts */
|
||||
};
|
||||
|
||||
static int koptions(int *, char *);
|
||||
static int moptions(int *, char *);
|
||||
static void mmsg(enum mandocerr, enum mandoclevel,
|
||||
const char *, int, int, const char *);
|
||||
static void parse(struct curparse *, int,
|
||||
const char *, enum mandoclevel *);
|
||||
static enum mandoclevel passthrough(const char *, int, int);
|
||||
static void spawn_pager(void);
|
||||
static int toptions(struct curparse *, char *);
|
||||
static void usage(void) __attribute__((noreturn));
|
||||
static void usage(enum argmode) __attribute__((noreturn));
|
||||
static void version(void) __attribute__((noreturn));
|
||||
static int woptions(struct curparse *, char *);
|
||||
|
||||
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
|
||||
static const char *progname;
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
struct curparse curp;
|
||||
int options;
|
||||
enum mandoclevel rc;
|
||||
struct mansearch search;
|
||||
struct manpaths paths;
|
||||
char *conf_file, *defpaths, *auxpaths;
|
||||
char *defos;
|
||||
#if HAVE_SQLITE3
|
||||
struct manpage *res, *resp;
|
||||
size_t isec, i, sz;
|
||||
int prio, best_prio;
|
||||
char sec;
|
||||
#endif
|
||||
enum mandoclevel rc;
|
||||
enum outmode outmode;
|
||||
int fd;
|
||||
int show_usage;
|
||||
int use_pager;
|
||||
int synopsis_only;
|
||||
int options;
|
||||
int c;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname == NULL)
|
||||
@ -96,15 +128,57 @@ main(int argc, char *argv[])
|
||||
else
|
||||
++progname;
|
||||
|
||||
memset(&curp, 0, sizeof(struct curparse));
|
||||
/* Search options. */
|
||||
|
||||
options = MPARSE_SO;
|
||||
memset(&paths, 0, sizeof(struct manpaths));
|
||||
conf_file = defpaths = auxpaths = NULL;
|
||||
|
||||
memset(&search, 0, sizeof(struct mansearch));
|
||||
search.outkey = "Nd";
|
||||
|
||||
if (strcmp(progname, "man") == 0)
|
||||
search.argmode = ARG_NAME;
|
||||
else if (strncmp(progname, "apropos", 7) == 0)
|
||||
search.argmode = ARG_EXPR;
|
||||
else if (strncmp(progname, "whatis", 6) == 0)
|
||||
search.argmode = ARG_WORD;
|
||||
else
|
||||
search.argmode = ARG_FILE;
|
||||
|
||||
/* Parser and formatter options. */
|
||||
|
||||
memset(&curp, 0, sizeof(struct curparse));
|
||||
curp.outtype = OUTT_ASCII;
|
||||
curp.wlevel = MANDOCLEVEL_FATAL;
|
||||
options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1;
|
||||
defos = NULL;
|
||||
|
||||
while (-1 != (c = getopt(argc, argv, "I:m:O:T:VW:")))
|
||||
use_pager = 1;
|
||||
show_usage = 0;
|
||||
synopsis_only = 0;
|
||||
outmode = OUTMODE_DEF;
|
||||
|
||||
while (-1 != (c = getopt(argc, argv,
|
||||
"aC:cfhI:iK:klM:m:O:S:s:T:VW:w"))) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
outmode = OUTMODE_ALL;
|
||||
break;
|
||||
case 'C':
|
||||
conf_file = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
use_pager = 0;
|
||||
break;
|
||||
case 'f':
|
||||
search.argmode = ARG_WORD;
|
||||
break;
|
||||
case 'h':
|
||||
(void)strlcat(curp.outopts, "synopsis,", BUFSIZ);
|
||||
synopsis_only = 1;
|
||||
use_pager = 0;
|
||||
outmode = OUTMODE_ALL;
|
||||
break;
|
||||
case 'I':
|
||||
if (strncmp(optarg, "os=", 3)) {
|
||||
fprintf(stderr,
|
||||
@ -120,14 +194,37 @@ main(int argc, char *argv[])
|
||||
}
|
||||
defos = mandoc_strdup(optarg + 3);
|
||||
break;
|
||||
case 'm':
|
||||
if ( ! moptions(&options, optarg))
|
||||
case 'i':
|
||||
outmode = OUTMODE_INT;
|
||||
break;
|
||||
case 'K':
|
||||
if ( ! koptions(&options, optarg))
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
break;
|
||||
case 'k':
|
||||
search.argmode = ARG_EXPR;
|
||||
break;
|
||||
case 'l':
|
||||
search.argmode = ARG_FILE;
|
||||
outmode = OUTMODE_ALL;
|
||||
break;
|
||||
case 'M':
|
||||
defpaths = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
auxpaths = optarg;
|
||||
break;
|
||||
case 'O':
|
||||
search.outkey = optarg;
|
||||
(void)strlcat(curp.outopts, optarg, BUFSIZ);
|
||||
(void)strlcat(curp.outopts, ",", BUFSIZ);
|
||||
break;
|
||||
case 'S':
|
||||
search.arch = optarg;
|
||||
break;
|
||||
case 's':
|
||||
search.sec = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
if ( ! toptions(&curp, optarg))
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
@ -136,15 +233,147 @@ main(int argc, char *argv[])
|
||||
if ( ! woptions(&curp, optarg))
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
break;
|
||||
case 'w':
|
||||
outmode = OUTMODE_FLN;
|
||||
break;
|
||||
case 'V':
|
||||
version();
|
||||
/* NOTREACHED */
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
show_usage = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (show_usage)
|
||||
usage(search.argmode);
|
||||
|
||||
/* Postprocess options. */
|
||||
|
||||
if (outmode == OUTMODE_DEF) {
|
||||
switch (search.argmode) {
|
||||
case ARG_FILE:
|
||||
outmode = OUTMODE_ALL;
|
||||
use_pager = 0;
|
||||
break;
|
||||
case ARG_NAME:
|
||||
outmode = OUTMODE_ONE;
|
||||
break;
|
||||
default:
|
||||
outmode = OUTMODE_LST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse arguments. */
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
#if HAVE_SQLITE3
|
||||
resp = NULL;
|
||||
#endif
|
||||
|
||||
/* Quirk for a man(1) section argument without -s. */
|
||||
|
||||
if (search.argmode == ARG_NAME &&
|
||||
argv[0] != NULL &&
|
||||
isdigit((unsigned char)argv[0][0]) &&
|
||||
(argv[0][1] == '\0' || !strcmp(argv[0], "3p"))) {
|
||||
search.sec = argv[0];
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
rc = MANDOCLEVEL_OK;
|
||||
|
||||
/* man(1), whatis(1), apropos(1) */
|
||||
|
||||
if (search.argmode != ARG_FILE) {
|
||||
#if HAVE_SQLITE3
|
||||
if (argc == 0)
|
||||
usage(search.argmode);
|
||||
|
||||
if (search.argmode == ARG_NAME &&
|
||||
outmode == OUTMODE_ONE)
|
||||
search.firstmatch = 1;
|
||||
|
||||
/* Access the mandoc database. */
|
||||
|
||||
manpath_parse(&paths, conf_file, defpaths, auxpaths);
|
||||
mansearch_setup(1);
|
||||
if( ! mansearch(&search, &paths, argc, argv, &res, &sz))
|
||||
usage(search.argmode);
|
||||
resp = res;
|
||||
|
||||
if (sz == 0) {
|
||||
if (search.argmode == ARG_NAME)
|
||||
fprintf(stderr, "%s: No entry for %s "
|
||||
"in the manual.\n", progname, argv[0]);
|
||||
rc = MANDOCLEVEL_BADARG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
curp.mp = mparse_alloc(options, curp.wlevel, mmsg, defos);
|
||||
/*
|
||||
* For standard man(1) and -a output mode,
|
||||
* prepare for copying filename pointers
|
||||
* into the program parameter array.
|
||||
*/
|
||||
|
||||
if (outmode == OUTMODE_ONE) {
|
||||
argc = 1;
|
||||
best_prio = 10;
|
||||
} else if (outmode == OUTMODE_ALL)
|
||||
argc = (int)sz;
|
||||
|
||||
/* Iterate all matching manuals. */
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (outmode == OUTMODE_FLN)
|
||||
puts(res[i].file);
|
||||
else if (outmode == OUTMODE_LST)
|
||||
printf("%s - %s\n", res[i].names,
|
||||
res[i].output == NULL ? "" :
|
||||
res[i].output);
|
||||
else if (outmode == OUTMODE_ONE) {
|
||||
/* Search for the best section. */
|
||||
isec = strcspn(res[i].file, "123456789");
|
||||
sec = res[i].file[isec];
|
||||
if ('\0' == sec)
|
||||
continue;
|
||||
prio = sec_prios[sec - '1'];
|
||||
if (prio >= best_prio)
|
||||
continue;
|
||||
best_prio = prio;
|
||||
resp = res + i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For man(1), -a and -i output mode, fall through
|
||||
* to the main mandoc(1) code iterating files
|
||||
* and running the parsers on each of them.
|
||||
*/
|
||||
|
||||
if (outmode == OUTMODE_FLN || outmode == OUTMODE_LST)
|
||||
goto out;
|
||||
#else
|
||||
fputs("mandoc: database support not compiled in\n",
|
||||
stderr);
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* mandoc(1) */
|
||||
|
||||
if ( ! moptions(&options, auxpaths))
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
|
||||
if (use_pager && isatty(STDOUT_FILENO))
|
||||
spawn_pager();
|
||||
|
||||
curp.mchars = mchars_alloc();
|
||||
curp.mp = mparse_alloc(options, curp.wlevel, mmsg,
|
||||
curp.mchars, defos);
|
||||
|
||||
/*
|
||||
* Conditionally start up the lookaside buffer before parsing.
|
||||
@ -152,25 +381,53 @@ main(int argc, char *argv[])
|
||||
if (OUTT_MAN == curp.outtype)
|
||||
mparse_keep(curp.mp);
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
rc = MANDOCLEVEL_OK;
|
||||
|
||||
if (NULL == *argv)
|
||||
if (argc == 0)
|
||||
parse(&curp, STDIN_FILENO, "<stdin>", &rc);
|
||||
|
||||
while (*argv) {
|
||||
parse(&curp, -1, *argv, &rc);
|
||||
while (argc) {
|
||||
#if HAVE_SQLITE3
|
||||
if (resp != NULL) {
|
||||
rc = mparse_open(curp.mp, &fd, resp->file);
|
||||
if (fd == -1)
|
||||
/* nothing */;
|
||||
else if (resp->form & FORM_SRC) {
|
||||
/* For .so only; ignore failure. */
|
||||
chdir(paths.paths[resp->ipath]);
|
||||
parse(&curp, fd, resp->file, &rc);
|
||||
} else
|
||||
rc = passthrough(resp->file, fd,
|
||||
synopsis_only);
|
||||
resp++;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
rc = mparse_open(curp.mp, &fd, *argv++);
|
||||
if (fd != -1)
|
||||
parse(&curp, fd, argv[-1], &rc);
|
||||
}
|
||||
|
||||
if (mparse_wait(curp.mp) != MANDOCLEVEL_OK)
|
||||
rc = MANDOCLEVEL_SYSERR;
|
||||
|
||||
if (MANDOCLEVEL_OK != rc && curp.wstop)
|
||||
break;
|
||||
++argv;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (curp.outfree)
|
||||
(*curp.outfree)(curp.outdata);
|
||||
if (curp.mp)
|
||||
mparse_free(curp.mp);
|
||||
mparse_free(curp.mp);
|
||||
mchars_free(curp.mchars);
|
||||
|
||||
#if HAVE_SQLITE3
|
||||
out:
|
||||
if (search.argmode != ARG_FILE) {
|
||||
manpath_free(&paths);
|
||||
mansearch_free(res, sz);
|
||||
mansearch_setup(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(defos);
|
||||
|
||||
return((int)rc);
|
||||
@ -180,24 +437,36 @@ static void
|
||||
version(void)
|
||||
{
|
||||
|
||||
printf("%s %s\n", progname, VERSION);
|
||||
printf("mandoc %s\n", VERSION);
|
||||
exit((int)MANDOCLEVEL_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
usage(enum argmode argmode)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: %s "
|
||||
"[-V] "
|
||||
"[-Ios=name] "
|
||||
"[-mformat] "
|
||||
"[-Ooption] "
|
||||
"[-Toutput] "
|
||||
"[-Wlevel]\n"
|
||||
"\t [file ...]\n",
|
||||
progname);
|
||||
|
||||
switch (argmode) {
|
||||
case ARG_FILE:
|
||||
fputs("usage: mandoc [-acfhklV] [-Ios=name] "
|
||||
"[-Kencoding] [-mformat] [-Ooption]\n"
|
||||
"\t [-Toutput] [-Wlevel] [file ...]\n", stderr);
|
||||
break;
|
||||
case ARG_NAME:
|
||||
fputs("usage: man [-acfhklVw] [-C file] "
|
||||
"[-M path] [-m path] [-S arch] [-s section]\n"
|
||||
"\t [section] name ...\n", stderr);
|
||||
break;
|
||||
case ARG_WORD:
|
||||
fputs("usage: whatis [-acfhklVw] [-C file] "
|
||||
"[-M path] [-m path] [-O outkey] [-S arch]\n"
|
||||
"\t [-s section] name ...\n", stderr);
|
||||
break;
|
||||
case ARG_EXPR:
|
||||
fputs("usage: apropos [-acfhklVw] [-C file] "
|
||||
"[-M path] [-m path] [-O outkey] [-S arch]\n"
|
||||
"\t [-s section] expression ...\n", stderr);
|
||||
break;
|
||||
}
|
||||
exit((int)MANDOCLEVEL_BADARG);
|
||||
}
|
||||
|
||||
@ -233,32 +502,34 @@ parse(struct curparse *curp, int fd, const char *file,
|
||||
|
||||
if ( ! (curp->outman && curp->outmdoc)) {
|
||||
switch (curp->outtype) {
|
||||
case OUTT_XHTML:
|
||||
curp->outdata = xhtml_alloc(curp->outopts);
|
||||
curp->outfree = html_free;
|
||||
break;
|
||||
case OUTT_HTML:
|
||||
curp->outdata = html_alloc(curp->outopts);
|
||||
curp->outdata = html_alloc(curp->mchars,
|
||||
curp->outopts);
|
||||
curp->outfree = html_free;
|
||||
break;
|
||||
case OUTT_UTF8:
|
||||
curp->outdata = utf8_alloc(curp->outopts);
|
||||
curp->outdata = utf8_alloc(curp->mchars,
|
||||
curp->outopts);
|
||||
curp->outfree = ascii_free;
|
||||
break;
|
||||
case OUTT_LOCALE:
|
||||
curp->outdata = locale_alloc(curp->outopts);
|
||||
curp->outdata = locale_alloc(curp->mchars,
|
||||
curp->outopts);
|
||||
curp->outfree = ascii_free;
|
||||
break;
|
||||
case OUTT_ASCII:
|
||||
curp->outdata = ascii_alloc(curp->outopts);
|
||||
curp->outdata = ascii_alloc(curp->mchars,
|
||||
curp->outopts);
|
||||
curp->outfree = ascii_free;
|
||||
break;
|
||||
case OUTT_PDF:
|
||||
curp->outdata = pdf_alloc(curp->outopts);
|
||||
curp->outdata = pdf_alloc(curp->mchars,
|
||||
curp->outopts);
|
||||
curp->outfree = pspdf_free;
|
||||
break;
|
||||
case OUTT_PS:
|
||||
curp->outdata = ps_alloc(curp->outopts);
|
||||
curp->outdata = ps_alloc(curp->mchars,
|
||||
curp->outopts);
|
||||
curp->outfree = pspdf_free;
|
||||
break;
|
||||
default:
|
||||
@ -267,8 +538,6 @@ parse(struct curparse *curp, int fd, const char *file,
|
||||
|
||||
switch (curp->outtype) {
|
||||
case OUTT_HTML:
|
||||
/* FALLTHROUGH */
|
||||
case OUTT_XHTML:
|
||||
curp->outman = html_man;
|
||||
curp->outmdoc = html_mdoc;
|
||||
break;
|
||||
@ -314,11 +583,97 @@ parse(struct curparse *curp, int fd, const char *file,
|
||||
*level = rc;
|
||||
}
|
||||
|
||||
static enum mandoclevel
|
||||
passthrough(const char *file, int fd, int synopsis_only)
|
||||
{
|
||||
const char synb[] = "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS";
|
||||
const char synr[] = "SYNOPSIS";
|
||||
|
||||
FILE *stream;
|
||||
const char *syscall;
|
||||
char *line;
|
||||
size_t len, off;
|
||||
ssize_t nw;
|
||||
int print;
|
||||
|
||||
if ((stream = fdopen(fd, "r")) == NULL) {
|
||||
close(fd);
|
||||
syscall = "fdopen";
|
||||
goto fail;
|
||||
}
|
||||
|
||||
print = 0;
|
||||
while ((line = fgetln(stream, &len)) != NULL) {
|
||||
if (synopsis_only) {
|
||||
if (print) {
|
||||
if ( ! isspace((unsigned char)*line))
|
||||
goto done;
|
||||
while (len &&
|
||||
isspace((unsigned char)*line)) {
|
||||
line++;
|
||||
len--;
|
||||
}
|
||||
} else {
|
||||
if ((len == sizeof(synb) &&
|
||||
! strncmp(line, synb, len - 1)) ||
|
||||
(len == sizeof(synr) &&
|
||||
! strncmp(line, synr, len - 1)))
|
||||
print = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (off = 0; off < len; off += nw)
|
||||
if ((nw = write(STDOUT_FILENO, line + off,
|
||||
len - off)) == -1 || nw == 0) {
|
||||
fclose(stream);
|
||||
syscall = "write";
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror(stream)) {
|
||||
fclose(stream);
|
||||
syscall = "fgetln";
|
||||
goto fail;
|
||||
}
|
||||
|
||||
done:
|
||||
fclose(stream);
|
||||
return(MANDOCLEVEL_OK);
|
||||
|
||||
fail:
|
||||
fprintf(stderr, "%s: %s: SYSERR: %s: %s",
|
||||
progname, file, syscall, strerror(errno));
|
||||
return(MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
|
||||
static int
|
||||
koptions(int *options, char *arg)
|
||||
{
|
||||
|
||||
if ( ! strcmp(arg, "utf-8")) {
|
||||
*options |= MPARSE_UTF8;
|
||||
*options &= ~MPARSE_LATIN1;
|
||||
} else if ( ! strcmp(arg, "iso-8859-1")) {
|
||||
*options |= MPARSE_LATIN1;
|
||||
*options &= ~MPARSE_UTF8;
|
||||
} else if ( ! strcmp(arg, "us-ascii")) {
|
||||
*options &= ~(MPARSE_UTF8 | MPARSE_LATIN1);
|
||||
} else {
|
||||
fprintf(stderr, "%s: -K%s: Bad argument\n",
|
||||
progname, arg);
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
moptions(int *options, char *arg)
|
||||
{
|
||||
|
||||
if (0 == strcmp(arg, "doc"))
|
||||
if (arg == NULL)
|
||||
/* nothing to do */;
|
||||
else if (0 == strcmp(arg, "doc"))
|
||||
*options |= MPARSE_MDOC;
|
||||
else if (0 == strcmp(arg, "andoc"))
|
||||
/* nothing to do */;
|
||||
@ -353,7 +708,7 @@ toptions(struct curparse *curp, char *arg)
|
||||
else if (0 == strcmp(arg, "locale"))
|
||||
curp->outtype = OUTT_LOCALE;
|
||||
else if (0 == strcmp(arg, "xhtml"))
|
||||
curp->outtype = OUTT_XHTML;
|
||||
curp->outtype = OUTT_HTML;
|
||||
else if (0 == strcmp(arg, "ps"))
|
||||
curp->outtype = OUTT_PS;
|
||||
else if (0 == strcmp(arg, "pdf"))
|
||||
@ -428,3 +783,79 @@ mmsg(enum mandocerr t, enum mandoclevel lvl,
|
||||
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
static void
|
||||
spawn_pager(void)
|
||||
{
|
||||
#define MAX_PAGER_ARGS 16
|
||||
char *argv[MAX_PAGER_ARGS];
|
||||
const char *pager;
|
||||
char *cp;
|
||||
int fildes[2];
|
||||
int argc;
|
||||
|
||||
if (pipe(fildes) == -1) {
|
||||
fprintf(stderr, "%s: pipe: %s\n",
|
||||
progname, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
fprintf(stderr, "%s: fork: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
case 0:
|
||||
close(fildes[0]);
|
||||
if (dup2(fildes[1], STDOUT_FILENO) == -1) {
|
||||
fprintf(stderr, "%s: dup output: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* The original 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);
|
||||
}
|
||||
|
||||
pager = getenv("MANPAGER");
|
||||
if (pager == NULL || *pager == '\0')
|
||||
pager = getenv("PAGER");
|
||||
if (pager == NULL || *pager == '\0')
|
||||
pager = "/usr/bin/more -s";
|
||||
cp = mandoc_strdup(pager);
|
||||
|
||||
/*
|
||||
* Parse the pager command into words.
|
||||
* Intentionally do not do anything fancy here.
|
||||
*/
|
||||
|
||||
argc = 0;
|
||||
while (argc + 1 < MAX_PAGER_ARGS) {
|
||||
argv[argc++] = cp;
|
||||
cp = strchr(cp, ' ');
|
||||
if (cp == NULL)
|
||||
break;
|
||||
*cp++ = '\0';
|
||||
while (*cp == ' ')
|
||||
cp++;
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
|
||||
/* Hand over to the pager. */
|
||||
|
||||
execvp(argv[0], argv);
|
||||
fprintf(stderr, "%s: exec: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
|
15
main.h
15
main.h
@ -1,4 +1,4 @@
|
||||
/* $Id: main.h,v 1.16 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/* $Id: main.h,v 1.17 2014/10/28 17:36:19 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -32,8 +32,7 @@ struct man;
|
||||
* terminal output routines with different character settings.
|
||||
*/
|
||||
|
||||
void *html_alloc(char *);
|
||||
void *xhtml_alloc(char *);
|
||||
void *html_alloc(const struct mchars *, char *);
|
||||
void html_mdoc(void *, const struct mdoc *);
|
||||
void html_man(void *, const struct man *);
|
||||
void html_free(void *);
|
||||
@ -44,13 +43,13 @@ void tree_man(void *, const struct man *);
|
||||
void man_mdoc(void *, const struct mdoc *);
|
||||
void man_man(void *, const struct man *);
|
||||
|
||||
void *locale_alloc(char *);
|
||||
void *utf8_alloc(char *);
|
||||
void *ascii_alloc(char *);
|
||||
void *locale_alloc(const struct mchars *, char *);
|
||||
void *utf8_alloc(const struct mchars *, char *);
|
||||
void *ascii_alloc(const struct mchars *, char *);
|
||||
void ascii_free(void *);
|
||||
|
||||
void *pdf_alloc(char *);
|
||||
void *ps_alloc(char *);
|
||||
void *pdf_alloc(const struct mchars *, char *);
|
||||
void *ps_alloc(const struct mchars *, char *);
|
||||
void pspdf_free(void *);
|
||||
|
||||
void terminal_mdoc(void *, const struct mdoc *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $Id: makewhatis.8,v 1.2 2014/04/25 12:13:15 schwarze Exp $
|
||||
.\" $Id: makewhatis.8,v 1.3 2014/08/17 21:03:06 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: April 25 2014 $
|
||||
.Dd $Mdocdate: August 17 2014 $
|
||||
.Dt MAKEWHATIS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -98,7 +98,7 @@ format.
|
||||
Display all files added or removed to the index.
|
||||
With a second
|
||||
.Fl D ,
|
||||
also show all keyswords added for each file.
|
||||
also show all keywords added for each file.
|
||||
.It Fl d Ar dir
|
||||
Merge (remove and re-add)
|
||||
.Ar
|
||||
|
402
man.1
Normal file
402
man.1
Normal file
@ -0,0 +1,402 @@
|
||||
.\" $Id: man.1,v 1.7 2014/11/11 02:43:41 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\" Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
|
||||
.\" Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
|
||||
.\"
|
||||
.Dd $Mdocdate: November 11 2014 $
|
||||
.Dt MAN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm man
|
||||
.Nd display manual pages
|
||||
.Sh SYNOPSIS
|
||||
.Nm man
|
||||
.Op Fl acfhklVw
|
||||
.Op Fl C Ar file
|
||||
.Op Fl M Ar path
|
||||
.Op Fl m Ar path
|
||||
.Op Fl S Ar subsection
|
||||
.Op Fl s Ar section
|
||||
.Op Ar section
|
||||
.Ar name ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
displays the
|
||||
manual pages entitled
|
||||
.Ar name .
|
||||
Pages may be selected according to
|
||||
a specific category
|
||||
.Pq Ar section
|
||||
or
|
||||
machine architecture
|
||||
.Pq Ar subsection .
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Display all of the manual pages for a specified
|
||||
.Ar section
|
||||
and
|
||||
.Ar name
|
||||
combination.
|
||||
Normally, only the first manual page found is displayed.
|
||||
.It Fl C Ar file
|
||||
Use the specified
|
||||
.Ar file
|
||||
instead of the default configuration file.
|
||||
This permits users to configure their own manual environment.
|
||||
See
|
||||
.Xr man.conf 5
|
||||
for a description of the contents of this file.
|
||||
.It Fl c
|
||||
Copy the manual page to the standard output instead of using
|
||||
.Xr more 1
|
||||
to paginate it.
|
||||
This is done by default if the standard output is not a terminal device.
|
||||
.It Fl f
|
||||
A synonym for
|
||||
.Xr whatis 1 .
|
||||
It searches for
|
||||
.Ar name
|
||||
in manual page names and displays the header lines from all matching pages.
|
||||
The search is case insensitive and matches whole words only.
|
||||
This overrides any earlier
|
||||
.Fl k
|
||||
and
|
||||
.Fl l
|
||||
options.
|
||||
.It Fl h
|
||||
Display only the SYNOPSIS lines of the requested manual pages.
|
||||
Implies
|
||||
.Fl a
|
||||
and
|
||||
.Fl c .
|
||||
.It Fl k
|
||||
A synonym for
|
||||
.Xr apropos 1 .
|
||||
Instead of
|
||||
.Ar name ,
|
||||
an expression can be provided using the syntax described in the
|
||||
.Xr apropos 1
|
||||
manual.
|
||||
By default, it displays the header lines of all matching pages.
|
||||
This overrides any earlier
|
||||
.Fl f
|
||||
and
|
||||
.Fl l
|
||||
options.
|
||||
.It Fl l
|
||||
A synonym for
|
||||
.Xr mandoc 1
|
||||
.Fl a .
|
||||
The
|
||||
.Ar name
|
||||
arguments are interpreted as filenames.
|
||||
No search is done and
|
||||
.Ar file ,
|
||||
.Ar path ,
|
||||
.Ar section ,
|
||||
and
|
||||
.Ar subsection
|
||||
are ignored.
|
||||
This overrides any earlier
|
||||
.Fl f ,
|
||||
.Fl k ,
|
||||
and
|
||||
.Fl w
|
||||
options.
|
||||
.It Fl M Ar path
|
||||
Override the list of standard directories which
|
||||
.Nm
|
||||
searches for manual pages.
|
||||
The supplied
|
||||
.Ar path
|
||||
must be a colon
|
||||
.Pq Ql \&:
|
||||
separated list of directories.
|
||||
This search path may also be set using the environment variable
|
||||
.Ev MANPATH .
|
||||
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
|
||||
Augment the list of standard directories which
|
||||
.Nm
|
||||
searches for manual pages.
|
||||
The supplied
|
||||
.Ar path
|
||||
must be a colon
|
||||
.Pq Ql \&:
|
||||
separated list of directories.
|
||||
These directories will be searched before the standard directories or
|
||||
the directories specified using the
|
||||
.Fl M
|
||||
option or the
|
||||
.Ev MANPATH
|
||||
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 S Ar subsection
|
||||
Restricts the directories that
|
||||
.Nm
|
||||
will search to those of a specific
|
||||
.Xr machine 1
|
||||
architecture.
|
||||
.Ar subsection
|
||||
is case insensitive.
|
||||
.Pp
|
||||
By default manual pages for all architectures are installed.
|
||||
Therefore this option can be used to view pages for one
|
||||
architecture whilst using another.
|
||||
.Pp
|
||||
This option overrides the
|
||||
.Ev MACHINE
|
||||
environment variable.
|
||||
.It Xo
|
||||
.Op Fl s
|
||||
.Ar section
|
||||
.Xc
|
||||
Restricts the directories that
|
||||
.Nm
|
||||
will search to a specific section.
|
||||
The currently available sections are:
|
||||
.Pp
|
||||
.Bl -tag -width "localXXX" -offset indent -compact
|
||||
.It 1
|
||||
General commands
|
||||
.Pq tools and utilities .
|
||||
.It 2
|
||||
System calls and error numbers.
|
||||
.It 3
|
||||
Libraries.
|
||||
.It 3f
|
||||
Fortran programmer's reference guide.
|
||||
.It 3p
|
||||
.Xr perl 1
|
||||
programmer's reference guide.
|
||||
.It 4
|
||||
Device drivers.
|
||||
.It 5
|
||||
File formats.
|
||||
.It 6
|
||||
Games.
|
||||
.It 7
|
||||
Miscellaneous.
|
||||
.It 8
|
||||
System maintenance and operation commands.
|
||||
.It 9
|
||||
Kernel internals.
|
||||
.It X11
|
||||
An alias for X11R6.
|
||||
.It X11R6
|
||||
X Window System.
|
||||
.It local
|
||||
Pages located in
|
||||
.Pa /usr/local .
|
||||
.It n
|
||||
Tcl/Tk commands.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
configuration file,
|
||||
.Xr man.conf 5 ,
|
||||
specifies the possible
|
||||
.Ar section
|
||||
values, and their search order.
|
||||
Additional sections may be specified.
|
||||
.It Fl V
|
||||
Print version and exit.
|
||||
.It Fl w
|
||||
List the pathnames of the manual pages which
|
||||
.Nm
|
||||
would display for the specified
|
||||
.Ar section
|
||||
and
|
||||
.Ar name
|
||||
combination.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility also supports the options
|
||||
.Fl IKOTW
|
||||
described in the
|
||||
.Xr mandoc 1
|
||||
manual.
|
||||
.Pp
|
||||
Guidelines for writing
|
||||
man pages can be found in
|
||||
.Xr mdoc 7 .
|
||||
.Pp
|
||||
If both a formatted and an unformatted version of the same manual page,
|
||||
for example
|
||||
.Pa cat1/foo.0
|
||||
and
|
||||
.Pa man1/foo.1 ,
|
||||
exist in the same directory, and at least one of them is selected,
|
||||
only the newer one is used.
|
||||
However, if both the
|
||||
.Fl a
|
||||
and the
|
||||
.Fl w
|
||||
options are specified, both file names are printed.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width MANPATHX
|
||||
.It Ev MACHINE
|
||||
As some manual pages are intended only for specific architectures,
|
||||
.Nm
|
||||
searches any subdirectories,
|
||||
with the same name as the current architecture,
|
||||
in every directory which it searches.
|
||||
Machine specific areas are checked before general areas.
|
||||
The current machine type may be overridden by setting the environment
|
||||
variable
|
||||
.Ev MACHINE
|
||||
to the name of a specific architecture,
|
||||
or with the
|
||||
.Fl S
|
||||
option.
|
||||
.Ev MACHINE
|
||||
is case insensitive.
|
||||
.It Ev MANPAGER
|
||||
Any non-empty value of the environment variable
|
||||
.Ev MANPAGER
|
||||
will be used instead of the standard pagination program,
|
||||
.Xr more 1 .
|
||||
.It Ev MANPATH
|
||||
The standard search path used by
|
||||
.Nm
|
||||
may be overridden by specifying a path in the
|
||||
.Ev MANPATH
|
||||
environment
|
||||
variable.
|
||||
The format of the path is a colon
|
||||
.Pq Ql \&:
|
||||
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
|
||||
Specifies the pagination program to use when
|
||||
.Ev MANPAGER
|
||||
is not defined.
|
||||
If neither PAGER nor MANPAGER is defined,
|
||||
.Pa /usr/bin/more Fl s
|
||||
will be used.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/man.conf -compact
|
||||
.It Pa /etc/man.conf
|
||||
default man configuration file
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std man
|
||||
.Sh SEE ALSO
|
||||
.Xr apropos 1 ,
|
||||
.Xr intro 1 ,
|
||||
.Xr whatis 1 ,
|
||||
.Xr whereis 1 ,
|
||||
.Xr intro 2 ,
|
||||
.Xr intro 3 ,
|
||||
.Xr intro 4 ,
|
||||
.Xr intro 5 ,
|
||||
.Xr man.conf 5 ,
|
||||
.Xr intro 6 ,
|
||||
.Xr intro 7 ,
|
||||
.Xr mdoc 7 ,
|
||||
.Xr intro 8 ,
|
||||
.Xr intro 9
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is compliant with the
|
||||
.St -p1003.1-2008
|
||||
specification.
|
||||
.Pp
|
||||
The flags
|
||||
.Op Fl aCcfhMmSsw ,
|
||||
as well as the environment variables
|
||||
.Ev MACHINE ,
|
||||
.Ev MANPAGER ,
|
||||
and
|
||||
.Ev MANPATH ,
|
||||
are extensions to that specification.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command first appeared in
|
||||
.At v3 .
|
||||
.Pp
|
||||
The
|
||||
.Fl w
|
||||
option first appeared in
|
||||
.At v7 ;
|
||||
.Fl f
|
||||
and
|
||||
.Fl k
|
||||
in
|
||||
.Bx 4 ;
|
||||
.Fl M
|
||||
in
|
||||
.Bx 4.3 ;
|
||||
.Fl a
|
||||
in
|
||||
.Bx 4.3 Tahoe ;
|
||||
.Fl c
|
||||
and
|
||||
.Fl m
|
||||
in
|
||||
.Bx 4.3 Reno ;
|
||||
.Fl h
|
||||
in
|
||||
.Bx 4.3 Net/2 ;
|
||||
.Fl C
|
||||
in
|
||||
.Nx 1.0 ;
|
||||
and
|
||||
.Fl s
|
||||
and
|
||||
.Fl S
|
||||
in
|
||||
.Ox 2.3 .
|
246
man.c
246
man.c
@ -1,4 +1,4 @@
|
||||
/* $Id: man.c,v 1.137 2014/08/01 21:24:17 schwarze Exp $ */
|
||||
/* $Id: man.c,v 1.145 2014/11/28 06:27:05 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -16,9 +16,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -52,8 +50,7 @@ const char * const *man_macronames = __man_macronames;
|
||||
|
||||
static struct man_node *man_node_alloc(struct man *, int, int,
|
||||
enum man_type, enum mant);
|
||||
static int man_node_append(struct man *,
|
||||
struct man_node *);
|
||||
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 *);
|
||||
@ -61,7 +58,7 @@ static int man_ptext(struct man *, int, char *, int);
|
||||
static int man_pmacro(struct man *, int, char *, int);
|
||||
static void man_free1(struct man *);
|
||||
static void man_alloc1(struct man *);
|
||||
static int man_descope(struct man *, int, int);
|
||||
static void man_descope(struct man *, int, int);
|
||||
|
||||
|
||||
const struct man_node *
|
||||
@ -114,14 +111,16 @@ int
|
||||
man_endparse(struct man *man)
|
||||
{
|
||||
|
||||
return(man_macroend(man));
|
||||
man_macroend(man);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
man_parseln(struct man *man, int ln, char *buf, int offs)
|
||||
{
|
||||
|
||||
man->flags |= MAN_NEWLINE;
|
||||
if (man->last->type != MAN_EQN || ln > man->last->line)
|
||||
man->flags |= MAN_NEWLINE;
|
||||
|
||||
return (roff_getcontrol(man->roff, buf, &offs) ?
|
||||
man_pmacro(man, ln, buf, offs) :
|
||||
@ -134,16 +133,11 @@ man_free1(struct man *man)
|
||||
|
||||
if (man->first)
|
||||
man_node_delete(man, man->first);
|
||||
if (man->meta.title)
|
||||
free(man->meta.title);
|
||||
if (man->meta.source)
|
||||
free(man->meta.source);
|
||||
if (man->meta.date)
|
||||
free(man->meta.date);
|
||||
if (man->meta.vol)
|
||||
free(man->meta.vol);
|
||||
if (man->meta.msec)
|
||||
free(man->meta.msec);
|
||||
free(man->meta.title);
|
||||
free(man->meta.source);
|
||||
free(man->meta.date);
|
||||
free(man->meta.vol);
|
||||
free(man->meta.msec);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -160,13 +154,13 @@ man_alloc1(struct man *man)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
static void
|
||||
man_node_append(struct man *man, struct man_node *p)
|
||||
{
|
||||
|
||||
assert(man->last);
|
||||
assert(man->first);
|
||||
assert(MAN_ROOT != p->type);
|
||||
assert(p->type != MAN_ROOT);
|
||||
|
||||
switch (man->next) {
|
||||
case MAN_NEXT_SIBLING:
|
||||
@ -192,15 +186,11 @@ man_node_append(struct man *man, struct man_node *p)
|
||||
man->flags &= ~MAN_LITERAL;
|
||||
break;
|
||||
case MAN_HEAD:
|
||||
assert(MAN_BLOCK == p->parent->type);
|
||||
assert(p->parent->type == MAN_BLOCK);
|
||||
p->parent->head = p;
|
||||
break;
|
||||
case MAN_TAIL:
|
||||
assert(MAN_BLOCK == p->parent->type);
|
||||
p->parent->tail = p;
|
||||
break;
|
||||
case MAN_BODY:
|
||||
assert(MAN_BLOCK == p->parent->type);
|
||||
assert(p->parent->type == MAN_BLOCK);
|
||||
p->parent->body = p;
|
||||
break;
|
||||
default:
|
||||
@ -213,14 +203,11 @@ man_node_append(struct man *man, struct man_node *p)
|
||||
case MAN_TBL:
|
||||
/* FALLTHROUGH */
|
||||
case MAN_TEXT:
|
||||
if ( ! man_valid_post(man))
|
||||
return(0);
|
||||
man_valid_post(man);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static struct man_node *
|
||||
@ -235,85 +222,76 @@ man_node_alloc(struct man *man, int line, int pos,
|
||||
p->type = type;
|
||||
p->tok = tok;
|
||||
|
||||
if (MAN_NEWLINE & man->flags)
|
||||
if (man->flags & MAN_NEWLINE)
|
||||
p->flags |= MAN_LINE;
|
||||
man->flags &= ~MAN_NEWLINE;
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
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);
|
||||
if ( ! man_node_append(man, p))
|
||||
return(0);
|
||||
man_node_append(man, p);
|
||||
man->next = MAN_NEXT_CHILD;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
man_tail_alloc(struct man *man, int line, int pos, enum mant tok)
|
||||
{
|
||||
struct man_node *p;
|
||||
|
||||
p = man_node_alloc(man, line, pos, MAN_TAIL, tok);
|
||||
if ( ! man_node_append(man, p))
|
||||
return(0);
|
||||
man->next = MAN_NEXT_CHILD;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
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);
|
||||
if ( ! man_node_append(man, p))
|
||||
return(0);
|
||||
man_node_append(man, p);
|
||||
man->next = MAN_NEXT_CHILD;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
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);
|
||||
if ( ! man_node_append(man, p))
|
||||
return(0);
|
||||
man_node_append(man, p);
|
||||
man->next = MAN_NEXT_CHILD;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
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);
|
||||
if ( ! man_node_append(man, p))
|
||||
return(0);
|
||||
man_node_append(man, p);
|
||||
man->next = MAN_NEXT_CHILD;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
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);
|
||||
|
||||
if ( ! man_node_append(man, n))
|
||||
return(0);
|
||||
|
||||
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;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -324,8 +302,7 @@ static void
|
||||
man_node_free(struct man_node *p)
|
||||
{
|
||||
|
||||
if (p->string)
|
||||
free(p->string);
|
||||
free(p->string);
|
||||
free(p);
|
||||
}
|
||||
|
||||
@ -340,37 +317,33 @@ man_node_delete(struct man *man, struct man_node *p)
|
||||
man_node_free(p);
|
||||
}
|
||||
|
||||
int
|
||||
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 ( ! man_node_append(man, n))
|
||||
return(0);
|
||||
|
||||
if (ep->ln > man->last->line)
|
||||
n->flags |= MAN_LINE;
|
||||
man_node_append(man, n);
|
||||
man->next = MAN_NEXT_SIBLING;
|
||||
return(man_descope(man, ep->ln, ep->pos));
|
||||
man_descope(man, ep->ln, ep->pos);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
man_addspan(struct man *man, const struct tbl_span *sp)
|
||||
{
|
||||
struct man_node *n;
|
||||
|
||||
n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX);
|
||||
n->span = sp;
|
||||
|
||||
if ( ! man_node_append(man, n))
|
||||
return(0);
|
||||
|
||||
man_node_append(man, n);
|
||||
man->next = MAN_NEXT_SIBLING;
|
||||
return(man_descope(man, sp->line, 0));
|
||||
man_descope(man, sp->line, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
man_descope(struct man *man, int line, int offs)
|
||||
{
|
||||
/*
|
||||
@ -379,19 +352,15 @@ man_descope(struct man *man, int line, int offs)
|
||||
* out the block scope (also if applicable).
|
||||
*/
|
||||
|
||||
if (MAN_ELINE & man->flags) {
|
||||
if (man->flags & MAN_ELINE) {
|
||||
man->flags &= ~MAN_ELINE;
|
||||
if ( ! man_unscope(man, man->last->parent))
|
||||
return(0);
|
||||
man_unscope(man, man->last->parent);
|
||||
}
|
||||
|
||||
if ( ! (MAN_BLINE & man->flags))
|
||||
return(1);
|
||||
if ( ! (man->flags & MAN_BLINE))
|
||||
return;
|
||||
man->flags &= ~MAN_BLINE;
|
||||
|
||||
if ( ! man_unscope(man, man->last->parent))
|
||||
return(0);
|
||||
return(man_body_alloc(man, line, offs, man->last->tok));
|
||||
man_unscope(man, man->last->parent);
|
||||
man_body_alloc(man, line, offs, man->last->tok);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -401,13 +370,13 @@ man_ptext(struct man *man, int line, char *buf, int offs)
|
||||
|
||||
/* Literal free-form text whitespace is preserved. */
|
||||
|
||||
if (MAN_LITERAL & man->flags) {
|
||||
if ( ! man_word_alloc(man, line, offs, buf + offs))
|
||||
return(0);
|
||||
return(man_descope(man, line, offs));
|
||||
if (man->flags & MAN_LITERAL) {
|
||||
man_word_alloc(man, line, offs, buf + offs);
|
||||
man_descope(man, line, offs);
|
||||
return(1);
|
||||
}
|
||||
|
||||
for (i = offs; ' ' == buf[i]; i++)
|
||||
for (i = offs; buf[i] == ' '; i++)
|
||||
/* Skip leading whitespace. */ ;
|
||||
|
||||
/*
|
||||
@ -415,12 +384,11 @@ man_ptext(struct man *man, int line, char *buf, int offs)
|
||||
* but add a single vertical space elsewhere.
|
||||
*/
|
||||
|
||||
if ('\0' == buf[i]) {
|
||||
if (buf[i] == '\0') {
|
||||
/* Allocate a blank entry. */
|
||||
if (MAN_SH != man->last->tok &&
|
||||
MAN_SS != man->last->tok) {
|
||||
if ( ! man_elem_alloc(man, line, offs, MAN_sp))
|
||||
return(0);
|
||||
if (man->last->tok != MAN_SH &&
|
||||
man->last->tok != MAN_SS) {
|
||||
man_elem_alloc(man, line, offs, MAN_sp);
|
||||
man->next = MAN_NEXT_SIBLING;
|
||||
}
|
||||
return(1);
|
||||
@ -447,9 +415,7 @@ man_ptext(struct man *man, int line, char *buf, int offs)
|
||||
|
||||
buf[i] = '\0';
|
||||
}
|
||||
|
||||
if ( ! man_word_alloc(man, line, offs, buf + offs))
|
||||
return(0);
|
||||
man_word_alloc(man, line, offs, buf + offs);
|
||||
|
||||
/*
|
||||
* End-of-sentence check. If the last character is an unescaped
|
||||
@ -461,50 +427,59 @@ man_ptext(struct man *man, int line, char *buf, int offs)
|
||||
if (mandoc_eos(buf, (size_t)i))
|
||||
man->last->flags |= MAN_EOS;
|
||||
|
||||
return(man_descope(man, line, offs));
|
||||
man_descope(man, line, offs);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
man_pmacro(struct man *man, int ln, char *buf, int offs)
|
||||
{
|
||||
char mac[5];
|
||||
struct man_node *n;
|
||||
const char *cp;
|
||||
enum mant tok;
|
||||
int i, ppos;
|
||||
int bline;
|
||||
|
||||
if ('"' == buf[offs]) {
|
||||
mandoc_msg(MANDOCERR_COMMENT_BAD, man->parse,
|
||||
ln, offs, NULL);
|
||||
return(1);
|
||||
} else if ('\0' == buf[offs])
|
||||
return(1);
|
||||
char mac[5];
|
||||
|
||||
ppos = offs;
|
||||
|
||||
/*
|
||||
* Copy the first word into a nil-terminated buffer.
|
||||
* Stop copying when a tab, space, or eoln is encountered.
|
||||
* Stop when a space, tab, escape, or eoln is encountered.
|
||||
*/
|
||||
|
||||
i = 0;
|
||||
while (i < 4 && '\0' != buf[offs] && ' ' != buf[offs] &&
|
||||
'\t' != buf[offs])
|
||||
while (i < 4 && strchr(" \t\\", buf[offs]) == NULL)
|
||||
mac[i++] = buf[offs++];
|
||||
|
||||
mac[i] = '\0';
|
||||
|
||||
tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
|
||||
|
||||
if (MAN_MAX == tok) {
|
||||
if (tok == MAN_MAX) {
|
||||
mandoc_msg(MANDOCERR_MACRO, man->parse,
|
||||
ln, ppos, buf + ppos - 1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* The macro is sane. Jump to the next word. */
|
||||
/* Skip a leading escape sequence or tab. */
|
||||
|
||||
while (buf[offs] && ' ' == buf[offs])
|
||||
switch (buf[offs]) {
|
||||
case '\\':
|
||||
cp = buf + offs + 1;
|
||||
mandoc_escape(&cp, NULL, NULL);
|
||||
offs = cp - buf;
|
||||
break;
|
||||
case '\t':
|
||||
offs++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Jump to the next non-whitespace word. */
|
||||
|
||||
while (buf[offs] && buf[offs] == ' ')
|
||||
offs++;
|
||||
|
||||
/*
|
||||
@ -512,7 +487,7 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
|
||||
* into the parser as "text", so we only warn about spaces here.
|
||||
*/
|
||||
|
||||
if ('\0' == buf[offs] && ' ' == buf[offs - 1])
|
||||
if (buf[offs] == '\0' && buf[offs - 1] == ' ')
|
||||
mandoc_msg(MANDOCERR_SPACE_EOL, man->parse,
|
||||
ln, offs - 1, NULL);
|
||||
|
||||
@ -522,14 +497,14 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
|
||||
* macros---they don't print text---so we let those slip by.
|
||||
*/
|
||||
|
||||
if ( ! (MAN_NSCOPED & man_macros[tok].flags) &&
|
||||
if ( ! (man_macros[tok].flags & MAN_NSCOPED) &&
|
||||
man->flags & MAN_ELINE) {
|
||||
n = man->last;
|
||||
assert(MAN_TEXT != n->type);
|
||||
|
||||
/* Remove repeated NSCOPED macros causing ELINE. */
|
||||
|
||||
if (MAN_NSCOPED & man_macros[n->tok].flags)
|
||||
if (man_macros[n->tok].flags & MAN_NSCOPED)
|
||||
n = n->parent;
|
||||
|
||||
mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, n->line,
|
||||
@ -544,24 +519,24 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
|
||||
* Remove prior BLINE macro that is being clobbered.
|
||||
*/
|
||||
if ((man->flags & MAN_BLINE) &&
|
||||
(MAN_BSCOPE & man_macros[tok].flags)) {
|
||||
(man_macros[tok].flags & MAN_BSCOPE)) {
|
||||
n = man->last;
|
||||
|
||||
/* Might be a text node like 8 in
|
||||
* .TP 8
|
||||
* .SH foo
|
||||
*/
|
||||
if (MAN_TEXT == n->type)
|
||||
if (n->type == MAN_TEXT)
|
||||
n = n->parent;
|
||||
|
||||
/* Remove element that didn't end BLINE, if any. */
|
||||
if ( ! (MAN_BSCOPE & man_macros[n->tok].flags))
|
||||
if ( ! (man_macros[n->tok].flags & MAN_BSCOPE))
|
||||
n = n->parent;
|
||||
|
||||
assert(MAN_HEAD == n->type);
|
||||
assert(n->type == MAN_HEAD);
|
||||
n = n->parent;
|
||||
assert(MAN_BLOCK == n->type);
|
||||
assert(MAN_SCOPED & man_macros[n->tok].flags);
|
||||
assert(n->type == MAN_BLOCK);
|
||||
assert(man_macros[n->tok].flags & MAN_SCOPED);
|
||||
|
||||
mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, n->line,
|
||||
n->pos, "%s breaks %s", man_macronames[tok],
|
||||
@ -578,14 +553,13 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
|
||||
/* Call to handler... */
|
||||
|
||||
assert(man_macros[tok].fp);
|
||||
if ( ! (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf))
|
||||
return(0);
|
||||
(*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf);
|
||||
|
||||
/* In quick mode (for mandocdb), abort after the NAME section. */
|
||||
|
||||
if (man->quick && MAN_SH == tok) {
|
||||
if (man->quick && tok == MAN_SH) {
|
||||
n = man->last;
|
||||
if (MAN_BODY == n->type &&
|
||||
if (n->type == MAN_BODY &&
|
||||
strcmp(n->prev->child->string, "NAME"))
|
||||
return(2);
|
||||
}
|
||||
@ -600,12 +574,12 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
|
||||
man_macros[tok].flags & MAN_NSCOPED)
|
||||
return(1);
|
||||
|
||||
assert(MAN_BLINE & man->flags);
|
||||
assert(man->flags & MAN_BLINE);
|
||||
man->flags &= ~MAN_BLINE;
|
||||
|
||||
if ( ! man_unscope(man, man->last->parent))
|
||||
return(0);
|
||||
return(man_body_alloc(man, ln, ppos, man->last->tok));
|
||||
man_unscope(man, man->last->parent);
|
||||
man_body_alloc(man, ln, ppos, man->last->tok);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -663,7 +637,7 @@ man_deroff(char **dest, const struct man_node *n)
|
||||
char *cp;
|
||||
size_t sz;
|
||||
|
||||
if (MAN_TEXT != n->type) {
|
||||
if (n->type != MAN_TEXT) {
|
||||
for (n = n->child; n; n = n->next)
|
||||
man_deroff(dest, n);
|
||||
return;
|
||||
|
12
man.cgi.8
12
man.cgi.8
@ -1,4 +1,4 @@
|
||||
.\" $Id: man.cgi.8,v 1.9 2014/07/22 18:14:13 schwarze Exp $
|
||||
.\" $Id: man.cgi.8,v 1.11 2014/09/14 19:44:28 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
@ -14,7 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: July 22 2014 $
|
||||
.Dd $Mdocdate: September 14 2014 $
|
||||
.Dt MAN.CGI 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -43,6 +43,12 @@ either a name of a manual page or an
|
||||
using the syntax described in the
|
||||
.Xr apropos 1
|
||||
manual; filling this in is required for each search.
|
||||
.Pp
|
||||
The expression is broken into words at whitespace.
|
||||
Whitespace characters and backslashes can be escaped
|
||||
by prepending a backslash.
|
||||
The effect of prepending a backslash to another character is undefined;
|
||||
in the current implementation, it has no effect.
|
||||
.It
|
||||
A
|
||||
.Dq Submit
|
||||
@ -307,7 +313,7 @@ and ending before the
|
||||
.Ev QUERY_STRING .
|
||||
It is used by the
|
||||
.Cm show
|
||||
page to aquire the manpath and filename it needs.
|
||||
page to acquire the manpath and filename it needs.
|
||||
.It Ev QUERY_STRING
|
||||
The HTTP query string passed from the client to the server.
|
||||
It is the final part of the URI, after the question mark.
|
||||
|
3
man.h
3
man.h
@ -1,4 +1,4 @@
|
||||
/* $Id: man.h,v 1.65 2014/06/20 23:02:31 schwarze Exp $ */
|
||||
/* $Id: man.h,v 1.66 2014/11/28 05:51:32 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -68,7 +68,6 @@ enum man_type {
|
||||
MAN_BLOCK,
|
||||
MAN_HEAD,
|
||||
MAN_BODY,
|
||||
MAN_TAIL,
|
||||
MAN_TBL,
|
||||
MAN_EQN
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: man_hash.c,v 1.27 2014/04/20 16:46:04 schwarze Exp $ */
|
||||
/* $Id: man_hash.c,v 1.28 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,9 +14,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
63
man_html.c
63
man_html.c
@ -1,6 +1,6 @@
|
||||
/* $Id: man_html.c,v 1.96 2014/08/01 19:25:52 schwarze Exp $ */
|
||||
/* $Id: man_html.c,v 1.104 2014/09/27 11:17:19 kristaps Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -144,7 +142,7 @@ print_bvspace(struct html *h, const struct man_node *n)
|
||||
if (NULL == n->prev)
|
||||
return;
|
||||
|
||||
print_otag(h, TAG_P, 0, NULL);
|
||||
print_paragraph(h);
|
||||
}
|
||||
|
||||
void
|
||||
@ -221,7 +219,7 @@ print_man_node(MAN_ARGS)
|
||||
* before printing the line's data.
|
||||
*/
|
||||
if ('\0' == *n->string) {
|
||||
print_otag(h, TAG_P, 0, NULL);
|
||||
print_paragraph(h);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -301,7 +299,7 @@ a2width(const struct man_node *n, struct roffsu *su)
|
||||
static void
|
||||
man_root_pre(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag[3];
|
||||
struct htmlpair tag;
|
||||
struct tag *t, *tt;
|
||||
char *title;
|
||||
|
||||
@ -309,34 +307,26 @@ man_root_pre(MAN_ARGS)
|
||||
assert(man->msec);
|
||||
mandoc_asprintf(&title, "%s(%s)", man->title, man->msec);
|
||||
|
||||
PAIR_SUMMARY_INIT(&tag[0], "Document Header");
|
||||
PAIR_CLASS_INIT(&tag[1], "head");
|
||||
PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
|
||||
t = print_otag(h, TAG_TABLE, 3, tag);
|
||||
PAIR_INIT(&tag[0], ATTR_WIDTH, "30%");
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
PAIR_CLASS_INIT(&tag, "head");
|
||||
t = print_otag(h, TAG_TABLE, 1, &tag);
|
||||
|
||||
print_otag(h, TAG_TBODY, 0, NULL);
|
||||
|
||||
tt = print_otag(h, TAG_TR, 0, NULL);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "head-ltitle");
|
||||
print_otag(h, TAG_TD, 1, tag);
|
||||
PAIR_CLASS_INIT(&tag, "head-ltitle");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_text(h, title);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "head-vol");
|
||||
PAIR_INIT(&tag[1], ATTR_ALIGN, "center");
|
||||
print_otag(h, TAG_TD, 2, tag);
|
||||
PAIR_CLASS_INIT(&tag, "head-vol");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
if (NULL != man->vol)
|
||||
print_text(h, man->vol);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "head-rtitle");
|
||||
PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
|
||||
print_otag(h, TAG_TD, 2, tag);
|
||||
PAIR_CLASS_INIT(&tag, "head-rtitle");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_text(h, title);
|
||||
print_tagq(h, t);
|
||||
free(title);
|
||||
@ -345,29 +335,23 @@ man_root_pre(MAN_ARGS)
|
||||
static void
|
||||
man_root_post(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag[3];
|
||||
struct htmlpair tag;
|
||||
struct tag *t, *tt;
|
||||
|
||||
PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
|
||||
PAIR_CLASS_INIT(&tag[1], "foot");
|
||||
PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
|
||||
t = print_otag(h, TAG_TABLE, 3, tag);
|
||||
PAIR_INIT(&tag[0], ATTR_WIDTH, "50%");
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
PAIR_CLASS_INIT(&tag, "foot");
|
||||
t = print_otag(h, TAG_TABLE, 1, &tag);
|
||||
|
||||
tt = print_otag(h, TAG_TR, 0, NULL);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "foot-date");
|
||||
print_otag(h, TAG_TD, 1, tag);
|
||||
PAIR_CLASS_INIT(&tag, "foot-date");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
|
||||
assert(man->date);
|
||||
print_text(h, man->date);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "foot-os");
|
||||
PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
|
||||
print_otag(h, TAG_TD, 2, tag);
|
||||
PAIR_CLASS_INIT(&tag, "foot-os");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
|
||||
if (man->source)
|
||||
print_text(h, man->source);
|
||||
@ -554,7 +538,7 @@ man_IP_pre(MAN_ARGS)
|
||||
static int
|
||||
man_HP_pre(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
struct htmlpair tag[2];
|
||||
struct roffsu su;
|
||||
const struct man_node *np;
|
||||
|
||||
@ -574,8 +558,9 @@ man_HP_pre(MAN_ARGS)
|
||||
bufcat_su(h, "margin-left", &su);
|
||||
su.scale = -su.scale;
|
||||
bufcat_su(h, "text-indent", &su);
|
||||
PAIR_STYLE_INIT(&tag, h);
|
||||
print_otag(h, TAG_P, 1, &tag);
|
||||
PAIR_STYLE_INIT(&tag[0], h);
|
||||
PAIR_CLASS_INIT(&tag[1], "spacer");
|
||||
print_otag(h, TAG_DIV, 2, tag);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
171
man_macro.c
171
man_macro.c
@ -1,7 +1,7 @@
|
||||
/* $Id: man_macro.c,v 1.87 2014/07/30 23:01:39 schwarze Exp $ */
|
||||
/* $Id: man_macro.c,v 1.91 2014/11/28 05:51:32 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -16,9 +16,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@ -36,14 +36,14 @@ enum rew {
|
||||
REW_HALT
|
||||
};
|
||||
|
||||
static int blk_close(MACRO_PROT_ARGS);
|
||||
static int blk_exp(MACRO_PROT_ARGS);
|
||||
static int blk_imp(MACRO_PROT_ARGS);
|
||||
static int in_line_eoln(MACRO_PROT_ARGS);
|
||||
static void blk_close(MACRO_PROT_ARGS);
|
||||
static void blk_exp(MACRO_PROT_ARGS);
|
||||
static void blk_imp(MACRO_PROT_ARGS);
|
||||
static void in_line_eoln(MACRO_PROT_ARGS);
|
||||
static int man_args(struct man *, int,
|
||||
int *, char *, char **);
|
||||
|
||||
static int rew_scope(enum man_type,
|
||||
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 *);
|
||||
@ -61,15 +61,15 @@ const struct man_macro __man_macros[MAN_MAX] = {
|
||||
{ blk_imp, MAN_BSCOPE }, /* P */
|
||||
{ blk_imp, MAN_BSCOPE }, /* IP */
|
||||
{ blk_imp, MAN_BSCOPE }, /* HP */
|
||||
{ in_line_eoln, MAN_SCOPED }, /* SM */
|
||||
{ in_line_eoln, MAN_SCOPED }, /* SB */
|
||||
{ in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* SM */
|
||||
{ in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* SB */
|
||||
{ in_line_eoln, 0 }, /* BI */
|
||||
{ in_line_eoln, 0 }, /* IB */
|
||||
{ in_line_eoln, 0 }, /* BR */
|
||||
{ in_line_eoln, 0 }, /* RB */
|
||||
{ in_line_eoln, MAN_SCOPED }, /* R */
|
||||
{ in_line_eoln, MAN_SCOPED }, /* B */
|
||||
{ in_line_eoln, MAN_SCOPED }, /* I */
|
||||
{ in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* R */
|
||||
{ in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* B */
|
||||
{ in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* I */
|
||||
{ in_line_eoln, 0 }, /* IR */
|
||||
{ in_line_eoln, 0 }, /* RI */
|
||||
{ in_line_eoln, MAN_NSCOPED }, /* na */
|
||||
@ -95,12 +95,11 @@ const struct man_macro __man_macros[MAN_MAX] = {
|
||||
const struct man_macro * const man_macros = __man_macros;
|
||||
|
||||
|
||||
int
|
||||
void
|
||||
man_unscope(struct man *man, const struct man_node *to)
|
||||
{
|
||||
struct man_node *n;
|
||||
|
||||
man->next = MAN_NEXT_SIBLING;
|
||||
to = to->parent;
|
||||
n = man->last;
|
||||
while (n != to) {
|
||||
@ -139,20 +138,29 @@ man_unscope(struct man *man, const struct man_node *to)
|
||||
* Save a pointer to the parent such that
|
||||
* we know where to continue the iteration.
|
||||
*/
|
||||
|
||||
man->last = n;
|
||||
n = n->parent;
|
||||
if ( ! man_valid_post(man))
|
||||
return(0);
|
||||
man_valid_post(man);
|
||||
}
|
||||
return(1);
|
||||
|
||||
/*
|
||||
* If we ended up at the parent of the node we were
|
||||
* supposed to rewind to, that means the target node
|
||||
* got deleted, so add the next node we parse as a child
|
||||
* of the parent instead of as a sibling of the target.
|
||||
*/
|
||||
|
||||
man->next = (man->last == to) ?
|
||||
MAN_NEXT_CHILD : MAN_NEXT_SIBLING;
|
||||
}
|
||||
|
||||
static enum rew
|
||||
rew_block(enum mant ntok, enum man_type type, const struct man_node *n)
|
||||
{
|
||||
|
||||
if (MAN_BLOCK == type && ntok == n->parent->tok &&
|
||||
MAN_BODY == n->parent->type)
|
||||
if (type == MAN_BLOCK && ntok == n->parent->tok &&
|
||||
n->parent->type == MAN_BODY)
|
||||
return(REW_REWIND);
|
||||
return(ntok == n->tok ? REW_HALT : REW_NOHALT);
|
||||
}
|
||||
@ -235,7 +243,7 @@ rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
|
||||
* for example, the `SH' macro will close out any intervening `SS'
|
||||
* scopes. When a scope is closed, it must be validated and actioned.
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
rew_scope(enum man_type type, struct man *man, enum mant tok)
|
||||
{
|
||||
struct man_node *n;
|
||||
@ -249,7 +257,7 @@ rew_scope(enum man_type type, struct man *man, enum mant tok)
|
||||
*/
|
||||
c = rew_dohalt(tok, type, n);
|
||||
if (REW_HALT == c)
|
||||
return(1);
|
||||
return;
|
||||
if (REW_REWIND == c)
|
||||
break;
|
||||
}
|
||||
@ -258,16 +266,15 @@ rew_scope(enum man_type type, struct man *man, enum mant tok)
|
||||
* Rewind until the current point. Warn if we're a roff
|
||||
* instruction that's mowing over explicit scopes.
|
||||
*/
|
||||
assert(n);
|
||||
|
||||
return(man_unscope(man, n));
|
||||
man_unscope(man, n);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close out a generic explicit macro.
|
||||
*/
|
||||
int
|
||||
void
|
||||
blk_close(MACRO_PROT_ARGS)
|
||||
{
|
||||
enum mant ntok;
|
||||
@ -286,57 +293,46 @@ blk_close(MACRO_PROT_ARGS)
|
||||
}
|
||||
|
||||
for (nn = man->last->parent; nn; nn = nn->parent)
|
||||
if (ntok == nn->tok && MAN_BLOCK == nn->type)
|
||||
if (nn->tok == ntok && nn->type == MAN_BLOCK)
|
||||
break;
|
||||
|
||||
if (NULL == nn) {
|
||||
if (nn == NULL) {
|
||||
mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
|
||||
line, ppos, man_macronames[tok]);
|
||||
if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))
|
||||
return(0);
|
||||
rew_scope(MAN_BLOCK, man, MAN_PP);
|
||||
} else
|
||||
man_unscope(man, nn);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
blk_exp(MACRO_PROT_ARGS)
|
||||
{
|
||||
struct man_node *n;
|
||||
int la;
|
||||
char *p;
|
||||
|
||||
/* Close out prior implicit scopes. */
|
||||
|
||||
if ( ! rew_scope(MAN_BLOCK, man, tok))
|
||||
return(0);
|
||||
|
||||
if ( ! man_block_alloc(man, line, ppos, tok))
|
||||
return(0);
|
||||
if ( ! man_head_alloc(man, line, ppos, tok))
|
||||
return(0);
|
||||
rew_scope(MAN_BLOCK, man, tok);
|
||||
man_block_alloc(man, line, ppos, tok);
|
||||
man_head_alloc(man, line, ppos, tok);
|
||||
|
||||
for (;;) {
|
||||
la = *pos;
|
||||
if ( ! man_args(man, line, pos, buf, &p))
|
||||
break;
|
||||
if ( ! man_word_alloc(man, line, la, p))
|
||||
return(0);
|
||||
man_word_alloc(man, line, la, p);
|
||||
}
|
||||
|
||||
assert(man);
|
||||
assert(tok != MAN_MAX);
|
||||
|
||||
for (n = man->last; n; n = n->parent) {
|
||||
if (n->tok != tok)
|
||||
continue;
|
||||
assert(MAN_HEAD == n->type);
|
||||
man_unscope(man, n);
|
||||
break;
|
||||
}
|
||||
for (n = man->last; n; n = n->parent)
|
||||
if (n->tok == tok) {
|
||||
assert(n->type == MAN_HEAD);
|
||||
man_unscope(man, n);
|
||||
break;
|
||||
}
|
||||
|
||||
return(man_body_alloc(man, line, ppos, tok));
|
||||
man_body_alloc(man, line, ppos, tok);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -345,27 +341,17 @@ blk_exp(MACRO_PROT_ARGS)
|
||||
* scopes, such as `SH' closing out an `SS', are defined in the rew
|
||||
* routines.
|
||||
*/
|
||||
int
|
||||
void
|
||||
blk_imp(MACRO_PROT_ARGS)
|
||||
{
|
||||
int la;
|
||||
char *p;
|
||||
struct man_node *n;
|
||||
|
||||
/* Close out prior scopes. */
|
||||
|
||||
if ( ! rew_scope(MAN_BODY, man, tok))
|
||||
return(0);
|
||||
if ( ! rew_scope(MAN_BLOCK, man, tok))
|
||||
return(0);
|
||||
|
||||
/* Allocate new block & head scope. */
|
||||
|
||||
if ( ! man_block_alloc(man, line, ppos, tok))
|
||||
return(0);
|
||||
if ( ! man_head_alloc(man, line, ppos, tok))
|
||||
return(0);
|
||||
|
||||
rew_scope(MAN_BODY, man, tok);
|
||||
rew_scope(MAN_BLOCK, man, tok);
|
||||
man_block_alloc(man, line, ppos, tok);
|
||||
man_head_alloc(man, line, ppos, tok);
|
||||
n = man->last;
|
||||
|
||||
/* Add line arguments. */
|
||||
@ -374,46 +360,44 @@ blk_imp(MACRO_PROT_ARGS)
|
||||
la = *pos;
|
||||
if ( ! man_args(man, line, pos, buf, &p))
|
||||
break;
|
||||
if ( ! man_word_alloc(man, line, la, p))
|
||||
return(0);
|
||||
man_word_alloc(man, line, la, p);
|
||||
}
|
||||
|
||||
/* Close out head and open body (unless MAN_SCOPE). */
|
||||
|
||||
if (MAN_SCOPED & man_macros[tok].flags) {
|
||||
if (man_macros[tok].flags & MAN_SCOPED) {
|
||||
/* If we're forcing scope (`TP'), keep it open. */
|
||||
if (MAN_FSCOPED & man_macros[tok].flags) {
|
||||
if (man_macros[tok].flags & MAN_FSCOPED) {
|
||||
man->flags |= MAN_BLINE;
|
||||
return(1);
|
||||
return;
|
||||
} else if (n == man->last) {
|
||||
man->flags |= MAN_BLINE;
|
||||
return(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! rew_scope(MAN_HEAD, man, tok))
|
||||
return(0);
|
||||
return(man_body_alloc(man, line, ppos, tok));
|
||||
rew_scope(MAN_HEAD, man, tok);
|
||||
man_body_alloc(man, line, ppos, tok);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
in_line_eoln(MACRO_PROT_ARGS)
|
||||
{
|
||||
int la;
|
||||
char *p;
|
||||
struct man_node *n;
|
||||
|
||||
if ( ! man_elem_alloc(man, line, ppos, tok))
|
||||
return(0);
|
||||
|
||||
man_elem_alloc(man, line, ppos, tok);
|
||||
n = man->last;
|
||||
|
||||
for (;;) {
|
||||
la = *pos;
|
||||
if ( ! man_args(man, line, pos, buf, &p))
|
||||
break;
|
||||
if ( ! man_word_alloc(man, line, la, p))
|
||||
return(0);
|
||||
if (man_macros[tok].flags & MAN_JOIN &&
|
||||
man->last->type == MAN_TEXT)
|
||||
man_word_append(man, p);
|
||||
else
|
||||
man_word_alloc(man, line, la, p);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -431,13 +415,13 @@ in_line_eoln(MACRO_PROT_ARGS)
|
||||
* waiting for terms to load into our context.
|
||||
*/
|
||||
|
||||
if (n == man->last && MAN_SCOPED & man_macros[tok].flags) {
|
||||
assert( ! (MAN_NSCOPED & man_macros[tok].flags));
|
||||
if (n == man->last && man_macros[tok].flags & MAN_SCOPED) {
|
||||
assert( ! (man_macros[tok].flags & MAN_NSCOPED));
|
||||
man->flags |= MAN_ELINE;
|
||||
return(1);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(MAN_ROOT != man->last->type);
|
||||
assert(man->last->type != MAN_ROOT);
|
||||
man->next = MAN_NEXT_SIBLING;
|
||||
|
||||
/*
|
||||
@ -451,8 +435,7 @@ in_line_eoln(MACRO_PROT_ARGS)
|
||||
break;
|
||||
if (man->last->type == MAN_ROOT)
|
||||
break;
|
||||
if ( ! man_valid_post(man))
|
||||
return(0);
|
||||
man_valid_post(man);
|
||||
}
|
||||
|
||||
assert(man->last);
|
||||
@ -461,18 +444,16 @@ in_line_eoln(MACRO_PROT_ARGS)
|
||||
* Same here regarding whether we're back at the root.
|
||||
*/
|
||||
|
||||
if (man->last->type != MAN_ROOT && ! man_valid_post(man))
|
||||
return(0);
|
||||
|
||||
return(1);
|
||||
if (man->last->type != MAN_ROOT)
|
||||
man_valid_post(man);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
void
|
||||
man_macroend(struct man *man)
|
||||
{
|
||||
|
||||
return(man_unscope(man, man->first));
|
||||
man_unscope(man, man->first);
|
||||
}
|
||||
|
||||
static int
|
||||
|
77
man_term.c
77
man_term.c
@ -1,4 +1,4 @@
|
||||
/* $Id: man_term.c,v 1.149 2014/06/20 23:02:31 schwarze Exp $ */
|
||||
/* $Id: man_term.c,v 1.156 2014/11/21 01:52:53 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -143,38 +141,47 @@ void
|
||||
terminal_man(void *arg, const struct man *man)
|
||||
{
|
||||
struct termp *p;
|
||||
const struct man_node *n;
|
||||
const struct man_meta *meta;
|
||||
struct man_node *n;
|
||||
struct mtermp mt;
|
||||
|
||||
p = (struct termp *)arg;
|
||||
|
||||
if (0 == p->defindent)
|
||||
p->defindent = 7;
|
||||
|
||||
p->overstep = 0;
|
||||
p->maxrmargin = p->defrmargin;
|
||||
p->rmargin = p->maxrmargin = p->defrmargin;
|
||||
p->tabwidth = term_len(p, 5);
|
||||
|
||||
if (NULL == p->symtab)
|
||||
p->symtab = mchars_alloc();
|
||||
|
||||
n = man_node(man);
|
||||
n = man_node(man)->child;
|
||||
meta = man_meta(man);
|
||||
|
||||
term_begin(p, print_man_head, print_man_foot, meta);
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
memset(&mt, 0, sizeof(struct mtermp));
|
||||
|
||||
mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
|
||||
mt.offset = term_len(p, p->defindent);
|
||||
mt.pardist = 1;
|
||||
|
||||
if (n->child)
|
||||
print_man_nodelist(p, &mt, n->child, meta);
|
||||
|
||||
term_end(p);
|
||||
if (p->synopsisonly) {
|
||||
while (n != NULL) {
|
||||
if (n->tok == MAN_SH &&
|
||||
n->child->child->type == MAN_TEXT &&
|
||||
!strcmp(n->child->child->string, "SYNOPSIS")) {
|
||||
if (n->child->next->child != NULL)
|
||||
print_man_nodelist(p, &mt,
|
||||
n->child->next->child, meta);
|
||||
term_newln(p);
|
||||
break;
|
||||
}
|
||||
n = n->next;
|
||||
}
|
||||
} else {
|
||||
if (p->defindent == 0)
|
||||
p->defindent = 7;
|
||||
term_begin(p, print_man_head, print_man_foot, meta);
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
if (n != NULL)
|
||||
print_man_nodelist(p, &mt, n, meta);
|
||||
term_end(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -449,11 +456,6 @@ pre_in(DECL_ARGS)
|
||||
else
|
||||
p->offset = v;
|
||||
|
||||
/* Don't let this creep beyond the right margin. */
|
||||
|
||||
if (p->offset > p->rmargin)
|
||||
p->offset = p->rmargin;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -647,8 +649,7 @@ pre_IP(DECL_ARGS)
|
||||
return(0);
|
||||
case MAN_BODY:
|
||||
p->offset = mt->offset + len;
|
||||
p->rmargin = p->maxrmargin > p->offset ?
|
||||
p->maxrmargin : p->offset;
|
||||
p->rmargin = p->maxrmargin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -739,8 +740,7 @@ pre_TP(DECL_ARGS)
|
||||
return(0);
|
||||
case MAN_BODY:
|
||||
p->offset = mt->offset + len;
|
||||
p->rmargin = p->maxrmargin > p->offset ?
|
||||
p->maxrmargin : p->offset;
|
||||
p->rmargin = p->maxrmargin;
|
||||
p->trailspace = 0;
|
||||
p->flags &= ~TERMP_NOBREAK;
|
||||
break;
|
||||
@ -891,8 +891,7 @@ pre_RS(DECL_ARGS)
|
||||
|
||||
mt->offset += sz;
|
||||
p->offset = mt->offset;
|
||||
p->rmargin = p->maxrmargin > p->offset ?
|
||||
p->maxrmargin : p->offset;
|
||||
p->rmargin = p->maxrmargin;
|
||||
|
||||
if (++mt->lmarginsz < MAXMARGINS)
|
||||
mt->lmargincur = mt->lmarginsz;
|
||||
@ -977,7 +976,11 @@ print_man_node(DECL_ARGS)
|
||||
goto out;
|
||||
|
||||
case MAN_EQN:
|
||||
if ( ! (n->flags & MAN_LINE))
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_eqn(p, n->eqn);
|
||||
if (n->next != NULL && ! (n->next->flags & MAN_LINE))
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
return;
|
||||
case MAN_TBL:
|
||||
/*
|
||||
@ -1052,7 +1055,7 @@ print_man_foot(struct termp *p, const void *arg)
|
||||
{
|
||||
const struct man_meta *meta;
|
||||
char *title;
|
||||
size_t datelen;
|
||||
size_t datelen, titlen;
|
||||
|
||||
meta = (const struct man_meta *)arg;
|
||||
assert(meta->title);
|
||||
@ -1089,7 +1092,8 @@ print_man_foot(struct termp *p, const void *arg)
|
||||
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
|
||||
p->trailspace = 1;
|
||||
p->offset = 0;
|
||||
p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2;
|
||||
p->rmargin = p->maxrmargin > datelen ?
|
||||
(p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0;
|
||||
|
||||
if (meta->source)
|
||||
term_word(p, meta->source);
|
||||
@ -1097,11 +1101,10 @@ print_man_foot(struct termp *p, const void *arg)
|
||||
|
||||
/* At the bottom in the middle: manual date. */
|
||||
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
p->offset = p->rmargin;
|
||||
p->rmargin = p->maxrmargin - term_strlen(p, title);
|
||||
if (p->offset + datelen >= p->rmargin)
|
||||
p->rmargin = p->offset + datelen;
|
||||
titlen = term_strlen(p, title);
|
||||
p->rmargin = p->maxrmargin > titlen ? p->maxrmargin - titlen : 0;
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
term_word(p, meta->date);
|
||||
term_flushln(p);
|
||||
@ -1144,7 +1147,7 @@ print_man_head(struct termp *p, const void *arg)
|
||||
p->offset = 0;
|
||||
p->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ?
|
||||
(p->maxrmargin - vollen + term_len(p, 1)) / 2 :
|
||||
p->maxrmargin - vollen;
|
||||
vollen < p->maxrmargin ? p->maxrmargin - vollen : 0;
|
||||
|
||||
term_word(p, title);
|
||||
term_flushln(p);
|
||||
|
113
man_validate.c
113
man_validate.c
@ -1,4 +1,4 @@
|
||||
/* $Id: man_validate.c,v 1.105 2014/08/06 15:09:05 schwarze Exp $ */
|
||||
/* $OpenBSD$ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -38,26 +36,26 @@
|
||||
|
||||
#define CHKARGS struct man *man, struct man_node *n
|
||||
|
||||
typedef int (*v_check)(CHKARGS);
|
||||
typedef void (*v_check)(CHKARGS);
|
||||
|
||||
static int check_eq0(CHKARGS);
|
||||
static int check_eq2(CHKARGS);
|
||||
static int check_le1(CHKARGS);
|
||||
static int check_le5(CHKARGS);
|
||||
static int check_par(CHKARGS);
|
||||
static int check_part(CHKARGS);
|
||||
static int check_root(CHKARGS);
|
||||
static int check_text(CHKARGS);
|
||||
static void check_eq0(CHKARGS);
|
||||
static void check_eq2(CHKARGS);
|
||||
static void check_le1(CHKARGS);
|
||||
static void check_le5(CHKARGS);
|
||||
static void check_par(CHKARGS);
|
||||
static void check_part(CHKARGS);
|
||||
static void check_root(CHKARGS);
|
||||
static void check_text(CHKARGS);
|
||||
|
||||
static int post_AT(CHKARGS);
|
||||
static int post_IP(CHKARGS);
|
||||
static int post_vs(CHKARGS);
|
||||
static int post_fi(CHKARGS);
|
||||
static int post_ft(CHKARGS);
|
||||
static int post_nf(CHKARGS);
|
||||
static int post_TH(CHKARGS);
|
||||
static int post_UC(CHKARGS);
|
||||
static int post_UR(CHKARGS);
|
||||
static void post_AT(CHKARGS);
|
||||
static void post_IP(CHKARGS);
|
||||
static void post_vs(CHKARGS);
|
||||
static void post_fi(CHKARGS);
|
||||
static void post_ft(CHKARGS);
|
||||
static void post_nf(CHKARGS);
|
||||
static void post_TH(CHKARGS);
|
||||
static void post_UC(CHKARGS);
|
||||
static void post_UR(CHKARGS);
|
||||
|
||||
static v_check man_valids[MAN_MAX] = {
|
||||
post_vs, /* br */
|
||||
@ -102,7 +100,7 @@ static v_check man_valids[MAN_MAX] = {
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
void
|
||||
man_valid_post(struct man *man)
|
||||
{
|
||||
struct man_node *n;
|
||||
@ -110,25 +108,29 @@ man_valid_post(struct man *man)
|
||||
|
||||
n = man->last;
|
||||
if (n->flags & MAN_VALID)
|
||||
return(1);
|
||||
return;
|
||||
n->flags |= MAN_VALID;
|
||||
|
||||
switch (n->type) {
|
||||
case MAN_TEXT:
|
||||
return(check_text(man, n));
|
||||
check_text(man, n);
|
||||
break;
|
||||
case MAN_ROOT:
|
||||
return(check_root(man, n));
|
||||
check_root(man, n);
|
||||
break;
|
||||
case MAN_EQN:
|
||||
/* FALLTHROUGH */
|
||||
case MAN_TBL:
|
||||
return(1);
|
||||
break;
|
||||
default:
|
||||
cp = man_valids + n->tok;
|
||||
return(*cp ? (*cp)(man, n) : 1);
|
||||
if (*cp)
|
||||
(*cp)(man, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
check_root(CHKARGS)
|
||||
{
|
||||
|
||||
@ -154,35 +156,31 @@ check_root(CHKARGS)
|
||||
man->meta.date = man->quick ? mandoc_strdup("") :
|
||||
mandoc_normdate(man->parse, NULL, n->line, n->pos);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
check_text(CHKARGS)
|
||||
{
|
||||
char *cp, *p;
|
||||
|
||||
if (MAN_LITERAL & man->flags)
|
||||
return(1);
|
||||
return;
|
||||
|
||||
cp = n->string;
|
||||
for (p = cp; NULL != (p = strchr(p, '\t')); p++)
|
||||
mandoc_msg(MANDOCERR_FI_TAB, man->parse,
|
||||
n->line, n->pos + (p - cp), NULL);
|
||||
return(1);
|
||||
}
|
||||
|
||||
#define INEQ_DEFINE(x, ineq, name) \
|
||||
static int \
|
||||
static void \
|
||||
check_##name(CHKARGS) \
|
||||
{ \
|
||||
if (n->nchild ineq (x)) \
|
||||
return(1); \
|
||||
return; \
|
||||
mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line, n->pos, \
|
||||
"line arguments %s %d (have %d)", \
|
||||
#ineq, (x), n->nchild); \
|
||||
return(1); \
|
||||
}
|
||||
|
||||
INEQ_DEFINE(0, ==, eq0)
|
||||
@ -190,25 +188,24 @@ INEQ_DEFINE(2, ==, eq2)
|
||||
INEQ_DEFINE(1, <=, le1)
|
||||
INEQ_DEFINE(5, <=, le5)
|
||||
|
||||
static int
|
||||
static void
|
||||
post_UR(CHKARGS)
|
||||
{
|
||||
|
||||
if (MAN_HEAD == n->type && 1 != n->nchild)
|
||||
mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
|
||||
n->pos, "line arguments eq 1 (have %d)", n->nchild);
|
||||
|
||||
return(check_part(man, n));
|
||||
check_part(man, n);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
post_ft(CHKARGS)
|
||||
{
|
||||
char *cp;
|
||||
int ok;
|
||||
|
||||
if (0 == n->nchild)
|
||||
return(1);
|
||||
return;
|
||||
|
||||
ok = 0;
|
||||
cp = n->child->string;
|
||||
@ -250,22 +247,18 @@ post_ft(CHKARGS)
|
||||
if (1 < n->nchild)
|
||||
mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
|
||||
n->pos, "want one child (have %d)", n->nchild);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
check_part(CHKARGS)
|
||||
{
|
||||
|
||||
if (MAN_BODY == n->type && 0 == n->nchild)
|
||||
mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line,
|
||||
n->pos, "want children (have none)");
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
check_par(CHKARGS)
|
||||
{
|
||||
|
||||
@ -291,11 +284,9 @@ check_par(CHKARGS)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
post_IP(CHKARGS)
|
||||
{
|
||||
|
||||
@ -313,10 +304,9 @@ post_IP(CHKARGS)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
post_TH(CHKARGS)
|
||||
{
|
||||
struct man_node *nb;
|
||||
@ -404,10 +394,9 @@ post_TH(CHKARGS)
|
||||
* meta-data.
|
||||
*/
|
||||
man_node_delete(man, man->last);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
post_nf(CHKARGS)
|
||||
{
|
||||
|
||||
@ -418,10 +407,9 @@ post_nf(CHKARGS)
|
||||
n->line, n->pos, "nf");
|
||||
|
||||
man->flags |= MAN_LITERAL;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
post_fi(CHKARGS)
|
||||
{
|
||||
|
||||
@ -432,10 +420,9 @@ post_fi(CHKARGS)
|
||||
n->line, n->pos, "fi");
|
||||
|
||||
man->flags &= ~MAN_LITERAL;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
post_UC(CHKARGS)
|
||||
{
|
||||
static const char * const bsd_versions[] = {
|
||||
@ -470,10 +457,9 @@ post_UC(CHKARGS)
|
||||
|
||||
free(man->meta.source);
|
||||
man->meta.source = mandoc_strdup(p);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
post_AT(CHKARGS)
|
||||
{
|
||||
static const char * const unix_versions[] = {
|
||||
@ -508,10 +494,9 @@ post_AT(CHKARGS)
|
||||
|
||||
free(man->meta.source);
|
||||
man->meta.source = mandoc_strdup(p);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
post_vs(CHKARGS)
|
||||
{
|
||||
|
||||
@ -521,7 +506,7 @@ post_vs(CHKARGS)
|
||||
check_le1(man, n);
|
||||
|
||||
if (NULL != n->prev)
|
||||
return(1);
|
||||
return;
|
||||
|
||||
switch (n->parent->tok) {
|
||||
case MAN_SH:
|
||||
@ -541,6 +526,4 @@ post_vs(CHKARGS)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
254
mandoc.1
254
mandoc.1
@ -1,4 +1,4 @@
|
||||
.\" $Id: mandoc.1,v 1.106 2014/08/08 01:50:59 schwarze Exp $
|
||||
.\" $Id: mandoc.1,v 1.125 2014/11/28 18:09:01 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: August 8 2014 $
|
||||
.Dd $Mdocdate: November 28 2014 $
|
||||
.Dt MANDOC 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -23,10 +23,11 @@
|
||||
.Nd format and display UNIX manuals
|
||||
.Sh SYNOPSIS
|
||||
.Nm mandoc
|
||||
.Op Fl V
|
||||
.Op Fl acfhklV
|
||||
.Sm off
|
||||
.Op Fl I Cm os Li = Ar name
|
||||
.Sm on
|
||||
.Op Fl K Ns Ar encoding
|
||||
.Op Fl m Ns Ar format
|
||||
.Op Fl O Ns Ar option
|
||||
.Op Fl T Ns Ar output
|
||||
@ -51,8 +52,31 @@ and produces
|
||||
.Fl T Ns Cm ascii
|
||||
output.
|
||||
.Pp
|
||||
The arguments are as follows:
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
If the standard output is a terminal device and
|
||||
.Fl c
|
||||
is not specified, use
|
||||
.Xr more 1
|
||||
to paginate the output, just like
|
||||
.Xr man 1
|
||||
would.
|
||||
.It Fl c
|
||||
Copy the formatted manual pages to the standard output without using
|
||||
.Xr more 1
|
||||
to paginate them.
|
||||
This is the default.
|
||||
It can be specified to override
|
||||
.Fl a .
|
||||
.It Fl f
|
||||
A synonym for
|
||||
.Xr whatis 1 .
|
||||
This overrides any earlier
|
||||
.Fl k
|
||||
and
|
||||
.Fl l
|
||||
options.
|
||||
.Sm off
|
||||
.It Fl I Cm os Li = Ar name
|
||||
.Sm on
|
||||
@ -62,6 +86,51 @@ for the
|
||||
.Xr mdoc 7
|
||||
.Sq \&Os
|
||||
macro.
|
||||
.It Fl h
|
||||
Display only the SYNOPSIS lines.
|
||||
Implies
|
||||
.Fl c .
|
||||
.It Fl K Ns Ar encoding
|
||||
Specify the input encoding.
|
||||
The supported
|
||||
.Ar encoding
|
||||
arguments are
|
||||
.Cm us-ascii ,
|
||||
.Cm iso-8859-1 ,
|
||||
and
|
||||
.Cm utf-8 .
|
||||
If not specified, autodetection uses the first match:
|
||||
.Bl -tag -width iso-8859-1
|
||||
.It Cm utf-8
|
||||
if the first three bytes of the input file
|
||||
are the UTF-8 byte order mark (BOM, 0xefbbbf)
|
||||
.It Ar encoding
|
||||
if the first or second line of the input file matches the
|
||||
.Sy emacs
|
||||
mode line format
|
||||
.Pp
|
||||
.D1 .\e" -*- Oo ...; Oc coding: Ar encoding ; No -*-
|
||||
.It Cm utf-8
|
||||
if the first non-ASCII byte in the file introduces a valid UTF-8 sequence
|
||||
.It Cm iso-8859-1
|
||||
otherwise
|
||||
.El
|
||||
.It Fl k
|
||||
A synonym for
|
||||
.Xr apropos 1 .
|
||||
This overrides any earlier
|
||||
.Fl f
|
||||
and
|
||||
.Fl l
|
||||
options.
|
||||
.It Fl l
|
||||
A synonym for
|
||||
.Fl a .
|
||||
Also reverts any earlier
|
||||
.Fl f
|
||||
and
|
||||
.Fl k
|
||||
options.
|
||||
.It Fl m Ns Ar format
|
||||
Input format.
|
||||
See
|
||||
@ -122,6 +191,18 @@ If multiple files are specified,
|
||||
.Nm
|
||||
will halt with the first failed parse.
|
||||
.El
|
||||
.Pp
|
||||
In
|
||||
.Fl f
|
||||
and
|
||||
.Fl k
|
||||
mode,
|
||||
.Nm
|
||||
also supports the options
|
||||
.Fl CMmOSsw
|
||||
described in the
|
||||
.Xr apropos 1
|
||||
manual.
|
||||
.Ss Input Formats
|
||||
The
|
||||
.Nm
|
||||
@ -178,7 +259,7 @@ This is the default.
|
||||
See
|
||||
.Sx ASCII Output .
|
||||
.It Fl T Ns Cm html
|
||||
Produce strict CSS1/HTML-4.01 output.
|
||||
Produce HTML5, CSS1, and MathML output.
|
||||
See
|
||||
.Sx HTML Output .
|
||||
.It Fl T Ns Cm lint
|
||||
@ -210,9 +291,8 @@ Encode output in the UTF\-8 multi-byte format.
|
||||
See
|
||||
.Sx UTF\-8 Output .
|
||||
.It Fl T Ns Cm xhtml
|
||||
Produce strict CSS1/XHTML-1.0 output.
|
||||
See
|
||||
.Sx XHTML Output .
|
||||
This is a synonym for
|
||||
.Fl T Ns Cm html .
|
||||
.El
|
||||
.Pp
|
||||
If multiple input files are specified, these will be processed by the
|
||||
@ -265,7 +345,11 @@ which will normalise to \(>=60.
|
||||
.Ss HTML Output
|
||||
Output produced by
|
||||
.Fl T Ns Cm html
|
||||
conforms to HTML-4.01 strict.
|
||||
conforms to HTML5 using optional self-closing tags.
|
||||
Default styles use only CSS1.
|
||||
Equations rendered from
|
||||
.Xr eqn 7
|
||||
blocks use MathML.
|
||||
.Pp
|
||||
The
|
||||
.Pa example.style.css
|
||||
@ -273,7 +357,8 @@ file documents style-sheet classes available for customising output.
|
||||
If a style-sheet is not specified with
|
||||
.Fl O Ns Ar style ,
|
||||
.Fl T Ns Cm html
|
||||
defaults to simple output readable in any graphical or text-based web
|
||||
defaults to simple output (via an embedded style-sheet)
|
||||
readable in any graphical or text-based web
|
||||
browser.
|
||||
.Pp
|
||||
Special characters are rendered in decimal-encoded UTF\-8.
|
||||
@ -283,16 +368,8 @@ The following
|
||||
arguments are accepted:
|
||||
.Bl -tag -width Ds
|
||||
.It Cm fragment
|
||||
Omit the
|
||||
.Aq !DOCTYPE
|
||||
declaration and the
|
||||
.Aq html ,
|
||||
.Aq head ,
|
||||
and
|
||||
.Aq body
|
||||
elements and only emit the subtree below the
|
||||
.Aq body
|
||||
element.
|
||||
Omit the <!DOCTYPE> declaration and the <html>, <head>, and <body>
|
||||
elements and only emit the subtree below the <body> element.
|
||||
The
|
||||
.Cm style
|
||||
argument will be ignored.
|
||||
@ -416,15 +493,21 @@ to force a UTF\-8 locale.
|
||||
See
|
||||
.Sx Locale Output
|
||||
for details and options.
|
||||
.Ss XHTML Output
|
||||
Output produced by
|
||||
.Fl T Ns Cm xhtml
|
||||
conforms to XHTML-1.0 strict.
|
||||
.Pp
|
||||
See
|
||||
.Sx HTML Output
|
||||
for details; beyond generating XHTML tags instead of HTML tags, these
|
||||
output modes are identical.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width MANPAGER
|
||||
.It Ev MANPAGER
|
||||
Any non-empty value of the environment variable
|
||||
.Ev MANPAGER
|
||||
will be used instead of the standard pagination program,
|
||||
.Xr more 1 .
|
||||
.It Ev PAGER
|
||||
Specifies the pagination program to use when
|
||||
.Ev MANPAGER
|
||||
is not defined.
|
||||
If neither PAGER nor MANPAGER is defined,
|
||||
.Pa /usr/bin/more Fl s
|
||||
will be used.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
@ -582,12 +665,6 @@ macro lacks the mandatory section argument.
|
||||
The section number in a
|
||||
.Ic \&Dt
|
||||
line is invalid, but still used.
|
||||
.It Sy "unknown manual volume or arch"
|
||||
.Pq mdoc
|
||||
The volume name in a
|
||||
.Ic \&Dt
|
||||
line is invalid, but still used.
|
||||
The manual is assumed to be architecture-independent.
|
||||
.It Sy "missing date, using today's date"
|
||||
.Pq mdoc, man
|
||||
The document was parsed as
|
||||
@ -696,6 +773,28 @@ The same standard section title occurs more than once.
|
||||
.Pq mdoc
|
||||
A standard section header occurs in a section of the manual
|
||||
where it normally isn't useful.
|
||||
.It Sy "unusual Xr order"
|
||||
.Pq mdoc
|
||||
In the SEE ALSO section, an
|
||||
.Ic \&Xr
|
||||
macro with a lower section number follows one with a higher number,
|
||||
or two
|
||||
.Ic \&Xr
|
||||
macros refering to the same section are out of alphabetical order.
|
||||
.It Sy "unusual Xr punctuation"
|
||||
.Pq mdoc
|
||||
In the SEE ALSO section, punctuation between two
|
||||
.Ic \&Xr
|
||||
macros differs from a single comma, or there is trailing punctuation
|
||||
after the last
|
||||
.Ic \&Xr
|
||||
macro.
|
||||
.It Sy "AUTHORS section without An macro"
|
||||
.Pq mdoc
|
||||
An AUTHORS sections contains no
|
||||
.Ic \&An
|
||||
macros, or only empty ones.
|
||||
Probably, there are author names lacking markup.
|
||||
.El
|
||||
.Ss "Warnings related to macros and nesting"
|
||||
.Bl -ohang
|
||||
@ -824,8 +923,11 @@ The previous, interrupted macro is deleted from the parse tree.
|
||||
.Ss "Warnings related to missing arguments"
|
||||
.Bl -ohang
|
||||
.It Sy "skipping empty request"
|
||||
.Pq roff
|
||||
The macro name is missing from a macro definition request.
|
||||
.Pq roff , eqn
|
||||
The macro name is missing from a macro definition request,
|
||||
or an
|
||||
.Xr eqn 7
|
||||
control statement or operation keyword lacks its required argument.
|
||||
.It Sy "conditional request controls empty scope"
|
||||
.Pq roff
|
||||
A conditional request is only useful if any of the following
|
||||
@ -959,6 +1061,11 @@ The
|
||||
utility assumes
|
||||
.Fl std
|
||||
even when it is not specified, but other implementations may not.
|
||||
.It Sy "missing eqn box, using \(dq\(dq"
|
||||
.Pq eqn
|
||||
A diacritic mark or a binary operator is found,
|
||||
but there is nothing to the left of it.
|
||||
An empty box is inserted.
|
||||
.El
|
||||
.Ss "Warnings related to bad macro arguments"
|
||||
.Bl -ohang
|
||||
@ -1026,6 +1133,21 @@ macro has an invalid argument.
|
||||
It is used verbatim, with
|
||||
.Qq "AT&T UNIX "
|
||||
prefixed to it.
|
||||
.It Sy "comma in function argument"
|
||||
.Pq mdoc
|
||||
An argument of an
|
||||
.Ic \&Fa
|
||||
or
|
||||
.Ic \&Fn
|
||||
macro contains a comma; it should probably be split into two arguments.
|
||||
.It Sy "parenthesis in function name"
|
||||
.Pq mdoc
|
||||
The first argument of an
|
||||
.Ic \&Fc
|
||||
or
|
||||
.Ic \&Fn
|
||||
macro contains an opening or closing parenthesis; that's probably wrong,
|
||||
parentheses are added automatically.
|
||||
.It Sy "invalid content in Rs block"
|
||||
.Pq mdoc
|
||||
An
|
||||
@ -1044,11 +1166,16 @@ or
|
||||
The invalid argument is moved out of the macro, which leaves the macro
|
||||
empty, causing it to toggle the spacing mode.
|
||||
.It Sy "unknown font, skipping request"
|
||||
.Pq man
|
||||
.Pq man , tbl
|
||||
A
|
||||
.Xr roff 7
|
||||
.Ic \&ft
|
||||
request has an invalid argument.
|
||||
request or a
|
||||
.Xr tbl 7
|
||||
.Ic \&f
|
||||
layout modifier has an unknown
|
||||
.Ar font
|
||||
argument.
|
||||
.El
|
||||
.Ss "Warnings related to plain text"
|
||||
.Bl -ohang
|
||||
@ -1111,7 +1238,6 @@ keeps the code more readable.
|
||||
.It "equation scope open on exit"
|
||||
.It "overlapping equation scopes"
|
||||
.It "unexpected end of equation"
|
||||
.It "equation syntax error"
|
||||
.El
|
||||
.Ss "Errors related to tables"
|
||||
.Bl -inset -compact
|
||||
@ -1165,12 +1291,15 @@ macro.
|
||||
It may be mistyped or unsupported.
|
||||
The request or macro is discarded including its arguments.
|
||||
.It Sy "skipping item outside list"
|
||||
.Pq mdoc
|
||||
.Pq mdoc , eqn
|
||||
An
|
||||
.Ic \&It
|
||||
macro occurs outside any
|
||||
.Ic \&Bl
|
||||
list.
|
||||
list, or an
|
||||
.Xr eqn 7
|
||||
.Ic above
|
||||
delimiter occurs outside any pile.
|
||||
It is discarded including its arguments.
|
||||
.It Sy "skipping column outside column list"
|
||||
.Pq mdoc
|
||||
@ -1191,7 +1320,9 @@ block closing macro, a
|
||||
.Ic \&RE
|
||||
or
|
||||
.Ic \&UE
|
||||
macro, or the end of an equation, table, or
|
||||
macro, an
|
||||
.Xr eqn 7
|
||||
right delimiter or closing brace, or the end of an equation, table, or
|
||||
.Xr roff 7
|
||||
conditional request is encountered but no matching block is open.
|
||||
The offending request or macro is discarded.
|
||||
@ -1259,6 +1390,17 @@ The indicated request or macro has too few or too many arguments.
|
||||
The syntax tree will contain the wrong number of arguments as given.
|
||||
Formatting behaviour depends on the specific request or macro in question.
|
||||
Note that the same message may also occur as a WARNING, see above.
|
||||
.It Sy "NOT IMPLEMENTED: Bd -file"
|
||||
.Pq mdoc
|
||||
For security reasons, the
|
||||
.Ic \&Bd
|
||||
macro does not support the
|
||||
.Fl file
|
||||
argument.
|
||||
By requesting the inclusion of a sensitive file, a malicious document
|
||||
might otherwise trick a privileged user into inadvertently displaying
|
||||
the file on the screen, revealing the file content to bystanders.
|
||||
The argument is ignored including the file name following it.
|
||||
.It Sy "missing list type, using -item"
|
||||
.Pq mdoc
|
||||
A
|
||||
@ -1288,11 +1430,16 @@ An
|
||||
.Ic \&St
|
||||
macro has an unknown argument and is discarded.
|
||||
.It Sy "skipping request without numeric argument"
|
||||
.Pq roff
|
||||
.Pq roff , eqn
|
||||
An
|
||||
.Ic \&it
|
||||
request has a non-numeric or negative argument or no argument at all.
|
||||
The invalid request is ignored.
|
||||
request or an
|
||||
.Xr eqn 7
|
||||
.Ic \&size
|
||||
or
|
||||
.Ic \&gsize
|
||||
statement has a non-numeric or negative argument or no argument at all.
|
||||
The invalid request or statement is ignored.
|
||||
.It Sy "skipping all arguments"
|
||||
.Pq mdoc , man , eqn , roff
|
||||
An
|
||||
@ -1315,6 +1462,8 @@ or
|
||||
.Ic \&PP
|
||||
macro, an
|
||||
.Xr eqn 7
|
||||
.Ic \&EQ
|
||||
or
|
||||
.Ic \&EN
|
||||
macro, or a
|
||||
.Xr roff 7
|
||||
@ -1340,17 +1489,6 @@ cannot handle input files larger than its arbitrary size limit
|
||||
of 2^31 bytes (2 Gigabytes).
|
||||
Since useful manuals are always small, this is not a problem in practice.
|
||||
Parsing is aborted as soon as the condition is detected.
|
||||
.It Sy "NOT IMPLEMENTED: Bd -file"
|
||||
.Pq mdoc
|
||||
For security reasons, the
|
||||
.Ic \&Bd
|
||||
macro does not support the
|
||||
.Fl file
|
||||
argument.
|
||||
By requesting the inclusion of a sensitive file, a malicious document
|
||||
might otherwise trick a privileged user into inadvertently displaying
|
||||
the file on the screen, revealing the file content to bystanders.
|
||||
The parser exits immediately.
|
||||
.It Sy "NOT IMPLEMENTED: .so with absolute path or \(dq..\(dq"
|
||||
.Pq roff
|
||||
For security reasons,
|
||||
@ -1430,7 +1568,7 @@ has no effect.
|
||||
.It
|
||||
Words aren't hyphenated.
|
||||
.El
|
||||
.Ss HTML/XHTML Compatibility
|
||||
.Ss HTML Compatibility
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
The
|
||||
|
89
mandoc.3
89
mandoc.3
@ -1,4 +1,4 @@
|
||||
.\" $Id: mandoc.3,v 1.25 2014/08/05 05:48:56 schwarze Exp $
|
||||
.\" $Id: mandoc.3,v 1.29 2014/11/26 23:42:14 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: August 5 2014 $
|
||||
.Dd $Mdocdate: November 26 2014 $
|
||||
.Dt MANDOC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -31,11 +31,13 @@
|
||||
.Nm mparse_free ,
|
||||
.Nm mparse_getkeep ,
|
||||
.Nm mparse_keep ,
|
||||
.Nm mparse_open ,
|
||||
.Nm mparse_readfd ,
|
||||
.Nm mparse_reset ,
|
||||
.Nm mparse_result ,
|
||||
.Nm mparse_strerror ,
|
||||
.Nm mparse_strlevel
|
||||
.Nm mparse_wait ,
|
||||
.Nd mandoc macro compiler library
|
||||
.Sh LIBRARY
|
||||
.Lb libmandoc
|
||||
@ -50,6 +52,7 @@
|
||||
.Fa "int options"
|
||||
.Fa "enum mandoclevel wlevel"
|
||||
.Fa "mandocmsg mmsg"
|
||||
.Fa "const struct mchars *mchars"
|
||||
.Fa "char *defos"
|
||||
.Fc
|
||||
.Ft void
|
||||
@ -74,6 +77,12 @@
|
||||
.Fa "struct mparse *parse"
|
||||
.Fc
|
||||
.Ft "enum mandoclevel"
|
||||
.Fo mparse_open
|
||||
.Fa "struct mparse *parse"
|
||||
.Fa "int *fd"
|
||||
.Fa "const char *fname"
|
||||
.Fc
|
||||
.Ft "enum mandoclevel"
|
||||
.Fo mparse_readfd
|
||||
.Fa "struct mparse *parse"
|
||||
.Fa "int fd"
|
||||
@ -98,6 +107,10 @@
|
||||
.Fo mparse_strlevel
|
||||
.Fa "enum mandoclevel"
|
||||
.Fc
|
||||
.Ft "enum mandoclevel"
|
||||
.Fo mparse_wait
|
||||
.Fa "struct mparse *parse"
|
||||
.Fc
|
||||
.In sys/types.h
|
||||
.In mandoc.h
|
||||
.In mdoc.h
|
||||
@ -159,6 +172,8 @@ The following describes a general parse sequence:
|
||||
.Bl -enum
|
||||
.It
|
||||
initiate a parsing sequence with
|
||||
.Xr mchars_alloc 3
|
||||
and
|
||||
.Fn mparse_alloc ;
|
||||
.It
|
||||
parse files or file descriptors with
|
||||
@ -173,7 +188,9 @@ or
|
||||
.Fn man_node ;
|
||||
.It
|
||||
free all allocated memory with
|
||||
.Fn mparse_free ,
|
||||
.Fn mparse_free
|
||||
and
|
||||
.Xr mchars_free 3 ,
|
||||
or invoke
|
||||
.Fn mparse_reset
|
||||
and parse new files.
|
||||
@ -194,6 +211,12 @@ A fatal error, error, or warning message during parsing.
|
||||
A classification of an
|
||||
.Vt "enum mandocerr"
|
||||
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"
|
||||
An opaque pointer to a running parse sequence.
|
||||
Created with
|
||||
@ -318,6 +341,9 @@ A callback function to handle errors and warnings.
|
||||
See
|
||||
.Pa main.c
|
||||
for an example.
|
||||
.It Ar mchars
|
||||
An opaque pointer to a a character table obtained from
|
||||
.Xr mchars_alloc 3 .
|
||||
.It Ar defos
|
||||
A default string for the
|
||||
.Xr mdoc 7
|
||||
@ -361,18 +387,47 @@ Declared in
|
||||
.In mandoc.h ,
|
||||
implemented in
|
||||
.Pa read.c .
|
||||
.It Fn mparse_open
|
||||
If the
|
||||
.Fa fname
|
||||
ends in
|
||||
.Pa .gz ,
|
||||
open with
|
||||
.Xr gunzip 1 ;
|
||||
otherwise, with
|
||||
.Xr open 2 .
|
||||
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
|
||||
.Fn mparse_readfd
|
||||
or used directly.
|
||||
Declared in
|
||||
.In mandoc.h ,
|
||||
implemented in
|
||||
.Pa read.c .
|
||||
.It Fn mparse_readfd
|
||||
Parse a file or file descriptor.
|
||||
If
|
||||
.Va fd
|
||||
is -1,
|
||||
is -1, open
|
||||
.Va fname
|
||||
is opened for reading.
|
||||
with
|
||||
.Fn mparse_open .
|
||||
Otherwise,
|
||||
.Va fname
|
||||
is assumed to be the name associated with
|
||||
.Va fd .
|
||||
This may be called multiple times with different parameters; however,
|
||||
Calls
|
||||
.Fn mparse_wait
|
||||
before returning.
|
||||
This function may be called multiple times with different parameters; however,
|
||||
.Fn mparse_reset
|
||||
should be invoked between parses.
|
||||
Declared in
|
||||
@ -413,6 +468,28 @@ Declared in
|
||||
.In mandoc.h ,
|
||||
implemented in
|
||||
.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
|
||||
.Ss Variables
|
||||
.Bl -ohang
|
||||
|
37
mandoc.c
37
mandoc.c
@ -1,4 +1,4 @@
|
||||
/* $Id: mandoc.c,v 1.83 2014/07/06 19:09:00 schwarze Exp $ */
|
||||
/* $Id: mandoc.c,v 1.88 2014/10/28 13:24:44 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -81,24 +79,13 @@ mandoc_escape(const char **end, const char **start, int *sz)
|
||||
break;
|
||||
case '[':
|
||||
gly = ESCAPE_SPECIAL;
|
||||
/*
|
||||
* Unicode escapes are defined in groff as \[uXXXX] to
|
||||
* \[u10FFFF], where the contained value must be a valid
|
||||
* Unicode codepoint. Here, however, only check whether
|
||||
* it's not a zero-width escape.
|
||||
*/
|
||||
if ('u' == (*start)[0] && ']' != (*start)[1])
|
||||
gly = ESCAPE_UNICODE;
|
||||
term = ']';
|
||||
break;
|
||||
case 'C':
|
||||
if ('\'' != **start)
|
||||
return(ESCAPE_ERROR);
|
||||
*start = ++*end;
|
||||
if ('u' == (*start)[0] && '\'' != (*start)[1])
|
||||
gly = ESCAPE_UNICODE;
|
||||
else
|
||||
gly = ESCAPE_SPECIAL;
|
||||
gly = ESCAPE_SPECIAL;
|
||||
term = '\'';
|
||||
break;
|
||||
|
||||
@ -201,7 +188,8 @@ mandoc_escape(const char **end, const char **start, int *sz)
|
||||
/* FALLTHROUGH */
|
||||
case 'x':
|
||||
if (strchr(" %&()*+-./0123456789:<=>", **start)) {
|
||||
++*end;
|
||||
if ('\0' != **start)
|
||||
++*end;
|
||||
return(ESCAPE_ERROR);
|
||||
}
|
||||
gly = ESCAPE_IGNORE;
|
||||
@ -345,6 +333,21 @@ mandoc_escape(const char **end, const char **start, int *sz)
|
||||
case ESCAPE_SPECIAL:
|
||||
if (1 == *sz && 'c' == **start)
|
||||
gly = ESCAPE_NOSPACE;
|
||||
/*
|
||||
* Unicode escapes are defined in groff as \[u0000]
|
||||
* to \[u10FFFF], where the contained value must be
|
||||
* a valid Unicode codepoint. Here, however, only
|
||||
* check the length and range.
|
||||
*/
|
||||
if (**start != 'u' || *sz < 5 || *sz > 7)
|
||||
break;
|
||||
if (*sz == 7 && ((*start)[1] != '1' || (*start)[2] != '0'))
|
||||
break;
|
||||
if (*sz == 6 && (*start)[1] == '0')
|
||||
break;
|
||||
if ((int)strspn(*start + 1, "0123456789ABCDEFabcdef")
|
||||
+ 1 == *sz)
|
||||
gly = ESCAPE_UNICODE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -457,7 +460,7 @@ a2time(time_t *t, const char *fmt, const char *p)
|
||||
memset(&tm, 0, sizeof(struct tm));
|
||||
|
||||
pp = NULL;
|
||||
#ifdef HAVE_STRPTIME
|
||||
#if HAVE_STRPTIME
|
||||
pp = strptime(p, fmt, &tm);
|
||||
#endif
|
||||
if (NULL != pp && '\0' == *pp) {
|
||||
|
23
mandoc.db.5
23
mandoc.db.5
@ -1,4 +1,4 @@
|
||||
.\" $Id: mandoc.db.5,v 1.1 2014/04/15 20:18:26 schwarze Exp $
|
||||
.\" $Id: mandoc.db.5,v 1.2 2014/09/03 18:09:14 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
@ -14,7 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: April 15 2014 $
|
||||
.Dd $Mdocdate: September 3 2014 $
|
||||
.Dt MANDOC.DB 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -67,13 +67,26 @@ The description line
|
||||
.Pq Sq \&Nd
|
||||
of the page.
|
||||
.It Sy mpages.form
|
||||
The
|
||||
An
|
||||
.Vt INTEGER
|
||||
1 if the page is unformatted, i.e. in
|
||||
bit field.
|
||||
If bit
|
||||
.Dv FORM_GZ
|
||||
is set, the page is compressed and requires
|
||||
.Xr gunzip 1
|
||||
for display.
|
||||
If bit
|
||||
.Dv FORM_SRC
|
||||
is set, the page is unformatted, that is in
|
||||
.Xr mdoc 7
|
||||
or
|
||||
.Xr man 7
|
||||
format, and 2 if it is formatted, i.e. a
|
||||
format, and requires
|
||||
.Xr mandoc 1
|
||||
for display.
|
||||
If bit
|
||||
.Dv FORM_SRC
|
||||
is not set, the page is formatted, i.e. a
|
||||
.Sq cat
|
||||
page.
|
||||
.It Sy mlinks.sec
|
||||
|
68
mandoc.h
68
mandoc.h
@ -1,6 +1,6 @@
|
||||
/* $Id: mandoc.h,v 1.152 2014/08/06 15:09:05 schwarze Exp $ */
|
||||
/* $Id: mandoc.h,v 1.171 2014/11/28 18:09:01 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -54,7 +54,6 @@ enum mandocerr {
|
||||
MANDOCERR_TITLE_CASE, /* lower case character in document title */
|
||||
MANDOCERR_MSEC_MISSING, /* missing manual section, using "": macro */
|
||||
MANDOCERR_MSEC_BAD, /* unknown manual section: Dt ... section */
|
||||
MANDOCERR_ARCH_BAD, /* unknown manual volume or arch: Dt ... volume */
|
||||
MANDOCERR_DATE_MISSING, /* missing date, using today's date */
|
||||
MANDOCERR_DATE_BAD, /* cannot parse date, using it verbatim: date */
|
||||
MANDOCERR_OS_MISSING, /* missing Os macro, using "" */
|
||||
@ -72,6 +71,9 @@ enum mandocerr {
|
||||
MANDOCERR_SEC_ORDER, /* sections out of conventional order: Sh title */
|
||||
MANDOCERR_SEC_REP, /* duplicate section title: Sh title */
|
||||
MANDOCERR_SEC_MSEC, /* unexpected section: Sh title for ... only */
|
||||
MANDOCERR_XR_ORDER, /* unusual Xr order: ... after ... */
|
||||
MANDOCERR_XR_PUNCT, /* unusual Xr punctuation: ... after ... */
|
||||
MANDOCERR_AN_MISSING, /* AUTHORS section without An macro */
|
||||
|
||||
/* related to macros and nesting */
|
||||
MANDOCERR_MACRO_OBS, /* obsolete macro: macro */
|
||||
@ -101,6 +103,7 @@ enum mandocerr {
|
||||
MANDOCERR_BF_NOFONT, /* missing font type, using \fR: Bf */
|
||||
MANDOCERR_BF_BADFONT, /* unknown font type, using \fR: Bf font */
|
||||
MANDOCERR_ARG_STD, /* missing -std argument, adding it: macro */
|
||||
MANDOCERR_EQN_NOBOX, /* missing eqn box, using "": op */
|
||||
|
||||
/* related to bad arguments */
|
||||
MANDOCERR_ARG_QUOTE, /* unterminated quoted argument */
|
||||
@ -110,6 +113,8 @@ enum mandocerr {
|
||||
MANDOCERR_BL_REP, /* skipping duplicate list type: Bl -type */
|
||||
MANDOCERR_BL_SKIPW, /* skipping -width argument: Bl -type */
|
||||
MANDOCERR_AT_BAD, /* unknown AT&T UNIX version: At version */
|
||||
MANDOCERR_FA_COMMA, /* comma in function argument: arg */
|
||||
MANDOCERR_FN_PAREN, /* parenthesis in function name: arg */
|
||||
MANDOCERR_RS_BAD, /* invalid content in Rs block: macro */
|
||||
MANDOCERR_SM_BAD, /* invalid Boolean argument: macro arg */
|
||||
MANDOCERR_FT_BAD, /* unknown font, skipping request: ft font */
|
||||
@ -129,7 +134,6 @@ enum mandocerr {
|
||||
MANDOCERR_EQNSCOPE, /* equation scope open on exit */
|
||||
MANDOCERR_EQNBADSCOPE, /* overlapping equation scopes */
|
||||
MANDOCERR_EQNEOF, /* unexpected end of equation */
|
||||
MANDOCERR_EQNSYNT, /* equation syntax error */
|
||||
|
||||
/* related to tables */
|
||||
MANDOCERR_TBL, /* bad table syntax */
|
||||
@ -154,6 +158,7 @@ enum mandocerr {
|
||||
/* related to request and macro arguments */
|
||||
MANDOCERR_NAMESC, /* escaped character not allowed in a name: name */
|
||||
MANDOCERR_ARGCOUNT, /* argument count wrong */
|
||||
MANDOCERR_BD_FILE, /* NOT IMPLEMENTED: Bd -file */
|
||||
MANDOCERR_BL_NOTYPE, /* missing list type, using -item: Bl */
|
||||
MANDOCERR_NM_NONAME, /* missing manual name, using "": Nm */
|
||||
MANDOCERR_OS_UNAME, /* uname(3) system call failed, using UNKNOWN */
|
||||
@ -161,19 +166,26 @@ enum mandocerr {
|
||||
MANDOCERR_IT_NONUM, /* skipping request without numeric argument */
|
||||
MANDOCERR_ARG_SKIP, /* skipping all arguments: macro args */
|
||||
MANDOCERR_ARG_EXCESS, /* skipping excess arguments: macro ... args */
|
||||
MANDOCERR_DIVZERO, /* divide by zero */
|
||||
|
||||
MANDOCERR_FATAL, /* ===== start of fatal errors ===== */
|
||||
|
||||
MANDOCERR_TOOLARGE, /* input too large */
|
||||
MANDOCERR_BD_FILE, /* NOT IMPLEMENTED: Bd -file */
|
||||
MANDOCERR_SO_PATH, /* NOT IMPLEMENTED: .so with absolute path or ".." */
|
||||
MANDOCERR_SO_FAIL, /* .so request failed */
|
||||
|
||||
/* ===== system errors ===== */
|
||||
|
||||
MANDOCERR_SYSDUP, /* cannot dup file descriptor */
|
||||
MANDOCERR_SYSEXEC, /* cannot exec */
|
||||
MANDOCERR_SYSEXIT, /* gunzip failed with code */
|
||||
MANDOCERR_SYSFORK, /* cannot fork */
|
||||
MANDOCERR_SYSOPEN, /* cannot open file */
|
||||
MANDOCERR_SYSSTAT, /* cannot stat file */
|
||||
MANDOCERR_SYSPIPE, /* cannot open pipe */
|
||||
MANDOCERR_SYSREAD, /* cannot read file */
|
||||
MANDOCERR_SYSSIG, /* gunzip died from signal */
|
||||
MANDOCERR_SYSSTAT, /* cannot stat file */
|
||||
MANDOCERR_SYSWAIT, /* wait failed */
|
||||
|
||||
MANDOCERR_MAX
|
||||
};
|
||||
@ -234,6 +246,7 @@ struct tbl_cell {
|
||||
#define TBL_CELL_EQUAL (1 << 4) /* e, E */
|
||||
#define TBL_CELL_UP (1 << 5) /* u, U */
|
||||
#define TBL_CELL_WIGN (1 << 6) /* z, Z */
|
||||
#define TBL_CELL_WMAX (1 << 7) /* x, X */
|
||||
struct tbl_head *head;
|
||||
};
|
||||
|
||||
@ -295,21 +308,10 @@ enum eqn_boxt {
|
||||
EQN_ROOT, /* root of parse tree */
|
||||
EQN_TEXT, /* text (number, variable, whatever) */
|
||||
EQN_SUBEXPR, /* nested `eqn' subexpression */
|
||||
EQN_LIST, /* subexpressions list */
|
||||
EQN_MATRIX /* matrix subexpression */
|
||||
};
|
||||
|
||||
enum eqn_markt {
|
||||
EQNMARK_NONE = 0,
|
||||
EQNMARK_DOT,
|
||||
EQNMARK_DOTDOT,
|
||||
EQNMARK_HAT,
|
||||
EQNMARK_TILDE,
|
||||
EQNMARK_VEC,
|
||||
EQNMARK_DYAD,
|
||||
EQNMARK_BAR,
|
||||
EQNMARK_UNDER,
|
||||
EQNMARK__MAX
|
||||
EQN_LIST, /* list (braces, etc.) */
|
||||
EQN_LISTONE, /* singleton list */
|
||||
EQN_PILE, /* vertical pile */
|
||||
EQN_MATRIX /* pile of piles */
|
||||
};
|
||||
|
||||
enum eqn_fontt {
|
||||
@ -323,11 +325,14 @@ enum eqn_fontt {
|
||||
|
||||
enum eqn_post {
|
||||
EQNPOS_NONE = 0,
|
||||
EQNPOS_OVER,
|
||||
EQNPOS_SUP,
|
||||
EQNPOS_SUBSUP,
|
||||
EQNPOS_SUB,
|
||||
EQNPOS_TO,
|
||||
EQNPOS_FROM,
|
||||
EQNPOS_FROMTO,
|
||||
EQNPOS_OVER,
|
||||
EQNPOS_SQRT,
|
||||
EQNPOS__MAX
|
||||
};
|
||||
|
||||
@ -355,12 +360,16 @@ struct eqn_box {
|
||||
struct eqn_box *first; /* first child node */
|
||||
struct eqn_box *last; /* last child node */
|
||||
struct eqn_box *next; /* node sibling */
|
||||
struct eqn_box *prev; /* node sibling */
|
||||
struct eqn_box *parent; /* node sibling */
|
||||
char *text; /* text (or NULL) */
|
||||
char *left;
|
||||
char *right;
|
||||
char *left; /* fence left-hand */
|
||||
char *right; /* fence right-hand */
|
||||
char *top; /* expression over-symbol */
|
||||
char *bottom; /* expression under-symbol */
|
||||
size_t args; /* arguments in parent */
|
||||
size_t expectargs; /* max arguments in parent */
|
||||
enum eqn_post pos; /* position of next box */
|
||||
enum eqn_markt mark; /* a mark about the box */
|
||||
enum eqn_fontt font; /* font of box */
|
||||
enum eqn_pilet pile; /* equation piling */
|
||||
};
|
||||
@ -383,6 +392,8 @@ struct eqn {
|
||||
#define MPARSE_MAN 2 /* assume -man */
|
||||
#define MPARSE_SO 4 /* honour .so requests */
|
||||
#define MPARSE_QUICK 8 /* abort the parse early */
|
||||
#define MPARSE_UTF8 16 /* accept UTF-8 input */
|
||||
#define MPARSE_LATIN1 32 /* accept ISO-LATIN-1 input */
|
||||
|
||||
enum mandoc_esc {
|
||||
ESCAPE_ERROR = 0, /* bail! unparsable escape */
|
||||
@ -413,16 +424,18 @@ __BEGIN_DECLS
|
||||
enum mandoc_esc mandoc_escape(const char **, const char **, int *);
|
||||
struct mchars *mchars_alloc(void);
|
||||
void mchars_free(struct mchars *);
|
||||
char mchars_num2char(const char *, size_t);
|
||||
int mchars_num2char(const char *, size_t);
|
||||
const char *mchars_uc2str(int);
|
||||
int mchars_num2uc(const char *, size_t);
|
||||
int mchars_spec2cp(const struct mchars *,
|
||||
const char *, size_t);
|
||||
const char *mchars_spec2str(const struct mchars *,
|
||||
const char *, size_t, size_t *);
|
||||
struct mparse *mparse_alloc(int, enum mandoclevel, mandocmsg,
|
||||
const char *);
|
||||
const struct mchars *, const char *);
|
||||
void mparse_free(struct mparse *);
|
||||
void mparse_keep(struct mparse *);
|
||||
enum mandoclevel mparse_open(struct mparse *, int *, const char *);
|
||||
enum mandoclevel mparse_readfd(struct mparse *, int, const char *);
|
||||
enum mandoclevel mparse_readmem(struct mparse *, const void *, size_t,
|
||||
const char *);
|
||||
@ -432,6 +445,7 @@ void mparse_result(struct mparse *,
|
||||
const char *mparse_getkeep(const struct mparse *);
|
||||
const char *mparse_strerror(enum mandocerr);
|
||||
const char *mparse_strlevel(enum mandoclevel);
|
||||
enum mandoclevel mparse_wait(struct mparse *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: mandoc_aux.c,v 1.3 2014/07/09 08:20:34 schwarze Exp $ */
|
||||
/* $Id: mandoc_aux.c,v 1.4 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $Id: mandoc_escape.3,v 1.1 2014/08/05 05:48:56 schwarze Exp $
|
||||
.\" $Id: mandoc_escape.3,v 1.2 2014/10/28 14:06:31 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
@ -14,7 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: August 5 2014 $
|
||||
.Dd $Mdocdate: October 28 2014 $
|
||||
.Dt MANDOC_ESCAPE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -197,15 +197,9 @@ form, directly follows the initial backslash:
|
||||
Note that the one-character argument short form can only be used for
|
||||
argument characters that do not clash with escape sequence identifiers.
|
||||
.Pp
|
||||
If the argument consists of more than one character
|
||||
and starts with the character
|
||||
.Sq u ,
|
||||
.Dv ESCAPE_UNICODE
|
||||
is returned as described below.
|
||||
If the argument is just the single character
|
||||
.Sq u ,
|
||||
.Dv ESCAPE_ERROR
|
||||
is returned.
|
||||
If the argument matches one of the forms described below under
|
||||
.Dv ESCAPE_UNICODE ,
|
||||
that value is returned instead.
|
||||
.Pp
|
||||
The
|
||||
.Dv ESCAPE_SPECIAL
|
||||
@ -219,17 +213,27 @@ manual.
|
||||
.It Dv ESCAPE_UNICODE
|
||||
Escape sequences of the same format as described above under
|
||||
.Dv ESCAPE_SPECIAL ,
|
||||
but with an argument starting with the character
|
||||
.Sq u :
|
||||
but with an argument of the forms
|
||||
.Ic u Ns Ar XXXX ,
|
||||
.Ic u Ns Ar YXXXX ,
|
||||
or
|
||||
.Ic u10 Ns Ar XXXX
|
||||
where
|
||||
.Ar X
|
||||
and
|
||||
.Ar Y
|
||||
are hexadecimal digits and
|
||||
.Ar Y
|
||||
is not zero:
|
||||
.Ic \eC'u , \e[u .
|
||||
As a special exception,
|
||||
.Fa start
|
||||
is set to the character after the
|
||||
.Sq u ,
|
||||
.Ic u ,
|
||||
and the
|
||||
.Fa sz
|
||||
return value does not include the
|
||||
.Sq u
|
||||
.Ic u
|
||||
either.
|
||||
.Pp
|
||||
Such Unicode character escape sequences can be rendered using the function
|
||||
|
184
mandocdb.c
184
mandocdb.c
@ -1,4 +1,4 @@
|
||||
/* $Id: mandocdb.c,v 1.155 2014/08/06 15:09:05 schwarze Exp $ */
|
||||
/* $Id: mandocdb.c,v 1.171 2014/11/27 01:58:21 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,10 +15,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
@ -26,7 +25,11 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#if HAVE_FTS
|
||||
#include <fts.h>
|
||||
#else
|
||||
#include "compat_fts.h"
|
||||
#endif
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
@ -36,7 +39,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_OHASH
|
||||
#if HAVE_OHASH
|
||||
#include <ohash.h>
|
||||
#else
|
||||
#include "compat_ohash.h"
|
||||
@ -80,12 +83,6 @@ enum op {
|
||||
OP_TEST /* change no databases, report potential problems */
|
||||
};
|
||||
|
||||
enum form {
|
||||
FORM_NONE, /* format is unknown */
|
||||
FORM_SRC, /* format is -man or -mdoc */
|
||||
FORM_CAT /* format is cat */
|
||||
};
|
||||
|
||||
struct str {
|
||||
char *rendered; /* key in UTF-8 or ASCII form */
|
||||
const struct mpage *mpage; /* if set, the owning parse */
|
||||
@ -101,24 +98,24 @@ struct inodev {
|
||||
struct mpage {
|
||||
struct inodev inodev; /* used for hashing routine */
|
||||
int64_t pageid; /* pageid in mpages SQL table */
|
||||
enum form form; /* format from file content */
|
||||
char *sec; /* section from file content */
|
||||
char *arch; /* architecture from file content */
|
||||
char *title; /* title from file content */
|
||||
char *desc; /* description from file content */
|
||||
struct mlink *mlinks; /* singly linked list */
|
||||
int form; /* format from file content */
|
||||
};
|
||||
|
||||
struct mlink {
|
||||
char file[PATH_MAX]; /* filename rel. to manpath */
|
||||
enum form dform; /* format from directory */
|
||||
enum form fform; /* format from file name suffix */
|
||||
char *dsec; /* section from directory */
|
||||
char *arch; /* architecture from directory */
|
||||
char *name; /* name from file name (not empty) */
|
||||
char *fsec; /* section from file name suffix */
|
||||
struct mlink *next; /* singly linked list */
|
||||
struct mpage *mpage; /* parent */
|
||||
int dform; /* format from directory */
|
||||
int fform; /* format from file name suffix */
|
||||
int gzip; /* filename has a .gz suffix */
|
||||
};
|
||||
|
||||
@ -141,6 +138,7 @@ struct mdoc_handler {
|
||||
static void dbclose(int);
|
||||
static void dbadd(struct mpage *, struct mchars *);
|
||||
static void dbadd_mlink(const struct mlink *mlink);
|
||||
static void dbadd_mlink_name(const struct mlink *mlink);
|
||||
static int dbopen(int);
|
||||
static void dbprune(void);
|
||||
static void filescan(const char *);
|
||||
@ -172,7 +170,7 @@ static void putmdockey(const struct mpage *,
|
||||
const struct mdoc_node *, uint64_t);
|
||||
static void render_key(struct mchars *, struct str *);
|
||||
static void say(const char *, const char *, ...);
|
||||
static int set_basedir(const char *);
|
||||
static int set_basedir(const char *, int);
|
||||
static int treescan(void);
|
||||
static size_t utf8(unsigned int, char [7]);
|
||||
|
||||
@ -318,6 +316,7 @@ static const struct mdoc_handler mdocs[MDOC_MAX] = {
|
||||
{ NULL, 0 }, /* sp */
|
||||
{ NULL, 0 }, /* %U */
|
||||
{ NULL, 0 }, /* Ta */
|
||||
{ NULL, 0 }, /* ll */
|
||||
};
|
||||
|
||||
|
||||
@ -427,9 +426,9 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
exitcode = (int)MANDOCLEVEL_OK;
|
||||
mp = mparse_alloc(mparse_options, MANDOCLEVEL_FATAL, NULL, NULL);
|
||||
mc = mchars_alloc();
|
||||
|
||||
mp = mparse_alloc(mparse_options, MANDOCLEVEL_FATAL, NULL,
|
||||
mc, NULL);
|
||||
ohash_init(&mpages, 6, &mpages_info);
|
||||
ohash_init(&mlinks, 6, &mlinks_info);
|
||||
|
||||
@ -439,7 +438,7 @@ main(int argc, char *argv[])
|
||||
* Most of these deal with a specific directory.
|
||||
* Jump into that directory first.
|
||||
*/
|
||||
if (OP_TEST != op && 0 == set_basedir(path_arg))
|
||||
if (OP_TEST != op && 0 == set_basedir(path_arg, 1))
|
||||
goto out;
|
||||
|
||||
if (dbopen(1)) {
|
||||
@ -505,12 +504,12 @@ main(int argc, char *argv[])
|
||||
ohash_init(&mlinks, 6, &mlinks_info);
|
||||
}
|
||||
|
||||
if (0 == set_basedir(dirs.paths[j]))
|
||||
goto out;
|
||||
if (0 == set_basedir(dirs.paths[j], argc > 0))
|
||||
continue;
|
||||
if (0 == treescan())
|
||||
goto out;
|
||||
continue;
|
||||
if (0 == dbopen(0))
|
||||
goto out;
|
||||
continue;
|
||||
|
||||
mpages_merge(mc, mp);
|
||||
if (warnings && !nodb &&
|
||||
@ -527,8 +526,8 @@ main(int argc, char *argv[])
|
||||
}
|
||||
out:
|
||||
manpath_free(&dirs);
|
||||
mchars_free(mc);
|
||||
mparse_free(mp);
|
||||
mchars_free(mc);
|
||||
mpages_free();
|
||||
ohash_delete(&mpages);
|
||||
ohash_delete(&mlinks);
|
||||
@ -835,6 +834,7 @@ filescan(const char *file)
|
||||
}
|
||||
|
||||
mlink = mandoc_calloc(1, sizeof(struct mlink));
|
||||
mlink->dform = FORM_NONE;
|
||||
if (strlcpy(mlink->file, start, sizeof(mlink->file)) >=
|
||||
sizeof(mlink->file)) {
|
||||
say(start, "Filename too long");
|
||||
@ -1078,15 +1078,13 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
{
|
||||
char any[] = "any";
|
||||
struct ohash_info str_info;
|
||||
int fd[2];
|
||||
struct mpage *mpage, *mpage_dest;
|
||||
struct mlink *mlink, *mlink_dest;
|
||||
struct mdoc *mdoc;
|
||||
struct man *man;
|
||||
char *sodest;
|
||||
char *cp;
|
||||
pid_t child_pid;
|
||||
int status;
|
||||
int fd;
|
||||
unsigned int pslot;
|
||||
enum mandoclevel lvl;
|
||||
|
||||
@ -1095,13 +1093,13 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
str_info.free = hash_free;
|
||||
str_info.key_offset = offsetof(struct str, key);
|
||||
|
||||
if (0 == nodb)
|
||||
if ( ! nodb)
|
||||
SQL_EXEC("BEGIN TRANSACTION");
|
||||
|
||||
mpage = ohash_first(&mpages, &pslot);
|
||||
while (NULL != mpage) {
|
||||
while (mpage != NULL) {
|
||||
mlinks_undupe(mpage);
|
||||
if (NULL == mpage->mlinks) {
|
||||
if (mpage->mlinks == NULL) {
|
||||
mpage = ohash_next(&mpages, &pslot);
|
||||
continue;
|
||||
}
|
||||
@ -1113,39 +1111,11 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
mdoc = NULL;
|
||||
man = NULL;
|
||||
sodest = NULL;
|
||||
child_pid = 0;
|
||||
fd[0] = -1;
|
||||
fd[1] = -1;
|
||||
|
||||
if (mpage->mlinks->gzip) {
|
||||
if (-1 == pipe(fd)) {
|
||||
exitcode = (int)MANDOCLEVEL_SYSERR;
|
||||
say(mpage->mlinks->file, "&pipe gunzip");
|
||||
goto nextpage;
|
||||
}
|
||||
switch (child_pid = fork()) {
|
||||
case -1:
|
||||
exitcode = (int)MANDOCLEVEL_SYSERR;
|
||||
say(mpage->mlinks->file, "&fork gunzip");
|
||||
child_pid = 0;
|
||||
close(fd[1]);
|
||||
close(fd[0]);
|
||||
goto nextpage;
|
||||
case 0:
|
||||
close(fd[0]);
|
||||
if (-1 == dup2(fd[1], STDOUT_FILENO)) {
|
||||
say(mpage->mlinks->file,
|
||||
"&dup gunzip");
|
||||
exit(1);
|
||||
}
|
||||
execlp("gunzip", "gunzip", "-c",
|
||||
mpage->mlinks->file, NULL);
|
||||
say(mpage->mlinks->file, "&exec gunzip");
|
||||
exit(1);
|
||||
default:
|
||||
close(fd[1]);
|
||||
break;
|
||||
}
|
||||
mparse_open(mp, &fd, mpage->mlinks->file);
|
||||
if (fd == -1) {
|
||||
say(mpage->mlinks->file, "&open");
|
||||
goto nextpage;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1153,17 +1123,23 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
* source code, unless it is already known to be
|
||||
* formatted. Fall back to formatted mode.
|
||||
*/
|
||||
if (FORM_CAT != mpage->mlinks->dform ||
|
||||
FORM_CAT != mpage->mlinks->fform) {
|
||||
lvl = mparse_readfd(mp, fd[0], mpage->mlinks->file);
|
||||
if (mpage->mlinks->dform != FORM_CAT ||
|
||||
mpage->mlinks->fform != FORM_CAT) {
|
||||
lvl = mparse_readfd(mp, fd, mpage->mlinks->file);
|
||||
if (lvl < MANDOCLEVEL_FATAL)
|
||||
mparse_result(mp, &mdoc, &man, &sodest);
|
||||
}
|
||||
|
||||
if (NULL != sodest) {
|
||||
if (sodest != NULL) {
|
||||
mlink_dest = ohash_find(&mlinks,
|
||||
ohash_qlookup(&mlinks, sodest));
|
||||
if (NULL != mlink_dest) {
|
||||
if (mlink_dest == NULL) {
|
||||
mandoc_asprintf(&cp, "%s.gz", sodest);
|
||||
mlink_dest = ohash_find(&mlinks,
|
||||
ohash_qlookup(&mlinks, cp));
|
||||
free(cp);
|
||||
}
|
||||
if (mlink_dest != NULL) {
|
||||
|
||||
/* The .so target exists. */
|
||||
|
||||
@ -1182,9 +1158,9 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
*/
|
||||
|
||||
if (mpage_dest->pageid)
|
||||
dbadd_mlink(mlink);
|
||||
dbadd_mlink_name(mlink);
|
||||
|
||||
if (NULL == mlink->next)
|
||||
if (mlink->next == NULL)
|
||||
break;
|
||||
mlink = mlink->next;
|
||||
}
|
||||
@ -1196,17 +1172,17 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
mpage->mlinks = NULL;
|
||||
}
|
||||
goto nextpage;
|
||||
} else if (NULL != mdoc) {
|
||||
} else if (mdoc != NULL) {
|
||||
mpage->form = FORM_SRC;
|
||||
mpage->sec = mdoc_meta(mdoc)->msec;
|
||||
mpage->sec = mandoc_strdup(
|
||||
NULL == mpage->sec ? "" : mpage->sec);
|
||||
mpage->sec == NULL ? "" : mpage->sec);
|
||||
mpage->arch = mdoc_meta(mdoc)->arch;
|
||||
mpage->arch = mandoc_strdup(
|
||||
NULL == mpage->arch ? "" : mpage->arch);
|
||||
mpage->arch == NULL ? "" : mpage->arch);
|
||||
mpage->title =
|
||||
mandoc_strdup(mdoc_meta(mdoc)->title);
|
||||
} else if (NULL != man) {
|
||||
} else if (man != NULL) {
|
||||
mpage->form = FORM_SRC;
|
||||
mpage->sec =
|
||||
mandoc_strdup(man_meta(man)->msec);
|
||||
@ -1224,8 +1200,8 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
mandoc_strdup(mpage->mlinks->name);
|
||||
}
|
||||
putkey(mpage, mpage->sec, TYPE_sec);
|
||||
putkey(mpage, '\0' == *mpage->arch ?
|
||||
any : mpage->arch, TYPE_arch);
|
||||
if (*mpage->arch != '\0')
|
||||
putkey(mpage, mpage->arch, TYPE_arch);
|
||||
|
||||
for (mlink = mpage->mlinks; mlink; mlink = mlink->next) {
|
||||
if ('\0' != *mlink->dsec)
|
||||
@ -1245,7 +1221,7 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
} else if (NULL != man)
|
||||
parse_man(mpage, man_node(man));
|
||||
else
|
||||
parse_cat(mpage, fd[0]);
|
||||
parse_cat(mpage, fd);
|
||||
if (NULL == mpage->desc)
|
||||
mpage->desc = mandoc_strdup(mpage->mlinks->name);
|
||||
|
||||
@ -1257,21 +1233,9 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
|
||||
dbadd(mpage, mc);
|
||||
|
||||
nextpage:
|
||||
if (child_pid) {
|
||||
if (-1 == waitpid(child_pid, &status, 0)) {
|
||||
exitcode = (int)MANDOCLEVEL_SYSERR;
|
||||
say(mpage->mlinks->file, "&wait gunzip");
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
exitcode = (int)MANDOCLEVEL_SYSERR;
|
||||
say(mpage->mlinks->file,
|
||||
"gunzip died from signal %d",
|
||||
WTERMSIG(status));
|
||||
} else if (WEXITSTATUS(status)) {
|
||||
exitcode = (int)MANDOCLEVEL_SYSERR;
|
||||
say(mpage->mlinks->file,
|
||||
"gunzip failed with code %d",
|
||||
WEXITSTATUS(status));
|
||||
}
|
||||
if (mparse_wait(mp) != MANDOCLEVEL_OK) {
|
||||
exitcode = (int)MANDOCLEVEL_SYSERR;
|
||||
say(mpage->mlinks->file, "&wait gunzip");
|
||||
}
|
||||
ohash_delete(&strings);
|
||||
ohash_delete(&names);
|
||||
@ -1329,6 +1293,8 @@ parse_cat(struct mpage *mpage, int fd)
|
||||
fopen(mpage->mlinks->file, "r") :
|
||||
fdopen(fd, "r");
|
||||
if (NULL == stream) {
|
||||
if (-1 != fd)
|
||||
close(fd);
|
||||
if (warnings)
|
||||
say(mpage->mlinks->file, "&fopen");
|
||||
return;
|
||||
@ -1764,7 +1730,8 @@ putkeys(const struct mpage *mpage,
|
||||
if (TYPE_Nm & v) {
|
||||
htab = &names;
|
||||
v &= name_mask;
|
||||
name_mask &= ~NAME_FIRST;
|
||||
if (v & NAME_FIRST)
|
||||
name_mask &= ~NAME_FIRST;
|
||||
if (debug > 1)
|
||||
say(mpage->mlinks->file,
|
||||
"Adding name %*s", sz, cp);
|
||||
@ -1772,7 +1739,7 @@ putkeys(const struct mpage *mpage,
|
||||
htab = &strings;
|
||||
if (debug > 1)
|
||||
for (i = 0; i < mansearch_keymax; i++)
|
||||
if (1 << i & v)
|
||||
if ((uint64_t)1 << i & v)
|
||||
say(mpage->mlinks->file,
|
||||
"Adding key %s=%*s",
|
||||
mansearch_keynames[i], sz, cp);
|
||||
@ -1939,7 +1906,7 @@ render_key(struct mchars *mc, struct str *key)
|
||||
*/
|
||||
|
||||
if (write_utf8) {
|
||||
if (0 == (u = mchars_spec2cp(mc, seq, len)))
|
||||
if ((u = mchars_spec2cp(mc, seq, len)) <= 0)
|
||||
continue;
|
||||
cpp = utfbuf;
|
||||
if (0 == (sz = utf8(u, utfbuf)))
|
||||
@ -1981,6 +1948,21 @@ dbadd_mlink(const struct mlink *mlink)
|
||||
sqlite3_reset(stmts[STMT_INSERT_LINK]);
|
||||
}
|
||||
|
||||
static void
|
||||
dbadd_mlink_name(const struct mlink *mlink)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
dbadd_mlink(mlink);
|
||||
|
||||
i = 1;
|
||||
SQL_BIND_INT64(stmts[STMT_INSERT_NAME], i, NAME_FILE & NAME_MASK);
|
||||
SQL_BIND_TEXT(stmts[STMT_INSERT_NAME], i, mlink->name);
|
||||
SQL_BIND_INT64(stmts[STMT_INSERT_NAME], i, mlink->mpage->pageid);
|
||||
SQL_STEP(stmts[STMT_INSERT_NAME]);
|
||||
sqlite3_reset(stmts[STMT_INSERT_NAME]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush the current page's terms (and their bits) into the database.
|
||||
* Wrap the entire set of additions in a transaction to make sqlite be a
|
||||
@ -2045,7 +2027,7 @@ dbadd(struct mpage *mpage, struct mchars *mc)
|
||||
|
||||
i = 1;
|
||||
SQL_BIND_TEXT(stmts[STMT_INSERT_PAGE], i, key->rendered);
|
||||
SQL_BIND_INT(stmts[STMT_INSERT_PAGE], i, FORM_SRC == mpage->form);
|
||||
SQL_BIND_INT(stmts[STMT_INSERT_PAGE], i, mpage->form);
|
||||
SQL_STEP(stmts[STMT_INSERT_PAGE]);
|
||||
mpage->pageid = sqlite3_last_insert_rowid(db);
|
||||
sqlite3_reset(stmts[STMT_INSERT_PAGE]);
|
||||
@ -2342,7 +2324,7 @@ dbopen(int real)
|
||||
"PRAGMA synchronous = OFF", NULL, NULL, NULL)) {
|
||||
exitcode = (int)MANDOCLEVEL_SYSERR;
|
||||
say(MANDOC_DB, "PRAGMA synchronous: %s",
|
||||
sqlite3_errmsg(db));
|
||||
sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return(0);
|
||||
}
|
||||
@ -2373,7 +2355,7 @@ hash_free(void *p, void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
set_basedir(const char *targetdir)
|
||||
set_basedir(const char *targetdir, int report_baddir)
|
||||
{
|
||||
static char startdir[PATH_MAX];
|
||||
static int getcwd_status; /* 1 = ok, 2 = failure */
|
||||
@ -2426,12 +2408,16 @@ set_basedir(const char *targetdir)
|
||||
* we can reliably check whether files are inside.
|
||||
*/
|
||||
if (NULL == realpath(targetdir, basedir)) {
|
||||
exitcode = (int)MANDOCLEVEL_BADARG;
|
||||
say("", "&%s: realpath", targetdir);
|
||||
if (report_baddir || errno != ENOENT) {
|
||||
exitcode = (int)MANDOCLEVEL_BADARG;
|
||||
say("", "&%s: realpath", targetdir);
|
||||
}
|
||||
return(0);
|
||||
} else if (-1 == chdir(basedir)) {
|
||||
exitcode = (int)MANDOCLEVEL_BADARG;
|
||||
say("", "&chdir");
|
||||
if (report_baddir || errno != ENOENT) {
|
||||
exitcode = (int)MANDOCLEVEL_BADARG;
|
||||
say("", "&chdir");
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
chdir_status = 1;
|
||||
|
11
manpage.c
11
manpage.c
@ -1,4 +1,4 @@
|
||||
/* $Id: manpage.c,v 1.7 2014/01/06 03:02:46 schwarze Exp $ */
|
||||
/* $Id: manpage.c,v 1.9 2014/08/17 03:24:47 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <getopt.h>
|
||||
@ -87,10 +87,11 @@ main(int argc, char *argv[])
|
||||
if (0 == argc)
|
||||
goto usage;
|
||||
|
||||
search.deftype = TYPE_Nm | TYPE_Nd;
|
||||
search.outkey = "Nd";
|
||||
search.argmode = ARG_EXPR;
|
||||
|
||||
manpath_parse(&paths, conf_file, defpaths, auxpaths);
|
||||
ch = mansearch(&search, &paths, argc, argv, "Nd", &res, &sz);
|
||||
ch = mansearch(&search, &paths, argc, argv, &res, &sz);
|
||||
manpath_free(&paths);
|
||||
|
||||
if (0 == ch)
|
||||
|
55
manpath.c
55
manpath.c
@ -1,6 +1,6 @@
|
||||
/* $Id: manpath.c,v 1.15 2014/04/23 21:06:41 schwarze Exp $ */
|
||||
/* $Id: manpath.c,v 1.19 2014/11/27 00:30:40 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -15,9 +15,10 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@ -32,14 +33,14 @@
|
||||
#define MAN_CONF_FILE "/etc/man.conf"
|
||||
#define MAN_CONF_KEY "_whatdb"
|
||||
|
||||
static void manpath_add(struct manpaths *, const char *);
|
||||
static void manpath_parseline(struct manpaths *, char *);
|
||||
static void manpath_add(struct manpaths *, const char *, int);
|
||||
static void manpath_parseline(struct manpaths *, char *, int);
|
||||
|
||||
void
|
||||
manpath_parse(struct manpaths *dirs, const char *file,
|
||||
char *defp, char *auxp)
|
||||
{
|
||||
#ifdef USE_MANPATH
|
||||
#if HAVE_MANPATH
|
||||
char cmd[(PATH_MAX * 3) + 20];
|
||||
FILE *stream;
|
||||
char *buf;
|
||||
@ -79,7 +80,7 @@ manpath_parse(struct manpaths *dirs, const char *file,
|
||||
if ( ! ferror(stream) && feof(stream) &&
|
||||
bsz && '\n' == buf[bsz - 1]) {
|
||||
buf[bsz - 1] = '\0';
|
||||
manpath_parseline(dirs, buf);
|
||||
manpath_parseline(dirs, buf, 1);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
@ -88,11 +89,11 @@ manpath_parse(struct manpaths *dirs, const char *file,
|
||||
char *insert;
|
||||
|
||||
/* Always prepend -m. */
|
||||
manpath_parseline(dirs, auxp);
|
||||
manpath_parseline(dirs, auxp, 1);
|
||||
|
||||
/* If -M is given, it overrides everything else. */
|
||||
if (NULL != defp) {
|
||||
manpath_parseline(dirs, defp);
|
||||
manpath_parseline(dirs, defp, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -110,13 +111,13 @@ manpath_parse(struct manpaths *dirs, const char *file,
|
||||
/* Prepend man.conf(5) to MANPATH. */
|
||||
if (':' == defp[0]) {
|
||||
manpath_manconf(dirs, file);
|
||||
manpath_parseline(dirs, defp);
|
||||
manpath_parseline(dirs, defp, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Append man.conf(5) to MANPATH. */
|
||||
if (':' == defp[strlen(defp) - 1]) {
|
||||
manpath_parseline(dirs, defp);
|
||||
manpath_parseline(dirs, defp, 0);
|
||||
manpath_manconf(dirs, file);
|
||||
return;
|
||||
}
|
||||
@ -125,14 +126,14 @@ manpath_parse(struct manpaths *dirs, const char *file,
|
||||
insert = strstr(defp, "::");
|
||||
if (NULL != insert) {
|
||||
*insert++ = '\0';
|
||||
manpath_parseline(dirs, defp);
|
||||
manpath_parseline(dirs, defp, 0);
|
||||
manpath_manconf(dirs, file);
|
||||
manpath_parseline(dirs, insert + 1);
|
||||
manpath_parseline(dirs, insert + 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* MANPATH overrides man.conf(5) completely. */
|
||||
manpath_parseline(dirs, defp);
|
||||
manpath_parseline(dirs, defp, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -140,7 +141,7 @@ manpath_parse(struct manpaths *dirs, const char *file,
|
||||
* Parse a FULL pathname from a colon-separated list of arrays.
|
||||
*/
|
||||
static void
|
||||
manpath_parseline(struct manpaths *dirs, char *path)
|
||||
manpath_parseline(struct manpaths *dirs, char *path, int complain)
|
||||
{
|
||||
char *dir;
|
||||
|
||||
@ -148,7 +149,7 @@ manpath_parseline(struct manpaths *dirs, char *path)
|
||||
return;
|
||||
|
||||
for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
|
||||
manpath_add(dirs, dir);
|
||||
manpath_add(dirs, dir, complain);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -156,19 +157,33 @@ manpath_parseline(struct manpaths *dirs, char *path)
|
||||
* Grow the array one-by-one for simplicity's sake.
|
||||
*/
|
||||
static void
|
||||
manpath_add(struct manpaths *dirs, const char *dir)
|
||||
manpath_add(struct manpaths *dirs, const char *dir, int complain)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
struct stat sb;
|
||||
char *cp;
|
||||
size_t i;
|
||||
|
||||
if (NULL == (cp = realpath(dir, buf)))
|
||||
if (NULL == (cp = realpath(dir, buf))) {
|
||||
if (complain) {
|
||||
fputs("manpath: ", stderr);
|
||||
perror(dir);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < dirs->sz; i++)
|
||||
if (0 == strcmp(dirs->paths[i], dir))
|
||||
return;
|
||||
|
||||
if (stat(cp, &sb) == -1) {
|
||||
if (complain) {
|
||||
fputs("manpath: ", stderr);
|
||||
perror(dir);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
dirs->paths = mandoc_reallocarray(dirs->paths,
|
||||
dirs->sz + 1, sizeof(char *));
|
||||
|
||||
@ -215,7 +230,7 @@ manpath_manconf(struct manpaths *dirs, const char *file)
|
||||
if (NULL == (q = strrchr(p, '/')))
|
||||
continue;
|
||||
*q = '\0';
|
||||
manpath_add(dirs, p);
|
||||
manpath_add(dirs, p, 0);
|
||||
}
|
||||
|
||||
fclose(stream);
|
||||
|
104
mansearch.c
104
mansearch.c
@ -1,4 +1,4 @@
|
||||
/* $Id: mansearch.c,v 1.42 2014/08/09 14:24:53 schwarze Exp $ */
|
||||
/* $Id: mansearch.c,v 1.51 2014/11/27 01:58:21 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,11 +15,11 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
@ -32,7 +32,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_OHASH
|
||||
#if HAVE_OHASH
|
||||
#include <ohash.h>
|
||||
#else
|
||||
#include "compat_ohash.h"
|
||||
@ -79,8 +79,9 @@ struct expr {
|
||||
|
||||
struct match {
|
||||
uint64_t pageid; /* identifier in database */
|
||||
uint64_t bits; /* name type mask */
|
||||
char *desc; /* manual page description */
|
||||
int form; /* 0 == catpage */
|
||||
int form; /* bit field: formatted, zipped? */
|
||||
};
|
||||
|
||||
static void buildnames(struct manpage *, sqlite3 *,
|
||||
@ -159,7 +160,6 @@ int
|
||||
mansearch(const struct mansearch *search,
|
||||
const struct manpaths *paths,
|
||||
int argc, char *argv[],
|
||||
const char *outkey,
|
||||
struct manpage **res, size_t *sz)
|
||||
{
|
||||
int fd, rc, c, indexbit;
|
||||
@ -195,11 +195,11 @@ mansearch(const struct mansearch *search,
|
||||
goto out;
|
||||
|
||||
outbit = 0;
|
||||
if (NULL != outkey) {
|
||||
if (NULL != search->outkey) {
|
||||
for (indexbit = 0, iterbit = 1;
|
||||
indexbit < mansearch_keymax;
|
||||
indexbit++, iterbit <<= 1) {
|
||||
if (0 == strcasecmp(outkey,
|
||||
if (0 == strcasecmp(search->outkey,
|
||||
mansearch_keynames[indexbit])) {
|
||||
outbit = iterbit;
|
||||
break;
|
||||
@ -302,6 +302,7 @@ mansearch(const struct mansearch *search,
|
||||
mp = mandoc_calloc(1, sizeof(struct match));
|
||||
mp->pageid = pageid;
|
||||
mp->form = sqlite3_column_int(s, 1);
|
||||
mp->bits = sqlite3_column_int64(s, 3);
|
||||
if (TYPE_Nd == outbit)
|
||||
mp->desc = mandoc_strdup((const char *)
|
||||
sqlite3_column_text(s, 0));
|
||||
@ -336,6 +337,8 @@ mansearch(const struct mansearch *search,
|
||||
maxres, sizeof(struct manpage));
|
||||
}
|
||||
mpage = *res + cur;
|
||||
mpage->ipath = i;
|
||||
mpage->bits = mp->bits;
|
||||
mpage->sec = 10;
|
||||
mpage->form = mp->form;
|
||||
buildnames(mpage, db, s, mp->pageid,
|
||||
@ -352,6 +355,14 @@ mansearch(const struct mansearch *search,
|
||||
sqlite3_finalize(s2);
|
||||
sqlite3_close(db);
|
||||
ohash_delete(&htab);
|
||||
|
||||
/*
|
||||
* In man(1) mode, prefer matches in earlier trees
|
||||
* over matches in later trees.
|
||||
*/
|
||||
|
||||
if (cur && search->firstmatch)
|
||||
break;
|
||||
}
|
||||
qsort(*res, cur, sizeof(struct manpage), manpage_compare);
|
||||
rc = 1;
|
||||
@ -367,6 +378,19 @@ mansearch(const struct mansearch *search,
|
||||
return(rc);
|
||||
}
|
||||
|
||||
void
|
||||
mansearch_free(struct manpage *res, size_t sz)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
free(res[i].file);
|
||||
free(res[i].names);
|
||||
free(res[i].output);
|
||||
}
|
||||
free(res);
|
||||
}
|
||||
|
||||
static int
|
||||
manpage_compare(const void *vp1, const void *vp2)
|
||||
{
|
||||
@ -375,8 +399,9 @@ manpage_compare(const void *vp1, const void *vp2)
|
||||
|
||||
mp1 = vp1;
|
||||
mp2 = vp2;
|
||||
diff = mp1->sec - mp2->sec;
|
||||
return(diff ? diff : strcasecmp(mp1->names, mp2->names));
|
||||
return( (diff = mp2->bits - mp1->bits) ? diff :
|
||||
(diff = mp1->sec - mp2->sec) ? diff :
|
||||
strcasecmp(mp1->names, mp2->names));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -447,28 +472,28 @@ buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s,
|
||||
|
||||
/* Also save the first file name encountered. */
|
||||
|
||||
if (NULL != mpage->file)
|
||||
if (mpage->file != NULL)
|
||||
continue;
|
||||
|
||||
if (form) {
|
||||
if (form & FORM_SRC) {
|
||||
sep1 = "man";
|
||||
fsec = sec;
|
||||
} else {
|
||||
sep1 = "cat";
|
||||
fsec = "0";
|
||||
}
|
||||
sep2 = '\0' == *arch ? "" : "/";
|
||||
sep2 = *arch == '\0' ? "" : "/";
|
||||
mandoc_asprintf(&mpage->file, "%s/%s%s%s%s/%s.%s",
|
||||
path, sep1, sec, sep2, arch, name, fsec);
|
||||
}
|
||||
if (SQLITE_DONE != c)
|
||||
if (c != SQLITE_DONE)
|
||||
fprintf(stderr, "%s\n", sqlite3_errmsg(db));
|
||||
sqlite3_reset(s);
|
||||
|
||||
/* Append one final section to the names. */
|
||||
|
||||
if (NULL != prevsec) {
|
||||
sep2 = '\0' == *prevarch ? "" : "/";
|
||||
if (prevsec != NULL) {
|
||||
sep2 = *prevarch == '\0' ? "" : "/";
|
||||
mandoc_asprintf(&newnames, "%s(%s%s%s)",
|
||||
mpage->names, prevsec, sep2, prevarch);
|
||||
free(mpage->names);
|
||||
@ -566,8 +591,10 @@ sql_statement(const struct expr *e)
|
||||
size_t sz;
|
||||
int needop;
|
||||
|
||||
sql = mandoc_strdup(
|
||||
"SELECT desc, form, pageid FROM mpages WHERE ");
|
||||
sql = mandoc_strdup(e->equal ?
|
||||
"SELECT desc, form, pageid, bits "
|
||||
"FROM mpages NATURAL JOIN names WHERE " :
|
||||
"SELECT desc, form, pageid, 0 FROM mpages WHERE ");
|
||||
sz = strlen(sql);
|
||||
|
||||
for (needop = 0; NULL != e; e = e->next) {
|
||||
@ -587,8 +614,7 @@ sql_statement(const struct expr *e)
|
||||
? "pageid IN (SELECT pageid FROM names "
|
||||
"WHERE name REGEXP ?)"
|
||||
: e->equal
|
||||
? "pageid IN (SELECT pageid FROM names "
|
||||
"WHERE name = ?)"
|
||||
? "name = ? "
|
||||
: "pageid IN (SELECT pageid FROM names "
|
||||
"WHERE name MATCH ?)")
|
||||
: (NULL == e->substr
|
||||
@ -739,35 +765,30 @@ exprterm(const struct mansearch *search, char *buf, int cs)
|
||||
|
||||
e = mandoc_calloc(1, sizeof(struct expr));
|
||||
|
||||
if (MANSEARCH_MAN & search->flags) {
|
||||
e->bits = search->deftype;
|
||||
if (search->argmode == ARG_NAME) {
|
||||
e->bits = TYPE_Nm;
|
||||
e->substr = buf;
|
||||
e->equal = 1;
|
||||
return(e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for an '=' or '~' operator,
|
||||
* unless forced to some fixed macro keys.
|
||||
* Separate macro keys from search string.
|
||||
* If needed, request regular expression handling
|
||||
* by setting e->substr to NULL.
|
||||
*/
|
||||
|
||||
if (MANSEARCH_WHATIS & search->flags)
|
||||
val = NULL;
|
||||
else
|
||||
val = strpbrk(buf, "=~");
|
||||
|
||||
if (NULL == val) {
|
||||
e->bits = search->deftype;
|
||||
if (search->argmode == ARG_WORD) {
|
||||
e->bits = TYPE_Nm;
|
||||
e->substr = NULL;
|
||||
mandoc_asprintf(&val, "[[:<:]]%s[[:>:]]", buf);
|
||||
cs = 0;
|
||||
} else if ((val = strpbrk(buf, "=~")) == NULL) {
|
||||
e->bits = TYPE_Nm | TYPE_Nd;
|
||||
e->substr = buf;
|
||||
|
||||
/*
|
||||
* Found an operator.
|
||||
* Regexp search is requested by !e->substr.
|
||||
*/
|
||||
|
||||
} else {
|
||||
if (val == buf)
|
||||
e->bits = search->deftype;
|
||||
e->bits = TYPE_Nm | TYPE_Nd;
|
||||
if ('=' == *val)
|
||||
e->substr = val + 1;
|
||||
*val++ = '\0';
|
||||
@ -777,15 +798,10 @@ exprterm(const struct mansearch *search, char *buf, int cs)
|
||||
|
||||
/* Compile regular expressions. */
|
||||
|
||||
if (MANSEARCH_WHATIS & search->flags) {
|
||||
e->substr = NULL;
|
||||
mandoc_asprintf(&val, "[[:<:]]%s[[:>:]]", buf);
|
||||
}
|
||||
|
||||
if (NULL == e->substr) {
|
||||
irc = regcomp(&e->regexp, val,
|
||||
REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE));
|
||||
if (MANSEARCH_WHATIS & search->flags)
|
||||
if (search->argmode == ARG_WORD)
|
||||
free(val);
|
||||
if (irc) {
|
||||
regerror(irc, &e->regexp, errbuf, sizeof(errbuf));
|
||||
|
36
mansearch.h
36
mansearch.h
@ -1,4 +1,4 @@
|
||||
/* $Id: mansearch.h,v 1.15 2014/07/24 20:30:45 schwarze Exp $ */
|
||||
/* $Id: mansearch.h,v 1.21 2014/11/27 01:58:21 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -62,18 +62,29 @@
|
||||
#define TYPE_Nd 0x0000008000000000ULL
|
||||
|
||||
#define NAME_SYN 0x0000004000000001ULL
|
||||
#define NAME_FILE 0x0000004000000002ULL
|
||||
#define NAME_TITLE 0x000000400000000cULL
|
||||
#define NAME_FIRST 0x0000004000000008ULL
|
||||
#define NAME_HEAD 0x0000004000000010ULL
|
||||
#define NAME_FIRST 0x0000004000000004ULL
|
||||
#define NAME_TITLE 0x0000004000000006ULL
|
||||
#define NAME_HEAD 0x0000004000000008ULL
|
||||
#define NAME_FILE 0x0000004000000010ULL
|
||||
#define NAME_MASK 0x000000000000001fULL
|
||||
|
||||
__BEGIN_DECLS
|
||||
#define FORM_CAT 0 /* manual page is preformatted */
|
||||
#define FORM_SRC 1 /* format is mdoc(7) or man(7) */
|
||||
#define FORM_NONE 4 /* format is unknown */
|
||||
|
||||
enum argmode {
|
||||
ARG_FILE = 0,
|
||||
ARG_NAME,
|
||||
ARG_WORD,
|
||||
ARG_EXPR
|
||||
};
|
||||
|
||||
struct manpage {
|
||||
char *file; /* to be prefixed by manpath */
|
||||
char *names; /* a list of names with sections */
|
||||
char *output; /* user-defined additional output */
|
||||
size_t ipath; /* number of the manpath */
|
||||
uint64_t bits; /* name type mask */
|
||||
int sec; /* section number, 10 means invalid */
|
||||
int form; /* 0 == catpage */
|
||||
};
|
||||
@ -81,21 +92,22 @@ struct manpage {
|
||||
struct mansearch {
|
||||
const char *arch; /* architecture/NULL */
|
||||
const char *sec; /* mansection/NULL */
|
||||
uint64_t deftype; /* type if no key */
|
||||
int flags;
|
||||
#define MANSEARCH_WHATIS 0x01 /* whatis(1) mode: whole words, no keys */
|
||||
#define MANSEARCH_MAN 0x02 /* man(1) mode: string equality, no keys */
|
||||
const char *outkey; /* show content of this macro */
|
||||
enum argmode argmode; /* interpretation of arguments */
|
||||
int firstmatch; /* first matching database only */
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int mansearch_setup(int);
|
||||
int mansearch(const struct mansearch *cfg, /* options */
|
||||
const struct manpaths *paths, /* manpaths */
|
||||
int argc, /* size of argv */
|
||||
char *argv[], /* search terms */
|
||||
const char *outkey, /* name of additional output key */
|
||||
struct manpage **res, /* results */
|
||||
size_t *ressz); /* results returned */
|
||||
void mansearch_free(struct manpage *, size_t);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /*!MANSEARCH_H*/
|
||||
#endif /* MANSEARCH_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: mansearch_const.c,v 1.5 2014/08/09 14:05:21 schwarze Exp $ */
|
||||
/* $Id: mansearch_const.c,v 1.6 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
@ -14,11 +14,10 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "manpath.h"
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $Id: mchars_alloc.3,v 1.1 2014/08/05 05:48:56 schwarze Exp $
|
||||
.\" $Id: mchars_alloc.3,v 1.2 2014/10/26 18:07:28 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
@ -14,7 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: August 5 2014 $
|
||||
.Dd $Mdocdate: October 26 2014 $
|
||||
.Dt MCHARS_ALLOC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -59,6 +59,8 @@
|
||||
.Fa "size_t sz"
|
||||
.Fa "size_t *rsz"
|
||||
.Fc
|
||||
.Ft "const char *"
|
||||
.Fn mchars_uc2str "int codepoint"
|
||||
.Sh DESCRIPTION
|
||||
These functions translate Unicode character numbers and
|
||||
.Xr roff 7
|
||||
@ -199,6 +201,14 @@ output module use this function to render
|
||||
and
|
||||
.Ic \eC\(aq Ns Ar name Ns Ic \(aq
|
||||
escape sequences.
|
||||
.Pp
|
||||
The function
|
||||
.Fn mchars_uc2str
|
||||
performs a reverse lookup of the Unicode
|
||||
.Fa codepoint
|
||||
and returns an ASCII string representation, or the string
|
||||
.Qq <?>
|
||||
if none is available.
|
||||
.Sh FILES
|
||||
These funtions are implemented in the file
|
||||
.Pa chars.c .
|
||||
@ -218,6 +228,7 @@ following mandoc versions:
|
||||
.It Fn mchars_num2uc Ta 1.11.3 Ta \(em Ta \(em
|
||||
.It Fn mchars_spec2cp Ta 1.11.2 Ta Fn chars_spec2cp Ta 1.10.5
|
||||
.It Fn mchars_spec2str Ta 1.11.2 Ta Fn a2ascii Ta 1.5.3
|
||||
.It Fn mchars_uc2str Ta 1.13.2 Ta \(em Ta \(em
|
||||
.El
|
||||
.Sh AUTHORS
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
|
||||
|
175
mdoc.7
175
mdoc.7
@ -1,4 +1,4 @@
|
||||
.\" $Id: mdoc.7,v 1.234 2014/08/08 16:38:06 schwarze Exp $
|
||||
.\" $Id: mdoc.7,v 1.244 2014/11/28 18:36:35 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" 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
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: August 8 2014 $
|
||||
.Dd $Mdocdate: November 28 2014 $
|
||||
.Dt MDOC 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -388,7 +388,7 @@ See
|
||||
References other manuals with related topics.
|
||||
This section should exist for most manuals.
|
||||
Cross-references should conventionally be ordered first by section, then
|
||||
alphabetically.
|
||||
alphabetically (ignoring case).
|
||||
.Pp
|
||||
References to other documentation concerning the topic of the manual page,
|
||||
for example authoritative books or journal articles, may also be
|
||||
@ -433,7 +433,7 @@ in the alphabetical
|
||||
.Ss Document preamble and NAME section macros
|
||||
.Bl -column "Brq, Bro, Brc" description
|
||||
.It Sx \&Dd Ta document date: Cm $\&Mdocdate$ | Ar month day , year
|
||||
.It Sx \&Dt Ta document title: Ar TITLE section Op Ar volume | arch
|
||||
.It Sx \&Dt Ta document title: Ar TITLE section Op Ar arch
|
||||
.It Sx \&Os Ta operating system version: Op Ar system Op Ar version
|
||||
.It Sx \&Nm Ta document name (one argument)
|
||||
.It Sx \&Nd Ta document description (one line)
|
||||
@ -937,8 +937,11 @@ The
|
||||
.Fl width
|
||||
and
|
||||
.Fl offset
|
||||
arguments accept scaling widths as described in
|
||||
.Xr roff 7
|
||||
arguments accept macro names as described for
|
||||
.Sx \&Bd
|
||||
.Fl offset ,
|
||||
scaling widths as described in
|
||||
.Xr roff 7 ,
|
||||
or use the length of the given string.
|
||||
The
|
||||
.Fl offset
|
||||
@ -1182,13 +1185,12 @@ See also
|
||||
and
|
||||
.Sx \&Dl .
|
||||
.Ss \&Db
|
||||
Switch debugging mode.
|
||||
Its syntax is as follows:
|
||||
.Pp
|
||||
.D1 Pf \. Sx \&Db Cm on | off
|
||||
.Pp
|
||||
This macro is ignored by
|
||||
.Xr mandoc 1 .
|
||||
This macro is obsolete.
|
||||
No replacement is needed.
|
||||
It is ignored by
|
||||
.Xr mandoc 1
|
||||
and groff including its arguments.
|
||||
It was formerly used to toggle a debugging mode.
|
||||
.Ss \&Dc
|
||||
Close a
|
||||
.Sx \&Do
|
||||
@ -1245,7 +1247,7 @@ See also
|
||||
and
|
||||
.Sx \&Os .
|
||||
.Ss \&Dl
|
||||
One-line intended display.
|
||||
One-line indented display.
|
||||
This is formatted as literal text and is useful for commands and
|
||||
invocations.
|
||||
It is followed by a newline.
|
||||
@ -1297,7 +1299,7 @@ Its syntax is as follows:
|
||||
.Pf \. Sx \&Dt
|
||||
.Ar TITLE
|
||||
.Ar section
|
||||
.Op Ar volume | arch
|
||||
.Op Ar arch
|
||||
.Ed
|
||||
.Pp
|
||||
Its arguments are as follows:
|
||||
@ -1346,35 +1348,6 @@ or
|
||||
.Pq paper .
|
||||
It should correspond to the manual's filename suffix and defaults to
|
||||
the empty string if unspecified.
|
||||
.It Ar volume
|
||||
This overrides the volume inferred from
|
||||
.Ar section .
|
||||
This field is optional, and if specified, must be one of
|
||||
.Cm USD
|
||||
.Pq users' supplementary documents ,
|
||||
.Cm PS1
|
||||
.Pq programmers' supplementary documents ,
|
||||
.Cm AMD
|
||||
.Pq administrators' supplementary documents ,
|
||||
.Cm SMM
|
||||
.Pq system managers' manuals ,
|
||||
.Cm URM
|
||||
.Pq users' reference manuals ,
|
||||
.Cm PRM
|
||||
.Pq programmers' reference manuals ,
|
||||
.Cm KM
|
||||
.Pq kernel manuals ,
|
||||
.Cm IND
|
||||
.Pq master index ,
|
||||
.Cm MMI
|
||||
.Pq master index ,
|
||||
.Cm LOCAL
|
||||
.Pq local manuals ,
|
||||
.Cm LOC
|
||||
.Pq local manuals ,
|
||||
or
|
||||
.Cm CON
|
||||
.Pq contributed manuals .
|
||||
.It Ar arch
|
||||
This specifies the machine architecture a manual page applies to,
|
||||
where relevant, for example
|
||||
@ -1383,17 +1356,11 @@ where relevant, for example
|
||||
.Cm i386 ,
|
||||
or
|
||||
.Cm sparc64 .
|
||||
The list of supported architectures varies by operating system.
|
||||
For the full list of all architectures recognized by
|
||||
.Xr mandoc 1 ,
|
||||
see the file
|
||||
.Pa arch.in
|
||||
in the source distribution.
|
||||
The list of valid architectures varies by operating system.
|
||||
.El
|
||||
.Pp
|
||||
Examples:
|
||||
.Dl \&.Dt FOO 1
|
||||
.Dl \&.Dt FOO 4 KM
|
||||
.Dl \&.Dt FOO 9 i386
|
||||
.Pp
|
||||
See also
|
||||
@ -1467,16 +1434,29 @@ See also
|
||||
and
|
||||
.Sx \&It .
|
||||
.Ss \&Em
|
||||
Denotes text that should be
|
||||
.Em emphasised .
|
||||
Note that this is a presentation term and should not be used for
|
||||
stylistically decorating technical terms.
|
||||
Depending on the output device, this is usually represented
|
||||
using an italic font or underlined characters.
|
||||
Request an italic font.
|
||||
If the output device does not provide that, underline.
|
||||
.Pp
|
||||
This is most often used for stress emphasis (not to be confused with
|
||||
importance, see
|
||||
.Sx \&Sy ) .
|
||||
In the rare cases where none of the semantic markup macros fit,
|
||||
it can also be used for technical terms and placeholders, except
|
||||
that for syntax elements,
|
||||
.Sx \&Sy
|
||||
and
|
||||
.Sx \&Ar
|
||||
are preferred, respectively.
|
||||
.Pp
|
||||
Examples:
|
||||
.Dl \&.Em Warnings!
|
||||
.Dl \&.Em Remarks :
|
||||
.Bd -literal -compact -offset indent
|
||||
Selected lines are those
|
||||
\&.Em not
|
||||
matching any of the specified patterns.
|
||||
Some of the functions use a
|
||||
\&.Em hold space
|
||||
to save the pattern space for subsequent retrieval.
|
||||
.Ed
|
||||
.Pp
|
||||
See also
|
||||
.Sx \&Bf ,
|
||||
@ -1557,7 +1537,7 @@ arguments are treated as separate utilities.
|
||||
See also
|
||||
.Sx \&Rv .
|
||||
.Ss \&Fa
|
||||
Function argument.
|
||||
Function argument or parameter.
|
||||
Its syntax is as follows:
|
||||
.Bd -ragged -offset indent
|
||||
.Pf \. Sx \&Fa
|
||||
@ -2497,10 +2477,12 @@ Based on POSIX.1 and POSIX.2, published in 1992.
|
||||
.It Single UNIX Specification version 1 and related standards
|
||||
.Pp
|
||||
.Bl -tag -width "-p1003.1g-2000" -compact
|
||||
.It \-susv1
|
||||
.St -susv1
|
||||
.It \-xpg4.2
|
||||
.St -xpg4.2
|
||||
.br
|
||||
This standard was published in 1994 and is also called SUSv1.
|
||||
This standard was published in 1994.
|
||||
It was used as the basis for UNIX 95 certification.
|
||||
The following three refer to parts of it.
|
||||
.Pp
|
||||
@ -2544,17 +2526,8 @@ The following refer to parts of it.
|
||||
.Pp
|
||||
.It \-xns5
|
||||
.St -xns5
|
||||
.It \-xns5.2d2.0
|
||||
.St -xns5.2d2.0
|
||||
.It \-xns5.2
|
||||
.St -xns5.2
|
||||
.Pp
|
||||
.It \-p1387.2
|
||||
.St -p1387.2
|
||||
.It \-p1387.2-95
|
||||
.St -p1387.2-95
|
||||
.br
|
||||
POSIX software administration.
|
||||
.El
|
||||
.It Single UNIX Specification version 3 and related standards
|
||||
.Pp
|
||||
@ -2564,16 +2537,6 @@ POSIX software administration.
|
||||
.br
|
||||
Additional real-time extensions.
|
||||
.Pp
|
||||
.It \-p1003.1j-2000
|
||||
.St -p1003.1j-2000
|
||||
.br
|
||||
Advanced real-time extensions.
|
||||
.Pp
|
||||
.It \-p1003.1q-2000
|
||||
.St -p1003.1q-2000
|
||||
.br
|
||||
Amendment 7: Tracing [C Language].
|
||||
.Pp
|
||||
.It \-p1003.1-2001
|
||||
.St -p1003.1-2001
|
||||
.It \-susv3
|
||||
@ -2593,8 +2556,10 @@ The second and last Technical Corrigendum.
|
||||
.Bl -tag -width "-p1003.1g-2000" -compact
|
||||
.It \-p1003.1-2008
|
||||
.St -p1003.1-2008
|
||||
.It \-susv4
|
||||
.St -susv4
|
||||
.br
|
||||
This standard is also called SUSv4 and
|
||||
This standard is also called
|
||||
X/Open Portability Guide version 7.
|
||||
.Pp
|
||||
.It \-p1003.1-2013
|
||||
@ -2637,10 +2602,24 @@ See also
|
||||
and
|
||||
.Sx \&Ss .
|
||||
.Ss \&Sy
|
||||
Format enclosed arguments in symbolic
|
||||
.Pq Dq boldface .
|
||||
Note that this is a presentation term and should not be used for
|
||||
stylistically decorating technical terms.
|
||||
Request a boldface font.
|
||||
.Pp
|
||||
This is most often used to indicate importance or seriousness (not to be
|
||||
confused with stress emphasis, see
|
||||
.Sx \&Em ) .
|
||||
When none of the semantic macros fit, it is also adequate for syntax
|
||||
elements that have to be given or that appear verbatim.
|
||||
.Pp
|
||||
Examples:
|
||||
.Bd -literal -compact -offset indent
|
||||
\&.Sy Warning :
|
||||
If
|
||||
\&.Sy s
|
||||
appears in the owner permissions, set-user-ID mode is set.
|
||||
This utility replaces the former
|
||||
\&.Sy dumpdir
|
||||
program.
|
||||
.Ed
|
||||
.Pp
|
||||
See also
|
||||
.Sx \&Bf ,
|
||||
@ -2673,8 +2652,17 @@ A variable name.
|
||||
Examples:
|
||||
.Dl \&.Va foo
|
||||
.Dl \&.Va const char *bar ;
|
||||
.Pp
|
||||
For function arguments and parameters, use
|
||||
.Sx \&Fa
|
||||
instead.
|
||||
For declarations of global variables in the
|
||||
.Em SYNOPSIS
|
||||
section, use
|
||||
.Sx \&Vt .
|
||||
.Ss \&Vt
|
||||
A variable type.
|
||||
.Pp
|
||||
This is also used for indicating global variables in the
|
||||
.Em SYNOPSIS
|
||||
section, in which case a variable name is also specified.
|
||||
@ -2689,18 +2677,21 @@ In the former case, this macro starts a new output line,
|
||||
and a blank line is inserted in front if there is a preceding
|
||||
function definition or include directive.
|
||||
.Pp
|
||||
Note that this should not be confused with
|
||||
.Sx \&Ft ,
|
||||
which is used for function return types.
|
||||
.Pp
|
||||
Examples:
|
||||
.Dl \&.Vt unsigned char
|
||||
.Dl \&.Vt extern const char * const sys_signame[] \&;
|
||||
.Pp
|
||||
For parameters in function prototypes, use
|
||||
.Sx \&Fa
|
||||
instead, for function return types
|
||||
.Sx \&Ft ,
|
||||
and for variable names outside the
|
||||
.Em SYNOPSIS
|
||||
section
|
||||
.Sx \&Va ,
|
||||
even when including a type with the name.
|
||||
See also
|
||||
.Sx MANUAL STRUCTURE
|
||||
and
|
||||
.Sx \&Va .
|
||||
.Sx MANUAL STRUCTURE .
|
||||
.Ss \&Xc
|
||||
Close a scope opened by
|
||||
.Sx \&Xo .
|
||||
|
229
mdoc.c
229
mdoc.c
@ -1,4 +1,4 @@
|
||||
/* $Id: mdoc.c,v 1.223 2014/08/06 15:09:05 schwarze Exp $ */
|
||||
/* $Id: mdoc.c,v 1.233 2014/11/28 06:27:05 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -91,11 +89,7 @@ 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 int node_append(struct mdoc *,
|
||||
struct mdoc_node *);
|
||||
#if 0
|
||||
static int mdoc_preptext(struct mdoc *, int, char *, int);
|
||||
#endif
|
||||
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);
|
||||
|
||||
@ -200,37 +194,32 @@ int
|
||||
mdoc_endparse(struct mdoc *mdoc)
|
||||
{
|
||||
|
||||
return(mdoc_macroend(mdoc));
|
||||
mdoc_macroend(mdoc);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
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 ( ! node_append(mdoc, n))
|
||||
return(0);
|
||||
|
||||
if (ep->ln > mdoc->last->line)
|
||||
n->flags |= MDOC_LINE;
|
||||
node_append(mdoc, n);
|
||||
mdoc->next = MDOC_NEXT_SIBLING;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
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;
|
||||
|
||||
if ( ! node_append(mdoc, n))
|
||||
return(0);
|
||||
|
||||
node_append(mdoc, n);
|
||||
mdoc->next = MDOC_NEXT_SIBLING;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -241,7 +230,8 @@ int
|
||||
mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs)
|
||||
{
|
||||
|
||||
mdoc->flags |= MDOC_NEWLINE;
|
||||
if (mdoc->last->type != MDOC_EQN || ln > mdoc->last->line)
|
||||
mdoc->flags |= MDOC_NEWLINE;
|
||||
|
||||
/*
|
||||
* Let the roff nS register switch SYNOPSIS mode early,
|
||||
@ -259,7 +249,7 @@ mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs)
|
||||
mdoc_ptext(mdoc, ln, buf, offs));
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
mdoc_macro(MACRO_PROT_ARGS)
|
||||
{
|
||||
assert(tok < MDOC_MAX);
|
||||
@ -269,7 +259,7 @@ mdoc_macro(MACRO_PROT_ARGS)
|
||||
mandoc_vmsg(MANDOCERR_DT_LATE,
|
||||
mdoc->parse, line, ppos,
|
||||
"Dt %s", buf + *pos);
|
||||
return(1);
|
||||
return;
|
||||
}
|
||||
} else if ( ! (mdoc_macros[tok].flags & MDOC_PROLOGUE)) {
|
||||
if (mdoc->meta.title == NULL) {
|
||||
@ -282,12 +272,11 @@ mdoc_macro(MACRO_PROT_ARGS)
|
||||
mdoc->meta.vol = mandoc_strdup("LOCAL");
|
||||
mdoc->flags |= MDOC_PBODY;
|
||||
}
|
||||
|
||||
return((*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf));
|
||||
(*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
static void
|
||||
node_append(struct mdoc *mdoc, struct mdoc_node *p)
|
||||
{
|
||||
|
||||
@ -331,8 +320,7 @@ node_append(struct mdoc *mdoc, struct mdoc_node *p)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! mdoc_valid_pre(mdoc, p))
|
||||
return(0);
|
||||
mdoc_valid_pre(mdoc, p);
|
||||
|
||||
switch (p->type) {
|
||||
case MDOC_HEAD:
|
||||
@ -359,14 +347,11 @@ node_append(struct mdoc *mdoc, struct mdoc_node *p)
|
||||
case MDOC_TBL:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_TEXT:
|
||||
if ( ! mdoc_valid_post(mdoc))
|
||||
return(0);
|
||||
mdoc_valid_post(mdoc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static struct mdoc_node *
|
||||
@ -396,46 +381,41 @@ node_alloc(struct mdoc *mdoc, int line, int pos,
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
mdoc_tail_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
|
||||
{
|
||||
struct mdoc_node *p;
|
||||
|
||||
p = node_alloc(mdoc, line, pos, tok, MDOC_TAIL);
|
||||
if ( ! node_append(mdoc, p))
|
||||
return(0);
|
||||
node_append(mdoc, p);
|
||||
mdoc->next = MDOC_NEXT_CHILD;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
struct mdoc_node *
|
||||
mdoc_head_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
|
||||
{
|
||||
struct mdoc_node *p;
|
||||
|
||||
assert(mdoc->first);
|
||||
assert(mdoc->last);
|
||||
|
||||
p = node_alloc(mdoc, line, pos, tok, MDOC_HEAD);
|
||||
if ( ! node_append(mdoc, p))
|
||||
return(0);
|
||||
node_append(mdoc, p);
|
||||
mdoc->next = MDOC_NEXT_CHILD;
|
||||
return(1);
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
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);
|
||||
if ( ! node_append(mdoc, p))
|
||||
return(0);
|
||||
node_append(mdoc, p);
|
||||
mdoc->next = MDOC_NEXT_CHILD;
|
||||
return(1);
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok,
|
||||
struct mdoc_node *body, enum mdoc_endbody end)
|
||||
{
|
||||
@ -445,13 +425,11 @@ mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok,
|
||||
p->pending = body;
|
||||
p->norm = body->norm;
|
||||
p->end = end;
|
||||
if ( ! node_append(mdoc, p))
|
||||
return(0);
|
||||
node_append(mdoc, p);
|
||||
mdoc->next = MDOC_NEXT_SIBLING;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
struct mdoc_node *
|
||||
mdoc_block_alloc(struct mdoc *mdoc, int line, int pos,
|
||||
enum mdoct tok, struct mdoc_arg *args)
|
||||
{
|
||||
@ -477,14 +455,12 @@ mdoc_block_alloc(struct mdoc *mdoc, int line, int pos,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! node_append(mdoc, p))
|
||||
return(0);
|
||||
node_append(mdoc, p);
|
||||
mdoc->next = MDOC_NEXT_CHILD;
|
||||
return(1);
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
mdoc_elem_alloc(struct mdoc *mdoc, int line, int pos,
|
||||
enum mdoct tok, struct mdoc_arg *args)
|
||||
{
|
||||
@ -502,26 +478,19 @@ mdoc_elem_alloc(struct mdoc *mdoc, int line, int pos,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! node_append(mdoc, p))
|
||||
return(0);
|
||||
node_append(mdoc, p);
|
||||
mdoc->next = MDOC_NEXT_CHILD;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
mdoc_word_alloc(struct mdoc *mdoc, int line, int pos, const char *p)
|
||||
{
|
||||
struct mdoc_node *n;
|
||||
|
||||
n = node_alloc(mdoc, line, pos, MDOC_MAX, MDOC_TEXT);
|
||||
n->string = roff_strdup(mdoc->roff, p);
|
||||
|
||||
if ( ! node_append(mdoc, n))
|
||||
return(0);
|
||||
|
||||
node_append(mdoc, n);
|
||||
mdoc->next = MDOC_NEXT_SIBLING;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -603,68 +572,14 @@ mdoc_node_delete(struct mdoc *mdoc, struct mdoc_node *p)
|
||||
mdoc_node_free(p);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
mdoc_node_relink(struct mdoc *mdoc, struct mdoc_node *p)
|
||||
{
|
||||
|
||||
mdoc_node_unlink(mdoc, p);
|
||||
return(node_append(mdoc, p));
|
||||
node_append(mdoc, p);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Pre-treat a text line.
|
||||
* Text lines can consist of equations, which must be handled apart from
|
||||
* the regular text.
|
||||
* Thus, use this function to step through a line checking if it has any
|
||||
* equations embedded in it.
|
||||
* This must handle multiple equations AND equations that do not end at
|
||||
* the end-of-line, i.e., will re-enter in the next roff parse.
|
||||
*/
|
||||
static int
|
||||
mdoc_preptext(struct mdoc *mdoc, int line, char *buf, int offs)
|
||||
{
|
||||
char *start, *end;
|
||||
char delim;
|
||||
|
||||
while ('\0' != buf[offs]) {
|
||||
/* Mark starting position if eqn is set. */
|
||||
start = NULL;
|
||||
if ('\0' != (delim = roff_eqndelim(mdoc->roff)))
|
||||
if (NULL != (start = strchr(buf + offs, delim)))
|
||||
*start++ = '\0';
|
||||
|
||||
/* Parse text as normal. */
|
||||
if ( ! mdoc_ptext(mdoc, line, buf, offs))
|
||||
return(0);
|
||||
|
||||
/* Continue only if an equation exists. */
|
||||
if (NULL == start)
|
||||
break;
|
||||
|
||||
/* Read past the end of the equation. */
|
||||
offs += start - (buf + offs);
|
||||
assert(start == &buf[offs]);
|
||||
if (NULL != (end = strchr(buf + offs, delim))) {
|
||||
*end++ = '\0';
|
||||
while (' ' == *end)
|
||||
end++;
|
||||
}
|
||||
|
||||
/* Parse the equation itself. */
|
||||
roff_openeqn(mdoc->roff, NULL, line, offs, buf);
|
||||
|
||||
/* Process a finished equation? */
|
||||
if (roff_closeeqn(mdoc->roff))
|
||||
if ( ! mdoc_addeqn(mdoc, roff_eqn(mdoc->roff)))
|
||||
return(0);
|
||||
offs += (end - (buf + offs));
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Parse free-form text, that is, a line that does not begin with the
|
||||
* control character.
|
||||
@ -689,7 +604,8 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
|
||||
LIST_column == n->norm->Bl.type) {
|
||||
/* `Bl' is open without any children. */
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
return(mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf));
|
||||
mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
|
||||
@ -698,7 +614,8 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
|
||||
LIST_column == n->parent->norm->Bl.type) {
|
||||
/* `Bl' has block-level `It' children. */
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
return(mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf));
|
||||
mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -746,7 +663,7 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
|
||||
mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse,
|
||||
line, (int)(ws-buf), NULL);
|
||||
|
||||
if ('\0' == buf[offs] && ! (MDOC_LITERAL & mdoc->flags)) {
|
||||
if (buf[offs] == '\0' && ! (mdoc->flags & MDOC_LITERAL)) {
|
||||
mandoc_msg(MANDOCERR_FI_BLANK, mdoc->parse,
|
||||
line, (int)(c - buf), NULL);
|
||||
|
||||
@ -755,18 +672,15 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
|
||||
* blank lines aren't allowed, but enough manuals assume this
|
||||
* behaviour that we want to work around it.
|
||||
*/
|
||||
if ( ! mdoc_elem_alloc(mdoc, line, offs, MDOC_sp, NULL))
|
||||
return(0);
|
||||
|
||||
mdoc_elem_alloc(mdoc, line, offs, MDOC_sp, NULL);
|
||||
mdoc->next = MDOC_NEXT_SIBLING;
|
||||
|
||||
return(mdoc_valid_post(mdoc));
|
||||
mdoc_valid_post(mdoc);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if ( ! mdoc_word_alloc(mdoc, line, offs, buf+offs))
|
||||
return(0);
|
||||
mdoc_word_alloc(mdoc, line, offs, buf+offs);
|
||||
|
||||
if (MDOC_LITERAL & mdoc->flags)
|
||||
if (mdoc->flags & MDOC_LITERAL)
|
||||
return(1);
|
||||
|
||||
/*
|
||||
@ -779,7 +693,6 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
|
||||
|
||||
if (mandoc_eos(buf+offs, (size_t)(end-buf-offs)))
|
||||
mdoc->last->flags |= MDOC_EOS;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -790,46 +703,47 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
|
||||
static int
|
||||
mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
|
||||
{
|
||||
struct mdoc_node *n;
|
||||
const char *cp;
|
||||
enum mdoct tok;
|
||||
int i, sv;
|
||||
char mac[5];
|
||||
struct mdoc_node *n;
|
||||
|
||||
/* Empty post-control lines are ignored. */
|
||||
|
||||
if ('"' == buf[offs]) {
|
||||
mandoc_msg(MANDOCERR_COMMENT_BAD, mdoc->parse,
|
||||
ln, offs, NULL);
|
||||
return(1);
|
||||
} else if ('\0' == buf[offs])
|
||||
return(1);
|
||||
|
||||
sv = offs;
|
||||
|
||||
/*
|
||||
* Copy the first word into a nil-terminated buffer.
|
||||
* Stop copying when a tab, space, or eoln is encountered.
|
||||
* Stop when a space, tab, escape, or eoln is encountered.
|
||||
*/
|
||||
|
||||
i = 0;
|
||||
while (i < 4 && '\0' != buf[offs] && ' ' != buf[offs] &&
|
||||
'\t' != buf[offs])
|
||||
while (i < 4 && strchr(" \t\\", buf[offs]) == NULL)
|
||||
mac[i++] = buf[offs++];
|
||||
|
||||
mac[i] = '\0';
|
||||
|
||||
tok = (i > 1 && i < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
|
||||
|
||||
if (MDOC_MAX == tok) {
|
||||
if (tok == MDOC_MAX) {
|
||||
mandoc_msg(MANDOCERR_MACRO, mdoc->parse,
|
||||
ln, sv, buf + sv - 1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Disregard the first trailing tab, if applicable. */
|
||||
/* Skip a leading escape sequence or tab. */
|
||||
|
||||
if ('\t' == buf[offs])
|
||||
switch (buf[offs]) {
|
||||
case '\\':
|
||||
cp = buf + offs + 1;
|
||||
mandoc_escape(&cp, NULL, NULL);
|
||||
offs = cp - buf;
|
||||
break;
|
||||
case '\t':
|
||||
offs++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Jump to the next non-whitespace word. */
|
||||
|
||||
@ -850,8 +764,10 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
|
||||
* into macro processing.
|
||||
*/
|
||||
|
||||
if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok)
|
||||
return(mdoc_macro(mdoc, tok, ln, sv, &offs, buf));
|
||||
if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) {
|
||||
mdoc_macro(mdoc, tok, ln, sv, &offs, buf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
n = mdoc->last;
|
||||
assert(mdoc->last);
|
||||
@ -864,7 +780,8 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
|
||||
if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
|
||||
LIST_column == n->norm->Bl.type) {
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
return(mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf));
|
||||
mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -878,13 +795,13 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
|
||||
MDOC_Bl == n->parent->tok &&
|
||||
LIST_column == n->parent->norm->Bl.type) {
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
return(mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf));
|
||||
mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Normal processing of a macro. */
|
||||
|
||||
if ( ! mdoc_macro(mdoc, tok, ln, sv, &offs, buf))
|
||||
return(0);
|
||||
mdoc_macro(mdoc, tok, ln, sv, &offs, buf);
|
||||
|
||||
/* In quick mode (for mandocdb), abort after the NAME section. */
|
||||
|
||||
|
214
mdoc_argv.c
214
mdoc_argv.c
@ -1,7 +1,7 @@
|
||||
/* $Id: mdoc_argv.c,v 1.95 2014/07/06 19:09:00 schwarze Exp $ */
|
||||
/* $OpenBSD$ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2012, 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
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -56,9 +54,9 @@ static void argn_free(struct mdoc_arg *, int);
|
||||
static enum margserr args(struct mdoc *, int, int *,
|
||||
char *, enum argsflag, char **);
|
||||
static int args_checkpunct(const char *, int);
|
||||
static int argv_multi(struct mdoc *, int,
|
||||
static void argv_multi(struct mdoc *, int,
|
||||
struct mdoc_argv *, int *, char *);
|
||||
static int argv_single(struct mdoc *, int,
|
||||
static void argv_single(struct mdoc *, int,
|
||||
struct mdoc_argv *, int *, char *);
|
||||
|
||||
static const enum argvflag argvflags[MDOC_ARG_MAX] = {
|
||||
@ -272,100 +270,105 @@ static const struct mdocarg mdocargs[MDOC_MAX] = {
|
||||
|
||||
|
||||
/*
|
||||
* Parse an argument from line text. This comes in the form of -key
|
||||
* [value0...], which may either have a single mandatory value, at least
|
||||
* one mandatory value, an optional single value, or no value.
|
||||
* Parse flags and their arguments from the input line.
|
||||
* These come in the form -flag [argument ...].
|
||||
* Some flags take no argument, some one, some multiple.
|
||||
*/
|
||||
enum margverr
|
||||
void
|
||||
mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok,
|
||||
struct mdoc_arg **v, int *pos, char *buf)
|
||||
struct mdoc_arg **reta, int *pos, char *buf)
|
||||
{
|
||||
char *p, sv;
|
||||
struct mdoc_argv tmp;
|
||||
struct mdoc_arg *arg;
|
||||
const enum mdocargt *ap;
|
||||
struct mdoc_argv tmpv;
|
||||
struct mdoc_argv **retv;
|
||||
const enum mdocargt *argtable;
|
||||
char *argname;
|
||||
int ipos, retc;
|
||||
char savechar;
|
||||
|
||||
if ('\0' == buf[*pos])
|
||||
return(ARGV_EOLN);
|
||||
else if (NULL == (ap = mdocargs[tok].argvs))
|
||||
return(ARGV_WORD);
|
||||
else if ('-' != buf[*pos])
|
||||
return(ARGV_WORD);
|
||||
*reta = NULL;
|
||||
|
||||
/* Seek to the first unescaped space. */
|
||||
/* Which flags does this macro support? */
|
||||
|
||||
p = &buf[++(*pos)];
|
||||
argtable = mdocargs[tok].argvs;
|
||||
if (argtable == NULL)
|
||||
return;
|
||||
|
||||
assert(*pos > 0);
|
||||
/* Loop over the flags on the input line. */
|
||||
|
||||
for ( ; buf[*pos] ; (*pos)++)
|
||||
if (' ' == buf[*pos] && '\\' != buf[*pos - 1])
|
||||
break;
|
||||
ipos = *pos;
|
||||
while (buf[ipos] == '-') {
|
||||
|
||||
/*
|
||||
* We want to nil-terminate the word to look it up (it's easier
|
||||
* that way). But we may not have a flag, in which case we need
|
||||
* to restore the line as-is. So keep around the stray byte,
|
||||
* which we'll reset upon exiting (if necessary).
|
||||
*/
|
||||
/* Seek to the first unescaped space. */
|
||||
|
||||
if ('\0' != (sv = buf[*pos]))
|
||||
buf[(*pos)++] = '\0';
|
||||
for (argname = buf + ++ipos; buf[ipos] != '\0'; ipos++)
|
||||
if (buf[ipos] == ' ' && buf[ipos - 1] != '\\')
|
||||
break;
|
||||
|
||||
/*
|
||||
* Now look up the word as a flag. Use temporary storage that
|
||||
* we'll copy into the node's flags, if necessary.
|
||||
*/
|
||||
|
||||
memset(&tmp, 0, sizeof(struct mdoc_argv));
|
||||
|
||||
tmp.line = line;
|
||||
tmp.pos = *pos;
|
||||
tmp.arg = MDOC_ARG_MAX;
|
||||
|
||||
while (MDOC_ARG_MAX != (tmp.arg = *ap++))
|
||||
if (0 == strcmp(p, mdoc_argnames[tmp.arg]))
|
||||
break;
|
||||
|
||||
if (MDOC_ARG_MAX == tmp.arg) {
|
||||
/*
|
||||
* The flag was not found.
|
||||
* Restore saved zeroed byte and return as a word.
|
||||
* We want to nil-terminate the word to look it up.
|
||||
* But we may not have a flag, in which case we need
|
||||
* to restore the line as-is. So keep around the
|
||||
* stray byte, which we'll reset upon exiting.
|
||||
*/
|
||||
if (sv)
|
||||
buf[*pos - 1] = sv;
|
||||
return(ARGV_WORD);
|
||||
|
||||
if ((savechar = buf[ipos]) != '\0')
|
||||
buf[ipos++] = '\0';
|
||||
|
||||
/*
|
||||
* Now look up the word as a flag. Use temporary
|
||||
* storage that we'll copy into the node's flags.
|
||||
*/
|
||||
|
||||
while ((tmpv.arg = *argtable++) != MDOC_ARG_MAX)
|
||||
if ( ! strcmp(argname, mdoc_argnames[tmpv.arg]))
|
||||
break;
|
||||
|
||||
/* If it isn't a flag, restore the saved byte. */
|
||||
|
||||
if (tmpv.arg == MDOC_ARG_MAX) {
|
||||
if (savechar != '\0')
|
||||
buf[ipos - 1] = savechar;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read to the next word (the first argument). */
|
||||
|
||||
while (buf[ipos] == ' ')
|
||||
ipos++;
|
||||
|
||||
/* Parse the arguments of the flag. */
|
||||
|
||||
tmpv.line = line;
|
||||
tmpv.pos = ipos;
|
||||
tmpv.sz = 0;
|
||||
tmpv.value = NULL;
|
||||
|
||||
switch (argvflags[tmpv.arg]) {
|
||||
case ARGV_SINGLE:
|
||||
argv_single(mdoc, line, &tmpv, &ipos, buf);
|
||||
break;
|
||||
case ARGV_MULTI:
|
||||
argv_multi(mdoc, line, &tmpv, &ipos, buf);
|
||||
break;
|
||||
case ARGV_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Append to the return values. */
|
||||
|
||||
if (*reta == NULL)
|
||||
*reta = mandoc_calloc(1, sizeof(**reta));
|
||||
|
||||
retc = ++(*reta)->argc;
|
||||
retv = &(*reta)->argv;
|
||||
*retv = mandoc_reallocarray(*retv, retc, sizeof(**retv));
|
||||
memcpy(*retv + retc - 1, &tmpv, sizeof(**retv));
|
||||
|
||||
/* Prepare for parsing the next flag. */
|
||||
|
||||
*pos = ipos;
|
||||
argtable = mdocargs[tok].argvs;
|
||||
}
|
||||
|
||||
/* Read to the next word (the argument). */
|
||||
|
||||
while (buf[*pos] && ' ' == buf[*pos])
|
||||
(*pos)++;
|
||||
|
||||
switch (argvflags[tmp.arg]) {
|
||||
case ARGV_SINGLE:
|
||||
if ( ! argv_single(mdoc, line, &tmp, pos, buf))
|
||||
return(ARGV_ERROR);
|
||||
break;
|
||||
case ARGV_MULTI:
|
||||
if ( ! argv_multi(mdoc, line, &tmp, pos, buf))
|
||||
return(ARGV_ERROR);
|
||||
break;
|
||||
case ARGV_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL == (arg = *v))
|
||||
arg = *v = mandoc_calloc(1, sizeof(struct mdoc_arg));
|
||||
|
||||
arg->argc++;
|
||||
arg->argv = mandoc_reallocarray(arg->argv,
|
||||
arg->argc, sizeof(struct mdoc_argv));
|
||||
|
||||
memcpy(&arg->argv[(int)arg->argc - 1], &tmp,
|
||||
sizeof(struct mdoc_argv));
|
||||
|
||||
return(ARGV_ARG);
|
||||
}
|
||||
|
||||
void
|
||||
@ -408,23 +411,18 @@ argn_free(struct mdoc_arg *p, int iarg)
|
||||
p->argv[iarg] = p->argv[iarg+1];
|
||||
}
|
||||
|
||||
enum margserr
|
||||
mdoc_zargs(struct mdoc *mdoc, int line, int *pos, char *buf, char **v)
|
||||
{
|
||||
|
||||
return(args(mdoc, line, pos, buf, ARGSFL_NONE, v));
|
||||
}
|
||||
|
||||
enum margserr
|
||||
mdoc_args(struct mdoc *mdoc, int line, int *pos,
|
||||
char *buf, enum mdoct tok, char **v)
|
||||
{
|
||||
enum argsflag fl;
|
||||
struct mdoc_node *n;
|
||||
char *v_local;
|
||||
enum argsflag fl;
|
||||
|
||||
fl = mdocargs[tok].flags;
|
||||
|
||||
if (MDOC_It != tok)
|
||||
if (v == NULL)
|
||||
v = &v_local;
|
||||
fl = tok == MDOC_MAX ? ARGSFL_NONE : mdocargs[tok].flags;
|
||||
if (tok != MDOC_It)
|
||||
return(args(mdoc, line, pos, buf, fl, v));
|
||||
|
||||
/*
|
||||
@ -654,7 +652,7 @@ args_checkpunct(const char *buf, int i)
|
||||
return('\0' == buf[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
argv_multi(struct mdoc *mdoc, int line,
|
||||
struct mdoc_argv *v, int *pos, char *buf)
|
||||
{
|
||||
@ -662,25 +660,21 @@ argv_multi(struct mdoc *mdoc, int line,
|
||||
char *p;
|
||||
|
||||
for (v->sz = 0; ; v->sz++) {
|
||||
if ('-' == buf[*pos])
|
||||
if (buf[*pos] == '-')
|
||||
break;
|
||||
ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p);
|
||||
if (ARGS_ERROR == ac)
|
||||
return(0);
|
||||
else if (ARGS_EOLN == ac)
|
||||
if (ac == ARGS_EOLN)
|
||||
break;
|
||||
|
||||
if (0 == v->sz % MULTI_STEP)
|
||||
if (v->sz % MULTI_STEP == 0)
|
||||
v->value = mandoc_reallocarray(v->value,
|
||||
v->sz + MULTI_STEP, sizeof(char *));
|
||||
|
||||
v->value[(int)v->sz] = mandoc_strdup(p);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
argv_single(struct mdoc *mdoc, int line,
|
||||
struct mdoc_argv *v, int *pos, char *buf)
|
||||
{
|
||||
@ -688,14 +682,10 @@ argv_single(struct mdoc *mdoc, int line,
|
||||
char *p;
|
||||
|
||||
ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p);
|
||||
if (ARGS_ERROR == ac)
|
||||
return(0);
|
||||
if (ARGS_EOLN == ac)
|
||||
return(1);
|
||||
if (ac == ARGS_EOLN)
|
||||
return;
|
||||
|
||||
v->sz = 1;
|
||||
v->value = mandoc_malloc(sizeof(char *));
|
||||
v->value[0] = mandoc_strdup(p);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: mdoc_hash.c,v 1.20 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: mdoc_hash.c,v 1.21 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,9 +14,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
181
mdoc_html.c
181
mdoc_html.c
@ -1,6 +1,6 @@
|
||||
/* $Id: mdoc_html.c,v 1.195 2014/08/06 15:09:05 schwarze Exp $ */
|
||||
/* $Id: mdoc_html.c,v 1.213 2014/11/27 22:27:56 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -58,7 +56,6 @@ static void synopsis_pre(struct html *,
|
||||
const struct mdoc_node *);
|
||||
|
||||
static void a2width(const char *, struct roffsu *);
|
||||
static void a2offs(const char *, struct roffsu *);
|
||||
|
||||
static void mdoc_root_post(MDOC_ARGS);
|
||||
static int mdoc_root_pre(MDOC_ARGS);
|
||||
@ -101,6 +98,7 @@ static int mdoc_mt_pre(MDOC_ARGS);
|
||||
static int mdoc_ms_pre(MDOC_ARGS);
|
||||
static int mdoc_nd_pre(MDOC_ARGS);
|
||||
static int mdoc_nm_pre(MDOC_ARGS);
|
||||
static int mdoc_no_pre(MDOC_ARGS);
|
||||
static int mdoc_ns_pre(MDOC_ARGS);
|
||||
static int mdoc_pa_pre(MDOC_ARGS);
|
||||
static void mdoc_pf_post(MDOC_ARGS);
|
||||
@ -185,7 +183,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
|
||||
{mdoc_quote_pre, mdoc_quote_post}, /* Bq */
|
||||
{mdoc_xx_pre, NULL}, /* Bsx */
|
||||
{mdoc_bx_pre, NULL}, /* Bx */
|
||||
{NULL, NULL}, /* Db */
|
||||
{mdoc_skip_pre, NULL}, /* Db */
|
||||
{NULL, NULL}, /* Dc */
|
||||
{mdoc_quote_pre, mdoc_quote_post}, /* Do */
|
||||
{mdoc_quote_pre, mdoc_quote_post}, /* Dq */
|
||||
@ -195,7 +193,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
|
||||
{mdoc_quote_pre, mdoc_quote_post}, /* Eo */
|
||||
{mdoc_xx_pre, NULL}, /* Fx */
|
||||
{mdoc_ms_pre, NULL}, /* Ms */
|
||||
{mdoc_igndelim_pre, NULL}, /* No */
|
||||
{mdoc_no_pre, NULL}, /* No */
|
||||
{mdoc_ns_pre, NULL}, /* Ns */
|
||||
{mdoc_xx_pre, NULL}, /* Nx */
|
||||
{mdoc_xx_pre, NULL}, /* Ox */
|
||||
@ -283,7 +281,7 @@ a2width(const char *p, struct roffsu *su)
|
||||
{
|
||||
|
||||
if ( ! a2roffsu(p, su, SCALE_MAX)) {
|
||||
su->unit = SCALE_BU;
|
||||
su->unit = SCALE_EN;
|
||||
su->scale = html_strlen(p);
|
||||
}
|
||||
}
|
||||
@ -316,11 +314,11 @@ synopsis_pre(struct html *h, const struct mdoc_node *n)
|
||||
case MDOC_In:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Vt:
|
||||
print_otag(h, TAG_P, 0, NULL);
|
||||
print_paragraph(h);
|
||||
break;
|
||||
case MDOC_Ft:
|
||||
if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
|
||||
print_otag(h, TAG_P, 0, NULL);
|
||||
print_paragraph(h);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
@ -330,27 +328,6 @@ synopsis_pre(struct html *h, const struct mdoc_node *n)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the scaling unit passed in an `-offset' argument. This
|
||||
* uses either a native scaling unit (e.g., 1i, 2m), one of a set of
|
||||
* predefined strings (indent, etc.), or the string length of the value.
|
||||
*/
|
||||
static void
|
||||
a2offs(const char *p, struct roffsu *su)
|
||||
{
|
||||
|
||||
/* FIXME: "right"? */
|
||||
|
||||
if (0 == strcmp(p, "left"))
|
||||
SCALE_HS_INIT(su, 0);
|
||||
else if (0 == strcmp(p, "indent"))
|
||||
SCALE_HS_INIT(su, INDENT);
|
||||
else if (0 == strcmp(p, "indent-two"))
|
||||
SCALE_HS_INIT(su, INDENT * 2);
|
||||
else if ( ! a2roffsu(p, su, SCALE_MAX))
|
||||
SCALE_HS_INIT(su, html_strlen(p));
|
||||
}
|
||||
|
||||
static void
|
||||
print_mdoc(MDOC_ARGS)
|
||||
{
|
||||
@ -446,13 +423,12 @@ print_mdoc_node(MDOC_ARGS)
|
||||
* the "meta" table state. This will be reopened on the
|
||||
* next table element.
|
||||
*/
|
||||
if (h->tblt) {
|
||||
if (h->tblt != NULL) {
|
||||
print_tblclose(h);
|
||||
t = h->tags.head;
|
||||
}
|
||||
|
||||
assert(NULL == h->tblt);
|
||||
if (mdocs[n->tok].pre && ENDBODY_NOT == n->end)
|
||||
assert(h->tblt == NULL);
|
||||
if (mdocs[n->tok].pre && (n->end == ENDBODY_NOT || n->child))
|
||||
child = (*mdocs[n->tok].pre)(meta, n, h);
|
||||
break;
|
||||
}
|
||||
@ -477,8 +453,13 @@ print_mdoc_node(MDOC_ARGS)
|
||||
case MDOC_EQN:
|
||||
break;
|
||||
default:
|
||||
if (mdocs[n->tok].post && ENDBODY_NOT == n->end)
|
||||
(*mdocs[n->tok].post)(meta, n, h);
|
||||
if ( ! mdocs[n->tok].post || n->flags & MDOC_ENDED)
|
||||
break;
|
||||
(*mdocs[n->tok].post)(meta, n, h);
|
||||
if (n->end != ENDBODY_NOT)
|
||||
n->pending->flags |= MDOC_ENDED;
|
||||
if (n->end == ENDBODY_NOSPACE)
|
||||
h->flags |= HTML_NOSPACE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -486,29 +467,23 @@ print_mdoc_node(MDOC_ARGS)
|
||||
static void
|
||||
mdoc_root_post(MDOC_ARGS)
|
||||
{
|
||||
struct htmlpair tag[3];
|
||||
struct htmlpair tag;
|
||||
struct tag *t, *tt;
|
||||
|
||||
PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
|
||||
PAIR_CLASS_INIT(&tag[1], "foot");
|
||||
PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
|
||||
t = print_otag(h, TAG_TABLE, 3, tag);
|
||||
PAIR_INIT(&tag[0], ATTR_WIDTH, "50%");
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
PAIR_CLASS_INIT(&tag, "foot");
|
||||
t = print_otag(h, TAG_TABLE, 1, &tag);
|
||||
|
||||
print_otag(h, TAG_TBODY, 0, NULL);
|
||||
|
||||
tt = print_otag(h, TAG_TR, 0, NULL);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "foot-date");
|
||||
print_otag(h, TAG_TD, 1, tag);
|
||||
PAIR_CLASS_INIT(&tag, "foot-date");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_text(h, meta->date);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "foot-os");
|
||||
PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
|
||||
print_otag(h, TAG_TD, 2, tag);
|
||||
PAIR_CLASS_INIT(&tag, "foot-os");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_text(h, meta->os);
|
||||
print_tagq(h, t);
|
||||
}
|
||||
@ -516,7 +491,7 @@ mdoc_root_post(MDOC_ARGS)
|
||||
static int
|
||||
mdoc_root_pre(MDOC_ARGS)
|
||||
{
|
||||
struct htmlpair tag[3];
|
||||
struct htmlpair tag;
|
||||
struct tag *t, *tt;
|
||||
char *volume, *title;
|
||||
|
||||
@ -532,33 +507,25 @@ mdoc_root_pre(MDOC_ARGS)
|
||||
mandoc_asprintf(&title, "%s(%s)",
|
||||
meta->title, meta->msec);
|
||||
|
||||
PAIR_SUMMARY_INIT(&tag[0], "Document Header");
|
||||
PAIR_CLASS_INIT(&tag[1], "head");
|
||||
PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
|
||||
t = print_otag(h, TAG_TABLE, 3, tag);
|
||||
PAIR_INIT(&tag[0], ATTR_WIDTH, "30%");
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
print_otag(h, TAG_COL, 1, tag);
|
||||
PAIR_CLASS_INIT(&tag, "head");
|
||||
t = print_otag(h, TAG_TABLE, 1, &tag);
|
||||
|
||||
print_otag(h, TAG_TBODY, 0, NULL);
|
||||
|
||||
tt = print_otag(h, TAG_TR, 0, NULL);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "head-ltitle");
|
||||
print_otag(h, TAG_TD, 1, tag);
|
||||
PAIR_CLASS_INIT(&tag, "head-ltitle");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_text(h, title);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "head-vol");
|
||||
PAIR_INIT(&tag[1], ATTR_ALIGN, "center");
|
||||
print_otag(h, TAG_TD, 2, tag);
|
||||
PAIR_CLASS_INIT(&tag, "head-vol");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_text(h, volume);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag[0], "head-rtitle");
|
||||
PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
|
||||
print_otag(h, TAG_TD, 2, tag);
|
||||
PAIR_CLASS_INIT(&tag, "head-rtitle");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_text(h, title);
|
||||
print_tagq(h, t);
|
||||
|
||||
@ -572,12 +539,18 @@ mdoc_sh_pre(MDOC_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
switch (n->type) {
|
||||
case MDOC_BLOCK:
|
||||
PAIR_CLASS_INIT(&tag, "section");
|
||||
print_otag(h, TAG_DIV, 1, &tag);
|
||||
return(1);
|
||||
} else if (MDOC_BODY == n->type)
|
||||
case MDOC_BODY:
|
||||
if (n->sec == SEC_AUTHORS)
|
||||
h->flags &= ~(HTML_SPLIT|HTML_NOSPLIT);
|
||||
return(1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bufinit(h);
|
||||
bufcat(h, "x");
|
||||
@ -642,9 +615,10 @@ mdoc_fl_pre(MDOC_ARGS)
|
||||
|
||||
print_text(h, "\\-");
|
||||
|
||||
if (n->child)
|
||||
h->flags |= HTML_NOSPACE;
|
||||
else if (n->next && n->next->line == n->line)
|
||||
if ( ! (n->nchild == 0 &&
|
||||
(n->next == NULL ||
|
||||
n->next->type == MDOC_TEXT ||
|
||||
n->next->flags & MDOC_LINE)))
|
||||
h->flags |= HTML_NOSPACE;
|
||||
|
||||
return(1);
|
||||
@ -1003,7 +977,7 @@ mdoc_bl_pre(MDOC_ARGS)
|
||||
/* Set the block's left-hand margin. */
|
||||
|
||||
if (n->norm->Bl.offs) {
|
||||
a2offs(n->norm->Bl.offs, &su);
|
||||
a2width(n->norm->Bl.offs, &su);
|
||||
bufcat_su(h, "margin-left", &su);
|
||||
}
|
||||
|
||||
@ -1165,13 +1139,21 @@ mdoc_bd_pre(MDOC_ARGS)
|
||||
break;
|
||||
}
|
||||
if ( ! comp)
|
||||
print_otag(h, TAG_P, 0, NULL);
|
||||
print_paragraph(h);
|
||||
return(1);
|
||||
}
|
||||
|
||||
SCALE_HS_INIT(&su, 0);
|
||||
if (n->norm->Bd.offs)
|
||||
a2offs(n->norm->Bd.offs, &su);
|
||||
/* Handle the -offset argument. */
|
||||
|
||||
if (n->norm->Bd.offs == NULL ||
|
||||
! strcmp(n->norm->Bd.offs, "left"))
|
||||
SCALE_HS_INIT(&su, 0);
|
||||
else if ( ! strcmp(n->norm->Bd.offs, "indent"))
|
||||
SCALE_HS_INIT(&su, INDENT);
|
||||
else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
|
||||
SCALE_HS_INIT(&su, INDENT * 2);
|
||||
else
|
||||
a2width(n->norm->Bd.offs, &su);
|
||||
|
||||
bufinit(h);
|
||||
bufcat_su(h, "margin-left", &su);
|
||||
@ -1259,7 +1241,25 @@ mdoc_an_pre(MDOC_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
|
||||
/* TODO: -split and -nosplit (see termp_an_pre()). */
|
||||
if (n->norm->An.auth == AUTH_split) {
|
||||
h->flags &= ~HTML_NOSPLIT;
|
||||
h->flags |= HTML_SPLIT;
|
||||
return(0);
|
||||
}
|
||||
if (n->norm->An.auth == AUTH_nosplit) {
|
||||
h->flags &= ~HTML_SPLIT;
|
||||
h->flags |= HTML_NOSPLIT;
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (n->child == NULL)
|
||||
return(0);
|
||||
|
||||
if (h->flags & HTML_SPLIT)
|
||||
print_otag(h, TAG_BR, 0, NULL);
|
||||
|
||||
if (n->sec == SEC_AUTHORS && ! (h->flags & HTML_NOSPLIT))
|
||||
h->flags |= HTML_SPLIT;
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "author");
|
||||
print_otag(h, TAG_SPAN, 1, &tag);
|
||||
@ -1553,7 +1553,7 @@ static int
|
||||
mdoc_pp_pre(MDOC_ARGS)
|
||||
{
|
||||
|
||||
print_otag(h, TAG_P, 0, NULL);
|
||||
print_paragraph(h);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -1881,13 +1881,23 @@ mdoc_rs_pre(MDOC_ARGS)
|
||||
return(1);
|
||||
|
||||
if (n->prev && SEC_SEE_ALSO == n->sec)
|
||||
print_otag(h, TAG_P, 0, NULL);
|
||||
print_paragraph(h);
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "ref");
|
||||
print_otag(h, TAG_SPAN, 1, &tag);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
mdoc_no_pre(MDOC_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "none");
|
||||
print_otag(h, TAG_CODE, 1, &tag);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
mdoc_li_pre(MDOC_ARGS)
|
||||
{
|
||||
@ -2069,7 +2079,8 @@ mdoc_quote_pre(MDOC_ARGS)
|
||||
case MDOC_Ao:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Aq:
|
||||
print_text(h, "\\(la");
|
||||
print_text(h, n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? "<" : "\\(la");
|
||||
break;
|
||||
case MDOC_Bro:
|
||||
/* FALLTHROUGH */
|
||||
@ -2135,17 +2146,19 @@ static void
|
||||
mdoc_quote_post(MDOC_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_BODY != n->type)
|
||||
if (n->type != MDOC_BODY && n->type != MDOC_ELEM)
|
||||
return;
|
||||
|
||||
if (MDOC_En != n->tok)
|
||||
if ( ! (n->tok == MDOC_En ||
|
||||
(n->tok == MDOC_Eo && n->end == ENDBODY_SPACE)))
|
||||
h->flags |= HTML_NOSPACE;
|
||||
|
||||
switch (n->tok) {
|
||||
case MDOC_Ao:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Aq:
|
||||
print_text(h, "\\(ra");
|
||||
print_text(h, n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? ">" : "\\(ra");
|
||||
break;
|
||||
case MDOC_Bro:
|
||||
/* FALLTHROUGH */
|
||||
|
1170
mdoc_macro.c
1170
mdoc_macro.c
File diff suppressed because it is too large
Load Diff
99
mdoc_man.c
99
mdoc_man.c
@ -1,4 +1,4 @@
|
||||
/* $Id: mdoc_man.c,v 1.68 2014/08/06 15:09:05 schwarze Exp $ */
|
||||
/* $Id: mdoc_man.c,v 1.76 2014/11/27 22:27:56 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
@ -14,9 +14,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -46,6 +46,7 @@ static void font_push(char);
|
||||
static void font_pop(void);
|
||||
static void mid_it(void);
|
||||
static void post__t(DECL_ARGS);
|
||||
static void post_aq(DECL_ARGS);
|
||||
static void post_bd(DECL_ARGS);
|
||||
static void post_bf(DECL_ARGS);
|
||||
static void post_bk(DECL_ARGS);
|
||||
@ -72,6 +73,7 @@ static void post_vt(DECL_ARGS);
|
||||
static int pre__t(DECL_ARGS);
|
||||
static int pre_an(DECL_ARGS);
|
||||
static int pre_ap(DECL_ARGS);
|
||||
static int pre_aq(DECL_ARGS);
|
||||
static int pre_bd(DECL_ARGS);
|
||||
static int pre_bf(DECL_ARGS);
|
||||
static int pre_bk(DECL_ARGS);
|
||||
@ -82,7 +84,8 @@ static int pre_dl(DECL_ARGS);
|
||||
static int pre_en(DECL_ARGS);
|
||||
static int pre_enc(DECL_ARGS);
|
||||
static int pre_em(DECL_ARGS);
|
||||
static int pre_es(DECL_ARGS);
|
||||
static int pre_skip(DECL_ARGS);
|
||||
static int pre_eo(DECL_ARGS);
|
||||
static int pre_ex(DECL_ARGS);
|
||||
static int pre_fa(DECL_ARGS);
|
||||
static int pre_fd(DECL_ARGS);
|
||||
@ -112,7 +115,7 @@ static int pre_xr(DECL_ARGS);
|
||||
static void print_word(const char *);
|
||||
static void print_line(const char *, int);
|
||||
static void print_block(const char *, int);
|
||||
static void print_offs(const char *);
|
||||
static void print_offs(const char *, int);
|
||||
static void print_width(const char *,
|
||||
const struct mdoc_node *, size_t);
|
||||
static void print_count(int *);
|
||||
@ -172,8 +175,8 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
||||
{ NULL, pre__t, post__t, NULL, NULL }, /* %T */
|
||||
{ NULL, NULL, post_percent, NULL, NULL }, /* %V */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ac */
|
||||
{ cond_body, pre_enc, post_enc, "<", ">" }, /* Ao */
|
||||
{ cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
|
||||
{ cond_body, pre_aq, post_aq, NULL, NULL }, /* Ao */
|
||||
{ cond_body, pre_aq, post_aq, NULL, NULL }, /* Aq */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* At */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Bc */
|
||||
{ NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
|
||||
@ -181,14 +184,14 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
||||
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
|
||||
{ NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */
|
||||
{ NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Db */
|
||||
{ NULL, pre_skip, NULL, NULL, NULL }, /* Db */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Dc */
|
||||
{ cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
|
||||
{ cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ec */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ef */
|
||||
{ NULL, pre_em, post_font, NULL, NULL }, /* Em */
|
||||
{ NULL, NULL, post_eo, NULL, NULL }, /* Eo */
|
||||
{ cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */
|
||||
{ NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */
|
||||
{ NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
|
||||
{ NULL, pre_no, NULL, NULL, NULL }, /* No */
|
||||
@ -233,7 +236,7 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
||||
{ cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Brc */
|
||||
{ NULL, NULL, post_percent, NULL, NULL }, /* %C */
|
||||
{ NULL, pre_es, NULL, NULL, NULL }, /* Es */
|
||||
{ NULL, pre_skip, NULL, NULL, NULL }, /* Es */
|
||||
{ cond_body, pre_en, post_en, NULL, NULL }, /* En */
|
||||
{ NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */
|
||||
{ NULL, NULL, post_percent, NULL, NULL }, /* %Q */
|
||||
@ -416,7 +419,7 @@ print_block(const char *s, int newflags)
|
||||
}
|
||||
|
||||
static void
|
||||
print_offs(const char *v)
|
||||
print_offs(const char *v, int keywords)
|
||||
{
|
||||
char buf[24];
|
||||
struct roffsu su;
|
||||
@ -425,11 +428,11 @@ print_offs(const char *v)
|
||||
print_line(".RS", MMAN_Bk_susp);
|
||||
|
||||
/* Convert v into a number (of characters). */
|
||||
if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
|
||||
if (NULL == v || '\0' == *v || (keywords && !strcmp(v, "left")))
|
||||
sz = 0;
|
||||
else if (0 == strcmp(v, "indent"))
|
||||
else if (keywords && !strcmp(v, "indent"))
|
||||
sz = 6;
|
||||
else if (0 == strcmp(v, "indent-two"))
|
||||
else if (keywords && !strcmp(v, "indent-two"))
|
||||
sz = 12;
|
||||
else if (a2roffsu(v, &su, SCALE_MAX)) {
|
||||
if (SCALE_EN == su.unit)
|
||||
@ -594,15 +597,19 @@ print_node(DECL_ARGS)
|
||||
printf("\\&");
|
||||
outflags &= ~MMAN_spc;
|
||||
}
|
||||
if (outflags & MMAN_Sm && ! (n->flags & MDOC_DELIMC))
|
||||
outflags |= MMAN_spc_force;
|
||||
print_word(n->string);
|
||||
if (outflags & MMAN_Sm && ! (n->flags & MDOC_DELIMO))
|
||||
outflags |= MMAN_spc;
|
||||
} else {
|
||||
/*
|
||||
* Conditionally run the pre-node action handler for a
|
||||
* node.
|
||||
*/
|
||||
act = manacts + n->tok;
|
||||
cond = NULL == act->cond || (*act->cond)(meta, n);
|
||||
if (cond && act->pre && ENDBODY_NOT == n->end)
|
||||
cond = act->cond == NULL || (*act->cond)(meta, n);
|
||||
if (cond && act->pre && (n->end == ENDBODY_NOT || n->nchild))
|
||||
do_sub = (*act->pre)(meta, n);
|
||||
}
|
||||
|
||||
@ -865,6 +872,25 @@ pre_ap(DECL_ARGS)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
pre_aq(DECL_ARGS)
|
||||
{
|
||||
|
||||
print_word(n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? "<" : "\\(la");
|
||||
outflags &= ~MMAN_spc;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
post_aq(DECL_ARGS)
|
||||
{
|
||||
|
||||
outflags &= ~(MMAN_spc | MMAN_nl);
|
||||
print_word(n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? ">" : "\\(ra");
|
||||
}
|
||||
|
||||
static int
|
||||
pre_bd(DECL_ARGS)
|
||||
{
|
||||
@ -876,7 +902,7 @@ pre_bd(DECL_ARGS)
|
||||
print_line(".nf", 0);
|
||||
if (0 == n->norm->Bd.comp && NULL != n->parent->prev)
|
||||
outflags |= MMAN_sp;
|
||||
print_offs(n->norm->Bd.offs);
|
||||
print_offs(n->norm->Bd.offs, 1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -963,7 +989,7 @@ pre_bl(DECL_ARGS)
|
||||
* just nest and do not add up their indentation.
|
||||
*/
|
||||
if (n->norm->Bl.offs) {
|
||||
print_offs(n->norm->Bl.offs);
|
||||
print_offs(n->norm->Bl.offs, 0);
|
||||
Bl_stack[Bl_stack_len++] = 0;
|
||||
}
|
||||
|
||||
@ -1048,7 +1074,7 @@ static int
|
||||
pre_dl(DECL_ARGS)
|
||||
{
|
||||
|
||||
print_offs("6n");
|
||||
print_offs("6n", 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -1098,21 +1124,22 @@ post_en(DECL_ARGS)
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
pre_eo(DECL_ARGS)
|
||||
{
|
||||
|
||||
outflags &= ~(MMAN_spc | MMAN_nl);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
post_eo(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_HEAD == n->type || MDOC_BODY == n->type)
|
||||
if (n->end != ENDBODY_SPACE)
|
||||
outflags &= ~MMAN_spc;
|
||||
}
|
||||
|
||||
static int
|
||||
pre_es(DECL_ARGS)
|
||||
{
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
pre_fa(DECL_ARGS)
|
||||
{
|
||||
@ -1166,7 +1193,8 @@ pre_fl(DECL_ARGS)
|
||||
|
||||
font_push('B');
|
||||
print_word("\\-");
|
||||
outflags &= ~MMAN_spc;
|
||||
if (n->nchild)
|
||||
outflags &= ~MMAN_spc;
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -1175,8 +1203,10 @@ post_fl(DECL_ARGS)
|
||||
{
|
||||
|
||||
font_pop();
|
||||
if (0 == n->nchild && NULL != n->next &&
|
||||
n->next->line == n->line)
|
||||
if ( ! (n->nchild ||
|
||||
n->next == NULL ||
|
||||
n->next->type == MDOC_TEXT ||
|
||||
n->next->flags & MDOC_LINE))
|
||||
outflags &= ~MMAN_spc;
|
||||
}
|
||||
|
||||
@ -1337,7 +1367,7 @@ pre_it(DECL_ARGS)
|
||||
outflags |= MMAN_nl;
|
||||
font_push('B');
|
||||
if (LIST_bullet == bln->norm->Bl.type)
|
||||
print_word("o");
|
||||
print_word("\\(bu");
|
||||
else
|
||||
print_word("-");
|
||||
font_pop();
|
||||
@ -1649,6 +1679,13 @@ pre_rv(DECL_ARGS)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
pre_skip(DECL_ARGS)
|
||||
{
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
pre_sm(DECL_ARGS)
|
||||
{
|
||||
|
274
mdoc_term.c
274
mdoc_term.c
@ -1,4 +1,4 @@
|
||||
/* $Id: mdoc_term.c,v 1.275 2014/08/06 15:09:05 schwarze Exp $ */
|
||||
/* $Id: mdoc_term.c,v 1.297 2014/11/28 16:54:23 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -16,9 +16,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -53,7 +51,6 @@ struct termact {
|
||||
|
||||
static size_t a2width(const struct termp *, const char *);
|
||||
static size_t a2height(const struct termp *, const char *);
|
||||
static size_t a2offs(const struct termp *, const char *);
|
||||
|
||||
static void print_bvspace(struct termp *,
|
||||
const struct mdoc_node *,
|
||||
@ -67,7 +64,6 @@ static void synopsis_pre(struct termp *,
|
||||
|
||||
static void termp____post(DECL_ARGS);
|
||||
static void termp__t_post(DECL_ARGS);
|
||||
static void termp_an_post(DECL_ARGS);
|
||||
static void termp_bd_post(DECL_ARGS);
|
||||
static void termp_bk_post(DECL_ARGS);
|
||||
static void termp_bl_post(DECL_ARGS);
|
||||
@ -95,7 +91,6 @@ static int termp_bt_pre(DECL_ARGS);
|
||||
static int termp_bx_pre(DECL_ARGS);
|
||||
static int termp_cd_pre(DECL_ARGS);
|
||||
static int termp_d1_pre(DECL_ARGS);
|
||||
static int termp_es_pre(DECL_ARGS);
|
||||
static int termp_ex_pre(DECL_ARGS);
|
||||
static int termp_fa_pre(DECL_ARGS);
|
||||
static int termp_fd_pre(DECL_ARGS);
|
||||
@ -115,6 +110,7 @@ static int termp_quote_pre(DECL_ARGS);
|
||||
static int termp_rs_pre(DECL_ARGS);
|
||||
static int termp_rv_pre(DECL_ARGS);
|
||||
static int termp_sh_pre(DECL_ARGS);
|
||||
static int termp_skip_pre(DECL_ARGS);
|
||||
static int termp_sm_pre(DECL_ARGS);
|
||||
static int termp_sp_pre(DECL_ARGS);
|
||||
static int termp_ss_pre(DECL_ARGS);
|
||||
@ -140,7 +136,7 @@ static const struct termact termacts[MDOC_MAX] = {
|
||||
{ NULL, NULL }, /* El */
|
||||
{ termp_it_pre, termp_it_post }, /* It */
|
||||
{ termp_under_pre, NULL }, /* Ad */
|
||||
{ termp_an_pre, termp_an_post }, /* An */
|
||||
{ termp_an_pre, NULL }, /* An */
|
||||
{ termp_under_pre, NULL }, /* Ar */
|
||||
{ termp_cd_pre, NULL }, /* Cd */
|
||||
{ termp_bold_pre, NULL }, /* Cm */
|
||||
@ -187,7 +183,7 @@ static const struct termact termacts[MDOC_MAX] = {
|
||||
{ termp_quote_pre, termp_quote_post }, /* Bq */
|
||||
{ termp_xx_pre, NULL }, /* Bsx */
|
||||
{ termp_bx_pre, NULL }, /* Bx */
|
||||
{ NULL, NULL }, /* Db */
|
||||
{ termp_skip_pre, NULL }, /* Db */
|
||||
{ NULL, NULL }, /* Dc */
|
||||
{ termp_quote_pre, termp_quote_post }, /* Do */
|
||||
{ termp_quote_pre, termp_quote_post }, /* Dq */
|
||||
@ -197,7 +193,7 @@ static const struct termact termacts[MDOC_MAX] = {
|
||||
{ termp_quote_pre, termp_quote_post }, /* Eo */
|
||||
{ termp_xx_pre, NULL }, /* Fx */
|
||||
{ termp_bold_pre, NULL }, /* Ms */
|
||||
{ NULL, NULL }, /* No */
|
||||
{ termp_li_pre, NULL }, /* No */
|
||||
{ termp_ns_pre, NULL }, /* Ns */
|
||||
{ termp_xx_pre, NULL }, /* Nx */
|
||||
{ termp_xx_pre, NULL }, /* Ox */
|
||||
@ -239,7 +235,7 @@ static const struct termact termacts[MDOC_MAX] = {
|
||||
{ termp_quote_pre, termp_quote_post }, /* Bro */
|
||||
{ NULL, NULL }, /* Brc */
|
||||
{ NULL, termp____post }, /* %C */
|
||||
{ termp_es_pre, NULL }, /* Es */
|
||||
{ termp_skip_pre, NULL }, /* Es */
|
||||
{ termp_quote_pre, termp_quote_post }, /* En */
|
||||
{ termp_xx_pre, NULL }, /* Dx */
|
||||
{ NULL, termp____post }, /* %Q */
|
||||
@ -254,34 +250,41 @@ static const struct termact termacts[MDOC_MAX] = {
|
||||
void
|
||||
terminal_mdoc(void *arg, const struct mdoc *mdoc)
|
||||
{
|
||||
const struct mdoc_node *n;
|
||||
const struct mdoc_meta *meta;
|
||||
struct mdoc_node *n;
|
||||
struct termp *p;
|
||||
|
||||
p = (struct termp *)arg;
|
||||
|
||||
if (0 == p->defindent)
|
||||
p->defindent = 5;
|
||||
|
||||
p->overstep = 0;
|
||||
p->maxrmargin = p->defrmargin;
|
||||
p->rmargin = p->maxrmargin = p->defrmargin;
|
||||
p->tabwidth = term_len(p, 5);
|
||||
|
||||
if (NULL == p->symtab)
|
||||
p->symtab = mchars_alloc();
|
||||
|
||||
n = mdoc_node(mdoc);
|
||||
n = mdoc_node(mdoc)->child;
|
||||
meta = mdoc_meta(mdoc);
|
||||
|
||||
term_begin(p, print_mdoc_head, print_mdoc_foot, meta);
|
||||
|
||||
if (n->child) {
|
||||
if (MDOC_Sh != n->child->tok)
|
||||
term_vspace(p);
|
||||
print_mdoc_nodelist(p, NULL, meta, n->child);
|
||||
if (p->synopsisonly) {
|
||||
while (n != NULL) {
|
||||
if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) {
|
||||
if (n->child->next->child != NULL)
|
||||
print_mdoc_nodelist(p, NULL,
|
||||
meta, n->child->next->child);
|
||||
term_newln(p);
|
||||
break;
|
||||
}
|
||||
n = n->next;
|
||||
}
|
||||
} else {
|
||||
if (p->defindent == 0)
|
||||
p->defindent = 5;
|
||||
term_begin(p, print_mdoc_head, print_mdoc_foot, meta);
|
||||
if (n != NULL) {
|
||||
if (n->tok != MDOC_Sh)
|
||||
term_vspace(p);
|
||||
print_mdoc_nodelist(p, NULL, meta, n);
|
||||
}
|
||||
term_end(p);
|
||||
}
|
||||
|
||||
term_end(p);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -337,13 +340,18 @@ print_mdoc_node(DECL_ARGS)
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
break;
|
||||
case MDOC_EQN:
|
||||
if ( ! (n->flags & MDOC_LINE))
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_eqn(p, n->eqn);
|
||||
if (n->next != NULL && ! (n->next->flags & MDOC_LINE))
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
break;
|
||||
case MDOC_TBL:
|
||||
term_tbl(p, n->span);
|
||||
break;
|
||||
default:
|
||||
if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
|
||||
if (termacts[n->tok].pre &&
|
||||
(n->end == ENDBODY_NOT || n->nchild))
|
||||
chld = (*termacts[n->tok].pre)
|
||||
(p, &npair, meta, n);
|
||||
break;
|
||||
@ -398,6 +406,7 @@ static void
|
||||
print_mdoc_foot(struct termp *p, const void *arg)
|
||||
{
|
||||
const struct mdoc_meta *meta;
|
||||
size_t sz;
|
||||
|
||||
meta = (const struct mdoc_meta *)arg;
|
||||
|
||||
@ -414,8 +423,9 @@ print_mdoc_foot(struct termp *p, const void *arg)
|
||||
term_vspace(p);
|
||||
|
||||
p->offset = 0;
|
||||
p->rmargin = (p->maxrmargin -
|
||||
term_strlen(p, meta->date) + term_len(p, 1)) / 2;
|
||||
sz = term_strlen(p, meta->date);
|
||||
p->rmargin = p->maxrmargin > sz ?
|
||||
(p->maxrmargin + term_len(p, 1) - sz) / 2 : 0;
|
||||
p->trailspace = 1;
|
||||
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
|
||||
|
||||
@ -423,7 +433,8 @@ print_mdoc_foot(struct termp *p, const void *arg)
|
||||
term_flushln(p);
|
||||
|
||||
p->offset = p->rmargin;
|
||||
p->rmargin = p->maxrmargin - term_strlen(p, meta->os);
|
||||
sz = term_strlen(p, meta->os);
|
||||
p->rmargin = p->maxrmargin > sz ? p->maxrmargin - sz : 0;
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
term_word(p, meta->date);
|
||||
@ -465,9 +476,6 @@ print_mdoc_head(struct termp *p, const void *arg)
|
||||
* switches on the manual section.
|
||||
*/
|
||||
|
||||
p->offset = 0;
|
||||
p->rmargin = p->maxrmargin;
|
||||
|
||||
assert(meta->vol);
|
||||
if (NULL == meta->arch)
|
||||
volume = mandoc_strdup(meta->vol);
|
||||
@ -488,7 +496,7 @@ print_mdoc_head(struct termp *p, const void *arg)
|
||||
p->offset = 0;
|
||||
p->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ?
|
||||
(p->maxrmargin - vollen + term_len(p, 1)) / 2 :
|
||||
p->maxrmargin - vollen;
|
||||
vollen < p->maxrmargin ? p->maxrmargin - vollen : 0;
|
||||
|
||||
term_word(p, title);
|
||||
term_flushln(p);
|
||||
@ -537,27 +545,10 @@ a2width(const struct termp *p, const char *v)
|
||||
struct roffsu su;
|
||||
|
||||
assert(v);
|
||||
if ( ! a2roffsu(v, &su, SCALE_MAX))
|
||||
SCALE_HS_INIT(&su, term_strlen(p, v));
|
||||
|
||||
return(term_hspan(p, &su));
|
||||
}
|
||||
|
||||
static size_t
|
||||
a2offs(const struct termp *p, const char *v)
|
||||
{
|
||||
struct roffsu su;
|
||||
|
||||
if ('\0' == *v)
|
||||
return(0);
|
||||
else if (0 == strcmp(v, "left"))
|
||||
return(0);
|
||||
else if (0 == strcmp(v, "indent"))
|
||||
return(term_len(p, p->defindent + 1));
|
||||
else if (0 == strcmp(v, "indent-two"))
|
||||
return(term_len(p, (p->defindent + 1) * 2));
|
||||
else if ( ! a2roffsu(v, &su, SCALE_MAX))
|
||||
if ( ! a2roffsu(v, &su, SCALE_MAX)) {
|
||||
SCALE_HS_INIT(&su, term_strlen(p, v));
|
||||
su.scale /= term_strlen(p, "0");
|
||||
}
|
||||
|
||||
return(term_hspan(p, &su));
|
||||
}
|
||||
@ -585,16 +576,18 @@ print_bvspace(struct termp *p,
|
||||
|
||||
/* Do not vspace directly after Ss/Sh. */
|
||||
|
||||
for (nn = n; nn; nn = nn->parent) {
|
||||
if (MDOC_BLOCK != nn->type)
|
||||
continue;
|
||||
if (MDOC_Ss == nn->tok)
|
||||
nn = n;
|
||||
while (nn->prev == NULL) {
|
||||
do {
|
||||
nn = nn->parent;
|
||||
if (nn->type == MDOC_ROOT)
|
||||
return;
|
||||
} while (nn->type != MDOC_BLOCK);
|
||||
if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss)
|
||||
return;
|
||||
if (MDOC_Sh == nn->tok)
|
||||
return;
|
||||
if (NULL == nn->prev)
|
||||
continue;
|
||||
break;
|
||||
if (nn->tok == MDOC_It &&
|
||||
nn->parent->parent->norm->Bl.type != LIST_item)
|
||||
break;
|
||||
}
|
||||
|
||||
/* A `-column' does not assert vspace within the list. */
|
||||
@ -650,7 +643,7 @@ termp_it_pre(DECL_ARGS)
|
||||
width = offset = 0;
|
||||
|
||||
if (bl->norm->Bl.offs)
|
||||
offset = a2offs(p, bl->norm->Bl.offs);
|
||||
offset = a2width(p, bl->norm->Bl.offs);
|
||||
|
||||
switch (type) {
|
||||
case LIST_column:
|
||||
@ -808,7 +801,8 @@ termp_it_pre(DECL_ARGS)
|
||||
* the "overstep" effect in term_flushln() and treat
|
||||
* this as a `-ohang' list instead.
|
||||
*/
|
||||
if (n->next->child &&
|
||||
if (NULL != n->next &&
|
||||
NULL != n->next->child &&
|
||||
(MDOC_Bl == n->next->child->tok ||
|
||||
MDOC_Bd == n->next->child->tok))
|
||||
break;
|
||||
@ -864,7 +858,9 @@ termp_it_pre(DECL_ARGS)
|
||||
* don't want to recalculate rmargin and offsets when
|
||||
* using `Bd' or `Bl' within `-hang' overstep lists.
|
||||
*/
|
||||
if (MDOC_HEAD == n->type && n->next->child &&
|
||||
if (MDOC_HEAD == n->type &&
|
||||
NULL != n->next &&
|
||||
NULL != n->next->child &&
|
||||
(MDOC_Bl == n->next->child->tok ||
|
||||
MDOC_Bd == n->next->child->tok))
|
||||
break;
|
||||
@ -881,11 +877,8 @@ termp_it_pre(DECL_ARGS)
|
||||
assert(width);
|
||||
if (MDOC_HEAD == n->type)
|
||||
p->rmargin = p->offset + width;
|
||||
else {
|
||||
else
|
||||
p->offset += width;
|
||||
if (p->rmargin < p->offset)
|
||||
p->rmargin = p->offset;
|
||||
}
|
||||
break;
|
||||
case LIST_column:
|
||||
assert(width);
|
||||
@ -1002,6 +995,7 @@ termp_it_post(DECL_ARGS)
|
||||
static int
|
||||
termp_nm_pre(DECL_ARGS)
|
||||
{
|
||||
const char *cp;
|
||||
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
p->flags |= TERMP_PREKEEP;
|
||||
@ -1012,14 +1006,15 @@ termp_nm_pre(DECL_ARGS)
|
||||
if (NULL == n->child)
|
||||
return(0);
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
p->offset += term_len(p, 1) +
|
||||
(NULL == n->prev->child ?
|
||||
term_strlen(p, meta->name) :
|
||||
MDOC_TEXT == n->prev->child->type ?
|
||||
term_strlen(p, n->prev->child->string) :
|
||||
term_len(p, 5));
|
||||
if (p->rmargin < p->offset)
|
||||
p->rmargin = p->offset;
|
||||
cp = NULL;
|
||||
if (n->prev->child != NULL)
|
||||
cp = n->prev->child->string;
|
||||
if (cp == NULL)
|
||||
cp = meta->name;
|
||||
if (cp == NULL)
|
||||
p->offset += term_len(p, 6);
|
||||
else
|
||||
p->offset += term_len(p, 1) + term_strlen(p, cp);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -1029,7 +1024,8 @@ termp_nm_pre(DECL_ARGS)
|
||||
if (MDOC_HEAD == n->type)
|
||||
synopsis_pre(p, n->parent);
|
||||
|
||||
if (MDOC_HEAD == n->type && n->next->child) {
|
||||
if (MDOC_HEAD == n->type &&
|
||||
NULL != n->next && NULL != n->next->child) {
|
||||
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK | TERMP_BRIND;
|
||||
p->trailspace = 1;
|
||||
p->rmargin = p->offset + term_len(p, 1);
|
||||
@ -1057,7 +1053,8 @@ termp_nm_post(DECL_ARGS)
|
||||
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
|
||||
} else if (MDOC_HEAD == n->type && n->next->child) {
|
||||
} else if (MDOC_HEAD == n->type &&
|
||||
NULL != n->next && NULL != n->next->child) {
|
||||
term_flushln(p);
|
||||
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG);
|
||||
p->trailspace = 0;
|
||||
@ -1072,9 +1069,10 @@ termp_fl_pre(DECL_ARGS)
|
||||
term_fontpush(p, TERMFONT_BOLD);
|
||||
term_word(p, "\\-");
|
||||
|
||||
if (n->child)
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
else if (n->next && n->next->line == n->line)
|
||||
if ( ! (n->nchild == 0 &&
|
||||
(n->next == NULL ||
|
||||
n->next->type == MDOC_TEXT ||
|
||||
n->next->flags & MDOC_LINE)))
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
return(1);
|
||||
@ -1095,54 +1093,27 @@ static int
|
||||
termp_an_pre(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (NULL == n->child)
|
||||
return(1);
|
||||
|
||||
/*
|
||||
* If not in the AUTHORS section, `An -split' will cause
|
||||
* newlines to occur before the author name. If in the AUTHORS
|
||||
* section, by default, the first `An' invocation is nosplit,
|
||||
* then all subsequent ones, regardless of whether interspersed
|
||||
* with other macros/text, are split. -split, in this case,
|
||||
* will override the condition of the implied first -nosplit.
|
||||
*/
|
||||
|
||||
if (n->sec == SEC_AUTHORS) {
|
||||
if ( ! (TERMP_ANPREC & p->flags)) {
|
||||
if (TERMP_SPLIT & p->flags)
|
||||
term_newln(p);
|
||||
return(1);
|
||||
}
|
||||
if (TERMP_NOSPLIT & p->flags)
|
||||
return(1);
|
||||
term_newln(p);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (TERMP_SPLIT & p->flags)
|
||||
term_newln(p);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
termp_an_post(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (n->child) {
|
||||
if (SEC_AUTHORS == n->sec)
|
||||
p->flags |= TERMP_ANPREC;
|
||||
return;
|
||||
}
|
||||
|
||||
if (AUTH_split == n->norm->An.auth) {
|
||||
if (n->norm->An.auth == AUTH_split) {
|
||||
p->flags &= ~TERMP_NOSPLIT;
|
||||
p->flags |= TERMP_SPLIT;
|
||||
} else if (AUTH_nosplit == n->norm->An.auth) {
|
||||
return(0);
|
||||
}
|
||||
if (n->norm->An.auth == AUTH_nosplit) {
|
||||
p->flags &= ~TERMP_SPLIT;
|
||||
p->flags |= TERMP_NOSPLIT;
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (n->child == NULL)
|
||||
return(0);
|
||||
|
||||
if (p->flags & TERMP_SPLIT)
|
||||
term_newln(p);
|
||||
|
||||
if (n->sec == SEC_AUTHORS && ! (p->flags & TERMP_NOSPLIT))
|
||||
p->flags |= TERMP_SPLIT;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1256,14 +1227,8 @@ static int
|
||||
termp_nd_pre(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_BODY != n->type)
|
||||
return(1);
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__linux__)
|
||||
term_word(p, "\\(en");
|
||||
#else
|
||||
term_word(p, "\\(em");
|
||||
#endif
|
||||
if (n->type == MDOC_BODY)
|
||||
term_word(p, "\\(en");
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -1408,14 +1373,17 @@ static int
|
||||
termp_sh_pre(DECL_ARGS)
|
||||
{
|
||||
|
||||
/* No vspace between consecutive `Sh' calls. */
|
||||
|
||||
switch (n->type) {
|
||||
case MDOC_BLOCK:
|
||||
if (n->prev && MDOC_Sh == n->prev->tok)
|
||||
if (NULL == n->prev->body->child)
|
||||
break;
|
||||
term_vspace(p);
|
||||
/*
|
||||
* Vertical space before sections, except
|
||||
* when the previous section was empty.
|
||||
*/
|
||||
if (n->prev == NULL ||
|
||||
MDOC_Sh != n->prev->tok ||
|
||||
(n->prev->body != NULL &&
|
||||
n->prev->body->child != NULL))
|
||||
term_vspace(p);
|
||||
break;
|
||||
case MDOC_HEAD:
|
||||
term_fontpush(p, TERMFONT_BOLD);
|
||||
@ -1593,8 +1561,17 @@ termp_bd_pre(DECL_ARGS)
|
||||
} else if (MDOC_HEAD == n->type)
|
||||
return(0);
|
||||
|
||||
if (n->norm->Bd.offs)
|
||||
p->offset += a2offs(p, n->norm->Bd.offs);
|
||||
/* Handle the -offset argument. */
|
||||
|
||||
if (n->norm->Bd.offs == NULL ||
|
||||
! strcmp(n->norm->Bd.offs, "left"))
|
||||
/* nothing */;
|
||||
else if ( ! strcmp(n->norm->Bd.offs, "indent"))
|
||||
p->offset += term_len(p, p->defindent + 1);
|
||||
else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
|
||||
p->offset += term_len(p, (p->defindent + 1) * 2);
|
||||
else
|
||||
p->offset += a2width(p, n->norm->Bd.offs);
|
||||
|
||||
/*
|
||||
* If -ragged or -filled are specified, the block does nothing
|
||||
@ -1860,7 +1837,7 @@ termp_sp_pre(DECL_ARGS)
|
||||
}
|
||||
|
||||
static int
|
||||
termp_es_pre(DECL_ARGS)
|
||||
termp_skip_pre(DECL_ARGS)
|
||||
{
|
||||
|
||||
return(0);
|
||||
@ -1877,7 +1854,8 @@ termp_quote_pre(DECL_ARGS)
|
||||
case MDOC_Ao:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Aq:
|
||||
term_word(p, "<");
|
||||
term_word(p, n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? "<" : "\\(la");
|
||||
break;
|
||||
case MDOC_Bro:
|
||||
/* FALLTHROUGH */
|
||||
@ -1938,17 +1916,19 @@ static void
|
||||
termp_quote_post(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_BODY != n->type && MDOC_ELEM != n->type)
|
||||
if (n->type != MDOC_BODY && n->type != MDOC_ELEM)
|
||||
return;
|
||||
|
||||
if (MDOC_En != n->tok)
|
||||
if ( ! (n->tok == MDOC_En ||
|
||||
(n->tok == MDOC_Eo && n->end == ENDBODY_SPACE)))
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
switch (n->tok) {
|
||||
case MDOC_Ao:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Aq:
|
||||
term_word(p, ">");
|
||||
term_word(p, n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? ">" : "\\(ra");
|
||||
break;
|
||||
case MDOC_Bro:
|
||||
/* FALLTHROUGH */
|
||||
|
835
mdoc_validate.c
835
mdoc_validate.c
File diff suppressed because it is too large
Load Diff
6
msec.c
6
msec.c
@ -1,4 +1,4 @@
|
||||
/* $Id: msec.c,v 1.11 2014/03/23 11:25:26 schwarze Exp $ */
|
||||
/* $Id: msec.c,v 1.12 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,9 +14,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
6
msec.in
6
msec.in
@ -1,4 +1,4 @@
|
||||
/* $Id: msec.in,v 1.6 2010/06/19 20:46:28 kristaps Exp $ */
|
||||
/* $Id: msec.in,v 1.7 2014/08/26 11:21:40 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -25,8 +25,8 @@
|
||||
LINE("1", "General Commands Manual")
|
||||
LINE("2", "System Calls Manual")
|
||||
LINE("3", "Library Functions Manual")
|
||||
LINE("3p", "Perl Library Functions Manual")
|
||||
LINE("4", "Kernel Interfaces Manual")
|
||||
LINE("3p", "Perl Library Manual")
|
||||
LINE("4", "Device Drivers Manual")
|
||||
LINE("5", "File Formats Manual")
|
||||
LINE("6", "Games Manual")
|
||||
LINE("7", "Miscellaneous Information Manual")
|
||||
|
80
out.c
80
out.c
@ -1,7 +1,7 @@
|
||||
/* $Id: out.c,v 1.49 2014/08/01 19:25:52 schwarze Exp $ */
|
||||
/* $Id: out.c,v 1.53 2014/10/14 18:18:05 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011, 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
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -112,7 +110,7 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
|
||||
case '\0':
|
||||
if (SCALE_MAX == def)
|
||||
return(0);
|
||||
unit = SCALE_BU;
|
||||
unit = SCALE_EN;
|
||||
break;
|
||||
case 'u':
|
||||
unit = SCALE_BU;
|
||||
@ -141,11 +139,14 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
|
||||
* used for the actual width calculations.
|
||||
*/
|
||||
void
|
||||
tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
|
||||
tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
|
||||
size_t totalwidth)
|
||||
{
|
||||
const struct tbl_dat *dp;
|
||||
struct roffcol *col;
|
||||
size_t ewidth, xwidth;
|
||||
int spans;
|
||||
int icol, maxcol, necol, nxcol;
|
||||
|
||||
/*
|
||||
* Allocate the master column specifiers. These will hold the
|
||||
@ -157,7 +158,7 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
|
||||
tbl->cols = mandoc_calloc((size_t)sp->opts->cols,
|
||||
sizeof(struct roffcol));
|
||||
|
||||
for ( ; sp; sp = sp->next) {
|
||||
for (maxcol = -1; sp; sp = sp->next) {
|
||||
if (TBL_SPAN_DATA != sp->pos)
|
||||
continue;
|
||||
spans = 1;
|
||||
@ -172,11 +173,72 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
|
||||
spans = dp->spans;
|
||||
if (1 < spans)
|
||||
continue;
|
||||
assert(dp->layout);
|
||||
col = &tbl->cols[dp->layout->head->ident];
|
||||
icol = dp->layout->head->ident;
|
||||
if (maxcol < icol)
|
||||
maxcol = icol;
|
||||
col = tbl->cols + icol;
|
||||
col->flags |= dp->layout->flags;
|
||||
if (dp->layout->flags & TBL_CELL_WIGN)
|
||||
continue;
|
||||
tblcalc_data(tbl, col, sp->opts, dp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Count columns to equalize and columns to maximize.
|
||||
* Find maximum width of the columns to equalize.
|
||||
* Find total width of the columns *not* to maximize.
|
||||
*/
|
||||
|
||||
necol = nxcol = 0;
|
||||
ewidth = xwidth = 0;
|
||||
for (icol = 0; icol <= maxcol; icol++) {
|
||||
col = tbl->cols + icol;
|
||||
if (col->flags & TBL_CELL_EQUAL) {
|
||||
necol++;
|
||||
if (ewidth < col->width)
|
||||
ewidth = col->width;
|
||||
}
|
||||
if (col->flags & TBL_CELL_WMAX)
|
||||
nxcol++;
|
||||
else
|
||||
xwidth += col->width;
|
||||
}
|
||||
|
||||
/*
|
||||
* Equalize columns, if requested for any of them.
|
||||
* Update total width of the columns not to maximize.
|
||||
*/
|
||||
|
||||
if (necol) {
|
||||
for (icol = 0; icol <= maxcol; icol++) {
|
||||
col = tbl->cols + icol;
|
||||
if ( ! (col->flags & TBL_CELL_EQUAL))
|
||||
continue;
|
||||
if (col->width == ewidth)
|
||||
continue;
|
||||
if (nxcol && totalwidth)
|
||||
xwidth += ewidth - col->width;
|
||||
col->width = ewidth;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are any columns to maximize, find the total
|
||||
* available width, deducting 3n margins between columns.
|
||||
* Distribute the available width evenly.
|
||||
*/
|
||||
|
||||
if (nxcol && totalwidth) {
|
||||
xwidth = totalwidth - 3*maxcol - xwidth;
|
||||
for (icol = 0; icol <= maxcol; icol++) {
|
||||
col = tbl->cols + icol;
|
||||
if ( ! (col->flags & TBL_CELL_WMAX))
|
||||
continue;
|
||||
col->width = xwidth / nxcol--;
|
||||
xwidth -= col->width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
8
out.h
8
out.h
@ -1,4 +1,4 @@
|
||||
/* $Id: out.h,v 1.22 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: out.h,v 1.24 2014/10/14 02:16:06 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -34,6 +34,7 @@ enum roffscale {
|
||||
struct roffcol {
|
||||
size_t width; /* width of cell */
|
||||
size_t decimal; /* decimal position in cell */
|
||||
int flags; /* layout flags, see tbl_cell */
|
||||
};
|
||||
|
||||
struct roffsu {
|
||||
@ -59,12 +60,13 @@ __BEGIN_DECLS
|
||||
while (/* CONSTCOND */ 0)
|
||||
|
||||
#define SCALE_HS_INIT(p, v) \
|
||||
do { (p)->unit = SCALE_BU; \
|
||||
do { (p)->unit = SCALE_EN; \
|
||||
(p)->scale = (v); } \
|
||||
while (/* CONSTCOND */ 0)
|
||||
|
||||
int a2roffsu(const char *, struct roffsu *, enum roffscale);
|
||||
void tblcalc(struct rofftbl *tbl, const struct tbl_span *);
|
||||
void tblcalc(struct rofftbl *tbl,
|
||||
const struct tbl_span *, size_t);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
157
preconv.1
157
preconv.1
@ -1,157 +0,0 @@
|
||||
.\" $Id: preconv.1,v 1.7 2013/07/13 19:41:16 schwarze Exp $
|
||||
.\"
|
||||
.\" 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 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: July 13 2013 $
|
||||
.Dt PRECONV 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm preconv
|
||||
.Nd recode multibyte UNIX manuals
|
||||
.Sh SYNOPSIS
|
||||
.Nm preconv
|
||||
.Op Fl D Ar enc
|
||||
.Op Fl e Ar enc
|
||||
.Op Ar file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility recodes multibyte
|
||||
.Ux
|
||||
manual files into
|
||||
.Xr mandoc 1
|
||||
.Po
|
||||
or other troff system supporting the
|
||||
.Sq \e[uNNNN]
|
||||
escape sequence
|
||||
.Pc
|
||||
input.
|
||||
.Pp
|
||||
By default, it parses from standard output, determining encoding as
|
||||
described in
|
||||
.Sx Algorithm .
|
||||
.Pp
|
||||
Its arguments are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl D Ar enc
|
||||
The default encoding.
|
||||
.It Fl e Ar enc
|
||||
The document's encoding.
|
||||
.It Ar file
|
||||
The input file.
|
||||
.El
|
||||
.Pp
|
||||
The recoded input is written to standard output: Unicode characters in
|
||||
the ASCII range are printed as regular ASCII characters, while those
|
||||
above this range are printed using the
|
||||
.Sq \e[uNNNN]
|
||||
format documented in
|
||||
.Xr mandoc_char 7 .
|
||||
.Pp
|
||||
If input bytes are improperly formed in the current encoding, they're
|
||||
passed unmodified to standard output.
|
||||
For some encodings, such as UTF-8, unrecoverable input sequences will
|
||||
cause
|
||||
.Nm
|
||||
to stop processing and exit.
|
||||
.Ss Algorithm
|
||||
An encoding is chosen according to the following steps:
|
||||
.Bl -enum
|
||||
.It
|
||||
From the argument passed to
|
||||
.Fl e Ar enc .
|
||||
.It
|
||||
If a BOM exists, UTF\-8 encoding is selected.
|
||||
.It
|
||||
From the coding tags parsed from
|
||||
.Qq File Variables
|
||||
on the first two lines of input.
|
||||
A file variable is an input line of the form
|
||||
.Pp
|
||||
.Dl \%.\e\(dq -*- key: val [; key: val ]* -*-
|
||||
.Pp
|
||||
A coding tag variable is where
|
||||
.Cm key
|
||||
is
|
||||
.Qq coding
|
||||
and
|
||||
.Cm val
|
||||
is the name of the encoding.
|
||||
A typical file variable with a coding tag is
|
||||
.Pp
|
||||
.Dl \%.\e\(dq -*- mode: troff; coding: utf-8 -*-
|
||||
.It
|
||||
From the argument passed to
|
||||
.Fl D Ar enc .
|
||||
.It
|
||||
If all else fails, Latin\-1 is used.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility recognises the UTF\-8, us\-ascii, and latin\-1 encodings as
|
||||
passed to the
|
||||
.Fl e
|
||||
and
|
||||
.Fl D
|
||||
arguments, or as coding tags.
|
||||
Encodings are matched case-insensitively.
|
||||
.\" .Sh IMPLEMENTATION NOTES
|
||||
.\" Not used in OpenBSD.
|
||||
.\" .Sh RETURN VALUES
|
||||
.\" For sections 2, 3, & 9 only.
|
||||
.\" .Sh ENVIRONMENT
|
||||
.\" For sections 1, 6, 7, & 8 only.
|
||||
.\" .Sh FILES
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
Explicitly page a UTF\-8 manual
|
||||
.Pa foo.1
|
||||
in the current locale:
|
||||
.Pp
|
||||
.Dl $ preconv \-e utf\-8 foo.1 | mandoc -Tlocale | less
|
||||
.\" .Sh DIAGNOSTICS
|
||||
.\" For sections 1, 4, 6, 7, & 8 only.
|
||||
.\" .Sh ERRORS
|
||||
.\" For sections 2, 3, & 9 only.
|
||||
.Sh SEE ALSO
|
||||
.Xr mandoc 1 ,
|
||||
.Xr mandoc_char 7
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility references the US-ASCII character set standard, ANSI_X3.4\-1968;
|
||||
the Latin\-1 character set standard, ISO/IEC 8859\-1:1998; the UTF\-8
|
||||
character set standard; and UCS (Unicode), ISO/IEC 10646.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in the GNU troff
|
||||
.Pq Dq groff
|
||||
system in December 2005, authored by Tomohiro Kubota and Werner
|
||||
Lemberg.
|
||||
The implementation that is part of the
|
||||
.Xr mandoc 1
|
||||
utility appeared in May 2011.
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
|
||||
.\" .Sh CAVEATS
|
||||
.\" .Sh BUGS
|
||||
.\" .Sh SECURITY CONSIDERATIONS
|
||||
.\" Not used in OpenBSD.
|
460
preconv.c
460
preconv.c
@ -1,6 +1,7 @@
|
||||
/* $Id: preconv.c,v 1.6 2013/06/02 03:52:21 schwarze Exp $ */
|
||||
/* $Id: preconv.c,v 1.12 2014/11/14 04:24:04 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
@ -14,325 +15,132 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "mandoc.h"
|
||||
#include "libmandoc.h"
|
||||
|
||||
/*
|
||||
* The read_whole_file() and resize_buf() functions are copied from
|
||||
* read.c, including all dependency code.
|
||||
*/
|
||||
|
||||
enum enc {
|
||||
ENC_UTF_8, /* UTF-8 */
|
||||
ENC_US_ASCII, /* US-ASCII */
|
||||
ENC_LATIN_1, /* Latin-1 */
|
||||
ENC__MAX
|
||||
};
|
||||
|
||||
struct buf {
|
||||
char *buf; /* binary input buffer */
|
||||
size_t sz; /* size of binary buffer */
|
||||
size_t offs; /* starting buffer offset */
|
||||
};
|
||||
|
||||
struct encode {
|
||||
const char *name;
|
||||
int (*conv)(const struct buf *);
|
||||
};
|
||||
|
||||
static int cue_enc(const struct buf *, size_t *, enum enc *);
|
||||
static int conv_latin_1(const struct buf *);
|
||||
static int conv_us_ascii(const struct buf *);
|
||||
static int conv_utf_8(const struct buf *);
|
||||
static int read_whole_file(const char *, int,
|
||||
struct buf *, int *);
|
||||
static void resize_buf(struct buf *, size_t);
|
||||
static void usage(void);
|
||||
|
||||
static const struct encode encs[ENC__MAX] = {
|
||||
{ "utf-8", conv_utf_8 }, /* ENC_UTF_8 */
|
||||
{ "us-ascii", conv_us_ascii }, /* ENC_US_ASCII */
|
||||
{ "latin-1", conv_latin_1 }, /* ENC_LATIN_1 */
|
||||
};
|
||||
|
||||
static const char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: %s "
|
||||
"[-D enc] "
|
||||
"[-e ENC] "
|
||||
"[file]\n", progname);
|
||||
}
|
||||
|
||||
static int
|
||||
conv_latin_1(const struct buf *b)
|
||||
int
|
||||
preconv_encode(struct buf *ib, size_t *ii, struct buf *ob, size_t *oi,
|
||||
int *filenc)
|
||||
{
|
||||
size_t i;
|
||||
unsigned char cu;
|
||||
const char *cp;
|
||||
|
||||
cp = b->buf + (int)b->offs;
|
||||
|
||||
/*
|
||||
* Latin-1 falls into the first 256 code-points of Unicode, so
|
||||
* there's no need for any sort of translation. Just make the
|
||||
* 8-bit characters use the Unicode escape.
|
||||
* Note that binary values 128 < v < 160 are passed through
|
||||
* unmodified to mandoc.
|
||||
*/
|
||||
|
||||
for (i = b->offs; i < b->sz; i++) {
|
||||
cu = (unsigned char)*cp++;
|
||||
cu < 160U ? putchar(cu) : printf("\\[u%.4X]", cu);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
conv_us_ascii(const struct buf *b)
|
||||
{
|
||||
|
||||
/*
|
||||
* US-ASCII has no conversion since it falls into the first 128
|
||||
* bytes of Unicode.
|
||||
*/
|
||||
|
||||
fwrite(b->buf, 1, b->sz, stdout);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int
|
||||
conv_utf_8(const struct buf *b)
|
||||
{
|
||||
int state, be;
|
||||
int state;
|
||||
unsigned int accum;
|
||||
size_t i;
|
||||
unsigned char cu;
|
||||
const char *cp;
|
||||
const long one = 1L;
|
||||
|
||||
cp = b->buf + (int)b->offs;
|
||||
if ( ! (*filenc & MPARSE_UTF8))
|
||||
goto latin;
|
||||
|
||||
state = 0;
|
||||
accum = 0U;
|
||||
be = 0;
|
||||
|
||||
/* Quick test for big-endian value. */
|
||||
|
||||
if ( ! (*((const char *)(&one))))
|
||||
be = 1;
|
||||
|
||||
for (i = b->offs; i < b->sz; i++) {
|
||||
cu = (unsigned char)*cp++;
|
||||
for (i = *ii; i < ib->sz; i++) {
|
||||
cu = ib->buf[i];
|
||||
if (state) {
|
||||
if ( ! (cu & 128) || (cu & 64)) {
|
||||
/* Bad sequence header. */
|
||||
return(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Accept only legitimate bit patterns. */
|
||||
|
||||
if (cu > 191 || cu < 128) {
|
||||
/* Bad in-sequence bits. */
|
||||
return(0);
|
||||
break;
|
||||
}
|
||||
|
||||
accum |= (cu & 63) << --state * 6;
|
||||
|
||||
/*
|
||||
* Accum is held in little-endian order as
|
||||
* stipulated by the UTF-8 sequence coding. We
|
||||
* need to convert to a native big-endian if our
|
||||
* architecture requires it.
|
||||
*/
|
||||
if (state)
|
||||
continue;
|
||||
|
||||
if (0 == state && be)
|
||||
accum = (accum >> 24) |
|
||||
((accum << 8) & 0x00FF0000) |
|
||||
((accum >> 8) & 0x0000FF00) |
|
||||
(accum << 24);
|
||||
|
||||
if (0 == state) {
|
||||
accum < 128U ? putchar(accum) :
|
||||
printf("\\[u%.4X]", accum);
|
||||
accum = 0U;
|
||||
}
|
||||
} else if (cu & (1 << 7)) {
|
||||
if (accum < 0x80)
|
||||
ob->buf[(*oi)++] = accum;
|
||||
else
|
||||
*oi += snprintf(ob->buf + *oi,
|
||||
11, "\\[u%.4X]", accum);
|
||||
*ii = i + 1;
|
||||
*filenc &= ~MPARSE_LATIN1;
|
||||
return(1);
|
||||
} else {
|
||||
/*
|
||||
* Entering a UTF-8 state: if we encounter a
|
||||
* UTF-8 bitmask, calculate the expected UTF-8
|
||||
* state from it.
|
||||
*/
|
||||
for (state = 0; state < 7; state++)
|
||||
for (state = 0; state < 7; state++)
|
||||
if ( ! (cu & (1 << (7 - state))))
|
||||
break;
|
||||
|
||||
/* Accept only legitimate bit patterns. */
|
||||
|
||||
switch (state) {
|
||||
switch (state--) {
|
||||
case (4):
|
||||
if (cu <= 244 && cu >= 240) {
|
||||
accum = (cu & 7) << 18;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
/* Bad 4-sequence start bits. */
|
||||
return(0);
|
||||
break;
|
||||
case (3):
|
||||
if (cu <= 239 && cu >= 224) {
|
||||
accum = (cu & 15) << 12;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
/* Bad 3-sequence start bits. */
|
||||
return(0);
|
||||
break;
|
||||
case (2):
|
||||
if (cu <= 223 && cu >= 194) {
|
||||
accum = (cu & 31) << 6;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
/* Bad 2-sequence start bits. */
|
||||
return(0);
|
||||
break;
|
||||
default:
|
||||
/* Bad sequence bit mask. */
|
||||
return(0);
|
||||
break;
|
||||
}
|
||||
state--;
|
||||
} else
|
||||
putchar(cu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != state) {
|
||||
/* Bad trailing bits. */
|
||||
/* FALLTHROUGH: Invalid or incomplete UTF-8 sequence. */
|
||||
|
||||
latin:
|
||||
if ( ! (*filenc & MPARSE_LATIN1))
|
||||
return(0);
|
||||
}
|
||||
|
||||
*oi += snprintf(ob->buf + *oi, 11,
|
||||
"\\[u%.4X]", (unsigned char)ib->buf[(*ii)++]);
|
||||
|
||||
*filenc &= ~MPARSE_UTF8;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
resize_buf(struct buf *buf, size_t initial)
|
||||
{
|
||||
|
||||
buf->sz = buf->sz > initial / 2 ?
|
||||
2 * buf->sz : initial;
|
||||
|
||||
buf->buf = realloc(buf->buf, buf->sz);
|
||||
if (NULL == buf->buf) {
|
||||
perror(NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
read_whole_file(const char *f, int fd,
|
||||
struct buf *fb, int *with_mmap)
|
||||
{
|
||||
size_t off;
|
||||
ssize_t ssz;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
struct stat st;
|
||||
if (-1 == fstat(fd, &st)) {
|
||||
perror(f);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're a regular file, try just reading in the whole entry
|
||||
* via mmap(). This is faster than reading it into blocks, and
|
||||
* since each file is only a few bytes to begin with, I'm not
|
||||
* concerned that this is going to tank any machines.
|
||||
*/
|
||||
|
||||
if (S_ISREG(st.st_mode) && st.st_size >= (1U << 31)) {
|
||||
fprintf(stderr, "%s: input too large\n", f);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
*with_mmap = 1;
|
||||
fb->sz = (size_t)st.st_size;
|
||||
fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (fb->buf != MAP_FAILED)
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
*with_mmap = 0;
|
||||
off = 0;
|
||||
fb->sz = 0;
|
||||
fb->buf = NULL;
|
||||
for (;;) {
|
||||
if (off == fb->sz && fb->sz == (1U << 31)) {
|
||||
fprintf(stderr, "%s: input too large\n", f);
|
||||
break;
|
||||
}
|
||||
|
||||
if (off == fb->sz)
|
||||
resize_buf(fb, 65536);
|
||||
|
||||
ssz = read(fd, fb->buf + (int)off, fb->sz - off);
|
||||
if (ssz == 0) {
|
||||
fb->sz = off;
|
||||
return(1);
|
||||
}
|
||||
if (ssz == -1) {
|
||||
perror(f);
|
||||
break;
|
||||
}
|
||||
off += (size_t)ssz;
|
||||
}
|
||||
|
||||
free(fb->buf);
|
||||
fb->buf = NULL;
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
cue_enc(const struct buf *b, size_t *offs, enum enc *enc)
|
||||
int
|
||||
preconv_cue(const struct buf *b, size_t offset)
|
||||
{
|
||||
const char *ln, *eoln, *eoph;
|
||||
size_t sz, phsz, nsz;
|
||||
int i;
|
||||
size_t sz, phsz;
|
||||
|
||||
ln = b->buf + (int)*offs;
|
||||
sz = b->sz - *offs;
|
||||
ln = b->buf + offset;
|
||||
sz = b->sz - offset;
|
||||
|
||||
/* Look for the end-of-line. */
|
||||
|
||||
if (NULL == (eoln = memchr(ln, '\n', sz)))
|
||||
return(-1);
|
||||
|
||||
/* Set next-line marker. */
|
||||
|
||||
*offs = (size_t)((eoln + 1) - b->buf);
|
||||
eoln = ln + sz;
|
||||
|
||||
/* Check if we have the correct header/trailer. */
|
||||
|
||||
if ((sz = (size_t)(eoln - ln)) < 10 ||
|
||||
memcmp(ln, ".\\\" -*-", 7) ||
|
||||
memcmp(eoln - 3, "-*-", 3))
|
||||
return(0);
|
||||
if ((sz = (size_t)(eoln - ln)) < 10 ||
|
||||
memcmp(ln, ".\\\" -*-", 7) || memcmp(eoln - 3, "-*-", 3))
|
||||
return(MPARSE_UTF8 | MPARSE_LATIN1);
|
||||
|
||||
/* Move after the header and adjust for the trailer. */
|
||||
|
||||
@ -356,12 +164,12 @@ cue_enc(const struct buf *b, size_t *offs, enum enc *enc)
|
||||
|
||||
/* Only account for the "coding" phrase. */
|
||||
|
||||
if ((phsz = (size_t)(eoph - ln)) < 7 ||
|
||||
strncasecmp(ln, "coding:", 7)) {
|
||||
if ((phsz = eoph - ln) < 7 ||
|
||||
strncasecmp(ln, "coding:", 7)) {
|
||||
sz -= phsz;
|
||||
ln += phsz;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sz -= 7;
|
||||
ln += 7;
|
||||
@ -371,153 +179,15 @@ cue_enc(const struct buf *b, size_t *offs, enum enc *enc)
|
||||
sz--;
|
||||
}
|
||||
if (0 == sz)
|
||||
break;
|
||||
return(0);
|
||||
|
||||
/* Check us against known encodings. */
|
||||
|
||||
for (i = 0; i < (int)ENC__MAX; i++) {
|
||||
nsz = strlen(encs[i].name);
|
||||
if (phsz < nsz)
|
||||
continue;
|
||||
if (strncasecmp(ln, encs[i].name, nsz))
|
||||
continue;
|
||||
|
||||
*enc = (enum enc)i;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Unknown encoding. */
|
||||
|
||||
*enc = ENC__MAX;
|
||||
return(1);
|
||||
if (phsz > 4 && !strncasecmp(ln, "utf-8", 5))
|
||||
return(MPARSE_UTF8);
|
||||
if (phsz > 10 && !strncasecmp(ln, "iso-latin-1", 11))
|
||||
return(MPARSE_LATIN1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, ch, map, fd, rc;
|
||||
struct buf b;
|
||||
const char *fn;
|
||||
enum enc enc, def;
|
||||
unsigned char bom[3] = { 0xEF, 0xBB, 0xBF };
|
||||
size_t offs;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname == NULL)
|
||||
progname = argv[0];
|
||||
else
|
||||
++progname;
|
||||
|
||||
fn = "<stdin>";
|
||||
fd = STDIN_FILENO;
|
||||
rc = EXIT_FAILURE;
|
||||
enc = def = ENC__MAX;
|
||||
map = 0;
|
||||
|
||||
memset(&b, 0, sizeof(struct buf));
|
||||
|
||||
while (-1 != (ch = getopt(argc, argv, "D:e:rdvh")))
|
||||
switch (ch) {
|
||||
case ('D'):
|
||||
/* FALLTHROUGH */
|
||||
case ('e'):
|
||||
for (i = 0; i < (int)ENC__MAX; i++) {
|
||||
if (strcasecmp(optarg, encs[i].name))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (i < (int)ENC__MAX) {
|
||||
if ('D' == ch)
|
||||
def = (enum enc)i;
|
||||
else
|
||||
enc = (enum enc)i;
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: Bad encoding\n", optarg);
|
||||
return(EXIT_FAILURE);
|
||||
case ('r'):
|
||||
/* FALLTHROUGH */
|
||||
case ('d'):
|
||||
/* FALLTHROUGH */
|
||||
case ('v'):
|
||||
/* Compatibility with GNU preconv. */
|
||||
break;
|
||||
case ('h'):
|
||||
/* Compatibility with GNU preconv. */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
usage();
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* Open and read the first argument on the command-line.
|
||||
* If we don't have one, we default to stdin.
|
||||
*/
|
||||
|
||||
if (argc > 0) {
|
||||
fn = *argv;
|
||||
fd = open(fn, O_RDONLY, 0);
|
||||
if (-1 == fd) {
|
||||
perror(fn);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! read_whole_file(fn, fd, &b, &map))
|
||||
goto out;
|
||||
|
||||
/* Try to read the UTF-8 BOM. */
|
||||
|
||||
if (ENC__MAX == enc)
|
||||
if (b.sz > 3 && 0 == memcmp(b.buf, bom, 3)) {
|
||||
b.offs = 3;
|
||||
enc = ENC_UTF_8;
|
||||
}
|
||||
|
||||
/* Try reading from the "-*-" cue. */
|
||||
|
||||
if (ENC__MAX == enc) {
|
||||
offs = b.offs;
|
||||
ch = cue_enc(&b, &offs, &enc);
|
||||
if (0 == ch)
|
||||
ch = cue_enc(&b, &offs, &enc);
|
||||
}
|
||||
|
||||
/*
|
||||
* No encoding has been detected.
|
||||
* Thus, we either fall into our default encoder, if specified,
|
||||
* or use Latin-1 if all else fails.
|
||||
*/
|
||||
|
||||
if (ENC__MAX == enc)
|
||||
enc = ENC__MAX == def ? ENC_LATIN_1 : def;
|
||||
|
||||
if ( ! (*encs[(int)enc].conv)(&b)) {
|
||||
fprintf(stderr, "%s: Bad encoding\n", fn);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EXIT_SUCCESS;
|
||||
out:
|
||||
#ifdef HAVE_MMAP
|
||||
if (map)
|
||||
munmap(b.buf, b.sz);
|
||||
else
|
||||
#endif
|
||||
free(b.buf);
|
||||
|
||||
if (fd > STDIN_FILENO)
|
||||
close(fd);
|
||||
|
||||
return(rc);
|
||||
return(MPARSE_UTF8 | MPARSE_LATIN1);
|
||||
}
|
||||
|
430
read.c
430
read.c
@ -1,4 +1,4 @@
|
||||
/* $Id: read.c,v 1.79 2014/08/06 15:09:05 schwarze Exp $ */
|
||||
/* $Id: read.c,v 1.101 2014/11/28 18:09:01 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -16,14 +16,14 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
# include <sys/stat.h>
|
||||
# include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#if HAVE_MMAP
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@ -45,32 +45,31 @@
|
||||
|
||||
#define REPARSE_LIMIT 1000
|
||||
|
||||
struct buf {
|
||||
char *buf; /* binary input buffer */
|
||||
size_t sz; /* size of binary buffer */
|
||||
};
|
||||
|
||||
struct mparse {
|
||||
enum mandoclevel file_status; /* status of current parse */
|
||||
enum mandoclevel wlevel; /* ignore messages below this */
|
||||
int line; /* line number in the file */
|
||||
int options; /* parser options */
|
||||
struct man *pman; /* persistent man parser */
|
||||
struct mdoc *pmdoc; /* persistent mdoc parser */
|
||||
struct man *man; /* man parser */
|
||||
struct mdoc *mdoc; /* mdoc parser */
|
||||
struct roff *roff; /* roff parser (!NULL) */
|
||||
const struct mchars *mchars; /* character table */
|
||||
char *sodest; /* filename pointed to by .so */
|
||||
int reparse_count; /* finite interp. stack */
|
||||
mandocmsg mmsg; /* warning/error message handler */
|
||||
const char *file;
|
||||
struct buf *secondary;
|
||||
const char *file; /* filename of current input file */
|
||||
struct buf *primary; /* buffer currently being parsed */
|
||||
struct buf *secondary; /* preprocessed copy of input */
|
||||
const char *defos; /* default operating system */
|
||||
mandocmsg mmsg; /* warning/error message handler */
|
||||
enum mandoclevel file_status; /* status of current parse */
|
||||
enum mandoclevel wlevel; /* ignore messages below this */
|
||||
int options; /* parser options */
|
||||
int filenc; /* encoding of the current file */
|
||||
int reparse_count; /* finite interp. stack */
|
||||
int line; /* line number in the file */
|
||||
pid_t child; /* the gunzip(1) process */
|
||||
};
|
||||
|
||||
static void choose_parser(struct mparse *);
|
||||
static void resize_buf(struct buf *, size_t);
|
||||
static void mparse_buf_r(struct mparse *, struct buf, int);
|
||||
static void pset(const char *, int, struct mparse *);
|
||||
static void mparse_buf_r(struct mparse *, struct buf, size_t, int);
|
||||
static int read_whole_file(struct mparse *, const char *, int,
|
||||
struct buf *, int *);
|
||||
static void mparse_end(struct mparse *);
|
||||
@ -98,7 +97,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"lower case character in document title",
|
||||
"missing manual section, using \"\"",
|
||||
"unknown manual section",
|
||||
"unknown manual volume or arch",
|
||||
"missing date, using today's date",
|
||||
"cannot parse date, using it verbatim",
|
||||
"missing Os macro, using \"\"",
|
||||
@ -116,6 +114,9 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"sections out of conventional order",
|
||||
"duplicate section title",
|
||||
"unexpected section",
|
||||
"unusual Xr order",
|
||||
"unusual Xr punctuation",
|
||||
"AUTHORS section without An macro",
|
||||
|
||||
/* related to macros and nesting */
|
||||
"obsolete macro",
|
||||
@ -145,6 +146,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"missing font type, using \\fR",
|
||||
"unknown font type, using \\fR",
|
||||
"missing -std argument, adding it",
|
||||
"missing eqn box, using \"\"",
|
||||
|
||||
/* related to bad macro arguments */
|
||||
"unterminated quoted argument",
|
||||
@ -154,6 +156,8 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"skipping duplicate list type",
|
||||
"skipping -width argument",
|
||||
"unknown AT&T UNIX version",
|
||||
"comma in function argument",
|
||||
"parenthesis in function name",
|
||||
"invalid content in Rs block",
|
||||
"invalid Boolean argument",
|
||||
"unknown font, skipping request",
|
||||
@ -173,7 +177,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"equation scope open on exit",
|
||||
"overlapping equation scopes",
|
||||
"unexpected end of equation",
|
||||
"equation syntax error",
|
||||
|
||||
/* related to tables */
|
||||
"bad table syntax",
|
||||
@ -198,6 +201,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
/* related to request and macro arguments */
|
||||
"escaped character not allowed in a name",
|
||||
"argument count wrong",
|
||||
"NOT IMPLEMENTED: Bd -file",
|
||||
"missing list type, using -item",
|
||||
"missing manual name, using \"\"",
|
||||
"uname(3) system call failed, using UNKNOWN",
|
||||
@ -205,18 +209,25 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"skipping request without numeric argument",
|
||||
"skipping all arguments",
|
||||
"skipping excess arguments",
|
||||
"divide by zero",
|
||||
|
||||
"generic fatal error",
|
||||
|
||||
"input too large",
|
||||
"NOT IMPLEMENTED: Bd -file",
|
||||
"NOT IMPLEMENTED: .so with absolute path or \"..\"",
|
||||
".so request failed",
|
||||
|
||||
/* system errors */
|
||||
"cannot dup file descriptor",
|
||||
"cannot exec",
|
||||
"gunzip failed with code",
|
||||
"cannot fork",
|
||||
NULL,
|
||||
"cannot stat file",
|
||||
"cannot open pipe",
|
||||
"cannot read file",
|
||||
"gunzip died from signal",
|
||||
"cannot stat file",
|
||||
"wait failed",
|
||||
};
|
||||
|
||||
static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
|
||||
@ -239,38 +250,40 @@ resize_buf(struct buf *buf, size_t initial)
|
||||
}
|
||||
|
||||
static void
|
||||
pset(const char *buf, int pos, struct mparse *curp)
|
||||
choose_parser(struct mparse *curp)
|
||||
{
|
||||
int i;
|
||||
char *cp, *ep;
|
||||
int format;
|
||||
|
||||
/*
|
||||
* Try to intuit which kind of manual parser should be used. If
|
||||
* passed in by command-line (-man, -mdoc), then use that
|
||||
* explicitly. If passed as -mandoc, then try to guess from the
|
||||
* line: either skip dot-lines, use -mdoc when finding `.Dt', or
|
||||
* default to -man, which is more lenient.
|
||||
*
|
||||
* Separate out pmdoc/pman from mdoc/man: the first persists
|
||||
* through all parsers, while the latter is used per-parse.
|
||||
* If neither command line arguments -mdoc or -man select
|
||||
* a parser nor the roff parser found a .Dd or .TH macro
|
||||
* yet, look ahead in the main input buffer.
|
||||
*/
|
||||
|
||||
if ('.' == buf[0] || '\'' == buf[0]) {
|
||||
for (i = 1; buf[i]; i++)
|
||||
if (' ' != buf[i] && '\t' != buf[i])
|
||||
if ((format = roff_getformat(curp->roff)) == 0) {
|
||||
cp = curp->primary->buf;
|
||||
ep = cp + curp->primary->sz;
|
||||
while (cp < ep) {
|
||||
if (*cp == '.' || *cp == '\'') {
|
||||
cp++;
|
||||
if (cp[0] == 'D' && cp[1] == 'd') {
|
||||
format = MPARSE_MDOC;
|
||||
break;
|
||||
}
|
||||
if (cp[0] == 'T' && cp[1] == 'H') {
|
||||
format = MPARSE_MAN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cp = memchr(cp, '\n', ep - cp);
|
||||
if (cp == NULL)
|
||||
break;
|
||||
if ('\0' == buf[i])
|
||||
return;
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
if (MPARSE_MDOC & curp->options) {
|
||||
curp->mdoc = curp->pmdoc;
|
||||
return;
|
||||
} else if (MPARSE_MAN & curp->options) {
|
||||
curp->man = curp->pman;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
|
||||
if (format == MPARSE_MDOC) {
|
||||
if (NULL == curp->pmdoc)
|
||||
curp->pmdoc = mdoc_alloc(
|
||||
curp->roff, curp, curp->defos,
|
||||
@ -280,6 +293,8 @@ pset(const char *buf, int pos, struct mparse *curp)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fall back to man(7) as a last resort. */
|
||||
|
||||
if (NULL == curp->pman)
|
||||
curp->pman = man_alloc(curp->roff, curp,
|
||||
MPARSE_QUICK & curp->options ? 1 : 0);
|
||||
@ -288,36 +303,43 @@ pset(const char *buf, int pos, struct mparse *curp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Main parse routine for an opened file. This is called for each
|
||||
* opened file and simply loops around the full input file, possibly
|
||||
* nesting (i.e., with `so').
|
||||
* Main parse routine for a buffer.
|
||||
* It assumes encoding and line numbering are already set up.
|
||||
* It can recurse directly (for invocations of user-defined
|
||||
* macros, inline equations, and input line traps)
|
||||
* and indirectly (for .so file inclusion).
|
||||
*/
|
||||
static void
|
||||
mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
|
||||
{
|
||||
const struct tbl_span *span;
|
||||
struct buf ln;
|
||||
size_t pos; /* byte number in the ln buffer */
|
||||
enum rofferr rr;
|
||||
int i, of, rc;
|
||||
int pos; /* byte number in the ln buffer */
|
||||
int of;
|
||||
int lnn; /* line number in the real file */
|
||||
unsigned char c;
|
||||
|
||||
memset(&ln, 0, sizeof(struct buf));
|
||||
memset(&ln, 0, sizeof(ln));
|
||||
|
||||
lnn = curp->line;
|
||||
pos = 0;
|
||||
|
||||
for (i = 0; i < (int)blk.sz; ) {
|
||||
while (i < blk.sz) {
|
||||
if (0 == pos && '\0' == blk.buf[i])
|
||||
break;
|
||||
|
||||
if (start) {
|
||||
curp->line = lnn;
|
||||
curp->reparse_count = 0;
|
||||
|
||||
if (lnn < 3 &&
|
||||
curp->filenc & MPARSE_UTF8 &&
|
||||
curp->filenc & MPARSE_LATIN1)
|
||||
curp->filenc = preconv_cue(&blk, i);
|
||||
}
|
||||
|
||||
while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {
|
||||
while (i < blk.sz && (start || blk.buf[i] != '\0')) {
|
||||
|
||||
/*
|
||||
* When finding an unescaped newline character,
|
||||
@ -325,7 +347,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
* Skip a preceding carriage return, if any.
|
||||
*/
|
||||
|
||||
if ('\r' == blk.buf[i] && i + 1 < (int)blk.sz &&
|
||||
if ('\r' == blk.buf[i] && i + 1 < blk.sz &&
|
||||
'\n' == blk.buf[i + 1])
|
||||
++i;
|
||||
if ('\n' == blk.buf[i]) {
|
||||
@ -335,27 +357,35 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we have space for at least
|
||||
* one backslash and one other character
|
||||
* and the trailing NUL byte.
|
||||
* Make sure we have space for the worst
|
||||
* case of 11 bytes: "\\[u10ffff]\0"
|
||||
*/
|
||||
|
||||
if (pos + 2 >= (int)ln.sz)
|
||||
if (pos + 11 > ln.sz)
|
||||
resize_buf(&ln, 256);
|
||||
|
||||
/*
|
||||
* Warn about bogus characters. If you're using
|
||||
* non-ASCII encoding, you're screwing your
|
||||
* readers. Since I'd rather this not happen,
|
||||
* I'll be helpful and replace these characters
|
||||
* with "?", so we don't display gibberish.
|
||||
* Note to manual writers: use special characters.
|
||||
* Encode 8-bit input.
|
||||
*/
|
||||
|
||||
c = (unsigned char) blk.buf[i];
|
||||
c = blk.buf[i];
|
||||
if (c & 0x80) {
|
||||
if ( ! (curp->filenc && preconv_encode(
|
||||
&blk, &i, &ln, &pos, &curp->filenc))) {
|
||||
mandoc_vmsg(MANDOCERR_BADCHAR,
|
||||
curp, curp->line, pos,
|
||||
"0x%x", c);
|
||||
ln.buf[pos++] = '?';
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! (isascii(c) &&
|
||||
(isgraph(c) || isblank(c)))) {
|
||||
/*
|
||||
* Exclude control characters.
|
||||
*/
|
||||
|
||||
if (c == 0x7f || (c < 0x20 && c != 0x09)) {
|
||||
mandoc_vmsg(MANDOCERR_BADCHAR, curp,
|
||||
curp->line, pos, "0x%x", c);
|
||||
i++;
|
||||
@ -365,7 +395,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
|
||||
/* Trailing backslash = a plain char. */
|
||||
|
||||
if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
|
||||
if (blk.buf[i] != '\\' || i + 1 == blk.sz) {
|
||||
ln.buf[pos++] = blk.buf[i++];
|
||||
continue;
|
||||
}
|
||||
@ -377,7 +407,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
* skip that one as well.
|
||||
*/
|
||||
|
||||
if ('\r' == blk.buf[i + 1] && i + 2 < (int)blk.sz &&
|
||||
if ('\r' == blk.buf[i + 1] && i + 2 < blk.sz &&
|
||||
'\n' == blk.buf[i + 2])
|
||||
++i;
|
||||
if ('\n' == blk.buf[i + 1]) {
|
||||
@ -389,7 +419,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
if ('"' == blk.buf[i + 1] || '#' == blk.buf[i + 1]) {
|
||||
i += 2;
|
||||
/* Comment, skip to end of line */
|
||||
for (; i < (int)blk.sz; ++i) {
|
||||
for (; i < blk.sz; ++i) {
|
||||
if ('\n' == blk.buf[i]) {
|
||||
++i;
|
||||
++lnn;
|
||||
@ -426,7 +456,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
ln.buf[pos++] = blk.buf[i++];
|
||||
}
|
||||
|
||||
if (pos >= (int)ln.sz)
|
||||
if (pos >= ln.sz)
|
||||
resize_buf(&ln, 256);
|
||||
|
||||
ln.buf[pos] = '\0';
|
||||
@ -463,20 +493,19 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
[curp->secondary->sz] = '\0';
|
||||
}
|
||||
rerun:
|
||||
rr = roff_parseln(curp->roff, curp->line,
|
||||
&ln.buf, &ln.sz, of, &of);
|
||||
rr = roff_parseln(curp->roff, curp->line, &ln, &of);
|
||||
|
||||
switch (rr) {
|
||||
case ROFF_REPARSE:
|
||||
if (REPARSE_LIMIT >= ++curp->reparse_count)
|
||||
mparse_buf_r(curp, ln, 0);
|
||||
mparse_buf_r(curp, ln, of, 0);
|
||||
else
|
||||
mandoc_msg(MANDOCERR_ROFFLOOP, curp,
|
||||
curp->line, pos, NULL);
|
||||
pos = 0;
|
||||
continue;
|
||||
case ROFF_APPEND:
|
||||
pos = (int)strlen(ln.buf);
|
||||
pos = strlen(ln.buf);
|
||||
continue;
|
||||
case ROFF_RERUN:
|
||||
goto rerun;
|
||||
@ -487,8 +516,8 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
assert(MANDOCLEVEL_FATAL <= curp->file_status);
|
||||
break;
|
||||
case ROFF_SO:
|
||||
if (0 == (MPARSE_SO & curp->options) &&
|
||||
(i >= (int)blk.sz || '\0' == blk.buf[i])) {
|
||||
if ( ! (curp->options & MPARSE_SO) &&
|
||||
(i >= blk.sz || blk.buf[i] == '\0')) {
|
||||
curp->sodest = mandoc_strdup(ln.buf + of);
|
||||
free(ln.buf);
|
||||
return;
|
||||
@ -529,12 +558,10 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
*/
|
||||
|
||||
if ( ! (curp->man || curp->mdoc))
|
||||
pset(ln.buf + of, pos - of, curp);
|
||||
choose_parser(curp);
|
||||
|
||||
/*
|
||||
* Lastly, push down into the parsers themselves. One
|
||||
* of these will have already been set in the pset()
|
||||
* routine.
|
||||
* Lastly, push down into the parsers themselves.
|
||||
* If libroff returns ROFF_TBL, then add it to the
|
||||
* currently open parse. Since we only get here if
|
||||
* there does exist data (see tbl_data.c), we're
|
||||
@ -542,34 +569,21 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
|
||||
* Do the same for ROFF_EQN.
|
||||
*/
|
||||
|
||||
rc = -1;
|
||||
|
||||
if (ROFF_TBL == rr)
|
||||
while (NULL != (span = roff_span(curp->roff))) {
|
||||
rc = curp->man ?
|
||||
man_addspan(curp->man, span) :
|
||||
mdoc_addspan(curp->mdoc, span);
|
||||
if (0 == rc)
|
||||
break;
|
||||
}
|
||||
else if (ROFF_EQN == rr)
|
||||
rc = curp->mdoc ?
|
||||
mdoc_addeqn(curp->mdoc,
|
||||
roff_eqn(curp->roff)) :
|
||||
man_addeqn(curp->man,
|
||||
roff_eqn(curp->roff));
|
||||
else if (curp->man || curp->mdoc)
|
||||
rc = curp->man ?
|
||||
man_parseln(curp->man,
|
||||
curp->line, ln.buf, of) :
|
||||
mdoc_parseln(curp->mdoc,
|
||||
curp->line, ln.buf, of);
|
||||
|
||||
if (0 == rc) {
|
||||
assert(MANDOCLEVEL_FATAL <= curp->file_status);
|
||||
break;
|
||||
} else if (2 == rc)
|
||||
break;
|
||||
if (rr == ROFF_TBL) {
|
||||
while ((span = roff_span(curp->roff)) != NULL)
|
||||
if (curp->man == NULL)
|
||||
mdoc_addspan(curp->mdoc, span);
|
||||
else
|
||||
man_addspan(curp->man, span);
|
||||
} else if (rr == ROFF_EQN) {
|
||||
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)
|
||||
break;
|
||||
|
||||
/* Temporary buffers typically are not full. */
|
||||
|
||||
@ -591,7 +605,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
|
||||
size_t off;
|
||||
ssize_t ssz;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#if HAVE_MMAP
|
||||
struct stat st;
|
||||
if (-1 == fstat(fd, &st)) {
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
@ -702,7 +716,9 @@ mparse_end(struct mparse *curp)
|
||||
static void
|
||||
mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
|
||||
{
|
||||
struct buf *svprimary;
|
||||
const char *svfile;
|
||||
size_t offset;
|
||||
static int recursion_depth;
|
||||
|
||||
if (64 < recursion_depth) {
|
||||
@ -713,14 +729,27 @@ mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
|
||||
/* Line number is per-file. */
|
||||
svfile = curp->file;
|
||||
curp->file = file;
|
||||
svprimary = curp->primary;
|
||||
curp->primary = &blk;
|
||||
curp->line = 1;
|
||||
recursion_depth++;
|
||||
|
||||
mparse_buf_r(curp, blk, 1);
|
||||
/* Skip an UTF-8 byte order mark. */
|
||||
if (curp->filenc & MPARSE_UTF8 && blk.sz > 2 &&
|
||||
(unsigned char)blk.buf[0] == 0xef &&
|
||||
(unsigned char)blk.buf[1] == 0xbb &&
|
||||
(unsigned char)blk.buf[2] == 0xbf) {
|
||||
offset = 3;
|
||||
curp->filenc &= ~MPARSE_LATIN1;
|
||||
} else
|
||||
offset = 0;
|
||||
|
||||
mparse_buf_r(curp, blk, offset, 1);
|
||||
|
||||
if (0 == --recursion_depth && MANDOCLEVEL_FATAL > curp->file_status)
|
||||
mparse_end(curp);
|
||||
|
||||
curp->primary = svprimary;
|
||||
curp->file = svfile;
|
||||
}
|
||||
|
||||
@ -737,49 +766,159 @@ mparse_readmem(struct mparse *curp, const void *buf, size_t len,
|
||||
return(curp->file_status);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a file descriptor is given, use it and assume it points
|
||||
* to the named file. Otherwise, open the named file.
|
||||
* Read the whole file into memory and call the parsers.
|
||||
* Called recursively when an .so request is encountered.
|
||||
*/
|
||||
enum mandoclevel
|
||||
mparse_readfd(struct mparse *curp, int fd, const char *file)
|
||||
{
|
||||
struct buf blk;
|
||||
int with_mmap;
|
||||
int save_filenc;
|
||||
pid_t save_child;
|
||||
|
||||
if (-1 == fd && -1 == (fd = open(file, O_RDONLY, 0))) {
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_SYSOPEN,
|
||||
curp->file_status,
|
||||
file, 0, 0, strerror(errno));
|
||||
save_child = curp->child;
|
||||
if (fd != -1)
|
||||
curp->child = 0;
|
||||
else if (mparse_open(curp, &fd, file) >= MANDOCLEVEL_SYSERR)
|
||||
goto out;
|
||||
|
||||
if (read_whole_file(curp, file, fd, &blk, &with_mmap)) {
|
||||
save_filenc = curp->filenc;
|
||||
curp->filenc = curp->options &
|
||||
(MPARSE_UTF8 | MPARSE_LATIN1);
|
||||
mparse_parse_buffer(curp, blk, file);
|
||||
curp->filenc = save_filenc;
|
||||
#if HAVE_MMAP
|
||||
if (with_mmap)
|
||||
munmap(blk.buf, blk.sz);
|
||||
else
|
||||
#endif
|
||||
free(blk.buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Run for each opened file; may be called more than once for
|
||||
* each full parse sequence if the opened file is nested (i.e.,
|
||||
* from `so'). Simply sucks in the whole file and moves into
|
||||
* the parse phase for the file.
|
||||
*/
|
||||
|
||||
if ( ! read_whole_file(curp, file, fd, &blk, &with_mmap))
|
||||
goto out;
|
||||
|
||||
mparse_parse_buffer(curp, blk, file);
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
if (with_mmap)
|
||||
munmap(blk.buf, blk.sz);
|
||||
else
|
||||
#endif
|
||||
free(blk.buf);
|
||||
|
||||
if (STDIN_FILENO != fd && -1 == close(fd))
|
||||
if (fd != STDIN_FILENO && close(fd) == -1)
|
||||
perror(file);
|
||||
|
||||
mparse_wait(curp);
|
||||
out:
|
||||
curp->child = save_child;
|
||||
return(curp->file_status);
|
||||
}
|
||||
|
||||
enum mandoclevel
|
||||
mparse_open(struct mparse *curp, int *fd, const char *file)
|
||||
{
|
||||
int pfd[2];
|
||||
int save_errno;
|
||||
char *cp;
|
||||
enum mandocerr err;
|
||||
|
||||
pfd[1] = -1;
|
||||
curp->file = file;
|
||||
|
||||
/* Unless zipped, try to just open the file. */
|
||||
|
||||
if ((cp = strrchr(file, '.')) == NULL ||
|
||||
strcmp(cp + 1, "gz")) {
|
||||
curp->child = 0;
|
||||
if ((*fd = open(file, O_RDONLY)) != -1)
|
||||
return(MANDOCLEVEL_OK);
|
||||
|
||||
/* Open failed; try to append ".gz". */
|
||||
|
||||
mandoc_asprintf(&cp, "%s.gz", file);
|
||||
file = cp;
|
||||
} 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;
|
||||
err = MANDOCERR_SYSOPEN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Run gunzip(1). */
|
||||
|
||||
if (pipe(pfd) == -1) {
|
||||
err = MANDOCERR_SYSPIPE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (curp->child = fork()) {
|
||||
case -1:
|
||||
err = MANDOCERR_SYSFORK;
|
||||
close(pfd[0]);
|
||||
close(pfd[1]);
|
||||
pfd[1] = -1;
|
||||
break;
|
||||
case 0:
|
||||
close(pfd[0]);
|
||||
if (dup2(pfd[1], STDOUT_FILENO) == -1) {
|
||||
err = MANDOCERR_SYSDUP;
|
||||
break;
|
||||
}
|
||||
execlp("gunzip", "gunzip", "-c", file, NULL);
|
||||
err = MANDOCERR_SYSEXEC;
|
||||
break;
|
||||
default:
|
||||
close(pfd[1]);
|
||||
*fd = pfd[0];
|
||||
return(MANDOCLEVEL_OK);
|
||||
}
|
||||
|
||||
out:
|
||||
free(cp);
|
||||
*fd = -1;
|
||||
curp->child = 0;
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(err, curp->file_status, curp->file,
|
||||
0, 0, strerror(errno));
|
||||
if (pfd[1] != -1)
|
||||
exit(1);
|
||||
return(curp->file_status);
|
||||
}
|
||||
|
||||
enum mandoclevel
|
||||
mparse_wait(struct mparse *curp)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (curp->child == 0)
|
||||
return(MANDOCLEVEL_OK);
|
||||
|
||||
if (waitpid(curp->child, &status, 0) == -1) {
|
||||
mandoc_msg(MANDOCERR_SYSWAIT, curp, 0, 0,
|
||||
strerror(errno));
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
return(curp->file_status);
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
mandoc_vmsg(MANDOCERR_SYSSIG, curp, 0, 0,
|
||||
"%d", WTERMSIG(status));
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
return(curp->file_status);
|
||||
}
|
||||
if (WEXITSTATUS(status)) {
|
||||
mandoc_vmsg(MANDOCERR_SYSEXIT, curp, 0, 0,
|
||||
"%d", WEXITSTATUS(status));
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
return(curp->file_status);
|
||||
}
|
||||
return(MANDOCLEVEL_OK);
|
||||
}
|
||||
|
||||
struct mparse *
|
||||
mparse_alloc(int options, enum mandoclevel wlevel,
|
||||
mandocmsg mmsg, const char *defos)
|
||||
mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
|
||||
const struct mchars *mchars, const char *defos)
|
||||
{
|
||||
struct mparse *curp;
|
||||
|
||||
@ -792,7 +931,8 @@ mparse_alloc(int options, enum mandoclevel wlevel,
|
||||
curp->mmsg = mmsg;
|
||||
curp->defos = defos;
|
||||
|
||||
curp->roff = roff_alloc(curp, options);
|
||||
curp->mchars = mchars;
|
||||
curp->roff = roff_alloc(curp, curp->mchars, options);
|
||||
if (curp->options & MPARSE_MDOC)
|
||||
curp->pmdoc = mdoc_alloc(
|
||||
curp->roff, curp, curp->defos,
|
||||
|
27
roff.7
27
roff.7
@ -1,4 +1,4 @@
|
||||
.\" $Id: roff.7,v 1.55 2014/07/07 11:35:06 schwarze Exp $
|
||||
.\" $Id: roff.7,v 1.59 2014/11/19 01:20:25 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2010, 2011, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: July 7 2014 $
|
||||
.Dd $Mdocdate: November 19 2014 $
|
||||
.Dt ROFF 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -239,8 +239,9 @@ pica (~1/6 inch)
|
||||
.It p
|
||||
point (~1/72 inch)
|
||||
.It f
|
||||
synonym for
|
||||
scale
|
||||
.Sq u
|
||||
by 65536
|
||||
.It v
|
||||
default vertical span
|
||||
.It m
|
||||
@ -254,7 +255,7 @@ width of rendered
|
||||
.Pq en
|
||||
character
|
||||
.It u
|
||||
default horizontal span
|
||||
default horizontal span for the terminal
|
||||
.It M
|
||||
mini-em (~1/100 em)
|
||||
.El
|
||||
@ -262,7 +263,6 @@ mini-em (~1/100 em)
|
||||
Using anything other than
|
||||
.Sq m ,
|
||||
.Sq n ,
|
||||
.Sq u ,
|
||||
or
|
||||
.Sq v
|
||||
is necessarily non-portable across output media.
|
||||
@ -747,16 +747,18 @@ If the first character of COND is
|
||||
.Pq even page ,
|
||||
.Sq r
|
||||
.Pq register accessed ,
|
||||
or
|
||||
.Sq t
|
||||
.Pq troff mode ,
|
||||
or
|
||||
.Sq v
|
||||
.Pq vroff mode ,
|
||||
COND evaluates to false.
|
||||
.It
|
||||
If COND starts with a parenthesis or with an optionally signed
|
||||
integer number, it is evaluated according to the rules of
|
||||
.Sx Numerical expressions
|
||||
explained below.
|
||||
It evaluates to true if the the result is positive,
|
||||
It evaluates to true if the result is positive,
|
||||
or to false if the result is zero or negative.
|
||||
.It
|
||||
Otherwise, the first character of COND is regarded as a delimiter
|
||||
@ -935,6 +937,11 @@ Turn on no-space mode.
|
||||
This line-scoped request is intended to take no arguments.
|
||||
Currently, it is ignored including its arguments,
|
||||
and the number of arguments is not checked.
|
||||
.Ss \&pl
|
||||
Change page length.
|
||||
This line-scoped request is intended to take one height argument.
|
||||
Currently, it is ignored including its arguments,
|
||||
and the number of arguments is not checked.
|
||||
.Ss \&ps
|
||||
Change point size.
|
||||
This line-scoped request is intended to take one numerical argument.
|
||||
@ -1348,6 +1355,12 @@ refers to groff version 1.15.
|
||||
.Pp
|
||||
.Bl -dash -compact
|
||||
.It
|
||||
The
|
||||
.Sq u
|
||||
scaling unit is the default terminal unit.
|
||||
In traditional troff systems, this unit would change depending on the
|
||||
output media.
|
||||
.It
|
||||
In mandoc, the
|
||||
.Sx \&EQ ,
|
||||
.Sx \&TE ,
|
||||
|
6
st.c
6
st.c
@ -1,4 +1,4 @@
|
||||
/* $Id: st.c,v 1.10 2014/03/23 11:25:26 schwarze Exp $ */
|
||||
/* $Id: st.c,v 1.11 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,9 +14,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
9
st.in
9
st.in
@ -1,4 +1,4 @@
|
||||
/* $Id: st.in,v 1.24 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: st.in,v 1.26 2014/11/16 20:46:21 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -42,13 +42,9 @@ LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(lqPOSIX.1c\\(rq)")
|
||||
LINE("-p1003.1d-99", "IEEE Std 1003.1d-1999 (\\(lqPOSIX.1d\\(rq)")
|
||||
LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(lqPOSIX.1g\\(rq)")
|
||||
LINE("-p1003.1i-95", "IEEE Std 1003.1i-1995 (\\(lqPOSIX.1i\\(rq)")
|
||||
LINE("-p1003.1j-2000", "IEEE Std 1003.1j-2000 (\\(lqPOSIX.1j\\(rq)")
|
||||
LINE("-p1003.1q-2000", "IEEE Std 1003.1q-2000 (\\(lqPOSIX.1q\\(rq)")
|
||||
LINE("-p1003.2", "IEEE Std 1003.2 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1003.2-92", "IEEE Std 1003.2-1992 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1003.2a-92", "IEEE Std 1003.2a-1992 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1387.2", "IEEE Std 1387.2 (\\(lqPOSIX.7.2\\(rq)")
|
||||
LINE("-p1387.2-95", "IEEE Std 1387.2-1995 (\\(lqPOSIX.7.2\\(rq)")
|
||||
LINE("-isoC", "ISO/IEC 9899:1990 (\\(lqISO\\~C90\\(rq)")
|
||||
LINE("-isoC-90", "ISO/IEC 9899:1990 (\\(lqISO\\~C90\\(rq)")
|
||||
LINE("-isoC-amd1", "ISO/IEC 9899/AMD1:1995 (\\(lqISO\\~C90, Amendment 1\\(rq)")
|
||||
@ -76,8 +72,9 @@ LINE("-xsh4.2", "X/Open System Interfaces and Headers Issue\\~4, Version\\~2 (\
|
||||
LINE("-xsh5", "X/Open System Interfaces and Headers Issue\\~5 (\\(lqXSH5\\(rq)")
|
||||
LINE("-xns5", "X/Open Networking Services Issue\\~5 (\\(lqXNS5\\(rq)")
|
||||
LINE("-xns5.2", "X/Open Networking Services Issue\\~5.2 (\\(lqXNS5.2\\(rq)")
|
||||
LINE("-xns5.2d2.0", "X/Open Networking Services Issue\\~5.2 Draft\\~2.0 (\\(lqXNS5.2D2.0\\(rq)")
|
||||
LINE("-xcurses4.2", "X/Open Curses Issue\\~4, Version\\~2 (\\(lqXCURSES4.2\\(rq)")
|
||||
LINE("-susv1", "Version\\~1 of the Single UNIX Specification (\\(lqSUSv1\\(rq)")
|
||||
LINE("-susv2", "Version\\~2 of the Single UNIX Specification (\\(lqSUSv2\\(rq)")
|
||||
LINE("-susv3", "Version\\~3 of the Single UNIX Specification (\\(lqSUSv3\\(rq)")
|
||||
LINE("-susv4", "Version\\~4 of the Single UNIX Specification (\\(lqSUSv4\\(rq)")
|
||||
LINE("-svid4", "System\\~V Interface Definition, Fourth Edition (\\(lqSVID4\\(rq)")
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: style.css,v 1.25 2011/08/26 09:03:17 kristaps Exp $ */
|
||||
/* $Id: style.css,v 1.30 2014/09/27 11:16:24 kristaps Exp $ */
|
||||
|
||||
/*
|
||||
* This is an example style-sheet provided for mandoc(1) and the -Thtml
|
||||
@ -20,16 +20,17 @@ blockquote { margin-left: 5ex; margin-top: 0ex; margin-bottom: 0ex; } /* D1. */
|
||||
div.section { margin-bottom: 2ex; margin-left: 5ex; } /* Sections (Sh, SH). */
|
||||
div.subsection { } /* Sub-sections (Ss, SS). */
|
||||
table.synopsis { } /* SYNOPSIS section table. */
|
||||
div.spacer { margin: 1em 0; }
|
||||
|
||||
/* Preamble structure. */
|
||||
|
||||
table.foot { font-size: smaller; margin-top: 1em; border-top: 1px dotted #dddddd; } /* Document footer. */
|
||||
td.foot-date { width: 50%; } /* Document footer: date. */
|
||||
td.foot-os { width: 50%; text-align: right; } /* Document footer: OS/source. */
|
||||
td.foot-os { width: 50%; } /* Document footer: OS/source. */
|
||||
table.head { font-size: smaller; margin-bottom: 1em; border-bottom: 1px dotted #dddddd; } /* Document header. */
|
||||
td.head-ltitle { width: 10%; } /* Document header: left-title. */
|
||||
td.head-vol { width: 80%; text-align: center; } /* Document header: volume. */
|
||||
td.head-rtitle { width: 10%; text-align: right; } /* Document header: right-title. */
|
||||
td.head-vol { width: 80%; } /* Document header: volume. */
|
||||
td.head-rtitle { width: 10%; } /* Document header: right-title. */
|
||||
|
||||
/* General font modes. */
|
||||
|
||||
|
62
tbl.7
62
tbl.7
@ -1,6 +1,7 @@
|
||||
.\" $Id: tbl.7,v 1.18 2013/09/16 22:39:19 schwarze Exp $
|
||||
.\" $Id: tbl.7,v 1.21 2014/11/26 17:51:55 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 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
|
||||
@ -14,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: September 16 2013 $
|
||||
.Dd $Mdocdate: November 26 2014 $
|
||||
.Dt TBL 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -134,6 +135,7 @@ in the case of
|
||||
.Ss Options
|
||||
The first line of a table consists of space-separated option keys and
|
||||
modifiers terminated by a semicolon.
|
||||
For GNU compatibility, option keys can also be separated by commas.
|
||||
If the first line does not have a terminating semicolon, it is assumed
|
||||
that no options are specified and instead a
|
||||
.Sx Layout
|
||||
@ -195,7 +197,7 @@ Each layout line corresponds to a line of data; the last layout line
|
||||
applies to all remaining data lines.
|
||||
Layout lines may also be separated by a comma.
|
||||
Each layout cell consists of one of the following case-insensitive keys:
|
||||
.Bl -tag -width Ds
|
||||
.Bl -tag -width 2n
|
||||
.It Cm c
|
||||
Centre a literal string within its column.
|
||||
.It Cm r
|
||||
@ -244,35 +246,45 @@ Keys may be followed by a set of modifiers.
|
||||
A modifier is either a modifier key or a natural number for specifying
|
||||
the minimum width of a column.
|
||||
The following case-insensitive modifier keys are available:
|
||||
.Cm z ,
|
||||
.Cm u ,
|
||||
.Cm e ,
|
||||
.Cm t ,
|
||||
.Bl -tag -width 2n
|
||||
.It Cm b
|
||||
Use a bold font for the contents of this column.
|
||||
.It Cm e
|
||||
Make this column wider to match the maximum width
|
||||
of any other column also having the
|
||||
.Cm e
|
||||
modifier.
|
||||
.It Cm f
|
||||
The next character selects the font to use for this column.
|
||||
See the
|
||||
.Xr roff 7
|
||||
manual for supported one-character font names.
|
||||
.It Cm i
|
||||
Use an italic font for the contents of this column.
|
||||
.It Cm x
|
||||
After determining the width of all other columns, distribute the
|
||||
rest of the line length among all columns having the
|
||||
.Cm x
|
||||
modifier.
|
||||
.It Cm z
|
||||
Do not use this cell for determining the width of this column.
|
||||
.El
|
||||
.Pp
|
||||
The modifiers
|
||||
.Cm d ,
|
||||
.Cm b ,
|
||||
.Cm i ,
|
||||
.Cm r ,
|
||||
.Cm t ,
|
||||
.Cm u ,
|
||||
and
|
||||
.Cm f
|
||||
.Po
|
||||
followed by
|
||||
.Cm b ,
|
||||
.Cm i ,
|
||||
.Cm r ,
|
||||
.Cm 3 ,
|
||||
.Cm 2 ,
|
||||
or
|
||||
.Cm 1
|
||||
.Pc .
|
||||
All of these are ignored by
|
||||
.Cm w
|
||||
are ignored by
|
||||
.Xr mandoc 1 .
|
||||
.Pp
|
||||
For example, the following layout specifies a centre-justified column of
|
||||
minimum width 10, followed by vertical bar, followed by a left-justified
|
||||
column of minimum width 10, another vertical bar, then a column
|
||||
justified about the decimal point in numbers:
|
||||
column of minimum width 10, another vertical bar, then a column using
|
||||
bold font justified about the decimal point in numbers:
|
||||
.Pp
|
||||
.Dl c10 | l10 | n
|
||||
.Dl c10 | l10 | nfB
|
||||
.Ss Data
|
||||
The data section follows the last layout row.
|
||||
By default, cells in a data section are delimited by a tab.
|
||||
|
6
tbl.c
6
tbl.c
@ -1,4 +1,4 @@
|
||||
/* $Id: tbl.c,v 1.29 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: tbl.c,v 1.30 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: tbl_data.c,v 1.31 2014/04/23 16:08:33 schwarze Exp $ */
|
||||
/* $Id: tbl_data.c,v 1.32 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: tbl_html.c,v 1.11 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: tbl_html.c,v 1.13 2014/10/14 02:16:06 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,9 +14,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -57,7 +57,7 @@ html_tblopen(struct html *h, const struct tbl_span *sp)
|
||||
if (TBL_SPAN_FIRST & sp->flags) {
|
||||
h->tbl.len = html_tbl_len;
|
||||
h->tbl.slen = html_tbl_strlen;
|
||||
tblcalc(&h->tbl, sp);
|
||||
tblcalc(&h->tbl, sp, 0);
|
||||
}
|
||||
|
||||
assert(NULL == h->tblt);
|
||||
|
111
tbl_layout.c
111
tbl_layout.c
@ -1,4 +1,4 @@
|
||||
/* $Id: tbl_layout.c,v 1.26 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: tbl_layout.c,v 1.30 2014/11/25 21:41:47 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
@ -59,7 +59,6 @@ static int mods(struct tbl_node *, struct tbl_cell *,
|
||||
int, const char *, int *);
|
||||
static int cell(struct tbl_node *, struct tbl_row *,
|
||||
int, const char *, int *);
|
||||
static void row(struct tbl_node *, int, const char *, int *);
|
||||
static struct tbl_cell *cell_alloc(struct tbl_node *, struct tbl_row *,
|
||||
enum tbl_cellt, int vert);
|
||||
|
||||
@ -168,6 +167,9 @@ mods(struct tbl_node *tbl, struct tbl_cell *cp,
|
||||
goto mod;
|
||||
case 'w': /* XXX for now, ignore minimal column width */
|
||||
goto mod;
|
||||
case 'x':
|
||||
cp->flags |= TBL_CELL_WMAX;
|
||||
goto mod;
|
||||
case 'f':
|
||||
break;
|
||||
case 'r':
|
||||
@ -201,6 +203,11 @@ mods(struct tbl_node *tbl, struct tbl_cell *cp,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isalnum((unsigned char)p[*pos - 1])) {
|
||||
mandoc_vmsg(MANDOCERR_FT_BAD, tbl->parse,
|
||||
ln, *pos - 1, "TS f%c", p[*pos - 1]);
|
||||
goto mod;
|
||||
}
|
||||
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
|
||||
ln, *pos - 1, NULL);
|
||||
@ -292,68 +299,54 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
|
||||
return(mods(tbl, cell_alloc(tbl, rp, c, vert), ln, p, pos));
|
||||
}
|
||||
|
||||
static void
|
||||
row(struct tbl_node *tbl, int ln, const char *p, int *pos)
|
||||
{
|
||||
struct tbl_row *rp;
|
||||
|
||||
row: /*
|
||||
* EBNF describing this section:
|
||||
*
|
||||
* row ::= row_list [:space:]* [.]?[\n]
|
||||
* row_list ::= [:space:]* row_elem row_tail
|
||||
* row_tail ::= [:space:]*[,] row_list |
|
||||
* epsilon
|
||||
* row_elem ::= [\t\ ]*[:alpha:]+
|
||||
*/
|
||||
|
||||
rp = mandoc_calloc(1, sizeof(struct tbl_row));
|
||||
if (tbl->last_row)
|
||||
tbl->last_row->next = rp;
|
||||
else
|
||||
tbl->first_row = rp;
|
||||
tbl->last_row = rp;
|
||||
|
||||
cell:
|
||||
while (isspace((unsigned char)p[*pos]))
|
||||
(*pos)++;
|
||||
|
||||
/* Safely exit layout context. */
|
||||
|
||||
if ('.' == p[*pos]) {
|
||||
tbl->part = TBL_PART_DATA;
|
||||
if (NULL == tbl->first_row)
|
||||
mandoc_msg(MANDOCERR_TBLNOLAYOUT,
|
||||
tbl->parse, ln, *pos, NULL);
|
||||
(*pos)++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* End (and possibly restart) a row. */
|
||||
|
||||
if (',' == p[*pos]) {
|
||||
(*pos)++;
|
||||
goto row;
|
||||
} else if ('\0' == p[*pos])
|
||||
return;
|
||||
|
||||
if ( ! cell(tbl, rp, ln, p, pos))
|
||||
return;
|
||||
|
||||
goto cell;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int
|
||||
tbl_layout(struct tbl_node *tbl, int ln, const char *p)
|
||||
{
|
||||
struct tbl_row *rp;
|
||||
int pos;
|
||||
|
||||
pos = 0;
|
||||
row(tbl, ln, p, &pos);
|
||||
rp = NULL;
|
||||
|
||||
/* Always succeed. */
|
||||
return(1);
|
||||
for (;;) {
|
||||
/* Skip whitespace before and after each cell. */
|
||||
|
||||
while (isspace((unsigned char)p[pos]))
|
||||
pos++;
|
||||
|
||||
switch (p[pos]) {
|
||||
case ',': /* Next row on this input line. */
|
||||
pos++;
|
||||
rp = NULL;
|
||||
continue;
|
||||
case '\0': /* Next row on next input line. */
|
||||
return(1);
|
||||
case '.': /* End of layout. */
|
||||
pos++;
|
||||
tbl->part = TBL_PART_DATA;
|
||||
if (tbl->first_row != NULL)
|
||||
return(1);
|
||||
mandoc_msg(MANDOCERR_TBLNOLAYOUT,
|
||||
tbl->parse, ln, pos, NULL);
|
||||
rp = mandoc_calloc(1, sizeof(*rp));
|
||||
cell_alloc(tbl, rp, TBL_CELL_LEFT, 0);
|
||||
tbl->first_row = tbl->last_row = rp;
|
||||
return(1);
|
||||
default: /* Cell. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (rp == NULL) { /* First cell on this line. */
|
||||
rp = mandoc_calloc(1, sizeof(*rp));
|
||||
if (tbl->last_row)
|
||||
tbl->last_row->next = rp;
|
||||
else
|
||||
tbl->first_row = rp;
|
||||
tbl->last_row = rp;
|
||||
}
|
||||
if ( ! cell(tbl, rp, ln, p, &pos))
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
static struct tbl_cell *
|
||||
|
10
tbl_opts.c
10
tbl_opts.c
@ -1,4 +1,4 @@
|
||||
/* $Id: tbl_opts.c,v 1.13 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: tbl_opts.c,v 1.15 2014/11/26 17:51:55 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -14,9 +14,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
@ -182,7 +182,7 @@ opt(struct tbl_node *tbl, int ln, const char *p, int *pos)
|
||||
*
|
||||
* options ::= option_list [:space:]* [;][\n]
|
||||
* option_list ::= option option_tail
|
||||
* option_tail ::= [:space:]+ option_list |
|
||||
* option_tail ::= [,:space:]+ option_list |
|
||||
* ::= epsilon
|
||||
* option ::= [:alpha:]+ args
|
||||
* args ::= [:space:]* [(] [:alpha:]+ [)]
|
||||
@ -213,7 +213,7 @@ opt(struct tbl_node *tbl, int ln, const char *p, int *pos)
|
||||
|
||||
buf[i] = '\0';
|
||||
|
||||
while (isspace((unsigned char)p[*pos]))
|
||||
while (isspace((unsigned char)p[*pos]) || p[*pos] == ',')
|
||||
(*pos)++;
|
||||
|
||||
/*
|
||||
|
30
tbl_term.c
30
tbl_term.c
@ -1,4 +1,4 @@
|
||||
/* $Id: tbl_term.c,v 1.27 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: tbl_term.c,v 1.31 2014/10/14 18:18:05 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,9 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@ -43,6 +43,7 @@ static void tbl_number(struct termp *, const struct tbl_opts *,
|
||||
const struct roffcol *);
|
||||
static void tbl_hrule(struct termp *, const struct tbl_span *);
|
||||
static void tbl_vrule(struct termp *, const struct tbl_head *);
|
||||
static void tbl_word(struct termp *, const struct tbl_dat *);
|
||||
|
||||
|
||||
static size_t
|
||||
@ -90,7 +91,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
|
||||
tp->tbl.slen = term_tbl_strlen;
|
||||
tp->tbl.arg = tp;
|
||||
|
||||
tblcalc(&tp->tbl, sp);
|
||||
tblcalc(&tp->tbl, sp, rmargin - tp->offset);
|
||||
}
|
||||
|
||||
/* Horizontal frame at the start of boxed tables. */
|
||||
@ -106,7 +107,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
|
||||
/* Vertical frame at the start of each row. */
|
||||
|
||||
if ((TBL_OPT_BOX | TBL_OPT_DBOX) & sp->opts->opts ||
|
||||
sp->head->vert)
|
||||
(sp->head != NULL && sp->head->vert))
|
||||
term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
|
||||
TBL_SPAN_DHORIZ == sp->pos ? "+" : "|");
|
||||
|
||||
@ -378,7 +379,7 @@ tbl_literal(struct termp *tp, const struct tbl_dat *dp,
|
||||
}
|
||||
|
||||
tbl_char(tp, ASCII_NBRSP, padl);
|
||||
term_word(tp, dp->string);
|
||||
tbl_word(tp, dp);
|
||||
tbl_char(tp, ASCII_NBRSP, padr);
|
||||
}
|
||||
|
||||
@ -419,8 +420,23 @@ tbl_number(struct termp *tp, const struct tbl_opts *opts,
|
||||
padl = col->decimal - d;
|
||||
|
||||
tbl_char(tp, ASCII_NBRSP, padl);
|
||||
term_word(tp, dp->string);
|
||||
tbl_word(tp, dp);
|
||||
if (col->width > sz + padl)
|
||||
tbl_char(tp, ASCII_NBRSP, col->width - sz - padl);
|
||||
}
|
||||
|
||||
static void
|
||||
tbl_word(struct termp *tp, const struct tbl_dat *dp)
|
||||
{
|
||||
const void *prev_font;
|
||||
|
||||
prev_font = term_fontq(tp);
|
||||
if (dp->layout->flags & TBL_CELL_BOLD)
|
||||
term_fontpush(tp, TERMFONT_BOLD);
|
||||
else if (dp->layout->flags & TBL_CELL_ITALIC)
|
||||
term_fontpush(tp, TERMFONT_UNDER);
|
||||
|
||||
term_word(tp, dp->string);
|
||||
|
||||
term_fontpopq(tp, prev_font);
|
||||
}
|
||||
|
190
term.c
190
term.c
@ -1,4 +1,4 @@
|
||||
/* $Id: term.c,v 1.226 2014/08/01 19:38:29 schwarze Exp $ */
|
||||
/* $Id: term.c,v 1.236 2014/11/21 01:52:53 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,9 +15,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -44,11 +42,7 @@ void
|
||||
term_free(struct termp *p)
|
||||
{
|
||||
|
||||
if (p->buf)
|
||||
free(p->buf);
|
||||
if (p->symtab)
|
||||
mchars_free(p->symtab);
|
||||
|
||||
free(p->buf);
|
||||
free(p);
|
||||
}
|
||||
|
||||
@ -106,7 +100,7 @@ term_flushln(struct termp *p)
|
||||
size_t j; /* temporary loop index for p->buf */
|
||||
size_t jhy; /* last hyph before overflow w/r/t j */
|
||||
size_t maxvis; /* output position of visible boundary */
|
||||
size_t mmax; /* used in calculating bp */
|
||||
size_t rmargin; /* the rightmost of the two margins */
|
||||
|
||||
/*
|
||||
* First, establish the maximum columns of "visible" content.
|
||||
@ -119,13 +113,17 @@ term_flushln(struct termp *p)
|
||||
* is negative, it gets sign extended. Subtracting that
|
||||
* very large size_t effectively adds a small number to dv.
|
||||
*/
|
||||
assert (p->rmargin >= p->offset);
|
||||
dv = p->rmargin - p->offset;
|
||||
rmargin = p->rmargin > p->offset ? p->rmargin : p->offset;
|
||||
dv = p->rmargin - p->offset;
|
||||
maxvis = (int)dv > p->overstep ? dv - (size_t)p->overstep : 0;
|
||||
dv = p->maxrmargin - p->offset;
|
||||
mmax = (int)dv > p->overstep ? dv - (size_t)p->overstep : 0;
|
||||
|
||||
bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;
|
||||
if (p->flags & TERMP_NOBREAK) {
|
||||
dv = p->maxrmargin > p->offset ?
|
||||
p->maxrmargin - p->offset : 0;
|
||||
bp = (int)dv > p->overstep ?
|
||||
dv - (size_t)p->overstep : 0;
|
||||
} else
|
||||
bp = maxvis;
|
||||
|
||||
/*
|
||||
* Calculate the required amount of padding.
|
||||
@ -194,8 +192,8 @@ term_flushln(struct termp *p)
|
||||
(*p->endline)(p);
|
||||
p->viscol = 0;
|
||||
if (TERMP_BRIND & p->flags) {
|
||||
vbl = p->rmargin;
|
||||
vend += p->rmargin - p->offset;
|
||||
vbl = rmargin;
|
||||
vend += rmargin - p->offset;
|
||||
} else
|
||||
vbl = p->offset;
|
||||
|
||||
@ -222,7 +220,7 @@ term_flushln(struct termp *p)
|
||||
break;
|
||||
if (' ' == p->buf[i]) {
|
||||
j = i;
|
||||
while (' ' == p->buf[i])
|
||||
while (i < p->col && ' ' == p->buf[i])
|
||||
i++;
|
||||
dv = (i - j) * (*p->width)(p, ' ');
|
||||
vbl += dv;
|
||||
@ -260,8 +258,10 @@ term_flushln(struct termp *p)
|
||||
* If there was trailing white space, it was not printed;
|
||||
* so reset the cursor position accordingly.
|
||||
*/
|
||||
if (vis)
|
||||
if (vis > vbl)
|
||||
vis -= vbl;
|
||||
else
|
||||
vis = 0;
|
||||
|
||||
p->col = 0;
|
||||
p->overstep = 0;
|
||||
@ -397,7 +397,6 @@ term_word(struct termp *p, const char *word)
|
||||
{
|
||||
const char nbrsp[2] = { ASCII_NBRSP, 0 };
|
||||
const char *seq, *cp;
|
||||
char c;
|
||||
int sz, uc;
|
||||
size_t ssz;
|
||||
enum mandoc_esc esc;
|
||||
@ -446,68 +445,70 @@ term_word(struct termp *p, const char *word)
|
||||
if (ESCAPE_ERROR == esc)
|
||||
continue;
|
||||
|
||||
if (TERMENC_ASCII != p->enc)
|
||||
switch (esc) {
|
||||
case ESCAPE_UNICODE:
|
||||
uc = mchars_num2uc(seq + 1, sz - 1);
|
||||
if ('\0' == uc)
|
||||
break;
|
||||
encode1(p, uc);
|
||||
continue;
|
||||
case ESCAPE_SPECIAL:
|
||||
uc = mchars_spec2cp(p->symtab, seq, sz);
|
||||
if (uc <= 0)
|
||||
break;
|
||||
encode1(p, uc);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (esc) {
|
||||
case ESCAPE_UNICODE:
|
||||
encode1(p, '?');
|
||||
uc = mchars_num2uc(seq + 1, sz - 1);
|
||||
break;
|
||||
case ESCAPE_NUMBERED:
|
||||
c = mchars_num2char(seq, sz);
|
||||
if ('\0' != c)
|
||||
encode(p, &c, 1);
|
||||
uc = mchars_num2char(seq, sz);
|
||||
if (uc < 0)
|
||||
continue;
|
||||
break;
|
||||
case ESCAPE_SPECIAL:
|
||||
cp = mchars_spec2str(p->symtab, seq, sz, &ssz);
|
||||
if (NULL != cp)
|
||||
encode(p, cp, ssz);
|
||||
else if (1 == ssz)
|
||||
encode(p, seq, sz);
|
||||
break;
|
||||
if (p->enc == TERMENC_ASCII) {
|
||||
cp = mchars_spec2str(p->symtab,
|
||||
seq, sz, &ssz);
|
||||
if (cp != NULL)
|
||||
encode(p, cp, ssz);
|
||||
} else {
|
||||
uc = mchars_spec2cp(p->symtab, seq, sz);
|
||||
if (uc > 0)
|
||||
encode1(p, uc);
|
||||
}
|
||||
continue;
|
||||
case ESCAPE_FONTBOLD:
|
||||
term_fontrepl(p, TERMFONT_BOLD);
|
||||
break;
|
||||
continue;
|
||||
case ESCAPE_FONTITALIC:
|
||||
term_fontrepl(p, TERMFONT_UNDER);
|
||||
break;
|
||||
continue;
|
||||
case ESCAPE_FONTBI:
|
||||
term_fontrepl(p, TERMFONT_BI);
|
||||
break;
|
||||
continue;
|
||||
case ESCAPE_FONT:
|
||||
/* FALLTHROUGH */
|
||||
case ESCAPE_FONTROMAN:
|
||||
term_fontrepl(p, TERMFONT_NONE);
|
||||
break;
|
||||
continue;
|
||||
case ESCAPE_FONTPREV:
|
||||
term_fontlast(p);
|
||||
break;
|
||||
continue;
|
||||
case ESCAPE_NOSPACE:
|
||||
if (TERMP_SKIPCHAR & p->flags)
|
||||
p->flags &= ~TERMP_SKIPCHAR;
|
||||
else if ('\0' == *word)
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
break;
|
||||
continue;
|
||||
case ESCAPE_SKIPCHAR:
|
||||
p->flags |= TERMP_SKIPCHAR;
|
||||
break;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common handling for Unicode and numbered
|
||||
* character escape sequences.
|
||||
*/
|
||||
|
||||
if (p->enc == TERMENC_ASCII) {
|
||||
cp = ascii_uc2str(uc);
|
||||
encode(p, cp, strlen(cp));
|
||||
} else {
|
||||
if ((uc < 0x20 && uc != 0x09) ||
|
||||
(uc > 0x7E && uc < 0xA0))
|
||||
uc = 0xFFFD;
|
||||
encode1(p, uc);
|
||||
}
|
||||
}
|
||||
p->flags &= ~TERMP_NBRWORD;
|
||||
@ -659,7 +660,7 @@ size_t
|
||||
term_strlen(const struct termp *p, const char *cp)
|
||||
{
|
||||
size_t sz, rsz, i;
|
||||
int ssz, skip, c;
|
||||
int ssz, skip, uc;
|
||||
const char *seq, *rhs;
|
||||
enum mandoc_esc esc;
|
||||
static const char rej[] = { '\\', ASCII_NBRSP, ASCII_HYPH,
|
||||
@ -685,62 +686,65 @@ term_strlen(const struct termp *p, const char *cp)
|
||||
if (ESCAPE_ERROR == esc)
|
||||
continue;
|
||||
|
||||
if (TERMENC_ASCII != p->enc)
|
||||
switch (esc) {
|
||||
case ESCAPE_UNICODE:
|
||||
c = mchars_num2uc(seq + 1,
|
||||
ssz - 1);
|
||||
if ('\0' == c)
|
||||
break;
|
||||
sz += cond_width(p, c, &skip);
|
||||
continue;
|
||||
case ESCAPE_SPECIAL:
|
||||
c = mchars_spec2cp(p->symtab,
|
||||
seq, ssz);
|
||||
if (c <= 0)
|
||||
break;
|
||||
sz += cond_width(p, c, &skip);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rhs = NULL;
|
||||
|
||||
switch (esc) {
|
||||
case ESCAPE_UNICODE:
|
||||
sz += cond_width(p, '?', &skip);
|
||||
uc = mchars_num2uc(seq + 1, ssz - 1);
|
||||
break;
|
||||
case ESCAPE_NUMBERED:
|
||||
c = mchars_num2char(seq, ssz);
|
||||
if ('\0' != c)
|
||||
sz += cond_width(p, c, &skip);
|
||||
uc = mchars_num2char(seq, ssz);
|
||||
if (uc < 0)
|
||||
continue;
|
||||
break;
|
||||
case ESCAPE_SPECIAL:
|
||||
rhs = mchars_spec2str(p->symtab,
|
||||
seq, ssz, &rsz);
|
||||
|
||||
if (ssz != 1 || rhs)
|
||||
break;
|
||||
|
||||
rhs = seq;
|
||||
rsz = ssz;
|
||||
break;
|
||||
if (p->enc == TERMENC_ASCII) {
|
||||
rhs = mchars_spec2str(p->symtab,
|
||||
seq, ssz, &rsz);
|
||||
if (rhs != NULL)
|
||||
break;
|
||||
} else {
|
||||
uc = mchars_spec2cp(p->symtab,
|
||||
seq, ssz);
|
||||
if (uc > 0)
|
||||
sz += cond_width(p, uc, &skip);
|
||||
}
|
||||
continue;
|
||||
case ESCAPE_SKIPCHAR:
|
||||
skip = 1;
|
||||
break;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NULL == rhs)
|
||||
break;
|
||||
/*
|
||||
* Common handling for Unicode and numbered
|
||||
* character escape sequences.
|
||||
*/
|
||||
|
||||
if (rhs == NULL) {
|
||||
if (p->enc == TERMENC_ASCII) {
|
||||
rhs = ascii_uc2str(uc);
|
||||
rsz = strlen(rhs);
|
||||
} else {
|
||||
if ((uc < 0x20 && uc != 0x09) ||
|
||||
(uc > 0x7E && uc < 0xA0))
|
||||
uc = 0xFFFD;
|
||||
sz += cond_width(p, uc, &skip);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
skip = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common handling for all escape sequences
|
||||
* printing more than one character.
|
||||
*/
|
||||
|
||||
for (i = 0; i < rsz; i++)
|
||||
sz += (*p->width)(p, *rhs++);
|
||||
break;
|
||||
|
12
term.h
12
term.h
@ -1,4 +1,4 @@
|
||||
/* $Id: term.h,v 1.101 2014/04/20 16:46:05 schwarze Exp $ */
|
||||
/* $Id: term.h,v 1.105 2014/10/28 17:36:19 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -54,6 +54,7 @@ struct termp_tbl {
|
||||
struct termp {
|
||||
enum termtype type;
|
||||
struct rofftbl tbl; /* table configuration */
|
||||
int synopsisonly; /* print the synopsis only */
|
||||
int mdocstyle; /* imitate mdoc(7) output */
|
||||
size_t defindent; /* Default indent for text. */
|
||||
size_t defrmargin; /* Right margin of the device. */
|
||||
@ -80,12 +81,11 @@ struct termp {
|
||||
#define TERMP_BRIND (1 << 9) /* See term_flushln(). */
|
||||
#define TERMP_DANGLE (1 << 10) /* See term_flushln(). */
|
||||
#define TERMP_HANG (1 << 11) /* See term_flushln(). */
|
||||
#define TERMP_NOSPLIT (1 << 12) /* See termp_an_pre/post(). */
|
||||
#define TERMP_SPLIT (1 << 13) /* See termp_an_pre/post(). */
|
||||
#define TERMP_ANPREC (1 << 14) /* See termp_an_pre(). */
|
||||
#define TERMP_NOSPLIT (1 << 12) /* Do not break line before .An. */
|
||||
#define TERMP_SPLIT (1 << 13) /* Break line before .An. */
|
||||
int *buf; /* Output buffer. */
|
||||
enum termenc enc; /* Type of encoding. */
|
||||
struct mchars *symtab; /* Encoded-symbol table. */
|
||||
const struct mchars *symtab; /* Character table. */
|
||||
enum termfont fontl; /* Last font set. */
|
||||
enum termfont fontq[10]; /* Symmetric fonts. */
|
||||
int fonti; /* Index of font stack. */
|
||||
@ -104,6 +104,8 @@ struct termp {
|
||||
struct termp_ps *ps;
|
||||
};
|
||||
|
||||
const char *ascii_uc2str(int);
|
||||
|
||||
void term_eqn(struct termp *, const struct eqn *);
|
||||
void term_tbl(struct termp *, const struct tbl_span *);
|
||||
void term_free(struct termp *);
|
||||
|
171
term_ascii.c
171
term_ascii.c
@ -1,4 +1,4 @@
|
||||
/* $Id: term_ascii.c,v 1.27 2014/08/01 19:25:52 schwarze Exp $ */
|
||||
/* $Id: term_ascii.c,v 1.40 2014/11/20 13:56:20 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,21 +15,20 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef USE_WCHAR
|
||||
# include <locale.h>
|
||||
#include <assert.h>
|
||||
#if HAVE_WCHAR
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#ifdef USE_WCHAR
|
||||
# include <wchar.h>
|
||||
#if HAVE_WCHAR
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
#include "mandoc.h"
|
||||
@ -38,18 +37,8 @@
|
||||
#include "term.h"
|
||||
#include "main.h"
|
||||
|
||||
/*
|
||||
* Sadly, this doesn't seem to be defined on systems even when they
|
||||
* support it. For the time being, remove it and let those compiling
|
||||
* the software decide for themselves what to use.
|
||||
*/
|
||||
#if 0
|
||||
#if ! defined(__STDC_ISO_10646__)
|
||||
# undef USE_WCHAR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static struct termp *ascii_init(enum termenc, char *);
|
||||
static struct termp *ascii_init(enum termenc,
|
||||
const struct mchars *, char *);
|
||||
static double ascii_hspan(const struct termp *,
|
||||
const struct roffsu *);
|
||||
static size_t ascii_width(const struct termp *, int);
|
||||
@ -60,7 +49,7 @@ static void ascii_endline(struct termp *);
|
||||
static void ascii_letter(struct termp *, int);
|
||||
static void ascii_setwidth(struct termp *, int, size_t);
|
||||
|
||||
#ifdef USE_WCHAR
|
||||
#if HAVE_WCHAR
|
||||
static void locale_advance(struct termp *, size_t);
|
||||
static void locale_endline(struct termp *);
|
||||
static void locale_letter(struct termp *, int);
|
||||
@ -69,14 +58,15 @@ static size_t locale_width(const struct termp *, int);
|
||||
|
||||
|
||||
static struct termp *
|
||||
ascii_init(enum termenc enc, char *outopts)
|
||||
ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts)
|
||||
{
|
||||
const char *toks[4];
|
||||
const char *toks[5];
|
||||
char *v;
|
||||
struct termp *p;
|
||||
|
||||
p = mandoc_calloc(1, sizeof(struct termp));
|
||||
|
||||
p->symtab = mchars;
|
||||
p->tabwidth = 5;
|
||||
p->defrmargin = p->lastrmargin = 78;
|
||||
|
||||
@ -92,7 +82,7 @@ ascii_init(enum termenc enc, char *outopts)
|
||||
p->setwidth = ascii_setwidth;
|
||||
p->width = ascii_width;
|
||||
|
||||
#ifdef USE_WCHAR
|
||||
#if HAVE_WCHAR
|
||||
if (TERMENC_ASCII != enc) {
|
||||
v = TERMENC_LOCALE == enc ?
|
||||
setlocale(LC_ALL, "") :
|
||||
@ -110,7 +100,8 @@ ascii_init(enum termenc enc, char *outopts)
|
||||
toks[0] = "indent";
|
||||
toks[1] = "width";
|
||||
toks[2] = "mdoc";
|
||||
toks[3] = NULL;
|
||||
toks[3] = "synopsis";
|
||||
toks[4] = NULL;
|
||||
|
||||
while (outopts && *outopts)
|
||||
switch (getsubopt(&outopts, UNCONST(toks), &v)) {
|
||||
@ -128,6 +119,9 @@ ascii_init(enum termenc enc, char *outopts)
|
||||
p->mdocstyle = 1;
|
||||
p->defindent = 5;
|
||||
break;
|
||||
case 3:
|
||||
p->synopsisonly = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -140,24 +134,24 @@ ascii_init(enum termenc enc, char *outopts)
|
||||
}
|
||||
|
||||
void *
|
||||
ascii_alloc(char *outopts)
|
||||
ascii_alloc(const struct mchars *mchars, char *outopts)
|
||||
{
|
||||
|
||||
return(ascii_init(TERMENC_ASCII, outopts));
|
||||
return(ascii_init(TERMENC_ASCII, mchars, outopts));
|
||||
}
|
||||
|
||||
void *
|
||||
utf8_alloc(char *outopts)
|
||||
utf8_alloc(const struct mchars *mchars, char *outopts)
|
||||
{
|
||||
|
||||
return(ascii_init(TERMENC_UTF8, outopts));
|
||||
return(ascii_init(TERMENC_UTF8, mchars, outopts));
|
||||
}
|
||||
|
||||
void *
|
||||
locale_alloc(char *outopts)
|
||||
locale_alloc(const struct mchars *mchars, char *outopts)
|
||||
{
|
||||
|
||||
return(ascii_init(TERMENC_LOCALE, outopts));
|
||||
return(ascii_init(TERMENC_LOCALE, mchars, outopts));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -165,12 +159,14 @@ ascii_setwidth(struct termp *p, int iop, size_t width)
|
||||
{
|
||||
|
||||
p->rmargin = p->defrmargin;
|
||||
if (0 < iop)
|
||||
if (iop > 0)
|
||||
p->defrmargin += width;
|
||||
else if (0 > iop)
|
||||
else if (iop == 0)
|
||||
p->defrmargin = width ? width : p->lastrmargin;
|
||||
else if (p->defrmargin > width)
|
||||
p->defrmargin -= width;
|
||||
else
|
||||
p->defrmargin = width ? width : p->lastrmargin;
|
||||
p->defrmargin = 0;
|
||||
p->lastrmargin = p->rmargin;
|
||||
p->rmargin = p->maxrmargin = p->defrmargin;
|
||||
}
|
||||
@ -232,38 +228,125 @@ ascii_hspan(const struct termp *p, const struct roffsu *su)
|
||||
double r;
|
||||
|
||||
/*
|
||||
* Approximate based on character width. These are generated
|
||||
* entirely by eyeballing the screen, but appear to be correct.
|
||||
* Approximate based on character width.
|
||||
* None of these will be actually correct given that an inch on
|
||||
* the screen depends on character size, terminal, etc., etc.
|
||||
*/
|
||||
|
||||
switch (su->unit) {
|
||||
case SCALE_BU:
|
||||
r = su->scale * 10.0 / 240.0;
|
||||
break;
|
||||
case SCALE_CM:
|
||||
r = su->scale * 4.0;
|
||||
r = su->scale * 10.0 / 2.54;
|
||||
break;
|
||||
case SCALE_FS:
|
||||
r = su->scale * 2730.666;
|
||||
break;
|
||||
case SCALE_IN:
|
||||
r = su->scale * 10.0;
|
||||
break;
|
||||
case SCALE_MM:
|
||||
r = su->scale / 100.0;
|
||||
break;
|
||||
case SCALE_PC:
|
||||
r = (su->scale * 10.0) / 6.0;
|
||||
r = su->scale * 10.0 / 6.0;
|
||||
break;
|
||||
case SCALE_PT:
|
||||
r = (su->scale * 10.0) / 72.0;
|
||||
break;
|
||||
case SCALE_MM:
|
||||
r = su->scale / 1000.0;
|
||||
r = su->scale * 10.0 / 72.0;
|
||||
break;
|
||||
case SCALE_VS:
|
||||
r = su->scale * 2.0 - 1.0;
|
||||
break;
|
||||
default:
|
||||
case SCALE_EN:
|
||||
/* FALLTHROUGH */
|
||||
case SCALE_EM:
|
||||
r = su->scale;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
#ifdef USE_WCHAR
|
||||
const char *
|
||||
ascii_uc2str(int uc)
|
||||
{
|
||||
static const char nbrsp[2] = { ASCII_NBRSP, '\0' };
|
||||
static const char *tab[] = {
|
||||
"<NUL>","<SOH>","<STX>","<ETX>","<EOT>","<ENQ>","<ACK>","<BEL>",
|
||||
"<BS>", "\t", "<LF>", "<VT>", "<FF>", "<CR>", "<SO>", "<SI>",
|
||||
"<DLE>","<DC1>","<DC2>","<DC3>","<DC4>","<NAK>","<SYN>","<ETB>",
|
||||
"<CAN>","<EM>", "<SUB>","<ESC>","<FS>", "<GS>", "<RS>", "<US>",
|
||||
" ", "!", "\"", "#", "$", "%", "&", "'",
|
||||
"(", ")", "*", "+", ",", "-", ".", "/",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7",
|
||||
"8", "9", ":", ";", "<", "=", ">", "?",
|
||||
"@", "A", "B", "C", "D", "E", "F", "G",
|
||||
"H", "I", "J", "K", "L", "M", "N", "O",
|
||||
"P", "Q", "R", "S", "T", "U", "V", "W",
|
||||
"X", "Y", "Z", "[", "\\", "]", "^", "_",
|
||||
"`", "a", "b", "c", "d", "e", "f", "g",
|
||||
"h", "i", "j", "k", "l", "m", "n", "o",
|
||||
"p", "q", "r", "s", "t", "u", "v", "w",
|
||||
"x", "y", "z", "{", "|", "}", "~", "<DEL>",
|
||||
"<80>", "<81>", "<82>", "<83>", "<84>", "<85>", "<86>", "<87>",
|
||||
"<88>", "<89>", "<8A>", "<8B>", "<8C>", "<8D>", "<8E>", "<8F>",
|
||||
"<90>", "<91>", "<92>", "<93>", "<94>", "<95>", "<96>", "<97>",
|
||||
"<99>", "<99>", "<9A>", "<9B>", "<9C>", "<9D>", "<9E>", "<9F>",
|
||||
nbrsp, "!", "/\bc", "GBP", "o\bx", "=\bY", "|", "<sec>",
|
||||
"\"", "(C)", "_\ba", "<<", "~", "", "(R)", "-",
|
||||
"<deg>","+-", "2", "3", "'", ",\bu", "<par>",".",
|
||||
",", "1", "_\bo", ">>", "1/4", "1/2", "3/4", "?",
|
||||
"`\bA", "'\bA", "^\bA", "~\bA", "\"\bA","o\bA", "AE", ",\bC",
|
||||
"`\bE", "'\bE", "^\bE", "\"\bE","`\bI", "'\bI", "^\bI", "\"\bI",
|
||||
"-\bD", "~\bN", "`\bO", "'\bO", "^\bO", "~\bO", "\"\bO","x",
|
||||
"/\bO", "`\bU", "'\bU", "^\bU", "\"\bU","'\bY", "Th", "ss",
|
||||
"`\ba", "'\ba", "^\ba", "~\ba", "\"\ba","o\ba", "ae", ",\bc",
|
||||
"`\be", "'\be", "^\be", "\"\be","`\bi", "'\bi", "^\bi", "\"\bi",
|
||||
"d", "~\bn", "`\bo", "'\bo", "^\bo", "~\bo", "\"\bo","-:-",
|
||||
"/\bo", "`\bu", "'\bu", "^\bu", "\"\bu","'\by", "th", "\"\by",
|
||||
"A", "a", "A", "a", "A", "a", "'\bC", "'\bc",
|
||||
"^\bC", "^\bc", "C", "c", "C", "c", "D", "d",
|
||||
"/\bD", "/\bd", "E", "e", "E", "e", "E", "e",
|
||||
"E", "e", "E", "e", "^\bG", "^\bg", "G", "g",
|
||||
"G", "g", ",\bG", ",\bg", "^\bH", "^\bh", "/\bH", "/\bh",
|
||||
"~\bI", "~\bi", "I", "i", "I", "i", "I", "i",
|
||||
"I", "i", "IJ", "ij", "^\bJ", "^\bj", ",\bK", ",\bk",
|
||||
"q", "'\bL", "'\bl", ",\bL", ",\bl", "L", "l", "L",
|
||||
"l", "/\bL", "/\bl", "'\bN", "'\bn", ",\bN", ",\bn", "N",
|
||||
"n", "'n", "Ng", "ng", "O", "o", "O", "o",
|
||||
"O", "o", "OE", "oe", "'\bR", "'\br", ",\bR", ",\br",
|
||||
"R", "r", "'\bS", "'\bs", "^\bS", "^\bs", ",\bS", ",\bs",
|
||||
"S", "s", ",\bT", ",\bt", "T", "t", "/\bT", "/\bt",
|
||||
"~\bU", "~\bu", "U", "u", "U", "u", "U", "u",
|
||||
"U", "u", "U", "u", "^\bW", "^\bw", "^\bY", "^\by",
|
||||
"\"\bY","'\bZ", "'\bz", "Z", "z", "Z", "z", "s",
|
||||
"b", "B", "B", "b", "6", "6", "O", "C",
|
||||
"c", "D", "D", "D", "d", "d", "3", "@",
|
||||
"E", "F", ",\bf", "G", "G", "hv", "I", "/\bI",
|
||||
"K", "k", "/\bl", "l", "W", "N", "n", "~\bO",
|
||||
"O", "o", "OI", "oi", "P", "p", "YR", "2",
|
||||
"2", "SH", "sh", "t", "T", "t", "T", "U",
|
||||
"u", "Y", "V", "Y", "y", "/\bZ", "/\bz", "ZH",
|
||||
"ZH", "zh", "zh", "/\b2", "5", "5", "ts", "w",
|
||||
"|", "||", "|=", "!", "DZ", "Dz", "dz", "LJ",
|
||||
"Lj", "lj", "NJ", "Nj", "nj", "A", "a", "I",
|
||||
"i", "O", "o", "U", "u", "U", "u", "U",
|
||||
"u", "U", "u", "U", "u", "@", "A", "a",
|
||||
"A", "a", "AE", "ae", "/\bG", "/\bg", "G", "g",
|
||||
"K", "k", "O", "o", "O", "o", "ZH", "zh",
|
||||
"j", "DZ", "Dz", "dz", "'\bG", "'\bg", "HV", "W",
|
||||
"`\bN", "`\bn", "A", "a", "'\bAE","'\bae","O", "o"};
|
||||
|
||||
assert(uc >= 0);
|
||||
if ((size_t)uc < sizeof(tab)/sizeof(tab[0]))
|
||||
return(tab[uc]);
|
||||
return(mchars_uc2str(uc));
|
||||
}
|
||||
|
||||
#if HAVE_WCHAR
|
||||
static size_t
|
||||
locale_width(const struct termp *p, int c)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user