Changes in version 1.14.1, released on February 21, 2017
--- MAJOR NEW FEATURES --- * apropos(1): Reimplement complete semantic search functionality without the dependency on SQLite3, using only POSIX APIs. This comes with a completely new mandoc.db(5) file format. * man(1): Support more than one tag entry for the same search term, plus some minor improvements to the less(1) :t support. * -Thtml: Use real macro names for CSS classes. Systematic cleanup of and many improvements to mandoc.css. * -Thtml: Produce human readable HTML code by using indentation and better line breaks. Improve various HTML elements, and trim several useless ones. * New catman(8) utility, still somewhat experimental. * Now includes a portable version of the OpenBSD mandoc regression suite, see regress/regress.pl.1 for details. --- REMOVED FUNCTIONALITY --- * Operating systems that don't provide mmap(3) are no longer supported. * Drop support for manpath(1). Even if your system has manpath(1), it is simpler to use MANPATH_DEFAULT in configure.local for operating system defaults, man.conf(5) for machine-specific modifications, and ${MANPATH}, -m, and -M for user preferences than to bother with the complexity of manpath(1). * makewhatis(8) -p: No longer warn about missing MLINKS since these are no longer needed for anything. --- MINOR NEW FEATURES --- * mdoc(7): Warn about invalid punctuation and content below NAME. * mdoc(7): Warn about .Xr lacking the second argument (section). * mdoc(7): Warn about violations of the rule "new sentence, new line". * roff(7): Warn about trailing whitespace at the end of comments. * mdoc(7): Improve rendering of double quotes. * mdoc(7): Always do text production in the validator, never in the formatters. Cleaner, simpler, shorter, helps NetBSD apropos(1) and also makes -Ttree output more useful. * -Ttree: Show metadata and some additional node flags. New -Onoval output option to show the unvalidated tree. --- RELIABILITY BUGFIXES --- * man(1): Make "man -l" work with standard input from a pipe or file, as long as standard output is a terminal. * man(7): Fix out of bounds read access if a text node immediately preceded the first .SH header. * mdoc(7): Fix out of bounds read access for .Bl without a type but with a width. * mdoc(7): Fix out of bounds read access for .Bl -column starting with a tab character instead of a child .It macro. * mdoc(7): Fix syntax tree corruption leading to segfaults caused by stray block end macros in nested blocks of mismatching type. * man(1): Fix NULL dereference when the first of multiple pages shown was preformatted. * mdoc(7): Fix syntax tree corruption leading to NULL dereference caused by partial implicit macros inside .Bl -column table cells. * mdoc(7): Fix syntax tree corruption leading to NULL dereference for macro sequences like .Bl .Bl .It Bo .El .It. * mdoc(7): Fix syntax tree corruption leading to NULL dereference caused by .Ta following a nested .Bl -column breaking another block. * mdoc(7): Fix syntax tree corruption sometimes leading to NULL dereference caused by indirectly broken .Nd or .Nm blocks. * mdoc(7) -Thtml: Fix a NULL dereference for .Bl -column with 0 columns. * mdoc(7): Fix NULL dereference in some specific cases of a block-end macro calling another block-end macro. * mdoc(7): Fix NULL dereference if the only child of the head of the first .Sh was an empty in-line macro. * eqn(7): Fix NULL dereference in the terminal formatter for empty matrices and empty square roots. * mdoc(7): Fix an assertion failure for a .Bd without a type that breaks another block. * mdoc(7): Fix an assertion failure that happened for some .Bl -column lists containing a column width of "-4n", "-3n", or "-2n". * mdoc(7): Fix an assertion failure caused by .Bl -column without .It but containing eqn(7) or tbl(7) code. * roff(7): Fix an assertion failure caused by \z\[u00FF] with -Tps/-Tpdf. * roff(7): Fix an assertion failures caused by whitespace inside \o'' (overstrike) sequences. * -Thtml: Fix an assertion failure caused by -Oman or -Oincludes of excessive length. --- PORTABILITY IMPROVEMENTS --- * man(1): Do not mix stdio narrow and wide stream orientation on stdout, which could cause output corruption on glibc. * mandoc(1): Autodetect a suitable locale for -Tutf8 mode. * ./configure: Autodetect whether PATH_MAX and O_DIRECTORY are defined. * ./configure: Autodetect if nanosleep(3) needs -lrt. * ./configure: Provide an ${LN} configuration variable. * ./configure: Put compiler arguments that may contain -l at the end. --- MINOR BUGFIXES --- * mdoc(7): Fix SYNOPSIS output if the first child of .Nm is a macro. * mdoc(7) -Thtml: Improve formatting of .Bl -tag with short tags. * man(7) -Thtml: Preserve whitespace in .nf (nofill) mode. * mandoc(1): Error out on invalid output options on the command line. --- STRUCTURAL CHANGES, no functional change --- * Redesign part of the mandoc_html(3) interfaces, making them much easier to use and reducing the amount of code by a few hundred lines. --- THANKS TO --- * Michael Stapelberg (Debian) for designing the new mandocd(8) and parts of the new catman(8), for release testing, and for a number of patches and bug reports. * Baptiste Daroussin (FreeBSD) for profiling the new makewhatis(8) implementation and suggesting an algorithmic improvement which more than doubled performance, and for a few bug reports. * Ed Maste (FreeBSD) for an important patch improving reproducibility of builds in makewhatis(8), and for a few bug reports. * Theo Buehler (OpenBSD) for almost twenty important bug reports, most of them found by systematic afl(1) fuzzing. * Benny Lofgren, David Dahlberg, and in particular Vadim Zhukov for crucial help in getting .Bl -tag CSS formatting fixed. * Svyatoslav Mishyn (Crux Linux) for an initial version of the patch to autodetect a suitable locale for -Tutf8 mode and for release testing. * Jason McIntyre (OpenBSD) for multiple useful discussions and a number of bug reports. * Sevan Janiyan (NetBSD) for extensive release testing and multiple bug reports. * Thomas Klausner and Christos Zoulas (NetBSD), Yuri Pankov (illumos), and Leah Neukirchen (Void Linux) for release testing and bug reports. * Ulrich Spoerlein (FreeBSD) for release testing. * Alexander Bluhm, Andrew Fresh, Antoine Jacoutot, Antony Bentley, Christian Weisgerber, Jonathan Gray, Marc Espie, Martijn van Duren, Stuart Henderson, Ted Unangst, Theo de Raadt (OpenBSD), Abhinav Upadhyay, Kamil Rytarowski (NetBSD), Aaron M. Ucko, Bdale Garbee, Reiner Herrmann, Shane Kerr (Debian), Daniel Sabogal (Alpine Linux), Carsten Kunze (Heirloom roff), Kristaps Dzonsons (bsd.lv), Anton Lindqvist, Jan Stary, Jeremy A. Mates, Mark Patruck, Pavan Maddamsetti, Sean Levy <attila@stalphonsos.com>, and Tiago Silva for bug reports. * Brent Cook, Marc Espie, Philip Guenther, Todd Miller (OpenBSD) and Markus Waldeck for useful discussions. * And as usual, OpenCSW for providing me with a Solaris 9/10/11 testing environment.
This commit is contained in:
parent
46dcb1c33a
commit
9508192e44
|
@ -1,4 +1,4 @@
|
|||
Id: INSTALL,v 1.15 2016/07/14 11:09:06 schwarze Exp
|
||||
Id: INSTALL,v 1.18 2017/02/08 12:24:10 schwarze Exp
|
||||
|
||||
About mdocml, the portable mandoc distribution
|
||||
----------------------------------------------
|
||||
|
@ -16,7 +16,7 @@ tech@ mailing list, too.
|
|||
|
||||
Enjoy using the mandoc toolset!
|
||||
|
||||
Ingo Schwarze, Karlsruhe, July 2016
|
||||
Ingo Schwarze, Karlsruhe, February 2017
|
||||
|
||||
|
||||
Installation
|
||||
|
@ -31,11 +31,21 @@ 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. If you want to build the CGI program, man.cgi(8), too, run the
|
||||
command "echo BUILD_CGI=1 > configure.local". Then run "cp
|
||||
cgi.h.examples cgi.h" and edit cgi.h as desired.
|
||||
1. If you want to build the CGI program, man.cgi(8), too,
|
||||
run the command "echo BUILD_CGI=1 >> configure.local".
|
||||
Then run "cp cgi.h.example cgi.h" and edit cgi.h as desired.
|
||||
|
||||
2. Run "./configure".
|
||||
2. If you also want to build the new catman(8) utility, run the
|
||||
command "echo BUILD_CATMAN=1 >> configure.local". Note that it
|
||||
is unlikely to be a drop-in replacement providing the same
|
||||
functionality as your system's "catman", if your operating
|
||||
system contains one.
|
||||
|
||||
3. Define MANPATH_DEFAULT in configure.local
|
||||
if /usr/share/man:/usr/X11R6/man:/usr/local/man is not appropriate
|
||||
for your operating system.
|
||||
|
||||
4. Run "./configure".
|
||||
This script attempts autoconfiguration of mandoc for your system.
|
||||
Read both its standard output and the file "Makefile.local" it
|
||||
generates. If anything looks wrong or different from what you
|
||||
|
@ -45,34 +55,31 @@ result seems right to you.
|
|||
On Solaris 10 and earlier, you may have to run "ksh ./configure"
|
||||
because the native /bin/sh lacks some POSIX features.
|
||||
|
||||
3. Run "make".
|
||||
5. Run "make".
|
||||
Any POSIX-compatible make, in particular both BSD make and GNU make,
|
||||
should work. If the build fails, look at "configure.local.example"
|
||||
and go back to step 2.
|
||||
|
||||
4. Run "make -n install" and check whether everything will be
|
||||
6. Run "make -n install" and check whether everything will be
|
||||
installed to the intended places. Otherwise, put some *DIR or *NM*
|
||||
variables into "configure.local" and go back to step 2.
|
||||
variables into "configure.local" and go back to step 4.
|
||||
|
||||
5. Run "sudo make install". If you intend to build a binary
|
||||
7. Optionally run the regression suite.
|
||||
Basically, that amounts to "cd regress && ./regress.pl".
|
||||
But you should probably look at "./mandoc -l regress/regress.pl.1"
|
||||
first.
|
||||
|
||||
8. Run "sudo make install". If you intend to build a binary
|
||||
package using some kind of fake root mechanism, you may need a
|
||||
command like "make DESTDIR=... install". Read the *-install targets
|
||||
in the "Makefile" to understand how DESTDIR is used.
|
||||
|
||||
6. If you want to use the integrated man(1) and your system uses
|
||||
manpath(1), make sure it is configured correctly, in particular,
|
||||
it returns all directory trees where manual pages are installed.
|
||||
Otherwise, if your system uses man.conf(5), make sure it contains
|
||||
a "manpath" line for each directory tree, and the order of these
|
||||
lines meets your wishes.
|
||||
9. Run the command "sudo makewhatis" to build mandoc.db(5) databases
|
||||
in all the directory trees configured in step 6. Whenever installing
|
||||
new manual pages, re-run makewhatis(8) to update the databases, or
|
||||
apropos(1) will not find the new pages.
|
||||
|
||||
7. If you compiled with database support, run the command "sudo
|
||||
makewhatis" to build mandoc.db(5) databases in all the directory
|
||||
trees configured in step 6. Whenever installing new manual pages,
|
||||
re-run makewhatis(8) to update the databases, or apropos(1) will
|
||||
not find the new pages.
|
||||
|
||||
8. To set up a man.cgi(8) server, read its manual page.
|
||||
10. To set up a man.cgi(8) server, read its manual page.
|
||||
|
||||
Note that some man(7) pages may contain low-level roff(7) markup
|
||||
that mandoc does not yet understand. On some BSD systems using
|
||||
|
@ -84,26 +91,16 @@ manual page source.
|
|||
|
||||
Understanding mandoc dependencies
|
||||
---------------------------------
|
||||
The mandoc(1), man(1), and demandoc(1) utilities only depend
|
||||
on the zlib library for decompressing gzipped manual pages,
|
||||
but makewhatis(8) and apropos(1) depend on the following
|
||||
additional software:
|
||||
The following libraries are required:
|
||||
|
||||
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. zlib for decompressing gzipped manual pages.
|
||||
|
||||
2. The fts(3) directory traversion functions.
|
||||
If your system does not have them, the bundled compatibility version
|
||||
will be used, so you need not worry in that case. But be careful: the
|
||||
glibc version of fts(3) is known to be broken on 32bit platforms,
|
||||
see <https://sourceware.org/bugzilla/show_bug.cgi?id=15838>.
|
||||
will be used, so you need not worry in that case. But be careful: old
|
||||
glibc versions of fts(3) were known to be broken on 32bit platforms,
|
||||
see <https://sourceware.org/bugzilla/show_bug.cgi?id=11460>.
|
||||
That was presumably fixed in glibc-2.23.
|
||||
If you run into that problem, set "HAVE_FTS=0" in configure.local.
|
||||
|
||||
3. Marc Espie's ohash(3) library.
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
Id: LICENSE,v 1.12 2016/07/07 23:46:36 schwarze Exp
|
||||
Id: LICENSE,v 1.14 2017/02/08 12:24:10 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-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
|
||||
Copyright (c) 2010-2017 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) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
|
||||
Copyright (c) 2014 Baptiste Daroussin <bapt@freebsd.org>
|
||||
Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
|
||||
Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
|
||||
Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
|
||||
Copyright (c) 1998, 2004, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
|
||||
|
@ -41,7 +43,7 @@ other people's Copyright and are distributed under various 2-clause
|
|||
and 3-clause BSD licenses; see these individual files for details.
|
||||
|
||||
soelim.c, soelim.1:
|
||||
Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
|
||||
Copyright (c) 2014 Baptiste Daroussin <bapt@freebsd.org>
|
||||
|
||||
compat_err.c, compat_fts.c, compat_fts.h,
|
||||
compat_getsubopt.c, compat_strcasestr.c, compat_strsep.c,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
att.o: att.c config.h roff.h mdoc.h libmdoc.h
|
||||
catman.o: catman.c config.h compat_fts.h
|
||||
cgi.o: cgi.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h main.h manconf.h mansearch.h cgi.h
|
||||
chars.o: chars.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h libmandoc.h
|
||||
compat_err.o: compat_err.c config.h
|
||||
|
@ -10,7 +11,6 @@ compat_mkdtemp.o: compat_mkdtemp.c config.h
|
|||
compat_ohash.o: compat_ohash.c config.h compat_ohash.h
|
||||
compat_progname.o: compat_progname.c config.h
|
||||
compat_reallocarray.o: compat_reallocarray.c config.h
|
||||
compat_sqlite3_errstr.o: compat_sqlite3_errstr.c config.h
|
||||
compat_strcasestr.o: compat_strcasestr.c config.h
|
||||
compat_stringlist.o: compat_stringlist.c config.h compat_stringlist.h
|
||||
compat_strlcat.o: compat_strlcat.c config.h
|
||||
|
@ -18,6 +18,12 @@ compat_strlcpy.o: compat_strlcpy.c config.h
|
|||
compat_strsep.o: compat_strsep.c config.h
|
||||
compat_strtonum.o: compat_strtonum.c config.h
|
||||
compat_vasprintf.o: compat_vasprintf.c config.h
|
||||
dba.o: dba.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mansearch.h dba_write.h dba_array.h dba.h
|
||||
dba_array.o: dba_array.c mandoc_aux.h dba_write.h dba_array.h
|
||||
dba_read.o: dba_read.c mandoc_aux.h mansearch.h dba_array.h dba.h dbm.h
|
||||
dba_write.o: dba_write.c config.h dba_write.h
|
||||
dbm.o: dbm.c config.h mansearch.h dbm_map.h dbm.h
|
||||
dbm_map.o: dbm_map.c config.h mansearch.h dbm_map.h dbm.h
|
||||
demandoc.o: demandoc.c config.h roff.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
|
||||
|
@ -26,7 +32,7 @@ html.o: html.c config.h mandoc.h mandoc_aux.h out.h html.h manconf.h main.h
|
|||
lib.o: lib.c config.h roff.h mdoc.h libmdoc.h lib.in
|
||||
main.o: main.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h tag.h main.h manconf.h mansearch.h
|
||||
man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
|
||||
man_hash.o: man_hash.c config.h roff.h man.h libman.h
|
||||
man_hash.o: man_hash.c config.h mandoc.h roff.h man.h libmandoc.h libman.h
|
||||
man_html.o: man_html.c config.h mandoc_aux.h roff.h man.h out.h html.h main.h
|
||||
man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
|
||||
man_term.o: man_term.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h term.h main.h
|
||||
|
@ -34,14 +40,14 @@ man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h libma
|
|||
mandoc.o: mandoc.c config.h mandoc.h mandoc_aux.h libmandoc.h
|
||||
mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h
|
||||
mandoc_ohash.o: mandoc_ohash.c mandoc_aux.h mandoc_ohash.h compat_ohash.h
|
||||
mandocdb.o: mandocdb.c config.h compat_fts.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h mdoc.h man.h manconf.h mansearch.h
|
||||
mandocd.o: mandocd.c config.h mandoc.h roff.h mdoc.h man.h main.h manconf.h
|
||||
mandocdb.o: mandocdb.c config.h compat_fts.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h mdoc.h man.h manconf.h mansearch.h dba_array.h dba.h
|
||||
manpage.o: manpage.c config.h manconf.h mansearch.h
|
||||
manpath.o: manpath.c config.h mandoc_aux.h manconf.h
|
||||
mansearch.o: mansearch.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h manconf.h mansearch.h
|
||||
mansearch_const.o: mansearch_const.c config.h mansearch.h
|
||||
mansearch.o: mansearch.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h manconf.h mansearch.h dbm.h
|
||||
mdoc.o: mdoc.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
|
||||
mdoc_argv.o: mdoc_argv.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h
|
||||
mdoc_hash.o: mdoc_hash.c config.h roff.h mdoc.h libmdoc.h
|
||||
mdoc_argv.o: mdoc_argv.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
|
||||
mdoc_hash.o: mdoc_hash.c config.h mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h
|
||||
mdoc_html.o: mdoc_html.c config.h mandoc_aux.h roff.h mdoc.h out.h html.h main.h
|
||||
mdoc_macro.o: mdoc_macro.c config.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
|
||||
mdoc_man.o: mdoc_man.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h out.h main.h
|
||||
|
|
|
@ -1,7 +1,135 @@
|
|||
Id: NEWS,v 1.12 2016/07/14 11:09:06 schwarze Exp
|
||||
Id: NEWS,v 1.20 2017/02/16 14:38:12 schwarze Exp
|
||||
|
||||
This file lists the most important changes in the mdocml.bsd.lv distribution.
|
||||
|
||||
Changes in version 1.14.1, released on February 21, 2017
|
||||
|
||||
--- MAJOR NEW FEATURES ---
|
||||
* apropos(1): Reimplement complete semantic search functionality
|
||||
without the dependency on SQLite3, using only POSIX APIs.
|
||||
This comes with a completely new mandoc.db(5) file format.
|
||||
* man(1): Support more than one tag entry for the same search term,
|
||||
plus some minor improvements to the less(1) :t support.
|
||||
* -Thtml: Use real macro names for CSS classes.
|
||||
Systematic cleanup of and many improvements to mandoc.css.
|
||||
* -Thtml: Produce human readable HTML code by using indentation
|
||||
and better line breaks. Improve various HTML elements,
|
||||
and trim several useless ones.
|
||||
* New catman(8) utility, still somewhat experimental.
|
||||
* Now includes a portable version of the OpenBSD mandoc regression
|
||||
suite, see regress/regress.pl.1 for details.
|
||||
--- REMOVED FUNCTIONALITY ---
|
||||
* Operating systems that don't provide mmap(3) are no longer supported.
|
||||
* Drop support for manpath(1). Even if your system has manpath(1),
|
||||
it is simpler to use MANPATH_DEFAULT in configure.local for
|
||||
operating system defaults, man.conf(5) for machine-specific
|
||||
modifications, and ${MANPATH}, -m, and -M for user preferences
|
||||
than to bother with the complexity of manpath(1).
|
||||
* makewhatis(8) -p: No longer warn about missing MLINKS since these
|
||||
are no longer needed for anything.
|
||||
--- MINOR NEW FEATURES ---
|
||||
* mdoc(7): Warn about invalid punctuation and content below NAME.
|
||||
* mdoc(7): Warn about .Xr lacking the second argument (section).
|
||||
* mdoc(7): Warn about violations of the rule "new sentence, new line".
|
||||
* roff(7): Warn about trailing whitespace at the end of comments.
|
||||
* mdoc(7): Improve rendering of double quotes.
|
||||
* mdoc(7): Always do text production in the validator, never in the
|
||||
formatters. Cleaner, simpler, shorter, helps NetBSD apropos(1)
|
||||
and also makes -Ttree output more useful.
|
||||
* -Ttree: Show metadata and some additional node flags.
|
||||
New -Onoval output option to show the unvalidated tree.
|
||||
--- RELIABILITY BUGFIXES ---
|
||||
* man(1): Make "man -l" work with standard input from a pipe or file,
|
||||
as long as standard output is a terminal.
|
||||
* man(7): Fix out of bounds read access if a text node immediately
|
||||
preceded the first .SH header.
|
||||
* mdoc(7): Fix out of bounds read access for .Bl without a type
|
||||
but with a width.
|
||||
* mdoc(7): Fix out of bounds read access for .Bl -column starting
|
||||
with a tab character instead of a child .It macro.
|
||||
* mdoc(7): Fix syntax tree corruption leading to segfaults caused
|
||||
by stray block end macros in nested blocks of mismatching type.
|
||||
* man(1): Fix NULL dereference when the first of multiple pages
|
||||
shown was preformatted.
|
||||
* mdoc(7): Fix syntax tree corruption leading to NULL dereference
|
||||
caused by partial implicit macros inside .Bl -column table cells.
|
||||
* mdoc(7): Fix syntax tree corruption leading to NULL dereference
|
||||
for macro sequences like .Bl .Bl .It Bo .El .It.
|
||||
* mdoc(7): Fix syntax tree corruption leading to NULL dereference
|
||||
caused by .Ta following a nested .Bl -column breaking another block.
|
||||
* mdoc(7): Fix syntax tree corruption sometimes leading to NULL
|
||||
dereference caused by indirectly broken .Nd or .Nm blocks.
|
||||
* mdoc(7) -Thtml: Fix a NULL dereference for .Bl -column with 0 columns.
|
||||
* mdoc(7): Fix NULL dereference in some specific cases of a
|
||||
block-end macro calling another block-end macro.
|
||||
* mdoc(7): Fix NULL dereference if the only child of the head
|
||||
of the first .Sh was an empty in-line macro.
|
||||
* eqn(7): Fix NULL dereference in the terminal formatter
|
||||
for empty matrices and empty square roots.
|
||||
* mdoc(7): Fix an assertion failure for a .Bd without a type that
|
||||
breaks another block.
|
||||
* mdoc(7): Fix an assertion failure that happened for some .Bl -column
|
||||
lists containing a column width of "-4n", "-3n", or "-2n".
|
||||
* mdoc(7): Fix an assertion failure caused by .Bl -column without .It
|
||||
but containing eqn(7) or tbl(7) code.
|
||||
* roff(7): Fix an assertion failure caused by \z\[u00FF] with -Tps/-Tpdf.
|
||||
* roff(7): Fix an assertion failures caused by whitespace inside \o''
|
||||
(overstrike) sequences.
|
||||
* -Thtml: Fix an assertion failure caused by -Oman or -Oincludes of
|
||||
excessive length.
|
||||
--- PORTABILITY IMPROVEMENTS ---
|
||||
* man(1): Do not mix stdio narrow and wide stream orientation
|
||||
on stdout, which could cause output corruption on glibc.
|
||||
* mandoc(1): Autodetect a suitable locale for -Tutf8 mode.
|
||||
* ./configure: Autodetect whether PATH_MAX and O_DIRECTORY are defined.
|
||||
* ./configure: Autodetect if nanosleep(3) needs -lrt.
|
||||
* ./configure: Provide an ${LN} configuration variable.
|
||||
* ./configure: Put compiler arguments that may contain -l at the end.
|
||||
--- MINOR BUGFIXES ---
|
||||
* mdoc(7): Fix SYNOPSIS output if the first child of .Nm is a macro.
|
||||
* mdoc(7) -Thtml: Improve formatting of .Bl -tag with short tags.
|
||||
* man(7) -Thtml: Preserve whitespace in .nf (nofill) mode.
|
||||
* mandoc(1): Error out on invalid output options on the command line.
|
||||
--- STRUCTURAL CHANGES, no functional change ---
|
||||
* Redesign part of the mandoc_html(3) interfaces, making them much
|
||||
easier to use and reducing the amount of code by a few hundred lines.
|
||||
--- THANKS TO ---
|
||||
* Michael Stapelberg (Debian) for designing the new mandocd(8)
|
||||
and parts of the new catman(8), for release testing, and for a
|
||||
number of patches and bug reports.
|
||||
* Baptiste Daroussin (FreeBSD) for profiling the new makewhatis(8)
|
||||
implementation and suggesting an algorithmic improvement which
|
||||
more than doubled performance, and for a few bug reports.
|
||||
* Ed Maste (FreeBSD) for an important patch improving reproducibility
|
||||
of builds in makewhatis(8), and for a few bug reports.
|
||||
* Theo Buehler (OpenBSD) for almost twenty important bug reports,
|
||||
most of them found by systematic afl(1) fuzzing.
|
||||
* Benny Lofgren, David Dahlberg, and in particular Vadim Zhukov
|
||||
for crucial help in getting .Bl -tag CSS formatting fixed.
|
||||
* Svyatoslav Mishyn (Crux Linux) for an initial version of the
|
||||
patch to autodetect a suitable locale for -Tutf8 mode
|
||||
and for release testing.
|
||||
* Jason McIntyre (OpenBSD) for multiple useful discussions
|
||||
and a number of bug reports.
|
||||
* Sevan Janiyan (NetBSD) for extensive release testing and multiple
|
||||
bug reports.
|
||||
* Thomas Klausner and Christos Zoulas (NetBSD), Yuri Pankov (illumos),
|
||||
and Leah Neukirchen (Void Linux) for release testing and bug reports.
|
||||
* Ulrich Spoerlein (FreeBSD) for release testing.
|
||||
* Alexander Bluhm, Andrew Fresh, Antoine Jacoutot, Antony Bentley,
|
||||
Christian Weisgerber, Jonathan Gray, Marc Espie, Martijn van Duren,
|
||||
Stuart Henderson, Ted Unangst, Theo de Raadt (OpenBSD), Abhinav
|
||||
Upadhyay, Kamil Rytarowski (NetBSD), Aaron M. Ucko, Bdale Garbee,
|
||||
Reiner Herrmann, Shane Kerr (Debian), Daniel Sabogal (Alpine Linux),
|
||||
Carsten Kunze (Heirloom roff), Kristaps Dzonsons (bsd.lv),
|
||||
Anton Lindqvist, Jan Stary, Jeremy A. Mates, Mark Patruck,
|
||||
Pavan Maddamsetti, Sean Levy <attila@stalphonsos.com>, and
|
||||
Tiago Silva for bug reports.
|
||||
* Brent Cook, Marc Espie, Philip Guenther, Todd Miller (OpenBSD)
|
||||
and Markus Waldeck for useful discussions.
|
||||
* And as usual, OpenCSW for providing me with a Solaris 9/10/11
|
||||
testing environment.
|
||||
|
||||
Changes in version 1.13.4, released on July 14, 2016
|
||||
|
||||
--- MAJOR NEW FEATURES ---
|
||||
|
@ -109,7 +237,7 @@ Changes in version 1.13.4, released on July 14, 2016
|
|||
again resulting in more than half a dozen important bug reports.
|
||||
* Svyatoslav Mishyn (Crux Linux) for some patches, several bug
|
||||
reports, and extensive release testing.
|
||||
* Christian Neukirchen (void Linux) for a number of compatibility
|
||||
* Leah Neukirchen (Void Linux) for a number of compatibility
|
||||
patches and suggestions and several bug reports.
|
||||
* Christos Zoulas (NetBSD) for a bug fix patch and some useful
|
||||
suggestions for cleanup.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
************************************************************************
|
||||
* Official mandoc TODO.
|
||||
* Id: TODO,v 1.218 2016/06/05 21:06:04 schwarze Exp
|
||||
* Id: TODO,v 1.234 2017/02/18 11:53:33 schwarze Exp
|
||||
************************************************************************
|
||||
|
||||
Many issues are annotated for difficulty as follows:
|
||||
|
@ -32,15 +32,6 @@ Many issues are annotated for difficulty as follows:
|
|||
Obviously, as the issues have not been solved yet, these annotations
|
||||
are mere guesses, and some may be wrong.
|
||||
|
||||
************************************************************************
|
||||
* 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.
|
||||
loc ** exist * algo * size ** imp **
|
||||
|
||||
************************************************************************
|
||||
* missing features
|
||||
************************************************************************
|
||||
|
@ -202,10 +193,6 @@ are mere guesses, and some may be wrong.
|
|||
uqs@ Thu, 2 Jun 2011 11:33:35 +0200
|
||||
loc * exist ** algo *** size * imp **
|
||||
|
||||
--- missing man features -----------------------------------------------
|
||||
|
||||
- -T[x]html doesn't stipulate non-collapsing spaces in literal mode
|
||||
|
||||
--- missing tbl features -----------------------------------------------
|
||||
|
||||
- horizontal lines in the layout still consume data cells
|
||||
|
@ -213,6 +200,13 @@ are mere guesses, and some may be wrong.
|
|||
synaptics(4) found by tedu@ Mon, 17 Aug 2015 21:17:42 -0400
|
||||
loc ** exist ** algo ** size ** imp ***
|
||||
|
||||
- break long text into lines inside cells
|
||||
net/lftp(1) from jirib via bentley@ Sep 13, 2016
|
||||
|
||||
- layout l1 for a column of max text width 3 reduces the following
|
||||
inter-column spacing for groff, but not for mandoc
|
||||
net/lftp(1) from jirib via bentley@ Sep 13, 2016
|
||||
|
||||
- the "w" layout option is ignored
|
||||
synaptics(4) found by tedu@ Mon, 17 Aug 2015 21:17:42 -0400
|
||||
loc * exist * algo * size * imp **
|
||||
|
@ -225,13 +219,16 @@ are mere guesses, and some may be wrong.
|
|||
- support mdoc(7) and man(7) macros inside tbl(7) code;
|
||||
probably requires the parser reorg and letting tbl(7)
|
||||
use roff_node such that macro sets can mix;
|
||||
informed by bapt@ that FreeBSD needs this.
|
||||
informed by bapt@ that FreeBSD needs this: 3 Jan 2015 23:32:23 +0100
|
||||
loc *** exist ** algo *** size ** imp ***
|
||||
|
||||
- look at the POSIX manuals in the books/man-pages-posix port,
|
||||
they use some unsupported tbl(7) features.
|
||||
loc * exist ** algo ** size ** imp ***
|
||||
|
||||
- look what Joerg Schilling manual pages use
|
||||
Thu, 19 Mar 2015 18:31:48 +0100
|
||||
|
||||
- use Unicode U+2500 to U+256C for table borders
|
||||
in tbl(7) -Tutf-8 output
|
||||
suggested by bentley@ Tue, 14 Oct 2014 04:10:55 -0600
|
||||
|
@ -265,15 +262,6 @@ are mere guesses, and some may be wrong.
|
|||
even for apropos title line output; req by bapt@
|
||||
loc * exist * algo * size * imp ***
|
||||
|
||||
- makewhatis(8) for preformatted pages:
|
||||
parse the section number from the header line
|
||||
and compare to the section number from the directory name
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- Does makewhatis(8) detect missing NAME sections, missing names,
|
||||
and missing descriptions in all the file formats?
|
||||
loc * exist * algo * size * imp ***
|
||||
|
||||
- clean up escape sequence handling, creating three classes:
|
||||
(1) fully implemented, or parsed and ignored without loss of content
|
||||
(2) unimplemented, potentially causing loss of content
|
||||
|
@ -302,6 +290,8 @@ are mere guesses, and some may be wrong.
|
|||
- look at AT&T DWB http://www2.research.att.com/sw/download
|
||||
Carsten Kunze <carsten dot kunze at arcor dot de> has patches
|
||||
Mon, 4 Aug 2014 17:01:28 +0200
|
||||
ported version: https://github.com/n-t-roff/DWB3.3
|
||||
Carsten Kunze Wed, 22 Apr 2015 11:21:43 +0200
|
||||
|
||||
- look at pages generated from reStructeredText, e.g. devel/mercurial hg(1)
|
||||
These are a weird mixture of man(7) and custom autogenerated low-level
|
||||
|
@ -336,6 +326,9 @@ are mere guesses, and some may be wrong.
|
|||
https://github.com/schmonz/ikiwiki/compare/mandoc
|
||||
Amitai Schlair Mon, 19 May 2014 14:05:53 -0400
|
||||
|
||||
- check features of the Slackware man.conf(5) format
|
||||
Carsten Kunze Wed, 11 Mar 2015 17:57:24 +0100
|
||||
|
||||
************************************************************************
|
||||
* formatting issues: ugly output
|
||||
************************************************************************
|
||||
|
@ -396,7 +389,7 @@ are mere guesses, and some may be wrong.
|
|||
reveals lots of bugs both in groff and mandoc...
|
||||
reported by bentley@ Wed, 22 May 2013 23:49:30 -0600
|
||||
|
||||
--- PDF issues ---------------------------------------------------------
|
||||
--- PostScript and PDF issues ------------------------------------------
|
||||
|
||||
- PDF output doesn't use a monospaced font for .Bd -literal
|
||||
Example: "mandoc -Tpdf afterboot.8 > output.pdf && pdfviewer output.pdf".
|
||||
|
@ -406,21 +399,11 @@ are mere guesses, and some may be wrong.
|
|||
instructions from juanfra@ Wed, 11 Jun 2014 02:21:01 +0200
|
||||
add a new <</Type /Font>> block to the PDF files with /BaseFont /Courier
|
||||
and change the /Name from /F0 to the new font (/F5 (?)).
|
||||
re-reported by tb@ Mon, 16 Mar 2015 16:47:21 +0100
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
--- 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
|
||||
loc * exist * algo ** size * imp ***
|
||||
|
||||
- In -man -Thtml, .nf does not preserve indentation.
|
||||
It should either convert blanks to
|
||||
or use <pre> rather than <div> (like .Bd -literal does).
|
||||
Reported by afresh1@ 12 Apr 2016 14:35:45 -0700
|
||||
|
||||
- .Bf at the beginning of a paragraph inserts a bogus 1ex horizontal
|
||||
space, see for example random(3). Introduced in
|
||||
http://mdocml.bsd.lv/cgi-bin/cvsweb/mdoc_html.c.diff?r1=1.91&r2=1.92
|
||||
|
@ -429,6 +412,9 @@ are mere guesses, and some may be wrong.
|
|||
|
||||
- jsg on icb, Nov 3, 2014:
|
||||
try to guess Xr in man(7) for hyperlinking
|
||||
and render them with <a class="Xr" href=...>
|
||||
https://github.com/Debian/debiman/issues/15
|
||||
loc * exist * algo ** size ** imp **
|
||||
|
||||
- The tables used to render the three-part page headers actually force
|
||||
the width of the <body> to the max-width given for <html>.
|
||||
|
@ -437,9 +423,6 @@ are mere guesses, and some may be wrong.
|
|||
http://undeadly.org/cgi?action=article&sid=20140925064244&pid=1
|
||||
loc * exist * algo ** size * imp ***
|
||||
|
||||
- consider whether <var> can be used for Ar Dv Er Ev Fa Va.
|
||||
from bentley@ Wed, 13 Aug 2014 09:17:55 -0600
|
||||
|
||||
- generate <img> tags in HTML
|
||||
idea from florian@ Tue, 7 Apr 2015 00:26:28 +0000
|
||||
may be possible to implement with .Lk img://something.png alt_text
|
||||
|
@ -456,6 +439,9 @@ are mere guesses, and some may be wrong.
|
|||
Steffen Nurpmeso Sat, 08 Nov 2014 13:34:59 +0100
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- .Lk formatting for long links with line breaks
|
||||
Franco Fichtner 8 Oct 2013 00:33:42 +0200
|
||||
|
||||
- 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
|
||||
|
@ -500,6 +486,7 @@ are mere guesses, and some may be wrong.
|
|||
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
|
||||
reported again by Bruce Evans Fri, 17 Feb 2017 21:22:44 +0100 via bapt@
|
||||
loc *** exist *** algo *** size ** imp ***
|
||||
An easy partial fix would be to just skip the first word if it starts
|
||||
with a dot, including any following white space, when measuring.
|
||||
|
@ -510,12 +497,6 @@ are mere guesses, and some may be wrong.
|
|||
we want three blank lines, not two as in mandoc.
|
||||
loc ** exist ** algo ** size * imp **
|
||||
|
||||
- Header lines of excessive length:
|
||||
Port OpenBSD man_term.c rev. 1.25 to mdoc_term.c
|
||||
and document it in mdoc(7) and man(7) COMPATIBILITY
|
||||
found while talking to Chris Bennett
|
||||
loc * exist * algo * size * imp *
|
||||
|
||||
- Sequences of multiple man(7) paragraphs (.PP, .IP) interspersed
|
||||
with .ps and .nf/.fi produce execessive blank lines, see libJudy
|
||||
and graphics/dcmtk. The parser reorg may help with this.
|
||||
|
@ -528,16 +509,6 @@ are mere guesses, and some may be wrong.
|
|||
in dig(1).
|
||||
loc ** exist ** algo ** size * imp **
|
||||
|
||||
************************************************************************
|
||||
* portability
|
||||
************************************************************************
|
||||
|
||||
- systems having UTF-8 but not en_US.UTF-8
|
||||
call locale(1) from ./configure, select a UTF-8-locale,
|
||||
and use that for test-wchar.c and term_ascii.c
|
||||
to Markus Waldeck Sat, 18 Jul 2015 01:55:37 +0200
|
||||
loc * exist * algo * size * imp *
|
||||
|
||||
************************************************************************
|
||||
* warning issues
|
||||
************************************************************************
|
||||
|
@ -547,21 +518,10 @@ are mere guesses, and some may be wrong.
|
|||
to access the manpath and mandoc.db(3) after parsing.
|
||||
asked for by jmc@ Fri, 4 Dec 2015 22:39:40 +0000
|
||||
|
||||
- Report errors in -O suboption parsing.
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- warn when .Sh or .Ss contain other macros
|
||||
Steffen Nurpmeso, savannah.gnu.org/bugs/index.php?45034
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- check that MANDOCERR_BADTAB is thrown in the right cases,
|
||||
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)
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
- warn about attempts to call non-callable macros
|
||||
Steffen Nurpmeso Tue, 11 Nov 2014 22:55:16 +0100
|
||||
Note that formatting is inconsistent in groff.
|
||||
|
@ -570,9 +530,6 @@ are mere guesses, and some may be wrong.
|
|||
all over mdoc_macro.c and all subtly different.
|
||||
loc ** exist ** algo ** size ** imp **
|
||||
|
||||
- warn about "new sentence, new line"
|
||||
loc ** exist ** algo *** size * imp **
|
||||
|
||||
- mandoc_special does not really check the escape sequence,
|
||||
but just the overall format
|
||||
loc ** exist ** algo *** size ** imp **
|
||||
|
@ -592,13 +549,6 @@ are mere guesses, and some may be wrong.
|
|||
* 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?
|
||||
|
||||
|
@ -612,25 +562,25 @@ are mere guesses, and some may be wrong.
|
|||
************************************************************************
|
||||
|
||||
- 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
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
************************************************************************
|
||||
* structural issues
|
||||
************************************************************************
|
||||
|
||||
- POSIX says in the documentation of sysconf(3) that PATH_MAX
|
||||
is allowed to be so large that it is a bad idea to use it
|
||||
for sizing static buffers. So use dynamic buffers throughout.
|
||||
See the file test-PATH_MAX.c for details.
|
||||
Found by Aaron M. Ucko in the GNU Hurd via Bdale Garbee,
|
||||
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=829624
|
||||
|
||||
- We use the input line number at several places to distinguish
|
||||
same-line from different-line input. That plainly doesn't work
|
||||
with user-defined macros, leading to random breakage.
|
||||
|
@ -646,11 +596,6 @@ Several areas can be cleaned up to make mandoc even faster. These are
|
|||
- struct mparse refactoring
|
||||
Steffen Nurpmeso Thu, 04 Sep 2014 12:50:00 +0200
|
||||
|
||||
- Consider creating some views that will make the database more
|
||||
readable from the sqlite3 shell. Consider using them to
|
||||
abstract from the database structure, too.
|
||||
suggested by espie@ Sat, 19 Apr 2014 14:52:57 +0200
|
||||
|
||||
************************************************************************
|
||||
* CGI issues
|
||||
************************************************************************
|
||||
|
@ -659,9 +604,6 @@ Several areas can be cleaned up to make mandoc even faster. These are
|
|||
output through libz.
|
||||
- Sandbox (see OpenSSH).
|
||||
- Enable caching support via HTTP 304 and If-Modified-Since.
|
||||
- Allow for cgi.h to be overridden by CGI environment variables.
|
||||
Otherwise, binary distributions will inherit the compile-time
|
||||
behaviour, which is not optimal.
|
||||
- Have Mac OSX systems automatically disable -static compilation of the
|
||||
CGI: -static isn't supported.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Id: apropos.1,v 1.39 2015/04/03 08:46:17 schwarze Exp
|
||||
.\" Id: apropos.1,v 1.40 2017/01/31 19:44:04 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
|
@ -15,7 +15,7 @@
|
|||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd April 3, 2015
|
||||
.Dd January 31, 2017
|
||||
.Dt APROPOS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -468,6 +468,10 @@ and in
|
|||
.Ox 5.6
|
||||
for
|
||||
.Nm whatis .
|
||||
The options
|
||||
.Fl acfhIKklOTWw
|
||||
appeared in
|
||||
.Ox 5.7 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
.An Bill Joy
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Id: cgi.c,v 1.135 2016/07/11 22:48:37 schwarze Exp */
|
||||
/* Id: cgi.c,v 1.147 2017/02/08 13:34:27 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@usta.de>
|
||||
* Copyright (c) 2014, 2015, 2016, 2017 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
|
||||
|
@ -21,7 +21,9 @@
|
|||
#include <sys/time.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#if HAVE_ERR
|
||||
#include <err.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
@ -113,17 +115,18 @@ static const char *const sec_names[] = {
|
|||
static const int sec_MAX = sizeof(sec_names) / sizeof(char *);
|
||||
|
||||
static const char *const arch_names[] = {
|
||||
"amd64", "alpha", "armish", "armv7",
|
||||
"hppa", "hppa64", "i386", "landisk",
|
||||
"amd64", "alpha", "armv7", "arm64",
|
||||
"hppa", "i386", "landisk",
|
||||
"loongson", "luna88k", "macppc", "mips64",
|
||||
"octeon", "sgi", "socppc", "sparc",
|
||||
"sparc64", "zaurus",
|
||||
"amiga", "arc", "arm32", "atari",
|
||||
"aviion", "beagle", "cats", "hp300",
|
||||
"octeon", "sgi", "socppc", "sparc64",
|
||||
"amiga", "arc", "armish", "arm32",
|
||||
"atari", "aviion", "beagle", "cats",
|
||||
"hppa64", "hp300",
|
||||
"ia64", "mac68k", "mvme68k", "mvme88k",
|
||||
"mvmeppc", "palm", "pc532", "pegasos",
|
||||
"pmax", "powerpc", "solbourne", "sun3",
|
||||
"vax", "wgrisc", "x68k"
|
||||
"pmax", "powerpc", "solbourne", "sparc",
|
||||
"sun3", "vax", "wgrisc", "x68k",
|
||||
"zaurus"
|
||||
};
|
||||
static const int arch_MAX = sizeof(arch_names) / sizeof(char *);
|
||||
|
||||
|
@ -137,7 +140,7 @@ html_putchar(char c)
|
|||
|
||||
switch (c) {
|
||||
case ('"'):
|
||||
printf(""e;");
|
||||
printf(""");
|
||||
break;
|
||||
case ('&'):
|
||||
printf("&");
|
||||
|
@ -337,6 +340,7 @@ resp_copy(const char *filename)
|
|||
fflush(stdout);
|
||||
while ((sz = read(fd, buf, sizeof(buf))) > 0)
|
||||
write(STDOUT_FILENO, buf, sz);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,13 +353,12 @@ resp_begin_html(int code, const char *msg)
|
|||
printf("<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
"<meta charset=\"UTF-8\"/>\n"
|
||||
"<link rel=\"stylesheet\" href=\"%s/mandoc.css\""
|
||||
" <meta charset=\"UTF-8\"/>\n"
|
||||
" <link rel=\"stylesheet\" href=\"%s/mandoc.css\""
|
||||
" type=\"text/css\" media=\"all\">\n"
|
||||
"<title>%s</title>\n"
|
||||
" <title>%s</title>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
"<!-- Begin page content. //-->\n",
|
||||
"<body>\n",
|
||||
CSS_DIR, CUSTOMIZE_TITLE);
|
||||
|
||||
resp_copy(MAN_DIR "/header.html");
|
||||
|
@ -376,16 +379,14 @@ resp_searchform(const struct req *req, enum focus focus)
|
|||
{
|
||||
int i;
|
||||
|
||||
puts("<!-- Begin search form. //-->");
|
||||
printf("<div id=\"mancgi\">\n"
|
||||
"<form action=\"/%s\" method=\"get\">\n"
|
||||
"<fieldset>\n"
|
||||
"<legend>Manual Page Search Parameters</legend>\n",
|
||||
printf("<form action=\"/%s\" method=\"get\">\n"
|
||||
" <fieldset>\n"
|
||||
" <legend>Manual Page Search Parameters</legend>\n",
|
||||
scriptname);
|
||||
|
||||
/* Write query input box. */
|
||||
|
||||
printf("<input type=\"text\" name=\"query\" value=\"");
|
||||
printf(" <input type=\"text\" name=\"query\" value=\"");
|
||||
if (req->q.query != NULL)
|
||||
html_print(req->q.query);
|
||||
printf( "\" size=\"40\"");
|
||||
|
@ -395,45 +396,46 @@ resp_searchform(const struct req *req, enum focus focus)
|
|||
|
||||
/* Write submission buttons. */
|
||||
|
||||
printf( "<button type=\"submit\" name=\"apropos\" value=\"0\">"
|
||||
printf( " <button type=\"submit\" name=\"apropos\" value=\"0\">"
|
||||
"man</button>\n"
|
||||
"<button type=\"submit\" name=\"apropos\" value=\"1\">"
|
||||
"apropos</button>\n<br/>\n");
|
||||
" <button type=\"submit\" name=\"apropos\" value=\"1\">"
|
||||
"apropos</button>\n"
|
||||
" <br/>\n");
|
||||
|
||||
/* Write section selector. */
|
||||
|
||||
puts("<select name=\"sec\">");
|
||||
puts(" <select name=\"sec\">");
|
||||
for (i = 0; i < sec_MAX; i++) {
|
||||
printf("<option value=\"%s\"", sec_numbers[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>");
|
||||
puts(" </select>");
|
||||
|
||||
/* Write architecture selector. */
|
||||
|
||||
printf( "<select name=\"arch\">\n"
|
||||
"<option value=\"default\"");
|
||||
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]);
|
||||
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>");
|
||||
puts(" </select>");
|
||||
|
||||
/* Write manpath selector. */
|
||||
|
||||
if (req->psz > 1) {
|
||||
puts("<select name=\"manpath\">");
|
||||
puts(" <select name=\"manpath\">");
|
||||
for (i = 0; i < (int)req->psz; i++) {
|
||||
printf("<option ");
|
||||
printf(" <option ");
|
||||
if (strcmp(req->q.manpath, req->p[i]) == 0)
|
||||
printf("selected=\"selected\" ");
|
||||
printf("value=\"");
|
||||
|
@ -442,13 +444,11 @@ resp_searchform(const struct req *req, enum focus focus)
|
|||
html_print(req->p[i]);
|
||||
puts("</option>");
|
||||
}
|
||||
puts("</select>");
|
||||
puts(" </select>");
|
||||
}
|
||||
|
||||
puts("</fieldset>\n"
|
||||
"</form>\n"
|
||||
"</div>");
|
||||
puts("<!-- End search form. //-->");
|
||||
puts(" </fieldset>\n"
|
||||
"</form>");
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -496,9 +496,9 @@ pg_index(const struct req *req)
|
|||
resp_searchform(req, FOCUS_QUERY);
|
||||
printf("<p>\n"
|
||||
"This web interface is documented in the\n"
|
||||
"<a href=\"/%s%sman.cgi.8\">man.cgi(8)</a>\n"
|
||||
"<a class=\"Xr\" href=\"/%s%sman.cgi.8\">man.cgi(8)</a>\n"
|
||||
"manual, and the\n"
|
||||
"<a href=\"/%s%sapropos.1\">apropos(1)</a>\n"
|
||||
"<a class=\"Xr\" href=\"/%s%sapropos.1\">apropos(1)</a>\n"
|
||||
"manual explains the query syntax.\n"
|
||||
"</p>\n",
|
||||
scriptname, *scriptname == '\0' ? "" : "/",
|
||||
|
@ -578,27 +578,21 @@ pg_searchres(const struct req *req, struct manpage *r, size_t sz)
|
|||
req->q.equal || sz == 1 ? FOCUS_NONE : FOCUS_QUERY);
|
||||
|
||||
if (sz > 1) {
|
||||
puts("<div class=\"results\">");
|
||||
puts("<table>");
|
||||
|
||||
puts("<table class=\"results\">");
|
||||
for (i = 0; i < sz; i++) {
|
||||
printf("<tr>\n"
|
||||
"<td class=\"title\">\n"
|
||||
"<a href=\"/%s%s%s/%s",
|
||||
printf(" <tr>\n"
|
||||
" <td>"
|
||||
"<a class=\"Xr\" href=\"/%s%s%s/%s\">",
|
||||
scriptname, *scriptname == '\0' ? "" : "/",
|
||||
req->q.manpath, r[i].file);
|
||||
printf("\">");
|
||||
html_print(r[i].names);
|
||||
printf("</a>\n"
|
||||
"</td>\n"
|
||||
"<td class=\"desc\">");
|
||||
printf("</a></td>\n"
|
||||
" <td><span class=\"Nd\">");
|
||||
html_print(r[i].output);
|
||||
puts("</td>\n"
|
||||
"</tr>");
|
||||
puts("</span></td>\n"
|
||||
" </tr>");
|
||||
}
|
||||
|
||||
puts("</table>\n"
|
||||
"</div>");
|
||||
puts("</table>");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -800,12 +794,14 @@ resp_format(const struct req *req, const char *file)
|
|||
}
|
||||
|
||||
mchars_alloc();
|
||||
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, req->q.manpath);
|
||||
mp = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1,
|
||||
MANDOCLEVEL_BADARG, NULL, req->q.manpath);
|
||||
mparse_readfd(mp, fd, file);
|
||||
close(fd);
|
||||
|
||||
memset(&conf, 0, sizeof(conf));
|
||||
conf.fragment = 1;
|
||||
conf.style = mandoc_strdup(CSS_DIR "/mandoc.css");
|
||||
usepath = strcmp(req->q.manpath, req->p[0]);
|
||||
mandoc_asprintf(&conf.man, "/%s%s%%N.%%S",
|
||||
usepath ? req->q.manpath : "", usepath ? "/" : "");
|
||||
|
@ -833,6 +829,7 @@ resp_format(const struct req *req, const char *file)
|
|||
mparse_free(mp);
|
||||
mchars_free();
|
||||
free(conf.man);
|
||||
free(conf.style);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Id: chars.c,v 1.68 2015/10/13 22:59:54 schwarze Exp */
|
||||
/* Id: chars.c,v 1.69 2017/02/17 18:28:06 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
|
@ -101,8 +101,8 @@ static struct ln lines[] = {
|
|||
{ "bq", ",", 0x201a },
|
||||
{ "lq", "\"", 0x201c },
|
||||
{ "rq", "\"", 0x201d },
|
||||
{ "Lq", "``", 0x201c },
|
||||
{ "Rq", "''", 0x201d },
|
||||
{ "Lq", "\"", 0x201c },
|
||||
{ "Rq", "\"", 0x201d },
|
||||
{ "oq", "`", 0x2018 },
|
||||
{ "cq", "\'", 0x2019 },
|
||||
{ "aq", "\'", 0x0027 },
|
||||
|
|
|
@ -6,8 +6,8 @@ int dummy;
|
|||
|
||||
#else
|
||||
|
||||
/* Id: compat_fts.c,v 1.9 2015/03/18 19:29:48 schwarze Exp */
|
||||
/* $OpenBSD: fts.c,v 1.50 2015/01/16 16:48:51 deraadt Exp $ */
|
||||
/* Id: compat_fts.c,v 1.14 2017/02/18 12:24:24 schwarze Exp */
|
||||
/* $OpenBSD: fts.c,v 1.56 2016/09/21 04:38:56 guenther Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
|
@ -59,12 +59,10 @@ static void fts_load(FTS *, FTSENT *);
|
|||
static size_t fts_maxarglen(char * const *);
|
||||
static void fts_padjust(FTS *, FTSENT *);
|
||||
static int fts_palloc(FTS *, size_t);
|
||||
static FTSENT *fts_sort(FTS *, FTSENT *, int);
|
||||
static unsigned short fts_stat(FTS *, FTSENT *);
|
||||
|
||||
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
|
||||
#ifndef O_DIRECTORY
|
||||
#define O_DIRECTORY 0
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
@ -74,13 +72,13 @@ static unsigned short fts_stat(FTS *, FTSENT *);
|
|||
#define SET(opt) (sp->fts_options |= (opt))
|
||||
|
||||
FTS *
|
||||
fts_open(char * const *argv, int options, void *dummy)
|
||||
fts_open(char * const *argv, int options,
|
||||
int (*compar)(const FTSENT **, const FTSENT **))
|
||||
{
|
||||
FTS *sp;
|
||||
FTSENT *p, *root;
|
||||
int nitems;
|
||||
FTSENT *parent, *tmp;
|
||||
size_t len;
|
||||
FTSENT *parent, *prev;
|
||||
|
||||
/* Options check. */
|
||||
if (options & ~FTS_OPTIONMASK) {
|
||||
|
@ -88,9 +86,16 @@ fts_open(char * const *argv, int options, void *dummy)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/* At least one path must be specified. */
|
||||
if (*argv == NULL) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Allocate/initialize the stream */
|
||||
if ((sp = calloc(1, sizeof(FTS))) == NULL)
|
||||
return (NULL);
|
||||
sp->fts_compar = compar;
|
||||
sp->fts_options = options;
|
||||
|
||||
/*
|
||||
|
@ -106,14 +111,8 @@ fts_open(char * const *argv, int options, void *dummy)
|
|||
parent->fts_level = FTS_ROOTPARENTLEVEL;
|
||||
|
||||
/* Allocate/initialize root(s). */
|
||||
for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
|
||||
/* Don't allow zero-length paths. */
|
||||
if ((len = strlen(*argv)) == 0) {
|
||||
errno = ENOENT;
|
||||
goto mem3;
|
||||
}
|
||||
|
||||
if ((p = fts_alloc(sp, *argv, len)) == NULL)
|
||||
for (root = prev = NULL, nitems = 0; *argv; ++argv, ++nitems) {
|
||||
if ((p = fts_alloc(sp, *argv, strlen(*argv))) == NULL)
|
||||
goto mem3;
|
||||
p->fts_level = FTS_ROOTLEVEL;
|
||||
p->fts_parent = parent;
|
||||
|
@ -124,14 +123,24 @@ fts_open(char * const *argv, int options, void *dummy)
|
|||
if (p->fts_info == FTS_DOT)
|
||||
p->fts_info = FTS_D;
|
||||
|
||||
p->fts_link = NULL;
|
||||
if (root == NULL)
|
||||
tmp = root = p;
|
||||
else {
|
||||
tmp->fts_link = p;
|
||||
tmp = p;
|
||||
/*
|
||||
* If comparison routine supplied, traverse in sorted
|
||||
* order; otherwise traverse in the order specified.
|
||||
*/
|
||||
if (compar) {
|
||||
p->fts_link = root;
|
||||
root = p;
|
||||
} else {
|
||||
p->fts_link = NULL;
|
||||
if (root == NULL)
|
||||
root = p;
|
||||
else
|
||||
prev->fts_link = p;
|
||||
prev = p;
|
||||
}
|
||||
}
|
||||
if (compar && nitems > 1)
|
||||
root = fts_sort(sp, root, nitems);
|
||||
|
||||
/*
|
||||
* Allocate a dummy pointer and make fts_read think that we've just
|
||||
|
@ -201,6 +210,7 @@ fts_close(FTS *sp)
|
|||
/* Free up child linked list, sort array, path buffer, stream ptr.*/
|
||||
if (sp->fts_child)
|
||||
fts_lfree(sp->fts_child);
|
||||
free(sp->fts_array);
|
||||
free(sp->fts_path);
|
||||
free(sp);
|
||||
|
||||
|
@ -317,7 +327,6 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
|
|||
* semantics to fts using fts_set. An error return is allowed for similar
|
||||
* reasons.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
fts_set(FTS *sp, FTSENT *p, int instr)
|
||||
{
|
||||
|
@ -416,8 +425,7 @@ fts_build(FTS *sp)
|
|||
* structures already allocated.
|
||||
*/
|
||||
mem1: saved_errno = errno;
|
||||
if (p)
|
||||
free(p);
|
||||
free(p);
|
||||
fts_lfree(head);
|
||||
(void)closedir(dirp);
|
||||
cur->fts_info = FTS_ERR;
|
||||
|
@ -490,6 +498,10 @@ mem1: saved_errno = errno;
|
|||
cur->fts_info = FTS_DP;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Sort the entries. */
|
||||
if (sp->fts_compar && nitems > 1)
|
||||
head = fts_sort(sp, head, nitems);
|
||||
return (head);
|
||||
}
|
||||
|
||||
|
@ -546,6 +558,40 @@ fts_stat(FTS *sp, FTSENT *p)
|
|||
return (FTS_DEFAULT);
|
||||
}
|
||||
|
||||
static FTSENT *
|
||||
fts_sort(FTS *sp, FTSENT *head, int nitems)
|
||||
{
|
||||
FTSENT **ap, *p;
|
||||
|
||||
/*
|
||||
* Construct an array of pointers to the structures and call qsort(3).
|
||||
* Reassemble the array in the order returned by qsort. If unable to
|
||||
* sort for memory reasons, return the directory entries in their
|
||||
* current order. Allocate enough space for the current needs plus
|
||||
* 40 so don't realloc one entry at a time.
|
||||
*/
|
||||
if (nitems > sp->fts_nitems) {
|
||||
struct _ftsent **a;
|
||||
|
||||
sp->fts_nitems = nitems + 40;
|
||||
if ((a = reallocarray(sp->fts_array,
|
||||
sp->fts_nitems, sizeof(FTSENT *))) == NULL) {
|
||||
free(sp->fts_array);
|
||||
sp->fts_array = NULL;
|
||||
sp->fts_nitems = 0;
|
||||
return (head);
|
||||
}
|
||||
sp->fts_array = a;
|
||||
}
|
||||
for (ap = sp->fts_array, p = head; p; p = p->fts_link)
|
||||
*ap++ = p;
|
||||
qsort(sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
|
||||
for (head = *(ap = sp->fts_array); --nitems; ++ap)
|
||||
ap[0]->fts_link = ap[1];
|
||||
ap[0]->fts_link = NULL;
|
||||
return (head);
|
||||
}
|
||||
|
||||
static FTSENT *
|
||||
fts_alloc(FTS *sp, const char *name, size_t namelen)
|
||||
{
|
||||
|
@ -597,8 +643,7 @@ fts_palloc(FTS *sp, size_t more)
|
|||
*/
|
||||
more += 256;
|
||||
if (sp->fts_pathlen + more < sp->fts_pathlen) {
|
||||
if (sp->fts_path)
|
||||
free(sp->fts_path);
|
||||
free(sp->fts_path);
|
||||
sp->fts_path = NULL;
|
||||
errno = ENAMETOOLONG;
|
||||
return (1);
|
||||
|
@ -606,8 +651,7 @@ fts_palloc(FTS *sp, size_t more)
|
|||
sp->fts_pathlen += more;
|
||||
p = realloc(sp->fts_path, sp->fts_pathlen);
|
||||
if (p == NULL) {
|
||||
if (sp->fts_path)
|
||||
free(sp->fts_path);
|
||||
free(sp->fts_path);
|
||||
sp->fts_path = NULL;
|
||||
return (1);
|
||||
}
|
||||
|
|
|
@ -38,9 +38,12 @@
|
|||
typedef struct {
|
||||
struct _ftsent *fts_cur; /* current node */
|
||||
struct _ftsent *fts_child; /* linked list of children */
|
||||
struct _ftsent **fts_array; /* sort array */
|
||||
dev_t fts_dev; /* starting device # */
|
||||
char *fts_path; /* path for this descent */
|
||||
size_t fts_pathlen; /* sizeof(path) */
|
||||
int fts_nitems; /* elements in the sort array */
|
||||
int (*fts_compar)(); /* compare function */
|
||||
|
||||
#define FTS_NOCHDIR 0x0004 /* don't change directories */
|
||||
#define FTS_PHYSICAL 0x0010 /* physical walk */
|
||||
|
@ -94,7 +97,8 @@ typedef struct _ftsent {
|
|||
|
||||
|
||||
int fts_close(FTS *);
|
||||
FTS *fts_open(char * const *, int, void *);
|
||||
FTS *fts_open(char * const *, int,
|
||||
int (*)(const FTSENT **, const FTSENT **));
|
||||
FTSENT *fts_read(FTS *);
|
||||
int fts_set(FTS *, FTSENT *, int);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Id: configure.local.example,v 1.13 2016/07/14 11:09:06 schwarze Exp
|
||||
# Id: configure.local.example,v 1.29 2017/02/18 12:24:24 schwarze Exp
|
||||
#
|
||||
# Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org>
|
||||
# Copyright (c) 2014, 2015, 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
|
||||
|
@ -48,10 +48,17 @@ HAVE_WCHAR=1
|
|||
|
||||
HAVE_WCHAR=0
|
||||
|
||||
# For -Tutf8 mode, mandoc needs to set an arbitrary locale having
|
||||
# a UTF-8 character set. If autodetection of a suitable locale
|
||||
# fails or selects an undesirable locale, you can manually choose
|
||||
# the locale for -Tutf8 mode:
|
||||
|
||||
UTF8_LOCALE=en_US.UTF-8
|
||||
|
||||
# When man(1) or apropos(1) is called without -m and -M options,
|
||||
# MANPATH is not set in the environment, man.conf(5) is not available
|
||||
# and manpath(1) not used, manuals are searched for in the following
|
||||
# directory trees by default.
|
||||
# MANPATH is not set in the environment, and man.conf(5) is not
|
||||
# available, manuals are searched for in the following directory
|
||||
# trees by default.
|
||||
|
||||
MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
|
||||
|
||||
|
@ -65,7 +72,7 @@ MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
|
|||
# If you do not want uname(3) to be called but instead want a fixed
|
||||
# string to be used, use the following line:
|
||||
|
||||
OSNAME="OpenBSD 5.9"
|
||||
OSNAME="OpenBSD 6.0"
|
||||
|
||||
# The following installation directories are used.
|
||||
# It is possible to set only one or a few of these variables,
|
||||
|
@ -76,25 +83,8 @@ OSNAME="OpenBSD 5.9"
|
|||
PREFIX="/usr/local"
|
||||
BINDIR="${PREFIX}/bin"
|
||||
SBINDIR="${PREFIX}/sbin"
|
||||
INCLUDEDIR="${PREFIX}/include/mandoc"
|
||||
LIBDIR="${PREFIX}/lib/mandoc"
|
||||
MANDIR="${PREFIX}/man"
|
||||
|
||||
# The man(1) utility needs to know where the manuals reside.
|
||||
# We know of two ways to tell it: via manpath(1) or man.conf(5).
|
||||
# The latter is used by OpenBSD and NetBSD, the former by most
|
||||
# other systems.
|
||||
|
||||
# Force usage of manpath(1).
|
||||
# If it is not installed or not operational,
|
||||
# man(1), makewhatis(8), and apropos(1) will not work properly.
|
||||
HAVE_MANPATH=1
|
||||
|
||||
# Force usage of man.conf(5).
|
||||
# If it does not exist or contains no valid configuration,
|
||||
# man(1), makewhatis(8), and apropos(1) will not work properly.
|
||||
HAVE_MANPATH=0
|
||||
|
||||
# Some distributions may want to avoid naming conflicts
|
||||
# with the configuration files of other man(1) implementations.
|
||||
# This changes the name of the installed section 5 manual page as well.
|
||||
|
@ -113,16 +103,31 @@ MANM_ROFF="mandoc_roff" # default is "roff"
|
|||
MANM_EQN="mandoc_eqn" # default is "eqn"
|
||||
MANM_TBL="mandoc_tbl" # default is "tbl"
|
||||
|
||||
# Some distributions may want to avoid naming conflicts
|
||||
# with other man(1) and soelim(1) utilities.
|
||||
# Some distributions may want to avoid naming conflicts with
|
||||
# other man(1), apropos(1), makewhatis(8), or soelim(1) utilities.
|
||||
# If you want to change the names of binary programs,
|
||||
# the following alternative names are suggested.
|
||||
# Using different names is possible as well.
|
||||
# This changes the names of the installed section 1 manual pages as well.
|
||||
# This changes the names of the installed section 1 and section 8
|
||||
# manual pages as well.
|
||||
# It is possible to set only one or two of these variables,
|
||||
# there is no need to copy the whole block.
|
||||
|
||||
BINM_MAN=mman # default is "man"
|
||||
BINM_APROPOS=mapropos # default is "apropos"
|
||||
BINM_WHATIS=mwhatis # default is "whatis"
|
||||
BINM_MAKEWHATIS=mandocdb # default is "makewhatis"
|
||||
BINM_SOELIM=msoelim # default is "soelim"
|
||||
|
||||
# Some distributions do not want hardlinks
|
||||
# between installed binary programs.
|
||||
# Set the following variable to use symbolic links instead.
|
||||
# It is also used for links between manual pages.
|
||||
# It is only used by the install* targets.
|
||||
# When using this, DESTDIR must be empty or an absolute path.
|
||||
|
||||
LN="ln -sf" # default is "ln -f"
|
||||
|
||||
# Before falling back to the bundled version of the ohash(3) hashing
|
||||
# library, autoconfiguration tries the following linker flag to
|
||||
# link against your system version. If you do have ohash(3) on
|
||||
|
@ -131,11 +136,30 @@ BINM_SOELIM=msoelim # default is "soelim"
|
|||
|
||||
LD_OHASH="-lutil"
|
||||
|
||||
# Some platforms may need additional linker flags to link against libmandoc
|
||||
# that are not autodetected.
|
||||
# For example, Solaris 9 and 10 need -lrt for nanosleep(2).
|
||||
# When library autodetection decides to use -L/usr/local/lib,
|
||||
# -I/usr/local/include is automatically added to CFLAGS.
|
||||
# If you manually set LD_OHASH to something including -L/usr/local/lib,
|
||||
# chances are you will also need the following line:
|
||||
|
||||
LDADD="-lrt"
|
||||
CFLAGS="${CFLAGS} -I/usr/local/include"
|
||||
|
||||
# Some platforms may need an additional linker flag for nanosleep(2).
|
||||
# If none is needed or it is -lrt, it is autodetected.
|
||||
# Otherwise, set the following variable.
|
||||
|
||||
LD_NANOSLEEP="-lrt"
|
||||
|
||||
# Some platforms may need an additional linker flag for recvmsg(2).
|
||||
# If none is needed or it is -lsocket, it is autodetected.
|
||||
# Otherwise, set the following variable.
|
||||
|
||||
LD_RECVMSG="-lsocket"
|
||||
|
||||
# Some platforms might need additional linker flags to link against
|
||||
# libmandoc that are not autodetected, though no such cases are
|
||||
# currently known.
|
||||
|
||||
LDADD="-lm"
|
||||
|
||||
# Some systems may want to set additional linker flags for all the
|
||||
# binaries, not only for those using libmandoc, for example for
|
||||
|
@ -152,43 +176,6 @@ INSTALL_LIB="${INSTALL} -m 0444"
|
|||
INSTALL_MAN="${INSTALL} -m 0444"
|
||||
INSTALL_DATA="${INSTALL} -m 0444"
|
||||
|
||||
# --- user settings related to database support ------------------------
|
||||
|
||||
# By default, building makewhatis(8) and apropos(1) is enabled.
|
||||
# To disable it, for example to avoid the dependency on SQLite3,
|
||||
# use the following line. It that case, the remaining settings
|
||||
# in this section are irrelevant.
|
||||
|
||||
BUILD_DB=0
|
||||
|
||||
# Autoconfiguration tries the following linker flags to find the
|
||||
# SQLite3 library installed on your system. If none of these work,
|
||||
# set the following variable to specify the required linker flags.
|
||||
|
||||
LD_SQLITE3="-lsqlite3"
|
||||
LD_SQLITE3="-L/usr/local/lib -lsqlite3"
|
||||
|
||||
# When library autodetection decides to use -L/usr/local/lib,
|
||||
# -I/usr/local/include is automatically added to CFLAGS.
|
||||
# If you manually set LD_SQLITE3 to something including -L/usr/local/lib,
|
||||
# chances are you will also need the following line:
|
||||
|
||||
CFLAGS="${CFLAGS} -I/usr/local/include"
|
||||
|
||||
# Some distributions may want to avoid naming conflicts
|
||||
# with another implementation of apropos(1) and makewhatis(8).
|
||||
# If you want to change the names of the binary programs,
|
||||
# the following alternative names are suggested.
|
||||
# Using other names is possible as well.
|
||||
# This changes the names of the installed section 1 and section 8
|
||||
# manual pages as well.
|
||||
# It is possible to set only one or two of these variables,
|
||||
# there is no need to copy the whole block.
|
||||
|
||||
BINM_APROPOS=mapropos # default is "apropos"
|
||||
BINM_WHATIS=mwhatis # default is "whatis"
|
||||
BINM_MAKEWHATIS=mandocdb # default is "makewhatis"
|
||||
|
||||
# When using the "homebrew" package manager on Mac OS X, the actual
|
||||
# manuals are located in a so-called "cellar" and only symlinked
|
||||
# into the manual trees. To allow mandoc to follow such symlinks,
|
||||
|
@ -198,11 +185,25 @@ BINM_MAKEWHATIS=mandocdb # default is "makewhatis"
|
|||
PREFIX="/usr/local"
|
||||
HOMEBREWDIR="${PREFIX}/Cellar"
|
||||
|
||||
# --- user settings related man.cgi ------------------------------------
|
||||
# --- user settings for the mandoc(3) library --------------------------
|
||||
|
||||
# By default, libmandoc.a is not installed. It is almost never needed
|
||||
# because there is almost no non-mandoc software out there using this
|
||||
# library. The one notable exception is NetBSD apropos(1).
|
||||
# So, when building for the NetBSD base system - but not for NetBSD
|
||||
# ports nor for pkgsrc! - you may want the following:
|
||||
|
||||
INSTALL_LIBMANDOC=1
|
||||
|
||||
# The following settings are only used when INSTALL_LIBMANDOC is set.
|
||||
|
||||
INCLUDEDIR="${PREFIX}/include/mandoc"
|
||||
LIBDIR="${PREFIX}/lib/mandoc"
|
||||
|
||||
# --- user settings related to man.cgi ---------------------------------
|
||||
|
||||
# By default, building man.cgi(8) is disabled. To enable it, copy
|
||||
# cgi.h.example to cgi.h, edit it, and use the following line.
|
||||
# Obviously, this requires that BUILD_DB is enabled, too.
|
||||
|
||||
BUILD_CGI=1
|
||||
|
||||
|
@ -226,6 +227,20 @@ WWWPREFIX="/var/www"
|
|||
HTDOCDIR="${WWWPREFIX}/htdocs"
|
||||
CGIBINDIR="${WWWPREFIX}/cgi-bin"
|
||||
|
||||
# --- user settings related to catman ----------------------------------
|
||||
|
||||
# By default, building mandocd(8) and catman(8) is disabled.
|
||||
# To enable it, use the following line.
|
||||
# It does not work on SunOS 5.10 because there is no mkdirat(2)
|
||||
# nor on SunOS 5.9 which also lacks CMSG_LEN(3) and CMSG_SPACE(3).
|
||||
|
||||
BUILD_CATMAN=1
|
||||
|
||||
# Install catman(8) with a different name.
|
||||
# See BINM_MAN above for details of how this works.
|
||||
|
||||
BINM_CATMAN=mcatman # default is "catman"
|
||||
|
||||
# --- settings that rarely need to be touched --------------------------
|
||||
|
||||
# Do not set these variables unless you really need to.
|
||||
|
@ -254,13 +269,19 @@ CFLAGS="-g"
|
|||
# be regarded as successful).
|
||||
|
||||
HAVE_DIRENT_NAMLEN=0
|
||||
HAVE_ENDIAN=0
|
||||
HAVE_EFTYPE=0
|
||||
HAVE_ERR=0
|
||||
HAVE_FTS=0
|
||||
HAVE_FTS=0 # Setting this implies HAVE_FTS_COMPARE_CONST=0.
|
||||
HAVE_FTS_COMPARE_CONST=0 # Setting this implies HAVE_FTS=1.
|
||||
HAVE_GETLINE=0
|
||||
HAVE_GETSUBOPT=0
|
||||
HAVE_ISBLANK=0
|
||||
HAVE_MKDTEMP=0
|
||||
HAVE_MMAP=0
|
||||
HAVE_NTOHL=0
|
||||
HAVE_O_DIRECTORY=0
|
||||
HAVE_OHASH=0
|
||||
HAVE_PATH_MAX=0
|
||||
HAVE_PLEDGE=0
|
||||
HAVE_PROGNAME=0
|
||||
HAVE_REALLOCARRAY=0
|
||||
|
@ -273,9 +294,6 @@ HAVE_STRLCPY=0
|
|||
HAVE_STRPTIME=0
|
||||
HAVE_STRSEP=0
|
||||
HAVE_STRTONUM=0
|
||||
HAVE_SYS_ENDIAN=0
|
||||
HAVE_VASPRINTF=0
|
||||
HAVE_WCHAR=0
|
||||
|
||||
HAVE_SQLITE3=0
|
||||
HAVE_SQLITE3_ERRSTR=0
|
||||
HAVE_OHASH=0
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 *);
|
|
@ -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');
|
||||
}
|
|
@ -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 *);
|
|
@ -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;
|
||||
}
|
|
@ -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");
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* Id: dba_write.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.
|
||||
*
|
||||
* Internal interface to low-level functions
|
||||
* for serializing allocation-based data to disk.
|
||||
* For use by dba_array.c and dba.c only.
|
||||
*/
|
||||
|
||||
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);
|
|
@ -0,0 +1,480 @@
|
|||
/* Id: dbm.c,v 1.5 2016/10/18 22:27:25 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)";
|
||||
res.sect = dbm_get(pages[ip].sect);
|
||||
if (res.sect == NULL)
|
||||
res.sect = "(NULL)";
|
||||
res.arch = pages[ip].arch ? dbm_get(pages[ip].arch) : NULL;
|
||||
res.desc = dbm_get(pages[ip].desc);
|
||||
if (res.desc == NULL)
|
||||
res.desc = "(NULL)";
|
||||
res.file = dbm_get(pages[ip].file);
|
||||
if (res.file == NULL)
|
||||
res.file = " (NULL)";
|
||||
res.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 ¯o;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
|
@ -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);
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/* Id: dbm_map.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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
struct dbm_match;
|
||||
|
||||
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 *);
|
|
@ -1,4 +1,4 @@
|
|||
/* Id: demandoc.c,v 1.27 2016/07/09 15:24:19 schwarze Exp */
|
||||
/* Id: demandoc.c,v 1.28 2017/01/10 13:47:00 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
|
@ -239,7 +239,7 @@ pmdoc(const struct roff_node *p, int *line, int *col, int list)
|
|||
{
|
||||
|
||||
for ( ; p; p = p->next) {
|
||||
if (MDOC_LINE & p->flags)
|
||||
if (NODE_LINE & p->flags)
|
||||
pline(p->line, line, col, list);
|
||||
if (ROFFT_TEXT == p->type)
|
||||
pstring(p->string, p->pos, col, list);
|
||||
|
@ -253,7 +253,7 @@ pman(const struct roff_node *p, int *line, int *col, int list)
|
|||
{
|
||||
|
||||
for ( ; p; p = p->next) {
|
||||
if (MAN_LINE & p->flags)
|
||||
if (NODE_LINE & p->flags)
|
||||
pline(p->line, line, col, list);
|
||||
if (ROFFT_TEXT == p->type)
|
||||
pstring(p->string, p->pos, col, list);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Id: eqn_html.c,v 1.10 2014/10/12 19:31:41 schwarze Exp */
|
||||
/* Id: eqn_html.c,v 1.11 2017/01/17 01:47:51 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 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
|
||||
|
@ -31,7 +32,6 @@ static void
|
|||
eqn_box(struct html *p, const struct eqn_box *bp)
|
||||
{
|
||||
struct tag *post, *row, *cell, *t;
|
||||
struct htmlpair tag[2];
|
||||
const struct eqn_box *child, *parent;
|
||||
size_t i, j, rows;
|
||||
|
||||
|
@ -59,10 +59,10 @@ eqn_box(struct html *p, const struct eqn_box *bp)
|
|||
for (rows = 0; NULL != child; rows++)
|
||||
child = child->next;
|
||||
/* Print row-by-row. */
|
||||
post = print_otag(p, TAG_MTABLE, 0, NULL);
|
||||
post = print_otag(p, TAG_MTABLE, "");
|
||||
for (i = 0; i < rows; i++) {
|
||||
parent = bp->first->first;
|
||||
row = print_otag(p, TAG_MTR, 0, NULL);
|
||||
row = print_otag(p, TAG_MTR, "");
|
||||
while (NULL != parent) {
|
||||
child = parent->first;
|
||||
for (j = 0; j < i; j++) {
|
||||
|
@ -70,8 +70,7 @@ eqn_box(struct html *p, const struct eqn_box *bp)
|
|||
break;
|
||||
child = child->next;
|
||||
}
|
||||
cell = print_otag
|
||||
(p, TAG_MTD, 0, NULL);
|
||||
cell = print_otag(p, TAG_MTD, "");
|
||||
/*
|
||||
* If we have no data for this
|
||||
* particular cell, then print a
|
||||
|
@ -89,28 +88,28 @@ eqn_box(struct html *p, const struct eqn_box *bp)
|
|||
|
||||
switch (bp->pos) {
|
||||
case (EQNPOS_TO):
|
||||
post = print_otag(p, TAG_MOVER, 0, NULL);
|
||||
post = print_otag(p, TAG_MOVER, "");
|
||||
break;
|
||||
case (EQNPOS_SUP):
|
||||
post = print_otag(p, TAG_MSUP, 0, NULL);
|
||||
post = print_otag(p, TAG_MSUP, "");
|
||||
break;
|
||||
case (EQNPOS_FROM):
|
||||
post = print_otag(p, TAG_MUNDER, 0, NULL);
|
||||
post = print_otag(p, TAG_MUNDER, "");
|
||||
break;
|
||||
case (EQNPOS_SUB):
|
||||
post = print_otag(p, TAG_MSUB, 0, NULL);
|
||||
post = print_otag(p, TAG_MSUB, "");
|
||||
break;
|
||||
case (EQNPOS_OVER):
|
||||
post = print_otag(p, TAG_MFRAC, 0, NULL);
|
||||
post = print_otag(p, TAG_MFRAC, "");
|
||||
break;
|
||||
case (EQNPOS_FROMTO):
|
||||
post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
|
||||
post = print_otag(p, TAG_MUNDEROVER, "");
|
||||
break;
|
||||
case (EQNPOS_SUBSUP):
|
||||
post = print_otag(p, TAG_MSUBSUP, 0, NULL);
|
||||
post = print_otag(p, TAG_MSUBSUP, "");
|
||||
break;
|
||||
case (EQNPOS_SQRT):
|
||||
post = print_otag(p, TAG_MSQRT, 0, NULL);
|
||||
post = print_otag(p, TAG_MSQRT, "");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -119,52 +118,49 @@ eqn_box(struct html *p, const struct eqn_box *bp)
|
|||
if (bp->top || bp->bottom) {
|
||||
assert(NULL == post);
|
||||
if (bp->top && NULL == bp->bottom)
|
||||
post = print_otag(p, TAG_MOVER, 0, NULL);
|
||||
post = print_otag(p, TAG_MOVER, "");
|
||||
else if (bp->top && bp->bottom)
|
||||
post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
|
||||
post = print_otag(p, TAG_MUNDEROVER, "");
|
||||
else if (bp->bottom)
|
||||
post = print_otag(p, TAG_MUNDER, 0, NULL);
|
||||
post = print_otag(p, TAG_MUNDER, "");
|
||||
}
|
||||
|
||||
if (EQN_PILE == bp->type) {
|
||||
assert(NULL == post);
|
||||
if (bp->first != NULL && bp->first->type == EQN_LIST)
|
||||
post = print_otag(p, TAG_MTABLE, 0, NULL);
|
||||
post = print_otag(p, TAG_MTABLE, "");
|
||||
} else if (bp->type == EQN_LIST &&
|
||||
bp->parent && bp->parent->type == EQN_PILE) {
|
||||
assert(NULL == post);
|
||||
post = print_otag(p, TAG_MTR, 0, NULL);
|
||||
print_otag(p, TAG_MTD, 0, NULL);
|
||||
post = print_otag(p, TAG_MTR, "");
|
||||
print_otag(p, TAG_MTD, "");
|
||||
}
|
||||
|
||||
if (NULL != bp->text) {
|
||||
assert(NULL == post);
|
||||
post = print_otag(p, TAG_MI, 0, NULL);
|
||||
post = print_otag(p, TAG_MI, "");
|
||||
print_text(p, bp->text);
|
||||
} else if (NULL == post) {
|
||||
if (NULL != bp->left || NULL != bp->right) {
|
||||
PAIR_INIT(&tag[0], ATTR_OPEN,
|
||||
NULL == bp->left ? "" : bp->left);
|
||||
PAIR_INIT(&tag[1], ATTR_CLOSE,
|
||||
NULL == bp->right ? "" : bp->right);
|
||||
post = print_otag(p, TAG_MFENCED, 2, tag);
|
||||
}
|
||||
if (NULL != bp->left || NULL != bp->right)
|
||||
post = print_otag(p, TAG_MFENCED, "??",
|
||||
"open", bp->left == NULL ? "" : bp->left,
|
||||
"close", bp->right == NULL ? "" : bp->right);
|
||||
if (NULL == post)
|
||||
post = print_otag(p, TAG_MROW, 0, NULL);
|
||||
post = print_otag(p, TAG_MROW, "");
|
||||
else
|
||||
print_otag(p, TAG_MROW, 0, NULL);
|
||||
print_otag(p, TAG_MROW, "");
|
||||
}
|
||||
|
||||
eqn_box(p, bp->first);
|
||||
|
||||
out:
|
||||
if (NULL != bp->bottom) {
|
||||
t = print_otag(p, TAG_MO, 0, NULL);
|
||||
t = print_otag(p, TAG_MO, "");
|
||||
print_text(p, bp->bottom);
|
||||
print_tagq(p, t);
|
||||
}
|
||||
if (NULL != bp->top) {
|
||||
t = print_otag(p, TAG_MO, 0, NULL);
|
||||
t = print_otag(p, TAG_MO, "");
|
||||
print_text(p, bp->top);
|
||||
print_tagq(p, t);
|
||||
}
|
||||
|
@ -178,11 +174,9 @@ out:
|
|||
void
|
||||
print_eqn(struct html *p, const struct eqn *ep)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
struct tag *t;
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "eqn");
|
||||
t = print_otag(p, TAG_MATH, 1, &tag);
|
||||
t = print_otag(p, TAG_MATH, "c", "eqn");
|
||||
|
||||
p->flags |= HTML_NONOSPACE;
|
||||
eqn_box(p, ep->root);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Id: eqn_term.c,v 1.8 2015/01/01 15:36:08 schwarze Exp */
|
||||
/* Id: eqn_term.c,v 1.9 2017/02/12 14:19:01 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -68,8 +68,10 @@ eqn_box(struct termp *p, const struct eqn_box *bp)
|
|||
|
||||
if (bp->pos == EQNPOS_SQRT) {
|
||||
term_word(p, "sqrt");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
eqn_box(p, bp->first);
|
||||
if (bp->first != NULL) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
eqn_box(p, bp->first);
|
||||
}
|
||||
} else if (bp->type == EQN_SUBEXPR) {
|
||||
child = bp->first;
|
||||
eqn_box(p, child);
|
||||
|
@ -93,7 +95,8 @@ eqn_box(struct termp *p, const struct eqn_box *bp)
|
|||
}
|
||||
} else {
|
||||
child = bp->first;
|
||||
if (bp->type == EQN_MATRIX && child->type == EQN_LIST)
|
||||
if (bp->type == EQN_MATRIX &&
|
||||
child != NULL && child->type == EQN_LIST)
|
||||
child = child->first;
|
||||
while (child != NULL) {
|
||||
eqn_box(p,
|
||||
|
|
|
@ -19,7 +19,7 @@ if [ `id -u` -eq 0 ]; then
|
|||
fi
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "usage: $0 -h manual_source_file ..."
|
||||
echo "usage: $0 [-h] manual_source_file ..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -33,7 +33,7 @@ else
|
|||
EQN="eqn -Tascii"
|
||||
ROFF="groff -ww -Tascii -P -c"
|
||||
fi
|
||||
MOPT="-Werror $MOPT"
|
||||
MOPT="-Werror -Tascii $MOPT"
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
file=$1
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Id: html.c,v 1.192 2016/01/04 12:45:29 schwarze Exp */
|
||||
/* Id: html.c,v 1.207 2017/02/05 20:22:04 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -38,74 +38,67 @@
|
|||
struct htmldata {
|
||||
const char *name;
|
||||
int flags;
|
||||
#define HTML_CLRLINE (1 << 0)
|
||||
#define HTML_NOSTACK (1 << 1)
|
||||
#define HTML_AUTOCLOSE (1 << 2) /* Tag has auto-closure. */
|
||||
#define HTML_NOSTACK (1 << 0)
|
||||
#define HTML_AUTOCLOSE (1 << 1)
|
||||
#define HTML_NLBEFORE (1 << 2)
|
||||
#define HTML_NLBEGIN (1 << 3)
|
||||
#define HTML_NLEND (1 << 4)
|
||||
#define HTML_NLAFTER (1 << 5)
|
||||
#define HTML_NLAROUND (HTML_NLBEFORE | HTML_NLAFTER)
|
||||
#define HTML_NLINSIDE (HTML_NLBEGIN | HTML_NLEND)
|
||||
#define HTML_NLALL (HTML_NLAROUND | HTML_NLINSIDE)
|
||||
#define HTML_INDENT (1 << 6)
|
||||
#define HTML_NOINDENT (1 << 7)
|
||||
};
|
||||
|
||||
static const struct htmldata htmltags[TAG_MAX] = {
|
||||
{"html", HTML_CLRLINE}, /* TAG_HTML */
|
||||
{"head", HTML_CLRLINE}, /* TAG_HEAD */
|
||||
{"body", HTML_CLRLINE}, /* TAG_BODY */
|
||||
{"meta", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_META */
|
||||
{"title", HTML_CLRLINE}, /* TAG_TITLE */
|
||||
{"div", HTML_CLRLINE}, /* TAG_DIV */
|
||||
{"h1", 0}, /* TAG_H1 */
|
||||
{"h2", 0}, /* TAG_H2 */
|
||||
{"span", 0}, /* TAG_SPAN */
|
||||
{"link", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_LINK */
|
||||
{"br", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_BR */
|
||||
{"a", 0}, /* TAG_A */
|
||||
{"table", HTML_CLRLINE}, /* TAG_TABLE */
|
||||
{"tbody", HTML_CLRLINE}, /* TAG_TBODY */
|
||||
{"col", HTML_CLRLINE | HTML_NOSTACK | HTML_AUTOCLOSE}, /* TAG_COL */
|
||||
{"tr", HTML_CLRLINE}, /* TAG_TR */
|
||||
{"td", HTML_CLRLINE}, /* TAG_TD */
|
||||
{"li", HTML_CLRLINE}, /* TAG_LI */
|
||||
{"ul", HTML_CLRLINE}, /* TAG_UL */
|
||||
{"ol", HTML_CLRLINE}, /* TAG_OL */
|
||||
{"dl", HTML_CLRLINE}, /* TAG_DL */
|
||||
{"dt", HTML_CLRLINE}, /* TAG_DT */
|
||||
{"dd", HTML_CLRLINE}, /* TAG_DD */
|
||||
{"blockquote", HTML_CLRLINE}, /* TAG_BLOCKQUOTE */
|
||||
{"pre", HTML_CLRLINE }, /* TAG_PRE */
|
||||
{"b", 0 }, /* TAG_B */
|
||||
{"i", 0 }, /* TAG_I */
|
||||
{"code", 0 }, /* TAG_CODE */
|
||||
{"small", 0 }, /* TAG_SMALL */
|
||||
{"style", HTML_CLRLINE}, /* TAG_STYLE */
|
||||
{"math", HTML_CLRLINE}, /* TAG_MATH */
|
||||
{"mrow", 0}, /* TAG_MROW */
|
||||
{"mi", 0}, /* TAG_MI */
|
||||
{"mo", 0}, /* TAG_MO */
|
||||
{"msup", 0}, /* TAG_MSUP */
|
||||
{"msub", 0}, /* TAG_MSUB */
|
||||
{"msubsup", 0}, /* TAG_MSUBSUP */
|
||||
{"mfrac", 0}, /* TAG_MFRAC */
|
||||
{"msqrt", 0}, /* TAG_MSQRT */
|
||||
{"mfenced", 0}, /* TAG_MFENCED */
|
||||
{"mtable", 0}, /* TAG_MTABLE */
|
||||
{"mtr", 0}, /* TAG_MTR */
|
||||
{"mtd", 0}, /* TAG_MTD */
|
||||
{"munderover", 0}, /* TAG_MUNDEROVER */
|
||||
{"munder", 0}, /* TAG_MUNDER*/
|
||||
{"mover", 0}, /* TAG_MOVER*/
|
||||
};
|
||||
|
||||
static const char *const htmlattrs[ATTR_MAX] = {
|
||||
"name", /* ATTR_NAME */
|
||||
"rel", /* ATTR_REL */
|
||||
"href", /* ATTR_HREF */
|
||||
"type", /* ATTR_TYPE */
|
||||
"media", /* ATTR_MEDIA */
|
||||
"class", /* ATTR_CLASS */
|
||||
"style", /* ATTR_STYLE */
|
||||
"id", /* ATTR_ID */
|
||||
"colspan", /* ATTR_COLSPAN */
|
||||
"charset", /* ATTR_CHARSET */
|
||||
"open", /* ATTR_OPEN */
|
||||
"close", /* ATTR_CLOSE */
|
||||
"mathvariant", /* ATTR_MATHVARIANT */
|
||||
{"html", HTML_NLALL},
|
||||
{"head", HTML_NLALL | HTML_INDENT},
|
||||
{"body", HTML_NLALL},
|
||||
{"meta", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
|
||||
{"title", HTML_NLAROUND},
|
||||
{"div", HTML_NLAROUND},
|
||||
{"h1", HTML_NLAROUND},
|
||||
{"h2", HTML_NLAROUND},
|
||||
{"span", 0},
|
||||
{"link", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
|
||||
{"br", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
|
||||
{"a", 0},
|
||||
{"table", HTML_NLALL | HTML_INDENT},
|
||||
{"colgroup", HTML_NLALL | HTML_INDENT},
|
||||
{"col", HTML_NOSTACK | HTML_AUTOCLOSE | HTML_NLALL},
|
||||
{"tr", HTML_NLALL | HTML_INDENT},
|
||||
{"td", HTML_NLAROUND},
|
||||
{"li", HTML_NLAROUND | HTML_INDENT},
|
||||
{"ul", HTML_NLALL | HTML_INDENT},
|
||||
{"ol", HTML_NLALL | HTML_INDENT},
|
||||
{"dl", HTML_NLALL | HTML_INDENT},
|
||||
{"dt", HTML_NLAROUND},
|
||||
{"dd", HTML_NLAROUND | HTML_INDENT},
|
||||
{"pre", HTML_NLALL | HTML_NOINDENT},
|
||||
{"var", 0},
|
||||
{"cite", 0},
|
||||
{"b", 0},
|
||||
{"i", 0},
|
||||
{"code", 0},
|
||||
{"small", 0},
|
||||
{"style", HTML_NLALL | HTML_INDENT},
|
||||
{"math", HTML_NLALL | HTML_INDENT},
|
||||
{"mrow", 0},
|
||||
{"mi", 0},
|
||||
{"mo", 0},
|
||||
{"msup", 0},
|
||||
{"msub", 0},
|
||||
{"msubsup", 0},
|
||||
{"mfrac", 0},
|
||||
{"msqrt", 0},
|
||||
{"mfenced", 0},
|
||||
{"mtable", 0},
|
||||
{"mtr", 0},
|
||||
{"mtd", 0},
|
||||
{"munderover", 0},
|
||||
{"munder", 0},
|
||||
{"mover", 0},
|
||||
};
|
||||
|
||||
static const char *const roffscales[SCALE_MAX] = {
|
||||
|
@ -121,12 +114,17 @@ static const char *const roffscales[SCALE_MAX] = {
|
|||
"ex", /* SCALE_FS */
|
||||
};
|
||||
|
||||
static void bufncat(struct html *, const char *, size_t);
|
||||
static void a2width(const char *, struct roffsu *);
|
||||
static void print_byte(struct html *, char);
|
||||
static void print_endword(struct html *);
|
||||
static void print_indent(struct html *);
|
||||
static void print_word(struct html *, const char *);
|
||||
|
||||
static void print_ctag(struct html *, struct tag *);
|
||||
static int print_escape(char);
|
||||
static int print_encode(struct html *, const char *, int);
|
||||
static int print_escape(struct html *, char);
|
||||
static int print_encode(struct html *, const char *, const char *, int);
|
||||
static void print_href(struct html *, const char *, const char *, int);
|
||||
static void print_metaf(struct html *, enum mandoc_esc);
|
||||
static void print_attr(struct html *, const char *, const char *);
|
||||
|
||||
|
||||
void *
|
||||
|
@ -136,7 +134,7 @@ html_alloc(const struct manoutput *outopts)
|
|||
|
||||
h = mandoc_calloc(1, sizeof(struct html));
|
||||
|
||||
h->tags.head = NULL;
|
||||
h->tag = NULL;
|
||||
h->style = outopts->style;
|
||||
h->base_man = outopts->man;
|
||||
h->base_includes = outopts->includes;
|
||||
|
@ -154,8 +152,8 @@ html_free(void *p)
|
|||
|
||||
h = (struct html *)p;
|
||||
|
||||
while ((tag = h->tags.head) != NULL) {
|
||||
h->tags.head = tag->next;
|
||||
while ((tag = h->tag) != NULL) {
|
||||
h->tag = tag->next;
|
||||
free(tag);
|
||||
}
|
||||
|
||||
|
@ -165,36 +163,27 @@ html_free(void *p)
|
|||
void
|
||||
print_gen_head(struct html *h)
|
||||
{
|
||||
struct htmlpair tag[4];
|
||||
struct tag *t;
|
||||
|
||||
tag[0].key = ATTR_CHARSET;
|
||||
tag[0].val = "utf-8";
|
||||
print_otag(h, TAG_META, 1, tag);
|
||||
print_otag(h, TAG_META, "?", "charset", "utf-8");
|
||||
|
||||
/*
|
||||
* Print a default style-sheet.
|
||||
*/
|
||||
t = print_otag(h, TAG_STYLE, 0, NULL);
|
||||
print_text(h, "table.head, table.foot { width: 100%; }\n"
|
||||
"td.head-rtitle, td.foot-os { text-align: right; }\n"
|
||||
"td.head-vol { text-align: center; }\n"
|
||||
"table.foot td { width: 50%; }\n"
|
||||
"table.head td { width: 33%; }\n"
|
||||
"div.spacer { margin: 1em 0; }\n");
|
||||
|
||||
t = print_otag(h, TAG_STYLE, "");
|
||||
print_text(h, "table.head, table.foot { width: 100%; }");
|
||||
print_endline(h);
|
||||
print_text(h, "td.head-rtitle, td.foot-os { text-align: right; }");
|
||||
print_endline(h);
|
||||
print_text(h, "td.head-vol { text-align: center; }");
|
||||
print_endline(h);
|
||||
print_text(h, "div.Pp { margin: 1ex 0ex; }");
|
||||
print_tagq(h, t);
|
||||
|
||||
if (h->style) {
|
||||
tag[0].key = ATTR_REL;
|
||||
tag[0].val = "stylesheet";
|
||||
tag[1].key = ATTR_HREF;
|
||||
tag[1].val = h->style;
|
||||
tag[2].key = ATTR_TYPE;
|
||||
tag[2].val = "text/css";
|
||||
tag[3].key = ATTR_MEDIA;
|
||||
tag[3].val = "all";
|
||||
print_otag(h, TAG_LINK, 4, tag);
|
||||
}
|
||||
if (h->style)
|
||||
print_otag(h, TAG_LINK, "?h??", "rel", "stylesheet",
|
||||
h->style, "type", "text/css", "media", "all");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -233,14 +222,14 @@ print_metaf(struct html *h, enum mandoc_esc deco)
|
|||
|
||||
switch (font) {
|
||||
case HTMLFONT_ITALIC:
|
||||
h->metaf = print_otag(h, TAG_I, 0, NULL);
|
||||
h->metaf = print_otag(h, TAG_I, "");
|
||||
break;
|
||||
case HTMLFONT_BOLD:
|
||||
h->metaf = print_otag(h, TAG_B, 0, NULL);
|
||||
h->metaf = print_otag(h, TAG_B, "");
|
||||
break;
|
||||
case HTMLFONT_BI:
|
||||
h->metaf = print_otag(h, TAG_B, 0, NULL);
|
||||
print_otag(h, TAG_I, 0, NULL);
|
||||
h->metaf = print_otag(h, TAG_B, "");
|
||||
print_otag(h, TAG_I, "");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -299,27 +288,27 @@ html_strlen(const char *cp)
|
|||
}
|
||||
|
||||
static int
|
||||
print_escape(char c)
|
||||
print_escape(struct html *h, char c)
|
||||
{
|
||||
|
||||
switch (c) {
|
||||
case '<':
|
||||
printf("<");
|
||||
print_word(h, "<");
|
||||
break;
|
||||
case '>':
|
||||
printf(">");
|
||||
print_word(h, ">");
|
||||
break;
|
||||
case '&':
|
||||
printf("&");
|
||||
print_word(h, "&");
|
||||
break;
|
||||
case '"':
|
||||
printf(""");
|
||||
print_word(h, """);
|
||||
break;
|
||||
case ASCII_NBRSP:
|
||||
printf(" ");
|
||||
print_word(h, " ");
|
||||
break;
|
||||
case ASCII_HYPH:
|
||||
putchar('-');
|
||||
print_byte(h, '-');
|
||||
break;
|
||||
case ASCII_BREAK:
|
||||
break;
|
||||
|
@ -330,8 +319,9 @@ print_escape(char c)
|
|||
}
|
||||
|
||||
static int
|
||||
print_encode(struct html *h, const char *p, int norecurse)
|
||||
print_encode(struct html *h, const char *p, const char *pend, int norecurse)
|
||||
{
|
||||
char numbuf[16];
|
||||
size_t sz;
|
||||
int c, len, nospace;
|
||||
const char *seq;
|
||||
|
@ -339,24 +329,28 @@ print_encode(struct html *h, const char *p, int norecurse)
|
|||
static const char rejs[9] = { '\\', '<', '>', '&', '"',
|
||||
ASCII_NBRSP, ASCII_HYPH, ASCII_BREAK, '\0' };
|
||||
|
||||
if (pend == NULL)
|
||||
pend = strchr(p, '\0');
|
||||
|
||||
nospace = 0;
|
||||
|
||||
while ('\0' != *p) {
|
||||
while (p < pend) {
|
||||
if (HTML_SKIPCHAR & h->flags && '\\' != *p) {
|
||||
h->flags &= ~HTML_SKIPCHAR;
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
|
||||
sz = strcspn(p, rejs);
|
||||
for (sz = strcspn(p, rejs); sz-- && p < pend; p++)
|
||||
if (*p == ' ')
|
||||
print_endword(h);
|
||||
else
|
||||
print_byte(h, *p);
|
||||
|
||||
fwrite(p, 1, sz, stdout);
|
||||
p += (int)sz;
|
||||
|
||||
if ('\0' == *p)
|
||||
if (p >= pend)
|
||||
break;
|
||||
|
||||
if (print_escape(*p++))
|
||||
if (print_escape(h, *p++))
|
||||
continue;
|
||||
|
||||
esc = mandoc_escape(&p, &seq, &len);
|
||||
|
@ -415,50 +409,77 @@ print_encode(struct html *h, const char *p, int norecurse)
|
|||
if ((c < 0x20 && c != 0x09) ||
|
||||
(c > 0x7E && c < 0xA0))
|
||||
c = 0xFFFD;
|
||||
if (c > 0x7E)
|
||||
printf("&#%d;", c);
|
||||
else if ( ! print_escape(c))
|
||||
putchar(c);
|
||||
if (c > 0x7E) {
|
||||
(void)snprintf(numbuf, sizeof(numbuf), "&#%d;", c);
|
||||
print_word(h, numbuf);
|
||||
} else if (print_escape(h, c) == 0)
|
||||
print_byte(h, c);
|
||||
}
|
||||
|
||||
return nospace;
|
||||
}
|
||||
|
||||
static void
|
||||
print_attr(struct html *h, const char *key, const char *val)
|
||||
print_href(struct html *h, const char *name, const char *sec, int man)
|
||||
{
|
||||
printf(" %s=\"", key);
|
||||
(void)print_encode(h, val, 1);
|
||||
putchar('\"');
|
||||
const char *p, *pp;
|
||||
|
||||
pp = man ? h->base_man : h->base_includes;
|
||||
while ((p = strchr(pp, '%')) != NULL) {
|
||||
print_encode(h, pp, p, 1);
|
||||
if (man && p[1] == 'S') {
|
||||
if (sec == NULL)
|
||||
print_byte(h, '1');
|
||||
else
|
||||
print_encode(h, sec, NULL, 1);
|
||||
} else if ((man && p[1] == 'N') ||
|
||||
(man == 0 && p[1] == 'I'))
|
||||
print_encode(h, name, NULL, 1);
|
||||
else
|
||||
print_encode(h, p, p + 2, 1);
|
||||
pp = p + 2;
|
||||
}
|
||||
if (*pp != '\0')
|
||||
print_encode(h, pp, NULL, 1);
|
||||
}
|
||||
|
||||
struct tag *
|
||||
print_otag(struct html *h, enum htmltag tag,
|
||||
int sz, const struct htmlpair *p)
|
||||
print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
|
||||
{
|
||||
int i;
|
||||
va_list ap;
|
||||
struct roffsu mysu, *su;
|
||||
char numbuf[16];
|
||||
struct tag *t;
|
||||
const char *attr;
|
||||
char *arg1, *arg2;
|
||||
double v;
|
||||
int i, have_style, tflags;
|
||||
|
||||
/* Push this tags onto the stack of open scopes. */
|
||||
tflags = htmltags[tag].flags;
|
||||
|
||||
if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
|
||||
/* Push this tag onto the stack of open scopes. */
|
||||
|
||||
if ((tflags & HTML_NOSTACK) == 0) {
|
||||
t = mandoc_malloc(sizeof(struct tag));
|
||||
t->tag = tag;
|
||||
t->next = h->tags.head;
|
||||
h->tags.head = t;
|
||||
t->next = h->tag;
|
||||
h->tag = t;
|
||||
} else
|
||||
t = NULL;
|
||||
|
||||
if ( ! (HTML_NOSPACE & h->flags))
|
||||
if ( ! (HTML_CLRLINE & htmltags[tag].flags)) {
|
||||
/* Manage keeps! */
|
||||
if ( ! (HTML_KEEP & h->flags)) {
|
||||
if (HTML_PREKEEP & h->flags)
|
||||
h->flags |= HTML_KEEP;
|
||||
putchar(' ');
|
||||
} else
|
||||
printf(" ");
|
||||
if (tflags & HTML_NLBEFORE)
|
||||
print_endline(h);
|
||||
if (h->col == 0)
|
||||
print_indent(h);
|
||||
else if ((h->flags & HTML_NOSPACE) == 0) {
|
||||
if (h->flags & HTML_KEEP)
|
||||
print_word(h, " ");
|
||||
else {
|
||||
if (h->flags & HTML_PREKEEP)
|
||||
h->flags |= HTML_KEEP;
|
||||
print_endword(h);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! (h->flags & HTML_NONOSPACE))
|
||||
h->flags &= ~HTML_NOSPACE;
|
||||
|
@ -467,21 +488,185 @@ print_otag(struct html *h, enum htmltag tag,
|
|||
|
||||
/* Print out the tag name and attributes. */
|
||||
|
||||
printf("<%s", htmltags[tag].name);
|
||||
for (i = 0; i < sz; i++)
|
||||
print_attr(h, htmlattrs[p[i].key], p[i].val);
|
||||
print_byte(h, '<');
|
||||
print_word(h, htmltags[tag].name);
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
have_style = 0;
|
||||
while (*fmt != '\0') {
|
||||
if (*fmt == 's') {
|
||||
have_style = 1;
|
||||
fmt++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Parse a non-style attribute and its arguments. */
|
||||
|
||||
arg1 = va_arg(ap, char *);
|
||||
switch (*fmt++) {
|
||||
case 'c':
|
||||
attr = "class";
|
||||
break;
|
||||
case 'h':
|
||||
attr = "href";
|
||||
break;
|
||||
case 'i':
|
||||
attr = "id";
|
||||
break;
|
||||
case '?':
|
||||
attr = arg1;
|
||||
arg1 = va_arg(ap, char *);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
arg2 = NULL;
|
||||
if (*fmt == 'M')
|
||||
arg2 = va_arg(ap, char *);
|
||||
if (arg1 == NULL)
|
||||
continue;
|
||||
|
||||
/* Print the non-style attributes. */
|
||||
|
||||
print_byte(h, ' ');
|
||||
print_word(h, attr);
|
||||
print_byte(h, '=');
|
||||
print_byte(h, '"');
|
||||
switch (*fmt) {
|
||||
case 'M':
|
||||
print_href(h, arg1, arg2, 1);
|
||||
fmt++;
|
||||
break;
|
||||
case 'I':
|
||||
print_href(h, arg1, NULL, 0);
|
||||
fmt++;
|
||||
break;
|
||||
case 'R':
|
||||
print_byte(h, '#');
|
||||
fmt++;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
print_encode(h, arg1, NULL, 1);
|
||||
break;
|
||||
}
|
||||
print_byte(h, '"');
|
||||
}
|
||||
|
||||
/* Print out styles. */
|
||||
|
||||
while (*fmt != '\0') {
|
||||
arg1 = NULL;
|
||||
su = NULL;
|
||||
|
||||
/* First letter: input argument type. */
|
||||
|
||||
switch (*fmt++) {
|
||||
case 'h':
|
||||
i = va_arg(ap, int);
|
||||
su = &mysu;
|
||||
SCALE_HS_INIT(su, i);
|
||||
break;
|
||||
case 's':
|
||||
arg1 = va_arg(ap, char *);
|
||||
break;
|
||||
case 'u':
|
||||
su = va_arg(ap, struct roffsu *);
|
||||
break;
|
||||
case 'v':
|
||||
i = va_arg(ap, int);
|
||||
su = &mysu;
|
||||
SCALE_VS_INIT(su, i);
|
||||
break;
|
||||
case 'w':
|
||||
case 'W':
|
||||
if ((arg2 = va_arg(ap, char *)) == NULL)
|
||||
break;
|
||||
su = &mysu;
|
||||
a2width(arg2, su);
|
||||
if (fmt[-1] == 'W')
|
||||
su->scale *= -1.0;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Second letter: style name. */
|
||||
|
||||
switch (*fmt++) {
|
||||
case 'b':
|
||||
attr = "margin-bottom";
|
||||
break;
|
||||
case 'h':
|
||||
attr = "height";
|
||||
break;
|
||||
case 'i':
|
||||
attr = "text-indent";
|
||||
break;
|
||||
case 'l':
|
||||
attr = "margin-left";
|
||||
break;
|
||||
case 't':
|
||||
attr = "margin-top";
|
||||
break;
|
||||
case 'w':
|
||||
attr = "width";
|
||||
break;
|
||||
case 'W':
|
||||
attr = "min-width";
|
||||
break;
|
||||
case '?':
|
||||
attr = arg1;
|
||||
arg1 = va_arg(ap, char *);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if (su == NULL && arg1 == NULL)
|
||||
continue;
|
||||
|
||||
if (have_style == 1)
|
||||
print_word(h, " style=\"");
|
||||
else
|
||||
print_byte(h, ' ');
|
||||
print_word(h, attr);
|
||||
print_byte(h, ':');
|
||||
print_byte(h, ' ');
|
||||
if (su != NULL) {
|
||||
v = su->scale;
|
||||
if (su->unit == SCALE_MM && (v /= 100.0) == 0.0)
|
||||
v = 1.0;
|
||||
else if (su->unit == SCALE_BU)
|
||||
v /= 24.0;
|
||||
(void)snprintf(numbuf, sizeof(numbuf), "%.2f", v);
|
||||
print_word(h, numbuf);
|
||||
print_word(h, roffscales[su->unit]);
|
||||
} else
|
||||
print_word(h, arg1);
|
||||
print_byte(h, ';');
|
||||
have_style = 2;
|
||||
}
|
||||
if (have_style == 2)
|
||||
print_byte(h, '"');
|
||||
|
||||
va_end(ap);
|
||||
|
||||
/* Accommodate for "well-formed" singleton escaping. */
|
||||
|
||||
if (HTML_AUTOCLOSE & htmltags[tag].flags)
|
||||
putchar('/');
|
||||
print_byte(h, '/');
|
||||
|
||||
putchar('>');
|
||||
print_byte(h, '>');
|
||||
|
||||
h->flags |= HTML_NOSPACE;
|
||||
if (tflags & HTML_NLBEGIN)
|
||||
print_endline(h);
|
||||
else
|
||||
h->flags |= HTML_NOSPACE;
|
||||
|
||||
if ((HTML_AUTOCLOSE | HTML_CLRLINE) & htmltags[tag].flags)
|
||||
putchar('\n');
|
||||
if (tflags & HTML_INDENT)
|
||||
h->indent++;
|
||||
if (tflags & HTML_NOINDENT)
|
||||
h->noindent++;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
@ -489,6 +674,7 @@ print_otag(struct html *h, enum htmltag tag,
|
|||
static void
|
||||
print_ctag(struct html *h, struct tag *tag)
|
||||
{
|
||||
int tflags;
|
||||
|
||||
/*
|
||||
* Remember to close out and nullify the current
|
||||
|
@ -499,55 +685,64 @@ print_ctag(struct html *h, struct tag *tag)
|
|||
if (tag == h->tblt)
|
||||
h->tblt = NULL;
|
||||
|
||||
printf("</%s>", htmltags[tag->tag].name);
|
||||
if (HTML_CLRLINE & htmltags[tag->tag].flags) {
|
||||
h->flags |= HTML_NOSPACE;
|
||||
putchar('\n');
|
||||
}
|
||||
tflags = htmltags[tag->tag].flags;
|
||||
|
||||
h->tags.head = tag->next;
|
||||
if (tflags & HTML_INDENT)
|
||||
h->indent--;
|
||||
if (tflags & HTML_NOINDENT)
|
||||
h->noindent--;
|
||||
if (tflags & HTML_NLEND)
|
||||
print_endline(h);
|
||||
print_indent(h);
|
||||
print_byte(h, '<');
|
||||
print_byte(h, '/');
|
||||
print_word(h, htmltags[tag->tag].name);
|
||||
print_byte(h, '>');
|
||||
if (tflags & HTML_NLAFTER)
|
||||
print_endline(h);
|
||||
|
||||
h->tag = tag->next;
|
||||
free(tag);
|
||||
}
|
||||
|
||||
void
|
||||
print_gen_decls(struct html *h)
|
||||
{
|
||||
|
||||
puts("<!DOCTYPE html>");
|
||||
print_word(h, "<!DOCTYPE html>");
|
||||
print_endline(h);
|
||||
}
|
||||
|
||||
void
|
||||
print_text(struct html *h, const char *word)
|
||||
{
|
||||
|
||||
if ( ! (HTML_NOSPACE & h->flags)) {
|
||||
/* Manage keeps! */
|
||||
if (h->col && (h->flags & HTML_NOSPACE) == 0) {
|
||||
if ( ! (HTML_KEEP & h->flags)) {
|
||||
if (HTML_PREKEEP & h->flags)
|
||||
h->flags |= HTML_KEEP;
|
||||
putchar(' ');
|
||||
print_endword(h);
|
||||
} else
|
||||
printf(" ");
|
||||
print_word(h, " ");
|
||||
}
|
||||
|
||||
assert(NULL == h->metaf);
|
||||
switch (h->metac) {
|
||||
case HTMLFONT_ITALIC:
|
||||
h->metaf = print_otag(h, TAG_I, 0, NULL);
|
||||
h->metaf = print_otag(h, TAG_I, "");
|
||||
break;
|
||||
case HTMLFONT_BOLD:
|
||||
h->metaf = print_otag(h, TAG_B, 0, NULL);
|
||||
h->metaf = print_otag(h, TAG_B, "");
|
||||
break;
|
||||
case HTMLFONT_BI:
|
||||
h->metaf = print_otag(h, TAG_B, 0, NULL);
|
||||
print_otag(h, TAG_I, 0, NULL);
|
||||
h->metaf = print_otag(h, TAG_B, "");
|
||||
print_otag(h, TAG_I, "");
|
||||
break;
|
||||
default:
|
||||
print_indent(h);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(word);
|
||||
if ( ! print_encode(h, word, 0)) {
|
||||
if ( ! print_encode(h, word, NULL, 0)) {
|
||||
if ( ! (h->flags & HTML_NONOSPACE))
|
||||
h->flags &= ~HTML_NOSPACE;
|
||||
h->flags &= ~HTML_NONEWLINE;
|
||||
|
@ -567,7 +762,7 @@ print_tagq(struct html *h, const struct tag *until)
|
|||
{
|
||||
struct tag *tag;
|
||||
|
||||
while ((tag = h->tags.head) != NULL) {
|
||||
while ((tag = h->tag) != NULL) {
|
||||
print_ctag(h, tag);
|
||||
if (until && tag == until)
|
||||
return;
|
||||
|
@ -579,7 +774,7 @@ print_stagq(struct html *h, const struct tag *suntil)
|
|||
{
|
||||
struct tag *tag;
|
||||
|
||||
while ((tag = h->tags.head) != NULL) {
|
||||
while ((tag = h->tag) != NULL) {
|
||||
if (suntil && tag == suntil)
|
||||
return;
|
||||
print_ctag(h, tag);
|
||||
|
@ -590,138 +785,136 @@ void
|
|||
print_paragraph(struct html *h)
|
||||
{
|
||||
struct tag *t;
|
||||
struct htmlpair tag;
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "spacer");
|
||||
t = print_otag(h, TAG_DIV, 1, &tag);
|
||||
t = print_otag(h, TAG_DIV, "c", "Pp");
|
||||
print_tagq(h, t);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bufinit(struct html *h)
|
||||
{
|
||||
|
||||
h->buf[0] = '\0';
|
||||
h->buflen = 0;
|
||||
}
|
||||
|
||||
void
|
||||
bufcat_style(struct html *h, const char *key, const char *val)
|
||||
{
|
||||
|
||||
bufcat(h, key);
|
||||
bufcat(h, ":");
|
||||
bufcat(h, val);
|
||||
bufcat(h, ";");
|
||||
}
|
||||
|
||||
void
|
||||
bufcat(struct html *h, const char *p)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX This is broken and not easy to fix.
|
||||
* When using the -Oincludes option, buffmt_includes()
|
||||
* may pass in strings overrunning BUFSIZ, causing a crash.
|
||||
*/
|
||||
|
||||
h->buflen = strlcat(h->buf, p, BUFSIZ);
|
||||
assert(h->buflen < BUFSIZ);
|
||||
}
|
||||
|
||||
void
|
||||
bufcat_fmt(struct html *h, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
(void)vsnprintf(h->buf + (int)h->buflen,
|
||||
BUFSIZ - h->buflen - 1, fmt, ap);
|
||||
va_end(ap);
|
||||
h->buflen = strlen(h->buf);
|
||||
}
|
||||
/***********************************************************************
|
||||
* Low level output functions.
|
||||
* They implement line breaking using a short static buffer.
|
||||
***********************************************************************/
|
||||
|
||||
/*
|
||||
* Buffer one HTML output byte.
|
||||
* If the buffer is full, flush and deactivate it and start a new line.
|
||||
* If the buffer is inactive, print directly.
|
||||
*/
|
||||
static void
|
||||
bufncat(struct html *h, const char *p, size_t sz)
|
||||
print_byte(struct html *h, char c)
|
||||
{
|
||||
|
||||
assert(h->buflen + sz + 1 < BUFSIZ);
|
||||
strncat(h->buf, p, sz);
|
||||
h->buflen += sz;
|
||||
}
|
||||
|
||||
void
|
||||
buffmt_includes(struct html *h, const char *name)
|
||||
{
|
||||
const char *p, *pp;
|
||||
|
||||
pp = h->base_includes;
|
||||
|
||||
bufinit(h);
|
||||
while (NULL != (p = strchr(pp, '%'))) {
|
||||
bufncat(h, pp, (size_t)(p - pp));
|
||||
switch (*(p + 1)) {
|
||||
case'I':
|
||||
bufcat(h, name);
|
||||
break;
|
||||
default:
|
||||
bufncat(h, p, 2);
|
||||
break;
|
||||
}
|
||||
pp = p + 2;
|
||||
if ((h->flags & HTML_BUFFER) == 0) {
|
||||
putchar(c);
|
||||
h->col++;
|
||||
return;
|
||||
}
|
||||
if (pp)
|
||||
bufcat(h, pp);
|
||||
}
|
||||
|
||||
void
|
||||
buffmt_man(struct html *h, const char *name, const char *sec)
|
||||
{
|
||||
const char *p, *pp;
|
||||
|
||||
pp = h->base_man;
|
||||
|
||||
bufinit(h);
|
||||
while (NULL != (p = strchr(pp, '%'))) {
|
||||
bufncat(h, pp, (size_t)(p - pp));
|
||||
switch (*(p + 1)) {
|
||||
case 'S':
|
||||
bufcat(h, sec ? sec : "1");
|
||||
break;
|
||||
case 'N':
|
||||
bufcat_fmt(h, "%s", name);
|
||||
break;
|
||||
default:
|
||||
bufncat(h, p, 2);
|
||||
break;
|
||||
}
|
||||
pp = p + 2;
|
||||
if (h->col + h->bufcol < sizeof(h->buf)) {
|
||||
h->buf[h->bufcol++] = c;
|
||||
return;
|
||||
}
|
||||
if (pp)
|
||||
bufcat(h, pp);
|
||||
|
||||
putchar('\n');
|
||||
h->col = 0;
|
||||
print_indent(h);
|
||||
putchar(' ');
|
||||
putchar(' ');
|
||||
fwrite(h->buf, h->bufcol, 1, stdout);
|
||||
putchar(c);
|
||||
h->col = (h->indent + 1) * 2 + h->bufcol + 1;
|
||||
h->bufcol = 0;
|
||||
h->flags &= ~HTML_BUFFER;
|
||||
}
|
||||
|
||||
/*
|
||||
* If something was printed on the current output line, end it.
|
||||
* Not to be called right after print_indent().
|
||||
*/
|
||||
void
|
||||
bufcat_su(struct html *h, const char *p, const struct roffsu *su)
|
||||
print_endline(struct html *h)
|
||||
{
|
||||
double v;
|
||||
if (h->col == 0)
|
||||
return;
|
||||
|
||||
v = su->scale;
|
||||
if (SCALE_MM == su->unit && 0.0 == (v /= 100.0))
|
||||
v = 1.0;
|
||||
else if (SCALE_BU == su->unit)
|
||||
v /= 24.0;
|
||||
|
||||
bufcat_fmt(h, "%s: %.2f%s;", p, v, roffscales[su->unit]);
|
||||
if (h->bufcol) {
|
||||
putchar(' ');
|
||||
fwrite(h->buf, h->bufcol, 1, stdout);
|
||||
h->bufcol = 0;
|
||||
}
|
||||
putchar('\n');
|
||||
h->col = 0;
|
||||
h->flags |= HTML_NOSPACE;
|
||||
h->flags &= ~HTML_BUFFER;
|
||||
}
|
||||
|
||||
void
|
||||
bufcat_id(struct html *h, const char *src)
|
||||
/*
|
||||
* Flush the HTML output buffer.
|
||||
* If it is inactive, activate it.
|
||||
*/
|
||||
static void
|
||||
print_endword(struct html *h)
|
||||
{
|
||||
if (h->noindent) {
|
||||
print_byte(h, ' ');
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cf. <http://www.w3.org/TR/html5/dom.html#the-id-attribute>. */
|
||||
|
||||
for (; '\0' != *src; src++)
|
||||
bufncat(h, *src == ' ' ? "_" : src, 1);
|
||||
if ((h->flags & HTML_BUFFER) == 0) {
|
||||
h->col++;
|
||||
h->flags |= HTML_BUFFER;
|
||||
} else if (h->bufcol) {
|
||||
putchar(' ');
|
||||
fwrite(h->buf, h->bufcol, 1, stdout);
|
||||
h->col += h->bufcol + 1;
|
||||
}
|
||||
h->bufcol = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If at the beginning of a new output line,
|
||||
* perform indentation and mark the line as containing output.
|
||||
* Make sure to really produce some output right afterwards,
|
||||
* but do not use print_otag() for producing it.
|
||||
*/
|
||||
static void
|
||||
print_indent(struct html *h)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (h->col)
|
||||
return;
|
||||
|
||||
if (h->noindent == 0) {
|
||||
h->col = h->indent * 2;
|
||||
for (i = 0; i < h->col; i++)
|
||||
putchar(' ');
|
||||
}
|
||||
h->flags &= ~HTML_NOSPACE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print or buffer some characters
|
||||
* depending on the current HTML output buffer state.
|
||||
*/
|
||||
static void
|
||||
print_word(struct html *h, const char *cp)
|
||||
{
|
||||
while (*cp != '\0')
|
||||
print_byte(h, *cp++);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the scaling unit passed in a `-width' argument. This uses
|
||||
* either a native scaling unit (e.g., 1i, 2m) or the string length of
|
||||
* the value.
|
||||
*/
|
||||
static void
|
||||
a2width(const char *p, struct roffsu *su)
|
||||
{
|
||||
if (a2roffsu(p, su, SCALE_MAX) < 2) {
|
||||
su->unit = SCALE_EN;
|
||||
su->scale = html_strlen(p);
|
||||
} else if (su->scale < 0.0)
|
||||
su->scale = 0.0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Id: html.h,v 1.72 2015/11/07 14:01:16 schwarze Exp */
|
||||
/* Id: html.h,v 1.83 2017/02/05 20:22:04 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 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
|
||||
|
@ -29,7 +30,7 @@ enum htmltag {
|
|||
TAG_BR,
|
||||
TAG_A,
|
||||
TAG_TABLE,
|
||||
TAG_TBODY,
|
||||
TAG_COLGROUP,
|
||||
TAG_COL,
|
||||
TAG_TR,
|
||||
TAG_TD,
|
||||
|
@ -39,8 +40,9 @@ enum htmltag {
|
|||
TAG_DL,
|
||||
TAG_DT,
|
||||
TAG_DD,
|
||||
TAG_BLOCKQUOTE,
|
||||
TAG_PRE,
|
||||
TAG_VAR,
|
||||
TAG_CITE,
|
||||
TAG_B,
|
||||
TAG_I,
|
||||
TAG_CODE,
|
||||
|
@ -65,23 +67,6 @@ enum htmltag {
|
|||
TAG_MAX
|
||||
};
|
||||
|
||||
enum htmlattr {
|
||||
ATTR_NAME,
|
||||
ATTR_REL,
|
||||
ATTR_HREF,
|
||||
ATTR_TYPE,
|
||||
ATTR_MEDIA,
|
||||
ATTR_CLASS,
|
||||
ATTR_STYLE,
|
||||
ATTR_ID,
|
||||
ATTR_COLSPAN,
|
||||
ATTR_CHARSET,
|
||||
ATTR_OPEN,
|
||||
ATTR_CLOSE,
|
||||
ATTR_MATHVARIANT,
|
||||
ATTR_MAX
|
||||
};
|
||||
|
||||
enum htmlfont {
|
||||
HTMLFONT_NONE = 0,
|
||||
HTMLFONT_BOLD,
|
||||
|
@ -95,26 +80,6 @@ struct tag {
|
|||
enum htmltag tag;
|
||||
};
|
||||
|
||||
struct tagq {
|
||||
struct tag *head;
|
||||
};
|
||||
|
||||
struct htmlpair {
|
||||
enum htmlattr key;
|
||||
const char *val;
|
||||
};
|
||||
|
||||
#define PAIR_INIT(p, t, v) \
|
||||
do { \
|
||||
(p)->key = (t); \
|
||||
(p)->val = (v); \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
#define PAIR_ID_INIT(p, v) PAIR_INIT(p, ATTR_ID, v)
|
||||
#define PAIR_CLASS_INIT(p, v) PAIR_INIT(p, ATTR_CLASS, v)
|
||||
#define PAIR_HREF_INIT(p, v) PAIR_INIT(p, ATTR_HREF, v)
|
||||
#define PAIR_STYLE_INIT(p, h) PAIR_INIT(p, ATTR_STYLE, (h)->buf)
|
||||
|
||||
struct html {
|
||||
int flags;
|
||||
#define HTML_NOSPACE (1 << 0) /* suppress next space */
|
||||
|
@ -127,14 +92,18 @@ struct html {
|
|||
#define HTML_NOSPLIT (1 << 7) /* do not break line before .An */
|
||||
#define HTML_SPLIT (1 << 8) /* break line before .An */
|
||||
#define HTML_NONEWLINE (1 << 9) /* No line break in nofill mode. */
|
||||
struct tagq tags; /* stack of open tags */
|
||||
#define HTML_BUFFER (1 << 10) /* Collect a word to see if it fits. */
|
||||
size_t indent; /* current output indentation level */
|
||||
int noindent; /* indent disabled by <pre> */
|
||||
size_t col; /* current output byte position */
|
||||
size_t bufcol; /* current buf byte position */
|
||||
char buf[80]; /* output buffer */
|
||||
struct tag *tag; /* last open tag */
|
||||
struct rofftbl tbl; /* current table */
|
||||
struct tag *tblt; /* current open table scope */
|
||||
char *base_man; /* base for manpage href */
|
||||
char *base_includes; /* base for include href */
|
||||
char *style; /* style-sheet URI */
|
||||
char buf[BUFSIZ]; /* see bufcat and friends */
|
||||
size_t buflen;
|
||||
struct tag *metaf; /* current open font scope */
|
||||
enum htmlfont metal; /* last used font */
|
||||
enum htmlfont metac; /* current font mode */
|
||||
|
@ -148,8 +117,7 @@ struct eqn;
|
|||
|
||||
void print_gen_decls(struct html *);
|
||||
void print_gen_head(struct html *);
|
||||
struct tag *print_otag(struct html *, enum htmltag,
|
||||
int, const struct htmlpair *);
|
||||
struct tag *print_otag(struct html *, enum htmltag, const char *, ...);
|
||||
void print_tagq(struct html *, const struct tag *);
|
||||
void print_stagq(struct html *, const struct tag *);
|
||||
void print_text(struct html *, const char *);
|
||||
|
@ -157,20 +125,6 @@ void print_tblclose(struct html *);
|
|||
void print_tbl(struct html *, const struct tbl_span *);
|
||||
void print_eqn(struct html *, const struct eqn *);
|
||||
void print_paragraph(struct html *);
|
||||
|
||||
#if __GNUC__ - 0 >= 4
|
||||
__attribute__((__format__ (__printf__, 2, 3)))
|
||||
#endif
|
||||
void bufcat_fmt(struct html *, const char *, ...);
|
||||
void bufcat(struct html *, const char *);
|
||||
void bufcat_id(struct html *, const char *);
|
||||
void bufcat_style(struct html *,
|
||||
const char *, const char *);
|
||||
void bufcat_su(struct html *, const char *,
|
||||
const struct roffsu *);
|
||||
void bufinit(struct html *);
|
||||
void buffmt_man(struct html *,
|
||||
const char *, const char *);
|
||||
void buffmt_includes(struct html *, const char *);
|
||||
void print_endline(struct html *);
|
||||
|
||||
int html_strlen(const char *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Id: libmdoc.h,v 1.108 2015/11/07 14:01:16 schwarze Exp */
|
||||
/* Id: libmdoc.h,v 1.109 2017/02/16 03:00:23 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
|
@ -70,7 +70,7 @@ struct roff_node *mdoc_block_alloc(struct roff_man *, int, int,
|
|||
int, struct mdoc_arg *);
|
||||
void mdoc_tail_alloc(struct roff_man *, int, int, int);
|
||||
struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int, int,
|
||||
struct roff_node *, enum mdoc_endbody);
|
||||
struct roff_node *);
|
||||
void mdoc_node_relink(struct roff_man *, struct roff_node *);
|
||||
void mdoc_node_validate(struct roff_man *);
|
||||
void mdoc_state(struct roff_man *, struct roff_node *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Id: makewhatis.8,v 1.3 2014/08/17 21:03:06 schwarze Exp
|
||||
.\" Id: makewhatis.8,v 1.4 2016/07/19 22:40:33 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
|
||||
|
@ -15,7 +15,7 @@
|
|||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd August 17, 2014
|
||||
.Dd July 19, 2016
|
||||
.Dt MAKEWHATIS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -79,8 +79,6 @@ If
|
|||
is not provided,
|
||||
.Nm
|
||||
uses the default paths stipulated by
|
||||
.Xr manpath 1 ,
|
||||
or
|
||||
.Xr man.conf 5 .
|
||||
.Pp
|
||||
The arguments are as follows:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Id: man.1,v 1.17 2016/07/01 20:24:04 schwarze Exp
|
||||
.\" Id: man.1,v 1.21 2017/01/31 19:44:04 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -31,7 +31,7 @@
|
|||
.\"
|
||||
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
|
||||
.\"
|
||||
.Dd July 1, 2016
|
||||
.Dd January 31, 2017
|
||||
.Dt MAN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -69,12 +69,8 @@ machine architecture
|
|||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Display all of the manual pages for a specified
|
||||
.Ar section
|
||||
and
|
||||
.Ar name
|
||||
combination.
|
||||
Normally, only the first manual page found is displayed.
|
||||
Display all matching manual pages.
|
||||
Normally, only the first page found is displayed.
|
||||
.It Fl C Ar file
|
||||
Use the specified
|
||||
.Ar file
|
||||
|
@ -100,6 +96,12 @@ This overrides any earlier
|
|||
and
|
||||
.Fl l
|
||||
options.
|
||||
.It Fl h
|
||||
Display only the SYNOPSIS lines of the requested manual pages.
|
||||
Implies
|
||||
.Fl a
|
||||
and
|
||||
.Fl c .
|
||||
.It Fl I Cm os Ns = Ns Ar name
|
||||
Override the default operating system
|
||||
.Ar name
|
||||
|
@ -110,12 +112,6 @@ and for the
|
|||
.Xr man 7
|
||||
.Ic \&TH
|
||||
macro.
|
||||
.It Fl h
|
||||
Display only the SYNOPSIS lines of the requested manual pages.
|
||||
Implies
|
||||
.Fl a
|
||||
and
|
||||
.Fl c .
|
||||
.It Fl K Ar encoding
|
||||
Specify the input encoding.
|
||||
The supported
|
||||
|
@ -330,7 +326,19 @@ is used, the interactive
|
|||
.Ic :t
|
||||
command can be used to go to the definitions of various terms, for
|
||||
example command line options, command modifiers, internal commands,
|
||||
and environment variables.
|
||||
environment variables, function names, preprocessor macros,
|
||||
.Xr errno 2
|
||||
values, and some other emphasized words.
|
||||
Some terms may have defining text at more than one place.
|
||||
In that case, the
|
||||
.Xr less 1
|
||||
interactive commands
|
||||
.Ic t
|
||||
and
|
||||
.Ic T
|
||||
can be used to move to the next and to the previous place providing
|
||||
information about the term last searched for with
|
||||
.Ic :t .
|
||||
.It Ev MANPATH
|
||||
The standard search path used by
|
||||
.Nm
|
||||
|
@ -419,9 +427,23 @@ in
|
|||
.Fl C
|
||||
in
|
||||
.Nx 1.0 ;
|
||||
and
|
||||
.Fl s
|
||||
and
|
||||
.Fl S
|
||||
in
|
||||
.Ox 2.3 .
|
||||
.Ox 2.3 ;
|
||||
and
|
||||
.Fl I ,
|
||||
.Fl K ,
|
||||
.Fl l ,
|
||||
.Fl O ,
|
||||
and
|
||||
.Fl W
|
||||
in
|
||||
.Ox 5.7 .
|
||||
The
|
||||
.Fl T
|
||||
option first appeared in
|
||||
.At III
|
||||
and was also added in
|
||||
.Ox 5.7 .
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Id: man.conf.5,v 1.3 2015/03/27 21:33:20 schwarze Exp
|
||||
.\" Id: man.conf.5,v 1.4 2016/12/28 22:52:17 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
|
@ -14,7 +14,7 @@
|
|||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd March 27, 2015
|
||||
.Dd December 28, 2016
|
||||
.Dt MAN.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -91,7 +91,7 @@ manual.
|
|||
.It Ic fragment Ta none Ta Cm html Ta print only body
|
||||
.It Ic includes Ta string Ta Cm html Ta path to header files
|
||||
.It Ic indent Ta integer Ta Cm ascii , utf8 Ta left margin
|
||||
.It Ic man Ta string Ta Cm html Ta path for Xr links
|
||||
.It Ic man Ta string Ta Cm html Ta path for \&Xr links
|
||||
.It Ic paper Ta string Ta Cm ps , pdf Ta paper size
|
||||
.It Ic style Ta string Ta Cm html Ta CSS file
|
||||
.It Ic width Ta integer Ta Cm ascii , utf8 Ta right margin
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/* Id: man_html.c,v 1.120 2016/01/08 17:48:09 schwarze Exp */
|
||||
/* Id: man_html.c,v 1.133 2017/02/05 18:15:39 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013, 2014, 2015, 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
|
||||
|
@ -32,21 +32,14 @@
|
|||
#include "html.h"
|
||||
#include "main.h"
|
||||
|
||||
/* TODO: preserve ident widths. */
|
||||
/* FIXME: have PD set the default vspace width. */
|
||||
|
||||
#define INDENT 5
|
||||
|
||||
#define MAN_ARGS const struct roff_meta *man, \
|
||||
const struct roff_node *n, \
|
||||
struct mhtml *mh, \
|
||||
struct html *h
|
||||
|
||||
struct mhtml {
|
||||
int fl;
|
||||
#define MANH_LITERAL (1 << 0) /* literal context */
|
||||
};
|
||||
|
||||
struct htmlman {
|
||||
int (*pre)(MAN_ARGS);
|
||||
int (*post)(MAN_ARGS);
|
||||
|
@ -57,6 +50,7 @@ static void print_bvspace(struct html *,
|
|||
static void print_man_head(MAN_ARGS);
|
||||
static void print_man_nodelist(MAN_ARGS);
|
||||
static void print_man_node(MAN_ARGS);
|
||||
static int fillmode(struct html *, int);
|
||||
static int a2width(const struct roff_node *,
|
||||
struct roffsu *);
|
||||
static int man_B_pre(MAN_ARGS);
|
||||
|
@ -74,7 +68,6 @@ static int man_alt_pre(MAN_ARGS);
|
|||
static int man_br_pre(MAN_ARGS);
|
||||
static int man_ign_pre(MAN_ARGS);
|
||||
static int man_in_pre(MAN_ARGS);
|
||||
static int man_literal_pre(MAN_ARGS);
|
||||
static void man_root_post(MAN_ARGS);
|
||||
static void man_root_pre(MAN_ARGS);
|
||||
|
||||
|
@ -101,8 +94,8 @@ static const struct htmlman mans[MAN_MAX] = {
|
|||
{ man_alt_pre, NULL }, /* IR */
|
||||
{ man_alt_pre, NULL }, /* RI */
|
||||
{ man_br_pre, NULL }, /* sp */
|
||||
{ man_literal_pre, NULL }, /* nf */
|
||||
{ man_literal_pre, NULL }, /* fi */
|
||||
{ NULL, NULL }, /* nf */
|
||||
{ NULL, NULL }, /* fi */
|
||||
{ NULL, NULL }, /* RE */
|
||||
{ man_RS_pre, NULL }, /* RS */
|
||||
{ man_ign_pre, NULL }, /* DT */
|
||||
|
@ -112,8 +105,8 @@ static const struct htmlman mans[MAN_MAX] = {
|
|||
{ man_in_pre, NULL }, /* in */
|
||||
{ man_ign_pre, NULL }, /* ft */
|
||||
{ man_OP_pre, NULL }, /* OP */
|
||||
{ man_literal_pre, NULL }, /* EX */
|
||||
{ man_literal_pre, NULL }, /* EE */
|
||||
{ NULL, NULL }, /* EX */
|
||||
{ NULL, NULL }, /* EE */
|
||||
{ man_UR_pre, NULL }, /* UR */
|
||||
{ NULL, NULL }, /* UE */
|
||||
{ man_ign_pre, NULL }, /* ll */
|
||||
|
@ -146,41 +139,38 @@ print_bvspace(struct html *h, const struct roff_node *n)
|
|||
void
|
||||
html_man(void *arg, const struct roff_man *man)
|
||||
{
|
||||
struct mhtml mh;
|
||||
struct htmlpair tag;
|
||||
struct html *h;
|
||||
struct tag *t, *tt;
|
||||
struct tag *t;
|
||||
|
||||
memset(&mh, 0, sizeof(mh));
|
||||
PAIR_CLASS_INIT(&tag, "mandoc");
|
||||
h = (struct html *)arg;
|
||||
|
||||
if ( ! (HTML_FRAGMENT & h->oflags)) {
|
||||
if ((h->oflags & HTML_FRAGMENT) == 0) {
|
||||
print_gen_decls(h);
|
||||
t = print_otag(h, TAG_HTML, 0, NULL);
|
||||
tt = print_otag(h, TAG_HEAD, 0, NULL);
|
||||
print_man_head(&man->meta, man->first, &mh, h);
|
||||
print_tagq(h, tt);
|
||||
print_otag(h, TAG_BODY, 0, NULL);
|
||||
print_otag(h, TAG_DIV, 1, &tag);
|
||||
} else
|
||||
t = print_otag(h, TAG_DIV, 1, &tag);
|
||||
print_otag(h, TAG_HTML, "");
|
||||
t = print_otag(h, TAG_HEAD, "");
|
||||
print_man_head(&man->meta, man->first, h);
|
||||
print_tagq(h, t);
|
||||
print_otag(h, TAG_BODY, "");
|
||||
}
|
||||
|
||||
print_man_nodelist(&man->meta, man->first, &mh, h);
|
||||
man_root_pre(&man->meta, man->first, h);
|
||||
t = print_otag(h, TAG_DIV, "c", "manual-text");
|
||||
print_man_nodelist(&man->meta, man->first->child, h);
|
||||
print_tagq(h, t);
|
||||
putchar('\n');
|
||||
man_root_post(&man->meta, man->first, h);
|
||||
print_tagq(h, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
print_man_head(MAN_ARGS)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
print_gen_head(h);
|
||||
assert(man->title);
|
||||
assert(man->msec);
|
||||
bufcat_fmt(h, "%s(%s)", man->title, man->msec);
|
||||
print_otag(h, TAG_TITLE, 0, NULL);
|
||||
print_text(h, h->buf);
|
||||
mandoc_asprintf(&cp, "%s(%s)", man->title, man->msec);
|
||||
print_otag(h, TAG_TITLE, "");
|
||||
print_text(h, cp);
|
||||
free(cp);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -188,7 +178,7 @@ print_man_nodelist(MAN_ARGS)
|
|||
{
|
||||
|
||||
while (n != NULL) {
|
||||
print_man_node(man, n, mh, h);
|
||||
print_man_node(man, n, h);
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
@ -196,30 +186,95 @@ print_man_nodelist(MAN_ARGS)
|
|||
static void
|
||||
print_man_node(MAN_ARGS)
|
||||
{
|
||||
int child;
|
||||
struct tag *t;
|
||||
static int want_fillmode = MAN_fi;
|
||||
static int save_fillmode;
|
||||
|
||||
child = 1;
|
||||
t = h->tags.head;
|
||||
struct tag *t;
|
||||
int child;
|
||||
|
||||
/*
|
||||
* Handle fill mode switch requests up front,
|
||||
* they would just cause trouble in the subsequent code.
|
||||
*/
|
||||
|
||||
switch (n->tok) {
|
||||
case MAN_nf:
|
||||
case MAN_EX:
|
||||
want_fillmode = MAN_nf;
|
||||
return;
|
||||
case MAN_fi:
|
||||
case MAN_EE:
|
||||
want_fillmode = MAN_fi;
|
||||
if (fillmode(h, 0) == MAN_fi)
|
||||
print_otag(h, TAG_BR, "");
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set up fill mode for the upcoming node. */
|
||||
|
||||
switch (n->type) {
|
||||
case ROFFT_ROOT:
|
||||
man_root_pre(man, n, mh, h);
|
||||
case ROFFT_BLOCK:
|
||||
save_fillmode = 0;
|
||||
/* Some block macros suspend or cancel .nf. */
|
||||
switch (n->tok) {
|
||||
case MAN_TP: /* Tagged paragraphs */
|
||||
case MAN_IP: /* temporarily disable .nf */
|
||||
case MAN_HP: /* for the head. */
|
||||
save_fillmode = want_fillmode;
|
||||
/* FALLTHROUGH */
|
||||
case MAN_SH: /* Section headers */
|
||||
case MAN_SS: /* permanently cancel .nf. */
|
||||
want_fillmode = MAN_fi;
|
||||
/* FALLTHROUGH */
|
||||
case MAN_PP: /* These have no head. */
|
||||
case MAN_LP: /* They will simply */
|
||||
case MAN_P: /* reopen .nf in the body. */
|
||||
case MAN_RS:
|
||||
case MAN_UR:
|
||||
fillmode(h, MAN_fi);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ROFFT_TBL:
|
||||
fillmode(h, MAN_fi);
|
||||
break;
|
||||
case ROFFT_ELEM:
|
||||
/*
|
||||
* Some in-line macros produce tags and/or text
|
||||
* in the handler, so they require fill mode to be
|
||||
* configured up front just like for text nodes.
|
||||
* For the others, keep the traditional approach
|
||||
* of doing the same, for now.
|
||||
*/
|
||||
fillmode(h, want_fillmode);
|
||||
break;
|
||||
case ROFFT_TEXT:
|
||||
if ('\0' == *n->string) {
|
||||
print_paragraph(h);
|
||||
return;
|
||||
}
|
||||
if (n->flags & MAN_LINE && (*n->string == ' ' ||
|
||||
(n->prev != NULL && mh->fl & MANH_LITERAL &&
|
||||
! (h->flags & HTML_NONEWLINE))))
|
||||
print_otag(h, TAG_BR, 0, NULL);
|
||||
print_text(h, n->string);
|
||||
if (fillmode(h, want_fillmode) == MAN_fi &&
|
||||
want_fillmode == MAN_fi &&
|
||||
n->flags & NODE_LINE && *n->string == ' ')
|
||||
print_otag(h, TAG_BR, "");
|
||||
if (*n->string != '\0')
|
||||
break;
|
||||
print_paragraph(h);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Produce output for this node. */
|
||||
|
||||
child = 1;
|
||||
switch (n->type) {
|
||||
case ROFFT_TEXT:
|
||||
t = h->tag;
|
||||
print_text(h, n->string);
|
||||
break;
|
||||
case ROFFT_EQN:
|
||||
if (n->flags & MAN_LINE)
|
||||
putchar('\n');
|
||||
t = h->tag;
|
||||
print_eqn(h, n->eqn);
|
||||
break;
|
||||
case ROFFT_TBL:
|
||||
|
@ -245,32 +300,55 @@ print_man_node(MAN_ARGS)
|
|||
* the "meta" table state. This will be reopened on the
|
||||
* next table element.
|
||||
*/
|
||||
if (h->tblt) {
|
||||
if (h->tblt)
|
||||
print_tblclose(h);
|
||||
t = h->tags.head;
|
||||
}
|
||||
|
||||
t = h->tag;
|
||||
if (mans[n->tok].pre)
|
||||
child = (*mans[n->tok].pre)(man, n, mh, h);
|
||||
child = (*mans[n->tok].pre)(man, n, h);
|
||||
|
||||
/* Some block macros resume .nf in the body. */
|
||||
if (save_fillmode && n->type == ROFFT_BODY)
|
||||
want_fillmode = save_fillmode;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (child && n->child)
|
||||
print_man_nodelist(man, n->child, mh, h);
|
||||
print_man_nodelist(man, n->child, h);
|
||||
|
||||
/* This will automatically close out any font scope. */
|
||||
print_stagq(h, t);
|
||||
|
||||
switch (n->type) {
|
||||
case ROFFT_ROOT:
|
||||
man_root_post(man, n, mh, h);
|
||||
break;
|
||||
case ROFFT_EQN:
|
||||
break;
|
||||
default:
|
||||
if (mans[n->tok].post)
|
||||
(*mans[n->tok].post)(man, n, mh, h);
|
||||
break;
|
||||
if (fillmode(h, 0) == MAN_nf &&
|
||||
n->next != NULL && n->next->flags & NODE_LINE)
|
||||
print_endline(h);
|
||||
}
|
||||
|
||||
/*
|
||||
* MAN_nf switches to no-fill mode, MAN_fi to fill mode.
|
||||
* Other arguments do not switch.
|
||||
* The old mode is returned.
|
||||
*/
|
||||
static int
|
||||
fillmode(struct html *h, int want)
|
||||
{
|
||||
struct tag *pre;
|
||||
int had;
|
||||
|
||||
for (pre = h->tag; pre != NULL; pre = pre->next)
|
||||
if (pre->tag == TAG_PRE)
|
||||
break;
|
||||
|
||||
had = pre == NULL ? MAN_fi : MAN_nf;
|
||||
|
||||
if (want && want != had) {
|
||||
if (want == MAN_nf)
|
||||
print_otag(h, TAG_PRE, "");
|
||||
else
|
||||
print_tagq(h, pre);
|
||||
}
|
||||
return had;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -288,7 +366,6 @@ a2width(const struct roff_node *n, struct roffsu *su)
|
|||
static void
|
||||
man_root_pre(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
struct tag *t, *tt;
|
||||
char *title;
|
||||
|
||||
|
@ -296,26 +373,19 @@ man_root_pre(MAN_ARGS)
|
|||
assert(man->msec);
|
||||
mandoc_asprintf(&title, "%s(%s)", man->title, man->msec);
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "head");
|
||||
t = print_otag(h, TAG_TABLE, 1, &tag);
|
||||
t = print_otag(h, TAG_TABLE, "c", "head");
|
||||
tt = print_otag(h, TAG_TR, "");
|
||||
|
||||
print_otag(h, TAG_TBODY, 0, NULL);
|
||||
|
||||
tt = print_otag(h, TAG_TR, 0, NULL);
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "head-ltitle");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_otag(h, TAG_TD, "c", "head-ltitle");
|
||||
print_text(h, title);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "head-vol");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_otag(h, TAG_TD, "c", "head-vol");
|
||||
if (NULL != man->vol)
|
||||
print_text(h, man->vol);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "head-rtitle");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_otag(h, TAG_TD, "c", "head-rtitle");
|
||||
print_text(h, title);
|
||||
print_tagq(h, t);
|
||||
free(title);
|
||||
|
@ -324,24 +394,16 @@ man_root_pre(MAN_ARGS)
|
|||
static void
|
||||
man_root_post(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
struct tag *t, *tt;
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "foot");
|
||||
t = print_otag(h, TAG_TABLE, 1, &tag);
|
||||
t = print_otag(h, TAG_TABLE, "c", "foot");
|
||||
tt = print_otag(h, TAG_TR, "");
|
||||
|
||||
tt = print_otag(h, TAG_TR, 0, NULL);
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "foot-date");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
|
||||
assert(man->date);
|
||||
print_otag(h, TAG_TD, "c", "foot-date");
|
||||
print_text(h, man->date);
|
||||
print_stagq(h, tt);
|
||||
|
||||
PAIR_CLASS_INIT(&tag, "foot-os");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
|
||||
print_otag(h, TAG_TD, "c", "foot-os");
|
||||
if (man->os)
|
||||
print_text(h, man->os);
|
||||
print_tagq(h, t);
|
||||
|
@ -352,7 +414,6 @@ static int
|
|||
man_br_pre(MAN_ARGS)
|
||||
{
|
||||
struct roffsu su;
|
||||
struct htmlpair tag;
|
||||
|
||||
SCALE_VS_INIT(&su, 1);
|
||||
|
||||
|
@ -363,10 +424,7 @@ man_br_pre(MAN_ARGS)
|
|||
} else
|
||||
su.scale = 0.0;
|
||||
|
||||
bufinit(h);
|
||||
bufcat_su(h, "height", &su);
|
||||
PAIR_STYLE_INIT(&tag, h);
|
||||
print_otag(h, TAG_DIV, 1, &tag);
|
||||
print_otag(h, TAG_DIV, "suh", &su);
|
||||
|
||||
/* So the div isn't empty: */
|
||||
print_text(h, "\\~");
|
||||
|
@ -377,17 +435,8 @@ man_br_pre(MAN_ARGS)
|
|||
static int
|
||||
man_SH_pre(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
|
||||
if (n->type == ROFFT_BLOCK) {
|
||||
mh->fl &= ~MANH_LITERAL;
|
||||
PAIR_CLASS_INIT(&tag, "section");
|
||||
print_otag(h, TAG_DIV, 1, &tag);
|
||||
return 1;
|
||||
} else if (n->type == ROFFT_BODY)
|
||||
return 1;
|
||||
|
||||
print_otag(h, TAG_H1, 0, NULL);
|
||||
if (n->type == ROFFT_HEAD)
|
||||
print_otag(h, TAG_H1, "c", "Sh");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -395,17 +444,11 @@ static int
|
|||
man_alt_pre(MAN_ARGS)
|
||||
{
|
||||
const struct roff_node *nn;
|
||||
int i, savelit;
|
||||
int i;
|
||||
enum htmltag fp;
|
||||
struct tag *t;
|
||||
|
||||
if ((savelit = mh->fl & MANH_LITERAL))
|
||||
print_otag(h, TAG_BR, 0, NULL);
|
||||
|
||||
mh->fl &= ~MANH_LITERAL;
|
||||
|
||||
for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
|
||||
t = NULL;
|
||||
switch (n->tok) {
|
||||
case MAN_BI:
|
||||
fp = i % 2 ? TAG_I : TAG_B;
|
||||
|
@ -432,45 +475,31 @@ man_alt_pre(MAN_ARGS)
|
|||
if (i)
|
||||
h->flags |= HTML_NOSPACE;
|
||||
|
||||
if (TAG_MAX != fp)
|
||||
t = print_otag(h, fp, 0, NULL);
|
||||
if (fp != TAG_MAX)
|
||||
t = print_otag(h, fp, "");
|
||||
|
||||
print_man_node(man, nn, mh, h);
|
||||
print_text(h, nn->string);
|
||||
|
||||
if (t)
|
||||
if (fp != TAG_MAX)
|
||||
print_tagq(h, t);
|
||||
}
|
||||
|
||||
if (savelit)
|
||||
mh->fl |= MANH_LITERAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
man_SM_pre(MAN_ARGS)
|
||||
{
|
||||
|
||||
print_otag(h, TAG_SMALL, 0, NULL);
|
||||
print_otag(h, TAG_SMALL, "");
|
||||
if (MAN_SB == n->tok)
|
||||
print_otag(h, TAG_B, 0, NULL);
|
||||
print_otag(h, TAG_B, "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
man_SS_pre(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
|
||||
if (n->type == ROFFT_BLOCK) {
|
||||
mh->fl &= ~MANH_LITERAL;
|
||||
PAIR_CLASS_INIT(&tag, "subsection");
|
||||
print_otag(h, TAG_DIV, 1, &tag);
|
||||
return 1;
|
||||
} else if (n->type == ROFFT_BODY)
|
||||
return 1;
|
||||
|
||||
print_otag(h, TAG_H2, 0, NULL);
|
||||
if (n->type == ROFFT_HEAD)
|
||||
print_otag(h, TAG_H2, "c", "Ss");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -492,30 +521,30 @@ man_IP_pre(MAN_ARGS)
|
|||
const struct roff_node *nn;
|
||||
|
||||
if (n->type == ROFFT_BODY) {
|
||||
print_otag(h, TAG_DD, 0, NULL);
|
||||
print_otag(h, TAG_DD, "c", "It-tag");
|
||||
return 1;
|
||||
} else if (n->type != ROFFT_HEAD) {
|
||||
print_otag(h, TAG_DL, 0, NULL);
|
||||
print_otag(h, TAG_DL, "c", "Bl-tag");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME: width specification. */
|
||||
|
||||
print_otag(h, TAG_DT, 0, NULL);
|
||||
print_otag(h, TAG_DT, "c", "It-tag");
|
||||
|
||||
/* For IP, only print the first header element. */
|
||||
|
||||
if (MAN_IP == n->tok && n->child)
|
||||
print_man_node(man, n->child, mh, h);
|
||||
print_man_node(man, n->child, h);
|
||||
|
||||
/* For TP, only print next-line header elements. */
|
||||
|
||||
if (MAN_TP == n->tok) {
|
||||
nn = n->child;
|
||||
while (NULL != nn && 0 == (MAN_LINE & nn->flags))
|
||||
while (NULL != nn && 0 == (NODE_LINE & nn->flags))
|
||||
nn = nn->next;
|
||||
while (NULL != nn) {
|
||||
print_man_node(man, nn, mh, h);
|
||||
print_man_node(man, nn, h);
|
||||
nn = nn->next;
|
||||
}
|
||||
}
|
||||
|
@ -526,8 +555,7 @@ man_IP_pre(MAN_ARGS)
|
|||
static int
|
||||
man_HP_pre(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag[2];
|
||||
struct roffsu su;
|
||||
struct roffsu sum, sui;
|
||||
const struct roff_node *np;
|
||||
|
||||
if (n->type == ROFFT_HEAD)
|
||||
|
@ -537,18 +565,14 @@ man_HP_pre(MAN_ARGS)
|
|||
|
||||
np = n->head->child;
|
||||
|
||||
if (NULL == np || ! a2width(np, &su))
|
||||
SCALE_HS_INIT(&su, INDENT);
|
||||
if (np == NULL || !a2width(np, &sum))
|
||||
SCALE_HS_INIT(&sum, INDENT);
|
||||
|
||||
bufinit(h);
|
||||
sui.unit = sum.unit;
|
||||
sui.scale = -sum.scale;
|
||||
|
||||
print_bvspace(h, n);
|
||||
bufcat_su(h, "margin-left", &su);
|
||||
su.scale = -su.scale;
|
||||
bufcat_su(h, "text-indent", &su);
|
||||
PAIR_STYLE_INIT(&tag[0], h);
|
||||
PAIR_CLASS_INIT(&tag[1], "spacer");
|
||||
print_otag(h, TAG_DIV, 2, tag);
|
||||
print_otag(h, TAG_DIV, "csului", "Pp", &sum, &sui);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -556,22 +580,20 @@ static int
|
|||
man_OP_pre(MAN_ARGS)
|
||||
{
|
||||
struct tag *tt;
|
||||
struct htmlpair tag;
|
||||
|
||||
print_text(h, "[");
|
||||
h->flags |= HTML_NOSPACE;
|
||||
PAIR_CLASS_INIT(&tag, "opt");
|
||||
tt = print_otag(h, TAG_SPAN, 1, &tag);
|
||||
tt = print_otag(h, TAG_SPAN, "c", "Op");
|
||||
|
||||
if (NULL != (n = n->child)) {
|
||||
print_otag(h, TAG_B, 0, NULL);
|
||||
print_otag(h, TAG_B, "");
|
||||
print_text(h, n->string);
|
||||
}
|
||||
|
||||
print_stagq(h, tt);
|
||||
|
||||
if (NULL != n && NULL != n->next) {
|
||||
print_otag(h, TAG_I, 0, NULL);
|
||||
print_otag(h, TAG_I, "");
|
||||
print_text(h, n->next->string);
|
||||
}
|
||||
|
||||
|
@ -584,37 +606,21 @@ man_OP_pre(MAN_ARGS)
|
|||
static int
|
||||
man_B_pre(MAN_ARGS)
|
||||
{
|
||||
|
||||
print_otag(h, TAG_B, 0, NULL);
|
||||
print_otag(h, TAG_B, "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
man_I_pre(MAN_ARGS)
|
||||
{
|
||||
|
||||
print_otag(h, TAG_I, 0, NULL);
|
||||
print_otag(h, TAG_I, "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
man_literal_pre(MAN_ARGS)
|
||||
{
|
||||
|
||||
if (MAN_fi == n->tok || MAN_EE == n->tok) {
|
||||
print_otag(h, TAG_BR, 0, NULL);
|
||||
mh->fl &= ~MANH_LITERAL;
|
||||
} else
|
||||
mh->fl |= MANH_LITERAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
man_in_pre(MAN_ARGS)
|
||||
{
|
||||
|
||||
print_otag(h, TAG_BR, 0, NULL);
|
||||
print_otag(h, TAG_BR, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -628,7 +634,6 @@ man_ign_pre(MAN_ARGS)
|
|||
static int
|
||||
man_RS_pre(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
struct roffsu su;
|
||||
|
||||
if (n->type == ROFFT_HEAD)
|
||||
|
@ -640,32 +645,25 @@ man_RS_pre(MAN_ARGS)
|
|||
if (n->head->child)
|
||||
a2width(n->head->child, &su);
|
||||
|
||||
bufinit(h);
|
||||
bufcat_su(h, "margin-left", &su);
|
||||
PAIR_STYLE_INIT(&tag, h);
|
||||
print_otag(h, TAG_DIV, 1, &tag);
|
||||
print_otag(h, TAG_DIV, "sul", &su);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
man_UR_pre(MAN_ARGS)
|
||||
{
|
||||
struct htmlpair tag[2];
|
||||
|
||||
n = n->child;
|
||||
assert(n->type == ROFFT_HEAD);
|
||||
if (n->child != NULL) {
|
||||
assert(n->child->type == ROFFT_TEXT);
|
||||
PAIR_CLASS_INIT(&tag[0], "link-ext");
|
||||
PAIR_HREF_INIT(&tag[1], n->child->string);
|
||||
print_otag(h, TAG_A, 2, tag);
|
||||
print_otag(h, TAG_A, "ch", "Lk", n->child->string);
|
||||
}
|
||||
|
||||
assert(n->next->type == ROFFT_BODY);
|
||||
if (n->next->child != NULL)
|
||||
n = n->next;
|
||||
|
||||
print_man_nodelist(man, n->child, mh, h);
|
||||
print_man_nodelist(man, n->child, h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ struct manoutput {
|
|||
int fragment;
|
||||
int mdoc;
|
||||
int synopsisonly;
|
||||
int noval;
|
||||
};
|
||||
|
||||
struct manconf {
|
||||
|
@ -44,5 +45,5 @@ struct manconf {
|
|||
|
||||
|
||||
void manconf_parse(struct manconf *, const char *, char *, char *);
|
||||
void manconf_output(struct manoutput *, const char *);
|
||||
int manconf_output(struct manoutput *, const char *, int);
|
||||
void manconf_free(struct manconf *);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.\" Id: mandoc.1,v 1.164 2015/11/05 17:47:51 schwarze Exp
|
||||
.\" Id: mandoc.1,v 1.174 2017/02/10 15:45:28 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2012, 2014-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
|
||||
|
@ -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 November 5, 2015
|
||||
.Dd February 10, 2017
|
||||
.Dt MANDOC 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -75,6 +75,10 @@ This overrides any earlier
|
|||
and
|
||||
.Fl l
|
||||
options.
|
||||
.It Fl h
|
||||
Display only the SYNOPSIS lines.
|
||||
Implies
|
||||
.Fl c .
|
||||
.It Fl I Cm os Ns = Ns Ar name
|
||||
Override the default operating system
|
||||
.Ar name
|
||||
|
@ -85,10 +89,6 @@ and for the
|
|||
.Xr man 7
|
||||
.Sq \&TH
|
||||
macro.
|
||||
.It Fl h
|
||||
Display only the SYNOPSIS lines.
|
||||
Implies
|
||||
.Fl c .
|
||||
.It Fl K Ar encoding
|
||||
Specify the input encoding.
|
||||
The supported
|
||||
|
@ -498,7 +498,15 @@ Use
|
|||
to show a human readable representation of the syntax tree.
|
||||
It is useful for debugging the source code of manual pages.
|
||||
The exact format is subject to change, so don't write parsers for it.
|
||||
Each output line shows one syntax tree node.
|
||||
.Pp
|
||||
The first paragraph shows meta data found in the
|
||||
.Xr mdoc 7
|
||||
prologue, on the
|
||||
.Xr man 7
|
||||
.Ic \&TH
|
||||
line, or the fallbacks used.
|
||||
.Pp
|
||||
In the tree dump, each output line shows one syntax tree node.
|
||||
Child nodes are indented with respect to their parent node.
|
||||
The columns are:
|
||||
.Pp
|
||||
|
@ -529,8 +537,27 @@ The input column number (starting at one).
|
|||
A closing parenthesis if the node is a closing delimiter.
|
||||
.It
|
||||
A full stop if the node ends a sentence.
|
||||
.It
|
||||
BROKEN if the node is a block broken by another block.
|
||||
.It
|
||||
NOSRC if the node is not in the input file,
|
||||
but automatically generated from macros.
|
||||
.It
|
||||
NOPRT if the node is not supposed to generate output
|
||||
for any output format.
|
||||
.El
|
||||
.El
|
||||
.Pp
|
||||
The following
|
||||
.Fl O
|
||||
argument is accepted:
|
||||
.Bl -tag -width Ds
|
||||
.It Cm noval
|
||||
Skip validation and show the unvalidated syntax tree.
|
||||
This can help to find out whether a given behaviour is caused by
|
||||
the parser or by the validator.
|
||||
Meta data is not available in this case.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width MANPAGER
|
||||
.It Ev MANPAGER
|
||||
|
@ -809,11 +836,13 @@ This may confuse
|
|||
.Xr makewhatis 8
|
||||
and
|
||||
.Xr apropos 1 .
|
||||
.It Sy "NAME section without name"
|
||||
.It Sy "NAME section without Nm before Nd"
|
||||
.Pq mdoc
|
||||
The NAME section does not contain any
|
||||
.Ic \&Nm
|
||||
child macro.
|
||||
child macro before the first
|
||||
.Ic \&Nd
|
||||
macro.
|
||||
.It Sy "NAME section without description"
|
||||
.Pq mdoc
|
||||
The NAME section lacks the mandatory
|
||||
|
@ -830,6 +859,11 @@ The NAME section contains plain text or macros other than
|
|||
.Ic \&Nm
|
||||
and
|
||||
.Ic \&Nd .
|
||||
.It Sy "missing comma before name"
|
||||
.Pq mdoc
|
||||
The NAME section contains an
|
||||
.Ic \&Nm
|
||||
macro that is neither the first one nor preceded by a comma.
|
||||
.It Sy "missing description line, using \(dq\(dq"
|
||||
.Pq mdoc
|
||||
The
|
||||
|
@ -1147,6 +1181,13 @@ macro is immediately followed by an
|
|||
.Ic \&Re
|
||||
macro on the next input line.
|
||||
Such an empty block does not produce any output.
|
||||
.It Sy "missing section argument"
|
||||
.Pq mdoc
|
||||
An
|
||||
.Ic \&Xr
|
||||
macro lacks its second, section number argument.
|
||||
The first argument, i.e. the name, is printed, but without subsequent
|
||||
parentheses.
|
||||
.It Sy "missing -std argument, adding it"
|
||||
.Pq mdoc
|
||||
An
|
||||
|
@ -1329,6 +1370,10 @@ it is hard to predict which tab stop position the tab will advance to.
|
|||
Whitespace at the end of input lines is almost never semantically
|
||||
significant \(em but in the odd case where it might be, it is
|
||||
extremely confusing when reviewing and maintaining documents.
|
||||
.It Sy "new sentence, new line"
|
||||
.Pq mdoc
|
||||
A new sentence starts in the middle of a text line.
|
||||
Start it on a new input line to help formatters produce correct spacing.
|
||||
.It Sy "bad comment style"
|
||||
.Pq roff
|
||||
Comment lines start with a dot, a backslash, and a double-quote character.
|
||||
|
@ -1615,8 +1660,8 @@ macro fails to specify the list type.
|
|||
.It Sy "missing manual name, using \(dq\(dq"
|
||||
.Pq mdoc
|
||||
The first call to
|
||||
.Ic \&Nm
|
||||
lacks the required argument.
|
||||
.Ic \&Nm ,
|
||||
or any call in the NAME section, lacks the required argument.
|
||||
.It Sy "uname(3) system call failed, using UNKNOWN"
|
||||
.Pq mdoc
|
||||
The
|
||||
|
@ -1804,6 +1849,19 @@ as if they were a text line.
|
|||
.Xr mdoc 7 ,
|
||||
.Xr roff 7 ,
|
||||
.Xr tbl 7
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Ox 4.8 .
|
||||
The option
|
||||
.Fl I
|
||||
appeared in
|
||||
.Ox 5.2 ,
|
||||
and
|
||||
.Fl aCcfhKklMSsw
|
||||
in
|
||||
.Ox 5.7 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
|
@ -1812,12 +1870,3 @@ utility was written by
|
|||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
|
||||
and is maintained by
|
||||
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
|
||||
.Sh BUGS
|
||||
In
|
||||
.Fl T Cm html ,
|
||||
the maximum size of an element attribute is determined by
|
||||
.Dv BUFSIZ ,
|
||||
which is usually 1024 bytes.
|
||||
Be aware of this when setting long link
|
||||
formats such as
|
||||
.Fl O Cm style Ns = Ns Ar really/long/link .
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.\" Id: mandoc.3,v 1.37 2016/07/07 19:19:01 schwarze Exp
|
||||
.\" Id: mandoc.3,v 1.38 2017/01/09 01:37:03 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2010-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
|
||||
|
@ -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 July 7, 2016
|
||||
.Dd January 9, 2017
|
||||
.Dt MANDOC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -34,7 +34,8 @@
|
|||
.Nm mparse_reset ,
|
||||
.Nm mparse_result ,
|
||||
.Nm mparse_strerror ,
|
||||
.Nm mparse_strlevel
|
||||
.Nm mparse_strlevel ,
|
||||
.Nm mparse_updaterc
|
||||
.Nd mandoc macro compiler library
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
|
@ -100,6 +101,11 @@
|
|||
.Fo mparse_strlevel
|
||||
.Fa "enum mandoclevel"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mparse_updaterc
|
||||
.Fa "struct mparse *parse"
|
||||
.Fa "enum mandoclevel *rc"
|
||||
.Fc
|
||||
.In roff.h
|
||||
.Ft void
|
||||
.Fo deroff
|
||||
|
@ -181,6 +187,9 @@ or
|
|||
.Fn man_validate ,
|
||||
respectively;
|
||||
.It
|
||||
if information about the validity of the input is needed, fetch it with
|
||||
.Fn mparse_updaterc ;
|
||||
.It
|
||||
iterate over parse nodes with starting from the
|
||||
.Fa first
|
||||
member of the returned
|
||||
|
@ -416,6 +425,22 @@ Declared in
|
|||
.In mandoc.h ,
|
||||
implemented in
|
||||
.Pa read.c .
|
||||
.It Fn mparse_updaterc
|
||||
If the highest warning or error level that occurred during the current
|
||||
.Fa parse
|
||||
is higher than
|
||||
.Pf * Fa rc ,
|
||||
update
|
||||
.Pf * Fa rc
|
||||
accordingly.
|
||||
This is useful after calling
|
||||
.Fn mdoc_validate
|
||||
or
|
||||
.Fn man_validate .
|
||||
Declared in
|
||||
.In mandoc.h ,
|
||||
implemented in
|
||||
.Pa read.c .
|
||||
.El
|
||||
.Ss Variables
|
||||
.Bl -ohang
|
||||
|
|
|
@ -1,159 +1,189 @@
|
|||
/* Id: mandoc.css,v 1.2 2016/04/13 10:19:23 schwarze Exp */
|
||||
|
||||
/* Id: mandoc.css,v 1.17 2017/02/05 21:00:43 schwarze Exp */
|
||||
/*
|
||||
* This is an example style-sheet provided for mandoc(1) and the -Thtml
|
||||
* or -Txhtml output mode.
|
||||
*
|
||||
* It mimics the appearance of the traditional cvsweb output.
|
||||
*
|
||||
* See mdoc(7) and man(7) for macro explanations.
|
||||
* Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
|
||||
*/
|
||||
|
||||
html { max-width: 880px; margin-left: 1em; }
|
||||
body { font-size: smaller; font-family: Helvetica,Arial,sans-serif; }
|
||||
body > div { padding-left: 2em;
|
||||
padding-top: 1em; }
|
||||
body > div.mandoc,
|
||||
body > div#mancgi { padding-left: 0em;
|
||||
padding-top: 0em; }
|
||||
body > div.results { font-size: smaller; }
|
||||
#mancgi fieldset { text-align: center;
|
||||
border: thin solid silver;
|
||||
border-radius: 1em;
|
||||
font-size: small; }
|
||||
#mancgi input[name=expr] { width: 25%; }
|
||||
.results td.title { vertical-align: top;
|
||||
padding-right: 1em; }
|
||||
h1 { margin-bottom: 1ex; font-size: 110% }
|
||||
div.section > h1 { margin-left: -4ex; } /* Section header (Sh, SH). */
|
||||
h2 { margin-bottom: 1ex; font-size: 105%; margin-left: -2ex; } /* Sub-section header (Ss, SS). */
|
||||
table { width: 100%; margin-top: 0ex; margin-bottom: 0ex; } /* All tables. */
|
||||
td { vertical-align: top; } /* All table cells. */
|
||||
p { } /* Paragraph: Pp, Lp. */
|
||||
blockquote { margin-left: 5ex; margin-top: 0ex; margin-bottom: 0ex; } /* D1. */
|
||||
div.section { margin-bottom: 2ex; margin-left: 5ex; } /* Sections (Sh, SH). */
|
||||
div.subsection { } /* Sub-sections (Ss, SS). */
|
||||
table.synopsis { } /* SYNOPSIS section table. */
|
||||
div.spacer { margin: 1em 0; }
|
||||
/* Global defaults. */
|
||||
|
||||
/* Preamble structure. */
|
||||
html { max-width: 100ex; }
|
||||
body { font-family: Helvetica,Arial,sans-serif; }
|
||||
table { margin-top: 0em;
|
||||
margin-bottom: 0em; }
|
||||
td { vertical-align: top; }
|
||||
ul, ol, dl { margin-top: 0em;
|
||||
margin-bottom: 0em; }
|
||||
li, dt { margin-top: 1em; }
|
||||
|
||||
table.foot { font-size: smaller; margin-top: 1em; border-top: 1px dotted #dddddd; } /* Document footer. */
|
||||
td.foot-date { width: 50%; } /* Document footer: date. */
|
||||
td.foot-os { width: 50%; } /* Document footer: OS/source. */
|
||||
table.head { font-size: smaller; margin-bottom: 1em; border-bottom: 1px dotted #dddddd; } /* Document header. */
|
||||
td.head-ltitle { width: 10%; } /* Document header: left-title. */
|
||||
td.head-vol { width: 80%; } /* Document header: volume. */
|
||||
td.head-rtitle { width: 10%; } /* Document header: right-title. */
|
||||
/* Search form and search results. */
|
||||
|
||||
/* General font modes. */
|
||||
fieldset { border: thin solid silver;
|
||||
border-radius: 1em;
|
||||
text-align: center; }
|
||||
input[name=expr] {
|
||||
width: 25%; }
|
||||
|
||||
i { } /* Italic: BI, IB, I, (implicit). */
|
||||
.emph { font-style: italic; font-weight: normal; } /* Emphasis: Em, Bl -emphasis. */
|
||||
b { } /* Bold: SB, BI, IB, BR, RB, B, (implicit). */
|
||||
.symb { font-style: normal; font-weight: bold; } /* Symbolic: Sy, Ms, Bf -symbolic. */
|
||||
small { } /* Small: SB, SM. */
|
||||
.lit { font-style: normal; font-weight: normal; font-family: monospace; } /* Literal: Dl, Li, Ql, Bf -literal, Bl -literal, Bl -unfilled. */
|
||||
table.results { margin-top: 1em;
|
||||
margin-left: 2em;
|
||||
font-size: smaller; }
|
||||
|
||||
/* Block modes. */
|
||||
/* Header and footer lines. */
|
||||
|
||||
.display { } /* Top of all Bd, D1, Dl. */
|
||||
.list { } /* Top of all Bl. */
|
||||
table.head { width: 100%;
|
||||
border-bottom: 1px dotted #808080;
|
||||
margin-bottom: 1em;
|
||||
font-size: smaller; }
|
||||
td.head-vol { text-align: center; }
|
||||
td.head-rtitle {
|
||||
text-align: right; }
|
||||
span.Nd { }
|
||||
|
||||
/* Context-specific modes. */
|
||||
table.foot { width: 100%;
|
||||
border-top: 1px dotted #808080;
|
||||
margin-top: 1em;
|
||||
font-size: smaller; }
|
||||
td.foot-os { text-align: right; }
|
||||
|
||||
i.addr { font-weight: normal; } /* Address (Ad). */
|
||||
i.arg { font-weight: normal; } /* Command argument (Ar). */
|
||||
span.author { } /* Author name (An). */
|
||||
b.cmd { font-style: normal; } /* Command (Cm). */
|
||||
b.config { font-style: normal; } /* Config statement (Cd). */
|
||||
span.define { } /* Defines (Dv). */
|
||||
span.desc { } /* Nd. After em-dash. */
|
||||
b.diag { font-style: normal; } /* Diagnostic (Bl -diag). */
|
||||
span.env { } /* Environment variables (Ev). */
|
||||
span.errno { } /* Error string (Er). */
|
||||
i.farg { font-weight: normal; } /* Function argument (Fa, Fn). */
|
||||
i.file { font-weight: normal; } /* File (Pa). */
|
||||
b.flag { font-style: normal; } /* Flag (Fl, Cm). */
|
||||
b.fname { font-style: normal; } /* Function name (Fa, Fn, Rv). */
|
||||
i.ftype { font-weight: normal; } /* Function types (Ft, Fn). */
|
||||
b.includes { font-style: normal; } /* Header includes (In). */
|
||||
span.lib { } /* Library (Lb). */
|
||||
i.link-sec { font-weight: normal; } /* Section links (Sx). */
|
||||
b.macro { font-style: normal; } /* Macro-ish thing (Fd). */
|
||||
b.name { font-style: normal; } /* Name of utility (Nm). */
|
||||
span.opt { } /* Options (Op, Oo/Oc). */
|
||||
span.ref { } /* Citations (Rs). */
|
||||
span.ref-auth { } /* Reference author (%A). */
|
||||
i.ref-book { font-weight: normal; } /* Reference book (%B). */
|
||||
span.ref-city { } /* Reference city (%C). */
|
||||
span.ref-date { } /* Reference date (%D). */
|
||||
i.ref-issue { font-weight: normal; } /* Reference issuer/publisher (%I). */
|
||||
i.ref-jrnl { font-weight: normal; } /* Reference journal (%J). */
|
||||
span.ref-num { } /* Reference number (%N). */
|
||||
span.ref-opt { } /* Reference optionals (%O). */
|
||||
span.ref-page { } /* Reference page (%P). */
|
||||
span.ref-corp { } /* Reference corporate/foreign author (%Q). */
|
||||
span.ref-rep { } /* Reference report (%R). */
|
||||
span.ref-title { text-decoration: underline; } /* Reference title (%T). */
|
||||
span.ref-vol { } /* Reference volume (%V). */
|
||||
span.type { font-style: italic; font-weight: normal; } /* Variable types (Vt). */
|
||||
span.unix { } /* Unices (Ux, Ox, Nx, Fx, Bx, Bsx, Dx). */
|
||||
b.utility { font-style: normal; } /* Name of utility (Ex). */
|
||||
b.var { font-style: normal; } /* Variables (Rv). */
|
||||
/* Sections and paragraphs. */
|
||||
|
||||
a.link-ext { } /* Off-site link (Lk). */
|
||||
a.link-includes { } /* Include-file link (In). */
|
||||
a.link-mail { } /* Mailto links (Mt). */
|
||||
a.link-man { } /* Manual links (Xr). */
|
||||
a.link-ref { } /* Reference section links (%Q). */
|
||||
a.link-sec { } /* Section links (Sx). */
|
||||
div.manual-text {
|
||||
margin-left: 5ex; }
|
||||
h1.Sh { margin-top: 2ex;
|
||||
margin-bottom: 1ex;
|
||||
margin-left: -4ex;
|
||||
font-size: 110%; }
|
||||
h2.Ss { margin-top: 2ex;
|
||||
margin-bottom: 1ex;
|
||||
margin-left: -2ex;
|
||||
font-size: 105%; }
|
||||
div.Pp { margin: 1ex 0ex; }
|
||||
a.Sx { }
|
||||
a.Xr { }
|
||||
|
||||
/* Formatting for lists. See mdoc(7). */
|
||||
/* Displays and lists. */
|
||||
|
||||
dl.list-diag { }
|
||||
dt.list-diag { }
|
||||
dd.list-diag { }
|
||||
div.Bd { }
|
||||
div.D1 { margin-left: 5ex; }
|
||||
|
||||
dl.list-hang { }
|
||||
dt.list-hang { }
|
||||
dd.list-hang { }
|
||||
ul.Bl-bullet { list-style-type: disc;
|
||||
padding-left: 1em; }
|
||||
li.It-bullet { }
|
||||
ul.Bl-dash { list-style-type: none;
|
||||
padding-left: 0em; }
|
||||
li.It-dash:before {
|
||||
content: "\2014 "; }
|
||||
ul.Bl-item { list-style-type: none;
|
||||
padding-left: 0em; }
|
||||
li.It-item { }
|
||||
|
||||
dl.list-inset { }
|
||||
dt.list-inset { }
|
||||
dd.list-inset { }
|
||||
ol.Bl-enum { padding-left: 2em; }
|
||||
li.It-enum { }
|
||||
|
||||
dl.list-ohang { }
|
||||
dt.list-ohang { }
|
||||
dd.list-ohang { margin-left: 0ex; }
|
||||
dl.Bl-diag { }
|
||||
dt.It-diag { }
|
||||
dd.It-diag { }
|
||||
b.It-diag { font-style: normal; }
|
||||
dl.Bl-hang { }
|
||||
dt.It-hang { }
|
||||
dd.It-hang { }
|
||||
dl.Bl-inset { }
|
||||
dt.It-inset { }
|
||||
dd.It-inset { }
|
||||
dl.Bl-ohang { }
|
||||
dt.It-ohang { }
|
||||
dd.It-ohang { margin-left: 0ex; }
|
||||
dl.Bl-tag { margin-left: 8ex; }
|
||||
dt.It-tag { float: left;
|
||||
clear: both;
|
||||
margin-top: 0ex;
|
||||
margin-left: -8ex;
|
||||
padding-right: 2ex;
|
||||
vertical-align: top; }
|
||||
dd.It-tag { width: 100%;
|
||||
margin-top: 0ex;
|
||||
margin-left: 0ex;
|
||||
vertical-align: top;
|
||||
overflow: auto; }
|
||||
|
||||
dl.list-tag { }
|
||||
dt.list-tag { }
|
||||
dd.list-tag { }
|
||||
table.Bl-column { }
|
||||
tr.It-column { }
|
||||
td.It-column { margin-top: 1em; }
|
||||
|
||||
table.list-col { }
|
||||
tr.list-col { }
|
||||
td.list-col { }
|
||||
cite.Rs { font-style: normal;
|
||||
font-weight: normal; }
|
||||
span.RsA { }
|
||||
i.RsB { font-weight: normal; }
|
||||
span.RsC { }
|
||||
span.RsD { }
|
||||
i.RsI { font-weight: normal; }
|
||||
i.RsJ { font-weight: normal; }
|
||||
span.RsN { }
|
||||
span.RsO { }
|
||||
span.RsP { }
|
||||
span.RsQ { }
|
||||
span.RsR { }
|
||||
span.RsT { text-decoration: underline; }
|
||||
a.RsU { }
|
||||
span.RsV { }
|
||||
|
||||
ul.list-bul { list-style-type: disc; padding-left: 1em; }
|
||||
li.list-bul { }
|
||||
span.eqn { }
|
||||
table.tbl { }
|
||||
|
||||
ul.list-dash { list-style-type: none; padding-left: 0em; }
|
||||
li.list-dash:before { content: "\2014 "; }
|
||||
/* Semantic markup for command line utilities. */
|
||||
|
||||
ul.list-hyph { list-style-type: none; padding-left: 0em; }
|
||||
li.list-hyph:before { content: "\2013 "; }
|
||||
table.Nm { }
|
||||
b.Nm { font-style: normal; }
|
||||
b.Fl { font-style: normal; }
|
||||
b.Cm { font-style: normal; }
|
||||
var.Ar { font-style: italic;
|
||||
font-weight: normal; }
|
||||
span.Op { }
|
||||
b.Ic { font-style: normal; }
|
||||
code.Ev { font-style: normal;
|
||||
font-weight: normal;
|
||||
font-family: monospace; }
|
||||
i.Pa { font-weight: normal; }
|
||||
|
||||
ul.list-item { list-style-type: none; padding-left: 0em; }
|
||||
li.list-item { }
|
||||
/* Semantic markup for function libraries. */
|
||||
|
||||
ol.list-enum { padding-left: 2em; }
|
||||
li.list-enum { }
|
||||
span.Lb { }
|
||||
b.In { font-style: normal; }
|
||||
a.In { }
|
||||
b.Fd { font-style: normal; }
|
||||
var.Ft { font-style: italic;
|
||||
font-weight: normal; }
|
||||
b.Fn { font-style: normal; }
|
||||
var.Fa { font-style: italic;
|
||||
font-weight: normal; }
|
||||
var.Vt { font-style: italic;
|
||||
font-weight: normal; }
|
||||
var.Va { font-style: italic;
|
||||
font-weight: normal; }
|
||||
code.Dv { font-style: normal;
|
||||
font-weight: normal;
|
||||
font-family: monospace; }
|
||||
code.Er { font-style: normal;
|
||||
font-weight: normal;
|
||||
font-family: monospace; }
|
||||
|
||||
/* Equation modes. See eqn(7). */
|
||||
/* Various semantic markup. */
|
||||
|
||||
span.eqn { }
|
||||
span.An { }
|
||||
a.Lk { }
|
||||
a.Mt { }
|
||||
b.Cd { font-style: normal; }
|
||||
i.Ad { font-weight: normal; }
|
||||
b.Ms { font-style: normal; }
|
||||
span.St { }
|
||||
a.Ux { }
|
||||
|
||||
/* Table modes. See tbl(7). */
|
||||
/* Physical markup. */
|
||||
|
||||
table.tbl { }
|
||||
.No { font-style: normal;
|
||||
font-weight: normal; }
|
||||
.Em { font-style: italic;
|
||||
font-weight: normal; }
|
||||
.Sy { font-style: normal;
|
||||
font-weight: bold; }
|
||||
.Li { font-style: normal;
|
||||
font-weight: normal;
|
||||
font-family: monospace; }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Id: mandoc.db.5,v 1.4 2016/07/07 14:35:48 schwarze Exp
|
||||
.\" Id: mandoc.db.5,v 1.5 2016/08/01 12:27:15 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2014, 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
|
||||
|
@ -14,7 +14,7 @@
|
|||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd July 7, 2016
|
||||
.Dd August 1, 2016
|
||||
.Dt MANDOC.DB 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -23,7 +23,7 @@
|
|||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
SQLite3 file format is used to store information about installed manual
|
||||
file format is used to store information about installed manual
|
||||
pages to facilitate semantic searching for manuals.
|
||||
Each manual page tree contains its own
|
||||
.Nm
|
||||
|
@ -34,87 +34,156 @@ for examples.
|
|||
Such database files are generated by
|
||||
.Xr makewhatis 8
|
||||
and used by
|
||||
.Xr man 1 ,
|
||||
.Xr apropos 1
|
||||
and
|
||||
.Xr whatis 1 .
|
||||
.Pp
|
||||
One line in the following tables describes:
|
||||
.Bl -tag -width Ds
|
||||
.It Sy mpages
|
||||
One physical manual page file, no matter how many times and under which
|
||||
names it may appear in the file system.
|
||||
.It Sy mlinks
|
||||
One entry in the file system, no matter which content it points to.
|
||||
.It Sy names
|
||||
One manual page name, no matter whether it appears in a page header,
|
||||
in a NAME or SYNOPSIS section, or as a file name.
|
||||
.It Sy keys
|
||||
One chunk of text from some macro invocation.
|
||||
The file format uses three datatypes:
|
||||
.Pp
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
32-bit signed integer numbers in big endian (network) byte ordering
|
||||
.It
|
||||
NUL-terminated strings
|
||||
.It
|
||||
lists of NUL-terminated strings, terminated by a second NUL character
|
||||
.El
|
||||
.Pp
|
||||
Each record in the latter three tables uses its
|
||||
.Va pageid
|
||||
column to point to a record in the
|
||||
.Sy mpages
|
||||
table.
|
||||
Numbers are aligned to four-byte boundaries; where they follow
|
||||
strings or lists of strings, padding with additional NUL characters
|
||||
occurs.
|
||||
Some, but not all, numbers point to positions in the file.
|
||||
These pointers are measured in bytes, and the first byte of the
|
||||
file is considered to be byte 0.
|
||||
.Pp
|
||||
The other columns are as follows; unless stated otherwise, they are
|
||||
of type
|
||||
.Vt TEXT .
|
||||
.Bl -tag -width mpages.desc
|
||||
.It Sy mpages.desc
|
||||
The description line
|
||||
.Pq Sq \&Nd
|
||||
of the page.
|
||||
.It Sy mpages.form
|
||||
An
|
||||
.Vt INTEGER
|
||||
bit field.
|
||||
If bit
|
||||
.Dv FORM_GZ
|
||||
is set, the page is compressed and requires
|
||||
.Xr gunzip 1
|
||||
for display.
|
||||
If bit
|
||||
.Dv FORM_SRC
|
||||
is set, the page is unformatted, that is in
|
||||
Each file consists of:
|
||||
.Pp
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
One magic number, 0x3a7d0cdb.
|
||||
.It
|
||||
One version number, currently 1.
|
||||
.It
|
||||
One pointer to the macros table.
|
||||
.It
|
||||
One pointer to the final magic number.
|
||||
.It
|
||||
The pages table (variable length).
|
||||
.It
|
||||
The macros table (variable length).
|
||||
.It
|
||||
The magic number once again, 0x3a7d0cdb.
|
||||
.El
|
||||
.Pp
|
||||
The pages table contains one entry for each physical manual page
|
||||
file, no matter how many hard and soft links it may have in the
|
||||
file system.
|
||||
The pages table consists of:
|
||||
.Pp
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
The number of pages in the database.
|
||||
.It
|
||||
For each page:
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
One pointer to the list of names.
|
||||
.It
|
||||
One pointer to the list of sections.
|
||||
.It
|
||||
One pointer to the list of architectures
|
||||
or 0 if the page is machine-independent.
|
||||
.It
|
||||
One pointer to the one-line description string.
|
||||
.It
|
||||
One pointer to the list of filenames.
|
||||
.El
|
||||
.It
|
||||
For each page, the list of names.
|
||||
Each name is preceded by a single byte indicating the sources of the name.
|
||||
The meaning of the bits is:
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
0x10: The name appears in a filename.
|
||||
.It
|
||||
0x08: The name appears in a header line, i.e. in a .Dt or .TH macro.
|
||||
.It
|
||||
0x04: The name is the first one in the title line, i.e. it appears
|
||||
in the first .Nm macro in the NAME section.
|
||||
.It
|
||||
0x02: The name appears in any .Nm macro in the NAME section.
|
||||
.It
|
||||
0x01: The name appears in an .Nm block in the SYNOPSIS section.
|
||||
.El
|
||||
.It
|
||||
For each page, the list of sections.
|
||||
Each section is given as a string, not as a number.
|
||||
.It
|
||||
For each architecture-dependent page, the list of architectures.
|
||||
.It
|
||||
For each page, the one-line description string taken from the .Nd macro.
|
||||
.It
|
||||
For each page, the list of filenames relative to the root of the
|
||||
respective manpath.
|
||||
This list includes hard links, soft links, and links simulated
|
||||
with .so
|
||||
.Xr roff 7
|
||||
requests.
|
||||
The first filename is preceded by a single byte
|
||||
having the following significance:
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
.Dv FORM_SRC No = 0x01 :
|
||||
The file format is
|
||||
.Xr mdoc 7
|
||||
or
|
||||
.Xr man 7
|
||||
format, and requires
|
||||
.Xr mandoc 1
|
||||
for display.
|
||||
If bit
|
||||
.Dv FORM_SRC
|
||||
is not set, the page is formatted, i.e. a
|
||||
.Sq cat
|
||||
page.
|
||||
.It Sy mlinks.sec
|
||||
The manual section as found in the subdirectory name.
|
||||
.It Sy mlinks.arch
|
||||
The manual architecture as found in the subdirectory name, or
|
||||
.Qq any .
|
||||
.It Sy mlinks.name
|
||||
The manual name as found in the file name.
|
||||
.It Sy names.bits
|
||||
An
|
||||
.Vt INTEGER
|
||||
bit mask telling whether the name came from a header line, from the
|
||||
NAME or SYNOPSIS section, or from a file name.
|
||||
Bits are defined in
|
||||
.In mansearch.h .
|
||||
.It Sy names.name
|
||||
The name itself.
|
||||
.It Sy keys.bits
|
||||
An
|
||||
.Vt INTEGER
|
||||
bit mask telling which semantic contexts the key was found in;
|
||||
defined in
|
||||
.In mansearch.h ,
|
||||
documented in
|
||||
.Xr man 7 .
|
||||
.It
|
||||
.Dv FORM_CAT No = 0x02 :
|
||||
The manual page is preformatted.
|
||||
.El
|
||||
.It
|
||||
Zero to three NUL bytes for padding.
|
||||
.El
|
||||
.Pp
|
||||
The macros table consists of:
|
||||
.Pp
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
The number of different macro keys, currently 36.
|
||||
The ordering of macros is defined in
|
||||
.In mansearch.h
|
||||
and the significance of the macro keys is documented in
|
||||
.Xr apropos 1 .
|
||||
.It Sy keys.key
|
||||
The string found in those contexts.
|
||||
.It
|
||||
For each macro key, one pointer to the respective macro table.
|
||||
.It
|
||||
For each macro key, the macro table (variable length).
|
||||
.El
|
||||
.Pp
|
||||
Each macro table consists of:
|
||||
.Pp
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
The number of entries in the table.
|
||||
.It
|
||||
For each entry:
|
||||
.Bl -dash -compact -offset 2n -width 1n
|
||||
.It
|
||||
One pointer to the value of the macro key.
|
||||
Each value is a string of text taken from some macro invocation.
|
||||
.It
|
||||
One pointer to the list of pages.
|
||||
.El
|
||||
.It
|
||||
For each entry, the value of the macro key.
|
||||
.It
|
||||
Zero to three NUL bytes for padding.
|
||||
.It
|
||||
For each entry, one or more pointers to pages in the pages table,
|
||||
pointing to the pointer to the list of names,
|
||||
followed by the number 0.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/share/man/mandoc.db -compact
|
||||
|
@ -128,10 +197,16 @@ Window System.
|
|||
The same for
|
||||
.Xr packages 7 .
|
||||
.El
|
||||
.Pp
|
||||
A program to dump
|
||||
.Nm
|
||||
files in a human-readable format suitable for
|
||||
.Xr diff 1
|
||||
is provided in the directory
|
||||
.Pa /usr/src/regress/usr.bin/mandoc/db/dbm_dump/ .
|
||||
.Sh SEE ALSO
|
||||
.Xr apropos 1 ,
|
||||
.Xr man 1 ,
|
||||
.Xr sqlite3 1 ,
|
||||
.Xr whatis 1 ,
|
||||
.Xr makewhatis 8
|
||||
.Sh HISTORY
|
||||
|
@ -140,7 +215,7 @@ A manual page database
|
|||
first appeared in
|
||||
.Bx 2 .
|
||||
The present format first appeared in
|
||||
.Ox 5.6 .
|
||||
.Ox 6.1 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The original version of
|
||||
|
@ -148,9 +223,6 @@ The original version of
|
|||
was written by
|
||||
.An Bill Joy
|
||||
in 1979.
|
||||
An SQLite3 version was first implemented by
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
|
||||
in 2012.
|
||||
The present database format was designed by
|
||||
.An Ingo Schwarze Aq Mt schwarze@openbsd.org
|
||||
in 2014.
|
||||
in 2016.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" Id: mandoc_char.7,v 1.63 2015/09/02 15:38:35 schwarze Exp
|
||||
.\" Id: mandoc_char.7,v 1.64 2017/02/05 21:41:21 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
|
@ -16,7 +16,7 @@
|
|||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd September 2, 2015
|
||||
.Dd February 5, 2017
|
||||
.Dt MANDOC_CHAR 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -62,6 +62,30 @@ blue-eyed
|
|||
lorry-driver
|
||||
.Ed
|
||||
.Pp
|
||||
If a word on a text input line contains a hyphen, a formatter may decide
|
||||
to insert an output line break after the hyphen if that helps filling
|
||||
the current output line, but the whole word would overflow the line.
|
||||
If it is important that the word is not broken across lines in this
|
||||
way, a zero-width space
|
||||
.Pq Sq \e&
|
||||
can be inserted before or after the hyphen.
|
||||
While
|
||||
.Xr mandoc 1
|
||||
never breaks the output line after hyphens adjacent to a zero-width
|
||||
space, after any of the other dash- or hyphen-like characters
|
||||
represented by escape sequences, or after hyphens inside words in
|
||||
macro arguments, other software may not respect these rules and may
|
||||
break the line even in such cases.
|
||||
.Pp
|
||||
Some
|
||||
.Xr roff 7
|
||||
implementations contains dictionaries allowing to break the line
|
||||
at syllable boundaries even inside words that contain no hyphens.
|
||||
Such automatic hyphenation is not supported by
|
||||
.Xr mandoc 1 ,
|
||||
which only breaks the line at whitespace, and inside words only
|
||||
after existing hyphens.
|
||||
.Pp
|
||||
The mathematical minus sign is used for negative numbers or subtraction.
|
||||
It should be written as
|
||||
.Sq \e(mi :
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Id: mandoc_html.3,v 1.1 2014/07/23 18:13:09 schwarze Exp
|
||||
.\" Id: mandoc_html.3,v 1.5 2017/01/28 22:36:38 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2014, 2017 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -14,7 +14,7 @@
|
|||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd July 23, 2014
|
||||
.Dd January 28, 2017
|
||||
.Dt MANDOC_HTML 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -30,8 +30,8 @@
|
|||
.Fo print_otag
|
||||
.Fa "struct html *h"
|
||||
.Fa "enum htmltag tag"
|
||||
.Fa "int sz"
|
||||
.Fa "const struct htmlpair *p"
|
||||
.Fa "const char *fmt"
|
||||
.Fa ...
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo print_tagq
|
||||
|
@ -84,15 +84,6 @@ These structures are declared in
|
|||
.Bl -tag -width Ds
|
||||
.It Vt struct html
|
||||
Internal state of the HTML formatter.
|
||||
.It Vt struct htmlpair
|
||||
Holds one HTML attribute.
|
||||
Members are
|
||||
.Fa "enum htmlattr key"
|
||||
and
|
||||
.Fa "const char *val" .
|
||||
Helper macros
|
||||
.Fn PAIR_*
|
||||
are provided to support initialization of such structures.
|
||||
.It Vt struct tag
|
||||
One entry for the LIFO stack of HTML elements.
|
||||
Members are
|
||||
|
@ -134,14 +125,150 @@ The function
|
|||
.Fn print_otag
|
||||
prints the start tag of an HTML element with the name
|
||||
.Fa tag ,
|
||||
including the
|
||||
.Fa sz
|
||||
attributes that can optionally be provided in the
|
||||
.Fa p
|
||||
array.
|
||||
It uses the private function
|
||||
.Fn print_attr
|
||||
which in turn uses the private function
|
||||
optionally including the attributes specified by
|
||||
.Fa fmt .
|
||||
If
|
||||
.Fa fmt
|
||||
is the empty string, no attributes are written.
|
||||
Each letter of
|
||||
.Fa fmt
|
||||
specifies one attribute to write.
|
||||
Most attributes require one
|
||||
.Va char *
|
||||
argument which becomes the value of the attribute.
|
||||
The arguments have to be given in the same order as the attribute letters.
|
||||
If an argument is
|
||||
.Dv NULL ,
|
||||
the respective attribute is not written.
|
||||
.Bl -tag -width 1n -offset indent
|
||||
.It Cm c
|
||||
Print a
|
||||
.Cm class
|
||||
attribute.
|
||||
.It Cm h
|
||||
Print a
|
||||
.Cm href
|
||||
attribute.
|
||||
This attribute letter can optionally be followed by a modifier letter.
|
||||
If followed by
|
||||
.Cm R ,
|
||||
it formats the link as a local one by prefixing a
|
||||
.Sq #
|
||||
character.
|
||||
If followed by
|
||||
.Cm I ,
|
||||
it interpretes the argument as a header file name
|
||||
and generates a link using the
|
||||
.Xr mandoc 1
|
||||
.Fl O Cm includes
|
||||
option.
|
||||
If followed by
|
||||
.Cm M ,
|
||||
it takes two arguments instead of one, a manual page name and
|
||||
section, and formats them as a link to a manual page using the
|
||||
.Xr mandoc 1
|
||||
.Fl O Cm man
|
||||
option.
|
||||
.It Cm i
|
||||
Print an
|
||||
.Cm id
|
||||
attribute.
|
||||
.It Cm \&?
|
||||
Print an arbitrary attribute.
|
||||
This format letter requires two
|
||||
.Vt char *
|
||||
arguments, the attribute name and the value.
|
||||
The name must not be
|
||||
.Dv NULL .
|
||||
.It Cm s
|
||||
Print a
|
||||
.Cm style
|
||||
attribute.
|
||||
If present, it must be the last format letter.
|
||||
In contrast to the other format letters, this one does not yet
|
||||
print the value and does not take an argument.
|
||||
Instead, the rest of the format string consists of pairs of
|
||||
argument type letters and style name letters.
|
||||
.El
|
||||
.Pp
|
||||
Argument type letters each require on argument as follows:
|
||||
.Bl -tag -width 1n -offset indent
|
||||
.It Cm h
|
||||
Requires one
|
||||
.Vt int
|
||||
argument, interpreted as a horizontal length in units of
|
||||
.Dv SCALE_EN .
|
||||
.It Cm s
|
||||
Requires one
|
||||
.Vt char *
|
||||
argument, used as a style value.
|
||||
.It Cm u
|
||||
Requires one
|
||||
.Vt struct roffsu *
|
||||
argument, used as a length.
|
||||
.It Cm v
|
||||
Requires one
|
||||
.Vt int
|
||||
argument, interpreted as a vertical length in units of
|
||||
.Dv SCALE_VS .
|
||||
.It Cm w
|
||||
Requires one
|
||||
.Vt char *
|
||||
argument, interpreted as an
|
||||
.Xr mdoc 7 Ns -style
|
||||
width specifier.
|
||||
If the argument is
|
||||
.Dv NULL ,
|
||||
nothing is printed for this pair.
|
||||
.It Cm W
|
||||
Similar to
|
||||
.Cm w ,
|
||||
but makes the width negative by multiplying it with \(mi1.
|
||||
.El
|
||||
.Pp
|
||||
Style name letters decide what to do with the preceding argument:
|
||||
.Bl -tag -width 1n -offset indent
|
||||
.It Cm b
|
||||
Set
|
||||
.Cm margin-bottom
|
||||
to the given length.
|
||||
.It Cm h
|
||||
Set
|
||||
.Cm height
|
||||
to the given length.
|
||||
.It Cm i
|
||||
Set
|
||||
.Cm text-indent
|
||||
to the given length.
|
||||
.It Cm l
|
||||
Set
|
||||
.Cm margin-left
|
||||
to the given length.
|
||||
.It Cm t
|
||||
Set
|
||||
.Cm margin-top
|
||||
to the given length.
|
||||
.It Cm w
|
||||
Set
|
||||
.Cm width
|
||||
to the given length.
|
||||
.It Cm W
|
||||
Set
|
||||
.Cm min-width
|
||||
to the given length.
|
||||
.It Cm \&?
|
||||
The special pair
|
||||
.Cm s?
|
||||
requires two
|
||||
.Vt char *
|
||||
arguments.
|
||||
The first is the style name, the second its value.
|
||||
The style name must not be
|
||||
.Dv NULL .
|
||||
.El
|
||||
.Pp
|
||||
.Fn print_otag
|
||||
uses the private function
|
||||
.Fn print_encode
|
||||
to take care of HTML encoding.
|
||||
If required by the element type, it remembers in
|
||||
|
@ -175,28 +302,6 @@ and
|
|||
functions.
|
||||
.Pp
|
||||
The functions
|
||||
.Fn bufinit ,
|
||||
.Fn bufcat* ,
|
||||
and
|
||||
.Fn buffmt*
|
||||
do not directly produce output but buffer text in the
|
||||
.Fa buf
|
||||
member of
|
||||
.Fa h .
|
||||
They are not used internally by
|
||||
.Pa html.c
|
||||
but intended for use by the language-specific formatters
|
||||
to ease preparation of strings for the
|
||||
.Fa p
|
||||
argument of
|
||||
.Fn print_otag
|
||||
and for the
|
||||
.Fa word
|
||||
argument of
|
||||
.Fn print_text .
|
||||
Consequently, these functions do not do any HTML encoding.
|
||||
.Pp
|
||||
The functions
|
||||
.Fn html_strlen ,
|
||||
.Fn print_eqn ,
|
||||
.Fn print_tbl ,
|
||||
|
@ -245,5 +350,6 @@ implementation of common mandoc utility functions
|
|||
.An -nosplit
|
||||
The mandoc HTML formatter was written by
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
|
||||
This manual was written by
|
||||
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
|
||||
It is maintained by
|
||||
.An Ingo Schwarze Aq Mt schwarze@openbsd.org ,
|
||||
who also wrote this manual.
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
.\" Id: mandocd.8,v 1.1 2017/02/06 19:04:21 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 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.
|
||||
.\"
|
||||
.Dd February 6, 2017
|
||||
.Dt MANDOCD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mandocd
|
||||
.Nd server process to format manual pages in batch mode
|
||||
.Sh SYNOPSIS
|
||||
.Nm mandocd
|
||||
.Op Fl I Cm os Ns = Ns Ar name
|
||||
.Op Fl T Ar output
|
||||
.Ar socket_fd
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility formats many manual pages without requiring
|
||||
.Xr fork 2
|
||||
and
|
||||
.Xr exec 3
|
||||
overhead in between.
|
||||
It does not require listing all the manuals to be formatted on the
|
||||
command line, and it supports writing each formatted manual to its
|
||||
own file descriptor.
|
||||
.Pp
|
||||
This server requires that a connected UNIX domain
|
||||
.Xr socket 2
|
||||
is already present at
|
||||
.Xr exec 3
|
||||
time.
|
||||
Consequently, it cannot be started from the
|
||||
.Xr sh 1
|
||||
command line because the shell cannot supply such a socket.
|
||||
Typically, the socket is created by the parent process using
|
||||
.Xr socketpair 2
|
||||
before calling
|
||||
.Xr fork 2
|
||||
and
|
||||
.Xr exec 3
|
||||
on
|
||||
.Nm .
|
||||
The parent process will pass the file descriptor number as an argument to
|
||||
.Xr exec 3 ,
|
||||
formatted as a decimal ASCII-encoded integer.
|
||||
See
|
||||
.Xr catman 8
|
||||
for a typical implementation of a parent process.
|
||||
.Pp
|
||||
.Nm
|
||||
loops reading one-byte messages with
|
||||
.Xr recvmsg 2
|
||||
from the file descriptor number
|
||||
.Ar socket_fd .
|
||||
It ignores the byte read and only uses the out-of-band auxiliary
|
||||
.Vt struct cmsghdr
|
||||
control data, typically supplied by the calling process using
|
||||
.Xr CMSG_FIRSTHDR 3 .
|
||||
The parent process is expected to pass three file descriptors
|
||||
with each dummy byte.
|
||||
The first one is used for
|
||||
.Xr mdoc 7
|
||||
or
|
||||
.Xr man 7
|
||||
input, the second one for formatted output, and the third one
|
||||
for error output.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl I Cm os Ns = Ns Ar name
|
||||
Override the default operating system
|
||||
.Ar name
|
||||
for the
|
||||
.Xr mdoc 7
|
||||
.Ic Os
|
||||
and for the
|
||||
.Xr man 7
|
||||
.Ic TH
|
||||
macro.
|
||||
.It Fl T Ar output
|
||||
Output format.
|
||||
The
|
||||
.Ar output
|
||||
argument can be
|
||||
.Cm ascii ,
|
||||
.Cm utf8 ,
|
||||
or
|
||||
.Cm html ;
|
||||
see
|
||||
.Xr mandoc 1 .
|
||||
In
|
||||
.Cm html
|
||||
output mode, the
|
||||
.Cm fragment
|
||||
output option is implied.
|
||||
Other output options are not supported.
|
||||
.El
|
||||
.Pp
|
||||
After exhausting one input file descriptor, all three file descriptors
|
||||
are closed before reading the next dummy byte and control message.
|
||||
.Pp
|
||||
When a zero-byte message is read, when the
|
||||
.Ar socket_fd
|
||||
is closed by the parent process,
|
||||
or when an error occurs,
|
||||
.Nm
|
||||
exits.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Pp
|
||||
A zero-byte message or a closed
|
||||
.Ar socket_fd
|
||||
is considered success.
|
||||
Possible errors include:
|
||||
.Bl -bullet
|
||||
.It
|
||||
missing, invalid, or excessive
|
||||
.Xr exec 3
|
||||
arguments
|
||||
.It
|
||||
.Xr recvmsg 2
|
||||
failure, for example due to
|
||||
.Er EMSGSIZE
|
||||
.It
|
||||
missing or unexpected control data, in particular a
|
||||
.Fa cmsg_level
|
||||
in the
|
||||
.Vt struct cmsghdr
|
||||
that differs from
|
||||
.Dv SOL_SOCKET ,
|
||||
a
|
||||
.Fa cmsg_type
|
||||
that differs from
|
||||
.Dv SCM_RIGHTS ,
|
||||
or a
|
||||
.Fa cmsg_len
|
||||
that is not three times the size of an
|
||||
.Vt int
|
||||
.It
|
||||
invalid file descriptors passed in the
|
||||
.Xr CMSG_DATA 3
|
||||
.It
|
||||
resource exhaustion, in particular
|
||||
.Xr dup 2
|
||||
or
|
||||
.Xr malloc 3
|
||||
failure
|
||||
.El
|
||||
.Pp
|
||||
Except for memory exhaustion and similar system-level failures,
|
||||
parsing and formatting errors do not cause
|
||||
.Nm
|
||||
to return an error exit status.
|
||||
Even after severe parsing errors,
|
||||
.Nm
|
||||
will simply accept and process the next input file descriptor.
|
||||
.Sh SEE ALSO
|
||||
.Xr mandoc 1 ,
|
||||
.Xr mandoc 3 ,
|
||||
.Xr catman 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in version 1.14.1 or the
|
||||
.Sy mandoc
|
||||
toolkit.
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The concept was designed and implemented by
|
||||
.An Michael Stapelberg Aq Mt stapelberg@debian.org .
|
||||
The
|
||||
.Xr mandoc 3
|
||||
glue needed to make it a stand-alone process was added by
|
||||
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
|
||||
.Sh CAVEATS
|
||||
If the parsed manual pages contain
|
||||
.Xr roff 7
|
||||
.Pf . Ic so
|
||||
requests,
|
||||
.Nm
|
||||
needs to be started with the current working directory set to the
|
||||
root of the manual page tree.
|
||||
Avoid starting it in directories that contain secret files in any
|
||||
subdirectories, in particular in the user starting it has read
|
||||
access to these secret files.
|
|
@ -0,0 +1,285 @@
|
|||
/* Id: mandocd.c,v 1.5 2017/02/17 14:31:52 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
|
||||
* Copyright (c) 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 AUTHORS DISCLAIM ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_CMSG_XPG42
|
||||
#define _XPG4_2
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if HAVE_ERR
|
||||
#include <err.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mandoc.h"
|
||||
#include "roff.h"
|
||||
#include "mdoc.h"
|
||||
#include "man.h"
|
||||
#include "main.h"
|
||||
#include "manconf.h"
|
||||
|
||||
enum outt {
|
||||
OUTT_ASCII = 0,
|
||||
OUTT_UTF8,
|
||||
OUTT_HTML
|
||||
};
|
||||
|
||||
static void process(struct mparse *, enum outt, void *);
|
||||
static int read_fds(int, int *);
|
||||
static void usage(void) __attribute__((__noreturn__));
|
||||
|
||||
|
||||
#define NUM_FDS 3
|
||||
static int
|
||||
read_fds(int clientfd, int *fds)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
unsigned char dummy[1];
|
||||
struct cmsghdr *cmsg;
|
||||
int *walk;
|
||||
int cnt;
|
||||
|
||||
/* Union used for alignment. */
|
||||
union {
|
||||
uint8_t controlbuf[CMSG_SPACE(NUM_FDS * sizeof(int))];
|
||||
struct cmsghdr align;
|
||||
} u;
|
||||
|
||||
memset(&msg, '\0', sizeof(msg));
|
||||
msg.msg_control = u.controlbuf;
|
||||
msg.msg_controllen = sizeof(u.controlbuf);
|
||||
|
||||
/*
|
||||
* Read a dummy byte - sendmsg cannot send an empty message,
|
||||
* even if we are only interested in the OOB data.
|
||||
*/
|
||||
|
||||
iov[0].iov_base = dummy;
|
||||
iov[0].iov_len = sizeof(dummy);
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
switch (recvmsg(clientfd, &msg, 0)) {
|
||||
case -1:
|
||||
warn("recvmsg");
|
||||
return -1;
|
||||
case 0:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((cmsg = CMSG_FIRSTHDR(&msg)) == NULL) {
|
||||
warnx("CMSG_FIRSTHDR: missing control message");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cmsg->cmsg_level != SOL_SOCKET ||
|
||||
cmsg->cmsg_type != SCM_RIGHTS ||
|
||||
cmsg->cmsg_len != CMSG_LEN(NUM_FDS * sizeof(int))) {
|
||||
warnx("CMSG_FIRSTHDR: invalid control message");
|
||||
return -1;
|
||||
}
|
||||
|
||||
walk = (int *)CMSG_DATA(cmsg);
|
||||
for (cnt = 0; cnt < NUM_FDS; cnt++)
|
||||
fds[cnt] = *walk++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct manoutput options;
|
||||
struct mparse *parser;
|
||||
void *formatter;
|
||||
const char *defos;
|
||||
const char *errstr;
|
||||
int clientfd;
|
||||
int old_stdin;
|
||||
int old_stdout;
|
||||
int old_stderr;
|
||||
int fds[3];
|
||||
int state, opt;
|
||||
enum outt outtype;
|
||||
|
||||
defos = NULL;
|
||||
outtype = OUTT_ASCII;
|
||||
while ((opt = getopt(argc, argv, "I:T:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'I':
|
||||
if (strncmp(optarg, "os=", 3) == 0)
|
||||
defos = optarg + 3;
|
||||
else {
|
||||
warnx("-I %s: Bad argument", optarg);
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
if (strcmp(optarg, "ascii") == 0)
|
||||
outtype = OUTT_ASCII;
|
||||
else if (strcmp(optarg, "utf8") == 0)
|
||||
outtype = OUTT_UTF8;
|
||||
else if (strcmp(optarg, "html") == 0)
|
||||
outtype = OUTT_HTML;
|
||||
else {
|
||||
warnx("-T %s: Bad argument", optarg);
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 0) {
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
}
|
||||
if (argc != 1)
|
||||
usage();
|
||||
|
||||
errstr = NULL;
|
||||
clientfd = strtonum(argv[0], 3, INT_MAX, &errstr);
|
||||
if (errstr)
|
||||
errx(1, "file descriptor %s %s", argv[1], errstr);
|
||||
|
||||
mchars_alloc();
|
||||
parser = mparse_alloc(MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1,
|
||||
MANDOCLEVEL_BADARG, NULL, defos);
|
||||
|
||||
memset(&options, 0, sizeof(options));
|
||||
switch (outtype) {
|
||||
case OUTT_ASCII:
|
||||
formatter = ascii_alloc(&options);
|
||||
break;
|
||||
case OUTT_UTF8:
|
||||
formatter = utf8_alloc(&options);
|
||||
break;
|
||||
case OUTT_HTML:
|
||||
options.fragment = 1;
|
||||
formatter = html_alloc(&options);
|
||||
break;
|
||||
}
|
||||
|
||||
state = 1; /* work to do */
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
if ((old_stdin = dup(STDIN_FILENO)) == -1 ||
|
||||
(old_stdout = dup(STDOUT_FILENO)) == -1 ||
|
||||
(old_stderr = dup(STDERR_FILENO)) == -1) {
|
||||
warn("dup");
|
||||
state = -1; /* error */
|
||||
}
|
||||
|
||||
while (state == 1 && (state = read_fds(clientfd, fds)) == 1) {
|
||||
if (dup2(fds[0], STDIN_FILENO) == -1 ||
|
||||
dup2(fds[1], STDOUT_FILENO) == -1 ||
|
||||
dup2(fds[2], STDERR_FILENO) == -1) {
|
||||
warn("dup2");
|
||||
state = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
close(fds[2]);
|
||||
|
||||
process(parser, outtype, formatter);
|
||||
mparse_reset(parser);
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
/* Close file descriptors by restoring the old ones. */
|
||||
if (dup2(old_stderr, STDERR_FILENO) == -1 ||
|
||||
dup2(old_stdout, STDOUT_FILENO) == -1 ||
|
||||
dup2(old_stdin, STDIN_FILENO) == -1) {
|
||||
warn("dup2");
|
||||
state = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
close(clientfd);
|
||||
switch (outtype) {
|
||||
case OUTT_ASCII:
|
||||
case OUTT_UTF8:
|
||||
ascii_free(formatter);
|
||||
break;
|
||||
case OUTT_HTML:
|
||||
html_free(formatter);
|
||||
break;
|
||||
}
|
||||
mparse_free(parser);
|
||||
mchars_free();
|
||||
return state == -1 ? 1 : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
process(struct mparse *parser, enum outt outtype, void *formatter)
|
||||
{
|
||||
struct roff_man *man;
|
||||
|
||||
mparse_readfd(parser, STDIN_FILENO, "<unixfd>");
|
||||
mparse_result(parser, &man, NULL);
|
||||
|
||||
if (man == NULL)
|
||||
return;
|
||||
|
||||
if (man->macroset == MACROSET_MDOC) {
|
||||
mdoc_validate(man);
|
||||
switch (outtype) {
|
||||
case OUTT_ASCII:
|
||||
case OUTT_UTF8:
|
||||
terminal_mdoc(formatter, man);
|
||||
break;
|
||||
case OUTT_HTML:
|
||||
html_mdoc(formatter, man);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (man->macroset == MACROSET_MAN) {
|
||||
man_validate(man);
|
||||
switch (outtype) {
|
||||
case OUTT_ASCII:
|
||||
case OUTT_UTF8:
|
||||
terminal_man(formatter, man);
|
||||
break;
|
||||
case OUTT_HTML:
|
||||
html_man(formatter, man);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: mandocd [-I os=name] [-T output] socket_fd\n");
|
||||
exit(1);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* Id: manpath.c,v 1.30 2016/05/28 13:44:13 schwarze Exp */
|
||||
/* Id: manpath.c,v 1.33 2017/02/10 15:45:28 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
|
@ -32,9 +32,7 @@
|
|||
#include "mandoc_aux.h"
|
||||
#include "manconf.h"
|
||||
|
||||
#if !HAVE_MANPATH
|
||||
static void manconf_file(struct manconf *, const char *);
|
||||
#endif
|
||||
static void manpath_add(struct manpaths *, const char *, int);
|
||||
static void manpath_parseline(struct manpaths *, char *, int);
|
||||
|
||||
|
@ -43,52 +41,6 @@ void
|
|||
manconf_parse(struct manconf *conf, const char *file,
|
||||
char *defp, char *auxp)
|
||||
{
|
||||
#if HAVE_MANPATH
|
||||
char cmd[(PATH_MAX * 3) + 20];
|
||||
FILE *stream;
|
||||
char *buf;
|
||||
size_t sz, bsz;
|
||||
|
||||
strlcpy(cmd, "manpath", sizeof(cmd));
|
||||
if (file) {
|
||||
strlcat(cmd, " -C ", sizeof(cmd));
|
||||
strlcat(cmd, file, sizeof(cmd));
|
||||
}
|
||||
if (auxp) {
|
||||
strlcat(cmd, " -m ", sizeof(cmd));
|
||||
strlcat(cmd, auxp, sizeof(cmd));
|
||||
}
|
||||
if (defp) {
|
||||
strlcat(cmd, " -M ", sizeof(cmd));
|
||||
strlcat(cmd, defp, sizeof(cmd));
|
||||
}
|
||||
|
||||
/* Open manpath(1). Ignore errors. */
|
||||
|
||||
stream = popen(cmd, "r");
|
||||
if (NULL == stream)
|
||||
return;
|
||||
|
||||
buf = NULL;
|
||||
bsz = 0;
|
||||
|
||||
/* Read in as much output as we can. */
|
||||
|
||||
do {
|
||||
buf = mandoc_realloc(buf, bsz + 1024);
|
||||
sz = fread(buf + bsz, 1, 1024, stream);
|
||||
bsz += sz;
|
||||
} while (sz > 0);
|
||||
|
||||
if ( ! ferror(stream) && feof(stream) &&
|
||||
bsz && '\n' == buf[bsz - 1]) {
|
||||
buf[bsz - 1] = '\0';
|
||||
manpath_parseline(&conf->manpath, buf, 1);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
pclose(stream);
|
||||
#else
|
||||
char *insert;
|
||||
|
||||
/* Always prepend -m. */
|
||||
|
@ -137,7 +89,6 @@ manconf_parse(struct manconf *conf, const char *file,
|
|||
|
||||
/* MANPATH overrides man.conf(5) completely. */
|
||||
manpath_parseline(&conf->manpath, defp, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -204,7 +155,6 @@ manconf_free(struct manconf *conf)
|
|||
free(conf->output.style);
|
||||
}
|
||||
|
||||
#if !HAVE_MANPATH
|
||||
static void
|
||||
manconf_file(struct manconf *conf, const char *file)
|
||||
{
|
||||
|
@ -257,7 +207,7 @@ manconf_file(struct manconf *conf, const char *file)
|
|||
*manpath_default = '\0';
|
||||
break;
|
||||
case 1: /* output */
|
||||
manconf_output(&conf->output, cp);
|
||||
manconf_output(&conf->output, cp, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -270,17 +220,18 @@ out:
|
|||
if (*manpath_default != '\0')
|
||||
manpath_parseline(&conf->manpath, manpath_default, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
manconf_output(struct manoutput *conf, const char *cp)
|
||||
int
|
||||
manconf_output(struct manoutput *conf, const char *cp, int fromfile)
|
||||
{
|
||||
const char *const toks[] = {
|
||||
"includes", "man", "paper", "style",
|
||||
"indent", "width", "fragment", "mdoc"
|
||||
"indent", "width", "fragment", "mdoc", "noval"
|
||||
};
|
||||
|
||||
size_t len, tok;
|
||||
const char *errstr;
|
||||
char *oldval;
|
||||
size_t len, tok;
|
||||
|
||||
for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
|
||||
len = strlen(toks[tok]);
|
||||
|
@ -295,41 +246,81 @@ manconf_output(struct manoutput *conf, const char *cp)
|
|||
}
|
||||
}
|
||||
|
||||
if (tok < 6 && *cp == '\0')
|
||||
return;
|
||||
if (tok < 6 && *cp == '\0') {
|
||||
warnx("-O %s=?: Missing argument value", toks[tok]);
|
||||
return -1;
|
||||
}
|
||||
if ((tok == 6 || tok == 7) && *cp != '\0') {
|
||||
warnx("-O %s: Does not take a value: %s", toks[tok], cp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (tok) {
|
||||
case 0:
|
||||
if (conf->includes == NULL)
|
||||
conf->includes = mandoc_strdup(cp);
|
||||
break;
|
||||
if (conf->includes != NULL) {
|
||||
oldval = mandoc_strdup(conf->includes);
|
||||
break;
|
||||
}
|
||||
conf->includes = mandoc_strdup(cp);
|
||||
return 0;
|
||||
case 1:
|
||||
if (conf->man == NULL)
|
||||
conf->man = mandoc_strdup(cp);
|
||||
break;
|
||||
if (conf->man != NULL) {
|
||||
oldval = mandoc_strdup(conf->man);
|
||||
break;
|
||||
}
|
||||
conf->man = mandoc_strdup(cp);
|
||||
return 0;
|
||||
case 2:
|
||||
if (conf->paper == NULL)
|
||||
conf->paper = mandoc_strdup(cp);
|
||||
break;
|
||||
if (conf->paper != NULL) {
|
||||
oldval = mandoc_strdup(conf->paper);
|
||||
break;
|
||||
}
|
||||
conf->paper = mandoc_strdup(cp);
|
||||
return 0;
|
||||
case 3:
|
||||
if (conf->style == NULL)
|
||||
conf->style = mandoc_strdup(cp);
|
||||
break;
|
||||
if (conf->style != NULL) {
|
||||
oldval = mandoc_strdup(conf->style);
|
||||
break;
|
||||
}
|
||||
conf->style = mandoc_strdup(cp);
|
||||
return 0;
|
||||
case 4:
|
||||
if (conf->indent == 0)
|
||||
conf->indent = strtonum(cp, 0, 1000, NULL);
|
||||
break;
|
||||
if (conf->indent) {
|
||||
mandoc_asprintf(&oldval, "%zu", conf->indent);
|
||||
break;
|
||||
}
|
||||
conf->indent = strtonum(cp, 0, 1000, &errstr);
|
||||
if (errstr == NULL)
|
||||
return 0;
|
||||
warnx("-O indent=%s is %s", cp, errstr);
|
||||
return -1;
|
||||
case 5:
|
||||
if (conf->width == 0)
|
||||
conf->width = strtonum(cp, 58, 1000, NULL);
|
||||
break;
|
||||
if (conf->width) {
|
||||
mandoc_asprintf(&oldval, "%zu", conf->width);
|
||||
break;
|
||||
}
|
||||
conf->width = strtonum(cp, 58, 1000, &errstr);
|
||||
if (errstr == NULL)
|
||||
return 0;
|
||||
warnx("-O width=%s is %s", cp, errstr);
|
||||
return -1;
|
||||
case 6:
|
||||
conf->fragment = 1;
|
||||
break;
|
||||
return 0;
|
||||
case 7:
|
||||
conf->mdoc = 1;
|
||||
break;
|
||||
return 0;
|
||||
case 8:
|
||||
conf->noval = 1;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
if (fromfile)
|
||||
warnx("-O %s: Bad argument", cp);
|
||||
return -1;
|
||||
}
|
||||
if (fromfile == 0)
|
||||
warnx("-O %s=%s: Option already set to %s",
|
||||
toks[tok], cp, oldval);
|
||||
free(oldval);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Id: mansearch.h,v 1.24 2015/11/07 14:01:16 schwarze Exp */
|
||||
/* Id: mansearch.h,v 1.27 2016/08/01 12:31:00 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013, 2014, 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
|
||||
|
@ -17,6 +17,12 @@
|
|||
*/
|
||||
|
||||
#define MANDOC_DB "mandoc.db"
|
||||
#define MANDOCDB_MAGIC 0x3a7d0cdb
|
||||
#define MANDOCDB_VERSION 1
|
||||
|
||||
#define MACRO_MAX 36
|
||||
#define KEY_Nd 39
|
||||
#define KEY_MAX 40
|
||||
|
||||
#define TYPE_arch 0x0000000000000001ULL
|
||||
#define TYPE_sec 0x0000000000000002ULL
|
||||
|
@ -66,9 +72,11 @@
|
|||
#define NAME_FILE 0x0000004000000010ULL
|
||||
#define NAME_MASK 0x000000000000001fULL
|
||||
|
||||
#define FORM_CAT 0 /* manual page is preformatted */
|
||||
#define FORM_SRC 1 /* format is mdoc(7) or man(7) */
|
||||
#define FORM_NONE 4 /* format is unknown */
|
||||
enum form {
|
||||
FORM_SRC = 1, /* Format is mdoc(7) or man(7). */
|
||||
FORM_CAT, /* Manual page is preformatted. */
|
||||
FORM_NONE /* Format is unknown. */
|
||||
};
|
||||
|
||||
enum argmode {
|
||||
ARG_FILE = 0,
|
||||
|
@ -84,7 +92,7 @@ struct manpage {
|
|||
size_t ipath; /* number of the manpath */
|
||||
uint64_t bits; /* name type mask */
|
||||
int sec; /* section number, 10 means invalid */
|
||||
int form; /* 0 == catpage */
|
||||
enum form form;
|
||||
};
|
||||
|
||||
struct mansearch {
|
||||
|
@ -98,7 +106,6 @@ struct mansearch {
|
|||
|
||||
struct manpaths;
|
||||
|
||||
int mansearch_setup(int);
|
||||
int mansearch(const struct mansearch *cfg, /* options */
|
||||
const struct manpaths *paths, /* manpaths */
|
||||
int argc, /* size of argv */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.\" Id: mdoc.7,v 1.257 2015/11/05 12:06:45 schwarze Exp
|
||||
.\" Id: mdoc.7,v 1.262 2017/02/16 14:38:12 schwarze Exp
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2010, 2011, 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2010, 2011, 2013-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
|
||||
|
@ -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 November 5, 2015
|
||||
.Dd February 16, 2017
|
||||
.Dt MDOC 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -974,10 +974,8 @@ argument.
|
|||
A columnated list.
|
||||
The
|
||||
.Fl width
|
||||
argument has no effect; instead, each argument specifies the width
|
||||
of one column, using either the scaling width syntax described in
|
||||
.Xr roff 7
|
||||
or the string length of the argument.
|
||||
argument has no effect; instead, the string length of each argument
|
||||
specifies the width of one column.
|
||||
If the first line of the body of a
|
||||
.Fl column
|
||||
list is not an
|
||||
|
@ -1831,14 +1829,25 @@ The
|
|||
list is the most complicated.
|
||||
Its syntax is as follows:
|
||||
.Pp
|
||||
.D1 Pf \. Sx \&It Ar cell Op <TAB> Ar cell ...
|
||||
.D1 Pf \. Sx \&It Ar cell Op Sx \&Ta Ar cell ...
|
||||
.D1 Pf \. Sx \&It Ar cell Op <TAB> Ar cell ...
|
||||
.Pp
|
||||
The arguments consist of one or more lines of text and macros
|
||||
representing a complete table line.
|
||||
Cells within the line are delimited by tabs or by the special
|
||||
Cells within the line are delimited by the special
|
||||
.Sx \&Ta
|
||||
block macro.
|
||||
block macro or by literal tab characters.
|
||||
.Pp
|
||||
Using literal tabs is strongly discouraged because they are very
|
||||
hard to use correctly and
|
||||
.Nm
|
||||
code using them is very hard to read.
|
||||
In particular, a blank character is syntactically significant
|
||||
before and after the literal tab character.
|
||||
If a word precedes or follows the tab without an intervening blank,
|
||||
that word is never interpreted as a macro call, but always output
|
||||
literally.
|
||||
.Pp
|
||||
The tab cell delimiter may only be used within the
|
||||
.Sx \&It
|
||||
line itself; on following lines, only the
|
||||
|
@ -1853,9 +1862,10 @@ Note that quoted strings may span tab-delimited cells on an
|
|||
line.
|
||||
For example,
|
||||
.Pp
|
||||
.Dl .It \(dqcol1 ; <TAB> col2 ;\(dq \&;
|
||||
.Dl .It \(dqcol1 ,\& <TAB> col2 ,\(dq \&;
|
||||
.Pp
|
||||
will preserve the semicolon whitespace except for the last.
|
||||
will preserve the whitespace before both commas,
|
||||
but not the whitespace before the semicolon.
|
||||
.Pp
|
||||
See also
|
||||
.Sx \&Bl .
|
||||
|
@ -2714,14 +2724,13 @@ Link to another manual
|
|||
.Pq Qq cross-reference .
|
||||
Its syntax is as follows:
|
||||
.Pp
|
||||
.D1 Pf \. Sx \&Xr Ar name Op section
|
||||
.D1 Pf \. Sx \&Xr Ar name section
|
||||
.Pp
|
||||
Cross reference the
|
||||
.Ar name
|
||||
and
|
||||
.Ar section
|
||||
number of another man page;
|
||||
omitting the section number is rarely useful.
|
||||
number of another man page.
|
||||
.Pp
|
||||
Examples:
|
||||
.Dl \&.Xr mandoc 1
|
||||
|
@ -3033,7 +3042,7 @@ then the macro accepts an arbitrary number of arguments.
|
|||
.It Sx \&Ux Ta Yes Ta Yes Ta n
|
||||
.It Sx \&Va Ta Yes Ta Yes Ta n
|
||||
.It Sx \&Vt Ta Yes Ta Yes Ta >0
|
||||
.It Sx \&Xr Ta Yes Ta Yes Ta >0
|
||||
.It Sx \&Xr Ta Yes Ta Yes Ta 2
|
||||
.It Sx \&br Ta \&No Ta \&No Ta 0
|
||||
.It Sx \&sp Ta \&No Ta \&No Ta 1
|
||||
.El
|
||||
|
@ -3053,6 +3062,8 @@ For many macros, when the leading arguments are opening delimiters,
|
|||
these delimiters are put before the macro scope,
|
||||
and when the trailing arguments are closing delimiters,
|
||||
these delimiters are put after the macro scope.
|
||||
Spacing is suppressed after opening delimiters
|
||||
and before closing delimiters.
|
||||
For example,
|
||||
.Pp
|
||||
.D1 Pf \. \&Aq "( [ word ] ) ."
|
||||
|
@ -3109,7 +3120,7 @@ renders as:
|
|||
.D1 Fl a ( b | c \*(Ba d ) e
|
||||
.Pp
|
||||
This applies to both opening and closing delimiters,
|
||||
and also to the middle delimiter:
|
||||
and also to the middle delimiter, which does not suppress spacing:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -offset indent -compact
|
||||
.It \&|
|
||||
|
@ -3217,6 +3228,12 @@ but produces large indentations.
|
|||
.Xr mandoc_char 7 ,
|
||||
.Xr roff 7 ,
|
||||
.Xr tbl 7
|
||||
.Pp
|
||||
The web page
|
||||
.Lk http://mdocml.bsd.lv/mdoc/ "extended documentation for the mdoc language"
|
||||
provides a few tutorial-style pages for beginners, an extensive style
|
||||
guide for advanced authors, and an alphabetic index helping to choose
|
||||
the best macros for various kinds of content.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Id: mdoc.c,v 1.256 2015/10/30 19:04:16 schwarze Exp */
|
||||
/* Id: mdoc.c,v 1.260 2017/02/16 03:00:23 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010, 2012-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
|
||||
|
@ -136,16 +136,16 @@ mdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, int tok)
|
|||
|
||||
struct roff_node *
|
||||
mdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos, int tok,
|
||||
struct roff_node *body, enum mdoc_endbody end)
|
||||
struct roff_node *body)
|
||||
{
|
||||
struct roff_node *p;
|
||||
|
||||
body->flags |= MDOC_ENDED;
|
||||
body->parent->flags |= MDOC_ENDED;
|
||||
body->flags |= NODE_ENDED;
|
||||
body->parent->flags |= NODE_ENDED;
|
||||
p = roff_node_alloc(mdoc, line, pos, ROFFT_BODY, tok);
|
||||
p->body = body;
|
||||
p->norm = body->norm;
|
||||
p->end = end;
|
||||
p->end = ENDBODY_SPACE;
|
||||
roff_node_append(mdoc, p);
|
||||
mdoc->next = ROFF_NEXT_SIBLING;
|
||||
return p;
|
||||
|
@ -219,29 +219,19 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
|
|||
struct roff_node *n;
|
||||
char *c, *ws, *end;
|
||||
|
||||
assert(mdoc->last);
|
||||
n = mdoc->last;
|
||||
|
||||
/*
|
||||
* Divert directly to list processing if we're encountering a
|
||||
* columnar ROFFT_BLOCK with or without a prior ROFFT_BLOCK entry
|
||||
* (a ROFFT_BODY means it's already open, in which case we should
|
||||
* process within its context in the normal way).
|
||||
* If a column list contains plain text, assume an implicit item
|
||||
* macro. This can happen one or more times at the beginning
|
||||
* of such a list, intermixed with non-It mdoc macros and with
|
||||
* nodes generated on the roff level, for example by tbl.
|
||||
*/
|
||||
|
||||
if (n->tok == MDOC_Bl && n->type == ROFFT_BODY &&
|
||||
n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) {
|
||||
/* `Bl' is open without any children. */
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (n->tok == MDOC_It && n->type == ROFFT_BLOCK &&
|
||||
NULL != n->parent &&
|
||||
MDOC_Bl == n->parent->tok &&
|
||||
LIST_column == n->parent->norm->Bl.type) {
|
||||
/* `Bl' has block-level `It' children. */
|
||||
if ((n->tok == MDOC_Bl && n->type == ROFFT_BODY &&
|
||||
n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) ||
|
||||
(n->parent != NULL && n->parent->tok == MDOC_Bl &&
|
||||
n->parent->norm->Bl.type == LIST_column)) {
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
|
||||
return 1;
|
||||
|
@ -302,7 +292,7 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
|
|||
* behaviour that we want to work around it.
|
||||
*/
|
||||
roff_elem_alloc(mdoc, line, offs, MDOC_sp);
|
||||
mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;
|
||||
mdoc->last->flags |= NODE_VALID | NODE_ENDED;
|
||||
mdoc->next = ROFF_NEXT_SIBLING;
|
||||
return 1;
|
||||
}
|
||||
|
@ -321,7 +311,23 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
|
|||
assert(buf < end);
|
||||
|
||||
if (mandoc_eos(buf+offs, (size_t)(end-buf-offs)))
|
||||
mdoc->last->flags |= MDOC_EOS;
|
||||
mdoc->last->flags |= NODE_EOS;
|
||||
|
||||
for (c = buf + offs; c != NULL; c = strchr(c + 1, '.')) {
|
||||
if (c - buf < offs + 2)
|
||||
continue;
|
||||
if (end - c < 4)
|
||||
break;
|
||||
if (isalpha((unsigned char)c[-2]) &&
|
||||
isalpha((unsigned char)c[-1]) &&
|
||||
c[1] == ' ' &&
|
||||
isupper((unsigned char)(c[2] == ' ' ? c[3] : c[2])) &&
|
||||
(c[-2] != 'n' || c[-1] != 'c') &&
|
||||
(c[-2] != 'v' || c[-1] != 's'))
|
||||
mandoc_msg(MANDOCERR_EOS, mdoc->parse,
|
||||
line, (int)(c - buf), NULL);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -393,36 +399,23 @@ mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs)
|
|||
* into macro processing.
|
||||
*/
|
||||
|
||||
if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) {
|
||||
n = mdoc->last;
|
||||
if (n == NULL || tok == MDOC_It || tok == MDOC_El) {
|
||||
mdoc_macro(mdoc, tok, ln, sv, &offs, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = mdoc->last;
|
||||
assert(mdoc->last);
|
||||
|
||||
/*
|
||||
* If the first macro of a `Bl -column', open an `It' block
|
||||
* context around the parsed macro.
|
||||
* If a column list contains a non-It macro, assume an implicit
|
||||
* item macro. This can happen one or more times at the
|
||||
* beginning of such a list, intermixed with text lines and
|
||||
* with nodes generated on the roff level, for example by tbl.
|
||||
*/
|
||||
|
||||
if (n->tok == MDOC_Bl && n->type == ROFFT_BODY &&
|
||||
n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) {
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're following a block-level `It' within a `Bl -column'
|
||||
* context (perhaps opened in the above block or in ptext()),
|
||||
* then open an `It' block context around the parsed macro.
|
||||
*/
|
||||
|
||||
if (n->tok == MDOC_It && n->type == ROFFT_BLOCK &&
|
||||
NULL != n->parent &&
|
||||
MDOC_Bl == n->parent->tok &&
|
||||
LIST_column == n->parent->norm->Bl.type) {
|
||||
if ((n->tok == MDOC_Bl && n->type == ROFFT_BODY &&
|
||||
n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) ||
|
||||
(n->parent != NULL && n->parent->tok == MDOC_Bl &&
|
||||
n->parent->norm->Bl.type == LIST_column)) {
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
|
||||
return 1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
/* Id: mdoc_man.c,v 1.96 2016/01/08 17:48:09 schwarze Exp */
|
||||
/* Id: mdoc_man.c,v 1.104 2017/02/17 19:15:41 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011-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
|
||||
|
@ -79,7 +79,6 @@ static int pre_bf(DECL_ARGS);
|
|||
static int pre_bk(DECL_ARGS);
|
||||
static int pre_bl(DECL_ARGS);
|
||||
static int pre_br(DECL_ARGS);
|
||||
static int pre_bx(DECL_ARGS);
|
||||
static int pre_dl(DECL_ARGS);
|
||||
static int pre_en(DECL_ARGS);
|
||||
static int pre_enc(DECL_ARGS);
|
||||
|
@ -103,14 +102,12 @@ static int pre_no(DECL_ARGS);
|
|||
static int pre_ns(DECL_ARGS);
|
||||
static int pre_pp(DECL_ARGS);
|
||||
static int pre_rs(DECL_ARGS);
|
||||
static int pre_rv(DECL_ARGS);
|
||||
static int pre_sm(DECL_ARGS);
|
||||
static int pre_sp(DECL_ARGS);
|
||||
static int pre_sect(DECL_ARGS);
|
||||
static int pre_sy(DECL_ARGS);
|
||||
static void pre_syn(const struct roff_node *);
|
||||
static int pre_vt(DECL_ARGS);
|
||||
static int pre_ux(DECL_ARGS);
|
||||
static int pre_xr(DECL_ARGS);
|
||||
static void print_word(const char *);
|
||||
static void print_line(const char *, int);
|
||||
|
@ -158,7 +155,7 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
|||
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
|
||||
{ NULL, pre_ft, post_font, NULL, NULL }, /* Ot */
|
||||
{ NULL, pre_em, post_font, NULL, NULL }, /* Pa */
|
||||
{ NULL, pre_rv, NULL, NULL, NULL }, /* Rv */
|
||||
{ NULL, pre_ex, NULL, NULL, NULL }, /* Rv */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* St */
|
||||
{ NULL, pre_em, post_font, NULL, NULL }, /* Va */
|
||||
{ NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
|
||||
|
@ -182,8 +179,8 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
|||
{ NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
|
||||
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
|
||||
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
|
||||
{ NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */
|
||||
{ NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Bsx */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Bx */
|
||||
{ NULL, pre_skip, NULL, NULL, NULL }, /* Db */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Dc */
|
||||
{ cond_body, pre_enc, post_enc, "\\(Lq", "\\(Rq" }, /* Do */
|
||||
|
@ -192,12 +189,12 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
|||
{ NULL, NULL, NULL, NULL, NULL }, /* Ef */
|
||||
{ NULL, pre_em, post_font, NULL, NULL }, /* Em */
|
||||
{ cond_body, pre_eo, post_eo, NULL, NULL }, /* Eo */
|
||||
{ NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Fx */
|
||||
{ NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
|
||||
{ NULL, pre_no, NULL, NULL, NULL }, /* No */
|
||||
{ NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
|
||||
{ NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */
|
||||
{ NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Nx */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ox */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Pc */
|
||||
{ NULL, NULL, post_pf, NULL, NULL }, /* Pf */
|
||||
{ cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
|
||||
|
@ -215,7 +212,7 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
|||
{ NULL, pre_em, post_font, NULL, NULL }, /* Sx */
|
||||
{ NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
|
||||
{ NULL, pre_li, post_font, NULL, NULL }, /* Tn */
|
||||
{ NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ux */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Xc */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Xo */
|
||||
{ NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
|
||||
|
@ -224,10 +221,10 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
|||
{ NULL, NULL, NULL, NULL, NULL }, /* Oc */
|
||||
{ NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ek */
|
||||
{ NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Bt */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Hf */
|
||||
{ NULL, pre_em, post_font, NULL, NULL }, /* Fr */
|
||||
{ NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ud */
|
||||
{ NULL, NULL, post_lb, NULL, NULL }, /* Lb */
|
||||
{ NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
|
||||
{ NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
|
||||
|
@ -238,7 +235,7 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
|||
{ NULL, NULL, post_percent, NULL, NULL }, /* %C */
|
||||
{ NULL, pre_skip, NULL, NULL, NULL }, /* Es */
|
||||
{ cond_body, pre_en, post_en, NULL, NULL }, /* En */
|
||||
{ NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Dx */
|
||||
{ NULL, NULL, post_percent, NULL, NULL }, /* %Q */
|
||||
{ NULL, pre_br, NULL, NULL, NULL }, /* br */
|
||||
{ NULL, pre_sp, post_sp, NULL, NULL }, /* sp */
|
||||
|
@ -575,17 +572,20 @@ print_node(DECL_ARGS)
|
|||
struct roff_node *sub;
|
||||
int cond, do_sub;
|
||||
|
||||
if (n->flags & NODE_NOPRT)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Break the line if we were parsed subsequent the current node.
|
||||
* This makes the page structure be more consistent.
|
||||
*/
|
||||
if (MMAN_spc & outflags && MDOC_LINE & n->flags)
|
||||
if (MMAN_spc & outflags && NODE_LINE & n->flags)
|
||||
outflags |= MMAN_nl;
|
||||
|
||||
act = NULL;
|
||||
cond = 0;
|
||||
do_sub = 1;
|
||||
n->flags &= ~MDOC_ENDED;
|
||||
n->flags &= ~NODE_ENDED;
|
||||
|
||||
if (n->type == ROFFT_TEXT) {
|
||||
/*
|
||||
|
@ -598,10 +598,14 @@ print_node(DECL_ARGS)
|
|||
printf("\\&");
|
||||
outflags &= ~MMAN_spc;
|
||||
}
|
||||
if (outflags & MMAN_Sm && ! (n->flags & MDOC_DELIMC))
|
||||
if (n->flags & NODE_DELIMC)
|
||||
outflags &= ~(MMAN_spc | MMAN_spc_force);
|
||||
else if (outflags & MMAN_Sm)
|
||||
outflags |= MMAN_spc_force;
|
||||
print_word(n->string);
|
||||
if (outflags & MMAN_Sm && ! (n->flags & MDOC_DELIMO))
|
||||
if (n->flags & NODE_DELIMO)
|
||||
outflags &= ~(MMAN_spc | MMAN_spc_force);
|
||||
else if (outflags & MMAN_Sm)
|
||||
outflags |= MMAN_spc;
|
||||
} else {
|
||||
/*
|
||||
|
@ -627,17 +631,14 @@ print_node(DECL_ARGS)
|
|||
/*
|
||||
* Lastly, conditionally run the post-node handler.
|
||||
*/
|
||||
if (MDOC_ENDED & n->flags)
|
||||
if (NODE_ENDED & n->flags)
|
||||
return;
|
||||
|
||||
if (cond && act->post)
|
||||
(*act->post)(meta, n);
|
||||
|
||||
if (ENDBODY_NOT != n->end)
|
||||
n->body->flags |= MDOC_ENDED;
|
||||
|
||||
if (ENDBODY_NOSPACE == n->end)
|
||||
outflags &= ~(MMAN_spc | MMAN_nl);
|
||||
n->body->flags |= NODE_ENDED;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -682,36 +683,8 @@ post_enc(DECL_ARGS)
|
|||
static int
|
||||
pre_ex(DECL_ARGS)
|
||||
{
|
||||
struct roff_node *nch;
|
||||
|
||||
outflags |= MMAN_br | MMAN_nl;
|
||||
|
||||
print_word("The");
|
||||
|
||||
for (nch = n->child; nch != NULL; nch = nch->next) {
|
||||
font_push('B');
|
||||
print_word(nch->string);
|
||||
font_pop();
|
||||
|
||||
if (nch->next == NULL)
|
||||
continue;
|
||||
|
||||
if (nch->prev != NULL || nch->next->next != NULL) {
|
||||
outflags &= ~MMAN_spc;
|
||||
print_word(",");
|
||||
}
|
||||
if (nch->next->next == NULL)
|
||||
print_word("and");
|
||||
}
|
||||
|
||||
if (n->child != NULL && n->child->next != NULL)
|
||||
print_word("utilities exit\\~0");
|
||||
else
|
||||
print_word("utility exits\\~0");
|
||||
|
||||
print_word("on success, and\\~>0 if an error occurs.");
|
||||
outflags |= MMAN_nl;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -744,8 +717,7 @@ pre__t(DECL_ARGS)
|
|||
|
||||
if (n->parent && MDOC_Rs == n->parent->tok &&
|
||||
n->parent->norm->Rs.quote_T) {
|
||||
print_word("");
|
||||
putchar('\"');
|
||||
print_word("\\(lq");
|
||||
outflags &= ~MMAN_spc;
|
||||
} else
|
||||
font_push('I');
|
||||
|
@ -759,8 +731,7 @@ post__t(DECL_ARGS)
|
|||
if (n->parent && MDOC_Rs == n->parent->tok &&
|
||||
n->parent->norm->Rs.quote_T) {
|
||||
outflags &= ~MMAN_spc;
|
||||
print_word("");
|
||||
putchar('\"');
|
||||
print_word("\\(rq");
|
||||
} else
|
||||
font_pop();
|
||||
post_percent(meta, n);
|
||||
|
@ -805,7 +776,7 @@ static void
|
|||
pre_syn(const struct roff_node *n)
|
||||
{
|
||||
|
||||
if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
|
||||
if (NULL == n->prev || ! (NODE_SYNPRETTY & n->flags))
|
||||
return;
|
||||
|
||||
if (n->prev->tok == n->tok &&
|
||||
|
@ -1050,26 +1021,6 @@ pre_br(DECL_ARGS)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pre_bx(DECL_ARGS)
|
||||
{
|
||||
|
||||
n = n->child;
|
||||
if (n) {
|
||||
print_word(n->string);
|
||||
outflags &= ~MMAN_spc;
|
||||
n = n->next;
|
||||
}
|
||||
print_word("BSD");
|
||||
if (NULL == n)
|
||||
return 0;
|
||||
outflags &= ~MMAN_spc;
|
||||
print_word("-");
|
||||
outflags &= ~MMAN_spc;
|
||||
print_word(n->string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pre_dl(DECL_ARGS)
|
||||
{
|
||||
|
@ -1173,7 +1124,7 @@ pre_fa(DECL_ARGS)
|
|||
|
||||
while (NULL != n) {
|
||||
font_push('I');
|
||||
if (am_Fa || MDOC_SYNPRETTY & n->flags)
|
||||
if (am_Fa || NODE_SYNPRETTY & n->flags)
|
||||
outflags |= MMAN_nbrword;
|
||||
print_node(meta, n);
|
||||
font_pop();
|
||||
|
@ -1227,7 +1178,7 @@ post_fl(DECL_ARGS)
|
|||
if (!(n->child != NULL ||
|
||||
n->next == NULL ||
|
||||
n->next->type == ROFFT_TEXT ||
|
||||
n->next->flags & MDOC_LINE))
|
||||
n->next->flags & NODE_LINE))
|
||||
outflags &= ~MMAN_spc;
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1192,7 @@ pre_fn(DECL_ARGS)
|
|||
if (NULL == n)
|
||||
return 0;
|
||||
|
||||
if (MDOC_SYNPRETTY & n->flags)
|
||||
if (NODE_SYNPRETTY & n->flags)
|
||||
print_block(".HP 4n", MMAN_nl);
|
||||
|
||||
font_push('B');
|
||||
|
@ -1262,7 +1213,7 @@ post_fn(DECL_ARGS)
|
|||
{
|
||||
|
||||
print_word(")");
|
||||
if (MDOC_SYNPRETTY & n->flags) {
|
||||
if (NODE_SYNPRETTY & n->flags) {
|
||||
print_word(";");
|
||||
outflags |= MMAN_PP;
|
||||
}
|
||||
|
@ -1279,7 +1230,7 @@ pre_fo(DECL_ARGS)
|
|||
case ROFFT_HEAD:
|
||||
if (n->child == NULL)
|
||||
return 0;
|
||||
if (MDOC_SYNPRETTY & n->flags)
|
||||
if (NODE_SYNPRETTY & n->flags)
|
||||
print_block(".HP 4n", MMAN_nl);
|
||||
font_push('B');
|
||||
break;
|
||||
|
@ -1324,7 +1275,7 @@ static int
|
|||
pre_in(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_SYNPRETTY & n->flags) {
|
||||
if (NODE_SYNPRETTY & n->flags) {
|
||||
pre_syn(n);
|
||||
font_push('B');
|
||||
print_word("#include <");
|
||||
|
@ -1341,7 +1292,7 @@ static void
|
|||
post_in(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_SYNPRETTY & n->flags) {
|
||||
if (NODE_SYNPRETTY & n->flags) {
|
||||
outflags &= ~MMAN_spc;
|
||||
print_word(">");
|
||||
font_pop();
|
||||
|
@ -1562,7 +1513,7 @@ pre_nm(DECL_ARGS)
|
|||
}
|
||||
if (n->type != ROFFT_ELEM && n->type != ROFFT_HEAD)
|
||||
return 1;
|
||||
name = n->child ? n->child->string : meta->name;
|
||||
name = n->child == NULL ? NULL : n->child->string;
|
||||
if (NULL == name)
|
||||
return 0;
|
||||
if (n->type == ROFFT_HEAD) {
|
||||
|
@ -1573,8 +1524,6 @@ pre_nm(DECL_ARGS)
|
|||
outflags |= MMAN_nl;
|
||||
}
|
||||
font_push('B');
|
||||
if (NULL == n->child)
|
||||
print_word(meta->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1588,7 +1537,7 @@ post_nm(DECL_ARGS)
|
|||
break;
|
||||
case ROFFT_HEAD:
|
||||
case ROFFT_ELEM:
|
||||
if (n->child != NULL || meta->name != NULL)
|
||||
if (n->child != NULL && n->child->string != NULL)
|
||||
font_pop();
|
||||
break;
|
||||
default:
|
||||
|
@ -1616,7 +1565,7 @@ static void
|
|||
post_pf(DECL_ARGS)
|
||||
{
|
||||
|
||||
if ( ! (n->next == NULL || n->next->flags & MDOC_LINE))
|
||||
if ( ! (n->next == NULL || n->next->flags & NODE_LINE))
|
||||
outflags &= ~MMAN_spc;
|
||||
}
|
||||
|
||||
|
@ -1642,57 +1591,6 @@ pre_rs(DECL_ARGS)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
pre_rv(DECL_ARGS)
|
||||
{
|
||||
struct roff_node *nch;
|
||||
|
||||
outflags |= MMAN_br | MMAN_nl;
|
||||
|
||||
if (n->child != NULL) {
|
||||
print_word("The");
|
||||
|
||||
for (nch = n->child; nch != NULL; nch = nch->next) {
|
||||
font_push('B');
|
||||
print_word(nch->string);
|
||||
font_pop();
|
||||
|
||||
outflags &= ~MMAN_spc;
|
||||
print_word("()");
|
||||
|
||||
if (nch->next == NULL)
|
||||
continue;
|
||||
|
||||
if (nch->prev != NULL || nch->next->next != NULL) {
|
||||
outflags &= ~MMAN_spc;
|
||||
print_word(",");
|
||||
}
|
||||
if (nch->next->next == NULL)
|
||||
print_word("and");
|
||||
}
|
||||
|
||||
if (n->child != NULL && n->child->next != NULL)
|
||||
print_word("functions return");
|
||||
else
|
||||
print_word("function returns");
|
||||
|
||||
print_word("the value\\~0 if successful;");
|
||||
} else
|
||||
print_word("Upon successful completion, "
|
||||
"the value\\~0 is returned;");
|
||||
|
||||
print_word("otherwise the value\\~\\-1 is returned"
|
||||
" and the global variable");
|
||||
|
||||
font_push('I');
|
||||
print_word("errno");
|
||||
font_pop();
|
||||
|
||||
print_word("is set to indicate the error.");
|
||||
outflags |= MMAN_nl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pre_skip(DECL_ARGS)
|
||||
{
|
||||
|
@ -1748,7 +1646,7 @@ static int
|
|||
pre_vt(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (MDOC_SYNPRETTY & n->flags) {
|
||||
if (NODE_SYNPRETTY & n->flags) {
|
||||
switch (n->type) {
|
||||
case ROFFT_BLOCK:
|
||||
pre_syn(n);
|
||||
|
@ -1767,7 +1665,7 @@ static void
|
|||
post_vt(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (n->flags & MDOC_SYNPRETTY && n->type != ROFFT_BODY)
|
||||
if (n->flags & NODE_SYNPRETTY && n->type != ROFFT_BODY)
|
||||
return;
|
||||
font_pop();
|
||||
}
|
||||
|
@ -1789,16 +1687,3 @@ pre_xr(DECL_ARGS)
|
|||
print_word(")");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pre_ux(DECL_ARGS)
|
||||
{
|
||||
|
||||
print_word(manacts[n->tok].prefix);
|
||||
if (NULL == n->child)
|
||||
return 0;
|
||||
outflags &= ~MMAN_spc;
|
||||
print_word("\\ ");
|
||||
outflags &= ~MMAN_spc;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Id: mdoc_state.c,v 1.3 2015/10/30 18:53:54 schwarze Exp */
|
||||
/* Id: mdoc_state.c,v 1.4 2017/01/10 13:47:00 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
|
@ -249,7 +249,7 @@ state_sh(STATE_ARGS)
|
|||
if (n->type != ROFFT_HEAD)
|
||||
return;
|
||||
|
||||
if ( ! (n->flags & MDOC_VALID)) {
|
||||
if ( ! (n->flags & NODE_VALID)) {
|
||||
secname = NULL;
|
||||
deroff(&secname, n);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Id: tbl_html.c,v 1.18 2015/10/12 00:08:16 schwarze Exp */
|
||||
/* Id: tbl_html.c,v 1.20 2017/02/05 18:15:39 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -50,9 +50,7 @@ html_tbl_strlen(const char *p, void *arg)
|
|||
static void
|
||||
html_tblopen(struct html *h, const struct tbl_span *sp)
|
||||
{
|
||||
struct htmlpair tag;
|
||||
struct roffsu su;
|
||||
struct roffcol *col;
|
||||
struct tag *t;
|
||||
int ic;
|
||||
|
||||
if (h->tbl.cols == NULL) {
|
||||
|
@ -62,19 +60,12 @@ html_tblopen(struct html *h, const struct tbl_span *sp)
|
|||
}
|
||||
|
||||
assert(NULL == h->tblt);
|
||||
PAIR_CLASS_INIT(&tag, "tbl");
|
||||
h->tblt = print_otag(h, TAG_TABLE, 1, &tag);
|
||||
h->tblt = print_otag(h, TAG_TABLE, "c", "tbl");
|
||||
|
||||
for (ic = 0; ic < sp->opts->cols; ic++) {
|
||||
bufinit(h);
|
||||
col = h->tbl.cols + ic;
|
||||
SCALE_HS_INIT(&su, col->width);
|
||||
bufcat_su(h, "width", &su);
|
||||
PAIR_STYLE_INIT(&tag, h);
|
||||
print_otag(h, TAG_COL, 1, &tag);
|
||||
}
|
||||
|
||||
print_otag(h, TAG_TBODY, 0, NULL);
|
||||
t = print_otag(h, TAG_COLGROUP, "");
|
||||
for (ic = 0; ic < sp->opts->cols; ic++)
|
||||
print_otag(h, TAG_COL, "shw", h->tbl.cols[ic].width);
|
||||
print_tagq(h, t);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -90,7 +81,6 @@ void
|
|||
print_tbl(struct html *h, const struct tbl_span *sp)
|
||||
{
|
||||
const struct tbl_dat *dp;
|
||||
struct htmlpair tag;
|
||||
struct tag *tt;
|
||||
int ic;
|
||||
|
||||
|
@ -104,19 +94,18 @@ print_tbl(struct html *h, const struct tbl_span *sp)
|
|||
h->flags |= HTML_NONOSPACE;
|
||||
h->flags |= HTML_NOSPACE;
|
||||
|
||||
tt = print_otag(h, TAG_TR, 0, NULL);
|
||||
tt = print_otag(h, TAG_TR, "");
|
||||
|
||||
switch (sp->pos) {
|
||||
case TBL_SPAN_HORIZ:
|
||||
case TBL_SPAN_DHORIZ:
|
||||
PAIR_INIT(&tag, ATTR_COLSPAN, "0");
|
||||
print_otag(h, TAG_TD, 1, &tag);
|
||||
print_otag(h, TAG_TD, "?", "colspan", "0");
|
||||
break;
|
||||
default:
|
||||
dp = sp->first;
|
||||
for (ic = 0; ic < sp->opts->cols; ic++) {
|
||||
print_stagq(h, tt);
|
||||
print_otag(h, TAG_TD, 0, NULL);
|
||||
print_otag(h, TAG_TD, "");
|
||||
|
||||
if (dp == NULL || dp->layout->col > ic)
|
||||
continue;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Id: term_ascii.c,v 1.53 2016/07/08 22:29:05 schwarze Exp */
|
||||
/* Id: term_ascii.c,v 1.54 2016/07/31 09:29:13 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
|
@ -98,7 +98,7 @@ ascii_init(enum termenc enc, const struct manoutput *outopts)
|
|||
|
||||
v = TERMENC_LOCALE == enc ?
|
||||
setlocale(LC_CTYPE, "") :
|
||||
setlocale(LC_CTYPE, "en_US.UTF-8");
|
||||
setlocale(LC_CTYPE, UTF8_LOCALE);
|
||||
if (NULL != v && MB_CUR_MAX > 1) {
|
||||
p->enc = enc;
|
||||
p->advance = locale_advance;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Id: term_ps.c,v 1.80 2015/12/23 20:50:13 schwarze Exp */
|
||||
/* Id: term_ps.c,v 1.83 2017/02/17 14:31:52 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2014, 2015, 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
|
||||
|
@ -98,15 +98,13 @@ static void ps_begin(struct termp *);
|
|||
static void ps_closepage(struct termp *);
|
||||
static void ps_end(struct termp *);
|
||||
static void ps_endline(struct termp *);
|
||||
static void ps_fclose(struct termp *);
|
||||
static void ps_growbuf(struct termp *, size_t);
|
||||
static void ps_letter(struct termp *, int);
|
||||
static void ps_pclose(struct termp *);
|
||||
static void ps_plast(struct termp *);
|
||||
static void ps_pletter(struct termp *, int);
|
||||
#if __GNUC__ - 0 >= 4
|
||||
__attribute__((__format__ (__printf__, 2, 3)))
|
||||
#endif
|
||||
static void ps_printf(struct termp *, const char *, ...);
|
||||
static void ps_printf(struct termp *, const char *, ...)
|
||||
__attribute__((__format__ (__printf__, 2, 3)));
|
||||
static void ps_putchar(struct termp *, char);
|
||||
static void ps_setfont(struct termp *, enum termfont);
|
||||
static void ps_setwidth(struct termp *, int, int);
|
||||
|
@ -782,6 +780,9 @@ ps_end(struct termp *p)
|
|||
{
|
||||
size_t i, xref, base;
|
||||
|
||||
ps_plast(p);
|
||||
ps_pclose(p);
|
||||
|
||||
/*
|
||||
* At the end of the file, do one last showpage. This is the
|
||||
* same behaviour as groff(1) and works for multiple pages as
|
||||
|
@ -1025,39 +1026,53 @@ ps_pclose(struct termp *p)
|
|||
p->ps->flags &= ~PS_INLINE;
|
||||
}
|
||||
|
||||
/* If we have a `last' char that wasn't printed yet, print it now. */
|
||||
static void
|
||||
ps_fclose(struct termp *p)
|
||||
ps_plast(struct termp *p)
|
||||
{
|
||||
size_t wx;
|
||||
|
||||
/*
|
||||
* Strong closure: if we have a last-char, spit it out after
|
||||
* checking that we're in the right font mode. This will of
|
||||
* course open a new scope, if applicable.
|
||||
*
|
||||
* Following this, close out any scope that's open.
|
||||
*/
|
||||
|
||||
if (p->ps->last != '\0') {
|
||||
assert( ! (p->ps->flags & PS_BACKSP));
|
||||
if (p->ps->nextf != p->ps->lastf) {
|
||||
ps_pclose(p);
|
||||
ps_setfont(p, p->ps->nextf);
|
||||
}
|
||||
p->ps->nextf = TERMFONT_NONE;
|
||||
ps_pletter(p, p->ps->last);
|
||||
p->ps->last = '\0';
|
||||
}
|
||||
|
||||
if ( ! (PS_INLINE & p->ps->flags))
|
||||
if (p->ps->last == '\0')
|
||||
return;
|
||||
|
||||
ps_pclose(p);
|
||||
/* Check the font mode; open a new scope if it doesn't match. */
|
||||
|
||||
if (p->ps->nextf != p->ps->lastf) {
|
||||
ps_pclose(p);
|
||||
ps_setfont(p, p->ps->nextf);
|
||||
}
|
||||
p->ps->nextf = TERMFONT_NONE;
|
||||
|
||||
/*
|
||||
* For an overstrike, if a previous character
|
||||
* was wider, advance to center the new one.
|
||||
*/
|
||||
|
||||
if (p->ps->pscolnext) {
|
||||
wx = fonts[p->ps->lastf].gly[(int)p->ps->last-32].wx;
|
||||
if (p->ps->pscol + wx < p->ps->pscolnext)
|
||||
p->ps->pscol = (p->ps->pscol +
|
||||
p->ps->pscolnext - wx) / 2;
|
||||
}
|
||||
|
||||
ps_pletter(p, p->ps->last);
|
||||
p->ps->last = '\0';
|
||||
|
||||
/*
|
||||
* For an overstrike, if a previous character
|
||||
* was wider, advance to the end of the old one.
|
||||
*/
|
||||
|
||||
if (p->ps->pscol < p->ps->pscolnext) {
|
||||
ps_pclose(p);
|
||||
p->ps->pscol = p->ps->pscolnext;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ps_letter(struct termp *p, int arg)
|
||||
{
|
||||
size_t savecol, wx;
|
||||
size_t savecol;
|
||||
char c;
|
||||
|
||||
c = arg >= 128 || arg <= 0 ? '?' : arg;
|
||||
|
@ -1123,43 +1138,12 @@ ps_letter(struct termp *p, int arg)
|
|||
* Use them and print it.
|
||||
*/
|
||||
|
||||
if (p->ps->last != '\0') {
|
||||
if (p->ps->nextf != p->ps->lastf) {
|
||||
ps_pclose(p);
|
||||
ps_setfont(p, p->ps->nextf);
|
||||
}
|
||||
p->ps->nextf = TERMFONT_NONE;
|
||||
|
||||
/*
|
||||
* For an overstrike, if a previous character
|
||||
* was wider, advance to center the new one.
|
||||
*/
|
||||
|
||||
if (p->ps->pscolnext) {
|
||||
wx = fonts[p->ps->lastf].gly[(int)p->ps->last-32].wx;
|
||||
if (p->ps->pscol + wx < p->ps->pscolnext)
|
||||
p->ps->pscol = (p->ps->pscol +
|
||||
p->ps->pscolnext - wx) / 2;
|
||||
}
|
||||
|
||||
ps_pletter(p, p->ps->last);
|
||||
|
||||
/*
|
||||
* For an overstrike, if a previous character
|
||||
* was wider, advance to the end of the old one.
|
||||
*/
|
||||
|
||||
if (p->ps->pscol < p->ps->pscolnext) {
|
||||
ps_pclose(p);
|
||||
p->ps->pscol = p->ps->pscolnext;
|
||||
}
|
||||
}
|
||||
ps_plast(p);
|
||||
|
||||
/*
|
||||
* Do not print the current character yet because font
|
||||
* instructions might follow; only remember it.
|
||||
* For the first character, nothing else is done.
|
||||
* The final character will get printed from ps_fclose().
|
||||
* instructions might follow; only remember the character.
|
||||
* It will get printed later from ps_plast().
|
||||
*/
|
||||
|
||||
p->ps->last = c;
|
||||
|
@ -1192,7 +1176,8 @@ ps_advance(struct termp *p, size_t len)
|
|||
* and readjust our column settings.
|
||||
*/
|
||||
|
||||
ps_fclose(p);
|
||||
ps_plast(p);
|
||||
ps_pclose(p);
|
||||
p->ps->pscol += len;
|
||||
}
|
||||
|
||||
|
@ -1202,7 +1187,8 @@ ps_endline(struct termp *p)
|
|||
|
||||
/* Close out any scopes we have open: we're at eoln. */
|
||||
|
||||
ps_fclose(p);
|
||||
ps_plast(p);
|
||||
ps_pclose(p);
|
||||
|
||||
/*
|
||||
* If we're in the margin, don't try to recalculate our current
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return !EFTYPE;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#include <fcntl.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return open(".", O_RDONLY | O_DIRECTORY) == -1;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* POSIX allows PATH_MAX to not be defined, see
|
||||
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html;
|
||||
* the GNU Hurd is an example of a system not having it.
|
||||
*
|
||||
* Arguably, it would be better to test sysconf(_SC_PATH_MAX),
|
||||
* but since the individual *.c files include "config.h" before
|
||||
* <limits.h>, overriding an excessive value of PATH_MAX from
|
||||
* "config.h" is impossible anyway, so for now, the simplest
|
||||
* fix is to provide a value only on systems not having any.
|
||||
* So far, we encountered no system defining PATH_MAX to an
|
||||
* impractically large value, even though POSIX explicitly
|
||||
* allows that.
|
||||
*
|
||||
* The real fix would be to replace all static buffers of size
|
||||
* PATH_MAX by dynamically allocated buffers. But that is
|
||||
* somewhat intrusive because it touches several files and
|
||||
* because it requires changing struct mlink in mandocdb.c.
|
||||
* So i'm postponing that for now.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
printf("PATH_MAX is defined to be %ld\n", (long)PATH_MAX);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifdef SYS_ENDIAN
|
||||
#include <sys/endian.h>
|
||||
#else
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return htobe32(be32toh(0x3a7d0cdb)) != 0x3a7d0cdb;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#include <stddef.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
struct msghdr msg;
|
||||
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
|
||||
return CMSG_FIRSTHDR(&msg) != NULL;
|
||||
}
|
|
@ -2,6 +2,13 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FTS_COMPARE_CONST
|
||||
int fts_compare(const FTSENT *const *, const FTSENT *const *);
|
||||
#else
|
||||
int fts_compare(const FTSENT **, const FTSENT **);
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
|
@ -14,7 +21,7 @@ main(void)
|
|||
argv[1] = (char *)NULL;
|
||||
|
||||
ftsp = fts_open((char * const *)argv,
|
||||
FTS_PHYSICAL | FTS_NOCHDIR, NULL);
|
||||
FTS_PHYSICAL | FTS_NOCHDIR, fts_compare);
|
||||
|
||||
if (ftsp == NULL) {
|
||||
perror("fts_open");
|
||||
|
@ -40,3 +47,13 @@ main(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
#ifdef FTS_COMPARE_CONST
|
||||
fts_compare(const FTSENT *const *a, const FTSENT *const *b)
|
||||
#else
|
||||
fts_compare(const FTSENT **a, const FTSENT **b)
|
||||
#endif
|
||||
{
|
||||
return strcmp((*a)->fts_name, (*b)->fts_name);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
struct timespec timeout;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 100000000; /* 0.1 seconds */
|
||||
|
||||
if (nanosleep(&timeout, NULL)) {
|
||||
perror("nanosleep");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#include <arpa/inet.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return htonl(ntohl(0x3a7d0cdb)) != 0x3a7d0cdb;
|
||||
}
|
|
@ -3,9 +3,27 @@
|
|||
#include <stdlib.h>
|
||||
#include <ohash.h>
|
||||
|
||||
void *xmalloc(size_t sz, void *arg) { return calloc(1,sz); }
|
||||
void *xcalloc(size_t nmemb, size_t sz, void *arg) { return calloc(nmemb,sz); }
|
||||
void xfree(void *p, void *arg) { free(p); }
|
||||
static void *xmalloc(size_t, void *);
|
||||
static void *xcalloc(size_t, size_t, void *);
|
||||
static void xfree(void *, void *);
|
||||
|
||||
|
||||
static void *
|
||||
xmalloc(size_t sz, void *arg) {
|
||||
return calloc(1,sz);
|
||||
}
|
||||
|
||||
static void *
|
||||
xcalloc(size_t nmemb, size_t sz, void *arg)
|
||||
{
|
||||
return calloc(nmemb,sz);
|
||||
}
|
||||
|
||||
static void
|
||||
xfree(void *p, void *arg)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#include <sys/socket.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return recvmsg(-1, NULL, 0) != -1;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* Id: test-vasprintf.c,v 1.3 2015/10/06 18:32:20 schwarze Exp */
|
||||
/* Id: test-vasprintf.c,v 1.4 2016/07/18 18:35:05 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
|
@ -23,7 +23,10 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
static int testfunc(char **, const char *, ...);
|
||||
|
||||
|
||||
static int
|
||||
testfunc(char **ret, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Id: test-wchar.c,v 1.3 2015/10/06 18:32:20 schwarze Exp */
|
||||
/* Id: test-wchar.c,v 1.4 2016/07/31 09:29:13 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
|
@ -35,9 +35,9 @@ main(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) {
|
||||
fputs("setlocale(LC_CTYPE, \"en_US.UTF-8\") failed\n",
|
||||
stderr);
|
||||
if (setlocale(LC_CTYPE, UTF8_LOCALE) == NULL) {
|
||||
fprintf(stderr, "setlocale(LC_CTYPE, \"%s\") failed\n",
|
||||
UTF8_LOCALE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Id: tree.c,v 1.69 2015/10/12 00:08:16 schwarze Exp */
|
||||
/* Id: tree.c,v 1.73 2017/02/10 15:45:28 schwarze Exp */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -33,6 +33,7 @@
|
|||
|
||||
static void print_box(const struct eqn_box *, int);
|
||||
static void print_man(const struct roff_node *, int);
|
||||
static void print_meta(const struct roff_meta *);
|
||||
static void print_mdoc(const struct roff_node *, int);
|
||||
static void print_span(const struct tbl_span *, int);
|
||||
|
||||
|
@ -40,17 +41,40 @@ static void print_span(const struct tbl_span *, int);
|
|||
void
|
||||
tree_mdoc(void *arg, const struct roff_man *mdoc)
|
||||
{
|
||||
|
||||
print_meta(&mdoc->meta);
|
||||
putchar('\n');
|
||||
print_mdoc(mdoc->first->child, 0);
|
||||
}
|
||||
|
||||
void
|
||||
tree_man(void *arg, const struct roff_man *man)
|
||||
{
|
||||
|
||||
print_meta(&man->meta);
|
||||
if (man->meta.hasbody == 0)
|
||||
puts("body = empty");
|
||||
putchar('\n');
|
||||
print_man(man->first->child, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
print_meta(const struct roff_meta *meta)
|
||||
{
|
||||
if (meta->title != NULL)
|
||||
printf("title = \"%s\"\n", meta->title);
|
||||
if (meta->name != NULL)
|
||||
printf("name = \"%s\"\n", meta->name);
|
||||
if (meta->msec != NULL)
|
||||
printf("sec = \"%s\"\n", meta->msec);
|
||||
if (meta->vol != NULL)
|
||||
printf("vol = \"%s\"\n", meta->vol);
|
||||
if (meta->arch != NULL)
|
||||
printf("arch = \"%s\"\n", meta->arch);
|
||||
if (meta->os != NULL)
|
||||
printf("os = \"%s\"\n", meta->os);
|
||||
if (meta->date != NULL)
|
||||
printf("date = \"%s\"\n", meta->date);
|
||||
}
|
||||
|
||||
static void
|
||||
print_mdoc(const struct roff_node *n, int indent)
|
||||
{
|
||||
|
@ -159,15 +183,21 @@ print_mdoc(const struct roff_node *n, int indent)
|
|||
}
|
||||
|
||||
putchar(' ');
|
||||
if (MDOC_DELIMO & n->flags)
|
||||
if (NODE_DELIMO & n->flags)
|
||||
putchar('(');
|
||||
if (MDOC_LINE & n->flags)
|
||||
if (NODE_LINE & n->flags)
|
||||
putchar('*');
|
||||
printf("%d:%d", n->line, n->pos + 1);
|
||||
if (MDOC_DELIMC & n->flags)
|
||||
if (NODE_DELIMC & n->flags)
|
||||
putchar(')');
|
||||
if (MDOC_EOS & n->flags)
|
||||
if (NODE_EOS & n->flags)
|
||||
putchar('.');
|
||||
if (NODE_BROKEN & n->flags)
|
||||
printf(" BROKEN");
|
||||
if (NODE_NOSRC & n->flags)
|
||||
printf(" NOSRC");
|
||||
if (NODE_NOPRT & n->flags)
|
||||
printf(" NOPRT");
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
|
@ -248,10 +278,10 @@ print_man(const struct roff_node *n, int indent)
|
|||
for (i = 0; i < indent; i++)
|
||||
putchar(' ');
|
||||
printf("%s (%s) ", p, t);
|
||||
if (MAN_LINE & n->flags)
|
||||
if (NODE_LINE & n->flags)
|
||||
putchar('*');
|
||||
printf("%d:%d", n->line, n->pos + 1);
|
||||
if (MAN_EOS & n->flags)
|
||||
if (NODE_EOS & n->flags)
|
||||
putchar('.');
|
||||
putchar('\n');
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue