Import mandoc-1.14.5 and leave only the files we need. vendor/MDOCML
authorSascha Wildner <saw@online.de>
Sun, 17 Mar 2019 11:18:18 +0000 (12:18 +0100)
committerSascha Wildner <saw@online.de>
Sun, 17 Mar 2019 11:18:18 +0000 (12:18 +0100)
It is in preparation for eventually switching to it for manual page
displaying.

161 files changed:
contrib/mdocml/INSTALL [deleted file]
contrib/mdocml/LICENSE [deleted file]
contrib/mdocml/Makefile [deleted file]
contrib/mdocml/Makefile.depend [deleted file]
contrib/mdocml/NEWS [deleted file]
contrib/mdocml/TODO [deleted file]
contrib/mdocml/apropos.1
contrib/mdocml/apropos.c [deleted file]
contrib/mdocml/arch.c
contrib/mdocml/arch.in [deleted file]
contrib/mdocml/att.c
contrib/mdocml/att.in [deleted file]
contrib/mdocml/cgi.c [deleted file]
contrib/mdocml/cgi.h.example [deleted file]
contrib/mdocml/chars.c
contrib/mdocml/chars.in [deleted file]
contrib/mdocml/compat_fgetln.c [deleted file]
contrib/mdocml/compat_getsubopt.c [deleted file]
contrib/mdocml/compat_ohash.c
contrib/mdocml/compat_ohash.h
contrib/mdocml/compat_reallocarray.c [deleted file]
contrib/mdocml/compat_recallocarray.c [new file with mode: 0644]
contrib/mdocml/compat_sqlite3_errstr.c [deleted file]
contrib/mdocml/compat_strcasestr.c [deleted file]
contrib/mdocml/compat_strlcat.c [deleted file]
contrib/mdocml/compat_strlcpy.c [deleted file]
contrib/mdocml/compat_strsep.c [deleted file]
contrib/mdocml/config.h.post [deleted file]
contrib/mdocml/config.h.pre [deleted file]
contrib/mdocml/configure [deleted file]
contrib/mdocml/dba.c [new file with mode: 0644]
contrib/mdocml/dba.h [new file with mode: 0644]
contrib/mdocml/dba_array.c [new file with mode: 0644]
contrib/mdocml/dba_array.h [new file with mode: 0644]
contrib/mdocml/dba_read.c [new file with mode: 0644]
contrib/mdocml/dba_write.c [new file with mode: 0644]
contrib/mdocml/dba_write.h [copied from contrib/mdocml/lib.c with 58% similarity]
contrib/mdocml/dbm.c [new file with mode: 0644]
contrib/mdocml/dbm.h [new file with mode: 0644]
contrib/mdocml/dbm_map.c [new file with mode: 0644]
contrib/mdocml/dbm_map.h [copied from contrib/mdocml/att.c with 60% similarity]
contrib/mdocml/demandoc.1
contrib/mdocml/demandoc.c
contrib/mdocml/eqn.7
contrib/mdocml/eqn.c
contrib/mdocml/eqn.h [new file with mode: 0644]
contrib/mdocml/eqn_html.c
contrib/mdocml/eqn_parse.h [new file with mode: 0644]
contrib/mdocml/eqn_term.c
contrib/mdocml/example.style.css [deleted file]
contrib/mdocml/gmdiff [deleted file]
contrib/mdocml/html.c
contrib/mdocml/html.h
contrib/mdocml/lib.c
contrib/mdocml/lib.in
contrib/mdocml/libman.h
contrib/mdocml/libmandoc.h
contrib/mdocml/libmdoc.h
contrib/mdocml/libroff.h [deleted file]
contrib/mdocml/main.c
contrib/mdocml/main.h
contrib/mdocml/makewhatis.8
contrib/mdocml/man-cgi.css [deleted file]
contrib/mdocml/man.7
contrib/mdocml/man.c
contrib/mdocml/man.cgi.8 [deleted file]
contrib/mdocml/man.h
contrib/mdocml/man_hash.c [deleted file]
contrib/mdocml/man_html.c
contrib/mdocml/man_macro.c
contrib/mdocml/man_term.c
contrib/mdocml/man_validate.c
contrib/mdocml/manconf.h [new file with mode: 0644]
contrib/mdocml/mandoc.1
contrib/mdocml/mandoc.3 [deleted file]
contrib/mdocml/mandoc.c
contrib/mdocml/mandoc.db.5
contrib/mdocml/mandoc.h
contrib/mdocml/mandoc_aux.c
contrib/mdocml/mandoc_aux.h
contrib/mdocml/mandoc_char.7
contrib/mdocml/mandoc_escape.3 [deleted file]
contrib/mdocml/mandoc_html.3 [deleted file]
contrib/mdocml/mandoc_malloc.3 [deleted file]
contrib/mdocml/mandoc_msg.c [new file with mode: 0644]
contrib/mdocml/mandoc_ohash.c [new file with mode: 0644]
contrib/mdocml/mandoc_ohash.h [moved from contrib/mdocml/vol.c with 67% similarity]
contrib/mdocml/mandoc_parse.h [new file with mode: 0644]
contrib/mdocml/mandoc_xr.c [new file with mode: 0644]
contrib/mdocml/mandoc_xr.h [copied from contrib/mdocml/att.c with 61% similarity]
contrib/mdocml/mandocd.8 [new file with mode: 0644]
contrib/mdocml/mandocd.c [new file with mode: 0644]
contrib/mdocml/mandocdb.c
contrib/mdocml/manpage.c [deleted file]
contrib/mdocml/manpath.c
contrib/mdocml/manpath.h [deleted file]
contrib/mdocml/mansearch.3 [deleted file]
contrib/mdocml/mansearch.c
contrib/mdocml/mansearch.h
contrib/mdocml/mansearch_const.c [deleted file]
contrib/mdocml/mchars_alloc.3 [deleted file]
contrib/mdocml/mdoc.7
contrib/mdocml/mdoc.c
contrib/mdocml/mdoc.h
contrib/mdocml/mdoc_argv.c
contrib/mdocml/mdoc_hash.c [deleted file]
contrib/mdocml/mdoc_html.c
contrib/mdocml/mdoc_macro.c
contrib/mdocml/mdoc_man.c
contrib/mdocml/mdoc_markdown.c [new file with mode: 0644]
contrib/mdocml/mdoc_state.c [new file with mode: 0644]
contrib/mdocml/mdoc_term.c
contrib/mdocml/mdoc_validate.c
contrib/mdocml/msec.c
contrib/mdocml/msec.in
contrib/mdocml/out.c
contrib/mdocml/out.h
contrib/mdocml/preconv.1 [deleted file]
contrib/mdocml/preconv.c
contrib/mdocml/read.c
contrib/mdocml/roff.7
contrib/mdocml/roff.c
contrib/mdocml/roff.h [new file with mode: 0644]
contrib/mdocml/roff_html.c [new file with mode: 0644]
contrib/mdocml/roff_int.h [new file with mode: 0644]
contrib/mdocml/roff_term.c [new file with mode: 0644]
contrib/mdocml/roff_validate.c [new file with mode: 0644]
contrib/mdocml/st.c
contrib/mdocml/st.in [deleted file]
contrib/mdocml/style.css [deleted file]
contrib/mdocml/tag.c [new file with mode: 0644]
contrib/mdocml/tag.h [copied from contrib/mdocml/att.c with 66% similarity]
contrib/mdocml/tbl.3 [deleted file]
contrib/mdocml/tbl.7
contrib/mdocml/tbl.c
contrib/mdocml/tbl.h [new file with mode: 0644]
contrib/mdocml/tbl_data.c
contrib/mdocml/tbl_html.c
contrib/mdocml/tbl_int.h [new file with mode: 0644]
contrib/mdocml/tbl_layout.c
contrib/mdocml/tbl_opts.c
contrib/mdocml/tbl_parse.h [new file with mode: 0644]
contrib/mdocml/tbl_term.c
contrib/mdocml/term.c
contrib/mdocml/term.h
contrib/mdocml/term_ascii.c
contrib/mdocml/term_ps.c
contrib/mdocml/term_tab.c [new file with mode: 0644]
contrib/mdocml/test-fgetln.c [deleted file]
contrib/mdocml/test-getsubopt.c [deleted file]
contrib/mdocml/test-mmap.c [deleted file]
contrib/mdocml/test-ohash.c [deleted file]
contrib/mdocml/test-reallocarray.c [deleted file]
contrib/mdocml/test-sqlite3_errstr.c [deleted file]
contrib/mdocml/test-strcasestr.c [deleted file]
contrib/mdocml/test-strlcat.c [deleted file]
contrib/mdocml/test-strlcpy.c [deleted file]
contrib/mdocml/test-strptime.c [deleted file]
contrib/mdocml/test-strsep.c [deleted file]
contrib/mdocml/tree.c
contrib/mdocml/vol.in [deleted file]

