diff -u -r --new-file groff-1.19.1/contrib/groffer/ChangeLog groff-1.19.2/contrib/groffer/ChangeLog --- groff-1.19.1/contrib/groffer/ChangeLog 2004-04-30 00:37:39.000000000 -0700 +++ groff-1.19.2/contrib/groffer/ChangeLog 2005-08-22 15:11:05.000000000 -0700 @@ -1,3 +1,749 @@ + ________________________________________________________________ + * release of groffer 0.9.22 + +2005-22-04 Bernd Warken + + ### `--whatis' + + Produce a `groff' output and allow wild cards on filespec + parameters for `--whatis'. + + * groffer2.sh: + - $_FILESPEC_ARG: New variable for storing the actual filespec + parameter. + - main_do_fileargs(): Set $_FILESPEC_ARG and add + what_is_filespec(). + - main_parse_args(): Add --all to --whatis. + - to_tmp_line(): New function to write the arguments to the + temorary cat file. + - whatis_filename(): Rename of what_is(). Construct a better + printout using $_FILESPEC_ARG. Repair the sed sequneces. + - whatis_filespec(): New function to print the filespec once + during the `whatis' process. + - whatis_header(): New funtion for printing the header of the + `whatis' output. + + * groffer.man: Revise the documentation of --whatis. + + ### `--apropos*' + + Produce `groff' for `--apropos*'. Allow `--sections' for + `--apropos', ignore it with `--apropos-*'. + + * groffer2.sh: + - --apropos*: Make these options without argument. + - $_APROPOS_PROG: New variable for the program that is is used for + `apropos'. + - $_APROPOS_SECTIONS: New variable to determine the sections that + are filtered out of `apropos' output depending on `--apropos-*'. + - apropos_filespec(): Handling of apropos at the filespec level. + - apropos_run(): Remove it. + - apropos_setup(): New function. + - main_set_mode(): Remove handling of $_OPT_APROPOS*. + + * groffer.man: + - Revise the documentation of `--apropos*'. + - Split section 'options for GNU man' into two sections `options + for man pages' and `long options taken over from GNU man'. + - Move `--apropos*', `--whatis', `--man', and `--no-man' to + section `options for man pages'. + + ### special display (apropos and whatis) + + * groffer2.sh: + - special_setup(): New function that chooses the setup between + apropos and whatis. + - special_filespec(): New function that does the output at the + filespec level for apropos or whatis. + + ### handle `--sections' for man page searching + + * groffer2.sh: + - man_do_filespec(): Use $_OPT_SECTIONS of --sections instead of + $_MAN_AUTO_SEC if non-empty. If a section was given on the + filespec parameter $_OPT_SECTIONS is ignored. This differs from + `man' which always uses the restricted sections of --sections. + This function works for both normal man page search and whatis. + - apropos_filespec(): Use --sections for --apropos, but not for + --apropos-* because these provide already their own sections. + + ### wildcards in filespec arguments + + * groffer2.sh: Wildcards are now accepted. In `--apropos*' and + `--whatis' they are interpreted as wildcard search elements; but + in normal display they are only handled as their own character. + + ### development; new option + + * groffer2.sh: + - --print: New option that prints just its argument for parameter + check. + - usage(): Add new option. + - $_OPT_DO_NOTHING: New variable for do_nothing(). Handle it at + the end of main_parse_Args(). + + * groffer.man: Add information on --print. + + ### safe exit + + * groffer2.sh: + - error(): Always exit with $_ERROR. + - exit_test(): New function to exit when first exit was hidden by + (). Call it after each $(). + + ### automatic shell determination + + * groffer.sh: + - If no option --shell is given perform a test of several shells + to automatically start some shell for groffer2.sh. `ksh' is used + first because it can be safely terminated by Ctrl-C. + - This can be cancelled by providing --shell=''. + - Add test on `sed' program. + + * groffer.man: Revise information on --shell. + + ### trap + + * groffer2.sh: + - trap_set(): Remove argument. Instead of $_ALL_EXIT use only + signal 0. + - trap_unset(): Rename trap_clean(). Instead of $_ALL_EXIT use + only signal 0. + - $_ALL_EXIT: Remove this variable. + - Replace all direct `trap' calls by trap_set(). + + * README_SH: New section `Bugs' on `trap'.. + + ### user errors, error output without function stack + + * groffer2.sh: + - error_user(): New function for user errors. + - error(): Remove call of clean_up() because the trap will do it + with the exit. Remove the `kill' commands. Create a temporary + file `.error' that can be tested by exit_test() for a better exit + test (especially for shell `ksh'). + - $_DEBUG_USER_WITH_STACK: New variable to enable function stack + output in error_user(). + - list_from_cmdline(), list_single_from_abbrev(), main_set_mode(): + Use error_user(). + + ### test modes on X and tty + + * groffer2,sh: + - is_X(), is_not_X(): New functions for checking on X Window. + - $_VIEWER_HTML_TTY, $_VIEWER_HTML_X: New variables that split + $_VIEWER_HTML. Add `galeon'. + - main_parse_args(): Allow mode change for graphical modes only + when in X Window. + - _do_display() of main_display(): Create a special run for + viewers that run on the terminal; `lynx' is the only one so far. + + ### add $GROFFER_MODE to command line + + * groffer.sh: + - After the handling of the configuration files integrate + $GROFFER_OPT to the command line. + - This makes a `set' in the shell determination unnecessary. + + * groffer2.sh: + - The debug test gets simpler because quotes are vanished without + $GROFFER_OPT. + - main_parse_MANOPT(): Prepend $mpm_list to the command line. + - main_parse_args(): `set' is unnecessary. + + ### debug; new options + + * groffer2.sh: + - --debug-all, --debug-lm, --debug-params, --debug-shell, + --debug-stacks, --debug-tmpdir, --debug-user: New options. + - --debug: Enable all debug variables except $_DEBUG_STACKS and + $_DEBUG_LM. By the new options the smallest abbreviation is now + `--debug'. + - $_DEBUG_STACKS: Rename $_DEBUG. + - $_DEBUG_PRINT_TMPDIR: New debug variable for printing the name + of the temporary directory in main_init(). + - $_OPT_DEBUG: Remove this variable because debug is handled at + the early part of the script. + - clean_up(): Enlarge $_DEBUG_KEEP_FILES to not deleting the + temporary directory. + - usage(): Move all development options on a section of its own. + - Move the test of rudimentary shell functionality at the + beginning of the script. Add test on `sed'. + - Follow this by the debug section. The determination of all + --debug* options can be done without a function. + + * groffer.man: Revise information on --debug and add new options. + + ### variables + + * groffer.sh: + - $_ERROR: Move the definition of this variable here. + - $_GROFF_VERSION: New variable, is set over @...@ construct. + - $_OUTPUT_FILE_NAME: Move this variable to groffer2.sh. + + * groffer2.sh: + - $_MAN_AUTO_SEC_LIST: Rename $_MAN_AUTO_SEC because it represents + a list. + - $_MAN_AUTO_SEC_CHARS: New read-only variable for storing + $_MAN_AUTO_SEC_LIST in [] construct. Use it in man_do_filespec() + and whatis_filename(). + - $_SPACE_CASE: New read-only variable with [] on space characters + with \ for `case' patterns. Use it in several functions. + - $_SPACE_SED: New read-only variable with [] on space characters + for `sed'. Use it in several functions. + + ### options and display + + * groffer2.sh: + - list_from_cmdline(): Add test whether the same abbreviation is + part of long options with and without arguments. Give handling of + `=' a `case' pattern of its own. + - main_display(): Remove unnecessary calls of `clean_up' in order + to use `mozilla' without problems. In _do_display(): Fix -X by + providing a different process when $_DISPLAY_PROG is empty. + - main_set_mode(): Accept options for viewers as is, without check + for program. Add test whether no program is given for a mode. + This avoids unnecessary empty $_DISPLAY_PROG in main_display(). + + ### viewer programs that run on the terminal (tty); new options + + * groffer2.sh: + - $_VIEWER_TERMINAL: New variable that stores whether a viewer was + supposed to run on tty. + - --dvi-viewer-tty, --html-viewer-tty, --pdf-viewer-tty, + --ps-viewer-tty, --tty-viewer-tty, --X-viewer-tty, --x-viewer-tty, + --www-viewer-tty: New options for viewers that run on a terminal. + - main_parse_args(), _do_display() of main_display(): Use the new + options and the new variable. + - usage(): Add the new options. + + * groffer.man: Add information on options --*-viewer-tty. + + ### other fixes + + * groffer2.sh: + - _do_display() of main_display(): Bear errors of `groff' run. + - is_not_file: Fix to have exactly one argument. + - is_not_prog(): Handle no arguments. + - list_has_not(): Fix. + - main_do_fileargs(): Remove $mdfa_exitcode. + - register_title(): Limit title to 4 elements. + - version(): Print the version information to standard output just + like `groff' does. + - --no-special: New option to disable former calls of `--all', + `--apropos*', and `whatis. + - --title: Make it an option with argument. + +2005-08-07 Keith Marshall + + * contrib/groffer/Makefile.sub (install): Reference groffer2.sh + as $(srcdir)/groffer2.sh, so it will install when building in a + different directory from the source. + + ________________________________________________________________ + * release of groffer 0.9.21 + +2005-08-02 Bernd Warken + + ### @...@ constructs + + * groffer.sh: + - $_AT: New variable for `@'. + - @...@: Replace the @...@ constructs by variables _AT_..._AT. + These constructs are transformed by `make' to useful information. + Keep all of these constructs in the first part of groffer.sh. For + a run before a `make' call, the script sets these variables to + special values for testing purpose. + - $_GROFFER_LIBDIR: Variable pointing to the groffer library + directory @libdir@/groff/groffer. + + ### Configuration files + + * groffer.sh: + - Add test for `$()' construct. + - Read and transform the configuration files and execute the + emerging commands. The `sed' script was heavily enlarged to + handle line with spaces and quotes. The emerging script is now + called by `eval', so no temporary file is needed. + - $_CONF_FILE_ETC, $_CONF_FILE_HOME: New variables for the config + files. + - $_SQ, $_SP: Move variables for characters before the handling of + the configuration files. Rename $_SQUOTE to $_SQ and $_SPACE to + $_SP. + - $GROFFER_OPT: Remove cleaning of this variable before the + reading of the configuration files. + + * groffer2.sh: + - main_init(): Remove the getting of the configuration files. + + ### Rewrite the shell determination + + * groffer.sh: + - Get rid of all functions in `groffer.sh'. Rewrite the shell + determination with `` and $(). + - --shell: Shortest abbreviation is `--sh'. Allow arguments for + the shell name. + - Allow an empty argument for --shell as shell name to overwrite a + specified shell; an empty shell name gets back to the default + shell. + - The shell determination now inludes the full handling of the + config files. The `--shell' option needs no longer a line + starting with `-'. + + ### Test of unset + + * groffer.sh: + - Remove test of `unset'. + - Remove all calls of `unset'. + - Use one character names for all variables that are meant to be + local in this script. + + * groffer2.sh: + - Move the test of `unset' to the testing of rudimentary shell + functionality without change. + + ### Allow abbreviations for long options + + * groffer2.sh: + - list_has_abbrev(): New function for checking a list having an + element with a given abbreviation. + - list_get_single_from_abbrev(): New function to retrieve the + element having a given abbreviation. + - list_from_cmd_line(): For an option abbreviation determine the + corresponding long option. + - From the man option lists remove the elements that are also in + a groffer list. + - Allow abbreviation for the early test of --debug. + + * groffer.sh: Allow abbreviation for the early test on --shell. + - get_opt_shell(): Rewrite _get_opt_shell() and the shell test + around it. + - test_on_shell(): Rename function _test_on_shell(). + - $_SHELL: global variable for the shell to run groffer2.sh. + + ### Get rid of `sh -c' + + * groffer2.sh: + - main_display(), _do_display(): Remove the `sh -c' calls. Make + the cleanup working without it. + - _do_display(): Extend _do_display() such that it can be used for + the pdf mode as well. + - _make_pdf(): New subfunction of main_display() for running the + additional parts of pdf mode in _do_display(). + - rm_file(), rm_file_with_debug(), rm_tree(): New functions for + removing files and directories. + + ### Change directory + + * groffer2.sh: + - $_START_DIR: New variable to store the directory at the starting + time of the script. + - main_display(): Go to the groffer temporary directory to be able + to process internal `groff' data like pictures. + - clean_up(): Get back to the starting directory. + + ### Compatibility with strange shells + + * groffer2.sh: + - clean_up(): `zsh' and `posh' had difficulties with `eval'. + - is_*(): Add test on empty argument. Some shells return true on + `test -d' etc. with empty argument, while most shells return + false. + - echo1(); New function to print single line `cat <file' for generating an empty file. + - rmdir: Replace `rmdir' by `rm -f -r'. + - eval: Add `eval' to many commands with variable arguments. + + * groffer.sh: repair `debug' + - Print all debug output to stderr. + - $_FUNC_STACK: Built function call stack even when $_DEBUG is not + set. Now the arguments are not added. + - $_DEBUG: If set to `yes' print 3 call stack events: the function + that is added with its arguments is printed with `+++ ' + (func_push()); the call stack after the addition is printed with + `>>> ' (func_push()); the call stack after the removing is printed + with `<<< ' (func_pop()). + - error(): Always print the function call stack on errors. + + * groffer.sh: Corrections + - $_groffer_run: Rename to $_GROFFER_RUN. + - $unset: Rename to $_UNSET. + - Repair test of `unset'. + - Repair test for `--shell'. The script is now rerun under the + shell specified in the option argument. This can increase the + speed. + + * README_SH: `zsh' now works. + + * groffer.man: + - Reformulate the information for the `groffer' specific details + of option `-V'. + - Add information on the debug process. + - Add information on the default devices in `x mode'. + - Minor corrections. + + ________________________________________________________________ + * release of groffer 0.9.18 + +2005-07-01 Bernd Warken + + * groffer.sh: further shell compatibility + - `echo': Remove options and possible options of `echo' by + preceding the argument with a character `x' that is removed by + `sed' or replace `echo' by `cat </README_SH - + ******* Extension of the `apropos' handling The output of man's `apropos' has grown immensely meanwhile, so it @@ -80,7 +826,7 @@ 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. @@ -102,7 +848,7 @@ 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. @@ -110,8 +856,8 @@ directory. - The system configuration file in /etc has the lowest precedence. - - * groffer.sh: + + * groffer.sh: The configuration files are now called after the determination of the temporary files in main_init(). @@ -128,7 +874,7 @@ - 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 @@ -136,7 +882,7 @@ 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(). @@ -201,9 +947,9 @@ - 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. @@ -213,19 +959,19 @@ * 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 +2003-01-22 Bernd Warken ________________________________________________________________ * release of groffer 0.9.4 @@ -242,11 +988,11 @@ - Test existence of directory before deleting it in the `clean_up' definitions. - Correct help output in `usage' (called by `--help'). - + * TODO: Remove mention of `shoop' and `apropos'. -2002-10-21 Bernd Warken +2002-10-21 Bernd Warken ________________________________________________________________ * release of groffer 0.9.3 @@ -269,8 +1015,8 @@ * TODO: think about... - 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 @@ -282,12 +1028,12 @@ - New macro ".Header_CB" for CB font in .TP headers; used for definition of variables in option --mode. - Fix some option references to refer to long options. - + * README: 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:" @@ -299,7 +1045,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 @@ -321,16 +1067,16 @@ - New macro for file names ".File_name". - "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 - + * TODO: remove done entries - 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 @@ -354,7 +1100,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 @@ -364,7 +1110,7 @@ - the string `is part of ' - groff's version information (version number and copyright), but not groff's `called subprograms' information. - + * groffer.sh: minor fixes - Fix the argument parser to process argument `-' correctly. - Some display programs have trouble with empty input; feed a @@ -374,7 +1120,7 @@ * TODO: fix entry `shoop' (not 'shopt'). -2002-06-28 Bernd Warken +2002-06-28 Bernd Warken ________________________________________________________________ * release of groffer 0.9.0 @@ -387,25 +1133,25 @@ - New options `--pdf', `--pdf-viewer', `--mode pdf'. - Standard pdf viewers `xpdf' and `acroread'. - For `xpdf', choose zoom `z 3' for 100 dpi, `z 2' for 75 dpi. - + * groffer.sh: support bzip2 decompression - add test for `bzip2' with necessary options - extend functions `catz()' and `save_stdin()'. * TODO remove entry on `bzip' decompression (done). - + * groffer.man: - Document new `pdf' features. - Document new `bzip2' decompression. - Fix documentation for `--auto-modes'. - + * groffer.sh: minor fixes - Improve device tests in `tty' and `dvi' modes. - 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. @@ -413,7 +1159,7 @@ * groffer.man: Fix some indentations. -2002-06-23 Bernd Warken +2002-06-23 Bernd Warken ________________________________________________________________ * release of groffer 0.8 @@ -425,7 +1171,7 @@ - Document the configuration files in new section `FILES'. - Redesign section `EXAMPLES'. - Remove documentation for `-W'. - + * groffer.sh: new debugging features - Disabled by default; enabled by environment variables. - Add landmark() to catch typos with quotes. @@ -437,7 +1183,7 @@ - Actually, the groffer script uses only shell builtins found in `ash' (a subset of POSIX) and POSIX `sed' as the only external shell utility. - + * groffer.sh: customization of viewers - In `groff' mode, the groffer viewing facilities are disabled. - The postprocessor option `-P' costumizes the viewer only in @@ -458,7 +1204,7 @@ -> `--title': set viewer window title. -> `--xrm': set X resource. - Remove misnamed option `--xrdb'. - + * groffer.sh: new mode structure - New Postcript mode `ps' (`--ps'): -> default viewers: gv,ghostview,gs_x11,gs; @@ -483,7 +1229,7 @@ -> automatically active with one of `-V', `-X', `-Z'. - Revise `tty' mode: -> allow several text devices. - -> + -> - Reorganize the mode management: -> new mode setting option `--mode'. -> logically separate source, groff, and display modes. @@ -496,7 +1242,7 @@ - `${HOME}/.groff/groffer.conf' user configuration. - The configuration file are shell scripts for now; later implementations can identify this from the `#! /bin/sh' line. - + * groffer.sh: new data structure `list': - Implement a `list' data structure as a string consisting of single-quoted elements, separated by a space character; @@ -513,18 +1259,18 @@ allow unusual characters in options. - Parse $MANOPT first; translate essential arguments into groffer options. - + * groffer.man: - determine prompt length for `.Shell_cmd'* dynamically. - naming scheme for static strings and registers changed to `namespace:macro.variable'. - + 2002-06-16 Werner Lemberg * groffer.sh: Implement man option `--ascii' by `-mtty-char'. - + 2002-05-31 Werner LEMBERG @@ -532,7 +1278,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 @@ -568,14 +1314,14 @@ - fix TP_header. -2002-05-28 Bernd Warken +2002-05-28 Bernd Warken ________________________________________________________________ * release of groffer 0.6 This is almost a complete rewrite since groffer 0.5 . ________________________________________________________________ * Documentation - + * groffer.man: - Apply the changes done in www.tmac (.URL and .MTO) - Replace \fP by \f[]. @@ -608,7 +1354,7 @@ - The only external programs used are POSIX `sed' and the fallback to `apropos'. All other program calls were replaced by shell builtins and functions. - + ________________________________________________________________ * Cosmetics @@ -660,10 +1406,10 @@ characters in file names). - Fix and complement usage(). - 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 * groffer.man: @@ -672,7 +1418,7 @@ - Examples of shell commands now print in font CR instead of CB. - Remove documentation for option `-X'. - Add documentation for option `--dpi'. - + * groffer.sh: - New method for creating temporary files, based on process IDs. This is reliable enough and suitable for GNU and POSIX. @@ -689,15 +1435,15 @@ - 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') - + * groffer.man: - New features documented. - Macros stream-lined. - Section EXAMPLES added. - + * groffer.sh: - System tests added/optimized. - Speed/memory optimizations by defining some shell functions @@ -728,7 +1474,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). @@ -746,20 +1492,20 @@ * 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. * Name changed from `groffview' to `groffer'. * Comments added. - + * Name changed from `groffview' to `groffer'. * Options harmonized with groff. @@ -771,26 +1517,30 @@ * Bugs with temporary files fixed. * 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) * Options : -h --help, -v --version - + * 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. + Copyright (C) 2001,2002,2003,2004,2005 + 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. + This file is part of `groffer', which is part of the `groff' + project. diff -u -r --new-file groff-1.19.1/contrib/groffer/Makefile.sub groff-1.19.2/contrib/groffer/Makefile.sub --- groff-1.19.1/contrib/groffer/Makefile.sub 2004-04-27 16:40:39.000000000 -0700 +++ groff-1.19.2/contrib/groffer/Makefile.sub 2005-08-15 07:49:38.000000000 -0700 @@ -1,47 +1,60 @@ -# Makefile.sub for `groffer' (integration into the groff source tree) +# Makefile.sub for `groffer' (integration into the `groff' source tree) # File position: /contrib/groffer/Makefile.sub -# Last update: 21 October 2002 +# Copyright (C) 2001,2002,2005 Free Software Foundation, Inc. +# Written by Werner Lemberg and Bernd Warken. -# Copyright (C) 2001,2002 Free Software Foundation, Inc. -# Written by Werner Lemberg +# Last update: 15 August 2005 -# This file is part of groff. +# This file is part of `groffer' which is part of `groff'. -# groff is free software; you can redistribute it and/or modify it +# `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. +# `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. +# 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. ######################################################################## MAN1=groffer.n CLEANADD=groffer +# not all make programs have $(RM) predefined. +RM=rm -f + all: groffer -groffer: groffer.sh - rm -f $@; \ - sed -e "s|@BINDIR@|$(bindir)|g" \ +groffer: groffer.sh groffer2.sh $(SH_DEPS_SED_SCRIPT) + $(RM) $@; + sed -f $(SH_DEPS_SED_SCRIPT) \ + -e "s|@g@|$(g)|g" \ + -e "s|@BINDIR@|$(bindir)|g" \ + -e "s|@libdir@|$(libdir)|g" \ -e "s|@VERSION@|$(version)$(revision)|g" \ - -e $(SH_SCRIPT_SED_CMD) $(srcdir)/groffer.sh >$@; \ + -e $(SH_SCRIPT_SED_CMD) $(srcdir)/groffer.sh >$@; chmod +x $@ install_data: groffer -test -d $(bindir) || $(mkinstalldirs) $(bindir) - -rm -f $(bindir)/groffer + -$(RM) $(bindir)/groffer $(INSTALL_SCRIPT) groffer $(bindir)/groffer + -test -d $(libdir)/groff/groffer || \ + $(mkinstalldirs) $(libdir)/groff/groffer + -$(RM) $(libdir)/groff/groffer/groffer2.sh + $(INSTALL_SCRIPT) $(srcdir)/groffer2.sh \ + $(libdir)/groff/groffer/groffer2.sh uninstall_sub: - -rm -f $(bindir)/groffer + -$(RM) $(bindir)/groffer + -$(RM) $(libdir)/groff/groffer/groffer2.sh + -rmdir $(libdir)/groff/groffer diff -u -r --new-file groff-1.19.1/contrib/groffer/README groff-1.19.2/contrib/groffer/README --- groff-1.19.1/contrib/groffer/README 2004-04-27 16:51:05.000000000 -0700 +++ groff-1.19.2/contrib/groffer/README 2005-08-02 15:02:43.000000000 -0700 @@ -1,44 +1,104 @@ +README + 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 -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 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. +some `roff' language, such as the `man pages', the manual pages in +many operating systems. + + +Input + +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'. + +`groffer' has many built-in `man' functionalities to find and read the +manual pages on UNIX and similar operating systems. It accepts the +information from an installed `man' program, but tries to find a man +path by itself. + +`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 use 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. + + +Output + +All input is first sent to `grog' to determine the necessary `groff' +options and then to `groff'. So no special `groff' arguments must be +given. But all `groff' options can be specified when this seems to be +appropriate. + +The following displaying modes for the output are available: +- Display formatted input with +-- the X `roff' viewer `gxditview', +-- a Postcript viewer, +-- a PDF viewer, +-- a DVI viewer, +-- a web browser, +-- a pager in a text terminal (tty). +- Generate `groff' output on stdout without a viewer. +- Generate the `groff intermediate output' on standard output without + postprocessing. +- Output the source code without any `groff' processing. +- There are some information outputs without `groff' processing, such + as by option `-V' and the `man' like `whatis' and `apropos' + outputs. + +By default, the program tries to display with `gxditview' as graphical +device in X; on non-X text terminals, the `tty' text mode with a pager +is tried by default. + + +Compatibility + +`groffer' consists of two shell scripts. It should run on any POSIX +or Bourne style shell that supports shell functions. See file +`README_SH' for more information. + + +Mailing lists For reporting bugs of `groffer', groff's free mailing list - can be used. For a general discussion, the - is more useful; see the `README' file in the top -directory of the `groff' source package for more details on this -mailing list. + can be used. + +For a general discussion, the mailing list is more +useful, but one has to subscribe to this list at +http://lists.gnu.org/mailman/listinfo/groff. + +See the `README' file in the top directory of the `groff' source +package for more details on these mailing lists. ####### License -Copyright (C) 2003,2004 Free Software Foundation, Inc. +Last update: 2 August 2005 + +Copyright (C) 2003,2004,2005 Free Software Foundation, Inc. Written by Bernd Warken -This file is part of groffer, which is part of groff. +This file is part of `groffer', which is part of `groff'. -groff is free software; you can redistribute it and/or modify it +`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. +`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. +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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. + + +####### Emacs settings + +Local Variables: +mode: text +End: diff -u -r --new-file groff-1.19.1/contrib/groffer/README_SH groff-1.19.2/contrib/groffer/README_SH --- groff-1.19.1/contrib/groffer/README_SH 2004-04-30 00:35:05.000000000 -0700 +++ groff-1.19.2/contrib/groffer/README_SH 2005-08-18 16:37:18.000000000 -0700 @@ -1,39 +1,39 @@ -Description of groffer.sh, the shell version of groffer +Additional description for the shell version of `groffer' -Display groff files and man pages on X or tty, even when compressed. +Scripts -Usage +The shell version of `groffer' contains two files, `groffer.sh' and +`groffer2.sh'. -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. +`groffer.sh' is a short introductory script without any functions. I +can be run with a very poor Bourne shell. It just contains some basic +variables, the reading of the configuration files, and the +determination of the shell for `groffer2.sh'. This script is +transformed by `make' into `groffer' which will be installed into +@bindir@, which is usually /usr/local/bin. + +`groffer2.sh' is a long main script with all functions; it is called +by `groffer.sh' (`groffer' after installation). It is installed +unchanged into @libdir@/groff/groffer, which is usually +/usr/local/lib/groff/groffer. This script can be called with a +different shell, using the `groffer' option `--shell'. + + +Options + +The `groffer' script provides its own option parser. It is compatible +to the usual GNU style command line This includes long option names +with two signs such as `--option', clusters of short options, the +mixing of options and non-option file names, the option `--' to close +the option handling, and it is possible to abbreviate the long option +names. + +The flexible mixing of options and file names in GNU style is always +possible, even if the environment variable `$POSIXLY_CORRECT' is set +to a non-empty value. This disables the rather wicked POSIX behavior +to terminate option parsing when the first non-option command line +argument is found. Error Handling @@ -44,115 +44,32 @@ 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 () - +Function Definitions in `groffer2.sh' -External non-groffer Environment Variables - -If these variables are exported in the script the `ash' shell coughs -when calling `groff' in `main_display()'. +Each funtion in groffer2.sh has a description that starts with the +function name and symbols for its arguments in paranthesis `()'. Each +`<>' construction gives an argument name that just gives a hint on +what the argument is meant to be; these argument names are otherwise +irrelevant. The `>' sign can be followed by another character that +shows how many of these arguments are possible. + + exactly 1 of this argument +? 0 or 1 of these arguments +* arbitrarily many such arguments, incl. none ++ one or more such arguments +... one or more such arguments +[...] optional arguments + +A function that starts with an underscore `_' is an internal function +for some other function. The internal functions are defined just +after their corresponding function. + + +External Environment Variables + +The groffer.sh script uses the following external system variables. +It is supposed that these variables are already exported outside of +groffer.sh; otherwise they do not have a value within the script. external system environment variables that are explicitly used $DISPLAY: Presets the X display. @@ -160,7 +77,7 @@ $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). +$PATH: Path for the programs called (`:' separated list). groffer native environment variables $GROFFER_OPT preset options for groffer. @@ -196,24 +113,156 @@ The class `list' represents an array structure, see list_*(). +Shell Compatibility + +The `groffer' shell scripts are compatible to 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. This draft is +available at http://www.funet.fi/pub/doc/posix/p1003.2/d11.2 in the +internet. + +The POSIX draft does not include `local' variables for functions. So +this concept was replaced by global variables with a prefix that +differs for each function. The prefix is chosen from the function +name. These quasi-local variables are unset before each return of the +function. + +The `groffer' scripts were tested under the shells `ash', `bash', +`bash-minimal', `dash', 'ksh', `mksh', `pdksh', 'posh', and `zsh' +without problems in Linux Debian. A shell can be tested by the +`groffer' option `--shell', but that will run only with groffer2.sh. +To start it directly from the beginning under this shell the following +command can be used. + + groffer.sh --shell= ... + + +Some shells are not fully POSIX compatible. For them the following +restrictions were done. For more information look at the +documentation `Portable shells' in the `info' page of `autoconf' +(look-up in Emacs-Help-Manuals_Info). + +- The command parts `then', `else', and `do' must be written each on a + line of their own. + +- Replace `for i in "$@"' by `for i' and remove internal `;' (kah). + +- Replace `set -- ...' by `set x ...; shift'. After the first + non-option argument, all arguments including those starting with `-' + are accepted as non-option. For variables or `$()' constructs with + line-breaks, use `eval set' without quotes. That transforms a + line-break within a variable to a space. + +- The name of the variable in `for' is chosen as a single character + (old ash). The content of such variables is not safe because it can + also occur in other functions. So it is often stored in an + additional quasi-local variable. + +- `echo' is not portable on options; some `echo' commands have many + options, others have none. So `echo -n' cannot be used, such that + the output of each function has complete lines. There are two + methods to avoid having `-' as the first character of any argument. + Either a character such as `x' can be prepended to the argument; + this must later on be removed by `sed'. Otherwise, `echo' can be + replaced by `cat </contrib/groffer/groffer.man Installed position: $prefix/share/man/man1/groffer.1 -Version : groffer 0.9.7 -Last update : 03 May 2004 +Last update: 22 August 2005 Source file position: /contrib/groffer/groffer.man - -Copyright (C) 2001,2002,2004 Free Software Foundation, Inc. -Written by Bernd Warken - -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 -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. +.. +.de author +This file was written by +.MTO "" "Bernd Warken" . +.. +.de copyleft +Copyright (C) 2001,2002,2004,2005 Free Software Foundation, Inc. +. +.P +This file is part of +.IR \%groffer , +which is part of +.IR \%groff , +a free software project. +. +You can redistribute it and/or modify it under the terms of the +.nh +.B GNU General Public License +.hy +as published by the +.nh +.BR "Free Software Foundation" , +.hy +either version 2, or (at your option) any later version. +. +.P +You should have received a copy of the \f[CR]GNU General Public +License\f[] along with +.IR groff , +see the files \%\f[CB]COPYING\f[] and \%\f[CB]LICENSE\f[] in the top +directory of the +.I groff +source package. +. +Or read the +.I man\~page +.BR gpl (1). +You can also write to the +.nh +.B Free Software Foundation, 51 Franklin St - Fifth Floor, Boston, +.BR "MA 02110-1301, USA" . +.hy .. . .\" -------------------------------------------------------------------- @@ -58,15 +79,6 @@ . ftr CB CW .\} . -.ds @- "\-\"" -.ds @-- "\-\^\-\"" -. -.ds @b- "\f[CB]-\f[]\"" -.ds @b-- "\f[CB]--\f[]\"" -. -.ds @i- "\f[CI]-\f[]\"" -.ds @i-- "\f[CI]--\f[]\"" -. .ds Ellipsis ".\|.\|.\"" . .\" -------------------------------------------------------------------- @@ -188,7 +200,7 @@ .c -------------------------------------------------------------------- .c .Opt_- ([]) .c -.c Print `-' (minus sign); optional punctuation. +.c Print `-' (minus sign); optional punctuation. .c .de Opt_- . ie (\\n[.$] == 0) \ @@ -199,7 +211,7 @@ .c -------------------------------------------------------------------- .c .Opt_[-] ([]) .c -.c Print `Opt_[-]' (minus sign in brackets); optional punctuation. +.c Print `Opt_[-]' (minus sign in brackets); optional punctuation. .c .de Opt_[-] . ie (\\n[.$] == 0) \ @@ -210,7 +222,7 @@ .c -------------------------------------------------------------------- .c .Opt_-- ([]) .c -.c Print `--' (double minus); optional punctuation. +.c Print `--' (double minus); optional punctuation. .c .de Opt_-- . ie (\\n[.$] == 0) \ @@ -221,7 +233,7 @@ .c -------------------------------------------------------------------- .c .Opt_[--] ([]) .c -.c Print `Opt_[--]' (double minus in brackets); optional punctuation. +.c Print `Opt_[--]' (double minus in brackets); optional punctuation. .c .de Opt_[--] . ie (\\n[.$] == 0) \ @@ -284,7 +296,7 @@ .c Alternating options; base macro for many others; do not use directly. .c .c Arguments: -.c
: prefix, resulted is preceded by this.
+.c   
: prefix, result is preceded by this.
 .c   : separator between minus/opt pairs.
 .c   : postfix, is appended to the result.
 .c   : either `-' or `--' (font CB).
@@ -294,7 +306,8 @@
 .c Result:
 .c   String `
' followed by the / argument pairs, each
 .c   separated by string `', optionally add '', separated by
-.c   a single space ` ', followed by the string `'.
+.c   a single space ` ', followed by the string `'.  Terminated
+.c   by the optional punctuation .
 .c
 .de Opt_alt_base
 .  nr @font \\n[.f]\"
@@ -314,9 +327,13 @@
 .    \}
 .    c                                  separator
 .    if (\\n[@count] > 0) \
-.      as @res \f[CR]\\*[@sep]\"
+.      as @res \f[CR]\\*[@sep]\:\"
 .    nr @count +1
-.    as @res \f[CB]\\$1\\$2\:\"         combine minus with option name
+.    c                                  combine minus with option name
+.    as @res \f[CB]\\-\"
+.    if '\\$1'--' \
+.      as @res \\-\"
+.    as @res \\$2\"
 .    shift 2
 .  \}
 .  if (\\n[.$] >= 3) \
@@ -553,7 +570,9 @@
 .de Text
 .  if (\\n[.$] == 0) \
 .    return
+.  nh
 .  nop \)\\$*\)
+.  hy
 ..
 .c --------------------------------------------------------------------
 .c .Topic  ([])
@@ -646,13 +665,9 @@
 .
 .ad l
 .Synopsis groffer
-.RI [ option...\& ]
+.RI [ option... ]
 .Opt_[--]
-.RI [ "filespec" "\*[Ellipsis]]"
-./Synopsis
-.
-.Synopsis groffer
-.Opt_alt -- apropos -- apropos-data -- apropos-devel -- apropos-progs name
+.RI [ "\%filespec" "\*[Ellipsis]]"
 ./Synopsis
 .
 .Synopsis groffer
@@ -669,62 +684,83 @@
 .\" --------------------------------------------------------------------
 .
 The
-.I groffer
+.B \%groffer
 program is the easiest way to use
-.BR groff (@MAN1EXT@).
+.BR \%groff (@MAN1EXT@).
 It can display arbitrary documents written in the
-.BR groff (@MAN7EXT@)
-language or other
-.BR roff (@MAN7EXT@)
-languages that are compatible to the original troff language.
+.I \%groff
+language, see
+.BR \%groff (@MAN7EXT@),
+or other
+.I \%roff
+languages, see
+.BR \%roff (@MAN7EXT@),
+that are compatible to the original
+.I \%troff
+language.
 .
 The
-.I groffer
+.B \%groffer
 program also includes many of the features for finding and displaying
-the UNIX manual pages
+the \%\f[CR]Unix\f[] manual pages
+.nh
 .RI ( man\~pages ),
+.hy
 such that it can be used as a replacement for a
-.BR man (1)
+.BR \%man (1)
 program.
 .
 Moreover, compressed files that can be handled by
-.BR gzip (1)
+.BR \%gzip (1)
 or
-.BR bzip2 (1)
+.BR \%bzip2 (1)
 are decompressed on-the-fly.
 .
 .
 .P
 The normal usage is quite simple by supplying a file name or name of a
-man\~page without further options.
+.I \%man\~page
+without further options.
 .
 But the option handling has many possibilities for creating special
 behaviors.
 .
-This can be done in configuration files, with the shell environment
-variable
-.BR $GROFFER_OPT ,
+This can be done either in configuration files, with the shell
+environment variable
+.BR \%$GROFFER_OPT ,
 or on the command line.
 .
 .
 .P
 The output can be generated and viewed in several different ways
 available for
-.IR groff .
+.IR \%groff .
 .
-This includes the groff native X viewer
-.BR gxditview (@MAN1EXT@),
-each Postcript or dvi display program, a web browser by generating
-html in www-mode, or several text modes in text terminals.
+This includes the
+.I \%groff
+native \%\f[CR]X\~Window\f[] viewer
+.BR \%gxditview (@MAN1EXT@),
+each
+.IR \%Postcript ,
+.IR \%pdf ,
+or
+.I \%dvi
+display program, a web browser by generating
+.I \%html
+in
+.IR \%www\~mode ,
+or several
+.I \%text\~modes
+in text terminals.
 .
 .
 .P
 Most of the options that must be named when running
-.I groff
+.B \%groff
 directly are determined automatically for
-.IR groffer ,
+.BR \%groffer ,
 due to the internal usage of the
-.BR grog (@MAN1EXT@)
+.BR \%grog (@MAN1EXT@)
 program.
 .
 But all parts can also be controlled manually by arguments.
@@ -734,7 +770,20 @@
 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 .
+.BR \%groff .
+.
+.
+.P
+Option handling is done in \f[CR]GNU\f[] style.
+.
+Options and file names can be mixed freely.
+.
+The option
+.RB ` \-\- '
+closes the option handling, all following arguments are treated as
+file names.
+.
+Long options can be abbreviated.
 .
 .
 .\" --------------------------------------------------------------------
@@ -745,41 +794,42 @@
 .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
+.I \%groffer mode options
 .RS
 .P
 .Opt_[alt] -- auto
 .Opt_[alt] -- default
-.Opt_[alt] -- default-modes mode1,mode2,\*[Ellipsis]
+.Opt_[alt] -- default\-modes mode1,mode2,\*[Ellipsis]
 .Opt_[alt] -- dvi
-.Opt_[alt] -- dvi-viewer prog
+.Opt_[alt] -- dvi\-viewer prog
+.Opt_[alt] -- dvi\-viewer\-tty prog
 .Opt_[alt] -- groff
 .Opt_[alt] -- html
-.Opt_[alt] -- html-viewer prog
-.Opt_[alt] -- man
+.Opt_[alt] -- html\-viewer prog
+.Opt_[alt] -- html\-viewer\-tty prog
 .Opt_[alt] -- mode display_mode
-.Opt_[alt] -- no-man
 .Opt_[alt] -- pdf
-.Opt_[alt] -- pdf-viewer prog
+.Opt_[alt] -- pdf\-viewer prog
+.Opt_[alt] -- pdf\-viewer\-tty prog
 .Opt_[alt] -- ps
-.Opt_[alt] -- ps-viewer prog
+.Opt_[alt] -- ps\-viewer prog
+.Opt_[alt] -- ps\-viewer\-tty prog
 .Opt_[alt] -- text
 .Opt_[alt] -- tty
-.Opt_[alt] -- tty-viewer prog
+.Opt_[alt] -- tty\-viewer prog
+.Opt_[alt] -- tty\-viewer\-tty prog
 .Opt_[alt] -- www
-.Opt_[alt] -- www-viewer prog
+.Opt_[alt] -- www\-viewer prog
+.Opt_[alt] -- www\-viewer\- prog
 .Opt_[alt] -- x -- X
-.Opt_[alt] -- x-viewer -- X-viewer prog
+.Opt_[alt] -- x\-viewer -- X\-viewer prog
+.Opt_[alt] -- x\-viewer\-tty -- X\-viewer\-tty prog
 .RE
 .
 .
@@ -788,45 +838,40 @@
 .RS
 .P
 .Opt_[alt] -- debug
-.Opt_[alt] -- shell
+.Opt_[alt] -- do\-nothing
+.Opt_[alt] -- shell prog
+.Opt_[alt] - Q -- source
+.Opt_[alt] - V
 .RE
 .
 .
 .TP
-.I options related to groff
+.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
+.Opt_[alt] - Z -- intermediate\-output -- ditroff
 .P
 All further
-.I groff
+.B \%groff
 short options are accepted.
 .RE
 .
 .
 .TP
-.I X Window toolkit options
-.RS
-.P
-.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
+.I options for man\~pages
+.Opt_[alt] -- apropos
+.Opt_[alt] -- apropos\-data
+.Opt_[alt] -- apropos\-devel
+.Opt_[alt] -- apropos\-progs
+.Opt_[alt] -- whatis
+.Opt_[alt] -- man
+.Opt_[alt] -- no-man
+.Opt_[alt] -- no-special
 .
 .
 .TP
-.I options from man
+.I long options taken over from GNU man
 .RS
 .P
 .Opt_[alt] -- all
@@ -840,20 +885,37 @@
 .Opt_[alt] -- sections sec1:sec2:\*[Ellipsis]
 .Opt_[alt] -- systems sys1,sys2,\*[Ellipsis]
 .Opt_[alt] -- troff-device device
-.Opt_[alt] -- whatis
 .P
-Further long options of GNU
-.I man
+Further long options of \f[CR]GNU\f[]
+.B man
 are accepted as well.
 .RE
 .
 .
 .TP
-.I filespec argument
+.I X Window Toolkit options
+.RS
+.P
+.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
+.
+.
+.TP
+.I \%filespec arguments
 .RS
 .P
 No
-.I filespec
+.I \%filespec
 parameters means standard input.
 .
 .
@@ -871,9 +933,9 @@
 .BI man: name ( section )
 .TP+
 .IB name ( section )
-search the man\~page
-.I name
-in man\~section\~\c
+search the \%man\~page
+.I \%name
+in \%man\~section
 .IR section .
 .
 .
@@ -884,17 +946,17 @@
 if
 .I s
 is a character in
-.BR [1-9on] ,
-search for a man\~page
-.I name
-in man\~section
+.BR \%[1-9on] ,
+search for a \%man\~page
+.I \%name
+in \%man\~section
 .IR s .
 .
 .
 .TP
 .BI man: name
-man\~page in the lowest man\~section that has
-.IR name .
+\%man\~page in the lowest \%man\~section that has
+.IR \%name .
 .
 .
 .TP
@@ -902,19 +964,19 @@
 if
 .I s
 is a character in
-.BR [1-9on] ,
-search for a man\~page
-.I name
-in man\~section
+.BR \%[1-9on] ,
+search for a \%man\~page
+.I \%name
+in \%man\~section
 .IR s .
 .
 .
 .TP
 .I name
-if 
-.I name
+if
+.I \%name
 is not an existing file search for the man\~page
-.I name
+.I \%name
 in the lowest man\~section.
 .
 .RE
@@ -925,7 +987,7 @@
 .\" --------------------------------------------------------------------
 .
 The
-.I groffer
+.B \%groffer
 program can usually be run with very few options.
 .
 But for special purposes, it supports many options.
@@ -935,14 +997,14 @@
 .
 .P
 All short options of
-.I groffer
+.B \%groffer
 are compatible with the short options of
-.BR groff (@MAN1EXT@).
+.BR \%groff (@MAN1EXT@).
 .
 All long options of
-.I groffer
+.B \%groffer
 are compatible with the long options of
-.BR man (1).
+.BR \%man (1).
 .
 .
 .\" --------------------------------------------------------------------
@@ -951,52 +1013,12 @@
 .
 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
+.B \%groffer
 is terminated thereafter.
 .
 All other arguments are ignored.
 .
 .
-.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.
-.
-Practically both concepts are compatible.
-.
-.
-.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 -- apropos-devel name
-Show only the
-.BR apropos (1)
-descriptions for development documents, in the
-.BR man (7)
-sections 2, 3, and 9.
-.
-.
-.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 - h -- help
 Print a helping information with a short explanation of option sto
 standard output.
@@ -1014,9 +1036,60 @@
 options.
 .
 If none of these mode and viewer options is specified
-.I groffer
+.B \%groffer
 tries to find a suitable display mode automatically.
 .
+The default modes are
+.I mode x
+with
+.B gxditview
+in \%\f[CR]X\~Window\f[] and
+.I mode tty
+with device
+.I latin1
+under
+.B less
+on a terminal.
+.
+.
+.P
+There are two kinds of options for viewers.
+.Opt_long \fImode\fP-viewer
+chooses the normal viewer programs that run on their own in
+\%\f[CR]X\~Window\f[], while
+.Opt_long \fImode\fP-viewer-tty
+chooses programs that run on the terminal (on tty).
+.
+Most graphical viewers are programs running in \%\f[CR]X\~Window\f[],
+so there aren't many opportunities to call the tty viewers.
+.
+But they give the chance to view the output source; for example,
+.Opt_long ps\-viewer\-tty=less
+shows the content of the
+.I Postscript
+output with the pager
+.BR less .
+.
+.
+.P
+The \%\f[CR]X\~Window\f[] viewers are not critical, you can use both
+.Opt_long *\-viewer
+and
+.Opt_long *\-viewer\-tty
+for them; with
+.Opt_long *\-viewer\-tty
+the viewer program will not become independently, it just stays
+coupled with
+.BR groffer .
+But the program will not run if you specify a terminal program with
+.Opt_long *\-viewer
+because this viewer will stay in background without a chance to reach
+it.
+.
+So you really need
+.Opt_long *\-viewer\-tty
+for viewers that run on tty.
+.
 .
 .Opt_def -- auto
 Equivalent to
@@ -1032,9 +1105,9 @@
 and restart option processing using only the rest of the command line.
 .
 .
-.Opt_def -- default-modes mode1,mode2,\*[Ellipsis]
+.Opt_def -- default\-modes mode1,mode2,\*[Ellipsis]
 Set the sequence of modes for
-.I auto mode
+.I \%auto\~mode
 to the comma separated list given in the argument.
 .
 See
@@ -1044,30 +1117,42 @@
 .IR x ,
 .IR ps ,
 and
-.I tty
+.I \%tty
 in this sequence.
 .
 .
 .
 .Opt_def -- dvi
 Equivalent to
-.Opt_long_arg mode dvi .
+.Opt_long_arg mode \%dvi .
 .
 .
-.Opt_def -- dvi-viewer prog
-Set the viewer program for dvi mode.
+.Opt_def -- dvi\-viewer prog
+Choose an \%\f[CR]X\~Window\f[] viewer program for
+.IR \%dvi\~mode .
 .
 This can be a file name or a program to be searched in
 .Env_var $PATH .
 .
-Known dvi viewers inlude
-.BR xdvi (1)
+Known \%\f[CR]X\~Window\f[]
+.I \%dvi
+viewers include
+.BR \%xdvi (1)
 and
-.BR dvilx (1)
+.BR \%dvilx (1)
 .
 In each case, arguments can be provided additionally.
 .
 .
+.Opt_def -- dvi\-viewer\-tty prog
+Choose a program running on the terminal for viewing the output of
+.IR \%dvi\~mode .
+.
+This can be a file name or a program to be searched in
+.Env_var $PATH ;
+arguments can be provided additionally.
+.
+.
 .Opt_def -- groff
 Equivalent to
 .Opt_long_arg mode groff .
@@ -1078,9 +1163,23 @@
 .Opt_long_arg mode html .
 .
 .
-.Opt_def -- html-viewer
-Equivalent to
-.Opt_long www-viewer .
+.Opt_def -- html\-viewer
+Choose an \%\f[CR]X\~Window\f[] web browser program for viewing in
+.I \%html\~mode .
+.
+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 -- html\-viewer\-tty
+Choose a terminal program for viewing the output of
+.I \%html\~mode .
+.
+It can be the path name of an executable file or a program in
+.Env_var $PATH ;
+arguments can be provided additionally.
 .
 .
 .Opt_def -- mode value
@@ -1096,21 +1195,22 @@
 Select the automatic determination of the display mode.
 .
 The sequence of modes that are tried can be set with the
-.Opt_long default-modes
+.Opt_long default\-modes
 option.
 .
-Useful for restoring the default mode when a different mode was
-specified before.
+Useful for restoring the
+.I \%default\~mode
+when a different mode was specified before.
 .
 .
 .TP
 .Header_CB dvi
 Display formatted input in a
-.I dvi
+.I \%dvi
 viewer program.
 .
 By default, the formatted input is displayed with the
-.BR xdvi (1)
+.BR \%xdvi (1)
 program.
 .Opt_long dvi .
 .
@@ -1118,13 +1218,13 @@
 .TP
 .Header_CB groff
 After the file determination, switch
-.I groffer
+.B \%groffer
 to process the input like
-.BR groff (@MAN1EXT@)
-would do .
+.BR \%groff (@MAN1EXT@)
+would do.
 .
 This disables the
-.I groffer
+.I \%groffer
 viewing features.
 .
 .
@@ -1135,34 +1235,37 @@
 .
 By default, the existence of a sequence of standard web browsers is
 tested, starting with
-.BR konqueror (1)
+.BR \%konqueror (1)
 and
-.BR mozilla (1).
+.BR \%mozilla (1).
 The text html viewer is
-.BR lynx (1).
+.BR \%lynx (1).
 .
 .
 .TP
 .Header_CB pdf
 Display formatted input in a
-.I PDF
+.I \%PDF
 (Portable Document Format) viewer
 program.
 .
-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),
+By default, the input is formatted by
+.B \%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)
+.BR \%xpdf (1)
 or the
-.BR acroread (1)
+.BR \%acroread (1)
 program.
 .
 PDF has a big advantage because the text is displayed graphically and
 is searchable as well.
 .
 But as the transformation takes a considerable amount of time, this
-mode is not suitable as a default device for the auto mode.
+mode is not suitable as a default device for the
+.I \%auto\~mode .
 .
 .
 .TP
@@ -1170,19 +1273,19 @@
 Display formatted input in a Postscript viewer program.
 .
 By default, the formatted input is displayed with the
-.BR ghostview (@MAN1EXT@)
+.BR \%ghostview (@MAN1EXT@)
 program.
 .
 .
 .TP
 .Header_CB text
 Format in a
-.I groff
-text mode and write the result to standard output without a pager or
-viewer program.
+.I \%groff\~text\~mode
+and write the result to standard output without a pager or viewer
+program.
 .
 The text device,
-.I latin1
+.I \%latin1
 by default, can be chosen with option
 .Opt_short T .
 .
@@ -1190,37 +1293,68 @@
 .TP
 .Header_CB 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.
+.I \%groff\~text\~mode
+and write the result to standard output using a text pager program,
+even when in \%\f[CR]X\~Window\f[].
 .
 .
 .TP
 .Header_CB www
 Equivalent to
-.Opt_long www .
+.Opt_long_arg mode html .
 .
 .
 .TP
-.Header_CB X
-Display formatted input in a native roff viewer.
+.Header_CB x
+Display the formatted input in a native
+.I 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.
+.BR \%gxditview (@MAN1EXT@)
+program being distributed together with
+.BR \%groff .
+But the standard \%\f[CR]X\~Window\f[] tool
+.BR \%xditview (1)
+can also be chosen with the option
+.Opt_long x\-viewer .
+The default resolution is
+.BR 75\~dpi ,
+but
+.B 100\~dpi
+are also possible.
+.
+The default
+.I groff
+device
+for the resolution of
+.B 75\~dpi
+is
+.BR X75\-12 ,
+for
+.B 100\~dpi
+it is
+.BR X100 .
+.
+The corresponding
+.I "groff intermediate output"
+for the actual device is generated and the result is displayed.
+.
+For a resolution of
+.BR 100\~dpi ,
+the default width of the geometry of the display program is chosen to
+.BR 850\~dpi .
 .
 .
 .TP
-.Header_CB x
+.Header_CB X
 Equivalent to
-.Opt_long_arg mode X .
+.Opt_long_arg mode x .
 .
 .
 .P
 The following modes do not use the
-.I groffer
+.I \%groffer
 viewing features.
 .
 They are only interesting for advanced applications.
@@ -1229,15 +1363,15 @@
 .TP
 .Header_CB groff
 Generate device output with plain
-.I groff
+.I \%groff
 without using the special viewing features of
-.IR groffer .
+.IR \%groffer .
 If no device was specified by option
 .Opt_short T
 the
-.I groff
+.I \%groff
 default
-.B ps
+.B \%ps
 is assumed.
 .
 .
@@ -1255,15 +1389,22 @@
 .Opt_long_arg mode pdf .
 .
 .
-.Opt_def -- pdf-viewer prog
-Set the viewer program for
-.I pdf
-mode.
+.Opt_def -- pdf\-viewer prog
+Choose an \%\f[CR]X\~Window\f[] viewer program for
+.IR \%pdf\~mode .
 .
 This can be a file name or a program to be searched in
-.Env_var $PATH .
+.Env_var $PATH ;
+arguments can be provided additionally.
 .
-In each case, arguments can be provided additionally.
+.
+.Opt_def -- pdf\-viewer\-tty prog
+Choose a terminal viewer program for
+.IR \%pdf\~mode .
+.
+This can be a file name or a program to be searched in
+.Env_var $PATH ;
+arguments can be provided additionally.
 .
 .
 .Opt_def -- ps
@@ -1271,23 +1412,31 @@
 .Opt_long_arg mode ps .
 .
 .
-.Opt_def -- ps-viewer prog
-Set the viewer program for
-.I ps
-mode.
+.Opt_def -- ps\-viewer prog
+Choose an \%\f[CR]X\~Window\f[] viewer program for
+.IR \%ps\~mode .
 .
 This can be a file name or a program to be searched in
 .Env_var $PATH .
 .
 Common Postscript viewers inlude
-.BR gv (1),
-.BR ghostview (1),
+.BR \%gv (1),
+.BR \%ghostview (1),
 and
-.BR gs (1),
+.BR \%gs (1),
 .
 In each case, arguments can be provided additionally.
 .
 .
+.Opt_def -- ps\-viewer\-tty prog
+Choose a terminal viewer program for
+.IR \%ps\~mode .
+.
+This can be a file name or a program to be searched in
+.Env_var $PATH ;
+arguments can be provided additionally.
+.
+.
 .Opt_def -- text
 Equivalent to
 .Opt_long_arg mode text .
@@ -1298,74 +1447,93 @@
 .Opt_long_arg mode tty .
 .
 .
-.Opt_def -- tty-viewer
-Choose tty display mode, that means displaying in a text pager even
-when in X; eqivalent to
-.Opt_long_arg mode tty .
+.Opt_def -- tty\-viewer prog
+Choose a text pager for mode
+.IR tty .
+The standard pager is
+.BR less (1).
+This option is eqivalent to
+.I man
+option
+.Opt_long_arg pager prog .
+The option argument can be a file name or a program to be searched in
+.Env_var $PATH ;
+arguments can be provided additionally.
+.
+.
+.Opt_def -- tty\-viewer\-tty prog
+This is equivalent to
+.Opt_long tty\-viewer
+because the programs for
+.I tty
+mode run on a terminal anyway.
 .
 .
 .Opt_def -- www
 Equivalent to
-.Opt_long_arg mode www .
-.
+.Opt_long_arg mode html .
 .
-.Opt_def -- www-viewer prog
-Set the web browser program for viewing in
-.I www
-mode.
-.
-Each program that accepts html input and allows the
-.BI file://localhost/ dir / file
-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 -- www\-viewer prog
+Equivalent to
+.Opt_long html\-viewer .
 .
 .
-.Opt_def - X -- X -- x
+.Opt_def -- www\-viewer\-tty prog
 Equivalent to
-.Opt_long_arg mode X .
+.Opt_long html\-viewer\-tty .
 .
 .
-.Opt_def -- X-viewer -- x-viewer prog
-Set the viewer program for
-.I x
-mode.
+.Opt_def -- X -- x
+Equivalent to
+.Opt_long_arg mode x .
+.
 .
+.Opt_def -- X\-viewer -- x\-viewer prog
+Choose an \%\f[CR]X\~Window\f[] viewer program for
+.IR \%x\~mode .
 Suitable viewer programs are
-.BR gxditview (@MAN1EXT@)
-and
-.BR xditview (1).
+.BR \%gxditview (@MAN1EXT@)
+which is the default and
+.BR \%xditview (1).
+The argument can be any executable file or a program in
+.Env_var $PATH ;
+arguments can be provided additionally.
 .
-But the argument can be any executable file or a program in
-.Env_var $PATH .
 .
-In each case, arguments can be provided additionally.
+.Opt_def -- X\-viewer\-tty -- x\-viewer\-tty prog
+Choose a terminal viewer program for
+.IR \%x\~mode .
+The argument can be any executable file or a program in
+.Env_var $PATH ;
+arguments can be provided additionally.
 .
 .
 .TP
 .Opt_--
 Signals the end of option processing; all remaining arguments are
 interpreted as
-.I filespec
+.I \%filespec
 parameters.
 .
 .
 .P
 Besides these,
-.I groffer
-accepts all arguments that are valid for the
-.BR groff (@MAN1EXT@)
+.B \%groffer
+accepts all short options that are valid for the
+.BR \%groff (@MAN1EXT@)
 program.
 .
-All non-groffer options are sent unmodified via
-.I grog
+All
+.RB \%non- groffer
+options are sent unmodified via
+.B \%grog
 to
-.IR groff .
+.BR \%groff .
 .
-Postprocessors, macro packages, compatibility with classical
-.IR troff ,
+So postprocessors, macro packages, compatibility with
+.I classical
+.IR \%troff ,
 and much more can be manually specified.
 .
 .
@@ -1374,19 +1542,86 @@
 .\" --------------------------------------------------------------------
 .
 .Opt_def -- debug
-Print debugging information for development only.
+Enable five debugging informations.
+.
+The temporary files are kept and not deleted, the name of the
+temporary directory and the shell name for
+.File_name groffer2.sh
+are printed, the parameters are printed at several steps of
+development, and a function stack is output with function
+\f[CR]error_user()\f[] as well.
+.
+Neither the function call stack that is printed at each opening and
+closing of a function call nor the landmark information that is
+printed to determine how far the program is running are used.
+.
+This seems to be the most useful among all debugging options.
+.
+.
+.Opt_def -- debug\-all
+Enable all seven debugging informations including the function call
+stack and the landmark information.
+.
+.
+.Opt_def -- debug\-keep
+Enable two debugging information, the printing of the name of the
+temporary directory and the keeping of the temporary files.
+.
+.
+.Opt_def -- debug\-lm
+Enable one debugging information, the landmark information.
+.
+.
+.Opt_def -- debug\-params
+Enable one debugging information, the parameters at several steps.
+.
+.
+.Opt_def -- debug\-shell
+Enable one debugging information, the shell name for
+.File_name groffer2.sh .
+.
+.
+.Opt_def -- debug\-stacks
+Enable one debugging information, the function call stack.
+.
 .
-Actually, a function call stack is printed if an error occurs.
+.Opt_def -- debug\-tmpdir
+Enable one debugging information, the name of the temporary directory.
+.
+.
+.Opt_def -- debug\-user
+Enable one debugging information, the function stack with
+\f[CR]error_user()\f[].
+.
+.
+.Opt_def -- do-nothing
+This is like
+.Opt_long version ,
+but without the output; no viewer is started.
+.
+This makes only sense in development.
+.
+.
+.Opt_def -- print=text
+Just print the argument to standard error.
+.
+This is good for parameter check.
 .
 .
 .Opt_def -- shell "shell_program"
-Specify the shell under which the groffer script should be run.
+Specify the shell under which the
+.File_name \%groffer2.sh
+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.
+This option overwrites the automatic shell determination of the
+program.
+.
+If the argument
+.I shell_program
+is empty a former shell option and the automatic shell determination
+is cancelled and the default shell is restored.
+.
+Some shells run considerably faster than the standard shell.
 .
 .
 .Opt_def - Q -- source
@@ -1397,14 +1632,43 @@
 .Opt_long_arg mode source .
 .
 .
+.Opt_def - V
+This is an advanced option for debugging only.
+.
+Instead of displaying the formatted input, a lot of
+.I \%groffer
+specific information is printed to standard output:
+.
+.RS
+.Topic
+the output file name in the temporary directory,
+.
+.Topic
+the display mode of the actual
+.B \%groffer
+run,
+.
+.Topic
+the display program for viewing the output with its arguments,
+.
+.Topic
+the active parameters from the config files, the arguments in
+.Env_var $GROFFER_OPT ,
+and the arguments of the command line,
+.
+.Topic
+the pipeline that would be run by the
+.B \%groff
+program, but without executing it.
+.RE
+.
+.
 .P
 Other useful debugging options are the
-.I groff
-options
-.Opt_short V
-and
+.B \%groff
+option
 .Opt_short Z
-and option
+and
 .Opt_long_arg mode groff .
 .
 .
@@ -1413,49 +1677,49 @@
 .\" --------------------------------------------------------------------
 .
 All short options of
-.I groffer
+.B \%groffer
 are compatible with the short options of
-.BR groff (@MAN1EXT@).
+.BR \%groff (@MAN1EXT@).
 .
 The following of
-.I groff
+.B \%groff
 options have either an additional special meaning within
-.I groffer
+.B \%groffer
 or make sense for normal usage.
 .
 .
 .P
 Because of the special outputting behavior of the
-.I groff
-options
-.Opt_short V
-and
+.B \%groff
+option
 .Opt_short Z
-.I groffer
+.B \%groffer
 was designed to be switched into
-.I groff
-mode by these; the
-.I groffer
+.I \%groff\~mode ;
+the
+.I \%groffer
 viewing features are disabled there.
 .
 The other
-.I groff
+.B \%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.
+This generates an ascii approximation of output in the
+.IR \%text\~modes .
 .
 That could be important when the text pager has problems with control
-sequences.
+sequences in
+.IR "tty mode" .
 .
 .
 .Opt_def - m file
 Add
-.I file
+.I \%file
 as a
-.I groff
+.I \%groff
 macro file.
 .
 This is useful in case it cannot be recognized automatically.
@@ -1463,317 +1727,334 @@
 .
 .Opt_def - P opt_or_arg
 Send the argument
-.I opt_or_arg
+.I \%opt_or_arg
 as an option or option argument to the actual
-.I groff
+.B \%groff
 postprocessor.
 .
 .
 .Opt_def - T -- device devname
 .
 This option determines
-.IR groff 's
+.BR \%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 ,
+.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.
+.B \%groffer
+into a
+.I \%text\~mode
+using this device, to
+.I \%mode\~tty
+if the actual mode is not a
+.IR \%text\~mode .
 .
 The following
-.I devname
+.I \%devname
 arguments are mapped to the corresponding
-.I groffer
+.B \%groffer
 .Opt_long_arg mode \fIdevname\fR
 option:
-.BR dvi ,
-.BR html ,
+.BR \%dvi ,
+.BR \%html ,
 and
-.BR ps .
+.BR \%ps .
 All
-.B X*
-arguments are mapped to mode
-.BR X .
+.B \%X*
+arguments are mapped to
+.IR \%mode\~x .
 Each other
-.I devname
+.I \%devname
 argument switches to
-.I mode groff
+.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.
+is equivalent to
+.BR "groff \-X" .
+It displays the
+.I groff intermediate output
+with
+.BR gxditview .
+As the quality is relatively bad this option is deprecated; use
+.Opt_long X
+instead because the
+.I \%x\~mode
+uses an
+.IR X *
+device for a better display.
 .
 .
 .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@).
+.I \%groff\~mode
+and format the input with the
+.I \%groff intermediate output
+without postprocessing; see
+.BR \%groff_out (@MAN5EXT@).
 This is equivalent to option
 .Opt_long ditroff
 of
-.IR man ,
+.IR \%man ,
 which can be used as well.
 .
 .
 .P
 All other
-.I groff
+.B \%groff
 options are supported by
-.IR groffer ,
+.BR \%groffer ,
 but they are just transparently transferred to
-.I groff
+.B \%groff
 without any intervention.
 .
 The options that are not explicitly handled by
-.I groffer
+.B \%groffer
 are transparently passed to
-.IR groff .
+.BR \%groff .
 .
 Therefore these transparent options are not documented here, but in
-.BR groff (@MAN1EXT@).
+.BR \%groff (@MAN1EXT@).
 Due to the automatism in
-.IR groffer ,
+.BR \%groffer ,
 none of these
-.I groff
+.B \%groff
 options should be needed, except for advanced usage.
 .
 .
 .\" --------------------------------------------------------------------
-.SS "X Window toolkit Options"
+.SS "Options for man\~pages"
 .\" --------------------------------------------------------------------
 .
-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.
-.
+.Opt_def -- apropos
+Start the
+.BR \%apropos (1)
+command or facility of
+.BR \%man (1)
+for searching the
+.I \%filespec
+arguments within all
+.I \%man\~page
+descriptions.
 .
-.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.
+Each
+.I \%filespec
+argument is taken for search as it is; section specific parts are not
+handled, such that
+.B 7 groff
+searches for the two arguments
+.B 7
+and
+.B groff
+with a large result; for the
+.I \%filespec
+.B groff.7
+nothing will be found.
+.
+The display differs from the
+.B \%apropos
+program by the following concepts:
+.RS
+.Topic
+construct a
+.I \%groff
+frame to the output of
+.BR \%apropos ,
+.Topic
+each
+.I \%filespec
+argument is searched on its own.
+.Topic
+the restriction by
+.Opt_long sections
+is handled as well,
+.Topic
+wildcard characters are allowed and handled without a further option.
+.RE
 .
 .
-.Opt_def -- bg color
-This is equivalent to
-.Opt_long background .
+.Opt_def -- apropos\-data
+Show only the
+.B \%apropos
+descriptions for data documents, these are the
+.BR \%man (7)
+sections 4, 5, and 7.
 .
+Direct section declarations are ignored, wildcards are accepted.
 .
-.Opt_def -- bw pixels
-Specifies the width in pixels of the border surrounding the viewer
-window.
 .
+.Opt_def -- apropos\-devel
+Show only the
+.B \%apropos
+descriptions for development documents, these are the
+.BR man (7)
+sections 2, 3, and 9.
 .
-.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.
+Direct section declarations are ignored, wildcards are accepted.
 .
 .
-.Opt_def -- foreground color
-Set the foreground color of the viewer window.
+.Opt_def -- apropos\-progs
+Show only the
+.B \%apropos
+descriptions for documents on programs, these are the
+.BR \%man (7)
+sections 1, 6, and 8.
 .
+Direct section declarations are ignored, wildcards are accepted.
 .
-.Opt_def -- fg color
-This is equivalent to
-.Opt_short foreground .
 .
+.Opt_def -- whatis
+For each
+.I \%filespec
+argument search all
+.I \%man\~pages
+and display their description \[em] or say that it is not a
+.IR \%man\~page .
+This differs from
+.IR man 's
+.B whatis
+output by the following concepts
+.RS
+.Topic
+each retrieved file name is added,
+.Topic
+local files are handled as well,
+.Topic
+the display is framed by a
+.I groff
+output format,
+.Topic
+wildcard characters are allowed without a further option.
+.RE
 .
-.Opt_def -- font font_name
-Set the font used by the viewer window.
 .
-The argument is an X font name.
+.P
+The following two options were added to
+.B \%groffer
+for choosing whether the file name arguments are interpreted as names
+for local files or as a search pattern for
+.IR \%man\~pages .
 .
+The default is looking up for local files.
 .
-.Opt_def -- ft font_name
-This is equivalent to
-.Opt_long ft .
 .
+.Opt_def -- man
+Check the non-option command line arguments
+.nh
+.RI ( filespecs )
+.hy
+first on being
+.IR \%man\~pages ,
+then whether they represent an existing file.
+.
+By default, a
+.I \%filespec
+is first tested whether it is an existing file.
 .
-.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 -- no-man -- local-file
+Do not check for
+.IR \%man\~pages .
 .
+.Opt_long local-file
+is the corresponding
+.B man
+option.
 .
-.Opt_def -- resolution value
-Set X resolution in dpi (dots per inch) in some viewer programs.
 .
-The only supported dpi values are
-.B 75
+.Opt_def -- no-special
+Disable former calls of
+.Opt_long all ,
+.Opt_long apropos* ,
 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.
+.Opt_long whatis .
 .
 .
 .\" --------------------------------------------------------------------
-.SS "Options from man"
+.SS "Long options taken over from GNU man"
 .\" --------------------------------------------------------------------
 .
 The long options of
-.I groffer
-were synchronized with the long options of
-.IR GNU man .
+.B \%groffer
+were synchronized with the long options of \f[CR]GNU\f[]
+.BR man .
 .
-All long options of
-.I GNU man
+All long options of \f[CR]GNU\f[]
+.B man
 are recognized, but not all of these options are important to
-.IR groffer ,
+.BR \%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
+.B man
 options that have a special meaning for
-.I groffer
+.B \%groffer
 are documented.
 .
 .
 .P
-The full set of long and short options of the
-.I GNU man
+The full set of long and short options of the \f[CR]GNU\f[]
+.B man
 program can be passed via the environment variable
 .Env_var $MANOPT ;
 see
-.BR man (1)
-if your system has
-.I GNU man
+.BR \%man (1)
+if your system has \f[CR]GNU\f[]
+.B man
 installed.
 .
 .
 .Opt_def -- all
-In searching man\~pages, retrieve all suitable documents instead of
-only one.
+In searching
+.IR \%man\~pages ,
+retrieve all suitable documents instead of only one.
 .
 .
 .Opt_def - 7 -- ascii
-In text modes, display ASCII translation of special characters.
+In
+.IR \%text\~modes ,
+display ASCII translation of special characters for critical environment.
+.
+This is equivalent to
+.BR "groff -mtty_char" ;
+see
+.BR groff_tmac (@MAN5EXT@).
 .
 .
 .Opt_def -- ditroff
 Eqivalent to
-.I groffer
+.B \%groffer
 .Opt_short Z .
 .
 .
 .Opt_def -- extension suffix
-Restrict man\~page search to file names that have
-.I suffix
+Restrict
+.I \%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 .
+.I \%/usr/share/man/man3/terminfo.3ncurses.gz
+the
+.I \%man\~page
+extension is
+.IR \%ncurses .
 .
 .
 .Opt_def -- locale language
 .
-Set the language for man pages.
+Set the language for
+.IR \%man\~pages .
 .
 This has the same effect, but overwrites
 .Env_var $LANG
@@ -1789,50 +2070,166 @@
 .Opt_long location .
 .
 This was added by
-.IR groffer .
+.BR \%groffer .
 .
 .
 .Opt_def -- manpath "'dir1:dir2:\*[Ellipsis]'"
-Use the specified search path for retrieving man\~pages instead of the
-program defaults.
+Use the specified search path for retrieving
+.I \%man\~pages
+instead of the program defaults.
 .
-If the argument is set to the empty string "" the search for man\~page
+If the argument is set to the empty string "" the search for
+.I \%man\~page
 is disabled.
 .
 .
 .Opt_def -- pager
-Set the pager program in tty mode; default is
-.IR less .
+Set the pager program in
+.IR \%tty\~mode ;
+default is
+.BR \%less .
 This is equivalent to
-.Opt_long tty-viewer .
+.Opt_long tty\-viewer .
 .
 .
 .Opt_def -- sections "'sec1:sec2:\*[Ellipsis]'"
-Restrict searching for man\~pages to the given
+Restrict searching for
+.I \%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
+Search for
+.I \%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 .
 .
 .
+.\" --------------------------------------------------------------------
+.SS "X\~\%Window\~\%Toolkit Options"
+.\" --------------------------------------------------------------------
+.
+The following long options were adapted from the corresponding
+\%\f[CR]X\~\Window\~Toolkit\f[] options.
+.
+.B \%groffer
+will pass them to the actual viewer program if it is an
+\%\f[CR]X\~Window\f[] program.
+.
+Otherwise these options are ignored.
+.
+.
 .P
-Additionally, the following short option of
-.I man
-is supported as well.
+Unfortunately these options use the old style of a single minus for
+long options.
+.
+For
+.B \%groffer
+that was changed to the standard with using a double minus for long
+options, for example,
+.B \%groffer
+uses the option
+.Opt_long font
+for the \%\f[CR]X\~Window\f[] option
+.Opt_short font .
+.
+.
+.P
+See
+.BR \%X (1),
+.BR \%X (7),
+and the documentation on the \%\f[CR]X\~Window\~Toolkit\f[] 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 \%\f[CR]X\~Window\f[] display on which the viewer program
+shall be started, see the \%\f[CR]X\~Window\f[] 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 \%\f[CR]X\~Window\f[] 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 \%\f[CR]X\~Window\f[] 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
+.B \%groffer
+is set to
+.BR 75\~dpi .
+The resolution also sets the default device in
+.IR "mode x" .
+.
+.
+.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 \f[CR]\%X\~Window\f[] resource.
 .
 .
 .\" --------------------------------------------------------------------
@@ -1840,43 +2237,48 @@
 .\" --------------------------------------------------------------------
 .
 A
-.I filespec
-parameter is an argument meaning an input source, such as a file name
-or template for searching man\~pages.
+.I \%filespec
+parameter is an argument that is not an option or option argument.
 .
-These input sources are collected and composed into a single output
-file.
+It means an input source.
 .
-Each of these
-.I filespec
-parameters can have one of the following forms.
+In
+.BR \%groffer ,
+.I \%filespec
+parameters are a file name or a template for searching
+.IR \%man\~pages .
 .
+These input sources are collected and composed into a single output
+file such as
+.B \%groff
+does.
 .
-.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.
+.P
+The strange \%\f[CR]POSIX\f[] behavior to regard all arguments behind
+the first non-option argument as
+.I \%filespec
+arguments is ignored.
 .
-Next
-.I filespec
-is tested whether it is the path name of an existing file.
+The \f[CR]GNU\f[] behavior to recognize options even when mixed with
+.I \%filespec
+arguments is used througout.
 .
-Otherwise it is assumed as a searching pattern for a man\~page.
+But, as usual, the double minus argument
+.Opt_long
+ends the option handling and interprets all following arguments as
+.I \%filespec
+arguments; so the \%\f[CR]POSIX\f[] behavior can be easily adopted.
 .
 .
 .P
-On each system, the man pages are sorted according to their content
-into several sections.
+For the following, it is necessary to know that on each system the
+.I \%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
+have a single-character name, either a digit from
 .B 1
 to
 .B 9
@@ -1887,49 +2289,77 @@
 .
 In the following, a stand-alone character
 .I s
-means this scheme.
-.
-.
-.P
+stands for a
+.IR "classical man section" .
 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.
+.B \%man
+for searching
+.I \%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.
+.B \%groffer
+.I \%man\~page
+facility is based on the classical single character sections.
 .
 .
 .P
-.BI man: name ( section )
+Each
+.I \%filespec
+parameter can have one of the following forms in decreasing sequence.
+.
+.
+.Topic
+No
+.I \%filespec
+parameters means that
+.B \%groffer
+waits for standard input.
+.
+The minus option
+.Opt_short ""
+stands for standard input, too; it can occur several times.
+.
+.
+.Topic
+Next a
+.I \%filespec
+is tested whether it is the path name of an existing file.
+.
+Otherwise it is assumed to be a searching pattern for a
+.IR \%man\~page .
+.
+.
+.Topic
+.BI \%man: name ( section )
 and
-.IB name ( section )
-search the man\~page
-.I name
-in man\~section\~\c
-.IR section ,
+.IB \%name ( section )
+search the \%man\~page
+.I \%name
+in \%man\~section\~\c
+.IR \%section ,
 where
-.I section
+.I \%section
 can be any string, but it must exist in the
-.I man
+.I \%man
 system.
 .
 .
-.P
+.Topic
 Next some patterns based on the
 .I classical man sections
-were constructed.
+are checked.
 .
-.BI man: name . s
+.BI \%man: name . s
 and
-.IB name . s
-search for a man\~page
-.I name
-in man\~section
+.IB \%name . s
+search for a \%man\~page
+.I \%name
+in \%man\~section
 .I s
 if
 .I s
@@ -1937,67 +2367,87 @@
 .I classical man section
 mentioned above.
 .
-Otherwise search for a man\~page named
-.IR name.s
-in the lowest
-.I man
-section.
+Otherwise a
+.I \%man\~page
+named
+.IR \%name.s
+is searched in the lowest
+.B man\~section .
 .
 .
-.P
+.Topic
 Now
-.BI man: name
-searches for a man\~page in the lowest man\~section that has a
-document called
-.IR name .
+.BI \%man: name
+searches for a
+.I \%man\~page
+in the lowest
+.I \%man\~section
+that has a document called
+.IR \%name .
 .
 .
-.P
+.Topic
 The pattern
-.I "s name"
+.I \%s\~name
 originates from a strange argument parsing of the
-.I man
+.B man
 program.
 .
 If
 .I s
 is a
 .I classical man section
-interpret it as a search for a man\~page called
-.I name
+interpret it as a search for a
+.I \%man\~page
+called
+.I \%name
 in man\~section
 .IR s ,
-otherwise interpret
+otherwise interpret both
 .I s
-as a file argument and
-.I name
-as another
-.I filespec
-argument.
+and
+.I \%name
+as two independent
+.I \%filespec
+arguments.
 .
 .
-.P
+.Topic
 We are left with the argument
-.I name
+.I \%name
 which is not an existing file.
 .
-So this searches for the man\~page called
-.I name
-in the lowest man\~section that has a document for this name.
+So this searches for the
+.I \%man\~page
+called
+.I \%name
+in the lowest
+.I \%man\~section
+that has a document for this name.
+.
+.
+.P
+Wildcards in
+.I \%filespec
+arguments are only accepted for
+.Opt_long apropos*
+and
+.Opt_long whatis ;
+for normal display, they are interpreted as characters.
 .
 .
 .P
 Several file name arguments can be supplied.
 .
 They are mixed by
-.I groff
+.B \%groff
 into a single document.
 .
 Note that the set of option arguments must fit to all of these file
 arguments.
 .
 So they should have at least the same style of the
-.I groff
+.I \%groff
 language.
 .
 .
@@ -2006,19 +2456,19 @@
 .\" --------------------------------------------------------------------
 .
 By default, the
-.I groffer
+.B \%groffer
 program collects all input into a single file, formats it with the
-.I groff
+.B \%groff
 program for a certain device, and then chooses a suitable viewer
 program.
 .
 The device and viewer process in
-.I groffer
+.B \%groffer
 is called a
-.IR mode .
+.IR \%mode .
 .
 The mode and viewer of a running
-.I groffer
+.B \%groffer
 program is selected automatically, but the user can also choose it
 with options.
 .
@@ -2030,103 +2480,111 @@
 .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 .
+.Opt_long \fIanymode\fR\-viewer .
 .
 .
 .P
-Several different modes are offered, graphical X modes, text modes,
+Several different modes are offered, graphical modes for
+\f[CR]\%X\~Window\f[],
+.IR \%text\~modes ,
 and some direct
-.I groff
-modes for debugging and development.
+.I \%groff\~modes
+for debugging and development.
 .
 .
 .P
 By default,
-.I groffer
+.B \%groffer
 first tries whether
-.B x
-mode is possible, then
-.B ps
-mode, and finally
-.B tty
-mode.
+.I \%x\~mode
+is possible, then
+.IR \%ps\~mode ,
+and finally
+.IR \%tty\~mode .
 .
 This mode testing sequence for
-.B auto
-mode can be changed by specifying a comma separated list of modes
-with the option
+.I \%auto\~mode
+can be changed by specifying a comma separated list of modes with the
+option
 .Opt_long default\-modes.
 .
 .
 .P
-The searching for man\~pages and the decompression of the input are
-active in every mode.
+The searching for
+.I \%man\~pages
+and the decompression of the input are active in every mode.
 .
 .
 .\" --------------------------------------------------------------------
 .SS "Graphical Display Modes"
 .\" --------------------------------------------------------------------
 .
-The graphical display modes work only in the X Window environment (or
-similar implementations within other windowing environments).
+The graphical display modes work mostly in the \%\f[CR]X\~Window\f[]
+environment (or similar implementations within other windowing
+environments).
 .
 The environment variable
 .Env_var $DISPLAY
 and the option
 .Opt_long display
-are used for specifying the X display to be used.
+are used for specifying the \%\f[CR]X\~Window\f[] display to be used.
 .
-If neither is given,
-.I groffer
-assumes that no X and changes to one text mode.
+If this environment variable is empty
+.B \%groffer
+assumes that no \%\f[CR]X\~Window\f[] is running and changes to a
+.IR \%text\~mode .
 .
 You can change this automatic behavior by the option
 .Opt_long default\-modes .
 .
 .
 .P
-Known viewers for the graphical display modes and their standard X
-Window viewer progams are
+Known viewers for the graphical display modes and their standard
+\%\f[CR]X\~Window\f[] viewer progams are
 .
 .Topic
-X Window roff viewers such as
-.BR gxditview (@MAN1EXT@)
-or
-.BR xditview (1)
-.RI (in x
+\%\f[CR]X\~Window\f[]
+.I roff
+viewers such as
+.BR \%gxditview (@MAN1EXT@)
 or
-.I X
-mode),
+.BR \%xditview (1)
+(in
+.IR \%x\~mode ),
 .
 .Topic
 in a Postscript viewer
-.RI ( ps
-mode),
+.nh
+.RI ( \%ps\~mode ),
+.hy
 .
 .Topic
 in a dvi viewer program
-.RI ( dvi
-mode),
+.nh
+.RI ( \%dvi\~mode ),
+.hy
 .
 .Topic
 in a PDF viewer
-.RI ( pdf
-mode),
+.nh
+.RI ( \%pdf\~mode ),
+.hy
 .
 .Topic
 in a web browser
+.nh
 .RI ( html
 or
-.I www
-mode),
+.IR \%www\~mode ).
+.hy
 .RE
 .
 .
 .P
 The
-.I pdf
-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
+.I \%pdf\~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 some time to transform the input into the PDF
@@ -2134,38 +2592,42 @@
 .
 .
 .P
-These graphical viewers can be customized by options of the X Window
-Toolkit.
+These graphical viewers can be customized by options of the
+\%\f[CR]X\~Window\~Toolkit\f[].
 .
 But the
-.I groffer
+.B \%groffer
 options use a leading double minus instead of the single minus used by
-the X Window Toolkit.
+the \%\f[CR]X\~Window\~Toolkit\f[].
 .
 .
 .\" --------------------------------------------------------------------
-.SS "Text mode"
+.SS "Text modes"
 .\" --------------------------------------------------------------------
 .
-There are to modes for text output, mode
-.I text
-for plain output without a pager and mode
-.I tty
+There are two modes for text output,
+.I \%mode\~text
+for plain output without a pager and
+.I \%mode\~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 use
-.I tty
-mode.
+.Env_var \%$DISPLAY
+is not set or empty,
+.B \%groffer
+assumes that it should use
+.IR \%tty\~\%mode .
 .
 .
 .P
-In the actual implementation, the groff output device
-.I latin1
-is chosen for text modes.
+In the actual implementation, the
+.I groff
+output device
+.I \%latin1
+is chosen for
+.IR \%text\~modes .
 .
 This can be changed by specifying option
 .Opt_short T
@@ -2177,11 +2639,11 @@
 The pager to be used can be specified by one of the options
 .Opt_long pager
 and
-.Opt_long tty-viewer ,
+.Opt_long tty\-viewer ,
 or by the environment variable
 .Env_var $PAGER .
 If all of this is not used the
-.BR less (1)
+.BR \%less (1)
 program with the option
 .Opt_short r
 for correctly displaying control sequences is used as the default
@@ -2193,13 +2655,13 @@
 .\" --------------------------------------------------------------------
 .
 These modes use the
-.I groffer
+.I \%groffer
 file determination and decompression.
 .
 This is combined into a single input file that is fed directly into
-.I groff
+.B \%groff
 with different strategy without the
-.I groffer
+.I \%groffer
 viewing facilities.
 .
 These modes are regarded as advanced, they are useful for debugging
@@ -2208,15 +2670,21 @@
 .
 .P
 The
-.I source
-mode with just displays the generated input.
+.I \%source\~mode
+with option
+.Opt_short Q
+and
+.Opt_long source
+just displays the decompressed input.
 .
+.
+.P
 The
-.I groff
-mode passes the input to
-.I groff
+.I \%groff\~mode
+passes the input to
+.B \%groff
 using only some suitable options provided to
-.IR groffer .
+.BR \%groffer .
 .
 This enables the user to save the generated output into a file or pipe
 it into another program.
@@ -2224,90 +2692,115 @@
 .
 .P
 In
-.I groff
-mode, the option
+.IR \%groff\~\%mode ,
+the option
 .Opt_short Z
 disables post-processing, thus producing the
+.nh
 .I groff intermediate
 .IR output .
+.hy
 .
 In this mode, the input is formatted, but not postprocessed; see
-.BR groff_out (@MAN5EXT@)
+.BR \%groff_out (@MAN5EXT@)
 for details.
 .
 .
 .P
 All
-.I groff
+.B \%groff
 short options are supported by
-.IR groffer .
+.BR \%groffer .
 .
 .
 .\" --------------------------------------------------------------------
 .SH "MAN\~PAGE\~SEARCHING"
 .\" --------------------------------------------------------------------
 .
-The default behavior of groffer is to first test whether a file
-parameter represents a local file; if it is not an existing file name,
-it is assumed to represent a name of a man\~page.
+The default behavior of
+.B \%groffer
+is to first test whether a file parameter represents a local file; if
+it is not an existing file name, it is assumed to represent a name of
+a
+.IR \%man\~page .
 .
 This behavior can be modified by the following options.
 .
 .
 .TP
 .Opt_long man
-forces to interpret all file parameters as filespecs for searching
-man\~pages.
+forces to interpret all file parameters as
+.I \%filespecs
+for searching
+.IR \%man\~pages .
 .
 .TP
 .Opt_long no\-man
 .TP+
 .Opt_long local\-file
-disable the man searching; so only local files are displayed.
+disable the
+.I man
+searching; so only local files are displayed.
 .
 .
 .P
-If neither a local file nor a man\~page was retrieved for some file
-parameter a warning is issued on standard error, but processing is
-continued.
+If neither a local file nor a
+.I \%man\~page
+was retrieved for some file parameter a warning is issued on standard
+error, but processing is continued.
 .
 .
 .P
-The groffer program provides a search facility for man\~pages.
+The
+.B \%groffer
+program provides a search facility for
+.IR \%man\~pages .
 .
 All long options, all environment variables, and most of the
-functionality of the GNU
-.BR man (1)
+functionality of the \f[CR]GNU\f[]
+.BR \%man (1)
 program were implemented.
 .
-This inludes the extended file names of man\~pages, for example,
-the man\~page of
-.I groff
+This inludes the extended file names of
+.IR \%man\~pages ,
+for example, the
+.I \%man\~page
+of
+.B \%groff
 in man\~section 7 may be stored under
 .File_name /usr/share/man/man7/groff.7.gz ,
 where
 .File_name /usr/share/man/
 is part of the man\~path, the subdirectory
-.I man7
+.I \%man7
 and the file extension
 .I .7
 refer to the man\~section 7;
-.I .gz
+.I \%.gz
 shows the compression of the file.
 .
 .
 .P
 The
 .I cat\~pages
-(preformatted man\~pages) are intentionally excluded from the search
-because groffer is a roff program that wants to format by its own.
+(preformatted
+.IR \%man\~pages )
+are intentionally excluded from the search because
+.B \%groffer
+is a
+.I roff
+program that wants to format by its own.
 .
 With the excellent performance of the actual computers, the
-preformatted man\~pages aren't necessary any longer.
+preformatted
+.I \%man\~pages
+aren't necessary any longer.
 .
 .
 .P
-The algorithm for retrieving man\~pages uses five search methods.
+The algorithm for retrieving
+\I \%man\~pages
+uses five search methods.
 .
 They are successively tried until a method works.
 .
@@ -2315,7 +2808,9 @@
 .Topic
 The search path can be manually specified by using the option
 .Opt_long manpath .
-An empty argument disables the man\~page searching.
+An empty argument disables the
+.I \%man\~page
+searching.
 .
 This overwrites the other methods.
 .
@@ -2335,33 +2830,42 @@
 .Topic
 If this does not work a reasonable default path from
 .Env_var $PATH
-is searched for man\~pages.
+is searched for
+.IR \%man\~pages .
 .
 .
 .Topic
 If this does not work, the
-.BR manpath (1)
-program for determining a path of man directories is tried.
+.BR \%manpath (1)
+program for determining a path of
+.I man
+directories is tried.
 .
 .
 .P
 After this, the path elements for the language (locale) and operating
-system specific man\~pages are added to the man\~path; their sequence
-is determined automatically.
+system specific
+.I \%man\~pages
+are added to the
+.IR man\~path ;
+their sequence is determined automatically.
 .
 For example, both
-.I /usr/share/man/linux/fr
+.File_name /usr/share/man/linux/fr
 and
-.I /usr/share/man/fr/linux
-for french linux man\~pages are found.
+.File_name /usr/share/man/fr/linux
+for french linux
+.I \%man\~pages
+are found.
 .
 The language and operating system names are determined from both
 environment variables and command line options.
 .
 .
 .P
-The locale (language) is determined like in GNU man, that is from
-highest to lowest precedence:
+The locale (language) is determined like in \f[CR]GNU\f[]
+.BR man ,
+that is from highest to lowest precedence:
 .Topic
 .Opt_long locale
 .
@@ -2382,32 +2886,40 @@
 .
 .
 .P
-The language locale is usually specified in the POSIX 1003.1 based
-format:
+The language locale is usually specified in the
+\%\f[CR]POSIX\~1003.1\f[] based format:
 .P
+.nh
 \f[I]\f[][\f[CB]_\f[]\f[I]\f[][\f[CB].\f[]\
 \f[I]\f[][\f[CB],\f[]\f[I]\f[]]]],
+.hy
 .P
 but the two-letter code in
+.nh
 .I 
+.hy
 is sufficient for most purposes.
 .
 .
 .P
-If no man\~pages for a complicated locale are found the country part
-consisting of the first two characters (without the `\f[CB]_\f[]',
-`\f[CB].\f[]', and `\f[CB],\f[]', parts) of the locale is searched as
-well.
+If no
+.I \%man\~pages
+for a complicated locale are found the country part consisting of the
+first two characters (without the `\f[CB]_\f[]', `\f[CB].\f[]', and
+`\f[CB],\f[]' parts) of the locale is searched as well.
 .
 .
 .P
-If still not found the corresponding man\~page in the default language
-is used instead.
+If still not found the corresponding
+.I \%man\~page
+in the default language is used instead.
 .
 As usual, this default can be specified by one of \f[CR]C\f[] or
-\f[CR]POSIX\f[].
+\f[CR]\%POSIX\f[].
 .
-The man\~pages in the default language are usually in English.
+The
+.I \%man\~pages
+in the default language are usually in English.
 .
 .
 .P
@@ -2435,22 +2947,29 @@
 .
 .
 .P
-When searching for man\~pages this man\~path with the additional
-language and system specific directories is used.
+When searching for
+.I \%man\~pages
+this
+.I man\~path
+with the additional language and system specific directories is used.
 .
 .
 .P
 The search can further be restricted by limiting it to certain
 sections.
 .
-A single section can be specified within each filespec argument,
-several sections as a colon-separated list in command line option
+A single section can be specified within each
+.I \%filespec
+argument, several sections as a colon-separated list in command line
+option
 .Opt_long sections
 or environment variable
 .Env_var $MANSECT .
 .
 When no section was specified a set of standard sections is searched
-until a suitable man\~page was found.
+until a suitable
+.I \%man\~page
+was found.
 .
 .
 .P
@@ -2465,8 +2984,10 @@
 .
 .
 .P
-For further details on man\~page searching, see
-.BR man (1).
+For further details on
+.I \%man\~page
+searching, see
+.BR \%man (1).
 .
 .
 .\" --------------------------------------------------------------------
@@ -2477,16 +2998,16 @@
 .
 If standard input or a file that was retrieved from the command line
 parameters is compressed with a format that is supported by either
-.BR gzip (1)
+.BR \%gzip (1)
 or
-.BR bzip2 (1)
+.BR \%bzip2 (1)
 it is decompressed on-the-fly.
 .
-This includes the GNU
-.BR .gz ,
-.BR .bz2 ,
+This includes the \f[CR]GNU\f[]
+.BR \%.gz ,
+.BR \%.bz2 ,
 and the traditional
-.B .Z
+.B \%.Z
 compression.
 .
 The program displays the concatenation of all decompressed input in
@@ -2497,13 +3018,15 @@
 .SH "ENVIRONMENT"
 .\" --------------------------------------------------------------------
 .
-The groffer programs supports many system variables, most of them by
-courtesy of other programs.
+The
+.B \%groffer
+program supports many system variables, most of them by courtesy of
+other programs.
 .
 All environment variables of
-.BR groff (@MAN1EXT@)
-and GNU
-.BR man (1)
+.BR \%groff (@MAN1EXT@)
+and \f[CR]GNU\f[]
+.BR \%man (1)
 and some standard system variables are honored.
 .
 .
@@ -2513,7 +3036,8 @@
 .
 .TP
 .Env_var $GROFFER_OPT
-Store options for a run of groffer.
+Store options for a run of
+.BR \%groffer .
 .
 The options specified in this variable are overridden by the options
 given on the command line.
@@ -2522,33 +3046,43 @@
 so arguments containing white-space or special shell characters should
 be quoted.
 .
+Do not forget to export this variable, otherwise it does not exist
+during the run of
+.BR groffer .
+.
 .
 .\" --------------------------------------------------------------------
 .SS "System Variables"
 .\" --------------------------------------------------------------------
 .
-The groffer program is a shell script that is run through
-.BR /bin/sh ,
+The
+.B \%groffer
+program is a shell script that is run through
+.File_name /bin/sh ,
 which can be internally linked to programs like
-.BR bash (1).
+.BR \%bash (1).
 The corresponding system environment is automatically effective.
 .
-The following variables have a special meaning for groffer.
+The following variables have a special meaning for
+.BR \%groffer .
 .
 .
 .TP
 .Env_var $DISPLAY
-If this variable is set this indicates that the X Window system is
-running.
+If this variable is set this indicates that the \%\f[CR]X\~Window\f[]
+system is running.
 .
 Testing this variable decides on whether graphical or text output is
 generated.
 .
 This variable should not be changed by the user carelessly, but it can
-be used to start the graphical groffer on a remote X terminal.
-.
-For example, depending on your system, groffer can be started on the
-second monitor by the command
+be used to start the graphical
+.B \%groffer
+on a remote \%\f[CR]X\~Window\f[] terminal.
+.
+For example, depending on your system,
+.B \%groffer
+can be started on the second monitor by the command
 .Shell_cmd DISPLAY=:0.1\~groffer\~ what.ever &
 .
 .
@@ -2560,9 +3094,11 @@
 .Env_var $LANG
 If one of these variables is set (in the above sequence), its content
 is interpreted as the locale, the language to be used, especially when
-retrieving man\~pages.
+retrieving
+\IR \%man\~pages .
 .
 A locale name is typically of the form
+.nh
 .IR language [\c
 .B _\c
 .IR territory [\c
@@ -2570,22 +3106,21 @@
 .IR codeset [\c
 .B @\c
 .IR modifier ]]],
+.hy
 where
-.I language
+.I \%language
 is an ISO 639 language code,
-.I territory
+.I \%territory
 is an ISO 3166 country code, and
-.I codeset
+.I \%codeset
 is a character set or encoding identifier like ISO-8859-1 or UTF-8;
 see
-.BR setlocale (3).
+.BR \%setlocale (3).
 .
-The locale values\~\c
-.B C
-and
-.B POSIX
-stand for the default, i.e. the man\~page directories without a
-language prefix.
+The locale values \f[CR]C\f[] and \%\f[CR]POSIX\f[]
+stand for the default, i.e. the
+.I \%man\~page
+directories without a language prefix.
 .
 This is the same behavior as when all 3\~variables are unset.
 .
@@ -2596,65 +3131,77 @@
 .
 For example, to disable the use of a pager completely set this
 variable to the
-.BR cat (1)
+.BR \%cat (1)
 program
 .Shell_cmd PAGER=cat\~groffer\~ anything
 .
 .
 .TP
 .Env_var $PATH
-All programs within the groffer shell script are called without a
-fixed path.
+All programs within the
+.B \%groffer
+shell script are called without a fixed path.
 .
 Thus this environment variable determines the set of programs used
-within the run of groffer.
-.
-.
-.TP
-.Env_var $POSIXLY_CORRECT
-If set to a non-empty value this chooses the POSIX mode for option
-processing, that means that option processing will be finished as soon
-as a non-option argument is found.
-.
-Usually, you do not want to set this environment variable.
+within the run of
+.BR \%groffer .
 .
 .
 .\" --------------------------------------------------------------------
 .SS "Groff Variables"
 .\" --------------------------------------------------------------------
 .
-The groffer program internally calls groff, so all environment
-variables documented in
-.BR groff (@MAN1EXT@)
-are internally used within groffer as well.
+The
+.B \%groffer
+program internally calls
+.BR \%groff ,
+so all environment variables documented in
+.BR \%groff (@MAN1EXT@)
+are internally used within
+.B \%groffer
+as well.
 .
-The following variables have a direct meaning for the groffer program.
+The following variable has a direct meaning for the
+.B \%groffer
+program.
 .
 .TP
 .Env_var $GROFF_TMPDIR
 If the value of this variable is an existing, writable directory,
-groffer uses it for storing its temporary files, just as groff does.
+.B \%groffer
+uses it for storing its temporary files, just as
+.B groff
+does.
 .
 .
 .\" --------------------------------------------------------------------
 .SS "Man Variables"
 .\" --------------------------------------------------------------------
 .
-Parts of the functionality of the man\~program were implemented in
-groffer; support for all environment variables documented in
-.BR man (1)
-was added to groffer, but the meaning was slightly modified due to the
-different approach in groffer; but the user interface is the same.
+Parts of the functionality of the
+.B man
+program were implemented in
+.BR \%groffer ;
+support for all environment variables documented in
+.BR \%man (1)
+was added to
+.BR \%groffer ,
+but the meaning was slightly modified due to the different approach in
+.BR \%groffer ;
+but the user interface is the same.
 .
-The man environment variables can be overwritten by options provided
-with
+The
+.B man
+environment variables can be overwritten by options provided with
 .Env_var $MANOPT ,
 which in turn is overwritten by the command line.
 .
 .
 .TP
 .Env_var $EXTENSION
-Restrict the search for man\~pages to files having this extension.
+Restrict the search for
+.I \%man\~pages
+to files having this extension.
 .
 This is overridden by option
 .Opt_long extension ;
@@ -2664,12 +3211,14 @@
 .TP
 .Env_var $MANOPT
 This variable contains options as a preset for
-.BR man (1).
-As not all of these are relevant for groffer only the essential parts
-of its value are extracted.
+.BR \%man (1).
+As not all of these are relevant for
+.B \%groffer
+only the essential parts of its value are extracted.
 .
 The options specified in this variable overwrite the values of the
-other environment variables taht are specific to man.
+other environment variables that are specific to
+.IR man .
 .
 All options specified in this variable are overridden by the options
 given on the command line.
@@ -2677,7 +3226,8 @@
 .
 .TP
 .Env_var $MANPATH
-If set, this variable contains the directories in which the man\~page
+If set, this variable contains the directories in which the
+.I \%man\~page
 trees are stored.
 .
 This is overridden by option
@@ -2687,7 +3237,8 @@
 .TP
 .Env_var $MANSECT
 If this is a colon separated list of section names, the search for
-man\~pages is restricted to those manual sections in that order.
+.I \%man\~pages
+is restricted to those manual sections in that order.
 .
 This is overridden by option
 .Opt_long sections .
@@ -2696,7 +3247,9 @@
 .TP
 .Env_var $SYSTEM
 If this is set to a comma separated list of names these are interpreted
-as man\~page trees for different operating systems.
+as
+.I \%man\~page
+trees for different operating systems.
 .
 This variable can be overwritten by option
 .Opt_long systems ;
@@ -2706,8 +3259,9 @@
 .P
 The environment variable
 .Env_var $MANROFFSEQ
-is ignored by groffer because the necessary preprocessors are
-determined automatically.
+is ignored by
+.B \%groffer
+because the necessary preprocessors are determined automatically.
 .
 .
 .\" --------------------------------------------------------------------
@@ -2715,51 +3269,81 @@
 .\" --------------------------------------------------------------------
 .
 The
-.I groffer
+.B \%groffer
 program can be preconfigured by two configuration files.
 .
-This configuration can be overridden at each program start by command
-line options or by the environment variable
-.Env_var $GROFFER_OPT .
-.
 .
 .TP
 .File_name /etc/groff/groffer.conf
-System-wide configuration file for groffer.
+System-wide configuration file for
+.BR \%groffer .
 .
 .
 .TP
 .File_name $HOME/.groff/groffer.conf
-User-specific configuration file for groffer, where
+User-specific configuration file for
+.BR \%groffer ,
+where
 .Env_var $HOME
 denotes the user's home directory.
 .
-This script is called after the system-wide configuration file to
-enable overriding by the user.
+This file is called after the system-wide configuration file to enable
+overriding by the user.
+.
+.
+.P
+The precedence of option delivery is given in the following.
+.
+The configuration file in
+.File_name /etc
+has the lowest precedence; it is overwritten by the configuration file
+in the home directory; both configuration files are overwritten by the
+environment variable
+.Env_var $GROFFER_OPT ;
+everything is overwritten by the command line.
 .
 .
 .P
-Their lines either start with a minus character or are shell commands.
+In the configuration files, arbitrary spaces are allowed at the
+beginning of each line, they are just ignored.
+.
+Apart from that, the lines of the configuration lines either start
+with a minus character, all other lines are interpreted as 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.
+.P
+The lines with the beginning minus are interpreted as
+.B groffer
+options.
 .
 This easily allows to set general
-.I groffer
-options that are used with any call of
-.IR groffer .
+.B \%groffer
+options that should be used with any call of
+.BR \%groffer .
+.
+Each line can represent a single short option, a short option cluster,
+or a long option with two minus signs, eventually with an argument.
+.
+The argument can be appended either after a space character or an
+equal sign
+.RB ` = '.
+The argument can be surrounded by quotes, but this is not necessary.
+.
+The options from these lines are collected and prepended to the
+existing value of
+.Env_var $GROFFER_OPT
+at the end of each configuration file.
 .
 .
 .P
-After the transformation of the minus lines the emerging shell scripts
-that are called by
-.I groffer
+After the transformation of the minus lines, the configuration files
+have been transferred into a shell script that is called within
+.B \%groffer
 using the `\c
-.CB .\~\c
-.IR filename '
-syntax.
+.CB \.\~\c
+.IR \%filename '
+shell syntax.
 .
 .
 .P
@@ -2767,28 +3351,38 @@
 tasks:
 .
 .Topic
-Preset command line options by writing them into lines starting with a
-minus sign.
+Preset command line options, such as choosing a
+.I \%mode
+or a viewer.
+.
+These are written into lines starting with a single or double minus
+sign, followed by the option name.
 .
 .Topic
-Preset environment variables recognized by groffer.
+Preset environment variables recognized by
+.BR \%groffer ;
+but do not forget to export them.
 .
 .Topic
-Write a function for calling a viewer program for a special
-.I mode
-and feed this name into its corresponding
+You can also write a shell function for calling, for example a viewer
+program for some
+.IR \%mode .
+Such a function can be fed into a corresponding
 .Opt_long \f[I]mode\f[]\-viewer
 option.
 .
-Note that the name of such a function must coincide with some existing
-program in the system path
-.Env_var $PATH
-in order to be recognized by groffer.
+.Topic
+Enter
+.Opt_long shell
+to specify a shell for the run of
+.File_name groffer2.sh .
+Some shells run much faster than the standard shell.
 .
 .
 .P
 As an example, consider the following configuration file in
-~/.groff/groffer.conf, say.
+.File_name ~/.groff/groffer.conf ,
+say.
 .
 .P
 .ft CR
@@ -2797,13 +3391,14 @@
 # groffer configuration file
 #
 # groffer options that are used in each call of groffer
---resolution=100
---foreground=DarkBlue
---x-viewer 'gxditview -geometry 850x800'
+\-\-shell=ksh
+\-\-foreground=DarkBlue
+\-\-resolution=100
+\-\-x\-viewer='gxditview \-geometry 900x1200'
 #
 # some shell commands
 if test "$DISPLAY" = ""; then
-  DISPLAY='localhost:0.0'
+  export DISPLAY='localhost:0.0'
 fi
 date >>~/mygroffer.log
 .fi
@@ -2812,55 +3407,76 @@
 .
 .
 .P
-This configuration sets three
-.I groffer
-options and runs two shell commands.
+The lines starting with
+.B #
+are command lines.
+.
+This configuration sets four
+.B \%groffer
+options (the lines starting with `\-') and runs two shell commands (the
+rest of the script).
 .
 This has the following effects:
 .
 .
 .Topic
-Lines starting with a 
-.B #
-character
-are 
+Use
+.B ksh
+as the shell to run the
+.B \%groffer
+script; if it works it should be faster than the usual
+.BR sh .
+.
+.
+.Topic
+Use a text color of
+.B \%DarkBlue
+in all viewers that support this, such as
+.BR \%gxditview .
 .
 .
 .Topic
 Use a resolution of
-.B 100 dpi
-and a text color of
-.B DarkBlue
-in all viewers that support this.
+.B 100\~dpi
+in all viewers that support this, such as
+.BR \%gxditview .
+.
+By this, the default device in
+.I x mode
+is set to
+.BR X100 .
 .
 .
 .Topic
 Force
-.BR gxditview (@MAN1EXT@)
-as the X-mode viewer using the geometry option for setting the width
-to
-.B 850 dpi
+.BR \%gxditview (@MAN1EXT@)
+as the
+.I \%x-mode
+viewer using the geometry option for setting the width to
+.B 900\~dpi
 and the height to
-.B 800
-.BR dpi .
+.BR 1200\~dpi .
+This geometry is suitable for a resolution of
+.BR 100\~dpi .
 .
 .
 .Topic
-The variable
+If the environment 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.
+is empty set it to
+.IR localhost:0.0 .
+.
+That allows to start
+.B \%groffer
+in the standard \%\f[CR]X\~Window\f[] display, even when the program
+is called from a text console.
 .
 .
 .Topic
 Just for fun, the date of each
-.I groffer
+.B \%groffer
 start is written to the file
-.B mygroffer.log
+.File_name mygroffer.log
 in the home directory.
 .
 .
@@ -2868,44 +3484,54 @@
 .SH "EXAMPLES"
 .\" --------------------------------------------------------------------
 .
-The usage of groffer is very easy.
-.
-Usually, it is just called with a file name or man\~page.
-.
-The following examples, however, show that groffer has much more fancy
-capabilities.
+The usage of
+.B \%groffer
+is very easy.
+.
+Usually, it is just called with a file name or
+.IR \%man\~page .
+.
+The following examples, however, show that
+.B \%groffer
+has much more fancy capabilities.
 .
 .
 .TP
 .Shell_cmd "groffer\~/usr/local/share/doc/groff/meintro.ms.gz"
 Decompress, format and display the compressed file
-.I meintro.ms.gz
+.File_name meintro.ms.gz
 in the directory
-.IR /usr/local/share/doc/groff ,
-using
-.I gxditview
-as graphical viewer when in X Window, or the
-.BR less (1)
-pager program when not in X.
+.File_name /usr/local/share/doc/groff ,
+using the standard viewer
+.B \%gxditview
+as graphical viewer when in \%\f[CR]X\~Window\f[], or the
+.BR \%less (1)
+pager program when not in \%\f[CR]X\~Window\f[].
 .
 .
 .TP
 .Shell_cmd "groffer\~groff"
 If the file
-.I ./groff
+.File_name \%./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.
+Otherwise interpret the argument as a search for the
+.I \%man\~page
+named
+.B \%groff
+in the smallest possible
+.IR \%man\~section ,
+being section 1 in this case.
 .
 .
 .TP
 .Shell_cmd "groffer\~man:groff"
-search for the man\~page of
-.I groff
+search for the
+.I \%man\~page
+of
+.B \%groff
 even when the file
-.I ./groff
+.File_name ./groff
 exists.
 .
 .
@@ -2913,9 +3539,12 @@
 .Shell_cmd "groffer\~groff.7"
 .TP+
 .Shell_cmd "groffer\~7\~groff"
-search the man\~page of
-.I groff
-in man\~section
+search the
+.I \%man\~page
+of
+.B \%groff
+in
+.I \%man\~section
 .BR 7 .
 This section search works only for a digit or a single character from
 a small set.
@@ -2924,31 +3553,36 @@
 .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 .
+.File_name ./fb.modes
+does not exist interpret this as a search for the
+.I \%man\~page
+of
+.BR fb.modes .
 As the extension
-.I modes
+.I \%modes
 is not a single character in classical section style the argument is
 not split to a search for
-.IR fb .
+.BR 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
-(automatic search, should be found in man\~section\~1),
-.I troff
+following
+.IR \%man\~pages :
+.B \%groff
+(automatic search, should be found in \fIman\fP\~section\~1),
+.B \%troff
 (in section\~1),
 and
-.I roff
+.B \%roff
 (in the section with the lowest number, being\~7 in this case).
 .
 The quotes around
+.nh
 .I \[cq]troff(1)\[cq]
+.hy
 are necessary because the paranthesis are special shell characters;
 escaping them with a backslash character
 .I \[rs](
@@ -2960,44 +3594,55 @@
 .
 .
 .TP
-.Shell_cmd "LANG=de\~groffer\~--man\~--www\~--www-viever=mozilla\~ls"
+.Shell_cmd "LANG=de\~groffer\~--man\~--www\~--www-viever=galeon\~ls"
 .
-Retrieve the German man\~page (language
+Retrieve the German
+.I \%man\~page
+(language
 .IR de )
 for the
 .B ls
 program, decompress it, format it to
-.I html
+.I \%html
 format
-.RI ( www
-mode) and view the result in the web browser
-.I galeon .
+.nh
+.RI ( \%www\~mode )
+.hy
+and view the result in the web browser
+.BR \%galeon .
 The option
 .Opt_long man
-guarantees that the man\~page is retrieved, even when a local file
-.I ls
+guarantees that the
+.I \%man\~page
+is retrieved, even when a local file
+.File_name \%ls
 exists in the actual directory.
 .
 .
 .TP
 .Shell_cmd "groffer\~--source\~'man:roff(7)'"
 .
-Get the man\~page called
-.I roff
-in man\~section 7, decompress it, and print its unformatted content,
-its source code.
+Get the
+.I \%man\~page
+called
+.I \%roff
+in \fIman\fP\~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, send this to
-.I groff
-intermediate mode without post-processing (groff option
+.I \%groff intermediate output mode
+without post-processing
+.RB ( groff
+option
 .Opt_short Z ),
 using macro package by
-.I foo
-(groff option
+.I \%foo
+.RB ( groff
+option
 .Opt_short m ) .
 .
 .
@@ -3015,86 +3660,109 @@
 .\" --------------------------------------------------------------------
 .
 The
-.B groffer
-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 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.
+.B \%groffer
+program consists of two shell scripts.
 .
 .
 .P
-Most GNU shells are compatible with this interpretation of POSIX, but
-provide much more facilities.
+The starting script is the file
+.File_name \%groffer
+that is installed in a
+.File_name bin
+directory.
 .
-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.
+It is generated from the source file
+.File_name \%groffer.sh .
 .
-The groffer script should work on most actual free and commercial
-operating systems.
+It is just a short starting script without any functions such that it
+can run on very poor shells.
 .
 .
 .P
-The groffer program provides its own parser for command line options;
-it can handle option arguments and file names containing white space
-and a large set of special characters.
+The main part of the
+.B \%groffer
+program is the file
+.File_name groffer2.sh
+that is installed in the
+.I groff
+library directory.
+.
+This script can be run under a different shell by using the
+.B \%groffer
+option
+.Opt_long shell .
 .
 .
 .P
-The groffer shell script was tested with the following common
-implementations of the GNU shells:
-.BR ash (1),
-POSIX
-.BR sh (1),
-.BR bash (1),
-and others.
+Both scripts are compatible with both
+\f[CR]GNU\f[] and \%\f[CR]POSIX\f[].
 .
-Free POSIX compatible shells and shell utilities for most operating
-systems are available at the
-.URL http://\:www.gnu.org/software/ "GNU software archive" .
+\%\f[CR]POSIX\f[] compatibility refers to
+\%\f[CR]IEEE\~P1003.2/D11.2\f[] of September 1991, a very early
+version of the \%\f[CR]POSIX\f[] standard that is still freely
+available in the internet at
+.URL http://\:www.funet.fi/\:pub/\:doc/\:posix/\:p1003.2/\:d11.2/\:all \
+"\%POSIX\~P1003.2\~draft\~11.2" .
 .
 .
 .P
-The best performance was obtained with the
-.I ash
-shell; so
-.I groffer
-tries to run under
-.I ash
-whenever possible.
+Only a restricted set of shell language elements and shell builtins is
+used to achieve even compatibility with some Bourne shells that are
+not fully \%\f[CR]POSIX\f[] compatible.
 .
-If
-.I ash
-is not available the shell under which the script was started in the
-first place is used instead.
+The
+.B \%groffer
+shell scripts were tested on many shells, including the following
+Bourne shells:
+.BR \%ash (1),
+.BR \%bash (1),
+.BR \%dash (1),
+.BR \%ksh (1),
+.BR \%pdksh (1),
+.BR \%posh (1),
+and
+.BR \%zsh (1).
+So it should work on most actual free and commercial operating
+systems.
 .
-This can be modified by the option
+.
+.P
+The shell for the run of
+.File_name groffer2.sh
+can be chosen by the option
+.Opt_long shell
+on the command line or the environment variable
+.Env_var $GROFF_OPT .
+If you want to add it to one of the
+.B \%groffer
+configuration files you must write a line starting with
 .Opt_long shell .
 .
 .
 .P
-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)
-except for shortcuts of long options.
+The
+.B \%groffer
+program provides its own parser for command line arguments that is
+compatible to both \%\f[CR]POSIX\f[]
+.BR \%getopts (1)
+and \%\f[CR]GNU\f[]
+.BR \%getopt (1).
+It can handle option arguments and file names containing white space
+and a large set of special characters.
 .
 The following standard types of options are supported.
 .
 .
 .Topic
-A single minus always refers to single character option or a
-combination thereof, for example, the
-.I groffer
+The option consisiting of a single minus
+.Opt_short
+refers to standard input.
+.
+.
+.Topic
+A single minus followed by characters refers to a single character
+option or a combination thereof; for example, the
+.B \%groffer
 short option combination
 .Opt_short Qmfoo
 is equivalent to
@@ -3103,7 +3771,7 @@
 .
 .Topic
 Long options are options with names longer than one character; they
-are always prededed by a double minus.
+are always preceded 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,
@@ -3116,161 +3784,232 @@
 An argument of
 .Opt_--
 ends option parsing; all further command line arguments are
-interpreted as file name arguments.
+interpreted as
+.I \%filespec
+parameters, i.e. file names or constructs for searching
+.IR \%man\~pages ).
 .
 .
 .Topic
-By default, all command line arguments that are neither options nor
-option arguments are interpreted as filespec parameters and stored
-until option parsing has finished.
+All command line arguments that are neither options nor option
+arguments are interpreted as
+.I \%filespec
+parameters and stored until option parsing has finished.
 .
 For example, the command line
 .Shell_cmd "groffer file1 -a -o arg file2"
-is, by default, equivalent to
+is equivalent to
 .Shell_cmd "groffer -a -o arg -- file1 file2"
 .
 .
 .P
-This behavior can be changed by setting the environment variable
-.Env_var $POSIXLY_CORRECT
-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.
+The free mixing of options and
+.I \%filespec
+parameters follows the GNU principle.
 .
-For example, in posixly correct mode, the command line
-.Shell_cmd "groffer file1 -a -o arg file 2"
-is equivalent to
-.Shell_cmd "groffer -- file1 -a -o arg file 2"
-As this leads to unwanted behavior in most cases, most people do not
-want to set
-.Env_var $POSIXLY_CORRECT .
+That does not fulfill the strange option behavior of \%\f[CR]POSIX\f[]
+that ends option processing as soon as the first non-option argument
+has been reached.
+.
+The end of option processing can be forced by the option
+.RB ` \-\- '
+anyway.
 .
 .
 .\" --------------------------------------------------------------------
-.SH "SEE ALSO"
+.SH "BUGS"
 .\" --------------------------------------------------------------------
 .
-.TP
-.BR groff (@MAN1EXT@)
-.TP+
-.BR troff (@MAN1EXT@)
-Details on the options and environment variables available in
-.IR groff ;
-all of them can be used with groffer.
+Report bugs to the
+.MTO bug-groff@gnu.org "bug-groff mailing list" .
 .
+Include a complete, self-contained example that will allow the bug to
+be reproduced, and say which version of
+.B \%groffer
+you are using.
 .
-.TP
-.BR man (1)
-The standard program to diplay man\~pages.
 .
-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.
+.P
+You can also use the
+.MTO groff@gnu.org "groff mailing list" ,
+but you must first subscribe to this list.
 .
+You can do that by visiting the
+.URL http://\:lists.gnu.org/\:mailman/\:listinfo/\:groff \
+"groff mailing list web page" .
 .
-.TP
-.BR gxditview (@MAN1EXT@)
-.TP+
-.BR xditview (1x)
-Viewers for groffer's
-.I x
-mode.
 .
+.P
+See
+.BR \%groff (@MAN1EXT@)
+for information on availability.
 .
-.TP
-.BR gv (1)
-.TP+
-.BR ghostview (1)
-Viewers for groffer's
-.I ps
-mode.
 .
+.\" --------------------------------------------------------------------
+.SH "SEE ALSO"
+.\" --------------------------------------------------------------------
 .
-.TP+
-.BR gs (1)
-Transformer from
-.I ps
-to
-.IR pdf ;
-and a
-.I ps
-viewer.
+.P
+.BR \%groff (@MAN1EXT@),
+.BR \%@g@troff (@MAN1EXT@)
+.RS
+Details on the options and environment variables available in
+.BR \%groff ;
+all of them can be used with
+.BR \%groffer .
+.RE
 .
 .
 .TP
-.BR xpdf (1)
-Viewers for
-.I pdf
-files.
+.BR \%groff (@MAN7EXT@)
+Documentation of the
+.I \%groff
+language.
 .
 .
 .TP
-.BR xdvi (1)
-.TP+
-.BR dvilx (1)
-Viewers for groffer's
-.I dvi
-mode.
+.BR \%grog (@MAN1EXT@)
+Internally,
+.B \%groffer
+tries to guess the
+.B \%groff
+command line options from the input using this program.
 .
 .
 .TP
-.BR less (1)
-Standard pager program for the
-.I tty
-.IR mode .
+.BR groff_out (@MAN5EXT@)
+Documentation on the
+.I \%groff intermediate output
+.nh
+.RI ( ditroff
+output).
+.hy
 .
 .
 .TP
-.BR gzip (1)
-.TP+
-.BR bzip2 (1)
-The decompression programs supported by groffer.
+.BR groff_tmac (@MAN5EXT@)
+Documentation on the
+.I \%groff
+macro files.
 .
 .
 .TP
-.BR groff (@MAN7EXT@)
-Documentation of the
-.I groff
-language.
+.BR \%man (1)
+The standard program to display
+.IR \%man\~pages .
 .
+The information there is only useful if it is the
+.I \%man\~page
+for GNU
+.BR man .
+Then it documents the options and environment variables that are
+supported by
+.BR \%groffer .
 .
-.TP
-.BR grog (@MAN1EXT@)
-Internally, groffer tries to guess the groff command line options from
-the input using this program.
 .
+.P
+.BR \%ash (1),
+.BR \%bash (1),
+.BR \%dash (1),
+.BR \%ksh (1),
+.BR \%pdksh (1),
+.BR \%posh (1),
+.BR \%sh (1),
+.BR \%zsh (1)
+.RS
+Bourne shells that were tested with
+.BR \%groffer .
+.RE
 .
-.TP
-.BR groff_out (@MAN5EXT@)
-Documentation on the groff intermediate output (ditroff output).
 .
+.P
+.BR \%gxditview (@MAN1EXT@),
+.BR \%xditview (1x)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%x\~mode .
+.RE
 .
-.\" --------------------------------------------------------------------
-.SH "AUTHOR"
-.\" --------------------------------------------------------------------
 .
-Copyright (C) 2001,2002,2004 Free Software Foundation, Inc.
+.P
+.BR \%kghostview (1),
+.BR \%ggv (1),
+.BR \%gv (1),
+.BR \%ghostview (1),
+.BR \%gs (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%ps\~mode .
+.RE
+.
 .
 .P
-This document is distributed under the terms of the FDL (GNU Free
-Documentation License) version 1.1 or later.
+.BR \%kghostview (1),
+.BR \%ggv (1),
+.BR \%xpdf (1),
+.BR \%acroread (1),
+.BR \%kpdf (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%pdf\~mode .
+.RE
 .
-You should have received a copy of the FDL on your system, it is also
-available on-line at the
-.URL http://\:www.gnu.org/\:copyleft/\:fdl.html "GNU copyleft site" .
 .
 .P
-This document is part of
-.IR groff ,
-the GNU roff distribution.
+.BR \%kdvi (1),
+.BR \%xdvi (1),
+.BR \%dvilx (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%dvi\~mode .
+.RE
+.
+.
+.P
+.BR \%konqueror (1),
+.BR \%mozilla (1),
+.BR \%lynx (1)
+.RS
+Web-browsers for
+.BR \%groffer 's
+.I \%html
+or
+.IR \%www\~mode .
+.RE
+.
+.
+.TP
+.BR \%less (1)
+Standard pager program for the
+.I \%tty\~mode .
+.
 .
-It was written by Bernd Warken.
+.P
+.BR \%gzip (1),
+.BR \%bzip2 (1)
+.RS
+The decompression programs supported by
+.BR \%groffer .
+.RE
 .
 .
-\" --------------------------------------------------------------------
+.\" --------------------------------------------------------------------
+.SH "AUTHOR"
+.\" --------------------------------------------------------------------
+.author
+.
+.
+.\" --------------------------------------------------------------------
+.SH "COPYING"
+.\" --------------------------------------------------------------------
+.copyleft
+.
+.
+.\" --------------------------------------------------------------------
 .\" Emacs settings
 .\" --------------------------------------------------------------------
 .
diff -u -r --new-file groff-1.19.1/contrib/groffer/groffer.sh groff-1.19.2/contrib/groffer/groffer.sh
--- groff-1.19.1/contrib/groffer/groffer.sh	2004-05-03 22:03:01.000000000 -0700
+++ groff-1.19.2/contrib/groffer/groffer.sh	2005-08-22 15:08:40.000000000 -0700
@@ -1,4535 +1,299 @@
-#!/bin/sh
+#! /bin/sh
 
 # groffer - display groff files
 
 # Source file position: /contrib/groffer/groffer.sh
 
-# Copyright (C) 2001,2002,2003,2004 Free Software Foundation, Inc.
+# Copyright (C) 2001,2002,2003,2004,2005
+# Free Software Foundation, Inc.
 # Written by Bernd Warken
 
-# This file is part of groff version @VERSION@.
+# This file is part of `groffer', which is part of `groff' version
+# @VERSION@.  See $_GROFF_VERSION.
 
-# groff is free software; you can redistribute it and/or modify it
+# `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.
+# `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.
-
-_PROGRAM_NAME='groffer';
-_PROGRAM_VERSION='0.9.7';
-_LAST_UPDATE='30 Apr 2004';
-
-
-########################################################################
-# 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}" = ''; then
-  # only reached during the first run of the script
-
-  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 ("$@")
-  #
-  # Determine whether `--shell' was specified in $GROFF_OPT or in $*;
-  # if so echo its argument.
-  #
-  _get_opt_shell()
-  {
-    local i;
-    local _sh;
-    case " ${GROFFER_OPT} $*" in
-      *\ --shell\ *|*\ --shell=*)
-        (
-          eval set -- "${GROFFER_OPT}" '"$@"';
-          _sh='';
-          for i in "$@"; do
-            case "$1" in
-              --shell)
-                if test "$#" -ge 2; then
-                  _sh="$2";
-                  shift;
-                fi;
-                ;;
-              --shell=?*)
-                # delete up to first `=' character
-                _sh="$(echo -n "$1" | sed -e 's/^[^=]*=//')";
-                ;;
-            esac;
-            shift;
-          done;
-          echo -n "${_sh}";
-        )
-        ;;
-    esac;
-  }
-
-
-  ###########################
-  # _test_on_shell ()
-  #
-  # Test whether  is a shell program of Bourne type (POSIX sh).
-  #
-  _test_on_shell()
-  {
-    if test "$#" -le 0 || test "$1" = ''; then
-      return 1;
-    fi;
-    # do not quote $1 to allow arguments
-    test "$($1 -c 's=ok; echo -n "$s"' 2>/dev/null)" = 'ok';
-  }
-
-  # do the shell determination
-  _shell="$(_get_opt_shell "$@")";
-  if test "${_shell}" = ''; then
-    _shell='ash';
-  fi;
-  if _test_on_shell "${_shell}"; then
-    _groffer_run='second';
-    # do not quote $_shell to allow arguments
-    exec ${_shell} "${_GROFFER_SH}" "$@";
-    exit;
-  fi;
-
-  # clean-up of shell determination
-  unset _shell;
-  unset _GROFFER_SH;
-  unset _groffer_run;
-  _get_opt_shell()
-  {
-    return 0;
-  }
-  _test_on_shell()
-  {
-    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
-
-
-########################################################################
-# diagnostic messages
-#
-export _DEBUG;
-_DEBUG='no';			# disable debugging information
-#_DEBUG='yes';			# enable debugging information
-
-export _DEBUG_LM;
-_DEBUG_LM='no';			# disable landmark messages
-#_DEBUG_LM='yes';		# enable landmark messages
-
+# 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301,
+# USA.
 
 ########################################################################
-#                       Environment Variables
-########################################################################
-
-# Environment variables that exist only for this file start with an
-# underscore letter.  Global variables to this file are written in
-# upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
-# start with an underline and use only lower case letters and
-# underlines, e.g.  $_local_variable .
 
-#   [A-Z]*     system variables,      e.g. $MANPATH
-#   _[A-Z_]*   global file variables, e.g. $_MAN_PATH
-#   _[a-z_]*   temporary variables,   e.g. $_manpath
+_PROGRAM_VERSION='0.9.22';
+_LAST_UPDATE='22 August 2005';
 
-# Due to incompatibilities of the `ash' shell, the name of loop
-# variables in `for' must be single character
-#   [a-z]      local loop variables,   e.g. $i
+export _PROGRAM_VERSION;
+export _LAST_UPDATE;
 
+export GROFFER_OPT;		# option environment for groffer
 
-########################################################################
-# read-only variables (global to this file)
-########################################################################
+export _CONF_FILE_ETC;		# configuration file in /etc
+export _CONF_FILE_HOME;		# configuration file in $HOME
+export _CONF_FILES;		# configuration files
+_CONF_FILE_ETC='/etc/groff/groffer.conf';
+_CONF_FILE_HOME="${HOME}/.groff/groffer.conf";
+_CONF_FILES="${_CONF_FILE_ETC} ${_CONF_FILE_HOME}";
 
 # characters
 
-export _BQUOTE;
-export _BSLASH;
-export _DQUOTE;
-export _NEWLINE;
-export _LBRACK;
-export _LPAR;
-export _RBRACK;
-export _RPAR;
-export _SPACE;
-export _SQUOTE;
+export _AT;
+export _SP;
+export _SQ;
 export _TAB;
 
-_BQUOTE='`';
-_BSLASH='\';
-_DQUOTE='"';
-_NEWLINE='
-';
-_LBRACK='[';
-_LPAR='(';
-_RBRACK=']';
-_RPAR=')';
-_SPACE=' ';
-_SQUOTE="'";
+_AT='@';
+_SP=' ';
+_SQ="'";
 _TAB='	';
 
-# function return values; `0' means ok; other values are error codes
-export _ALL_EXIT;
-export _BAD;
 export _ERROR;
-export _GOOD;
-export _NO;
-export _OK;
-export _YES;
-
-_GOOD='0';			# return ok
-_BAD='1';			# return negatively, error code `1'
 _ERROR='7';			# for syntax errors; no `-1' in `ash'
 
-_ALL_EXIT="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')
-
-_NO="${_BAD}";
-_YES="${_GOOD}";
-_OK="${_GOOD}";
-
-# quasi-functions, call with `eval'
-export return_ok;
-export return_good;
-export return_bad;
-export return_yes;
-export return_no;
-export return_error;
-return_ok="func_pop; return ${_OK}";
-return_good="func_pop; return ${_GOOD}";
-return_bad="func_pop; return ${_BAD}";
-return_yes="func_pop; return ${_YES}";
-return_no="func_pop; return ${_NO}";
-return_error="func_pop; return ${_ERROR}";
-
-
-export _CONFFILES;
-_CONFFILES="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf";
-
-export _DEFAULT_MODES;
-_DEFAULT_MODES='x,ps,tty';
-export _DEFAULT_RESOLUTION;
-_DEFAULT_RESOLUTION='75';
-
-export _DEFAULT_TTY_DEVICE;
-_DEFAULT_TTY_DEVICE='latin1';
-
-# _VIEWER_* viewer programs for different modes (only X is necessary)
-# _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_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_HTML='konqueror,mozilla,netscape,opera,amaya,arena,lynx';
-_VIEWER_X='gxditview,xditview';
-
-# Search automatically in standard sections `1' to `8', and in the
-# traditional sections `9', `n', and `o'.  On many systems, there
-# exist even more sections, mostly containing a set of man pages
-# special to a specific program package.  These aren't searched for
-# automatically, but must be specified on the command line.
-export _MAN_AUTO_SEC;
-_MAN_AUTO_SEC="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"
-
-export _PROCESS_ID;		# for shutting down the program
-_PROCESS_ID="$$";
-
-
-############ the command line options of the involved programs
-#
-# The naming scheme for the options environment names is
-# $_OPTS__[_]
-#
-# :    program name GROFFER, GROFF, or CMDLINE (for all
-#            command line options)
-# :  LONG (long options) or SHORT (single character options)
-# : ARG for options with argument, NA for no argument;
-#            without _ both the ones with and without arg.
-#
-# Each option that takes an argument must be specified with a
-# trailing : (colon).
-
-# exports
-export _OPTS_GROFFER_SHORT_NA;
-export _OPTS_GROFFER_SHORT_ARG;
-export _OPTS_GROFFER_LONG_NA;
-export _OPTS_GROFFER_LONG_ARG;
-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_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_LONG_NA;
-export _OPTS_CMDLINE_LONG_ARG;
-
-###### groffer native options
-
-_OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
-_OPTS_GROFFER_SHORT_ARG="'T'";
-
-_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="\
-'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'";
-
-##### 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="'source'";
-_OPTS_GROFF_LONG_ARG="'device' 'macro-file'";
-
-##### groffer options inhereted from the X Window toolkit
-
-_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' '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'";
-
-###### additional options for parsing $MANOPT only
-
-_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'";
-
-_OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
-'apropos' 'debug' 'default' 'html' 'ignore-case' 'location-cat' \
-'match-case' 'troff' 'update' 'version' 'where-cat'";
+# @...@ constructs
 
-_OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
-'config_file' 'encoding' 'locale'";
-
-###### collections of command line options
-
-_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_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
-_OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
-${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
-
-
-########################################################################
-# read-write variables (global to this file)
-########################################################################
-
-export _ADDOPTS_GROFF;		# Transp. options for groff (`eval').
-export _ADDOPTS_POST;		# Transp. options postproc (`eval').
-export _ADDOPTS_X;		# Transp. options X postproc (`eval').
-export _DEFAULT_MODES;		# Set default modes.
-export _DISPLAY_MODE;		# Display mode.
-export _DISPLAY_PROG;		# Viewer program to be used for display.
-export _DISPLAY_ARGS;		# X resources for the viewer program.
-export _FILEARGS;		# Stores filespec parameters.
-export _FUNC_STACK;		# Store debugging information.
-export _REGISTERED_TITLE;	# Processed file names.
-# _HAS_* from availability tests
-export _HAS_COMPRESSION;	# `yes' if compression is available
-export _HAS_OPTS_GNU;		# `yes' if GNU `getopt' is available
-export _HAS_OPTS_POSIX;		# `yes' if POSIX `getopts' is available
-# _MAN_* finally used configuration of man searching
-export _MAN_ALL;		# search all man pages per filespec
-export _MAN_ENABLE;		# enable search for man pages
-export _MAN_EXT;		# extension for man pages
-export _MAN_FORCE;		# force file parameter to be man pages
-export _MAN_IS_SETUP;		# setup man variables only once
-export _MAN_LANG;		# language for man pages
-export _MAN_LANG_DONE;		# language dirs added to man path
-export _MAN_PATH;		# search path for man pages
-export _MAN_SEC;		# sections for man pages; sep. `:'
-export _MAN_SEC_DONE;		# sections added to man path
-export _MAN_SYS;		# system names for man pages; sep. `,'
-export _MAN_SYS;		# system names added to man path
-# _MANOPT_* as parsed from $MANOPT
-export _MANOPT_ALL;		# $MANOPT --all
-export _MANOPT_EXTENSION;	# $MANOPT --extension
-export _MANOPT_LANG;		# $MANOPT --locale
-export _MANOPT_PATH;		# $MANOPT --manpath
-export _MANOPT_PAGER;		# $MANOPT --pager
-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;		# 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.
-export _OPT_DEBUG;		# print debugging information on stderr.
-export _OPT_DEFAULT_MODES;	# `,'-list of modes when no mode given.
-export _OPT_DEVICE;		# device option.
-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, ""
-export _OPT_MANPATH;		# manual setting of path for man-pages
-export _OPT_PAGER;		# specify paging program for tty mode
-export _OPT_RESOLUTION;		# set X resolution in dpi
-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_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_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_XRM;		# specify X resource.
-export _OPT_Z;			# groff option -Z.
-# _TMP_* temporary files
-export _TMP_DIR;		# groff directory for temporary files
-export _TMP_DIR_SUB;		# groffer directory for temporary files
-export _TMP_CAT;		# stores concatenation of everything
-export _TMP_STDIN;		# stores stdin, if any
-
-# these variables are preset in section `Preset' after the rudim. test
+export _GROFF_VERSION
+_GROFF_VERSION='@VERSION@';
+if test _@VERSION@_ = _${_AT}VERSION${_AT}_
+then
+  _GROFF_VERSION='1.19.2';
+fi;
 
+export _AT_BINDIR_AT;
+export _AT_G_AT;
+export _AT_LIBDIR_AT;
+export _GROFFER_LIBDIR;
+if test _@BINDIR@_ = _${_AT}BINDIR${_AT}_
+then
+  # script before `make'
+  _AT_BINDIR_AT='.';
+  _AT_G_AT='';
+  _AT_LIBDIR_AT='';
+  _GROFFER_LIBDIR='.';
+else
+  _AT_BINDIR_AT='@BINDIR@';
+  _AT_G_AT='@g@';
+  _AT_LIBDIR_AT='@libdir@';
+  _GROFFER_LIBDIR="${_AT_LIBDIR_AT}"'/groff/groffer';
+fi;
 
-########################################################################
-#             Test of rudimentary shell functionality
-########################################################################
+export _GROFFER_SH;		# file name of this shell script
+case "$0" in
+*groffer*)
+  _GROFFER_SH="$0";
+  # was: _GROFFER_SH="${_AT_BINDIR_AT}/groffer";
+  ;;
+*)
+  echo 'The groffer script should be started directly.' >&2
+  exit 1;
+  ;;
+esac;
 
+export _GROFFER2_SH;		# file name of the script that follows up
+_GROFFER2_SH="${_GROFFER_LIBDIR}"/groffer2.sh;
 
-########################################################################
-# Test of `test'.
-#
-test "a" = "a" || exit 1;
+export _NULL_DEV;
+if test -c /dev/null
+then
+  _NULL_DEV="/dev/null";
+else
+  _NULL_DEV="NUL";
+fi;
 
 
-########################################################################
-# Test of `echo' and the `$()' construct.
-#
-echo -n '' >/dev/null || exit "${_ERROR}";
-if test "$(echo -n 'te' && echo -n '' && echo -n 'st')" != "test"; then
+# Test of the `$()' construct.
+if test _"$(echo "$(echo 'test')")"_ \
+     != _test_
+then
+  echo 'The "$()" construct did not work.' >&2;
   exit "${_ERROR}";
 fi;
 
-
-########################################################################
-# Test of function definitions.
-#
-_t_e_s_t_f_u_n_c_()
-{
-  return "${_OK}";
-}
-
-if _t_e_s_t_f_u_n_c_ 2>/dev/null; then
-  :
-else
-  echo 'shell does not support function definitions.' >&2;
+# Test of sed program
+if test _"$(echo red | sed -e 's/r/s/')"_ != _sed_
+then
+  echo 'The sed program did not work.' >&2;
   exit "${_ERROR}";
 fi;
 
 
-########################################################################
-# Preset and reset of read-write global variables
-########################################################################
-
-
-# For variables that can be reset by option `--default', see reset().
+########################### configuration
 
-_FILEARGS='';
-
-# _HAS_* from availability tests
-_HAS_COMPRESSION='';
-_HAS_OPTS_GNU='';
-_HAS_OPTS_POSIX='';
-
-# _TMP_* temporary files
-_TMP_DIR='';
-_TMP_DIR_SUB='';
-_TMP_CAT='';
-_TMP_STDIN='';
-
-
-########################################################################
-# reset ()
-#
-# Reset the variables that can be affected by options to their default.
-#
-reset()
-{
-  if test "$#" -ne 0; then
-    error "reset() does not have arguments.";
-  fi;
-
-  _ADDOPTS_GROFF='';
-  _ADDOPTS_POST='';
-  _ADDOPTS_X='';
-  _DISPLAY_ARGS='';
-  _DISPLAY_MODE='';
-  _DISPLAY_PROG='';
-  _REGISTERED_TITLE='';
-
-  # _MAN_* finally used configuration of man searching
-  _MAN_ALL='no';
-  _MAN_ENABLE='yes';		# do search for man-pages
-  _MAN_EXT='';
-  _MAN_FORCE='no';		# first local file, then search man page
-  _MAN_IS_SETUP='no';
-  _MAN_LANG='';
-  _MAN_LANG_DONE='no';
-  _MAN_PATH='';
-  _MAN_SEC='';
-  _MAN_SEC_DONE='no';
-  _MAN_SYS='';
-  _MAN_SYS_DONE='no';
-
-  # _MANOPT_* as parsed from $MANOPT
-  _MANOPT_ALL='no';
-  _MANOPT_EXTENSION='';
-  _MANOPT_LANG='';
-  _MANOPT_PATH='';
-  _MANOPT_PAGER='';
-  _MANOPT_SEC='';
-  _MANOPT_SYS='';
-
-  # _OPT_* as parsed from groffer command line
-  _OPT_ALL='no';
-  _OPT_APROPOS='';
-  _OPT_APROPOS_DATA='';
-  _OPT_APROPOS_DEVEL='';
-  _OPT_APROPOS_PROGS='';
-  _OPT_BD='';
-  _OPT_BG='';
-  _OPT_BW='';
-  _OPT_DEBUG='no';
-  _OPT_DEFAULT_MODES='';
-  _OPT_DEVICE='';
-  _OPT_DISPLAY='';
-  _OPT_FG='';
-  _OPT_FN='';
-  _OPT_GEOMETRY='';
-  _OPT_ICONIC='no';
-  _OPT_LANG='';
-  _OPT_LOCATION='no';
-  _OPT_MODE='';
-  _OPT_MANPATH='';
-  _OPT_PAGER='';
-  _OPT_RESOLUTION='';
-  _OPT_RV='no';
-  _OPT_SECTIONS='';
-  _OPT_SYSTEMS='';
-  _OPT_TITLE='';
-  _OPT_TEXT_DEVICE='';
-  _OPT_V='no';
-  _OPT_VIEWER_DVI='';
-  _OPT_VIEWER_PDF='';
-  _OPT_VIEWER_PS='';
-  _OPT_VIEWER_HTML='';
-  _OPT_VIEWER_X='';
-  _OPT_WHATIS='no';
-  _OPT_XRM='';
-  _OPT_Z='no';
-
-}
-
-reset;
-
-
-########################################################################
-#          Functions for error handling and debugging
-########################################################################
-
-
-##############
-# landmark ()
-#
-# Print  to standard error as a debugging aid.
-#
-# Globals: $_DEBUG_LM
-#
-landmark()
-{
-  if test "${_DEBUG_LM}" = 'yes'; then
-    echo ">>> $*" >&2;
-  fi;
-}
-
-landmark "1: debugging functions";
-
-
-##############
-# clean_up ()
-#
-# Clean up at exit.
-#
-clean_up()
-{
-  if test -d "${_TMP_DIR}"; then
-    rm -f "${_TMP_DIR}"/*;
-    rmdir "${_TMP_DIR}";
-  fi;
-}
-
-
-##############
-# echo2 (*)
-#
-# Output to stderr.
-#
-# Arguments : arbitrary text.
-#
-echo2()
-{
-  echo "$*" >&2;
-}
-
-
-##############
-# echo2n (*)
-#
-# Output to stderr.
-#
-# Arguments : arbitrary text.
-#
-echo2n()
-{
-  echo -n "$*" >&2;
-}
-
-
-#############
-# diag (text>*)
-#
-# Output a diagnostic message to stderr
-#
-diag()
-{
-  echo2 '>>>>>'"$*";
-}
-
-
-#############
-# error (*)
-#
-# Print an error message to standard error; exit with an error condition
-#
-error()
-{
-  local i;
-  local _code;
-  _code="${_ERROR}";
-  case "$#" in
-    0) true; ;;
-    1) echo2 'groffer error: '"$1"; ;;
-    2)
-      echo2 'groffer error: '"$1";
-      _code="$2";
-      ;;
-    *) echo2 'groffer error: wrong number of arguments in error().'; ;;
-  esac;
-  if test "${_DEBUG}" = 'yes'; then
-    func_stack_dump;
+# read and transform the configuration files, execute the arising commands
+for f in "${_CONF_FILE_HOME}" "${_CONF_FILE_ETC}"
+do
+  if test -f "$f"
+  then
+    o="";			# $o means groffer option
+    # use "" quotes because of ksh and posh
+    eval "$(cat "$f" | sed -n -e '
+# Ignore comments
+/^['"${_SP}${_TAB}"']*#/d
+# Delete leading and final space
+s/^['"${_SP}${_TAB}"']*//
+s/['"${_SP}${_TAB}"']*$//
+# Print all shell commands
+/^[^-]/p
+# Replace empty arguments
+s/^\(-[^ ]*\)=$/o="${o} \1 '"${_SQ}${_SQ}"'"/p
+# Replace division between option and argument by single space
+s/[='"${_SP}${_TAB}"']['"${_SP}${_TAB}"']*/'"${_SP}"'/
+# Handle lines without spaces
+s/^\(-[^'"${_SP}"']*\)$/o="${o} \1"/p
+# Print options that have their argument encircled with single quotes
+/^-[^ ]* '"${_SQ}"'.*'"${_SQ}"'$/s/^.*$/o="${o} &"/p
+# Replace encircled double quotes by single quotes and print the result
+s/^\(-[^ ]*\) "\(.*\)"$/o="${o} \1 '"${_SQ}"'\2'"${_SQ}"'"/p
+# Encircle the remaining arguments with single quotes
+s/^\(-[^ ]*\) \(.*\)$/o="${o} \1 '"${_SQ}"'\2'"${_SQ}"'"/p
+')"
+    if test _"${o}"_ != __
+    then
+      if test _"{GROFFER_OPT}"_ = __
+      then
+        GROFFER_OPT="${o}";
+      else
+        GROFFER_OPT="${o} ${GROFFER_OPT}";
+      fi;
+    fi;
   fi;
-  clean_up;
-  kill "${_PROCESS_ID}" >/dev/null 2>&1;
-  kill -9 "${_PROCESS_ID}" >/dev/null 2>&1;
-  exit "${_code}";
-}
+done;
 
-
-#############
-# abort (*)
-#
-# Terminate program with error condition
-#
-abort()
-{
-  error "Program aborted.";
-  exit 1;
-}
+# integrate $GROFFER_OPT into the command line; it isn't needed any more
+if test _"${GROFFER_OPT}"_ != __
+then
+  eval set x "${GROFFER_OPT}" '"$@"';
+  shift;
+  GROFFER_OPT='';
+fi;
 
 
-#############
-# func_check (   "$@")
-#
-# Check number of arguments and register to _FUNC_STACK.
-#
-# Arguments: >=3
-#   : name of the calling function.
-#   :    a relational operator: = != < > <= >= 
-#   :   number of arguments to be checked against 
-#   "$@":        the arguments of the calling function.
-#
-func_check()
-{
-  local _comp;
-  local _fname;
-  local _nargs;
-  local _op;
-  local _s;
-  if test "$#" -lt 3; then
-    error 'func_check() needs at least 3 arguments.';
-  fi;
-  _fname="$1";
-  case "$3" in
-    1)
-      _nargs="$3";
-      _s='';
-      ;;
-    0|[2-9])
-      _nargs="$3";
-      _s='s';
-      ;;
-    *)
-      error "func_check(): third argument must be a digit.";
-      ;;
-  esac;
-  case "$2" in
-    '='|'-eq')
-      _op='-eq';
-      _comp='exactly';
-      ;;
-    '>='|'-ge')
-      _op='-ge';
-      _comp='at least';
-      ;;
-    '<='|'-le')
-      _op='-le';
-      _comp='at most';
-      ;;
-    '<'|'-lt')
-      _op='-lt';
-      _comp='less than';
-      ;;
-    '>'|'-gt')
-      _op='-gt';
-      _comp='more than';
-      ;;
-    '!='|'-ne')
-      _op='-ne';
-      _comp='not';
-      ;;
-    *) 
-      error \
-        'func_check(): second argument is not a relational operator.';
-      ;;
-  esac;
-  shift 3;
-  if test "$#" "${_op}" "${_nargs}"; then
-    do_nothing;
-  else
-    error \
-      "${_fname}"'() needs '"${_comp} ${_nargs}"' argument'"${_s}"'.';
-  fi;
-  if test "${_DEBUG}" = 'yes'; then
-    func_push "${_fname} $*";
-  fi;
-}
+########################### Determine the shell
 
+export _SHELL;
 
-#############
-# func_pop ()
-#
-# Retrieve the top element from the stack.
-#
-# The stack elements are separated by `!'; the popped element is
-# identical to the original element, except that all `!' characters
-# were removed.
-#
-# Arguments: 1
-#
-func_pop()
-{
-  if test "${_DEBUG}" = 'yes'; then
-    if test "$#" -ne 0; then
-      error 'func_pop() does not have arguments.';
-    fi;
-    case "${_FUNC_STACK}" in
-      '')
-        error 'func_pop(): stack is empty.';
+# use "``" instead of "$()" for using the case ")" construct
+# do not use "" quotes because of ksh
+_SHELL=`
+  # $x means list.
+  # $s means shell.
+  # The command line arguments are taken over.
+  # Shifting herein does not have an effect outside.
+  export x;  
+  case " $*" in
+  *\ --sh*)			# abbreviation for --shell
+    x='';
+    s='';
+    # determine all --shell arguments, store them in $x in reverse order
+    while test $# != 0
+    do
+      case "$1" in
+      --shell|--sh|--she|--shel)
+        if test "$#" -ge 2
+        then
+          s="$2";
+          shift;
+        fi;
         ;;
-      *!*)
-        # split at first bang `!'.
-        _FUNC_STACK="$(echo -n ${_FUNC_STACK} \
-                       | sed -e 's/^[^!]*!//')";
+      --shell=*|--sh=*|--she=*|--shel=*)
+        # delete up to first "=" character
+        s="$(echo x"$1" | sed -e 's/^x[^=]*=//')";
         ;;
       *)
-        _FUNC_STACK='';
-        ;;
-    esac;
-  fi;
-}
-
+        shift;
+        continue;
+      esac;
+      if test _"${x}"_ = __
+      then
+        x="'${s}'";
+      else
+        x="'${s}' ${x}";
+      fi;
+      shift;
+    done;
 
-#############
-# func_push ()
-#
-# Store another element to stack.
-#
-# The stack elements are separated by `!'; if  contains a `!'
-# it is removed first.
-#
-# Arguments: 1
-#
-func_push()
-{
-  local _element;
-  if test "${_DEBUG}" = 'yes'; then
-    if test "$#" -ne 1; then
-      error 'func_push() needs 1 argument.';
-    fi;
-    case "$1" in
-      *'!'*)
-        # remove all bangs `!'.
-        _element="$(echo -n "$1" | sed -e 's/!//g')";
-        ;;
-      *)
-        _element="$1";
-        ;;
-    esac;
-    if test "${_FUNC_STACK}" = ''; then
-      _FUNC_STACK="${_element}";
-    else
-      _FUNC_STACK="${_element}!${_FUNC_STACK}";
+    # from all possible shells in $x determine the first being a shell
+    # or being empty
+    s="$(
+      # "" quotes because of posh
+      eval set x "${x}";
+      shift;
+      if test $# != 0
+      then
+        for i
+        do
+          if test _"$i"_ = __
+          then
+            # use the empty argument as the default shell
+            echo empty;
+            break;
+          else
+            # test $i on being a shell program;
+            # use this kind of quoting for posh
+            if test _"$(eval "$i -c 'echo ok'" 2>${_NULL_DEV})"_ = _ok_ >&2
+            then
+              # shell found
+              cat </dev/null 2>&1; then
-  true;
-else
-  true()
-  {
-    return "${_GOOD}";
-  }
-
-  false()
-  {
-    return "${_BAD}";
-  }
-fi;
-
-
-########################################################################
-# Test of `unset'.
-#
-_test='test';
-if unset _test >/dev/null 2>&1 && test "${_test}" = ''; then
-  true;
-else
-  unset()
-  {
-    for v in "$@"; do
-      eval "$v"='';
-    done;
-  }
-fi;
-unset _test;
-
-########################################################################
-# Test of builtin `local'
-#
+`
 
-_t_e_s_t_f_u_n_c_()
-{
-  local _test >/dev/null 2>&1 || return "${_BAD}";
-}
+########################### test fast shells for automatic run
 
-if _t_e_s_t_f_u_n_c_; then
-  :
-else
-  local()
-  {
-    if test "$1" != ''; then
-      error "overriding global variable \`$1' with local value.";
+if test _"${_SHELL}"_ = __
+then
+  for s in ksh ash dash pdksh zsh posh
+  do
+    if test _"$(eval "$s -c 'echo ok'" 2>${_NULL_DEV})"_ = _ok_ >&2
+    then
+      _SHELL="$s";
+      break;
     fi;
-  }
+  done;
 fi;
 
 
-########################################################################
-# Test of global setting in functions
-#
-_global='outside';
-_clobber='outside';
-
-_t_e_s_t_f_u_n_c_()
-{
-  local _clobber;
-  _global='inside';
-  _clobber='inside';
-}
+########################### start groffer2.sh
 
-_t_e_s_t_f_u_n_c_;
-if test "${_global}" != 'inside' || test "${_clobber}" != 'outside';
+if test _"${_SHELL}"_ = _empty_
 then
-  error "Cannot assign to global variables from within functions.";
+  _SHELL='';
 fi;
 
-unset _global;
-unset _clobber;
-
-
-########################################################################
-# Test of function `sed'.
-#
-if test "$(echo xTesTx \
-           | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
-           | sed -e '\|T|s||t|g')" != 'test';
+if test _"${_SHELL}"_ = __
 then
-  error 'Test of "sed" command failed.';
-fi;
-
-
-########################################################################
-# Test of function `cat'.
-#
-if test "$(echo test | cat)" != "test"; then
-  error 'Test of "cat" command failed.';
-fi;
-
-
-########################################################################
-# Test for compression.
-#
-if test "$(echo 'test' | gzip -c -d -f - 2>/dev/null)" = 'test'; then
-  _HAS_COMPRESSION='yes';
-  if echo 'test' | bzip2 -c 2>/dev/null | bzip2 -t 2>/dev/null \
-     && test "$(echo 'test' | bzip2 -c 2>/dev/null \
-                            | bzip2 -d -c 2>/dev/null)" \
-             = 'test'; then
-    _HAS_BZIP='yes';
-  else
-    _HAS_BZIP='no';
-  fi;
-else
-  _HAS_COMPRESSION='no';
-  _HAS_BZIP='no';
-fi;
-
-
-########################################################################
-_t_e_s_t_f_u_n_c_()
-{
-  :
-}
-
-
-########################################################################
-#                   Definition of normal Functions
-########################################################################
-landmark "3: functions";
-
-########################################################################
-# abort (*)
-#
-# Unconditionally terminate the program with error code;
-# useful for debugging.
-#
-# defined above
-
-
-########################################################################
-# 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 .  Remove final slashes, too, to get a
-# non-empty output.
-#
-# Arguments : 1
-# Output    : the file name part (without slashes)
-#
-base_name()
-{
-  func_check base_name = 1 "$@";
-  local f;
-  f="$1";
-  case "$f" in
-    */)
-      # 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 "$f" | sed -e '\|^.*//*\([^/]*\)$|s||\1|';
-      ;;
-    *)
-      echo -n "$f";
-      ;;
-  esac;
-  eval "${return_ok}";
-}
-
-
-########################################################################
-# catz ()
-#
-# Decompress if possible or just print  to standard output.
-#
-# gzip, bzip2, and .Z decompression is supported.
-#
-# Arguments: 1, a file name.
-# Output: the content of , possibly decompressed.
-#
-if test "${_HAS_COMPRESSION}" = 'yes'; then
-  catz()
-  {
-    func_check catz = 1 "$@";
-    case "$1" in
-      '')
-        error 'catz(): empty file name';
-        ;;
-      '-')
-        error 'catz(): for standard input use save_stdin()';
-        ;;
-    esac;
-    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}";
-      fi;
-    fi;
-    gzip -c -d -f "$1" 2>/dev/null;
-    eval "${return_ok}";
-  }
+  # no shell found, so start groffer2.sh normally
+  eval exec "'${_GROFFER2_SH}'" '"$@"';
+  exit;
 else
-  catz()
-  {
-    func_check catz = 1 "$@";
-    cat "$1";
-    eval "${return_ok}";
-  }
+  # start groffer2.sh with the found $_SHELL
+  # do not quote $_SHELL to allow arguments
+  eval exec "${_SHELL} '${_GROFFER2_SH}'" '"$@"';
+  exit;
 fi;
-
-
-########################################################################
-# clean_up ()
-#
-# Do the final cleaning up before exiting; used by the trap calls.
-#
-# defined above
-
-
-########################################################################
-# diag (*)
-#
-# Print marked message to standard error; useful for debugging.
-#
-# defined above
-
-
-########################################################################
-landmark '4: dirname()*';
-########################################################################
-
-#######################################################################
-# dirname_append ( )
-#
-# Append `name' to `dir' with clean handling of `/'.
-#
-# Arguments : 2
-# Output    : the generated new directory name /
-#
-dirname_append()
-{
-  func_check dirname_append = 2 "$@";
-  local _res;
-  if is_empty "$1"; then
-    error "dir_append(): first argument is empty.";
-  fi;
-  if is_empty "$2"; then
-    echo -n "$1";
-  else
-    dirname_chop "$1"/"$2";
-  fi;
-  eval "${return_ok}";
-}
-
-
-########################################################################
-# dirname_chop ()
-#
-# Remove unnecessary slashes from directory name.
-#
-# Argument: 1, a directory name.
-# Output:   path without double, or trailing slashes.
-#
-dirname_chop()
-{
-  func_check dirname_chop = 1 "$@";
-  local _arg;
-  local _res;
-  local _sep;
-  # replace all multiple slashes by a single slash `/'.
-  _res="$(echo -n "$1" | sed -e '\|///*|s||/|g')";
-  case "${_res}" in
-    ?*/)
-      # remove trailing slash '/';
-      echo -n "${_res}" | sed -e '\|/$|s|||';
-      ;;
-    *) echo -n "${_res}"; ;;
-  esac;
-  eval "${return_ok}";
-}
-
-
-########################################################################
-# do_filearg ()
-#
-# Append the file, man-page, or standard input corresponding to the
-# argument to the temporary file.  If this is compressed in the gzip
-# or Z format it is decompressed.  A title element is generated.
-#
-# Argument either:
-#   - name of an existing files.
-#   - `-' to represent standard input (several times allowed).
-#   - `man:name.(section)' the man-page for `name' in `section'.
-#   - `man:name.section' the man-page for `name' in `section'.
-#   - `man:name' the man-page for `name' in the lowest `section'.
-#   - `name.section' the man-page for `name' in `section'.
-#   - `name' the man-page for `name' in the lowest `section'.
-# Globals :
-#   $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
-#
-# Output  : none
-# Return  : $_GOOD if found, ${_BAD} otherwise.
-#
-do_filearg()
-{
-  func_check do_filearg = 1 "$@";
-  local _filespec;
-  local i;
-  _filespec="$1";
-  # store sequence into positional parameters
-  case "${_filespec}" in
-    '')
-       eval "${return_good}";
-       ;;
-    '-')
-      register_file '-';
-      eval "${return_good}";
-      ;;
-    */*)			# with directory part; so no man search
-      set -- 'File';
-      ;;
-    *)
-      if obj _MAN_ENABLE is_yes; then
-        if obj _MAN_FORCE is_yes; then
-          set -- 'Manpage' 'File';
-        else
-          set -- 'File' 'Manpage';
-        fi;
-      else
-        set -- 'File';
-      fi;
-      ;;
-  esac;
-  for i in "$@"; do
-    case "$i" in
-      File)
-        if test -f "${_filespec}"; then
-          if test -r "${_filespec}"; then
-            register_file "${_filespec}";
-            eval "${return_good}";
-          else
-	    echo2 "could not read \`${_filespec}'";
-            eval "${return_bad}";
-          fi;
-        else
-          continue;
-        fi;
-        ;;
-      Manpage)			# parse filespec as man page
-        if obj _MAN_IS_SETUP is_not_yes; then
-          man_setup;
-        fi;
-        if man_do_filespec "${_filespec}"; then
-          eval "${return_good}";
-        else
-          continue;
-	fi;
-        ;;
-    esac;
-  done;
-  eval "${return_bad}";
-} # do_filearg()
-
-
-########################################################################
-# do_nothing ()
-#
-# Dummy function.
-#
-do_nothing()
-{
-  return "${_OK}";
-}
-
-
-########################################################################
-# echo2 (*)
-#
-# Print to standard error with final line break.
-#
-# defined above
-
-
-########################################################################
-# echo2n (*)
-#
-# Print to standard error without final line break.
-#
-# defined above
-
-
-########################################################################
-# error (*)
-#
-# Print error message and exit with error code.
-#
-# defined above
-
-
-########################################################################
-# func_check (   "$@")
-#
-# Check number of arguments and register to _FUNC_STACK.
-#
-# Arguments: >=3
-#   : name of the calling function.
-#   :    a relational operator: = != < > <= >= 
-#   :   number of arguments to be checked against 
-#   "$@":        the arguments of the calling function.
-#
-# defined above
-
-#########################################################################
-# func_pop ()
-#
-# Delete the top element from the function call stack.
-#
-# defined above
-
-
-########################################################################
-# func_push ()
-#
-# Store another element to function call stack.
-#
-# defined above
-
-
-########################################################################
-# func_stack_dump ()
-#
-# Print the content of the stack.
-#
-# defined above
-
-
-########################################################################
-# get_first_essential (*)
-#
-# Retrieve first non-empty argument.
-#
-# Return  : `1' if all arguments are empty, `0' if found.
-# Output  : the retrieved non-empty argument.
-#
-get_first_essential()
-{
-  func_check get_first_essential '>=' 0 "$@";
-  local i;
-  if is_equal "$#" 0; then
-    eval "${return_ok}";
-  fi;
-  for i in "$@"; do
-    if obj i is_not_empty; then
-      echo -n "$i";
-      eval "${return_ok}";
-    fi;
-  done;
-  eval "${return_bad}";
-}
-
-
-########################################################################
-landmark '5: is_*()';
-########################################################################
-
-########################################################################
-# is_dir ()
-#
-# Test whether `name' is a directory.
-#
-# Arguments : 1
-# Return    : `0' if arg1 is a directory, `1' otherwise.
-#
-is_dir()
-{
-  func_check is_dir = 1 "$@";
-  if test -d "$1" && test -r "$1"; then
-    eval "${return_yes}";
-  fi;
-  eval "${return_no}";
-}
-
-
-########################################################################
-# is_empty ()
-#
-# Test whether `string' is empty.
-#
-# Arguments : <=1
-# Return    : `0' if arg1 is empty or does not exist, `1' otherwise.
-#
-is_empty()
-{
-  func_check is_empty = 1 "$@";
-  if test "$1" = ''; then
-    eval "${return_yes}";
-  fi;
-  eval "${return_no}";
-}
-
-
-########################################################################
-# is_equal ( )
-#
-# Test whether `string1' is equal to .
-#
-# Arguments : 2
-# Return    : `0' both arguments are equal strings, `1' otherwise.
-#
-is_equal()
-{
-  func_check is_equal = 2 "$@";
-  if test "$1" = "$2"; then
-    eval "${return_yes}";
-  fi;
-  eval "${return_no}";
-}
-
-
-########################################################################
-# is_file ()
-#
-# Test whether `name' is a readable file.
-#
-# Arguments : 1
-# Return    : `0' if arg1 is a readable file, `1' otherwise.
-#
-is_file()
-{
-  func_check is_file = 1 "$@";
-  if test -f "$1" && test -r "$1"; then
-    eval "${return_yes}";
-  fi;
-  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}";
-}
-
-
-########################################################################
-# is_not_dir ()
-#
-# Test whether `name' is not a readable directory.
-#
-# Arguments : 1
-# Return    : `0' if arg1 is a directory, `1' otherwise.
-#
-is_not_dir()
-{
-  func_check is_not_dir = 1 "$@";
-  if is_dir "$1"; then
-    eval "${return_no}";
-  fi;
-  eval "${return_yes}";
-}
-
-
-########################################################################
-# is_not_empty ()
-#
-# Test whether `string' is not empty.
-#
-# Arguments : <=1
-# Return    : `0' if arg1 exists and is not empty, `1' otherwise.
-#
-is_not_empty()
-{
-  func_check is_not_empty = 1 "$@";
-  if is_empty "$1"; then
-    eval "${return_no}";
-  fi;
-  eval "${return_yes}";
-}
-
-
-########################################################################
-# is_not_equal ( )
-#
-# Test whether `string1' differs from `string2'.
-#
-# Arguments : 2
-#
-is_not_equal()
-{
-  func_check is_not_equal = 2 "$@";
-  if is_equal "$1" "$2"; then
-    eval "${return_no}";
-  fi
-  eval "${return_yes}";
-}
-
-
-########################################################################
-# is_not_file ()
-#
-# Test whether `name' is a not readable file.
-#
-# Arguments : >=1 (empty allowed), more args are ignored
-#
-is_not_file()
-{
-  func_check is_not_file '>=' 1 "$@";
-  if is_file "$1"; then
-    eval "${return_no}";
-  fi;
-  eval "${return_yes}";
-}
-
-
-########################################################################
-# is_not_prog ()
-#
-# Verify that arg is a not program in $PATH.
-#
-# Arguments : >=1 (empty allowed)
-#   more args are ignored, this allows to specify progs with arguments
-#
-is_not_prog()
-{
-  func_check is_not_prog '>=' 1 "$@";
-  if where "$1" >/dev/null; then
-    eval "${return_no}";
-  fi;
-  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}";
-}
-
-
-########################################################################
-# is_not_yes ()
-#
-# Test whether `string' is not "yes".
-#
-# Arguments : 1
-#
-is_not_yes()
-{
-  func_check is_not_yes = 1 "$@";
-  if is_yes "$1"; then
-    eval "${return_no}";
-  fi;
-  eval "${return_yes}";
-}
-
-
-########################################################################
-# is_prog ()
-#
-# Determine whether arg is a program in $PATH
-#
-# Arguments : >=0 (empty allowed)
-#   more args are ignored, this allows to specify progs with arguments
-#
-is_prog()
-{
-  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_no}";
-}
-
-
-########################################################################
-# is_yes ()
-#
-# Test whether `string' has value "yes".
-#
-# Arguments : <=1
-# Return    : `0' if arg1 is `yes', `1' otherwise.
-#
-is_yes()
-{
-  func_check is_yes = 1 "$@";
-  if is_equal "$1" 'yes'; then
-    eval "${return_yes}";
-  fi;
-  eval "${return_no}";
-}
-
-
-########################################################################
-# landmark ()
-#
-# Print debugging information on standard error if $_DEBUG_LM is `yes'.
-#
-# Globals: $_DEBUG_LM
-#
-# Defined in section `Debugging functions'.
-
-
-########################################################################
-# leave ()
-#
-# Clean exit without an error.
-#
-leave()
-{
-  clean_up;
-  exit "${_OK}";
-}
-
-
-########################################################################
-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 variable name for a list of single-quoted elements
-#   :  some sequence of characters.
-# Output: none, but $ is set to
-#   if  is empty:  "'' '...'"
-#   otherwise:           "$list '' ..."
-#
-list_append()
-{
-  func_check list_append '>=' 2 "$@";
-  local _element;
-  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 in the following `sed'
-      _element="$(echo -n "$s" | sed -e 's/'"${_SQUOTE}"'/&\\&&/g')";
-      ;;
-    '')  
-      _element="";
-      ;;
-    *)
-      _element="$s";
-      ;;
-    esac;
-    if obj _list is_empty; then
-      _list="'${_element}'";
-    else
-      _list="${_list} '${_element}'";
-    fi;
-  done;
-  eval "${_name}"='"${_list}"';
-  eval "${return_ok}";
-}
-
-
-########################################################################
-# list_from_cmdline (    [...])
-#
-# Transform command line arguments into a normalized form.
-#
-# Options, option arguments, and file parameters are identified and
-# output each as a single-quoted argument of its own.  Options and
-# file parameters are separated by a '--' argument.
-#
-# Arguments: >=4
-#   : space-separated list of short options without an arg.
-#   : 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 a command line, such as "$@",
-#                     the content of a variable, or direct arguments.
-#
-# Globals: $POSIXLY_CORRECT (only kept for compatibility).
-#
-# Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
-#
-# Example:
-#     list_normalize 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
-#   will result in printing:
-#     '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
-#   If $POSIXLY_CORRECT is not empty, the result will be:
-#     '-a' '--' 'f1' '-bcarg' '--long=larg' 'f2'
-#
-#   Rationale:
-#     In POSIX, the first non-option ends the option processing.
-#     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 '...' '...' '...' '...' "$@")";
-#     while test "$1" != '--'; do
-#       case "$1" in
-#       ...
-#       esac;
-#       shift;
-#     done;
-#     shift;         #skip '--'
-#     # all positional parameters ("$@") left are file name parameters.
-#
-list_from_cmdline()
-{
-  func_check list_from_cmdline '>=' 4 "$@";
-  local _fparams;
-  local _fn;
-  local _result;
-  local _long_a;
-  local _long_n;
-  local _short_a;
-  local _short_n;
-  _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 is_equal "$#" 0; then
-    echo -n "'--'";
-    eval "${return_ok}";
-  fi;
-  _fparams='';
-  _result='';
-  while test "$#" -ge 1; do
-    _arg="$1";
-    shift;
-    case "$_arg" in
-      --) break; ;;
-      --?*)
-        # delete leading '--';
-        _opt="$(echo -n "${_arg}" | sed -e 's/^..//')";
-        if list_has _long_n "${_opt}"; then
-          # long option, no argument
-          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
-            # get the option argument by deleting up to first `='
-            _optarg="$(echo -n "${_opt}" | sed -e 's/^[^=]*=//')";
-            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 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
-            list_append _result "-${_optchar}";
-            continue;
-          elif list_has _short_a "${_optchar}"; then
-            if obj _rest is_empty; then
-              if test "$#" -ge 1; then
-                list_append _result "-${_optchar}" "$1";
-                shift;
-                continue;
-              else
-                error \
-                  "${_fn}"' no argument for option -'"${_optchar}."
-              fi;
-            else		# rest is the argument
-              list_append _result "-${_optchar}" "${_rest}";
-              _rest='';
-              continue;
-            fi;
-          else
-            error "${_fn} unknown option -${_optchar}."
-          fi;
-        done;
-        ;;
-      *)
-	# Here, $_arg is not an option, so a file parameter.
-        # When $POSIXLY_CORRECT is set this ends option parsing;
-        # otherwise, the argument is stored as a file parameter and
-        # option processing is continued.
-        list_append _fparams "${_arg}";
-	if obj POSIXLY_CORRECT is_not_empty; then
-          break;
-        fi;
-        ;;
-    esac;
-  done;
-  list_append _result '--';
-  if obj _fparams is_not_empty; then
-    _result="${_result} ${_fparams}";
-  fi;
-  if test "$#" -gt 0; then
-    list_append _result "$@";
-  fi;
-  echo -n "$_result";
-  eval "${return_ok}";
-} # list_from_cmdline()
-
-
-########################################################################
-# list_from_split ( )
-#
-# 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 list string
-#
-list_from_split()
-{
-  func_check list_from_split = 2 "$@";
-  local _s;
-
-  # precede each space or tab by a backslash `\' (doubled for `sed')
-  _s="$(echo -n "$1" | sed -e 's/\(['"${_SPACE}${_TAB}"']\)/\\\1/g')";
-
-  # replace split character of string by the list separator ` ' (space).
-  case "$2" in
-    /)				# cannot use normal `sed' separator
-      echo -n "${_s}" | sed -e '\|'"$2"'|s|| |g';
-      ;;
-    ?)				# use normal `sed' separator
-      echo -n "${_s}" | sed -e 's/'"$2"'/ /g';
-      ;;
-    ??*)
-      error 'list_from_split(): separator must be a single character.';
-      ;;
-  esac;
-  eval "${return_ok}";
-}
-
-
-########################################################################
-# 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 variable name for a list of single-quoted elements
-#   :  some sequence of characters.
-# Output:
-#   if  is empty:  "'' '...'"
-#   otherwise:           "list '' ..."
-#
-list_has()
-{
-  func_check list_has = 2 "$@";
-  eval _list='"${'$1'}"';
-  if obj _list is_empty; then
-    eval "${return_no}";
-  fi;
-  _element="$2";
-  case "$2" in
-    \'*\')  _element="$2"; ;;
-    *)      _element="'$2'"; ;;
-  esac;
-  if string_contains "${_list}" "${_element}"; then
-    eval "${return_yes}";
-  else
-    eval "${return_no}";
-  fi;
-  eval "${return_ok}";
-}
-
-
-########################################################################
-# list_has_not ( )
-#
-# Arguments: 2
-#   :    a space-separated list of single-quoted elements.
-#   : some sequence of characters.
-# Output:
-#   if  is empty:  "'' '...'"
-#   otherwise:           " '' ..."
-#
-list_has_not()
-{
-  func_check list_has_not = 2 "$@";
-  eval _list='"${'$1'}"';
-  if obj _list is_empty; then
-    eval "${return_yes}";
-  fi;
-  _element="$2";
-  case "$2" in
-    \'*\')  _element="$2"; ;;
-    *)      _element="'$2'"; ;;
-  esac;
-  if string_contains "${_list}" "${_element}"; then
-    eval "${return_no}";
-  else
-    eval "${return_yes}";
-  fi;
-  eval "${return_ok}";
-}
-
-
-########################################################################
-landmark '7: man_*()';
-########################################################################
-
-########################################################################
-# man_do_filespec ()
-#
-# Print suitable man page(s) for filespec to $_TMP_CAT.
-#
-# Arguments : 2
-#   : argument of the form `man:name.section', `man:name',
-#               `man:name(section)', `name.section', `name'.
-#
-# Globals   : $_OPT_ALL
-#
-# Output    : none.
-# Return    : `0' if man page was found, `1' else.
-#
-# Only called from do_fileargs(), checks on $MANPATH and
-# $_MAN_ENABLE are assumed.
-#
-man_do_filespec()
-{
-  func_check man_do_filespec = 1 "$@";
-  local _got_one;
-  local _name;
-  local _prevsec;
-  local _res;
-  local _section;
-  local _spec;
-  local _string;
-  local s;
-  if obj _MAN_PATH is_empty; then
-    eval "${return_bad}";
-  fi;
-  if is_empty "$1"; then
-    eval "${return_bad}";
-  fi;
-  _spec="$1";
-  _name='';
-  _section='';
-  case "${_spec}" in
-    */*)			# not a man spec when it contains '/'
-      eval "${return_bad}";
-      ;;
-    man:?*\(?*\))		# man:name(section)
-      _name="$(echo -n "${_spec}" \
-               | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
-      _section="$(echo -n "${_spec}" \
-               | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
-      ;;
-    man:?*.[0-9on])			# man:name.section
-      _name="$(echo -n "${_spec}" \
-               | sed -e 's/^man:\(..*\)\..$/\1/')";
-      _section="$(echo -n "${_spec}" \
-               | sed -e 's/^.*\(.\)$/\1/')";
-      ;;
-    man:?*)			# man:name
-      _name="$(echo -n "${_spec}" | sed -e 's/^man://')";
-      ;;
-    ?*\(?*\))			# name(section)
-      _name="$(echo -n "${_spec}" \
-               | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
-      _section="$(echo -n "${_spec}" \
-               | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
-      ;;
-    ?*.[0-9on])			# name.section
-      _name="$(echo -n "${_spec}" \
-               | sed -e 's/^\(..*\)\..$/\1/')";
-      _section="$(echo -n "${_spec}" \
-               | sed -e 's/^.*\(.\)$/\1/')";
-      ;;
-    ?*)
-      _name="${_filespec}";
-      ;;
-  esac;
-  if obj _name is_empty; then
-    eval "${return_bad}";
-  fi;
-  _got_one='no';
-  if obj _section is_empty; then
-    eval set -- "${_MAN_AUTO_SEC}";
-    for s in "$@"; do
-      if man_search_section "${_name}" "$s"; then # found
-        if obj _MAN_ALL is_yes; then
-          _got_one='yes';
-        else
-          eval "${return_good}";
-        fi;
-      fi;
-    done;
-  else
-    if man_search_section "${_name}" "${_section}"; then
-      eval "${return_good}";
-    else
-      eval "${return_bad}";
-    fi;
-  fi;
-  if obj _MAN_ALL is_yes && is_yes "${_got_one}"; then
-    eval "${return_good}";
-  fi;
-  eval "${return_bad}";
-} # man_do_filespec()
-
-
-########################################################################
-# man_register_file (  [
]) -# -# Write a found man page file and register the title element. -# -# Arguments: 1, 2, or 3; maybe empty -# Output: none -# -man_register_file() -{ - func_check man_register_file '>=' 2 "$@"; - case "$#" in - 2|3) do_nothing; ;; - *) - error "man_register_file() expects 2 or 3 arguments."; - ;; - esac; - if is_empty "$1"; then - error 'man_register_file(): file name is empty'; - fi; - to_tmp "$1"; - case "$#" in - 2) - register_title "man:$2"; - eval "${return_ok}"; - ;; - 3) - register_title "$2.$3"; - eval "${return_ok}"; - ;; - esac; - eval "${return_ok}"; -} - - -######################################################################## -# man_search_section (
) -# -# Retrieve man pages. -# -# Arguments : 2 -# Globals : $_MAN_PATH, $_MAN_EXT -# Return : 0 if found, 1 otherwise -# -man_search_section() -{ - func_check man_search_section = 2 "$@"; - local _dir; - local _ext; - local _got_one; - local _name; - local _prefix - local _section; - local d; - local f; - if obj _MAN_PATH is_empty; then - eval "${return_bad}"; - fi; - if is_empty "$1"; then - eval "${return_bad}"; - fi; - if is_empty "$2"; then - eval "${return_bad}"; - fi; - _name="$1"; - _section="$2"; - eval set -- "$(path_split "${_MAN_PATH}")"; - _got_one='no'; - if obj _MAN_EXT is_empty; then - for d in "$@"; do - _dir="$(dirname_append "$d" "man${_section}")"; - if obj _dir is_dir; then - _prefix="$(dirname_append "${_dir}" "${_name}.${_section}")"; - for f in $(echo -n ${_prefix}*); do - if obj f is_file; then - if is_yes "${_got_one}"; then - register_file "$f"; - elif obj _MAN_ALL is_yes; then - man_register_file "$f" "${_name}"; - else - man_register_file "$f" "${_name}" "${_section}"; - eval "${return_good}"; - fi; - _got_one='yes'; - fi; - done; - fi; - done; - else - _ext="${_MAN_EXT}"; - # check for directory name having trailing extension - for d in "$@"; do - _dir="$(dirname_append $d man${_section}${_ext})"; - if obj _dir is_dir; then - _prefix="$(dirname_append "${_dir}" "${_name}.${_section}")"; - for f in ${_prefix}*; do - if obj f is_file; then - if is_yes "${_got_one}"; then - register_file "$f"; - elif obj _MAN_ALL is_yes; then - man_register_file "$f" "${_name}"; - else - man_register_file "$f" "${_name}" "${_section}"; - eval "${return_good}"; - fi; - _got_one='yes'; - fi; - done; - fi; - done; - # check for files with extension in directories without extension - for d in "$@"; do - _dir="$(dirname_append "$d" "man${_section}")"; - if obj _dir is_dir; then - _prefix="$(dirname_append "${_dir}" \ - "${_name}.${_section}${_ext}")"; - for f in ${_prefix}*; do - if obj f is_file; then - if is_yes "${_got_one}"; then - register_file "$f"; - elif obj _MAN_ALL is_yes; then - man_register_file "$f" "${_name}"; - else - man_register_file "$f" "${_name}" "${_section}"; - eval "${return_good}"; - fi; - _got_one='yes'; - fi; - done; - fi; - done; - fi; - if obj _MAN_ALL is_yes && is_yes "${_got_one}"; then - eval "${return_good}"; - fi; - eval "${return_bad}"; -} # man_search_section() - - -######################################################################## -# man_setup () -# -# Setup the variables $_MAN_* needed for man page searching. -# -# Globals: -# in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL, -# $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT. -# out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2, -# $_MAN_SEC, $_MAN_ALL -# in/out: $_MAN_ENABLE -# -# The precedence for the variables related to `man' is that of GNU -# `man', i.e. -# -# $LANG; overridden by -# $LC_MESSAGES; overridden by -# $LC_ALL; this has the same precedence as -# $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by -# $MANOPT; overridden by -# the groffer command line options. -# -man_setup() -{ - func_check main_man_setup = 0 "$@"; - local _lang; - - if obj _MAN_IS_SETUP is_yes; then - eval "${return_ok}"; - fi; - _MAN_IS_SETUP='yes'; - - 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 obj _MAN_PATH is_empty; then - manpath_set_from_path; - else - _MAN_PATH="$(path_clean "${_MAN_PATH}")"; - fi; - 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 obj _MAN_ALL is_empty; then - _MAN_ALL='no'; - fi; - - _MAN_SYS="$(get_first_essential \ - "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")"; - _lang="$(get_first_essential \ - "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")"; - case "${_lang}" in - C|POSIX) - _MAN_LANG=""; - _MAN_LANG2=""; - ;; - ?) - _MAN_LANG="${_lang}"; - _MAN_LANG2=""; - ;; - *) - _MAN_LANG="${_lang}"; - # get first two characters of $_lang - _MAN_LANG2="$(echo -n "${_lang}" | sed -e 's/^\(..\).*$/\1/')"; - ;; - esac; - # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*. - - manpath_add_lang_sys; # this is very slow - - _MAN_SEC="$(get_first_essential \ - "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")"; - if obj _MAN_PATH is_empty; then - _MAN_ENABLE="no"; - eval "${return_ok}"; - fi; - - _MAN_EXT="$(get_first_essential \ - "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")"; - eval "${return_ok}"; -} # man_setup() - - -######################################################################## -landmark '8: manpath_*()'; -######################################################################## - -######################################################################## -# manpath_add_lang_sys () -# -# Add language and operating system specific directories to man path. -# -# Arguments : 0 -# Output : none -# Globals: -# in: $_MAN_SYS: has the form `os1,os2,...', a comma separated -# list of names of operating systems. -# $_MAN_LANG and $_MAN_LANG2: each a single name -# in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon -# separated list of directories. -# -manpath_add_lang_sys() -{ - func_check manpath_add_lang_sys = 0 "$@"; - local p; - local _mp; - if obj _MAN_PATH is_empty; then - eval "${return_ok}"; - fi; - # twice test both sys and lang - eval set -- "$(path_split "${_MAN_PATH}")"; - _mp=''; - for p in "$@"; do # loop on man path directories - _mp="$(_manpath_add_lang_sys_single "${_mp}" "$p")"; - done; - eval set -- "$(path_split "${_mp}")"; - for p in "$@"; do # loop on man path directories - _mp="$(_manpath_add_lang_sys_single "${_mp}" "$p")"; - done; - _MAN_PATH="$(path_chop "${_mp}")"; - eval "${return_ok}"; -} - - -_manpath_add_lang_sys_single() -{ - # To the directory in $1 append existing sys/lang subdirectories - # Function is necessary to split the OS list. - # - # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2 - # argument: 2: `man_path' and `dir' - # output: colon-separated path of the retrieved subdirectories - # - func_check _manpath_add_lang_sys_single = 2 "$@"; - local d; - _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 obj _res path_not_contains "${_dir}" && obj _dir is_dir; then - _res="${_res}:${_dir}"; - fi; - done; - if path_not_contains "${_res}" "${_parent}"; then - _res="${_res}:${_parent}"; - fi; - path_chop "${_res}"; -} - -# end manpath_add_lang_sys () - - -######################################################################## -# manpath_set_from_path () -# -# Determine basic search path for man pages from $PATH. -# -# Return: `0' if a valid man path was retrieved. -# Output: none -# Globals: -# in: $PATH -# out: $_MAN_PATH -# -manpath_set_from_path() -{ - func_check manpath_set_from_path = 0 "$@"; - local _base; - local _mandir; - local _manpath; - local d; - local e; - _manpath=''; - - # get a basic man path from $PATH - if obj PATH is_not_empty; then - eval set -- "$(path_split "${PATH}")"; - for d in "$@"; do - # delete the final `/bin' part - _base="$(echo -n "$d" | sed -e '\|//*bin/*$|s|||')"; - for e in /share/man /man; do - _mandir="${_base}$e"; - if test -d "${_mandir}" && test -r "${_mandir}"; then - _manpath="${_manpath}:${_mandir}"; - fi; - done; - done; - fi; - - # append some default directories - for d in /usr/local/share/man /usr/local/man \ - /usr/share/man /usr/man \ - /usr/X11R6/man /usr/openwin/man \ - /opt/share/man /opt/man \ - /opt/gnome/man /opt/kde/man; do - if obj _manpath path_not_contains "$d" && obj d is_dir; then - _manpath="${_manpath}:$d"; - fi; - done; - - _MAN_PATH="${_manpath}"; - eval "${return_ok}"; -} # manpath_set_from_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 () -# -# Remove unnecessary colons from path. -# -# Argument: 1, a colon separated path. -# Output: path without leading, double, or trailing colons. -# -path_chop() -{ - func_check path_chop = 1 "$@"; - local _res; - - # replace multiple colons by a single colon `:' - # remove leading and trailing colons - echo -n "$1" | sed -e 's/:::*/:/g' | - sed -e 's/^:*//' | - sed -e 's/:*$//'; - eval "${return_ok}"; -} - - -######################################################################## -# path_clean () -# -# Remove non-existing directories from a colon-separated list. -# -# Argument: 1, a colon separated path. -# Output: colon-separated list of existing directories. -# -path_clean() -{ - func_check path_clean = 1 "$@"; - local _arg; - local _dir; - local _res; - local i; - 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 obj i is_not_empty \ - && obj _res path_not_contains "$i" \ - && obj i is_dir; - then - case "$i" in - ?*/) _res="${_res}$(dirname_chop "$i")"; ;; - *) _res="${_res}:$i"; - esac; - fi; - done; - if path_chop "${_res}"; then - eval "${return_ok}"; - else - eval "${return_badk}"; - fi; -} - - -######################################################################## -# path_contains ( ) -#- -# Test whether `dir' is contained in `path', a list separated by `:'. -# -# Arguments : 2 arguments. -# Return : `0' if arg2 is substring of arg1, `1' otherwise. -# -path_contains() -{ - func_check path_contains = 2 "$@"; - case ":$1:" in - *":$2:"*) - eval "${return_yes}"; - ;; - *) - eval "${return_no}"; - ;; - esac; - eval "${return_ok}"; -} - - -######################################################################## -# path_not_contains ( ) -#- -# Test whether `dir' is not contained in colon separated `path'. -# -# Arguments : 2 arguments. -# -path_not_contains() -{ - func_check path_not_contains = 2 "$@"; - if path_contains "$1" "$2"; then - eval "${return_no}"; - else - eval "${return_yes}"; - fi; - eval "${return_ok}"; -} - - -######################################################################## -# path_split () -# -# In `path' escape white space and replace each colon by a space. -# -# Arguments: 1: a colon-separated path -# Output: the resulting list, process with `eval set --' -# -path_split() -{ - func_check path_split = 1 "$@"; - list_from_split "$1" ':'; - eval "${return_ok}"; -} - - -######################################################################## -landmark '10: register_*()'; -######################################################################## - -######################################################################## -# register_file () -# -# Write a found file and register the title element. -# -# Arguments: 1: a file name -# Output: none -# -register_file() -{ - func_check register_file = 1 "$@"; - if is_empty "$1"; then - error 'register_file(): file name is empty'; - fi; - if is_equal "$1" '-'; then - to_tmp "${_TMP_STDIN}"; - register_title '-'; - else - to_tmp "$1"; - register_title "$(base_name "$1")"; - fi; - eval "${return_ok}"; -} - - -######################################################################## -# register_title () -# -# Create title element from and append to $_REGISTERED_TITLE -# -# Globals: $_REGISTERED_TITLE (rw) -# -register_title() -{ - func_check register_title = 1 "$@"; - local _title; - if is_empty "$1"; then - eval "${return_ok}"; - fi; - _title="$(base_name "$1")"; # remove directory part - - # remove extension `.gz' - _title="$(echo -n "${_title}" | sed -e 's/\.gz$//')"; - # remove extension `.Z' - _title="$(echo -n "${_title}" | sed -e 's/\.Z$//')"; - - if obj _title is_empty; then - eval "${return_ok}"; - fi; - _REGISTERED_TITLE="${_REGISTERED_TITLE} ${_title}"; - eval "${return_ok}"; -} - - -######################################################################## -# 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 obj _HAS_COMPRESSION is_yes; then - save_stdin() - { - local _f; - func_check save_stdin = 0 "$@"; - _f="${_TMP_DIR}"/INPUT; - cat >"${_f}"; - catz "${_f}" >"${_TMP_STDIN}"; - rm -f "${_f}"; - eval "${return_ok}"; - } -else - save_stdin() - { - func_check save_stdin = 0 "$@"; - cat >"${_TMP_STDIN}"; - eval "${return_ok}"; - } -fi; - - -######################################################################## -landmark '11: stack_*()'; -######################################################################## - -######################################################################## -# string_contains ( ) -# -# Test whether `part' is contained in `string'. -# -# Arguments : 2 text arguments. -# Return : `0' if arg2 is substring of arg1, `1' otherwise. -# -string_contains() -{ - func_check string_contains = 2 "$@"; - case "$1" in - *"$2"*) - eval "${return_yes}"; - ;; - *) - eval "${return_no}"; - ;; - esac; - eval "${return_ok}"; -} - - -######################################################################## -# string_not_contains ( ) -# -# Test whether `part' is not substring of `string'. -# -# Arguments : 2 text arguments. -# Return : `0' if arg2 is substring of arg1, `1' otherwise. -# -string_not_contains() -{ - func_check string_not_contains = 2 "$@"; - if string_contains "$1" "$2"; then - eval "${return_no}"; - else - eval "${return_yes}"; - fi; - eval "${return_ok}"; -} - - -######################################################################## -landmark '12: tmp_*()'; -######################################################################## - -######################################################################## -# tmp_cat () -# -# output the temporary cat file (the concatenation of all input) -# -tmp_cat() -{ - cat "${_TMP_CAT}"; -} - - -######################################################################## -# tmp_create (?) -# -# create temporary file -# -# It's safe to use the shell process ID together with a suffix to -# have multiple temporary files. -# -# Output : name of created file -# -tmp_create() -{ - func_check tmp_create '<=' 1 "$@"; - local _tmp; - # 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}"; -} - - -######################################################################## -# to_tmp () -# -# print file (decompressed) to the temporary cat file -# -to_tmp() -{ - func_check to_tmp = 1 "$@"; - if is_file "$1"; then - if obj _OPT_LOCATION is_yes; then - echo2 "$1"; - fi; - if obj _OPT_WHATIS is_yes; then - what_is "$1" >>"${_TMP_CAT}"; - else - catz "$1" >>"${_TMP_CAT}"; - fi; - else - error "to_tmp(): could not read file \`$1'."; - fi; - eval "${return_ok}"; -} - - -######################################################################## -# trap_clean () -# -# disable trap on all exit codes ($_ALL_EXIT) -# -# Arguments: 0 -# Globals: $_ALL_EXIT -# -trap_clean() -{ - func_check trap_clean = 0 "$@"; - local i; - for i in ${_ALL_EXIT}; do - trap "" "$i" 2>/dev/null || true; - done; - eval "${return_ok}"; -} - - -######################################################################## -# trap_set () -# -# call function on all exit codes ($_ALL_EXIT) -# -# Arguments: 1 (name of a shell function) -# Globals: $_ALL_EXIT -# -trap_set() -{ - func_check trap_set = 1 "$@"; - local i; - for i in ${_ALL_EXIT}; do - trap "$1" "$i" 2>/dev/null || true; - done; - eval "${return_ok}"; -} - - -######################################################################## -# usage () -# -# print usage information to stderr; for groffer option --help. -# -usage() -{ - func_check usage = 0 "$@"; - echo; - version; - echo 'Usage: '"${_PROGRAM_NAME}"' [option]... [filespec]...'; - cat <&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /' >&2; -} - - -######################################################################## -# warning () -# -# Print warning to stderr -# -warning() -{ - echo2 "warning: $*"; -} - - -######################################################################## -# what_is () -# -# Interpret as a man page and display its `whatis' -# information as a fragment written in the groff language. -# -what_is() -{ - func_check what_is = 1 "$@"; - local _res; - local _dot; - if is_not_file "$1"; then - error "what_is(): argument is not a readable file." - fi; - _dot='^\.['"${_SPACE}${_TAB}"']*'; - echo '.br'; - echo "$1: "; - echo '.br'; - echo -n ' '; - # grep the line containing `.TH' macro, if any - _res="$(catz "$1" | sed -e '/'"${_dot}"'TH /p -d')"; - 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; - # - of this, delete the final .SH line; - catz "$1" | sed -e '1,/'"${_dot}"'SH/d' \ - | sed -e '1,/'"${_dot}"'SH/p -d' \ - | sed -e '/'"${_dot}"'SH/d'; - eval "${return_ok}"; - fi; - # grep the line containing `.Dd' macro, if any - _res="$(catz "$1" | sed -e '/'"${_dot}"'Dd /p -d')"; - 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; - # - of this, delete the final .Nd line; - catz "$1" | sed -e '1,/'"${_dot}"'Nd/d' \ - | sed -e '1,/'"${_dot}"'Nd/p -d' \ - | sed -e '/'"${_dot}"'Nd/d'; - eval "${return_ok}"; - fi; - echo 'is not a man page.'; - eval "${return_bad}"; -} - - -######################################################################## -# where () -# -# Output path of a program if in $PATH. -# -# Arguments : >=1 (empty allowed) -# more args are ignored, this allows to specify progs with arguments -# Return : `0' if arg1 is a program in $PATH, `1' otherwise. -# -where() -{ - func_check where '>=' 1 "$@"; - local _file; - local _arg; - local p; - _arg="$1"; - if obj _arg is_empty; then - eval "${return_bad}"; - fi; - case "${_arg}" in - /*) - if test -f "${_arg}" && test -x "${_arg}"; then - eval "${return_ok}"; - else - eval "${return_bad}"; - fi; - ;; - esac; - eval set -- "$(path_split "${PATH}")"; - for p in "$@"; do - case "$p" in - */) _file=${p}${_arg}; ;; - *) _file=${p}/${_arg}; ;; - esac; - if test -f "${_file}" && test -x "${_file}"; then - echo -n "${_file}"; - eval "${return_ok}"; - fi; - done; - eval "${return_bad}"; -} - - -######################################################################## -# main -######################################################################## - -# The main area contains the following parts: -# - main_init(): initialize temporary files and set exit trap -# - parse $MANOPT -# - main_parse_args(): argument parsing -# - determine display mode -# - process filespec arguments -# - setup X resources -# - do the displaying - -# These parts are implemented as functions, being defined below in the -# sequence they are called in the main() function. - - -####################################################################### -# main_init () -# -# set exit trap and create temporary files -# -# Globals: $_TMP_CAT, $_TMP_STDIN -# -landmark '13: main_init()'; -main_init() -{ - func_check main_init = 0 "$@"; - # call clean_up() on any signal - trap_set clean_up; - - # determine temporary directory - umask 000; - _TMP_DIR=''; - for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \ - "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'; - do - if is_not_empty "$d"; then - if obj d is_dir && obj d is_writable; then - _TMP_DIR="${d}/${_PROGRAM_NAME}${_PROCESS_ID}"; - if obj _TMP_DIR is_dir; then - rm -f "${_TMP_DIR}"/*; - break; - else - mkdir "${_TMP_DIR}"; - if obj _TMP_DIR is_not_dir; then - _TMP_DIR=''; - continue; - fi; - break; - fi; - fi; - if obj _TMP_DIR is_not_writable; then - _TMP_DIR=''; - continue; - fi; - fi; - done; - unset d; - 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() - - -######################################################################## -# main_parse_MANOPT () -# -# Parse $MANOPT to retrieve man options, but only if it is a non-empty -# string; found man arguments can be overwritten by the command line. -# -# Globals: -# in: $MANOPT, $_OPTS_MANOPT_* -# out: $_MANOPT_* -# in/out: $GROFFER_OPT -# -landmark '14: main_parse_MANOPT()'; -main_parse_MANOPT() -{ - func_check main_parse_MANOPT = 0 "$@"; - local _opt; - local _list; - _list=''; - if obj MANOPT is_not_empty; then - MANOPT="$(echo -n "${MANOPT}" | \ - sed -e 's/^'"${_SPACE}${_SPACE}"'*//')"; - fi; - 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_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_append _list '--ascii'; - ;; - -a|--all) - list_append _list '--all'; - ;; - -c|--catman) - do_nothing; - shift; - ;; - -d|--debug) - list_append _list '--debug'; - ;; - -D|--default) - # undo all man options so far - _list=''; - ;; - -e|--extension) - list_append _list '--extension'; - shift; - ;; - -f|--whatis) - list_append _list '--whatis'; - shift; - ;; - -h|--help) - do_nothing; - shift; - ;; - -k|--apropos) - # groffer's --apropos takes an argument, but man's does not, so - do_nothing; - shift; - ;; - -l|--local-file) - list_append _list '--local-file'; - ;; - -L|--locale) - list_append _list '--locale' "$1"; - shift; - ;; - -m|--systems) - list_append _list '--systems' "$1"; - shift; - ;; - -M|--manpath) - list_append _list '--manpath' "$1"; - shift; - ;; - -p|--preprocessor) - do_nothing; - shift; - ;; - -P|--pager|--tty-viewer) - list_append _list '--pager' "$1"; - shift; - ;; - -r|--prompt) - do_nothing; - shift; - ;; - -S|--sections) - list_append _list '--sections' "$1"; - shift; - ;; - -t|--troff) - do_nothing; - shift; - ;; - -T|--device) - list_append _list '-T' "$1"; - shift; - ;; - -u|--update) - do_nothing; - shift; - ;; - -V|--version) - do_nothing; - ;; - -w|--where|--location) - list_append _list '--location'; - ;; - -Z|--ditroff) - list_append _list '-Z' "$1"; - shift; - ;; - # ignore all other options - esac; - done; - # 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() - - -######################################################################## -# main_parse_args (*) -# -# Parse arguments; process options and filespec parameters -# -# Arguments: pass the command line arguments unaltered. -# Globals: -# in: $_OPTS_* -# out: $_OPT_*, $_ADDOPTS, $_FILEARGS -# -landmark '15: main_parse_args()'; -main_parse_args() -{ - func_check main_parse_args '>=' 0 "$@"; - local _arg; - local _code; - local _dpi; - local _longopt; - local _mode; - local _opt; - local _optchar; - local _optarg; - local _opts; - local _string; - - 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 \ - "$@")"; - -# By the call of `eval', unnecessary quoting was removed. So the -# positional shell parameters ($1, $2, ...) are now guaranteed to -# represent an option or an argument to the previous option, if any; -# then a `--' argument for separating options and -# parameters; followed by the filespec parameters if any. - -# Note, the existence of arguments to options has already been checked. -# So a check for `$#' or `--' should not be done for arguments. - - until test "$#" -le 0 || is_equal "$1" '--'; do - _opt="$1"; # $_opt is fed into the option handler - shift; - case "${_opt}" in - -h|--help) - usage; - leave; - ;; - -Q|--source) # output source code (`Quellcode'). - _OPT_MODE='source'; - ;; - -T|--device|--troff-device) # device; arg - _OPT_DEVICE="$1"; - _check_device_with_mode; - shift; - ;; - -v|--version) - version; - leave; - ;; - -V) - _OPT_V='yes'; - ;; - -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}"; - then - list_append _ADDOPTS_GROFF "${_opt}"; - elif list_has _OPTS_GROFF_SHORT_ARG "${_optchar}"; - then - list_append _ADDOPTS_GROFF "${_opt}" "$1"; - shift; - else - error "Unknown option : \`$1'"; - fi; - ;; - --all) - _OPT_ALL="yes"; - ;; - --ascii) - list_append _ADDOPTS_GROFF '-mtty-char'; - if obj _mode is_empty; then - _mode='text'; - fi; - ;; - --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=''; - ;; - --bd) # border color for viewers, arg; - _OPT_BD="$1"; - shift; - ;; - --bg|--backgroud) # background color for viewers, arg; - _OPT_BG="$1"; - shift; - ;; - --bw) # border width for viewers, arg; - _OPT_BW="$1"; - shift; - ;; - --default) # reset variables to default - reset; - ;; - --default-modes) # sequence of modes in auto mode; arg - _OPT_DEFAULT_MODES="$1"; - shift; - ;; - --debug) # buggy, only for development - _OPT_DEBUG='yes'; - ;; - --display) # set X display, arg - _OPT_DISPLAY="$1"; - shift; - ;; - --dvi) - _OPT_MODE='dvi'; - ;; - --dvi-viewer) # viewer program for dvi mode; arg - _OPT_VIEWER_DVI="$1"; - shift; - ;; - --extension) # the extension for man pages, arg - _OPT_EXTENSION="$1"; - shift; - ;; - --fg|--foreground) # foreground color for viewers, arg; - _OPT_FG="$1"; - shift; - ;; - --fn|--font) # set font for viewers, arg; - _OPT_FN="$1"; - shift; - ;; - --geometry) # window geometry for viewers, arg; - _OPT_GEOMETRY="$1"; - shift; - ;; - --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"; - shift; - ;; - --local-file) # force local files; same as `--no-man' - _MAN_FORCE='no'; - _MAN_ENABLE='no'; - ;; - --location|--where) # print file locations to stderr - _OPT_LOCATION='yes'; - ;; - --man) # force all file params to be man pages - _MAN_ENABLE='yes'; - _MAN_FORCE='yes'; - ;; - --manpath) # specify search path for man pages, arg - # arg is colon-separated list of directories - _OPT_MANPATH="$1"; - shift; - ;; - --mode) # display mode - _arg="$1"; - shift; - case "${_arg}" in - 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'; - ;; - pdf) # display with PDF viewer - _mode='pdf'; - ;; - ps) # display with Postscript viewer - _mode='ps'; - ;; - 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"; - ;; - *) - error "unknown mode ${_arg}"; - ;; - esac; - _OPT_MODE="${_mode}"; - ;; - --no-location) # disable former call to `--location' - _OPT_LOCATION='yes'; - ;; - --no-man) # disable search for man pages - # the same as --local-file - _MAN_FORCE="no"; - _MAN_ENABLE="no"; - ;; - --pager) # set paging program for tty mode, arg - _OPT_PAGER="$1"; - shift; - ;; - --pdf) - _OPT_MODE='pdf'; - ;; - --pdf-viewer) # viewer program for ps mode; arg - _OPT_VIEWER_PDF="$1"; - shift; - ;; - --ps) - _OPT_MODE='ps'; - ;; - --ps-viewer) # viewer program for ps mode; arg - _OPT_VIEWER_PS="$1"; - shift; - ;; - --resolution) # set resolution for X devices, arg - _arg="$1"; - shift; - case "${_arg}" in - 75|75dpi) - _dpi=75; - ;; - 100|100dpi) - _dpi=100; - ;; - *) - error "only resoutions of 75 or 100 dpi are supported"; - ;; - esac; - _OPT_RESOLUTION="${_dpi}"; - ;; - --rv) - _OPT_RV='yes'; - ;; - --sections) # specify sections for man pages, arg - # arg is colon-separated list of section names - _OPT_SECTIONS="$1"; - shift; - ;; - --shell) - shift; - ;; - --systems) # man pages for different OS's, arg - # argument is a comma-separated list - _OPT_SYSTEMS="$1"; - shift; - ;; - --text) # text mode without pager - _OPT_MODE=text; - ;; - --title) # title for X viewers; arg - _OPT_TITLE="$1"; - shift; - ;; - --tty) # tty mode, text with pager - _OPT_MODE=tty; - ;; - --text-device|--tty-device) # device for tty mode; arg - _OPT_TEXT_DEVICE="$1"; - shift; - ;; - --whatis) - _OPT_WHATIS='yes'; - ;; - --xrm) # pass X resource string, arg; - list_append _OPT_XRM "$1"; - shift; - ;; - --x-viewer|--X-viewer) # viewer program for x mode; arg - _OPT_VIEWER_X="$1"; - shift; - ;; - *) - error 'error on argument parsing : '"\`$*'"; - ;; - esac; - done; - shift; # remove `--' argument - - 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 is_equal "$#" 0; then # use "-" for standard input - set -- '-'; - fi; - _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 () -# -# Determine the display mode. -# -# Globals: -# in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE -# out: $_DISPLAY_MODE -# - -# _get_first_prog () -# -# Retrieve first argument that represents an existing program in $PATH. -# Local function for main_set_mode(). -# -# Arguments: 1; a comma-separated list of commands (with options), -# like $_VIEWER_*. -# -# Return : `1' if none found, `0' if found. -# Output : the argument that succeded. -# -landmark '16: main_set_mode()'; -main_set_mode() -{ - func_check main_set_mode = 0 "$@"; - local m; - local _modes; - local _viewer; - local _viewers; - - # handle 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 obj _OPT_DISPLAY is_not_empty; then - DISPLAY="${_OPT_DISPLAY}"; - fi; - - if obj _OPT_V is_yes; then - _DISPLAY_MODE='groff'; - list_append _ADDOPTS_GROFF '-V'; - fi; - if obj _OPT_Z is_yes; then - _DISPLAY_MODE='groff'; - list_append _ADDOPTS_GROFF '-Z'; - fi; - if obj _OPT_MODE is_equal 'groff'; then - _DISPLAY_MODE='groff'; - fi; - if obj _DISPLAY_MODE is_equal 'groff'; then - eval "${return_ok}"; - fi; - - if obj _OPT_MODE is_equal 'source'; then - _DISPLAY_MODE='source'; - eval "${return_ok}"; - fi; - - case "${_OPT_MODE}" in - '') # automatic mode - case "${_OPT_DEVICE}" in - X*) - 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) - if obj _DISPLAY_MODE is_not_equal 'text'; then - _DISPLAY_MODE='tty'; - fi; - eval "${return_ok}"; - ;; - esac; - if obj DISPLAY is_empty; then - _DISPLAY_MODE='tty'; - eval "${return_ok}"; - fi; - - 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 obj DISPLAY is_empty; then - error "you must be in X Window for ${_OPT_MODE} mode."; - fi; - _modes="${_OPT_MODE}"; - ;; - esac; - - # only viewer modes are left - eval set -- "$(list_from_split "${_modes}" ',')"; - while test "$#" -gt 0; do - m="$1"; - shift; - case "$m" in - text) - _DISPLAY_MODE='text'; - eval "${return_ok}"; - ;; - tty) - _DISPLAY_MODE='tty'; - eval "${return_ok}"; - ;; - x) - if obj _OPT_VIEWER_X is_not_empty; then - _viewers="${_OPT_VIEWER_X}"; - else - _viewers="${_VIEWER_X}"; - fi; - _viewer="$(_get_first_prog "${_viewers}")"; - if is_not_equal "$?" 0; then - continue; - fi; - _DISPLAY_PROG="${_viewer}"; - _DISPLAY_MODE='x'; - eval "${return_ok}"; - ;; - dvi) - if obj _OPT_VIEWER_DVI is_not_empty; then - _viewers="${_OPT_VIEWER_DVI}"; - else - _viewers="${_VIEWER_DVI}"; - fi; - _viewer="$(_get_first_prog "${_viewers}")"; - if is_not_equal "$?" 0; then - continue; - fi; - _DISPLAY_PROG="${_viewer}"; - _DISPLAY_MODE="dvi"; - eval "${return_ok}"; - ;; - pdf) - if obj _OPT_VIEWER_PDF is_not_empty; then - _viewers="${_OPT_VIEWER_PDF}"; - else - _viewers="${_VIEWER_PDF}"; - fi; - _viewer="$(_get_first_prog "${_viewers}")"; - if is_not_equal "$?" 0; then - continue; - fi; - _DISPLAY_PROG="${_viewer}"; - _DISPLAY_MODE="pdf"; - eval "${return_ok}"; - ;; - ps) - if obj _OPT_VIEWER_PS is_not_empty; then - _viewers="${_OPT_VIEWER_PS}"; - else - _viewers="${_VIEWER_PS}"; - fi; - _viewer="$(_get_first_prog "${_viewers}")"; - if is_not_equal "$?" 0; then - continue; - fi; - _DISPLAY_PROG="${_viewer}"; - _DISPLAY_MODE="ps"; - eval "${return_ok}"; - ;; - html) - if obj _OPT_VIEWER_HTML is_not_empty; then - _viewers="${_OPT_VIEWER_HTML}"; - else - _viewers="${_VIEWER_HTML}"; - fi; - _viewer="$(_get_first_prog "${_viewers}")"; - if is_not_equal "$?" 0; then - continue; - fi; - _DISPLAY_PROG="${_viewer}"; - _DISPLAY_MODE=html; - eval "${return_ok}"; - ;; - esac; - done; - error "no suitable display mode found."; -} - -_get_first_prog() -{ - local i; - if is_equal "$#" 0; then - error "_get_first_prog() needs 1 argument."; - fi; - if is_empty "$1"; then - return "${_BAD}"; - fi; - eval set -- "$(list_from_split "$1" ',')"; - for i in "$@"; do - if obj i is_empty; then - continue; - fi; - if is_prog "$(get_first_essential $i)"; then - echo -n "$i"; - return "${_GOOD}"; - fi; - done; - return "${_BAD}"; -} # main_set_mode() - - -####################################################################### -# main_do_fileargs () -# -# Process filespec arguments in $_FILEARGS. -# -# Globals: -# in: $_FILEARGS (process with `eval set -- "$_FILEARGS"') -# -landmark '17: main_do_fileargs()'; -main_do_fileargs() -{ - func_check main_do_fileargs = 0 "$@"; - local _exitcode; - local _filespec; - local _name; - _exitcode="${_BAD}"; - eval set -- "${_FILEARGS}"; - unset _FILEARGS; - # temporary storage of all input to $_TMP_CAT - while test "$#" -ge 2; do - # test for `s name' arguments, with `s' a 1-char standard section - _filespec="$1"; - shift; - case "${_filespec}" in - '') - continue; - ;; - '-') - if register_file '-'; then - _exitcode="${_GOOD}"; - fi; - continue; - ;; - ?) - if list_has_not _MAN_AUTO_SEC "${_filespec}"; then - if do_filearg "${_filespec}"; then - _exitcode="${_GOOD}"; - fi; - continue; - fi; - _name="$1"; - case "${_name}" in - */*|man:*|*\(*\)|*."${_filespec}") - if do_filearg "${_filespec}"; then - _exitcode="${_GOOD}"; - fi; - continue; - ;; - esac; - if do_filearg "man:${_name}(${_filespec})"; then - _exitcode="${_GOOD}"; - shift; - continue; - else - if do_filearg "${_filespec}"; then - _exitcode="${_GOOD}"; - fi; - continue; - fi; - ;; - *) - if do_filearg "${_filespec}"; then - _exitcode="${_GOOD}"; - fi; - continue; - ;; - esac; - done; # end of `s name' test - while test "$#" -gt 0; do - _filespec="$1"; - shift; - if do_filearg "${_filespec}"; then - _exitcode="${_GOOD}"; - fi; - done; - rm -f "${_TMP_STDIN}"; - if is_equal "${_exitcode}" "${_BAD}"; then - eval "${return_bad}"; - fi; - eval "${return_ok}"; -} # main_do_fileargs() - - -######################################################################## -# main_set_resources () -# -# Determine options for setting X resources with $_DISPLAY_PROG. -# -# Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME -# -landmark '18: main_set_resources()'; -main_set_resources() -{ - func_check main_set_resources = 0 "$@"; - local _prog; # viewer program - local _rl; # resource list - 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")"; - _rl=''; - if obj _OPT_BD is_not_empty; then - case "${_prog}" in - ghostview|gv|gxditview|xditview|xdvi) - list_append _rl '-bd' "${_OPT_BD}"; - ;; - esac; - fi; - if obj _OPT_BG is_not_empty; then - case "${_prog}" in - ghostview|gv|gxditview|xditview|xdvi) - list_append _rl '-bg' "${_OPT_BG}"; - ;; - xpdf) - list_append _rl '-papercolor' "${_OPT_BG}"; - ;; - esac; - fi; - if obj _OPT_BW is_not_empty; then - case "${_prog}" in - ghostview|gv|gxditview|xditview|xdvi) - _list_append _rl '-bw' "${_OPT_BW}"; - ;; - esac; - fi; - if obj _OPT_FG is_not_empty; then - case "${_prog}" in - ghostview|gv|gxditview|xditview|xdvi) - list_append _rl '-fg' "${_OPT_FG}"; - ;; - esac; - fi; - if is_not_empty "${_OPT_FN}"; then - case "${_prog}" in - ghostview|gv|gxditview|xditview|xdvi) - list_append _rl '-fn' "${_OPT_FN}"; - ;; - esac; - fi; - if is_not_empty "${_OPT_GEOMETRY}"; then - case "${_prog}" in - ghostview|gv|gxditview|xditview|xdvi|xpdf) - list_append _rl '-geometry' "${_OPT_GEOMETRY}"; - ;; - esac; - fi; - if is_empty "${_OPT_RESOLUTION}"; then - _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}"; - case "${_prog}" in - gxditview|xditview) - list_append _rl '-resolution' "${_DEFAULT_RESOLUTION}"; - ;; - xpdf) - case "${_DEFAULT_RESOLUTION}" in - 75) - # 72dpi is '100' - list_append _rl '-z' '104'; - ;; - 100) - list_append _rl '-z' '139'; - ;; - esac; - ;; - esac; - else - case "${_prog}" in - ghostview|gv|gxditview|xditview|xdvi) - list_append _rl '-resolution' "${_OPT_RESOLUTION}"; - ;; - xpdf) - case "${_OPT_RESOLUTION}" in - 75) - list_append _rl '-z' '104'; - # '100' corresponds to 72dpi - ;; - 100) - list_append _rl '-z' '139'; - ;; - esac; - ;; - esac; - fi; - 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) - list_append _rl '-rv'; - ;; - esac; - fi; - if is_not_empty "${_OPT_XRM}"; then - case "${_prog}" in - ghostview|gv|gxditview|xditview|xdvi|xpdf) - eval set -- "{$_OPT_XRM}"; - for i in "$@"; do - list_append _rl '-xrm' "$i"; - done; - ;; - esac; - fi; - if is_not_empty "${_title}"; then - case "${_prog}" in - gxditview|xditview) - list_append _rl '-title' "${_title}"; - ;; - esac; - fi; - _DISPLAY_ARGS="${_rl}"; - - eval "${return_ok}"; -} # main_set_resources - - -######################################################################## -# main_display () -# -# Do the actual display of the whole thing. -# -# Globals: -# in: $_DISPLAY_MODE, $_OPT_DEVICE, -# $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X, -# $_REGISTERED_TITLE, $_TMP_CAT, -# $_OPT_PAGER $PAGER $_MANOPT_PAGER -# -landmark '19: main_display()'; -main_display() -{ - func_check main_display = 0 "$@"; - local p; - local _addopts; - local _device; - local _groggy; - local _modefile; - local _options; - local _pager; - local _title; - export _addopts; - export _groggy; - export _modefile; - - 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 obj _OPT_DEVICE is_not_empty; then - _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}"; - fi; - _groggy="$(tmp_cat | eval grog "${_options}")"; - trap_clean; - # start a new shell program to get another process ID. - sh -c ' - set -e; - test -f "${_modefile}" && rm -f "${_modefile}"; - mv "${_TMP_CAT}" "${_modefile}"; - cat "${_modefile}" | \ - ( - clean_up() - { - 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}"; - ) &' - ;; - text|tty) - case "${_OPT_DEVICE}" in - '') - _device="$(get_first_essential \ - "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")"; - ;; - ascii|cp1047|latin1|utf8) - _device="${_OPT_DEVICE}"; - ;; - *) - warning \ - "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; - ;; - esac; - _addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}"; - _groggy="$(tmp_cat | grog -T${_device})"; - 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 obj _pager is_empty; then - error 'no pager program found for tty mode'; - fi; - tmp_cat | eval "${_groggy}" "${_addopts}" | \ - eval "${_pager}"; - fi; - clean_up; - ;; - - #### viewer modes - - dvi) - case "${_OPT_DEVICE}" in - ''|dvi) do_nothing; ;; - *) - warning \ - "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; - ;; - esac; - _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) - do_nothing; - ;; - *) - warning \ - "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; - _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}"; - gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \ - -sOutputFile="${_modefile}" -c save pop -f "${_psfile}"; - test -f "${_psfile}" && rm -f "${_psfile}"; - test -f "${_TMP_CAT}" && rm -f "${_TMP_CAT}"; - ( - 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}"; - ) &' - ;; - ps) - case "${_OPT_DEVICE}" in - ''|ps) - do_nothing; - ;; - *) - warning \ - "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; - ;; - esac; - _groggy="$(tmp_cat | grog -Tps)"; - _do_display; - ;; - source) - tmp_cat; - clean_up; - ;; - x) - case "${_OPT_DEVICE}" in - '') - _groggy="$(tmp_cat | grog -Z)"; - ;; - X*|ps) - _groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -Z)"; - ;; - *) - warning \ - "wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; - _groggy="$(tmp_cat | grog -Z)"; - ;; - esac; - _do_display; - ;; - *) - error "unknown mode \`${_DISPLAY_MODE}'"; - ;; - esac; - eval "${return_ok}"; -} # 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; - test -f "${_modefile}" && rm -f "${_modefile}"; - cat "${_TMP_CAT}" | \ - eval "${_groggy}" "${_ADDOPTS_GROFF}" > "${_modefile}"; - rm -f "${_TMP_CAT}"; - ( - clean_up() { - 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}"; - ) &' -} - - -######################################################################## -# main (*) -# -# The main function for groffer. -# -# Arguments: -# -main() -{ - func_check main '>=' 0 "$@"; - # Do not change the sequence of the following functions! - main_init; - main_parse_MANOPT; - main_parse_args "$@"; - main_set_mode; - main_do_fileargs; - main_set_resources; - main_display; - eval "${return_ok}"; -} - -landmark '20: end of function definitions'; - -######################################################################## - -main "$@"; diff -u -r --new-file groff-1.19.1/contrib/groffer/groffer2.sh groff-1.19.2/contrib/groffer/groffer2.sh --- groff-1.19.1/contrib/groffer/groffer2.sh 1969-12-31 16:00:00.000000000 -0800 +++ groff-1.19.2/contrib/groffer/groffer2.sh 2005-08-22 15:13:05.000000000 -0700 @@ -0,0 +1,5854 @@ +#! /bin/sh + +# groffer - display groff files + +# Source file position: /contrib/groffer/groffer2.sh +# Installed position: /lib/groff/groffer/groffer2.sh + +# This file should not be run independently. It is called by +# `groffer.sh' in the source or by the installed `groffer' program. + +# Copyright (C) 2001,2002,2003,2004,2005 +# Free Software Foundation, Inc. +# Written by Bernd Warken + +# Last update: 22 August 2005 + +# 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, +# USA. + + +######################################################################## +# Test of rudimentary shell functionality +######################################################################## + + +######################################################################## +# Test of `unset' +# +export _UNSET; +export _foo; +_foo=bar; +_res="$(unset _foo 2>&1)"; +if unset _foo >${_NULL_DEV} 2>&1 && \ + test _"${_res}"_ = __ && test _"${_foo}"_ = __ +then + _UNSET='unset'; + eval "${_UNSET}" _foo; + eval "${_UNSET}" _res; +else + _UNSET=':'; +fi; + + +######################################################################## +# Test of `test'. +# +if test a = a && test a != b && test -f "${_GROFFER_SH}" +then + :; +else + echo '"test" did not work.' >&2; + exit "${_ERROR}"; +fi; + + +######################################################################## +# Test of `echo' and the `$()' construct. +# +if echo '' >${_NULL_DEV} +then + :; +else + echo '"echo" did not work.' >&2; + exit "${_ERROR}"; +fi; +if test _"$(t1="$(echo te)" && + t2="$(echo '')" && + t3="$(echo 'st')" && + echo "${t1}${t2}${t3}")"_ \ + != _test_ +then + echo 'The "$()" construct did not work' >&2; + exit "${_ERROR}"; +fi; + + +######################################################################## +# Test of sed program; test in groffer.sh is not valid here. +# +if test _"$(echo red | sed -e 's/r/s/')"_ != _sed_ +then + echo 'The sed program did not work.' >&2; + exit "${_ERROR}"; +fi; + + +######################################################################## +# Test of function definitions. +# +_t_e_s_t_f_u_n_c_() +{ + return 0; +} + +if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV} +then + :; +else + echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2; + exit "${_ERROR}"; +fi; + + +######################################################################## +# debug - diagnostic messages +######################################################################## + +export _DEBUG_STACKS; +_DEBUG_STACKS='no'; # disable stack output in each function +#_DEBUG_STACKS='yes'; # enable stack output in each function + +export _DEBUG_LM; +_DEBUG_LM='no'; # disable landmark messages +#_DEBUG_LM='yes'; # enable landmark messages + +export _DEBUG_KEEP_FILES; +_DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir +#_DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir + +export _DEBUG_PRINT_PARAMS; +_DEBUG_PRINT_PARAMS='no'; # disable printing of all parameters +#_DEBUG_PRINT_PARAMS='yes'; # enable printing of all parameters + +export _DEBUG_PRINT_SHELL; +_DEBUG_PRINT_SHELL='no'; # disable printing of the shell name +#_DEBUG_PRINT_SHELL='yes'; # enable printing of the shell name + +export _DEBUG_PRINT_TMPDIR; +_DEBUG_PRINT_TMPDIR='no'; # disable printing of the temporary dir +#_DEBUG_PRINT_TMPDIR='yes'; # enable printing of the temporary dir + +export _DEBUG_USER_WITH_STACK; +_DEBUG_USER_WITH_STACK='no'; # disable stack dump in error_user() +#_DEBUG_USER_WITH_STACK='yes'; # enable stack dump in error_user() + +# determine all --debug* options +case " $*" in +*\ --debug*) + case " $* " in + *' --debug '*) + # _DEBUG_STACKS='yes'; + # _DEBUG_LM='yes'; + _DEBUG_KEEP_FILES='yes'; + _DEBUG_PRINT_PARAMS='yes'; + _DEBUG_PRINT_SHELL='yes'; + _DEBUG_PRINT_TMPDIR='yes'; + _DEBUG_USER_WITH_STACK='yes'; + ;; + esac; + d=' --debug-all --debug-keep --debug-lm --debug-params --debug-shell '\ +'--debug-stacks --debug-tmpdir --debug-user '; + for i + do + case "$i" in + --debug-s) + echo 'The abbreviation --debug-s has multiple options: '\ +'--debug-shell and --debug-stacks.' >&2 + exit "${_ERROR}"; + ;; + esac; + case "$d" in + *\ ${i}*) + # extract whole word of abbreviation $i + s="$(cat <&2; +fi; + +if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_ +then + if test _"${_SHELL}"_ = __ + then + if test _"${POSIXLY_CORRECT}"_ = _y_ + then + echo 'shell: bash as /bin/sh (none specified)' >&2; + else + echo 'shell: /bin/sh (none specified)' >&2; + fi; + else + echo "shell: ${_SHELL}" >&2; + fi; +fi; + + +######################################################################## +# Environment Variables +######################################################################## + +# Environment variables that exist only for this file start with an +# underscore letter. Global variables to this file are written in +# upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables +# start with an underline and use only lower case letters and +# underlines, e.g. $_local_variable . + +# [A-Z]* system variables, e.g. $MANPATH +# _[A-Z_]* global file variables, e.g. $_MAN_PATH +# _[a-z_]* temporary variables, e.g. $_manpath + +# Due to incompatibilities of the `ash' shell, the name of loop +# variables in `for' must be single character +# [a-z] local loop variables, e.g. $i + + +######################################################################## +# read-only variables (global to this file) +######################################################################## + +# function return values; `0' means ok; other values are error codes +export _ALL_EXIT; +export _BAD; +export _GOOD; +export _NO; +export _OK; +export _YES; + +_GOOD='0'; # return ok +_BAD='1'; # return negatively, error code `1' +# $_ERROR was already defined as `7' in groffer.sh. + +_NO="${_BAD}"; +_YES="${_GOOD}"; +_OK="${_GOOD}"; + +# quasi-functions, call with `eval', e.g `eval "${return_ok}"' +export return_ok; +export return_good; +export return_bad; +export return_yes; +export return_no; +export return_error; +export return_var; +return_ok="func_pop; return ${_OK}"; +return_good="func_pop; return ${_GOOD}"; +return_bad="func_pop; return ${_BAD}"; +return_yes="func_pop; return ${_YES}"; +return_no="func_pop; return ${_NO}"; +return_error="func_pop; return ${_ERROR}"; +return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n' + + +export _DEFAULT_MODES; +_DEFAULT_MODES='x,ps,tty'; +export _DEFAULT_RESOLUTION; +_DEFAULT_RESOLUTION='75'; + +export _DEFAULT_TTY_DEVICE; +_DEFAULT_TTY_DEVICE='latin1'; + +# _VIEWER_* viewer programs for different modes (only X is necessary) +# _VIEWER_* a comma-separated list of viewer programs (with options) +export _VIEWER_DVI; # viewer program for dvi mode +export _VIEWER_HTML_TTY; # viewer program for html mode in tty +export _VIEWER_HTML_X; # viewer program for html mode in X +export _VIEWER_PDF; # viewer program for pdf mode +export _VIEWER_PS; # viewer program for ps mode +export _VIEWER_X; # viewer program for X mode +_VIEWER_DVI='kdvi,xdvi,dvilx'; +_VIEWER_HTML_TTY='lynx'; +_VIEWER_HTML_X='konqueror,mozilla,netscape,galeon,opera,amaya,arena'; +_VIEWER_PDF='kghostview --scale 1.45,ggv,xpdf,acroread,kpdf'; +_VIEWER_PS='kghostview --scale 1.45,ggv,gv,ghostview,gs_x11,gs'; +_VIEWER_X='gxditview,xditview'; + +# Search automatically in standard sections `1' to `8', and in the +# traditional sections `9', `n', and `o'. On many systems, there +# exist even more sections, mostly containing a set of man pages +# special to a specific program package. These aren't searched for +# automatically, but must be specified on the command line. +export _MAN_AUTO_SEC_LIST; +_MAN_AUTO_SEC_LIST="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"; +export _MAN_AUTO_SEC_CHARS; +_MAN_AUTO_SEC_CHARS='[123456789no]'; + +export _SPACE_SED; +_SPACE_SED='['"${_SP}${_TAB}"']'; + +export _SPACE_CASE; +_SPACE_CASE='[\'"${_SP}"'\'"${_TAB}"']'; + +export _PROCESS_ID; # for shutting down the program +_PROCESS_ID="$$"; + + +############ the command line options of the involved programs +# +# The naming scheme for the options environment names is +# $_OPTS__[_] +# +# : program name GROFFER, GROFF, or CMDLINE (for all +# command line options) +# : LONG (long options) or SHORT (single character options) +# : ARG for options with argument, NA for no argument; +# without _ both the ones with and without arg. +# +# Each option that takes an argument must be specified with a +# trailing : (colon). + +# exports +export _OPTS_GROFFER_SHORT_NA; +export _OPTS_GROFFER_SHORT_ARG; +export _OPTS_GROFFER_LONG_NA; +export _OPTS_GROFFER_LONG_ARG; +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_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_LONG_NA; +export _OPTS_CMDLINE_LONG_ARG; + +###### groffer native options + +_OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'"; +_OPTS_GROFFER_SHORT_ARG="'T'"; + +_OPTS_GROFFER_LONG_NA="'auto' \ +'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \ +'debug' 'debug-all' 'debug-keep' 'debug-lm' 'debug-params' 'debug-shell' \ +'debug-stacks' 'debug-tmpdir' 'debug-user' 'default' 'do-nothing' 'dvi' \ +'groff' 'help' 'intermediate-output' 'html' 'man' \ +'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \ +'text' 'text-device' \ +'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'"; + +_OPTS_GROFFER_LONG_ARG="\ +'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \ +'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \ +'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \ +'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \ +'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'"; + +##### 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' '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=""; + +##### groffer options inhereted from the X Window toolkit + +_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' 'catman' 'ditroff' \ +'local-file' 'location' 'troff' 'update'"; + +_OPTS_MAN_LONG_ARG="'locale' 'manpath' \ +'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'"; + +###### additional options for parsing $MANOPT only + +_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'"; + +_OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \ +'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \ +'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'"; + +_OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \ +'config_file' 'encoding' 'extension' 'locale'"; + +###### collections of command line options + +_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_X_LONG_NA} ${_OPTS_MAN_LONG_NA}"; +_OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \ +${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}"; + + +######################################################################## +# read-write variables (global to this file) +######################################################################## + +export _ALL_PARAMS; # All options and file name parameters +export _ADDOPTS_GROFF; # Transp. options for groff (`eval'). +export _ADDOPTS_POST; # Transp. options postproc (`eval'). +export _ADDOPTS_X; # Transp. options X postproc (`eval'). +export _APROPOS_PROG; # Program to run apropos. +export _APROPOS_SECTIONS; # Sections for different --apropos-*. +export _DEFAULT_MODES; # Set default modes. +export _DISPLAY_MODE; # Display mode. +export _DISPLAY_PROG; # Viewer program to be used for display. +export _DISPLAY_ARGS; # X resources for the viewer program. +export _FILEARGS; # Stores filespec parameters. +export _FILESPEC_ARG; # Stores the actual filespec parameter. +export _FUNC_STACK; # Store debugging information. +export _REGISTERED_TITLE; # Processed file names. +# _HAS_* from availability tests +export _HAS_COMPRESSION; # `yes' if gzip compression is available +export _HAS_BZIP; # `yes' if bzip2 compression is available +# _MAN_* finally used configuration of man searching +export _MAN_ALL; # search all man pages per filespec +export _MAN_ENABLE; # enable search for man pages +export _MAN_EXT; # extension for man pages +export _MAN_FORCE; # force file parameter to be man pages +export _MAN_IS_SETUP; # setup man variables only once +export _MAN_LANG; # language for man pages +export _MAN_LANG2; # language for man pages +export _MAN_LANG_DONE; # language dirs added to man path +export _MAN_PATH; # search path for man pages +export _MAN_SEC; # sections for man pages; sep. `:' +export _MAN_SEC_DONE; # sections added to man path +export _MAN_SYS; # system names for man pages; sep. `,' +export _MAN_SYS; # system names added to man path +# _MANOPT_* as parsed from $MANOPT +export _MANOPT_ALL; # $MANOPT --all +export _MANOPT_EXTENSION; # $MANOPT --extension +export _MANOPT_LANG; # $MANOPT --locale +export _MANOPT_PATH; # $MANOPT --manpath +export _MANOPT_PAGER; # $MANOPT --pager +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; # call `apropos' program. +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. +export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given. +export _OPT_DEVICE; # device option. +export _OPT_DO_NOTHING; # do nothing in main_display(). +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, "" +export _OPT_MANPATH; # manual setting of path for man-pages +export _OPT_PAGER; # specify paging program for tty mode +export _OPT_RESOLUTION; # set X resolution in dpi +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_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_HTML; # viewer program for html mode +export _OPT_VIEWER_X; # viewer program for x mode +export _OPT_WHATIS; # print the man description +export _OPT_XRM; # specify X resource. +export _OPT_Z; # groff option -Z. +export _OUTPUT_FILE_NAME; # output generated, see main_set_res..() +export _VIEWER_TERMINAL; # viewer options for terminal (--*-viewer-tty) +# _TMP_* temporary directory and files +export _TMP_DIR; # groffer directory for temporary files +export _TMP_CAT; # stores concatenation of everything +export _TMP_STDIN; # stores stdin, if any + +# these variables are preset in section `Preset' after the rudim. test + + +######################################################################## +# Preset and reset of read-write global variables +######################################################################## + + +export _START_DIR; # directory at start time of the script +_START_DIR="$(pwd)"; + +# For variables that can be reset by option `--default', see reset(). + +_FILEARGS=''; + +# _HAS_* from availability tests +_HAS_COMPRESSION=''; +_HAS_BZIP=''; + +# _TMP_* temporary files +_TMP_DIR=''; +_TMP_CAT=''; +_TMP_CONF=''; +_TMP_STDIN=''; + + +######################################################################## +# reset () +# +# Reset the variables that can be affected by options to their default. +# +reset() +{ + if test "$#" -ne 0 + then + error "reset() does not have arguments."; + fi; + + _ADDOPTS_GROFF=''; + _ADDOPTS_POST=''; + _ADDOPTS_X=''; + _APROPOS_PROG=''; + _APROPOS_SECTIONS=''; + _DISPLAY_ARGS=''; + _DISPLAY_MODE=''; + _DISPLAY_PROG=''; + _REGISTERED_TITLE=''; + + # _MAN_* finally used configuration of man searching + _MAN_ALL='no'; + _MAN_ENABLE='yes'; # do search for man-pages + _MAN_EXT=''; + _MAN_FORCE='no'; # first local file, then search man page + _MAN_IS_SETUP='no'; + _MAN_LANG=''; + _MAN_LANG2=''; + _MAN_PATH=''; + _MAN_SEC=''; + _MAN_SEC_DONE='no'; + _MAN_SYS=''; + _MAN_SYS_DONE='no'; + + # _MANOPT_* as parsed from $MANOPT + _MANOPT_ALL='no'; + _MANOPT_EXTENSION=''; + _MANOPT_LANG=''; + _MANOPT_PATH=''; + _MANOPT_PAGER=''; + _MANOPT_SEC=''; + _MANOPT_SYS=''; + + # _OPT_* as parsed from groffer command line + _OPT_ALL='no'; + _OPT_APROPOS='no'; + _OPT_BD=''; + _OPT_BG=''; + _OPT_BW=''; + _OPT_DEFAULT_MODES=''; + _OPT_DEVICE=''; + _OPT_DISPLAY=''; + _OPT_DO_NOTHING='no'; + _OPT_FG=''; + _OPT_FN=''; + _OPT_GEOMETRY=''; + _OPT_ICONIC='no'; + _OPT_LANG=''; + _OPT_LOCATION='no'; + _OPT_MODE=''; + _OPT_MANPATH=''; + _OPT_PAGER=''; + _OPT_RESOLUTION=''; + _OPT_RV='no'; + _OPT_SECTIONS=''; + _OPT_SYSTEMS=''; + _OPT_TITLE=''; + _OPT_TEXT_DEVICE=''; + _OPT_V='no'; + _OPT_VIEWER_DVI=''; + _OPT_VIEWER_PDF=''; + _OPT_VIEWER_PS=''; + _OPT_VIEWER_HTML=''; + _OPT_VIEWER_X=''; + _OPT_WHATIS='no'; + _OPT_XRM=''; + _OPT_Z='no'; + _VIEWER_TERMINAL='no'; +} + +reset; + + +######################################################################## +# Functions for error handling and debugging +######################################################################## + + +############## +# echo1 (*) +# +# Output to stdout. +# +# Arguments : arbitrary text including `-'. +# +echo1() +{ + cat <*) +# +# Output to stderr. +# +# Arguments : arbitrary text. +# +echo2() +{ + cat >&2 <) +# +# Print to standard error as a debugging aid. +# +# Globals: $_DEBUG_LM +# +landmark() +{ + if test _"${_DEBUG_LM}"_ = _yes_ + then + echo2 "LM: $*"; + fi; +} + +landmark "1: debugging functions"; + + +############## +# clean_up () +# +# Clean up at exit. +# +clean_up() +{ + cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1; + if test _${_DEBUG_KEEP_FILES}_ = _yes_ + then + echo2 "Kept temporary directory ${_TMP_DIR}." + else + if test _"${_TMP_DIR}"_ != __ + then + if test -d "${_TMP_DIR}" || test -f "${_TMP_DIR}" + then + rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1; + fi; + fi; + fi; +} + + +############# +# diag (text>*) +# +# Output a diagnostic message to stderr +# +diag() +{ + echo2 '>>>>>'"$*"; +} + + +############# +# error (*) +# +# Print an error message to standard error, print the function stack, +# exit with an error condition. The argument should contain the name +# of the function from which it was called. This is for system errors. +# +error() +{ + case "$#" in + 1) echo2 'groffer error: '"$1"; ;; + *) echo2 'groffer error: wrong number of arguments in error().'; ;; + esac; + func_stack_dump; + if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}" + then + : >"${_TMP_DIR}"/,error; + fi; + exit "${_ERROR}"; +} + + +############# +# error_user (*) +# +# Print an error message to standard error; exit with an error condition. +# The error is supposed to be produce by the user. So the funtion stack +# is omitted. +# +error_user() +{ + case "$#" in + 1) + echo2 'groffer error: '"$1"; + ;; + *) + echo2 'groffer error: wrong number of arguments in error_user().'; + ;; + esac; + if test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_ + then + func_stack_dump; + fi; + if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}" + then + : >"${_TMP_DIR}"/,error; + fi; + exit "${_ERROR}"; +} + + +############# +# exit_test () +# +# Test whether the former command ended with error(). Exit again. +# +# Globals: $_ERROR +# +exit_test() +{ + if test "$?" = "${_ERROR}" + then + exit ${_ERROR}; + fi; + if test _"${_TMP_DIR}"_ != __ && test -f "${_TMP_DIR}"/,error + then + exit ${_ERROR}; + fi; +} + + +############# +# func_check ( "$@") +# +# Check number of arguments and register to _FUNC_STACK. +# +# Arguments: >=3 +# : name of the calling function. +# : a relational operator: = != < > <= >= +# : number of arguments to be checked against +# "$@": the arguments of the calling function. +# +# Variable prefix: fc +# +func_check() +{ + if test "$#" -lt 3 + then + error 'func_check() needs at least 3 arguments.'; + fi; + fc_fname="$1"; + case "$3" in + 1) + fc_nargs="$3"; + fc_s=''; + ;; + 0|[2-9]) + fc_nargs="$3"; + fc_s='s'; + ;; + *) + error "func_check(): third argument must be a digit."; + ;; + esac; + case "$2" in + '='|'-eq') + fc_op='-eq'; + fc_comp='exactly'; + ;; + '>='|'-ge') + fc_op='-ge'; + fc_comp='at least'; + ;; + '<='|'-le') + fc_op='-le'; + fc_comp='at most'; + ;; + '<'|'-lt') + fc_op='-lt'; + fc_comp='less than'; + ;; + '>'|'-gt') + fc_op='-gt'; + fc_comp='more than'; + ;; + '!='|'-ne') + fc_op='-ne'; + fc_comp='not'; + ;; + *) + error \ + 'func_check(): second argument is not a relational operator.'; + ;; + esac; + shift; + shift; + shift; + if test "$#" "${fc_op}" "${fc_nargs}" + then + do_nothing; + else + error "func_check(): \ +${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.'; + fi; + func_push "${fc_fname}"; + if test _"${_DEBUG_STACKS}"_ = _yes_ + then + echo2 '+++ '"${fc_fname} $@"; + echo2 '>>> '"${_FUNC_STACK}"; + fi; + eval ${_UNSET} fc_comp; + eval ${_UNSET} fc_fname; + eval ${_UNSET} fc_nargs; + eval ${_UNSET} fc_op; + eval ${_UNSET} fc_s; +} + + +############# +# func_pop () +# +# Retrieve the top element from the stack. +# +# The stack elements are separated by `!'; the popped element is +# identical to the original element, except that all `!' characters +# were removed. +# +# Arguments: 1 +# +func_pop() +{ + if test "$#" -ne 0 + then + error 'func_pop() does not have arguments.'; + fi; + case "${_FUNC_STACK}" in + '') + if test _"${_DEBUG_STACKS}"_ = _yes_ + then + error 'func_pop(): stack is empty.'; + fi; + ;; + *!*) + # split at first bang `!'. + _FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')"; + exit_test; + ;; + *) + _FUNC_STACK=''; + ;; + esac; + if test _"${_DEBUG_STACKS}"_ = _yes_ + then + echo2 '<<< '"${_FUNC_STACK}"; + fi; +} + + +############# +# func_push () +# +# Store another element to stack. +# +# The stack elements are separated by `!'; if contains a `!' +# it is removed first. +# +# Arguments: 1 +# +# Variable prefix: fp +# +func_push() +{ + if test "$#" -ne 1 + then + error 'func_push() needs 1 argument.'; + fi; + case "$1" in + *'!'*) + # remove all bangs `!'. + fp_element="$(echo1 "$1" | sed -e 's/!//g')"; + exit_test; + ;; + *) + fp_element="$1"; + ;; + esac; + if test _"${_FUNC_STACK}"_ = __ + then + _FUNC_STACK="${fp_element}"; + else + _FUNC_STACK="${fp_element}!${_FUNC_STACK}"; + fi; + eval ${_UNSET} fp_element; +} + + +############# +# func_stack_dump () +# +# Print the content of the stack. Ignore the arguments. +# +func_stack_dump() +{ + diag 'call stack: '"${_FUNC_STACK}"; +} + + +######################################################################## +# System Test +######################################################################## + +landmark "2: system test"; + +# Test the availability of the system utilities used in this script. + + +######################################################################## +# Test of function `sed'. +# + +if test _"$(echo xTesTx \ + | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \ + | sed -e 's|T|t|g')"_ != _test_ +then + error 'Test of "sed" command failed.'; +fi; + + +######################################################################## +# Test of function `cat'. +# +if test _"$(echo test | cat)"_ != _test_ +then + error 'Test of "cat" command failed.'; +fi; + + +######################################################################## +# Test for compression. +# +if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_ +then + _HAS_COMPRESSION='yes'; + if echo1 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \ + && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \ + | bzip2 -d -c 2>${_NULL_DEV})"_ \ + = _test_ + then + _HAS_BZIP='yes'; + else + _HAS_BZIP='no'; + fi; +else + _HAS_COMPRESSION='no'; + _HAS_BZIP='no'; +fi; + + +######################################################################## +# Definition of normal Functions in alphabetical order +######################################################################## +landmark "3: functions"; + +######################################################################## +# apropos_filespec () +# +# Setup for the --apropos* options +# +apropos_filespec() +{ + + func_check apropos_filespec '=' 0 "$@"; + if obj _OPT_APROPOS is_yes + then + eval to_tmp_line \ + "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'"; + exit_test; + if obj _APROPOS_PROG is_empty + then + error 'apropos_filespec: apropos_setup() must be run first.'; + fi; + if obj _APROPOS_SECTIONS is_empty + then + if obj _OPT_SECTIONS is_empty + then + s='^.*(.*).*$'; + else + s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/://g')"']'; + fi; + else + s='^.*(['"${_APROPOS_SECTIONS}"']'; + fi; + eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \ + sed -n -e ' +/^'"${_FILESPEC_ARG}"': /p +/'"$s"'/p +' | \ + sort |\ + sed -e ' +s/^\(.* (..*)\) *- *\(.*\)$/\.br\n\.TP 15\n\.BR \1\n\2/ +' >>"${_TMP_CAT}"; + fi; + eval "${return_ok}"; +} + + +######################################################################## +# apropos_setup () +# +# Setup for the --apropos* options +# +apropos_setup() +{ + func_check apropos_setup '=' 0 "$@"; + if obj _OPT_APROPOS is_yes + then + if is_prog apropos + then + _APROPOS_PROG='apropos'; + elif is_prog man + then + if man --apropos man >${_NULL_DEV} 2>${_NULL_DEV} + then + _APROPOS_PROG='man --apropos'; + elif man -k man >${_NULL_DEV} 2>${_NULL_DEV} + then + _APROPOS_PROG='man -k'; + fi; + fi; + if obj _APROPOS_PROG is_empty + then + error 'apropos_setup: no apropos program available.'; + fi; + to_tmp_line '.TH GROFFER APROPOS'; + fi; + eval "${return_ok}"; +} + + +######################################################################## +# base_name () +# +# Get the file name part of , i.e. delete everything up to last +# `/' from the beginning of . Remove final slashes, too, to get a +# non-empty output. +# +# Arguments : 1 +# Output : the file name part (without slashes) +# +# Variable prefix: bn +# +base_name() +{ + func_check base_name = 1 "$@"; + bn_name="$1"; + case "${bn_name}" in + */) + # delete all final slashes + bn_name="$(echo1 "${bn_name}" | sed -e 's|//*$||')"; + exit_test; + ;; + esac; + case "${bn_name}" in + /|'') + eval ${_UNSET} bn_name; + eval "${return_bad}"; + ;; + */*) + # delete everything before and including the last slash `/'. + echo1 "${bn_name}" | sed -e 's|^.*//*\([^/]*\)$|\1|'; + ;; + *) + obj bn_name echo1; + ;; + esac; + eval ${_UNSET} bn_name; + eval "${return_ok}"; +} + + +######################################################################## +# cat_z () +# +# Decompress if possible or just print to standard output. +# +# gzip, bzip2, and .Z decompression is supported. +# +# Arguments: 1, a file name. +# Output: the content of , possibly decompressed. +# +if test _"${_HAS_COMPRESSION}"_ = _yes_ +then + cat_z() + { + func_check cat_z = 1 "$@"; + case "$1" in + '') + error 'cat_z(): empty file name'; + ;; + '-') + error 'cat_z(): for standard input use save_stdin()'; + ;; + esac; + if obj _HAS_BZIP is_yes + then + if bzip2 -t "$1" 2>${_NULL_DEV} + then + bzip2 -c -d "$1" 2>${_NULL_DEV}; + eval "${return_ok}"; + fi; + fi; + gzip -c -d -f "$1" 2>${_NULL_DEV}; + eval "${return_ok}"; + } +else + cat_z() + { + func_check cat_z = 1 "$@"; + cat "$1"; + eval "${return_ok}"; + } +fi; + + +######################################################################## +# clean_up () +# +# Do the final cleaning up before exiting; used by the trap calls. +# +# defined above + + +######################################################################## +# diag (*) +# +# Print marked message to standard error; useful for debugging. +# +# defined above + + +######################################################################## +landmark '4: dirname()*'; +######################################################################## + +####################################################################### +# dirname_append ( ) +# +# Append `name' to `dir' with clean handling of `/'. +# +# Arguments : 2 +# Output : the generated new directory name / +# +dirname_append() +{ + func_check dirname_append = 2 "$@"; + if is_empty "$1" + then + error "dir_append(): first argument is empty."; + fi; + if is_empty "$2" + then + echo1 "$1"; + else + dirname_chop "$1"/"$2"; + fi; + eval "${return_ok}"; +} + + +######################################################################## +# dirname_chop () +# +# Remove unnecessary slashes from directory name. +# +# Argument: 1, a directory name. +# Output: path without double, or trailing slashes. +# +# Variable prefix: dc +# +dirname_chop() +{ + func_check dirname_chop = 1 "$@"; + # replace all multiple slashes by a single slash `/'. + dc_res="$(echo1 "$1" | sed -e 's|///*|/|g')"; + exit_test; + case "${dc_res}" in + ?*/) + # remove trailing slash '/'; + echo1 "${dc_res}" | sed -e 's|/$||'; + ;; + *) + obj dc_res echo1 + ;; + esac; + eval ${_UNSET} dc_res; + eval "${return_ok}"; +} + + +######################################################################## +# do_filearg () +# +# Append the file, man-page, or standard input corresponding to the +# argument to the temporary file. If this is compressed in the gzip +# or Z format it is decompressed. A title element is generated. +# +# Argument either: +# - name of an existing file. +# - `-' to represent standard input (several times allowed). +# - `man:name.(section)' the man-page for `name' in `section'. +# - `man:name.section' the man-page for `name' in `section'. +# - `man:name' the man-page for `name' in the lowest `section'. +# - `name.section' the man-page for `name' in `section'. +# - `name' the man-page for `name' in the lowest `section'. +# Globals : +# $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN +# +# Output : none +# Return : $_GOOD if found, ${_BAD} otherwise. +# +# Variable prefix: df +# +do_filearg() +{ + func_check do_filearg = 1 "$@"; + df_filespec="$1"; + # store sequence into positional parameters + case "${df_filespec}" in + '') + eval ${_UNSET} df_filespec; + eval "${return_good}"; + ;; + '-') + register_file '-'; + eval ${_UNSET} df_filespec; + eval "${return_good}"; + ;; + */*) # with directory part; so no man search + set 'File'; + ;; + *) + if obj _MAN_ENABLE is_yes + then + if obj _MAN_FORCE is_yes + then + set 'Manpage' 'File'; + else + set 'File' 'Manpage'; + fi; + else + set 'File'; + fi; + ;; + esac; + for i + do + case "$i" in + File) + if test -f "${df_filespec}" + then + if test -r "${df_filespec}" + then + register_file "${df_filespec}"; + eval ${_UNSET} df_filespec; + eval ${_UNSET} df_no_man; + eval "${return_good}"; + else + echo2 "could not read \`${df_filespec}'"; + eval ${_UNSET} df_filespec; + eval ${_UNSET} df_no_man; + eval "${return_bad}"; + fi; + else + if obj df_no_man is_not_empty + then + if obj _OPT_WHATIS is_yes + then + to_tmp_line "This is neither a file nor a man page." + else + echo2 "\`${df_filespec}' is neither a file nor a man page." + fi; + fi; + df_no_file=yes; + continue; + fi; + ;; + Manpage) # parse filespec as man page + if obj _MAN_IS_SETUP is_not_yes + then + man_setup; + fi; + if man_do_filespec "${df_filespec}" + then + eval ${_UNSET} df_filespec; + eval ${_UNSET} df_no_file; + eval "${return_good}"; + else + if obj df_no_file is_not_empty + then + if obj _OPT_WHATIS is_yes + then + to_tmp_line "This is neither a file nor a man page." + else + echo2 "\`${df_filespec}' is neither a file nor a man page." + fi; + fi; + df_no_man=yes; + continue; + fi; + ;; + esac; + done; + eval ${_UNSET} df_filespec; + eval ${_UNSET} df_no_file; + eval ${_UNSET} df_no_man; + eval "${return_bad}"; +} # do_filearg() + + +######################################################################## +# do_nothing () +# +# Dummy function. +# +do_nothing() +{ + eval return "${_OK}"; +} + + +######################################################################## +# echo2 (*) +# +# Print to standard error with final line break. +# +# defined above + + +######################################################################## +# error (*) +# +# Print error message and exit with error code. +# +# defined above + + +######################################################################## +# exit_test () +# +# Test whether the former command ended with error(). Exit again. +# +# defined above + + +######################################################################## +# func_check ( "$@") +# +# Check number of arguments and register to _FUNC_STACK. +# +# Arguments: >=3 +# : name of the calling function. +# : a relational operator: = != < > <= >= +# : number of arguments to be checked against +# "$@": the arguments of the calling function. +# +# defined above + +######################################################################### +# func_pop () +# +# Delete the top element from the function call stack. +# +# defined above + + +######################################################################## +# func_push () +# +# Store another element to function call stack. +# +# defined above + + +######################################################################## +# func_stack_dump () +# +# Print the content of the stack. +# +# defined above + + +######################################################################## +# get_first_essential (*) +# +# Retrieve first non-empty argument. +# +# Return : `1' if all arguments are empty, `0' if found. +# Output : the retrieved non-empty argument. +# +# Variable prefix: gfe +# +get_first_essential() +{ + func_check get_first_essential '>=' 0 "$@"; + if is_equal "$#" 0 + then + eval "${return_ok}"; + fi; + for i + do + gfe_var="$i"; + if obj gfe_var is_not_empty + then + obj gfe_var echo1; + eval ${_UNSET} gfe_var; + eval "${return_ok}"; + fi; + done; + eval ${_UNSET} gfe_var; + eval "${return_bad}"; +} + + +######################################################################## +landmark '5: is_*()'; +######################################################################## + +######################################################################## +# is_dir () +# +# Test whether `name' is a directory. +# +# Arguments : 1 +# Return : `0' if arg1 is a directory, `1' otherwise. +# +is_dir() +{ + func_check is_dir '=' 1 "$@"; + if test _"$1"_ != __ && test -d "$1" && test -r "$1" + then + eval "${return_yes}"; + fi; + eval "${return_no}"; +} + + +######################################################################## +# is_empty () +# +# Test whether `string' is empty. +# +# Arguments : <=1 +# Return : `0' if arg1 is empty or does not exist, `1' otherwise. +# +is_empty() +{ + func_check is_empty '=' 1 "$@"; + if test _"$1"_ = __ + then + eval "${return_yes}"; + fi; + eval "${return_no}"; +} + + +######################################################################## +# is_equal ( ) +# +# Test whether `string1' is equal to . +# +# Arguments : 2 +# Return : `0' both arguments are equal strings, `1' otherwise. +# +is_equal() +{ + func_check is_equal '=' 2 "$@"; + if test _"$1"_ = _"$2"_ + then + eval "${return_yes}"; + fi; + eval "${return_no}"; +} + + +######################################################################## +# is_existing () +# +# Test whether `name' is an existing file or directory. Solaris 2.5 does +# not have `test -e'. +# +# Arguments : 1 +# Return : `0' if arg1 exists, `1' otherwise. +# +is_existing() +{ + func_check is_existing '=' 1 "$@"; + if test _"$1"_ = __ + then + eval "${return_no}"; + fi; + if test -f "$1" || test -d "$1" || test -c "$1" + then + eval "${return_yes}"; + fi; + eval "${return_no}"; +} + + +######################################################################## +# is_file () +# +# Test whether `name' is a readable file. +# +# Arguments : 1 +# Return : `0' if arg1 is a readable file, `1' otherwise. +# +is_file() +{ + func_check is_file '=' 1 "$@"; + if is_not_empty "$1" && test -f "$1" && test -r "$1" + then + eval "${return_yes}"; + fi; + 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_non_empty_file '=' 1 "$@"; + if is_file "$1" && test -s "$1" + then + eval "${return_yes}"; + fi; + eval "${return_no}"; +} + + +######################################################################## +# is_not_dir () +# +# Test whether `name' is not a readable directory. +# +# Arguments : 1 +# Return : `0' if arg1 is a directory, `1' otherwise. +# +is_not_dir() +{ + func_check is_not_dir '=' 1 "$@"; + if is_dir "$1" + then + eval "${return_no}"; + fi; + eval "${return_yes}"; +} + + +######################################################################## +# is_not_empty () +# +# Test whether `string' is not empty. +# +# Arguments : <=1 +# Return : `0' if arg1 exists and is not empty, `1' otherwise. +# +is_not_empty() +{ + func_check is_not_empty '=' 1 "$@"; + if is_empty "$1" + then + eval "${return_no}"; + fi; + eval "${return_yes}"; +} + + +######################################################################## +# is_not_equal ( ) +# +# Test whether `string1' differs from `string2'. +# +# Arguments : 2 +# +is_not_equal() +{ + func_check is_not_equal '=' 2 "$@"; + if is_equal "$1" "$2" + then + eval "${return_no}"; + fi + eval "${return_yes}"; +} + + +######################################################################## +# is_not_file () +# +# Test whether `name' is a not readable file. +# +# Arguments : 1 (empty allowed) +# +is_not_file() +{ + func_check is_not_file '=' 1 "$@"; + if is_file "$1" + then + eval "${return_no}"; + fi; + eval "${return_yes}"; +} + + +######################################################################## +# is_not_prog ([ [*]]) +# +# Verify that arg is a not program in $PATH. +# +# Arguments : >=0 (empty allowed) +# more args are ignored, this allows to specify progs with arguments +# +is_not_prog() +{ + func_check is_not_prog '>=' 0 "$@"; + case "$#" in + 0) + eval "${return_yes}"; + ;; + *) + if where_is "$1" >${_NULL_DEV} + then + eval "${return_no}"; + fi; + ;; + esac + 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}"; +} + + +######################################################################## +# is_not_X () +# +# Test whether not running in X Window by checking $DISPLAY +# +is_not_X() +{ + func_check is_X '=' 0 "$@"; + if obj DISPLAY is_empty + then + eval "${return_yes}"; + fi; + eval "${return_no}"; +} + + +######################################################################## +# is_not_yes () +# +# Test whether `string' is not "yes". +# +# Arguments : 1 +# +is_not_yes() +{ + func_check is_not_yes = 1 "$@"; + if is_yes "$1" + then + eval "${return_no}"; + fi; + eval "${return_yes}"; +} + + +######################################################################## +# is_prog ([ [*]]) +# +# Determine whether is a program in $PATH +# +# Arguments : >=0 (empty allowed) +# * are ignored, this allows to specify progs with arguments. +# +is_prog() +{ + func_check is_prog '>=' 0 "$@"; + case "$#" in + 0) + eval "${return_no}"; + ;; + *) + if where_is "$1" >${_NULL_DEV} + 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 _"$1"_ = __ + then + eval "${return_no}"; + fi; + if test -r "$1" + then + if test -w "$1" + then + eval "${return_yes}"; + fi; + fi; + eval "${return_no}"; +} + + +######################################################################## +# is_X () +# +# Test whether running in X Window by checking $DISPLAY +# +is_X() +{ + func_check is_X '=' 0 "$@"; + if obj DISPLAY is_not_empty + then + eval "${return_yes}"; + fi; + eval "${return_no}"; +} + + +######################################################################## +# is_yes () +# +# Test whether `string' has value "yes". +# +# Return : `0' if arg1 is `yes', `1' otherwise. +# +is_yes() +{ + func_check is_yes '=' 1 "$@"; + if is_equal "$1" 'yes' + then + eval "${return_yes}"; + fi; + eval "${return_no}"; +} + + +######################################################################## +# landmark () +# +# Print debugging information on standard error if $_DEBUG_LM is `yes'. +# +# Globals: $_DEBUG_LM +# +# Defined in section `Debugging functions'. + + +######################################################################## +# leave ([]) +# +# Clean exit without an error or with . +# +leave() +{ + clean_up; + if test $# = 0 + then + exit "${_OK}"; + else + exit "$1"; + fi; +} + + +######################################################################## +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 `eval set x "$list"; shift`. + + +######################################################################## +# list_append ( ...) +# +# Arguments: >=2 +# : a variable name for a list of single-quoted elements +# : some sequence of characters. +# Output: none, but $ is set to +# if is empty: "'' '...'" +# otherwise: "$list '' ..." +# +# Variable prefix: la +# +list_append() +{ + func_check list_append '>=' 2 "$@"; + la_name="$1"; + eval la_list='"${'$1'}"'; + shift; + for s + do + la_s="$s"; + case "${la_s}" in + *\'*) + # escape each single quote by replacing each + # "'" (squote) by "'\''" (squote bslash squote squote); + # note that the backslash must be doubled in the following `sed' + la_element="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')"; + exit_test; + ;; + '') + la_element=""; + ;; + *) + la_element="${la_s}"; + ;; + esac; + if obj la_list is_empty + then + la_list="'${la_element}'"; + else + la_list="${la_list} '${la_element}'"; + fi; + done; + eval "${la_name}"='"${la_list}"'; + eval ${_UNSET} la_element; + eval ${_UNSET} la_list; + eval ${_UNSET} la_name; + eval ${_UNSET} la_s; + eval "${return_ok}"; +} + + +######################################################################## +# list_from_cmdline ( [...]) +# +# Transform command line arguments into a normalized form. +# +# Options, option arguments, and file parameters are identified and +# output each as a single-quoted argument of its own. Options and +# file parameters are separated by a '--' argument. +# +# Arguments: >=1 +# : common part of a set of 4 environment variable names: +# $_SHORT_NA: list of short options without an arg. +# $_SHORT_ARG: list of short options that have an arg. +# $_LONG_NA: list of long options without an arg. +# $_LONG_ARG: list of long options that have an arg. +# ...: the arguments from a command line, such as "$@", +# the content of a variable, or direct arguments. +# +# Output: ['-[-]opt' ['optarg']]... '--' ['filename']... +# +# Example: +# list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2 +# If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are +# none-empty option lists, this will result in printing: +# '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2' +# +# Use this function in the following way: +# eval set x "$(args_norm PRE_NAME "$@")"; +# shift; +# while test "$1" != '--'; do +# case "$1" in +# ... +# esac; +# shift; +# done; +# shift; #skip '--' +# # all positional parameters ("$@") left are file name parameters. +# +# Variable prefix: lfc +# +list_from_cmdline() +{ + func_check list_from_cmdline '>=' 1 "$@"; + lfc_short_n="$(obj_data "$1"_SHORT_NA)"; # short options, no argument + lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument + lfc_long_n="$(obj_data "$1"_LONG_NA)"; # long options, no argument + lfc_long_a="$(obj_data "$1"_LONG_ARG)"; # long options, with argument + exit_test; + if obj lfc_short_n is_empty + then + error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.'; + fi; + if obj lfc_short_a is_empty + then + error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.'; + fi; + if obj lfc_long_n is_empty + then + error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.'; + fi; + if obj lfc_long_a is_empty + then + error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.'; + fi; + + shift; + if is_equal "$#" 0 + then + echo1 -- + eval ${_UNSET} lfc_fparams; + eval ${_UNSET} lfc_short_a; + eval ${_UNSET} lfc_short_n; + eval ${_UNSET} lfc_long_a; + eval ${_UNSET} lfc_long_n; + eval ${_UNSET} lfc_result; + eval "${return_ok}"; + fi; + + lfc_fparams=''; + lfc_result=''; + while test "$#" -ge 1 + do + lfc_arg="$1"; + shift; + case "${lfc_arg}" in + --) break; ;; + --*=*) + # delete leading '--'; + lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')"; + lfc_with_equal="${lfc_abbrev}"; + # extract option by deleting from the first '=' to the end + lfc_abbrev="$(echo1 "${lfc_with_equal}" | \ + sed -e 's/^\([^=]*\)=.*$/\1/')"; + lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")"; + exit_test; + if obj lfc_opt is_empty + then + error_user "--${lfc_abbrev} is not an option."; + else + # get the option argument by deleting up to first `=' + lfc_optarg="$(echo1 "${lfc_with_equal}" | sed -e 's/^[^=]*=//')"; + exit_test; + list_append lfc_result "--${lfc_opt}" "${lfc_optarg}"; + continue; + fi; + ;; + --*) + # delete leading '--'; + lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')"; + if list_has lfc_long_n "${lfc_abbrev}" + then + lfc_opt="${lfc_abbrev}"; + else + exit_test; + lfc_opt="$(list_single_from_abbrev lfc_long_n "${lfc_abbrev}")"; + exit_test; + if obj lfc_opt is_not_empty && is_not_equal "$#" 0 + then + a="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")"; + exit_test; + if obj a is_not_empty + then + error_user "The abbreviation ${lfc_arg} \ +has multiple options: --${lfc_opt} and --${a}."; + fi; + fi; + fi; + if obj lfc_opt is_not_empty + then + # long option, no argument + list_append lfc_result "--${lfc_opt}"; + continue; + fi; + lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")"; + exit_test; + if obj lfc_opt is_not_empty + then + # long option with argument + if test "$#" -le 0 + then + error_user "no argument for option --${lfc_opt}." + fi; + list_append lfc_result "--${lfc_opt}" "$1"; + shift; + continue; + fi; + error_user "${lfc_arg} is not an option."; + ;; + -?*) # short option (cluster) + # delete leading `-'; + lfc_rest="$(echo1 "${lfc_arg}" | sed -e 's/^-//')"; + exit_test; + while obj lfc_rest is_not_empty + do + # get next short option from cluster (first char of $lfc_rest) + lfc_optchar="$(echo1 "${lfc_rest}" | sed -e 's/^\(.\).*$/\1/')"; + # remove first character from ${lfc_rest}; + lfc_rest="$(echo1 "${lfc_rest}" | sed -e 's/^.//')"; + exit_test; + if list_has lfc_short_n "${lfc_optchar}" + then + list_append lfc_result "-${lfc_optchar}"; + continue; + elif list_has lfc_short_a "${lfc_optchar}" + then + if obj lfc_rest is_empty + then + if test "$#" -ge 1 + then + list_append lfc_result "-${lfc_optchar}" "$1"; + shift; + continue; + else + error_user "no argument for option -${lfc_optchar}."; + fi; + else # rest is the argument + list_append lfc_result "-${lfc_optchar}" "${lfc_rest}"; + lfc_rest=''; + continue; + fi; + else + error_user "unknown option -${lfc_optchar}."; + fi; + done; + ;; + *) + # Here, $lfc_arg is not an option, so a file parameter. + list_append lfc_fparams "${lfc_arg}"; + + # Ignore the strange POSIX option handling to end option + # parsing after the first file name argument. To reuse it, do + # a `break' here if $POSIXLY_CORRECT of `bash' is not empty. + # When `bash' is called as `sh' $POSIXLY_CORRECT is set + # automatically to `y'. + ;; + esac; + done; + list_append lfc_result '--'; + if obj lfc_fparams is_not_empty + then + lfc_result="${lfc_result} ${lfc_fparams}"; + fi; + if test "$#" -gt 0 + then + list_append lfc_result "$@"; + fi; + obj lfc_result echo1; + eval ${_UNSET} lfc_abbrev; + eval ${_UNSET} lfc_fparams; + eval ${_UNSET} lfc_short_a; + eval ${_UNSET} lfc_short_n; + eval ${_UNSET} lfc_long_a; + eval ${_UNSET} lfc_long_n; + eval ${_UNSET} lfc_result; + eval ${_UNSET} lfc_arg; + eval ${_UNSET} lfc_opt; + eval ${_UNSET} lfc_opt_arg; + eval ${_UNSET} lfc_opt_char; + eval ${_UNSET} lfc_with_equal; + eval ${_UNSET} lfc_rest; + eval "${return_ok}"; +} # list_from_cmdline() + + +######################################################################## +# list_from_split ( ) +# +# 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 list string +# +# Variable prefix: lfs +# +list_from_split() +{ + func_check list_from_split = 2 "$@"; + + # precede each space or tab by a backslash `\' (doubled for `sed') + lfs_s="$(echo1 "$1" | sed -e 's/\('"${_SPACE_SED}"'\)/\\\1/g')"; + exit_test; + + # replace split character of string by the list separator ` ' (space). + case "$2" in + /) # cannot use normal `sed' separator + echo1 "${lfs_s}" | sed -e 's|'"$2"'| |g'; + ;; + ?) # use normal `sed' separator + echo1 "${lfs_s}" | sed -e 's/'"$2"'/ /g'; + ;; + ??*) + error 'list_from_split(): separator must be a single character.'; + ;; + esac; + eval ${_UNSET} lfs_s; + eval "${return_ok}"; +} + + +######################################################################## +# 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. +# +# Variable prefix: lg +# +list_get() +{ + func_check list_get = 1 "$@"; + eval lg_list='"${'$1'}"'; + # remove leading and final space characters + lg_list="$(echo1 "${lg_list}" | sed -e ' +s/^'"${_SPACE_SED}"'*// +s/'"${_SPACE_SED}"'*$// +')"; + exit_test; + case "${lg_list}" in + '') + eval ${_UNSET} lg_list; + eval "${return_ok}"; + ;; + \'*\') + obj lg_list echo1; + eval ${_UNSET} lg_list; + eval "${return_ok}"; + ;; + *) + error "list_get(): bad list: $1" + ;; + esac; + eval ${_UNSET} lg_list; + eval "${return_ok}"; +} + + +######################################################################## +# list_has ( ) +# +# Test whether the list has the element . +# +# Arguments: 2 +# : a variable name for a list of single-quoted elements +# : some sequence of characters. +# +# Variable prefix: lh +# +list_has() +{ + func_check list_has = 2 "$@"; + eval lh_list='"${'$1'}"'; + if obj lh_list is_empty + then + eval "${_UNSET}" lh_list; + eval "${return_no}"; + fi; + case "$2" in + \'*\') lh_element=" $2 "; ;; + *) lh_element=" '$2' "; ;; + esac; + if string_contains " ${lh_list} " "${lh_element}" + then + eval "${_UNSET}" lh_list; + eval "${_UNSET}" lh_element; + eval "${return_yes}"; + else + eval "${_UNSET}" lh_list; + eval "${_UNSET}" lh_element; + eval "${return_no}"; + fi; +} + + +######################################################################## +# list_has_abbrev ( ) +# +# Test whether the list has an element starting with . +# +# Arguments: 2 +# : a variable name for a list of single-quoted elements +# : some sequence of characters. +# +# Variable prefix: lha +# +list_has_abbrev() +{ + func_check list_has_abbrev = 2 "$@"; + eval lha_list='"${'$1'}"'; + if obj lha_list is_empty + then + eval "${_UNSET}" lha_list; + eval "${return_no}"; + fi; + case "$2" in + \'*) + lha_element="$(echo1 "$2" | sed -e 's/'"${_SQ}"'$//')"; + exit_test; + ;; + *) lha_element="'$2"; ;; + esac; + if string_contains " ${lha_list}" " ${lha_element}" + then + eval "${_UNSET}" lha_list; + eval "${_UNSET}" lha_element; + eval "${return_yes}"; + else + eval "${_UNSET}" lha_list; + eval "${_UNSET}" lha_element; + eval "${return_no}"; + fi; + eval "${return_ok}"; +} + + +######################################################################## +# list_has_not ( ) +# +# Test whether has no . +# +# Arguments: 2 +# : a space-separated list of single-quoted elements. +# : some sequence of characters. +# +# Variable prefix: lhn +# +list_has_not() +{ + func_check list_has_not = 2 "$@"; + eval lhn_list='"${'$1'}"'; + if obj lhn_list is_empty + then + eval "${_UNSET}" lhn_list; + eval "${return_yes}"; + fi; + case "$2" in + \'*\') lhn_element=" $2 "; ;; + *) lhn_element=" '$2' "; ;; + esac; + if string_contains " ${lhn_list} " "${lhn_element}" + then + eval "${_UNSET}" lhn_list; + eval "${_UNSET}" lhn_element; + eval "${return_no}"; + else + eval "${_UNSET}" lhn_list; + eval "${_UNSET}" lhn_element; + eval "${return_yes}"; + fi; +} + + +######################################################################## +# list_single_from_abbrev ( ) +# +# Check whether the list has an element starting with . If +# there are more than a single element an error is created. +# +# Arguments: 2 +# : a variable name for a list of single-quoted elements +# : some sequence of characters. +# +# Output: the found element. +# +# Variable prefix: lsfa +# +list_single_from_abbrev() +{ + func_check list_single_from_abbrev = 2 "$@"; + eval lsfa_list='"${'$1'}"'; + if obj lsfa_list is_empty + then + eval "${_UNSET}" lsfa_list; + eval "${return_no}"; + fi; + lsfa_abbrev="$2"; + if list_has lsfa_list "${lsfa_abbrev}" + then + obj lsfa_abbrev echo1; + eval "${_UNSET}" lsfa_abbrev; + eval "${_UNSET}" lsfa_list; + eval "${return_yes}"; + fi; + if list_has_abbrev lsfa_list "${lsfa_abbrev}" + then + lsfa_element=''; + eval set x "${lsfa_list}"; + shift; + for i + do + case "$i" in + ${lsfa_abbrev}*) + if obj lsfa_element is_not_empty + then + error_user "The abbreviation --${lsfa_abbrev} \ +has multiple options: --${lsfa_element} and --${i}."; + fi; + lsfa_element="$i"; + ;; + esac; + done; + obj lsfa_element echo1; + eval "${_UNSET}" lsfa_abbrev; + eval "${_UNSET}" lsfa_element; + eval "${_UNSET}" lsfa_list; + eval "${return_yes}"; + else + eval "${_UNSET}" lsfa_abbrev; + eval "${_UNSET}" lsfa_element; + eval "${_UNSET}" lsfa_list; + eval "${return_no}"; + fi; +} + + +######################################################################## +landmark '7: man_*()'; +######################################################################## + +######################################################################## +# man_do_filespec () +# +# Print suitable man page(s) for filespec to $_TMP_CAT. +# +# Arguments : 2 +# : argument of the form `man:name.section', `man:name', +# `man:name(section)', `name.section', `name'. +# +# Globals : $_OPT_ALL +# +# Output : none. +# Return : `0' if man page was found, `1' else. +# +# Only called from do_fileargs(), checks on $MANPATH and $_MAN_ENABLE +# are assumed (see man_setup()). +# +# Variable prefix: mdf +# +man_do_filespec() +{ + func_check man_do_filespec = 1 "$@"; + if obj _MAN_PATH is_empty + then + eval "${return_bad}"; + fi; + if is_empty "$1" + then + eval "${return_bad}"; + fi; + mdf_spec="$1"; + mdf_name=''; + mdf_section=''; + case "${mdf_spec}" in + */*) # not a man spec with containing '/' + eval ${_UNSET} mdf_got_one; + eval ${_UNSET} mdf_name; + eval ${_UNSET} mdf_section; + eval ${_UNSET} mdf_spec; + eval "${return_bad}"; + ;; + man:?*\(?*\)) # man:name(section) + mdf_name="$(echo1 "${mdf_spec}" \ + | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')"; + mdf_section="$(echo1 "${mdf_spec}" \ + | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')"; + exit_test; + ;; + man:?*.${_MAN_AUTO_SEC_CHARS}) # man:name.section + mdf_name="$(echo1 "${mdf_spec}" \ + | sed -e 's/^man:\(..*\)\..$/\1/')"; + mdf_section="$(echo1 "${mdf_spec}" \ + | sed -e 's/^.*\(.\)$/\1/')"; + exit_test; + ;; + man:?*) # man:name + mdf_name="$(echo1 "${mdf_spec}" | sed -e 's/^man://')"; + exit_test; + ;; + ?*\(?*\)) # name(section) + mdf_name="$(echo1 "${mdf_spec}" \ + | sed -e 's/^\(..*\)(\(..*\))$/\1/')"; + mdf_section="$(echo1 "${mdf_spec}" \ + | sed -e 's/^\(..*\)(\(..*\))$/\2/')"; + exit_test; + ;; + ?*.${_MAN_AUTO_SEC_CHARS}) # name.section + mdf_name="$(echo1 "${mdf_spec}" \ + | sed -e 's/^\(..*\)\..$/\1/')"; + mdf_section="$(echo1 "${mdf_spec}" \ + | sed -e 's/^.*\(.\)$/\1/')"; + exit_test; + ;; + ?*) + mdf_name="${mdf_spec}"; + ;; + esac; + if obj mdf_name is_empty + then + eval ${_UNSET} mdf_got_one; + eval ${_UNSET} mdf_name; + eval ${_UNSET} mdf_section; + eval ${_UNSET} mdf_spec; + eval "${return_bad}"; + fi; + mdf_got_one='no'; + if obj mdf_section is_empty + then + if obj _OPT_SECTIONS is_empty + then + eval set x "${_MAN_AUTO_SEC_LIST}"; + else + # use --sections when no section is given to filespec + eval set x "$(echo1 "${_OPT_SECTIONS}" | sed -e 's/:/ /g')"; + fi; + shift; + for s + do + mdf_s="$s"; + if man_search_section "${mdf_name}" "${mdf_s}" + then # found + if obj _MAN_ALL is_yes + then + mdf_got_one='yes'; + else + eval ${_UNSET} mdf_got_one; + eval ${_UNSET} mdf_name; + eval ${_UNSET} mdf_s; + eval ${_UNSET} mdf_section; + eval ${_UNSET} mdf_spec; + eval "${return_good}"; + fi; + fi; + done; + else + if man_search_section "${mdf_name}" "${mdf_section}" + then + eval ${_UNSET} mdf_got_one; + eval ${_UNSET} mdf_name; + eval ${_UNSET} mdf_s; + eval ${_UNSET} mdf_section; + eval ${_UNSET} mdf_spec; + eval "${return_good}"; + else + eval ${_UNSET} mdf_got_one; + eval ${_UNSET} mdf_name; + eval ${_UNSET} mdf_section; + eval ${_UNSET} mdf_spec; + eval "${return_bad}"; + fi; + fi; + if obj _MAN_ALL is_yes && obj mdf_got_one is_yes + then + eval ${_UNSET} mdf_got_one; + eval ${_UNSET} mdf_name; + eval ${_UNSET} mdf_s; + eval ${_UNSET} mdf_section; + eval ${_UNSET} mdf_spec; + eval "${return_good}"; + fi; + eval ${_UNSET} mdf_got_one; + eval ${_UNSET} mdf_name; + eval ${_UNSET} mdf_s; + eval ${_UNSET} mdf_section; + eval ${_UNSET} mdf_spec; + eval "${return_bad}"; +} # man_do_filespec() + + +######################################################################## +# man_register_file ( [
]) +# +# Write a found man page file and register the title element. +# +# Arguments: 1, 2, or 3; maybe empty +# Output: none +# +man_register_file() +{ + func_check man_register_file '>=' 2 "$@"; + case "$#" in + 2|3) do_nothing; ;; + *) + error "man_register_file() expects 2 or 3 arguments."; + ;; + esac; + if is_empty "$1" + then + error 'man_register_file(): file name is empty'; + fi; + to_tmp "$1"; + case "$#" in + 2) + register_title "man:$2"; + eval "${return_ok}"; + ;; + 3) + register_title "$2.$3"; + eval "${return_ok}"; + ;; + esac; + eval "${return_ok}"; +} + + +######################################################################## +# man_search_section (
) +# +# Retrieve man pages. +# +# Arguments : 2 +# Globals : $_MAN_PATH, $_MAN_EXT +# Return : 0 if found, 1 otherwise +# +# Variable prefix: mss +# +man_search_section() +{ + func_check man_search_section = 2 "$@"; + if obj _MAN_PATH is_empty + then + eval "${return_bad}"; + fi; + if is_empty "$1" + then + eval "${return_bad}"; + fi; + if is_empty "$2" + then + eval "${return_bad}"; + fi; + mss_name="$1"; + mss_section="$2"; + eval set x "$(path_split "${_MAN_PATH}")"; + exit_test; + shift; + mss_got_one='no'; + if obj _MAN_EXT is_empty + then + for d + do + mss_dir="$(dirname_append "$d" "man${mss_section}")"; + exit_test; + if obj mss_dir is_dir + then + mss_prefix="$(\ + dirname_append "${mss_dir}" "${mss_name}.${mss_section}")"; + if obj _OPT_WHATIS is_yes + then + mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} | + sed -e '\| found|s|.*||' + )"; + else + mss_files="$(eval ls "'${mss_prefix}'"'*' 2>${_NULL_DEV} | + sed -e '\| found|s|.*||' + )"; + fi; + exit_test; + if obj mss_files is_not_empty + then + # for f in $mss_files + for f in $(eval set x ${mss_files}; shift; echo1 "$@") + do + exit_test; + mss_f="$f"; + if obj mss_f is_file + then + if is_yes "${mss_got_one}" + then + register_file "${mss_f}"; + elif obj _MAN_ALL is_yes + then + man_register_file "${mss_f}" "${mss_name}"; + else + man_register_file "${mss_f}" "${mss_name}" "${mss_section}"; + eval ${_UNSET} mss_dir; + eval ${_UNSET} mss_ext; + eval ${_UNSET} mss_f; + eval ${_UNSET} mss_files; + eval ${_UNSET} mss_got_one; + eval ${_UNSET} mss_name; + eval ${_UNSET} mss_prefix; + eval ${_UNSET} mss_section; + eval "${return_good}"; + fi; + mss_got_one='yes'; + fi; + done; + fi; + fi; + done; + else + mss_ext="${_MAN_EXT}"; + # check for directory name having trailing extension + for d + do + mss_dir="$(dirname_append $d man${mss_section}${mss_ext})"; + exit_test; + if obj mss_dir is_dir + then + mss_prefix=\ + "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")"; + mss_files="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} | + sed -e '\|not found|s|.*||' + )"; + exit_test; + if obj mss_files is_not_empty + then + # for f in $mss_files + for f in $(eval set x ${mss_files}; shift; echo1 "$@") + do + mss_f="$f"; + if obj mss_f is_file + then + if is_yes "${mss_got_one}" + then + register_file "${mss_f}"; + elif obj _MAN_ALL is_yes + then + man_register_file "${mss_f}" "${mss_name}"; + else + man_register_file "${mss_f}" "${mss_name}" "${mss_section}"; + eval ${_UNSET} mss_dir; + eval ${_UNSET} mss_ext; + eval ${_UNSET} mss_f; + eval ${_UNSET} mss_files; + eval ${_UNSET} mss_got_one; + eval ${_UNSET} mss_name; + eval ${_UNSET} mss_prefix; + eval ${_UNSET} mss_section; + eval "${return_good}"; + fi; + mss_got_one='yes'; + fi; + done; + fi; + fi; + done; + # check for files with extension in directories without extension + for d + do + mss_dir="$(dirname_append "$d" "man${mss_section}")"; + exit_test; + if obj mss_dir is_dir + then + mss_prefix="$(dirname_append "${mss_dir}" \ + "${mss_name}.${mss_section}${mss_ext}")"; + mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} | + sed -e '\|not found|s|.*||' + )"; + exit_test; + if obj mss_files is_not_empty + then + # for f in $mss_files + for f in $(eval set x ${mss_files}; shift; echo1 "$@") + do + mss_f="$f"; + if obj mss_f is_file + then + if is_yes "${mss_got_one}" + then + register_file "${mss_f}"; + elif obj _MAN_ALL is_yes + then + man_register_file "${mss_f}" "${mss_name}"; + else + man_register_file "${mss_f}" "${mss_name}" "${mss_section}"; + eval ${_UNSET} mss_dir; + eval ${_UNSET} mss_ext; + eval ${_UNSET} mss_f; + eval ${_UNSET} mss_files; + eval ${_UNSET} mss_got_one; + eval ${_UNSET} mss_name; + eval ${_UNSET} mss_prefix; + eval ${_UNSET} mss_section; + eval "${return_good}"; + fi; + mss_got_one='yes'; + fi; + done; + fi; + fi; + done; + fi; + if obj _MAN_ALL is_yes && is_yes "${mss_got_one}" + then + eval ${_UNSET} mss_dir; + eval ${_UNSET} mss_ext; + eval ${_UNSET} mss_f; + eval ${_UNSET} mss_files; + eval ${_UNSET} mss_got_one; + eval ${_UNSET} mss_name; + eval ${_UNSET} mss_prefix; + eval ${_UNSET} mss_section; + eval "${return_good}"; + fi; + eval ${_UNSET} mss_dir; + eval ${_UNSET} mss_ext; + eval ${_UNSET} mss_f; + eval ${_UNSET} mss_files; + eval ${_UNSET} mss_got_one; + eval ${_UNSET} mss_name; + eval ${_UNSET} mss_prefix; + eval ${_UNSET} mss_section; + eval "${return_bad}"; +} # man_search_section() + + +######################################################################## +# man_setup () +# +# Setup the variables $_MAN_* needed for man page searching. +# +# Globals: +# in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL, +# $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT. +# out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2, +# $_MAN_SEC, $_MAN_ALL +# in/out: $_MAN_ENABLE +# +# The precedence for the variables related to `man' is that of GNU +# `man', i.e. +# +# $LANG; overridden by +# $LC_MESSAGES; overridden by +# $LC_ALL; this has the same precedence as +# $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by +# $MANOPT; overridden by +# the groffer command line options. +# +# Variable prefix: ms +# +man_setup() +{ + func_check main_man_setup = 0 "$@"; + + if obj _MAN_IS_SETUP is_yes + then + eval "${return_ok}"; + fi; + _MAN_IS_SETUP='yes'; + + 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}")"; + exit_test; + if obj _MAN_PATH is_empty + then + manpath_set_from_path; + else + _MAN_PATH="$(path_clean "${_MAN_PATH}")"; + exit_test; + fi; + if obj _MAN_PATH is_empty + then + if is_prog 'manpath' + then + _MAN_PATH="$(manpath 2>${_NULL_DEV})"; # not always available + exit_test; + 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}")"; + exit_test; + if obj _MAN_ALL is_empty + then + _MAN_ALL='no'; + fi; + + _MAN_SYS="$(get_first_essential \ + "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")"; + ms_lang="$(get_first_essential \ + "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")"; + exit_test; + case "${ms_lang}" in + C|POSIX) + _MAN_LANG=""; + _MAN_LANG2=""; + ;; + ?) + _MAN_LANG="${ms_lang}"; + _MAN_LANG2=""; + ;; + *) + _MAN_LANG="${ms_lang}"; + # get first two characters of $ms_lang + _MAN_LANG2="$(echo1 "${ms_lang}" | sed -e 's/^\(..\).*$/\1/')"; + exit_test; + ;; + esac; + # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*. + + manpath_add_lang_sys; # this is very slow + + _MAN_SEC="$(get_first_essential \ + "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")"; + exit_test; + if obj _MAN_PATH is_empty + then + _MAN_ENABLE="no"; + eval ${_UNSET} ms_lang; + eval "${return_ok}"; + fi; + + _MAN_EXT="$(get_first_essential \ + "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")"; + exit_test; + eval ${_UNSET} ms_lang; + eval "${return_ok}"; +} # man_setup() + + +######################################################################## +landmark '8: manpath_*()'; +######################################################################## + +######################################################################## +# manpath_add_lang_sys () +# +# Add language and operating system specific directories to man path. +# +# Arguments : 0 +# Output : none +# Globals: +# in: $_MAN_SYS: has the form `os1,os2,...', a comma separated +# list of names of operating systems. +# $_MAN_LANG and $_MAN_LANG2: each a single name +# in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon +# separated list of directories. +# +# Variable prefix: mals +# +manpath_add_lang_sys() +{ + func_check manpath_add_lang_sys = 0 "$@"; + if obj _MAN_PATH is_empty + then + eval "${return_ok}"; + fi; + # twice test both sys and lang + eval set x "$(path_split "${_MAN_PATH}")"; + shift; + exit_test; + mals_mp=''; + for p + do # loop on man path directories + mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")"; + exit_test; + done; + eval set x "$(path_split "${mals_mp}")"; + shift; + exit_test; + for p + do # loop on man path directories + mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")"; + exit_test; + done; + _MAN_PATH="$(path_chop "${mals_mp}")"; + exit_test; + eval ${_UNSET} mals_mp; + eval "${return_ok}"; +} + + +# To the directory in $1 append existing sys/lang subdirectories +# Function is necessary to split the OS list. +# +# globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2 +# argument: 2: `man_path' and `dir' +# output: colon-separated path of the retrieved subdirectories +# +# Variable prefix: _mals +# +_manpath_add_lang_sys_single() +{ + func_check _manpath_add_lang_sys_single = 2 "$@"; + _mals_res="$1"; + _mals_parent="$2"; + eval set x "$(list_from_split "${_MAN_SYS}" ',')"; + shift; + exit_test; + for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}" + do + _mals_dir="$(dirname_append "${_mals_parent}" "$d")"; + exit_test; + if obj _mals_res path_not_contains "${_mals_dir}" && \ + obj _mals_dir is_dir + then + _mals_res="${_mals_res}:${_mals_dir}"; + fi; + done; + if path_not_contains "${_mals_res}" "${_mals_parent}" + then + _mals_res="${_mals_res}:${_mals_parent}"; + fi; + path_chop "${_mals_res}"; + eval ${_UNSET} _mals_dir; + eval ${_UNSET} _mals_parent; + eval ${_UNSET} _mals_res; + eval "${return_ok}"; +} + +# end manpath_add_lang_sys () + + +######################################################################## +# manpath_set_from_path () +# +# Determine basic search path for man pages from $PATH. +# +# Return: `0' if a valid man path was retrieved. +# Output: none +# Globals: +# in: $PATH +# out: $_MAN_PATH +# +# Variable prefix: msfp +# +manpath_set_from_path() +{ + func_check manpath_set_from_path = 0 "$@"; + + msfp_manpath=''; + + # get a basic man path from $PATH + if obj PATH is_not_empty + then + eval set x "$(path_split "${PATH}")"; + shift; + exit_test; + for d + do + # delete the final `/bin' part + msfp_base="$(echo1 "$d" | sed -e 's|//*bin/*$||')"; + exit_test; + for e in /share/man /man + do + msfp_mandir="${msfp_base}$e"; + if test -d "${msfp_mandir}" && test -r "${msfp_mandir}" + then + msfp_manpath="${msfp_manpath}:${msfp_mandir}"; + fi; + done; + done; + fi; + + # append some default directories + for d in /usr/local/share/man /usr/local/man \ + /usr/share/man /usr/man \ + /usr/X11R6/man /usr/openwin/man \ + /opt/share/man /opt/man \ + /opt/gnome/man /opt/kde/man + do + msfp_d="$d"; + if obj msfp_manpath path_not_contains "${msfp_d}" && obj mfsp_d is_dir + then + msfp_manpath="${msfp_manpath}:${mfsp_d}"; + fi; + done; + + _MAN_PATH="${msfp_manpath}"; + eval ${_UNSET} msfp_base; + eval ${_UNSET} msfp_d; + eval ${_UNSET} msfp_mandir; + eval ${_UNSET} msfp_manpath; + eval "${return_ok}"; +} # manpath_set_from_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 +# +# Variable prefix: o +# +obj() +{ + func_check obj '>=' 2 "$@"; + eval o_arg1='"${'$1'}"'; + if is_empty "$2" + then + error "obj(): function name is empty." + else + o_func="$2"; + fi; + shift; + shift; + eval "${o_func}"' "${o_arg1}" "$@"'; + n="$?"; + eval ${_UNSET} o_arg1; + eval ${_UNSET} o_func; + eval "${return_var} $n"; +} # obj() + + +######################################################################## +# obj_data () +# +# Print the data of , i.e. the content of $. +# For possible later extensions. +# +# Arguments: 1 +# : a variable name +# Output: the data of +# +# Variable prefix: od +# +obj_data() +{ + func_check obj '=' 1 "$@"; + if is_empty "$1" + then + error "obj_data(): object name is empty." + fi; + eval od_res='"${'$1'}"'; + obj od_res echo1; + eval ${_UNSET} od_res; + eval "${return_ok}"; +} + + +######################################################################## +# 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 +# +# Variable prefix: ofo +# +obj_from_output() +{ + func_check obj_from_output '>=' 2 "$@"; + if is_empty "$1" + then + error "res(): variable name is empty."; + elif is_empty "$2" + then + error "res(): function name is empty." + else + ofo_result_name="$1"; + fi; + shift; + eval "${ofo_result_name}"'="$('"$@"')"'; + exit_test; + eval "${return_ok}"; +} + + +######################################################################## +# 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"'; + eval "${return_ok}"; +} + + +######################################################################## +# path_chop () +# +# Remove unnecessary colons from path. +# +# Argument: 1, a colon separated path. +# Output: path without leading, double, or trailing colons. +# +path_chop() +{ + func_check path_chop = 1 "$@"; + + # replace multiple colons by a single colon `:' + # remove leading and trailing colons + echo1 "$1" | sed -e ' +s/^:*// +s/:::*/:/g +s/:*$// +'; + eval "${return_ok}"; +} + + +######################################################################## +# path_clean () +# +# Remove non-existing directories from a colon-separated list. +# +# Argument: 1, a colon separated path. +# Output: colon-separated list of existing directories. +# +# Variable prefix: pc +# +path_clean() +{ + func_check path_clean = 1 "$@"; + if is_not_equal "$#" 1 + then + error 'path_clean() needs 1 argument.'; + fi; + pc_arg="$1"; + eval set x "$(path_split "${pc_arg}")"; + exit_test; + shift; + pc_res=""; + for i + do + pc_i="$i"; + if obj pc_i is_not_empty \ + && obj pc_res path_not_contains "${pc_i}" \ + && obj pc_i is_dir + then + case "${pc_i}" in + ?*/) + pc_res="${pc_res}$(dirname_chop "${pc_i}")"; + exit_test; + ;; + *) + pc_res="${pc_res}:${pc_i}"; + exit_test; + ;; + esac; + fi; + done; + eval ${_UNSET} pc_arg; + eval ${_UNSET} pc_i; + eval ${_UNSET} pc_res; + if path_chop "${pc_res}" + then + eval "${return_ok}"; + else + eval "${return_bad}"; + fi; +} + + +######################################################################## +# path_contains ( ) +#- +# Test whether `dir' is contained in `path', a list separated by `:'. +# +# Arguments : 2 arguments. +# Return : `0' if arg2 is substring of arg1, `1' otherwise. +# +path_contains() +{ + func_check path_contains = 2 "$@"; + case ":$1:" in + *":$2:"*) + eval "${return_yes}"; + ;; + *) + eval "${return_no}"; + ;; + esac; + eval "${return_ok}"; +} + + +######################################################################## +# path_not_contains ( ) +# +# Test whether `dir' is not contained in colon separated `path'. +# +# Arguments : 2 arguments. +# +path_not_contains() +{ + func_check path_not_contains = 2 "$@"; + if path_contains "$1" "$2" + then + eval "${return_no}"; + else + eval "${return_yes}"; + fi; + eval "${return_ok}"; +} + + +######################################################################## +# path_split () +# +# In `path' escape white space and replace each colon by a space. +# +# Arguments: 1: a colon-separated path +# Output: the resulting list, process with `eval set' +# +path_split() +{ + func_check path_split = 1 "$@"; + list_from_split "$1" ':'; + eval "${return_ok}"; +} + + +######################################################################## +landmark '10: register_*()'; +######################################################################## + +######################################################################## +# register_file () +# +# Write a found file and register the title element. +# +# Arguments: 1: a file name +# Output: none +# +register_file() +{ + func_check register_file = 1 "$@"; + if is_empty "$1" + then + error 'register_file(): file name is empty'; + fi; + if is_equal "$1" '-' + then + to_tmp "${_TMP_STDIN}"; + register_title 'stdin'; + else + to_tmp "$1"; + register_title "$(base_name "$1")"; + exit_test; + fi; + eval "${return_ok}"; +} # register_file() + + +######################################################################## +# register_title () +# +# Create title element from and append to $_REGISTERED_TITLE +# +# Globals: $_REGISTERED_TITLE (rw) +# +# Variable prefix: rt +# +register_title() +{ + func_check register_title '=' 1 "$@"; + if is_empty "$1" + then + eval "${return_ok}"; + fi; + + case "${_REGISTERED_TITLE}" in + *\ *\ *\ *) + eval "${return_ok}"; + ;; + esac; + + # remove directory part + rt_title="$(base_name "$1")"; + # replace space characters by `_' + rt_title="$(echo1 "${rt_title}" | sed -e 's/[ ]/_/g')"; + # remove extension `.bz2' + rt_title="$(echo1 "${rt_title}" | sed -e 's/\.bz2$//')"; + # remove extension `.gz' + rt_title="$(echo1 "${rt_title}" | sed -e 's/\.gz$//')"; + # remove extension `.Z' + rt_title="$(echo1 "${rt_title}" | sed -e 's/\.Z$//')"; + exit_test; + + if obj rt_title is_empty + then + eval ${_UNSET} rt_title; + eval "${return_ok}"; + fi; + if obj _REGISTERED_TITLE is_empty + then + _REGISTERED_TITLE="${rt_title}"; + else + _REGISTERED_TITLE="${_REGISTERED_TITLE} ${rt_title}"; + fi; + eval ${_UNSET} rt_title; + eval "${return_ok}"; +} # register_title() + + +######################################################################## +# reset () +# +# Reset the variables that can be affected by options to their default. +# +# +# Defined in section `Preset' after the rudimentary shell tests. + + +######################################################################## +# rm_file () +# +# Remove file if $_DEBUG_KEEP_FILES allows it. +# +# Globals: $_DEBUG_KEEP_FILES +# +rm_file() +{ + func_check rm_file '=' 1 "$@"; + if is_file "$1" + then + rm -f "$1" >${_NULL_DEV} 2>&1; + fi; + if is_existing "$1" + then + eval "${return_bad}"; + else + eval "${return_good}"; + fi; +} + + +######################################################################## +# rm_file_with_debug () +# +# Remove file if $_DEBUG_KEEP_FILES allows it. +# +# Globals: $_DEBUG_KEEP_FILES +# +rm_file_with_debug() +{ + func_check rm_file_with_debug '=' 1 "$@"; + if obj _DEBUG_KEEP_FILES is_not_yes + then + if is_file "$1" + then + rm -f "$1" >${_NULL_DEV} 2>&1; + fi; + fi; + if is_existing "$1" + then + eval "${return_bad}"; + else + eval "${return_good}"; + fi; +} + + +######################################################################## +# rm_tree () +# +# Remove file if $_DEBUG_KEEP_FILES allows it. +# +# Globals: $_DEBUG_KEEP_FILES +# +rm_tree() +{ + func_check rm_tree '=' 1 "$@"; + if is_existing "$1" + then + rm -f -r "$1" >${_NULL_DEV} 2>&1; + fi; + if is_existing "$1" + then + eval "${return_bad}"; + else + eval "${return_good}"; + fi; +} + + +######################################################################## +# save_stdin () +# +# Store standard input to temporary file (with decompression). +# +# Variable prefix: ss +# +if obj _HAS_COMPRESSION is_yes +then + save_stdin() + { + func_check save_stdin '=' 0 "$@"; + ss_f="${_TMP_DIR}"/INPUT; + cat >"${ss_f}"; + cat_z "${ss_f}" >"${_TMP_STDIN}"; + rm_file "${ss_f}"; + eval ${_UNSET} ss_f; + eval "${return_ok}"; + } +else + save_stdin() + { + func_check save_stdin = 0 "$@"; + cat >"${_TMP_STDIN}"; + eval "${return_ok}"; + } +fi; + + +######################################################################## +# special_filespec () +# +# Handle special modes like whatis and apropos. +# +special_filespec() +{ + func_check special_setup '=' 0 "$@"; + if obj _OPT_APROPOS is_yes + then + if obj _OPT_WHATIS is_yes + then + error \ + 'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"'; + fi; + apropos_filespec; + eval "${return_ok}"; + fi; + if obj _OPT_WHATIS is_yes + then + whatis_filespec; + fi; + eval "${return_ok}"; +} + + +######################################################################## +# special_setup () +# +# Handle special modes like whatis and apropos. +# +special_setup() +{ + func_check special_setup '=' 0 "$@"; + if obj _OPT_APROPOS is_yes + then + if obj _OPT_WHATIS is_yes + then + error \ + 'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"'; + fi; + apropos_setup; + eval "${return_ok}"; + fi; + if obj _OPT_WHATIS is_yes + then + whatis_header; + fi; + eval "${return_ok}"; +} + + +######################################################################## +landmark '11: stack_*()'; +######################################################################## + +######################################################################## +# string_contains ( ) +# +# Test whether `part' is contained in `string'. +# +# Arguments : 2 text arguments. +# Return : `0' if arg2 is substring of arg1, `1' otherwise. +# +string_contains() +{ + func_check string_contains '=' 2 "$@"; + case "$1" in + *"$2"*) + eval "${return_yes}"; + ;; + *) + eval "${return_no}"; + ;; + esac; + eval "${return_ok}"; +} + + +######################################################################## +# string_not_contains ( ) +# +# Test whether `part' is not substring of `string'. +# +# Arguments : 2 text arguments. +# Return : `0' if arg2 is substring of arg1, `1' otherwise. +# +string_not_contains() +{ + func_check string_not_contains '=' 2 "$@"; + if string_contains "$1" "$2" + then + eval "${return_no}"; + else + eval "${return_yes}"; + fi; + eval "${return_ok}"; +} + + +######################################################################## +landmark '12: tmp_*()'; +######################################################################## + +######################################################################## +# tmp_cat () +# +# output the temporary cat file (the concatenation of all input) +# +tmp_cat() +{ + func_check tmp_cat '=' 0 "$@"; + cat "${_TMP_CAT}"; + eval "${return_var}" "$?"; +} + + +######################################################################## +# tmp_create (?) +# +# Create temporary file. +# +# It's safe to use the shell process ID together with a suffix to +# have multiple temporary files. +# +# Globals: $_TMP_DIR +# +# Output : name of created file +# +# Variable prefix: tc +# +tmp_create() +{ + func_check tmp_create '<=' 1 "$@"; + # the output file does not have `,' as first character, so these are + # different names from the output file. + tc_tmp="${_TMP_DIR}/,$1"; + : >"${tc_tmp}" + obj tc_tmp echo1; + eval ${_UNSET} tc_tmp; + eval "${return_ok}"; +} + + +######################################################################## +# to_tmp () +# +# print file (decompressed) to the temporary cat file +# +to_tmp() +{ + func_check to_tmp '=' 1 "$@"; + if obj _TMP_CAT is_empty + then + error 'to_tmp_line: $_TMP_CAT is not yet set'; + fi; + if is_file "$1" + then + if obj _OPT_LOCATION is_yes + then + echo2 "$1"; + fi; + if obj _OPT_WHATIS is_yes + then + whatis_filename "$1" >>"${_TMP_CAT}"; + else + cat_z "$1" >>"${_TMP_CAT}"; + fi; + else + error "to_tmp(): could not read file \`$1'."; + fi; + eval "${return_ok}"; +} + + +######################################################################## +# to_tmp_line ([]) +# +# print line to the temporary cat file +# +to_tmp_line() +{ + func_check to_tmp '>=' 0 "$@"; + if obj _TMP_CAT is_empty + then + error 'to_tmp_line: $_TMP_CAT is not yet set'; + fi; + echo1 "$*" >>"${_TMP_CAT}"; + eval "${return_ok}"; +} + + +######################################################################## +# trap_set +# +# call function on signal 0 +# +trap_set() +{ + func_check trap_set '=' 0 "$@"; + trap 'clean_up' 0 2>${_NULL_DEV} || :; + eval "${return_ok}"; +} + + +######################################################################## +# trap_unset () +# +# disable trap on signal 0. +# +trap_unset() +{ + func_check trap_unset '=' 0 "$@"; + trap '' 0 2>${_NULL_DEV} || :; + eval "${return_ok}"; +} + + +######################################################################## +# usage () +# +# print usage information to stderr; for groffer option --help. +# +usage() +{ + func_check usage = 0 "$@"; + echo; + version; + echo1 'Usage: groffer [option]... [filespec]...'; + cat <&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /'; + eval "${return_ok}"; +} + + +######################################################################## +# warning () +# +# Print warning to stderr +# +warning() +{ + echo2 "warning: $*"; +} + + +######################################################################## +# whatis_filename () +# +# Interpret as a man page and display its `whatis' +# information as a fragment written in the groff language. +# +# Variable prefix: wf +# +whatis_filename() +{ + func_check whatis_filename = 1 "$@"; + wf_arg="$1"; + if obj wf_arg is_not_file + then + error "whatis_filename(): argument is not a readable file." + fi; + wf_dot='^\.'"${_SPACE_SED}"'*'; + if obj _FILESPEC_ARG is_equal '-' + then + wf_arg='stdin'; + fi; + cat <) +# +# Output path of a program if in $PATH. +# +# Arguments : >=1 (empty allowed) +# more args are ignored, this allows to specify progs with arguments +# Return : `0' if arg1 is a program in $PATH, `1' otherwise. +# +# Variable prefix: w +# +where_is() +{ + func_check where_is '>=' 1 "$@"; + w_arg="$1"; + if obj w_arg is_empty + then + eval ${_UNSET} w_arg; + eval "${return_bad}"; + fi; + case "${w_arg}" in + /*) + eval ${_UNSET} w_arg; + eval ${_UNSET} w_file; + if test -f "${w_arg}" && test -x "${w_arg}" + then + eval "${return_ok}"; + else + eval "${return_bad}"; + fi; + ;; + esac; + eval set x "$(path_split "${PATH}")"; + exit_test; + shift; + for p + do + case "$p" in + */) w_file=${p}${w_arg}; ;; + *) w_file=${p}/${w_arg}; ;; + esac; + if test -f "${w_file}" && test -x "${w_file}" + then + obj w_file echo1; + eval ${_UNSET} w_arg; + eval ${_UNSET} w_file; + eval "${return_ok}"; + fi; + done; + eval ${_UNSET} w_arg; + eval ${_UNSET} w_file; + eval "${return_bad}"; +} + + +######################################################################## +# main* Functions +######################################################################## + +# The main area contains the following parts: +# - main_init(): initialize temporary files and set exit trap +# - main_parse_MANOPT(): parse $MANOPT +# - main_parse_args(): argument parsing +# - main_set_mode (): determine the display mode +# - main_do_fileargs(): process filespec arguments +# - main_set_resources(): setup X resources +# - main_display(): do the displaying +# - main(): the main function that calls all main_*() + + +####################################################################### +# main_init () +# +# set exit trap and create temporary files +# +# Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN +# +# Variable prefix: mi +# +main_init() +{ + func_check main_init = 0 "$@"; + # call clean_up() on shell termination. + trap_set; + + # create temporary directory + umask 0022; + _TMP_DIR=''; + for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \ + "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.' + do + mi_dir="$d"; + if obj mi_dir is_empty || obj mi_dir is_not_dir || \ + obj mi_dir is_not_writable + then + continue; + fi; + + case "${mi_dir}" in + */) + _TMP_DIR="${mi_dir}"; + ;; + *) + _TMP_DIR="${mi_dir}"'/'; + ;; + esac; + _TMP_DIR="${_TMP_DIR}groffer${_PROCESS_ID}"; + if obj _TMP_DIR rm_tree + then + : + else + mi_tdir_="${_TMP_DIR}"_; + mi_n=1; + mi_tdir_n="${mi_tdir_}${mi_n}"; + while obj mi_tdir_n is_existing + do + if obj mi_tdir_n rm_tree + then + # directory could not be removed + mi_n="$(expr "${mi_n}" + 1)"; + mi_tdir_n="${mi_tdir_}${mi_n}"; + continue; + fi; + done; + _TMP_DIR="${mi_tdir_n}"; + fi; + eval mkdir "${_TMP_DIR}"; + if is_not_equal "$?" 0 + then + obj _TMP_DIR rm_tree; + _TMP_DIR=''; + continue; + fi; + if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable + then + # $_TMP_DIR can now be used as temporary directory + break; + fi; + obj _TMP_DIR rm_tree; + _TMP_DIR=''; + continue; + done; + if obj _TMP_DIR is_empty + then + error "main_init: \ +Couldn't create a directory for storing temporary files."; + fi; + if obj _DEBUG_PRINT_TMPDIR is_yes + then + echo2 "temporary directory: ${_TMP_DIR}"; + fi; + + _TMP_CAT="$(tmp_create groffer_cat)"; + _TMP_STDIN="$(tmp_create groffer_input)"; + exit_test; + + eval ${_UNSET} mi_dir; + eval ${_UNSET} mi_n; + eval ${_UNSET} mi_tdir_; + eval ${_UNSET} mi_tdir_n; + eval "${return_ok}"; +} # main_init() + + +######################################################################## +# main_parse_MANOPT () +# +# Parse $MANOPT to retrieve man options, but only if it is a non-empty +# string; found man arguments can be overwritten by the command line. +# +# Globals: +# in: $MANOPT, $_OPTS_MANOPT_* +# out: $_MANOPT_* +# +# Variable prefix: mpm +# +main_parse_MANOPT() +{ + func_check main_parse_MANOPT = 0 "$@"; + + if obj MANOPT is_not_empty + then + # Delete leading and final spaces + MANOPT="$(echo1 "${MANOPT}" | sed -e ' +s/^'"${_SPACE_SED}"'*// +s/'"${_SPACE_SED}"'*$// +')"; + exit_test; + fi; + if obj MANOPT is_empty + then + eval "${return_ok}"; + fi; + + mpm_list=''; + # add arguments in $MANOPT by mapping them to groffer options + eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")"; + exit_test; + shift; + until test "$#" -le 0 || is_equal "$1" '--' + do + mpm_opt="$1"; + shift; + case "${mpm_opt}" in + -7|--ascii) + list_append mpm_list '--ascii'; + ;; + -a|--all) + list_append mpm_list '--all'; + ;; + -c|--catman) + do_nothing; + shift; + ;; + -d|--debug) + do_nothing; + ;; + -D|--default) + # undo all man options so far + mpm_list=''; + ;; + -e|--extension) + list_append mpm_list '--extension'; + shift; + ;; + -f|--whatis) + list_append mpm_list '--whatis'; + shift; + ;; + -h|--help) + do_nothing; + shift; + ;; + -k|--apropos) + # groffer's --apropos takes an argument, but man's does not, so + do_nothing; + ;; + -l|--local-file) + do_nothing; + ;; + -L|--locale) + list_append mpm_list '--locale' "$1"; + shift; + ;; + -m|--systems) + list_append mpm_list '--systems' "$1"; + shift; + ;; + -M|--manpath) + list_append mpm_list '--manpath' "$1"; + shift; + ;; + -p|--preprocessor) + do_nothing; + shift; + ;; + -P|--pager) + list_append mpm_list '--pager' "$1"; + shift; + ;; + -r|--prompt) + do_nothing; + shift; + ;; + -S|--sections) + list_append mpm_list '--sections' "$1"; + shift; + ;; + -t|--troff) + do_nothing; + shift; + ;; + -T|--device) + list_append mpm_list '-T' "$1"; + shift; + ;; + -u|--update) + do_nothing; + shift; + ;; + -V|--version) + do_nothing; + ;; + -w|--where|--location) + list_append mpm_list '--location'; + ;; + -Z|--ditroff) + do_nothing; + ;; + # ignore all other options + esac; + done; + + # prepend $mpm_list to the command line + if obj mpm_list is_not_empty + then + eval set x "${mpm_list}" '"$@"'; + shift; + fi; + + eval ${_UNSET} mpm_list; + eval ${_UNSET} mpm_opt; + eval "${return_ok}"; +} # main_parse_MANOPT() + + +######################################################################## +# main_parse_args (*) +# +# Parse arguments; process options and filespec parameters +# +# Arguments: pass the command line arguments unaltered. +# Globals: +# in: $_OPTS_* +# out: $_OPT_*, $_ADDOPTS, $_FILEARGS +# +# Variable prefix: mpa +# +main_parse_args() +{ + func_check main_parse_args '>=' 0 "$@"; + _ALL_PARAMS="$(list_from_cmdline _OPTS_CMDLINE "$@")"; + exit_test; + if obj _DEBUG_PRINT_PARAMS is_yes + then + echo2 "parameters: ${_ALL_PARAMS}"; + fi; + eval set x "${_ALL_PARAMS}"; + shift; + + # By the call of `eval', unnecessary quoting was removed. So the + # positional shell parameters ($1, $2, ...) are now guaranteed to + # represent an option or an argument to the previous option, if any; + # then a `--' argument for separating options and + # parameters; followed by the filespec parameters if any. + + # Note, the existence of arguments to options has already been checked. + # So a check for `$#' or `--' should not be done for arguments. + + until test "$#" -le 0 || is_equal "$1" '--' + do + mpa_opt="$1"; # $mpa_opt is fed into the option handler + shift; + case "${mpa_opt}" in + -h|--help) + usage; + leave; + ;; + -Q|--source) # output source code (`Quellcode'). + _OPT_MODE='source'; + ;; + -T|--device|--troff-device) # device; arg + _OPT_DEVICE="$1"; + _check_device_with_mode; + shift; + ;; + -v|--version) + version; + leave; + ;; + -V) + _OPT_V='yes'; + ;; + -Z|--ditroff|--intermediate-output) # groff intermediate output + _OPT_Z='yes'; + ;; + -X) + if is_X + then + _OPT_MODE=X; + fi; + ;; + -?) + # delete leading `-' + mpa_optchar="$(echo1 "${mpa_opt}" | sed -e 's/^-//')"; + exit_test; + if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}" + then + list_append _ADDOPTS_GROFF "${mpa_opt}"; + elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}" + then + list_append _ADDOPTS_GROFF "${mpa_opt}" "$1"; + shift; + else + error "main_parse_args(): Unknown option : \`$1'"; + fi; + ;; + --all) + _OPT_ALL='yes'; + ;; + --apropos) # run `apropos' + _OPT_APROPOS='yes'; + _APROPOS_SECTIONS=''; + _OPT_WHATIS='no'; + ;; + --apropos-data) # run `apropos' for data sections + _OPT_APROPOS='yes'; + _APROPOS_SECTIONS='457'; + _OPT_WHATIS='no'; + ;; + --apropos-devel) # run `apropos' for development sections + _OPT_APROPOS='yes'; + _APROPOS_SECTIONS='239'; + _OPT_WHATIS='no'; + ;; + --apropos-progs) # run `apropos' for program sections + _OPT_APROPOS='yes'; + _APROPOS_SECTIONS='168'; + _OPT_WHATIS='no'; + ;; + --ascii) + list_append _ADDOPTS_GROFF '-mtty-char'; + if obj _OPT_MODE is_empty + then + _OPT_MODE='text'; + fi; + ;; + --auto) # the default automatic mode + _OPT_MODE=''; + ;; + --bd) # border color for viewers, arg; + _OPT_BD="$1"; + shift; + ;; + --bg|--backgroud) # background color for viewers, arg; + _OPT_BG="$1"; + shift; + ;; + --bw) # border width for viewers, arg; + _OPT_BW="$1"; + shift; + ;; + --debug|--debug-all|--debug-keep|--debug-lm|--debug-params|\ +--debug-shell|--debug-stacks|--debug-tmpdir|--debug-user) + # debug is handled at the beginning + :; + ;; + --default) # reset variables to default + reset; + ;; + --default-modes) # sequence of modes in auto mode; arg + _OPT_DEFAULT_MODES="$1"; + shift; + ;; + --display) # set X display, arg + _OPT_DISPLAY="$1"; + shift; + ;; + --do-nothing) + _OPT_DO_NOTHING='yes'; + ;; + --dvi) + if is_X + then + _OPT_MODE='dvi'; + fi; + ;; + --dvi-viewer) # viewer program for dvi mode; arg + _VIEWER_TERMINAL='no'; + _OPT_VIEWER_DVI="$1"; + shift; + ;; + --dvi-viewer-tty) # viewer program for dvi mode in tty; arg + _VIEWER_TERMINAL='yes'; + _OPT_VIEWER_DVI="$1"; + shift; + ;; + --extension) # the extension for man pages, arg + _OPT_EXTENSION="$1"; + shift; + ;; + --fg|--foreground) # foreground color for viewers, arg; + _OPT_FG="$1"; + shift; + ;; + --fn|--font) # set font for viewers, arg; + _OPT_FN="$1"; + shift; + ;; + --geometry) # window geometry for viewers, arg; + _OPT_GEOMETRY="$1"; + shift; + ;; + --groff) + _OPT_MODE='groff'; + ;; + --html|--www) # display with web browser + _OPT_MODE=html; + ;; + --html-viewer|--www-viewer) # viewer program for html mode; arg + _VIEWER_TERMINAL='no'; + _OPT_VIEWER_HTML="$1"; + shift; + ;; + --html-viewer-tty|--www-viewer-tty) # viewer for html mode in tty; arg + _VIEWER_TERMINAL='yes'; + _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"; + shift; + ;; + --local-file) # force local files; same as `--no-man' + _MAN_FORCE='no'; + _MAN_ENABLE='no'; + ;; + --location|--where) # print file locations to stderr + _OPT_LOCATION='yes'; + ;; + --man) # force all file params to be man pages + _MAN_ENABLE='yes'; + _MAN_FORCE='yes'; + ;; + --manpath) # specify search path for man pages, arg + # arg is colon-separated list of directories + _OPT_MANPATH="$1"; + shift; + ;; + --mode) # display mode + mpa_arg="$1"; + shift; + case "${mpa_arg}" in + auto|'') # search mode automatically among default + _OPT_MODE=''; + ;; + groff) # pass input to plain groff + _OPT_MODE='groff'; + ;; + html|www) # display with a web browser + _OPT_MODE='html'; + ;; + dvi) # display with xdvi viewer + if is_X + then + _OPT_MODE='dvi'; + fi; + ;; + pdf) # display with PDF viewer + if is_X + then + _OPT_MODE='pdf'; + fi; + ;; + ps) # display with Postscript viewer + if is_X + then + _OPT_MODE='ps'; + fi; + ;; + text) # output on terminal + _OPT_MODE='text'; + ;; + tty) # output on terminal + _OPT_MODE='tty'; + ;; + X|x) # output on X roff viewer + if is_X + then + _OPT_MODE='x'; + fi; + ;; + Q|source) # display source code + _OPT_MODE="source"; + ;; + *) + error "main_parse_args(): unknown mode ${mpa_arg}"; + ;; + esac; + ;; + --no-location) # disable former call to `--location' + _OPT_LOCATION='yes'; + ;; + --no-man) # disable search for man pages + # the same as --local-file + _MAN_FORCE='no'; + _MAN_ENABLE='no'; + ;; + --no-special) # disable some special former calls + _OPT_ALL='no' + _OPT_APROPOS='no' + _OPT_WHATIS='no' + ;; + --pager|--tty-viewer|--tty-viewer-tty) + # set paging program for tty mode, arg + _VIEWER_TERMINAL='yes'; + _OPT_PAGER="$1"; + shift; + ;; + --pdf) + if is_X + then + _OPT_MODE='pdf'; + fi; + ;; + --pdf-viewer) # viewer program for ps mode; arg + _VIEWER_TERMINAL='no'; + _OPT_VIEWER_PDF="$1"; + shift; + ;; + --pdf-viewer-tty) # viewer program for ps mode in tty; arg + _VIEWER_TERMINAL='yes'; + _OPT_VIEWER_PDF="$1"; + shift; + ;; + --print) # for argument test + echo2 "$1"; + shift; + ;; + --ps) + if is_X + then + _OPT_MODE='ps'; + fi; + ;; + --ps-viewer) # viewer program for ps mode; arg + _VIEWER_TERMINAL='no'; + _OPT_VIEWER_PS="$1"; + shift; + ;; + --ps-viewer-tty) # viewer program for ps mode in tty; arg + _VIEWER_TERMINAL='yes'; + _OPT_VIEWER_PS="$1"; + shift; + ;; + --resolution) # set resolution for X devices, arg + mpa_arg="$1"; + shift; + case "${mpa_arg}" in + 75|75dpi) + mpa_dpi=75; + ;; + 100|100dpi) + mpa_dpi=100; + ;; + *) + error "main_parse_args(): \ +only resoutions of 75 or 100 dpi are supported"; + ;; + esac; + _OPT_RESOLUTION="${mpa_dpi}"; + ;; + --rv) + _OPT_RV='yes'; + ;; + --sections) # specify sections for man pages, arg + # arg is colon-separated list of section names + _OPT_SECTIONS="$1"; + shift; + ;; + --shell) + # already done during the first run; so ignore the argument + shift; + ;; + --systems) # man pages for different OS's, arg + # argument is a comma-separated list + _OPT_SYSTEMS="$1"; + shift; + ;; + --text) # text mode without pager + _OPT_MODE=text; + ;; + --title) # title for X viewers; arg + _OPT_TITLE="$1"; + shift; + ;; + --tty) # tty mode, text with pager + _OPT_MODE=tty; + ;; + --text-device|--tty-device) # device for tty mode; arg + _OPT_TEXT_DEVICE="$1"; + shift; + ;; + --whatis) + _OPT_WHATIS='yes'; + _OPT_ALL='yes'; + _OPT_APROPOS='no'; + ;; + --X|--x) + if is_X + then + _OPT_MODE=x; + fi; + ;; + --xrm) # pass X resource string, arg; + list_append _OPT_XRM "$1"; + shift; + ;; + --x-viewer|--X-viewer) # viewer program for x mode; arg + _VIEWER_TERMINAL='no'; + _OPT_VIEWER_X="$1"; + shift; + ;; + --x-viewer-tty|--X-viewer-tty) # viewer program for x mode in tty; arg + _VIEWER_TERMINAL='yes'; + _OPT_VIEWER_X="$1"; + shift; + ;; + *) + error 'main_parse_args(): error on argument parsing : '"\`$*'"; + ;; + esac; + done; + shift; # remove `--' argument + + if obj _OPT_DO_NOTHING is_yes + then + leave; + fi; + + # Remaining arguments are file names (filespecs). + # Save them to list $_FILEARGS + if is_equal "$#" 0 + then # use "-" for standard input + set x '-'; + shift; + fi; + _FILEARGS=''; + list_append _FILEARGS "$@"; + if list_has _FILEARGS '-' + then + save_stdin; + fi; + # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;' + eval ${_UNSET} mpa_arg; + eval ${_UNSET} mpa_dpi; + eval ${_UNSET} mpa_opt; + eval ${_UNSET} mpa_optchar; + 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}"; +} # _check_device_with_mode() of main_parse_args() + + +######################################################################## +# main_set_mode () +# +# Determine the display mode. +# +# Globals: +# in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE +# out: $_DISPLAY_MODE +# +# Variable prefix: msm +# +main_set_mode() +{ + func_check main_set_mode = 0 "$@"; + + # set display + if obj _OPT_DISPLAY is_not_empty + then + DISPLAY="${_OPT_DISPLAY}"; + fi; + + if obj _OPT_V is_yes + then + list_append _ADDOPTS_GROFF '-V'; + fi; + if obj _OPT_Z is_yes + then + _DISPLAY_MODE='groff'; + list_append _ADDOPTS_GROFF '-Z'; + fi; + if obj _OPT_MODE is_equal 'groff' + then + _DISPLAY_MODE='groff'; + fi; + if obj _DISPLAY_MODE is_equal 'groff' + then + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + fi; + + if obj _OPT_MODE is_equal 'source' + then + _DISPLAY_MODE='source'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + fi; + + case "${_OPT_MODE}" in + '') # automatic mode + case "${_OPT_DEVICE}" in + X*) + if is_not_X + then + error_user "no X display found for device ${_OPT_DEVICE}"; + fi; + _DISPLAY_MODE='x'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + ascii|cp1047|latin1|utf8) + if obj _DISPLAY_MODE is_not_equal 'text' + then + _DISPLAY_MODE='tty'; + fi; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + esac; + if is_not_X + then + _DISPLAY_MODE='tty'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + fi; + + if obj _OPT_DEFAULT_MODES is_empty + then + msm_modes="${_DEFAULT_MODES}"; + else + msm_modes="${_OPT_DEFAULT_MODES}"; + fi; + ;; + text) + _DISPLAY_MODE='text'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + tty) + _DISPLAY_MODE='tty'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + html) + _DISPLAY_MODE='html'; + msm_modes="${_OPT_MODE}"; + ;; + *) # display mode was given + if is_not_X + then + error_user "You must be in X Window for ${_OPT_MODE} mode."; + fi; + msm_modes="${_OPT_MODE}"; + ;; + esac; + + # only viewer modes are left + eval set x "$(list_from_split "${msm_modes}" ',')"; + exit_test; + shift; + while test "$#" -gt 0 + do + m="$1"; + shift; + case "$m" in + dvi) + if obj _OPT_VIEWER_DVI is_not_empty + then + msm_viewer="${_OPT_VIEWER_DVI}"; + else + msm_viewer="$(_get_first_prog "$_VIEWER_DVI}")"; + exit_test; + fi; + if obj msm_viewer is_empty + then + error 'No viewer for dvi mode available.'; + fi; + if is_not_equal "$?" 0 + then + continue; + fi; + _DISPLAY_PROG="${msm_viewer}"; + _DISPLAY_MODE="dvi"; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + html) + if obj _OPT_VIEWER_HTML is_not_empty + then + msm_viewer="${_OPT_VIEWER_HTML}"; + else + if is_X + then + msm_viewers="${_VIEWER_HTML_X}"; + else + msm_viewers="${_VIEWER_HTML_TTY}"; + fi; + msm_viewer="$(_get_first_prog "${msm_viewers}")"; + exit_test; + fi; + if obj msm_viewer is_empty + then + error 'No viewer for html mode available.'; + fi; + if is_not_equal "$?" 0 + then + continue; + fi; + _DISPLAY_PROG="${msm_viewer}"; + _DISPLAY_MODE=html; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + pdf) + if obj _OPT_VIEWER_PDF is_not_empty + then + msm_viewer="${_OPT_VIEWER_PDF}"; + else + msm_viewer="$(_get_first_prog "${_VIEWER_PDF}")"; + exit_test; + fi; + if obj msm_viewer is_empty + then + error 'No viewer for pdf mode available.'; + fi; + if is_not_equal "$?" 0 + then + continue; + fi; + _DISPLAY_PROG="${msm_viewer}"; + _DISPLAY_MODE="pdf"; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + ps) + if obj _OPT_VIEWER_PS is_not_empty + then + msm_viewer="${_OPT_VIEWER_PS}"; + else + msm_viewer="$(_get_first_prog "${_VIEWER_PS}")"; + exit_test; + fi; + if obj msm_viewer is_empty + then + error 'No viewer for ps mode available.'; + fi; + if is_not_equal "$?" 0 + then + continue; + fi; + _DISPLAY_PROG="${msm_viewer}"; + _DISPLAY_MODE="ps"; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + text) + _DISPLAY_MODE='text'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + tty) + _DISPLAY_MODE='tty'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + x) + if obj _OPT_VIEWER_X is_not_empty + then + msm_viewer="${_OPT_VIEWER_X}"; + else + msm_viewer="$(_get_first_prog "${_VIEWER_X}")"; + exit_test; + fi; + if obj msm_viewer is_empty + then + error 'No viewer for x mode available.'; + fi; + if is_not_equal "$?" 0 + then + continue; + fi; + _DISPLAY_PROG="${msm_viewer}"; + _DISPLAY_MODE='x'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + X) + _DISPLAY_MODE='X'; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + eval "${return_ok}"; + ;; + esac; + done; + eval ${_UNSET} msm_modes; + eval ${_UNSET} msm_viewer; + eval ${_UNSET} msm_viewers; + error_user "No suitable display mode found."; +} # main_set_mode() + + +# _get_first_prog () +# +# Retrieve first argument that represents an existing program in $PATH. +# Local function for main_set_mode(). +# +# Arguments: 1; a comma-separated list of commands (with options), +# like $_VIEWER_*. +# +# Return : `1' if none found, `0' if found. +# Output : the argument that succeded. +# +# Variable prefix: _gfp +# +_get_first_prog() +{ + if is_equal "$#" 0 + then + error "_get_first_prog() needs 1 argument."; + fi; + if is_empty "$1" + then + return "${_BAD}"; + fi; + eval set x "$(list_from_split "$1" ',')"; + exit_test; + shift; + for i + do + _gfp_i="$i"; + if obj _gfp_i is_empty + then + continue; + fi; + if eval is_prog "$(get_first_essential ${_gfp_i})" + then + exit_test; + obj _gfp_i echo1; + eval ${_UNSET} _gfp_i; + return "${_GOOD}"; + fi; + done; + eval ${_UNSET} _gfp_i; + return "${_BAD}"; +} # _get_first_prog() of main_set_mode() + + +####################################################################### +# main_do_fileargs () +# +# Process filespec arguments in $_FILEARGS. +# +# Globals: +# in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;') +# +# Variable prefix: mdfa +# +main_do_fileargs() +{ + func_check main_do_fileargs = 0 "$@"; + special_setup; + eval set x "${_FILEARGS}"; + shift; + eval ${_UNSET} _FILEARGS; + # temporary storage of all input to $_TMP_CAT + while test "$#" -ge 2 + do + # test for `s name' arguments, with `s' a 1-char standard section + mdfa_filespec="$1"; + _FILESPEC_ARG="$1"; + shift; + case "${mdfa_filespec}" in + '') + continue; + ;; + '-') + special_filespec; + if obj _OPT_APROPOS is_yes + then + continue; + fi; + register_file '-' + continue; + ;; + ?) + if obj _OPT_APROPOS is_yes + then + special_filespec; + continue; + fi; + if list_has_not _MAN_AUTO_SEC_LIST "${mdfa_filespec}" + then + special_filespec; + do_filearg "${mdfa_filespec}" + continue; + fi; + mdfa_name="$1"; + _FILESPEC_ARG="${_FILESPEC_ARG} $1"; + special_filespec; + case "${mdfa_name}" in + */*|man:*|*\(*\)|*."${mdfa_filespec}") + do_filearg "${mdfa_filespec}" + continue; + ;; + esac; + shift; + if do_filearg "man:${mdfa_name}(${mdfa_filespec})" + then + continue; + else + do_filearg "${mdfa_filespec}" + continue; + fi; + ;; + *) + special_filespec; + if obj _OPT_APROPOS is_yes + then + continue; + fi; + do_filearg "${mdfa_filespec}" + continue; + ;; + esac; + done; # end of `s name' test + while test "$#" -gt 0 + do + mdfa_filespec="$1"; + _FILESPEC_ARG="$1"; + shift; + special_filespec; + if obj _OPT_APROPOS is_yes + then + continue; + fi; + do_filearg "${mdfa_filespec}" + done; + obj _TMP_STDIN rm_file_with_debug; + eval ${_UNSET} mdfa_filespec; + eval ${_UNSET} mdfa_name; + eval "${return_ok}"; +} # main_do_fileargs() + + +######################################################################## +# main_set_resources () +# +# Determine options for setting X resources with $_DISPLAY_PROG. +# +# Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME +# +# Variable prefix: msr +# +main_set_resources() +{ + func_check main_set_resources = 0 "$@"; + # $msr_prog viewer program + # $msr_rl resource list + msr_title="$(get_first_essential \ + "${_OPT_TITLE}" "${_REGISTERED_TITLE}")"; + exit_test; + _OUTPUT_FILE_NAME=''; + eval set x "${msr_title}"; + shift; + until is_equal "$#" 0 + do + msr_n="$1"; + case "${msr_n}" in + '') + continue; + ;; + ,*) + msr_n="$(echo1 "$1" | sed -e 's/^,,*//')"; + exit_test; + ;; + esac + if obj msr_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}${msr_n}"; + shift; + done; + case "${_OUTPUT_FILE_NAME}" in + '') + _OUTPUT_FILE_NAME='-'; + ;; + ,*) + error "main_set_resources(): ${_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 ${_UNSET} msr_n; + eval ${_UNSET} msr_prog; + eval ${_UNSET} msr_rl; + eval ${_UNSET} msr_title; + eval "${return_ok}"; + fi; + + eval set x "${_DISPLAY_PROG}"; + shift; + msr_prog="$(base_name "$1")"; + exit_test; + shift; + if test $# != 0 + then + if obj _DISPLAY_PROG is_empty + then + _DISPLAY_ARGS="$*"; + else + _DISPLAY_ARGS="$* ${_DISPLAY_ARGS}"; + fi; + fi; + msr_rl=''; + if obj _OPT_BD is_not_empty + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + list_append msr_rl '-bd' "${_OPT_BD}"; + ;; + esac; + fi; + if obj _OPT_BG is_not_empty + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + list_append msr_rl '-bg' "${_OPT_BG}"; + ;; + kghostview) + list_append msr_rl '--bg' "${_OPT_BG}"; + ;; + xpdf) + list_append msr_rl '-papercolor' "${_OPT_BG}"; + ;; + esac; + fi; + if obj _OPT_BW is_not_empty + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + _list_append msr_rl '-bw' "${_OPT_BW}"; + ;; + esac; + fi; + if obj _OPT_FG is_not_empty + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + list_append msr_rl '-fg' "${_OPT_FG}"; + ;; + kghostview) + list_append msr_rl '--fg' "${_OPT_FG}"; + ;; + esac; + fi; + if is_not_empty "${_OPT_FN}" + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + list_append msr_rl '-fn' "${_OPT_FN}"; + ;; + kghostview) + list_append msr_rl '--fn' "${_OPT_FN}"; + ;; + esac; + fi; + if is_not_empty "${_OPT_GEOMETRY}" + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi|xpdf) + list_append msr_rl '-geometry' "${_OPT_GEOMETRY}"; + ;; + kghostview) + list_append msr_rl '--geometry' "${_OPT_GEOMETRY}"; + ;; + esac; + fi; + if is_empty "${_OPT_RESOLUTION}" + then + _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}"; + case "${msr_prog}" in + gxditview|xditview) + list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}"; + ;; + xpdf) + case "${_DEFAULT_RESOLUTION}" in + 75) + # 72dpi is '100' + list_append msr_rl '-z' '104'; + ;; + 100) + list_append msr_rl '-z' '139'; + ;; + esac; + ;; + esac; + else + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + list_append msr_rl '-resolution' "${_OPT_RESOLUTION}"; + ;; + xpdf) + case "${_OPT_RESOLUTION}" in + 75) + list_append msr_rl '-z' '104'; + # '100' corresponds to 72dpi + ;; + 100) + list_append msr_rl '-z' '139'; + ;; + esac; + ;; + esac; + fi; + if is_yes "${_OPT_ICONIC}" + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + list_append msr_rl '-iconic'; + ;; + esac; + fi; + if is_yes "${_OPT_RV}" + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi) + list_append msr_rl '-rv'; + ;; + esac; + fi; + if is_not_empty "${_OPT_XRM}" + then + case "${msr_prog}" in + ghostview|gv|gxditview|xditview|xdvi|xpdf) + eval set x "${_OPT_XRM}"; + shift; + for i + do + list_append msr_rl '-xrm' "$i"; + done; + ;; + esac; + fi; + if is_not_empty "${msr_title}" + then + case "${msr_prog}" in + gxditview|xditview) + list_append msr_rl '-title' "${msr_title}"; + ;; + esac; + fi; + _DISPLAY_ARGS="${msr_rl}"; + eval ${_UNSET} msr_n; + eval ${_UNSET} msr_prog; + eval ${_UNSET} msr_rl; + eval ${_UNSET} msr_title; + eval "${return_ok}"; +} # main_set_resources + + +######################################################################## +# main_display () +# +# Do the actual display of the whole thing. +# +# Globals: +# in: $_DISPLAY_MODE, $_OPT_DEVICE, +# $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X, +# $_TMP_CAT, $_OPT_PAGER, $PAGER, $_MANOPT_PAGER, +# $_OUTPUT_FILE_NAME +# +# Variable prefix: md +# +main_display() +{ + func_check main_display = 0 "$@"; + + export md_addopts; + export md_groggy; + export md_modefile; + + if obj _TMP_CAT is_non_empty_file + then + md_modefile="${_OUTPUT_FILE_NAME}"; + else + echo2 'groffer: empty input.'; + clean_up; + eval ${_UNSET} md_modefile; + eval "${return_ok}"; + fi; + + # go to the temporary directory to be able to access internal data files + cd "${_TMP_DIR}" >"${_NULL_DEV}" 2>&1; + + case "${_DISPLAY_MODE}" in + groff) + _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}"; + if obj _OPT_DEVICE is_not_empty + then + _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}"; + fi; + md_groggy="$(tmp_cat | eval grog "${md_options}")"; + exit_test; + _do_opt_V; + + obj md_modefile rm_file; + mv "${_TMP_CAT}" "${md_modefile}"; + trap_unset; + cat "${md_modefile}" | \ + { + trap_set; + eval "${md_groggy}" "${_ADDOPTS_GROFF}"; + } & + ;; + text|tty) + case "${_OPT_DEVICE}" in + '') + md_device="$(get_first_essential \ + "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")"; + exit_test; + ;; + ascii|cp1047|latin1|utf8) + md_device="${_OPT_DEVICE}"; + ;; + *) + warning "main_display(): \ +wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; + ;; + esac; + md_addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}"; + md_groggy="$(tmp_cat | grog -T${md_device})"; + exit_test; + if obj _DISPLAY_MODE is_equal 'text' + then + _do_opt_V; + tmp_cat | eval "${md_groggy}" "${md_addopts}"; + else + md_pager=''; + for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \ + 'less -r -R' 'more' 'pager' 'cat' + do + md_p="$p"; + if eval is_prog ${md_p} + then # no "" for is_prog() allows args for $p + md_pager="${md_p}"; + break; + fi; + done; + if obj md_pager is_empty + then + error 'main_display(): no pager program found for tty mode'; + fi; + _do_opt_V; + tmp_cat | eval "${md_groggy}" "${md_addopts}" | \ + eval "${md_pager}"; + fi; + clean_up; + ;; + source) + tmp_cat; + clean_up; + ;; + + #### viewer modes + + dvi) + case "${_OPT_DEVICE}" in + ''|dvi) do_nothing; ;; + *) + warning "main_display(): \ +wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}" + ;; + esac; + md_modefile="${md_modefile}".dvi; + md_groggy="$(tmp_cat | grog -Tdvi)"; + exit_test; + _do_display; + ;; + html) + case "${_OPT_DEVICE}" in + ''|html) do_nothing; ;; + *) + warning "main_display(): \ +wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; + ;; + esac; + md_modefile="${md_modefile}".html; + md_groggy="$(tmp_cat | grog -Thtml)"; + exit_test; + _do_display; + ;; + pdf) + case "${_OPT_DEVICE}" in + ''|ps) + do_nothing; + ;; + *) + warning "main_display(): \ +wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; + ;; + esac; + md_groggy="$(tmp_cat | grog -Tps)"; + exit_test; + _do_display _make_pdf; + ;; + ps) + case "${_OPT_DEVICE}" in + ''|ps) + do_nothing; + ;; + *) + warning "main_display(): \ +wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; + ;; + esac; + md_modefile="${md_modefile}".ps; + md_groggy="$(tmp_cat | grog -Tps)"; + exit_test; + _do_display; + ;; + x) + case "${_OPT_DEVICE}" in + X*) + md_device="${_OPT_DEVICE}" + ;; + *) + case "${_OPT_RESOLUTION}" in + 100) + md_device='X100'; + if obj _OPT_GEOMETRY is_empty + then + case "${_DISPLAY_PROG}" in + gxditview|xditview) + # add width of 800dpi for resolution of 100dpi to the args + list_append _DISPLAY_ARGS '-geometry' '800'; + ;; + esac; + fi; + ;; + *) + md_device='X75-12'; + ;; + esac + esac; + md_groggy="$(tmp_cat | grog -T${md_device} -Z)"; + exit_test; + _do_display; + ;; + X) + case "${_OPT_DEVICE}" in + '') + md_groggy="$(tmp_cat | grog -X)"; + exit_test; + ;; + X*|dvi|html|lbp|lj4|ps) + # these devices work with + md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)"; + exit_test; + ;; + *) + warning "main_display(): \ +wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"; + md_groggy="$(tmp_cat | grog -Z)"; + exit_test; + ;; + esac; + _do_display; + ;; + *) + error "main_display(): unknown mode \`${_DISPLAY_MODE}'"; + ;; + esac; + eval ${_UNSET} md_addopts; + eval ${_UNSET} md_device; + eval ${_UNSET} md_groggy; + eval ${_UNSET} md_modefile; + eval ${_UNSET} md_options; + eval ${_UNSET} md_p; + eval ${_UNSET} md_pager; + eval "${return_ok}"; +} # main_display() + + +######################## +# _do_display ([]) +# +# Perform the generation of the output and view the result. If an +# argument is given interpret it as a function name that is called in +# the midst (actually only for `pdf'). +# +# Globals: $md_modefile, $md_groggy (from main_display()) +# +_do_display() +{ + func_check _do_display '>=' 0 "$@"; + _do_opt_V; + if obj _DISPLAY_PROG is_empty + then + trap_unset; + { + trap_set; + eval "${md_groggy}" "${_ADDOPTS_GROFF}" "${_TMP_CAT}"; + } & + else + obj md_modefile rm_file; + cat "${_TMP_CAT}" | \ + eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}"; + if is_not_empty "$1" + then + eval "$1"; + fi; + obj _TMP_CAT rm_file_with_debug; + if obj _VIEWER_TERMINAL is_yes # for programs that run on tty + then + eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\""; + else + case "${_DISPLAY_PROG}" in +# lynx\ *|less\ *|more\ *) # programs known to run on the terminal +# eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\""; +# ;; + *) + trap_unset; + { + trap_set; + eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\""; + } & + ;; + esac; + fi; + fi; + eval "${return_ok}"; +} # _do_display() of main_display() + + +############# +# _do_opt_V () +# +# Check on option `-V'; if set print the corresponding output and leave. +# +# Globals: $_ALL_PARAMS, $_ADDOPTS_GROFF, $_DISPLAY_MODE, $_DISPLAY_PROG, +# $_DISPLAY_ARGS, $md_groggy, $md_modefile +# +# Variable prefix: _doV +# +_do_opt_V() +{ + func_check _do_opt_V '=' 0 "$@"; + if obj _OPT_V is_yes + then + _OPT_V='no'; + echo1 "Parameters: ${_ALL_PARAMS}"; + echo1 "Display mode: ${_DISPLAY_MODE}"; + echo1 "Output file: ${md_modefile}"; + echo1 "Display prog: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}"; + a="$(eval echo1 "'${_ADDOPTS_GROFF}'")"; + exit_test; + echo1 "Output of grog: ${md_groggy} $a"; + _doV_res="$(eval "${md_groggy}" "${_ADDOPTS_GROFF}")"; + exit_test; + echo1 "groff -V: ${_doV_res}" + leave; + fi; + eval "${return_ok}"; +} # _do_opt_V() of main_display() + + +############## +# _make_pdf () +# +# Transform to pdf format; for pdf mode in _do_display(). +# +# Globals: $md_modefile (from main_display()) +# +# Variable prefix: _mp +# +_make_pdf() +{ + func_check _do_display '=' 0 "$@"; + _mp_psfile="${md_modefile}"; + md_modefile="${md_modefile}.pdf"; + obj md_modefile rm_file; + if gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \ + -sOutputFile="${md_modefile}" -c save pop -f "${_mp_psfile}" + then + :; + else + error '_make_pdf: could not transform into pdf format.'; + fi; + obj _mp_psfile rm_file_with_debug; + eval ${_UNSET} _mp_psfile; + eval "${return_ok}"; +} # _make_pdf() of main_display() + + +######################################################################## +# main (*) +# +# The main function for groffer. +# +# Arguments: +# +main() +{ + func_check main '>=' 0 "$@"; + # Do not change the sequence of the following functions! + landmark '13: main_init()'; + main_init; + landmark '14: main_parse_MANOPT()'; + main_parse_MANOPT; + landmark '15: main_parse_args()'; + main_parse_args "$@"; + landmark '16: main_set_mode()'; + main_set_mode; + landmark '17: main_do_fileargs()'; + main_do_fileargs; + landmark '18: main_set_resources()'; + main_set_resources; + landmark '19: main_display()'; + main_display; + eval "${return_ok}"; +} + + +######################################################################## + +main "$@";