From a854ed63d9001a804af8c52eb914834f0d8bb8c0 Mon Sep 17 00:00:00 2001 From: Werner LEMBERG Date: Tue, 4 May 2004 04:46:54 +0000 Subject: [PATCH] Update to groffer 0.9.7. --- contrib/groffer/ChangeLog | 277 +++++- contrib/groffer/Makefile.sub | 6 +- contrib/groffer/README | 39 +- contrib/groffer/README_SH | 219 +++++ contrib/groffer/TODO | 110 +-- contrib/groffer/groffer.man | 2226 ++++++++++++++++++++++++++---------------- contrib/groffer/groffer.sh | 1772 +++++++++++++++++---------------- 7 files changed, 2865 insertions(+), 1784 deletions(-) create mode 100644 contrib/groffer/README_SH rewrite contrib/groffer/TODO (60%) diff --git a/contrib/groffer/ChangeLog b/contrib/groffer/ChangeLog index f706907d..bea3e38b 100644 --- a/contrib/groffer/ChangeLog +++ b/contrib/groffer/ChangeLog @@ -1,4 +1,231 @@ -2003-01-22 Bernd Warken +2004-04-30 Bernd Warken + ________________________________________________________________ + * release of groffer 0.9.7 + + * groffer.sh: + - obj(), obj_data(), obj_from_output(), obj_set(): New object + oriented functions to minimize complicated `eval' commands. + - list_*(): Corrections. + - usage(): Streamlining. + + * groffer.man, README_SH: + Corrections. + +2004-04-27 Bernd Warken + ________________________________________________________________ + * release of groffer 0.9.6 + + This version replaces the license of all files except ChangeLog of + the groffer source to the GNU General Public License (GPL) of the + version described in files COPYING and LICENSE in the groff top + source directory. + + * groffer.man: + Changement from the GNU Free Documentation License (FDL) to + the GNU General Public License (GPL). + + * README, README_SH, TODO: + Add license GNU General Public License (GPL). + + * Makefile.sub, groffer.sh: + Keep the GNU General Public License (GPL), but refer to the + COPYING and LICENSE files. + + * ChangeLog: Add a license in the style of Emacs ChangeLog file, + which is weaker than the GPL, but has its flavor. + +2004-04-24 Bernd Warken + ________________________________________________________________ + * release of groffer 0.9.5 + + This version is a rewrite of groffer in many parts, but it is kept + in the old single script style. + + Overview of new options: + --text, --mode text, --tty-viewer, + --X, --mode X, --X-viewer, --html, --mode html, --html-view, + --apropos-data, --apropos-devel, --apropos-progs + + New file: + /README_SH + + + ******* Extension of the `apropos' handling + + The output of man's `apropos' has grown immensely meanwhile, so it + has become inefficient. Now `groffer' provides new options to get + the a selected information from this output. + + * groffer.sh: + `--apropos-progs': new option for displaying only information + on programs (man page sections 1, 6, and 8) + `--apropos-data': new option for displaying only information + on documented data (man page sections 4, 5 and 7) + `--apropos-devel': new option for displaying only information + on development documentation (man page sections 2, 3 and 9) + `--apropos': still displays just the output of man's `apropos' + program. + - Specify all of these options as a single argument option; that + makes groffer's `--apropos' option slightly different because + the corresponding `man' option does not have arguments, but takes + all file arguments as apropos targets. So just ignore the `man' + options `-k' and `--apropos' in the parsing of $MANOPT. + - Exit after processing one `apropos' call. + + + ******* Quasi object oriented function arguments + + An object is the name of an environment variable. The value of + this variable contains the object's content. This allows to + specify function arguments and the calling syntax in a simpler way + by letting the first argument be a variable name, usable for input + or output. + + Such an object type is `list', the string value of a shell + variable arranged in space-separated single-quoted elements, such + as $GROFFER_OPT internally. + + * groffer.sh: + - Remove list_from_args(), list_element_from_arg() + list_from_lists(), list_length(), and list_prepend(). + They can be replaced by list_append(). + - All list*() functions are rearranged such that the first + argument is a list object, the name of a variable. + + + ******* Simplification of configuration files + + The new syntax of the groffer configuration files is + - all lines starting with a `-' character are interpreted as + command line options for all calls of groffer; they are collected + and prepended to the actual value of $GROFFER_OPT; optional + spaces at the beginning.of the line are omitted. + - all other lines are interpreted as a shell command and executed + in the current shell of the groffer call. + + Precedence: + - The command line and the external environment variables such as + $GROFFER_OPT of the groffer call have the highest precedence. + - This is overwritten by the configuration file in the user's home + directory. + - The system configuration file in /etc has the lowest + precedence. + + * groffer.sh: + The configuration files are now called after the determination of + the temporary files in main_init(). + + + ******* Script file name + + The file name of the script is needed for the several calls during + the search for the optimal shell. + + * groffer.sh: + - $_GROFFER_SH: replace $_this by $_GROFFER_SH and use $0 for + determining the file name of the script for the following calls, + instead of the cumbersome @BINDIR@ construction. + - Force the script to be called as an executable file, so $0 must + contain the program name. + + + ******* Improved temporary file names + + Just like groff, groffer mixes all file parameters into a single + output file. Its name is now constructed as a comma-separated + list built from the file name arguments without a leading comma. + So a leading comma can be used for the internal temporary file + names. + + * groffer.sh: + - $_OUTPUT_FILE_NAME: new global variable as basis for the output + file name; it is set in main_set_resources(). + - tmp_create(): use `,name' for temporary files different from + output file because the output file name does not start with a + comma. `$$' is not needed anymore. + - main_display(): simplification of $_modefile in _do_display() + and single display modes. + - Add extension `.html' to output file name in html mode. + - base_name(): correction for strange positions of `/'. + + + ******* Mode fixes + + * groffer.sh: + - Set the main default mode to `x' with groff's X Window viewer + `gxditview'. + - Allow 'x' and 'X' in `--mode' for the X Window mode; the same + for `--x' and `X', `--x-viewer' and `--X-viewer'. + - Make groff's `-X' equivalent to `mode X'. + - Fix `--auto', `--mode auto', and `--default-modes'. + - `html' mode: new mode equivalent to `www', add `konqueror' and + `lynx' as viewers. + - `pdf' mode: fix zoom options for pdf-viewer `xpdf' in + main_set_resources(); in main_display() fix the display structure. + - Set default X Window resolution to 75dpi. This is not optimal, + but with a higher value the options and resources for some viewers + must be optimized. + `--text' and `--mode text': new option for text output without a + pager. + - `--tty-viewer': new option equivalent to `--pager'. + - Correct the pagers for `tty' mode. + - Fix `groff' mode in main_set_resources() and main_display(). + - Harmonize `--mode arg' with the equivalent options `--arg'. + + + ******* Fixes for command line options + + * groffer.sh: + - list_from_cmdline(): fix the parsing of options with arguments. + - Rename $_OPT_TTY_DEVICE to $_OPT_TEXT_DEVICE. + - $_OPTS_X_*: new variables for the inhereted X Window variables. + - Improve the distribution of the command line options into + $_OPTS_GROFFER_*, $_OPTS_GROFF_*, $_OPTS_X_*, and $_OPTS_MAN_*. + - $_OPTS_MANOPT_*: new variables for the parsing of $MANOPT. + - Correct $_OPTS_CMDLINE_*. + - Remove some unused $_OPTS_*. + - `--iconic': new option from `-iconic' of the X Window toolkit. + - Correct `--rv' to an option without argument. + - Minor fixes of other X Window toolkit options. + + + ******* Other fixes + + * groffer.sh: + - is_prog(): allow 0 arguments. + - is_not_writable(): new function. + - is_*(): fix trailing return codes. + - Replace most `test' calls by is_*() functions. + - man_setup(): due to bugs in `manpath', prefer + manpath_set_from_path() for the determination of the man page path. + - man_search_section(): correction of some `for' loops. + - Remove export of external non-groffer variables. + + + ******* Documentation + + * groffer.man: + - Reorder the option details according to the option origin as + groffer, groff, X, and man options. + - Add the programming changes information mentioned above. + - Support man pages with a dot in their name + + * README_SH: new file + Move large parts of the documentation in `groffer.sh' into this + file. + + * groffer.sh: usage(): + - Change the output for `--help' to standard output. + - Restructure the information for this help output. + + + ******* Removement of the author's email address + + Because of the extreme spam attacks, the author removed all + occurencies of his email address in every file of the groffer + source. + +2003-01-22 Bernd Warken ________________________________________________________________ * release of groffer 0.9.4 @@ -19,7 +246,7 @@ * TODO: Remove mention of `shoop' and `apropos'. -2002-10-21 Bernd Warken +2002-10-21 Bernd Warken ________________________________________________________________ * release of groffer 0.9.3 @@ -43,7 +270,7 @@ - writing part of groffer in C/C++. - handling several files with different macro packages. -2002-10-17 Bernd Warken +2002-10-17 Bernd Warken ________________________________________________________________ * fixes of groffer 0.9.2 @@ -60,7 +287,7 @@ New file for general information on the groffer source; it is not installed. -2002-10-14 Bernd Warken +2002-10-14 Bernd Warken * Makefile.sub: add replacement "@BINDIR@" to "$(bindir)" for "groffer:" @@ -72,7 +299,7 @@ * groffer.man: Remove double definition of filespec parameters. -2002-10-13 Bernd Warken +2002-10-13 Bernd Warken ________________________________________________________________ * release of groffer 0.9.2 @@ -95,7 +322,7 @@ - "Option Parsing" is moved to section "COMPATIBILITY". - Fix some "EXAMPLES". -2002-09-30 Bernd Warken +2002-09-30 Bernd Warken ________________________________________________________________ * release of groffer 0.9.1 @@ -103,7 +330,7 @@ - Remove request for different shells. - Remove the 'sed' complaints. -2002-07-15 Bernd Warken +2002-07-15 Bernd Warken * groffer.sh: replace `sed' interface by direct `sed' - This improves the performance of the shell programming parts @@ -127,7 +354,7 @@ groffer was called from the command line, or with the shell name in the first line of the script, actually `/bin/sh'. -2002-07-12 Bernd Warken +2002-07-12 Bernd Warken ________________________________________________________________ * fixes for groffer 0.9.0 @@ -147,7 +374,7 @@ * TODO: fix entry `shoop' (not 'shopt'). -2002-06-28 Bernd Warken +2002-06-28 Bernd Warken ________________________________________________________________ * release of groffer 0.9.0 @@ -178,7 +405,7 @@ - Internally, map mode `auto' to '' to facilitate tests. - Fix auto mode sequence to: `ps,x,tty' as was intended. -2002-06-25 Bernd Warken +2002-06-25 Bernd Warken * groffer.sh: Fix `source' mode. @@ -186,7 +413,7 @@ * groffer.man: Fix some indentations. -2002-06-23 Bernd Warken +2002-06-23 Bernd Warken ________________________________________________________________ * release of groffer 0.8 @@ -305,7 +532,7 @@ Increase to 4m (we use `sh#' as the prompt). -2002-05-31 Bernd Warken +2002-05-31 Bernd Warken ________________________________________________________________ * release of groffer 0.7 @@ -341,7 +568,7 @@ - fix TP_header. -2002-05-28 Bernd Warken +2002-05-28 Bernd Warken ________________________________________________________________ * release of groffer 0.6 @@ -435,7 +662,7 @@ - The filespec parsers gets a function of its own do_manpage(). -2002-01-08 Bernd Warken +2002-01-08 Bernd Warken * groffer 0.5 (beta) released @@ -462,7 +689,7 @@ - Implement option `--dpi' for setting the resolution for the X viewer, which had already been documented in earlier versions. -2002-01-07 Bernd Warken +2002-01-07 Bernd Warken * groffer 0.4 (beta) released (as groff `contrib') @@ -501,7 +728,7 @@ * groffer.man (OptDef): Add missing backslashes. Update copyright. -2001-12-15 Bernd Warken +2001-12-15 Bernd Warken * groffer 0.3 (alpha) released (still stand-alone package). @@ -520,12 +747,12 @@ * Recognize the following filespecs as man-page parameters: man:name(section), man:name, name.section, name. -2001-12-03 Bernd Warken +2001-12-03 Bernd Warken * Stand-alone package for groffer 0.2 (alpha) created Files: groffer, groffer.man, Makefile, TODO, ChangeLog -2001-12-02 Bernd Warken +2001-12-02 Bernd Warken * groffer 0.2 (alpha) program released. @@ -545,7 +772,7 @@ * Code restructured and comments added. -2001-11-28 Bernd Warken +2001-11-28 Bernd Warken ***** groffview 0.1 (experimental) and groffview.man released (predecessor of groffer, shell script) @@ -555,3 +782,15 @@ * Search for man-pages based on $MANPATH * development of `groffview' shell script started + +2001-11-28 Bernd Warken + ________________________________________________________________ + License + + Copyright (C) 2001,2002,2003,2004 Free Software Foundation, Inc. + Written by Bernd Warken + Copying and distribution of this file, with or without + modification, are permitted provided the copyright notice and this + notice are preserved. + + This file is part of groffer, which is part of the groff project. diff --git a/contrib/groffer/Makefile.sub b/contrib/groffer/Makefile.sub index 333dedbd..5a549396 100644 --- a/contrib/groffer/Makefile.sub +++ b/contrib/groffer/Makefile.sub @@ -20,9 +20,9 @@ # License for more details. # You should have received a copy of the GNU General Public License -# along with groff; see the file COPYING. If not, write to the -# Free Software Foundation, 59 Temple Place - Suite 330, Boston, -# MA 02111-1307, USA. +# along with groff; see the files COPYING and LICENSE in the top +# directory of the groff source. If not, write to the Free Software +# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ######################################################################## diff --git a/contrib/groffer/README b/contrib/groffer/README index 413f49f0..a1040222 100644 --- a/contrib/groffer/README +++ b/contrib/groffer/README @@ -1,6 +1,7 @@ -The `groffer' program is the easiest way to read `groff' documents. -All input is sent to `grog' and then to `groff' such that no special -`groff' arguments must be determined. +The `groffer' program is the easiest way to read documents written in +some `groff' language, such as the `man pages', the manual pages in +many operating systems. All input is sent to `grog' and then to +`groff' such that no special `groff' arguments must be determined. `groffer' also has many built-in `man' functionalities to find and read the manual pages on UNIX and similar operating systems. It @@ -8,10 +9,10 @@ accepts the information from an installed `man' program, but tries to find a man path by itself if there isn't any. So far, `groffer' is a shell script. It should run on any POSIX or -Bourne style shell, but it runs the fastest if the `ash' shell is -installed on the system. This shell is found out and started -automatically. There are efforts to port part of the shell script to -C/C++ to increase the speed independent of the shell. +Bourne style shell, but it runs the fastest under the GNU `ash' shell. +If this shell is available, it is started automatically. There are +efforts to port part of the shell script to C/C++ to increase the +speed independent of the shell. For reporting bugs of `groffer', groff's free mailing list can be used. For a general discussion, the @@ -19,5 +20,25 @@ For reporting bugs of `groffer', groff's free mailing list directory of the `groff' source package for more details on this mailing list. -`groffer' is a `groff contrib' project that was written by Bernd -Warken . + +####### License + +Copyright (C) 2003,2004 Free Software Foundation, Inc. +Written by Bernd Warken + +This file is part of groffer, which is part of groff. + +groff is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +groff is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +License for more details. + +You should have received a copy of the GNU General Public License +along with groff; see the files COPYING and LICENSE in the top +directory of the groff source. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. diff --git a/contrib/groffer/README_SH b/contrib/groffer/README_SH new file mode 100644 index 00000000..db97f397 --- /dev/null +++ b/contrib/groffer/README_SH @@ -0,0 +1,219 @@ +Description of groffer.sh, the shell version of groffer + +Display groff files and man pages on X or tty, even when compressed. + + +Usage + +Input comes from either standard input or command line parameters that +represent names of exisiting roff files or standardized specifications +for searching man pages. All of these can be compressed in a format +that is decompressible by `gzip', including `.gz', `bz2', and `.Z'. + +The following displaying modes are available: +- Display formatted input with the X roff viewer `gxditview', +- with a Prostcript viewer, +- with a dvi viewer, +- with a web browser. +- Display formatted input in plain text mode. +- Run a pager on the formatted input in a text terminal (tty). +- Generate output for some groff device on stdout without a viewer. +- Output only the source code without any groff processing. +- Generate the troff intermediate output on standard output + without groff postprocessing. +By default, the program tries to display with `gxditview' as graphical +device, `tty' mode with a pager is tried as text display. + + +Several File Arguments + +So far, `groffer' bundles all filespec parameters into a single output +file in the same way as `groff'. The disadvantage of this is that all +file name arguments must have the same groff language. + +To change this, the option parsing must be revised for large parts. +It seems that this would create incompatibilities, so the actual +option strategy is kept. + + +Error Handling + +Error handling and exit behavior is complicated by the fact that +`exit' can only escape from the current shell; trouble occurs in +subshells. This was solved by sending kill signals, see $_PROCESS_ID +and error(). + + +Shell Compatibility + +This shell script is compatible to the both the GNU and the POSIX +shell and utilities. Care was taken to restrict the programming +technics used here in order to achieve POSIX compatibility as far +back as POSIX P1003.2 Draft 11.2 of September 1991. + +The only non-builtin used here is POSIX `sed'. This script was +tested under `bash', `ash', and `ksh'. The speed under `ash' is +more than double when compared to the larger shells. + +This script provides its own option parser. It is compatible to the +usual GNU style command line (option clusters, long options, mixing +of options and non-option file names), except that it is not +possible to abbreviate long option names. + +The mixing of options and file names can be prohibited by setting +the environment variable `$POSIXLY_CORRECT' to a non-empty value. +This enables the rather wicked POSIX behavior to terminate option +parsing when the first non-option command line argument is found. + + +Survey of Functions defined in groffer.sh + +The elements specified within paranthesis `(<>)' give hints to what +the arguments are meant to be; the argument names are irrelevant. +<>? 0 or 1 +<>* arbitrarily many such arguments, incl. none +<>+ one or more such arguments +<> exactly 1 + +A function that starts with an underscore `_' is an internal +function for some function. The internal functions are defined just +after their corresponding function; they are not mentioned in the +following. + +abort (text>*) +base_name (path) +catz () +clean_up () +diag (text>*) +dirname_append ( []) +dirname_chop () +do_filearg () +do_nothing () +echo2 (*) +echo2n (*) +error (*) +get_first_essential (*) +is_dir () +is_empty () +is_equal ( ) +is_file () +is_non_empty_file () +is_not_dir () +is_not_empty () +is_not_equal ( ) +is_not_file () +is_not_prog () +is_not_writable () +is_not_yes () +is_prog () +is_yes () +leave () +landmark () +list_append ( ...) +list_from_cmdline ( [...]) +list_from_split ( ) +list_get () +list_has ( ) +list_has_not ( ) +main_*(), see after the functions +man_do_filespec () +man_setup () +man_register_file ( [ [
]]) +man_search_section (
) +man_set() +manpath_add_lang( ) +manpath_add_system() +manpath_from_path () +normalize_args ( *) +path_chop () +path_clean () +path_contains ( ) +path_not_contains ( ) +path_split () +register_file () +register_title () +res ( ...) +reset () +save_stdin () +string_contains ( ) +string_not_contains ( ) +tmp_cat () +tmp_create (?) +to_tmp () +trap_clean () +trap_set () +usage () +version () +warning () +whatis () +where () + + +External non-groffer Environment Variables + +If these variables are exported in the script the `ash' shell coughs +when calling `groff' in `main_display()'. + +external system environment variables that are explicitly used +$DISPLAY: Presets the X display. +$LANG: For language specific man pages. +$LC_ALL: For language specific man pages. +$LC_MESSAGES: For language specific man pages. +$PAGER: Paging program for tty mode. +$PATH: Path for the programs called (: list). + +groffer native environment variables +$GROFFER_OPT preset options for groffer. + +all groff environment variables are used, see groff(1) +$GROFF_BIN_PATH: Path for all groff programs. +$GROFF_COMMAND_PREFIX: '' (normally) or 'g' (several troffs). +$GROFF_FONT_PATH: Path to non-default groff fonts. +$GROFF_TMAC_PATH: Path to non-default groff macro files. +$GROFF_TMPDIR: Directory for groff temporary files. +$GROFF_TYPESETTER: Preset default device. + +all GNU man environment variables are used, see man(1). +$MANOPT: Preset options for man pages. +$MANPATH: Search path for man pages (: list). +$MANROFFSEQ: Ignored because of grog guessing. +$MANSECT: Search man pages only in sections (:). +$SYSTEM: Man pages for different OS's (, list). + + +Object-oriented Functions + +The groffer script provides an object-oriented construction (OOP). In +object-oriented terminology, a type of object is called a `class'; a +function that handles objects from a class is named `method'. + +In the groffer script, the object is a variable name whose content is +the object's data. Methods are functions that have an object as first +argument. + +The basic functions for object handling are obj_*(). + +The class `list' represents an array structure, see list_*(). + + +####### License + +Copyright (C) 2003,2004 Free Software Foundation, Inc. +Written by Bernd Warken + +This file is part of groffer, which is part of groff. + +groff is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +groff is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +License for more details. + +You should have received a copy of the GNU General Public License +along with groff; see the files COPYING and LICENSE in the top +directory of the groff source. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. diff --git a/contrib/groffer/TODO b/contrib/groffer/TODO dissimilarity index 60% index 3aadb19e..5dd9b253 100644 --- a/contrib/groffer/TODO +++ b/contrib/groffer/TODO @@ -1,56 +1,54 @@ -# TODO file for `groffer' - -# File position: /contrib/groffer/TODO - -# Last update: 22 Jan 2003 - -# Copyright (C) 2001,2002,2003 Free Software Foundation, Inc. -# Written by Bernd Warken - -# This file is part of groff. - -# groff is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# groff is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -# License for more details. - -# You should have received a copy of the GNU General Public License -# along with groff; see the file COPYING. If not, write to the -# Free Software Foundation, 59 Temple Place - Suite 330, Boston, -# MA 02111-1307, USA. - -######################################################################## - -TODO - -Optimization: -- Optimize man path determination in manpath_add_lang_sys() for speed - by building-up the man path only by and by as far as necessary - (not trivial). -- To increase the running speed write part of the groffer shell script - in C/C++. - -Features: -- Revise option handling of `grog'. -- `gxditview' needs a complete shower. - -Revision: -- Should there be a native implementation for `--apropos'? -- Revise the `--all' feature to better reflect GNU man. -- The debug function stack is buggy (no effect on normal operation). -- The actual `groff' and `grog' do not support file arguments each -of which has a different macro package (except `man' and `doc'). So -`roffer' should create several display files for such arguments. - -Documentation: -- Improve the documentation of the search algorithm for man pages in - both the groffer script and the man page `groffer.man'. -- In `groff.man', add more documentation for parts that were taken over - from GNU `man'. -- The documentation in the headers for some function definitions in - `groffer.sh' needs to be updated. +TODO file for `groffer' + +File position: /contrib/groffer/TODO + + +####### TODO + +Optimization: +- Optimize man path determination in manpath_add_lang_sys() for speed + by building-up the man path only by and by as far as necessary + (not trivial). +- To increase the running speed write part of the groffer shell script + in C/C++. +- Split the groffer.sh shell script into several files for better tests + of the shell compatibility. + +Features: +- Revise option handling of `grog'. +- `gxditview' needs a complete shower. + +Revision: +- Revise the `--all' feature to better reflect GNU man. +- The debug function stack is buggy (no effect on normal operation). + +Documentation: +- Improve the documentation of the search algorithm for man pages in + both the groffer script and the man page `groffer.man'. +- In `groff.man', add more documentation for parts that were taken over + from GNU `man'. +- The documentation in the headers for some function definitions in + `groffer.sh' needs to be updated. + + +####### License + +Copyright (C) 2003,2004 Free Software Foundation, Inc. +Written by Bernd Warken + +This file is part of groffer, which is part of groff. + +groff is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +groff is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +License for more details. + +You should have received a copy of the GNU General Public License +along with groff; see the files COPYING and LICENSE in the top +directory of the groff source. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. diff --git a/contrib/groffer/groffer.man b/contrib/groffer/groffer.man index 6d76db41..b4fa31c4 100644 --- a/contrib/groffer/groffer.man +++ b/contrib/groffer/groffer.man @@ -15,31 +15,36 @@ groffer.1 - man page for groffer (section 1). Source file position: /contrib/groffer/groffer.man Installed position: $prefix/share/man/man1/groffer.1 -Version : groffer 0.9.2 -Last update : 17 Jul 2003 +Version : groffer 0.9.7 +Last update : 03 May 2004 -This file is part of groff, the GNU roff type-setting system. +Source file position: /contrib/groffer/groffer.man -Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. -Written by Bernd Warken +Copyright (C) 2001,2002,2004 Free Software Foundation, Inc. +Written by Bernd Warken -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.1 or -any later version published by the Free Software Foundation; with the -Invariant Sections being this .ig-section and AUTHORS, with no -Front-Cover Texts, and with no Back-Cover Texts. +This file is part of groff version @VERSION@. -A copy of the Free Documentation License is included as a file called -FDL in the main directory of the groff source package. +groff is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +groff is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +License for more details. + +You should have received a copy of the GNU General Public License +along with groff; see the files COPYING and LICENSE in the top +directory of the groff source. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. .. . .\" -------------------------------------------------------------------- .\" Setup .\" -------------------------------------------------------------------- . -.do nr groffer_C \n[.C] -.cp 0 -. .mso www.tmac . .if n \{\ @@ -280,7 +285,7 @@ FDL in the main directory of the groff source package. .c .c Arguments: .c
: prefix, resulted is preceded by this.
-.c   : separator between minux/opt pairs.
+.c   : separator between minus/opt pairs.
 .c   : postfix, is appended to the result.
 .c   : either `-' or `--' (font CB).
 .c   : a name for an option, empty allowed (font CB).
@@ -311,22 +316,23 @@ FDL in the main directory of the groff source package.
 .    if (\\n[@count] > 0) \
 .      as @res \f[CR]\\*[@sep]\"
 .    nr @count +1
-.    as @res \f[CB]\\$1\\$2\:\"           combine minus with option name
+.    as @res \f[CB]\\$1\\$2\:\"         combine minus with option name
 .    shift 2
 .  \}
 .  if (\\n[.$] >= 3) \
 .    Error .\\0: wrong arguments: \\$@
-.  c                                     all pairs are done
+.  c                                    all pairs are done
 .  ie (\\n[.$] == 0) \
 .    as @res \f[CR]\\*[@post]\"
 .  el \{\
-.    c                                   optional option argument
+.    c                                  optional option argument
 .    if !'\\$1'' \
 .      as @res \f[CR] \,\f[I]\\$1\"
 .    shift
-.    as @res \\f[CR]\\*[@post]\"         postfix
+.    c                                  postfix
+.    as @res \\f[CR]\\*[@post]\"
 .    if (\\n[.$] >= 1) \{\
-.      c                                 add punctuation
+.      c                                add punctuation
 .      as @res \f[\\n[@font]]\\$1\"
 .    \}
 .  \}
@@ -402,6 +408,14 @@ FDL in the main directory of the groff source package.
 .  Opt_alt -- "\\$1" "" "\\$2"
 ..
 .c --------------------------------------------------------------------
+.c .Opt_long_arg  ([  []])
+.c
+.c Print `--name=arg' somewhere in the text; optional punctuation.
+.c
+.de Opt_long_arg
+.  Opt_alt -- "\\$1=\\$2" "" "\\$3"
+..
+.c --------------------------------------------------------------------
 .c .Opt_[long]  ([ []])
 .c
 .c Print `--name' somewhere in the text; optional punctuation.
@@ -632,13 +646,16 @@ FDL in the main directory of the groff source package.
 .
 .ad l
 .Synopsis groffer
-.RI [ groffer_options ]
-.RI [ groff_options ]
+.RI [ option...\& ]
 .Opt_[--]
 .RI [ "filespec" "\*[Ellipsis]]"
 ./Synopsis
 .
 .Synopsis groffer
+.Opt_alt -- apropos -- apropos-data -- apropos-devel -- apropos-progs name
+./Synopsis
+.
+.Synopsis groffer
 .Opt_alt - h -- help
 ./Synopsis
 .
@@ -684,7 +701,10 @@ man\~page without further options.
 But the option handling has many possibilities for creating special
 behaviors.
 .
-These can be stored in a configuration file.
+This can be done in configuration files, with the shell environment
+variable
+.BR $GROFFER_OPT ,
+or on the command line.
 .
 .
 .P
@@ -699,15 +719,22 @@ html in www-mode, or several text modes in text terminals.
 .
 .
 .P
-Most options that must be named when running
+Most of the options that must be named when running
 .I groff
-are determined automatically because
-.I groffer
-internally calls the
+directly are determined automatically for
+.IR groffer ,
+due to the internal usage of the
 .BR grog (@MAN1EXT@)
 program.
 .
-But all parts can be controlled manually by supplying options.
+But all parts can also be controlled manually by arguments.
+.
+.
+.P
+Several file names can be specified on the command line arguments.
+.
+They are transformed into a single document in the normal way of
+.IR groff .
 .
 .
 .\" --------------------------------------------------------------------
@@ -715,165 +742,115 @@ But all parts can be controlled manually by supplying options.
 .\" --------------------------------------------------------------------
 .
 .TP
-.I groffer_options
-The following options determine and configure the display mode.
-.
-They were synchronized with the options of both
-.BR groff (@MAN1EXT@)
-and GNU
-.BR man (1).
-.
-If none of these options is used groffer tries to find a suitable
-display mode automatically.
+.I breaking options
+.RS
+.P
+.Opt_[alt] -- apropos name
+.Opt_[alt] -- apropos-data name
+.Opt_[alt] -- apropos-devel name
+.Opt_[alt] -- apropos-progs name
+.Opt_[alt] - h -- help
+.Opt_[alt] - v -- version
+.RE
 .
 .
+.TP
+.I groffer mode options
 .RS
-.
 .P
-.Opt_[alt] - Q -- source
-.Opt_[alt] - T -- device device
-.Opt_[alt] -- auto-modes mode1,mode2,\*[Ellipsis]
-.Opt_[alt] -- debug
+.Opt_[alt] -- auto
 .Opt_[alt] -- default
+.Opt_[alt] -- default-modes mode1,mode2,\*[Ellipsis]
 .Opt_[alt] -- dvi
 .Opt_[alt] -- dvi-viewer prog
 .Opt_[alt] -- groff
-.Opt_[alt] -- location
+.Opt_[alt] -- html
+.Opt_[alt] -- html-viewer prog
+.Opt_[alt] -- man
 .Opt_[alt] -- mode display_mode
-.Opt_[alt] -- pager program
+.Opt_[alt] -- no-man
 .Opt_[alt] -- pdf
 .Opt_[alt] -- pdf-viewer prog
 .Opt_[alt] -- ps
 .Opt_[alt] -- ps-viewer prog
-.Opt_[alt] -- shell
+.Opt_[alt] -- text
 .Opt_[alt] -- tty
+.Opt_[alt] -- tty-viewer prog
 .Opt_[alt] -- www
 .Opt_[alt] -- www-viewer prog
-.Opt_[alt] -- x
-.Opt_[alt] -- x-viewer prog
+.Opt_[alt] -- x -- X
+.Opt_[alt] -- x-viewer -- X-viewer prog
+.RE
 .
 .
+.TP
+.I development options
+.RS
 .P
-The following long options were adapted from the corresponding X
-Toolkit options.
+.Opt_[alt] -- debug
+.Opt_[alt] -- shell
+.RE
+.
 .
-Their single leading minus in X Toolkit was changed to a double minus
-for long options; see
-.BR X (1).
+.TP
+.I options related to groff
+.RS
+.P
+.Opt_[alt] - P -- postproc-arg opt_or_arg
+.Opt_[alt] - Q -- source
+.Opt_[alt] - T -- device device
+.Opt_[alt] - Z -- intermediate-output -- ditroff
+.P
+All further
+.I groff
+short options are accepted.
+.RE
 .
 .
+.TP
+.I X Window toolkit options
+.RS
 .P
-.Opt_[alt] -- bd
-.Opt_[alt] -- bg -- background
-.Opt_[alt] -- bw
-.Opt_[alt] -- display
-.Opt_[alt] -- fg -- foreground
-.Opt_[alt] -- ft -- font
+.Opt_[alt] -- bd pixels
+.Opt_[alt] -- bg -- background color
+.Opt_[alt] -- bw pixels
+.Opt_[alt] -- display X-display
+.Opt_[alt] -- fg -- foreground color
+.Opt_[alt] -- ft -- font font_name
 .Opt_[alt] -- geometry size_pos
 .Opt_[alt] -- resolution value
 .Opt_[alt] -- rv
 .Opt_[alt] -- title string
 .Opt_[alt] -- xrm X_resource
+.RE
 .
 .
-.P
-The following long options regulate whether and how
-.I man\~pages
-(UNIX manual pages) are searched.
-.
-They were constructed for
-.IR groffer ,
-but they are compatible with the long options of the
-.I GNU man
-program.
-.
-.
+.TP
+.I options from man
+.RS
 .P
 .Opt_[alt] -- all
 .Opt_[alt] -- ascii
-.Opt_[alt] -- apropos
 .Opt_[alt] -- ditroff
 .Opt_[alt] -- extension suffix
 .Opt_[alt] -- locale language
 .Opt_[alt] -- local-file
-.Opt_[alt] -- man
 .Opt_[alt] -- manpath dir1:dir2:\*[Ellipsis]
-.Opt_[alt] -- no-location
-.Opt_[alt] -- no-man
+.Opt_[alt] -- pager program
 .Opt_[alt] -- sections sec1:sec2:\*[Ellipsis]
 .Opt_[alt] -- systems sys1,sys2,\*[Ellipsis]
 .Opt_[alt] -- troff-device device
 .Opt_[alt] -- whatis
-.
-.
 .P
-The GNU
+Further long options of GNU
 .I man
-long options that are not mentioned are recognized, but they are just
-ignored because of alternative implementations.
-.
-The full set of long and short options of the GNU man program can be
-passed via the environment variable
-.Env_var $MANOPT ;
-see
-.BR man (1)
-if your system has GNU man installed.
-.
-.RE
-.
-.
-.TP
-.I groff_options
-Any combination of (short) options from the
-.BR groff (@MAN1EXT@)
-program is accepted; the options that are not explicitly handled by
-groffer are transparently passed to groff.
-.
-Due to the automatism in groffer, none of these groff options should
-be necessary, except for advanced usage.
-.
-.
-.RS
-.
-.P
-Because of the special outputting behavior of the groff options
-.Opt_short V,
-.Opt_short X,
-and
-.Opt_short Z,
-groffer was designed to be switched into
-.I groff
-mode by each of these options; in this mode, the groffer viewing
-features are disabled.
-.
-.P
-The other groff options do not switch the mode, but allow to customize
-the formatting process.
-.
-Useful groff formatting options include
-.Opt_short m
-(to add macro files that cannot be recognized by grog), and
-.Opt_short T
-(to specify an alternative device for the modes
-.I tty
-and
-.IR x ).
-.
+are accepted as well.
 .RE
 .
 .
 .TP
-.I filespec
-is one or more file names or templates for searching
-man\~pages, see
-.BR man (1).
-Each
-.I filespec
-can have one of the following forms.
-.
-.
+.I filespec argument
 .RS
-.
 .P
 No
 .I filespec
@@ -881,7 +858,7 @@ parameters means standard input.
 .
 .
 .TP 10m
-.Opt_short
+.Opt_short ""
 stands for standard input (can occur several times).
 .
 .
@@ -891,262 +868,190 @@ the path name of an existing file.
 .
 .
 .TP
+.BI man: name ( section )
+.TP+
+.IB name ( section )
+search the man\~page
 .I name
-if 
+in man\~section\~\c
+.IR section .
+.
+.
+.TP
+.BI man: name . s
+.TP+
+.IB name . s
+if
+.I s
+is a character in
+.BR [1-9on] ,
+search for a man\~page
 .I name
-is not an existing file search for the man\~page called in the lowest
-man\~section that has a document for this name.
+in man\~section
+.IR s .
 .
 .
 .TP
 .BI man: name
-search for a man\~page in the lowest man\~section that has a document
-called
+man\~page in the lowest man\~section that has
 .IR name .
 .
 .
 .TP
-.BI man: name . section
-.TP+
-.BI man: name ( section )
-.TP+
-.IB name ( section )
-.TP+
-.IB name . section
-each of these search the man\~page
+.I "s name"
+if
+.I s
+is a character in
+.BR [1-9on] ,
+search for a man\~page
 .I name
-in man\~section\~\c
-.IR section .
+in man\~section
+.IR s .
 .
 .
 .TP
-.I "std_section name"
-two arguments like in the
-.BR man (1)
-program to find man\~page
 .I name
-in man\~section
-.IR std_section .
-.
-In
-.IR groffer ,
-the argument
-.I std_section
-is a standard section name for man\~pages; these are a digit `1',
-\&\*[Ellipsis], `9', or the single letters `o' or `n'.
-.
-This should be used only with care.
+if 
+.I name
+is not an existing file search for the man\~page
+.I name
+in the lowest man\~section.
 .
 .RE
 .
 .
 .\" --------------------------------------------------------------------
-.SH "GROFFER OPTIONS"
+.SH "OPTION DETAILS"
 .\" --------------------------------------------------------------------
 .
-All short options of
+The
 .I groffer
-are compatible with the short options of
-.BR groff (@MAN1EXT@).
+program can usually be run with very few options.
 .
-Some of the
-.I groff
-options were given a special meaning within
-.IR groffer .
-.
-All other
-.I groff
-options are supported by
-.IR groffer ,
-but they are just transparently transferred to
-.I groff
-without any intervention.
+But for special purposes, it supports many options.
 .
-Therefore these transparent options are not documented here, but in
-.BR groff (@MAN1EXT@).
+These can be classified in 5 option classes.
 .
 .
 .P
+All short options of
+.I groffer
+are compatible with the short options of
+.BR groff (@MAN1EXT@).
+.
 All long options of
 .I groffer
 are compatible with the long options of
 .BR man (1).
 .
-Most of the
-.I man
-long options were implemented as native options into
-.IR groffer .
-.
-These options are documented in the following; the other
-.I man
-options are recognized, but ignored.
-.
-.
-.Opt_def - h
-Print usage message to standard error and exit.
-.
-.
-.Opt_def - Q
-Output the roff source code of the input files unprocessed.
-.
-This is the equivalent
-.Opt_long mode\~source .
-.
 .
-.Opt_def - T devname
-Switch to
-.Opt_long mode
-.IR devname .
-.
-The input is formatted and postprocessed using plain
-.I groff
-with
-.I devname
-as the output device.
-.
-The allowed device names are listed in
-.BR groff (@MAN1EXT@).
-.
-Note that this forces all device names that begin with the letter
-.I X
-to be displayed with
-.BR gxditview (@MAN1EXT@);
-all other device names generate output for the specified device; this
-is printed onto standard output without a pager.
-.
-.
-.Opt_def - v
-Print version information onto standard error.
-.
-.
-.Opt_def - V
-Switch into
-.I groff
-mode and format the input with groff option
-.Opt_short V ;
-this produces the groff calling pipe without formatting the input.
-.
-This an advanced option from
-.BR groff (@MAN1EXT@) ,
-only useful for debugging.
-.
-.
-.Opt_def - X
-Switch into
-.I groff
-mode and format the input with groff option
-.Opt_short X ;
-actually, this formats the input and displays it with
-.BR gxditview (@MAN1EXT@) .
-.
-This differs from groffer's mode
-.I x
-because groffer's viewer options are not used, but the viewer is
-configured like in groff with the groff option
-.Opt_short P .
-This option is inhereted from
-.BR groff (@MAN1EXT@) .
-.
-.
-.Opt_def - Z
-Switch into
-.I groff
-mode and format the input with groff option
-.Opt_short Z ;
-this produces the groff intermediate output without postprocessing; see
-.BR groff_out (@MAN1EXT@) .
-This an advanced option from
-.BR groff (@MAN1EXT@) ,
-useful for debugging.
+.\" --------------------------------------------------------------------
+.SS "groffer breaking Options"
+.\" --------------------------------------------------------------------
 .
+As soon as one of these options is found on the command line it is
+executed, printed to standard output, and the running
+.I groffer
+is terminated thereafter.
 .
-.Opt_def -- all
-In searching man pages, retrieve all suitable ones instead of only one.
+All other arguments are ignored.
 .
 .
-.Opt_def -- apropos
-Instead of displaying, start the `apropos' command for searching
-within man page descriptions; only kept for compatibility with `man'.
+.Opt_def -- apropos name
+Start the
+.BR apropos (1)
+command for searching within man page
+descriptions.
 .
+That slightly differs from the strange behavior of the
+.Opt_long apropos
+program of
+.BR man (1),
+which has no argument of its own, but takes the file arguments
+instead.
 .
-.Opt_def -- auto-modes mode1,mode2,\*[Ellipsis]
-Set the sequence of modes for default mode to the comma separated list
-given in the argument.
+Practically both concepts are compatible.
 .
 .
-.Opt_def -- background color
-This is equivalent to
-.Opt_long bg .
+.Opt_def -- apropos-data name
+Show only the
+.BR apropos (1)
+descriptions for data documents, in the
+.BR man (7)
+sections 4, 5, and 7.
 .
 .
-.Opt_def -- bd pixels
-Specifies the color of the border surrounding the viewer
-window.
+.Opt_def -- apropos-devel name
+Show only the
+.BR apropos (1)
+descriptions for development documents, in the
+.BR man (7)
+sections 2, 3, and 9.
 .
-This is an adaption of the X Toolkit option
-.Opt_short bd .
 .
-The argument is an X color name, see
-.BR (1)
-for details.
+.Opt_def -- apropos-progs name
+Show only the
+.BR apropos (1)
+descriptions for documents on programs, in the
+.BR man (7)
+sections 1, 6, and 8.
 .
 .
-.Opt_def -- bg color
-Set the background color of the viewer window.
+.Opt_def - h -- help
+Print a helping information with a short explanation of option sto
+standard output.
 .
-This is an adaption of the X Toolkit option
-.Opt_short bg .
 .
-The argument is an X color name, see
-.BR (1)
-for details.
+.Opt_def - v -- version
+Print version information to standard output.
 .
 .
-.Opt_def -- bw pixels
-Specifies the width in pixels of the border surrounding the viewer
-window (not available for all viewers).
+.\" --------------------------------------------------------------------
+.SS "groffer Mode Options"
+.\" --------------------------------------------------------------------
 .
-This is an adaption of the X Toolkit option
-.Opt_short bw .
+The display mode and the viewer programs are determined by these
+options.
 .
+If none of these mode and viewer options is specified
+.I groffer
+tries to find a suitable display mode automatically.
 .
-.Opt_def -- debug
-Print debugging information.
 .
-Actually, a function call stack is printed if an error occurs.
+.Opt_def -- auto
+Equivalent to
+.Opt_long_arg mode auto .
 .
 .
 .Opt_def -- default
 Reset all configuration from previously processed command line options
 to the default values.
 .
-This is useful to wipe out all effects of former options and restart
-option processing using only the rest of the command line.
-.
-.
-.Opt_def -- device
-Eqivalent to
-.Opt_short T .
+This is useful to wipe out all former options of the configuration, in
+.Env_var $GROFFER_OPT ,
+and restart option processing using only the rest of the command line.
 .
 .
-.Opt_def -- display X-display
-Set the X display on which the viewer program shall be started, see
-.BR X (1)
-for the syntax of the argument.
+.Opt_def -- default-modes mode1,mode2,\*[Ellipsis]
+Set the sequence of modes for
+.I auto mode
+to the comma separated list given in the argument.
 .
+See
+.Opt_long mode
+for details on modes.  Display in the default manner; actually, this
+means to try the modes
+.IR x ,
+.IR ps ,
+and
+.I tty
+in this sequence.
 .
-.Opt_def -- ditroff
-Eqivalent to
-.Opt_short Z .
-This is kept for compatibiliy with GNU
-.BR man (1).
 .
 .
 .Opt_def -- dvi
-Choose dvi mode; the formatted input is displayed with the  
-by default, the formatted input is displayed with the
-.BR xdvi (1)
-program.
+Equivalent to
+.Opt_long_arg mode dvi .
 .
 .
 .Opt_def -- dvi-viewer prog
@@ -1163,168 +1068,154 @@ and
 In each case, arguments can be provided additionally.
 .
 .
-.Opt_def -- extension suffix
-Restrict man\~page search to file names that have
-.I suffix
-appended to their section element.
+.Opt_def -- groff
+Equivalent to
+.Opt_long_arg mode groff .
 .
-For example, in the file name
-.I /usr/share/man/man3/terminfo.3ncurses.gz
-the man\~page extension is
-.IR ncurses .
 .
-Originates from GNU
-.IR man .
+.Opt_def -- html
+Equivalent to
+.Opt_long_arg mode html .
 .
 .
-.Opt_def -- foreground color
-This is equivalent to
-.Opt_long fg .
+.Opt_def -- html-viewer
+Equivalent to
+.Opt_long www-viewer .
 .
 .
-.Opt_def -- fg color
-Set the foreground color of the viewer window.
+.Opt_def -- mode value
 .
-This is an adaption of the X Toolkit option
-.Opt_long bg .
+Set the display mode.
 .
-The argument is an X color name, see
-.BR (1)
-for details.
+The following mode values are recognized:
 .
+.RS
 .
-.Opt_def -- font font_name
-This is equivalent to
-.Opt_long ft .
-.
-.
-.Opt_def -- ft font_name
-Set the font used by the viewer window.
-.
-This is an adaption of the X Toolkit option
-.Opt_short ft .
-.
-The argument is an X font name, see
-.BR (1)
-for details.
-.
-.
-.Opt_def -- geometry size_pos
-Set the geometry of the display window, that means its size and its
-starting position.
-.
-See
-.BR X (1)
-for details on the syntax of the argument.
-.
-If the actual display mode is not X then this option is ignored.
-.
-.
-.Opt_def -- groff
-Set
-.I groff
-mode.
-.
-Switch groffer to process the input like
-.BR groff (@MAN1EXT@).
-.
-This disables the groffer viewing features, all groffer viewing
-options are ignored.
-.
-.
-.Opt_def -- help
-Eqivalent to
-.Opt_short h .
-.
-.
-.Opt_def -- location
-Print the location of the retrieved files to standard error.
+.TP
+.Header_CB auto
+Select the automatic determination of the display mode.
 .
+The sequence of modes that are tried can be set with the
+.Opt_long default-modes
+option.
 .
-.Opt_def -- locale language
+Useful for restoring the default mode when a different mode was
+specified before.
 .
-Set the language for man pages.
 .
-This option originates from GNU
-.BR man (1).
+.TP
+.Header_CB dvi
+Display formatted input in a
+.I dvi
+viewer program.
 .
+By default, the formatted input is displayed with the
+.BR xdvi (1)
+program.
+.Opt_long dvi .
 .
-.Opt_def -- man
-Check the non-option command line arguments (filespecs) first on being
-man\~pages, then whether they represent an existing file.
 .
-By default, a filespec is first tested if it is an existing file.
+.TP
+.Header_CB groff
+After the file determination, switch
+.I groffer
+to process the input like
+.BR groff (@MAN1EXT@)
+would do .
 .
+This disables the
+.I groffer
+viewing features.
 .
-.Opt_def -- manpath "'dir1:dir2:\*[Ellipsis]'"
-Use the specified search path for retrieving man\~pages instead of the
-program defaults.
 .
-If the argument is set to the empty string "" the search for man\~page
-is disabled.
+.TP
+.Header_CB html
+Translate the input into html format and display the result in a web
+browser program.
 .
+By default, the existence of a sequence of standard web browsers is
+tested, starting with
+.BR konqueror (1)
+and
+.BR mozilla (1).
+The text html viewer is
+.BR lynx (1).
 .
-.Opt_def -- mode value
 .
-Set the display mode.
+.TP
+.Header_CB pdf
+Display formatted input in a
+.I PDF
+(Portable Document Format) viewer
+program.
 .
-The following mode values are recognized:
+By default, the input is formatted by groff using the Postscript
+device, then it is transformed into the PDF file format using
+.BR gs (1),
+and finally displayed either with the
+.BR xpdf (1)
+or the
+.BR acroread (1)
+program.
 .
+PDF has a big advantage because the text is displayed graphically and
+is searchable as well.
 .
-.RS
+But as the transformation takes a considerable amount of time, this
+mode is not suitable as a default device for the auto mode.
 .
 .
 .TP
-.Header_CB auto
-Display in the default manner; this actually means to try the modes
-.IR ps ,
-.IR x ,
-and
-.I tty
-in this sequence.
-.
-Useful for restoring default mode when a different mode was specified
-with
-.Env_var $GROFFER_OPT .
-.
+.Header_CB ps
+Display formatted input in a Postscript viewer program.
 .
-.TP
-.Header_CB dvi
-Display formatted input in a dvi viewer program; equivalent to
-.Opt_long dvi .
+By default, the formatted input is displayed with the
+.BR ghostview (@MAN1EXT@)
+program.
 .
 .
 .TP
-.Header_CB pdf
-Display formatted input in a PDF (Portable Document Format) viewer
-program; equivalent to
-.Opt_long pdf .
-.
+.Header_CB text
+Format in a
+.I groff
+text mode and write the result to standard output without a pager or
+viewer program.
 .
-.TP
-.Header_CB ps
-Display formatted input in a Postscript viewer program; equivalent to
-.Opt_long ps .
+The text device,
+.I latin1
+by default, can be chosen with option
+.Opt_short T .
 .
 .
 .TP
 .Header_CB tty
-Display formatted input in a text terminal; equivalent to
-.Opt_long tty .
+Format in a
+.I groff
+text mode and write the result to standard output using a text pager
+program, even when in X Window.
 .
 .
 .TP
 .Header_CB www
-Display formatted input in a internet browser program; equivalent to
+Equivalent to
 .Opt_long www .
 .
 .
 .TP
+.Header_CB X
+Display formatted input in a native roff viewer.
+.
+By default, the formatted input is displayed with the
+.BR gxditview (@MAN1EXT@)
+program, being distributed together with groff, or with
+.BR xditview (1),
+which is distributed as a standard X tool.
+.
+.
+.TP
 .Header_CB x
-Display formatted input in a native roff viewer such as
-.BR gxditview (@MAN1EXT@);
-equivalent to
-.Opt_long x .
+Equivalent to
+.Opt_long_arg mode X .
 .
 .
 .P
@@ -1352,49 +1243,16 @@ is assumed.
 .
 .TP
 .Header_CB source
-Display source code; same as
+Display the source code of the input without formatting; equivalent to
 .Opt_short Q .
 .
 .
 .RE
 .
 .
-.Opt_def -- no-location
-Do not display the location of retireved files; this resets a former
-call to
-.Opt_long location .
-.
-.
-.Opt_def -- no-man
-Do not check for man\~pages.
-.
-.
-.Opt_def -- pager
-Set the pager program in tty mode; default is
-.IR less .
-.
-.
 .Opt_def -- pdf
-Choose pdf mode (Portable Document Format).
-.
-By default, the input is formatted by groff using the Postscript
-device, then it is transformed into the PDF file format using
-.BR gs (1)
-(this is quite slow), and finally displayed either with the
-.BR xpdf (1)
-or the
-.BR acroread (1)
-program; this can be configured with option
-.Opt_long viewer-pdf .
-.
-PDF has a big advantage because the text is displayed graphically and
-is searchable nevertheless; but as thtransformation into pdf takes a
-considerable amount of time, the pdf mode is not suitable as a default
-device for the auto mode.
-.
-The only device that is compatible to this mode is
-.IR ps ,
-which is also the default when no device is specified.
+Equivalent to
+.Opt_long_arg mode pdf .
 .
 .
 .Opt_def -- pdf-viewer prog
@@ -1409,16 +1267,8 @@ In each case, arguments can be provided additionally.
 .
 .
 .Opt_def -- ps
-Choose ps mode (Postscript).
-.
-By default, the formatted input is displayed with the
-.BR ghostview (@MAN1EXT@)
-program; this can be configured with option
-.Opt_long viewer-ps .
-.
-The only device that is compatible to this mode is
-.IR ps ,
-which is also the default when no device is specified.
+Equivalent to
+.Opt_long_arg mode ps .
 .
 .
 .Opt_def -- ps-viewer prog
@@ -1438,99 +1288,25 @@ and
 In each case, arguments can be provided additionally.
 .
 .
-.Opt_def -- resolution value
-Set X resolution in dpi (dots per inch) in some viewer programs.
-.
-The only supported dpi values are
-.B 75
-and
-.BR 100 .
-This is an adaption of the X Toolkit option
-.Opt_short resolution .
-.
-.
-.Opt_def -- rv
-Reverse foreground and background color of the viewer window.
-.
-This is an adaption of the X Toolkit option
-.Opt_short rv .
-This feature is not available in all viewer programs.
-.
-.
-.Opt_def -- sections
-Restrict searching for man pages to the given
-.IR sections ,
-a colon-separated list.
-.
-.
-.Opt_def -- shell "shell_program"
-Specify the shell under which the groffer script should be run.
-.
-The script first tests whether this option is set (either within
-.Env_var $GROFF_OPT
-or as a command line option); if so, the script is rerun under the
-shell program specified with the option argument.
-.
-.
-.Opt_def -- source
+.Opt_def -- text
 Equivalent to
-.Opt_short Q .
-.
-.
-.Opt_def -- systems
-Search for man pages for the given operating systems; the argument
-.I systems
-is a comma-separated list.
-.
-.
-.Opt_def -- title "'some text'"
-Set the title for the viewer window.
-.
-This feature is not available in all viewer programs.
-.
-.
-.Opt_def -- to-postproc opt_or_arg
-Eqivalent to
-.Opt_short P .
+.Opt_long_arg mode text .
 .
 .
-.Opt_def -- troff-device
-Eqivalent to
-.Opt_short T .
-This option is only kept for compatibility with GNU
-.BR man (1).
+.Opt_def -- tty
+Equivalent to
+.Opt_long_arg mode tty .
 .
 .
-.Opt_def -- tty
+.Opt_def -- tty-viewer
 Choose tty display mode, that means displaying in a text pager even
 when in X; eqivalent to
-.Opt_long mode\~tty .
-.
-.
-.Opt_def -- version
-Eqivalent to
-.Opt_short v .
-.
-.
-.Opt_def -- whatis
-Instead of displaying the content, get the one-liner description from
-the retrieved man page files \[em] or say that it is not a man page.
-.
-.
-.Opt_def -- where
-Eqivalent to
-.Opt_long location .
+.Opt_long_arg mode tty .
 .
 .
 .Opt_def -- www
-Choose www mode (html), display in a web browser program, which can be
-specified with option
-.Opt_long www-viewer .
-By default, the existence of a sequence of standard web browsers is
-tested, starting with
-.BR mozilla (1)
-and
-.BR netscape (1)
+Equivalent to
+.Opt_long_arg mode www .
 .
 .
 .Opt_def -- www-viewer prog
@@ -1540,40 +1316,19 @@ mode.
 .
 Each program that accepts html input and allows the
 .BI file://localhost/ dir / file
-syntax on the command line is suitable; it can be the path name of an
-executable file or a program in
+syntax on the command line is suitable as viewer program; it can be
+the path name of an executable file or a program in
 .Env_var $PATH .
 .
 In each case, arguments can be provided additionally.
 .
 .
-.Opt_def -- x
-Choose
-.I x
-mode (view in X roff viewer).
-.
-By default, the formatted input is displayed with the
-.BR gxditview (@MAN1EXT@)
-program, being distributed together with groff, or with
-.BR xditview (1),
-which is distributed as a standard X tool.
-.
-This can be configured with option
-.Opt_long x-viewer .
-.
-The only devices (option
-.Opt_short T )
-that are compatible with this mode are
-.IR X75 ,
-.IR X100 ,
-.IR X75-12 ,
-.IR X100-12 ,
-and
-.I ps
-(the default device).
+.Opt_def - X -- X -- x
+Equivalent to
+.Opt_long_arg mode X .
 .
 .
-.Opt_def -- x-viewer prog
+.Opt_def -- X-viewer -- x-viewer prog
 Set the viewer program for
 .I x
 mode.
@@ -1594,80 +1349,699 @@ In each case, arguments can be provided additionally.
 Signals the end of option processing; all remaining arguments are
 interpreted as
 .I filespec
-parameters.
+parameters.
+.
+.
+.P
+Besides these,
+.I groffer
+accepts all arguments that are valid for the
+.BR groff (@MAN1EXT@)
+program.
+.
+All non-groffer options are sent unmodified via
+.I grog
+to
+.IR groff .
+.
+Postprocessors, macro packages, compatibility with classical
+.IR troff ,
+and much more can be manually specified.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "Options for Development"
+.\" --------------------------------------------------------------------
+.
+.Opt_def -- debug
+Print debugging information for development only.
+.
+Actually, a function call stack is printed if an error occurs.
+.
+.
+.Opt_def -- shell "shell_program"
+Specify the shell under which the groffer script should be run.
+.
+The script first tests whether this option is set (either by
+configuration, within
+.Env_var $GROFF_OPT
+or as a command line option); if so, the script is rerun under the
+shell program specified with the option argument.
+.
+.
+.Opt_def - Q -- source
+Output the roff source code of the input files without further
+processing.
+.
+This is the equivalent
+.Opt_long_arg mode source .
+.
+.
+.P
+Other useful debugging options are the
+.I groff
+options
+.Opt_short V
+and
+.Opt_short Z
+and option
+.Opt_long_arg mode groff .
+.
+.
+.\" --------------------------------------------------------------------
+.SH "Options related to groff"
+.\" --------------------------------------------------------------------
+.
+All short options of
+.I groffer
+are compatible with the short options of
+.BR groff (@MAN1EXT@).
+.
+The following of
+.I groff
+options have either an additional special meaning within
+.I groffer
+or make sense for normal usage.
+.
+.
+.P
+Because of the special outputting behavior of the
+.I groff
+options
+.Opt_short V
+and
+.Opt_short Z
+.I groffer
+was designed to be switched into
+.I groff
+mode by these; the
+.I groffer
+viewing features are disabled there.
+.
+The other
+.I groff
+options do not switch the mode, but allow to customize the formatting
+process.
+.
+.
+.Opt_def - a
+This generates an ascii approximation of output in text modes.
+.
+That could be important when the text pager has problems with control
+sequences.
+.
+.
+.Opt_def - m file
+Add
+.I file
+as a
+.I groff
+macro file.
+.
+This is useful in case it cannot be recognized automatically.
+.
+.
+.Opt_def - P opt_or_arg
+Send the argument
+.I opt_or_arg
+as an option or option argument to the actual
+.I groff
+postprocessor.
+.
+.
+.Opt_def - T -- device devname
+.
+This option determines
+.IR groff 's
+output device.
+.
+The most important devices are the text output devices for referring
+to the different character sets, such as
+.BR ascii ,
+.BR utf8 ,
+.BR latin1 ,
+and others.
+.
+Each of these arguments switches
+.I groffer
+into a text mode using this device, to
+.I mode tty
+if the actual mode is not a text mode.
+.
+The following
+.I devname
+arguments are mapped to the corresponding
+.I groffer
+.Opt_long_arg mode \fIdevname\fR
+option:
+.BR dvi ,
+.BR html ,
+and
+.BR ps .
+All
+.B X*
+arguments are mapped to mode
+.BR X .
+Each other
+.I devname
+argument switches to
+.I mode groff
+using this device.
+.
+.
+.Opt_def - V
+Switch into
+.I groff
+mode and show only the
+.I groff
+calling pipe without formatting the input.
+.
+This an advanced option from
+.BR groff (@MAN1EXT@) ,
+only useful for debugging.
+.
+.
+.Opt_def - X
+was made equivalent to
+.Opt_long_arg mode x ;
+this slightly enhances the facility of
+.IR groff 's
+option.
+.
+.
+.Opt_def - Z -- intermediate-output -- ditroff
+Switch into
+.I groff
+mode and format the input with
+.I groff
+intermediate output without postprocessing; see
+.BR groff_out (@MAN1EXT@).
+This is equivalent to option
+.Opt_long ditroff
+of
+.IR man ,
+which can be used as well.
+.
+.
+.P
+All other
+.I groff
+options are supported by
+.IR groffer ,
+but they are just transparently transferred to
+.I groff
+without any intervention.
+.
+The options that are not explicitly handled by
+.I groffer
+are transparently passed to
+.IR groff .
+.
+Therefore these transparent options are not documented here, but in
+.BR groff (@MAN1EXT@).
+Due to the automatism in
+.IR groffer ,
+none of these
+.I groff
+options should be needed, except for advanced usage.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "X Window toolkit Options"
+.\" --------------------------------------------------------------------
+.
+The following long options were adapted from the corresponding X
+Toolkit options.
+.
+.I groffer
+will pass them to the actual viewer program if it is an X Window
+program.
+.
+Otherwise these options are ignored.
+.
+.
+.P
+Unfortunately these options use the old style of a single minus for
+long options.
+.
+For
+.I groffer
+that was changed to the standard with using a double minus for long
+options, for example,
+.I groffer
+uses the option
+.Opt_long font
+for the
+.I X
+option
+.Opt_short font .
+.
+.
+.P
+See
+.BR X (1),
+.BR X (7),
+and the documentation on the X toolkit options for more details on
+these options and their arguments.
+.
+.
+.Opt_def -- background color
+Set the background color of the viewer window.
+.
+.
+.Opt_def -- bd pixels
+Specifies the color of the border surrounding the viewer window.
+.
+.
+.Opt_def -- bg color
+This is equivalent to
+.Opt_long background .
+.
+.
+.Opt_def -- bw pixels
+Specifies the width in pixels of the border surrounding the viewer
+window.
+.
+.
+.Opt_def -- display X-display
+Set the X display on which the viewer program shall be started, see the
+.I X Window
+documentation for the syntax of the argument.
+.
+.
+.Opt_def -- foreground color
+Set the foreground color of the viewer window.
+.
+.
+.Opt_def -- fg color
+This is equivalent to
+.Opt_short foreground .
+.
+.
+.Opt_def -- font font_name
+Set the font used by the viewer window.
+.
+The argument is an X font name.
+.
+.
+.Opt_def -- ft font_name
+This is equivalent to
+.Opt_long ft .
+.
+.
+.Opt_def -- geometry size_pos
+Set the geometry of the display window, that means its size and its
+starting position.
+.
+See
+.BR X (7)
+for the syntax of the argument.
+.
+.
+.Opt_def -- resolution value
+Set X resolution in dpi (dots per inch) in some viewer programs.
+.
+The only supported dpi values are
+.B 75
+and
+.BR 100 .
+.
+Actually, the default resolution for
+.I groffer
+is set to
+.BR 75 .
+.
+.
+.Opt_def -- rv
+Reverse foreground and background color of the viewer window.
+.
+.
+.Opt_def -- title "'some text'"
+Set the title for the viewer window.
+.
+.
+.Opt_def -- xrm "'resource'"
+Set X resource.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Options from man"
+.\" --------------------------------------------------------------------
+.
+The long options of
+.I groffer
+were synchronized with the long options of
+.IR GNU man .
+.
+All long options of
+.I GNU man
+are recognized, but not all of these options are important to
+.IR groffer ,
+so most of them are just ignored.
+.
+.
+.P
+The following two options were added by
+.I groffer
+for choosing whether the file name arguments are interpreted as names
+for local files or as a search pattern for man pages.
+.
+The default is looking up for local files.
+.
+.
+.Opt_def -- man
+Check the non-option command line arguments (filespecs) first on being
+man\~pages, then whether they represent an existing file.
+.
+By default, a filespec is first tested whether it is an existing file.
+.
+.
+.Opt_def -- no-man -- local-file
+Do not check for man\~pages.
+.
+.Opt_long local-file
+is the corresponding
+.I man
+option.
+.
+.
+.P
+In the following, the
+.I man
+options that have a special meaning for
+.I groffer
+are documented.
+.
+.
+.P
+The full set of long and short options of the
+.I GNU man
+program can be passed via the environment variable
+.Env_var $MANOPT ;
+see
+.BR man (1)
+if your system has
+.I GNU man
+installed.
+.
+.
+.Opt_def -- all
+In searching man\~pages, retrieve all suitable documents instead of
+only one.
+.
+.
+.Opt_def - 7 -- ascii
+In text modes, display ASCII translation of special characters.
+.
+.
+.Opt_def -- ditroff
+Eqivalent to
+.I groffer
+.Opt_short Z .
+.
+.
+.Opt_def -- extension suffix
+Restrict man\~page search to file names that have
+.I suffix
+appended to their section element.
+.
+For example, in the file name
+.I /usr/share/man/man3/terminfo.3ncurses.gz
+the man\~page extension is
+.IR ncurses .
+.
+.
+.Opt_def -- locale language
+.
+Set the language for man pages.
+.
+This has the same effect, but overwrites
+.Env_var $LANG
+.
+.
+.Opt_def -- location
+Print the location of the retrieved files to standard error.
+.
+.
+.Opt_def -- no-location
+Do not display the location of retrieved files; this resets a former
+call to
+.Opt_long location .
+.
+This was added by
+.IR groffer .
+.
+.
+.Opt_def -- manpath "'dir1:dir2:\*[Ellipsis]'"
+Use the specified search path for retrieving man\~pages instead of the
+program defaults.
+.
+If the argument is set to the empty string "" the search for man\~page
+is disabled.
+.
+.
+.Opt_def -- pager
+Set the pager program in tty mode; default is
+.IR less .
+This is equivalent to
+.Opt_long tty-viewer .
+.
+.
+.Opt_def -- sections "'sec1:sec2:\*[Ellipsis]'"
+Restrict searching for man\~pages to the given
+.IR sections ,
+a colon-separated list.
+.
+.
+.Opt_def -- systems "'sys1,sys2,\*[Ellipsis]'"
+Search for man pages for the given operating systems; the argument
+.I systems
+is a comma-separated list.
+.
+.
+.Opt_def -- whatis
+Instead of displaying the content, get the one-liner description from
+the retrieved man\~page files \[em] or say that it is not a man\~page.
+.
+.
+.Opt_def -- where
+Eqivalent to
+.Opt_long location .
+.
+.
+.P
+Additionally, the following short option of
+.I man
+is supported as well.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Filespec Arguments"
+.\" --------------------------------------------------------------------
+.
+A
+.I filespec
+parameter is an argument meaning an input source, such as a file name
+or template for searching man\~pages.
+.
+These input sources are collected and composed into a single output
+file.
+.
+Each of these
+.I filespec
+parameters can have one of the following forms.
+.
+.
+.P
+No
+.I filespec
+parameters means that
+.I groffer
+waits for standard input.
+.
+The minus option
+.Opt_short ""
+stands for standard input, too, but can occur several times.
+.
+Next
+.I filespec
+is tested whether it is the path name of an existing file.
+.
+Otherwise it is assumed as a searching pattern for a man\~page.
+.
+.
+.P
+On each system, the man pages are sorted according to their content
+into several sections.
+.
+The
+.I classical man sections
+have a single-character name, either are a digit from
+.B 1
+to
+.B 9
+or one of the characters
+.B n
+or
+.BR o .
+.
+In the following, a stand-alone character
+.I s
+means this scheme.
+.
+.
+.P
+The internal precedence of
+.I man
+for searching man pages with the same name within several sections
+goes according to the classical single-character sequence.
+.
+On some systems, this single character can be extended by a following
+string.
+.
+But the special
+.I groffer
+man page facility is based on the classical single character sections.
+.
+.
+.P
+.BI man: name ( section )
+and
+.IB name ( section )
+search the man\~page
+.I name
+in man\~section\~\c
+.IR section ,
+where
+.I section
+can be any string, but it must exist in the
+.I man
+system.
+.
+.
+.P
+Next some patterns based on the
+.I classical man sections
+were constructed.
+.
+.BI man: name . s
+and
+.IB name . s
+search for a man\~page
+.I name
+in man\~section
+.I s
+if
+.I s
+is a
+.I classical man section
+mentioned above.
+.
+Otherwise search for a man\~page named
+.IR name.s
+in the lowest
+.I man
+section.
+.
+.
+.P
+Now
+.BI man: name
+searches for a man\~page in the lowest man\~section that has a
+document called
+.IR name .
+.
+.
+.P
+The pattern
+.I "s name"
+originates from a strange argument parsing of the
+.I man
+program.
+.
+If
+.I s
+is a
+.I classical man section
+interpret it as a search for a man\~page called
+.I name
+in man\~section
+.IR s ,
+otherwise interpret
+.I s
+as a file argument and
+.I name
+as another
+.I filespec
+argument.
 .
 .
 .P
-Besides these, groffer accepts all arguments that are valid for the
-.BR groff (@MAN1EXT@)
-program.
+We are left with the argument
+.I name
+which is not an existing file.
 .
-All non-groffer options are sent unmodified via grog to groff.
+So this searches for the man\~page called
+.I name
+in the lowest man\~section that has a document for this name.
 .
-Postprocessors, macro packages, compatibility with classical troff,
-and much more can be manually specified.
 .
+.P
+Several file name arguments can be supplied.
 .
-.\" --------------------------------------------------------------------
-.SH "OUTPUT MODES"
-.\" --------------------------------------------------------------------
+They are mixed by
+.I groff
+into a single document.
 .
-By default, the groffer program formats the input and then
-automatically chooses a suitable display mode, but the user can also
-choose between the following modes:
+Note that the set of option arguments must fit to all of these file
+arguments.
 .
-.Topic
-graphically display the formatted input with an X window program,
-including
+So they should have at least the same style of the
+.I groff
+language.
 .
-.RS
-.Topic
-with X window roff viewers such as
-.BR gxditview (@MAN1EXT@)
-.RI ( x
-mode),
 .
-.Topic
-in a dvi viewer program
-.RI ( dvi
-mode),
+.\" --------------------------------------------------------------------
+.SH "OUTPUT MODES"
+.\" --------------------------------------------------------------------
 .
-.Topic
-in a Postscript viewer
-.RI ( ps
-mode),
+By default, the
+.I groffer
+program collects all input into a single file, formats it with the
+.I groff
+program for a certain device, and then chooses a suitable viewer
+program.
 .
-.Topic
-in a PDF viewer
-.RI ( pdf
-mode),
+The device and viewer process in
+.I groffer
+is called a
+.IR mode .
 .
-.Topic
-in a web browser
-.RI ( www
-mode),
-.RE
+The mode and viewer of a running
+.I groffer
+program is selected automatically, but the user can also choose it
+with options.
 .
-.Topic
-display formatted input in a pager on the text terminal
-.RI ( tty
-mode),
 .
-.Topic
-run groffer like groff, but with decompression and man\~page searching
-.RI ( groff
-mode); this includes things like generating the groff intermediate
-output.
+The modes are selected by option the arguments of
+.Opt_long_arg mode \fIanymode .
+Additionally, each of this argument can be specified as an option of
+its own, such as
+.Opt_long \fIanymode .
+Most of these modes have a viewer program, which can be chosen by an
+option that is constructed like
+.Opt_long \fIanymode\fR-viewer .
 .
-.Topic
-stream the unformatted source code of the input onto standard output
-.RI ( source
-mode),
+.
+.P
+Several different modes are offered, graphical X modes, text modes,
+and some direct
+.I groff
+modes for debugging and development.
 .
 .
 .P
-By
-.IR default ,
+By default,
 .I groffer
 first tries whether
 .B x
@@ -1678,7 +2052,7 @@ mode, and finally
 mode.
 .
 This mode testing sequence for
-.B default
+.B auto
 mode can be changed by specifying a comma separated list of modes
 with the option
 .Opt_long default\-modes.
@@ -1693,47 +2067,59 @@ active in every mode.
 .SS "Graphical Display Modes"
 .\" --------------------------------------------------------------------
 .
-The graphical display modes work only in the X window environment (or
+The graphical display modes work only in the X Window environment (or
 similar implementations within other windowing environments).
 .
 The environment variable
 .Env_var $DISPLAY
-or the option
+and the option
 .Opt_long display
-are used for specifying the X display to be used; if neither is
-specified, groffer assumes that no X is running.
+are used for specifying the X display to be used.
+.
+If neither is given,
+.I groffer
+assumes that no X and changes to one text mode.
+.
+You can change this automatic behavior by the option
+.Opt_long default\-modes .
 .
 .
 .P
-A certain graphical display mode can be selected by one of the options
-.Opt_long dvi ,
-.Opt_long pdf ,
-.Opt_long ps ,
-.Opt_short X ,
-and
-.Opt_long www .
+Known viewers for the graphical display modes and their standard X
+Window viewer progams are
 .
-By default, some graphical modes are tried first.  If none succeeds
-groffer switches to
-.B tty
-mode.
+.Topic
+X Window roff viewers such as
+.BR gxditview (@MAN1EXT@)
+or
+.BR xditview (1)
+.RI (in x
+or
+.I X
+mode),
+.
+.Topic
+in a Postscript viewer
+.RI ( ps
+mode),
 .
+.Topic
+in a dvi viewer program
+.RI ( dvi
+mode),
 .
-.P
-The graphical modes can be customized by options that were named
-according to the resource options in the
-.BR X (1)
-Toolkit but using a leading double minus instead of the single minus
-used by X.
+.Topic
+in a PDF viewer
+.RI ( pdf
+mode),
 .
-These include
-.Opt_long background ,
-.Opt_long foreground ,
-.Opt_long geometry ,
-.Opt_long resolution ,
-.Opt_long title ,
-.Opt_long xrm ,
-etc.
+.Topic
+in a web browser
+.RI ( html
+or
+.I www
+mode),
+.RE
 .
 .
 .P
@@ -1743,93 +2129,118 @@ mode has a major advantage \[em] it is the only graphical diplay mode
 that allows to search for text within the viewer; this can be a really
 important feature.
 .
-Unfortunately, it takes a long time to transform the input into the
-PDF format, so it was not chosen as the major mode.
+Unfortunately, it takes some time to transform the input into the PDF
+format, so it was not chosen as the major mode.
 .
-You can change this by the options
-.Opt_long pdf
-and
-.Opt_long auto\-modes .
+.
+.P
+These graphical viewers can be customized by options of the X Window
+Toolkit.
+.
+But the
+.I groffer
+options use a leading double minus instead of the single minus used by
+the X Window Toolkit.
 .
 .
 .\" --------------------------------------------------------------------
 .SS "Text mode"
 .\" --------------------------------------------------------------------
 .
+There are to modes for text output, mode
+.I text
+for plain output without a pager and mode
+.I tty
+for a text output on a text terminal using some pager program.
+.
+.
+.P
 If the variable
 .Env_var $DISPLAY
-is not set or empty, groffer assumes that it should produce output on
-a text terminal.
-.
-This mode can also be forced by option
-.Opt_long tty .
+is not set or empty, groffer assumes that it should use
+.I tty
+mode.
 .
 .
 .P
 In the actual implementation, the groff output device
 .I latin1
-is chosen and the processed output is piped into a pager program.
+is chosen for text modes.
 .
 This can be changed by specifying option
-.Opt_long tty-device .
+.Opt_short T
+or
+.Opt_long device .
 .
 .
 .P
-The pager to be used can be specified by option
+The pager to be used can be specified by one of the options
 .Opt_long pager
+and
+.Opt_long tty-viewer ,
 or by the environment variable
 .Env_var $PAGER .
-If this is not set or empty the
+If all of this is not used the
 .BR less (1)
-program is used as the default pager.
+program with the option
+.Opt_short r
+for correctly displaying control sequences is used as the default
+pager.
 .
 .
 .\" --------------------------------------------------------------------
-.SS "Non-displaying Modes"
+.SS "Special Modes for Debugging and Development"
 .\" --------------------------------------------------------------------
 .
-There are some special modes that do not display the formatted output
-in a viewer program.
-.
-These modes are regarded as advanced, they are useful for debugging
-purposes.
-.
+These modes use the
+.I groffer
+file determination and decompression.
 .
-.TP
-.I source mode
-Instead of displaying the formatted output, it is also possible to
-have the roff source code streamed onto the standard output.
+This is combined into a single input file that is fed directly into
+.I groff
+with different strategy without the
+.I groffer
+viewing facilities.
 .
-This mode must be requested by one of the options
-.Opt_short Q
-or
-.Opt_long source .
+These modes are regarded as advanced, they are useful for debugging
+and development purposes.
 .
 .
-.TP
-.I groff mode
-This mode disables the groffer viewing facilities.
+.P
+The
+.I source
+mode with just displays the generated input.
 .
-The input is handled as usual with decompression and man\~page
-searching, but then it is passed to groff using only the options
-provided by groff.
+The
+.I groff
+mode passes the input to
+.I groff
+using only some suitable options provided to
+.IR groffer .
 .
 This enables the user to save the generated output into a file or pipe
 it into another program.
 .
+.
+.P
+In
+.I groff
+mode, the option
+.Opt_short Z
+disables post-processing, thus producing the
+.I groff intermediate
+.IR output .
+.
 In this mode, the input is formatted, but not postprocessed; see
 .BR groff_out (@MAN5EXT@)
 for details.
 .
-This mode is activated automatically by the three groff options
-.Opt_short V
-(print roff pipe, no formatting),
-.Opt_short X
-(display with gxditview in groff's native way, using
-.Opt_short P
-for customization), and
-.Opt_short Z
-(disable post-processing, thus producing the groff intermediate output).
+.
+.P
+All
+.I groff
+short options are supported by
+.IR groffer .
 .
 .
 .\" --------------------------------------------------------------------
@@ -1920,15 +2331,17 @@ If this is empty, the program tries to read it from the environment
 variable
 .Env_var $MANOPT .
 .
+.
 .Topic
-If this does not work, the
-.BR manpath (1)
-program for determining a path of man directories is tried.
+If this does not work a reasonable default path from
+.Env_var $PATH
+is searched for man\~pages.
 .
 .
 .Topic
-If this does not work a reasonable default path is searched for
-man\~pages.
+If this does not work, the
+.BR manpath (1)
+program for determining a path of man directories is tried.
 .
 .
 .P
@@ -2105,7 +2518,7 @@ Store options for a run of groffer.
 The options specified in this variable are overridden by the options
 given on the command line.
 .
-The content of this variable is run through the shell builitin `eval';
+The content of this variable is run through the shell builtin `eval';
 so arguments containing white-space or special shell characters should
 be quoted.
 .
@@ -2125,7 +2538,7 @@ The following variables have a special meaning for groffer.
 .
 .TP
 .Env_var $DISPLAY
-If this variable is set this indicates that the X window system is
+If this variable is set this indicates that the X Window system is
 running.
 .
 Testing this variable decides on whether graphical or text output is
@@ -2301,13 +2714,13 @@ determined automatically.
 .SH "CONFIGURATION FILES"
 .\" --------------------------------------------------------------------
 .
-The groffer program can be preconfigured by two configuration files.
+The
+.I groffer
+program can be preconfigured by two configuration files.
 .
-Both of them are shell scripts that are called at the beginning of
-groffer using the `\c
-.CB .\~\c
-.IR filename '
-syntax.
+This configuration can be overridden at each program start by command
+line options or by the environment variable
+.Env_var $GROFFER_OPT .
 .
 .
 .TP
@@ -2326,19 +2739,39 @@ enable overriding by the user.
 .
 .
 .P
+Their lines either start with a minus character or are shell commands.
+.
+Arbitrary spaces are allowed at the beginning, they are just ignored.
+.
+The lines with the beginning minus are appended to the existing value
+of $GROFFER_OPT.
+.
+This easily allows to set general
+.I groffer
+options that are used with any call of
+.IR groffer .
+.
+.
+.P
+After the transformation of the minus lines the emerging shell scripts
+that are called by
+.I groffer
+using the `\c
+.CB .\~\c
+.IR filename '
+syntax.
+.
+.
+.P
 It makes sense to use these configuration files for the following
 tasks:
 .
 .Topic
-Preset environment variables recognized by groffer; preferably a
-variable should only be set when it is unset in order not to override
-a user-provided value.
+Preset command line options by writing them into lines starting with a
+minus sign.
 .
 .Topic
-Preset command line options by prepending them to
-.Env_var $GROFFER_OPT ;
-prepending should be preferred to appending and setting in order not
-to delete the environment variable provided by the 
+Preset environment variables recognized by groffer.
 .
 .Topic
 Write a function for calling a viewer program for a special
@@ -2354,57 +2787,81 @@ in order to be recognized by groffer.
 .
 .
 .P
-As an example, consider the following configuration file.
+As an example, consider the following configuration file in
+~/.groff/groffer.conf, say.
 .
 .P
 .ft CR
 .nh
 .nf
-#! /bin/sh
-# ~/.groff/groffer.conf
+# groffer configuration file
+#
+# groffer options that are used in each call of groffer
+--resolution=100
+--foreground=DarkBlue
+--x-viewer 'gxditview -geometry 850x800'
+#
+# some shell commands
 if test "$DISPLAY" = ""; then
-  DISPLAY='localhost:0.0';
-fi;
-GROFF_OPT="--resolution=100 $GROFF_OPT";
-gxditview()
-{
-  /usr/local/bin/gxditview --fg DarkBlue "$@";
-}
-GROFF_OPT="--x-viewer gxditview $GROFF_OPT";
+  DISPLAY='localhost:0.0'
+fi
+date >>~/mygroffer.log
 .fi
 .hy
 .ft
 .
 .
 .P
+This configuration sets three
+.I groffer
+options and runs two shell commands.
+.
 This has the following effects:
+.
+.
 .Topic
-allows to start groffer in a graphical mode (here on first running X
-display by
-.IR localhost:0.0 )
-even from a text terminal (empty
-.Env_var $DISPLAY );
+Lines starting with a 
+.B #
+character
+are 
+.
+.
 .Topic
-all graphical modes use a resolution of
-.I 100 dpi
-where applicable;
+Use a resolution of
+.B 100 dpi
+and a text color of
+.B DarkBlue
+in all viewers that support this.
+.
+.
 .Topic
-the
+Force
 .BR gxditview (@MAN1EXT@)
-program is told to use
-.I DarkBlue
-as the text color by defining a shell function with the program's name
+as the X-mode viewer using the geometry option for setting the width
+to
+.B 850 dpi
+and the height to
+.B 800
+.BR dpi .
+.
+.
 .Topic
-force
-.I gxditview
-to be used in X mode by option
-.Opt_long x\­viewer .
+The variable
+.Env_var $DISPLAY
+is set to
+.IR localhost:0.0
+which allows to start
+.I groffer
+in the standard X display, even when the program is called from a text
+console.
 .
 .
-.P
-These configurations can be overridden by command line options and by
-environment variable
-.Env_var $GROFFER_OPT .
+.Topic
+Just for fun, the date of each
+.I groffer
+start is written to the file
+.B mygroffer.log
+in the home directory.
 .
 .
 .\" --------------------------------------------------------------------
@@ -2425,19 +2882,64 @@ Decompress, format and display the compressed file
 .I meintro.ms.gz
 in the directory
 .IR /usr/local/share/doc/groff ,
-using a default graphical viewer when in X window, or the
+using
+.I gxditview
+as graphical viewer when in X Window, or the
 .BR less (1)
 pager program when not in X.
 .
 .
 .TP
-.Shell_cmd "groffer\~groff.7\~groff\~\[cq]troff(1)\[cq]\~man:roff"
+.Shell_cmd "groffer\~groff"
+If the file
+.I ./groff
+exists use it as input.
+.
+Otherwise interpret the argument as a search for the man\~page named
+.I groff
+in the smallest possible man\~section, being secion 1 in this case.
+.
+.
+.TP
+.Shell_cmd "groffer\~man:groff"
+search for the man\~page of
+.I groff
+even when the file
+.I ./groff
+exists.
+.
+.
+.TP
+.Shell_cmd "groffer\~groff.7"
+.TP+
+.Shell_cmd "groffer\~7\~groff"
+search the man\~page of
+.I groff
+in man\~section
+.BR 7 .
+This section search works only for a digit or a single character from
+a small set.
+.
+.
+.TP
+.Shell_cmd "groffer\~fb.modes"
+If the file
+.I ./fb.modes
+does not exist interpret this as a search for the man\~page of
+.IR fb.modes .
+As the extension
+.I modes
+is not a single character in classical section style the argument is
+not split to a search for
+.IR fb .
+.
+.
+.TP
+.Shell_cmd "groffer\~groff\~\[cq]troff(1)\[cq]\~man:roff"
 .
 The arguments that are not existing files are looked-up as the
 following man\~pages:
 .I groff
-(in man\~section\~7),
-.I groff
 (automatic search, should be found in man\~section\~1),
 .I troff
 (in section\~1),
@@ -2458,16 +2960,18 @@ The formatted files are concatenated and displayed in one piece.
 .
 .
 .TP
-.Shell_cmd "LANG=de\~groffer\~--man\~--www\~--www-viever=netscape\~ls"
+.Shell_cmd "LANG=de\~groffer\~--man\~--www\~--www-viever=mozilla\~ls"
 .
 Retrieve the German man\~page (language
 .IR de )
 for the
 .B ls
-program (the English version is used if there is no German version),
-decompress it, format it into the html format (www mode) and view the
-result in the default web browser
-.I netscape .
+program, decompress it, format it to
+.I html
+format
+.RI ( www
+mode) and view the result in the web browser
+.I galeon .
 The option
 .Opt_long man
 guarantees that the man\~page is retrieved, even when a local file
@@ -2476,28 +2980,25 @@ exists in the actual directory.
 .
 .
 .TP
-.Shell_cmd "groffer\~-Q\~'man:roff(7)'"
+.Shell_cmd "groffer\~--source\~'man:roff(7)'"
 .
 Get the man\~page called
 .I roff
-in man\~section 7 and print its unformatted content (source code
-because of option
-.Opt_short Q )
-on standard output.
+in man\~section 7, decompress it, and print its unformatted content,
+its source code.
 .
 .
 .TP
 .Shell_cmd "cat\~file.gz\~|\~groffer\~-Z\~-mfoo"
 .
-Decompress the standard input, switch to
+Decompress the standard input, send this to
 .I groff
-using macro package
+intermediate mode without post-processing (groff option
+.Opt_short Z ),
+using macro package by
 .I foo
 (groff option
-.Opt_short m ) in non-postprocessing mode (groff option
-.Opt_short Z );
-this produces the groff intermediate output, see
-.BR groff_out (@MAN7EXT@).
+.Opt_short m ) .
 .
 .
 .TP
@@ -2515,16 +3016,27 @@ bold font, using color yellow on red background.
 .
 The
 .B groffer
-shell script is compatible to both POSIX and GNU.
+shell script is compatible with both GNU and POSIX.
 .
 POSIX compatibility refers to
 .B IEEE P1003.2/D11.2
-of September 1991, a very early version of this standard.
+of September 1991, a very early version of the POSIX standard that is
+still freely available in the internet.
+.
+Unfortunately, this version of the standard has `local' for shell
+function variables removed.
+.
+As `local' is needed for serious programming this temporary POSIX
+deprecation was ignored.
+.
+.
+.P
+Most GNU shells are compatible with this interpretation of POSIX, but
+provide much more facilities.
 .
-The script uses only a quite restricted set of shell language elements
-and shell builtins, common to all POSIX versions; the only external
-program used is `sed', again only the most basic POSIX features of
-`sed' are used.
+Nevertheless this script uses only a restricted set of shell language
+elements and shell builtins, such that it can be run on `ash', a GNU
+shell that is quite fast, but has a slightly limited shell language.
 .
 The groffer script should work on most actual free and commercial
 operating systems.
@@ -2538,12 +3050,11 @@ and a large set of special characters.
 .
 .P
 The groffer shell script was tested with the following common
-implementations of the POSIX shell:
+implementations of the GNU shells:
 .BR ash (1),
-.BR bash (1),
-.BR ksh (1),
 POSIX
 .BR sh (1),
+.BR bash (1),
 and others.
 .
 Free POSIX compatible shells and shell utilities for most operating
@@ -2554,11 +3065,15 @@ systems are available at the
 .P
 The best performance was obtained with the
 .I ash
-shell; so groffer tries to run under
+shell; so
+.I groffer
+tries to run under
 .I ash
 whenever possible.
 .
-If not available the shell under which the script was started in the
+If
+.I ash
+is not available the shell under which the script was started in the
 first place is used instead.
 .
 This can be modified by the option
@@ -2570,23 +3085,28 @@ The groffer program provides its own parser for command line arguments
 that is compatible to both POSIX
 .BR getopts (1)
 and GNU
-.BR getopt (1).
+.BR getopt (1)
+except for shortcuts of long options.
 .
-The following usual types of options are supported.
+The following standard types of options are supported.
 .
 .
 .Topic
-A single minus always refers to single character options, for example,
+A single minus always refers to single character option or a
+combination thereof, for example, the
+.I groffer
+short option combination
 .Opt_short Qmfoo
 is equivalent to
-.Opt_short Q\~\-m\~foo.
+.Opt_short Q\~\-m\~foo .
 .
 .
 .Topic
-Long options that means option with names longer than one character
-are always prededed by a double minus; an option argument can either
-go to the next command line argument or be appended with an equal sign
-to the argument; for example,
+Long options are options with names longer than one character; they
+are always prededed by a double minus.
+.
+An option argument can either go to the next command line argument or
+be appended with an equal sign to the argument; for example,
 .Opt_alt -- long=arg
 is equivalent to
 .Opt_alt -- long\~arg .
@@ -2596,7 +3116,7 @@ is equivalent to
 An argument of
 .Opt_--
 ends option parsing; all further command line arguments are
-interpreted as filespec arguments.
+interpreted as file name arguments.
 .
 .
 .Topic
@@ -2613,8 +3133,11 @@ is, by default, equivalent to
 .P
 This behavior can be changed by setting the environment variable
 .Env_var $POSIXLY_CORRECT
-to a non-empty value; in this case, option processing is stopped as
-soon as the first non-option argument is found.
+to a non-empty value.
+.
+Then the strange POSIX non-option behavior is adopted, i. e. option
+processing is stopped as soon as the first non-option argument is
+found and each following argument is taken as a file name.
 .
 For example, in posixly correct mode, the command line
 .Shell_cmd "groffer file1 -a -o arg file 2"
@@ -2633,27 +3156,27 @@ want to set
 .BR groff (@MAN1EXT@)
 .TP+
 .BR troff (@MAN1EXT@)
-Details on the options and environment variables available in groff;
+Details on the options and environment variables available in
+.IR groff ;
 all of them can be used with groffer.
 .
 .
 .TP
-.BR grog (@MAN1EXT@)
-Internally, groffer tries to guess the groff command line options from
-the input using this program.
-.
+.BR man (1)
+The standard program to diplay man\~pages.
 .
-.TP
-.BR groff_out (@MAN5EXT@)
-Documentation on the groff intermediate output (ditroff output).
+The information there is only useful if it is the man\~page for
+.IR "GNU\~man" .
+Then it documents the options and environment variables that are
+supported by groffer.
 .
 .
 .TP
-.BR xdvi (1)
+.BR gxditview (@MAN1EXT@)
 .TP+
-.BR dvilx (1)
+.BR xditview (1x)
 Viewers for groffer's
-.I dvi
+.I x
 mode.
 .
 .
@@ -2685,15 +3208,22 @@ files.
 .
 .
 .TP
-.BR gxditview (@MAN1EXT@)
+.BR xdvi (1)
 .TP+
-.BR xditview (1x)
+.BR dvilx (1)
 Viewers for groffer's
-.I x
+.I dvi
 mode.
 .
 .
 .TP
+.BR less (1)
+Standard pager program for the
+.I tty
+.IR mode .
+.
+.
+.TP
 .BR gzip (1)
 .TP+
 .BR bzip2 (1)
@@ -2701,20 +3231,28 @@ The decompression programs supported by groffer.
 .
 .
 .TP
-.BR man (1)
-The standard program to diplay man\~pages.
+.BR groff (@MAN7EXT@)
+Documentation of the
+.I groff
+language.
 .
-The information there is only useful if it is the man\~page for
-.IR "GNU\~man" .
-Then it documents the options and environment variables that are
-supported by groffer.
+.
+.TP
+.BR grog (@MAN1EXT@)
+Internally, groffer tries to guess the groff command line options from
+the input using this program.
+.
+.
+.TP
+.BR groff_out (@MAN5EXT@)
+Documentation on the groff intermediate output (ditroff output).
 .
 .
 .\" --------------------------------------------------------------------
 .SH "AUTHOR"
 .\" --------------------------------------------------------------------
 .
-Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+Copyright (C) 2001,2002,2004 Free Software Foundation, Inc.
 .
 .P
 This document is distributed under the terms of the FDL (GNU Free
@@ -2729,10 +3267,8 @@ This document is part of
 .IR groff ,
 the GNU roff distribution.
 .
-It was written by
-.MTO bwarken@mayn.de "Bernd Warken" .
+It was written by Bernd Warken.
 .
-.cp \n[groffer_C]
 .
 \" --------------------------------------------------------------------
 .\" Emacs settings
diff --git a/contrib/groffer/groffer.sh b/contrib/groffer/groffer.sh
index f019e206..f3c14125 100644
--- a/contrib/groffer/groffer.sh
+++ b/contrib/groffer/groffer.sh
@@ -4,10 +4,10 @@
 
 # Source file position: /contrib/groffer/groffer.sh
 
-# Copyright (C) 2001,2002,2003 Free Software Foundation, Inc.
-# Written by Bernd Warken 
+# Copyright (C) 2001,2002,2003,2004 Free Software Foundation, Inc.
+# Written by Bernd Warken
 
-# This file is part of groff.
+# This file is part of groff version @VERSION@.
 
 # groff is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -20,33 +20,44 @@
 # License for more details.
 
 # You should have received a copy of the GNU General Public License
-# along with groff; see the file COPYING.  If not, write to the
-# Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-# MA 02111-1307, USA.
-
-export _PROGRAM_NAME;
-export _PROGRAM_VERSION;
-export _LAST_UPDATE;
+# along with groff; see the files COPYING and LICENSE in the top
+# directory of the groff source.  If not, write to the Free Software
+# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 _PROGRAM_NAME='groffer';
-_PROGRAM_VERSION='0.9.4';
-_LAST_UPDATE='22 Jan 2003';
+_PROGRAM_VERSION='0.9.7';
+_LAST_UPDATE='30 Apr 2004';
 
-# This program is installed with groff version @VERSION@.
 
 ########################################################################
 # Determine the shell under which to run this script;
 # if `ash' is available restart the script using `ash';
 # otherwise just go on.
 
-if test "${_groffer_run}" != 'second'; then
+if test "${_groffer_run}" = ''; then
   # only reached during the first run of the script
 
-  export GROFFER_OPT;
-  export _groffer_run;
-  export _this;
-
-  _this="@BINDIR@/${_PROGRAM_NAME}";
+  export _PROGRAM_NAME;
+  export _PROGRAM_VERSION;
+  export _LAST_UPDATE;
+
+  export GROFFER_OPT;		# option environment for groffer
+  export _GROFFER_SH;		# file name of this shell script
+  export _OUTPUT_FILE_NAME;	# output generated, see main_set_res..()
+  export _groffer_run;		# counter for the runs of groffer
+
+  _groffer_run='first';
+
+  case "$0" in
+  *${_PROGRAM_NAME}*)
+    _GROFFER_SH="$0";
+    # was: _GROFFER_SH="@BINDIR@/${_PROGRAM_NAME}";
+    ;;
+  *)
+    echo "The ${_PROGRAM_NAME} script should be started directly." >&2
+    exit 1;
+    ;;
+  esac;
 
   ###########################
   # _get_opt_shell ("$@")
@@ -107,13 +118,13 @@ if test "${_groffer_run}" != 'second'; then
   if _test_on_shell "${_shell}"; then
     _groffer_run='second';
     # do not quote $_shell to allow arguments
-    exec ${_shell} "${_this}" "$@";
+    exec ${_shell} "${_GROFFER_SH}" "$@";
     exit;
   fi;
 
   # clean-up of shell determination
   unset _shell;
-  unset _this;
+  unset _GROFFER_SH;
   unset _groffer_run;
   _get_opt_shell()
   {
@@ -124,7 +135,14 @@ if test "${_groffer_run}" != 'second'; then
     return 0;
   }
 
+fi; # end of first run
+
+if test "${_groffer_run}" != 'second';
+then
+  echo "$_groffer_run should be 'second' here." >&2
+  exit 1
 fi;
+unset _groffer_run
 
 
 ########################################################################
@@ -140,146 +158,6 @@ _DEBUG_LM='no';			# disable landmark messages
 
 
 ########################################################################
-#                          Description
-########################################################################
-
-# Display groff files and man pages on X or tty, even when compressed.
-
-
-### Usage
-
-# Input comes from either standard input or command line parameters
-# that represent either names of exisiting roff files or standardized
-# specifications for man pages.  All of these can be compressed in a
-# format that is decompressible by `gzip'.
-
-# The following displaying modes are available:
-# - Display formatted input with the X roff viewer `gxditview',
-# - with a Prostcript viewer,
-# - with a dvi viewer,
-# - with a web browser.
-# - Display formatted input in a text terminal using a text device.
-# - Generate output for some groff device on stdout without a viewer.
-# - Output only the source code without any groff processing.
-# - Generate the troff intermediate output on standard output
-#   without groff postprocessing.
-# By default, the program tries to display with `gxditview' (1); if
-# this does not work, text display (2) is used.
-
-
-### Error handling
-
-# Error handling and exit behavior is complicated by the fact that
-# `exit' can only escape from the current shell; trouble occurs in
-# subshells.  This was solved by sending kill signals, see
-# $_PROCESS_ID and error().
-
-
-### Compatibility
-
-# This shell script is compatible to the both the GNU and the POSIX
-# shell and utilities.  Care was taken to restrict the programming
-# technics used here in order to achieve POSIX compatibility as far
-# back as POSIX P1003.2 Draft 11.2 of September 1991.
-
-# The only non-builtin used here is POSIX `sed'.  This script was
-# tested under `bash', `ash', and `ksh'.  The speed under `ash' is
-# more than double when compared to the larger shells.
-
-# This script provides its own option parser.  It is compatible to the
-# usual GNU style command line (option clusters, long options, mixing
-# of options and non-option file names), except that it is not
-# possible to abbreviate long option names.
-
-# The mixing of options and file names can be prohibited by setting
-# the environment variable `$POSIXLY_CORRECT' to a non-empty value.
-# This enables the rather wicked POSIX behavior to terminate option
-# parsing when the first non-option command line argument is found.
-
-
-########################################################################
-#            Survey of functions defined in this document
-########################################################################
-
-# The elements specified within paranthesis `(<>)' give hints to what
-# the arguments are meant to be; the argument names are irrelevant.
-# <>?     0 or 1
-# <>*     arbitrarily many such arguments, incl. none
-# <>+     one or more such arguments
-# <>      exactly 1
-
-# A function that starts with an underscore `_' is an internal
-# function for some function.  The internal functions are defined just
-# after their corresponding function; they are not mentioned in the
-# following.
-
-# abort (text>*)
-# base_name (path)
-# catz ()
-# clean_up ()
-# diag (text>*)
-# dirname_append ( [])
-# dirname_chop ()
-# do_filearg ()
-# do_nothing ()
-# echo2 (*)
-# echo2n (*)
-# error (*)
-# get_first_essential (*)
-# is_dir ()
-# is_empty ()
-# is_equal ( )
-# is_file ()
-# is_not_empty ()
-# is_not_equal ( )
-# is_not_file ()
-# is_not_prog ()
-# is_prog ()
-# is_yes ()
-# leave ()
-# landmark ()
-# list_append ( ...)
-# list_check ()
-# list_from_args (...)
-# list_from_cmdline (    [...])
-# list_from_split ( )
-# list_has ( )
-# list_has_not ( )
-# list_length ()
-#   main_*(), see after the functions
-# man_do_filespec ()
-# man_setup ()
-# man_register_file ( [ [
]]) -# man_search_section (
) -# man_set() -# manpath_add_lang( ) -# manpath_add_system() -# manpath_from_path () -# normalize_args ( *) -# path_chop () -# path_clean () -# path_contains ( ) -# path_not_contains ( ) -# path_split () -# register_file () -# register_title () -# reset () -# save_stdin () -# string_contains ( ) -# string_not_contains ( ) -# tmp_cat () -# tmp_create (?) -# to_tmp () -# trap_clean () -# trap_set () -# usage () -# version () -# warning () -# whatis () -# where () - - -######################################################################## # Environment Variables ######################################################################## @@ -299,43 +177,6 @@ _DEBUG_LM='no'; # disable landmark messages ######################################################################## -# External environment variables - -# If these variables are exported here then the `ash' shell coughs -# when calling `groff' in `main_display()'. - -if test "${GROFFER_EXPORT_EXTERNALS}" = 'yes'; then - - # external system environment variables that are explicitly used - export DISPLAY; # Presets the X display. - export LANG; # For language specific man pages. - export LC_ALL; # For language specific man pages. - export LC_MESSAGES; # For language specific man pages. - export PAGER; # Paging program for tty mode. - export PATH; # Path for the programs called (: list). - - # groffer native environment variables - export GROFFER_OPT # preset options for groffer. - - # all groff environment variables are used, see groff(1) - export GROFF_BIN_PATH; # Path for all groff programs. - export GROFF_COMMAND_PREFIX; # '' (normally) or 'g' (several troffs). - export GROFF_FONT_PATH; # Path to non-default groff fonts. - export GROFF_TMAC_PATH; # Path to non-default groff macro files. - export GROFF_TMPDIR; # Directory for groff temporary files. - export GROFF_TYPESETTER; # Preset default device. - - # all GNU man environment variables are used, see man(1). - export MANOPT; # Preset options for man pages. - export MANPATH; # Search path for man pages (: list). - export MANROFFSEQ; # Ignored because of grog guessing. - export MANSECT; # Search man pages only in sections (:). - export SYSTEM; # Man pages for different OS's (, list). - -fi; - - -######################################################################## # read-only variables (global to this file) ######################################################################## @@ -404,9 +245,9 @@ export _CONFFILES; _CONFFILES="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf"; export _DEFAULT_MODES; -_DEFAULT_MODES='ps,x,tty'; +_DEFAULT_MODES='x,ps,tty'; export _DEFAULT_RESOLUTION; -_DEFAULT_RESOLUTION='100'; +_DEFAULT_RESOLUTION='75'; export _DEFAULT_TTY_DEVICE; _DEFAULT_TTY_DEVICE='latin1'; @@ -415,12 +256,12 @@ _DEFAULT_TTY_DEVICE='latin1'; # _VIEWER_* a comma-separated list of viewer programs (with options) export _VIEWER_DVI; # viewer program for dvi mode export _VIEWER_PS; # viewer program for ps mode -export _VIEWER_WWW_X; # viewer program for www mode in X -export _VIEWER_WWW_TTY; # viewer program for www mode in tty +export _VIEWER_HTML_X; # viewer program for html mode in X +export _VIEWER_HTML_TTY; # viewer program for html mode in tty _VIEWER_DVI='xdvi,dvilx'; _VIEWER_PDF='xpdf,acroread'; _VIEWER_PS='gv,ghostview,gs_x11,gs'; -_VIEWER_WWW='mozilla,netscape,opera,amaya,arena'; +_VIEWER_HTML='konqueror,mozilla,netscape,opera,amaya,arena,lynx'; _VIEWER_X='gxditview,xditview'; # Search automatically in standard sections `1' to `8', and in the @@ -458,86 +299,95 @@ export _OPTS_GROFF_SHORT_NA; export _OPTS_GROFF_SHORT_ARG; export _OPTS_GROFF_LONG_NA; export _OPTS_GROFF_LONG_ARG; +export _OPTS_X_SHORT_ARG; +export _OPTS_X_SHORT_NA; +export _OPTS_X_LONG_ARG; +export _OPTS_X_LONG_NA; export _OPTS_MAN_SHORT_ARG; export _OPTS_MAN_SHORT_NA; export _OPTS_MAN_LONG_ARG; export _OPTS_MAN_LONG_NA; -export _OPTS_GROFFER_LONG; -export _OPTS_GROFFER_SHORT; -export _OPTS_GROFF_LONG; -export _OPTS_GROFF_SHORT; +export _OPTS_MANOPT_SHORT_ARG; +export _OPTS_MANOPT_SHORT_NA; +export _OPTS_MANOPT_LONG_ARG; +export _OPTS_MANOPT_LONG_NA; export _OPTS_CMDLINE_SHORT_NA; export _OPTS_CMDLINE_SHORT_ARG; -export _OPTS_CMDLINE_SHORT; export _OPTS_CMDLINE_LONG_NA; export _OPTS_CMDLINE_LONG_ARG; -export _OPTS_CMDLINE_LONG; - -###### native groffer options +###### groffer native options _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'"; _OPTS_GROFFER_SHORT_ARG="'T'"; -_OPTS_GROFFER_LONG_NA="'all' 'apropos' 'ascii' 'auto' 'default' 'dvi' \ -'groff' 'help' 'intermediate-output' 'local-file' 'location' 'man' \ -'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'tty' 'tty-device' \ -'version' 'whatis' 'where' 'www' 'x'"; +_OPTS_GROFFER_LONG_NA="'auto' 'debug' 'default' 'dvi' \ +'groff' 'help' 'intermediate-output' 'html' 'man' \ +'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'text' 'text-device' \ +'title' 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'"; -_OPTS_GROFFER_LONG_ARG="'background' 'bd' 'bg' 'bw' 'default-modes' \ -'device' 'display' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \ -'foreground' 'geometry' 'locale' 'manpath' 'mode' 'pager' \ -'pdf-viewer' 'ps-viewer' 'resolution' 'sections' 'shell' \ -'systems' 'title' 'troff-device' 'www-viewer' 'xrm' 'x-viewer'"; +_OPTS_GROFFER_LONG_ARG="\ +'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \ +'default-modes' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \ +'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \ +'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'"; -##### options inhereted from groff +##### groffer options inhereted from groff _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \ 'R' 's' 'S' 't' 'U' 'V' 'z'"; _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \ 'w' 'W'"; -_OPTS_GROFF_LONG_NA=""; -_OPTS_GROFF_LONG_ARG=""; +_OPTS_GROFF_LONG_NA="'source'"; +_OPTS_GROFF_LONG_ARG="'device' 'macro-file'"; -###### man options (for parsing $MANOPT only) +##### groffer options inhereted from the X Window toolkit -_OPTS_MAN_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \ -'V' 'w' 'Z'"; -_OPTS_MAN_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'"; +_OPTS_X_SHORT_NA=""; +_OPTS_X_SHORT_ARG=""; + +_OPTS_X_LONG_NA="'iconic' 'rv'"; + +_OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \ +'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft', 'geometry' +'resolution' 'title' 'xrm'"; + +###### groffer options inherited from man + +_OPTS_MAN_SHORT_NA=""; +_OPTS_MAN_SHORT_ARG=""; -_OPTS_MAN_LONG_NA="'all' 'ascii' 'apropos' 'catman' 'debug' 'default' \ -'ditroff' 'help' 'local-file' 'location' 'troff' 'update' 'version' \ +_OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'debug' 'ditroff' 'help' \ +'local-file' 'location' 'pager' 'troff' 'update' 'version' \ 'whatis' 'where'"; _OPTS_MAN_LONG_ARG="'extension' 'locale' 'manpath' \ 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'"; -###### collections of options +###### additional options for parsing $MANOPT only -# groffer - -_OPTS_GROFFER_LONG="${_OPTS_GROFFER_LONG_ARG} ${_OPTS_GROFFER_LONG_NA}"; -_OPTS_GROFFER_SHORT=\ -"${_OPTS_GROFFER_SHORT_ARG} ${_OPTS_GROFFER_SHORT_NA}"; +_OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \ +'V' 'w' 'Z'"; +_OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'"; -# groff +_OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \ +'apropos' 'debug' 'default' 'html' 'ignore-case' 'location-cat' \ +'match-case' 'troff' 'update' 'version' 'where-cat'"; -_OPTS_GROFF_LONG="${_OPTS_GROFF_LONG_ARG} ${_OPTS_GROFF_LONG_NA}"; -_OPTS_GROFF_SHORT="${_OPTS_GROFF_SHORT_ARG} ${_OPTS_GROFF_SHORT_NA}"; +_OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \ +'config_file' 'encoding' 'locale'"; -# all command line options +###### collections of command line options -_OPTS_CMDLINE_SHORT_NA="\ -${_OPTS_GROFFER_SHORT_NA} ${_OPTS_GROFF_SHORT_NA}"; -_OPTS_CMDLINE_SHORT_ARG="\ -${_OPTS_GROFFER_SHORT_ARG} ${_OPTS_GROFF_SHORT_ARG}"; -_OPTS_CMDLINE_SHORT="${_OPTS_GROFFER_SHORT} ${_OPTS_GROFF_SHORT}"; +_OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA}\ +${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}"; +_OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \ +${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}"; _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \ -${_OPTS_GROFF_LONG_NA} ${_OPTS_MAN_LONG_NA}"; +${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}"; _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \ -${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG}"; -_OPTS_CMDLINE_LONG="${_OPTS_GROFFER_LONG} ${_OPTS_GROFF_LONG}"; +${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}"; ######################################################################## @@ -581,7 +431,10 @@ export _MANOPT_SEC; # $MANOPT --sections export _MANOPT_SYS; # $MANOPT --systems # _OPT_* as parsed from groffer command line export _OPT_ALL; # display all suitable man pages. -export _OPT_APROPOS; # branch to `apropos' program. +export _OPT_APROPOS; # call `apropos' program. +export _OPT_APROPOS_DATA; # `apropos' for man sections 4, 5, 7 +export _OPT_APROPOS_DEVEL; # `apropos' for man sections 2, 3, 9 +export _OPT_APROPOS_PROGS; # `apropos' for man sections 1, 6, 8 export _OPT_BD; # set border color in some modes. export _OPT_BG; # set background color in some modes. export _OPT_BW; # set border width in some modes. @@ -592,6 +445,7 @@ export _OPT_DISPLAY; # set X display. export _OPT_FG; # set foreground color in some modes. export _OPT_FN; # set font in some modes. export _OPT_GEOMETRY; # set size and position of viewer in X. +export _OPT_ICONIC; # -iconic option for X viewers. export _OPT_LANG; # set language for man pages export _OPT_LOCATION; # print processed file names to stderr export _OPT_MODE; # values: X, tty, Q, Z, "" @@ -602,15 +456,14 @@ export _OPT_RV; # reverse fore- and background colors. export _OPT_SECTIONS; # sections for man page search export _OPT_SYSTEMS; # man pages of different OS's export _OPT_TITLE; # title for gxditview window -export _OPT_TTY_DEVICE; # set device for tty mode. +export _OPT_TEXT_DEVICE; # set device for tty mode. export _OPT_V; # groff option -V. export _OPT_VIEWER_DVI; # viewer program for dvi mode export _OPT_VIEWER_PDF; # viewer program for pdf mode export _OPT_VIEWER_PS; # viewer program for ps mode -export _OPT_VIEWER_WWW; # viewer program for www mode +export _OPT_VIEWER_HTML; # viewer program for html mode export _OPT_VIEWER_X; # viewer program for x mode export _OPT_WHATIS; # print the one-liner man info -export _OPT_X; # groff option -X. export _OPT_XRM; # specify X resource. export _OPT_Z; # groff option -Z. # _TMP_* temporary files @@ -723,7 +576,10 @@ reset() # _OPT_* as parsed from groffer command line _OPT_ALL='no'; - _OPT_APROPOS='no'; + _OPT_APROPOS=''; + _OPT_APROPOS_DATA=''; + _OPT_APROPOS_DEVEL=''; + _OPT_APROPOS_PROGS=''; _OPT_BD=''; _OPT_BG=''; _OPT_BW=''; @@ -734,25 +590,25 @@ reset() _OPT_FG=''; _OPT_FN=''; _OPT_GEOMETRY=''; + _OPT_ICONIC='no'; _OPT_LANG=''; _OPT_LOCATION='no'; _OPT_MODE=''; _OPT_MANPATH=''; _OPT_PAGER=''; _OPT_RESOLUTION=''; - _OPT_RV=''; + _OPT_RV='no'; _OPT_SECTIONS=''; _OPT_SYSTEMS=''; _OPT_TITLE=''; - _OPT_TTY_DEVICE=''; + _OPT_TEXT_DEVICE=''; _OPT_V='no'; _OPT_VIEWER_DVI=''; _OPT_VIEWER_PDF=''; _OPT_VIEWER_PS=''; - _OPT_VIEWER_WWW=''; + _OPT_VIEWER_HTML=''; _OPT_VIEWER_X=''; _OPT_WHATIS='no'; - _OPT_X='no'; _OPT_XRM=''; _OPT_Z='no'; @@ -1194,10 +1050,27 @@ landmark "3: functions"; ######################################################################## +# apropos_run () +# +# +apropos_run() { + func_check apropos_run = 1 "$@"; + if apropos apropos >/dev/null 2>/dev/null; then + apropos "$1"; + elif man --apropos man >/dev/null 2>/dev/null; then + man --apropos "$1"; + elif man -k man >/dev/null 2>/dev/null; then + man -k "$1"; + fi; +} + + +######################################################################## # base_name () # # Get the file name part of , i.e. delete everything up to last -# `/' from the beginning of . +# `/' from the beginning of . Remove final slashes, too, to get a +# non-empty output. # # Arguments : 1 # Output : the file name part (without slashes) @@ -1205,16 +1078,24 @@ landmark "3: functions"; base_name() { func_check base_name = 1 "$@"; - case "$1" in + local f; + f="$1"; + case "$f" in */) - do_nothing; + # delete all final slashes + f="$(echo -n "$f" | sed -e '\|//*$|s|||')"; + ;; + esac; + case "$f" in + /|'') + eval "${return_bad}"; ;; */*) # delete everything before and including the last slash `/'. - echo -n "$1" | sed -e '\|^.*//*\([^/]*\)$|s||\1|'; + echo -n "$f" | sed -e '\|^.*//*\([^/]*\)$|s||\1|'; ;; *) - echo -n "$1"; + echo -n "$f"; ;; esac; eval "${return_ok}"; @@ -1243,7 +1124,7 @@ if test "${_HAS_COMPRESSION}" = 'yes'; then error 'catz(): for standard input use save_stdin()'; ;; esac; - if is_yes "${_HAS_BZIP}"; then + if obj _HAS_BZIP is_yes; then if bzip2 -t "$1" 2>/dev/null; then bzip2 -c -d "$1" 2>/dev/null; eval "${return_ok}"; @@ -1373,8 +1254,8 @@ do_filearg() set -- 'File'; ;; *) - if is_yes "${_MAN_ENABLE}"; then - if is_yes "${_MAN_FORCE}"; then + if obj _MAN_ENABLE is_yes; then + if obj _MAN_FORCE is_yes; then set -- 'Manpage' 'File'; else set -- 'File' 'Manpage'; @@ -1400,7 +1281,7 @@ do_filearg() fi; ;; Manpage) # parse filespec as man page - if is_not_yes "${_MAN_IS_SETUP}"; then + if obj _MAN_IS_SETUP is_not_yes; then man_setup; fi; if man_do_filespec "${_filespec}"; then @@ -1499,11 +1380,11 @@ get_first_essential() { func_check get_first_essential '>=' 0 "$@"; local i; - if test "$#" -eq 0; then + if is_equal "$#" 0; then eval "${return_ok}"; fi; for i in "$@"; do - if is_not_empty "$i"; then + if obj i is_not_empty; then echo -n "$i"; eval "${return_ok}"; fi; @@ -1527,12 +1408,10 @@ landmark '5: is_*()'; is_dir() { func_check is_dir = 1 "$@"; - if is_not_empty "$1" && test -d "$1" && test -r "$1"; then + if test -d "$1" && test -r "$1"; then eval "${return_yes}"; - else - eval "${return_no}"; fi; - eval "${return_ok}"; + eval "${return_no}"; } @@ -1547,12 +1426,10 @@ is_dir() is_empty() { func_check is_empty = 1 "$@"; - if test -z "$1"; then + if test "$1" = ''; then eval "${return_yes}"; - else - eval "${return_no}"; fi; - eval "${return_ok}"; + eval "${return_no}"; } @@ -1569,10 +1446,8 @@ is_equal() func_check is_equal = 2 "$@"; if test "$1" = "$2"; then eval "${return_yes}"; - else - eval "${return_no}"; fi; - eval "${return_ok}"; + eval "${return_no}"; } @@ -1587,12 +1462,32 @@ is_equal() is_file() { func_check is_file = 1 "$@"; - if is_not_empty "$1" && test -f "$1" && test -r "$1"; then + if test -f "$1" && test -r "$1"; then eval "${return_yes}"; - else - eval "${return_no}"; fi; - eval "${return_ok}"; + eval "${return_no}"; +} + + +######################################################################## +# is_non_empty_file () +# +# Test whether `file_name' is a non-empty existing file. +# +# Arguments : <=1 +# Return : +# `0' if arg1 is a non-empty existing file +# `1' otherwise +# +is_non_empty_file() +{ + func_check is_empty = 1 "$@"; + if is_file "$1"; then + if is_not_empty "$(cat "$1" | sed -e '/./q')"; then + eval "${return_yes}"; + fi; + fi; + eval "${return_no}"; } @@ -1609,10 +1504,8 @@ is_not_dir() func_check is_not_dir = 1 "$@"; if is_dir "$1"; then eval "${return_no}"; - else - eval "${return_yes}"; fi; - eval "${return_ok}"; + eval "${return_yes}"; } @@ -1629,17 +1522,15 @@ is_not_empty() func_check is_not_empty = 1 "$@"; if is_empty "$1"; then eval "${return_no}"; - else - eval "${return_yes}"; fi; - eval "${return_ok}"; + eval "${return_yes}"; } ######################################################################## # is_not_equal ( ) # -# Test whether `string1' and differ. +# Test whether `string1' differs from `string2'. # # Arguments : 2 # @@ -1648,10 +1539,8 @@ is_not_equal() func_check is_not_equal = 2 "$@"; if is_equal "$1" "$2"; then eval "${return_no}"; - else - eval "${return_yes}"; - fi; - eval "${return_ok}"; + fi + eval "${return_yes}"; } @@ -1667,10 +1556,8 @@ is_not_file() func_check is_not_file '>=' 1 "$@"; if is_file "$1"; then eval "${return_no}"; - else - eval "${return_yes}"; fi; - eval "${return_ok}"; + eval "${return_yes}"; } @@ -1687,10 +1574,25 @@ is_not_prog() func_check is_not_prog '>=' 1 "$@"; if where "$1" >/dev/null; then eval "${return_no}"; - else - eval "${return_yes}"; fi; - eval "${return_ok}"; + eval "${return_yes}"; +} + + +######################################################################## +# is_not_writable () +# +# Test whether `name' is a not a writable file or directory. +# +# Arguments : >=1 (empty allowed), more args are ignored +# +is_not_writable() +{ + func_check is_not_writable '>=' 1 "$@"; + if is_writable "$1"; then + eval "${return_no}"; + fi; + eval "${return_yes}"; } @@ -1704,12 +1606,10 @@ is_not_prog() is_not_yes() { func_check is_not_yes = 1 "$@"; - if test "$1" = 'yes'; then + if is_yes "$1"; then eval "${return_no}"; - else - eval "${return_yes}"; fi; - eval "${return_ok}"; + eval "${return_yes}"; } @@ -1718,18 +1618,42 @@ is_not_yes() # # Determine whether arg is a program in $PATH # -# Arguments : >=1 (empty allowed) +# Arguments : >=0 (empty allowed) # more args are ignored, this allows to specify progs with arguments # is_prog() { - func_check is_prog '>=' 1 "$@"; - if where "$1" >/dev/null; then - eval "${return_yes}"; - else + func_check is_prog '>=' 0 "$@"; + case "$#" in + 0) eval "${return_no}"; + ;; + *) + if where "$1" >/dev/null; then + eval "${return_yes}"; + fi; + ;; + esac + eval "${return_no}"; +} + + +######################################################################## +# is_writable () +# +# Test whether `name' is a writable file or directory. +# +# Arguments : >=1 (empty allowed), more args are ignored +# +is_writable() +{ + func_check is_writable '>=' 1 "$@"; + if test -r "$1"; then + if test -w "$1"; then + eval "${return_yes}"; + fi; fi; - eval "${return_ok}"; + eval "${return_no}"; } @@ -1744,12 +1668,10 @@ is_prog() is_yes() { func_check is_yes = 1 "$@"; - if test "$1" = 'yes'; then + if is_equal "$1" 'yes'; then eval "${return_yes}"; - else - eval "${return_no}"; fi; - eval "${return_ok}"; + eval "${return_no}"; } @@ -1778,132 +1700,55 @@ leave() ######################################################################## landmark '6: list_*()'; ######################################################################## +# +# `list' is an object class that represents an array or list. Its +# data consists of space-separated single-quoted elements. So a list +# has the form "'first' 'second' '...' 'last'". See list_append() for +# more details on the list structure. The array elements of `list' +# can be get by `set -- $list`. + ######################################################################## # list_append ( ...) # # Arguments: >=2 -# : a space-separated list of single-quoted elements. -# : some sequence of characters. -# Output: +# : a variable name for a list of single-quoted elements +# : some sequence of characters. +# Output: none, but $ is set to # if is empty: "'' '...'" -# otherwise: " '' ..." +# otherwise: "$list '' ..." # list_append() { func_check list_append '>=' 2 "$@"; local _element; - local _res; - _res="$1"; + local _list; + local _name; + _name="$1"; + eval _list='"${'$1'}"'; shift; for s in "$@"; do case "$s" in - *\'*) - # escape each single quote by replacing each "'" (squote) - # by "'\''" (squote bslash squote squote); - # note that the backslash must be doubled for `sed'. - _element="$(echo -n "$s" | sed -e 's/'"${_SQUOTE}"'/&\\&&/g')"; - ;; - *) - _element="$s"; - ;; - esac; - _res="${_res} '${_element}'"; - done; - echo -n "${_res}"; - eval "${return_ok}"; -} - - -######################################################################## -# list_check () -# -# Check whether is a space-separated list of '-quoted elements. -# -# If the test fails an error is raised. -# If the test succeeds the argument is echoed. -# -# Testing criteria: -# A list has the form "'first' 'second' '...' 'last'". -# So it has a leading and a final quote and the elements are separated -# by "' '" constructs. If these are all removed there should not be -# any single-quotes left. Watch out for escaped single quotes; they -# have the form '\'' (sq bs sq sq). -# -# Arguments: 1 -# Output: the argument unchanged, it the check succeeded. -# -list_check() -{ - func_check list_check = 1 "$@"; - local _list; - if is_empty "$1"; then - eval "${return_ok}"; - fi; - case "$1" in - \'*\') _list="$1"; ;; - *) - error "list_check() bad list: $1" + *\'*) + # escape each single quote by replacing each + # "'" (squote) by "'\''" (squote bslash squote squote); + # note that the backslash must be doubled in the following `sed' + _element="$(echo -n "$s" | sed -e 's/'"${_SQUOTE}"'/&\\&&/g')"; ;; - esac; - # Remove leading single quote, - # remove final single quote, - # remove escaped single quotes (squote bslash squote squote) - # [note that `sed' doubles the backslash (bslash bslash)], - # remove field separators (squote space squote). - _list="$(echo -n "${_list}" \ - | sed -e 's/^'"${_SQUOTE}"'//' \ - | sed -e 's/'"${_SQUOTE}"'$//' \ - | sed -e \ - 's/'"${_SQUOTE}${_BSLASH}${_BSLASH}${_SQUOTE}${_SQUOTE}"'//g' \ - | sed -e 's/'"${_SQUOTE}${_SPACE}${_SPACE}"'*'"${_SQUOTE}"'//g')"; - case "${_list}" in - *\'*) # criterium fails if squote is left - error 'list_check() bad list: '"${_list}"; + '') + _element=""; ;; - esac; - echo -n "$1"; - eval "${return_ok}"; -} - - -######################################################################## -# list_element_from_arg () -# -# Arguments: 1 -# : some sequence of characters (also single quotes allowed). -# Output: the list element generated from . -# -list_element_from_arg() -{ - func_check list_element_from_arg = 1 "$@"; - local _res; - echo -n "'"; - # replace each single quote "'" by "'\''". - echo -n "$1" | sed -e 's/'\''/&\\&&/g'; # ' for emacs - echo -n "'"; - eval "${return_ok}"; -} - - -######################################################################## -# list_from_args (...) -# -# Generate a space-separated list of single-quoted elements from args. -# -# Arguments: -# : some sequence of characters. -# Output: "'' '...'" -# -list_from_args() -{ - func_check list_from_args '>=' 1 "$@"; - local _list; - _list=""; - for s in "$@"; do - _list="$(list_append "${_list}" "$s")"; + *) + _element="$s"; + ;; + esac; + if obj _list is_empty; then + _list="'${_element}'"; + else + _list="${_list} '${_element}'"; + fi; done; - echo -n "${_list}"; + eval "${_name}"='"${_list}"'; eval "${return_ok}"; } @@ -1922,7 +1767,8 @@ list_from_args() # : space-separated list of short options that have an arg. # : space-separated list of long options without an arg. # : space-separated list of long options that have an arg. -# ...: the arguments from the command line (by "$@"). +# ...: the arguments from a command line, such as "$@", +# the content of a variable, or direct arguments. # # Globals: $POSIXLY_CORRECT (only kept for compatibility). # @@ -1937,7 +1783,8 @@ list_from_args() # # Rationale: # In POSIX, the first non-option ends the option processing. -# In GNU mode (default), non-options are sorted behind the options. +# In GNU mode, used by default, non-option arguments are sorted +# behind the options. # # Use this function only in the following way: # eval set -- "$(args_norm '...' '...' '...' '...' "$@")"; @@ -1960,13 +1807,13 @@ list_from_cmdline() local _long_n; local _short_a; local _short_n; - _short_n="$(list_check "$1")"; # short options, no argument - _short_a="$(list_check "$2")"; # short options with argument - _long_n="$(list_check "$3")"; # long options, no argument - _long_a="$(list_check "$4")"; # long options with argument + _short_n="$(list_get "$1")"; # short options, no argument + _short_a="$(list_get "$2")"; # short options with argument + _long_n="$(list_get "$3")"; # long options, no argument + _long_a="$(list_get "$4")"; # long options with argument shift 4; _fn='list_from_cmdline():'; # for error messages - if test "$#" -eq 0; then + if is_equal "$#" 0; then echo -n "'--'"; eval "${return_ok}"; fi; @@ -1980,63 +1827,48 @@ list_from_cmdline() --?*) # delete leading '--'; _opt="$(echo -n "${_arg}" | sed -e 's/^..//')"; - if list_has "${_long_n}" "${_opt}"; then + if list_has _long_n "${_opt}"; then # long option, no argument - _result="$(list_append "${_result}" "--${_opt}")"; - continue; - fi; - if list_has "${_long_a}" "${_opt}"; then - # long option with argument - _result="$(list_append "${_result}" "--${_opt}")"; - if test "$#" -le 0; then - error "${_fn} no argument for option --${_opt}." - fi; - _result="$(list_append "${_result}" "$1")"; - shift; + list_append _result "--${_opt}"; continue; fi; # test on `--opt=arg' if string_contains "${_opt}" '='; then # extract option by deleting from the first '=' to the end _lopt="$(echo -n "${_opt}" | sed -e 's/=.*$//')"; - if list_has "${_long_a}" "${_lopt}"; then + if list_has _long_a "${_lopt}"; then # get the option argument by deleting up to first `=' _optarg="$(echo -n "${_opt}" | sed -e 's/^[^=]*=//')"; - _result="$(list_append "${_result}" \ - "--${_lopt}" "${_optarg}")"; + list_append _result "--${_lopt}" "${_optarg}"; continue; fi; fi; + if list_has _long_a "${_opt}"; then + # long option with argument + if test "$#" -le 0; then + error "${_fn} no argument for option --${_opt}." + fi; + list_append _result "--${_opt}" "$1"; + shift; + continue; + fi; error "${_fn} --${_opt} is not an option." ;; -?*) # short option (cluster) # delete leading `-'; - _rest="$(echo -n "${_arg}" | sed -e 's/^.//')"; - while is_not_empty "${_rest}"; do + _rest="$(echo -n "${_arg}" | sed -e 's/^-//')"; + while obj _rest is_not_empty; do # get next short option from cluster (first char of $_rest) _optchar="$(echo -n "${_rest}" | sed -e 's/^\(.\).*$/\1/')"; # remove first character from ${_rest}; _rest="$(echo -n "${_rest}" | sed -e 's/^.//')"; - if list_has "${_short_n}" "${_optchar}"; then - _result="$(list_append "${_result}" "-${_optchar}")"; + if list_has _short_n "${_optchar}"; then + list_append _result "-${_optchar}"; continue; - elif list_has "${_short_a}" "${_optchar}"; then - # remove leading character - case "${_optchar}" in - /) - _rest="$(echo -n "${_rest}" | sed -e '\|^.|s|||')"; - ;; - ?) - _rest="$(echo -n "${_rest}" | sed -e 's/^.//')"; - ;; - ??*) - error "${_fn} several chars parsed for short option." - ;; - esac; - if is_empty "${_rest}"; then + elif list_has _short_a "${_optchar}"; then + if obj _rest is_empty; then if test "$#" -ge 1; then - _result="$(list_append "${_result}" \ - "-${_optchar}" "$1")"; + list_append _result "-${_optchar}" "$1"; shift; continue; else @@ -2044,8 +1876,7 @@ list_from_cmdline() "${_fn}"' no argument for option -'"${_optchar}." fi; else # rest is the argument - _result="$(list_append "${_result}" \ - "-${_optchar}" "${_rest}")"; + list_append _result "-${_optchar}" "${_rest}"; _rest=''; continue; fi; @@ -2059,19 +1890,19 @@ list_from_cmdline() # When $POSIXLY_CORRECT is set this ends option parsing; # otherwise, the argument is stored as a file parameter and # option processing is continued. - _fparams="$(list_append "${_fparams}" "${_arg}")"; - if is_not_empty "$POSIXLY_CORRECT"; then + list_append _fparams "${_arg}"; + if obj POSIXLY_CORRECT is_not_empty; then break; fi; ;; esac; done; - _result="$(list_append "${_result}" '--')"; - if is_not_empty "${_fparams}"; then + list_append _result '--'; + if obj _fparams is_not_empty; then _result="${_result} ${_fparams}"; fi; if test "$#" -gt 0; then - _result="$(list_append "${_result}" "$@")"; + list_append _result "$@"; fi; echo -n "$_result"; eval "${return_ok}"; @@ -2079,30 +1910,14 @@ list_from_cmdline() ######################################################################## -# list_from_lists ( ...) -# -# Generate a list from the concatenation of the lists in the arguments. -# -# Arguments: >=2 -# : string of space-separated single-quoted elements. -# Output: "'' ..." -# -list_from_lists() -{ - func_check list_from_lists '>=' 2 "$@"; - _list=''; - echo -n "$*"; - eval "${return_ok}"; -} - -######################################################################## # list_from_split ( ) # -# In escape white space and replace each by space. +# In , escape all white space characters and replace each +# by space. # # Arguments: 2: a that is to be split into parts divided by # -# Output: the resulting string +# Output: the resulting list string # list_from_split() { @@ -2129,22 +1944,65 @@ list_from_split() ######################################################################## -# list_has ( ) +# list_get () +# +# Check whether is a space-separated list of '-quoted elements. +# +# If the test fails an error is raised. +# If the test succeeds the argument is echoed. +# +# Testing criteria: +# A list has the form "'first' 'second' '...' 'last'". So it has a +# leading and a final quote and the elements are separated by "' '" +# constructs. If these are all removed there should not be any +# unescaped single-quotes left. Watch out for escaped single +# quotes; they have the form '\'' (sq bs sq sq). + +# Arguments: 1 +# Output: the argument unchanged, if the check succeeded. +# +list_get() +{ + func_check list_get = 1 "$@"; + local _list; + eval _list='"${'$1'}"'; + # remove leading and final space characters + _list="$(echo -n "${_list}" | \ + sed -e '/^['"${_SPACE}${_TAB}"']*/s///' | \ + sed -e '/['"${_SPACE}${_TAB}"']*$/s///')"; + case "${_list}" in + '') + eval "${return_ok}"; + ;; + \'*\') + echo -n "${_list}"; + eval "${return_ok}"; + ;; + *) + error "list_get(): bad list: $1" + ;; + esac; + eval "${return_ok}"; +} + + +######################################################################## +# list_has ( ) # # Arguments: 2 -# : a space-separated list of single-quoted elements. -# : some sequence of characters. +# : a variable name for a list of single-quoted elements +# : some sequence of characters. # Output: # if is empty: "'' '...'" -# otherwise: " '' ..." +# otherwise: "list '' ..." # list_has() { func_check list_has = 2 "$@"; - if is_empty "$1"; then + eval _list='"${'$1'}"'; + if obj _list is_empty; then eval "${return_no}"; fi; - _list="$1"; _element="$2"; case "$2" in \'*\') _element="$2"; ;; @@ -2172,10 +2030,10 @@ list_has() list_has_not() { func_check list_has_not = 2 "$@"; - if is_empty "$1"; then + eval _list='"${'$1'}"'; + if obj _list is_empty; then eval "${return_yes}"; fi; - _list="$1"; _element="$2"; case "$2" in \'*\') _element="$2"; ;; @@ -2191,50 +2049,6 @@ list_has_not() ######################################################################## -# list_length () -# -# Arguments: 1 -# : a space-separated list of single-quoted elements. -# Output: the number of elements in -# -list_length() -{ - func_check list_length = 1 "$@"; - eval set -- "$1"; - echo -n "$#"; - eval "${return_ok}"; -} - - -######################################################################## -# list_prepend ( ...) -# -# Insert new at the beginning of -# -# Arguments: >=2 -# : a space-separated list of single-quoted elements. -# : some sequence of characters. -# Output: -# if is empty: "'' ..." -# otherwise: "'' ... " -# -list_prepend() -{ - func_check list_prepend '>=' 2 "$@"; - local _res; - _res="$1"; - shift; - for s in "$@"; do - # escape single quotes in list style (squote bslash squote squote). - _element="$(echo -n "$s" | sed -e 's/'\''/&\\&&/g')"; - _res="'${_element}' ${_res}"; - done; - echo -n "${_res}"; - eval "${return_ok}"; -} - - -######################################################################## landmark '7: man_*()'; ######################################################################## @@ -2266,7 +2080,7 @@ man_do_filespec() local _spec; local _string; local s; - if is_empty "${_MAN_PATH}"; then + if obj _MAN_PATH is_empty; then eval "${return_bad}"; fi; if is_empty "$1"; then @@ -2285,11 +2099,11 @@ man_do_filespec() _section="$(echo -n "${_spec}" \ | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')"; ;; - man:?*.?*) # man:name.section + man:?*.[0-9on]) # man:name.section _name="$(echo -n "${_spec}" \ - | sed -e 's/^man:\(..*\)\.\(..*\)$/\1/')"; + | sed -e 's/^man:\(..*\)\..$/\1/')"; _section="$(echo -n "${_spec}" \ - | sed -e 's/^man:\(..*\)\.\(..*\)$/\2/')"; + | sed -e 's/^.*\(.\)$/\1/')"; ;; man:?*) # man:name _name="$(echo -n "${_spec}" | sed -e 's/^man://')"; @@ -2300,25 +2114,25 @@ man_do_filespec() _section="$(echo -n "${_spec}" \ | sed -e 's/^\(..*\)(\(..*\))$/\2/')"; ;; - ?*.?*) # name.section + ?*.[0-9on]) # name.section _name="$(echo -n "${_spec}" \ - | sed -e 's/^\(..*\)\.\(..*\)$/\1/')"; + | sed -e 's/^\(..*\)\..$/\1/')"; _section="$(echo -n "${_spec}" \ - | sed -e 's/^\(..*\)\.\(..*\)$/\2/')"; + | sed -e 's/^.*\(.\)$/\1/')"; ;; ?*) _name="${_filespec}"; ;; esac; - if is_empty "${_name}"; then + if obj _name is_empty; then eval "${return_bad}"; fi; _got_one='no'; - if is_empty "${_section}"; then + if obj _section is_empty; then eval set -- "${_MAN_AUTO_SEC}"; for s in "$@"; do if man_search_section "${_name}" "$s"; then # found - if is_yes "${_MAN_ALL}"; then + if obj _MAN_ALL is_yes; then _got_one='yes'; else eval "${return_good}"; @@ -2332,7 +2146,7 @@ man_do_filespec() eval "${return_bad}"; fi; fi; - if is_yes "${_MAN_ALL}" && is_yes "${_got_one}"; then + if obj _MAN_ALL is_yes && is_yes "${_got_one}"; then eval "${return_good}"; fi; eval "${return_bad}"; @@ -2366,7 +2180,7 @@ man_register_file() eval "${return_ok}"; ;; 3) - register_title "$2($3)"; + register_title "$2.$3"; eval "${return_ok}"; ;; esac; @@ -2394,7 +2208,7 @@ man_search_section() local _section; local d; local f; - if is_empty "${_MAN_PATH}"; then + if obj _MAN_PATH is_empty; then eval "${return_bad}"; fi; if is_empty "$1"; then @@ -2407,16 +2221,16 @@ man_search_section() _section="$2"; eval set -- "$(path_split "${_MAN_PATH}")"; _got_one='no'; - if is_empty "${_MAN_EXT}"; then + if obj _MAN_EXT is_empty; then for d in "$@"; do _dir="$(dirname_append "$d" "man${_section}")"; - if is_dir "${_dir}"; then + if obj _dir is_dir; then _prefix="$(dirname_append "${_dir}" "${_name}.${_section}")"; for f in $(echo -n ${_prefix}*); do - if is_file "$f"; then + if obj f is_file; then if is_yes "${_got_one}"; then register_file "$f"; - elif is_yes "${_MAN_ALL}"; then + elif obj _MAN_ALL is_yes; then man_register_file "$f" "${_name}"; else man_register_file "$f" "${_name}" "${_section}"; @@ -2432,13 +2246,13 @@ man_search_section() # check for directory name having trailing extension for d in "$@"; do _dir="$(dirname_append $d man${_section}${_ext})"; - if is_dir "${_dir}"; then + if obj _dir is_dir; then _prefix="$(dirname_append "${_dir}" "${_name}.${_section}")"; for f in ${_prefix}*; do - if is_file "$f"; then + if obj f is_file; then if is_yes "${_got_one}"; then register_file "$f"; - elif is_yes "${_MAN_ALL}"; then + elif obj _MAN_ALL is_yes; then man_register_file "$f" "${_name}"; else man_register_file "$f" "${_name}" "${_section}"; @@ -2452,14 +2266,14 @@ man_search_section() # check for files with extension in directories without extension for d in "$@"; do _dir="$(dirname_append "$d" "man${_section}")"; - if is_dir "${_dir}"; then + if obj _dir is_dir; then _prefix="$(dirname_append "${_dir}" \ "${_name}.${_section}${_ext}")"; for f in ${_prefix}*; do - if is_file "$f"; then + if obj f is_file; then if is_yes "${_got_one}"; then register_file "$f"; - elif is_yes "${_MAN_ALL}"; then + elif obj _MAN_ALL is_yes; then man_register_file "$f" "${_name}"; else man_register_file "$f" "${_name}" "${_section}"; @@ -2471,7 +2285,7 @@ man_search_section() fi; done; fi; - if is_yes "${_MAN_ALL}" && is_yes "${_got_one}"; then + if obj _MAN_ALL is_yes && is_yes "${_got_one}"; then eval "${return_good}"; fi; eval "${return_bad}"; @@ -2505,35 +2319,35 @@ man_setup() func_check main_man_setup = 0 "$@"; local _lang; - if is_yes "${_MAN_IS_SETUP}"; then + if obj _MAN_IS_SETUP is_yes; then eval "${return_ok}"; fi; _MAN_IS_SETUP='yes'; - if is_not_yes "${_MAN_ENABLE}"; then + if obj _MAN_ENABLE is_not_yes; then eval "${return_ok}"; fi; # determine basic path for man pages _MAN_PATH="$(get_first_essential \ "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")"; - if is_empty "${_MAN_PATH}"; then - if is_prog 'manpath'; then - _MAN_PATH="$(manpath 2>/dev/null)"; # not always available - fi; - fi; - if is_empty "${_MAN_PATH}"; then + if obj _MAN_PATH is_empty; then manpath_set_from_path; else _MAN_PATH="$(path_clean "${_MAN_PATH}")"; fi; - if is_empty "${_MAN_PATH}"; then + if obj _MAN_PATH is_empty; then + if is_prog 'manpath'; then + _MAN_PATH="$(manpath 2>/dev/null)"; # not always available + fi; + fi; + if obj _MAN_PATH is_empty; then _MAN_ENABLE="no"; eval "${return_ok}"; fi; _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")"; - if is_empty "${_MAN_ALL}"; then + if obj _MAN_ALL is_empty; then _MAN_ALL='no'; fi; @@ -2562,7 +2376,7 @@ man_setup() _MAN_SEC="$(get_first_essential \ "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")"; - if is_empty "${_MAN_PATH}"; then + if obj _MAN_PATH is_empty; then _MAN_ENABLE="no"; eval "${return_ok}"; fi; @@ -2596,7 +2410,7 @@ manpath_add_lang_sys() func_check manpath_add_lang_sys = 0 "$@"; local p; local _mp; - if is_empty "${_MAN_PATH}"; then + if obj _MAN_PATH is_empty; then eval "${return_ok}"; fi; # twice test both sys and lang @@ -2623,16 +2437,14 @@ _manpath_add_lang_sys_single() # argument: 2: `man_path' and `dir' # output: colon-separated path of the retrieved subdirectories # + func_check _manpath_add_lang_sys_single = 2 "$@"; local d; -# if test "$#" -ne 2; then -# error "manpath_add_system_single() needs 2 arguments."; -# fi; _res="$1"; _parent="$2"; eval set -- "$(list_from_split "${_MAN_SYS}" ',')"; for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"; do _dir="$(dirname_append "${_parent}" "$d")"; - if path_not_contains "${_res}" "${_dir}" && is_dir "${_dir}"; then + if obj _res path_not_contains "${_dir}" && obj _dir is_dir; then _res="${_res}:${_dir}"; fi; done; @@ -2667,7 +2479,7 @@ manpath_set_from_path() _manpath=''; # get a basic man path from $PATH - if is_not_empty "${PATH}"; then + if obj PATH is_not_empty; then eval set -- "$(path_split "${PATH}")"; for d in "$@"; do # delete the final `/bin' part @@ -2687,7 +2499,7 @@ manpath_set_from_path() /usr/X11R6/man /usr/openwin/man \ /opt/share/man /opt/man \ /opt/gnome/man /opt/kde/man; do - if path_not_contains "${_manpath}" "$d" && is_dir "$d"; then + if obj _manpath path_not_contains "$d" && obj d is_dir; then _manpath="${_manpath}:$d"; fi; done; @@ -2698,8 +2510,106 @@ manpath_set_from_path() ######################################################################## -landmark '9: path_*()'; +landmark '9: obj_*()'; +######################################################################## + +######################################################################## +# obj ( ...) +# +# This works like a method (object function) call for an object. +# Run " $ ...". +# +# The first argument represents an object whose data is given as first +# argument to (). +# +# Argument: >=2 +# : variable name +# : a program or function name +# +obj() +{ + func_check obj '>=' 2 "$@"; + local func; + local var; + if is_empty "$2"; then + error "obj(): function name is empty." + else + func="$2"; + fi; + eval arg1='"${'$1'}"'; + shift; + shift; + eval "${func}"' "${arg1}" "$@"'; +} + + +######################################################################## +# obj_data () +# +# Print the data of , i.e. the content of $. +# For possible later extensions. +# +# Arguments: 1 +# : a variable name +# Output: the data of +# +obj_data() +{ + func_check obj '=' 1 "$@"; + if is_empty "$1"; then + error "obj_data(): object name is empty." + fi; + eval echo -n '"${'$1'}"'; +} + + +######################################################################## +# obj_from_output ( ...) +# +# Run '$="$( ...)"' to set the result of a +# function call to a global variable. +# +# Arguments: >=2 +# : a variable name +# : the name of a function or program +# : optional argument to +# Output: none +# +obj_from_output() +{ + func_check obj_from_output '>=' 2 "$@"; + local result_name; + if is_empty "$1"; then + error "res(): variable name is empty."; + elif is_empty "$2"; then + error "res(): function name is empty." + else + result_name="$1"; + fi; + shift; + eval "${result_name}"'="$('"$@"')"'; +} + + ######################################################################## +# obj_set ( ) +# +# Set the data of , i.e. call "$=". +# +# Arguments: 2 +# : a variable name +# : a string +# Output:: none +# +obj_set() +{ + func_check obj_set '=' 2 "$@"; + if is_empty "$1"; then + error "obj_set(): object name is empty." + fi; + eval "$1"='"$2"'; +} + ######################################################################## # path_chop () @@ -2738,16 +2648,16 @@ path_clean() local _dir; local _res; local i; - if test "$#" -ne 1; then + if is_not_equal "$#" 1; then error 'path_clean() needs 1 argument.'; fi; _arg="$1"; eval set -- "$(path_split "${_arg}")"; _res=""; for i in "$@"; do - if is_not_empty "$i" \ - && path_not_contains "${_res}" "$i" \ - && is_dir "$i"; + if obj i is_not_empty \ + && obj _res path_not_contains "$i" \ + && obj i is_dir; then case "$i" in ?*/) _res="${_res}$(dirname_chop "$i")"; ;; @@ -2822,15 +2732,6 @@ path_split() ######################################################################## -# reset () -# -# Reset the variables that can be affected by options to their default. -# -# -# Defined in section `Preset' after the rudimentary shell tests. - - -######################################################################## landmark '10: register_*()'; ######################################################################## @@ -2880,7 +2781,7 @@ register_title() # remove extension `.Z' _title="$(echo -n "${_title}" | sed -e 's/\.Z$//')"; - if is_empty "${_title}"; then + if obj _title is_empty; then eval "${return_ok}"; fi; _REGISTERED_TITLE="${_REGISTERED_TITLE} ${_title}"; @@ -2889,11 +2790,20 @@ register_title() ######################################################################## +# reset () +# +# Reset the variables that can be affected by options to their default. +# +# +# Defined in section `Preset' after the rudimentary shell tests. + + +######################################################################## # save_stdin () # # Store standard input to temporary file (with decompression). # -if test "${_HAS_COMPRESSION}" = 'yes'; then +if obj _HAS_COMPRESSION is_yes; then save_stdin() { local _f; @@ -2990,7 +2900,8 @@ tmp_create() { func_check tmp_create '<=' 1 "$@"; local _tmp; - _tmp="${_TMP_DIR}/$1"; + # the output file does not have `,' as first character + _tmp="${_TMP_DIR}/,$1"; echo -n >"${_tmp}"; echo -n "${_tmp}"; # output file name eval "${return_ok}"; @@ -3006,10 +2917,10 @@ to_tmp() { func_check to_tmp = 1 "$@"; if is_file "$1"; then - if is_yes "${_OPT_LOCATION}"; then + if obj _OPT_LOCATION is_yes; then echo2 "$1"; fi; - if is_yes "${_OPT_WHATIS}"; then + if obj _OPT_WHATIS is_yes; then what_is "$1" >>"${_TMP_CAT}"; else catz "$1" >>"${_TMP_CAT}"; @@ -3062,24 +2973,21 @@ trap_set() ######################################################################## # usage () # -# print usage information to stderr +# print usage information to stderr; for groffer option --help. # usage() { func_check usage = 0 "$@"; - echo2; + echo; version; - cat >&2 <&2 <&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /' >&2; @@ -3198,7 +3105,7 @@ what_is() # grep the line containing `.TH' macro, if any _res="$(catz "$1" | sed -e '/'"${_dot}"'TH /p d')"; - if is_not_empty "${_res}"; then # traditional man style + if obj _res is_not_empty; then # traditional man style # get the text between the first and the second `.SH' macro, by # - delete up to first .SH; # - of this, print everything up to next .SH, and delete the rest; @@ -3212,7 +3119,7 @@ d' \ # grep the line containing `.Dd' macro, if any _res="$(catz "$1" | sed -e '/'"${_dot}"'Dd /p d')"; - if is_not_empty "${_res}"; then # BSD doc style + if obj _res is_not_empty; then # BSD doc style # get the text between the first and the second `.Nd' macro, by # - delete up to first .Nd; # - of this, print everything up to next .Nd, and delete the rest; @@ -3244,7 +3151,7 @@ where() local _arg; local p; _arg="$1"; - if is_empty "${_arg}"; then + if obj _arg is_empty; then eval "${return_bad}"; fi; case "${_arg}" in @@ -3259,8 +3166,8 @@ where() eval set -- "$(path_split "${PATH}")"; for p in "$@"; do case "$p" in - */) _file=$p${_arg}; ;; - *) _file=$p/${_arg}; ;; + */) _file=${p}${_arg}; ;; + *) _file=${p}/${_arg}; ;; esac; if test -f "${_file}" && test -x "${_file}"; then echo -n "${_file}"; @@ -3302,46 +3209,56 @@ main_init() # call clean_up() on any signal trap_set clean_up; - for f in ${_CONFFILES}; do - if is_file "$f"; then - . "$f"; - fi; - done; - # determine temporary directory umask 000; _TMP_DIR=''; for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \ "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'; do - if test "$d" != ""; then - if test -d "$d" && test -r "$d" && test -w "$d"; then + if is_not_empty "$d"; then + if obj d is_dir && obj d is_writable; then _TMP_DIR="${d}/${_PROGRAM_NAME}${_PROCESS_ID}"; - if test -d "${_TMP_DIR}"; then + if obj _TMP_DIR is_dir; then rm -f "${_TMP_DIR}"/*; break; else mkdir "${_TMP_DIR}"; - if test ! -d "${_TMP_DIR}"; then - _TMP_DIR=''; + if obj _TMP_DIR is_not_dir; then + _TMP_DIR=''; continue; - fi; + fi; break; - fi; + fi; fi; - if test ! -w "${_TMP_DIR}"; then + if obj _TMP_DIR is_not_writable; then _TMP_DIR=''; continue; fi; fi; done; unset d; - if test "${_TMP_DIR}" = ''; then + if obj _TMP_DIR is_empty; then error "Couldn't create a directory for storing temporary files."; fi; _TMP_CAT="$(tmp_create groffer_cat)"; _TMP_STDIN="$(tmp_create groffer_input)"; + + # groffer configuration files + for f in ${_CONFFILES}; do + if obj f is_file; then + echo '_groffer_opt=""' >>${_TMP_CAT}; + # collect the lines starting with a minus + cat "$f" | sed -e \ + '/^[ ]*\(-.*\)$/s//_groffer_opt="${_groffer_opt} \1"'/ \ + >>${_TMP_CAT}; + # prepend the collected information to $GROFFER_OPT + echo 'GROFFER_OPT="${_groffer_opt} ${GROFFER_OPT}"' >>${_TMP_CAT}; + fi; + done; + . "${_TMP_CAT}"; + _TMP_CAT="$(tmp_create groffer_cat)"; + eval "${return_ok}"; } # main_init() @@ -3353,7 +3270,7 @@ main_init() # string; found man arguments can be overwritten by the command line. # # Globals: -# in: $MANOPT, $_OPTS_MAN_* +# in: $MANOPT, $_OPTS_MANOPT_* # out: $_MANOPT_* # in/out: $GROFFER_OPT # @@ -3364,45 +3281,45 @@ main_parse_MANOPT() local _opt; local _list; _list=''; - if test "${MANOPT}" != ''; then + if obj MANOPT is_not_empty; then MANOPT="$(echo -n "${MANOPT}" | \ sed -e 's/^'"${_SPACE}${_SPACE}"'*//')"; fi; - if test "${MANOPT}" = ''; then + if obj MANOPT is_empty; then eval "${return_ok}"; fi; # add arguments in $MANOPT by mapping them to groffer options eval set -- "$(list_from_cmdline \ - "${_OPTS_MAN_SHORT_NA}" "${_OPTS_MAN_SHORT_ARG}" \ - "${_OPTS_MAN_LONG_NA}" "${_OPTS_MAN_LONG_ARG}" \ + _OPTS_MANOPT_SHORT_NA _OPTS_MANOPT_SHORT_ARG \ + _OPTS_MANOPT_LONG_NA _OPTS_MANOPT_LONG_ARG \ "${MANOPT}")"; until test "$#" -le 0 || is_equal "$1" '--'; do _opt="$1"; shift; case "${_opt}" in -7|--ascii) - _list="$(list_append "${_list}" '--ascii')"; + list_append _list '--ascii'; ;; -a|--all) - _list="$(list_append "${_list}" '--all')"; + list_append _list '--all'; ;; -c|--catman) do_nothing; shift; ;; -d|--debug) - _list="$(list_append "${_list}" '--debug')"; + list_append _list '--debug'; ;; -D|--default) # undo all man options so far _list=''; ;; -e|--extension) - _list="$(list_append "${_list}" '--extension')"; + list_append _list '--extension'; shift; ;; -f|--whatis) - _list="$(list_append "${_list}" '--whatis')"; + list_append _list '--whatis'; shift; ;; -h|--help) @@ -3410,30 +3327,31 @@ main_parse_MANOPT() shift; ;; -k|--apropos) - _list="$(list_append "${_list}" '--apropos')"; + # groffer's --apropos takes an argument, but man's does not, so + do_nothing; shift; ;; -l|--local-file) - _list="$(list_append "${_list}" '--local-file')"; + list_append _list '--local-file'; ;; -L|--locale) - _list="$(list_append "${_list}" '--locale' "$1")"; + list_append _list '--locale' "$1"; shift; ;; -m|--systems) - _list="$(list_append "${_list}" '--systems' "$1")"; + list_append _list '--systems' "$1"; shift; ;; -M|--manpath) - _list="$(list_append "${_list}" '--manpath' "$1")"; + list_append _list '--manpath' "$1"; shift; ;; -p|--preprocessor) do_nothing; shift; ;; - -P|--pager) - _list="$(list_append "${_list}" '--pager' "$1")"; + -P|--pager|--tty-viewer) + list_append _list '--pager' "$1"; shift; ;; -r|--prompt) @@ -3441,7 +3359,7 @@ main_parse_MANOPT() shift; ;; -S|--sections) - _list="$(list_append "${_list}" '--sections' "$1")"; + list_append _list '--sections' "$1"; shift; ;; -t|--troff) @@ -3449,7 +3367,7 @@ main_parse_MANOPT() shift; ;; -T|--device) - _list="$(list_append "${_list}" '-T' "$1")"; + list_append _list '-T' "$1"; shift; ;; -u|--update) @@ -3460,16 +3378,21 @@ main_parse_MANOPT() do_nothing; ;; -w|--where|--location) - _list="$(list_append "${_list}" '--location')"; + list_append _list '--location'; ;; -Z|--ditroff) - _list="$(list_append "${_list}" '-Z' "$1")"; + list_append _list '-Z' "$1"; shift; ;; # ignore all other options esac; done; - GROFFER_OPT="$(list_from_lists "${_list}" "${GROFFER_OPT}")"; + # append the 2 lists in $_list and $GROFFER_OPT to $GROFFER_OPT + if obj GROFFER_OPT is_empty; then + GROFFER_OPT="${_list}"; + elif obj _list is_not_empty; then + GROFFER_OPT="${_list} ${GROFFER_OPT}"; + fi; eval "${return_ok}"; } # main_parse_MANOPT() @@ -3502,8 +3425,8 @@ main_parse_args() eval set -- "${GROFFER_OPT}" '"$@"'; eval set -- "$(list_from_cmdline \ - "$_OPTS_CMDLINE_SHORT_NA" "$_OPTS_CMDLINE_SHORT_ARG" \ - "$_OPTS_CMDLINE_LONG_NA" "$_OPTS_CMDLINE_LONG_ARG" \ + _OPTS_CMDLINE_SHORT_NA _OPTS_CMDLINE_SHORT_ARG \ + _OPTS_CMDLINE_LONG_NA _OPTS_CMDLINE_LONG_ARG \ "$@")"; # By the call of `eval', unnecessary quoting was removed. So the @@ -3526,9 +3449,9 @@ main_parse_args() -Q|--source) # output source code (`Quellcode'). _OPT_MODE='source'; ;; - -T|--device|--troff-device) - # device; arg + -T|--device|--troff-device) # device; arg _OPT_DEVICE="$1"; + _check_device_with_mode; shift; ;; -v|--version) @@ -3538,25 +3461,22 @@ main_parse_args() -V) _OPT_V='yes'; ;; - -X) - _OPT_X='yes'; - ;; - -Z|--ditroff|--intermediate-output) - # groff intermediate output + -Z|--ditroff|--intermediate-output) # groff intermediate output _OPT_Z='yes'; ;; + -X|--X|--x) + _OPT_MODE=x; + ;; -?) # delete leading `-' _optchar="$(echo -n "${_opt}" | sed -e 's/^.//')"; - if list_has "${_OPTS_GROFF_SHORT_NA}" "${_optchar}"; + if list_has _OPTS_GROFF_SHORT_NA "${_optchar}"; then - _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" \ - "${_opt}")"; - elif list_has "${_OPTS_GROFF_SHORT_ARG}" "${_optchar}"; + list_append _ADDOPTS_GROFF "${_opt}"; + elif list_has _OPTS_GROFF_SHORT_ARG "${_optchar}"; then - _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" \ - "${_opt}" "$1")"; - shift; + list_append _ADDOPTS_GROFF "${_opt}" "$1"; + shift; else error "Unknown option : \`$1'"; fi; @@ -3565,11 +3485,34 @@ main_parse_args() _OPT_ALL="yes"; ;; --ascii) - _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" \ - '-mtty-char')"; + list_append _ADDOPTS_GROFF '-mtty-char'; + if obj _mode is_empty; then + _mode='text'; + fi; ;; - --apropos) - _OPT_APROPOS="yes"; + --apropos) # run `apropos' + apropos_run "$1"; + _code="$?"; + clean_up; + exit "${_code}"; + ;; + --apropos-data) # run `apropos' for data sections + apropos_run "$1" | grep '^[^(]*([457])'; + _code="$?"; + clean_up; + exit "${_code}"; + ;; + --apropos-devel) # run `apropos' for development sections + apropos_run "$1" | grep '^[^(]*([239])'; + _code="$?"; + clean_up; + exit "${_code}"; + ;; + --apropos-progs) # run `apropos' for program sections + apropos_run "$1" | grep '^[^(]*([168])'; + _code="$?"; + clean_up; + exit "${_code}"; ;; --auto) # the default automatic mode _mode=''; @@ -3593,7 +3536,7 @@ main_parse_args() _OPT_DEFAULT_MODES="$1"; shift; ;; - --debug) # sequence of modes in auto mode; arg + --debug) # buggy, only for development _OPT_DEBUG='yes'; ;; --display) # set X display, arg @@ -3626,6 +3569,16 @@ main_parse_args() --groff) _OPT_MODE='groff'; ;; + --html|--www) # display with web browser + _OPT_MODE=html; + ;; + --html-viewer|--www-viewer) # viewer program for html mode; arg + _OPT_VIEWER_HTML="$1"; + shift; + ;; + --iconic) # start viewers as icons + _OPT_ICONIC='yes'; + ;; --locale) # set language for man pages, arg # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...) _OPT_LANG="$1"; @@ -3651,12 +3604,15 @@ main_parse_args() _arg="$1"; shift; case "${_arg}" in - auto|'') # the default automatic mode + auto|'') # search mode automatically among default _mode=''; ;; groff) # pass input to plain groff _mode='groff'; ;; + html|www) # display with a web browser + _mode='html'; + ;; dvi) # display with xdvi viewer _mode='dvi'; ;; @@ -3666,12 +3622,15 @@ main_parse_args() ps) # display with Postscript viewer _mode='ps'; ;; - X|x) # output on X roff viewer - _mode='x'; + text) # output on terminal + _mode='text'; ;; tty) # output on terminal _mode='tty'; ;; + X|x) # output on X roff viewer + _mode='x'; + ;; Q|source) # display source code _mode="source"; ;; @@ -3739,35 +3698,28 @@ main_parse_args() _OPT_SYSTEMS="$1"; shift; ;; + --text) # text mode without pager + _OPT_MODE=text; + ;; --title) # title for X viewers; arg _OPT_TITLE="$1"; shift; ;; - --tty) - _OPT_MODE="tty"; + --tty) # tty mode, text with pager + _OPT_MODE=tty; ;; - --tty-device) # device for tty mode; arg - _OPT_TTY_DEVICE="$1"; + --text-device|--tty-device) # device for tty mode; arg + _OPT_TEXT_DEVICE="$1"; shift; ;; --whatis) _OPT_WHATIS='yes'; ;; - --www) # display with web browser - _OPT_MODE='www'; - ;; - --www-viewer) # viewer program for www mode; arg - _OPT_VIEWER_WWW="$1"; - shift; - ;; - --x) - _OPT_MODE='x'; - ;; --xrm) # pass X resource string, arg; - _OPT_XRM="$(list_append "${_OPT_XRM}" "$1")"; + list_append _OPT_XRM "$1"; shift; ;; - --x-viewer) # viewer program for x mode; arg + --x-viewer|--X-viewer) # viewer program for x mode; arg _OPT_VIEWER_X="$1"; shift; ;; @@ -3778,25 +3730,66 @@ main_parse_args() done; shift; # remove `--' argument - if test "${_DEBUG}" != 'yes'; then - if test "${_OPT_DEBUG}" = 'yes'; then + if obj _DEBUG is_not_yes; then + if obj _OPT_DEBUG is_yes; then _DEBUG='yes'; fi; fi; # Remaining arguments are file names (filespecs). # Save them to list $_FILEARGS - if test "$#" -eq 0; then # use "-" for standard input + if is_equal "$#" 0; then # use "-" for standard input set -- '-'; fi; - _FILEARGS="$(list_from_args "$@")"; - if list_has "$_FILEARGS" '-'; then + _FILEARGS=''; + list_append _FILEARGS "$@"; + if list_has _FILEARGS '-'; then save_stdin; fi; # $_FILEARGS must be retrieved with `eval set -- "$_FILEARGS"' eval "${return_ok}"; } # main_parse_args() +# Called from main_parse_args() because double `case' is not possible. +# Globals: $_OPT_DEVICE, $_OPT_MODE +_check_device_with_mode() +{ + func_check _check_device_with_mode = 0 "$@"; + case "${_OPT_DEVICE}" in + dvi) + _OPT_MODE=dvi; + eval "${return_ok}"; + ;; + html) + _OPT_MODE=html; + eval "${return_ok}"; + ;; + lbp|lj4) + _OPT_MODE=groff; + eval "${return_ok}"; + ;; + ps) + _OPT_MODE=ps; + eval "${return_ok}"; + ;; + ascii|cp1047|latin1|utf8) + if obj _OPT_MODE is_not_equal text; then + _OPT_MODE=tty; # default text mode + fi; + eval "${return_ok}"; + ;; + X*) + _OPT_MODE=x; + eval "${return_ok}"; + ;; + *) # unknown device, go to groff mode + _OPT_MODE=groff; + eval "${return_ok}"; + ;; + esac; + eval "${return_error}"; +} + ######################################################################## # main_set_mode () @@ -3829,38 +3822,52 @@ main_set_mode() local _viewers; # handle apropos - if is_yes "${_OPT_APROPOS}"; then - apropos "$@"; + if obj _OPT_APROPOS is_not_empty; then + apropos "${_OPT_APROPOS}"; + _code="$?"; + clean_up; + exit "${_code}"; + fi; + if obj _OPT_APROPOS_DATA is_not_empty; then + apropos "$@" | grep '^[^(]*([457])'; + _code="$?"; + clean_up; + exit "${_code}"; + fi; + if obj _OPT_APROPOS_DEVEL is_not_empty; then + apropos "$@" | grep '^[^(]*([239])'; + _code="$?"; + clean_up; + exit "${_code}"; + fi; + if obj _OPT_APROPOS_PROGS is_not_empty; then + apropos "$@" | grep '^[^(]*([168])'; _code="$?"; clean_up; exit "${_code}"; fi; # set display - if is_not_empty "${_OPT_DISPLAY}"; then + if obj _OPT_DISPLAY is_not_empty; then DISPLAY="${_OPT_DISPLAY}"; fi; - if is_yes "${_OPT_V}"; then - _DISPLAY_MODE='groff'; - _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" '-V')"; - fi; - if is_yes "${_OPT_X}"; then + if obj _OPT_V is_yes; then _DISPLAY_MODE='groff'; - _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" '-X')"; + list_append _ADDOPTS_GROFF '-V'; fi; - if is_yes "${_OPT_Z}"; then + if obj _OPT_Z is_yes; then _DISPLAY_MODE='groff'; - _ADDOPTS_GROFF="$(list_append "${_ADDOPTS_GROFF}" '-Z')"; + list_append _ADDOPTS_GROFF '-Z'; fi; - if is_equal "${_OPT_MODE}" 'groff'; then + if obj _OPT_MODE is_equal 'groff'; then _DISPLAY_MODE='groff'; fi; - if is_equal "${_DISPLAY_MODE}" 'groff'; then + if obj _DISPLAY_MODE is_equal 'groff'; then eval "${return_ok}"; fi; - if is_equal "${_OPT_MODE}" 'source'; then + if obj _OPT_MODE is_equal 'source'; then _DISPLAY_MODE='source'; eval "${return_ok}"; fi; @@ -3869,34 +3876,40 @@ main_set_mode() '') # automatic mode case "${_OPT_DEVICE}" in X*) - if is_empty "${DISPLAY}"; then + if obj DISPLAY is_empty; then error "no X display found for device ${_OPT_DEVICE}"; fi; _DISPLAY_MODE='x'; eval "${return_ok}"; ;; ascii|cp1047|latin1|utf8) - _DISPLAY_MODE='tty'; + if obj _DISPLAY_MODE is_not_equal 'text'; then + _DISPLAY_MODE='tty'; + fi; eval "${return_ok}"; ;; esac; - if is_empty "${DISPLAY}"; then + if obj DISPLAY is_empty; then _DISPLAY_MODE='tty'; eval "${return_ok}"; fi; - if is_empty "${_OPT_DEFAULT_MODES}"; then + if obj _OPT_DEFAULT_MODES is_empty; then _modes="${_DEFAULT_MODES}"; else _modes="${_OPT_DEFAULT_MODES}"; fi; ;; + text) + _DISPLAY_MODE='text'; + eval "${return_ok}"; + ;; tty) _DISPLAY_MODE='tty'; eval "${return_ok}"; ;; *) # display mode was given - if is_empty "${DISPLAY}"; then + if obj DISPLAY is_empty; then error "you must be in X Window for ${_OPT_MODE} mode."; fi; _modes="${_OPT_MODE}"; @@ -3909,18 +3922,22 @@ main_set_mode() m="$1"; shift; case "$m" in + text) + _DISPLAY_MODE='text'; + eval "${return_ok}"; + ;; tty) _DISPLAY_MODE='tty'; eval "${return_ok}"; ;; x) - if is_not_empty "${_OPT_VIEWER_X}"; then + if obj _OPT_VIEWER_X is_not_empty; then _viewers="${_OPT_VIEWER_X}"; else _viewers="${_VIEWER_X}"; fi; _viewer="$(_get_first_prog "${_viewers}")"; - if test "$?" -ne 0; then + if is_not_equal "$?" 0; then continue; fi; _DISPLAY_PROG="${_viewer}"; @@ -3928,13 +3945,13 @@ main_set_mode() eval "${return_ok}"; ;; dvi) - if is_not_empty "${_OPT_VIEWER_DVI}"; then + if obj _OPT_VIEWER_DVI is_not_empty; then _viewers="${_OPT_VIEWER_DVI}"; else _viewers="${_VIEWER_DVI}"; fi; _viewer="$(_get_first_prog "${_viewers}")"; - if test "$?" -ne 0; then + if is_not_equal "$?" 0; then continue; fi; _DISPLAY_PROG="${_viewer}"; @@ -3942,13 +3959,13 @@ main_set_mode() eval "${return_ok}"; ;; pdf) - if is_not_empty "${_OPT_VIEWER_PDF}"; then + if obj _OPT_VIEWER_PDF is_not_empty; then _viewers="${_OPT_VIEWER_PDF}"; else _viewers="${_VIEWER_PDF}"; fi; _viewer="$(_get_first_prog "${_viewers}")"; - if test "$?" -ne 0; then + if is_not_equal "$?" 0; then continue; fi; _DISPLAY_PROG="${_viewer}"; @@ -3956,31 +3973,31 @@ main_set_mode() eval "${return_ok}"; ;; ps) - if is_not_empty "${_OPT_VIEWER_PS}"; then + if obj _OPT_VIEWER_PS is_not_empty; then _viewers="${_OPT_VIEWER_PS}"; else _viewers="${_VIEWER_PS}"; fi; _viewer="$(_get_first_prog "${_viewers}")"; - if test "$?" -ne 0; then + if is_not_equal "$?" 0; then continue; fi; _DISPLAY_PROG="${_viewer}"; _DISPLAY_MODE="ps"; eval "${return_ok}"; ;; - www) - if is_not_empty "${_OPT_VIEWER_WWW}"; then - _viewers="${_OPT_VIEWER_WWW}"; + html) + if obj _OPT_VIEWER_HTML is_not_empty; then + _viewers="${_OPT_VIEWER_HTML}"; else - _viewers="${_VIEWER_WWW}"; + _viewers="${_VIEWER_HTML}"; fi; _viewer="$(_get_first_prog "${_viewers}")"; - if test "$?" -ne 0; then + if is_not_equal "$?" 0; then continue; fi; _DISPLAY_PROG="${_viewer}"; - _DISPLAY_MODE="www"; + _DISPLAY_MODE=html; eval "${return_ok}"; ;; esac; @@ -3991,7 +4008,7 @@ main_set_mode() _get_first_prog() { local i; - if test "$#" -eq 0; then + if is_equal "$#" 0; then error "_get_first_prog() needs 1 argument."; fi; if is_empty "$1"; then @@ -3999,7 +4016,7 @@ _get_first_prog() fi; eval set -- "$(list_from_split "$1" ',')"; for i in "$@"; do - if is_empty "$i"; then + if obj i is_empty; then continue; fi; if is_prog "$(get_first_essential $i)"; then @@ -4045,7 +4062,7 @@ main_do_fileargs() continue; ;; ?) - if list_has_not "${_MAN_AUTO_SEC}" "${_filespec}"; then + if list_has_not _MAN_AUTO_SEC "${_filespec}"; then if do_filearg "${_filespec}"; then _exitcode="${_GOOD}"; fi; @@ -4097,7 +4114,9 @@ main_do_fileargs() ######################################################################## # main_set_resources () # -# Determine options for setting X resources with $_DISPLAY_PROG. +# Determine options for setting X resources with $_DISPLAY_PROG. +# +# Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME # landmark '18: main_set_resources()'; main_set_resources() @@ -4105,70 +4124,107 @@ main_set_resources() func_check main_set_resources = 0 "$@"; local _prog; # viewer program local _rl; # resource list - _rl=''; - if is_empty "${_DISPLAY_PROG}"; then + local n; + _title="$(get_first_essential \ + "${_OPT_TITLE}" "${_REGISTERED_TITLE}")"; + _OUTPUT_FILE_NAME=''; + set -- ${_title}; + until is_equal "$#" 0; do + n="$1"; + case "$n" in + '') + continue; + ;; + ,*) + n="$(echo -n "$1" | sed -e '/^,,*/s///')"; + ;; + esac + if obj n is_empty; then + continue; + fi; + if obj _OUTPUT_FILE_NAME is_not_empty; then + _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME},"; + fi; + _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}$n"; + shift; + done; + case "${_OUTPUT_FILE_NAME}" in + '') + _OUTPUT_FILE_NAME='-'; + ;; + ,*) + error "$_OUTPUT_FILE_NAME starts with a comma."; + ;; + esac; + _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}"; + + if obj _DISPLAY_PROG is_empty; then # for example, for groff mode + _DISPLAY_ARGS=''; eval "${return_ok}"; fi; + set -- ${_DISPLAY_PROG}; _prog="$(base_name "$1")"; - if is_not_empty "${_OPT_BD}"; then + _rl=''; + if obj _OPT_BD is_not_empty; then case "${_prog}" in ghostview|gv|gxditview|xditview|xdvi) - _rl="$(list_append "$_rl" '-bd' "${_OPT_BD}")"; + list_append _rl '-bd' "${_OPT_BD}"; ;; esac; fi; - if is_not_empty "${_OPT_BG}"; then + if obj _OPT_BG is_not_empty; then case "${_prog}" in ghostview|gv|gxditview|xditview|xdvi) - _rl="$(list_append "$_rl" '-bg' "${_OPT_BG}")"; + list_append _rl '-bg' "${_OPT_BG}"; ;; xpdf) - _rl="$(list_append "$_rl" '-papercolor' "${_OPT_BG}")"; + list_append _rl '-papercolor' "${_OPT_BG}"; ;; esac; fi; - if is_not_empty "${_OPT_BW}"; then + if obj _OPT_BW is_not_empty; then case "${_prog}" in ghostview|gv|gxditview|xditview|xdvi) - _rl="$(list_append "$_rl" '-bw' "${_OPT_BW}")"; + _list_append _rl '-bw' "${_OPT_BW}"; ;; esac; fi; - if is_not_empty "${_OPT_FG}"; then + if obj _OPT_FG is_not_empty; then case "${_prog}" in ghostview|gv|gxditview|xditview|xdvi) - _rl="$(list_append "$_rl" '-fg' "${_OPT_FG}")"; + list_append _rl '-fg' "${_OPT_FG}"; ;; esac; fi; if is_not_empty "${_OPT_FN}"; then case "${_prog}" in ghostview|gv|gxditview|xditview|xdvi) - _rl="$(list_append "$_rl" '-fn' "${_OPT_FN}")"; + list_append _rl '-fn' "${_OPT_FN}"; ;; esac; fi; if is_not_empty "${_OPT_GEOMETRY}"; then case "${_prog}" in ghostview|gv|gxditview|xditview|xdvi|xpdf) - _rl="$(list_append "$_rl" '-geometry' "${_OPT_GEOMETRY}")"; + list_append _rl '-geometry' "${_OPT_GEOMETRY}"; ;; esac; fi; if is_empty "${_OPT_RESOLUTION}"; then + _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}"; case "${_prog}" in gxditview|xditview) - _rl="$(list_append "$_rl" \ - '-resolution' "${_DEFAULT_RESOLUTION}")"; + list_append _rl '-resolution' "${_DEFAULT_RESOLUTION}"; ;; xpdf) case "${_DEFAULT_RESOLUTION}" in 75) - _rl="$(list_append "$_rl" '-z' '2')"; + # 72dpi is '100' + list_append _rl '-z' '104'; ;; 100) - _rl="$(list_append "$_rl" '-z' '3')"; + list_append _rl '-z' '139'; ;; esac; ;; @@ -4176,24 +4232,32 @@ main_set_resources() else case "${_prog}" in ghostview|gv|gxditview|xditview|xdvi) - _rl="$(list_append "$_rl" '-resolution' "${_OPT_RESOLUTION}")"; + list_append _rl '-resolution' "${_OPT_RESOLUTION}"; ;; xpdf) case "${_OPT_RESOLUTION}" in 75) - _rl="$(list_append "$_rl" '-z' '2')"; + list_append _rl '-z' '104'; + # '100' corresponds to 72dpi ;; 100) - _rl="$(list_append "$_rl" '-z' '3')"; + list_append _rl '-z' '139'; ;; esac; ;; esac; fi; - if is_not_empty "${_OPT_RV}"; then + if is_yes "${_OPT_ICONIC}"; then + case "${_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + list_append _rl '-iconic'; + ;; + esac; + fi; + if is_yes "${_OPT_RV}"; then case "${_prog}" in ghostview|gv|gxditview|xditview|xdvi) - _rl="$(list_append "$_rl" '-rv')"; + list_append _rl '-rv'; ;; esac; fi; @@ -4202,21 +4266,20 @@ main_set_resources() ghostview|gv|gxditview|xditview|xdvi|xpdf) eval set -- "{$_OPT_XRM}"; for i in "$@"; do - _rl="$(list_append "$_rl" '-xrm' "$i")"; + list_append _rl '-xrm' "$i"; done; ;; esac; fi; - _title="$(get_first_essential \ - "${_OPT_TITLE}" "${_REGISTERED_TITLE}")"; if is_not_empty "${_title}"; then case "${_prog}" in gxditview|xditview) - _rl="$(list_append "$_rl" '-title' "${_title}")"; + list_append _rl '-title' "${_title}"; ;; esac; fi; _DISPLAY_ARGS="${_rl}"; + eval "${return_ok}"; } # main_set_resources @@ -4248,17 +4311,16 @@ main_display() export _groggy; export _modefile; - # Some display programs have trouble with empty input. - # This is avoided by feeding a space character in this case. - # Test on non-empty file by tracking a line with at least 1 character. - if is_empty "$(tmp_cat | sed -e '/./q')"; then - echo ' ' > "${_TMP_CAT}"; + if obj _TMP_CAT is_non_empty_file; then + _modefile="${_OUTPUT_FILE_NAME}"; + else + clean_up; + eval "${return_ok}"; fi; - case "${_DISPLAY_MODE}" in groff) _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}"; - if is_not_empty "${_OPT_DEVICE}"; then + if obj _OPT_DEVICE is_not_empty; then _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}"; fi; _groggy="$(tmp_cat | eval grog "${_options}")"; @@ -4266,26 +4328,26 @@ main_display() # start a new shell program to get another process ID. sh -c ' set -e; - _PROCESS_ID="$$"; - _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}"; - rm -f "${_modefile}"; + test -f "${_modefile}" && rm -f "${_modefile}"; mv "${_TMP_CAT}" "${_modefile}"; - rm -f "${_TMP_CAT}"; cat "${_modefile}" | \ ( clean_up() { - rm -f "${_modefile}"; + if test -d "${_TMP_DIR}"; then + rm -f "${_TMP_DIR}"/* || true; + rmdir "${_TMP_DIR}"; + fi; } trap clean_up 0 2>/dev/null || true; eval "${_groggy}" "${_ADDOPTS_GROFF}"; ) &' ;; - tty) + text|tty) case "${_OPT_DEVICE}" in '') _device="$(get_first_essential \ - "${_OPT_TTY_DEVICE}" "${_DEFAULT_TTY_DEVICE}")"; + "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")"; ;; ascii|cp1047|latin1|utf8) _device="${_OPT_DEVICE}"; @@ -4297,19 +4359,23 @@ main_display() esac; _addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}"; _groggy="$(tmp_cat | grog -T${_device})"; - _pager=''; - for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \ - 'less' 'more' 'cat'; do - if is_prog "$p"; then + if obj _DISPLAY_MODE is_equal 'text'; then + tmp_cat | eval "${_groggy}" "${_addopts}"; + else + _pager=''; + for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \ + 'less -r -R' 'more' 'pager' 'cat'; do + if is_prog $p; then # no "" for is_prog() allows args for $p _pager="$p"; break; fi; - done; - if is_empty "${_pager}"; then - error 'no pager program found for tty mode'; + done; + if obj _pager is_empty; then + error 'no pager program found for tty mode'; + fi; + tmp_cat | eval "${_groggy}" "${_addopts}" | \ + eval "${_pager}"; fi; - tmp_cat | eval "${_groggy}" "${_addopts}" | \ - eval "${_pager}"; clean_up; ;; @@ -4326,6 +4392,18 @@ main_display() _groggy="$(tmp_cat | grog -Tdvi)"; _do_display; ;; + html) + case "${_OPT_DEVICE}" in + ''|html) do_nothing; ;; + *) + warning \ + "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; + ;; + esac; + _modefile="${_modefile}".html + _groggy="$(tmp_cat | grog -Thtml)"; + _do_display; + ;; pdf) case "${_OPT_DEVICE}" in ''|ps) @@ -4336,26 +4414,29 @@ main_display() "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; ;; esac; + _modefile="${_modefile}" _groggy="$(tmp_cat | grog -Tps)"; trap_clean; # start a new shell program to get another process ID. sh -c ' set -e; - _PROCESS_ID="$$"; - _psfile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}"; - _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}.pdf"; - rm -f "${_psfile}"; - rm -f "${_modefile}"; + _psfile="${_modefile}.ps"; + _modefile="${_modefile}.pdf"; + test -f "${_psfile}" && rm -f "${_psfile}"; + test -f "${_modefile}" && rm -f "${_modefile}"; cat "${_TMP_CAT}" | \ - eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}"; + eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}"; gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \ -sOutputFile="${_modefile}" -c save pop -f "${_psfile}"; - rm -f "${_psfile}"; - rm -f "${_TMP_CAT}"; + test -f "${_psfile}" && rm -f "${_psfile}"; + test -f "${_TMP_CAT}" && rm -f "${_TMP_CAT}"; ( - clean_up() - { + clean_up() { rm -f "${_modefile}"; + if test -d "${_TMP_DIR}"; then + rm -f "${_TMP_DIR}"/* || true; + rmdir "${_TMP_DIR}"; + fi; } trap clean_up 0 2>/dev/null || true; eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${_modefile}"; @@ -4378,17 +4459,6 @@ main_display() tmp_cat; clean_up; ;; - www) - case "${_OPT_DEVICE}" in - ''|html) do_nothing; ;; - *) - warning \ - "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; - ;; - esac; - _groggy="$(tmp_cat | grog -Thtml)"; - _do_display; - ;; x) case "${_OPT_DEVICE}" in '') @@ -4414,22 +4484,20 @@ main_display() _do_display() { + func_check _do_display = 0 "$@"; trap_clean; # start a new shell program for another process ID and better # cleaning-up of the temporary files. sh -c ' set -e; - _PROCESS_ID="$$"; - _modefile="${_TMP_DIR}/${_PROGRAM_NAME}${_PROCESS_ID}"; - rm -f "${_modefile}"; + test -f "${_modefile}" && rm -f "${_modefile}"; cat "${_TMP_CAT}" | \ eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_modefile}"; rm -f "${_TMP_CAT}"; ( - clean_up() - { + clean_up() { if test -d "${_TMP_DIR}"; then - rm -f "${_TMP_DIR}"/*; + rm -f "${_TMP_DIR}"/* || true; rmdir "${_TMP_DIR}"; fi; } -- 2.11.4.GIT