diff --git a/contrib/mdocml/INSTALL b/contrib/mdocml/INSTALL
deleted file mode 100644 (file)
index da8eeab..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-$Id: INSTALL,v 1.2 2014/08/10 17:22:26 schwarze Exp $
-
-About mdocml, the portable mandoc distribution
-----------------------------------------------
-The mandoc manpage compiler toolset is a suite of tools compiling
-mdoc(7), the roff(7) macro language of choice for BSD manual pages,
-and man(7), the predominant historical language for UNIX manuals.
-The toolset does not yet implement man(1); that is only scheduled
-for the next release, 1.13.2.  It can, however, already serve to
-translate source manpages to the output displayed by man(1).
-For general information, see <http://mdocml.bsd.lv/>.
-
-In this document, we describe the installation and deployment of
-mandoc(1), first as a simple, standalone formatter, and then as part of
-the man(1) system.
-
-In case you have questions or want to provide feedback, read
-<http://mdocml.bsd.lv/contact.html>.  Consider subscribing to the
-discuss@ mailing list mentioned on that page.  If you intend to
-help with the development of mandoc, consider subscribing to the
-tech@ mailing list, too.
-
-Enjoy using the mandoc toolset!
-
-Ingo Schwarze, Karlsruhe, August 2014
-
-
-Installation
-------------
-Before manually installing mandoc on your system, please check
-whether the newest version of mandoc is already installed by default
-or available via a binary package or a ports system.  A list of the
-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".
-
-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.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
-missing SQLITE_DETERMINISTIC optimization flag.  Versions older
-than 3.8.0 may not show full error information if opening a database
-fails due to the missing sqlite3_errstr() API.  Both are very minor
-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
-glibc version of fts(3) is known to be broken on 32bit platforms,
-see <https://sourceware.org/bugzilla/show_bug.cgi?id=15838>.
-
-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
-----------------------------------
-If you want to check whether automatic configuration works well
-on your platform, consider the following:
-
-The mandoc package intentionally does not use GNU autoconf because
-we consider that toolset a blatant example of overengineering that
-is obsolete nowadays, since all modern operating systems are now
-reasonably close to POSIX and do not need arcane shell magic any
-longer.  If your system does need such magic, consider upgrading
-to reasonably modern POSIX-compliant tools rather than asking for
-autoconf-style workarounds.
-
-As far as mandoc is using any features not mandated by ANSI X3.159-1989
-("ANSI C") or IEEE Std 1003.1-2008 ("POSIX") that some modern systems
-do not have, we intend to provide autoconfiguration tests and
-compat_*.c implementations.  Please report any that turn out to be
-missing.  Note that while we do strive to produce portable code,
-we do not slavishly restrict ourselves to POSIX-only interfaces.
-For improved security and readability, we do use well-designed,
-modern interfaces like reallocarray(3) even if they are still rather
-uncommon, of course bundling compat_*.c implementations as needed.
-
-Where mandoc is using ANSI C or POSIX features that some systems
-still lack and that compat_*.c implementations can be provided for
-without too much hassle, we will consider adding them, too, so
-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".
-
-2. Run "make config.h"
-
-3. Read the file "config.log".  It shows the compiler commands used
-to test the libraries installed on your system and the standard
-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".
-
-
-Deployment
-----------
-If you want to integrate the mandoc(1) tools with your existing
-man(1) system as a formatter, then contact us first: on systems without
-mandoc(1) as the default, you may have your work cut out for you!
-Usually, you can have your default installation and mandoc(1) work right
-alongside each other by using user-specific versions of the files
-mentioned below.
-
-0. Back up each file you want to change!
-
-1. First see whether your system has "/etc/man.conf" or "/etc/manpath.conf"
-(if it has neither, but man(1) is functional, then let us know) or,
-if running as your own user, a per-user override file.  In either
-case, find where man(1) is executing nroff(1) or groff(1) to format
-manuals.  Replace these calls with mandoc(1).
-
-2. Then make sure that man(1) isn't running preprocessors, so you may
-need to replace tbl(1), eqn(1), and similar references with cat(1).
-Some man(1) implementations, like that on Mac OSX, let you run "man -d"
-to see how the formatter is invoked.  Use this to test your changes.  On
-Mac OS X, for instance, man(1) will prepend all files with ".ll" and
-".nr" to set the terminal size, so you need to pass "tail -n+2 |
-mandoc(1)" to disregard them.
-
-3. Finally, make sure that mandoc(1) is actually being invoked instead
-of cached pages being pulled up.  You can usually do this by commenting
-out NOCACHE or similar.
-
-mandoc(1) still has a long way to go in understanding non-trivial
-low-level roff(7) markup embedded in some man(7) pages.  On the BSD
-systems using mandoc(1), third-party software is generally vetted
-on whether it may be formatted with mandoc(1).  If not, groff(1)
-is pulled in as a dependency and used to install a pre-formatted
-"catpage" intead of directly as manual page source.
-
-For more background on switching operating systems to use mandoc(1)
-instead of groff(1) to format manuals, see the two BSDCan presentations
-by Ingo Schwarze:
-<http://www.openbsd.org/papers/bsdcan11-mandoc-openbsd.html>
-<http://www.openbsd.org/papers/bsdcan14-mandoc.pdf>
diff --git a/contrib/mdocml/LICENSE b/contrib/mdocml/LICENSE
deleted file mode 100644 (file)
index 35072fb..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-$Id: LICENSE,v 1.2 2014/04/23 21:06:41 schwarze Exp $
-
-With the exceptions noted below, all code and documentation
-contained in the mdocml toolkit is protected by the Copyright
-of the following developers:
-
-Copyright (c) 2008, 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-Copyright (c) 2010, 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
-Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org>
-Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
-Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
-Copyright (c) 1998, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
-Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
-Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
-
-See the individual source files for information about who contributed
-to which file during which years.
-
-
-The mdocml distribution as a whole is distributed by its developers
-under the following license:
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-The 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_fgetln.c:
-Copyright (c) 1998 The NetBSD Foundation, Inc.
diff --git a/contrib/mdocml/Makefile b/contrib/mdocml/Makefile
deleted file mode 100644 (file)
index 47f37a7..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-# $Id: Makefile,v 1.435 2014/08/10 02:45:04 schwarze Exp $
-#
-# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-# Copyright (c) 2011, 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
-# 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.
-
-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
-CGIBIN          = man.cgi
-
-DBLIB          += -lsqlite3
-
-TESTSRCS        = test-fgetln.c \
-                  test-getsubopt.c \
-                  test-mmap.c \
-                  test-ohash.c \
-                  test-reallocarray.c \
-                  test-sqlite3_errstr.c \
-                  test-strcasestr.c \
-                  test-strlcat.c \
-                  test-strlcpy.c \
-                  test-strptime.c \
-                  test-strsep.c
-
-SRCS            = apropos.c \
-                  arch.c \
-                  att.c \
-                  cgi.c \
-                  chars.c \
-                  compat_fgetln.c \
-                  compat_getsubopt.c \
-                  compat_ohash.c \
-                  compat_reallocarray.c \
-                  compat_sqlite3_errstr.c \
-                  compat_strcasestr.c \
-                  compat_strlcat.c \
-                  compat_strlcpy.c \
-                  compat_strsep.c \
-                  demandoc.c \
-                  eqn.c \
-                  eqn_html.c \
-                  eqn_term.c \
-                  html.c \
-                  lib.c \
-                  main.c \
-                  man.c \
-                  man_hash.c \
-                  man_html.c \
-                  man_macro.c \
-                  man_term.c \
-                  man_validate.c \
-                  mandoc.c \
-                  mandoc_aux.c \
-                  mandocdb.c \
-                  manpage.c \
-                  manpath.c \
-                  mansearch.c \
-                  mansearch_const.c \
-                  mdoc.c \
-                  mdoc_argv.c \
-                  mdoc_hash.c \
-                  mdoc_html.c \
-                  mdoc_macro.c \
-                  mdoc_man.c \
-                  mdoc_term.c \
-                  mdoc_validate.c \
-                  msec.c \
-                  out.c \
-                  preconv.c \
-                  read.c \
-                  roff.c \
-                  st.c \
-                  tbl.c \
-                  tbl_data.c \
-                  tbl_html.c \
-                  tbl_layout.c \
-                  tbl_opts.c \
-                  tbl_term.c \
-                  term.c \
-                  term_ascii.c \
-                  term_ps.c \
-                  tree.c \
-                  vol.c \
-                  $(TESTSRCS)
-
-DISTFILES       = INSTALL \
-                  LICENSE \
-                  Makefile \
-                  Makefile.depend \
-                  NEWS \
-                  TODO \
-                  apropos.1 \
-                  arch.in \
-                  att.in \
-                  cgi.h.example \
-                  chars.in \
-                  compat_ohash.h \
-                  config.h.post \
-                  config.h.pre \
-                  configure \
-                  demandoc.1 \
-                  eqn.7 \
-                  example.style.css \
-                  gmdiff \
-                  html.h \
-                  lib.in \
-                  libman.h \
-                  libmandoc.h \
-                  libmdoc.h \
-                  libroff.h \
-                  main.h \
-                  makewhatis.8 \
-                  man-cgi.css \
-                  man.7 \
-                  man.cgi.8 \
-                  man.h \
-                  mandoc.1 \
-                  mandoc.3 \
-                  mandoc.db.5 \
-                  mandoc.h \
-                  mandoc_aux.h \
-                  mandoc_char.7 \
-                  mandoc_escape.3 \
-                  mandoc_html.3 \
-                  mandoc_malloc.3 \
-                  manpath.h \
-                  mansearch.3 \
-                  mansearch.h \
-                  mchars_alloc.3 \
-                  mdoc.7 \
-                  mdoc.h \
-                  msec.in \
-                  out.h \
-                  preconv.1 \
-                  predefs.in \
-                  roff.7 \
-                  st.in \
-                  style.css \
-                  tbl.3 \
-                  tbl.7 \
-                  term.h \
-                  vol.in \
-                  $(SRCS)
-
-LIBMAN_OBJS     = man.o \
-                  man_hash.o \
-                  man_macro.o \
-                  man_validate.o
-
-LIBMDOC_OBJS    = arch.o \
-                  att.o \
-                  lib.o \
-                  mdoc.o \
-                  mdoc_argv.o \
-                  mdoc_hash.o \
-                  mdoc_macro.o \
-                  mdoc_validate.o \
-                  st.o \
-                  vol.o
-
-LIBROFF_OBJS    = eqn.o \
-                  roff.o \
-                  tbl.o \
-                  tbl_data.o \
-                  tbl_layout.o \
-                  tbl_opts.o
-
-LIBMANDOC_OBJS  = $(LIBMAN_OBJS) \
-                  $(LIBMDOC_OBJS) \
-                  $(LIBROFF_OBJS) \
-                  chars.o \
-                  mandoc.o \
-                  mandoc_aux.o \
-                  msec.o \
-                  read.o
-
-COMPAT_OBJS     = compat_fgetln.o \
-                  compat_getsubopt.o \
-                  compat_ohash.o \
-                  compat_reallocarray.o \
-                  compat_sqlite3_errstr.o \
-                  compat_strcasestr.o \
-                  compat_strlcat.o \
-                  compat_strlcpy.o \
-                  compat_strsep.o
-
-MANDOC_HTML_OBJS = eqn_html.o \
-                  html.o \
-                  man_html.o \
-                  mdoc_html.o \
-                  tbl_html.o
-
-MANDOC_MAN_OBJS  = mdoc_man.o
-
-MANDOC_TERM_OBJS = eqn_term.o \
-                  man_term.o \
-                  mdoc_term.o \
-                  term.o \
-                  term_ascii.o \
-                  term_ps.o \
-                  tbl_term.o
-
-MANDOC_OBJS     = $(MANDOC_HTML_OBJS) \
-                  $(MANDOC_MAN_OBJS) \
-                  $(MANDOC_TERM_OBJS) \
-                  main.o \
-                  out.o \
-                  tree.o
-
-MAKEWHATIS_OBJS         = mandocdb.o mansearch_const.o manpath.o
-
-PRECONV_OBJS    = preconv.o
-
-APROPOS_OBJS    = apropos.o mansearch.o mansearch_const.o manpath.o
-
-CGI_OBJS        = $(MANDOC_HTML_OBJS) \
-                  cgi.o \
-                  mansearch.o \
-                  mansearch_const.o \
-                  out.o
-
-MANPAGE_OBJS    = manpage.o mansearch.o mansearch_const.o manpath.o
-
-DEMANDOC_OBJS   = demandoc.o
-
-WWW_MANS        = apropos.1.html \
-                  demandoc.1.html \
-                  mandoc.1.html \
-                  preconv.1.html \
-                  mandoc.3.html \
-                  mandoc_escape.3.html \
-                  mandoc_html.3.html \
-                  mandoc_malloc.3.html \
-                  mansearch.3.html \
-                  mchars_alloc.3.html \
-                  tbl.3.html \
-                  mandoc.db.5.html \
-                  eqn.7.html \
-                  man.7.html \
-                  mandoc_char.7.html \
-                  mdoc.7.html \
-                  roff.7.html \
-                  tbl.7.html \
-                  makewhatis.8.html \
-                  man.cgi.8.html \
-                  man.h.html \
-                  mandoc.h.html \
-                  mandoc_aux.h.html \
-                  manpath.h.html \
-                  mansearch.h.html \
-                  mdoc.h.html
-
-WWW_OBJS        = mdocml.tar.gz \
-                  mdocml.sha256
-
-# === DEPENDENCY HANDLING ==============================================
-
-all: base-build $(BUILD_TARGETS)
-
-base-build: $(BASEBIN)
-
-db-build: $(DBBIN)
-
-cgi-build: $(CGIBIN)
-
-install: base-install $(INSTALL_TARGETS)
-
-www: $(WWW_OBJS) $(WWW_MANS)
-
-include Makefile.depend
-
-# === TARGETS CONTAINING SHELL COMMANDS ================================
-
-clean:
-       rm -f libmandoc.a $(LIBMANDOC_OBJS)
-       rm -f apropos $(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
-
-base-install: base-build
-       mkdir -p $(DESTDIR)$(BINDIR)
-       mkdir -p $(DESTDIR)$(EXAMPLEDIR)
-       mkdir -p $(DESTDIR)$(LIBDIR)
-       mkdir -p $(DESTDIR)$(INCLUDEDIR)
-       mkdir -p $(DESTDIR)$(MANDIR)/man1
-       mkdir -p $(DESTDIR)$(MANDIR)/man3
-       mkdir -p $(DESTDIR)$(MANDIR)/man7
-       $(INSTALL_PROGRAM) $(BASEBIN) $(DESTDIR)$(BINDIR)
-       $(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) 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 \
-               $(DESTDIR)$(MANDIR)/man7
-       $(INSTALL_DATA) example.style.css $(DESTDIR)$(EXAMPLEDIR)
-
-db-install: db-build
-       mkdir -p $(DESTDIR)$(BINDIR)
-       mkdir -p $(DESTDIR)$(SBINDIR)
-       mkdir -p $(DESTDIR)$(MANDIR)/man1
-       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
-       $(INSTALL_PROGRAM) makewhatis $(DESTDIR)$(SBINDIR)
-       $(INSTALL_MAN) apropos.1 $(DESTDIR)$(MANDIR)/man1
-       ln -f $(DESTDIR)$(MANDIR)/man1/apropos.1 \
-               $(DESTDIR)$(MANDIR)/man1/whatis.1
-       $(INSTALL_MAN) mansearch.3 $(DESTDIR)$(MANDIR)/man3
-       $(INSTALL_MAN) mandoc.db.5 $(DESTDIR)$(MANDIR)/man5
-       $(INSTALL_MAN) makewhatis.8 $(DESTDIR)$(MANDIR)/man8
-
-cgi-install: cgi-build
-       mkdir -p $(DESTDIR)$(CGIBINDIR)
-       mkdir -p $(DESTDIR)$(HTDOCDIR)
-       mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1
-       mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8
-       $(INSTALL_PROGRAM) man.cgi $(DESTDIR)$(CGIBINDIR)
-       $(INSTALL_DATA) example.style.css $(DESTDIR)$(HTDOCDIR)/man.css
-       $(INSTALL_DATA) man-cgi.css $(DESTDIR)$(HTDOCDIR)
-       $(INSTALL_MAN) apropos.1 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1/
-       $(INSTALL_MAN) man.cgi.8 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8/
-
-www-install: www
-       mkdir -p $(DESTDIR)$(HTDOCDIR)/snapshots
-       $(INSTALL_DATA) $(WWW_MANS) style.css $(DESTDIR)$(HTDOCDIR)
-       $(INSTALL_DATA) $(WWW_OBJS) $(DESTDIR)$(HTDOCDIR)/snapshots
-       $(INSTALL_DATA) mdocml.tar.gz \
-               $(DESTDIR)$(HTDOCDIR)/snapshots/mdocml-$(VERSION).tar.gz
-       $(INSTALL_DATA) mdocml.sha256 \
-               $(DESTDIR)$(HTDOCDIR)/snapshots/mdocml-$(VERSION).sha256
-
-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
-       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
-
-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)
-
-demandoc: $(DEMANDOC_OBJS) libmandoc.a
-       $(CC) $(LDFLAGS) -o $@ $(DEMANDOC_OBJS) libmandoc.a
-
-mdocml.sha256: mdocml.tar.gz
-       sha256 mdocml.tar.gz > $@
-
-mdocml.tar.gz: $(DISTFILES)
-       mkdir -p .dist/mdocml-$(VERSION)/
-       $(INSTALL_SOURCE) $(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
-.SUFFIXES:      .1       .3       .5       .7       .8       .h
-.SUFFIXES:      .1.html  .3.html  .5.html  .7.html  .8.html  .h.html
-
-.h.h.html:
-       highlight -I $< > $@
-
-.1.1.html .3.3.html .5.5.html .7.7.html .8.8.html: mandoc
-       ./mandoc -Thtml -Wall,stop \
-               -Ostyle=style.css,man=%N.%S.html,includes=%I.html $< > $@
diff --git a/contrib/mdocml/Makefile.depend b/contrib/mdocml/Makefile.depend
deleted file mode 100644 (file)
index dc49310..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-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
-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 
-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
-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
-man_macro.o: man_macro.c config.h man.h mandoc.h libmandoc.h libman.h
-man_term.o: man_term.c config.h mandoc.h mandoc_aux.h out.h man.h term.h main.h
-man_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
-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_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
-mdoc_hash.o: mdoc_hash.c config.h mdoc.h libmdoc.h
-mdoc_html.o: mdoc_html.c config.h mandoc.h mandoc_aux.h out.h html.h mdoc.h main.h
-mdoc_macro.o: mdoc_macro.c config.h mdoc.h mandoc.h libmdoc.h libmandoc.h
-mdoc_man.o: mdoc_man.c config.h mandoc.h mandoc_aux.h out.h man.h mdoc.h main.h
-mdoc_term.o: mdoc_term.c config.h mandoc.h mandoc_aux.h out.h term.h mdoc.h main.h
-mdoc_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 
-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
-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
-tbl_html.o: tbl_html.c config.h mandoc.h out.h html.h
-tbl_layout.o: tbl_layout.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
-tbl_opts.o: tbl_opts.c config.h mandoc.h libmandoc.h libroff.h
-tbl_term.o: tbl_term.c config.h mandoc.h out.h term.h
-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 
diff --git a/contrib/mdocml/NEWS b/contrib/mdocml/NEWS
deleted file mode 100644 (file)
index 61006b5..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-$Id: NEWS,v 1.5 2014/08/10 16:32:57 schwarze Exp $
-
-This file lists the most important changes in the mdocml.bsd.lv distribution.
-
-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.
-   Almost all fatal errors were downgraded to normal errors and some
-   even to warnings.  Almost all messages now mention the macro where
-   the issue is detected and many indicate the workaround employed.
-   The mandoc(1) manual now includes a list explaining all messages.
-    --- MINOR NEW FEATURES ---
- * The roff(7) parser now supports the .ami (append to macro with
-   indirectly specified name), .as (append to user-defined
-   string), .dei (define macro with indirectly specified name),
-   .ll (line length), and .rr (remove register) requests.
- * The roff(7) parser now supports string comparison and numerical
-   conditionals in the .if and .ie requests.
- * The roff parser now fully supports the \B (validate numerical
-   expression) and partially supports the \w (measure text width)
-   escape sequences.
- * The terminal formatter now supports the \: (optional line break)
-   escape sequence.
- * The roff parser now supports expansion of user-defined strings
-   involving indirect references.
- * The roff(7) parser now handles some pre-defined read-only
-   number registers that occur in the pod2man(1) preamble.
- * For backward compatibility, the mdoc(7) parser and formatters
-   now support the obsolete macros .En, .Es, .Fr, and .Ot.
- * The mdoc(7) formatter non partially supports .Bd -centered.
- * tbl(7) now handles leading and trailing vertical lines.
- * The build system now provides fallback versions of strcasestr(3)
-   and strsep(3) for systems lacking them.
- * The mdoc(7) manual now explains how various standards
-   supported by the .St macro are related to each other.
-    --- BUGFIXES ---
- * In the roff(7) parser, several bugs were fixed with respect
-   to closing conditional blocks on macro lines.
- * Parsing of roff(7) identifiers and escape sequences was improved
-   in multiple respects.
- * In the mdoc(7) parser, the handling of defective document
-   prologues was improved in multiple ways.
- * The mdoc(7) parser no longer skips content before the first section
-   header, and it no longer deletes non-.% content from .Rs blocks.
- * In the mdoc(7) parser, a crash was fixed related to weird .Sh headers.
- * In the mdoc(7) parser, handling of .Sm with missing or invalid
-   arguments was corrected.
- * In the mdoc(7) parser, trailing punctuation at the end of partial
-   implicit macros no longer triggers end-of-sentence spacing.
- * In the terminal formatter, two crashes were fixed: one triggered by
-   excessive indentation and another by excessively long .Nm arguments.
- * In the terminal formatter, a floating point rounding bug was
-   fixed that sometimes caused an off-by-one error in indentation.
- * In the UTF-8 formatter, rendering of accents, breakable hyphens,
-   and non-breakable spaces was corrected.
- * In the HTML formatter, encoding of special characters was
-   corrected in multiple respects.
- * In the mdoc(7) formatter, rendering of .Ex and .Rv was
-   improved for various edge cases.
- * In the mdoc(7) formatter, handling of empty .Bl -inset item
-   heads was improved.
- * In the man(7) formatter, some bugs were fixed with respect
-   to same-line detection in the context of .TP and .nf macros,
-   and the indentation of .IP and .TP blocks was improved.
- * The mandoc(3) library no longer prints to stderr.
-    --- THANKS TO ---
-   Abhinav Upadhyay (NetBSD), Andreas Voegele, Anthony Bentley (OpenBSD),
-   Christian Weisgerber (OpenBSD), Havard Eidnes (NetBSD), Jan Stary,
-   Jason McIntyre (OpenBSD), Jeremie Courreges-Anglas (OpenBSD),
-   Joerg Sonnenberger (NetBSD), Juan Francisco Cantero Hurtado (OpenBSD),
-   Marc Espie (OpenBSD), Matthias Scheler (NetBSD), Pascal Stumpf (OpenBSD),
-   Paul Onyschuk (Alpine Linux), Sebastien Marie, Steffen Nurpmeso,
-   Stuart Henderson (OpenBSD), Ted Unangst (OpenBSD), Theo de Raadt (OpenBSD),
-   Thomas Klausner (NetBSD), and Ulrich Spoerlein (FreeBSD)
-   for reporting bugs and missing features.
-
-Changes in version 1.12.3, released on December 31, 2013
-
- * In the mdoc(7) SYNOPSIS, line breaks and hanging indentation
-   now work correctly for .Fo/.Fa/.Fc and .Fn blocks.
-   Thanks to Franco Fichtner for doing part of the work.
- * The mdoc(7) .Bk macro got some addititonal bugfixes.
- * In mdoc(7) macro arguments, double quotes can now be quoted
-   by doubling them, just like in man(7).
-   Thanks to Tsugutomo ENAMI for the patch.
- * At the end of man(7) macro lines, end-of-sentence spacing
-   now works.  Thanks to Franco Fichtner for the patch.
- * For backward compatibility, the man(7) parser now supports the
-   man-ext .UR/.UE (uniform resource identifier) block macros.
- * The man(7) parser now handles closing blocks that are not open
-   more gracefully.
- * The man(7) parser now ignores blank lines right after .SH and .SS.
- * In the man(7) formatter, reset indentation when leaving a block,
-   not just when entering the next one.
- * The roff(7) .nr request now supports incrementing and decrementing
-   number registers and stops parsing the number right before the
-   first non-digit character.
- * The roff(7) parser now supports the alternative escape sequence
-   syntax \C'uXXXX' for Unicode characters.
- * The roff(7) parser now parses and ignores the .fam (font family)
-   and .hw (hyphenation points) requests and the \d and \u escape
-   sequences.
- * The roff(7) manual got a new ESCAPE SEQUENCE REFERENCE.
-
-Changes in version 1.12.2, released on Oktober 5, 2013
-
- * The mdoc(7) to man(7) converter, to be called as mandoc -Tman,
-   is now fully functional.
- * The mandoc(1) utility now supports the -Ios (default operating system)
-   input option, and the -Tutf8 output mode now actually works.
- * The mandocdb(8) utility no longer truncates existing databases when
-   starting to build new ones, but only replaces them when the build
-   actually succeeds.
- * The man(7) parser now supports the PD macro (paragraph distance),
-   and (for GNU man-ext compatibility only) EX (example block) and EE
-   (example end).  Plus several bugfixes regarding indentation, line
-   breaks, and vertical spacing, and regarding RS following TP.
- * The roff(7) parser now supports the \f(BI (bold+italic) font escape,
-   the \z (zero cursor advance) escape and the cc (change control
-   character) and it (input line trap) requests. Plus bugfixes regarding
-   the \t (tab) escape, nested escape sequences, and conditional requests.
- * In mdoc(7), several bugs were fixed related to UTF-8 output of quoting
-   enclosures, delimiter handling, list indentation and horizontal and
-   vertical spacing, formatting of the Lk, %U, and %C macros, plus some
-   bugfixes related to the handling of syntax errors like badly nested
-   font blocks, stray Ta macros outside column lists, unterminated It Xo
-   blocks, and non-text children of Nm blocks.
- * In tbl(7), the width of horizontal spans and the vertical spacing
-   around tables was corrected, and in man(7) files, a crash was fixed
-   that was triggered by some particular unclosed T{ macros.
- * For mandoc developers, we now provide a tbl(3) library manual and
-   gmdiff, a very small, very simplistic groff-versus-mandoc output
-   comparison tool.
- * Provide this NEWS file.
-
-Changes in version 1.12.1, released on March 23, 2012
-
- * Significant work on apropos(1) and mandocdb(8). These tools are now
-   much more robust.  A whatis(1) implementation is now handled as an
-   apropos(1) mode.  These tools are also able to minimally handle
-   pre-formatted pages, that is, those already formatted by another
-   utility such as GNU troff.
- * The man.cgi(7) script is also now available for wider testing.
-   It interfaces with mandocdb(8) manuals cached by catman(8).
-   HTML output is generated on-the-fly by libmandoc or internal
-   methods to convert pre-formatted pages.
- * The mailing list archive for the discuss and tech lists are being
-   hosted by Gmane at gmane.comp.tools.mdocml.user and
-   gmane.comp.tools.mdocml.devel, respectively.
-
-Changes in version 1.12.0, released on October 8, 2011
-
- * This version features a new, work-in-progress mandoc(1) output mode:
-   -Tman.  This mode allows a system maintainer to distribute man(7)
-   media for older systems that may not natively support mdoc(7), such
-   as old Solaris systems.
- * The -Ofragment option was added to mandoc(1)'s -Thtml and -Txhtml modes.
- * While adding features, an apropos(1) utility has been merged from the
-   mandoc-tools sandbox.  This interfaces with mandocdb(8) for semantic
-   search of manual content.  apropos(1) is different from the traditional
-   apropos primarily in allowing keyword search (such as for functions,
-   utilities, etc.) and regular expressions.  Note that the calling
-   syntax for apropos is likely to change as it settles down.
- * In documentation news, the mdoc(7) and man(7) manuals have been
-   made considerably more readable by adding MACRO OVERVIEW sections, by
-   moving the gory details of the LANGUAGE SYNTAX to the roff(7) manual,
-   and by moving the very technical MACRO SYNTAX sections down to the
-   bottom of the page.
- * Furthermore, for tbl(7), the -Tascii mode horizontal spacing of tables
-   was rewritten completely.  It is now compatible with groff(1), both
-   with and without frames and rulers.
- * Nesting of indented blocks is now supported in man(7), and several
-   bugs were fixed regarding indentation and alignment.
- * The page headers in mdoc(7) are now nicer for very long titles.
-
-Changes in version 1.11.7, released on September 2, 2011
-
- * Added demandoc(1) utility for stripping away macros and escapes.
-   This replaces the historical deroff(1) utility.
- * Also improved the mdoc(7) and man(7) manuals.
-
-Changes in version 1.11.6, released on August 16, 2011
-
- * Handling of tr macro in roff(7) implemented.  This makes Perl
-   documentation much more readable.  Hyphenation is also now enabled in
-   man(7) format documents.  Many other general improvements have been
-   implemented.
-
-Changes in version 1.11.5, released on July 24, 2011
-
- * Significant eqn(7) improvements.  mdocml can now parse arbitrary eqn
-   input (although few GNU extensions are accepted, nor is mixing
-   low-level roff with eqn).  See the eqn(7) manual for details.
-   For the time being, equations are rendered as simple in-line text.
-   The equation parser satisfies the language specified in the
-   Second Edition User's Guide:
-   http://www.kohala.com/start/troff/v7man/eqn/eqn2e.ps
-
-Changes in version 1.11.4, released on July 12, 2011
-
- * Bug-fixes and clean-ups across all systems, especially in mandocdb(8)
-   and the man(7) parser.  This release was significantly assisted by
-   participants in OpenBSD's c2k11.  Thanks!
-
-Changes in version 1.11.3, released on May 26, 2011
-
- * Introduce locale-encoding of output with the -Tlocale output option and
-   Unicode escaped-character input.  See mandoc(1) and mandoc_char(7),
-   respectively, for details.  This allows for non-ASCII characters (e.g.,
-   \[u5000]) to be rendered in the locale's encoding, if said environment
-   supports wide-character encoding (if it does not, -Tascii is used
-   instead).  Locale support can be turned off at compile time by removing
-   -DUSE_WCHAR in the Makefile, in which case -Tlocale is always a synonym
-   for -Tascii.
- * Furthermore, multibyte-encoded documents, such as those in UTF-8, may
-   be on-the-fly recoded into mandoc(1) input by using the newly-added
-   preconv(1) utility.  Note: in the future, this feature may be
-   integrated into mandoc(1).
-
-Changes in version 1.11.2, released on May 12, 2011
-
- * Corrected some installation issues in version 1.11.1.
- * Further migration to libmandoc.
- * Initial public release (this utility is very much under development)
-   of mandocdb(8).  This utility produces keyword databases of manual
-   content, which features semantic querying of manual content.
-
-Changes in version 1.11.1, released on April 4, 2011
-
- * The earlier libroff, libmdoc, and libman soup have been merged into
-   a single library, libmandoc, which manages all aspects of parsing
-   real manuals, from line-handling to tbl(7) parsing.
- * As usual, many general fixes and improvements have also occurred.
-   In particular, a great deal of redundancy and superfluous code has
-   been removed with the merging of the backend libraries.
- * see also the changes in 1.10.10
-
-Changes in version 1.10.10, March 20, 2011, NOT released
-
- * Initial eqn(7) functionality is in place.  For the time being,
-   this is limited to the recognition of equation blocks;
-   future version of mdocml will expand upon this framework.
-
-Changes in version 1.10.9, released on January 7, 2011
-
- * Many back-end fixes have been implemented: argument handling (quoting),
-   man(7) improvements, error/warning classes, and many more.
- * Initial tbl(7) functionality (see the "TS", "TE", and "T&" macros in
-   the roff(7) manual) has been merged from tbl.bsd.lv.  Output is still
-   minimal, especially for -Thtml and -Txhtml, but manages to at least
-   display data.  This means that mandoc(1) now has built-in support
-   for two troff preprocessors via libroff: soelim(1) and tbl(1).
-
-Changes in version 1.10.8, released on December 24, 2010
-
- * Overhauled the -Thtml and -Txhtml output modes.  They now display
-   readable output in arbitrary browsers, including text-based ones like
-   lynx(1).  See HTML and XHTML manuals in the DOCUMENTATION section
-   for examples.  Attention: available style-sheet classes have been
-   considerably changed!  See the example.style.css file for details.
-   Lastly, libmdoc and libman have been cleaned up and reduced in size
-   and complexity.
- * see also the changes in 1.10.7
-
-Changes in version 1.10.7, December 6, 2010, NOT released
-
- Significant improvements merged from OpenBSD downstream, including:
- * many new roff(7) components,
- * in-line implementation of troff's soelim(1),
- * broken-block handling,
- * overhauled error classifications, and
- * cleaned up handling of error conditions.
-
-Changes in version 1.10.6, released on September 27, 2010
-
- * Calling conventions for mandoc(1) have changed: -W improved and -f
-   deprecated.
- * Non-ASCII characters are also now uniformly discarded.
- * Lots of documentation improvements.
- * Many incremental fixes accomodating for groff's more interesting
-   productions.
- * Lastly, pod2man(1) preambles are now fully accepted after some
-   considerable roff(7) and special character support.
-
-Changes in version 1.10.5, released on July 27, 2010
-
- * Primarily a bug-fix and polish release, but including -Tpdf support
-   in mandoc(1) by way of "Summer of Code".  Highlights:
- * fix "Sm" and "Bd" handling
- * fix end-of-sentence handling for embedded sentences
- * polish man(7) documentation
- * document all mdoc(7) macros
- * polish mandoc(1) -Tps output
- * lots of internal clean-ups in character escapes
- * un-break literal contexts in man(7) documents
- * improve -Thtml output for -man
- * add mandoc(1) -Tpdf support
-
-Changes in version 1.10.4, released on July 12, 2010
-
- * Lots of features developed during both "Summer of Code" and the
-   OpenBSD c2k10 hackathon:
- * minimal "ds" roff(7) symbols are supported
- * beautified SYNOPSIS section output
- * acceptance of scope-block breakage in mdoc(7)
- * clarify error message status
- * many minor bug-fixes and formatting issues resolved
- * see also changes in 1.10.3
-
-Changes in version 1.10.3, June 29, 2010, NOT released
-
- * variable font-width and paper-size support in mandoc(1) -Tps output
- * "Bk" mdoc(7) support
-
-Changes in version 1.10.2, released on June 19, 2010
-
- * Small release featuring text-decoration in -Tps output,
-   a few minor relaxations of errors, and some optimisations.
-
-Changes in version 1.10.1, released on June 7, 2010
-
- * This primarily focusses on the "Bl" and "It" macros described in
-   mdoc(7).  Multi-line column support is now fully compatible with groff,
-   as are implicit list entries for columns.
- * Removed manuals(7) in favour of http://manpages.bsd.lv.
- * The way we handle the SYNOPSIS section (see the SYNOPSIS documentation
-   in MANUAL STRUCTURE) has also been considerably simplified compared
-   to groff's method.
- * Furthermore, the -Owidth=width output option has been added to -Tascii,
-   see mandoc(1).
- * Lastly, initial PostScript output has been added with the -Tps option
-   to mandoc(1).  It's brutally simple at the moment: fixed-font, with no
-   font decorations.
-
-Changes in version 1.10.0, released on May 29, 2010
-
- * Release consisting of the results from the m2k10 hackathon and up-merge
-   from OpenBSD.  This requires a significant note of thanks to Ingo
-   Schwarze (OpenBSD) and Joerg Sonnenberger (NetBSD) for their hard work,
-   and again to Joerg for hosting m2k10.  Highlights (mostly cribbed from
-   Ingo's m2k10 report) follow in no particular order:
- * a libroff preprocessor in front of libmdoc and libman stripping out
-   roff(7) instructions;
- * end-of-sentence (EOS) detection in free-form and macro lines;
- * correct handling of tab-separated columnar lists in mdoc(7);
- * improved main calling routines to optionally use mmap(3) for better
-   performance;
- * cleaned up exiting when invoked as -Tlint or over multiple files
-   with -fign-errors;
- * error and warning message handling re-written to be unified for
-   libroff, libmdoc, and libman;
- * handling of badly-nested explicit-scoped macros;
- * improved free-form text parsing in libman and libmdoc;
- * significant GNU troff compatibility improvements in -Tascii,
-   largely in terms of spacing;
- * a regression framework for making sure the many fragilities of GNU
-   troff aren't trampled in subsequent work;
- * support for -Tascii breaking at hyphens encountered in free-form text;
- * and many more minor fixes and improvements
-
-Changes in version 1.9.25, released on May 13, 2010
-
- * Fixed handling of "\*(Ba" escape.
- * Backed out -fno-ign-chars (pointless complexity).
- * Fixed erroneous breaking of literal lines.
- * Fixed SYNOPSIS breaking lines before non-initial macros.
- * Changed default section ordering.
- * Most importantly, the framework for end-of-sentence double-spacing is
-   in place, now implemented for the "end-of-sentence, end-of-line" rule.
- * This is a stable roll-back point before the mandoc hackathon in Rostock!
-
-Changes in version 1.9.24, released on May 9, 2010
-
- * Rolled back break-at-hyphen.
- * -DUGLY is now the default (no feature splits!).
- * Free-form text is not de-chunked any more: lines are passed
-   whole-sale into the front-end, including whitespace.
- * Added mailing lists.
-
-Changes in version 1.9.23, released on April 7, 2010
-
- * mdocml has been linked to the OpenBSD build.
- * This version incorporates many small changes, mostly from patches
-   by OpenBSD, allowing crufty manuals to slip by with warnings instead
-   of erroring-out.
- * Some subtle semantic issues, such as punctuation scope, have also
-   been fixed.
- * Lastly, some issues with -Thtml have been fixed, which prompted an
-   update to the online manual pages style layout.
-
-Changes in version 1.9.22, released on March 31, 2010
-
- * Adjusted merge of the significant work by Ingo Schwarze
-   in getting "Xo" blocks (block full implicit, e.g., "It"
-   for non-columnar lists) to work properly.  This isn't
-   enabled by default: you must specify -DUGLY as a compiler
-   flag (see the Makefile for details).
-
-Changes in version 1.9.20, released on March 30, 2010
-
- * More efforts to get roff instructions in man(7) documents under
-   control.  Note that roff instructions embedded in line-scoped,
-   next-line macros (e.g. "B") are not supported.
- * Leading punctuation for mdoc(7) macros, such as "Fl ( ( a",
-   are now correctly handled.
-
-Changes in version 1.9.18, released on March 27, 2010
-
- * Many fixes (largely pertaining to scope)
-   and improvements (e.g., handling of apostrophe-control macros,
-   which fixes the strange "BR" seen in some macro output)
-   to handling roff instructions in man(7) documents.
-
-Changes in version 1.9.17, released on March 25, 2010
-
- * Accept perlpod(1) standard preamble.
- * Also accept (and discard) "de", "dei", "am", "ami", and "ig"
-   roff macro blocks.
-
-Changes in version 1.9.16, released on March 22, 2010
-
- * Inspired by patches and bug reports by Ingo Schwarze,
-   allowed man(7) to accept non-printing elements to be nested
-   within next-line scopes, such as "br" within "B" or "TH",
-   which is valid roff.
- * Longsoon architecture also noted and Makefile cleaned up.
-
-Changes in version 1.9.15, released on February 18, 2010
-
- * Moved to our new BSD.lv home.
- * XHTML is now an acceptable output mode for mandoc(1);
- * "Xr" made more compatible with groff;
- * "Vt" fixed when invoked in SYNOPSIS;
- * "\\" escape removed;
- * end-of-line white-space detected for all lines;
- * subtle bug fixed in list display for some modes;
- * compatibility layer checked in for compilation in diverse
-   UNIX systems;
- * and column lengths handled correctly.
-
-For older releases, see the ChangeLog files
-in http://mdocml.bsd.lv/snapshots/ .
diff --git a/contrib/mdocml/TODO b/contrib/mdocml/TODO
deleted file mode 100644 (file)
index a41df29..0000000
+++ /dev/null
@@ -1,437 +0,0 @@
-************************************************************************
-* Official mandoc TODO.
-* $Id: TODO,v 1.176 2014/08/09 14:24:53 schwarze Exp $
-************************************************************************
-
-************************************************************************
-* crashes
-************************************************************************
-
-- 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.
-
-************************************************************************
-* missing features
-************************************************************************
-
---- missing roff features ----------------------------------------------
-
-- .ad (adjust margins)
-  .ad l -- adjust left margin only (flush left)
-  .ad r -- adjust right margin only (flush right)
-  .ad c -- center text on line
-  .ad b -- adjust both margins (alias: .ad n)
-  .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).
-
-- .fc (field control)
-  found by naddy@ in xloadimage(1)
-  
-- .nr third argument (auto-increment step size, requires \n+)
-  found by bentley@ in sbcl(1)  Mon, 9 Dec 2013 18:36:57 -0700
-
-- .ns (no-space mode) occurs in xine-config(1)
-  reported by brad@  Sat, 15 Jan 2011 15:45:23 -0500
-
-- .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
-
-- .ti (temporary indent)
-  found by naddy@ in xloadimage(1)
-  found by bentley@ in nmh(1)  Mon, 23 Apr 2012 13:38:28 -0600
-
-- .while and .shift 
-  found by jca@ in ratpoison(1)  Sun, 30 Jun 2013 12:01:09 +0200
-
-- \c (interrupted text) should prevent the line break
-  even inside .Bd literal; that occurs in chat(8)
-  also found in cclive(1) - DocBook output
-
-- \h horizontal move
-  found in cclive(1) DocBook output
-  Anthony J. Bentley on discuss@  Sat, 21 Sep 2013 22:29:34 -0600
-
-- \n+ and \n- numerical register increment and decrement
-  found by bentley@ in sbcl(1)  Mon, 9 Dec 2013 18:36:57 -0700
-
-- \w'' 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
-
-- using undefined strings or macros defines them to be empty
-  wl@  Mon, 14 Nov 2011 14:37:01 +0000
-
---- missing mdoc features ----------------------------------------------
-
-- fix bad block nesting involving multiple identical explicit blocks
-  see the OpenBSD mdoc_macro.c 1.47 commit message
-
-- .Bl -column .Xo support is missing
-  ultimate goal:
-  restore .Xr and .Dv to
-  lib/libc/compat-43/sigvec.3
-  lib/libc/gen/signal.3
-  lib/libc/sys/sigaction.2
-
-- 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
-
-- \\ is now implemented correctly
-  * when defining strings and macros using .ds and .de
-  * when parsing roff(7) and man(7) macro arguments
-  It does not yet work in mdoc(7) macro arguments
-  because libmdoc does not yet use mandoc_getarg().
-  Also check what happens in plain text, it must be identical to \e.
-
-- .Bd -centered implies -filled, not -unfilled, which is not
-  easy to implement; it requires code similar to .ce, which
-  we don't have either.
-  Besides, groff has bug causing text right *before* .Bd -centered
-  to be centered as well.
-
-- .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).
-
-- implement blank `Bl -column', such as
-  .Bl -column
-  .It foo Ta bar
-  .El
-
-- explicitly disallow nested `Bl -column', which would clobber internal
-  flags defined for struct mdoc_macro
-
-- 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
-  ugly code from login.conf(5):
-    .Bl -column minpasswordlen program xetcxmotd
-    .It path Ta path Ta value of Dv _PATH_DEFPATH
-    .br
-    Default search path.
-  reported by Michal Mazurek <akfaew at jasminek dot net>
-  via jmc@ Thu, 7 Apr 2011 16:00:53 +0059
-
-- inside `.Bl -column' phrases, punctuation is handled like normal
-  text, e.g. `.Bl -column .It Fl x . Ta ...' should give "-x -."
-
-- inside `.Bl -column' phrases, TERMP_IGNDELIM handling by `Pf'
-  is not safe, e.g. `.Bl -column .It Pf a b .' gives "ab."
-  but should give "ab ."
-
-- set a meaningful default if no `Bl' list type is assigned
-
-- have a blank `It' head for `Bl -tag' not puke
-
-- check whether it is correct that `D1' uses INDENT+1;
-  does it need its own constant?
-
-- prohibit `Nm' from having non-text HEAD children
-  (e.g., NetBSD mDNSShared/dns-sd.1)
-  (mdoc_html.c and mdoc_term.c `Nm' handlers can be slightly simplified)
-
-- support translated section names
-  e.g. x11/scrotwm scrotwm_es.1:21:2: error: NAME section must be first
-  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
-
-- 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
-  macro, while mandoc treats it as a block macro and breaks the line.
-  No idea how the logic for distinguishing in-line and block instances
-  should be, needs investigation.
-  uqs@  Thu, 2 Jun 2011 11:03:51 +0200
-  uqs@  Thu, 2 Jun 2011 11:33:35 +0200
-
---- missing man features -----------------------------------------------
-
-- -T[x]html doesn't stipulate non-collapsing spaces in literal mode
-
---- missing tbl features -----------------------------------------------
-
-- look at the POSIX manuals in the books/man-pages-posix port,
-  they use some unsupported tbl(7) features.
-
-- investigate tbl(1) errors in sox(1)
-  see also naddy@  Sat, 16 Oct 2010 23:51:57 +0200
-
-- 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
-
---- missing misc features ----------------------------------------------
-
-- italic correction (\/) in PostScript mode
-  Werner LEMBERG on groff at gnu dot org  Sun, 10 Nov 2013 12:47:46
-
-- When makewhatis(8) encounters a FATAL parse error,
-  it silently treats the file as formatted, which makes no sense
-  at all for paths like man1/foo.1 - and which also contradicts
-  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.
-
-- makewhatis(8) for preformatted pages:
-  parse the section number from the header line
-  and compare to the section number from the directory name
-
-- Does makewhatis(8) detect missing NAME sections, missing names,
-  and missing descriptions in all the file formats?
-
-- clean up escape sequence handling, creating three classes:
-  (1) fully implemented, or parsed and ignored without loss of content
-  (2) unimplemented, potentially causing loss of content
-      or serious mangling of formatting (e.g. \n) -> ERROR
-      see textproc/mgdiff(1) for nice examples
-  (3) undefined, just output the character -> perhaps WARNING
-
-- kettenis wants base roff, ms, and me  Fri, 1 Jan 2010 22:13:15 +0100 (CET)
-
---- compatibility checks -----------------------------------------------
-
-- is .Bk implemented correctly in modern groff?
-  sobrado@  Tue, 19 Apr 2011 22:12:55 +0200
-
-- compare output to Heirloom roff, Solaris roff, and
-  http://repo.or.cz/w/neatroff.git  http://litcave.rudi.ir/
-
-- 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.
-  For details, see http://docutils.sourceforge.net/rst.html
-  noted by stsp@  Sat, 24 Apr 2010 09:17:55 +0200
-  reminded by nicm@  Mon, 3 May 2010 09:52:41 +0100
-
-- look at pages generated from ronn(1) github.com/rtomayko/ronn
-  (based on markdown)
-
-- look at pages generated from Texinfo source by yat2m, e.g. security/gnupg
-  First impression is not that bad.
-
-- look at pages generated by pandoc; see
-  https://github.com/jgm/pandoc/blob/master/src/Text/Pandoc/Writers/Man.hs
-  porting planned by kili@  Thu, 19 Jun 2014 19:46:28 +0200
-
-- check compatibility with Plan9:
-  http://swtch.com/usr/local/plan9/tmac/tmac.an
-  http://swtch.com/plan9port/man/man7/man.html
-  "Anthony J. Bentley" <anthonyjbentley@gmail.com> 28 Dec 2010 21:58:40 -0700
-
-- check compatibility with the man(7) formatter
-  https://raw.githubusercontent.com/rofl0r/hardcore-utils/master/man.c
-
-************************************************************************
-* formatting issues: ugly output
-************************************************************************
-
-- a column list with blank `Ta' cells triggers a spurrious
-  start-with-whitespace printing of a newline
-
-- In .Bl -column,
-  .It Em Authentication<tab>Key Length
-  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
-
-- 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
-
-- .%T can have trailing punctuation.  Currently, it puts the trailing
-  punctuation into a trailing MDOC_TEXT element inside its own scope.
-  That element should rather be outside its scope, such that the
-  punctuation does not get underlines.  This is not trivial to
-  implement because .%T then needs some features of in_line_eoln() -
-  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".
-
-- 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
-
-- global variables in the SYNOPSIS of section 3 pages
-  .Vt vs .Vt/.Va vs .Ft/.Va vs .Ft/.Fa ...
-  from kristaps@  Tue, 08 Jun 2010 11:13:32 +0200
-
-- in enclosures, mandoc sometimes fancies a bogus end of sentence
-  reminded by jmc@  Thu, 23 Sep 2010 18:13:39 +0059
-
-- formatting /usr/local/man/man1/latex2man.1 with groff and mandoc
-  reveals lots of bugs both in groff and mandoc...
-  reported by bentley@  Wed, 22 May 2013 23:49:30 -0600
-
---- PDF issues ---------------------------------------------------------
-
-- PDF output doesn't use a monospaced font for .Bd -literal
-  Example: "mandoc -Tpdf afterboot.8 > output.pdf && pdfviewer output.pdf".
-  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
-
---- HTML issues --------------------------------------------------------
-
-- <dl><dt><dd> formatting is ugly
-  hints are easy to find on the web, e.g.
-  http://stackoverflow.com/questions/1713048/
-  see also matthew@  Fri, 18 Jul 2014 19:25:12 -0700
-
-- check https://github.com/trentm/mdocml
-
-************************************************************************
-* formatting issues: gratuitous differences
-************************************************************************
-
-- .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.
-
-- In .Bl -bullet, the groff bullet is "+\b+\bo\bo", the mandoc bullet
-  is just "o\bo".
-  see for example OpenBSD ksh(1)
-
-- 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
-
-- .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)
-
-- 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).
-
-- 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
-
-- Trailing punctuation after .It should trigger EOS spacing.
-  reported by Nicolas Joly  Sat, 17 Nov 2012 11:49:54 +0100
-  Probably, this should be fixed somewhere in termp_it_pre(), not sure.
-
-- .Nx 1.0a
-  should be "NetBSD 1.0A", not "NetBSD 1.0a",
-  see OpenBSD ccdconfig(8).
-
-- 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).
-
-- When the -width string contains macros, the macros must be rendered
-  before measuring the width, for example
-    .Bl -tag -width ".Dv message"
-  in magic(5), located in src/usr.bin/file, is the same
-  as -width 7n, not -width 11n.
-  The same applies to .Bl -column column widths;
-  reported again by Nicolas Joly Thu, 1 Mar 2012 13:41:26 +0100 via wiz@ 5 Mar
-  reported again by Franco Fichtner Fri, 27 Sep 2013 21:02:28 +0200
-  An easy partial fix would be to just skip the first word if it starts
-  with a dot, including any following white space, when measuring.
-
-- The \& zero-width character counts as output.
-  That is, when it is alone on a line between two .Pp,
-  we want three blank lines, not two as in mandoc.
-
-- 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
-
-- trailing whitespace must be ignored even when followed by a font escape,
-  see for example 
-    makes
-    \fBdig \fR
-    operate in batch mode
-  in dig(1).
-
-************************************************************************
-* warning issues
-************************************************************************
-
-- check that MANDOCERR_BADTAB is thrown in the right cases,
-  i.e. when finding a literal tab character in fill mode,
-  and possibly change the wording of the warning message
-  to refer to fill mode, not literal mode
-  See the mail from Werner LEMBERG on the groff list,
-  Fri, 14 Feb 2014 18:54:42 +0100 (CET)
-
-- warn about "new sentence, new line"
-
-- mandoc_special does not really check the escape sequence,
-  but just the overall format
-
-- 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
-
-- -Tlint parser errors and warnings to stdout
-  to tech@mdocml, naddy@  Wed, 28 Sep 2011 11:21:46 +0200
-  wait!  kristaps@  Sun, 02 Oct 2011 17:12:52 +0200
-
-- for system errors, use errno/strerror/warn/err
-
-************************************************************************
-* documentation issues
-************************************************************************
-
-- mention hyphenation rules:
-  breaking at letter-letter in text mode (not macro args)
-  proper hyphenation is unimplemented
-
-- talk about spacing around delimiters
-  to jmc@, kristaps@  Sat, 23 Apr 2011 17:41:27 +0200
-
-- mark macros as: page structure domain, manual domain, general text domain
-  is this useful?
-
-- mention /usr/share/misc/mdoc.template in mdoc(7)?
-
-************************************************************************
-* performance issues
-************************************************************************
-
-- Why are we using MAP_SHARED, not MAP_PRIVATE for mmap(2)?
-  How does SQLITE_CONFIG_PAGECACHE actually work?  Document it!
-  from kristaps@  Sat, 09 Aug 2014 13:51:36 +0200
-
-Several areas can be cleaned up to make mandoc even faster.  These are 
-
-- improve hashing mechanism for macros (quite important: performance)
-
-- improve hashing mechanism for characters (not as important)
-
-- the PDF file is HUGE: this can be reduced by using relative offsets
-
-- instead of re-initialising the roff predefined-strings set before each
-  parse, create a read-only version the first time and copy it 
-
-************************************************************************
-* structural issues
-************************************************************************
-
-- 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.
-
-- Find better ways to prevent endless loops
-  in roff(7) macro and string expansion.
-- Finish cleanup of date handling.
-  Decide which formats should be recognized where.
-  Update both mdoc(7) and man(7) documentation.
-  Triggered by  Tim van der Molen  Tue, 22 Feb 2011 20:30:45 +0100
-
-- 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
-
index 1468242..01d2a6b 100644 (file)
@@ -1,7 +1,7 @@
-.\"    $Id: apropos.1,v 1.29 2014/04/24 00:28:19 schwarze Exp $
+.\"    $Id: apropos.1,v 1.49 2018/11/22 12:33:52 schwarze Exp $
 .\"
 .\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2011,2012,2014,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: April 24 2014 $
+.Dd $Mdocdate: November 22 2018 $
 .Dt APROPOS 1
 .Os
 .Sh NAME
@@ -24,6 +24,7 @@
 .Nd search manual page databases
 .Sh SYNOPSIS
 .Nm
+.Op Fl afk
 .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,
@@ -50,23 +51,56 @@ searches for
 .Xr makewhatis 8
 databases in the default paths stipulated by
 .Xr man 1
-and uses case-insensitive substring matching
-.Pq the Cm = No operator
+and uses case-insensitive extended regular expression matching
 over manual names and descriptions
 .Pq the Li \&Nm No and Li \&Nd No macro keys .
 Multiple terms imply pairwise
 .Fl o .
+.Pp
 .Nm whatis
-maps terms only to case-sensitive manual names.
+is a synonym for
+.Nm
+.Fl f .
 .Pp
-Its arguments are as follows:
+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 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.
+.It Fl k
+Support the full
+.Ar expression
+syntax.
+It is the default for
+.Nm .
 .It Fl M Ar path
 Use the colon-separated path instead of the default list of paths
 searched for
@@ -88,7 +122,7 @@ Restrict the search to pages for the specified
 .Xr machine 1
 architecture.
 .Ar arch
-is case insensitive.
+is case-insensitive.
 By default, pages for all architectures are shown.
 .It Fl s Ar section
 Restrict the search to the specified section of the manual.
@@ -98,6 +132,14 @@ See
 for a listing of sections.
 .El
 .Pp
+The options
+.Fl chlw
+are also supported and are documented in
+.Xr man 1 .
+The options
+.Fl fkl
+are mutually exclusive and override each other.
+.Pp
 An
 .Ar expression
 consists of search terms joined by logical operators
@@ -138,7 +180,7 @@ This has syntax
 .Sm off
 .Oo
 .Op Ar key Op , Ar key ...
-.Pq Cm = | ~
+.Pq Cm = | \(ti
 .Oc
 .Ar val ,
 .Sm on
@@ -155,8 +197,8 @@ for a list of available keys.
 Operator
 .Cm =
 evaluates a substring, while
-.Cm ~
-evaluates a regular expression.
+.Cm \(ti
+evaluates a case-sensitive extended regular expression.
 .It Fl i Ar term
 If
 .Ar term
@@ -165,12 +207,12 @@ is evaluated case-insensitively.
 Has no effect on substring terms.
 .El
 .Pp
-.Nm whatis
-considers an
-.Ar expression
-to consist of an opaque keyword.
+Results are sorted first according to the section number in ascending
+numerical order, then by the page name in ascending
+.Xr ascii 7
+alphabetical order, case-insensitive.
 .Pp
-Results are sorted by manual sections and names, with output formatted as
+Each output line is formatted as
 .Pp
 .D1 name[, name...](sec) \- description
 .Pp
@@ -269,25 +311,66 @@ Text production:
 .It Li \&Ox Ta Ox No version reference
 .It Li \&Dx Ta Dx No version reference
 .El
+.Pp
+In general, macro keys are supposed to yield complete results without
+expecting the user to consider actual macro usage.
+For example, results include:
+.Pp
+.Bl -tag -width 3n -offset 3n -compact
+.It Li \&Fa
+function arguments appearing on
+.Ic \&Fn
+lines
+.It Li \&Fn
+function names marked up with
+.Ic \&Fo
+macros
+.It Li \&In
+include file names marked up with
+.Ic \&Fd
+macros
+.It Li \&Vt
+types appearing as function return types and
+.It \&
+types appearing in function arguments in the SYNOPSIS
+.El
 .Sh ENVIRONMENT
-.Bl -tag -width MANPATH
+.Bl -tag -width MANPAGER
+.It Ev MANPAGER
+Any non-empty value of the environment variable
+.Ev MANPAGER
+is used instead of the standard pagination program,
+.Xr more 1 ;
+see
+.Xr man 1
+for details.
+Only used if
+.Fl a
+or
+.Fl l
+is specified.
 .It Ev MANPATH
-The standard search path used by
+A colon-separated list of directories to search for manual pages; see
 .Xr man 1
-may be changed by specifying a path in the
-.Ev MANPATH
-environment variable.
-Invalid paths, or paths without manual databases, are ignored.
+for details.
 Overridden by
-.Fl M .
-If
-.Ev MANPATH
-begins with a colon, it is appended to the default list;
-if it ends with a colon, it is prepended to the default list;
-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.
+.Fl M ,
+ignored if
+.Fl l
+is specified.
+.It Ev PAGER
+Specifies the pagination program to use when
+.Ev MANPAGER
+is not defined.
+If neither PAGER nor MANPAGER is defined,
+.Xr more 1
+.Fl s
+is used.
+Only used if
+.Fl a
+or
+.Fl l
+is specified.
 .El
 .Sh FILES
 .Bl -tag -width "/etc/man.conf" -compact
@@ -307,7 +390,7 @@ Search for
 .Qq .cf
 as a substring of manual names and descriptions:
 .Pp
-.Dl $ apropos .cf
+.Dl $ apropos =.cf
 .Pp
 Include matches for
 .Qq .cnf
@@ -315,11 +398,11 @@ and
 .Qq .conf
 as well:
 .Pp
-.Dl $ apropos .cf .cnf .conf
+.Dl $ apropos =.cf =.cnf =.conf
 .Pp
-Search in names and descriptions using a regular expression:
+Search in names and descriptions using a case-sensitive regular expression:
 .Pp
-.Dl $ apropos '~set.?[ug]id'
+.Dl $ apropos \(aq\(tiset.?[ug]id\(aq
 .Pp
 Search for manuals in the library section mentioning both the
 .Qq optind
@@ -330,30 +413,56 @@ variables:
 .Dl $ apropos \-s 3 Va=optind \-a Va=optarg
 .Pp
 Do exactly the same as calling
-.Xr whatis 1
+.Nm whatis
 with the argument
 .Qq ssh :
 .Pp
-.Dl $ apropos \-\- \-i 'Nm~[[:<:]]ssh[[:>:]]'
+.Dl $ apropos \-\- \-i \(aqNm\(ti[[:<:]]ssh[[:>:]]\(aq
 .Pp
 The following two invocations are equivalent:
 .Pp
 .D1 Li $ apropos -S Ar arch Li -s Ar section expression
 .Bd -ragged -offset indent
 .Li $ apropos \e( Ar expression Li \e)
-.Li -a arch~^( Ns Ar arch Ns Li |any)$
-.Li -a sec~^ Ns Ar section Ns Li $
+.Li -a arch\(ti^( Ns Ar arch Ns Li |any)$
+.Li -a sec\(ti^ Ns Ar section Ns Li $
 .Ed
 .Sh SEE ALSO
 .Xr man 1 ,
 .Xr re_format 7 ,
 .Xr makewhatis 8
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification of
+.Xr man 1
+.Fl k .
+.Pp
+All options, the
+.Nm whatis
+command, support for logical operators, macro keys,
+substring matching, sorting of results, the environment variables
+.Ev MANPAGER
+and
+.Ev MANPATH ,
+the database format, and the configuration file
+are extensions to that specification.
 .Sh HISTORY
-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 +482,27 @@ and
 and
 .Fl s
 in
-.Ox 4.5 .
+.Ox 4.5
+for
+.Nm
+and in
+.Ox 5.6
+for
+.Nm whatis .
+The options
+.Fl acfhIKklOTWw
+appeared in
+.Ox 5.7 .
 .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
diff --git a/contrib/mdocml/apropos.c b/contrib/mdocml/apropos.c
deleted file mode 100644 (file)
index 80b6bc6..0000000
+++ /dev/null
@@ -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);
-}
index 3e746d8..56b937e 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: arch.c,v 1.11 2014/04/20 16:46:04 schwarze Exp $ */
+/*     $Id: arch.c,v 1.14 2019/03/04 13:01:57 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2017, 2019 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * 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 <string.h>
 
-#include "mdoc.h"
-#include "libmdoc.h"
+#include "roff.h"
 
-#define LINE(x, y) \
-       if (0 == strcmp(p, x)) return(y);
-
-
-const char *
-mdoc_a2arch(const char *p)
+int
+arch_valid(const char *arch, enum mandoc_os os)
 {
+       const char *openbsd_arch[] = {
+               "alpha", "amd64", "arm64", "armv7", "hppa", "i386",
+               "landisk", "loongson", "luna88k", "macppc", "mips64",
+               "octeon", "sgi", "socppc", "sparc64", NULL
+       };
+       const char *netbsd_arch[] = {
+               "acorn26", "acorn32", "algor", "alpha", "amiga",
+               "arc", "atari",
+               "bebox", "cats", "cesfic", "cobalt", "dreamcast",
+               "emips", "evbarm", "evbmips", "evbppc", "evbsh3", "evbsh5",
+               "hp300", "hpcarm", "hpcmips", "hpcsh", "hppa",
+               "i386", "ibmnws", "luna68k",
+               "mac68k", "macppc", "mipsco", "mmeye", "mvme68k", "mvmeppc",
+               "netwinder", "news68k", "newsmips", "next68k",
+               "pc532", "playstation2", "pmax", "pmppc", "prep",
+               "sandpoint", "sbmips", "sgimips", "shark",
+               "sparc", "sparc64", "sun2", "sun3",
+               "vax", "walnut", "x68k", "x86", "x86_64", "xen", NULL
+       };
+       const char **arches[] = { NULL, netbsd_arch, openbsd_arch };
+       const char **arch_p;
 
-#include "arch.in"
-
-       return(NULL);
+       if ((arch_p = arches[os]) == NULL)
+               return 1;
+       for (; *arch_p != NULL; arch_p++)
+               if (strcmp(*arch_p, arch) == 0)
+                       return 1;
+       return 0;
 }
diff --git a/contrib/mdocml/arch.in b/contrib/mdocml/arch.in
deleted file mode 100644 (file)
index a22ffd5..0000000
+++ /dev/null
@@ -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")
index 059639a..5575bed 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: att.c,v 1.11 2014/04/20 16:46:04 schwarze Exp $ */
+/*     $Id: att.c,v 1.18 2018/12/13 11:55:46 schwarze Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * 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 "roff.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);
+       return NULL;
 }
diff --git a/contrib/mdocml/att.in b/contrib/mdocml/att.in
deleted file mode 100644 (file)
index b4ef822..0000000
+++ /dev/null
@@ -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")
diff --git a/contrib/mdocml/cgi.c b/contrib/mdocml/cgi.c
deleted file mode 100644 (file)
index 1e38e3d..0000000
+++ /dev/null
@@ -1,1150 +0,0 @@
-/*     $Id: cgi.c,v 1.92 2014/08/05 15:29:30 schwarze Exp $ */
-/*
- * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014 Ingo Schwarze <schwarze@usta.de>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * 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 <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "mandoc.h"
-#include "mandoc_aux.h"
-#include "main.h"
-#include "manpath.h"
-#include "mansearch.h"
-#include "cgi.h"
-
-/*
- * A query as passed to the search function.
- */
-struct query {
-       char            *manpath; /* desired manual directory */
-       char            *arch; /* architecture */
-       char            *sec; /* manual section */
-       char            *query; /* unparsed query expression */
-       int              equal; /* match whole names, not substrings */
-};
-
-struct req {
-       struct query      q;
-       char            **p; /* array of available manpaths */
-       size_t            psz; /* number of available manpaths */
-};
-
-static void             catman(const struct req *, const char *);
-static void             format(const struct req *, const char *);
-static void             html_print(const char *);
-static void             html_putchar(char);
-static int              http_decode(char *);
-static void             http_parse(struct req *, const char *);
-static void             http_print(const char *);
-static void             http_putchar(char);
-static void             http_printquery(const struct req *, const char *);
-static void             pathgen(struct req *);
-static void             pg_error_badrequest(const char *);
-static void             pg_error_internal(void);
-static void             pg_index(const struct req *);
-static void             pg_noresult(const struct req *, const char *);
-static void             pg_search(const struct req *);
-static void             pg_searchres(const struct req *,
-                               struct manpage *, size_t);
-static void             pg_show(struct req *, const char *);
-static void             resp_begin_html(int, const char *);
-static void             resp_begin_http(int, const char *);
-static void             resp_end_html(void);
-static void             resp_searchform(const struct req *);
-static void             resp_show(const struct req *, const char *);
-static void             set_query_attr(char **, char **);
-static int              validate_filename(const char *);
-static int              validate_manpath(const struct req *, const char *);
-static int              validate_urifrag(const char *);
-
-static const char       *scriptname; /* CGI script name */
-
-static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
-static const char *const sec_numbers[] = {
-    "0", "1", "2", "3", "3p", "4", "5", "6", "7", "8", "9"
-};
-static const char *const sec_names[] = {
-    "All Sections",
-    "1 - General Commands",
-    "2 - System Calls",
-    "3 - Subroutines",
-    "3p - Perl Subroutines",
-    "4 - Special Files",
-    "5 - File Formats",
-    "6 - Games",
-    "7 - Macros and Conventions",
-    "8 - Maintenance Commands",
-    "9 - Kernel Interface"
-};
-static const int sec_MAX = sizeof(sec_names) / sizeof(char *);
-
-static const char *const arch_names[] = {
-    "amd64",       "alpha",       "armish",      "armv7",
-    "aviion",      "hppa",        "hppa64",      "i386",
-    "ia64",        "landisk",     "loongson",    "luna88k",
-    "macppc",      "mips64",      "octeon",      "sgi",
-    "socppc",      "solbourne",   "sparc",       "sparc64",
-    "vax",         "zaurus",
-    "amiga",       "arc",         "arm32",       "atari",
-    "beagle",      "cats",        "hp300",       "mac68k",
-    "mvme68k",     "mvme88k",     "mvmeppc",     "palm",
-    "pc532",       "pegasos",     "pmax",        "powerpc",
-    "sun3",        "wgrisc",      "x68k"
-};
-static const int arch_MAX = sizeof(arch_names) / sizeof(char *);
-
-/*
- * Print a character, escaping HTML along the way.
- * This will pass non-ASCII straight to output: be warned!
- */
-static void
-html_putchar(char c)
-{
-
-       switch (c) {
-       case ('"'):
-               printf("&quote;");
-               break;
-       case ('&'):
-               printf("&amp;");
-               break;
-       case ('>'):
-               printf("&gt;");
-               break;
-       case ('<'):
-               printf("&lt;");
-               break;
-       default:
-               putchar((unsigned char)c);
-               break;
-       }
-}
-
-static void
-http_printquery(const struct req *req, const char *sep)
-{
-
-       if (NULL != req->q.query) {
-               printf("query=");
-               http_print(req->q.query);
-       }
-       if (0 == req->q.equal)
-               printf("%sapropos=1", sep);
-       if (NULL != req->q.sec) {
-               printf("%ssec=", sep);
-               http_print(req->q.sec);
-       }
-       if (NULL != req->q.arch) {
-               printf("%sarch=", sep);
-               http_print(req->q.arch);
-       }
-       if (NULL != req->q.manpath &&
-           strcmp(req->q.manpath, req->p[0])) {
-               printf("%smanpath=", sep);
-               http_print(req->q.manpath);
-       }
-}
-
-static void
-http_print(const char *p)
-{
-
-       if (NULL == p)
-               return;
-       while ('\0' != *p)
-               http_putchar(*p++);
-}
-
-/*
- * Call through to html_putchar().
- * Accepts NULL strings.
- */
-static void
-html_print(const char *p)
-{
-       
-       if (NULL == p)
-               return;
-       while ('\0' != *p)
-               html_putchar(*p++);
-}
-
-/*
- * Transfer the responsibility for the allocated string *val
- * to the query structure.
- */
-static void
-set_query_attr(char **attr, char **val)
-{
-
-       free(*attr);
-       if (**val == '\0') {
-               *attr = NULL;
-               free(*val);
-       } else
-               *attr = *val;
-       *val = NULL;
-}
-
-/*
- * Parse the QUERY_STRING for key-value pairs
- * and store the values into the query structure.
- */
-static void
-http_parse(struct req *req, const char *qs)
-{
-       char            *key, *val;
-       size_t           keysz, valsz;
-
-       req->q.manpath  = NULL;
-       req->q.arch     = NULL;
-       req->q.sec      = NULL;
-       req->q.query    = NULL;
-       req->q.equal    = 1;
-
-       key = val = NULL;
-       while (*qs != '\0') {
-
-               /* Parse one key. */
-
-               keysz = strcspn(qs, "=;&");
-               key = mandoc_strndup(qs, keysz);
-               qs += keysz;
-               if (*qs != '=')
-                       goto next;
-
-               /* Parse one value. */
-
-               valsz = strcspn(++qs, ";&");
-               val = mandoc_strndup(qs, valsz);
-               qs += valsz;
-
-               /* Decode and catch encoding errors. */
-
-               if ( ! (http_decode(key) && http_decode(val)))
-                       goto next;
-
-               /* Handle key-value pairs. */
-
-               if ( ! strcmp(key, "query"))
-                       set_query_attr(&req->q.query, &val);
-
-               else if ( ! strcmp(key, "apropos"))
-                       req->q.equal = !strcmp(val, "0");
-
-               else if ( ! strcmp(key, "manpath")) {
-#ifdef COMPAT_OLDURI
-                       if ( ! strncmp(val, "OpenBSD ", 8)) {
-                               val[7] = '-';
-                               if ('C' == val[8])
-                                       val[8] = 'c';
-                       }
-#endif
-                       set_query_attr(&req->q.manpath, &val);
-               }
-
-               else if ( ! (strcmp(key, "sec")
-#ifdef COMPAT_OLDURI
-                   && strcmp(key, "sektion")
-#endif
-                   )) {
-                       if ( ! strcmp(val, "0"))
-                               *val = '\0';
-                       set_query_attr(&req->q.sec, &val);
-               }
-
-               else if ( ! strcmp(key, "arch")) {
-                       if ( ! strcmp(val, "default"))
-                               *val = '\0';
-                       set_query_attr(&req->q.arch, &val);
-               }
-
-               /*
-                * The key must be freed in any case.
-                * The val may have been handed over to the query
-                * structure, in which case it is now NULL.
-                */
-next:
-               free(key);
-               key = NULL;
-               free(val);
-               val = NULL;
-
-               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
-http_putchar(char c)
-{
-
-       if (isalnum((unsigned char)c)) {
-               putchar((unsigned char)c);
-               return;
-       } else if (' ' == c) {
-               putchar('+');
-               return;
-       }
-       printf("%%%.2x", c);
-}
-
-/*
- * HTTP-decode a string.  The standard explanation is that this turns
- * "%4e+foo" into "n foo" in the regular way.  This is done in-place
- * over the allocated string.
- */
-static int
-http_decode(char *p)
-{
-       char             hex[3];
-       char            *q;
-       int              c;
-
-       hex[2] = '\0';
-
-       q = p;
-       for ( ; '\0' != *p; p++, q++) {
-               if ('%' == *p) {
-                       if ('\0' == (hex[0] = *(p + 1)))
-                               return(0);
-                       if ('\0' == (hex[1] = *(p + 2)))
-                               return(0);
-                       if (1 != sscanf(hex, "%x", &c))
-                               return(0);
-                       if ('\0' == c)
-                               return(0);
-
-                       *q = (char)c;
-                       p += 2;
-               } else
-                       *q = '+' == *p ? ' ' : *p;
-       }
-
-       *q = '\0';
-       return(1);
-}
-
-static void
-resp_begin_http(int code, const char *msg)
-{
-
-       if (200 != code)
-               printf("Status: %d %s\r\n", code, msg);
-
-       printf("Content-Type: text/html; charset=utf-8\r\n"
-            "Cache-Control: no-cache\r\n"
-            "Pragma: no-cache\r\n"
-            "\r\n");
-
-       fflush(stdout);
-}
-
-static void
-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"
-              "<HTML>\n"
-              "<HEAD>\n"
-              "<META HTTP-EQUIV=\"Content-Type\""
-              " CONTENT=\"text/html; 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\""
-              " TYPE=\"text/css\" media=\"all\">\n"
-              "<TITLE>%s</TITLE>\n"
-              "</HEAD>\n"
-              "<BODY>\n"
-              "<!-- Begin page content. //-->\n",
-              CSS_DIR, CSS_DIR, CUSTOMIZE_TITLE);
-}
-
-static void
-resp_end_html(void)
-{
-
-       puts("</BODY>\n"
-            "</HTML>");
-}
-
-static void
-resp_searchform(const struct req *req)
-{
-       int              i;
-
-       puts(CUSTOMIZE_BEGIN);
-       puts("<!-- Begin search form. //-->");
-       printf("<DIV ID=\"mancgi\">\n"
-              "<FORM ACTION=\"%s\" METHOD=\"get\">\n"
-              "<FIELDSET>\n"
-              "<LEGEND>Manual Page Search Parameters</LEGEND>\n",
-              scriptname);
-
-       /* Write query input box. */
-
-       printf( "<TABLE><TR><TD>\n"
-               "<INPUT TYPE=\"text\" NAME=\"query\" VALUE=\"");
-       if (NULL != req->q.query)
-               html_print(req->q.query);
-       puts("\" SIZE=\"40\">");
-
-       /* Write submission and reset buttons. */
-
-       printf( "<INPUT TYPE=\"submit\" VALUE=\"Submit\">\n"
-               "<INPUT TYPE=\"reset\" VALUE=\"Reset\">\n");
-
-       /* Write show radio button */
-
-       printf( "</TD><TD>\n"
-               "<INPUT TYPE=\"radio\" ");
-       if (req->q.equal)
-               printf("CHECKED=\"checked\" ");
-       printf( "NAME=\"apropos\" ID=\"show\" VALUE=\"0\">\n"
-               "<LABEL FOR=\"show\">Show named manual page</LABEL>\n");
-
-       /* Write section selector. */
-
-       puts(   "</TD></TR><TR><TD>\n"
-               "<SELECT NAME=\"sec\">");
-       for (i = 0; i < sec_MAX; i++) {
-               printf("<OPTION VALUE=\"%s\"", sec_numbers[i]);
-               if (NULL != req->q.sec &&
-                   0 == strcmp(sec_numbers[i], req->q.sec))
-                       printf(" SELECTED=\"selected\"");
-               printf(">%s</OPTION>\n", sec_names[i]);
-       }
-       puts("</SELECT>");
-
-       /* Write architecture selector. */
-
-       printf( "<SELECT NAME=\"arch\">\n"
-               "<OPTION VALUE=\"default\"");
-       if (NULL == req->q.arch)
-               printf(" SELECTED=\"selected\"");
-       puts(">All Architectures</OPTION>");
-       for (i = 0; i < arch_MAX; i++) {
-               printf("<OPTION VALUE=\"%s\"", arch_names[i]);
-               if (NULL != req->q.arch &&
-                   0 == strcmp(arch_names[i], req->q.arch))
-                       printf(" SELECTED=\"selected\"");
-               printf(">%s</OPTION>\n", arch_names[i]);
-       }
-       puts("</SELECT>");
-
-       /* Write manpath selector. */
-
-       if (req->psz > 1) {
-               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]))
-                               printf("SELECTED=\"selected\" ");
-                       printf("VALUE=\"");
-                       html_print(req->p[i]);
-                       printf("\">");
-                       html_print(req->p[i]);
-                       puts("</OPTION>");
-               }
-               puts("</SELECT>");
-       }
-
-       /* Write search radio button */
-
-       printf( "</TD><TD>\n"
-               "<INPUT TYPE=\"radio\" ");
-       if (0 == req->q.equal)
-               printf("CHECKED=\"checked\" ");
-       printf( "NAME=\"apropos\" ID=\"search\" VALUE=\"1\">\n"
-               "<LABEL FOR=\"search\">Search with apropos query</LABEL>\n");
-
-       puts("</TD></TR></TABLE>\n"
-            "</FIELDSET>\n"
-            "</FORM>\n"
-            "</DIV>");
-       puts("<!-- End search form. //-->");
-}
-
-static int
-validate_urifrag(const char *frag)
-{
-
-       while ('\0' != *frag) {
-               if ( ! (isalnum((unsigned char)*frag) ||
-                   '-' == *frag || '.' == *frag ||
-                   '/' == *frag || '_' == *frag))
-                       return(0);
-               frag++;
-       }
-       return(1);
-}
-
-static int
-validate_manpath(const struct req *req, const char* manpath)
-{
-       size_t   i;
-
-       if ( ! strcmp(manpath, "mandoc"))
-               return(1);
-
-       for (i = 0; i < req->psz; i++)
-               if ( ! strcmp(manpath, req->p[i]))
-                       return(1);
-
-       return(0);
-}
-
-static int
-validate_filename(const char *file)
-{
-
-       if ('.' == file[0] && '/' == file[1])
-               file += 2;
-
-       return ( ! (strstr(file, "../") || strstr(file, "/..") ||
-           (strncmp(file, "man", 3) && strncmp(file, "cat", 3))));
-}
-
-static void
-pg_index(const struct req *req)
-{
-
-       resp_begin_html(200, NULL);
-       resp_searchform(req);
-       printf("<P>\n"
-              "This web interface is documented in the\n"
-              "<A HREF=\"%s/mandoc/man8/man.cgi.8\">man.cgi</A>\n"
-              "manual, and the\n"
-              "<A HREF=\"%s/mandoc/man1/apropos.1\">apropos</A>\n"
-              "manual explains the query syntax.\n"
-              "</P>\n",
-              scriptname, scriptname);
-       resp_end_html();
-}
-
-static void
-pg_noresult(const struct req *req, const char *msg)
-{
-       resp_begin_html(200, NULL);
-       resp_searchform(req);
-       puts("<P>");
-       puts(msg);
-       puts("</P>");
-       resp_end_html();
-}
-
-static void
-pg_error_badrequest(const char *msg)
-{
-
-       resp_begin_html(400, "Bad Request");
-       puts("<H1>Bad Request</H1>\n"
-            "<P>\n");
-       puts(msg);
-       printf("Try again from the\n"
-              "<A HREF=\"%s\">main page</A>.\n"
-              "</P>", scriptname);
-       resp_end_html();
-}
-
-static void
-pg_error_internal(void)
-{
-       resp_begin_html(500, "Internal Server Error");
-       puts("<P>Internal Server Error</P>");
-       resp_end_html();
-}
-
-static void
-pg_searchres(const struct req *req, struct manpage *r, size_t sz)
-{
-       char            *arch, *archend;
-       size_t           i, iuse, isec;
-       int              archprio, archpriouse;
-       int              prio, priouse;
-       char             sec;
-
-       for (i = 0; i < sz; i++) {
-               if (validate_filename(r[i].file))
-                       continue;
-               fprintf(stderr, "invalid filename %s in %s database\n",
-                   r[i].file, req->q.manpath);
-               pg_error_internal();
-               return;
-       }
-
-       if (1 == sz) {
-               /*
-                * If we have just one result, then jump there now
-                * without any delay.
-                */
-               printf("Status: 303 See Other\r\n");
-               printf("Location: http://%s%s/%s/%s?",
-                   HTTP_HOST, scriptname, req->q.manpath, r[0].file);
-               http_printquery(req, "&");
-               printf("\r\n"
-                    "Content-Type: text/html; charset=utf-8\r\n"
-                    "\r\n");
-               return;
-       }
-
-       resp_begin_html(200, NULL);
-       resp_searchform(req);
-       puts("<DIV CLASS=\"results\">");
-       puts("<TABLE>");
-
-       for (i = 0; i < sz; i++) {
-               printf("<TR>\n"
-                      "<TD CLASS=\"title\">\n"
-                      "<A HREF=\"%s/%s/%s?", 
-                   scriptname, req->q.manpath, r[i].file);
-               http_printquery(req, "&amp;");
-               printf("\">");
-               html_print(r[i].names);
-               printf("</A>\n"
-                      "</TD>\n"
-                      "<TD CLASS=\"desc\">");
-               html_print(r[i].output);
-               puts("</TD>\n"
-                    "</TR>");
-       }
-
-       puts("</TABLE>\n"
-            "</DIV>");
-
-       /*
-        * In man(1) mode, show one of the pages
-        * even if more than one is found.
-        */
-
-       if (req->q.equal) {
-               puts("<HR>");
-               iuse = 0;
-               priouse = 10;
-               archpriouse = 3;
-               for (i = 0; i < sz; i++) {
-                       isec = strcspn(r[i].file, "123456789");
-                       sec = r[i].file[isec];
-                       if ('\0' == sec)
-                               continue;
-                       prio = sec_prios[sec - '1'];
-                       if (NULL == req->q.arch) {
-                               archprio =
-                                   (NULL == (arch = strchr(
-                                       r[i].file + isec, '/'))) ? 3 :
-                                   (NULL == (archend = strchr(
-                                       arch + 1, '/'))) ? 0 :
-                                   strncmp(arch, "amd64/",
-                                       archend - arch) ? 2 : 1;
-                               if (archprio < archpriouse) {
-                                       archpriouse = archprio;
-                                       priouse = prio;
-                                       iuse = i;
-                                       continue;
-                               }
-                               if (archprio > archpriouse)
-                                       continue;
-                       }
-                       if (prio >= priouse)
-                               continue;
-                       priouse = prio;
-                       iuse = i;
-               }
-               resp_show(req, r[iuse].file);
-       }
-
-       resp_end_html();
-}
-
-static void
-catman(const struct req *req, const char *file)
-{
-       FILE            *f;
-       size_t           len;
-       int              i;
-       char            *p;
-       int              italic, bold;
-
-       if (NULL == (f = fopen(file, "r"))) {
-               puts("<P>You specified an invalid manual file.</P>");
-               return;
-       }
-
-       puts("<DIV CLASS=\"catman\">\n"
-            "<PRE>");
-
-       while (NULL != (p = fgetln(f, &len))) {
-               bold = italic = 0;
-               for (i = 0; i < (int)len - 1; i++) {
-                       /* 
-                        * This means that the catpage is out of state.
-                        * Ignore it and keep going (although the
-                        * catpage is bogus).
-                        */
-
-                       if ('\b' == p[i] || '\n' == p[i])
-                               continue;
-
-                       /*
-                        * Print a regular character.
-                        * Close out any bold/italic scopes.
-                        * If we're in back-space mode, make sure we'll
-                        * have something to enter when we backspace.
-                        */
-
-                       if ('\b' != p[i + 1]) {
-                               if (italic)
-                                       printf("</I>");
-                               if (bold)
-                                       printf("</B>");
-                               italic = bold = 0;
-                               html_putchar(p[i]);
-                               continue;
-                       } else if (i + 2 >= (int)len)
-                               continue;
-
-                       /* Italic mode. */
-
-                       if ('_' == p[i]) {
-                               if (bold)
-                                       printf("</B>");
-                               if ( ! italic)
-                                       printf("<I>");
-                               bold = 0;
-                               italic = 1;
-                               i += 2;
-                               html_putchar(p[i]);
-                               continue;
-                       }
-
-                       /* 
-                        * Handle funny behaviour troff-isms.
-                        * These grok'd from the original man2html.c.
-                        */
-
-                       if (('+' == p[i] && 'o' == p[i + 2]) ||
-                                       ('o' == p[i] && '+' == p[i + 2]) ||
-                                       ('|' == p[i] && '=' == p[i + 2]) ||
-                                       ('=' == p[i] && '|' == p[i + 2]) ||
-                                       ('*' == p[i] && '=' == p[i + 2]) ||
-                                       ('=' == p[i] && '*' == p[i + 2]) ||
-                                       ('*' == p[i] && '|' == p[i + 2]) ||
-                                       ('|' == p[i] && '*' == p[i + 2]))  {
-                               if (italic)
-                                       printf("</I>");
-                               if (bold)
-                                       printf("</B>");
-                               italic = bold = 0;
-                               putchar('*');
-                               i += 2;
-                               continue;
-                       } else if (('|' == p[i] && '-' == p[i + 2]) ||
-                                       ('-' == p[i] && '|' == p[i + 1]) ||
-                                       ('+' == p[i] && '-' == p[i + 1]) ||
-                                       ('-' == p[i] && '+' == p[i + 1]) ||
-                                       ('+' == p[i] && '|' == p[i + 1]) ||
-                                       ('|' == p[i] && '+' == p[i + 1]))  {
-                               if (italic)
-                                       printf("</I>");
-                               if (bold)
-                                       printf("</B>");
-                               italic = bold = 0;
-                               putchar('+');
-                               i += 2;
-                               continue;
-                       }
-
-                       /* Bold mode. */
-                       
-                       if (italic)
-                               printf("</I>");
-                       if ( ! bold)
-                               printf("<B>");
-                       bold = 1;
-                       italic = 0;
-                       i += 2;
-                       html_putchar(p[i]);
-               }
-
-               /* 
-                * Clean up the last character.
-                * We can get to a newline; don't print that. 
-                */
-
-               if (italic)
-                       printf("</I>");
-               if (bold)
-                       printf("</B>");
-
-               if (i == (int)len - 1 && '\n' != p[i])
-                       html_putchar(p[i]);
-
-               putchar('\n');
-       }
-
-       puts("</PRE>\n"
-            "</DIV>");
-
-       fclose(f);
-}
-
-static void
-format(const struct req *req, const char *file)
-{
-       struct mparse   *mp;
-       struct mdoc     *mdoc;
-       struct man      *man;
-       void            *vp;
-       char            *opts;
-       enum mandoclevel rc;
-       int              fd;
-       int              usepath;
-
-       if (-1 == (fd = open(file, O_RDONLY, 0))) {
-               puts("<P>You specified an invalid manual file.</P>");
-               return;
-       }
-
-       mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_FATAL, NULL,
-           req->q.manpath);
-       rc = mparse_readfd(mp, fd, file);
-       close(fd);
-
-       if (rc >= MANDOCLEVEL_FATAL) {
-               fprintf(stderr, "fatal mandoc error: %s/%s\n",
-                   req->q.manpath, file);
-               pg_error_internal();
-               return;
-       }
-
-       usepath = strcmp(req->q.manpath, req->p[0]);
-       mandoc_asprintf(&opts,
-           "fragment,man=%s?query=%%N&sec=%%S%s%s%s%s",
-           scriptname,
-           req->q.arch ? "&arch="       : "",
-           req->q.arch ? req->q.arch    : "",
-           usepath     ? "&manpath="    : "",
-           usepath     ? req->q.manpath : "");
-
-       mparse_result(mp, &mdoc, &man, NULL);
-       if (NULL == man && NULL == mdoc) {
-               fprintf(stderr, "fatal mandoc error: %s/%s\n",
-                   req->q.manpath, file);
-               pg_error_internal();
-               mparse_free(mp);
-               return;
-       }
-
-       vp = html_alloc(opts);
-
-       if (NULL != mdoc)
-               html_mdoc(vp, mdoc);
-       else
-               html_man(vp, man);
-
-       html_free(vp);
-       mparse_free(mp);
-       free(opts);
-}
-
-static void
-resp_show(const struct req *req, const char *file)
-{
-
-       if ('.' == file[0] && '/' == file[1])
-               file += 2;
-
-       if ('c' == *file)
-               catman(req, file);
-       else
-               format(req, file);
-}
-
-static void
-pg_show(struct req *req, const char *fullpath)
-{
-       char            *manpath;
-       const char      *file;
-
-       if ((file = strchr(fullpath, '/')) == NULL) {
-               pg_error_badrequest(
-                   "You did not specify a page to show.");
-               return;
-       } 
-       manpath = mandoc_strndup(fullpath, file - fullpath);
-       file++;
-
-       if ( ! validate_manpath(req, manpath)) {
-               pg_error_badrequest(
-                   "You specified an invalid manpath.");
-               free(manpath);
-               return;
-       }
-
-       /*
-        * Begin by chdir()ing into the manpath.
-        * This way we can pick up the database files, which are
-        * relative to the manpath root.
-        */
-
-       if (chdir(manpath) == -1) {
-               fprintf(stderr, "chdir %s: %s\n",
-                   manpath, strerror(errno));
-               pg_error_internal();
-               free(manpath);
-               return;
-       }
-
-       if (strcmp(manpath, "mandoc")) {
-               free(req->q.manpath);
-               req->q.manpath = manpath;
-       } else
-               free(manpath);
-
-       if ( ! validate_filename(file)) {
-               pg_error_badrequest(
-                   "You specified an invalid manual file.");
-               return;
-       }
-
-       resp_begin_html(200, NULL);
-       resp_searchform(req);
-       resp_show(req, file);
-       resp_end_html();
-}
-
-static void
-pg_search(const struct req *req)
-{
-       struct mansearch          search;
-       struct manpaths           paths;
-       struct manpage           *res;
-       char                    **cp;
-       const char               *ep, *start;
-       size_t                    ressz;
-       int                       i, sz;
-
-       /*
-        * Begin by chdir()ing into the root of the manpath.
-        * This way we can pick up the database files, which are
-        * relative to the manpath root.
-        */
-
-       if (-1 == (chdir(req->q.manpath))) {
-               fprintf(stderr, "chdir %s: %s\n",
-                   req->q.manpath, strerror(errno));
-               pg_error_internal();
-               return;
-       }
-
-       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;
-
-       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.
-        */
-
-       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++;
-       }
-
-       if (0 == mansearch(&search, &paths, sz, cp, "Nd", &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(paths.paths[0]);
-       free(paths.paths);
-}
-
-int
-main(void)
-{
-       struct req       req;
-       const char      *path;
-       const char      *querystring;
-       int              i;
-
-       /* Scan our run-time environment. */
-
-       if (NULL == (scriptname = getenv("SCRIPT_NAME")))
-               scriptname = "";
-
-       if ( ! validate_urifrag(scriptname)) {
-               fprintf(stderr, "unsafe SCRIPT_NAME \"%s\"\n",
-                   scriptname);
-               pg_error_internal();
-               return(EXIT_FAILURE);
-       }
-
-       /*
-        * First we change directory into the MAN_DIR so that
-        * subsequent scanning for manpath directories is rooted
-        * relative to the same position.
-        */
-
-       if (-1 == chdir(MAN_DIR)) {
-               fprintf(stderr, "MAN_DIR: %s: %s\n",
-                   MAN_DIR, strerror(errno));
-               pg_error_internal();
-               return(EXIT_FAILURE);
-       } 
-
-       memset(&req, 0, sizeof(struct req));
-       pathgen(&req);
-
-       /* Next parse out the query string. */
-
-       if (NULL != (querystring = getenv("QUERY_STRING")))
-               http_parse(&req, querystring);
-
-       if ( ! (NULL == req.q.manpath ||
-           validate_manpath(&req, req.q.manpath))) {
-               pg_error_badrequest(
-                   "You specified an invalid manpath.");
-               return(EXIT_FAILURE);
-       }
-
-       if ( ! (NULL == req.q.arch || validate_urifrag(req.q.arch))) {
-               pg_error_badrequest(
-                   "You specified an invalid architecture.");
-               return(EXIT_FAILURE);
-       }
-
-       /* Dispatch to the three different pages. */
-
-       path = getenv("PATH_INFO");
-       if (NULL == path)
-               path = "";
-       else if ('/' == *path)
-               path++;
-
-       if ('\0' != *path)
-               pg_show(&req, path);
-       else if (NULL != req.q.query)
-               pg_search(&req);
-       else
-               pg_index(&req);
-
-       free(req.q.manpath);
-       free(req.q.arch);
-       free(req.q.sec);
-       free(req.q.query);
-       for (i = 0; i < (int)req.psz; i++)
-               free(req.p[i]);
-       free(req.p);
-       return(EXIT_SUCCESS);
-}
-
-/*
- * Scan for indexable paths.
- */
-static void
-pathgen(struct req *req)
-{
-       FILE    *fp;
-       char    *dp;
-       size_t   dpsz;
-
-       if (NULL == (fp = fopen("manpath.conf", "r"))) {
-               fprintf(stderr, "%s/manpath.conf: %s\n",
-                       MAN_DIR, strerror(errno));
-               pg_error_internal();
-               exit(EXIT_FAILURE);
-       }
-
-       while (NULL != (dp = fgetln(fp, &dpsz))) {
-               if ('\n' == dp[dpsz - 1])
-                       dpsz--;
-               req->p = mandoc_realloc(req->p,
-                   (req->psz + 1) * sizeof(char *));
-               dp = mandoc_strndup(dp, dpsz);
-               if ( ! validate_urifrag(dp)) {
-                       fprintf(stderr, "%s/manpath.conf contains "
-                           "unsafe path \"%s\"\n", MAN_DIR, dp);
-                       pg_error_internal();
-                       exit(EXIT_FAILURE);
-               }
-               if (NULL != strchr(dp, '/')) {
-                       fprintf(stderr, "%s/manpath.conf contains "
-                           "path with slash \"%s\"\n", MAN_DIR, dp);
-                       pg_error_internal();
-                       exit(EXIT_FAILURE);
-               }
-               req->p[req->psz++] = dp;
-       }
-
-       if ( req->p == NULL ) {
-               fprintf(stderr, "%s/manpath.conf is empty\n", MAN_DIR);
-               pg_error_internal();
-               exit(EXIT_FAILURE);
-       }
-}
diff --git a/contrib/mdocml/cgi.h.example b/contrib/mdocml/cgi.h.example
deleted file mode 100644 (file)
index f4c7831..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Example compile-time configuration file for man.cgi(8). */
-
-#define        HTTP_HOST "mdocml.bsd.lv"
-#define        MAN_DIR "/var/www/man"
-#define        CSS_DIR ""
-#define        CUSTOMIZE_TITLE "Manual pages with mandoc"
-#define        CUSTOMIZE_BEGIN "<H2>\nManual pages with " \
-       "<A HREF=\"http://mdocml.bsd.lv/\">mandoc</A>\n</H2>"
-#define        COMPAT_OLDURI Yes
index d758d0c..24166db 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: chars.c,v 1.58 2014/07/23 15:00:08 schwarze Exp $ */
+/*     $Id: chars.c,v 1.78 2018/12/15 19:30:26 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * 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 <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "mandoc.h"
 #include "mandoc_aux.h"
+#include "mandoc_ohash.h"
 #include "libmandoc.h"
 
-#define        PRINT_HI         126
-#define        PRINT_LO         32
-
 struct ln {
-       struct ln        *next;
-       const char       *code;
+       const char        roffcode[16];
        const char       *ascii;
        int               unicode;
 };
 
-#define        LINES_MAX         330
-
-#define CHAR(in, ch, code) \
-       { NULL, (in), (ch), (code) },
-
-#define        CHAR_TBL_START    static struct ln lines[LINES_MAX] = {
-#define        CHAR_TBL_END      };
-
-#include "chars.in"
-
-struct mchars {
-       struct ln       **htab;
+/* Special break control characters. */
+static const char ascii_nbrsp[2] = { ASCII_NBRSP, '\0' };
+static const char ascii_break[2] = { ASCII_BREAK, '\0' };
+
+static struct ln lines[] = {
+
+       /* Spacing. */
+       { " ",                  ascii_nbrsp,    0x00a0  },
+       { "~",                  ascii_nbrsp,    0x00a0  },
+       { "0",                  " ",            0x2002  },
+       { ":",                  ascii_break,    0       },
+
+       /* Lines. */
+       { "ba",                 "|",            0x007c  },
+       { "br",                 "|",            0x2502  },
+       { "ul",                 "_",            0x005f  },
+       { "_",                  "_",            0x005f  },
+       { "ru",                 "_",            0x005f  },
+       { "rn",                 "-",            0x203e  },
+       { "bb",                 "|",            0x00a6  },
+       { "sl",                 "/",            0x002f  },
+       { "rs",                 "\\",           0x005c  },
+
+       /* Text markers. */
+       { "ci",                 "O",            0x25cb  },
+       { "bu",                 "+\bo",         0x2022  },
+       { "dd",                 "<**>",         0x2021  },
+       { "dg",                 "<*>",          0x2020  },
+       { "lz",                 "<>",           0x25ca  },
+       { "sq",                 "[]",           0x25a1  },
+       { "ps",                 "<paragraph>",  0x00b6  },
+       { "sc",                 "<section>",    0x00a7  },
+       { "lh",                 "<=",           0x261c  },
+       { "rh",                 "=>",           0x261e  },
+       { "at",                 "@",            0x0040  },
+       { "sh",                 "#",            0x0023  },
+       { "CR",                 "<cr>",         0x21b5  },
+       { "OK",                 "\\/",          0x2713  },
+       { "CL",                 "C",            0x2663  },
+       { "SP",                 "S",            0x2660  },
+       { "HE",                 "H",            0x2665  },
+       { "DI",                 "D",            0x2666  },
+
+       /* Legal symbols. */
+       { "co",                 "(C)",          0x00a9  },
+       { "rg",                 "(R)",          0x00ae  },
+       { "tm",                 "tm",           0x2122  },
+
+       /* Punctuation. */
+       { "em",                 "--",           0x2014  },
+       { "en",                 "-",            0x2013  },
+       { "hy",                 "-",            0x2010  },
+       { "e",                  "\\",           0x005c  },
+       { ".",                  ".",            0x002e  },
+       { "r!",                 "!",            0x00a1  },
+       { "r?",                 "?",            0x00bf  },
+
+       /* Quotes. */
+       { "Bq",                 ",,",           0x201e  },
+       { "bq",                 ",",            0x201a  },
+       { "lq",                 "\"",           0x201c  },
+       { "rq",                 "\"",           0x201d  },
+       { "Lq",                 "\"",           0x201c  },
+       { "Rq",                 "\"",           0x201d  },
+       { "oq",                 "`",            0x2018  },
+       { "cq",                 "\'",           0x2019  },
+       { "aq",                 "\'",           0x0027  },
+       { "dq",                 "\"",           0x0022  },
+       { "Fo",                 "<<",           0x00ab  },
+       { "Fc",                 ">>",           0x00bb  },
+       { "fo",                 "<",            0x2039  },
+       { "fc",                 ">",            0x203a  },
+
+       /* Brackets. */
+       { "lB",                 "[",            0x005b  },
+       { "rB",                 "]",            0x005d  },
+       { "lC",                 "{",            0x007b  },
+       { "rC",                 "}",            0x007d  },
+       { "la",                 "<",            0x27e8  },
+       { "ra",                 ">",            0x27e9  },
+       { "bv",                 "|",            0x23aa  },
+       { "braceex",            "|",            0x23aa  },
+       { "bracketlefttp",      "|",            0x23a1  },
+       { "bracketleftbt",      "|",            0x23a3  },
+       { "bracketleftex",      "|",            0x23a2  },
+       { "bracketrighttp",     "|",            0x23a4  },
+       { "bracketrightbt",     "|",            0x23a6  },
+       { "bracketrightex",     "|",            0x23a5  },
+       { "lt",                 ",-",           0x23a7  },
+       { "bracelefttp",        ",-",           0x23a7  },
+       { "lk",                 "{",            0x23a8  },
+       { "braceleftmid",       "{",            0x23a8  },
+       { "lb",                 "`-",           0x23a9  },
+       { "braceleftbt",        "`-",           0x23a9  },
+       { "braceleftex",        "|",            0x23aa  },
+       { "rt",                 "-.",           0x23ab  },
+       { "bracerighttp",       "-.",           0x23ab  },
+       { "rk",                 "}",            0x23ac  },
+       { "bracerightmid",      "}",            0x23ac  },
+       { "rb",                 "-\'",          0x23ad  },
+       { "bracerightbt",       "-\'",          0x23ad  },
+       { "bracerightex",       "|",            0x23aa  },
+       { "parenlefttp",        "/",            0x239b  },
+       { "parenleftbt",        "\\",           0x239d  },
+       { "parenleftex",        "|",            0x239c  },
+       { "parenrighttp",       "\\",           0x239e  },
+       { "parenrightbt",       "/",            0x23a0  },
+       { "parenrightex",       "|",            0x239f  },
+
+       /* Arrows and lines. */
+       { "<-",                 "<-",           0x2190  },
+       { "->",                 "->",           0x2192  },
+       { "<>",                 "<->",          0x2194  },
+       { "da",                 "|\bv",         0x2193  },
+       { "ua",                 "|\b^",         0x2191  },
+       { "va",                 "^v",           0x2195  },
+       { "lA",                 "<=",           0x21d0  },
+       { "rA",                 "=>",           0x21d2  },
+       { "hA",                 "<=>",          0x21d4  },
+       { "uA",                 "=\b^",         0x21d1  },
+       { "dA",                 "=\bv",         0x21d3  },
+       { "vA",                 "^=v",          0x21d5  },
+       { "an",                 "-",            0x23af  },
+
+       /* Logic. */
+       { "AN",                 "^",            0x2227  },
+       { "OR",                 "v",            0x2228  },
+       { "no",                 "~",            0x00ac  },
+       { "tno",                "~",            0x00ac  },
+       { "te",                 "<there\037exists>", 0x2203 },
+       { "fa",                 "<for\037all>", 0x2200  },
+       { "st",                 "<such\037that>", 0x220b },
+       { "tf",                 "<therefore>",  0x2234  },
+       { "3d",                 "<therefore>",  0x2234  },
+       { "or",                 "|",            0x007c  },
+
+       /* Mathematicals. */
+       { "pl",                 "+",            0x002b  },
+       { "mi",                 "-",            0x2212  },
+       { "-",                  "-",            0x002d  },
+       { "-+",                 "-+",           0x2213  },
+       { "+-",                 "+-",           0x00b1  },
+       { "t+-",                "+-",           0x00b1  },
+       { "pc",                 ".",            0x00b7  },
+       { "md",                 ".",            0x22c5  },
+       { "mu",                 "x",            0x00d7  },
+       { "tmu",                "x",            0x00d7  },
+       { "c*",                 "O\bx",         0x2297  },
+       { "c+",                 "O\b+",         0x2295  },
+       { "di",                 "/",            0x00f7  },
+       { "tdi",                "/",            0x00f7  },
+       { "f/",                 "/",            0x2044  },
+       { "**",                 "*",            0x2217  },
+       { "<=",                 "<=",           0x2264  },
+       { ">=",                 ">=",           0x2265  },
+       { "<<",                 "<<",           0x226a  },
+       { ">>",                 ">>",           0x226b  },
+       { "eq",                 "=",            0x003d  },
+       { "!=",                 "!=",           0x2260  },
+       { "==",                 "==",           0x2261  },
+       { "ne",                 "!==",          0x2262  },
+       { "ap",                 "~",            0x223c  },
+       { "|=",                 "-~",           0x2243  },
+       { "=~",                 "=~",           0x2245  },
+       { "~~",                 "~~",           0x2248  },
+       { "~=",                 "~=",           0x2248  },
+       { "pt",                 "<proportional\037to>", 0x221d },
+       { "es",                 "{}",           0x2205  },
+       { "mo",                 "<element\037of>", 0x2208 },
+       { "nm",                 "<not\037element\037of>", 0x2209 },
+       { "sb",                 "<proper\037subset>", 0x2282 },
+       { "nb",                 "<not\037subset>", 0x2284 },
+       { "sp",                 "<proper\037superset>", 0x2283 },
+       { "nc",                 "<not\037superset>", 0x2285 },
+       { "ib",                 "<subset\037or\037equal>", 0x2286 },
+       { "ip",                 "<superset\037or\037equal>", 0x2287 },
+       { "ca",                 "<intersection>", 0x2229 },
+       { "cu",                 "<union>",      0x222a  },
+       { "/_",                 "<angle>",      0x2220  },
+       { "pp",                 "<perpendicular>", 0x22a5 },
+       { "is",                 "<integral>",   0x222b  },
+       { "integral",           "<integral>",   0x222b  },
+       { "sum",                "<sum>",        0x2211  },
+       { "product",            "<product>",    0x220f  },
+       { "coproduct",          "<coproduct>",  0x2210  },
+       { "gr",                 "<nabla>",      0x2207  },
+       { "sr",                 "<sqrt>",       0x221a  },
+       { "sqrt",               "<sqrt>",       0x221a  },
+       { "lc",                 "|~",           0x2308  },
+       { "rc",                 "~|",           0x2309  },
+       { "lf",                 "|_",           0x230a  },
+       { "rf",                 "_|",           0x230b  },
+       { "if",                 "<infinity>",   0x221e  },
+       { "Ah",                 "<Aleph>",      0x2135  },
+       { "Im",                 "<Im>",         0x2111  },
+       { "Re",                 "<Re>",         0x211c  },
+       { "wp",                 "p",            0x2118  },
+       { "pd",                 "<del>",        0x2202  },
+       { "-h",                 "/h",           0x210f  },
+       { "hbar",               "/h",           0x210f  },
+       { "12",                 "1/2",          0x00bd  },
+       { "14",                 "1/4",          0x00bc  },
+       { "34",                 "3/4",          0x00be  },
+       { "18",                 "1/8",          0x215B  },
+       { "38",                 "3/8",          0x215C  },
+       { "58",                 "5/8",          0x215D  },
+       { "78",                 "7/8",          0x215E  },
+       { "S1",                 "^1",           0x00B9  },
+       { "S2",                 "^2",           0x00B2  },
+       { "S3",                 "^3",           0x00B3  },
+
+       /* Ligatures. */
+       { "ff",                 "ff",           0xfb00  },
+       { "fi",                 "fi",           0xfb01  },
+       { "fl",                 "fl",           0xfb02  },
+       { "Fi",                 "ffi",          0xfb03  },
+       { "Fl",                 "ffl",          0xfb04  },
+       { "AE",                 "AE",           0x00c6  },
+       { "ae",                 "ae",           0x00e6  },
+       { "OE",                 "OE",           0x0152  },
+       { "oe",                 "oe",           0x0153  },
+       { "ss",                 "ss",           0x00df  },
+       { "IJ",                 "IJ",           0x0132  },
+       { "ij",                 "ij",           0x0133  },
+
+       /* Accents. */
+       { "a\"",                "\"",           0x02dd  },
+       { "a-",                 "-",            0x00af  },
+       { "a.",                 ".",            0x02d9  },
+       { "a^",                 "^",            0x005e  },
+       { "aa",                 "\'",           0x00b4  },
+       { "\'",                 "\'",           0x00b4  },
+       { "ga",                 "`",            0x0060  },
+       { "`",                  "`",            0x0060  },
+       { "ab",                 "'\b`",         0x02d8  },
+       { "ac",                 ",",            0x00b8  },
+       { "ad",                 "\"",           0x00a8  },
+       { "ah",                 "v",            0x02c7  },
+       { "ao",                 "o",            0x02da  },
+       { "a~",                 "~",            0x007e  },
+       { "ho",                 ",",            0x02db  },
+       { "ha",                 "^",            0x005e  },
+       { "ti",                 "~",            0x007e  },
+       { "u02DC",              "~",            0x02dc  },
+
+       /* Accented letters. */
+       { "'A",                 "'\bA",         0x00c1  },
+       { "'E",                 "'\bE",         0x00c9  },
+       { "'I",                 "'\bI",         0x00cd  },
+       { "'O",                 "'\bO",         0x00d3  },
+       { "'U",                 "'\bU",         0x00da  },
+       { "'Y",                 "'\bY",         0x00dd  },
+       { "'a",                 "'\ba",         0x00e1  },
+       { "'e",                 "'\be",         0x00e9  },
+       { "'i",                 "'\bi",         0x00ed  },
+       { "'o",                 "'\bo",         0x00f3  },
+       { "'u",                 "'\bu",         0x00fa  },
+       { "'y",                 "'\by",         0x00fd  },
+       { "`A",                 "`\bA",         0x00c0  },
+       { "`E",                 "`\bE",         0x00c8  },
+       { "`I",                 "`\bI",         0x00cc  },
+       { "`O",                 "`\bO",         0x00d2  },
+       { "`U",                 "`\bU",         0x00d9  },
+       { "`a",                 "`\ba",         0x00e0  },
+       { "`e",                 "`\be",         0x00e8  },
+       { "`i",                 "`\bi",         0x00ec  },
+       { "`o",                 "`\bo",         0x00f2  },
+       { "`u",                 "`\bu",         0x00f9  },
+       { "~A",                 "~\bA",         0x00c3  },
+       { "~N",                 "~\bN",         0x00d1  },
+       { "~O",                 "~\bO",         0x00d5  },
+       { "~a",                 "~\ba",         0x00e3  },
+       { "~n",                 "~\bn",         0x00f1  },
+       { "~o",                 "~\bo",         0x00f5  },
+       { ":A",                 "\"\bA",        0x00c4  },
+       { ":E",                 "\"\bE",        0x00cb  },
+       { ":I",                 "\"\bI",        0x00cf  },
+       { ":O",                 "\"\bO",        0x00d6  },
+       { ":U",                 "\"\bU",        0x00dc  },
+       { ":a",                 "\"\ba",        0x00e4  },
+       { ":e",                 "\"\be",        0x00eb  },
+       { ":i",                 "\"\bi",        0x00ef  },
+       { ":o",                 "\"\bo",        0x00f6  },
+       { ":u",                 "\"\bu",        0x00fc  },
+       { ":y",                 "\"\by",        0x00ff  },
+       { "^A",                 "^\bA",         0x00c2  },
+       { "^E",                 "^\bE",         0x00ca  },
+       { "^I",                 "^\bI",         0x00ce  },
+       { "^O",                 "^\bO",         0x00d4  },
+       { "^U",                 "^\bU",         0x00db  },
+       { "^a",                 "^\ba",         0x00e2  },
+       { "^e",                 "^\be",         0x00ea  },
+       { "^i",                 "^\bi",         0x00ee  },
+       { "^o",                 "^\bo",         0x00f4  },
+       { "^u",                 "^\bu",         0x00fb  },
+       { ",C",                 ",\bC",         0x00c7  },
+       { ",c",                 ",\bc",         0x00e7  },
+       { "/L",                 "/\bL",         0x0141  },
+       { "/l",                 "/\bl",         0x0142  },
+       { "/O",                 "/\bO",         0x00d8  },
+       { "/o",                 "/\bo",         0x00f8  },
+       { "oA",                 "o\bA",         0x00c5  },
+       { "oa",                 "o\ba",         0x00e5  },
+
+       /* Special letters. */
+       { "-D",                 "Dh",           0x00d0  },
+       { "Sd",                 "dh",           0x00f0  },
+       { "TP",                 "Th",           0x00de  },
+       { "Tp",                 "th",           0x00fe  },
+       { ".i",                 "i",            0x0131  },
+       { ".j",                 "j",            0x0237  },
+
+       /* Currency. */
+       { "Do",                 "$",            0x0024  },
+       { "ct",                 "/\bc",         0x00a2  },
+       { "Eu",                 "EUR",          0x20ac  },
+       { "eu",                 "EUR",          0x20ac  },
+       { "Ye",                 "=\bY",         0x00a5  },
+       { "Po",                 "-\bL",         0x00a3  },
+       { "Cs",                 "o\bx",         0x00a4  },
+       { "Fn",                 ",\bf",         0x0192  },
+
+       /* Units. */
+       { "de",                 "<degree>",     0x00b0  },
+       { "%0",                 "<permille>",   0x2030  },
+       { "fm",                 "\'",           0x2032  },
+       { "sd",                 "''",           0x2033  },
+       { "mc",                 "<micro>",      0x00b5  },
+       { "Of",                 "_\ba",         0x00aa  },
+       { "Om",                 "_\bo",         0x00ba  },
+
+       /* Greek characters. */
+       { "*A",                 "A",            0x0391  },
+       { "*B",                 "B",            0x0392  },
+       { "*G",                 "<Gamma>",      0x0393  },
+       { "*D",                 "<Delta>",      0x0394  },
+       { "*E",                 "E",            0x0395  },
+       { "*Z",                 "Z",            0x0396  },
+       { "*Y",                 "H",            0x0397  },
+       { "*H",                 "<Theta>",      0x0398  },
+       { "*I",                 "I",            0x0399  },
+       { "*K",                 "K",            0x039a  },
+       { "*L",                 "<Lambda>",     0x039b  },
+       { "*M",                 "M",            0x039c  },
+       { "*N",                 "N",            0x039d  },
+       { "*C",                 "<Xi>",         0x039e  },
+       { "*O",                 "O",            0x039f  },
+       { "*P",                 "<Pi>",         0x03a0  },
+       { "*R",                 "P",            0x03a1  },
+       { "*S",                 "<Sigma>",      0x03a3  },
+       { "*T",                 "T",            0x03a4  },
+       { "*U",                 "Y",            0x03a5  },
+       { "*F",                 "<Phi>",        0x03a6  },
+       { "*X",                 "X",            0x03a7  },
+       { "*Q",                 "<Psi>",        0x03a8  },
+       { "*W",                 "<Omega>",      0x03a9  },
+       { "*a",                 "<alpha>",      0x03b1  },
+       { "*b",                 "<beta>",       0x03b2  },
+       { "*g",                 "<gamma>",      0x03b3  },
+       { "*d",                 "<delta>",      0x03b4  },
+       { "*e",                 "<epsilon>",    0x03b5  },
+       { "*z",                 "<zeta>",       0x03b6  },
+       { "*y",                 "<eta>",        0x03b7  },
+       { "*h",                 "<theta>",      0x03b8  },
+       { "*i",                 "<iota>",       0x03b9  },
+       { "*k",                 "<kappa>",      0x03ba  },
+       { "*l",                 "<lambda>",     0x03bb  },
+       { "*m",                 "<mu>",         0x03bc  },
+       { "*n",                 "<nu>",         0x03bd  },
+       { "*c",                 "<xi>",         0x03be  },
+       { "*o",                 "o",            0x03bf  },
+       { "*p",                 "<pi>",         0x03c0  },
+       { "*r",                 "<rho>",        0x03c1  },
+       { "*s",                 "<sigma>",      0x03c3  },
+       { "*t",                 "<tau>",        0x03c4  },
+       { "*u",                 "<upsilon>",    0x03c5  },
+       { "*f",                 "<phi>",        0x03d5  },
+       { "*x",                 "<chi>",        0x03c7  },
+       { "*q",                 "<psi>",        0x03c8  },
+       { "*w",                 "<omega>",      0x03c9  },
+       { "+h",                 "<theta>",      0x03d1  },
+       { "+f",                 "<phi>",        0x03c6  },
+       { "+p",                 "<pi>",         0x03d6  },
+       { "+e",                 "<epsilon>",    0x03f5  },
+       { "ts",                 "<sigma>",      0x03c2  },
 };
 
-static const struct ln  *find(const struct mchars *,
-                               const char *, size_t);
+static struct ohash      mchars;
 
 
 void
-mchars_free(struct mchars *arg)
+mchars_free(void)
 {
 
-       free(arg->htab);
-       free(arg);
+       ohash_delete(&mchars);
 }
 
-struct mchars *
+void
 mchars_alloc(void)
 {
-       struct mchars    *tab;
-       struct ln       **htab;
-       struct ln        *pp;
-       int               i, hash;
-
-       /*
-        * Constructs a very basic chaining hashtable.  The hash routine
-        * is simply the integral value of the first character.
-        * Subsequent entries are chained in the order they're processed.
-        */
-
-       tab = mandoc_malloc(sizeof(struct mchars));
-       htab = mandoc_calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln *));
-
-       for (i = 0; i < LINES_MAX; i++) {
-               hash = (int)lines[i].code[0] - PRINT_LO;
-
-               if (NULL == (pp = htab[hash])) {
-                       htab[hash] = &lines[i];
-                       continue;
-               }
-
-               for ( ; pp->next; pp = pp->next)
-                       /* Scan ahead. */ ;
-               pp->next = &lines[i];
+       size_t            i;
+       unsigned int      slot;
+
+       mandoc_ohash_init(&mchars, 9, offsetof(struct ln, roffcode));
+       for (i = 0; i < sizeof(lines)/sizeof(lines[0]); i++) {
+               slot = ohash_qlookup(&mchars, lines[i].roffcode);
+               assert(ohash_find(&mchars, slot) == NULL);
+               ohash_insert(&mchars, slot, lines + i);
        }
-
-       tab->htab = htab;
-       return(tab);
 }
 
 int
-mchars_spec2cp(const struct mchars *arg, const char *p, size_t sz)
+mchars_spec2cp(const char *p, size_t sz)
 {
        const struct ln *ln;
+       const char      *end;
 
-       ln = find(arg, p, sz);
-       if (NULL == ln)
-               return(-1);
-       return(ln->unicode);
+       end = p + sz;
+       ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end));
+       return ln != NULL ? ln->unicode : -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,56 +474,33 @@ 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 *
-mchars_spec2str(const struct mchars *arg,
-               const char *p, size_t sz, size_t *rsz)
+mchars_spec2str(const char *p, size_t sz, size_t *rsz)
 {
        const struct ln *ln;
+       const char      *end;
 
-       ln = find(arg, p, sz);
-       if (NULL == ln) {
-               *rsz = 1;
-               return(NULL);
-       }
+       end = p + sz;
+       ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end));
+       if (ln == NULL)
+               return NULL;
 
        *rsz = strlen(ln->ascii);
-       return(ln->ascii);
+       return ln->ascii;
 }
 
-static const struct ln *
-find(const struct mchars *tab, const char *p, size_t sz)
+const char *
+mchars_uc2str(int uc)
 {
-       const struct ln  *pp;
-       int               hash;
-
-       assert(p);
-
-       if (0 == sz || p[0] < PRINT_LO || p[0] > PRINT_HI)
-               return(NULL);
-
-       hash = (int)p[0] - PRINT_LO;
-
-       for (pp = tab->htab[hash]; pp; pp = pp->next)
-               if (0 == strncmp(pp->code, p, sz) &&
-                   '\0' == pp->code[(int)sz])
-                       return(pp);
+       size_t    i;
 
-       return(NULL);
+       for (i = 0; i < sizeof(lines)/sizeof(lines[0]); i++)
+               if (uc == lines[i].unicode)
+                       return lines[i].ascii;
+       return "<?>";
 }
diff --git a/contrib/mdocml/chars.in b/contrib/mdocml/chars.in
deleted file mode 100644 (file)
index 098504f..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-/*     $Id: chars.in,v 1.46 2014/04/20 16:46:04 schwarze Exp $ */
-/*
- * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * The ASCII translation tables.
- *
- * The left-hand side corresponds to the input sequence (\x, \(xx, \*(xx
- * and so on) whose length is listed second element.  The right-hand
- * side is what's produced by the front-end, with the fourth element
- * being its length.
- *
- * XXX - C-escape strings!
- * XXX - update LINES_MAX if adding more!
- */
-
-/* Special break control characters. */
-static const char ascii_nbrsp[2] = { ASCII_NBRSP, '\0' };
-static const char ascii_break[2] = { ASCII_BREAK, '\0' };
-
-CHAR_TBL_START
-
-/* Spacing. */
-CHAR(" ",                      ascii_nbrsp,    160)
-CHAR("~",                      ascii_nbrsp,    160)
-CHAR("0",                      " ",            8194)
-CHAR("|",                      "",             0)
-CHAR("^",                      "",             0)
-CHAR("&",                      "",             0)
-CHAR("%",                      "",             0)
-CHAR(":",                      ascii_break,    0)
-/* XXX The following three do not really belong into this file. */
-CHAR("t",                      "",             0)
-CHAR("c",                      "",             0)
-CHAR("}",                      "",             0)
-
-/* Accents. */
-CHAR("a\"",                    "\"",           733)
-CHAR("a-",                     "-",            175)
-CHAR("a.",                     ".",            729)
-CHAR("a^",                     "^",            94)
-CHAR("\'",                     "\'",           180)
-CHAR("aa",                     "\'",           180)
-CHAR("ga",                     "`",            96)
-CHAR("`",                      "`",            96)
-CHAR("ab",                     "`",            728)
-CHAR("ac",                     ",",            184)
-CHAR("ad",                     "\"",           168)
-CHAR("ah",                     "v",            711)
-CHAR("ao",                     "o",            730)
-CHAR("a~",                     "~",            126)
-CHAR("ho",                     ",",            731)
-CHAR("ha",                     "^",            94)
-CHAR("ti",                     "~",            126)
-
-/* Quotes. */
-CHAR("Bq",                     ",,",           8222)
-CHAR("bq",                     ",",            8218)
-CHAR("lq",                     "``",           8220)
-CHAR("rq",                     "\'\'",         8221)
-CHAR("oq",                     "`",            8216)
-CHAR("cq",                     "\'",           8217)
-CHAR("aq",                     "\'",           39)
-CHAR("dq",                     "\"",           34)
-CHAR("Fo",                     "<<",           171)
-CHAR("Fc",                     ">>",           187)
-CHAR("fo",                     "<",            8249)
-CHAR("fc",                     ">",            8250)
-
-/* Brackets. */
-CHAR("lB",                     "[",            91)
-CHAR("rB",                     "]",            93)
-CHAR("lC",                     "{",            123)
-CHAR("rC",                     "}",            125)
-CHAR("la",                     "<",            60)
-CHAR("ra",                     ">",            62)
-CHAR("bv",                     "|",            9130)
-CHAR("braceex",                        "|",            9130)
-CHAR("bracketlefttp",          "|",            9121)
-CHAR("bracketleftbp",          "|",            9123)
-CHAR("bracketleftex",          "|",            9122)
-CHAR("bracketrighttp",         "|",            9124)
-CHAR("bracketrightbp",         "|",            9126)
-CHAR("bracketrightex",         "|",            9125)
-CHAR("lt",                     ",-",           9127)
-CHAR("bracelefttp",            ",-",           9127)
-CHAR("lk",                     "{",            9128)
-CHAR("braceleftmid",           "{",            9128)
-CHAR("lb",                     ",-",           9129)
-CHAR("braceleftbp",            "`-",           9129)
-CHAR("braceleftex",            "|",            9130)
-CHAR("rt",                     "-.",           9131)
-CHAR("bracerighttp",           "-.",           9131)
-CHAR("rk",                     "}",            9132)
-CHAR("bracerightmid",          "}",            9132)
-CHAR("rb",                     "-\'",          9133)
-CHAR("bracerightbp",           "-\'",          9133)
-CHAR("bracerightex",           "|",            9130)
-CHAR("parenlefttp",            "/",            9115)
-CHAR("parenleftbp",            "\\",           9117)
-CHAR("parenleftex",            "|",            9116)
-CHAR("parenrighttp",           "\\",           9118)
-CHAR("parenrightbp",           "/",            9120)
-CHAR("parenrightex",           "|",            9119)
-
-/* Greek characters. */
-CHAR("*A",                     "A",            913)
-CHAR("*B",                     "B",            914)
-CHAR("*G",                     "|",            915)
-CHAR("*D",                     "/\\",          916)
-CHAR("*E",                     "E",            917)
-CHAR("*Z",                     "Z",            918)
-CHAR("*Y",                     "H",            919)
-CHAR("*H",                     "O",            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("*O",                     "O",            927)
-CHAR("*P",                     "TT",           928)
-CHAR("*R",                     "P",            929)
-CHAR("*S",                     ">",            931)
-CHAR("*T",                     "T",            932)
-CHAR("*U",                     "Y",            933)
-CHAR("*F",                     "O_",           934)
-CHAR("*X",                     "X",            935)
-CHAR("*Q",                     "Y",            936)
-CHAR("*W",                     "O",            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("*y",                     "n",            951)
-CHAR("*h",                     "0",            952)
-CHAR("*i",                     "i",            953)
-CHAR("*k",                     "k",            954)
-CHAR("*l",                     "\\",           955)
-CHAR("*m",                     "u",            956)
-CHAR("*n",                     "v",            957)
-CHAR("*c",                     "E",            958)
-CHAR("*o",                     "o",            959)
-CHAR("*p",                     "n",            960)
-CHAR("*r",                     "p",            961)
-CHAR("*s",                     "o",            963)
-CHAR("*t",                     "t",            964)
-CHAR("*u",                     "u",            965)
-CHAR("*f",                     "o",            981)
-CHAR("*x",                     "x",            967)
-CHAR("*q",                     "u",            968)
-CHAR("*w",                     "w",            969)
-CHAR("+h",                     "0",            977)
-CHAR("+f",                     "o",            966)
-CHAR("+p",                     "w",            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)
-
-/* Arrows and lines. */
-CHAR("<-",                     "<-",           8592)
-CHAR("->",                     "->",           8594)
-CHAR("<>",                     "<>",           8596)
-CHAR("da",                     "v",            8595)
-CHAR("ua",                     "^",            8593)
-CHAR("va",                     "^v",           8597)
-CHAR("lA",                     "<=",           8656)
-CHAR("rA",                     "=>",           8658)
-CHAR("hA",                     "<=>",          8660)
-CHAR("dA",                     "v",            8659)
-CHAR("uA",                     "^",            8657)
-CHAR("vA",                     "^=v",          8661)
-
-/* Logic. */
-CHAR("AN",                     "^",            8743)
-CHAR("OR",                     "v",            8744)
-CHAR("no",                     "~",            172)
-CHAR("tno",                    "~",            172)
-CHAR("te",                     "3",            8707)
-CHAR("fa",                     "V",            8704)
-CHAR("st",                     "-)",           8715)
-CHAR("tf",                     ".:.",          8756)
-CHAR("3d",                     ".:.",          8756)
-CHAR("or",                     "|",            124)
-
-/* Mathematicals. */
-CHAR("pl",                     "+",            43)
-CHAR("mi",                     "-",            8722)
-CHAR("-",                      "-",            45)
-CHAR("-+",                     "-+",           8723)
-CHAR("+-",                     "+-",           177)
-CHAR("t+-",                    "+-",           177)
-CHAR("pc",                     ".",            183)
-CHAR("md",                     ".",            8901)
-CHAR("mu",                     "x",            215)
-CHAR("tmu",                    "x",            215)
-CHAR("c*",                     "x",            8855)
-CHAR("c+",                     "+",            8853)
-CHAR("di",                     "-:-",          247)
-CHAR("tdi",                    "-:-",          247)
-CHAR("f/",                     "/",            8260)
-CHAR("**",                     "*",            8727)
-CHAR("<=",                     "<=",           8804)
-CHAR(">=",                     ">=",           8805)
-CHAR("<<",                     "<<",           8810)
-CHAR(">>",                     ">>",           8811)
-CHAR("eq",                     "=",            61)
-CHAR("!=",                     "!=",           8800)
-CHAR("==",                     "==",           8801)
-CHAR("ne",                     "!==",          8802)
-CHAR("=~",                     "=~",           8773)
-CHAR("-~",                     "-~",           8771)
-CHAR("ap",                     "~",            8764)
-CHAR("~~",                     "~~",           8776)
-CHAR("~=",                     "~=",           8780)
-CHAR("pt",                     "oc",           8733)
-CHAR("es",                     "{}",           8709)
-CHAR("mo",                     "E",            8712)
-CHAR("nm",                     "!E",           8713)
-CHAR("sb",                     "(=",           8834)
-CHAR("nb",                     "(!=",          8836)
-CHAR("sp",                     "=)",           8835)
-CHAR("nc",                     "!=)",          8837)
-CHAR("ib",                     "(=",           8838)
-CHAR("ip",                     "=)",           8839)
-CHAR("ca",                     "(^)",          8745)
-CHAR("cu",                     "U",            8746)
-CHAR("/_",                     "/_",           8736)
-CHAR("pp",                     "_|_",          8869)
-CHAR("is",                     "I",            8747)
-CHAR("integral",               "I",            8747)
-CHAR("sum",                    "E",            8721)
-CHAR("product",                        "TT",           8719)
-CHAR("coproduct",              "U",            8720)
-CHAR("gr",                     "V",            8711)
-CHAR("sr",                     "\\/",          8730)
-CHAR("sqrt",                   "\\/",          8730)
-CHAR("lc",                     "|~",           8968)
-CHAR("rc",                     "~|",           8969)
-CHAR("lf",                     "|_",           8970)
-CHAR("rf",                     "_|",           8971)
-CHAR("if",                     "oo",           8734)
-CHAR("Ah",                     "N",            8501)
-CHAR("Im",                     "I",            8465)
-CHAR("Re",                     "R",            8476)
-CHAR("pd",                     "a",            8706)
-CHAR("-h",                     "/h",           8463)
-CHAR("12",                     "1/2",          189)
-CHAR("14",                     "1/4",          188)
-CHAR("34",                     "3/4",          190)
-
-/* Ligatures. */
-CHAR("ff",                     "ff",           64256)
-CHAR("fi",                     "fi",           64257)
-CHAR("fl",                     "fl",           64258)
-CHAR("Fi",                     "ffi",          64259)
-CHAR("Fl",                     "ffl",          64260)
-CHAR("AE",                     "AE",           198)
-CHAR("ae",                     "ae",           230)
-CHAR("OE",                     "OE",           338)
-CHAR("oe",                     "oe",           339)
-CHAR("ss",                     "ss",           223)
-CHAR("IJ",                     "IJ",           306)
-CHAR("ij",                     "ij",           307)
-
-/* Special letters. */
-CHAR("-D",                     "D",            208)
-CHAR("Sd",                     "o",            240)
-CHAR("TP",                     "b",            222)
-CHAR("Tp",                     "b",            254)
-CHAR(".i",                     "i",            305)
-CHAR(".j",                     "j",            567)
-
-/* Currency. */
-CHAR("Do",                     "$",            36)
-CHAR("ct",                     "c",            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)
-
-/* Lines. */
-CHAR("ba",                     "|",            124)
-CHAR("br",                     "|",            9474)
-CHAR("ul",                     "_",            95)
-CHAR("rl",                     "-",            8254)
-CHAR("bb",                     "|",            166)
-CHAR("sl",                     "/",            47)
-CHAR("rs",                     "\\",           92)
-
-/* Text markers. */
-CHAR("ci",                     "o",            9675)
-CHAR("bu",                     "o",            8226)
-CHAR("dd",                     "=",            8225)
-CHAR("dg",                     "-",            8224)
-CHAR("lz",                     "<>",           9674)
-CHAR("sq",                     "[]",           9633)
-CHAR("ps",                     "9|",           182)
-CHAR("sc",                     "S",            167)
-CHAR("lh",                     "<=",           9756)
-CHAR("rh",                     "=>",           9758)
-CHAR("at",                     "@",            64)
-CHAR("sh",                     "#",            35)
-CHAR("CR",                     "_|",           8629)
-CHAR("OK",                     "\\/",          10003)
-
-/* Legal symbols. */
-CHAR("co",                     "(C)",          169)
-CHAR("rg",                     "(R)",          174)
-CHAR("tm",                     "tm",           8482)
-
-/* Punctuation. */
-CHAR(".",                      ".",            46)
-CHAR("r!",                     "i",            161)
-CHAR("r?",                     "c",            191)
-CHAR("em",                     "--",           8212)
-CHAR("en",                     "-",            8211)
-CHAR("hy",                     "-",            8208)
-CHAR("e",                      "\\",           92)
-
-/* Units. */
-CHAR("de",                     "o",            176)
-CHAR("%0",                     "%o",           8240)
-CHAR("fm",                     "\'",           8242)
-CHAR("sd",                     "\"",           8243)
-CHAR("mc",                     "mu",           181)
-
-CHAR_TBL_END
diff --git a/contrib/mdocml/compat_fgetln.c b/contrib/mdocml/compat_fgetln.c
deleted file mode 100644 (file)
index 49c9985..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_FGETLN
-
-int dummy;
-
-#else
-
-/*     $NetBSD: fgetln.c,v 1.3 2006/09/25 07:18:17 lukem Exp $ */
-
-/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Christos Zoulas.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-char *
-fgetln(fp, len)
-       FILE *fp;
-       size_t *len;
-{
-       static char *buf = NULL;
-       static size_t bufsiz = 0;
-       char *ptr;
-
-
-       if (buf == NULL) {
-               bufsiz = BUFSIZ;
-               if ((buf = malloc(bufsiz)) == NULL)
-                       return NULL;
-       }
-
-       if (fgets(buf, bufsiz, fp) == NULL)
-               return NULL;
-
-       *len = 0;
-       while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
-               size_t nbufsiz = bufsiz + BUFSIZ;
-               char *nbuf = realloc(buf, nbufsiz);
-
-               if (nbuf == NULL) {
-                       int oerrno = errno;
-                       free(buf);
-                       errno = oerrno;
-                       buf = NULL;
-                       return NULL;
-               } else
-                       buf = nbuf;
-
-               *len = bufsiz;
-               if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL)
-                       return buf;
-
-               bufsiz = nbufsiz;
-       }
-
-       *len = (ptr - buf) + 1;
-       return buf;
-}
-
-#endif
diff --git a/contrib/mdocml/compat_getsubopt.c b/contrib/mdocml/compat_getsubopt.c
deleted file mode 100644 (file)
index 9cd4153..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_GETSUBOPT
-
-int dummy;
-
-#else
-
-/*     $OpenBSD: getsubopt.c,v 1.4 2005/08/08 08:05:36 espie Exp $     */
-
-/*-
- * Copyright (c) 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <unistd.h>
-#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 *p;
-
-       suboptarg = *valuep = NULL;
-
-       if (!optionp || !*optionp)
-               return(-1);
-
-       /* skip leading white-space, commas */
-       for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
-
-       if (!*p) {
-               *optionp = p;
-               return(-1);
-       }
-
-       /* save the start of the token, and skip the rest of the token. */
-       for (suboptarg = p;
-           *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
-
-       if (*p) {
-               /*
-                * If there's an equals sign, set the value pointer, and
-                * skip over the value part of the token.  Terminate the
-                * token.
-                */
-               if (*p == '=') {
-                       *p = '\0';
-                       for (*valuep = ++p;
-                           *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
-                       if (*p) 
-                               *p++ = '\0';
-               } else
-                       *p++ = '\0';
-               /* Skip any whitespace or commas after this token. */
-               for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
-       }
-
-       /* set optionp for next round. */
-       *optionp = p;
-
-       for (cnt = 0; *tokens; ++tokens, ++cnt)
-               if (!strcmp(suboptarg, *tokens))
-                       return(cnt);
-       return(-1);
-}
-
-#endif
index 0992b36..cbd6052 100644 (file)
@@ -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>
index e3124c9..58fb220 100644 (file)
@@ -49,7 +49,6 @@ struct ohash {
  * a hashing table index (opaque) to be used in find/insert/remove.
  * The keys are stored at a known position in the client data.
  */
-__BEGIN_DECLS
 void ohash_init(struct ohash *, unsigned, struct ohash_info *);
 void ohash_delete(struct ohash *);
 
@@ -69,5 +68,5 @@ uint32_t ohash_interval(const char *, const char **);
 
 unsigned int ohash_qlookupi(struct ohash *, const char *, const char **);
 unsigned int ohash_qlookup(struct ohash *, const char *);
-__END_DECLS
+
 #endif
diff --git a/contrib/mdocml/compat_reallocarray.c b/contrib/mdocml/compat_reallocarray.c
deleted file mode 100644 (file)
index e25d837..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_REALLOCARRAY
-
-int dummy;
-
-#else
-
-/*     $OpenBSD: malloc.c,v 1.158 2014/04/23 15:07:27 tedu Exp $       */
-/*
- * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/types.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
-
-void *
-reallocarray(void *optr, size_t nmemb, size_t size)
-{
-       if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
-           nmemb > 0 && SIZE_MAX / nmemb < size) {
-               errno = ENOMEM;
-               return NULL;
-       }
-       return realloc(optr, size * nmemb);
-}
-
-#endif /*!HAVE_REALLOCARRAY*/
diff --git a/contrib/mdocml/compat_recallocarray.c b/contrib/mdocml/compat_recallocarray.c
new file mode 100644 (file)
index 0000000..d86dc50
--- /dev/null
@@ -0,0 +1,108 @@
+#include "config.h"
+
+#if HAVE_RECALLOCARRAY
+
+int dummy;
+
+#else
+
+/*     $Id: compat_recallocarray.c,v 1.1 2017/06/12 19:05:47 schwarze Exp $ */
+/*     $OpenBSD: malloc.c,v 1.225 2017/05/13 07:11:29 otto Exp $ */
+/*
+ * Copyright (c) 2017 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW        ((size_t)1 << (sizeof(size_t) * 4))
+
+/*
+ * Even though specified in POSIX, the PAGESIZE and PAGE_SIZE
+ * macros have very poor portability.  Since we only use this
+ * to avoid free() overhead for small shrinking, simply pick
+ * an arbitrary number.
+ */
+#define MALLOC_PAGESIZE         (1UL << 12)
+
+
+void *
+recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
+{
+       size_t oldsize, newsize;
+       void *newptr;
+
+       if (ptr == NULL)
+               return calloc(newnmemb, size);
+
+       if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+           newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+               errno = ENOMEM;
+               return NULL;
+       }
+       newsize = newnmemb * size;
+
+       if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+           oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+               errno = EINVAL;
+               return NULL;
+       }
+       oldsize = oldnmemb * size;
+
+       /*
+        * Don't bother too much if we're shrinking just a bit,
+        * we do not shrink for series of small steps, oh well.
+        */
+       if (newsize <= oldsize) {
+               size_t d = oldsize - newsize;
+
+               if (d < oldsize / 2 && d < MALLOC_PAGESIZE) {
+                       memset((char *)ptr + newsize, 0, d);
+                       return ptr;
+               }
+       }
+
+       newptr = malloc(newsize);
+       if (newptr == NULL)
+               return NULL;
+
+       if (newsize > oldsize) {
+               memcpy(newptr, ptr, oldsize);
+               memset((char *)newptr + oldsize, 0, newsize - oldsize);
+       } else
+               memcpy(newptr, ptr, newsize);
+
+       /*
+        * At this point, the OpenBSD implementation calls
+        * explicit_bzero() on the old memory before it is
+        * freed.  Since explicit_bzero() is hard to implement
+        * portably and we don't handle confidential data in
+        * mandoc in the first place, simply free the memory
+        * without clearing it.
+        */
+
+       free(ptr);
+
+       return newptr;
+}
+
+#endif /* !HAVE_RECALLOCARRAY */
diff --git a/contrib/mdocml/compat_sqlite3_errstr.c b/contrib/mdocml/compat_sqlite3_errstr.c
deleted file mode 100644 (file)
index b8d6eb5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_SQLITE3_ERRSTR
-
-int dummy;
-
-#else
-
-const char *
-sqlite3_errstr(int rc)
-{
-
-       return(rc ? "unknown error" : "not an error");
-}
-
-#endif
diff --git a/contrib/mdocml/compat_strcasestr.c b/contrib/mdocml/compat_strcasestr.c
deleted file mode 100644 (file)
index 5216d02..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_STRCASESTR
-
-int dummy;
-
-#else
-
-/*     ($)NetBSD: strcasestr.c,v 1.2 2005/02/09 21:35:47 kleink Exp $ */
-
-/*-
- * Copyright (c) 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * 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/types.h>
-#include <ctype.h>
-#include <string.h>
-
-#define        __UNCONST(a)    ((void *)(unsigned long)(const void *)(a))
-
-/*
- * Find the first occurrence of find in s, ignore case.
- */
-char *
-strcasestr(const char *s, const char *find)
-{
-       char c, sc;
-       size_t len;
-
-       if ((c = *find++) != 0) {
-               c = tolower((unsigned char)c);
-               len = strlen(find);
-               do {
-                       do {
-                               if ((sc = *s++) == 0)
-                                       return (NULL);
-                       } while ((char)tolower((unsigned char)sc) != c);
-               } while (strncasecmp(s, find, len) != 0);
-               s--;
-       }
-       return __UNCONST(s);
-}
-
-#endif
diff --git a/contrib/mdocml/compat_strlcat.c b/contrib/mdocml/compat_strlcat.c
deleted file mode 100644 (file)
index 543d40b..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_STRLCAT
-
-int dummy;
-
-#else
-
-/*     $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $      */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Appends src to string dst of size siz (unlike strncat, siz is the
- * full size of dst, not space left).  At most siz-1 characters
- * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
- * Returns strlen(src) + MIN(siz, strlen(initial dst)).
- * If retval >= siz, truncation occurred.
- */
-size_t
-strlcat(char *dst, const char *src, size_t siz)
-{
-       char *d = dst;
-       const char *s = src;
-       size_t n = siz;
-       size_t dlen;
-
-       /* Find the end of dst and adjust bytes left but don't go past end */
-       while (n-- != 0 && *d != '\0')
-               d++;
-       dlen = d - dst;
-       n = siz - dlen;
-
-       if (n == 0)
-               return(dlen + strlen(s));
-       while (*s != '\0') {
-               if (n != 1) {
-                       *d++ = *s;
-                       n--;
-               }
-               s++;
-       }
-       *d = '\0';
-
-       return(dlen + (s - src));       /* count does not include NUL */
-}
-
-#endif
diff --git a/contrib/mdocml/compat_strlcpy.c b/contrib/mdocml/compat_strlcpy.c
deleted file mode 100644 (file)
index a7c64ff..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_STRLCPY
-
-int dummy;
-
-#else
-
-/*     $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $    */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-/*
- * Copy src to string dst of size siz.  At most siz-1 characters
- * will be copied.  Always NUL terminates (unless siz == 0).
- * Returns strlen(src); if retval >= siz, truncation occurred.
- */
-size_t
-strlcpy(char *dst, const char *src, size_t siz)
-{
-       char *d = dst;
-       const char *s = src;
-       size_t n = siz;
-
-       /* Copy as many bytes as will fit */
-       if (n != 0) {
-               while (--n != 0) {
-                       if ((*d++ = *s++) == '\0')
-                               break;
-               }
-       }
-
-       /* Not enough room in dst, add NUL and traverse rest of src */
-       if (n == 0) {
-               if (siz != 0)
-                       *d = '\0';              /* NUL-terminate dst */
-               while (*s++)
-                       ;
-       }
-
-       return(s - src - 1);    /* count does not include NUL */
-}
-
-#endif
diff --git a/contrib/mdocml/compat_strsep.c b/contrib/mdocml/compat_strsep.c
deleted file mode 100644 (file)
index a5c58c6..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_STRSEP
-
-int dummy;
-
-#else
-
-/*     ($)OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $      */
-
-/*-
- * Copyright (c) 1990, 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.
- */
-
-/*
- * Get next token from string *stringp, where tokens are possibly-empty
- * strings separated by characters from delim.  
- *
- * Writes NULs into the string at *stringp to end tokens.
- * delim need not remain constant from call to call.
- * On return, *stringp points past the last NUL written (if there might
- * be further tokens), or is NULL (if there are definitely no more tokens).
- *
- * If *stringp is NULL, strsep returns NULL.
- */
-char *
-strsep(char **stringp, const char *delim)
-{
-       char *s;
-       const char *spanp;
-       int c, sc;
-       char *tok;
-
-       if ((s = *stringp) == NULL)
-               return (NULL);
-       for (tok = s;;) {
-               c = *s++;
-               spanp = delim;
-               do {
-                       if ((sc = *spanp++) == c) {
-                               if (c == 0)
-                                       s = NULL;
-                               else
-                                       s[-1] = 0;
-                               *stringp = s;
-                               return (tok);
-                       }
-               } while (sc != 0);
-       }
-       /* NOTREACHED */
-}
-
-#endif
diff --git a/contrib/mdocml/config.h.post b/contrib/mdocml/config.h.post
deleted file mode 100644 (file)
index e95f5f5..0000000
+++ /dev/null
@@ -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 */
diff --git a/contrib/mdocml/config.h.pre b/contrib/mdocml/config.h.pre
deleted file mode 100644 (file)
index 1c3940d..0000000
+++ /dev/null
@@ -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>
diff --git a/contrib/mdocml/configure b/contrib/mdocml/configure
deleted file mode 100755 (executable)
index 5b987eb..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/sh
-#
-# 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.
-
-echo "/* RUNNING ./CONFIGURE - SHOULD BE USED ONLY VIA MAKE, READ INSTALL */"
-
-set -e
-exec > config.h 2> config.log
-
-CFLAGS="${CFLAGS} -Wno-unused -Werror"
-
-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}"
-}
-
-cat config.h.pre
-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
-echo
-cat config.h.post
-
-exit 0
diff --git a/contrib/mdocml/dba.c b/contrib/mdocml/dba.c
new file mode 100644 (file)
index 0000000..ee43933
--- /dev/null
@@ -0,0 +1,508 @@
+/*     $Id: dba.c,v 1.10 2017/02/17 14:43:54 schwarze Exp $ */
+/*
+ * Copyright (c) 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * 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.
+ *
+ * Allocation-based version of the mandoc database, for read-write access.
+ * The interface is defined in "dba.h".
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#if HAVE_ENDIAN
+#include <endian.h>
+#elif HAVE_SYS_ENDIAN
+#include <sys/endian.h>
+#elif HAVE_NTOHL
+#include <arpa/inet.h>
+#endif
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mandoc_aux.h"
+#include "mandoc_ohash.h"
+#include "mansearch.h"
+#include "dba_write.h"
+#include "dba_array.h"
+#include "dba.h"
+
+struct macro_entry {
+       struct dba_array        *pages;
+       char                     value[];
+};
+
+static void    *prepend(const char *, char);
+static void     dba_pages_write(struct dba_array *);
+static int      compare_names(const void *, const void *);
+static int      compare_strings(const void *, const void *);
+
+static struct macro_entry
+               *get_macro_entry(struct ohash *, const char *, int32_t);
+static void     dba_macros_write(struct dba_array *);
+static void     dba_macro_write(struct ohash *);
+static int      compare_entries(const void *, const void *);
+
+
+/*** top-level functions **********************************************/
+
+struct dba *
+dba_new(int32_t npages)
+{
+       struct dba      *dba;
+       struct ohash    *macro;
+       int32_t          im;
+
+       dba = mandoc_malloc(sizeof(*dba));
+       dba->pages = dba_array_new(npages, DBA_GROW);
+       dba->macros = dba_array_new(MACRO_MAX, 0);
+       for (im = 0; im < MACRO_MAX; im++) {
+               macro = mandoc_malloc(sizeof(*macro));
+               mandoc_ohash_init(macro, 4,
+                   offsetof(struct macro_entry, value));
+               dba_array_set(dba->macros, im, macro);
+       }
+       return dba;
+}
+
+void
+dba_free(struct dba *dba)
+{
+       struct dba_array        *page;
+       struct ohash            *macro;
+       struct macro_entry      *entry;
+       unsigned int             slot;
+
+       dba_array_FOREACH(dba->macros, macro) {
+               for (entry = ohash_first(macro, &slot); entry != NULL;
+                    entry = ohash_next(macro, &slot)) {
+                       dba_array_free(entry->pages);
+                       free(entry);
+               }
+               ohash_delete(macro);
+               free(macro);
+       }
+       dba_array_free(dba->macros);
+
+       dba_array_undel(dba->pages);
+       dba_array_FOREACH(dba->pages, page) {
+               dba_array_free(dba_array_get(page, DBP_NAME));
+               dba_array_free(dba_array_get(page, DBP_SECT));
+               dba_array_free(dba_array_get(page, DBP_ARCH));
+               free(dba_array_get(page, DBP_DESC));
+               dba_array_free(dba_array_get(page, DBP_FILE));
+               dba_array_free(page);
+       }
+       dba_array_free(dba->pages);
+
+       free(dba);
+}
+
+/*
+ * Write the complete mandoc database to disk; the format is:
+ * - One integer each for magic and version.
+ * - One pointer each to the macros table and to the final magic.
+ * - The pages table.
+ * - The macros table.
+ * - And at the very end, the magic integer again.
+ */
+int
+dba_write(const char *fname, struct dba *dba)
+{
+       int      save_errno;
+       int32_t  pos_end, pos_macros, pos_macros_ptr;
+
+       if (dba_open(fname) == -1)
+               return -1;
+       dba_int_write(MANDOCDB_MAGIC);
+       dba_int_write(MANDOCDB_VERSION);
+       pos_macros_ptr = dba_skip(1, 2);
+       dba_pages_write(dba->pages);
+       pos_macros = dba_tell();
+       dba_macros_write(dba->macros);
+       pos_end = dba_tell();
+       dba_int_write(MANDOCDB_MAGIC);
+       dba_seek(pos_macros_ptr);
+       dba_int_write(pos_macros);
+       dba_int_write(pos_end);
+       if (dba_close() == -1) {
+               save_errno = errno;
+               unlink(fname);
+               errno = save_errno;
+               return -1;
+       }
+       return 0;
+}
+
+
+/*** functions for handling pages *************************************/
+
+/*
+ * Create a new page and append it to the pages table.
+ */
+struct dba_array *
+dba_page_new(struct dba_array *pages, const char *arch,
+    const char *desc, const char *file, enum form form)
+{
+       struct dba_array *page, *entry;
+
+       page = dba_array_new(DBP_MAX, 0);
+       entry = dba_array_new(1, DBA_STR | DBA_GROW);
+       dba_array_add(page, entry);
+       entry = dba_array_new(1, DBA_STR | DBA_GROW);
+       dba_array_add(page, entry);
+       if (arch != NULL && *arch != '\0') {
+               entry = dba_array_new(1, DBA_STR | DBA_GROW);
+               dba_array_add(entry, (void *)arch);
+       } else
+               entry = NULL;
+       dba_array_add(page, entry);
+       dba_array_add(page, mandoc_strdup(desc));
+       entry = dba_array_new(1, DBA_STR | DBA_GROW);
+       dba_array_add(entry, prepend(file, form));
+       dba_array_add(page, entry);
+       dba_array_add(pages, page);
+       return page;
+}
+
+/*
+ * Add a section, architecture, or file name to an existing page.
+ * Passing the NULL pointer for the architecture makes the page MI.
+ * In that case, any earlier or later architectures are ignored.
+ */
+void
+dba_page_add(struct dba_array *page, int32_t ie, const char *str)
+{
+       struct dba_array        *entries;
+       char                    *entry;
+
+       entries = dba_array_get(page, ie);
+       if (ie == DBP_ARCH) {
+               if (entries == NULL)
+                       return;
+               if (str == NULL || *str == '\0') {
+                       dba_array_free(entries);
+                       dba_array_set(page, DBP_ARCH, NULL);
+                       return;
+               }
+       }
+       if (*str == '\0')
+               return;
+       dba_array_FOREACH(entries, entry) {
+               if (ie == DBP_FILE && *entry < ' ')
+                       entry++;
+               if (strcmp(entry, str) == 0)
+                       return;
+       }
+       dba_array_add(entries, (void *)str);
+}
+
+/*
+ * Add an additional name to an existing page.
+ */
+void
+dba_page_alias(struct dba_array *page, const char *name, uint64_t mask)
+{
+       struct dba_array        *entries;
+       char                    *entry;
+       char                     maskbyte;
+
+       if (*name == '\0')
+               return;
+       maskbyte = mask & NAME_MASK;
+       entries = dba_array_get(page, DBP_NAME);
+       dba_array_FOREACH(entries, entry) {
+               if (strcmp(entry + 1, name) == 0) {
+                       *entry |= maskbyte;
+                       return;
+               }
+       }
+       dba_array_add(entries, prepend(name, maskbyte));
+}
+
+/*
+ * Return a pointer to a temporary copy of instr with inbyte prepended.
+ */
+static void *
+prepend(const char *instr, char inbyte)
+{
+       static char     *outstr = NULL;
+       static size_t    outlen = 0;
+       size_t           newlen;
+
+       newlen = strlen(instr) + 1;
+       if (newlen > outlen) {
+               outstr = mandoc_realloc(outstr, newlen + 1);
+               outlen = newlen;
+       }
+       *outstr = inbyte;
+       memcpy(outstr + 1, instr, newlen);
+       return outstr;
+}
+
+/*
+ * Write the pages table to disk; the format is:
+ * - One integer containing the number of pages.
+ * - For each page, five pointers to the names, sections,
+ *   architectures, description, and file names of the page.
+ *   MI pages write 0 instead of the architecture pointer.
+ * - One list each for names, sections, architectures, descriptions and
+ *   file names.  The description for each page ends with a NUL byte.
+ *   For all the other lists, each string ends with a NUL byte,
+ *   and the last string for a page ends with two NUL bytes.
+ * - To assure alignment of following integers,
+ *   the end is padded with NUL bytes up to a multiple of four bytes.
+ */
+static void
+dba_pages_write(struct dba_array *pages)
+{
+       struct dba_array        *page, *entry;
+       int32_t                  pos_pages, pos_end;
+
+       pos_pages = dba_array_writelen(pages, 5);
+       dba_array_FOREACH(pages, page) {
+               dba_array_setpos(page, DBP_NAME, dba_tell());
+               entry = dba_array_get(page, DBP_NAME);
+               dba_array_sort(entry, compare_names);
+               dba_array_writelst(entry);
+       }
+       dba_array_FOREACH(pages, page) {
+               dba_array_setpos(page, DBP_SECT, dba_tell());
+               entry = dba_array_get(page, DBP_SECT);
+               dba_array_sort(entry, compare_strings);
+               dba_array_writelst(entry);
+       }
+       dba_array_FOREACH(pages, page) {
+               if ((entry = dba_array_get(page, DBP_ARCH)) != NULL) {
+                       dba_array_setpos(page, DBP_ARCH, dba_tell());
+                       dba_array_sort(entry, compare_strings);
+                       dba_array_writelst(entry);
+               } else
+                       dba_array_setpos(page, DBP_ARCH, 0);
+       }
+       dba_array_FOREACH(pages, page) {
+               dba_array_setpos(page, DBP_DESC, dba_tell());
+               dba_str_write(dba_array_get(page, DBP_DESC));
+       }
+       dba_array_FOREACH(pages, page) {
+               dba_array_setpos(page, DBP_FILE, dba_tell());
+               dba_array_writelst(dba_array_get(page, DBP_FILE));
+       }
+       pos_end = dba_align();
+       dba_seek(pos_pages);
+       dba_array_FOREACH(pages, page)
+               dba_array_writepos(page);
+       dba_seek(pos_end);
+}
+
+static int
+compare_names(const void *vp1, const void *vp2)
+{
+       const char      *cp1, *cp2;
+       int              diff;
+
+       cp1 = *(const char * const *)vp1;
+       cp2 = *(const char * const *)vp2;
+       return (diff = *cp2 - *cp1) ? diff :
+           strcasecmp(cp1 + 1, cp2 + 1);
+}
+
+static int
+compare_strings(const void *vp1, const void *vp2)
+{
+       const char      *cp1, *cp2;
+
+       cp1 = *(const char * const *)vp1;
+       cp2 = *(const char * const *)vp2;
+       return strcmp(cp1, cp2);
+}
+
+/*** functions for handling macros ************************************/
+
+/*
+ * In the hash table for a single macro, look up an entry by
+ * the macro value or add an empty one if it doesn't exist yet.
+ */
+static struct macro_entry *
+get_macro_entry(struct ohash *macro, const char *value, int32_t np)
+{
+       struct macro_entry      *entry;
+       size_t                   len;
+       unsigned int             slot;
+
+       slot = ohash_qlookup(macro, value);
+       if ((entry = ohash_find(macro, slot)) == NULL) {
+               len = strlen(value) + 1;
+               entry = mandoc_malloc(sizeof(*entry) + len);
+               memcpy(&entry->value, value, len);
+               entry->pages = dba_array_new(np, DBA_GROW);
+               ohash_insert(macro, slot, entry);
+       }
+       return entry;
+}
+
+/*
+ * In addition to get_macro_entry(), add multiple page references,
+ * converting them from the on-disk format (byte offsets in the file)
+ * to page pointers in memory.
+ */
+void
+dba_macro_new(struct dba *dba, int32_t im, const char *value,
+    const int32_t *pp)
+{
+       struct macro_entry      *entry;
+       const int32_t           *ip;
+       int32_t                  np;
+
+       np = 0;
+       for (ip = pp; *ip; ip++)
+               np++;
+
+       entry = get_macro_entry(dba_array_get(dba->macros, im), value, np);
+       for (ip = pp; *ip; ip++)
+               dba_array_add(entry->pages, dba_array_get(dba->pages,
+                   be32toh(*ip) / 5 / sizeof(*ip) - 1));
+}
+
+/*
+ * In addition to get_macro_entry(), add one page reference,
+ * directly taking the in-memory page pointer as an argument.
+ */
+void
+dba_macro_add(struct dba_array *macros, int32_t im, const char *value,
+    struct dba_array *page)
+{
+       struct macro_entry      *entry;
+
+       if (*value == '\0')
+               return;
+       entry = get_macro_entry(dba_array_get(macros, im), value, 1);
+       dba_array_add(entry->pages, page);
+}
+
+/*
+ * Write the macros table to disk; the format is:
+ * - The number of macro tables (actually, MACRO_MAX).
+ * - That number of pointers to the individual macro tables.
+ * - The individual macro tables.
+ */
+static void
+dba_macros_write(struct dba_array *macros)
+{
+       struct ohash            *macro;
+       int32_t                  im, pos_macros, pos_end;
+
+       pos_macros = dba_array_writelen(macros, 1);
+       im = 0;
+       dba_array_FOREACH(macros, macro) {
+               dba_array_setpos(macros, im++, dba_tell());
+               dba_macro_write(macro);
+       }
+       pos_end = dba_tell();
+       dba_seek(pos_macros);
+       dba_array_writepos(macros);
+       dba_seek(pos_end);
+}
+
+/*
+ * Write one individual macro table to disk; the format is:
+ * - The number of entries in the table.
+ * - For each entry, two pointers, the first one to the value
+ *   and the second one to the list of pages.
+ * - A list of values, each ending in a NUL byte.
+ * - To assure alignment of following integers,
+ *   padding with NUL bytes up to a multiple of four bytes.
+ * - A list of pointers to pages, each list ending in a 0 integer.
+ */
+static void
+dba_macro_write(struct ohash *macro)
+{
+       struct macro_entry      **entries, *entry;
+       struct dba_array         *page;
+       int32_t                  *kpos, *dpos;
+       unsigned int              ie, ne, slot;
+       int                       use;
+       int32_t                   addr, pos_macro, pos_end;
+
+       /* Temporary storage for filtering and sorting. */
+
+       ne = ohash_entries(macro);
+       entries = mandoc_reallocarray(NULL, ne, sizeof(*entries));
+       kpos = mandoc_reallocarray(NULL, ne, sizeof(*kpos));
+       dpos = mandoc_reallocarray(NULL, ne, sizeof(*dpos));
+
+       /* Build a list of non-empty entries and sort it. */
+
+       ne = 0;
+       for (entry = ohash_first(macro, &slot); entry != NULL;
+            entry = ohash_next(macro, &slot)) {
+               use = 0;
+               dba_array_FOREACH(entry->pages, page)
+                       if (dba_array_getpos(page))
+                               use = 1;
+               if (use)
+                       entries[ne++] = entry;
+       }
+       qsort(entries, ne, sizeof(*entries), compare_entries);
+
+       /* Number of entries, and space for the pointer pairs. */
+
+       dba_int_write(ne);
+       pos_macro = dba_skip(2, ne);
+
+       /* String table. */
+
+       for (ie = 0; ie < ne; ie++) {
+               kpos[ie] = dba_tell();
+               dba_str_write(entries[ie]->value);
+       }
+       dba_align();
+
+       /* Pages table. */
+
+       for (ie = 0; ie < ne; ie++) {
+               dpos[ie] = dba_tell();
+               dba_array_FOREACH(entries[ie]->pages, page)
+                       if ((addr = dba_array_getpos(page)))
+                               dba_int_write(addr);
+               dba_int_write(0);
+       }
+       pos_end = dba_tell();
+
+       /* Fill in the pointer pairs. */
+
+       dba_seek(pos_macro);
+       for (ie = 0; ie < ne; ie++) {
+               dba_int_write(kpos[ie]);
+               dba_int_write(dpos[ie]);
+       }
+       dba_seek(pos_end);
+
+       free(entries);
+       free(kpos);
+       free(dpos);
+}
+
+static int
+compare_entries(const void *vp1, const void *vp2)
+{
+       const struct macro_entry *ep1, *ep2;
+
+       ep1 = *(const struct macro_entry * const *)vp1;
+       ep2 = *(const struct macro_entry * const *)vp2;
+       return strcmp(ep1->value, ep2->value);
+}
diff --git a/contrib/mdocml/dba.h b/contrib/mdocml/dba.h
new file mode 100644 (file)
index 0000000..67a2759
--- /dev/null
@@ -0,0 +1,50 @@
+/*     $Id: dba.h,v 1.2 2016/08/17 20:46:56 schwarze Exp $ */
+/*
+ * Copyright (c) 2016 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.
+ *
+ * Public interface of the allocation-based version
+ * of the mandoc database, for read-write access.
+ * To be used by dba.c, dba_read.c, and makewhatis(8).
+ */
+
+#define        DBP_NAME        0
+#define        DBP_SECT        1
+#define        DBP_ARCH        2
+#define        DBP_DESC        3
+#define        DBP_FILE        4
+#define        DBP_MAX         5
+
+struct dba_array;
+
+struct dba {
+       struct dba_array        *pages;
+       struct dba_array        *macros;
+};
+
+
+struct dba     *dba_new(int32_t);
+void            dba_free(struct dba *);
+struct dba     *dba_read(const char *);
+int             dba_write(const char *, struct dba *);
+
+struct dba_array *dba_page_new(struct dba_array *, const char *,
+                       const char *, const char *, enum form);
+void            dba_page_add(struct dba_array *, int32_t, const char *);
+void            dba_page_alias(struct dba_array *, const char *, uint64_t);
+
+void            dba_macro_new(struct dba *, int32_t,
+                       const char *, const int32_t *);
+void            dba_macro_add(struct dba_array *, int32_t,
+                       const char *, struct dba_array *);
diff --git a/contrib/mdocml/dba_array.c b/contrib/mdocml/dba_array.c
new file mode 100644 (file)
index 0000000..18c9f09
--- /dev/null
@@ -0,0 +1,188 @@
+/*     $Id: dba_array.c,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */
+/*
+ * Copyright (c) 2016 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.
+ *
+ * Allocation-based arrays for the mandoc database, for read-write access.
+ * The interface is defined in "dba_array.h".
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mandoc_aux.h"
+#include "dba_write.h"
+#include "dba_array.h"
+
+struct dba_array {
+       void    **ep;   /* Array of entries. */
+       int32_t  *em;   /* Array of map positions. */
+       int       flags;
+       int32_t   ea;   /* Entries allocated. */
+       int32_t   eu;   /* Entries used (including deleted). */
+       int32_t   ed;   /* Entries deleted. */
+       int32_t   ec;   /* Currently active entry. */
+       int32_t   pos;  /* Map position of this array. */
+};
+
+
+struct dba_array *
+dba_array_new(int32_t ea, int flags)
+{
+       struct dba_array        *array;
+
+       assert(ea > 0);
+       array = mandoc_malloc(sizeof(*array));
+       array->ep = mandoc_reallocarray(NULL, ea, sizeof(*array->ep));
+       array->em = mandoc_reallocarray(NULL, ea, sizeof(*array->em));
+       array->ea = ea;
+       array->eu = 0;
+       array->ed = 0;
+       array->ec = 0;
+       array->flags = flags;
+       array->pos = 0;
+       return array;
+}
+
+void
+dba_array_free(struct dba_array *array)
+{
+       int32_t  ie;
+
+       if (array == NULL)
+               return;
+       if (array->flags & DBA_STR)
+               for (ie = 0; ie < array->eu; ie++)
+                       free(array->ep[ie]);
+       free(array->ep);
+       free(array->em);
+       free(array);
+}
+
+void
+dba_array_set(struct dba_array *array, int32_t ie, void *entry)
+{
+       assert(ie >= 0);
+       assert(ie < array->ea);
+       assert(ie <= array->eu);
+       if (ie == array->eu)
+               array->eu++;
+       if (array->flags & DBA_STR)
+               entry = mandoc_strdup(entry);
+       array->ep[ie] = entry;
+       array->em[ie] = 0;
+}
+
+void
+dba_array_add(struct dba_array *array, void *entry)
+{
+       if (array->eu == array->ea) {
+               assert(array->flags & DBA_GROW);
+               array->ep = mandoc_reallocarray(array->ep,
+                   2, sizeof(*array->ep) * array->ea);
+               array->em = mandoc_reallocarray(array->em,
+                   2, sizeof(*array->em) * array->ea);
+               array->ea *= 2;
+       }
+       dba_array_set(array, array->eu, entry);
+}
+
+void *
+dba_array_get(struct dba_array *array, int32_t ie)
+{
+       if (ie < 0 || ie >= array->eu || array->em[ie] == -1)
+               return NULL;
+       return array->ep[ie];
+}
+
+void
+dba_array_start(struct dba_array *array)
+{
+       array->ec = array->eu;
+}
+
+void *
+dba_array_next(struct dba_array *array)
+{
+       if (array->ec < array->eu)
+               array->ec++;
+       else
+               array->ec = 0;
+       while (array->ec < array->eu && array->em[array->ec] == -1)
+               array->ec++;
+       return array->ec < array->eu ? array->ep[array->ec] : NULL;
+}
+
+void
+dba_array_del(struct dba_array *array)
+{
+       if (array->ec < array->eu && array->em[array->ec] != -1) {
+               array->em[array->ec] = -1;
+               array->ed++;
+       }
+}
+
+void
+dba_array_undel(struct dba_array *array)
+{
+       memset(array->em, 0, sizeof(*array->em) * array->eu);
+}
+
+void
+dba_array_setpos(struct dba_array *array, int32_t ie, int32_t pos)
+{
+       array->em[ie] = pos;
+}
+
+int32_t
+dba_array_getpos(struct dba_array *array)
+{
+       return array->pos;
+}
+
+void
+dba_array_sort(struct dba_array *array, dba_compare_func func)
+{
+       assert(array->ed == 0);
+       qsort(array->ep, array->eu, sizeof(*array->ep), func);
+}
+
+int32_t
+dba_array_writelen(struct dba_array *array, int32_t nmemb)
+{
+       dba_int_write(array->eu - array->ed);
+       return dba_skip(nmemb, array->eu - array->ed);
+}
+
+void
+dba_array_writepos(struct dba_array *array)
+{
+       int32_t  ie;
+
+       array->pos = dba_tell();
+       for (ie = 0; ie < array->eu; ie++)
+               if (array->em[ie] != -1)
+                       dba_int_write(array->em[ie]);
+}
+
+void
+dba_array_writelst(struct dba_array *array)
+{
+       const char      *str;
+
+       dba_array_FOREACH(array, str)
+               dba_str_write(str);
+       dba_char_write('\0');
+}
diff --git a/contrib/mdocml/dba_array.h b/contrib/mdocml/dba_array.h
new file mode 100644 (file)
index 0000000..d9a6ee6
--- /dev/null
@@ -0,0 +1,47 @@
+/*     $Id: dba_array.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */
+/*
+ * Copyright (c) 2016 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.
+ *
+ * Public interface for allocation-based arrays
+ * for the mandoc database, for read-write access.
+ * To be used by dba*.c and by makewhatis(8).
+ */
+
+struct dba_array;
+
+#define        DBA_STR         0x01    /* Map contains strings, not pointers. */
+#define        DBA_GROW        0x02    /* Allow the array to grow. */
+
+#define        dba_array_FOREACH(a, e) \
+       dba_array_start(a); \
+       while (((e) = dba_array_next(a)) != NULL)
+
+typedef int dba_compare_func(const void *, const void *);
+
+struct dba_array *dba_array_new(int32_t, int);
+void            dba_array_free(struct dba_array *);
+void            dba_array_set(struct dba_array *, int32_t, void *);
+void            dba_array_add(struct dba_array *, void *);
+void           *dba_array_get(struct dba_array *, int32_t);
+void            dba_array_start(struct dba_array *);
+void           *dba_array_next(struct dba_array *);
+void            dba_array_del(struct dba_array *);
+void            dba_array_undel(struct dba_array *);
+void            dba_array_setpos(struct dba_array *, int32_t, int32_t);
+int32_t                 dba_array_getpos(struct dba_array *);
+void            dba_array_sort(struct dba_array *, dba_compare_func);
+int32_t                 dba_array_writelen(struct dba_array *, int32_t);
+void            dba_array_writepos(struct dba_array *);
+void            dba_array_writelst(struct dba_array *);
diff --git a/contrib/mdocml/dba_read.c b/contrib/mdocml/dba_read.c
new file mode 100644 (file)
index 0000000..e976057
--- /dev/null
@@ -0,0 +1,72 @@
+/*     $Id: dba_read.c,v 1.4 2016/08/17 20:46:56 schwarze Exp $ */
+/*
+ * Copyright (c) 2016 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.
+ *
+ * Function to read the mandoc database from disk into RAM,
+ * such that data can be added or removed.
+ * The interface is defined in "dba.h".
+ * This file is seperate from dba.c because this also uses "dbm.h".
+ */
+#include <regex.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mandoc_aux.h"
+#include "mansearch.h"
+#include "dba_array.h"
+#include "dba.h"
+#include "dbm.h"
+
+
+struct dba *
+dba_read(const char *fname)
+{
+       struct dba              *dba;
+       struct dba_array        *page;
+       struct dbm_page         *pdata;
+       struct dbm_macro        *mdata;
+       const char              *cp;
+       int32_t                  im, ip, iv, npages;
+
+       if (dbm_open(fname) == -1)
+               return NULL;
+       npages = dbm_page_count();
+       dba = dba_new(npages < 128 ? 128 : npages);
+       for (ip = 0; ip < npages; ip++) {
+               pdata = dbm_page_get(ip);
+               page = dba_page_new(dba->pages, pdata->arch,
+                   pdata->desc, pdata->file + 1, *pdata->file);
+               for (cp = pdata->name; *cp != '\0'; cp = strchr(cp, '\0') + 1)
+                       dba_page_add(page, DBP_NAME, cp);
+               for (cp = pdata->sect; *cp != '\0'; cp = strchr(cp, '\0') + 1)
+                       dba_page_add(page, DBP_SECT, cp);
+               if ((cp = pdata->arch) != NULL)
+                       while (*(cp = strchr(cp, '\0') + 1) != '\0')
+                               dba_page_add(page, DBP_ARCH, cp);
+               cp = pdata->file;
+               while (*(cp = strchr(cp, '\0') + 1) != '\0')
+                       dba_page_add(page, DBP_FILE, cp);
+       }
+       for (im = 0; im < MACRO_MAX; im++) {
+               for (iv = 0; iv < dbm_macro_count(im); iv++) {
+                       mdata = dbm_macro_get(im, iv);
+                       dba_macro_new(dba, im, mdata->value, mdata->pp);
+               }
+       }
+       dbm_close();
+       return dba;
+}
diff --git a/contrib/mdocml/dba_write.c b/contrib/mdocml/dba_write.c
new file mode 100644 (file)
index 0000000..89883b8
--- /dev/null
@@ -0,0 +1,127 @@
+/*     $Id: dba_write.c,v 1.3 2016/08/05 23:15:08 schwarze Exp $ */
+/*
+ * Copyright (c) 2016 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.
+ *
+ * Low-level functions for serializing allocation-based data to disk.
+ * The interface is defined in "dba_write.h".
+ */
+#include "config.h"
+
+#include <assert.h>
+#if HAVE_ENDIAN
+#include <endian.h>
+#elif HAVE_SYS_ENDIAN
+#include <sys/endian.h>
+#elif HAVE_NTOHL
+#include <arpa/inet.h>
+#endif
+#if HAVE_ERR
+#include <err.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "dba_write.h"
+
+static FILE    *ofp;
+
+
+int
+dba_open(const char *fname)
+{
+       ofp = fopen(fname, "w");
+       return ofp == NULL ? -1 : 0;
+}
+
+int
+dba_close(void)
+{
+       return fclose(ofp) == EOF ? -1 : 0;
+}
+
+int32_t
+dba_tell(void)
+{
+       long             pos;
+
+       if ((pos = ftell(ofp)) == -1)
+               err(1, "ftell");
+       if (pos >= INT32_MAX) {
+               errno = EOVERFLOW;
+               err(1, "ftell = %ld", pos);
+       }
+       return pos;
+}
+
+void
+dba_seek(int32_t pos)
+{
+       if (fseek(ofp, pos, SEEK_SET) == -1)
+               err(1, "fseek(%d)", pos);
+}
+
+int32_t
+dba_align(void)
+{
+       int32_t          pos;
+
+       pos = dba_tell();
+       while (pos & 3) {
+               dba_char_write('\0');
+               pos++;
+       }
+       return pos;
+}
+
+int32_t
+dba_skip(int32_t nmemb, int32_t sz)
+{
+       const int32_t    out[5] = {0, 0, 0, 0, 0};
+       int32_t          i, pos;
+
+       assert(sz >= 0);
+       assert(nmemb > 0);
+       assert(nmemb <= 5);
+       pos = dba_tell();
+       for (i = 0; i < sz; i++)
+               if (nmemb - fwrite(&out, sizeof(out[0]), nmemb, ofp))
+                       err(1, "fwrite");
+       return pos;
+}
+
+void
+dba_char_write(int c)
+{
+       if (putc(c, ofp) == EOF)
+               err(1, "fputc");
+}
+
+void
+dba_str_write(const char *str)
+{
+       if (fputs(str, ofp) == EOF)
+               err(1, "fputs");
+       dba_char_write('\0');
+}
+
+void
+dba_int_write(int32_t i)
+{
+       i = htobe32(i);
+       if (fwrite(&i, sizeof(i), 1, ofp) != 1)
+               err(1, "fwrite");
+}
similarity index 58%
copy from contrib/mdocml/lib.c
copy to contrib/mdocml/dba_write.h
index 8cc8a77..6adda05 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: lib.c,v 1.10 2014/03/23 11:25:26 schwarze Exp $ */
+/*     $Id: dba_write.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2016 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
  * 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.
+ *
+ * Internal interface to low-level functions
+ * for serializing allocation-based data to disk.
+ * For use by dba_array.c and dba.c only.
  */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "mdoc.h"
-#include "libmdoc.h"
-
-#define LINE(x, y) \
-       if (0 == strcmp(p, x)) return(y);
-
-const char *
-mdoc_a2lib(const char *p)
-{
-
-#include "lib.in"
 
-       return(NULL);
-}
+int     dba_open(const char *);
+int     dba_close(void);
+int32_t         dba_tell(void);
+void    dba_seek(int32_t);
+int32_t         dba_align(void);
+int32_t         dba_skip(int32_t, int32_t);
+void    dba_char_write(int);
+void    dba_str_write(const char *);
+void    dba_int_write(int32_t);
diff --git a/contrib/mdocml/dbm.c b/contrib/mdocml/dbm.c
new file mode 100644 (file)
index 0000000..f6b1259
--- /dev/null
@@ -0,0 +1,480 @@
+/*     $Id: dbm.c,v 1.6 2018/11/19 19:22:07 schwarze Exp $ */
+/*
+ * Copyright (c) 2016 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.
+ *
+ * Map-based version of the mandoc database, for read-only access.
+ * The interface is defined in "dbm.h".
+ */
+#include "config.h"
+
+#include <assert.h>
+#if HAVE_ENDIAN
+#include <endian.h>
+#elif HAVE_SYS_ENDIAN
+#include <sys/endian.h>
+#elif HAVE_NTOHL
+#include <arpa/inet.h>
+#endif
+#if HAVE_ERR
+#include <err.h>
+#endif
+#include <errno.h>
+#include <regex.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mansearch.h"
+#include "dbm_map.h"
+#include "dbm.h"
+
+struct macro {
+       int32_t value;
+       int32_t pages;
+};
+
+struct page {
+       int32_t name;
+       int32_t sect;
+       int32_t arch;
+       int32_t desc;
+       int32_t file;
+};
+
+enum iter {
+       ITER_NONE = 0,
+       ITER_NAME,
+       ITER_SECT,
+       ITER_ARCH,
+       ITER_DESC,
+       ITER_MACRO
+};
+
+static struct macro    *macros[MACRO_MAX];
+static int32_t          nvals[MACRO_MAX];
+static struct page     *pages;
+static int32_t          npages;
+static enum iter        iteration;
+
+static struct dbm_res   page_bytitle(enum iter, const struct dbm_match *);
+static struct dbm_res   page_byarch(const struct dbm_match *);
+static struct dbm_res   page_bymacro(int32_t, const struct dbm_match *);
+static char            *macro_bypage(int32_t, int32_t);
+
+
+/*** top level functions **********************************************/
+
+/*
+ * Open a disk-based mandoc database for read-only access.
+ * Map the pages and macros[] arrays.
+ * Return 0 on success.  Return -1 and set errno on failure.
+ */
+int
+dbm_open(const char *fname)
+{
+       const int32_t   *mp, *ep;
+       int32_t          im;
+
+       if (dbm_map(fname) == -1)
+               return -1;
+
+       if ((npages = be32toh(*dbm_getint(4))) < 0) {
+               warnx("dbm_open(%s): Invalid number of pages: %d",
+                   fname, npages);
+               goto fail;
+       }
+       pages = (struct page *)dbm_getint(5);
+
+       if ((mp = dbm_get(*dbm_getint(2))) == NULL) {
+               warnx("dbm_open(%s): Invalid offset of macros array", fname);
+               goto fail;
+       }
+       if (be32toh(*mp) != MACRO_MAX) {
+               warnx("dbm_open(%s): Invalid number of macros: %d",
+                   fname, be32toh(*mp));
+               goto fail;
+       }
+       for (im = 0; im < MACRO_MAX; im++) {
+               if ((ep = dbm_get(*++mp)) == NULL) {
+                       warnx("dbm_open(%s): Invalid offset of macro %d",
+                           fname, im);
+                       goto fail;
+               }
+               nvals[im] = be32toh(*ep);
+               macros[im] = (struct macro *)++ep;
+       }
+       return 0;
+
+fail:
+       dbm_unmap();
+       errno = EFTYPE;
+       return -1;
+}
+
+void
+dbm_close(void)
+{
+       dbm_unmap();
+}
+
+
+/*** functions for handling pages *************************************/
+
+int32_t
+dbm_page_count(void)
+{
+       return npages;
+}
+
+/*
+ * Give the caller pointers to the data for one manual page.
+ */
+struct dbm_page *
+dbm_page_get(int32_t ip)
+{
+       static struct dbm_page   res;
+
+       assert(ip >= 0);
+       assert(ip < npages);
+       res.name = dbm_get(pages[ip].name);
+       if (res.name == NULL)
+               res.name = "(NULL)\0";
+       res.sect = dbm_get(pages[ip].sect);
+       if (res.sect == NULL)
+               res.sect = "(NULL)\0";
+       res.arch = pages[ip].arch ? dbm_get(pages[ip].arch) : NULL;
+       res.desc = dbm_get(pages[ip].desc);
+       if (res.desc == NULL)
+               res.desc = "(NULL)";
+       res.file = dbm_get(pages[ip].file);
+       if (res.file == NULL)
+               res.file = " (NULL)\0";
+       res.addr = dbm_addr(pages + ip);
+       return &res;
+}
+
+/*
+ * Functions to start filtered iterations over manual pages.
+ */
+void
+dbm_page_byname(const struct dbm_match *match)
+{
+       assert(match != NULL);
+       page_bytitle(ITER_NAME, match);
+}
+
+void
+dbm_page_bysect(const struct dbm_match *match)
+{
+       assert(match != NULL);
+       page_bytitle(ITER_SECT, match);
+}
+
+void
+dbm_page_byarch(const struct dbm_match *match)
+{
+       assert(match != NULL);
+       page_byarch(match);
+}
+
+void
+dbm_page_bydesc(const struct dbm_match *match)
+{
+       assert(match != NULL);
+       page_bytitle(ITER_DESC, match);
+}
+
+void
+dbm_page_bymacro(int32_t im, const struct dbm_match *match)
+{
+       assert(im >= 0);
+       assert(im < MACRO_MAX);
+       assert(match != NULL);
+       page_bymacro(im, match);
+}
+
+/*
+ * Return the number of the next manual page in the current iteration.
+ */
+struct dbm_res
+dbm_page_next(void)
+{
+       struct dbm_res                   res = {-1, 0};
+
+       switch(iteration) {
+       case ITER_NONE:
+               return res;
+       case ITER_ARCH:
+               return page_byarch(NULL);
+       case ITER_MACRO:
+               return page_bymacro(0, NULL);
+       default:
+               return page_bytitle(iteration, NULL);
+       }
+}
+
+/*
+ * Functions implementing the iteration over manual pages.
+ */
+static struct dbm_res
+page_bytitle(enum iter arg_iter, const struct dbm_match *arg_match)
+{
+       static const struct dbm_match   *match;
+       static const char               *cp;    
+       static int32_t                   ip;
+       struct dbm_res                   res = {-1, 0};
+
+       assert(arg_iter == ITER_NAME || arg_iter == ITER_DESC ||
+           arg_iter == ITER_SECT);
+
+       /* Initialize for a new iteration. */
+
+       if (arg_match != NULL) {
+               iteration = arg_iter;
+               match = arg_match;
+               switch (iteration) {
+               case ITER_NAME:
+                       cp = dbm_get(pages[0].name);
+                       break;
+               case ITER_SECT:
+                       cp = dbm_get(pages[0].sect);
+                       break;
+               case ITER_DESC:
+                       cp = dbm_get(pages[0].desc);
+                       break;
+               default:
+                       abort();
+               }
+               if (cp == NULL) {
+                       iteration = ITER_NONE;
+                       match = NULL;
+                       cp = NULL;
+                       ip = npages;
+               } else
+                       ip = 0;
+               return res;
+       }
+
+       /* Search for a name. */
+
+       while (ip < npages) {
+               if (iteration == ITER_NAME)
+                       cp++;
+               if (dbm_match(match, cp))
+                       break;
+               cp = strchr(cp, '\0') + 1;
+               if (iteration == ITER_DESC)
+                       ip++;
+               else if (*cp == '\0') {
+                       cp++;
+                       ip++;
+               }
+       }
+
+       /* Reached the end without a match. */
+
+       if (ip == npages) {
+               iteration = ITER_NONE;
+               match = NULL;
+               cp = NULL;
+               return res;
+       }
+
+       /* Found a match; save the quality for later retrieval. */
+
+       res.page = ip;
+       res.bits = iteration == ITER_NAME ? cp[-1] : 0;
+
+       /* Skip the remaining names of this page. */
+
+       if (++ip < npages) {
+               do {
+                       cp++;
+               } while (cp[-1] != '\0' ||
+                   (iteration != ITER_DESC && cp[-2] != '\0'));
+       }
+       return res;
+}
+
+static struct dbm_res
+page_byarch(const struct dbm_match *arg_match)
+{
+       static const struct dbm_match   *match;
+       struct dbm_res                   res = {-1, 0};
+       static int32_t                   ip;
+       const char                      *cp;    
+
+       /* Initialize for a new iteration. */
+
+       if (arg_match != NULL) {
+               iteration = ITER_ARCH;
+               match = arg_match;
+               ip = 0;
+               return res;
+       }
+
+       /* Search for an architecture. */
+
+       for ( ; ip < npages; ip++)
+               if (pages[ip].arch)
+                       for (cp = dbm_get(pages[ip].arch);
+                           *cp != '\0';
+                           cp = strchr(cp, '\0') + 1)
+                               if (dbm_match(match, cp)) {
+                                       res.page = ip++;
+                                       return res;
+                               }
+
+       /* Reached the end without a match. */
+
+       iteration = ITER_NONE;
+       match = NULL;
+       return res;
+}
+
+static struct dbm_res
+page_bymacro(int32_t arg_im, const struct dbm_match *arg_match)
+{
+       static const struct dbm_match   *match;
+       static const int32_t            *pp;
+       static const char               *cp;
+       static int32_t                   im, iv;
+       struct dbm_res                   res = {-1, 0};
+
+       assert(im >= 0);
+       assert(im < MACRO_MAX);
+
+       /* Initialize for a new iteration. */
+
+       if (arg_match != NULL) {
+               iteration = ITER_MACRO;
+               match = arg_match;
+               im = arg_im;
+               cp = nvals[im] ? dbm_get(macros[im]->value) : NULL;
+               pp = NULL;
+               iv = -1;
+               return res;
+       }
+       if (iteration != ITER_MACRO)
+               return res;
+
+       /* Find the next matching macro value. */
+
+       while (pp == NULL || *pp == 0) {
+               if (++iv == nvals[im]) {
+                       iteration = ITER_NONE;
+                       return res;
+               }
+               if (iv)
+                       cp = strchr(cp, '\0') + 1;
+               if (dbm_match(match, cp))
+                       pp = dbm_get(macros[im][iv].pages);
+       }
+
+       /* Found a matching page. */
+
+       res.page = (struct page *)dbm_get(*pp++) - pages;
+       return res;
+}
+
+
+/*** functions for handling macros ************************************/
+
+int32_t
+dbm_macro_count(int32_t im)
+{
+       assert(im >= 0);
+       assert(im < MACRO_MAX);
+       return nvals[im];
+}
+
+struct dbm_macro *
+dbm_macro_get(int32_t im, int32_t iv)
+{
+       static struct dbm_macro macro;
+
+       assert(im >= 0);
+       assert(im < MACRO_MAX);
+       assert(iv >= 0);
+       assert(iv < nvals[im]);
+       macro.value = dbm_get(macros[im][iv].value);
+       macro.pp = dbm_get(macros[im][iv].pages);
+       return &macro;
+}
+
+/*
+ * Filtered iteration over macro entries.
+ */
+void
+dbm_macro_bypage(int32_t im, int32_t ip)
+{
+       assert(im >= 0);
+       assert(im < MACRO_MAX);
+       assert(ip != 0);
+       macro_bypage(im, ip);
+}
+
+char *
+dbm_macro_next(void)
+{
+       return macro_bypage(MACRO_MAX, 0);
+}
+
+static char *
+macro_bypage(int32_t arg_im, int32_t arg_ip)
+{
+       static const int32_t    *pp;
+       static int32_t           im, ip, iv;
+
+       /* Initialize for a new iteration. */
+
+       if (arg_im < MACRO_MAX && arg_ip != 0) {
+               im = arg_im;
+               ip = arg_ip;
+               pp = dbm_get(macros[im]->pages);
+               iv = 0;
+               return NULL;
+       }
+       if (im >= MACRO_MAX)
+               return NULL;
+
+       /* Search for the next value. */
+
+       while (iv < nvals[im]) {
+               if (*pp == ip)
+                       break;
+               if (*pp == 0)
+                       iv++;
+               pp++;
+       }
+
+       /* Reached the end without a match. */
+
+       if (iv == nvals[im]) {
+               im = MACRO_MAX;
+               ip = 0;
+               pp = NULL;
+               return NULL;
+       }
+
+       /* Found a match; skip the remaining pages of this entry. */
+
+       if (++iv < nvals[im])
+               while (*pp++ != 0)
+                       continue;
+
+       return dbm_get(macros[im][iv - 1].value);
+}
diff --git a/contrib/mdocml/dbm.h b/contrib/mdocml/dbm.h
new file mode 100644 (file)
index 0000000..ec2cd47
--- /dev/null
@@ -0,0 +1,68 @@
+/*     $Id: dbm.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */
+/*
+ * Copyright (c) 2016 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.
+ *
+ * Public interface for the map-based version
+ * of the mandoc database, for read-only access.
+ * To be used by dbm*.c, dba_read.c, and man(1) and apropos(1).
+ */
+
+enum dbm_mtype {
+       DBM_EXACT = 0,
+       DBM_SUB,
+       DBM_REGEX
+};
+
+struct dbm_match {
+       regex_t         *re;
+       const char      *str;
+       enum dbm_mtype   type;
+};
+
+struct dbm_res {
+       int32_t          page;
+       int32_t          bits;
+};
+
+struct dbm_page {
+       const char      *name;
+       const char      *sect;
+       const char      *arch;
+       const char      *desc;
+       const char      *file;
+       int32_t          addr;
+};
+
+struct dbm_macro {
+       const char      *value;
+       const int32_t   *pp;
+};
+
+int             dbm_open(const char *);
+void            dbm_close(void);
+
+int32_t                 dbm_page_count(void);
+struct dbm_page        *dbm_page_get(int32_t);
+void            dbm_page_byname(const struct dbm_match *);
+void            dbm_page_bysect(const struct dbm_match *);
+void            dbm_page_byarch(const struct dbm_match *);
+void            dbm_page_bydesc(const struct dbm_match *);
+void            dbm_page_bymacro(int32_t, const struct dbm_match *);
+struct dbm_res  dbm_page_next(void);
+
+int32_t                 dbm_macro_count(int32_t);
+struct dbm_macro *dbm_macro_get(int32_t, int32_t);
+void            dbm_macro_bypage(int32_t, int32_t);
+char           *dbm_macro_next(void);
diff --git a/contrib/mdocml/dbm_map.c b/contrib/mdocml/dbm_map.c
new file mode 100644 (file)
index 0000000..87c085d
--- /dev/null
@@ -0,0 +1,194 @@
+/*     $Id: dbm_map.c,v 1.8 2017/02/17 14:43:54 schwarze Exp $ */
+/*
+ * Copyright (c) 2016 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.
+ *
+ * Low-level routines for the map-based version
+ * of the mandoc database, for read-only access.
+ * The interface is defined in "dbm_map.h".
+ */
+#include "config.h"
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if HAVE_ENDIAN
+#include <endian.h>
+#elif HAVE_SYS_ENDIAN
+#include <sys/endian.h>
+#elif HAVE_NTOHL
+#include <arpa/inet.h>
+#endif
+#if HAVE_ERR
+#include <err.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mansearch.h"
+#include "dbm_map.h"
+#include "dbm.h"
+
+static struct stat      st;
+static char            *dbm_base;
+static int              ifd;
+static int32_t          max_offset;
+
+/*
+ * Open a disk-based database for read-only access.
+ * Validate the file format as far as it is not mandoc-specific.
+ * Return 0 on success.  Return -1 and set errno on failure.
+ */
+int
+dbm_map(const char *fname)
+{
+       int              save_errno;
+       const int32_t   *magic;
+
+       if ((ifd = open(fname, O_RDONLY)) == -1)
+               return -1;
+       if (fstat(ifd, &st) == -1)
+               goto fail;
+       if (st.st_size < 5) {
+               warnx("dbm_map(%s): File too short", fname);
+               errno = EFTYPE;
+               goto fail;
+       }
+       if (st.st_size > INT32_MAX) {
+               errno = EFBIG;
+               goto fail;
+       }
+       if ((dbm_base = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED,
+           ifd, 0)) == MAP_FAILED)
+               goto fail;
+       magic = dbm_getint(0);
+       if (be32toh(*magic) != MANDOCDB_MAGIC) {
+               if (strncmp(dbm_base, "SQLite format 3", 15))
+                       warnx("dbm_map(%s): "
+                           "Bad initial magic %x (expected %x)",
+                           fname, be32toh(*magic), MANDOCDB_MAGIC);
+               else
+                       warnx("dbm_map(%s): "
+                           "Obsolete format based on SQLite 3",
+                           fname);
+               errno = EFTYPE;
+               goto fail;
+       }
+       magic = dbm_getint(1);
+       if (be32toh(*magic) != MANDOCDB_VERSION) {
+               warnx("dbm_map(%s): Bad version number %d (expected %d)",
+                   fname, be32toh(*magic), MANDOCDB_VERSION);
+               errno = EFTYPE;
+               goto fail;
+       }
+       max_offset = be32toh(*dbm_getint(3)) + sizeof(int32_t);
+       if (st.st_size != max_offset) {
+               warnx("dbm_map(%s): Inconsistent file size %lld (expected %d)",
+                   fname, (long long)st.st_size, max_offset);
+               errno = EFTYPE;
+               goto fail;
+       }
+       if ((magic = dbm_get(*dbm_getint(3))) == NULL) {
+               errno = EFTYPE;
+               goto fail;
+       }
+       if (be32toh(*magic) != MANDOCDB_MAGIC) {
+               warnx("dbm_map(%s): Bad final magic %x (expected %x)",
+                   fname, be32toh(*magic), MANDOCDB_MAGIC);
+               errno = EFTYPE;
+               goto fail;
+       }
+       return 0;
+
+fail:
+       save_errno = errno;
+       close(ifd);
+       errno = save_errno;
+       return -1;
+}
+
+void
+dbm_unmap(void)
+{
+       if (munmap(dbm_base, st.st_size) == -1)
+               warn("dbm_unmap: munmap");
+       if (close(ifd) == -1)
+               warn("dbm_unmap: close");
+       dbm_base = (char *)-1;
+}
+
+/*
+ * Take a raw integer as it was read from the database.
+ * Interpret it as an offset into the database file
+ * and return a pointer to that place in the file.
+ */
+void *
+dbm_get(int32_t offset)
+{
+       offset = be32toh(offset);
+       if (offset < 0) {
+               warnx("dbm_get: Database corrupt: offset %d", offset);
+               return NULL;
+       }
+       if (offset >= max_offset) {
+               warnx("dbm_get: Database corrupt: offset %d > %d",
+                   offset, max_offset);
+               return NULL;
+       }
+       return dbm_base + offset;
+}
+
+/*
+ * Assume the database starts with some integers.
+ * Assume they are numbered starting from 0, increasing.
+ * Get a pointer to one with the number "offset".
+ */
+int32_t *
+dbm_getint(int32_t offset)
+{
+       return (int32_t *)dbm_base + offset;
+}
+
+/*
+ * The reverse of dbm_get().
+ * Take pointer into the database file
+ * and convert it to the raw integer
+ * that would be used to refer to that place in the file.
+ */
+int32_t
+dbm_addr(const void *p)
+{
+       return htobe32((const char *)p - dbm_base);
+}
+
+int
+dbm_match(const struct dbm_match *match, const char *str)
+{
+       switch (match->type) {
+       case DBM_EXACT:
+               return strcmp(str, match->str) == 0;
+       case DBM_SUB:
+               return strcasestr(str, match->str) != NULL;
+       case DBM_REGEX:
+               return regexec(match->re, str, 0, NULL, 0) == 0;
+       default:
+               abort();
+       }
+}
similarity index 60%
copy from contrib/mdocml/att.c
copy to contrib/mdocml/dbm_map.h
index 059639a..9768fc5 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: att.c,v 1.11 2014/04/20 16:46:04 schwarze Exp $ */
+/*     $Id: dbm_map.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2016 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
  * 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.
+ *
+ * Private interface for low-level routines for the map-based version 
+ * of the mandoc database, for read-only access.
+ * To be used by dbm*.c only.
  */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "mdoc.h"
-#include "libmdoc.h"
-
-#define LINE(x, y) \
-       if (0 == strcmp(p, x)) return(y);
-
-
-const char *
-mdoc_a2att(const char *p)
-{
 
-#include "att.in"
+struct dbm_match;
 
-       return(NULL);
-}
+int             dbm_map(const char *);
+void            dbm_unmap(void);
+void           *dbm_get(int32_t);
+int32_t                *dbm_getint(int32_t);
+int32_t                 dbm_addr(const void *);
+int             dbm_match(const struct dbm_match *, const char *);