summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwl <wl>2013-08-11 08:28:23 +0000
committerwl <wl>2013-08-11 08:28:23 +0000
commit2e4ed555a4ce1fcb09d45c9b829de0480390fe67 (patch)
tree21ccbb826607eeaac8d8b3bc2b0bcd4457f39c96
parent8375908f83748c8ed9a611f49da8e973f19badbc (diff)
downloadgroff-2e4ed555a4ce1fcb09d45c9b829de0480390fe67.tar.gz
Revert accidental removal in previous commit.
-rw-r--r--contrib/groffer/shell/ChangeLog.02122
-rw-r--r--contrib/groffer/shell/README_SH297
-rw-r--r--contrib/groffer/shell/groffer.man4124
-rwxr-xr-xcontrib/groffer/shell/groffer.sh384
-rw-r--r--contrib/groffer/shell/groffer2.sh7312
-rwxr-xr-xcontrib/groffer/shell/roff2.sh339
6 files changed, 14578 insertions, 0 deletions
diff --git a/contrib/groffer/shell/ChangeLog.0 b/contrib/groffer/shell/ChangeLog.0
new file mode 100644
index 00000000..7502c64f
--- /dev/null
+++ b/contrib/groffer/shell/ChangeLog.0
@@ -0,0 +1,2122 @@
+2006-10-10 Bernd Warken <groff-bernd.warken-72@web.de>
+
+ * ChangeLog.0: This file is the former ChangeLog file of the
+ `groffer' versions 0.* consisting of a shell version only. Since
+ then the files have been moved to the subdirectory `shell' of the
+ `groffer' main directory.
+
+2006-10-05 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.31
+
+ * groffer2.sh:
+ - _make_pdf(): Fix argument of `obj'.
+ - to_tmp(): Add option -r to soelim to omit the .lf request. The
+ new global variable $_SOELIM_R stores the option if it is
+ available. Use numbers for the names of the `file' and `so'
+ temporary files, such that the information for each filespec
+ argument is kept for debug. New global variable $_FILE_NR.
+ - main_set_resources(): Remove `man' temporary files except for
+ debug
+ - man_get(): Change name in $_TMP_MANSPEC.
+ - man_is_man(): Change name in $_TMP_MANSPEC. Remove file in
+ $_TMP_MANPEC if empty.
+ - _do_display() of main_display(): Add check on empty mode file.
+
+ * groffer.man: Filespec: Add information on the argument
+ handling of apropos.
+
+ Remove the space characters at the end of line in all files.
+
+2006-10-03 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.30
+
+ * groffer2.sh:
+ - Correct spacing.
+ - main_do_fileargs(): Distribute special_filespec() in order to
+ get a better heading for `whatis'.
+
+2006-10-03 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.29
+
+ * groffer2.sh:
+ - --to-stdtout: New option to display the generated mode file
+ without graphical display.
+ - _get_prog_args() of main_set_mode(): Make argument upper case.
+ - usage(): Add --to-stdout, remove -Q, reorder --source.
+
+ * groffer.man:
+ - Reorder the default viewers.
+ - Move `--source' to `groffer' options.
+ - Remove `-Q'.
+ - Add `--to-stdout'.
+ - Reconfigure the sections on filespec arguments.
+ - Remove information on wildcards.
+
+2006-10-01 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.28
+
+ * groffer.sh:
+ - Change all directories to end with `/'.
+ - In the state before the run of `make', make the script runnable
+ from each directory using $0 and `pwd'.
+
+ * groffer2.sh:
+ - main_init(): Change the umask to 0077 to allow only access for
+ the file owner for the temporary files. This is done for security
+ reasons.
+ - version(): Put the whole output under `<<EOF'.
+ - usage(): Add information on filespec arguments.
+ - main_do_fileargs(): Rewrite the handling of filespec
+ parameters. Fix filespec man:name.section.
+
+2006-09-26 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.27
+
+ * Makefile.sub: Add Emacs setting at the end of the file.
+
+ * TODO: Remove this file because it does not contain any actual
+ entries.
+
+ * groffer2.sh:
+ - main_set_mode(): Remove too early test of modes on X. Fix pdf
+ mode.
+ - where_is_prog(): Fix this function to detect files in the
+ current directory.
+ - _get_prog_args() of main_set_mode(): Fix return;
+ - _get_first_prog() of main_set_mode(): Fix call of exit_test().
+ - cat_z(): Make it a single function and add file test.
+ - whatis_setup(): Rename whatis_header(). Fix display title to
+ `whatis'.
+ - apropos_setup(): Fix display title to `apropos'.
+ - Globals: Fix this section in the description of several
+ functions.
+ - apropos_filespec(): Fix variable $s and the corresponding sed
+ call.
+ - man_setup(): Add $EXTENSION.
+ - _do_man_so() of to_tmp(): Fix variables.
+ - $_ALL_EXIT: Remove unused variable.
+ - $_TITLE_ELT: Remove unused variable.
+ - man_set_resources(): Fix setting of $_DISPLAY_ARGS.
+ - main_display(): Fix description. Remove $md_options. Let
+ $MANOPT override system variables.
+
+2006-09-16 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.26
+
+ ### Simplification of main_set_mode()
+
+ * groffer2.sh:
+ - _get_first_prog() of main_set_mode(): Rewrite this function
+ such that it does not have an output, but set the variables
+ $_DISPLAY_PROG and $_DISPLAY_ARGS.
+ - _check_prog_on_list() of main_set_mode(): Rename and rewrite
+ _check_X_prog(). Suitable for being called for $_VIEWER_<mode>_X
+ and $_VIEWER_<mode>_TTY. No output, but set the variables
+ $_DISPLAY_PROG and $_DISPLAY_ARGS.
+ - _obj_set_vars() of main_set_mode(): Remove this function. It is
+ no longer necessary because its variables are set by the other
+ functions.
+ - _get_prog_args() of main_set_mode(): New function that
+ simplifies the loop in main_set_mode() and handles both
+ $_VIEWER_<mode>_X and $_VIEWER_<mode>_TTY.
+ - _process_mode() of main_set_mode(): Remove this function.
+ - main_set_mode(): Remove case for calling _process_mode(). In
+ the loop, use _get_prog_args() for simplification.
+ - main_parse_args(): Make --<mode>-viewer equivalent to
+ --<mode>-viewer-tty to make _process_mode() unnecessary.
+ - $_VIEWER_BACKGROUND: Start with `no'.
+
+ ### Extend the documentation
+
+ * groffer2.sh:
+ - Environment Variables: Add information on the naming of
+ variables in functions.
+ - $_ADDOPTS_POST, $_ADDOPTS_X: Remove these unused variables.
+ - apropos_setup(), apropos_setup (), base_name(), dir_name(),
+ echo1(), echo2(), func_check(), func_pop(), func_push(),
+ is_greater_than(), list_append(), list_from_split(),
+ _manpath_add_sys() of manpath_add_lang_sys(), rm_tree(),
+ special_filespec(), special_setup(), tmp_create(), to_tmp_line(),
+ usage(), version(), where_is_prog(), main_set_mode():
+ Fix and extend the description. Many other function descriptions
+ were just fixed without being mentioned.
+ - landmark 7: man_*(): Add information on the search of `man'
+ pages.
+
+ * groffer.man:
+ - GNU `man' option overview: Add --location, --no-location, and
+ --where.
+ - GNU `man' options: Add the GNU `man' long options that are
+ accepted by `groffer', but just ignored.
+ - MAN PAGE SEARCHING: Correct and extend this section.
+
+ * TODO:
+ - Remove entry on function headers.
+ - Remove entry on GNU `man' options.
+ - Remove entry on search algorithm for `man' pages.
+
+ ### Other fixes
+
+ * groffer2.sh:
+ - man_get(): On `man' page search with given name and section
+ handle also files with extension when no files without extension
+ are found.
+
+2006-09-11 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.25
+
+ ### Version information
+
+ * groffer2.sh:
+ - version(): Add groffer to the version information; replace the
+ call of `groff --version'.
+
+ ### Configuration Files
+
+ * groffer.sh: Fix the configuration handling by removing all
+ quotes. Arguments are ended by the end of the line.
+
+ * groffer.man: Fix the section on the configuration files.
+
+ ### Options
+
+ * groffer2.sh:
+ - $_OPTS_GROFF_SHORT_NA: Add `-k' as new groff option.
+ - main_pars_args(): Add X options `--ft', `--bordercolor',
+ `--borderwidth'.
+ - usage(): Add `--debug-filenames'. Remove `*-viewer-tty'.
+ Correct first line after call of version().
+ - main_parse_MANOPT(): Fix `-h', `-t', and `-u' as options without
+ argument.
+
+ * groffer.man:
+ - Add documentation to `--fn', `--ft', `--bordercolor',
+ `--borderwidth'.
+ - Remove the `--*-viewer-tty' options. These options are still
+ supported by the groffer program, but they aren't needed any
+ more.
+
+ ### soelim: Allow manpath and compressed files in .so requests, as
+ ### man does.
+
+ * groffer2.sh:
+ - $_FILESPEC_IS_MAN: New variable for storing if a filespec is for
+ searching a man page.
+ - to_tmp(): Rewrite. For existing file as filespec argument, add
+ call of `soelim' with the corresponding `-I dir' before the call
+ of `grog'. For man paged, uncompress and store the files from .so
+ requests; replace the requests with the stored file names.
+ - _do_man_so() of to_tmp(): New function to handle the file of a
+ .so request.
+ - man_get(): For man pages without extension, add special search
+ strategy.
+
+ * README: Add the .so handling to the Compatiblity section.
+
+ ### Print file names debug
+
+ * groffer2.sh:
+ - $_OPT_LOCATION: Replace this variable by
+ $_DEBUG_PRINT_FILENAMES.
+ - register_file(): Move file name printing and call to basename to
+ register_title().
+ - _do_man_so() of to_tmp(): Add file name printing for man pages.
+
+ ### modes
+
+ * groffer2.sh:
+ - $_DEFAULT_MODES: New set of default modes in the sequence 'pdf',
+ 'html', 'ps', 'x', 'dvi', and 'tty'. That is done because the `x'
+ mode viewers `gxditview' and `xditview' are very bad programs.
+ - _make_pdf() of main_display(): If pdf format can not be
+ generated use Postscript mode (ps) instead for display.
+ - $_PDF_DID_NOT_WORK, $_PDF_HAS_PS2PDF, $_PDF_HAS_GS: New
+ variables for pdf mode to avoid several runs.
+ - $_VIEWER_TTY_TTY, $_VIEWER_TTY_X: Add these variables for the
+ viewers in tty mode.
+ - main_display(): Rewrite tty mode by using where_is_prog() to add
+ options to `less' from the command line.
+
+ * groffer.man:
+ - Add this information.
+ - Adjust the viewers in `SEE ALSO'.
+
+ ### Check viewer option for programs running in X Window
+
+ * groffer2.sh:
+ - _check_X_prog() of main_set_mode(): New function for checking if
+ a program of a command line argument is in the list for X for this
+ mode.
+ - _get_first_prog() of main_set_mode(): Use where_is_prog();
+ change the output to the same 3-element list as _check_X_prog().
+ - _obj_set_vars() of main_set_mode(): New function for setting
+ some variables in several modes. Argument is the 3-element list
+ from _check_X_prog() or _get_first_prog().
+ - _process_mode() of main_set_mode(): Remove part with
+ list_has_not_prog(). This is better done by _check_X_prog().
+ - main_set_mode(): Use _check_X_prog() in different modes.
+ Correct several modes. Add reset of $_VIEWER_BACKGROUND at the
+ beginning of the loop of default modes.
+
+ ### Allow man pages with space characters
+
+ * groffer2.sh:
+ - man_is_man(): Fix grep calls.
+ - list_from_file(): New function that reads the lines of a file as
+ list elements.
+ - man_get(): Fix `case' applications by double-quoting all
+ variables. Use list_from_file() instead of setting with `cat'.
+ Add further tests.
+ - _do_man_so() of to_tmp(): Use list_from_file() instead of
+ setting with `cat'.
+
+ ### Allow program names with space
+
+ * groffer2.sh:
+ - is_prog(), is_not_program(): Change to exactly one argument with
+ possible spaces and arguments. Fix all calls.
+ - where_is_prog(): Change to exactly one argument. Change
+ variable prefix to `wip'. Rewrite it to support programs with
+ spaces and arguments. Return a list with 3 elements: the
+ program's directory, the program name, and the given arguments.
+ - main_display(): Correct tty mode.
+
+ ### Further fixes
+
+ * groffer2.sh:
+ - main_setup(): Fix func_check.
+ - clean_up(): Add variable to avoid several prints.
+ - where_is_prog(): Remove possible arguments from program
+ argument.
+ - obj_from_output(): As return value take the return value of the
+ called function.
+ - is_not_empty(): Rename of is_non_emtpy().
+ - $_VIEWER_BACKGROUND: Rename $_VIEWER_TERMINAL and reverse its
+ values.
+ - list_has_prog(), list_has_not_prog(): Remove these functions,
+ they are no longer needed.
+
+ * groffer.man:
+ - Add `--print' in OPTION OVERVIEW.
+ - Correct many entries with the non-breaking `\%' construct.
+
+2006-07-28 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.24
+
+ ### Extent long option abbreviation to abbreviations before each `-'.
+
+ * groffer2.sh:
+ - list_from_cmdline_with_minus(): New function, the same as
+ list_from_cmdline() with multiple abbreviations around `-'.
+ - _search_abbrev(): Subfunction of list_from_cmdline_with_minus().
+ - main_parse_args(): Use list_from_cmdline_with_minus() for
+ getting the double abbreviation, but keep main_parse_MANOPT()
+ to list_from_cmdline() for simple abbreviation of long options.
+ - For the debug test at the beginning, add the double abbreviation
+ functionality.
+
+ * README_SH, groffer.man: Document the multiple set of
+ abbreviations by `-'.
+
+ ### Fix handling of `--apropos*' and `--whatis'
+
+ * groffer2.sh:
+ - apropos_filespec(): Fix handling of `/' and `.' in sed; add `\&'
+ at the beginning of each non-macro groff line in sed.
+ - main_parse_args(): Set $_MAN_OPT to `yes' if --whatis is called.
+ - main_do_fileargs(): Fix dealing with `apropos' for several
+ cases.
+ - apropos_*(), special_*(), whatis_*(): Add two different return
+ values.
+ - $_SPECIAL_SETUP: New variable to test whether apropos_setup() or
+ whatis_header() had been run.
+ - Add language locale to --whatis, the `whatis' program does not
+ support this.
+
+ ### Handle several macro packages
+
+ * groffer2.sh:
+ - $_MACROS: New variable to store the actual macro package.
+ - $_MACRO_PACKAGES: New variable for the full macro packages of
+ groff (man, mdoc, me, mm, mom, ms).
+ - to_tmp(): Add test for different macro packages. Ignore files
+ with a different one.
+ - main_do_fileargs(): Add different macro check before doing man
+ pages.
+
+ ### Rewrite the man page search
+
+ * groffer2.sh:
+ - $_MAN_SEC_CHARS, $_MAN_SEC_LIST: New variables from $_MAN_SEC.
+ Add these to man_setup().
+ - man_get(): New function that finally gets the man page or man
+ pages for a filespec. Avoid double files.
+ - man_is_man(): New function that checks whether a name goes as
+ man page.
+ - manpath_add_lang_sys(): Fix handling of language addition for
+ short language names.
+ - main_parse_args(): Move handling of `-' to main_do_fileargs().
+ - do_filearg(), man_do_filespec(), man_register_file(),
+ man_search_section(): Remove these functions.
+ - main_do_fileargs(): Rewrite this function together with
+ the removed functions.
+ - list_uniq(): New function to remove the multiple elements from a
+ list.
+
+ ### Version handling.
+
+ * version.sh: New file for $_PROGRAM_VERSION, $_LAST_UPDATE, and
+ $_GROFF_VERSION_PRESET.
+
+ * groffer.sh:
+ - Add running of version.sh with `.'.
+ - Remove $_PROGRAM_VERSION and $_LAST_UPDATE.
+ - Run groffer2.sh with `.' instead of `exec'. This allows to have
+ groffer2.sh without executive access permission.
+ - Determine $_BEFORE_MAKE by @VERSION@, use this variable on more
+ places.
+
+ * groffer2.sh:
+ - Remove executive access permission.
+ - version(): Write a version information without calling groff.
+
+ * Makefile.sub:
+ - Add version.sh. Use $(INSTALL_DATA) instead of
+ $(INSTALL_SCRIPT) for version.sh and groffer2.sh.
+ - Add $(DESTDIR) to some elements of `sed' call in `groffer:'.
+
+ ### viewers for different modes
+
+ * groffer2.sh:
+ - $_VIEWER_HTML_X: Add `epiphany' as browser.
+ - $_VIEWER_PDF_X: Add `kpdf' and `evince' as pdf viewer for X.
+ Make `kpdf', `acroread', `evince', and `xpdf' the first automatic
+ pdf viewers for X because they support searching. Add `gpdf'.
+ - $_VIEWER_PS_X: Add `kpdf' and `evince' as ps viewer for X; make
+ `kpdf' the first automatic ps viewer for X because it supports
+ searching even for Postscript.
+
+ ### pdf mode
+
+ * groffer2.sh:
+ - _make_pdf() of main_display(): add `ps2pdf' as secondary
+ transformer.
+ - main_set_resources(): Allow setting of resolution for `xpdf'
+ only if option -z is not set for `xpdf'.
+
+ ### Revise $_VIEWER_*
+
+ * groffer2.sh:
+ - $_VIEWER_<mode>_TTY: Add this variable to each mode even if it
+ is only empty.
+ - $_VIEWER_<mode>_X: Rename $_VIEWER_<mode> to this for each
+ mode.
+
+ ### Other fixes
+
+ * groffer2.sh:
+ - is_empty_file(): New function.
+ - obj_from_output(): Quote arguments by building a list.
+ - path_list(): Output path list with unique elements.
+ - where_is_prog(): Rename where_is(). Handle all file names
+ having a slash somewhere instead of only those that start with a
+ slash.
+ - $_REG_TITLE_LIST: Replace $_REGISTERED_TITLE and make it a
+ list.
+ - $_OPT_TITLE: Make it a list with at most 1 element.
+ - Remove double quotes in case patterns.
+ - _func_test(): For the function test at the beginning, add this
+ function for output check with $() construct.
+ - usage(): Add --shell.
+ - $_VIEWER_HTML_X: Add `firefox' and `mosaic'.
+ - list_get(): Remove this unused function.
+ - Fix func_check() calls in all functions.
+
+ * groffer.sh: Adjust groff version to 19.3.
+
+ * README: Add information list of the source files.
+
+2006-02-26 Claudio Fontana <claudio@gnu.org>
+
+ * Makefile.sub: Add DESTDIR to install and uninstall targets
+ to support staged installations.
+
+2005-09-14 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.23
+
+ ### Increase the speed for the search of man pages
+
+ Run `find' on all man directories and ask this with `grep' instead
+ of scanning through many `ls'.
+
+ * groffer2.sh:
+ - $_TMP_MAN: New variable with the name of the file that stores
+ the `find' of the man path.
+ - $_TMP_MANSPEC: New variable with the name of the file that
+ stores the man page file names for each filespec.
+ - man_setup(): Do the `find' of the man path with $_TMP_MAN.
+ - man_do_filespec(): Add creation of $_TMP_MANSPEC.
+ - man_search_section(): Rewrite it to use $_TMP_MANSPEC.
+
+ * TODO: The demand on the increase of speed for man pages is now
+ removed.
+
+ ### Increase speed by enhancement of debug
+
+ * groffer.sh: $_BEFORE_MAKE: New variable that stores whether the
+ @...@ constructs are still available or already transformed by
+ `make'.
+
+ * groffer2.sh:
+ - $_DEBUG_FUNC_CHECK: New debug variable that regulates the check
+ calls at the beginning and end of most functions done by the
+ functions func_<name>(). By default, this is enabled before the
+ run of `make', and disabled after. $_DEBUG_STACKS and
+ $_DEBUG_USER_WITH_STACK enable this variable automatically.
+ - --debug-func: New option for setting $_DEBUG_FUNC_CHECK.
+ - usage(), main_parse_args(): Add information for --debug-func.
+ - func_<name>(): Disable these functions if $_DEBUG_FUNC_CHECK is
+ not `yes'.
+
+ * groffer.man:
+ - Add information on --debug-func.
+ - Move the sections on options for development to the end of
+ option processing.
+
+ ### Fixes of man page search
+
+ - man_search_section(): Repair it such that extensions do not
+ occur in the directory name.
+ - manpath_set_from_path(): Rewrite it. Add `.../MAN/...'
+ subdirectories additionally to `.../man/...'.
+ - manpath_add_lang_sys(): Rewrite it to overwrite _MAN_PATH by
+ systems parameter if any. Then _MAN_PATH is prepended by the
+ language part.
+ - _manpath_add_sys(): New subfunction of manpath_add_lang_sys() to
+ handle the systems part.
+ - man_search_section: Fix it to handle section names that have
+ more than one character (an extension).
+ - $_MAN_PATH: Now stores man path as a list. This is done in
+ man_setup() and manpath_set_from_path(), and used in
+ manpath_add_lang_sys().
+ - $_MAN_SYS: Now stores man systems parameter as a list. This is
+ done in man_setup() and used in manpath_add_lang_sys().
+ - $_MAN_SEC_DONE, $_MAN_SYS_DONE, $_MAN_LANG_DONE: Remove these
+ variables.
+
+ ### Reorder the beginning of groffer2.sh
+
+ * groffer2.sh:
+ - func_<name>(): Move these functions to the functions in
+ alphabetical order.
+ - main_init(): Move "Test for compression" to this function.
+ - Move the "System Test" and function landmark() to the beginning
+ "Test of rudimentary shell functionality". Change landmarks 1 and
+ 2 to new positions.
+
+ ### Fix the mode when not in X
+
+ * groffer2.sh:
+ - main_parse_args(): Accept modes even when not in X, hoping for a
+ program given by option. Add $_OPT_VIEWER_<MODE>_TTY. Remove
+ $_VIEWER_TERMINAL.
+ - main_set_mode(): Add a section to set $_VIEWER_TERMINAL and move
+ the value of $_OPT_VIEWER_<MODE>_TTY to $_OPT_VIEWER_<MODE>. When
+ not in X and no terminal programs are set remove $_OPT_MODE. All
+ unknown programs are treated as terminal programs.
+ - usage(): Comment out options --<mode>-viewer-tty. They exist
+ and are handled by `groffer', but they are no longer documented.
+ - $_OPT_VIEWER_<MODE>_TTY: New variables for option
+ --<mode>-viewer-tty.
+ - $_DEFAULT_MODE, $_VIEWER_<MODE>: Change it from , separation to
+ a list. Rewrite _get_first_prog() of main_set_mode() to get
+ around with this.
+
+ * groffer.man: Remove information on --<mode>-viewer-tty.
+
+ ### Debug
+
+ * groffer2.sh:
+ - $_DEBUG_PRINT_FILENAMES: New variable for printing the file
+ names that are displayed by `groffer'.
+ - --debug-filenames: The corresponding option. It is used in
+ man_register_file(), register_file(), and main_parse_args().
+
+ * groffer.man: Add information on --debug-filenames.
+
+ ### Other changements
+
+ * groffer2.sh:
+ - is_greater_than(): New function. Use it where suitable.
+ - lists_combine(): New function to combine several lists to a
+ single list.
+ - list_from_split(): Rewrite it to output a list with quoted
+ elements.
+ - list_has_prog(), list_has_not_prog(): New functions to check the
+ list on an element that starts with a given word.
+ - obj_from_output(): Use this function at many places instead of
+ `var="$(...)"'; this makes the usage of exit_test() unnecessary.
+ - path_clean(): Fix assignment.
+ - path_list(): Rename path_split().
+ - tmp_create(): Add check of temporary file.
+ - usage(): Fix.
+
+ * README_SH:
+ - Fix section `Error handling'.
+ - Add section `Speed'.
+
+2005-08-22 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.22
+
+ ### `--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 <keith.d.marshall@ntlworld.com>
+
+ * 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.
+
+2005-08-02 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.21
+
+ ### @...@ 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 <<EOF'. Replace
+ all `echo x' by `echo1'.
+ - list_has_abbrev(), list_from_cmdline(): Correction.
+ - main_parse_MANOPT(): Repair and revise.
+ - --do-nothing: New option without output (for development).
+ - Rewrite rudimentary shell functionality near the beginning of
+ the script.
+
+ * groffer.sh, groffer2.sh:
+ - Remove `;' after the commands `if', `while', and `until'.
+
+ ### Debugging information
+
+ * groffer2.sh:
+ - $_DEBUG_PRINT_PARAMS: New variable for printing all parameters
+ from the config files, $GROFFER_OPT, and command line after they
+ have been transformed.
+ - $_DEBUG_PRINT_SHELL: New variable for printing the name of the
+ shell found in groff.sh.
+ - main(): Move the landmarks of main-*() into main().
+
+ ### Further checks and additions
+
+ * groffer.sh, groffer2.sh:
+ - $_PROGRAM_NAME: Replace this variable by `groffer'. The program
+ name is now stable.
+ - $_GROFFER_RUN: Remove this variable. As `groffer.sh' or
+ `groffer' is no longer rerun, this variable is not necessary any
+ more.
+
+ * groffer2.sh:
+ - main_set_resources(): Make the default viewers capable to use
+ arguments in the list.
+ - leave(): Add an argument for given exit code. Use it where
+ suitable in main_*().
+ - do_filearg(): Add error messages for non-existing files and man
+ pages.
+ - _do_opt_V(): New subfunction of main_display() to handle the
+ output for option `-V'. `groff -V' is greatly enlarged by
+ `groffer' specific information.
+ - register_title(): Handle file names with spaces. Replace spaces
+ by `_'.
+ - is_existing(): Add `test -c' for special files.
+ - usage(): Add `=arg' to the options with an argument. Add option
+ `--tty-viewer'.
+ - kghostview: In the default viewer list, add option
+ `--scale=1.45'.
+ - $_OPTS_CMDLINE_SHORT_NA: Correct a lacking space.
+
+ * Makefile.sub: Repair the installation instructions for
+ groffer2.sh.
+
+ * groffer.man:
+ - Add paragraph on option handling.
+ - Add option `--do-nothing'.
+ - Reorder option for development and `groff'.
+ - Rewrite documentation for option `-V'.
+ - Expand `--shell'.
+ - Reformulate sections CONFIGURATION FILES, COMPATIBILITY and SEE
+ ALSO.
+ - Make `man' italic where possible.
+ - .copyleft: Adjust the fonts.
+
+ * README: Update sections `Output' and `Compatibility'.
+
+ * README_SH:
+ - Add `mksh' as compatible shell.
+ - Add information on the scripts after the split.
+
+ * TODO: Remove some fulfilled parts.
+
+ * ChangeLog: Remove final spaces.
+
+2005-07-30 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.20
+
+ ### Split groffer.sh into two files groffer.sh and groffer2.sh.
+
+ * groffer.sh:
+ - Remove the second part of this script. It is now in
+ groffer2.sh.
+ - $_GROFFER2_SH: New variable to point to the installed position
+ of `groffer2.sh'. This position is presented using @libdir@.
+
+ * groffer2.sh: New script containing the second part of
+ groffer.sh. This script will be installed in the groffer library
+ directory @libdir@/groff/groffer, this might be
+ /usr/local/lib/groff/groffer/groffer2.sh for example.
+
+ * Makefile.sub:
+ - `groffer': Add replacement of @libdir@.
+ - `install_data': Add the installation of the groffer library
+ directory and groffer2.sh.
+ - `uninstall_sub': Delete the installed `groffer2.sh' and the
+ groffer library directory.
+
+ * README_SH:
+ - Remove the function list.
+ - Add argument options to the list of used commands.
+ - Documentation of the splitting of the script.
+ - Document the possible abbreviation of options.
+
+2005-07-07 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.19
+
+ * groffer.sh: extensions
+ - `mode x': Mode for the equivalent options `--x', `--mode x',
+ `--X' `--mode X', and the default mode. The default assumes a
+ resolution of 75 dpi. The default device for a resolution of 75
+ dpi is `X75-12', the default device for a resolution of 100 dpi is
+ `X100'. The default geometry for the resolution of 100 dpi is set
+ to the width 800 dpi.
+ - `mode X': New mode for option -X only.
+ - `-V': Extent the `groff' output of -V by `groffer' specific
+ information (in main_display()).
+ - register_file(): Replace title `-' by `stdin'.
+ - $_DEBUG_KEEP_FILES: If set to `yes' the files in the temporary
+ directory are not deleted before the end trap.
+
+ * groffer.sh: get `zsh' to work as well
+ - tmp_create(): Use `: >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.
+
+2005-07-01 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.18
+
+ * 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 <<EOF'. `echo -n' seems to be not
+ portable, so it is omitted.
+ - `for': Remove `;' from within `for' (because of ksh).
+ - `ls': Old UNIX systems echoed the error message to standard
+ output. So handle the output with `sed'. If the output contains
+ `not found' map it to an empty string.
+ - `true': Replace `true' by command `:'. Remove test of `true'
+ (because `ash' refuses the redefinition of builtins even in an
+ unreachable `if' branch).
+ - `false': Remove test of `false'; it isn't used any more.
+ - `test': As `test -e' does not exist in Solaris 2.5 replace it by
+ `test -f || test -d'.
+ - `unset': `unset' is said to be not portable. As `ash' protests
+ against the definition of the function `unset()' in the test of
+ `unset' replace the test by defining `$unset' to `unset' if it
+ exists and to `:' otherwise. Use `eval $unset' instead of the
+ direct command `unset'.
+ - _get_opt_shell(): Replace `for' loop with `shift' by `while'.
+ - man_search_section(): Replace `for f in filename*' by a test on
+ the existence of `filename*'.
+ - `zsh' interprets `$...' as `"$..."'. So `eval' must be called;
+ This cannot be used in `for i in $f', so it must be rewritten as
+ `for i in $(eval set x $f; shift; echo "$@")'
+
+ * groffer.sh:
+ - `--X', `--x', `--mode=X', `--mode=x': Make these options
+ equivalent to choosing an X device by setting `-TX75-12'. `-X' is
+ still equivalent to `groff -X'.
+ - main_init(): Choose the name of the temporary file by adding a
+ number using `expr' if it exists and cannot be removed.
+ - main_parse_args():Repair some options by replacing `$mpa_mode'
+ by `$_OPT_MODE'.
+ - catz(): Rename it to cat_z() to avoid problem with existing
+ programs.
+ - where(): Rename to where_is().
+ - $_CONFFILES: Rename to $_CONF_FILES.
+ - $_HAS_BZIP: export and preset it.
+
+ * groffer.man:
+ - Document the `X mode' changes.
+ - Add `@g@' to `troff'.
+
+ * README, README_SH, TODO:
+ - Add date line `Latest update:'.
+ - Add `...' quoting to essential terms.
+ - Add Emacs mode at the end.
+
+ * README_SH:
+ - Add documentation on the above compatibility changes.
+ - Add documentation on used commands.
+ - Mention the tested shells.
+
+ * Makefile.sub:
+ Readd `@g@'.
+
+2005-06-23 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.17
+
+ * groffer.sh: get rid of `local' in functions (it is not POSIX)
+ - Replace local variables by variable names with a special prefix
+ that is an abbreviation of the corresponding function name (quasi-
+ local variables).
+ - Unset the quasi-local function variables before returning.
+ - _t_e_s_t_f_u_n_c_(): Remove tests for local and global
+ variables.
+ - Add quasi-local variables for saving the content of
+ single-character variables.
+ - Remove some unused local and global variables.
+ - Several variables were forgotten to make local. They are now
+ made quasi-local.
+
+ * groffer.sh: other corrections
+ - $return_var: New function (after `eval') for an arbitrary
+ return value.
+ - obj*(): Add return modes.
+ - Rewrite tests for `true' and `false'.
+ - Add function names to error calls where it was forgotten.
+ - `for': Replace `for x in "$@"' by `for x'.
+ - `set': Replace `set -- ...' by `set x ...; shift'.
+ - `sed': Replace `\|.*|s|...|...|' by `s|...|...|'.
+
+ * README_SH:
+ - Add information on the removing of `local'.
+ - New section for non-POSIX shell restrictions.
+
+2005-06-20 Keith Marshall
+
+ * README-SH: Information of `Portable shells' in info autoconf.
+
+2005-06-19 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.16
+
+ * groffer.sh: Place each `then', `else', and `do' on a line of its
+ own because some shells do not support the mixture mode.
+
+ * groffer.man: Add section `BUGS'.
+
+ * README_SH:
+ - Add compatibility information.
+ - Correct documentation for function arguments.
+
+2005-06-18 Keith Marshall
+
+ * groffer.sh: $_NULL_DEV: Replace /dev/null by $_NULL_DEV which is
+ either /dev/null or NUL if /dev/null does not exist.
+
+2005-06-17 Zvezdan Petkovic
+
+ * Makefile.sub: $(RM): Define it to `rm -f' because not all `make'
+ programs have it predefined.
+
+2005-06-16 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.15
+
+ * Makefile.sub:
+ - Use `$(RM)'.
+ - Use `sed -f $(SH_DEPS_SED_SCRIPT)'.
+
+2005-05-20 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.14
+
+ * groffer.man: correction of non-hyphenation
+
+2005-05-17 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.13
+
+ * groffer.sh:
+ - $_VIEWER_DVI: Add `kdvi'.
+ - $_VIEWER_PDF: Add `kghostview', `ggv', and `kpdf'.
+ - $_VIEWER_PS: Add `kghostview' and `ggv'.
+ - $_modefile: For the output file name, add extension .ps for ps
+ mode and .dvi for dvi mode. This exists already for the html and
+ pdf modes.
+ - Update some parts of the documentation.
+
+ * README, README_SH:
+ - Move some parts on usage from README_SH to README.
+ - Reformulate several parts of both files.
+
+ * groffer.man: update
+
+2005-05-14 Keith Marshall
+
+ * groffer.sh:
+ - first line: Add space to `#! /bin/sh'.
+
+2004-11-15 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.12
+
+ * groffer.sh:
+ - main_init(): Rewriting of the creation of the temporary
+ directory to ensure that it cannot be made writable apart from the
+ user. If the directory already exists and cannot be removed then
+ append `X' to the directory name.
+ - is_non_empty_file(): fix it to use POSIX `test -s'.
+ - is_existing(): new function.
+ - POSIX `rm -f -r': use this in `clean_up()' and `main_init()'.
+ - `--macro-file': remove this unused long option.
+ - `-V', `--source', `--device': move these from groff options
+ to groffer options.
+ - `$_TMP_DIR_SUB': remove this unused variable.
+
+2004-06-15 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.11
+
+ * groffer.sh:
+ - To the search of the `--apropos-*' options, add man pages with a
+ subsection in their apropos output.
+
+2004-06-02 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.10
+
+ * groffer.sh:
+ - Remove automatic call of `ash' due to inconsistencies of
+ different ash versions.
+ - In the first run, add recognition of `--shell' lines in the
+ groffer configuration files. To configure an external shell in
+ a configuration file, a line starting with `--shell' is
+ necessary.
+ - list_from_cmdline(): Simplify the arguments.
+ - As $POSIXLY_CORRECT is internally set to `y' by some GNU
+ `/bin/sh' shells the following 2 fixes are necessary:
+ -- `sed': Empty patterns are not allowed with $POSIXLY_CORRECT
+ set; so move the address information before the `s' command to the
+ pattern after the command, and write `.*' to the address field.
+ -- list_from_cmdline(): Remove the strange $POSIXLY_CORRECT style
+ to finish the option processing after the first non-option
+ argument; use the flexible GNU mixing of options and file names
+ instead.
+
+ * groffer.man:
+ - Remove any hints on `ash'.
+ - Add minus line behavior of `--shell' for configuration and add a
+ corresponding example.
+ - Update the information on $POSIXLY_CORRECT.
+
+2004-05-29 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.9
+
+ * groffer.sh:
+ Fix first run section to allow the starting shell to go on if
+ `ash' is not available.
+
+ * groffer.man:
+ Remove unnecessary information on groffer version.
+
+2004-05-12 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.8
+
+ * groffer.sh:
+ Fix problems of `test' by adding subs to arguments.
+
+ * groffer.man:
+ Write the file license as macros that are called in sections
+ AUTHOR and COPYING.
+
+ * .cvsignore:
+ Restore this file.
+
+2004-04-30 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.7
+
+ * groffer.sh:
+ - obj(), obj_data(), obj_from_output(), obj_set(): New object
+ oriented functions to minimize complicated `eval' commands.
+ - list_*(): Corrections.
+ - usage(): Streamlining.
+
+ * groffer.man, README_SH:
+ Corrections.
+
+2004-04-27 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.6
+
+ This version replaces the license of all files except ChangeLog of
+ the groffer source to the GNU General Public License (GPL) of the
+ version described in files COPYING and LICENSE in the groff top
+ source directory.
+
+ * groffer.man:
+ Changement from the GNU Free Documentation License (FDL) to
+ the GNU General Public License (GPL).
+
+ * README, README_SH, TODO:
+ Add license GNU General Public License (GPL).
+
+ * Makefile.sub, groffer.sh:
+ Keep the GNU General Public License (GPL), but refer to the
+ COPYING and LICENSE files.
+
+ * ChangeLog: Add a license in the style of Emacs ChangeLog file,
+ which is weaker than the GPL, but has its flavor.
+
+2004-04-24 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.5
+
+ This version is a rewrite of groffer in many parts, but it is kept
+ in the old single script style.
+
+ Overview of new options:
+ --text, --mode text, --tty-viewer,
+ --X, --mode X, --X-viewer, --html, --mode html, --html-view,
+ --apropos-data, --apropos-devel, --apropos-progs
+
+ New file:
+ <groffer-source>/README_SH
+
+
+ ******* Extension of the `apropos' handling
+
+ The output of man's `apropos' has grown immensely meanwhile, so it
+ has become inefficient. Now `groffer' provides new options to get
+ the a selected information from this output.
+
+ * groffer.sh:
+ `--apropos-progs': new option for displaying only information
+ on programs (man page sections 1, 6, and 8)
+ `--apropos-data': new option for displaying only information
+ on documented data (man page sections 4, 5 and 7)
+ `--apropos-devel': new option for displaying only information
+ on development documentation (man page sections 2, 3 and 9)
+ `--apropos': still displays just the output of man's `apropos'
+ program.
+ - Specify all of these options as a single argument option; that
+ makes groffer's `--apropos' option slightly different because
+ the corresponding `man' option does not have arguments, but takes
+ all file arguments as apropos targets. So just ignore the `man'
+ options `-k' and `--apropos' in the parsing of $MANOPT.
+ - Exit after processing one `apropos' call.
+
+
+ ******* Quasi object oriented function arguments
+
+ An object is the name of an environment variable. The value of
+ this variable contains the object's content. This allows to
+ specify function arguments and the calling syntax in a simpler way
+ by letting the first argument be a variable name, usable for input
+ or output.
+
+ Such an object type is `list', the string value of a shell
+ variable arranged in space-separated single-quoted elements, such
+ as $GROFFER_OPT internally.
+
+ * groffer.sh:
+ - Remove list_from_args(), list_element_from_arg()
+ list_from_lists(), list_length(), and list_prepend().
+ They can be replaced by list_append().
+ - All list*() functions are rearranged such that the first
+ argument is a list object, the name of a variable.
+
+
+ ******* Simplification of configuration files
+
+ The new syntax of the groffer configuration files is
+ - all lines starting with a `-' character are interpreted as
+ command line options for all calls of groffer; they are collected
+ and prepended to the actual value of $GROFFER_OPT; optional
+ spaces at the beginning.of the line are omitted.
+ - all other lines are interpreted as a shell command and executed
+ in the current shell of the groffer call.
+
+ Precedence:
+ - The command line and the external environment variables such as
+ $GROFFER_OPT of the groffer call have the highest precedence.
+ - This is overwritten by the configuration file in the user's home
+ directory.
+ - The system configuration file in /etc has the lowest
+ precedence.
+
+ * groffer.sh:
+ The configuration files are now called after the determination of
+ the temporary files in main_init().
+
+
+ ******* Script file name
+
+ The file name of the script is needed for the several calls during
+ the search for the optimal shell.
+
+ * groffer.sh:
+ - $_GROFFER_SH: replace $_this by $_GROFFER_SH and use $0 for
+ determining the file name of the script for the following calls,
+ instead of the cumbersome @BINDIR@ construction.
+ - Force the script to be called as an executable file, so $0 must
+ contain the program name.
+
+
+ ******* Improved temporary file names
+
+ Just like groff, groffer mixes all file parameters into a single
+ output file. Its name is now constructed as a comma-separated
+ list built from the file name arguments without a leading comma.
+ So a leading comma can be used for the internal temporary file
+ names.
+
+ * groffer.sh:
+ - $_OUTPUT_FILE_NAME: new global variable as basis for the output
+ file name; it is set in main_set_resources().
+ - tmp_create(): use `,name' for temporary files different from
+ output file because the output file name does not start with a
+ comma. `$$' is not needed anymore.
+ - main_display(): simplification of $_modefile in _do_display()
+ and single display modes.
+ - Add extension `.html' to output file name in html mode.
+ - base_name(): correction for strange positions of `/'.
+
+
+ ******* Mode fixes
+
+ * groffer.sh:
+ - Set the main default mode to `x' with groff's X Window viewer
+ `gxditview'.
+ - Allow 'x' and 'X' in `--mode' for the X Window mode; the same
+ for `--x' and `X', `--x-viewer' and `--X-viewer'.
+ - Make groff's `-X' equivalent to `mode X'.
+ - Fix `--auto', `--mode auto', and `--default-modes'.
+ - `html' mode: new mode equivalent to `www', add `konqueror' and
+ `lynx' as viewers.
+ - `pdf' mode: fix zoom options for pdf-viewer `xpdf' in
+ main_set_resources(); in main_display() fix the display structure.
+ - Set default X Window resolution to 75dpi. This is not optimal,
+ but with a higher value the options and resources for some viewers
+ must be optimized.
+ `--text' and `--mode text': new option for text output without a
+ pager.
+ - `--tty-viewer': new option equivalent to `--pager'.
+ - Correct the pagers for `tty' mode.
+ - Fix `groff' mode in main_set_resources() and main_display().
+ - Harmonize `--mode arg' with the equivalent options `--arg'.
+
+
+ ******* Fixes for command line options
+
+ * groffer.sh:
+ - list_from_cmdline(): fix the parsing of options with arguments.
+ - Rename $_OPT_TTY_DEVICE to $_OPT_TEXT_DEVICE.
+ - $_OPTS_X_*: new variables for the inhereted X Window variables.
+ - Improve the distribution of the command line options into
+ $_OPTS_GROFFER_*, $_OPTS_GROFF_*, $_OPTS_X_*, and $_OPTS_MAN_*.
+ - $_OPTS_MANOPT_*: new variables for the parsing of $MANOPT.
+ - Correct $_OPTS_CMDLINE_*.
+ - Remove some unused $_OPTS_*.
+ - `--iconic': new option from `-iconic' of the X Window toolkit.
+ - Correct `--rv' to an option without argument.
+ - Minor fixes of other X Window toolkit options.
+
+
+ ******* Other fixes
+
+ * groffer.sh:
+ - is_prog(): allow 0 arguments.
+ - is_not_writable(): new function.
+ - is_*(): fix trailing return codes.
+ - Replace most `test' calls by is_*() functions.
+ - man_setup(): due to bugs in `manpath', prefer
+ manpath_set_from_path() for the determination of the man page path.
+ - man_search_section(): correction of some `for' loops.
+ - Remove export of external non-groffer variables.
+
+
+ ******* Documentation
+
+ * groffer.man:
+ - Reorder the option details according to the option origin as
+ groffer, groff, X, and man options.
+ - Add the programming changes information mentioned above.
+ - Support man pages with a dot in their name
+
+ * README_SH: new file
+ Move large parts of the documentation in `groffer.sh' into this
+ file.
+
+ * groffer.sh: usage():
+ - Change the output for `--help' to standard output.
+ - Restructure the information for this help output.
+
+
+ ******* Removement of the author's email address
+
+ Because of the extreme spam attacks, the author removed all
+ occurencies of his email address in every file of the groffer
+ source.
+
+2003-01-22 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.4
+
+ * groffer.sh: corrections for some restrictive shells
+ - Possible exit codes in actual `ash' are between 0 and 63. To
+ handle even deeper restrictions, use 7 as maximal code instead
+ of 255 as replacement for error -1.
+ - Remove variables $_BAD2 and $_BAD3.
+ - Replace `trap' argument `EXIT' by 0 and write new fuctions
+ `trap_clean' and `trap_set' to handle the restrictions of `trap'
+ for some shells.
+ - Correct wrong $MANPATH to $_MAN_PATH in function
+ `man_do_filespec'.
+ - 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 <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.3
+
+ * groffer.sh: new temporary subdirectory
+ - Generate temporary subdirectory for storing temporary files
+ with better names in future groffer versions (name:
+ "groffer$$" in usual temporary directory).
+ - Use `umask 000' for temporary files to allow cleaning up
+ for everyone after a system break.
+ - Change both clean_up() functions (for normal shell and
+ for main_display() subshell) to handle the new subdirectory.
+ - clean_up_secondary() and $_TMP_PREFIX are unnecessary now, so
+ they were removed.
+
+ * Makefile.sub: `sed' commands for "groffer:"
+ - Remove "@g@" entry (not used in "groffer.sh").
+ - Add global replace for "@BINDIR@" and "@VERSION@" for future
+ usage.
+
+ * TODO: think about...
+ - writing part of groffer in C/C++.
+ - handling several files with different macro packages.
+
+2002-10-17 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * fixes of groffer 0.9.2
+
+ * groffer.sh:
+ Terminate main_parse_MANOPT() if $MANOPT is empty or consists
+ of space characters only.
+
+ * groffer.man: some fixes in "GROFFER OPTIONS"
+ - 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 <groff-bernd.warken-72@web.de>
+
+ * Makefile.sub:
+ add replacement "@BINDIR@" to "$(bindir)" for "groffer:"
+
+ * groffer.sh:
+ Define $_this as "@BINDIR@/${_PROGRAM_NAME}" to save the right
+ installation position of groffer for the special shell calling.
+
+ * groffer.man:
+ Remove double definition of filespec parameters.
+
+2002-10-13 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.2
+
+ * groffer.sh: fixes
+ - Fix some 'sed' functions: two in func_stack_dump(), one in
+ base_name(), add 'sed' command in list_from_cmdline().
+ - Finish main_parse_MANOPT() if $MANOPT is empty.
+ - Sort $_OPTS_GROFF_SHORT_NA like groff short options (but
+ unchanged).
+ - Fix some comments.
+
+ * groffer.man: make it more readable (but no additions)
+ - A shortened section "SYNOPSIS" is followed by a simplified
+ section "DESCRIPTION".
+ - The options from "SYNOPSIS" go to new section "OPTION
+ OVERVIEW" with all groffer options in a single subsection.
+ - The details of all groffer options are described in section
+ "GROFFER OPTIONS".
+ - New macro for file names ".File_name".
+ - "Option Parsing" is moved to section "COMPATIBILITY".
+ - Fix some "EXAMPLES".
+
+2002-09-30 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.1
+
+ * TODO: remove done entries
+ - Remove request for different shells.
+ - Remove the 'sed' complaints.
+
+2002-07-15 Bernd Warken <groff-bernd.warken-72@web.de>
+
+ * groffer.sh: replace `sed' interface by direct `sed'
+ - This improves the performance of the shell programming parts
+ and shortens the groffer script by about 5%.
+ - Remove functions: string_del_append(), string_del_leading(),
+ string_del_trailing(), string_flatten(), string_get_before(),
+ string_get_leading(), string_replace_all(), string_sed_s(),
+ and their auxiliary functions.
+ - Replace all calls of these functions by direct `sed' commands.
+ - Define variables for special characters to ease `sed' calls.
+ - Remove `$APPEND'.
+ - Restrict list_from_string() to single character separators.
+ - Correct list_check() and base_name().
+ - Add comments to all calls of `sed'.
+
+ * groffer.sh: add run-time support for several shells
+ - New option `--shell': stop execution and rerun groffer under
+ the shell specified in the argument of `--shell'.
+ - If no shell was specified at run-time, `ash' is tried first;
+ if `ash' is not available continue with the shell with which
+ 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 <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * fixes for groffer 0.9.0
+
+ * groffer.sh: enhance version information
+ `groffer -v|--version' now print:
+ - groffer's version number and date
+ - 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
+ line consisting of a single space character in this case for
+ all display modes (not for source or groff modes).
+
+ * TODO:
+ fix entry `shoop' (not 'shopt').
+
+2002-06-28 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.9.0
+
+ * groffer.sh: new mode `pdf'
+ - PDF (Portable Document Format):
+ -> Transform groff `ps' output into pdf using `gs'.
+ -> Pro: PDF viewers provide text searching (!).
+ -> Con: the transformation is quite slow.
+ -> Not suitable as an auto mode.
+ - 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 <groff-bernd.warken-72@web.de>
+
+ * groffer.sh:
+ Fix `source' mode.
+
+ * groffer.man:
+ Fix some indentations.
+
+2002-06-23 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.8
+
+ * Makefile.sub: add copyright section
+
+ * groffer.man:
+ - Document the new options.
+ - Revise the documentation of the modes.
+ - 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.
+ - Add a function call stack for suitable functions; implemented
+ as within the argument checker func_check().
+ - This implies the need to provide `return' with some clean-up
+ facility; implemented as `eval "$_return_..."'.
+ - Add option `--debug' to enable debugging at run-time.
+ - 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
+ some situations in the `groff' mode, so a new infrastructure
+ for viewer customization is necessary.
+ - Allow to specify arguments to the viewer programs specified
+ in `--*-viewer()'.
+ - Implement some of the essential X Toolkit resource options in
+ groffer, but with use a leading double minus.
+ -> `--bd': set border color.
+ -> `--bg', `--background': set background color.
+ -> `--bw': set border width.
+ -> `--display': set X display.
+ -> `--geometry': set size and position of viewer window.
+ -> `--fg', `--foreground': set foreground color.
+ -> `--ft', `--font': set font.
+ -> `--resolution': set X resolution in dpi.
+ -> `--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;
+ -> `--ps-viewer' sets the Postscript viewer.
+ - New mode `www' (`--www') for displaying in a web browser:
+ -> default browsers: mozilla,netscape,opera,amaya,arena;
+ -> `--www-viewer' sets the web browser.
+ - New dvi mode (`--dvi'); default viewer `xdvi':
+ -> default viewers: xdvi,dvilx;
+ -> `--dvi-viewer' sets the dvi viewer.
+ - New mode `auto':
+ -> active if no other mode is given or by new option `--auto';
+ -> selects from a sequence of modes that are tested until one
+ of them succeeds.
+ -> the default mode sequence is actually `ps', `x', `tty'.
+ -> `--default-modes' sets this mode sequence as a comma
+ separated string of program names, optionally each one
+ with arguments).
+ - New mode `groff':
+ -> process input like groff, ignore viewing options.
+ -> activated by new option `--groff'.
+ -> 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.
+ -> intermediate output mode is now part of mode groff; remove
+ any special features around `-Z'.
+ - Update usage() to reflect the new option structure.
+
+ * groffer.sh: add configuration files
+ - `/etc/groff/groffer.conf' system-wide configuration.
+ - `${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;
+ embedded single-quotes are escaped.
+
+ * groffer.sh: new option parser based on `list':
+ - Write new option parser based on `list', compatible to both
+ POSIX getopts() and GNU getopt().
+ - Long options are now available on GNU and non-GNU systems.
+ - Get rid of POSIX getopts() and GNU getopt().
+ - the `-W--longopt' construct is now obsolete; remove it.
+ - add test/function for `unset'.
+ - Option strings are now implemented as `list's in order to
+ 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 <wl@gnu.org>
+
+ * groffer.sh:
+ Implement man option `--ascii' by `-mtty-char'.
+
+
+2002-05-31 Werner LEMBERG <wl@gnu.org>
+
+ * groffer.man (@.Shell_cmd_width):
+ Increase to 4m (we use `sh#' as the prompt).
+
+
+2002-05-31 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * release of groffer 0.7
+
+ * groffer.sh: remove incompatibilities with the `ash' shell:
+ - do not use `!command':
+ -> use `else'
+ -> write `_not_' equivalents for some functions
+ - do not use `[^]' in `case':
+ -> restructure some functions.
+ - only single-character names for loop variables:
+ -> spoils the paradigm of leading `_' for local variables.
+ - spurious trouble with `for i in ${var}':
+ -> use `eval set -- ${var}' and `for i in "$@"'
+ - do not change or use $IFS:
+ -> define new functions string_split() and `path_split()'.
+ -> result must be processed by `eval set --'.
+ -> solve conflicts with existing positional parameters.
+ - trouble with exporting external `$GROFF_*' variables:
+ -> hope that they were exported in the calling shell.
+ - not smart about additional blanks:
+ -> remove unnecessary white space.
+
+ * groffer.sh: improve run-time speed:
+ - `ash' more than doubles the speed of `bash'.
+ - speed-up `man_setup()'.
+
+
+2002-05-30 Werner Lemberg <wl@gnu.org>
+
+ * groffer.man:
+ - remove some wrong `\:'.
+ - rename macro names that start with a `[' (clashes with refer).
+ - fix TP_header.
+
+
+2002-05-28 Bernd Warken <groff-bernd.warken-72@web.de>
+ ________________________________________________________________
+ * 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[].
+ - Redesign and rewrite most macros.
+ - Include the documentation for the new features.
+ - Greatly enlarge section ENVIRONMENT
+ - Add examples.
+
+ * TODO:
+ - Start a TODO file with several sections.
+
+ * ChangeLog:
+ Due to the many changes, shorten and rearrange the entries
+ since groffer 0.5 .
+ ________________________________________________________________
+ * Shell compatibility
+
+ * groffer.sh:
+ - Due to possible conflicts in old BSD versions, `[]' was
+ replaced by `test'; the `test' options `-a' and `-o' were
+ replaced by multiple calls of `test'.
+ - Write interface to the `sed' command `s' to become
+ independent of the delimiter character. Rewrite all text
+ manipulating function to use this new scheme. The new
+ functions are named `string_*'.
+ - `tr' is not needed any longer, replaced by `sed'.
+ - `grep' is not needed any longer, mostly replaced by `case'.
+ - Revision of test for `getopt'.
+ - Remove `set -a'; explicitly export variables.
+ - 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
+
+ * groffer.sh:
+ - Implement a prefix based naming scheme for local variables
+ and functions (OOP-like).
+ - Introduce variables for white space (better readability with
+ $IFS).
+ - Store the names of the processed filespecs into a variable
+ instead of a temporary file.
+ - Error-prone shell constructions were replaced by functions
+ with a simple interface.
+ - To avoid too long pipes, replace supercat() by do_fileargs();
+ every input file is handled independently.
+
+ ________________________________________________________________
+ * New features:
+ - Add support for more X devices (e.g. X75-12 and X100-12).
+ - Add long option `--intermediate_output' to `-Z'.
+ - Make the options for mode selection clobber each other.
+ - Add option `--mode' with an argument having the following
+ values:
+ `X': force displaying in X, same as options `-X';
+ `tty': display with a pager on text terminal; same as `--tty';
+ `source', `default', `auto', etc.
+ - Make the handling of the X mode like in groff (e.g. -X -Tps).
+ - Make resolution for gxditview behave like groff (default
+ 75 dpi).
+ - Add environment variable $GROFFER_OPT to preset groffer
+ options.
+
+ ________________________________________________________________
+ * implement most of the functionality of GNU `man'.
+
+ - Add all `man' long options to groffer.
+ - Add all `man' environment variables.
+ - Parse and use content of `$MANOPT'.
+ - The precedence of the options and environment variables
+ is regulated like in GNU `man'.
+ - Force the option `--manpath' to have a colon-separated
+ argument like GNU `man'.
+ - Support `man section name' calling convention.
+ - Remove all dependencies on `man -w'.
+
+ * groffer.sh:
+ - Add the new features above.
+ - Rewrite the search algorithm for man pages.
+ - Remove searching with `man -w' (problems with space
+ characters in file names).
+ - Fix and complement usage().
+ - The filespec parsers gets a function of its own do_manpage().
+
+
+2002-01-08 Bernd Warken <groff-bernd.warken-72@web.de>
+
+ * groffer 0.5 (beta) released
+
+ * groffer.man:
+ - Fix hyphenation problems with macros describing options.
+ - Fix the handling of some `-' characters.
+ - 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.
+ - Run gxditview in a new shell instantiation for having a clean
+ handling of the temporary files when running in the
+ background.
+ - Revision of the retrieving method for the window title.
+ - Empty input is now tolerated.
+ - Export the variables that are set before the call of `set -a'.
+ - Function usage() corrected and updated.
+ - Unnecessary stuff removed.
+ - Comments adjusted.
+ - Pass option `-X' to groff, i.e. force X output with 75 dpi.
+ - Implement option `--dpi' for setting the resolution for the X
+ viewer, which had already been documented in earlier versions.
+
+2002-01-07 Bernd Warken <groff-bernd.warken-72@web.de>
+
+ * 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
+ alternatively depending on the text results.
+ - Use `gzip' for decompression instead of `zcat'.
+ - Signal handling added for clean exiting by `trap'.
+ - Temporary files exist only as long as necessary.
+ - Setup of path for man-pages moved after the option parsing.
+ - Fixed a bug in determining the path for man-pages.
+ - Fixed a bug in the handling of non-groffer options.
+
+ * New features:
+ - New option --tty for forcing paging on text terminal.
+ - New option --no-man for disabling the man-page feature.
+ - Implement reserved POSIX -W feature to simulate long options.
+ - gxditview is now run as a background process.
+
+2002-01-05 Werner LEMBERG <wl@gnu.org>
+
+ * Integrate groffer into groff's `contrib' tree.
+
+ * Makefile: Replaced by...
+ Makefile.sub: New file.
+
+ * groffer: Replaced by...
+ groffer.sh: New file.
+
+ * groffer.man (OptDef): Add missing backslashes.
+ Update copyright.
+
+2001-12-15 Bernd Warken <groff-bernd.warken-72@web.de>
+
+ * groffer 0.3 (alpha) released (still stand-alone package).
+
+ * GNU and POSIX are supported (POSIX without long options).
+
+ * New options : --man, --mandb, --title, --xrdb
+
+ * Support for command line arguments with embedded single space
+ characters (GNU only) .
+
+ * Several search methods for man-pages when no `man -w' is
+ available ($MANPATH, mandb, a default path).
+
+ * Language support for man-pages.
+
+ * Recognize the following filespecs as man-page parameters:
+ man:name(section), man:name, name.section, name.
+
+2001-12-03 Bernd Warken <groff-bernd.warken-72@web.de>
+
+ * Stand-alone package for groffer 0.2 (alpha) created
+ Files: groffer, groffer.man, Makefile, TODO, ChangeLog
+
+2001-12-02 Bernd Warken <groff-bernd.warken-72@web.de>
+
+ * groffer 0.2 (alpha) program released.
+
+ * Name changed from `groffview' to `groffer'.
+
+ * Comments added.
+
+ * Name changed from `groffview' to `groffer'.
+
+ * Options harmonized with groff.
+ New options : -Q --source, -T --device, -X .
+ Other options known from groff are passed unchanged.
+
+ * 100 dpi as default, 75 dpi only in emergency situations.
+
+ * Bugs with temporary files fixed.
+
+ * Code restructured and comments added.
+
+2001-11-28 Bernd Warken <groff-bernd.warken-72@web.de>
+
+ ***** 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 <groff-bernd.warken-72@web.de>
+
+ ________________________________________________________________
+ License
+
+ Copyright (C) 2001,2002,2003,2004,2005,2006
+ Free Software Foundation, Inc.
+ Written by Bernd Warken <groff-bernd.warken-72@web.de>.
+
+ 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.
+
+
+ Emacs settings
+
+ Local Variables:
+ mode: change-log
+ End:
diff --git a/contrib/groffer/shell/README_SH b/contrib/groffer/shell/README_SH
new file mode 100644
index 00000000..8047222b
--- /dev/null
+++ b/contrib/groffer/shell/README_SH
@@ -0,0 +1,297 @@
+README_SH
+
+Special description for the shell version of `groffer'
+
+
+The files related to the shell version are
+
+shell/groffer.sh starting script of groffer
+shell/groffer2.sh main script of groffer
+shell/groffer.man manual page of groffer
+shell/README_SH description of the shell version of the program
+shell/ChangeLog.0 information on all changements of groffer versions 0.*
+version.sh script that handles the version information
+
+
+Scripts
+
+The shell version of `groffer' contains two files, `groffer.sh' and
+`groffer2.sh'.
+
+`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 abbreviation of long options is enhanced by letting each
+internal `-' sign generate a new center of abbreviation. So each
+command line argument starting with `--' can represent a multiple set
+of abbreviations.
+
+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
+
+Error handling and exit behavior is complicated by the fact that
+`exit' can only escape from the current shell; trouble occurs in
+subshells. This was solved by adding a temporary error file that is
+tested by function exit_test() and by replacing `var=$(...)' by
+function obj_from_output().
+
+
+Function Definitions in `groffer2.sh'
+
+Each function in groffer2.sh has a description that starts with the
+function name and symbols for its arguments in parentheses `()'. 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.
+
+<arg> exactly 1 of this argument
+<arg>? 0 or 1 of these arguments
+<arg>* arbitrarily many such arguments, incl. none
+<arg>+ one or more such arguments
+<arg>... 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.
+$LANG: For language specific man pages.
+$LC_ALL: For language specific man pages.
+$LC_MESSAGES: For language specific man pages.
+$PAGER: Paging program for tty mode.
+$PATH: Path for the programs called (`:' separated list).
+
+groffer native environment variables
+$GROFFER_OPT preset options for groffer.
+
+all groff environment variables are used, see groff(1)
+$GROFF_BIN_PATH: Path for all groff programs.
+$GROFF_COMMAND_PREFIX: '' (normally) or 'g' (several troffs).
+$GROFF_FONT_PATH: Path to non-default groff fonts.
+$GROFF_TMAC_PATH: Path to non-default groff macro files.
+$GROFF_TMPDIR: Directory for groff temporary files.
+$GROFF_TYPESETTER: Preset default device.
+
+all GNU man environment variables are used, see man(1).
+$MANOPT: Preset options for man pages.
+$MANPATH: Search path for man pages (: list).
+$MANROFFSEQ: Ignored because of grog guessing.
+$MANSECT: Search man pages only in sections (:).
+$SYSTEM: Man pages for different OS's (, list).
+
+
+Object-oriented Functions
+
+The groffer script provides an object-oriented construction (OOP). In
+object-oriented terminology, a type of object is called a `class'; a
+function that handles objects from a class is named `method'.
+
+In the groffer script, the object is a variable name whose content is
+the object's data. Methods are functions that have an object as first
+argument.
+
+The basic functions for object handling are obj_*().
+
+The class `list' represents an array structure, see list_*().
+
+
+Speed
+
+The major speed gain is the disabling of all debug features. This is
+the default for the installed version of `groffer'. Before the run of
+`make', the debug feature of $_DEBUG_FUNC_CHECK, corresponding to
+option --debug-func, is enabled by default. The resulting heavy
+slowing down should be regarded as a temporary feature.
+
+Another increase of speed was the replacement of the many `ls' calls
+by analysing a `find' of manpath with `grep'.
+
+
+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 on 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.
+
+For shell compatibility, see also Autobook, chapter 22.
+
+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.
+
+ <shell-name> groffer.sh --shell=<shell-name> <argument>...
+
+
+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 <<EOF'.
+
+- `ls' has problems. Old UNIX systems echoed the error message to
+ standard output. So handle the output with `sed'. If the output
+ contains `not found' map it to an empty string.
+
+- As `test -e' is not available in Solaris 2.5 replace it by
+ `test -f || test -d'.
+
+- As `unset' is not supported by all shells replace it by `eval
+ ${_UNSET}' where this variable is `unset' if it exists and `:'
+ otherwise.
+
+- Some shells have problems with options in `eval'. So quoting must
+ be done right to hide the options from `eval'.
+
+- In backquote calls `` avoid the backquote ` in comments.
+
+- Replace `true' by `:', `false' isn't used.
+
+- Do not redefine builtins as functions (ash).
+
+- Avoid `[^...]' in `case' patterns (ash).
+
+- `trap' does not allow error code 127.
+
+The scripts call the following commands with all options used:
+.
+:
+apropos
+break
+bzip2 -c -d -t
+cat
+catz
+cd
+continue
+echo
+eval
+expr
+grep
+groff -v
+grog -T -X -Z
+gs -c -d -f -q -s
+gzip -c -d -f
+less -r -R
+ls
+man -k --apropos
+mkdir
+mv
+pwd
+return
+rm -f -r
+rmdir
+sed -e -n
+set -e
+sh -c
+shift
+test -c -d -f -r -s -w -x
+trap
+umask
+unset
+
+
+Bugs
+
+If the `groffer' run is interrupted by Crtl-C the clean up is not done
+by all shells. The `trap' commands work for the shells `bash',
+`bash-minimal', and 'ksh'; they do not work for `ash', `dash',
+`pdksh', `posh', and `zsh'.
+
+
+####### License
+
+Last update: 7 Feb 2011
+
+Copyright (C) 2003-2006, 2009, 2011
+ Free Software Foundation, Inc.
+Written by Bernd Warken <groff-bernd.warken-72@web.de>
+
+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 3 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+####### Emacs settings
+
+Local Variables:
+mode: text
+End:
diff --git a/contrib/groffer/shell/groffer.man b/contrib/groffer/shell/groffer.man
new file mode 100644
index 00000000..ec0a7825
--- /dev/null
+++ b/contrib/groffer/shell/groffer.man
@@ -0,0 +1,4124 @@
+.TH GROFFER @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groffer \- display groff files and man\~pages on X and tty
+.
+.SH "SYNOPSIS"
+.\" The .SH was moved to this place in order to appease `apropos'.
+.
+.\" --------------------------------------------------------------------
+.\" Legalese
+.\" --------------------------------------------------------------------
+.
+.de author
+This file was written by Bernd Warken <groff-bernd.warken-72@web.de>.
+..
+.de copyleft
+Copyright (C) 2001, 2002, 2004-2012
+ 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 3 of the License, 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 visit
+.nh
+.B <http://www.gnu.org/licenses/>.
+.hy
+..
+.
+.\" --------------------------------------------------------------------
+.\" Setup
+.\" --------------------------------------------------------------------
+.
+.ds Ellipsis "\&.\|.\|.\&\"
+.
+.\" --------------------------------------------------------------------
+.\" Macro definitions
+.
+.\" --------------------------------------------------------------------
+.\" .CB (<text>...)
+.\"
+.\" Print in constant-width bold font.
+.\"
+.de CB
+. ft CB
+. Text \\$*
+. ft
+..
+.\" --------------------------------------------------------------------
+.\" .CI (<text>...)
+.\"
+.\" Print in constant-width italic font.
+.\"
+.de CI
+. ft CI
+. Text \\$*
+. ft
+..
+.\" --------------------------------------------------------------------
+.\" .CR (<text>...)
+.\"
+.\" Print in constant-width roman font.
+.\"
+.de CR
+. ft CR
+. Text \\$*
+. ft
+..
+.\" --------------------------------------------------------------------
+.\" .Error (<text>...)
+.\"
+.\" Print error message to terminal and abort.
+.\"
+.de Error
+. tm \\$*
+. ab
+..
+.\" --------------------------------------------------------------------
+.\" .Env_var (<env_var_name> [<punct>])
+.\"
+.\" Display an environment variable, with optional punctuation.
+.\"
+.de Env_var
+. nh
+. SM
+. Text \f[CB]\\$1\f[]\\$2
+. hy
+..
+.\" --------------------------------------------------------------------
+.\" .File_name (<path_name>)
+.\"
+.\" Display a file or directory name in CB font.
+.\"
+.de File_name
+. Header_CB \\$@
+..
+.\" --------------------------------------------------------------------
+.\" .Header_CB (<path_name>)
+.\"
+.\" Display a line in CB font, for example after .TP
+.\"
+.de Header_CB
+. nh
+. Text \f[CB]\\$1\f[]\\$2
+. hy
+..
+.\" --------------------------------------------------------------------
+.\" .Text (<text>...)
+.\"
+.\" Treat the arguments as text, no matter how they look.
+.\"
+.de Text
+. if \\n[.$]=0 \
+. return
+. nh
+. nop \)\\$*\)
+. hy
+..
+.\" --------------------------------------------------------------------
+.\" .Topic ([<indent>])
+.\"
+.\" A bulleted paragraph
+.\"
+.de Topic
+. ie \\n[.$]=0 \
+. ds @indent 2m\"
+. el \
+. ds @indent \\$1\"
+. IP \[bu] \\*[@indent]
+. rm @indent
+..
+
+.\" End of macro definitions
+.
+.
+.\" --------------------------------------------------------------------
+.\" SH "SYNOPSIS"
+.\" --------------------------------------------------------------------
+.
+.SY groffer
+.OP option \*[Ellipsis]
+.OP --
+.OP \%filespec \*[Ellipsis]
+.YS
+.
+.SY groffer
+.BR -h | --help
+.YS
+.
+.SY groffer
+.BR -v | --version
+.YS
+.
+.
+.\" --------------------------------------------------------------------
+.SH DESCRIPTION
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program is the easiest way to use
+.BR \%groff (@MAN1EXT@).
+It can display arbitrary documents written in the
+.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.
+.
+It finds and runs all necessary
+.I groff
+preprocessors, such as
+.BR @g@chem .
+.
+.
+.P
+The
+.B \%groffer
+program also includes many of the features for finding and displaying
+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)
+program.
+.
+Moreover, compressed files that can be handled by
+.BR \%gzip (1)
+or
+.BR \%bzip2 (1)
+are decompressed on-the-fly.
+.
+.
+.P
+The normal usage is quite simple by supplying a file name or name of a
+.I \%man\~page
+without further options.
+.
+But the option handling has many possibilities for creating special
+behaviors.
+.
+This can be done either in configuration files, with the shell
+environment variable
+.Env_var \%$GROFFER_OPT ,
+or on the command line.
+.
+.
+.P
+The output can be generated and viewed in several different ways
+available for
+.IR \%groff .
+.
+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
+.B \%groff
+directly are determined automatically for
+.BR \%groffer ,
+due to the internal usage of the
+.BR \%grog (@MAN1EXT@)
+program.
+.
+But all parts can also be controlled manually by arguments.
+.
+.
+.P
+Several file names can be specified on the command line arguments.
+.
+They are transformed into a single document in the normal way of
+.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 in several ways.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "OPTION OVERVIEW"
+.\" --------------------------------------------------------------------
+.
+.TP
+.I breaking options
+.RS
+.P
+.SY
+.OP -h\~\fR|\fB\~--help
+.OP -v\~\fR|\fB\~--version
+.YS
+.RE
+.
+.
+.TP
+.I \%groffer mode options
+.RS
+.P
+.SY
+.OP --auto
+.OP --default
+.OP --default\-modes mode1,mode2,\*[Ellipsis]
+.OP --dvi
+.OP --dvi\-viewer prog
+.OP --groff
+.OP --html
+.OP --html\-viewer prog
+.OP --mode display_mode
+.OP --pdf
+.OP --pdf\-viewer prog
+.OP --ps
+.OP --ps\-viewer prog
+.OP --source
+.OP --text
+.OP --to\-stdout
+.OP --tty
+.OP --tty\-viewer prog
+.OP --www
+.OP --www\-viewer prog
+.OP --x\~\fR|\fB\~--X
+.OP --x\-viewer\~\fR|\fB\~--X\-viewer prog
+.YS
+.RE
+.
+.
+.TP
+.I options related to \%groff
+.RS
+.P
+.SY
+.OP -T\~\fR|\fB\~--device device
+.OP -Z\~\fR|\fB\~--intermediate\-output\~\fR|\fB\~--ditroff
+.YS
+.P
+All further
+.B \%groff
+short options are accepted.
+.RE
+.
+.
+.TP
+.I options for man\~pages
+.RS
+.P
+.SY
+.OP --apropos
+.OP --apropos\-data
+.OP --apropos\-devel
+.OP --apropos\-progs
+.OP --man
+.OP --no\-man
+.OP --no\-special
+.OP --whatis
+.YS
+.RE
+.
+.
+.TP
+.I long options taken over from GNU man
+.RS
+.P
+.SY
+.OP --all
+.OP --ascii
+.OP --ditroff
+.OP --extension suffix
+.OP --locale language
+.OP --local\-file
+.OP --location\~\fR|\fB\~--where
+.OP --manpath dir1:dir2:\*[Ellipsis]
+.OP --no\-location
+.OP --pager program
+.OP --sections sec1:sec2:\*[Ellipsis]
+.OP --systems sys1,sys2,\*[Ellipsis]
+.OP --troff\-device device
+.YS
+.P
+Further long options of \f[CR]GNU\f[]
+.B man
+are accepted as well.
+.RE
+.
+.
+.TP
+.I X Window Toolkit options
+.RS
+.P
+.SY
+.OP --bd\~\fR|\fB\~--bordercolor pixels
+.OP --bg\~\fR|\fB\~--background color
+.OP --bw\~\fR|\fB\~--borderwidth pixels
+.OP --display X-display
+.OP --fg\~\fR|\fB\~--foreground color
+.OP --fn\~\fR|\fB\~--ft\~\fR|\fB\~--font font_name
+.OP --geometry size_pos
+.OP --resolution value
+.OP --rv
+.OP --title string
+.OP --xrm X\-resource
+.YS
+.RE
+.
+.
+.TP
+.I options for development
+.RS
+.P
+.SY
+.OP --debug
+.OP --debug\-all
+.OP --debug\-filenames
+.OP --debug\-func
+.OP --debug\-grog
+.OP --debug\-keep
+.OP --debug\-lm
+.OP --debug\-params
+.OP --debug\-shell
+.OP --debug\-stacks
+.OP --debug\-tmpdir
+.OP --debug\-user
+.OP --do\-nothing
+.OP --print text
+.OP --shell prog
+.OP -V
+.YS
+.RE
+.
+.
+.TP
+.I \%filespec arguments
+.RS
+.P
+The
+.I \%filespec
+parameters are all arguments that are neither an option nor an option
+argument.
+.
+They usually mean a file name or a
+.I man page
+searching scheme.
+.
+.
+.P
+In the following, the term
+.I section_extension
+is used.
+.
+It means a word that consists of a
+.I man section
+that is optionally followed by an
+.IR extension .
+.
+The name of a
+.I man section
+is a single character from
+.BR \%[1-9on] ,
+the
+.I extension
+is some word.
+.
+The
+.I extension
+is mostly lacking.
+.
+.
+.P
+No
+.I \%filespec
+parameters means standard input.
+.
+.
+.TP 10m
+.B -
+stands for standard input (can occur several times).
+.
+.
+.TP
+.I filename
+the path name of an existing file.
+.
+.
+.TP
+.BI man: name ( section_extension )
+.TQ
+.BI man: name . section_extension
+.TQ
+.IB name ( section_extension )
+.TQ
+.IB name . section_extension
+.TQ
+.I "section_extension name"
+search the \%man\~page
+.I \%name
+in the section with optional extension
+.IR section_extension .
+.
+.
+.TP
+.BI man: name
+\%man\~page in the lowest
+.I \%man\~section
+that has
+.IR \%name .
+.
+.
+.TP
+.I name
+if
+.I \%name
+is not an existing file search for the man\~page
+.I \%name
+in the lowest man\~section.
+.
+.RE
+.
+.
+.\" --------------------------------------------------------------------
+.SH "OPTION DETAILS"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program can usually be run with very few options.
+.
+But for special purposes, it supports many options.
+.
+These can be classified in 5 option classes.
+.
+.
+.P
+All short options of
+.B \%groffer
+are compatible with the short options of
+.BR \%groff (@MAN1EXT@).
+.
+All long options of
+.B \%groffer
+are compatible with the long options of
+.BR \%man (1).
+.
+.
+.P
+Arguments for long option names can be abbreviated in several ways.
+.
+First, the argument is checked whether it can be prolonged as is.
+.
+Furthermore, each minus sign
+.B -
+is considered as a starting point for a new abbreviation.
+.
+This leads to a set of multiple abbreviations for a single argument.
+.
+For example,
+.B --de\-n\-f
+can be used as an abbreviation for
+.BR --debug\-not\-func ,
+but
+.B --de\-n
+works as well.
+.
+If the abbreviation of the argument leads to several resulting options
+an error is raised.
+.
+.
+.P
+These abbreviations are only allowed in the environment variable
+.Env_var \%$GROFFER_OPT ,
+but not in the configuration files.
+.
+In configuration, all long options must be exact.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "groffer breaking Options"
+.\" --------------------------------------------------------------------
+.
+As soon as one of these options is found on the command line it is
+executed, printed to standard output, and the running
+.B \%groffer
+is terminated thereafter.
+.
+All other arguments are ignored.
+.
+.
+.TP
+.B -h\~\fR|\fB\~--help
+Print help information with a short explanation of options to
+standard output.
+.
+.
+.TP
+.B -v\~\fR|\fB\~--version
+Print version information to standard output.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "groffer Mode Options"
+.\" --------------------------------------------------------------------
+.
+The display mode and the viewer programs are determined by these
+options.
+.
+If none of these mode and viewer options is specified
+.B \%groffer
+tries to find a suitable display mode automatically.
+.
+The default modes are
+.IR "mode pdf" ,
+.IR "mode ps" ,
+.IR "mode html" ,
+.IR "mode x" ,
+and
+.I "mode dvi"
+in \%\f[CR]X\~Window\f[] with different viewers and
+.I mode tty
+with device
+.I latin1
+under
+.B less
+on a terminal; other modes are tested if the programs for the main
+default mode do not exist.
+.
+.
+.P
+In \%\f[CR]X\~Window\f[],
+many programs create their own window when called.
+.B \%groffer
+can run these viewers as an independent program in the background.
+.
+As this does not work in text mode on a terminal (tty) there must be a
+way to know which viewers are \%\f[CR]X\~Window\f[] graphical
+programs.
+.
+The
+.B \%groffer
+script has a small set of information on some viewer names.
+.
+If a viewer argument of the command\-line chooses an element that is
+kept as \%\f[CR]X\~Window\f[] program in this list it is treated as a
+viewer that can run in the background.
+.
+All other, unknown viewer calls are not run in the background.
+.
+.
+.P
+For each mode, you are free to choose whatever viewer you want.
+.
+That need not be some graphical viewer suitable for this mode.
+.
+There is a chance to view the output source; for example, the
+combination of the options
+.B --mode=ps
+and
+.B --ps\-viewer=less
+shows the content of the
+.I Postscript
+output, the source code, with the pager
+.BR less .
+.
+.
+.TP
+.B --auto
+Equivalent to
+.BR --mode=auto .
+.
+.
+.TP
+.B --default
+Reset all configuration from previously processed command line options
+to the default values.
+.
+This is useful to wipe out all former options of the configuration, in
+.Env_var \%$GROFFER_OPT ,
+and restart option processing using only the rest of the command line.
+.
+.
+.TP
+.BI --default\-modes \ mode1,mode2,\*[Ellipsis]
+Set the sequence of modes for
+.I \%auto\~mode
+to the comma separated list given in the argument.
+.
+See
+.B --mode
+for details on modes. Display in the default manner; actually, this
+means to try the modes
+.IR x ,
+.IR ps ,
+and
+.I \%tty
+in this sequence.
+.
+.
+.
+.TP
+.B --dvi
+Equivalent to
+.BR --mode=\%dvi .
+.
+.
+.TP
+.BI --dvi\-viewer \ prog
+Choose a viewer program for
+.IR \%dvi\~mode .
+.
+This can be a file name or a program to be searched in
+.Env_var $PATH .
+.
+Known \%\f[CR]X\~Window\f[]
+.I \%dvi
+viewers include
+.BR \%xdvi (1)
+and
+.BR \%dvilx (1).
+.
+In each case, arguments can be provided additionally.
+.
+.
+.TP
+.B --groff
+Equivalent to
+.BR --mode=groff .
+.
+.
+.TP
+.B --html
+Equivalent to
+.BR --mode=html .
+.
+.
+.TP
+.B --html\-viewer
+Choose a web browser program for viewing in
+.IR \%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.
+.
+.
+.TP
+.BI --mode \ value
+.
+Set the display mode.
+.
+The following mode values are recognized:
+.
+.RS
+.
+.TP
+.Header_CB auto
+Select the automatic determination of the display mode.
+.
+The sequence of modes that are tried can be set with the
+.B --default\-modes
+option.
+.
+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
+viewer program.
+.
+By default, the formatted input is displayed with the
+.BR \%xdvi (1)
+program.
+.
+.
+.TP
+.Header_CB groff
+After the file determination, switch
+.B \%groffer
+to process the input like
+.BR \%groff (@MAN1EXT@)
+would do.
+.
+This disables the
+.I \%groffer
+viewing features.
+.
+.
+.TP
+.Header_CB html
+Translate the input into html format and display the result in a web
+browser program.
+.
+By default, the existence of a sequence of standard web browsers is
+tested, starting with
+.BR \%konqueror (1)
+and
+.BR \%mozilla (1).
+The text html viewer is
+.BR \%lynx (1).
+.
+.
+.TP
+.Header_CB pdf
+Display formatted input in a
+.I \%PDF
+(Portable Document Format) viewer
+program.
+.
+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),
+or
+.BR ps2pdf (1).
+If that's not possible, the
+.I Postscript mode (ps)
+is used instead.
+.
+Finally it is displayed using different viewer programs.
+.
+.I \%pdf
+has a big advantage because the text is displayed graphically and
+is searchable as well.
+.
+.
+.TP
+.Header_CB ps
+Display formatted input in a Postscript viewer program.
+.
+By default, the formatted input is displayed in one of many viewer
+programs.
+.
+.
+.TP
+.Header_CB text
+Format in a
+.I \%groff\~text\~mode
+and write the result to standard output without a pager or viewer
+program.
+.
+The text device,
+.I \%latin1
+by default, can be chosen with option
+.BR -T .
+.
+.
+.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 \%\f[CR]X\~Window\f[].
+.
+.
+.TP
+.Header_CB www
+Equivalent to
+.BR --mode=html .
+.
+.
+.TP
+.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
+.BR \%groff .
+But the standard \%\f[CR]X\~Window\f[] tool
+.BR \%xditview (1)
+can also be chosen with the option
+.BR --x\-viewer .
+The default resolution is
+.BR 75dpi ,
+but
+.B 100dpi
+are also possible.
+.
+The default
+.I groff
+device
+for the resolution of
+.B 75dpi
+is
+.BR X75\-12 ,
+for
+.B 100dpi
+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 100dpi ,
+the default width of the geometry of the display program is chosen to
+.BR 850dpi .
+.
+.
+.TP
+.Header_CB X
+Equivalent to
+.BR --mode=x .
+.
+.
+.P
+The following modes do not use the
+.I \%groffer
+viewing features.
+.
+They are only interesting for advanced applications.
+.
+.
+.TP
+.Header_CB groff
+Generate device output with plain
+.I \%groff
+without using the special viewing features of
+.IR \%groffer .
+If no device was specified by option
+.B -T
+the
+.I \%groff
+default
+.B \%ps
+is assumed.
+.
+.
+.TP
+.Header_CB source
+Output the roff source code of the input files without further
+processing.
+.
+.
+.RE
+.
+.
+.TP
+.B --pdf
+Equivalent to
+.BR --mode=pdf .
+.
+.
+.TP
+.BI --pdf\-viewer \ prog
+Choose a 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.
+.
+.
+.TP
+.B --ps
+Equivalent to
+.BR --mode=ps .
+.
+.
+.TP
+.BI --ps\-viewer \ prog
+Choose a 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 include
+.BR \%gv (1),
+.BR \%ghostview (1),
+and
+.BR \%gs (1),
+.
+In each case, arguments can be provided additionally.
+.
+.
+.TP
+.B --source
+Equivalent to
+.BR --mode=source .
+.
+.
+.TP
+.B --text
+Equivalent to
+.BR --mode=text .
+.
+.
+.TP
+.B --to\-stdout
+The file for the chosen mode is generated and its content is printed
+to standard output.
+.
+It will not be displayed in graphical mode.
+.
+.
+.TP
+.B --tty
+Equivalent to
+.BR --mode=tty .
+.
+.
+.TP
+.BI --tty\-viewer \ prog
+Choose a text pager for mode
+.IR tty .
+The standard pager is
+.BR less (1).
+This option is equivalent to
+.I man
+option
+.BR --pager=\fIprog\fP .
+The option argument can be a file name or a program to be searched in
+.Env_var $PATH ;
+arguments can be provided additionally.
+.
+.
+.TP
+.B --www
+Equivalent to
+.BR --mode=html .
+.
+.
+.TP
+.BI --www\-viewer \ prog
+Equivalent to
+.BR --html\-viewer .
+.
+.
+.TP
+.B --X\~\fR|\fB\~--x
+Equivalent to
+.BR --mode=x .
+.
+.
+.TP
+.BI --X\-viewer\~\fR|\fB\~--x\-viewer \ prog
+Choose a viewer program for
+.IR \%x\~mode .
+Suitable viewer programs are
+.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.
+.
+.
+.TP
+.B --
+Signals the end of option processing; all remaining arguments are
+interpreted as
+.I \%filespec
+parameters.
+.
+.
+.P
+Besides these,
+.B \%groffer
+accepts all short options that are valid for the
+.BR \%groff (@MAN1EXT@)
+program.
+.
+All
+.RB \%non- groffer
+options are sent unmodified via
+.B \%grog
+to
+.BR \%groff .
+.
+So postprocessors, macro packages, compatibility with
+.I classical
+.IR \%troff ,
+and much more can be manually specified.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Options related to groff"
+.\" --------------------------------------------------------------------
+.
+All short options of
+.B \%groffer
+are compatible with the short options of
+.BR \%groff (@MAN1EXT@).
+.
+The following of
+.B \%groff
+options have either an additional special meaning within
+.B \%groffer
+or make sense for normal usage.
+.
+.
+.P
+Because of the special outputting behavior of the
+.B \%groff
+option
+.B -Z
+.B \%groffer
+was designed to be switched into
+.IR \%groff\~mode ;
+the
+.I \%groffer
+viewing features are disabled there.
+.
+The other
+.B \%groff
+options do not switch the mode, but allow to customize the formatting
+process.
+.
+.
+.TP
+.B --a
+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 in
+.IR "tty mode" .
+.
+.
+.TP
+.BI --m \ file
+Add
+.I \%file
+as a
+.I \%groff
+macro file.
+.
+This is useful in case it cannot be recognized automatically.
+.
+.
+.TP
+.BI --P \ opt_or_arg
+Send the argument
+.I \%opt_or_arg
+as an option or option argument to the actual
+.B \%groff
+postprocessor.
+.
+.
+.TP
+.B --T \fIdevname\fR\~\fR|\fB\~--device \fIdevname\fR
+.
+This option determines
+.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 ,
+and others.
+.
+Each of these arguments switches
+.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
+arguments are mapped to the corresponding
+.B \%groffer
+.B --mode=\fIdevname\fR
+option:
+.BR \%dvi ,
+.BR \%html ,
+and
+.BR \%ps .
+All
+.B \%X*
+arguments are mapped to
+.IR \%mode\~x .
+Each other
+.I \%devname
+argument switches to
+.I \%mode\~groff
+using this device.
+.
+.
+.TP
+.B --X
+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
+.B --X
+instead because the
+.I \%x\~mode
+uses an
+.IR X *
+device for a better display.
+.
+.
+.TP
+.B -Z\~\fR|\fB\~--intermediate-output\~\fR|\fB\~--ditroff
+Switch into
+.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
+.B --ditroff
+of
+.IR \%man ,
+which can be used as well.
+.
+.
+.P
+All other
+.B \%groff
+options are supported by
+.BR \%groffer ,
+but they are just transparently transferred to
+.B \%groff
+without any intervention.
+.
+The options that are not explicitly handled by
+.B \%groffer
+are transparently passed to
+.BR \%groff .
+.
+Therefore these transparent options are not documented here, but in
+.BR \%groff (@MAN1EXT@).
+Due to the automatism in
+.BR \%groffer ,
+none of these
+.B \%groff
+options should be needed, except for advanced usage.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Options for man\~pages"
+.\" --------------------------------------------------------------------
+.
+.TP
+.B --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.
+.
+Each
+.I \%filespec
+argument is taken for search as it is;
+.I section
+specific parts are not handled, such that
+.B 7 groff
+searches for the two arguments
+.B 7
+and
+.BR groff ,
+with a large result; for the
+.I \%filespec
+.B groff.7
+nothing will be found.
+.
+The
+.I language
+locale is handled only when the called programs do support this; the
+GNU
+.B apropos
+and
+.B man \-k
+do not.
+.
+The display differs from the
+.B \%apropos
+program by the following concepts:
+.RS
+.Topic
+Construct a
+.I \%groff
+frame similar to a
+.I \%man\~page
+to the output of
+.BR \%apropos ,
+.Topic
+each
+.I \%filespec
+argument is searched on its own.
+.Topic
+The restriction by
+.B --sections
+is handled as well,
+.Topic
+wildcard characters are allowed and handled without a further option.
+.RE
+.
+.
+.TP
+.B --apropos\-data
+Show only the
+.B \%apropos
+descriptions for data documents, these are the
+.BR \%man (7)
+.IR sections\~4 ", " 5 ", and " 7 .
+.
+Direct
+.I section
+declarations are ignored, wildcards are accepted.
+.
+.
+.TP
+.B --apropos\-devel
+Show only the
+.B \%apropos
+descriptions for development documents, these are the
+.BR man (7)
+.IR sections\~2 ", " 3 ", and " 9 .
+.
+Direct
+.I section
+declarations are ignored, wildcards are accepted.
+.
+.
+.TP
+.B --apropos\-progs
+Show only the
+.B \%apropos
+descriptions for documents on programs, these are the
+.BR \%man (7)
+.IR sections\~1 ", " 6 ", and " 8 .
+.
+Direct
+.I section
+declarations are ignored, wildcards are accepted.
+.
+.
+.TP
+.B --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 is written from anew, so it 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 \fIlanguage\fP and \fIsystem\fP locale is supported,
+.Topic
+the display is framed by a
+.I groff
+output format similar to a
+.IR \%man\~page ,
+.Topic
+wildcard characters are allowed without a further option.
+.RE
+.
+.
+.P
+The following 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.
+.
+.
+.TP
+.B --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.
+.
+.
+.TP
+.B --no-man\~\fR|\fB\~--local-file
+Do not check for
+.IR \%man\~pages .
+.
+.B --local-file
+is the corresponding
+.B man
+option.
+.
+.
+.TP
+.B --no-special
+Disable former calls of
+.BR --all ,
+.BR --apropos* ,
+and
+.BR --whatis .
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Long options taken over from GNU man"
+.\" --------------------------------------------------------------------
+.
+The long options of
+.B \%groffer
+were synchronized with the long options of \f[CR]GNU\f[]
+.BR man .
+.
+All long options of \f[CR]GNU\f[]
+.B man
+are recognized, but not all of these options are important to
+.BR \%groffer ,
+so most of them are just ignored.
+.
+These ignored
+.B man
+options are
+.BR --catman ,
+.BR --troff ,
+and
+.BR --update .
+.
+.
+.P
+In the following, the
+.B man
+options that have a special meaning for
+.B \%groffer
+are documented.
+.
+.
+.P
+If your system has \f[CR]GNU\f[]
+.B man
+installed 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).
+.
+.
+.TP
+.B --all
+In searching
+.IR \%man\~pages ,
+retrieve all suitable documents instead of only one.
+.
+.
+.TP
+.B -7\~\fR|\fB\~--ascii
+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@).
+.
+.
+.TP
+.B --ditroff
+Produce
+.IR "groff intermediate output" .
+This is equivalent to
+.B \%groffer
+.BR -Z .
+.
+.
+.TP
+.BI --extension \ 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
+.I \%man\~page
+extension is
+.IR \%ncurses .
+.
+.
+.TP
+.BI --locale \ language
+.
+Set the language for
+.IR \%man\~pages .
+.
+This has the same effect, but overwrites
+.Env_var $LANG .
+.
+.
+.TP
+.B --location
+Print the location of the retrieved files to standard error.
+.
+.
+.TP
+.B --no-location
+Do not display the location of retrieved files; this resets a former
+call to
+.BR --location .
+.
+This was added by
+.BR \%groffer .
+.
+.
+.TP
+.BI --manpath \ 'dir1:dir2:\*[Ellipsis]'
+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
+.I \%man\~page
+is disabled.
+.
+.
+.TP
+.B --pager
+Set the pager program in
+.IR \%tty\~mode ;
+default is
+.BR \%less .
+This is equivalent to
+.BR --tty\-viewer .
+.
+.
+.TP
+.BI --sections \ sec1:sec2:\*[Ellipsis]
+Restrict searching for
+.I \%man\~pages
+to the given
+.IR sections ,
+a colon-separated list.
+.
+.
+.TP
+.BI --systems \ sys1,sys2,\*[Ellipsis]
+Search for
+.I \%man\~pages
+for the given operating systems; the argument
+.I \%systems
+is a comma-separated list.
+.
+.
+.TP
+.B --where
+Equivalent to
+.BR --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
+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
+.B --font
+for the \%\f[CR]X\~Window\f[] option
+.BR -font .
+.
+.
+.P
+See
+.BR X (7)
+and the documentation on the \%\f[CR]X\~Window\~Toolkit\f[] options
+for more details on these options and their arguments.
+.
+.
+.TP
+.BI --background \ color
+Set the background color of the viewer window.
+.
+.
+.TP
+.BI --bd \ pixels
+This is equivalent to
+.BR --bordercolor .
+.
+.
+.TP
+.BI --bg \ color
+This is equivalent to
+.BR --background .
+.
+.
+.TP
+.BI --bw \ pixels
+This is equivalent to
+.BR --borderwidth .
+.
+.
+.TP
+.BI --bordercolor \ pixels
+Specifies the color of the border surrounding the viewer window.
+.
+.
+.TP
+.BI --borderwidth \ pixels
+Specifies the width in pixels of the border surrounding the viewer
+window.
+.
+.
+.TP
+.BI --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.
+.
+.
+.TP
+.BI --foreground \ color
+Set the foreground color of the viewer window.
+.
+.
+.TP
+.BI --fg \ color
+This is equivalent to
+.BR -foreground .
+.
+.
+.TP
+.BI --fn \ font_name
+This is equivalent to
+.BR --font .
+.
+.
+.TP
+.BI --font \ font_name
+Set the font used by the viewer window.
+.
+The argument is an \%\f[CR]X\~Window\f[] font name.
+.
+.
+.TP
+.BI --ft \ font_name
+This is equivalent to
+.BR --font .
+.
+.
+.TP
+.BI --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.
+.
+.
+.TP
+.BI --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 75dpi .
+The resolution also sets the default device in
+.IR "mode x" .
+.
+.
+.TP
+.B --rv
+Reverse foreground and background color of the viewer window.
+.
+.
+.TP
+.BI --title "\ 'some text'"
+Set the title for the viewer window.
+.
+.
+.TP
+.BI --xrm \ 'resource'
+Set \f[CR]\%X\~Window\f[] resource.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Options for Development"
+.\" --------------------------------------------------------------------
+.
+.TP
+.B --debug
+Enable eight 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 displayed file names are printed, the
+.B grog
+output is 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 at the opening and closing of each
+function call nor the landmark information to determine how far the
+program is running are printed.
+.
+These seem to be the most useful parts among all debugging options.
+.
+.
+.TP
+.B --debug\-all
+Enable all ten debugging informations including the function call
+stack and the landmark information.
+.
+.
+.TP
+.B --debug\-filenames
+Print the names of the files and
+.I \%man\~pages
+that are displayed by
+.BR \&groffer .
+.
+.
+.TP
+.B --debug\-func
+Enable the basic debugging information for checking the functions on
+the beginning and end of each call.
+.
+The options
+.B --debug\-stacks
+and
+.B --debug\-user
+enable this option automatically.
+.
+This option is important for the development, but it decreases the
+speed of
+.B groffer
+by large amounts.
+.
+.
+.TP
+.B --debug\-grog
+Print the output of all
+.B grog
+commands.
+.
+.
+.TP
+.B --debug\-keep
+Enable two debugging informations, the printing of the name of the
+temporary directory and the keeping of the temporary files.
+.
+.
+.TP
+.B --debug\-lm
+Enable one debugging information, the landmark information.
+.
+.
+.TP
+.B --debug\-params
+Enable one debugging information, the parameters at several steps.
+.
+.
+.TP
+.B --debug\-shell
+Enable one debugging information, the shell name for
+.File_name groffer2.sh .
+.
+.
+.TP
+.B --debug\-stacks
+Enable one debugging information, the function call stack.
+.
+.
+.TP
+.B --debug\-tmpdir
+Enable one debugging information, the name of the temporary directory.
+.
+.
+.TP
+.B --debug\-user
+Enable one debugging information, the function stack with
+\f[CR]error_user()\f[].
+.
+.
+.TP
+.B --do-nothing
+This is like
+.BR --version ,
+but without the output; no viewer is started.
+.
+This makes only sense in development.
+.
+.
+.TP
+.B --print=\fItext\fR
+Just print the argument to standard error.
+.
+This is good for parameter check.
+.
+.
+.TP
+.B --shell \fIshell_program\fR
+Specify the shell under which the
+.File_name \%groffer2.sh
+script should be run.
+.
+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.
+.
+.
+.TP
+.B -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
+.B \%groff
+option
+.B -Z
+and
+.BR --mode=groff .
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Filespec Arguments"
+.\" --------------------------------------------------------------------
+.
+A
+.I \%filespec
+parameter is an argument that is not an option or option argument.
+.
+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
+The strange \%\f[CR]POSIX\f[] behavior to regard all arguments behind
+the first non-option argument as
+.I \%filespec
+arguments is ignored.
+.
+The \f[CR]GNU\f[] behavior to recognize options even when mixed with
+.I \%filespec
+arguments is used throughout.
+.
+But, as usual, the double minus argument
+.B --
+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
+The options
+.B --apropos*
+have a special handling of
+.I filespec
+arguments.
+.
+Each argument is taken as a search scheme of its own.
+.
+Also a regexp (regular expression) can be used in the filespec.
+.
+For example,
+.B groffer --apropos '^gro.f$'
+searches
+.B groff
+in the
+.I man\~page
+name, while
+.B groffer --apropos groff
+searches
+.B groff
+somewhere in the name or description of the
+.IR man\~pages .
+.
+.
+.P
+All other parts of
+.IR groffer ,
+such as the normal display or the output with
+.B --whatis
+have a different scheme for
+.IR filespecs .
+No regular expressions are used for the arguments.
+.
+The
+.I filespec
+arguments are handled by the following scheme.
+.
+.
+.P
+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 a digit from
+.B 1
+to
+.B 9
+or one of the characters
+.B n
+or
+.BR o .
+.
+.
+.P
+This can optionally be followed by a string, the so-called
+.IR extension .
+The
+.I extension
+allows to store several
+.I man\~pages
+with the same name in the same
+.IR section .
+But the
+.I extension
+is only rarely used, usually it is omitted.
+.
+Then the
+.I extensions
+are searched automatically by alphabet.
+.
+.
+.P
+In the following, we use the name
+.I section_extension
+for a word that consists of a single character
+.I section
+name or a
+.I section
+character that is followed by an
+.IR extension .
+.
+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
+.B -
+always stands for standard input; it can occur several times.
+.
+If you want to look up a
+.I \%man\~page
+called
+.B -
+use the argument
+.BR man:\- .
+.
+.
+.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_extension ) ,
+.BI \%man: name . section_extension,
+.IB \%name ( section_extension ) ,
+or
+.IB \%name . section_extension
+search the \%man\~page
+.I \%name
+in \%man\~section and possibly extension of
+.IR \%section_extension .
+.
+.
+.Topic
+Now
+.BI \%man: name
+searches for a
+.I \%man\~page
+in the lowest
+.I \%man\~section
+that has a document called
+.IR \%name .
+.
+.
+.Topic
+.I \%section_extension\~name
+is a pattern of 2 arguments that originates from a strange argument
+parsing of the
+.B man
+program.
+.
+Again, this searches the man page
+.I name
+with
+.IR \%section_extension ,
+a combination of a
+.I section
+character optionally followed by an
+.IR extension .
+.
+.
+.Topic
+We are left with the argument
+.I \%name
+which is not an existing file.
+.
+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
+Several file name arguments can be supplied.
+.
+They are mixed by
+.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
+language.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "OUTPUT MODES"
+.\" --------------------------------------------------------------------
+.
+By default, the
+.B \%groffer
+program collects all input into a single file, formats it with the
+.B \%groff
+program for a certain device, and then chooses a suitable viewer
+program.
+.
+The device and viewer process in
+.B \%groffer
+is called a
+.IR \%mode .
+.
+The mode and viewer of a running
+.B \%groffer
+program is selected automatically, but the user can also choose it
+with options.
+.
+.
+The modes are selected by option the arguments of
+.BR --mode=\fIanymode .
+Additionally, each of this argument can be specified as an option of
+its own, such as
+.BR anymode .
+Most of these modes have a viewer program, which can be chosen by an
+option that is constructed like
+.BR --\fIanymode\fR\-viewer .
+.
+.
+.P
+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.
+.
+.
+.P
+By default,
+.B \%groffer
+first tries whether
+.I \%x\~mode
+is possible, then
+.IR \%ps\~mode ,
+and finally
+.IR \%tty\~mode .
+.
+This mode testing sequence for
+.I \%auto\~mode
+can be changed by specifying a comma separated list of modes with the
+option
+.B --default\-modes.
+.
+.
+.P
+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 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
+.B --display
+are used for specifying the \%\f[CR]X\~Window\f[] display to be used.
+.
+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
+.BR --default\-modes .
+.
+.
+.P
+Known viewers for the graphical display modes and their standard
+\%\f[CR]X\~Window\f[] viewer programs are
+.
+.Topic
+in a PDF viewer
+.nh
+.RI ( \%pdf\~mode )
+.hy
+.
+.Topic
+in a web browser
+.nh
+.RI ( html
+or
+.IR \%www\~mode )
+.hy
+.RE
+.
+.Topic
+in a Postscript viewer
+.nh
+.RI ( \%ps\~mode )
+.hy
+.
+.Topic
+\%\f[CR]X\~Window\f[]
+.I roff
+viewers such as
+.BR \%gxditview (@MAN1EXT@)
+or
+.BR \%xditview (1)
+(in
+.IR \%x\~mode )
+.
+.Topic
+in a dvi viewer program
+.nh
+.RI ( \%dvi\~mode )
+.hy
+.
+.
+.P
+The
+.I \%pdf\~mode
+has a major advantage \[em] it is the only graphical display 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
+format, so it was not chosen as the major mode.
+.
+.
+.P
+These graphical viewers can be customized by options of the
+\%\f[CR]X\~Window\~Toolkit\f[].
+.
+But the
+.B \%groffer
+options use a leading double minus instead of the single minus used by
+the \%\f[CR]X\~Window\~Toolkit\f[].
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Text modes"
+.\" --------------------------------------------------------------------
+.
+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,
+.B \%groffer
+assumes that it should use
+.IR \%tty\~\%mode .
+.
+.
+.P
+In the actual implementation, the
+.I groff
+output device
+.I \%latin1
+is chosen for
+.IR \%text\~modes .
+.
+This can be changed by specifying option
+.B -T
+or
+.BR \%--device .
+.
+.
+.P
+The pager to be used can be specified by one of the options
+.B --pager
+and
+.BR --tty\-viewer ,
+or by the environment variable
+.Env_var \%$PAGER .
+If all of this is not used the
+.BR \%less (1)
+program with the option
+.B -r
+for correctly displaying control sequences is used as the default
+pager.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Special Modes for Debugging and Development"
+.\" --------------------------------------------------------------------
+.
+These modes use the
+.I \%groffer
+file determination and decompression.
+.
+This is combined into a single input file that is fed directly into
+.B \%groff
+with different strategy without the
+.I \%groffer
+viewing facilities.
+.
+These modes are regarded as advanced, they are useful for debugging
+and development purposes.
+.
+.
+.P
+The
+.I \%source\~mode
+with option
+.B --source
+just displays the decompressed input.
+.
+.
+.P
+Otion
+.B --to\-stdout
+does not display in a graphical mode.
+.
+It just generates the file for the chosen mode and then prints its
+content to standard output.
+.
+.
+.P
+The
+.I \%groff\~mode
+passes the input to
+.B \%groff
+using only some suitable options provided to
+.BR \%groffer .
+.
+This enables the user to save the generated output into a file or pipe
+it into another program.
+.
+.
+.P
+In
+.IR \%groff\~\%mode ,
+the option
+.B -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@)
+for details.
+.
+.
+.P
+All
+.B \%groff
+short options are supported by
+.BR \%groffer .
+.
+.
+.\" --------------------------------------------------------------------
+.SH "MAN PAGE SEARCHING"
+.\" --------------------------------------------------------------------
+.
+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 the name
+of a
+.IR \%man\~page .
+The following options can be used to determine whether the arguments
+should be handled as file name or
+.I \%man\~page
+arguments.
+.
+.TP
+.B --man
+forces to interpret all file parameters as
+.I \%filespecs
+for searching
+.IR \%man\~pages .
+.
+.TP
+.B --no\-man
+.TQ
+.B --local\-file
+disable the
+.I man
+searching; so only local files are displayed.
+.
+.
+.P
+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.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Search Algorithm"
+.\" --------------------------------------------------------------------
+.
+Let us now assume that a
+.I \%man\~page
+should be searched.
+.
+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 \f[CR]GNU\fP
+.BR \%man (1)
+program were implemented.
+.
+The search algorithm shall determine which file is displayed for a given
+.IR \%man\~page .
+The process can be modified by options and environment variables.
+.
+.
+.P
+The only
+.I man
+action that is omitted in
+.B \%groffer
+are the preformatted
+.IR \%man\~pages ,
+also called
+.IR cat\~pages .
+.
+With the excellent performance of the actual computers, the
+preformatted
+.I \%man\~pages
+aren't necessary any longer.
+.
+Additionally,
+.B \%groffer
+is a
+.I roff
+program; it wants to read
+.I roff
+source files and format them itself.
+.
+.
+.P
+The algorithm for retrieving the file for a
+.I \%man\~page
+needs first a set of directories.
+.
+This set starts with the so-called
+.I man\~path
+that is modified later on by adding names of
+.I operating system
+and
+.IR language .
+.
+This arising set is used for adding the section directories which
+contain the
+.I \%man\~page
+files.
+.
+.
+.P
+The
+.I man\~path
+is a list of directories that are separated by colon.
+.
+It is generated by the following methods.
+.
+.Topic
+The environment variable
+.Env_var \%$MANPATH
+can be set.
+.
+.Topic
+It can be read from the arguments of the environment variable
+.Env_var \%$MANOPT .
+.
+.Topic
+The
+.I man\~path
+can be manually specified by using the option
+.BR --manpath .
+An empty argument disables the
+.I \%man\~page
+searching.
+.
+.Topic
+When no
+.I man\~path
+was set the
+.BR \%manpath (1)
+program is tried to determine one.
+.
+.Topic
+If this does not work a reasonable default path from
+.Env_var $PATH
+is determined.
+.
+.
+.P
+We now have a starting set of directories.
+.
+The first way to change this set is by adding names of
+.I operating
+.IR systems .
+.
+This assumes that
+.I \%man\~pages
+for several
+.I operating systems
+are installed.
+.
+This is not always true.
+.
+The names of such
+.I operating systems
+can be provided by 3 methods.
+.
+.Topic
+The environment variable
+.Env_var \%$SYSTEM
+has the lowest precedence.
+.
+.Topic
+This can be overridden by an option in
+.Env_var \%$MANOPT .
+.
+.Topic
+This again is overridden by the command line option
+.BR --systems .
+.
+.
+.P
+Several names of
+.I operating systems
+can be given by appending their names, separated by a comma.
+.
+.
+.P
+The
+.I man\~path
+is changed by appending each
+.I system
+name as subdirectory at the end of each directory of the set.
+.
+No directory of the
+.I man\~path
+set is kept.
+.
+But if no
+.I system
+name is specified the
+.I man\~path
+is left unchanged.
+.
+.
+.P
+After this, the actual set of directories can be changed by
+.I language
+information.
+.
+This assumes that there exist
+.I man\~pages
+in different languages.
+.
+The wanted
+.I language
+can be chosen by several methods.
+.
+.Topic
+Environment variable
+.Env_var $LANG .
+.
+.Topic
+This is overridden by
+.Env_var \%$LC_MESSAGES .
+.
+.Topic
+This is overridden by
+.Env_var $LC_ALL .
+.
+.Topic
+This can be overridden by providing an option in
+.Env_var \%$MANOPT .
+.
+.Topic
+All these environment variables are overridden by the command line
+option
+.BR --locale .
+.
+.
+.P
+The
+.I default language
+can be specified by specifying one of the pseudo-language parameters
+\f[CR]C\fP or \f[CR]\%POSIX\fP.
+.
+This is like deleting a formerly given
+.I language
+information.
+.
+The
+.I \%man\~pages
+in the
+.I default language
+are usually in English.
+.
+.
+.P
+Of course, the
+.I language
+name is determined by
+.BR man .
+In \f[CR]GNU\fP
+.BR man ,
+it is specified in the \%\f[CR]POSIX\~1003.1\fP based format:
+.P
+.nh
+\f[I]<language>\f[][\f[CB]_\f[]\f[I]<territory>\f[][\f[CB].\fP\
+\f[I]<character-set>\f[][\f[CB],\fP\f[I]<version>\fP]]],
+.hy
+.P
+but the two-letter code in
+.nh
+.I <language>
+.hy
+is sufficient for most purposes.
+.
+If for a complicated
+.I language
+formulation no
+.I \%man\~pages
+are found
+.B \%groffer
+searches the country part consisting of these first two characters as
+well.
+.
+.
+.P
+The actual directory set is copied thrice.
+.
+The
+.I language
+name is appended as subdirectory to each directory in the first copy
+of the actual directory set (this is only done when a language
+information is given).
+.
+Then the 2-letter abbreviation of the
+.I language
+name is appended as subdirectories to the second copy of the directory
+set (this is only done when the given language name has more than 2
+letters).
+.
+The third copy of the directory set is kept unchanged (if no
+.I language
+information is given this is the kept directory set).
+.
+These maximally 3 copies are appended to get the new directory set.
+.
+.
+.P
+We now have a complete set of directories to work with.
+.
+In each of these directories, the
+.I man
+files are separated in
+.IR sections .
+.
+The name of a
+.I section
+is represented by a single character, a digit between
+.I 1
+and
+.IR 9 ,
+or the character
+.I o
+or
+.IR n ,
+in this order.
+.
+.
+.P
+For each available
+.IR section ,
+a subdirectory
+.File_name man \fI<section>\fP
+exists containing all
+.I man
+files for this
+.IR section ,
+where
+.I <section>
+is a single character as described before.
+.
+Each
+.I man
+file in a
+.I section
+directory has the form
+.IR \%\f[CB]man\fP<section>\f[CB]/\fP<name>\f[CB].\fP<section>\
+[<extension>][\f[CB].\fP<compression>] ,
+where
+.I \%<extension>
+and
+.I \%<compression>
+are optional.
+.
+.I \%<name>
+is the name of the
+.I \%man\~page
+that is also specified as filespec argument on the command line.
+.
+.
+.P
+The
+.I extension
+is an addition to the section.
+.
+This postfix acts like a subsection.
+.
+An
+.I extension
+occurs only in the file name, not in name of the
+.I section
+subdirectory.
+.
+It can be specified on the command line.
+.
+.
+.P
+On the other hand, the
+.I compression
+is just an information on how the file is compressed.
+.
+This is not important for the user, such that it cannot be specified
+on the command line.
+.
+.
+.P
+There are 4 methods to specify a
+.I section
+on the command line:
+.
+.Topic
+Environment variable
+.Env_var \%$MANSECT
+.
+.Topic
+Command line option
+.B --sections
+.
+.Topic
+Appendix to the
+.I name
+argument in the form
+.I <name>.<section>
+.
+.Topic
+Preargument before the
+.I name
+argument in the form
+.I <section> <name>
+.
+.
+.P
+It is also possible to specify several
+.I sections
+by appending the single characters separated by colons.
+.
+One can imagine that this means to restrict the
+.I \%man\~page
+search to only some
+.IR sections .
+.
+The multiple
+.I sections
+are only possible for
+.Env_var \%$MANSECT
+and
+.BR --sections .
+.
+.
+.P
+If no
+.I section
+is specified all
+.I sections
+are searched one after the other in the given order, starting with
+.IR section\~1 ,
+until a suitable file is found.
+.
+.
+.P
+There are 4 methods to specify an
+.I extension
+on the command line.
+.
+But it is not necessary to provide the whole extension name, some
+abbreviation is good enough in most cases.
+.
+.Topic
+Environment variable
+.Env_var \%$EXTENSION
+.
+.Topic
+Command line option
+.B --extension
+.
+.Topic
+Appendix to the
+.I <name>.<section>
+argument in the form
+.I <name>.<section><extension>
+.
+.Topic
+Preargument before the
+.I name
+argument in the form
+.I <section><extension> <name>
+.
+.
+.P
+For further details on
+.I \%man\~page
+searching, see
+.BR \%man (1).
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Examples of man files"
+.\" --------------------------------------------------------------------
+.
+.TP
+.File_name /usr/share/man/man1/groff.1
+This is an uncompressed file for the
+.I \%man\~page
+\f[CR]groff\fP in
+.IR section\~1 .
+.
+It can be called by
+.EX
+\fIsh#\fR groffer\~groff
+.EE
+No
+.I section
+is specified here, so all
+.I sections
+should be searched, but as
+.I section\~1
+is searched first this file will be found first.
+.
+The file name is composed of the following components.
+.File_name /usr/share/man
+must be part of the
+.IR \%man\~path ;
+the subdirectory
+.File_name man1/
+and the part
+.File_name .1
+stand for the
+.IR section ;
+.File_name groff
+is the name of the
+.IR \%man\~page .
+.
+.
+.TP
+.File_name /usr/local/share/man/man7/groff.7.gz
+The file name is composed of the following components.
+.File_name /usr/local/share/man
+must be part of the
+.IR \%man\~path ;
+the subdirectory
+.File_name man7/
+and the part
+.File_name .7
+stand for the
+.IR section ;
+.File_name groff
+is the name of the
+.IR \%man\~page ;
+the final part
+.File_name .gz
+stands for a compression with
+.BR gzip (1).
+As the
+.I section
+is not the first one it must be specified as well.
+.
+This can be done by one of the following commands.
+.EX
+\fIsh#\fR\~groffer\~groff.7
+\fIsh#\fR\~groffer\~7\~groff
+\fIsh#\fR\~groffer\~\-\-sections=7\~groff
+.EE
+.
+.TP
+.File_name /usr/local/man/man1/ctags.1emacs21.bz2
+Here
+.File_name /usr/local/man
+must be in
+.IR \%man\~path ;
+the subdirectory
+.File_name man1/
+and the file name part
+.File_name .1
+stand for
+.IR section\~1 ;
+the name of the
+.I \%man\~page
+is
+.File_name ctags ;
+the section has an extension
+.File_name emacs21 ;
+and the file is compressed as
+.File_name .bz2
+with
+.BR bzip2 (1).
+The file can be viewed with one of the following commands
+.EX
+\fIsh#\fR\~groffer\~ctags.1e
+\fIsh#\fR\~groffer\~1e\~ctags
+\fIsh#\fR\~groffer\~\-\-extension=e\~\-\-sections=1\~ctags
+.EE
+where \f[CR]e\fP works as an abbreviation for the extension
+\f[CR]emacs21\fP.
+.
+.
+.TP
+.File_name /usr/man/linux/de/man7/man.7.Z
+The directory
+.File_name /usr/man
+is now part of the
+.IR \%man\~path ;
+then there is a subdirectory for an
+.I operating system
+name
+.File_name linux/ ;
+next comes a subdirectory
+.File_name de/
+for the German
+.IR language ;
+the
+.I section
+names
+.File_name man7
+and
+.File_name .7
+are known so far;
+.File_name man
+is the name of the
+.IR \%man\~page ;
+and
+.File_name .Z
+signifies the compression that can be handled by
+.BR gzip (1).
+We want now show how to provide several values for some options.
+.
+That is possible for
+.I sections
+and
+.I operating system
+names.
+.
+So we use as
+.I sections\~5
+and
+.I 7
+and as
+.I system
+names
+.I linux
+and
+.IR aix .
+The command is then
+.sp
+.EX
+\fIsh#\fR groffer\~\-\-locale=de\~\-\-sections=5:7\~\-\-systems=linux,aix\~man
+\fIsh#\fR LANG=de\~MANSECT=5:7\~SYSTEM=linux,aix\~groffer\~man
+.EE
+.
+.
+.\" --------------------------------------------------------------------
+.SH DECOMPRESSION
+.\" --------------------------------------------------------------------
+.
+The program has a decompression facility.
+.
+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)
+or
+.BR \%bzip2 (1)
+it is decompressed on-the-fly.
+.
+This includes the \f[CR]GNU\fP
+.BR \%.gz ,
+.BR \%.bz2 ,
+and the traditional
+.B \%.Z
+compression.
+.
+The program displays the concatenation of all decompressed input in
+the sequence that was specified on the command line.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "ENVIRONMENT"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program supports many system variables, most of them by courtesy of
+other programs.
+.
+All environment variables of
+.BR \%groff (@MAN1EXT@)
+and \f[CR]GNU\fP
+.BR \%man (1)
+and some standard system variables are honored.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Native groffer Variables"
+.\" --------------------------------------------------------------------
+.
+.TP
+.Env_var \%$GROFFER_OPT
+Store options for a run of
+.BR \%groffer .
+.
+The options specified in this variable are overridden by the options
+given on the command line.
+.
+The content of this variable is run through the shell builtin `eval';
+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
+.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).
+The corresponding system environment is automatically effective.
+.
+The following variables have a special meaning for
+.BR \%groffer .
+.
+.
+.TP
+.Env_var \%$DISPLAY
+If this variable is set this indicates that the \%\f[CR]X\~Window\fP
+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
+.B \%groffer
+on a remote \%\f[CR]X\~Window\fP terminal.
+.
+For example, depending on your system,
+.B \%groffer
+can be started on the second monitor by the command
+.sp
+.EX
+\fIsh#\fR DISPLAY=:0.1\~groffer\~what.ever &
+.EE
+.
+.
+.TP
+.Env_var \%$LC_ALL
+.TQ
+.Env_var \%$LC_MESSAGES
+.TQ
+.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
+.IR \%man\~pages .
+.
+A locale name is typically of the form
+.nh
+.IR language [\c
+.B _\c
+.IR territory [\c
+.B .\c
+.IR codeset [\c
+.B @\c
+.IR modifier ]]],
+.hy
+where
+.I \%language
+is an ISO 639 language code,
+.I \%territory
+is an ISO 3166 country code, and
+.I \%codeset
+is a character set or encoding identifier like ISO-8859-1 or UTF-8;
+see
+.BR \%setlocale (3).
+.
+The locale values \f[CR]C\fP and \%\f[CR]POSIX\fP
+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.
+.
+.
+.TP
+.Env_var \%$PAGER
+This variable can be used to set the pager for the tty output.
+.
+For example, to disable the use of a pager completely set this
+variable to the
+.BR \%cat (1)
+program
+.sp
+.EX
+\fIsh#\fR PAGER=cat\~groffer\~anything
+.EE
+.sp
+.
+.TP
+.Env_var $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
+.BR \%groffer .
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Groff Variables"
+.\" --------------------------------------------------------------------
+.
+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 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,
+.B \%groffer
+uses it for storing its temporary files, just as
+.B groff
+does.
+.
+See the
+.BR \%groff (@MAN1EXT@)
+man page for more details on the location of temporary files.
+.
+.
+.\" --------------------------------------------------------------------
+.SS "Man Variables"
+.\" --------------------------------------------------------------------
+.
+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
+.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
+.I \%man\~pages
+to files having this extension.
+.
+This is overridden by option
+.BR --extension ;
+see there for details.
+.
+.
+.TP
+.Env_var \%$MANOPT
+This variable contains options as a preset for
+.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 that are specific to
+.IR man .
+.
+All options specified in this variable are overridden by the options
+given on the command line.
+.
+.
+.TP
+.Env_var \%$MANPATH
+If set, this variable contains the directories in which the
+.I \%man\~page
+trees are stored.
+.
+This is overridden by option
+.BR \%--manpath .
+.
+.
+.TP
+.Env_var \%$MANSECT
+If this is a colon separated list of section names, the search for
+.I \%man\~pages
+is restricted to those manual sections in that order.
+.
+This is overridden by option
+.BR --sections .
+.
+.
+.TP
+.Env_var \%$SYSTEM
+If this is set to a comma separated list of names these are interpreted
+as
+.I \%man\~page
+trees for different operating systems.
+.
+This variable can be overwritten by option
+.BR --systems ;
+see there for details.
+.
+.
+.P
+The environment variable
+.Env_var \%$MANROFFSEQ
+is ignored by
+.B \%groffer
+because the necessary preprocessors are determined automatically.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "CONFIGURATION FILES"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program can be preconfigured by two configuration files.
+.
+.
+.TP
+.File_name \%/etc/groff/groffer.conf
+System-wide configuration file for
+.BR \%groffer .
+.
+.
+.TP
+.File_name \%$HOME/.groff/groffer.conf
+User-specific configuration file for
+.BR \%groffer ,
+where
+.Env_var \%$HOME
+denotes the user's home directory.
+.
+This file is called after the system-wide configuration file to enable
+overriding by the user.
+.
+.
+.P
+Both files are handled for the configuration, but the configuration
+file in
+.File_name /etc
+comes first; 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 arguments.
+.
+.
+.P
+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.
+.
+.
+.P
+The lines with the beginning minus are interpreted as
+.B groffer
+options.
+.
+This easily allows to set general
+.B \%groffer
+options that should be used with any call of
+.BR \%groffer .
+.
+.
+.P
+If a lines starts with a double minus it represents a
+.B \%groffer
+long option; everything behind the first equal sign
+.RB ` = '
+or space character up to the end of the line is interpreted as its
+argument.
+.
+A line starting with a single minus represents a short options cluster
+with or without a final argument.
+.
+It is not necessary to use quotes in these lines; quotes are just
+ignored.
+.
+.
+.P
+The lines starting with a minus are changed into a prepend to the
+existing value of
+.Env_var \%$GROFFER_OPT .
+.
+So the configuration files will be transferred into a shell script
+that is called within
+.BR \%groffer .
+.
+.
+.P
+It makes sense to use these configuration files for the following
+tasks:
+.
+.Topic
+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
+.BR \%groffer ;
+but do not forget to export them.
+.
+.Topic
+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
+.B --\f[I]mode\fP\-viewer
+option.
+.
+.Topic
+Enter
+.B --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 that can be
+used either in
+.File_name \%/etc/groff/groffer.conf
+or
+.File_name \%~/.groff/groffer.conf .
+.
+.
+.P
+.ft CR
+.nh
+.nf
+# groffer configuration file
+#
+# groffer options that are used in each call of groffer
+\-\-shell=ksh
+\-\-foreground=DarkBlue
+\-\-resolution=100
+\-\-x\-viewer=gxditview \-geometry 900x1200
+#
+# some shell commands
+if test "$DISPLAY" = ""; then
+ export DISPLAY='localhost:0.0'
+fi
+date >>~/mygroffer.log
+.fi
+.hy
+.ft
+.
+.
+.P
+The lines starting with
+.B #
+are just ignored, so they act as 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
+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 100dpi
+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
+.I \%x-mode
+viewer using the geometry option for setting the width to
+.B 900px
+and the height to
+.BR 1200px .
+This geometry is suitable for a resolution of
+.BR 100dpi .
+.
+.
+.Topic
+If the environment variable
+.Env_var \%$DISPLAY
+is empty set it to
+.IR localhost:0.0 .
+.
+That allows to start
+.B \%groffer
+in the standard \%\f[CR]X\~Window\fP display, even when the program
+is called from a text console.
+.
+.
+.Topic
+Just for fun, the date of each
+.B \%groffer
+start is written to the file
+.File_name mygroffer.log
+in the home directory.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "EXAMPLES"
+.\" --------------------------------------------------------------------
+.
+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.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~/usr/local/share/doc/groff/meintro.ms.gz
+.EE
+.sp
+Decompress, format and display the compressed file
+.File_name meintro.ms.gz
+in the directory
+.File_name /usr/local/share/doc/groff ,
+using the standard viewer
+.B \%gxditview
+as graphical viewer when in \%\f[CR]X\~Window\fP, or the
+.BR \%less (1)
+pager program when not in \%\f[CR]X\~Window\fP.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~groff
+.EE
+.sp
+If the file
+.File_name \%./groff
+exists use it as input.
+.
+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.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~man:groff
+.EE
+.sp
+search for the
+.I \%man\~page
+of
+.B \%groff
+even when the file
+.File_name ./groff
+exists.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~groff.7
+\fIsh#\fR\~groffer\~7\~groff
+.EE
+.sp
+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.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~fb.modes
+.EE
+.sp
+If the file
+.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
+is not a single character in classical section style the argument is
+not split to a search for
+.BR fb .
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~groff\~\[cq]troff(1)\[cq]\~man:roff
+.EE
+.sp
+The arguments that are not existing files are looked-up as the
+following
+.IR \%man\~pages :
+.B \%groff
+(automatic search, should be found in \fIman\fP\~section\~1),
+.B \%troff
+(in section\~1),
+and
+.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 parentheses are special shell characters;
+escaping them with a backslash character
+.I \[rs](
+and
+.I \[rs])
+would be possible, too.
+.
+The formatted files are concatenated and displayed in one piece.
+.
+.sp
+.EX
+\fIsh#\fR\~LANG=de\~groffer\~--man\~--www\~--www-viewer=galeon\~ls
+.EE
+.sp
+Retrieve the German
+.I \%man\~page
+(language
+.IR de )
+for the
+.B ls
+program, decompress it, format it to
+.I \%html
+format
+.nh
+.RI ( \%www\~mode )
+.hy
+and view the result in the web browser
+.BR \%galeon .
+The option
+.B --man
+guarantees that the
+.I \%man\~page
+is retrieved, even when a local file
+.File_name \%ls
+exists in the actual directory.
+.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~--source\~'man:roff(7)'
+.EE
+.sp
+Get the
+.I \%man\~page
+called
+.I \%roff
+in \fIman\fP\~section 7, decompress it, and print its unformatted
+content, its source code.
+.
+.
+.sp
+.EX
+\fIsh#\fR\~groffer\~--de-p\~--in\~--ap
+.EE
+.sp
+This is a set of abbreviated arguments, it is determined as
+.br
+.sp
+.EX
+\fIsh#\fR\~groffer\~--debug-params\~--intermediate-output\~--apropos
+.EE
+.sp
+.
+.sp
+.EX
+\fIsh#\fR\~cat\~file.gz\~|\~groffer\~-Z\~-mfoo
+.EE
+.sp
+.
+The file
+.File_name file.gz
+is sent to standard input, this is decompressed, and then this is
+transported to the
+.I \%groff intermediate output mode
+without post-processing
+.RB ( groff
+option
+.BR -Z ),
+using macro package
+.I \%foo
+.RB ( groff
+option
+.BR -m ).
+.
+.
+.sp
+.EX
+\fIsh#\fR\~echo\~'\[rs]f[CB]WOW!'\~|
+> groffer --x --bg red --fg yellow --geometry 200x100 -
+.EX
+.sp
+.
+Display the word \f[CB]WOW!\fP in a small window in constant-width
+bold font, using color yellow on red background.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "COMPATIBILITY"
+.\" --------------------------------------------------------------------
+.
+The
+.B \%groffer
+program consists of two shell scripts.
+.
+.
+.P
+The starting script is the file
+.File_name \%groffer
+that is installed in a
+.File_name bin
+directory.
+.
+It is generated from the source file
+.File_name \%groffer.sh .
+.
+It is just a short starting script without any functions such that it
+can run on very poor shells.
+.
+.
+.P
+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
+.BR --shell .
+.
+.
+.P
+Both scripts are compatible with both
+\f[CR]GNU\fP and \%\f[CR]POSIX\fP.
+.
+\%\f[CR]POSIX\fP compatibility refers to
+\%\f[CR]IEEE\~P1003.2/D11.2\fP of September 1991, a very early
+version of the \%\f[CR]POSIX\fP standard that is still freely
+available on the Internet at
+.UR http://\:www.funet.fi/\:pub/\:doc/\:posix/\:p1003.2/\:d11.2/\:all
+\%POSIX\~P1003.2\~draft\~11.2
+.UE .
+.
+.
+.P
+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\fP compatible.
+.
+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.
+.
+.
+.P
+The shell for the run of
+.File_name groffer2.sh
+can be chosen by the option
+.BR --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
+.BR --shell .
+.
+.
+.P
+The
+.B \%groffer
+program provides its own parser for command line arguments that is
+compatible to both \%\f[CR]POSIX\fP
+.BR \%getopts (1)
+and \%\f[CR]GNU\fP
+.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
+The option consisting of a single minus
+.B -
+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
+.B -Qmfoo
+is equivalent to
+.BR -Q\~\-m\~foo .
+.
+.
+.Topic
+Long options are options with names longer than one character; they
+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,
+.B --long=arg
+is equivalent to
+.BR --long\~arg .
+.
+.
+.Topic
+An argument of
+.B --
+ends option parsing; all further command line arguments are
+interpreted as
+.I \%filespec
+parameters, i.e. file names or constructs for searching
+.IR \%man\~pages ).
+.
+.
+.Topic
+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
+.sp
+.EX
+\fIsh#\fR\~groffer file1 -a -o arg file2
+.EE
+.sp
+is equivalent to
+.sp
+.EX
+\fIsh#\fR\~groffer -a -o arg -- file1 file2
+.EE
+.sp
+.
+.P
+The free mixing of options and
+.I \%filespec
+parameters follows the GNU principle.
+.
+That does not fulfill the strange option behavior of \%\f[CR]POSIX\fP
+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 "BUGS"
+.\" --------------------------------------------------------------------
+.
+Report bugs to the
+.MT bug-groff@gnu.org
+bug-groff mailing list
+.ME .
+.
+Include a complete, self-contained example that will allow the bug to
+be reproduced, and say which version of
+.B \%groffer
+you are using.
+.
+.
+.P
+You can also use the
+.MT groff@gnu.org
+groff mailing list
+.ME ,
+but you must first subscribe to this list.
+.
+You can do that by visiting the
+.UR http://\:lists.gnu.org/\:mailman/\:listinfo/\:groff
+groff mailing list web page
+.UE .
+.
+.
+.P
+See
+.BR \%groff (@MAN1EXT@)
+for information on availability.
+.
+.
+.\" --------------------------------------------------------------------
+.SH "SEE ALSO"
+.\" --------------------------------------------------------------------
+.
+.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 \%groff (@MAN7EXT@)
+Documentation of the
+.I \%groff
+language.
+.
+.
+.TP
+.BR \%grog (@MAN1EXT@)
+Internally,
+.B \%groffer
+tries to guess the
+.B \%groff
+command line options from the input using this program.
+.
+.
+.TP
+.BR groff_out (@MAN5EXT@)
+Documentation on the
+.I \%groff intermediate output
+.nh
+.RI ( ditroff
+output).
+.hy
+.
+.
+.TP
+.BR groff_tmac (@MAN5EXT@)
+Documentation on the
+.I \%groff
+macro files.
+.
+.
+.TP
+.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 .
+.
+.
+.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
+.
+.
+.P
+.BR \%gxditview (@MAN1EXT@),
+.BR \%xditview (1x)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%x\~mode .
+.RE
+.
+.
+.P
+.BR \%kpdf (1),
+.BR \%kghostview (1),
+.BR \%evince (1),
+.BR \%ggv (1),
+.BR \%gv (1),
+.BR \%ghostview (1),
+.BR \%gs (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%ps\~mode .
+.RE
+.
+.
+.P
+.BR \%kpdf (1),
+.BR \%acroread (1),
+.BR \%evince (1),
+.BR \%xpdf (1),
+.BR \%gpdf (1),
+.BR \%kghostview (1),
+.BR \%ggv (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%pdf\~mode .
+.RE
+.
+.
+.P
+.BR \%kdvi (1),
+.BR \%xdvi (1),
+.BR \%dvilx (1)
+.RS
+Viewers for
+.BR \%groffer 's
+.IR \%dvi\~mode .
+.RE
+.
+.
+.P
+.BR \%konqueror (1),
+.BR \%epiphany (1),
+.BR \%firefox (1),
+.BR \%mozilla (1),
+.BR \%netscape (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
+.IR \%tty\~mode .
+.
+.
+.P
+.BR \%gzip (1),
+.BR \%bzip2 (1)
+.RS
+The decompression programs supported by
+.BR \%groffer .
+.RE
+.
+.
+.\" --------------------------------------------------------------------
+.SH "AUTHOR"
+.\" --------------------------------------------------------------------
+.author
+.
+.
+.\" --------------------------------------------------------------------
+.SH "COPYING"
+.\" --------------------------------------------------------------------
+.copyleft
+.
+.
+.\" --------------------------------------------------------------------
+.\" Emacs settings
+.\" --------------------------------------------------------------------
+.
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/contrib/groffer/shell/groffer.sh b/contrib/groffer/shell/groffer.sh
new file mode 100755
index 00000000..dc82ad81
--- /dev/null
+++ b/contrib/groffer/shell/groffer.sh
@@ -0,0 +1,384 @@
+#! /bin/sh
+
+# groffer - display groff files
+
+# Source file position: <groff-source>/contrib/groffer/groffer.sh
+# Installed position: <prefix>/bin/groffer
+
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+# Written by Bernd Warken <groff-bernd.warken-72@web.de>.
+
+# Last update: 5 Jan 2009
+
+# 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 3 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+########################################################################
+
+export GROFFER_OPT; # option environment for groffer
+
+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 _AT;
+export _SP;
+export _SQ;
+export _TAB;
+
+_AT='@';
+_SP=' ';
+_SQ="'";
+_TAB=' ';
+
+export _ERROR;
+_ERROR='7'; # for syntax errors; no `-1' in `ash'
+
+# @...@ constructs
+
+export _BEFORE_MAKE;
+if test _@VERSION@_ = _${_AT}VERSION${_AT}_
+then
+ # script before `make'
+ _BEFORE_MAKE='yes';
+else
+ _BEFORE_MAKE='no';
+fi;
+
+export _AT_BINDIR_AT;
+export _AT_G_AT;
+export _AT_LIBDIR_AT;
+export _GROFFER_LIBDIR;
+case "${_BEFORE_MAKE}" in
+yes)
+ self="$0";
+ case "${self}" in
+ /*) :; ;;
+ *)
+ curdir="$(pwd)";
+ case "${curdir}" in
+ */)
+ self="${curdir}${self}";
+ ;;
+ *)
+ self="${curdir}/${self}";
+ ;;
+ esac;
+ ;;
+ esac;
+ groffer_shell_dir="$(dirname ${self})";
+ case "${groffer_shell_dir}" in
+ */) :; ;;
+ *) groffer_shell_dir="${groffer_shell_dir}/";
+ esac;
+ groffer_top_dir="${groffer_shell_dir}../";
+ _AT_G_AT='';
+ _AT_BINDIR_AT="${groffer_shell_dir}";
+ _AT_LIBDIR_AT="${groffer_shell_dir}";
+ _GROFFER_LIBDIR="${_AT_LIBDIR_AT}";
+ _VERSION_SH="${groffer_top_dir}version.sh";
+ ;;
+no)
+ _AT_G_AT='@g@';
+ _AT_BINDIR_AT='@BINDIR@';
+ case "${_AT_BINDIR_AT}" in
+ */) :; ;;
+ *) _AT_BINDIR_AT="${_AT_BINDIR_AT}/";
+ esac;
+ _AT_LIBDIR_AT='@libdir@';
+ case "${_AT_LIBDIR_AT}" in
+ */) :; ;;
+ *) _AT_LIBDIR_AT="${_AT_LIBDIR_AT}/";
+ esac;
+ _GROFFER_LIBDIR="${_AT_LIBDIR_AT}"'groff/groffer/';
+ _VERSION_SH="${_GROFFER_LIBDIR}"'version.sh';
+ ;;
+esac;
+
+if test -f "${_VERSION_SH}"
+then
+ . "${_VERSION_SH}";
+fi;
+
+export _GROFF_VERSION;
+case "${_BEFORE_MAKE}" in
+yes)
+ _GROFF_VERSION="${_GROFF_VERSION_PRESET}";
+ ;;
+no)
+ _GROFF_VERSION='@VERSION@';
+ ;;
+esac;
+
+export _GROFFER2_SH; # file name of the script that follows up
+_GROFFER2_SH="${_GROFFER_LIBDIR}"'groffer2.sh';
+
+export _GROFFER_SH; # file name of this shell script
+case "$0" in
+*groffer*)
+ _GROFFER_SH="$0";
+ ;;
+*)
+ echo 'The groffer script should be started directly.' >&2
+ exit 1;
+ ;;
+esac;
+
+export _NULL_DEV;
+if test -c /dev/null
+then
+ _NULL_DEV="/dev/null";
+else
+ _NULL_DEV="NUL";
+fi;
+
+
+# Test of the `$()' construct.
+if test _"$(echo "$(echo 'test')")"_ \
+ != _test_
+then
+ echo 'The "$()" construct did not work.' >&2;
+ exit "${_ERROR}";
+fi;
+
+# Test of sed program
+if test _"$(echo red | sed 's/r/s/')"_ != _sed_
+then
+ echo 'The sed program did not work.' >&2;
+ exit "${_ERROR}";
+fi;
+
+# for some systems it is necessary to set some unset variables to `C'
+# according to Autobook, ch. 22
+for var in LANG LC_ALL LC_MESSAGES LC_CTYPES LANGUAGES
+do
+ if eval test _"\${$var+set}"_ = _set_
+ then
+ eval ${var}='C';
+ eval export ${var};
+ fi;
+done;
+
+
+########################### configuration
+
+# 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 '
+# Ignore comments
+/^['"${_SP}${_TAB}"']*#/d
+# Delete leading and final space
+s/^['"${_SP}${_TAB}"']*//
+s/['"${_SP}${_TAB}"']*$//
+# Print all lines with shell commands, those not starting with -
+/^[^-]/p
+# Remove all single and double quotes
+s/['"${_SQ}"'"]//g
+# 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
+# Encircle the remaining arguments with single quotes
+s/^\(-[^ ]*\) \(.*\)$/o="${o} \1 '"${_SQ}"'\2'"${_SQ}"'"/p
+')"
+
+ # Remove leading space
+ o="$(echo "$o" | sed 's/^ *//')";
+ if test _"${o}"_ != __
+ then
+ if test _"{GROFFER_OPT}"_ = __
+ then
+ GROFFER_OPT="${o}";
+ else
+ GROFFER_OPT="${o} ${GROFFER_OPT}";
+ fi;
+ fi;
+ fi;
+done;
+
+# 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;
+
+
+########################### Determine the shell
+
+export _SHELL;
+
+supports_func=no;
+foo() { echo bar; } 2>${_NULL_DEV};
+if test _"$(foo)"_ = _bar_
+then
+ supports_func=yes;
+fi;
+
+# 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;
+ ;;
+ --shell=*|--sh=*|--she=*|--shel=*)
+ # delete up to first "=" character
+ s="$(echo x"$1" | sed 's/^x[^=]*=//')";
+ ;;
+ *)
+ shift;
+ continue;
+ esac;
+ if test _"${x}"_ = __
+ then
+ x="'${s}'";
+ else
+ x="'${s}' ${x}";
+ fi;
+ shift;
+ done;
+
+ # 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
+ if test _"${supports_func}"_ = _yes_
+ then
+ # use the empty argument as the default shell
+ echo 'standard shell';
+ break;
+ else
+ echo groffer: standard shell does not support functions. >&2;
+ continue;
+ fi;
+ 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
+ # test whether shell supports functions
+ if eval "$i -c 'foo () { exit 0; }; foo'" 2>${_NULL_DEV}
+ then
+ # shell with function support found
+ cat <<EOF
+${i}
+EOF
+ break;
+ else
+ # if not being a shell with function support go on searching
+ echo groffer: argument $i is not a shell \
+with function support. >&2
+ continue;
+ fi;
+ else
+ # if not being a shell go on searching
+ echo groffer: argument $i is not a shell. >&2
+ continue;
+ fi;
+ fi;
+ done;
+ fi;
+ )";
+ if test _"${s}"_ != __
+ then
+ cat <<EOF
+${s}
+EOF
+ fi;
+ ;;
+ esac;
+`
+
+########################### test fast shells for automatic run
+
+if test _"${_SHELL}"_ = __
+then
+ # shell sorted by speed, bash is very slow
+ for s in ksh ash dash pdksh zsh posh sh bash
+ do
+ # test on shell with function support
+ if eval "$s -c 'foo () { exit 0; }; foo'" 2>${_NULL_DEV}
+ then
+ _SHELL="$s";
+ break;
+ fi;
+ done;
+fi;
+
+
+########################### start groffer2.sh
+
+if test _"${_SHELL}"_ = _'standard shell'_
+then
+ _SHELL='';
+fi;
+
+if test _"${_SHELL}"_ = __
+then
+ # no shell found, so start groffer2.sh normally
+ if test _${supports_func}_ = _yes_
+ then
+ eval . "'${_GROFFER2_SH}'" '"$@"';
+ exit;
+ else
+ echo groffer: standard shell does not support functions; no shell works.\
+Get some free working shell such as bash. >&2
+ exit "${_ERROR}";
+ fi;
+else
+ # start groffer2.sh with the found $_SHELL
+ # do not quote $_SHELL to allow arguments
+ eval exec "${_SHELL} '${_GROFFER2_SH}'" '"$@"';
+ exit;
+fi;
diff --git a/contrib/groffer/shell/groffer2.sh b/contrib/groffer/shell/groffer2.sh
new file mode 100644
index 00000000..d76c6bd5
--- /dev/null
+++ b/contrib/groffer/shell/groffer2.sh
@@ -0,0 +1,7312 @@
+#! /bin/sh
+
+# groffer - display groff files
+
+# Source file position: <groff-source>/contrib/groffer/shell/groffer2.sh
+# Installed position: <prefix>/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, 2006, 2009
+# Free Software Foundation, Inc.
+# Written by Bernd Warken <groff-bernd.warken-72@web.de>.
+
+# Last update: 5 Jan 2009
+
+# 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 3 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+########################################################################
+# Test of rudimentary shell functionality
+########################################################################
+
+# Zsh is not Bourne compatible without the following:
+if test -n "$ZSH_VERSION"; then
+ emulate sh
+ NULLCMD=:
+fi
+
+
+########################################################################
+# 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 xTesTx \
+ | sed -n 's/^.\([Tt]e*x*sTT*\).*$/\1/p' \
+ | sed 's|T|t|g')"_ != _test_
+then
+ echo 'The sed program did not work.' >&2;
+ exit "${_ERROR}";
+fi;
+
+
+########################################################################
+# Test of `cat'.
+#
+if test _"$(echo test | cat)"_ != _test_
+then
+ error 'Test of "cat" command failed.';
+fi;
+
+
+########################################################################
+# Test of function definitions.
+#
+_t_e_s_t_f_u_n_c_()
+{
+ return 0;
+}
+
+_test_func()
+{
+ echo test;
+}
+
+if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV} && \
+ test _"$(_test_func 2>${_NULL_DEV})"_ = _test_
+then
+ :;
+else
+ echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2;
+ exit "${_ERROR}";
+fi;
+
+
+########################################################################
+# landmark (<text>)
+#
+# Print <text> to standard error as a debugging aid.
+#
+# Globals: $_DEBUG_LM
+#
+landmark()
+{
+ if test _"${_DEBUG_LM}"_ = _yes_
+ then
+ echo "LM: $*" >&2;
+ fi;
+} # landmark()
+
+
+########################################################################
+# test for compression.
+#
+export _HAS_COMPRESSION;
+export _HAS_BZIP;
+if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_
+then
+ _HAS_COMPRESSION='yes';
+ if echo '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;
+
+
+########################################################################
+# debug - diagnostic messages
+########################################################################
+
+export _DEBUG_FUNC_CHECK;
+if test _"${_BEFORE_MAKE}"_ = _yes_
+then
+ _DEBUG_FUNC_CHECK='yes';
+else
+ _DEBUG_FUNC_CHECK='no';
+fi;
+_DEBUG_FUNC_CHECK='no'; # disable function checking
+#_DEBUG_FUNC_CHECK='yes'; # enable function checking
+
+export _DEBUG_STACKS;
+_DEBUG_STACKS='no'; # disable stack output in each function
+#_DEBUG_STACKS='yes'; # enable stack output in each function
+
+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()
+
+export _DEBUG_LM;
+_DEBUG_LM='no'; # disable landmark messages
+#_DEBUG_LM='yes'; # enable landmark messages
+
+export _DEBUG_GROG;
+_DEBUG_GROG='no'; # disable grog output
+#_DEBUG_GROG='yes'; # enable grog output
+
+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_PRINT_FILENAMES;
+_DEBUG_PRINT_FILENAMES='no'; # disable printing of the found file names
+#_DEBUG_PRINT_FILENAMES='yes'; # enable printing of the found file names
+
+# determine all --debug* options
+case " $*" in
+*\ --deb*|*\ --d*-*)
+ # --debug-* options
+ d=' --debug-all --debug-filenames --debug-func --debug-grog '\
+'--debug-not-func --debug-keep --debug-lm --debug-params '\
+'--debug-shell --debug-stacks --debug-tmpdir --debug-user ';
+ # non-debug options with scheme --d*-*
+ n=' --do-nothing --default-modes --dvi-viewer --dvi-viewer-tty ';
+ for i
+ do
+ case "$i" in
+ --deb|--debu|--debug)
+ _DEBUG_FUNC_CHECK='yes';
+ # _DEBUG_STACKS='yes';
+ _DEBUG_USER_WITH_STACK='yes';
+ # _DEBUG_LM='yes';
+ _DEBUG_GROG='yes';
+ _DEBUG_KEEP_FILES='yes';
+ _DEBUG_PRINT_PARAMS='yes';
+ _DEBUG_PRINT_SHELL='yes';
+ _DEBUG_PRINT_TMPDIR='yes';
+ _DEBUG_PRINT_FILENAMES='yes';
+ continue;
+ ;;
+ --d*-*)
+ # before `-'
+ b="$(echo x"$i" | sed 's/^x--\([^-]*\)-.*$/\1/')";
+ # after `-'
+ a="$(echo x"$i" | sed 's/^x--[^-]*-\(.*\)$/\1/')";
+ ;;
+ *)
+ continue;
+ ;;
+ esac;
+ case "$n" in
+ *\ --$b*-$a*)
+ continue;
+ ;;
+ esac;
+ case "$d" in
+ *\ --$b*-$a*)
+ case "$a" in
+ f|s) # double --debug-* options
+ continue;
+ ;;
+ esac;
+ # extract whole word of double abbreviation
+ s="$(cat <<EOF | sed -n 's/^.* \(--'"$b"'[^ -]*-'"$a"'[^ ]*\) .*/\1/p'
+$d
+EOF
+)"
+ case "$s" in
+ '') continue; ;;
+ --debug-all)
+ _DEBUG_FUNC_CHECK='yes';
+ _DEBUG_STACKS='yes';
+ _DEBUG_USER_WITH_STACK='yes';
+ _DEBUG_GROG='yes';
+ _DEBUG_LM='yes';
+ _DEBUG_KEEP_FILES='yes';
+ _DEBUG_PRINT_PARAMS='yes';
+ _DEBUG_PRINT_SHELL='yes';
+ _DEBUG_PRINT_TMPDIR='yes';
+ _DEBUG_PRINT_FILENAMES='yes';
+ _DEBUG_PRINT_FILENAMES='yes';
+ ;;
+ --debug-filenames)
+ _DEBUG_PRINT_FILENAMES='yes';
+ ;;
+ --debug-func)
+ _DEBUG_FUNC_CHECK='yes';
+ ;;
+ --debug-not-func)
+ _DEBUG_FUNC_CHECK='no';
+ _DEBUG_STACKS='no';
+ _DEBUG_USER_WITH_STACK='no';
+ ;;
+ --debug-grog)
+ _DEBUG_GROG='yes';
+ ;;
+ --debug-keep)
+ _DEBUG_PRINT_TMPDIR='yes';
+ _DEBUG_KEEP_FILES='yes';
+ ;;
+ --debug-lm)
+ _DEBUG_LM='yes';
+ ;;
+ --debug-params)
+ _DEBUG_PRINT_PARAMS='yes';
+ ;;
+ --debug-shell)
+ _DEBUG_PRINT_SHELL='yes';
+ ;;
+ --debug-stacks)
+ _DEBUG_STACKS='yes';
+ ;;
+ --debug-tmpdir)
+ _DEBUG_PRINT_TMPDIR='yes';
+ ;;
+ --debug-user)
+ _DEBUG_USER_WITH_STACK='yes';
+ ;;
+ esac;
+ ;;
+ esac;
+ done
+ ;;
+esac;
+
+if test _"${_DEBUG_STACKS}"_ = _yes_ || \
+ test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_
+then
+ _DEBUG_FUNC_CHECK='yes';
+fi
+
+if test _"${_DEBUG_PRINT_PARAMS}"_ = _yes_
+then
+ echo "parameters: $@" >&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
+########################################################################
+
+landmark "1: 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 a single character.
+# [a-z] local loop variables, e.g. $i
+
+# In functions, other writings are used for variables. As some shells
+# do not support the `local' command a unique prefix in lower case is
+# constructed for each function, most are the abbreviation of the
+# function name. All variable names start with this prefix.
+# ${prefix}_[a-z_]* variable name in a function, e.g. $msm_modes
+
+
+########################################################################
+# read-only variables (global to this file)
+########################################################################
+
+# function return values; `0' means ok; other values are error codes
+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="'pdf' 'html' 'ps' 'x' 'dvi' 'tty'";
+export _DEFAULT_RESOLUTION;
+_DEFAULT_RESOLUTION='75';
+
+export _DEFAULT_TTY_DEVICE;
+_DEFAULT_TTY_DEVICE='latin1';
+
+# _VIEWER_* viewer programs for different modes constructed as lists
+export _VIEWER_DVI_TTY; # viewer program for dvi mode in tty
+export _VIEWER_DVI_X; # viewer program for dvi mode in X
+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_TTY; # viewer program for pdf mode in tty
+export _VIEWER_PDF_X; # viewer program for pdf mode in X
+export _VIEWER_PS_TTY; # viewer program for ps mode in tty
+export _VIEWER_PS_X; # viewer program for ps mode in X
+export _VIEWER_TTY_TTY; # viewer program for X/x mode in tty
+export _VIEWER_TTY_X; # viewer program for X/x mode in X
+export _VIEWER_X_TTY; # viewer program for X/x mode in tty
+export _VIEWER_X_X; # viewer program for X/x mode in X
+_VIEWER_DVI_TTY="";
+_VIEWER_DVI_X="'kdvi' 'xdvi' 'dvilx'";
+_VIEWER_HTML_TTY="'lynx' 'w3m'";
+_VIEWER_HTML_X="'konqueror' 'epiphany' 'mozilla-firefox' 'firefox' 'mozilla' \
+'netscape' 'galeon' 'opera' 'amaya' 'arena' 'mosaic'";
+_VIEWER_PDF_TTY="";
+_VIEWER_PDF_X="'kpdf' 'acroread' 'evince' 'xpdf -z 150' 'gpdf' \
+'kghostview --scale 1.45' 'ggv'";
+_VIEWER_PS_TTY="";
+_VIEWER_PS_X="'kpdf' 'kghostview --scale 1.45' 'evince' 'ggv' 'gv' \
+'ghostview' 'gs_x11,gs'";
+_VIEWER_TTY_TTY="'less -r -R' 'more' 'pager'";
+_VIEWER_TTY_X="'xless'";
+_VIEWER_X_TTY="";
+_VIEWER_X_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="$$";
+
+export _START_DIR; # directory at start time of the script
+_START_DIR="$(pwd)";
+
+
+############ the command line options of the involved programs
+#
+# The naming scheme for the options environment names is
+# $_OPTS_<prog>_<length>[_<argspec>]
+#
+# <prog>: program name GROFFER, GROFF, or CMDLINE (for all
+# command line options)
+# <length>: LONG (long options) or SHORT (single character options)
+# <argspec>: ARG for options with argument, NA for no argument;
+# without _<argspec> 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-filenames' \
+'debug-func' 'debug-not-func' 'debug-grog' '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' 'to-stdout' 'text-device' 'tty' 'tty-device' \
+'version' 'whatis' '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' 'k' 'l' 'N' 'p' \
+'R' 's' 'S' 't' 'U' 'z'";
+_OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'K' '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' 'where'";
+
+_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 _APROPOS_PROG; # Program to run apropos.
+export _APROPOS_SECTIONS; # Sections for different --apropos-*.
+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 _FILE_NR; # number for temporary `,file,*'
+export _FILEARGS; # Stores filespec parameters.
+export _FILESPEC_ARG; # Stores the actual filespec parameter.
+export _FILESPEC_IS_MAN; # filespec is for searching a man page
+export _FUNC_STACK; # Store debugging information.
+export _MACRO_PACKAGES; # groff's macro packages.
+export _MACRO_PKG; # Macro package for each found file.
+export _NO_FILESPECS; # Yes, if there are no filespec arguments.
+export _OUTPUT_FILE_NAME; # output generated, see main_set_res..()
+export _REG_TITLE_LIST; # Processed file names.
+export _SOELIM_R; # option -r for soelim
+export _SPECIAL_FILESPEC; # Filespec ran for apropos or whatis.
+export _SPECIAL_SETUP; # Test on setup for apropos or whatis.
+export _VIEWER_BACKGROUND; # viewer shall be run in the background or not
+# _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_PATH; # search path for man pages as a list
+export _MAN_SEC; # sections for man pages; sep. `:'
+export _MAN_SEC_CHARS; # sections for man pages as [] construct
+export _MAN_SEC_LIST; # sections for man pages as a list
+export _MAN_SYS; # system names for man pages as a list
+# _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
+# variables for mode pdf
+export _PDF_DID_NOT_WORK;
+export _PDF_HAS_GS;
+export _PDF_HAS_PS2PDF;
+# _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_EXTENSION; # set extension for man page search
+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_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_STDOUT; # print mode file to standard output
+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_HTML; # viewer program for html mode
+export _OPT_VIEWER_PDF; # viewer program for pdf mode
+export _OPT_VIEWER_PS; # viewer program for ps 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
+# _TMP_* temporary directory and files
+export _TMP_DIR; # groffer directory for temporary files
+export _TMP_CAT; # stores concatenation of everything
+export _TMP_MAN; # stores find of man path
+export _TMP_MANSPEC; # filters man pages with filespec
+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
+########################################################################
+
+# For variables that can be reset by option `--default', see reset().
+
+_FILE_NR=0;
+_FILEARGS='';
+_MACRO_PACKAGES="'-man' '-mdoc' '-me' '-mm' '-mom' '-ms'";
+_SPECIAL_FILESPEC='no';
+_SPECIAL_SETUP='no';
+
+# _TMP_* temporary files
+_TMP_DIR='';
+_TMP_CAT='';
+_TMP_MAN='';
+_TMP_CONF='';
+_TMP_STDIN='';
+
+# variables for mode pdf
+_PDF_DID_NOT_WORK='no';
+_PDF_HAS_GS='no';
+_PDF_HAS_PS2PDF='no';
+
+# option -r for soelim
+if : | soelim -r 2>${_NULL_DEV} >${_NULL_DEV}
+then
+ _SOELIM_R='-r';
+else
+ _SOELIM_R='';
+fi;
+
+########################################################################
+# 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='';
+ _APROPOS_PROG='';
+ _APROPOS_SECTIONS='';
+ _DISPLAY_ARGS='';
+ _DISPLAY_MODE='';
+ _DISPLAY_PROG='';
+ _MACRO_PKG='';
+ _NO_FILESPECS='';
+ _REG_TITLE_LIST='';
+
+ # _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_CHARS='';
+ _MAN_SEC_LIST='';
+ _MAN_SYS='';
+
+ # _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_EXTENSION='';
+ _OPT_FG='';
+ _OPT_FN='';
+ _OPT_GEOMETRY='';
+ _OPT_ICONIC='no';
+ _OPT_LANG='';
+ _OPT_MODE='';
+ _OPT_MANPATH='';
+ _OPT_PAGER='';
+ _OPT_RESOLUTION='';
+ _OPT_RV='no';
+ _OPT_SECTIONS='';
+ _OPT_SYSTEMS='';
+ _OPT_STDOUT='no';
+ _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_BACKGROUND='no';
+}
+
+reset;
+
+
+########################################################################
+# Preliminary functions for error handling
+########################################################################
+
+landmark "2: preliminary functions";
+
+# These functions do not have a func-check frame. Basically they could be
+# moved to the functions in alphabetical order.
+
+##############
+# echo1 (<text>*)
+#
+# Output to stdout with final line break.
+#
+# Arguments : arbitrary text including `-'.
+#
+echo1()
+{
+ cat <<EOF
+$@
+EOF
+} # echo1()
+
+
+##############
+# echo2 (<text>*)
+#
+# Output to stderr with final line break.
+#
+# Arguments : arbitrary text including `-'.
+#
+echo2()
+{
+ cat >&2 <<EOF
+$@
+EOF
+} # echo2()
+
+
+
+
+##############
+# clean_up ()
+#
+# Clean up at exit.
+#
+cu_already='no';
+clean_up()
+{
+ cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1;
+ if test _${_DEBUG_KEEP_FILES}_ = _yes_
+ then
+ if test _"$cu_already"_ = _yes_
+ then
+ eval "${return_ok}";
+ fi;
+ cu_already=yes;
+ echo2 "Kept temporary directory ${_TMP_DIR}."
+ else
+ if test _"${_TMP_DIR}"_ != __
+ then
+ if test -e "${_TMP_DIR}"
+ then
+ rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1;
+ fi;
+ fi;
+ fi;
+ eval "${return_ok}";
+} # clean_up()
+
+
+#############
+# diag (text>*)
+#
+# Output a diagnostic message to stderr.
+#
+diag()
+{
+ echo2 '>>>>>'"$*";
+} # diag()
+
+
+#############
+# error (<text>*)
+#
+# 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()
+
+
+#############
+# error_user (<text>*)
+#
+# Print an error message to standard error; exit with an error condition.
+# The error is supposed to be produced 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}";
+} # error_user()
+
+
+
+#############
+# 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;
+} # exit_test()
+
+
+########################################################################
+# Definition of normal Functions in alphabetical order
+########################################################################
+
+landmark "3: functions";
+
+########################################################################
+# apropos_filespec ()
+#
+# Compose temporary file for filspec.
+#
+# Globals: in: $_OPT_APROPOS, $_SPECIAL_SETUP, $_FILESPEC_ARG,
+# $_APROPOS_PROG, $_APROPOS_SECTIONS, $_OPT_SECTIONS
+# out: $_SPECIAL_FILESPEC
+#
+# Variable prefix: af
+#
+apropos_filespec()
+{
+
+ func_check apropos_filespec '=' 0 "$@";
+ if obj _OPT_APROPOS is_yes
+ then
+ if obj _SPECIAL_SETUP is_not_yes
+ then
+ error 'apropos_filespec(): apropos_setup() must be run first.';
+ fi;
+ _SPECIAL_FILESPEC='yes';
+ if obj _NO_FILESPECS is_yes
+ then
+ to_tmp_line '.SH no filespec';
+ eval "${_APROPOS_PROG}" | sed 's/^/\\\&/' >>"${_TMP_CAT}";
+ eval "${return_ok}";
+ fi;
+ eval to_tmp_line \
+ "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
+ exit_test;
+ if obj _APROPOS_SECTIONS is_empty
+ then
+ if obj _OPT_SECTIONS is_empty
+ then
+ s='^.*(..*).*$';
+ else
+ s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed 's/://g')"']';
+ fi;
+ else
+ s='^.*(['"${_APROPOS_SECTIONS}"']';
+ fi;
+### apropos_filespec()
+ af_filespec="$(echo1 "${_FILESPEC_ARG}" | sed '
+s,/,\\/,g
+s/\./\\./g
+')";
+ eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \
+ sed -n '
+/^'"${af_filespec}"': /s/^\(.*\)$/\\\&\1/p
+/'"$s"'/p
+' | \
+ sort |\
+ sed '
+s/^\(.*(..*).*\) *- *\(.*\)$/\.br\n\.TP 15\n\.BR \"\1\"\n\\\&\2/
+' >>"${_TMP_CAT}";
+ eval ${_UNSET} af_filespec;
+ eval "${return_ok}";
+ else
+ eval "${return_bad}";
+ fi;
+} # apropos_filespec()
+
+
+########################################################################
+# apropos_setup ()
+#
+# Setup for the --apropos* options, just 2 global variables are set.
+#
+# Globals: in: $_OPT_APROPOS
+# out: $_SPECIAL_SETUP, $_APROPOS_PROG
+#
+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';
+ _SPECIAL_SETUP='yes';
+ if obj _OPT_TITLE is_empty
+ then
+ _OPT_TITLE='apropos';
+ fi;
+ eval "${return_ok}";
+ else
+ eval "${return_bad}";
+ fi;
+} # apropos_setup()
+
+
+########################################################################
+# base_name (<path>)
+#
+# Get the file name part of <path>, i.e. delete everything up to last
+# `/' from the beginning of <path>. Remove final slashes, too, to get
+# a non-empty output. The output is constructed according the shell
+# program `basename'.
+#
+# 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 's|//*$||')";
+ exit_test;
+ ;;
+ esac;
+ case "${bn_name}" in
+ '')
+ eval ${_UNSET} bn_name;
+ eval "${return_bad}";
+ ;;
+ /)
+ # this is like `basename' does
+ echo1 '/';
+ ;;
+ */*)
+ # delete everything before and including the last slash `/'.
+ echo1 "${bn_name}" | sed 's|^.*//*\([^/]*\)$|\1|';
+ ;;
+ *)
+ obj bn_name echo1;
+ ;;
+ esac;
+ eval ${_UNSET} bn_name;
+ eval "${return_ok}";
+} # base_name()
+
+
+########################################################################
+# cat_z (<file>)
+#
+# Decompress if possible or just print <file> to standard output.
+# gzip, bzip2, and .Z decompression is supported.
+#
+# Arguments: 1, a file name.
+# Output: the content of <file>, possibly decompressed.
+#
+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 is_file "$1"
+ then
+ :;
+ else
+ error 'cat_z(): argument $1 is not a file.';
+ fi;
+ if test -s "$1"
+ then
+ :;
+ else
+ eval "${return_ok}";
+ fi;
+ if obj _HAS_COMPRESSION is_yes
+ then
+ if obj _HAS_BZIP is_yes
+ then
+ # test whether being compressed with bz2
+ if bzip2 -t "$1" 2>${_NULL_DEV}
+ then
+ bzip2 -c -d "$1" 2>${_NULL_DEV};
+ eval "${return_ok}";
+ fi;
+ fi;
+ # if not compressed gzip acts like `cat'
+ gzip -c -d -f "$1" 2>${_NULL_DEV};
+ else
+ cat "$1";
+ fi;
+ eval "${return_ok}";
+} # cat_z()
+
+
+########################################################################
+# clean_up ()
+#
+# Do the final cleaning up before exiting; used by the trap calls.
+#
+# defined above
+
+
+########################################################################
+# diag (<text>*)
+#
+# Print marked message to standard error; useful for debugging.
+#
+# defined above
+
+
+########################################################################
+landmark '4: dir_name()*';
+########################################################################
+
+#######################################################################
+# dir_name (<name>)
+#
+# Get the directory name of <name>. The output is constructed
+# according to the shell program `dirname'.
+#
+# Arguments : 1
+# Output : the directory part of <name>
+#
+# Variable prefix: dn
+#
+dir_name()
+{
+ func_check dir_name = 1 "$@";
+ obj_from_output dn_name dir_name_chop "$1";
+ case "${dn_name}" in
+ ''|.)
+ echo1 '.';
+ ;;
+ /)
+ echo1 '/';
+ ;;
+ */*)
+ echo1 "$(echo1 "${dn_name}" | sed 's#/*[^/][^/]*$##')";
+ ;;
+ *)
+ echo1 "${dn_name}";
+ ;;
+ esac;
+ eval "${return_ok}";
+} # dir_name()
+
+
+#######################################################################
+# dir_name_append (<dir> <name>)
+#
+# Append `name' to `dir' with clean handling of `/'.
+#
+# Arguments : 2
+# Output : the generated new directory name <dir>/<name>
+#
+dir_name_append()
+{
+ func_check dir_name_append = 2 "$@";
+ if is_empty "$1"
+ then
+ echo1 "$2";
+ elif is_empty "$2"
+ then
+ echo1 "$1";
+ else
+ dir_name_chop "$1"/"$2";
+ fi;
+ eval "${return_ok}";
+} # dir_name_append()
+
+
+########################################################################
+# dir_name_chop (<name>)
+#
+# Remove unnecessary slashes from directory name.
+#
+# Argument: 1, a directory name.
+# Output: path without double, or trailing slashes.
+#
+# Variable prefix: dc
+#
+dir_name_chop()
+{
+ func_check dir_name_chop = 1 "$@";
+ # replace all multiple slashes by a single slash `/'.
+ dc_res="$(echo1 "$1" | sed 's|///*|/|g')";
+ exit_test;
+ case "${dc_res}" in
+ ?*/)
+ # remove trailing slash '/';
+ echo1 "${dc_res}" | sed 's|/$||';
+ ;;
+ *)
+ obj dc_res echo1
+ ;;
+ esac;
+ eval ${_UNSET} dc_res;
+ eval "${return_ok}";
+} # dir_name_chop()
+
+
+########################################################################
+# do_nothing ()
+#
+# Dummy function that does nothing.
+#
+do_nothing()
+{
+ eval return "${_OK}";
+} # do_nothing()
+
+
+########################################################################
+# echo1 (<text>*)
+#
+# Print to standard output with final line break.
+#
+# defined above
+
+
+########################################################################
+# echo2 (<text>*)
+#
+# Print to standard error with final line break.
+#
+# defined above
+
+
+
+########################################################################
+# error (<text>*)
+#
+# Print error message and exit with error code.
+#
+# defined above
+
+
+########################################################################
+# exit_test ()
+#
+# Test whether the former command ended with error(). Exit again.
+#
+# defined above
+
+
+if test _"${_DEBUG_FUNC_CHECK}"_ = _yes_
+then
+
+ #############
+ # func_check (<func_name> <rel_op> <nr_args> "$@")
+ #
+ # This is called at the first line of each function. It checks the
+ # number of arguments of function <func_name> and registers the
+ # function call to _FUNC_STACK.
+ #
+ # Arguments: >=3
+ # <func_name>: name of the calling function.
+ # <rel_op>: a relational operator: = != < > <= >=
+ # <nr_args>: number of arguments to be checked against <operator>
+ # "$@": 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;
+### func_check()
+ 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';
+ ;;
+### func_check()
+ *)
+ 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_check()
+
+
+ #############
+ # func_pop ()
+ #
+ # Retrieve the top element from the function stack. This is called
+ # by every return variable in each function.
+ #
+ # 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 's/^[^!]*!//')";
+ exit_test;
+ ;;
+ *)
+ _FUNC_STACK='';
+ ;;
+ esac;
+ if test _"${_DEBUG_STACKS}"_ = _yes_
+ then
+ echo2 '<<< '"${_FUNC_STACK}";
+ fi;
+ } # func_pop()
+
+
+ #############
+ # func_push (<element>)
+ #
+ # Store another element to the function stack. This is called by
+ # func_check() at the beginning of each function.
+ #
+ # The stack elements are separated by `!'; if <element> 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 '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_push()
+
+
+ #############
+ # func_stack_dump ()
+ #
+ # Print the content of the function stack. Ignore the arguments.
+ #
+ func_stack_dump()
+ {
+ diag 'call stack(): '"${_FUNC_STACK}";
+ } # func_stack_dump()
+
+else # $_DEBUG_FUNC_CHECK is not `yes'
+
+ func_check() { return; }
+ func_pop() { return; }
+ func_push() { return; }
+ func_stack_dump() { return; }
+
+fi; # test of $_DEBUG_FUNC_CHECK
+
+
+########################################################################
+# get_first_essential (<arg>*)
+#
+# 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}";
+} # get_first_essential()
+
+
+########################################################################
+landmark '5: is_*()';
+########################################################################
+
+########################################################################
+# is_dir (<name>)
+#
+# Test whether `name' is a readable directory.
+#
+# Arguments : 1
+# Return : `0' if arg1 is a directory, `1' otherwise.
+#
+is_dir()
+{
+ func_check is_dir '=' 1 "$@";
+ if is_not_empty "$1" && test -d "$1" && test -r "$1"
+ then
+ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+} # is_dir()
+
+
+########################################################################
+# is_empty (<string>)
+#
+# 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_empty()
+
+
+########################################################################
+# is_empty_file (<file_name>)
+#
+# Test whether <file_name> is an empty existing file.
+#
+# Arguments : <=1
+# Return :
+# `0' if arg1 is an empty existing file
+# `1' otherwise
+#
+is_empty_file()
+{
+ func_check is_empty_file '=' 1 "$@";
+ if is_file "$1"
+ then
+ if test -s "$1"
+ then
+ eval "${return_no}";
+ else
+ eval "${return_yes}";
+ fi;
+ fi;
+ eval "${return_no}";
+} # is_empty_file()
+
+
+########################################################################
+# is_equal (<string1> <string2>)
+#
+# Test whether <string1> is equal to <string2>.
+#
+# 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_equal()
+
+
+########################################################################
+# is_existing (<name>)
+#
+# 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 is_empty "$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_existing()
+
+
+########################################################################
+# is_file (<name>)
+#
+# 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_file()
+
+
+########################################################################
+# is_greater_than (<integer1> <integer2>)
+#
+# Test whether <integer1> is greater than <integer2>.
+#
+# Arguments : 2
+# Return : `0' if <integer1> is a greater integer than <integer2>,
+# `1' otherwise.
+#
+is_greater_than()
+{
+ func_check is_greater_than '=' 2 "$@";
+ if is_integer "$1" && is_integer "$2" && test "$1" -gt "$2"
+ then
+ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+} # is_greater_than()
+
+
+########################################################################
+# is_integer (<string>)
+#
+# Test whether `string' is an integer.
+#
+# Arguments : 1
+# Return : `0' if argument is an integer, `1' otherwise.
+#
+is_integer()
+{
+ func_check is_integer '=' 1 "$@";
+ if is_equal "$(echo1 "$1" | sed -n '
+s/^[0-9][0-9]*$/ok/p
+s/^[-+][0-9][0-9]*$/ok/p
+')" 'ok'
+ then
+ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+} # is_integer()
+
+
+########################################################################
+# is_not_empty_file (<file_name>)
+#
+# 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_not_empty_file()
+{
+ func_check is_not_empty_file '=' 1 "$@";
+ if is_file "$1" && test -s "$1"
+ then
+ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+} # is_not_empty_file()
+
+
+########################################################################
+# is_not_dir (<name>)
+#
+# 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_dir()
+
+
+########################################################################
+# is_not_empty (<string>)
+#
+# 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_empty()
+
+
+########################################################################
+# is_not_equal (<string1> <string2>)
+#
+# 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_equal()
+
+
+########################################################################
+# is_not_file (<filename>)
+#
+# Test whether <filename> 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_file()
+
+
+########################################################################
+# is_not_prog (<program>)
+#
+# Verify that <program> is not a command in $PATH.
+#
+# Arguments : 1, <program> can have spaces and arguments.
+#
+is_not_prog()
+{
+ func_check is_not_prog '=' 1 "$@";
+ if where_is_prog "$1" >${_NULL_DEV}
+ then
+ eval "${return_no}";
+ fi;
+ eval "${return_yes}";
+} # is_not_prog()
+
+
+########################################################################
+# is_not_writable (<name>)
+#
+# Test whether <name> is 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_writable()
+
+
+########################################################################
+# is_not_X ()
+#
+# Test whether the script is not running in X Window by checking $DISPLAY.
+#
+is_not_X()
+{
+ func_check is_not_X '=' 0 "$@";
+ if obj DISPLAY is_empty
+ then
+ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+} # is_not_X()
+
+
+########################################################################
+# is_not_yes (<string>)
+#
+# 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_not_yes()
+
+
+########################################################################
+# is_prog (<name>)
+#
+# Determine whether <name> is a program in $PATH.
+#
+# Arguments : 1, <program> can have spaces and arguments.
+#
+is_prog()
+{
+ func_check is_prog '=' 1 "$@";
+ if where_is_prog "$1" >${_NULL_DEV}
+ then
+ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+} # is_prog()
+
+
+########################################################################
+# is_writable (<name>)
+#
+# 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 is_empty "$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_writable()
+
+
+########################################################################
+# is_X ()
+#
+# Test whether the script is 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_X()
+
+
+########################################################################
+# is_yes (<string>)
+#
+# 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}";
+} # is_yes()
+
+
+########################################################################
+# landmark ()
+#
+# Print debugging information on standard error if $_DEBUG_LM is `yes'.
+#
+# Globals: $_DEBUG_LM
+#
+# Defined in section `Debugging functions'.
+
+
+########################################################################
+# leave ([<code>])
+#
+# Clean exit without an error or with error <code>.
+#
+leave()
+{
+ clean_up;
+ if test $# = 0
+ then
+ exit "${_OK}";
+ else
+ exit "$1";
+ fi;
+} # leave()
+
+
+########################################################################
+landmark '6: list_*()';
+########################################################################
+#
+# `list' is an object class that represents an array or list. Its
+# data consists of space-separated single-quoted elements. So a list
+# has the form "'first' 'second' '...' 'last'". See list_append() for
+# more details on the list structure. The array elements of `list'
+# can be get by `eval set x "$list"; shift`.
+
+
+########################################################################
+# list_append (<list> <element>...)
+#
+# Add one or more elements to an existing list. <list> may also be
+# empty.
+#
+# Arguments: >=2
+# <list>: a variable name for a list of single-quoted elements
+# <element>: some sequence of characters.
+# Output: none, but $<list> is set to
+# if <list> is empty: "'<element>' '...'"
+# otherwise: "$list '<element>' ..."
+#
+# 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 's/'"${_SQ}"'/&\\&&/g')";
+ exit_test;
+ ;;
+ '')
+ la_element="";
+ ;;
+ *)
+ la_element="${la_s}";
+ ;;
+ esac;
+### list_append()
+ 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_append()
+
+
+########################################################################
+# list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
+#
+# 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
+# <pre_name>: common part of a set of 4 environment variable names:
+# $<pre_name>_SHORT_NA: list of short options without an arg.
+# $<pre_name>_SHORT_ARG: list of short options that have an arg.
+# $<pre_name>_LONG_NA: list of long options without an arg.
+# $<pre_name>_LONG_ARG: list of long options that have an arg.
+# <cmdline_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 f1 -bcarg --lon=larg f2 low larg2
+# PRE_SHORT_NA="'a' 'b'"
+# PRE_SHORT_ARG="'c' 'd'"
+# PRE_LONG_NA="'help' 'version'"
+# PRE_LONG_ARG="'longer' 'lower'"
+# This will result in printing:
+# '-a' '-b' '-c' 'arg' '--longer' 'larg' '--lower' 'larg2' '--' 'f1' 'f2'
+#
+# Use this function in the following way:
+# eval set x "$(list_from_cmdline 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 "$@";
+ # short options, no argument
+ obj_from_output lfc_short_n obj_data "$1"_SHORT_NA;
+ # short options, with argument
+ obj_from_output lfc_short_a obj_data "$1"_SHORT_ARG;
+ # long options, no argument
+ obj_from_output lfc_long_n obj_data "$1"_LONG_NA;
+ # long options, with argument
+ obj_from_output lfc_long_a obj_data "$1"_LONG_ARG;
+ 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;
+### list_from_cmdline()
+ eval ${_UNSET} lfc_long_a;
+ eval ${_UNSET} lfc_long_n;
+ eval ${_UNSET} lfc_result;
+ eval "${return_ok}";
+ fi;
+
+ lfc_fparams='';
+ lfc_result='';
+ while is_greater_than "$#" 0
+ do
+ lfc_arg="$1";
+ shift;
+ case "${lfc_arg}" in
+ --) break; ;;
+ --*=*)
+ # delete leading '--';
+ lfc_with_equal="$(echo1 "${lfc_arg}" | sed 's/^--//')";
+ # extract option by deleting from the first '=' to the end
+ lfc_abbrev="$(echo1 "${lfc_with_equal}" | \
+ sed 's/^\([^=]*\)=.*$/\1/')";
+ obj_from_output lfc_opt \
+ list_single_from_abbrev lfc_long_a "${lfc_abbrev}";
+ 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 's/^[^=]*=//')";
+ exit_test;
+ list_append lfc_result "--${lfc_opt}" "${lfc_optarg}";
+ continue;
+ fi;
+### list_from_cmdline()
+ ;;
+ --*)
+ # delete leading '--';
+ lfc_abbrev="$(echo1 "${lfc_arg}" | sed 's/^--//')";
+ if list_has lfc_long_n "${lfc_abbrev}"
+ then
+ lfc_opt="${lfc_abbrev}";
+ else
+ obj_from_output lfc_opt \
+ list_single_from_abbrev lfc_long_n "${lfc_abbrev}";
+ if obj lfc_opt is_not_empty && is_not_equal "$#" 0
+ then
+ obj_from_output a \
+ list_single_from_abbrev lfc_long_a "${lfc_abbrev}";
+ if obj a is_not_empty
+ then
+ error_user "The abbreviation ${lfc_arg} \
+has multiple options: --${lfc_opt} and --${a}.";
+ fi;
+ fi;
+ fi; # if list_has lfc_long_n "${lfc_abbrev}"
+ if obj lfc_opt is_not_empty
+ then
+ # long option, no argument
+ list_append lfc_result "--${lfc_opt}";
+ continue;
+ fi;
+ obj_from_output lfc_opt \
+ list_single_from_abbrev lfc_long_a "${lfc_abbrev}";
+ if obj lfc_opt is_not_empty
+ then
+### list_from_cmdline()
+ # long option with argument
+ if is_equal "$#" 0
+ then
+ error_user "no argument for option --${lfc_opt}."
+ fi;
+ list_append lfc_result "--${lfc_opt}" "$1";
+ shift;
+ continue;
+ fi; # if obj lfc_opt is_not_empty
+ error_user "${lfc_arg} is not an option.";
+ ;;
+ -?*) # short option (cluster)
+ # delete leading `-';
+ lfc_rest="$(echo1 "${lfc_arg}" | sed '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 's/^\(.\).*$/\1/')";
+ # remove first character from ${lfc_rest};
+ lfc_rest="$(echo1 "${lfc_rest}" | sed '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 is_greater_than "$#" 0
+ then
+### list_from_cmdline()
+ 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; # if obj lfc_rest is_empty
+ else
+ error_user "unknown option -${lfc_optchar}.";
+ fi; # if list_has lfc_short_n "${lfc_optchar}"
+ done; # while obj lfc_rest is_not_empty
+ ;;
+ *)
+ # 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; # case "${lfc_arg}" in
+ done; # while is_greater_than "$#" 0
+ list_append lfc_result '--';
+ if obj lfc_fparams is_not_empty
+ then
+ lfc_result="${lfc_result} ${lfc_fparams}";
+ fi;
+### list_from_cmdline()
+ if is_greater_than "$#" 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_cmdline_with_minus (<pre_name_of_opt_lists> [<cmdline_arg>...])
+#
+# Transform command line arguments into a normalized form with a double
+# abbreviation before and after an internal `-' sign.
+#
+# 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
+# <pre_name>: common part of a set of 4 environment variable names:
+# $<pre_name>_SHORT_NA: list of short options without an arg.
+# $<pre_name>_SHORT_ARG: list of short options that have an arg.
+# $<pre_name>_LONG_NA: list of long options without an arg.
+# $<pre_name>_LONG_ARG: list of long options that have an arg.
+# <cmdline_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 f1 -bcarg --lon=larg --h-n f2 low larg2
+# PRE_SHORT_NA="'a' 'b'"
+# PRE_SHORT_ARG="'c' 'd'"
+# PRE_LONG_NA="'help' 'version' 'hi-non-arg'"
+# PRE_LONG_ARG="'long-arg' 'low-arg'"
+# This will result in printing:
+# '-a' '-b' '-c' 'arg' '--long-arg' 'larg' '--hi-non-arg' \
+# '--low-arg' 'larg2' '--' 'f1' 'f2'
+#
+# Use this function in the following way:
+# eval set x "$(list_from_cmdline_with_minus 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: lfcwm
+#
+list_from_cmdline_with_minus()
+{
+ func_check list_from_cmdline_with_minus '>=' 1 "$@";
+ # short options, no argument
+ obj_from_output lfcwm_short_n obj_data "$1"_SHORT_NA;
+ # short options, with argument
+ obj_from_output lfcwm_short_a obj_data "$1"_SHORT_ARG;
+ # long options, no argument
+ obj_from_output lfcwm_long_n obj_data "$1"_LONG_NA;
+ # long options, with argument
+ obj_from_output lfcwm_long_a obj_data "$1"_LONG_ARG;
+ if obj lfcwm_short_n is_empty
+ then
+ error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
+ fi;
+ if obj lfcwm_short_a is_empty
+ then
+ error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
+ fi;
+ if obj lfcwm_long_n is_empty
+ then
+ error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
+ fi;
+ if obj lfcwm_long_a is_empty
+ then
+ error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
+ fi;
+ shift;
+
+ if is_equal "$#" 0
+ then
+ echo1 "'--'";
+ eval ${_UNSET} lfcwm_short_a;
+ eval ${_UNSET} lfcwm_short_n;
+### list_from_cmdline_with_minus()
+ eval ${_UNSET} lfcwm_long_a;
+ eval ${_UNSET} lfcwm_long_n;
+ eval "${return_ok}";
+ fi;
+ obj_from_output lfcwm_long_both lists_combine lfcwm_long_a lfcwm_long_n;
+ lfcwm_fparams='';
+ lfcwm_result='';
+ while is_greater_than "$#" 0 # command line arguments
+ do
+ lfcwm_arg="$1";
+ shift;
+ lfcwm_optarg='';
+ case "${lfcwm_arg}" in
+ --)
+ break;
+ ;;
+ --*=*)
+ # delete leading '--';
+ lfcwm_with_equal="$(echo1 "${lfcwm_arg}" | sed 's/^--//')";
+ # extract option by deleting from the first '=' to the end
+ lfcwm_abbrev="$(echo1 "${lfcwm_with_equal}" | \
+ sed 's/^\([^=]*\)=.*$/\1/')";
+ # extract option argument by deleting up to the first '='
+ lfcwm_optarg="$(echo1 "${lfcwm_with_equal}" | \
+ sed 's/^[^=]*=\(.*\)$/\1/')";
+### list_from_cmdline_with_minus()
+ if list_has lfcwm_long_a "${lfcwm_abbrev}"
+ then
+ lfcwm_opt="${lfcwm_abbrev}";
+ else
+ obj_from_output lfcwm_opt \
+ _search_abbrev lfcwm_long_a "${lfcwm_abbrev}";
+ fi;
+ list_append lfcwm_result "--${lfcwm_opt}" "${lfcwm_optarg}";
+ continue;
+ ;;
+ --*)
+ # delete leading '--';
+ lfcwm_abbrev="$(echo1 "${lfcwm_arg}" | sed 's/^--//')";
+ if list_has lfcwm_long_both "${lfcwm_abbrev}"
+ then
+ lfcwm_opt="${lfcwm_abbrev}";
+ else
+ obj_from_output lfcwm_opt \
+ _search_abbrev lfcwm_long_both "${lfcwm_abbrev}";
+ fi;
+### list_from_cmdline_with_minus()
+ if list_has lfcwm_long_a "${lfcwm_opt}"
+ then
+ if is_equal "$#" 0
+ then
+ error_user "Option ${lfcwm_opt} needs an argument.";
+ fi;
+ lfcwm_optarg="$1";
+ shift;
+ list_append lfcwm_result "--${lfcwm_opt}" "${lfcwm_optarg}";
+ else
+ list_append lfcwm_result "--${lfcwm_opt}";
+ fi;
+ continue;
+ ;;
+ -?*) # short option (cluster)
+ # delete leading '-';
+ lfcwm_rest="$(echo1 "${lfcwm_arg}" | sed 's/^-//')";
+ while obj lfcwm_rest is_not_empty
+ do
+ # get next short option from cluster (first char of $lfcwm_rest)
+ lfcwm_optchar="$(echo1 "${lfcwm_rest}" | sed 's/^\(.\).*$/\1/')";
+ # remove first character from ${lfcwm_rest};
+ lfcwm_rest="$(echo1 "${lfcwm_rest}" | sed 's/^.//')";
+ if list_has lfcwm_short_n "${lfcwm_optchar}"
+ then
+ list_append lfcwm_result "-${lfcwm_optchar}";
+ continue;
+ elif list_has lfcwm_short_a "${lfcwm_optchar}"
+ then
+ if obj lfcwm_rest is_empty
+ then
+ if is_greater_than "$#" 0
+ then
+### list_from_cmdline_with_minus()
+ list_append lfcwm_result "-${lfcwm_optchar}" "$1";
+ shift;
+ continue;
+ else
+ error_user "no argument for option -${lfcwm_optchar}.";
+ fi;
+ else # rest is the argument
+ list_append lfcwm_result "-${lfcwm_optchar}" "${lfcwm_rest}";
+ lfcwm_rest='';
+ continue;
+ fi; # if obj lfcwm_rest is_empty
+ else
+ error_user "unknown option -${lfcwm_optchar}.";
+ fi; # if list_has lfcwm_short_n "${lfcwm_optchar}"
+ done; # while obj lfcwm_rest is_not_empty
+ ;;
+ *)
+ # Here, $lfcwm_arg is not an option, so a file parameter.
+ list_append lfcwm_fparams "${lfcwm_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 lfcwm_result '--';
+ if obj lfcwm_fparams is_not_empty
+ then
+ lfcwm_result="${lfcwm_result} ${lfcwm_fparams}";
+ fi;
+### list_from_cmdline_with_minus()
+ if is_greater_than "$#" 0
+ then
+ list_append lfcwm_result "$@";
+ fi;
+ obj lfcwm_result echo1;
+ eval ${_UNSET} lfcwm_abbrev;
+ eval ${_UNSET} lfcwm_fparams;
+ eval ${_UNSET} lfcwm_short_a;
+ eval ${_UNSET} lfcwm_short_n;
+ eval ${_UNSET} lfcwm_long_a;
+ eval ${_UNSET} lfcwm_long_both;
+ eval ${_UNSET} lfcwm_long_n;
+ eval ${_UNSET} lfcwm_result;
+ eval ${_UNSET} lfcwm_arg;
+ eval ${_UNSET} lfcwm_opt;
+ eval ${_UNSET} lfcwm_optarg;
+ eval ${_UNSET} lfcwm_optchar;
+ eval ${_UNSET} lfcwm_with_equal;
+ eval ${_UNSET} lfcwm_rest;
+ eval "${return_ok}";
+} # list_from_cmdline_with_minus()
+
+
+# _search_abbrev (<list> <abbrev>)
+#
+# Check whether <list> has an element constructed from the abbreviation
+# <abbrev>. All `-' in <abbrev> are replaced by `-*'. This construction
+# is searched first with `<construction>[^-]*'. If there is more than a
+# single element an error is created. If none is found `<construction>*'
+# is searched. Again an error is created for several results.
+# This function was constructed from the former function
+# list_single_from_abbrev().
+#
+# This is a local function of list_from_cmdline_with_minus().
+#
+# Arguments: 2
+# <list>: a variable name for a list of single-quoted elements
+# <abbrev>: some sequence of characters.
+#
+# Output: the found element (always not empty), error when none found.
+#
+# Variable prefix: _sa
+#
+_search_abbrev()
+{
+ func_check _search_abbrev '=' 2 "$@";
+ eval _sa_list='"${'$1'}"';
+ if obj _sa_list is_empty
+ then
+ error "_search_abbrev(): list is empty.";
+ fi;
+
+ _sa_abbrev="$2";
+ if obj _sa_abbrev is_empty
+ then
+ error "_search_abbrev(): abbreviation argument is empty.";
+ fi;
+
+ _sa_case="$(echo1 "${_sa_abbrev}" | sed 's/-/\*-/g')";
+ _sa_opt='';
+ case " ${_sa_list}" in
+ *\ \'${_sa_case}*) # list has the abbreviation
+ _sa_m1='';
+ _sa_m2='';
+ _sa_nm='';
+ eval set x "${_sa_list}";
+ shift;
+ for i # over the option list
+ do
+ _sa_i="$i";
+### _search_abbrev() of list_from_cmdline_with_minus()
+ case "${_sa_i}" in
+ ${_sa_case}*-*)
+ if obj _sa_m1 is_empty
+ then
+ _sa_m1="${_sa_i}";
+ continue;
+ fi;
+ _sa_m2="${_sa_i}";
+ continue;
+ ;;
+ ${_sa_case}*)
+ if obj _sa_nm is_empty
+ then
+ _sa_nm="${_sa_i}";
+ continue;
+ fi;
+ error_user "The abbreviation --${_sa_abbrev} has multiple options "\
+"--${_sa_nm} and --${_sa_i}.";
+ ;;
+ esac;
+ done;
+ if obj _sa_nm is_empty
+ then
+ if obj _sa_m2 is_not_empty
+ then
+ error_user "The abbreviation --${_sa_abbrev} has multiple options "\
+"--${_sa_m1} and --${_sa_m2}.";
+ fi;
+### _search_abbrev() of list_from_cmdline_with_minus()
+ if obj _sa_m1 is_not_empty
+ then
+ _sa_opt="${_sa_m1}";
+ fi;
+ else
+ _sa_opt="${_sa_nm}";
+ fi;
+ ;;
+ esac;
+ if obj _sa_opt is_empty
+ then
+ error_user "--${_sa_abbrev} is not an option.";
+ fi;
+ obj _sa_opt echo1;
+ eval "${_UNSET}" _sa_abbrev;
+ eval "${_UNSET}" _sa_case;
+ eval "${_UNSET}" _sa_i;
+ eval "${_UNSET}" _sa_list;
+ eval "${_UNSET}" _sa_m1;
+ eval "${_UNSET}" _sa_m2;
+ eval "${_UNSET}" _sa_nm;
+ eval "${_UNSET}" _sa_opt;
+ eval "${return_ok}";
+} # _search_abbrev() of list_from_cmdline_with_minus()
+
+
+########################################################################
+# list_from_file (<list_name> <file_name>)
+#
+# Extrect the lines from <file_name> and store them as elements to list
+# <list_name>.
+#
+# Arguments: 2
+# <list_name>: a variable name for output, a list of single-quoted elts
+# <file_name>: the name of an existing file
+#
+# Variable prefix: lff
+#
+list_from_file()
+{
+ func_check list_from_file '=' 2 "$@";
+ if is_not_file "$2"
+ then
+ eval "${return_bad}";
+ fi;
+ lff_n="$(wc -l "$2" | eval sed "'s/^[ ${_TAB}]*\([0-9]\+\).*$/\1/'")";
+ eval "$1"="''";
+ if obj lff_n is_equal 0
+ then
+ eval "${return_good}";
+ fi;
+ lff_i=0;
+ while obj lff_i is_not_equal "${lff_n}"
+ do
+ lff_i="$(expr "${lff_i}" + 1)";
+ list_append "$1" "$(eval sed -n "'${lff_i}p
+${lff_i}q'" "'$2'")";
+ done;
+ eval "${_UNSET}" lff_i;
+ eval "${_UNSET}" lff_n;
+ eval "${return_good}";
+} # list_from_file()
+
+
+########################################################################
+# list_from_split (<string> <separator_char>)
+#
+# Split <string> by <separator_char> into a list, omitting the separator.
+#
+# Arguments: 2: a <string> that is to be split into parts divided by
+# character <separator_char>
+# Output: the resulting list string
+#
+# Variable prefix: lfs
+#
+list_from_split()
+{
+ func_check list_from_split = 2 "$@";
+ if is_empty "$1"
+ then
+ eval "${return_ok}";
+ fi;
+ case "$2" in
+ ?)
+ lfs_splitter="$2";
+ ;;
+ '\:')
+ lfs_splitter=':';
+ ;;
+ *)
+ error "list_from_split(): split argument $2 must be a single character.";
+ ;;
+ esac;
+ lfs_list='';
+ lfs_rest="$1";
+ while :
+ do
+ case "${lfs_rest}" in
+ *${lfs_splitter}*)
+ case "${lfs_splitter}" in
+ /)
+ lfs_elt="$(echo1 ${lfs_rest} | sed \
+ 's|^\([^'"${lfs_splitter}"']*\)'"${lfs_splitter}"'.*|\1|')";
+ lfs_rest="$(echo1 ${lfs_rest} | sed \
+ 's|^[^'"${lfs_splitter}"']*'"${lfs_splitter}"'\(.*\)$|\1|')";
+ ;;
+ *)
+### list_from_split()
+ lfs_elt="$(echo1 ${lfs_rest} | sed \
+ 's/^\([^'"${lfs_splitter}"']*\)'"${lfs_splitter}"'.*/\1/')";
+ lfs_rest="$(echo1 ${lfs_rest} | sed \
+ 's/^[^'"${lfs_splitter}"']*'"${lfs_splitter}"'\(.*\)$/\1/')";
+ ;;
+ esac;
+ list_append lfs_list "${lfs_elt}"
+ continue;
+ ;;
+ *)
+ list_append lfs_list "${lfs_rest}"
+ break
+ ;;
+ esac;
+ done
+ echo1 "${lfs_list}";
+
+ eval ${_UNSET} lfs_elt;
+ eval ${_UNSET} lfs_list;
+ eval ${_UNSET} lfs_rest;
+ eval ${_UNSET} lfs_splitter;
+ eval "${return_ok}";
+} # list_from_split()
+
+
+########################################################################
+# list_has (<list-name> <element>)
+#
+# Test whether the list <list-name> has the element <element>.
+#
+# Arguments: 2
+# <list_name>: a variable name for a list of single-quoted elements
+# <element>: 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()
+
+
+########################################################################
+# list_has_abbrev (<list_var> <abbrev>)
+#
+# Test whether the list of <list_var> has an element starting with
+# <abbrev>.
+#
+# Arguments: 2
+# <list_var>: a variable name for a list of single-quoted elements
+# <abbrev>: 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 's/'"${_SQ}"'$//')";
+ ;;
+ *)
+ 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_abbrev()
+
+
+########################################################################
+# list_has_not (<list> <element>)
+#
+# Test whether <list> has no <element>.
+#
+# Arguments: 2
+# <list>: a space-separated list of single-quoted elements.
+# <element>: 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_has_not()
+
+
+########################################################################
+# list_single_from_abbrev (<list-var> <abbrev>)
+#
+# Check whether the list has an element starting with <abbrev>. If
+# there are more than a single element an error is raised.
+#
+# Arguments: 2
+# <list-var>: a variable name for a list of single-quoted elements
+# <abbrev>: 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;
+### list_single_from_abbrev()
+ 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;
+} # list_single_from_abbrev()
+
+
+########################################################################
+# list_uniq (<list>)
+#
+# Generate a list with only unique elements.
+#
+# Output: the corrected list
+#
+# Variable prefix: lu
+#
+list_uniq()
+{
+ func_check list_uniq '=' 1 "$@";
+ if is_empty "$1"
+ then
+ eval "${return_ok}";
+ fi;
+ eval a='"${'"$1"'}"';
+ if obj a is_empty
+ then
+ eval "${return_ok}";
+ fi;
+ eval set x "$a";
+ shift;
+ lu_list='';
+ for i
+ do
+ lu_i="$i";
+ if list_has lu_list "${lu_i}"
+ then
+ continue;
+ else
+ list_append lu_list ${lu_i};
+ fi;
+ done;
+ obj lu_list echo1;
+ eval "${_UNSET}" lu_i;
+ eval "${_UNSET}" lu_list;
+ eval "${return_ok}";
+} # list_uniq()
+
+
+########################################################################
+# lists_combine (<list1> <list2> ...)
+#
+# Combine several lists to a single list. All arguments are list names.
+#
+# Output: the combined list
+#
+# Variable prefix: lc
+#
+lists_combine()
+{
+ func_check lists_combine '>=' 2 "$@";
+ lc_list='';
+ for i
+ do
+ eval lc_arg='"${'"$i"'}"';
+ case "${lc_arg}" in
+ '') :; ;;
+ "'"*"'")
+ if obj lc_list is_empty
+ then
+ lc_list="${lc_arg}";
+ else
+ lc_list="${lc_list} ${lc_arg}";
+ fi;
+ ;;
+ *)
+ error 'lists_combine(): $'"$i"' is not a list.';
+ ;;
+ esac;
+ done;
+ obj lc_list echo1;
+ eval "${_UNSET}" lc_arg;
+ eval "${_UNSET}" lc_list;
+ eval "${return_ok}";
+} # lists_combine()
+
+
+########################################################################
+landmark '7: man_*()';
+########################################################################
+
+########################################################################
+# Information on the search of man pages in groffer
+
+# The search of man pages is based on a set of directories. That
+# starts with the so-called man path. This is determined in function
+# man_setup() either by the command-line option --manpath, by $MANOPT,
+# or by $MANPATH. There is also a program `manpath'. If all of this
+# does not work a man path is created from $PATH with function
+# manpath_set_from_path(). We now have a set of existing directories
+# for the search of man pages; usually they end with `/man'.
+
+# The directory set of the man path can be changed in 2 ways. If
+# operating system names are given in $SYSTEM or by --systems on the
+# command-line all man path directory will be appended by these names.
+# The appended system names replace the original man path; but if no
+# system name is set, the original man path is kept. In `groffer',
+# this is done by the function manpath_add_lang_sys() in man_setup().
+
+# The next addition for directories is the language. It is specified
+# by --locale or by one of the environment variables $LC_ALL,
+# $LC_MESSAGES, and $LANG. The language name of `C' or `POSIX' means
+# the return to the default language (usually English); this deletes
+# former language specifications. The language name and its
+# abbreviation with 2 characters is appended to the man page
+# directories. But these new arising directories are added to the man
+# page, they do not replace it such as the system names did. This is
+# done by function manpath_add_lang_sys() in man_setup() as well.
+
+# Now we have the basic set of directories for the search of man pages
+# for given filespec arguments. The real directories with the man
+# page source files are gotten by appending `man<section>' to each
+# directory, where section is a single character of the form
+# `[1-9on]'.
+
+# There you find files named according to the form
+# <name>.<section>[<extension>][<compression>], where `[]' means
+# optional this time. <name> is the name of the man page; <section>
+# is the single character from the last paragraphe; the optional
+# <extension> consists of some letters denoting special aspects for
+# the section; and the optional <compression> is something like `.gz',
+# `.Z', or `.bz2', meaning that the file is compressed.
+
+# If name, section. and extension are specified on the command-line
+# the file of the form <name>.<section><extension> with or without
+# <compression> are handled. The first one found according to the
+# directory set for the section is shown.
+
+# If just name and section are specified on the command-line then
+# first <name>.<section> with or without <compression> are searched.
+# If no matching file was found, <name>.<section><extension> with or
+# without <compression> are searched for all possible extensions.
+
+# If only name is specified on the command-line then the section
+# directories are searched by and by, starting with section `1', until
+# a file is matched.
+
+# The function man_is_man() determines all suitable man files for a
+# command-line argument, while man_get() searches the single matching
+# file for display.
+
+
+########################################################################
+# man_get (<man-name> [<section> [<extension>]])
+#
+# Write a man page to the temporary file.
+#
+# Globals in: $_TMP_MANSPEC, $_MAN_SEC_CHARS, $_MAN_EXT, $_MAN_ALL
+#
+# Arguments: 1, 2, or 3
+#
+# Variable prefix: mg
+#
+man_get()
+{
+ func_check man_get '>=' 1 "$@";
+ if obj _TMP_MANSPEC is_empty
+ then
+ error 'man_get(): man_is_man() must be run first on '"$*".;
+ fi;
+ mg_name="$1";
+ mg_sec="$2";
+ if is_empty "$2"
+ then
+ mg_sec="${_MAN_SEC_CHARS}"; # take care it is not a single section
+ fi;
+ mg_ext="$3";
+ if is_empty "$3"
+ then
+ mg_ext="${_MAN_EXT}";
+ fi;
+ if obj _TMP_MANSPEC is_not_equal "${_TMP_DIR}/,man:$1:${mg_sec}${mg_ext}"
+ then
+ error 'man_get(): $_TMP_MANSPEC does not suit to the arguments '"$*".;
+ fi;
+### man_get()
+
+ if obj _MAN_ALL is_yes
+ then
+ list_from_file mg_list "${_TMP_MANSPEC}";
+ eval set x ${mg_list};
+ shift;
+ mg_ok='no';
+ mg_list='';
+ for f
+ do
+ mg_f="$f";
+ if list_has mg_list "${mg_f}"
+ then
+ continue;
+ else
+ list_append mg_list "${mg_f}";
+ fi;
+### man_get()
+ if obj mg_f is_file
+ then
+ to_tmp "${mg_f}" && mg_ok='yes';
+ fi;
+ done;
+ if obj mg_ok is_yes
+ then
+ register_title man:"${mg_name}";
+ fi;
+ eval ${_UNSET} mg_ext;
+ eval ${_UNSET} mg_f;
+ eval ${_UNSET} mg_list;
+ eval ${_UNSET} mg_name;
+ eval ${_UNSET} mg_sec;
+ eval "${return_ok}";
+ else # $_MAN_ALL is not 'yes'
+ if is_empty "$2"
+ then # no section from command line
+ if obj _MAN_SEC_LIST is_empty
+ then
+ m="${_MAN_AUTO_SEC_LIST}"; # list of all sections
+ else
+ m="${_MAN_SEC_LIST}"; # from --sections
+ fi;
+### man_get()
+ for s in $(eval set x $m; shift; echo1 "$@")
+ do
+ mg_s="$s";
+ list_from_file mg_list "${_TMP_MANSPEC}";
+ eval set x ${mg_list};
+ shift;
+ if obj mg_ext is_empty
+ then
+ for f
+ do
+ mg_f="$f";
+ case "${mg_f}" in
+*/man"${mg_s}"/"${mg_name}"."${mg_s}"|*/man"${mg_s}"/"${mg_name}"."${mg_s}".*)
+ if obj mg_f is_file
+ then
+ to_tmp "${mg_f}" && register_title "${mg_name}(${mg_s})";
+ eval ${_UNSET} mg_ext;
+ eval ${_UNSET} mg_f;
+ eval ${_UNSET} mg_list;
+ eval ${_UNSET} mg_name;
+ eval ${_UNSET} mg_s;
+ eval ${_UNSET} mg_sec;
+ eval "${return_ok}";
+ fi;
+ ;;
+ esac; # "$mg_f"
+ done; # for f
+ fi; # mg_ext is_empty
+### man_get()
+ for f
+ do
+ mg_f="$f";
+ case "${mg_f}" in
+ */man"${mg_s}"/"${mg_name}"."${mg_s}""${mg_ext}"*)
+ if obj mg_f is_file
+ then
+ to_tmp "${mg_f}" && register_title "${mg_name}(${mg_s})";
+ eval ${_UNSET} mg_ext;
+ eval ${_UNSET} mg_f;
+ eval ${_UNSET} mg_list;
+ eval ${_UNSET} mg_name;
+ eval ${_UNSET} mg_s;
+ eval ${_UNSET} mg_sec;
+ eval "${return_ok}";
+ fi;
+ ;;
+ esac; # "$mg_f"
+ done; # for f
+ done; # for s
+ else # $mg_sec is not empty, do with section
+ list_from_file mg_list "${_TMP_MANSPEC}";
+ eval set x ${mg_list};
+ shift;
+ if obj mg_ext is_empty
+ then
+ for f
+ do
+ mg_f="$f";
+### man_get()
+ case "${mg_f}" in
+*/man"${mg_sec}"/"${mg_name}"."${mg_sec}"|\
+*/man"${mg_sec}"/"${mg_name}"."${mg_sec}".*)
+ if obj mg_f is_file
+ then
+ obj mg_f to_tmp && \
+ register_title "${mg_name}(${mg_sec})";
+ eval ${_UNSET} mg_ext;
+ eval ${_UNSET} mg_f;
+ eval ${_UNSET} mg_list;
+ eval ${_UNSET} mg_name;
+ eval ${_UNSET} mg_s;
+ eval ${_UNSET} mg_sec;
+ eval "${return_ok}";
+ fi;
+ ;;
+ esac;
+ done; # for f
+ for f
+ do
+ mg_f="$f";
+### man_get()
+ case "${mg_f}" in
+*/man"${mg_sec}"/"${mg_name}"."${mg_sec}"*)
+ if obj mg_f is_file
+ then
+ obj mg_f to_tmp && \
+ register_title "${mg_name}(${mg_sec})";
+ eval ${_UNSET} mg_ext;
+ eval ${_UNSET} mg_f;
+ eval ${_UNSET} mg_list;
+ eval ${_UNSET} mg_name;
+ eval ${_UNSET} mg_s;
+ eval ${_UNSET} mg_sec;
+ eval "${return_ok}";
+ fi;
+ ;;
+ esac;
+ done; # for f
+ else # mg_ext is not empty
+ for f
+ do
+ mg_f="$f";
+### man_get()
+ case "${mg_f}" in
+*/man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}"|\
+*/man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}".*)
+ if obj mg_f is_file
+ then
+ obj mg_f to_tmp && \
+ register_title "${mg_name}(${mg_sec}${mg_ext})";
+ eval ${_UNSET} mg_ext;
+ eval ${_UNSET} mg_f;
+ eval ${_UNSET} mg_list;
+ eval ${_UNSET} mg_name;
+ eval ${_UNSET} mg_s;
+ eval ${_UNSET} mg_sec;
+ eval "${return_ok}";
+ fi;
+ ;;
+ esac;
+ done; # for f
+ for f
+ do
+ mg_f="$f";
+### man_get()
+ case "${mg_f}" in
+ */man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}"*)
+ if obj mg_f is_file
+ then
+ obj mg_f to_tmp && \
+ register_title "${mg_name}(${mg_sec}${mg_ext})";
+ eval ${_UNSET} mg_ext;
+ eval ${_UNSET} mg_f;
+ eval ${_UNSET} mg_list;
+ eval ${_UNSET} mg_name;
+ eval ${_UNSET} mg_s;
+ eval ${_UNSET} mg_sec;
+ eval "${return_ok}";
+ fi;
+ ;;
+ esac;
+ done; # for f
+ fi;
+ fi; # $mg_sec
+ fi; # $_MAN_ALL
+
+ eval ${_UNSET} mg_ext;
+ eval ${_UNSET} mg_f;
+ eval ${_UNSET} mg_list;
+ eval ${_UNSET} mg_name;
+ eval ${_UNSET} mg_sec;
+ eval ${_UNSET} mg_s;
+ eval "${return_ok}";
+} # man_get()
+
+
+########################################################################
+# man_is_man (<man-name> [<section> [<extension>]])
+#
+# Test whether <man-name> exists as man page.
+#
+# Globals: in: $_TMP_MAN, $_MAN_SEC_CHARS, $_TMP_DIR, $_MAN_EXT,
+# $_MAN_AUTO_SEC_CHARS
+# out: $_TMP_MANSPEC
+#
+# Arguments: 1, 2, or 3
+#
+# Variable prefix: mim
+#
+man_is_man()
+{
+ func_check man_is_man '>=' 1 "$@";
+ if is_empty "$1"
+ then
+ _TMP_MANSPEC='';
+ eval "${return_no}";
+ fi;
+ if obj _TMP_DIR is_empty
+ then
+ error 'man_is_man(): main_init() must be run first.';
+ fi;
+ if obj _MAN_IS_SETUP is_not_yes
+ then
+ error 'man_is_man(): man_setup() must be run first.';
+ fi;
+ mim_sec="$2";
+ if is_empty "$2"
+ then
+ mim_sec="${_MAN_SEC_CHARS}";
+ fi;
+ if is_empty "$3"
+ then
+ mim_ext="${_MAN_EXT}";
+ else
+ mim_ext="$3";
+ fi;
+ _TMP_MANSPEC="${_TMP_DIR}/,man:$1:${mim_sec}${mim_ext}";
+### man_is_man()
+ if obj _TMP_MANSPEC is_not_file
+ then
+ if obj mim_sec is_empty
+ then
+ m="${_MAN_AUTO_SEC_CHARS}";
+ eval grep "'/man$m/$1\.$m${mim_ext}'" \
+ "${_TMP_MAN}" > "${_TMP_MANSPEC}";
+ else
+ eval grep "'/man${mim_sec}/$1\.${mim_sec}${mim_ext}'" \
+ "${_TMP_MAN}" > "${_TMP_MANSPEC}";
+ fi;
+ fi;
+ eval ${_UNSET} mim_ext;
+ eval ${_UNSET} mim_sec;
+ if obj _TMP_MANSPEC is_empty_file
+ then
+ rm_file_with_debug "${_TMP_MANSPEC}";
+ eval "${return_no}";
+ else
+ eval "${return_yes}";
+ fi;
+} # man_is_man()
+
+
+########################################################################
+# man_setup ()
+#
+# Setup the variables $_MAN_* needed for man page searching.
+#
+# Globals:
+# in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
+# $MANPATH, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
+# out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
+# $_MAN_SEC, $_MAN_ALL, $_TMP_MAN
+# 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, $MANSEC, $PAGER, $SYSTEM; overridden by
+# $MANOPT; overridden by
+# the groffer command line options.
+#
+# $MANROFFSEQ is ignored because grog determines the preprocessors.
+#
+# Variable prefix: ms
+#
+man_setup()
+{
+ func_check 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
+ obj_from_output ms_path \
+ get_first_essential "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}";
+ if obj ms_path is_empty && is_prog 'manpath'
+ then
+ obj_from_output ms_path manpath 2>${_NULL_DEV}; # not always available
+ fi;
+ if obj ms_path is_empty
+ then
+ manpath_set_from_path;
+ else
+ obj_from_output _MAN_PATH path_list "${ms_path}";
+ fi;
+ if obj _MAN_PATH is_empty
+ then
+ _MAN_ENABLE="no";
+ echo2 "man_setup(): man path is empty";
+ eval ${_UNSET} ms_path;
+ eval "${return_ok}";
+ fi;
+ obj_from_output _MAN_PATH list_uniq _MAN_PATH;
+### man_setup()
+
+ if obj _MAN_ALL is_not_yes
+ then
+ if obj _OPT_ALL is_yes || obj _MANOPT_ALL is_yes
+ then
+ _MAN_ALL='yes';
+ else
+ _MAN_ALL='no';
+ fi;
+ fi;
+
+ ms_sys="$(get_first_essential \
+ "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
+ if obj ms_sys is_not_empty
+ then
+ obj_from_output _MAN_SYS list_from_split "${ms_sys}" ',';
+ fi;
+
+ obj_from_output ms_lang get_first_essential \
+ "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}";
+ case "${ms_lang}" in
+ C|POSIX)
+ _MAN_LANG="";
+ _MAN_LANG2="";
+ ;;
+ ?)
+ _MAN_LANG="${ms_lang}";
+ _MAN_LANG2="";
+ ;;
+ ??)
+ _MAN_LANG="${ms_lang}";
+ _MAN_LANG2="${ms_lang}";
+ ;;
+### man_setup()
+ *)
+ _MAN_LANG="${ms_lang}";
+ # get first two characters of $ms_lang
+ _MAN_LANG2="$(echo1 "${ms_lang}" | sed 's/^\(..\).*$/\1/')";
+ exit_test;
+ ;;
+ esac;
+ # from now on, use only $_MAN_LANG*, forget about $_OPT_LANG, $LC_*.
+
+ manpath_add_lang_sys;
+ obj_from_output _MAN_PATH list_uniq _MAN_PATH;
+
+ obj_from_output _MAN_SEC get_first_essential \
+ "${_OPT_SECTIONS}" "${_MANOPT_SEC}" "${MANSEC}";
+ _MAN_SEC_LIST="";
+ _MAN_SEC_CHARS="";
+ case "${_MAN_SEC}" in
+ *:*)
+ eval set x "$(list_from_split "${_MAN_SEC}" :)";
+ shift;
+ for s
+ do
+ if list_has _MAN_AUTO_SEC_LIST "$s"
+ then
+ list_append _MAN_SEC_LIST "$s";
+ _MAN_SEC_CHARS="${_MAN_SEC_CHARS}$s";
+ fi;
+ done
+ if obj _MAN_SEC_CHARS is_not_empty
+ then
+ _MAN_SEC_CHARS="[${_MAN_SEC_CHARS}]";
+ fi;
+ ;;
+ *)
+ if list_has _MAN_AUTO_SEC_LIST "${_MAN_SEC}"
+ then
+ list_append _MAN_SEC_LIST "${_MAN_SEC}";
+ _MAN_SEC_CHARS="[${_MAN_SEC}]";
+ fi;
+ ;;
+ esac;
+
+### man_setup()
+ obj_from_output _MAN_EXT get_first_essential \
+ "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}" "${EXTENSION}";
+
+ _TMP_MAN="$(tmp_create man)";
+
+ eval set x "${_MAN_PATH}";
+ shift;
+ if is_not_equal "$#" 0
+ then
+ for i
+ do
+ for j in "$i"/man*
+ do
+ if obj j is_dir
+ then
+ find "$j" >>"${_TMP_MAN}";
+ fi;
+ done
+ done;
+ fi;
+
+ eval ${_UNSET} ms_lang;
+ eval ${_UNSET} ms_list;
+ eval ${_UNSET} ms_path;
+ eval ${_UNSET} ms_sys;
+ 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: a list of names of operating systems.
+# $_MAN_LANG and $_MAN_LANG2: each a single name
+# in/out: $_MAN_PATH: list of directories which shall have the `man?'
+# subdirectories.
+#
+# 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;
+ if obj _MAN_SYS is_empty
+ then
+ mals_mp="${_MAN_PATH}";
+ else
+ mals_mp='';
+ eval set x "${_MAN_SYS}";
+ shift;
+ for s
+ do
+ _manpath_add_sys "$s";
+ done;
+ fi;
+
+ if obj mals_mp is_not_empty
+ then
+ mals_lang_path='';
+ if is_equal "$_MAN_LANG" "$_MAN_LANG2"
+ then
+ mals_man_lang2='';
+ else
+ mals_man_lang2="${_MAN_LANG2}";
+ fi;
+ for i in "${_MAN_LANG}" "${mals_man_lang2}"
+ do
+ if obj i is_empty
+ then
+ continue;
+ fi;
+### manpath_add_lang_sys()
+ mals_lang="$i";
+ eval set x "${mals_mp}";
+ shift;
+ for p
+ do
+ obj_from_output mals_dir dir_name_append "${p}" "${mals_lang}";
+ if obj mals_dir is_dir
+ then
+ list_append mals_lang_path "${mals_dir}";
+ fi;
+ done;
+ done;
+ obj_from_output mals_mp lists_combine mals_lang_path mals_mp;
+ fi;
+
+ _MAN_PATH="${mals_mp}";
+ eval ${_UNSET} mals_dir;
+ eval ${_UNSET} mals_lang;
+ eval ${_UNSET} mals_lang_path;
+ eval ${_UNSET} mals_man_lang2;
+ eval ${_UNSET} mals_mp;
+ eval "${return_ok}";
+} # manpath_add_lang_sys()
+
+
+# _manpath_add_sys (<system>)
+#
+# Append the existing subdirectories <system> of man path directories to
+# the list $mals_mp.
+#
+# Local function to manpath_add_lang_sys().
+#
+# Argument: 1, a operating system name (for appending to a man path
+# directory)
+#
+# Globals in: $_MAN_PATH
+# Globals in/out: $mals_mp
+#
+# Variable prefix: _mas
+#
+_manpath_add_sys()
+{
+ func_check _manpath_add_sys '=' 1 "$@";
+ case "$1" in
+ '')
+ :;
+ ;;
+ man)
+ obj_from_output mals_mp lists_combine mals_mp _MAN_PATH;
+ ;;
+ *)
+ _mas_sys="$1";
+ eval set x "${_MAN_PATH}";
+ shift;
+ for p
+ do
+ obj_from_output _mas_dir dir_name_append "${p}" "${_mas_sys}";
+ if obj _mas_dir is_dir
+ then
+ list_append mals_mp "${_mas_dir}";
+ fi;
+ done;
+ ;;
+ esac;
+ eval ${_UNSET} _mas_dir;
+ eval ${_UNSET} _mas_sys;
+ eval "${return_ok}";
+} # _manpath_add_sys() of 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
+ # delete the final `/bin' part
+ p="$(echo1 "${PATH}" | sed 's|//*bin/*:|:|g')";
+ obj_from_output msfp_list path_list "$p";
+ # append some default directories
+ for b in /usr/local /usr/local /usr /usr \
+ /usr/X11R6 /usr/openwin \
+ /opt /opt/gnome /opt/kde
+ do
+ msfp_base="$b";
+ if list_has_not msfp_list "${msfp_base}" && obj msfp_base is_dir
+ then
+ list_append msfp_list "${msfp_base}";
+ fi;
+ done;
+ eval set x "${msfp_list}";
+ shift;
+ for d
+ do
+ # including empty for former `/bin'.
+ msfp_base="$d";
+ for e in /share/man /share/MAN /man /MAN
+ do
+ msfp_mandir="${msfp_base}$e";
+ if obj msfp_mandir is_dir
+ then
+ list_append msfp_manpath "${msfp_mandir}";
+ fi;
+ done;
+ done;
+ fi;
+
+ _MAN_PATH="${msfp_manpath}";
+ eval ${_UNSET} msfp_base;
+ eval ${_UNSET} msfp_list;
+ eval ${_UNSET} msfp_mandir;
+ eval ${_UNSET} msfp_manpath;
+ eval "${return_ok}";
+} # manpath_set_from_path()
+
+
+########################################################################
+landmark '9: obj_*()';
+########################################################################
+
+########################################################################
+# obj (<object> <call_name> <arg>...)
+#
+# This works like a method (object function) call for an object.
+# Run "<call_name> $<object> <arg> ...".
+#
+# The first argument represents an object name whose data is given as
+# first argument to <call_name>().
+#
+# Argument: >=2
+# <object>: variable name
+# <call_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 (<object>)
+#
+# Print the data of <object>, i.e. the content of $<object>.
+# For possible later extensions.
+#
+# Arguments: 1
+# <object>: a variable name
+# Output: the data of <object>
+#
+# Variable prefix: od
+#
+obj_data()
+{
+ func_check obj_data '=' 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_data()
+
+
+########################################################################
+# obj_from_output (<object> <call_name> <arg>...)
+#
+# Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
+# function call to a global variable. Variables are not stored.
+#
+# Arguments: >=2
+# <object>: a variable name
+# <call_name>: the name of a function or program
+# <arg>: optional argument to <call_name>
+# Output: none
+#
+# Variable prefix: ofo
+#
+obj_from_output()
+{
+ func_check obj_from_output '>=' 2 "$@";
+ if is_empty "$1"
+ then
+ error "obj_from_output(): variable name is empty.";
+ fi;
+ if is_empty "$2"
+ then
+ error "obj_from_output(): function name is empty."
+ fi;
+ ofo_result_name="$1";
+ shift;
+ ofo_return=0;
+ if is_equal "$#" 0
+ then
+ eval "${ofo_result_name}"'=""';
+ else
+ ofo_list='';
+ for i
+ do
+ list_append ofo_list "$i";
+ done;
+ eval "${ofo_result_name}"'="$('"${ofo_list}"')"';
+ ofo_return="$?";
+ exit_test;
+ fi;
+ r="${ofo_return}";
+ eval ${_UNSET} ofo_list;
+ eval ${_UNSET} ofo_return;
+ eval ${_UNSET} ofo_result_name;
+ eval "${return_var} $r";
+} # obj_from_output()
+
+
+########################################################################
+# obj_set (<object> <data>)
+#
+# Set the data of <object>, i.e. call "$<object>=<data>".
+#
+# Arguments: 2
+# <object>: a variable name
+# <data>: 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}";
+} # obj_set()
+
+
+########################################################################
+# path_chop (<path>)
+#
+# 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 '
+s/^:*//
+s/:::*/:/g
+s/:*$//
+';
+ eval "${return_ok}";
+} # path_chop()
+
+
+########################################################################
+# path_clean (<path>)
+#
+# 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_list "${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}:$(dir_name_chop "${pc_i}")";
+ exit_test;
+ ;;
+ *)
+ pc_res="${pc_res}:${pc_i}";
+ ;;
+ esac;
+ fi;
+ done;
+ path_chop "${pc_res}";
+ eval ${_UNSET} pc_arg;
+ eval ${_UNSET} pc_i;
+ eval ${_UNSET} pc_res;
+ eval "${return_ok}";
+} # path_clean()
+
+
+########################################################################
+# path_contains (<path> <dir>)
+#
+# Test whether <dir> is contained in <path>, a list separated by `:'.
+#
+# Arguments : 2
+# 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_contains()
+
+
+########################################################################
+# path_not_contains (<path> <dir>)
+#
+# Test whether <dir> is not contained in colon separated <path>.
+#
+# Arguments : 2
+#
+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_not_contains()
+
+
+########################################################################
+# path_list (<path>)
+#
+# From a `:' separated path generate a list with unique elements.
+#
+# Arguments: 1: a colon-separated path
+# Output: the resulting list, process it with `eval set'
+#
+# Variable prefix: pl
+#
+path_list()
+{
+ func_check path_list = 1 "$@";
+ eval set x "$(list_from_split "$1" '\:')";
+ shift;
+ pl_list='';
+ for e
+ do
+ pl_elt="$e";
+ if list_has pl_list "${pl_elt}"
+ then
+ continue;
+ else
+ list_append pl_list "${pl_elt}";
+ fi;
+ done;
+ obj pl_list echo1;
+ eval ${_UNSET} pl_elt;
+ eval ${_UNSET} pl_list;
+ eval "${return_ok}";
+} # path_list()
+
+
+########################################################################
+landmark '10: register_*()';
+########################################################################
+
+########################################################################
+# register_file (<filename>)
+#
+# 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 "$1";
+ exit_test;
+ fi;
+ eval "${return_ok}";
+} # register_file()
+
+
+########################################################################
+# register_title (<filespec>)
+#
+# Create title element from <filespec> and append to $_REG_TITLE_LIST.
+# Basename is created.
+#
+# Globals: $_REG_TITLE_LIST (rw)
+#
+# Variable prefix: rt
+#
+register_title()
+{
+ func_check register_title '=' 1 "$@";
+ if is_empty "$1"
+ then
+ eval "${return_ok}";
+ fi;
+
+ if obj _DEBUG_PRINT_FILENAMES is_yes
+ then
+ if is_equal "$1" 'stdin'
+ then
+ echo2 "file: standard input";
+ else
+ if obj _FILESPEC_IS_MAN is_yes
+ then
+ echo2 "file title: $1";
+ else
+ echo2 "file: $1";
+ fi;
+ fi;
+ fi;
+
+ case "${_REG_TITLE_LIST}" in
+ *\ *\ *\ *)
+ eval "${return_ok}";
+ ;;
+ esac;
+
+ # remove directory part
+ obj_from_output rt_title base_name "$1";
+ # replace space characters by `_'
+ rt_title="$(echo1 "${rt_title}" | sed 's/[ ]/_/g')";
+ # remove extension `.bz2'
+ rt_title="$(echo1 "${rt_title}" | sed 's/\.bz2$//')";
+ # remove extension `.gz'
+ rt_title="$(echo1 "${rt_title}" | sed 's/\.gz$//')";
+ # remove extension `.Z'
+ rt_title="$(echo1 "${rt_title}" | sed 's/\.Z$//')";
+
+ if obj rt_title is_empty
+ then
+ eval ${_UNSET} rt_title;
+ eval "${return_ok}";
+ fi;
+ list_append _REG_TITLE_LIST "${rt_title}";
+ 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 (<file_name>)
+#
+# Remove file.
+#
+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()
+
+
+########################################################################
+# rm_file_with_debug (<file_name>)
+#
+# 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_file_with_debug()
+
+
+########################################################################
+# rm_tree (<dir_name>)
+#
+# Remove a file or a complete directory tree.
+#
+# 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;
+} # rm_tree()
+
+
+########################################################################
+# 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}";
+ } # save_stdin()
+else # no compression
+ save_stdin()
+ {
+ func_check save_stdin '=' 0 "$@";
+ cat >"${_TMP_STDIN}";
+ eval "${return_ok}";
+ } # save_stdin()
+fi;
+
+
+########################################################################
+# special_filespec ()
+#
+# Handle special modes like whatis and apropos. Run their filespec
+# functions if suitable.
+#
+# Globals: in: $_OPT_APROPOS, $_OPT_WHATIS, $_SPECIAL_SETUP
+# out: $_SPECIAL_FILESPEC (internal)
+#
+special_filespec()
+{
+ func_check special_filespec '=' 0 "$@";
+ if obj _OPT_APROPOS is_not_yes && obj _OPT_WHATIS is_not_yes
+ then
+ eval "${return_bad}";
+ fi;
+ if obj _OPT_APROPOS is_yes && obj _OPT_WHATIS is_yes
+ then
+ error \
+ 'special_filespec(): $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
+ fi;
+ if obj _SPECIAL_SETUP is_not_yes
+ then
+ error 'special_filespec(): setup for apropos or whatis must be run first.';
+ fi;
+ if apropos_filespec || whatis_filespec;
+ then
+ eval "${return_ok}";
+ else
+ eval "${return_bad}";
+ fi;
+} # special_filespec()
+
+
+########################################################################
+# special_setup ()
+#
+# Handle special modes like whatis and apropos. Run their setup
+# functions if suitable.
+#
+special_setup()
+{
+ func_check special_setup '=' 0 "$@";
+ if obj _OPT_APROPOS is_yes && obj _OPT_WHATIS is_yes
+ then
+ error \
+ 'special_setup(): $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
+ fi;
+ if apropos_setup || whatis_setup
+ then
+ eval "${return_ok}";
+ else
+ eval "${return_bad}";
+ fi;
+} # special_setup()
+
+
+########################################################################
+landmark '11: stack_*()';
+########################################################################
+
+########################################################################
+# string_contains (<string> <part>)
+#
+# 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_contains()
+
+
+########################################################################
+# string_not_contains (<string> <part>)
+#
+# 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}";
+} # string_not_contains()
+
+
+########################################################################
+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_cat()
+
+
+########################################################################
+# tmp_create (<suffix>?)
+#
+# Create temporary file. The generated name is `,' followed by
+# <suffix>.
+#
+# Argument: 0 or 1
+#
+# Globals: $_TMP_DIR
+#
+# Output : name of created file
+#
+# Variable prefix: tc
+#
+tmp_create()
+{
+ func_check tmp_create '<=' 1 "$@";
+ if obj _TMP_DIR is_empty || obj _TMP_DIR is_not_dir
+ then
+ error 'tmp_create(): there is no temporary directory.';
+ else
+ # the output file does not have `,' as first character, so these are
+ # different names from the output file.
+ tc_tmp="${_TMP_DIR}/,$1";
+ obj tc_tmp rm_file;
+ : >"${tc_tmp}"
+ obj tc_tmp echo1;
+ fi;
+ eval ${_UNSET} tc_tmp;
+ eval "${return_ok}";
+} # tmp_create()
+
+
+########################################################################
+# to_tmp (<filename>)
+#
+# Print file (decompressed) to the temporary cat file.
+#
+# Variable prefix: tt
+#
+to_tmp()
+{
+ func_check to_tmp '=' 1 "$@";
+ if obj _TMP_CAT is_empty
+ then
+ error 'to_tmp(): $_TMP_CAT is not yet set';
+ fi;
+ tt_1="$1";
+ tt_so_nr=0; # number for temporary `,so,*,*'
+ if is_file "${tt_1}"
+ then
+ tt_dir="$(dir_name "${tt_1}")";
+ if obj _OPT_WHATIS is_yes
+ then
+ whatis_filename "${tt_1}" >>"${_TMP_CAT}";
+ else
+ _FILE_NR="$(expr ${_FILE_NR} + 1)";
+ tt_file="${_TMP_DIR}/,file${_FILE_NR}";
+ if obj _FILESPEC_IS_MAN is_yes
+ then
+ if obj _DEBUG_PRINT_FILENAMES is_yes
+ then
+ echo2 "file: ${tt_1}";
+ fi;
+ tt_tmp="${_TMP_DIR}/,tmp";
+ cat_z "${tt_1}" >"${tt_file}";
+ grep '^\.[ ]*so[ ]' "${tt_file}" |
+ sed 's/^\.[ ]*so[ ]*//' >"${tt_tmp}";
+ list_from_file tt_list "${tt_tmp}";
+ eval set x ${tt_list};
+ shift;
+ for i
+ do
+ tt_i="$i";
+ tt_so_nr="$(expr ${tt_so_nr} + 1)";
+ tt_sofile="${_TMP_DIR}/,so${_FILE_NR}_${tt_so_nr}";
+ tt_sofiles="${tt_sofiles} ${tt_sofile}";
+ _do_man_so "${tt_i}";
+ done;
+ rm_file "${tt_tmp}";
+ mv "${tt_file}" "${tt_tmp}";
+ cat "${tt_tmp}" | soelim -I "${tt_dir}" ${_SOELIM_R} >"${tt_file}";
+ for f in ${tt_sofiles}
+ do
+ rm_file_with_debug $f;
+ done;
+ rm_file "${tt_tmp}";
+ else # $_FILESPEC_IS_MAN ist not yes
+ cat_z "${tt_1}" | soelim -I "${tt_dir}" ${_SOELIM_R} >"${tt_file}";
+ fi;
+### to_tmp()
+ obj_from_output tt_grog grog "${tt_file}";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${tt_grog}";
+ case " ${tt_grog} " in
+ *\ -m*)
+ eval set x "$(echo1 " ${tt_grog} " | sed '
+s/'"${_TAB}"'/ /g
+s/ */ /g
+s/ -m / -m/g
+s/ -mm\([^ ]\)/ -m\1/g
+')";
+ shift;
+ for i
+ do
+ tt_i="$i";
+ case "${tt_i}" in
+ -m*)
+ if list_has _MACRO_PACKAGES "${tt_i}"
+ then
+ case "${_MACRO_PKG}" in
+ '')
+ _MACRO_PKG="${tt_i}";
+ ;;
+ ${tt_i})
+ :;
+ ;;
+ -m*)
+ echo2 "Ignore ${tt_1} because it needs ${tt_i} instead "\
+"of ${_MACRO_PKG}."
+ rm_file_with_debug "${tt_file}";
+ eval ${_UNSET} tt_1;
+ eval ${_UNSET} tt_dir;
+ eval ${_UNSET} tt_file;
+ eval ${_UNSET} tt_grog;
+ eval ${_UNSET} tt_i;
+ eval ${_UNSET} tt_so_nr;
+ eval ${_UNSET} tt_sofile;
+ eval ${_UNSET} tt_sofiles;
+ eval ${_UNSET} tt_sofound;
+ eval ${_UNSET} tt_list;
+ eval ${_UNSET} tt_tmp;
+ eval "${return_bad}";
+ ;;
+### to_tmp()
+ *)
+ error \
+'to_tmp(): $_MACRO_PKG does not start with -m: '"${_MACRO_PKG}";
+ ;;
+ esac;
+ fi;
+ ;;
+ esac;
+ done;
+ ;;
+ esac;
+ cat "${tt_file}" >>"${_TMP_CAT}";
+ rm_file_with_debug "${tt_file}";
+ fi;
+ else
+ error "to_tmp(): could not read file \`${tt_1}'.";
+ fi;
+ eval ${_UNSET} tt_1;
+ eval ${_UNSET} tt_dir;
+ eval ${_UNSET} tt_file;
+ eval ${_UNSET} tt_grog;
+ eval ${_UNSET} tt_i;
+ eval ${_UNSET} tt_so_nr;
+ eval ${_UNSET} tt_sofile;
+ eval ${_UNSET} tt_sofiles;
+ eval ${_UNSET} tt_sofound;
+ eval ${_UNSET} tt_list;
+ eval ${_UNSET} tt_tmp;
+ eval "${return_ok}";
+} # to_tmp()
+
+
+#############
+# _do_man_so (<so_arg>)
+#
+# Handle single .so file name for man pages.
+#
+# Local function to to_tmp().
+#
+# Globals from to_tmp(): $tt_tmp, $tt_sofile, $tt_file
+# Globals: $_TMP_MAN
+#
+# Variable prefix: dms
+#
+_do_man_so() {
+ func_check _do_man_so '=' 1 "$@";
+ _dms_so="$1"; # evt. with `\ '
+ _dms_soname="$(echo $1 | sed 's/\\[ ]/ /g')"; # without `\ '
+ case "${_dms_soname}" in
+ /*) # absolute path
+ if test -f "${_dms_soname}"
+ then
+ eval "${return_ok}";
+ fi;
+ if test -f "${_dms_soname}"'.gz'
+ then
+ _dms_sofound="${_dms_soname}"'.gz';
+ elif test -f "${_dms_soname}"'.Z'
+ then
+ _dms_sofound="${_dms_soname}"'.Z';
+ elif test -f "${_dms_soname}"'.bz2'
+ then
+ _dms_sofound="${_dms_soname}"'.bz2';
+ else
+ eval ${_UNSET} _dms_so;
+ eval ${_UNSET} _dms_soname;
+ eval "${return_ok}";
+ fi;
+ ;;
+### _do_man_so() of to_tmp()
+ *) # relative to man path
+ eval grep "'/${_dms_soname}\$'" "${_TMP_MAN}" >"${tt_tmp}";
+ if is_empty_file "${tt_tmp}"
+ then
+ eval grep "'/${_dms_soname}.gz\$'" "${_TMP_MAN}" >"${tt_tmp}";
+ if is_empty_file "${tt_tmp}"
+ then
+ eval grep "'/${_dms_soname}.Z\$'" "${_TMP_MAN}" >"${tt_tmp}";
+ if is_empty_file "${tt_tmp}"
+ then
+ eval grep "'/${_dms_soname}.bz2\$'" "${_TMP_MAN}" >"${tt_tmp}";
+ fi;
+ fi;
+ fi;
+ if is_empty_file "${tt_tmp}"
+ then
+ eval "${return_ok}";
+ fi;
+ _dms_done='no';
+ list_from_file _dms_list "${tt_tmp}";
+ eval set x ${_dms_list};
+ shift;
+ for i
+ do
+ _dms_sofound="$i";
+ if obj _dms_sofound is_empty
+ then
+ continue;
+ fi;
+ _dms_done='yes';
+ break;
+ done;
+### _do_man_so() of to_tmp()
+ if obj _dms_done is_not_yes
+ then
+ eval ${_UNSET} _dms_done;
+ eval ${_UNSET} _dms_sofound;
+ eval "${return_ok}";
+ fi;
+ ;;
+ esac;
+ if obj _DEBUG_PRINT_FILENAMES is_yes
+ then
+ echo2 "file from .so: ${_dms_so}";
+ fi;
+ cat_z "${_dms_sofound}" >"${tt_sofile}";
+ _dms_esc="$(echo ${_dms_so} | sed 's/\\/\\\\/g')";
+ cat "${tt_file}" | eval sed \
+"'s#^\\.[ ]*so[ ]*\(${_dms_so}\|${_dms_esc}\|${_dms_soname}\)[ ]*\$'"\
+"'#.so ${tt_sofile}#'" \
+ >"${tt_tmp}";
+ rm_file "${tt_file}";
+ mv "${tt_tmp}" "${tt_file}";
+ eval ${_UNSET} _dms_done;
+ eval ${_UNSET} _dms_esc;
+ eval ${_UNSET} _dms_so;
+ eval ${_UNSET} _dms_sofound;
+ eval ${_UNSET} _dms_soname;
+ eval "${return_ok}";
+} # _do_man_so() of to_tmp()
+
+
+########################################################################
+# to_tmp_line (<text>...)
+#
+# Print single line with <text> to the temporary cat file.
+#
+to_tmp_line()
+{
+ func_check to_tmp_line '>=' 1 "$@";
+ if obj _TMP_CAT is_empty
+ then
+ error 'to_tmp_line(): $_TMP_CAT is not yet set';
+ fi;
+ echo1 "$*" >>"${_TMP_CAT}";
+ eval "${return_ok}";
+} # to_tmp_line()
+
+
+########################################################################
+# 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_set()
+
+
+########################################################################
+# trap_unset ()
+#
+# Disable trap on signal 0.
+#
+trap_unset()
+{
+ func_check trap_unset '=' 0 "$@";
+ trap '' 0 2>${_NULL_DEV} || :;
+ eval "${return_ok}";
+} # trap_unset()
+
+
+########################################################################
+# usage ()
+#
+# Print usage information to standard output; for groffer option --help.
+#
+usage()
+{
+ func_check usage = 0 "$@";
+ echo;
+ version;
+ cat <<EOF
+
+Usage: groffer [option]... [filespec]...
+
+Display roff files, standard input, and/or Unix manual pages with a X
+Window viewer or in several text modes. All input is decompressed
+on-the-fly with all formats that gzip can handle.
+
+"filespec" is one of
+ "filename" name of a readable file
+ "-" for standard input
+ "man:name(n)" man page "name" in section "n"
+ "man:name.n" man page "name" in section "n"
+ "man:name" man page "name" in first section found
+ "name(n)" man page "name" in section "n"
+ "name.n" man page "name" in section "n"
+ "n name" man page "name" in section "n"
+ "name" man page "name" in first section found
+where `section' is a single character out of [1-9on], optionally followed
+by some more letters that are called the `extension'.
+
+-h --help print this usage message.
+-T --device=name pass to groff using output device "name".
+-v --version print version information.
+-V display the groff execution pipe instead of formatting.
+-X display with "gxditview" using groff -X.
+-Z --ditroff --intermediate-output
+ generate groff intermediate output without
+ post-processing and viewing, like groff -Z.
+All other short options are interpreted as "groff" formatting options.
+
+The most important groffer long options are
+
+--apropos=name start man's "apropos" program for "name".
+--apropos-data=name
+ "apropos" for "name" in man's data sections 4, 5, 7.
+--apropos-devel=name
+ "apropos" for "name" in development sections 2, 3, 9.
+--apropos-progs=name
+ "apropos" for "name" in man's program sections 1, 6, 8.
+--auto choose mode automatically from the default mode list.
+--default reset all options to the default value.
+--default-modes=mode1,mode2,...
+ set sequence of automatically tried modes.
+--dvi display in a viewer for TeX device independent format.
+--dvi-viewer=prog choose the viewer program for dvi mode.
+--groff process like groff, disable viewing features.
+--help display this helping output.
+--html display in a web browser.
+--html-viewer=program
+ choose a web browser for html mode.
+--man check file parameters first whether they are man pages.
+--mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
+ choose display mode.
+--no-man disable man-page facility.
+--no-special disable --all, --apropos*, and --whatis
+--pager=program preset the paging program for tty mode.
+--pdf display in a PDF viewer.
+--pdf-viewer=prog choose the viewer program for pdf mode.
+--ps display in a Postscript viewer.
+--ps-viewer=prog choose the viewer program for ps mode.
+--shell=program specify a shell under which to run groffer2.sh.
+--source output as roff source.
+--text output in a text device without a pager.
+--to-stdout output the content of the mode file without display.
+--tty display with a pager on text terminal even when in X.
+--tty-viewer=prog select a pager for tty mode; same as --pager.
+--whatis display the file name and description of man pages
+--www same as --html.
+--www-viewer=prog same as --html-viewer
+--x --X display with "gxditview" using an X* device.
+--x-viewer=prog choose viewer program for x mode (X mode).
+--X-viewer=prog same as "--xviewer".
+
+The usual X Windows toolkit options transformed into GNU long options:
+--background=color, --bd=size, --bg=color, --bordercolor=color,
+--borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
+--fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
+--resolution=dpi, --rv, --title=text, --xrm=resource
+
+Long options of GNU "man":
+--all, --ascii, --ditroff, --extension=suffix, --locale=language,
+--local-file=name, --location, --manpath=dir1:dir2:...,
+--sections=s1:s2:..., --systems=s1,s2,..., --where, ...
+
+Development options that are not useful for normal usage:
+--debug, --debug-all, --debug-filenames, --debug-func,
+--debug-not-func, --debug-grog, --debug-keep, --debug-lm,
+--debug-params, --debug-shell, --debug-stacks, --debug-tmpdir,
+--debug-user, --do-nothing, --print=text, --shell=prog
+
+EOF
+
+ eval "${return_ok}";
+} # usage()
+
+
+########################################################################
+# version ()
+#
+# Print version information to standard output.
+# For groffer option --version.
+#
+version()
+{
+ func_check version = 0 "$@";
+ y="$(echo "${_LAST_UPDATE}" | sed 's/^.* //')";
+ cat <<EOF
+groffer ${_PROGRAM_VERSION} of ${_LAST_UPDATE} (shell version)
+is part of groff version ${_GROFF_VERSION}.
+Copyright (C) $y Free Software Foundation, Inc.
+GNU groff and groffer come with ABSOLUTELY NO WARRANTY.
+You may redistribute copies of groff and its subprograms
+under the terms of the GNU General Public License.
+EOF
+ eval "${return_ok}";
+} # version()
+
+
+########################################################################
+# warning (<string>)
+#
+# Print warning to stderr.
+#
+warning()
+{
+ echo2 "warning: $*";
+} # warning()
+
+
+########################################################################
+# whatis_filename (<filename>)
+#
+# Interpret <filename> as a man page and display its `whatis'
+# information as a fragment written in the groff language.
+#
+# Globals: in: $_OPT_WHATIS, $_SPECIAL_SETUP, $_SPECIAL_FILESPEC,
+# $_FILESPEC_ARG
+#
+# Variable prefix: wf
+#
+whatis_filename()
+{
+ func_check whatis_filename = 1 "$@";
+ if obj _OPT_WHATIS is_not_yes
+ then
+ error 'whatis_filename(): $_OPT_WHATIS is not yes.';
+ fi;
+ if obj _SPECIAL_SETUP is_not_yes
+ then
+ error \
+ 'whatis_filename(): setup for whatis whatis_setup() must be run first.';
+ fi;
+ if obj _SPECIAL_FILESPEC is_not_yes
+ then
+ error 'whatis_filename(): whatis_filespec() must be run first.';
+ fi;
+ 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}"'*';
+### whatis_filename()
+ if obj _FILESPEC_ARG is_equal '-'
+ then
+ wf_arg='stdin';
+ fi;
+ cat <<EOF
+\f[CR]${wf_arg}\f[]:
+.br
+EOF
+
+ # get the parts of the file name
+ wf_name="$(base_name $1)";
+ wf_section="$(echo1 $1 | sed -n '
+s|^.*/man\('"${_MAN_AUTO_SEC_CHARS}"'\).*$|\1|p
+')";
+ if obj wf_section is_not_empty
+ then
+ case "${wf_name}" in
+ *.${wf_section}*)
+ s='yes';
+ ;;
+ *)
+ s='';
+ wf_section='';
+ ;;
+### whatis_filename()
+ esac
+ if obj s is_yes
+ then
+ wf_name="$(echo1 ${wf_name} | sed '
+s/^\(.*\)\.'${wf_section}'.*$/\1/
+')";
+ fi;
+ fi;
+
+ # traditional man style; grep the line containing `.TH' macro, if any
+ wf_res="$(cat_z "$1" | sed '
+/'"${wf_dot}"'TH /p
+d
+')";
+ exit_test;
+ if obj wf_res is_not_empty
+ then # traditional man style
+ # get the first line after the first `.SH' macro, by
+ # - delete up to first .SH;
+ # - print all lines before the next .SH;
+ # - quit.
+ wf_res="$(cat_z "$1" | sed -n '
+1,/'"${wf_dot}"'SH/d
+/'"${wf_dot}"'SH/q
+p
+')";
+
+ if obj wf_section is_not_empty
+ then
+ case "${wf_res}" in
+ ${wf_name}${_SPACE_CASE}*-${_SPACE_CASE}*)
+ s='yes';
+ ;;
+### whatis_filename()
+ *)
+ s='';
+ ;;
+ esac;
+ if obj s is_yes
+ then
+ wf_res="$(obj wf_res echo1 | sed '
+s/^'"${wf_name}${_SPACE_SED}"'[^-]*-'"${_SPACE_SED}"'*\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/
+')";
+ fi;
+ fi;
+ obj wf_res echo1;
+ echo;
+ eval ${_UNSET} wf_arg;
+ eval ${_UNSET} wf_dot;
+ eval ${_UNSET} wf_name;
+ eval ${_UNSET} wf_res;
+ eval ${_UNSET} wf_section;
+ eval "${return_ok}";
+ fi;
+
+ # mdoc style (BSD doc); grep the line containing `.Nd' macro, if any
+ wf_res="$(cat_z "$1" | sed -n '/'"${wf_dot}"'Nd /s///p')";
+ exit_test;
+ if obj wf_res is_not_empty
+ then # BSD doc style
+ if obj wf_section is_not_empty
+ then
+ wf_res="$(obj wf_res echo1 | sed -n '
+s/^\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/p
+')";
+ fi;
+### whatis_filename()
+ obj wf_res echo1;
+ echo;
+ eval ${_UNSET} wf_arg;
+ eval ${_UNSET} wf_dot;
+ eval ${_UNSET} wf_name;
+ eval ${_UNSET} wf_res;
+ eval ${_UNSET} wf_section;
+ eval "${return_ok}";
+ fi;
+ echo1 'is not a man page';
+ echo;
+ eval ${_UNSET} wf_arg;
+ eval ${_UNSET} wf_dot;
+ eval ${_UNSET} wf_name;
+ eval ${_UNSET} wf_res;
+ eval ${_UNSET} wf_section;
+ eval "${return_bad}";
+} # whatis_filename()
+
+
+
+########################################################################
+# whatis_filespec ()
+#
+# Print the filespec name as .SH to the temporary cat file.
+#
+# Globals: in: $_OPT_WHATIS, $_SPECIAL_SETUP
+# out: $_SPECIAL_FILESPEC
+#
+whatis_filespec()
+{
+ func_check whatis_filespec '=' 0 "$@";
+ if obj _OPT_WHATIS is_yes
+ then
+ if obj _SPECIAL_SETUP is_not_yes
+ then
+ error 'whatis_filespec(): whatis_setup() must be run first.';
+ fi;
+ _SPECIAL_FILESPEC='yes';
+ eval to_tmp_line \
+ "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
+ exit_test;
+ eval "${return_ok}";
+ else
+ eval "${return_bad}";
+ fi;
+} # whatis_filespec()
+
+
+########################################################################
+# whatis_setup ()
+#
+# Print the whatis header to the temporary cat file; this is the setup
+# for whatis.
+#
+# Globals: in: $_OPT_WHATIS
+# out: $_SPECIAL_SETUP
+#
+whatis_setup()
+{
+ func_check whatis_setup '=' 0 "$@";
+ if obj _OPT_WHATIS is_yes
+ then
+ to_tmp_line '.TH GROFFER WHATIS';
+ _SPECIAL_SETUP='yes';
+ if obj _OPT_TITLE is_empty
+ then
+ _OPT_TITLE='whatis';
+ fi;
+ eval "${return_ok}";
+ else
+ eval "${return_bad}";
+ fi;
+} # whatis_setup()
+
+
+########################################################################
+# where_is_prog (<program>)
+#
+# Output path of a program and the given arguments if in $PATH.
+#
+# Arguments : 1, <program> can have spaces and arguments.
+# Output : list of 2 elements: prog name (with directory) and arguments
+# Return : `0' if arg1 is a program in $PATH, `1' otherwise.
+#
+# Variable prefix: wip
+#
+where_is_prog()
+{
+ func_check where_is_prog '=' 1 "$@";
+ if is_empty "$1"
+ then
+ eval "${return_bad}";
+ fi;
+
+ # Remove disturbing multiple spaces and tabs
+ wip_1="$(echo1 "$1" | sed 's/[ ][ ]*/ /g' | \
+ sed 's/\(\\\)* / /g' | sed 's/^ //' | sed 's/ $//')";
+ wip_noarg="$(echo1 "${wip_1}" | sed 's/ -.*$//')";
+ exit_test;
+
+ if obj wip_noarg is_empty
+ then
+ eval ${_UNSET} wip_1;
+ eval ${_UNSET} wip_noarg;
+ eval "${return_bad}";
+ fi;
+
+ case "${wip_1}" in
+ *\ -*)
+ wip_args="$(echo1 "${wip_1}" |
+ eval sed "'s#^${wip_noarg} ##'")";
+ exit_test;
+ ;;
+ *)
+ wip_args='';
+ ;;
+ esac;
+
+ wip_result='';
+### where_is_prog()
+
+ if test -f "${wip_noarg}" && test -x "${wip_noarg}"
+ then
+ list_append wip_result "${wip_noarg}" "${wip_args}";
+ exit_test;
+ obj wip_result echo1;
+ exit_test;
+ eval ${_UNSET} wip_1;
+ eval ${_UNSET} wip_args;
+ eval ${_UNSET} wip_noarg;
+ eval ${_UNSET} wip_result;
+ eval "${return_ok}";
+ fi;
+
+ # test whether $wip_noarg has directory, so it is not tested with $PATH
+ case "${wip_noarg}" in
+ */*)
+ # now $wip_noarg (with /) is not an executable file
+
+ # test name with space
+ obj_from_output wip_name base_name "${wip_noarg}";
+ obj_from_output wip_dir dir_name "${wip_noarg}";
+ case "${wip_name}" in
+ *\ *)
+ wip_base="$(echo1 "${wip_name}" | sed 's/ .*$//')";
+ exit_test;
+ obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_base}";
+ exit_test;
+### where_is_prog()
+ if test -f "${wip_file}" && test -x "${wip_file}"
+ then
+ wip_baseargs="$(echo1 "${wip_name}" |
+ eval sed "'s#^${wip_base} ##'")";
+ exit_test;
+ if obj wip_args is_empty
+ then
+ wip_args="${wip_baseargs}";
+ else
+ wip_args="${wip_baseargs} ${wip_args}";
+ fi;
+
+ list_append wip_result "${wip_file}" "${wip_args}";
+ exit_test;
+ obj wip_result echo1;
+ exit_test;
+ eval ${_UNSET} wip_1;
+ eval ${_UNSET} wip_args;
+ eval ${_UNSET} wip_base;
+ eval ${_UNSET} wip_baseargs;
+ eval ${_UNSET} wip_dir;
+ eval ${_UNSET} wip_file;
+ eval ${_UNSET} wip_name;
+ eval ${_UNSET} wip_noarg;
+ eval ${_UNSET} wip_result;
+ eval "${return_ok}";
+ fi; # test ${wip_file}
+ ;;
+ esac; # end of test name with space
+
+### where_is_prog()
+ eval ${_UNSET} wip_1;
+ eval ${_UNSET} wip_args;
+ eval ${_UNSET} wip_base;
+ eval ${_UNSET} wip_dir;
+ eval ${_UNSET} wip_name;
+ eval ${_UNSET} wip_noarg;
+ eval ${_UNSET} wip_result;
+ eval "${return_bad}";
+ ;;
+ esac; # test of $wip_noarg on path with directory
+
+
+ # now $wip_noarg does not have a /, so it is checked with $PATH.
+
+ eval set x "$(path_list "${PATH}")";
+ exit_test;
+ shift;
+
+ # test path with $win_noarg, evt. with spaces
+ for d
+ do
+ wip_dir="$d";
+ obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_noarg}";
+### where_is_prog()
+
+ # test $win_file on executable file
+ if test -f "${wip_file}" && test -x "${wip_file}"
+ then
+ list_append wip_result "${wip_file}" "${wip_args}";
+ exit_test;
+ obj wip_result echo1;
+ exit_test;
+ eval ${_UNSET} wip_1;
+ eval ${_UNSET} wip_dir;
+ eval ${_UNSET} wip_file;
+ eval ${_UNSET} wip_noarg;
+ eval ${_UNSET} wip_result;
+ eval "${return_ok}";
+ fi; # test $win_file on executable file
+ done; # test path with $win_prog with spaces
+
+ case "${wip_noarg}" in
+ *\ *)
+ # test on path with base name without space
+ wip_base="$(echo1 "${wip_noarg}" | sed 's/^\([^ ]*\) .*$/\1/')";
+ exit_test;
+ for d
+ do
+ wip_dir="$d";
+ obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_base}";
+ exit_test;
+### where_is_prog()
+
+ # test $win_file on executable file
+ if test -f "${wip_file}" && test -x "${wip_file}"
+ then
+ wip_baseargs="$(echo1 "${wip_noarg}" |
+ sed 's/[^ ]* \(.*\)$/\1/')";
+ exit_test;
+ if obj wip_args is_empty
+ then
+ wip_args="${wip_baseargs}";
+ else
+ wip_args="${wip_args} ${wip_baseargs}";
+ fi;
+ list_append wip_result "${wip_file}" "${wip_args}";
+ exit_test;
+ obj wip_result echo1;
+ exit_test;
+ eval ${_UNSET} wip_1;
+ eval ${_UNSET} wip_args;
+ eval ${_UNSET} wip_base;
+ eval ${_UNSET} wip_baseargs;
+ eval ${_UNSET} wip_dir;
+ eval ${_UNSET} wip_file;
+ eval ${_UNSET} wip_name;
+ eval ${_UNSET} wip_noarg;
+ eval ${_UNSET} wip_result;
+ eval "${return_ok}";
+ fi; # test of $wip_file on executable file
+ done; # test path with base name without space
+### where_is_prog()
+ ;;
+ esac; # test of $wip_noarg on space
+
+ eval ${_UNSET} wip_1;
+ eval ${_UNSET} wip_args;
+ eval ${_UNSET} wip_base;
+ eval ${_UNSET} wip_baseargs;
+ eval ${_UNSET} wip_dir;
+ eval ${_UNSET} wip_file;
+ eval ${_UNSET} wip_name;
+ eval ${_UNSET} wip_noarg;
+ eval ${_UNSET} wip_result;
+ eval "${return_bad}";
+} # where_is_prog()
+
+
+########################################################################
+# 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 directory and some 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 0077;
+ _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}";
+### main_init()
+ 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;
+### main_init()
+ if obj _DEBUG_PRINT_TMPDIR is_yes
+ then
+ echo2 "temporary directory: ${_TMP_DIR}";
+ fi;
+
+ obj_from_output _TMP_CAT tmp_create groffer_cat;
+ obj_from_output _TMP_STDIN tmp_create groffer_input;
+
+ 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 '
+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';
+ ;;
+### main_parse_MANOPT()
+ -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;
+ ;;
+ -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;
+ ;;
+### main_parse_MANOPT()
+ -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;
+ ;;
+ -T|--device)
+ list_append mpm_list '-T' "$1";
+ shift;
+ ;;
+### main_parse_MANOPT()
+ -u|--update)
+ do_nothing;
+ ;;
+ -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 (<command_line_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 "$@";
+ obj_from_output _ALL_PARAMS list_from_cmdline_with_minus _OPTS_CMDLINE "$@";
+ 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';
+ ;;
+### main_parse_args()
+ -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)
+ _OPT_MODE=X;
+ ;;
+ -?)
+ # delete leading `-'
+ mpa_optchar="$(echo1 "${mpa_opt}" | sed '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;
+### main_parse_args()
+ 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';
+ ;;
+### main_parse_args()
+ --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|--bordercolor) # border color for viewers, arg;
+ _OPT_BD="$1";
+ shift;
+ ;;
+ --bg|--backgroud) # background color for viewers, arg;
+ _OPT_BG="$1";
+ shift;
+ ;;
+ --bw|--borderwidth) # border width for viewers, arg;
+ _OPT_BW="$1";
+ shift;
+ ;;
+ --debug|--debug-all|--debug-filenames|--debug-func|--debug-not-func|\
+--debug-grog|--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;
+ ;;
+### main_parse_args()
+ --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)
+ _OPT_MODE='dvi';
+ ;;
+ --dvi-viewer|--dvi-viewer-tty) # viewer program for dvi mode; arg
+ _OPT_VIEWER_DVI="$1";
+ shift;
+ ;;
+ --extension) # the extension for man pages, arg
+ _OPT_EXTENSION="$1";
+ shift;
+ ;;
+### main_parse_args()
+ --fg|--foreground) # foreground color for viewers, arg;
+ _OPT_FG="$1";
+ shift;
+ ;;
+ --fn|--ft|--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|--html-viewer-tty|--www-viewer-tty)
+ # viewer program for html mode; arg
+ _OPT_VIEWER_HTML="$1";
+ shift;
+ ;;
+ --iconic) # start viewers as icons
+ _OPT_ICONIC='yes';
+ ;;
+### main_parse_args()
+ --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
+ _DEBUG_PRINT_FILENAMES='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';
+ ;;
+### main_parse_args()
+ html|www) # display with a web browser
+ _OPT_MODE='html';
+ ;;
+ dvi) # display with xdvi viewer
+ _OPT_MODE='dvi';
+ ;;
+ pdf) # display with PDF viewer
+ _OPT_MODE='pdf';
+ ;;
+ ps) # display with Postscript viewer
+ _OPT_MODE='ps';
+ ;;
+ text) # output on terminal
+ _OPT_MODE='text';
+ ;;
+ tty) # output on terminal
+ _OPT_MODE='tty';
+ ;;
+ X|x) # output on X roff viewer
+ _OPT_MODE='x';
+ ;;
+### main_parse_args()
+ Q|source) # display source code
+ _OPT_MODE="source";
+ ;;
+ *)
+ error "main_parse_args(): unknown mode ${mpa_arg}";
+ ;;
+ esac;
+ ;;
+ --no-location) # disable former call to `--location'
+ _DEBUG_PRINT_FILENAMES='no';
+ ;;
+ --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
+ _OPT_PAGER="$1";
+ shift;
+ ;;
+ --pdf)
+ _OPT_MODE='pdf';
+ ;;
+### main_parse_args()
+ --pdf-viewer|--pdf-viewer-tty) # viewer program for pdf mode; arg
+ _OPT_VIEWER_PDF="$1";
+ shift;
+ ;;
+ --print) # for argument test
+ echo2 "$1";
+ shift;
+ ;;
+ --ps)
+ _OPT_MODE='ps';
+ ;;
+ --ps-viewer|--ps-viewer-tty) # viewer program for ps mode; arg
+ _OPT_VIEWER_PS="$1";
+ shift;
+ ;;
+### main_parse_args()
+ --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;
+ ;;
+### main_parse_args()
+ --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
+ if is_not_empty "$1"
+ then
+ list_append _OPT_TITLE "$1";
+ fi;
+ shift;
+ ;;
+ --to-stdout) # print mode file without display
+ _OPT_STDOUT='yes';
+ ;;
+ --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_APROPOS='no';
+ ;;
+ --X|--x)
+ _OPT_MODE=x;
+ ;;
+### main_parse_args()
+ --xrm) # pass X resource string, arg;
+ list_append _OPT_XRM "$1";
+ shift;
+ ;;
+ --x-viewer|--X-viewer|--x-viewer-tty|--X-viewer-tty)
+ # viewer program for x mode; arg
+ _OPT_VIEWER_X="$1";
+ shift;
+ ;;
+ *)
+ error 'main_parse_args(): unknown option '"\`${mpa_opt}'.";
+ ;;
+ esac;
+ done;
+ shift; # remove `--' argument
+
+ if obj _OPT_WHATIS is_yes
+ then
+ _MAN_ALL='yes';
+ _APROPOS_SECTIONS='';
+ fi;
+
+ if obj _OPT_DO_NOTHING is_yes
+ then
+ leave;
+ fi;
+
+### main_parse_args()
+ case "$_OPT_DEFAULT_MODES" in
+ '') :; ;;
+ *,*)
+ obj_from_output _OPT_DEFAULT_MODES \
+ obj _OPT_DEFAULT_MODES list_from_split ',';
+ ;;
+ *) :; ;;
+ esac;
+
+ # Remaining arguments are file names (filespecs).
+ # Save them to list $_FILEARGS
+ if is_equal "$#" 0
+ then # use "-" for standard input
+ _NO_FILESPECS='yes';
+ set x '-';
+ shift;
+ fi;
+ _FILEARGS='';
+ list_append _FILEARGS "$@";
+ # $_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 and the corresponding viewer program.
+#
+# 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_viewers;
+ eval "${return_ok}";
+ fi;
+
+### main_set_mode()
+
+ 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_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_viewers;
+ eval "${return_ok}";
+ ;;
+### main_set_mode()
+ esac;
+ if is_not_X
+ then
+ _DISPLAY_MODE='tty';
+ eval ${_UNSET} msm_modes;
+ 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;
+ ;;
+ source)
+ _DISPLAY_MODE='source';
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+ text)
+ _DISPLAY_MODE='text';
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+ tty)
+ _DISPLAY_MODE='tty';
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+### main_set_mode()
+ html)
+ _DISPLAY_MODE='html';
+ msm_modes="${_OPT_MODE}";
+ ;;
+ *) # display mode was given
+ msm_modes="${_OPT_MODE}";
+ ;;
+ esac;
+
+ eval set x "${msm_modes}";
+ shift;
+ while is_greater_than "$#" 0
+ do
+ msm_1="$1";
+ shift;
+
+ _VIEWER_BACKGROUND='no';
+
+ case "${msm_1}" in
+ dvi)
+ _get_prog_args DVI;
+ if is_not_equal "$?" 0
+ then
+ continue;
+ fi;
+ if obj _DISPLAY_PROG is_empty
+ then
+ if is_equal "$#" 0
+ then
+ error 'main_set_mode(): No viewer for dvi mode available.';
+ else
+ continue;
+ fi;
+ fi;
+### main_set_mode()
+ _DISPLAY_MODE="dvi";
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+ html)
+ _get_prog_args HTML;
+ if is_not_equal "$?" 0
+ then
+ continue;
+ fi;
+ if obj _DISPLAY_PROG is_empty
+ then
+ if is_equal "$#" 0
+ then
+ error 'main_set_mode(): No viewer for html mode available.';
+ else
+ continue;
+ fi;
+ fi;
+### main_set_mode()
+ _DISPLAY_MODE=html;
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+ pdf)
+ if obj _PDF_DID_NOT_WORK is_yes
+ then
+ if is_equal "$#" 0
+ then
+ error 'main_set_mode(): pdf mode did not work.';
+ else
+ continue;
+ fi;
+ fi;
+ if obj _PDF_HAS_PS2PDF is_not_yes
+ then
+ if is_prog ps2pdf
+ then
+ _PDF_HAS_PS2PDF='yes';
+ fi;
+ fi;
+ if obj _PDF_HAS_GS is_not_yes
+ then
+ if is_prog gs
+ then
+ _PDF_HAS_GS='yes';
+ fi;
+ fi;
+ _get_prog_args PDF;
+ if is_not_equal "$?" 0
+ then
+ _PDF_DID_NOT_WORK='yes';
+ continue;
+ fi;
+ if obj _DISPLAY_PROG is_empty
+ then
+ _PDF_DID_NOT_WORK='yes';
+ if is_equal "$#" 0
+ then
+ error 'main_set_mode(): No viewer for pdf mode available.';
+ else
+ continue;
+ fi;
+ fi;
+ _DISPLAY_MODE="pdf";
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+### main_set_mode()
+ ps)
+ _get_prog_args PS;
+ if is_not_equal "$?" 0
+ then
+ continue;
+ fi;
+ if obj _DISPLAY_PROG is_empty
+ then
+ if is_equal "$#" 0
+ then
+ error 'main_set_mode(): No viewer for ps mode available.';
+ else
+ continue;
+ fi;
+ fi;
+ _DISPLAY_MODE="ps";
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+ text)
+ _DISPLAY_MODE='text';
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+### main_set_mode()
+ tty)
+ _DISPLAY_MODE='tty';
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+ x)
+ _get_prog_args x;
+ if is_not_equal "$?" 0
+ then
+ continue;
+ fi;
+ if obj _DISPLAY_PROG is_empty
+ then
+ if is_equal "$#" 0
+ then
+ error 'main_set_mode(): No viewer for x mode available.';
+ else
+ continue;
+ fi;
+ fi;
+ _DISPLAY_MODE='x';
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+### main_set_mode()
+ X)
+ _DISPLAY_MODE='X';
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ eval "${return_ok}";
+ ;;
+ esac;
+ done;
+ eval ${_UNSET} msm_1;
+ eval ${_UNSET} msm_modes;
+ eval ${_UNSET} msm_viewers;
+ error_user "No suitable display mode found.";
+} # main_set_mode()
+
+
+# _get_prog_args (<MODE>)
+#
+# Simplification for loop in main_set_mode().
+#
+# Globals in/out: $_VIEWER_BACKGROUND
+# Globals in : $_OPT_VIEWER_<MODE>, $_VIEWER_<MODE>_X, $_VIEWER_<MODE>_TTY
+#
+# Variable prefix: _gpa
+#
+_get_prog_args()
+{
+ func_check _get_prog_args '=' 1 "$@";
+
+ x="$(echo1 $1 | tr [a-z] [A-Z])";
+ eval _gpa_opt='"${_OPT_VIEWER_'"$x"'}"';
+ _gpa_xlist=_VIEWER_"$x"_X;
+ _gpa_ttylist=_VIEWER_"$x"_TTY;
+
+ if obj _gpa_opt is_empty
+ then
+ _VIEWER_BACKGROUND='no';
+ if is_X
+ then
+ _get_first_prog "${_gpa_xlist}";
+ x="$?";
+ if is_equal "$x" 0
+ then
+ _VIEWER_BACKGROUND='yes';
+ fi;
+ else
+ _get_first_prog "${_gpa_ttylist}";
+ x="$?";
+ fi;
+ exit_test;
+ eval ${_UNSET} _gpa_opt;
+ eval ${_UNSET} _gpa_prog;
+ eval ${_UNSET} _gpa_ttylist;
+ eval ${_UNSET} _gpa_xlist;
+ eval "${return_var} $x";
+### _get_prog_args() of main_set_mode()
+ else # $_gpa_opt is not empty
+ obj_from_output _gpa_prog where_is_prog "${_gpa_opt}";
+ if is_not_equal "$?" 0 || obj _gpa_prog is_empty
+ then
+ exit_test;
+ echo2 "_get_prog_args(): '${_gpa_opt}' is not an existing program.";
+ eval ${_UNSET} _gpa_opt;
+ eval ${_UNSET} _gpa_prog;
+ eval ${_UNSET} _gpa_ttylist;
+ eval ${_UNSET} _gpa_xlist;
+ eval "${return_bad}";
+ fi;
+ exit_test;
+
+ # $_gpa_prog from opt is an existing program
+
+### _get_prog_args() of main_set_mode()
+ if is_X
+ then
+ eval _check_prog_on_list ${_gpa_prog} ${_gpa_xlist};
+ if is_equal "$?" 0
+ then
+ _VIEWER_BACKGROUND='yes';
+ else
+ _VIEWER_BACKGROUND='no';
+ eval _check_prog_on_list ${_gpa_prog} ${_gpa_ttylist};
+ fi;
+ else # is not X
+ _VIEWER_BACKGROUND='no';
+ eval _check_prog_on_list ${_gpa_prog} ${_gpa_ttylist};
+ fi; # is_X
+ fi; # test of $_gpa_opt
+ eval ${_UNSET} _gpa_opt;
+ eval ${_UNSET} _gpa_prog;
+ eval ${_UNSET} _gpa_ttylist;
+ eval ${_UNSET} _gpa_xlist;
+ eval "${return_good}";
+} # _get_prog_args() of main_set_mode()
+
+
+# _get_first_prog (<prog_list_name>)
+#
+# Retrieve from the elements of the list in the argument the first
+# existing program in $PATH.
+#
+# Local function for main_set_mode().
+#
+# Return : `1' if none found, `0' if found.
+# Output : none
+#
+# Variable prefix: _gfp
+#
+_get_first_prog()
+{
+ func_check _get_first_prog '=' 1 "$@";
+ eval x='"${'"$1"'}"';
+ eval set x "$x";
+ shift;
+ for i
+ do
+ _gfp_i="$i";
+ if obj _gfp_i is_empty
+ then
+ continue;
+ fi;
+ obj_from_output _gfp_result where_is_prog "${_gfp_i}";
+ if is_equal "$?" 0 && obj _gfp_result is_not_empty
+ then
+ exit_test;
+ eval set x ${_gfp_result};
+ shift;
+ _DISPLAY_PROG="$1";
+ _DISPLAY_ARGS="$2";
+ eval ${_UNSET} _gfp_i;
+ eval ${_UNSET} _gfp_result;
+ eval "${return_good}";
+ fi;
+ exit_test;
+ done;
+ eval ${_UNSET} _gfp_i;
+ eval ${_UNSET} _gfp_result;
+ eval "${return_bad}";
+} # _get_first_prog() of main_set_mode()
+
+
+# _check_prog_on_list (<prog> <args> <prog_list_name>)
+#
+# Check whether the content of <prog> is in the list <prog_list_name>.
+# The globals are set correspondingly.
+#
+# Local function for main_set_mode().
+#
+# Arguments: 3
+#
+# Return : `1' if not a part of the list, `0' if found in the list.
+# Output : none
+#
+# Globals in : $_VIEWER_<MODE>_X, $_VIEWER_<MODE>_TTY
+# Globals in/out: $_DISPLAY_PROG, $_DISPLAY_ARGS
+#
+# Variable prefix: _cpol
+#
+_check_prog_on_list()
+{
+ func_check _check_prog_on_list '=' 3 "$@";
+ _DISPLAY_PROG="$1";
+ _DISPLAY_ARGS="$2";
+
+ eval _cpol_3='"${'"$3"'}"';
+ eval set x "${_cpol_3}";
+ shift;
+ eval ${_UNSET} _cpol_3;
+
+ for i
+ do
+ _cpol_i="$i";
+ obj_from_output _cpol_list where_is_prog "${_cpol_i}";
+ if is_not_equal "$?" 0 || obj _cpol_list is_empty
+ then
+ exit_test;
+ continue;
+ fi;
+ exit_test;
+ _cpol_prog="$(eval set x ${_cpol_list}; shift; echo1 "$1")";
+
+ if is_not_equal "${_DISPLAY_PROG}" "${_cpol_prog}"
+ then
+ exit_test;
+ continue;
+ fi;
+ exit_test;
+### _check_prog_on_list() of main_set_mode()
+
+ # equal, prog found
+
+ _cpol_args="$(eval set x ${_cpol_list}; shift; echo1 "$2")";
+ eval ${_UNSET} _cpol_list;
+ if obj _cpol_args is_not_empty
+ then
+ if obj _DISPLAY_ARGS is_empty
+ then
+ _DISPLAY_ARGS="${_cpol_args}";
+ else
+ _DISPLAY_ARGS="${_cpol_args} ${_DISPLAY_ARGS}";
+ fi;
+ fi;
+
+ eval ${_UNSET} _cpol_i;
+ eval ${_UNSET} _cpol_args;
+ eval ${_UNSET} _cpol_prog;
+ eval "${return_good}";
+ done; # for vars in list
+
+ # prog was not in the list
+ eval ${_UNSET} _cpol_i;
+ eval ${_UNSET} _cpol_args;
+ eval ${_UNSET} _cpol_list;
+ eval ${_UNSET} _cpol_prog;
+ eval "${return_bad}";
+} # _check_prog_on_list() of main_set_mode()
+
+
+#######################################################################
+# main_do_fileargs ()
+#
+# Process filespec arguments.
+#
+# Globals:
+# in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
+#
+# Variable prefix: mdfa
+#
+main_do_fileargs()
+{
+ func_check main_do_fileargs = 0 "$@";
+ special_setup;
+ if obj _OPT_APROPOS is_yes
+ then
+ if obj _NO_FILESPECS is_yes
+ then
+ apropos_filespec;
+ eval "${return_ok}";
+ fi;
+ else
+ if list_has _FILEARGS '-'
+ then
+ save_stdin;
+ fi;
+ fi;
+ eval set x "${_FILEARGS}";
+ shift;
+ eval ${_UNSET} _FILEARGS;
+### main_do_fileargs()
+ while is_greater_than "$#" 0
+ do
+ mdfa_filespec="$1";
+ _FILESPEC_ARG="$1";
+ shift;
+ _FILESPEC_IS_MAN='no';
+ _TMP_MANSPEC='';
+ _SPECIAL_FILESPEC='no';
+
+ case "${mdfa_filespec}" in
+ '')
+ continue;
+ ;;
+ esac;
+
+ # check for file
+ case "${mdfa_filespec}" in
+ '-')
+ special_filespec;
+ if obj _OPT_APROPOS is_yes
+ then
+ continue;
+ fi;
+ register_file '-';
+ continue;
+ ;;
+### main_do_fileargs()
+ */*)
+ special_filespec;
+ if obj _OPT_APROPOS is_yes
+ then
+ continue;
+ fi;
+ if obj mdfa_filespec is_file
+ then
+ obj mdfa_filespec register_file;
+ else
+ echo2 "The argument ${mdfa_filespec} is not a file.";
+ fi;
+ continue;
+ ;;
+ *)
+ if obj _OPT_APROPOS is_yes
+ then
+ special_filespec;
+ continue;
+ fi;
+ # check whether filespec is an existing file
+ if obj _MAN_FORCE is_not_yes
+ then
+ if obj mdfa_filespec is_file
+ then
+ special_filespec;
+ obj mdfa_filespec register_file;
+ continue;
+ fi;
+ fi;
+ ;;
+ esac;
+### main_do_fileargs()
+
+ # now it must be a man page pattern
+
+ if obj _MACRO_PKG is_not_empty && obj _MACRO_PKG is_not_equal '-man'
+ then
+ echo2 "${mdfa_filespec} is not a file, man pages are ignored "\
+"due to ${_MACRO_PKG}.";
+ continue;
+ fi;
+
+ # check for man page
+ if obj _MAN_ENABLE is_not_yes
+ then
+ echo2 "The argument ${mdfa_filespec} is not a file.";
+ continue;
+ fi;
+ if obj _MAN_FORCE is_yes
+ then
+ mdfa_errmsg='is not a man page.';
+ else
+ mdfa_errmsg='is neither a file nor a man page.';
+ fi;
+### main_do_fileargs()
+ man_setup;
+ _FILESPEC_IS_MAN='yes';
+
+ # test filespec with `man:...' or `...(...)' on man page
+ mdfa_name='';
+ mdfa_section='';
+ mdfa_ext='';
+
+ mdfa_names="${mdfa_filespec}";
+ case "${mdfa_filespec}" in
+ man:*)
+ mdfa_names="${mdfa_names} "\
+"$(obj mdfa_filespec echo1 | sed 's/^man://')";
+ ;;
+ esac;
+
+ mdfa_continue='no';
+ for i in ${mdfa_names}
+ do
+ mdfa_i=$i;
+ if obj mdfa_i man_is_man
+ then
+ special_filespec;
+ obj mdfa_i man_get;
+ mdfa_continue='yes';
+ break;
+ fi;
+ case "${mdfa_i}" in
+ *\(${_MAN_AUTO_SEC_CHARS}*\))
+ mdfa_section="$(obj mdfa_i echo1 | sed 's/^[^(]*(\(.\).*)$/\1/')";
+ mdfa_name="$(obj mdfa_i echo1 | sed 's/^\([^(]*\)(.*)$/\1/')";
+ mdfa_ext="$(obj mdfa_i echo1 | sed 's/^[^(]*(.\(.*\))$/\1/')";
+ if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"
+ then
+ special_filespec;
+ man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}";
+ mdfa_continue='yes';
+ break;
+ fi;
+ ;;
+ *.${_MAN_AUTO_SEC_CHARS}*)
+ mdfa_name="$(obj mdfa_i echo1 | \
+ sed 's/^\(.*\)\.'"${_MAN_AUTO_SEC_CHARS}"'.*$/\1/')";
+ mdfa_section="$(obj mdfa_i echo1 | \
+ sed 's/^.*\.\('"${_MAN_AUTO_SEC_CHARS}"'\).*$/\1/')";
+ mdfa_ext="$(obj mdfa_i echo1 | \
+ sed 's/^.*\.'"${_MAN_AUTO_SEC_CHARS}"'\(.*\)$/\1/')";
+ if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"
+ then
+ special_filespec;
+ man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}";
+ mdfa_continue='yes';
+ break;
+ fi;
+ ;;
+ esac;
+ done;
+
+ if obj mdfa_continue is_yes
+ then
+ continue;
+ fi;
+
+### main_do_fileargs()
+ # check on "s name", where "s" is a section with or without an extension
+ if is_not_empty "$1"
+ then
+ mdfa_name="$1";
+ case "${mdfa_filespec}" in
+ ${_MAN_AUTO_SEC_CHARS})
+ mdfa_section="${mdfa_filespec}";
+ mdfa_ext='';
+ ;;
+ ${_MAN_AUTO_SEC_CHARS}*)
+ mdfa_section="$(echo1 "${mdfa_filespec}" | \
+ sed 's/^\(.\).*$/\1/')";
+ mdfa_ext="$(echo1 "${mdfa_filespec}" | \
+ sed 's/^.\(.*\)$/\1/')";
+ ;;
+ *)
+ echo2 "${mdfa_filespec} ${mdfa_errmsg}";
+ continue;
+ ;;
+ esac;
+ shift;
+ if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"
+ then
+ _FILESPEC_ARG="${mdfa_filespec} ${mdfa_name}";
+ special_filespec;
+ man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}";
+ continue;
+ else
+ echo2 "No man page for ${mdfa_name} with section ${mdfa_filespec}.";
+ continue;
+ fi;
+ fi;
+
+### main_do_fileargs()
+ echo2 "${mdfa_filespec} ${mdfa_errmsg}";
+ continue;
+ done;
+
+ obj _TMP_STDIN rm_file_with_debug;
+ eval ${_UNSET} mdfa_filespec;
+ eval ${_UNSET} mdfa_i;
+ eval ${_UNSET} mdfa_name;
+ eval ${_UNSET} mdfa_names;
+ 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
+ for f in ${_TMP_DIR}/,man*
+ do
+ rm_file_with_debug $f;
+ done;
+ obj_from_output msr_title \
+ get_first_essential "${_OPT_TITLE}" "${_REG_TITLE_LIST}";
+ _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 '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; # until $# is 0
+### main_set_resources()
+
+ 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;
+ obj_from_output msr_prog base_name "$1";
+ shift;
+ if is_greater_than $# 0
+ then
+ if obj _DISPLAY_ARGS is_empty
+ then
+ _DISPLAY_ARGS="$*";
+ else
+ _DISPLAY_ARGS="$* ${_DISPLAY_ARGS}";
+ fi;
+ fi;
+### main_set_resources()
+ 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;
+### main_set_resources()
+ 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;
+### main_set_resources()
+ 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 "${_DISPLAY_PROG}" in
+ *-z*)
+ :;
+ ;;
+ *) # if xpdf does not have option -z
+ case "${_DEFAULT_RESOLUTION}" in
+ 75)
+ # 72dpi is '100'
+ list_append msr_rl '-z' '104';
+ ;;
+ 100)
+ list_append msr_rl '-z' '139';
+ ;;
+ esac;
+ ;;
+ esac;
+ ;;
+ esac;
+ else
+ case "${msr_prog}" in
+ ghostview|gv|gxditview|xditview|xdvi)
+ list_append msr_rl '-resolution' "${_OPT_RESOLUTION}";
+ ;;
+ xpdf)
+ case "${_DISPLAY_PROG}" in
+ *-z*)
+ :;
+ ;;
+ *) # if xpdf does not have option -z
+ case "${_OPT_RESOLUTION}" in
+ 75)
+ list_append msr_rl '-z' '104';
+ # '100' corresponds to 72dpi
+ ;;
+### main_set_resources()
+ 100)
+ list_append msr_rl '-z' '139';
+ ;;
+ esac;
+ ;;
+ 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;
+### main_set_resources()
+ ;;
+ esac;
+ fi;
+ if is_not_empty "${msr_title}"
+ then
+ case "${msr_prog}" in
+ gxditview|xditview)
+ list_append msr_rl '-title' "${msr_title}";
+ ;;
+ esac;
+ fi;
+ if obj _DISPLAY_ARGS is_empty
+ then
+ _DISPLAY_ARGS="${msr_rl}";
+ else
+ _DISPLAY_ARGS="${msr_l} ${_DISPLAY_ARGS}";
+ fi;
+ 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,
+# $_TMP_CAT, $_OPT_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_empty_file
+ then
+ echo2 'groffer: empty input.';
+ clean_up;
+ eval "${return_ok}";
+ fi;
+
+ md_modefile="${_OUTPUT_FILE_NAME}";
+
+ # 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)
+ if obj _OPT_DEVICE is_not_empty
+ then
+ _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
+ fi;
+ md_groggy="$(tmp_cat | eval grog)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ exit_test;
+ _do_opt_V;
+
+### main_display()
+ 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
+ '')
+ obj_from_output md_device \
+ get_first_essential "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}";
+ ;;
+ ascii|cp1047|latin1|utf8)
+ md_device="${_OPT_DEVICE}";
+ ;;
+ *)
+ warning "main_display(): \
+wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
+ ;;
+ esac;
+ md_addopts="${_ADDOPTS_GROFF}";
+ md_groggy="$(tmp_cat | grog -T${md_device})";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ exit_test;
+ if obj _DISPLAY_MODE is_equal 'text'
+ then
+ _do_opt_V;
+ tmp_cat | eval "${md_groggy}" "${md_addopts}";
+ else # $_DISPLAY_MODE is 'tty'
+### main_display()
+ md_pager='';
+ for p in "${_OPT_PAGER}" "${_MANOPT_PAGER}" "${PAGER}"
+ do
+ if obj p is_empty
+ then
+ continue;
+ fi;
+ obj_from_output md_pager where_is_prog "$p";
+ if is_not_equal "$?" 0 || obj md_pager is_empty
+ then
+ md_pager='';
+ continue;
+ fi;
+ eval set x $md_pager;
+ shift;
+ case "$1" in
+ */less)
+ if is_empty "$2"
+ then
+ md_pager="$1"' -r -R';
+ else
+ md_pager="$1"' -r -R '"$2";
+ fi;
+ ;;
+### main_display()
+ *)
+ if is_empty "$2"
+ then
+ md_pager="$1";
+ else
+ md_pager="$1 $2";
+ fi;
+ ;;
+ esac;
+ break;
+ done;
+ if obj md_pager is_empty
+ then
+ eval set x ${_VIEWER_TTY_TTY} ${_VIEWER_TTY_X} 'cat';
+ shift;
+ # that is: 'less -r -R' 'more' 'pager' 'xless' 'cat'
+ for p
+ do
+ if obj p is_empty
+ then
+ continue;
+ fi;
+ md_p="$p";
+ if is_prog "${md_p}"
+ then
+ md_pager="${md_p}";
+ break;
+ fi;
+ done;
+ fi;
+### main_display()
+ 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; # $_DISPLAY_MODE
+ clean_up;
+ ;; # text|tty)
+ source)
+ tmp_cat;
+ clean_up;
+ ;;
+
+ #### viewer modes
+
+### main_display()
+ 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)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ 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)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ exit_test;
+ _do_display;
+ ;;
+### main_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)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ 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)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ exit_test;
+ _do_display;
+ ;;
+### main_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)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ exit_test;
+ _do_display;
+ ;;
+### main_display()
+ X)
+ case "${_OPT_DEVICE}" in
+ '')
+ md_groggy="$(tmp_cat | grog -X)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ exit_test;
+ ;;
+ X*|dvi|html|lbp|lj4|ps)
+ # these devices work with
+ md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ exit_test;
+ ;;
+ *)
+ warning "main_display(): \
+wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
+ md_groggy="$(tmp_cat | grog -Z)";
+ if is_not_equal "$?" 0
+ then
+ exit "${_ERROR}";
+ fi;
+ echo2 "grog output: ${md_groggy}";
+ 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_p;
+ eval ${_UNSET} md_pager;
+ eval "${return_ok}";
+} # main_display()
+
+
+########################
+# _do_display ([<prog>])
+#
+# 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 obj md_modefile is_empty_file
+ then
+ echo2 '_do_display(): empty output.';
+ clean_up;
+ exit;
+ fi;
+ if is_not_empty "$1"
+ then
+ eval "$1";
+ fi;
+### _do_display() of main_display()
+ obj _TMP_CAT rm_file_with_debug;
+ if obj _OPT_STDOUT is_yes
+ then
+ cat "${md_modefile}";
+ clean_up;
+ exit;
+ fi;
+ if obj _VIEWER_BACKGROUND is_not_yes # for programs that run on tty
+ then
+ eval "'${_DISPLAY_PROG}'" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
+ else
+ trap_unset;
+ {
+ trap_set;
+ eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
+ } &
+ 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 _make_pdf '=' 0 "$@";
+ _mp_psfile="${md_modefile}";
+ md_modefile="${md_modefile}.pdf";
+ obj md_modefile rm_file;
+ if obj _PDF_HAS_PS2PDF is_yes && ps2pdf "${_mp_psfile}" "${md_modefile}";
+ then
+ :;
+ elif obj _PDF_HAS_GS is_yes && gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
+ -sOutputFile="${md_modefile}" -c save pop -f "${_mp_psfile}";
+ then
+ :;
+ else
+ _PDF_DID_NOT_WORK='yes';
+ echo2 '_make_pdf(): Could not transform into pdf format. '\
+'The Postscript mode (ps) is used instead.';
+ _OPT_MODE='ps';
+ main_set_mode;
+ main_set_resources;
+ main_display;
+ exit;
+ fi;
+ obj _mp_psfile rm_file_with_debug;
+ eval ${_UNSET} _mp_psfile;
+ eval "${return_ok}";
+} # _make_pdf() of main_display()
+
+
+########################################################################
+# main (<command_line_args>*)
+#
+# 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 "$@";
diff --git a/contrib/groffer/shell/roff2.sh b/contrib/groffer/shell/roff2.sh
new file mode 100755
index 00000000..03db4896
--- /dev/null
+++ b/contrib/groffer/shell/roff2.sh
@@ -0,0 +1,339 @@
+#! /bin/sh
+
+# roff2* - transform roff files into other formats
+
+# Source file position: <groff-source>/contrib/groffer/shell/roff2.sh
+# Installed position: <prefix>/bin/roff2*
+
+# Copyright (C) 2006, 2009 Free Software Foundation, Inc.
+# Written by Bernd Warken <groff-bernd.warken-72@web.de>.
+
+# Last update: 5 Jan 2009
+
+# 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 3 of the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+########################################################################
+
+
+##############
+# echo1 (<text>*)
+#
+# Output to stdout with final line break.
+#
+# Arguments : arbitrary text including `-'.
+#
+echo1()
+{
+ cat <<EOF
+$@
+EOF
+} # echo1()
+
+
+##############
+# echo2 (<text>*)
+#
+# Output to stderr with final line break.
+#
+# Arguments : arbitrary text including `-'.
+#
+echo2()
+{
+ cat >&2 <<EOF
+$@
+EOF
+} # echo2()
+
+
+error_no_groffer='no';
+error_no_groffer() {
+ if test _"$error_no_groffer" = _yes
+ then
+ return;
+ fi;
+ error_no_groffer='yes';
+ echo2 "$name: groffer is not available.";
+}
+
+
+error_no_options='no';
+error_no_options() {
+ if test _"$error_no_options" = _yes
+ then
+ return;
+ fi;
+ error_no_groffer='yes';
+ echo2 "$name: groffer options are not allowed.";
+}
+
+
+usage_with_groffer() {
+ cat <<EOF
+usage: $Name [option]... [--] [filespec]...
+
+-h | --help print usage information
+-v | --version print version information
+
+All other options are arbitrary options of "groffer"; the options
+override the behavior of this program.
+
+"filespec"s are the same as in "groffer": either the names of
+existing, readable files or "-" for standard input or a search pattern
+for man pages. No "filespec" assumes standard input automatically.
+EOF
+}
+
+usage_without_groffer() {
+ cat <<EOF
+usage: $Name [option]... [--] [filespec]...
+
+-h | --help print usage information
+-v | --version print version information
+
+No other options are allowed because "groffer" is not available.
+
+The only "filespec"s allowed are the names of existing, readable files
+or "-" for standard input. No "filespec" assumes standard input
+automatically.
+EOF
+}
+
+
+where_is_prog() {
+ for p in `echo $PATH|sed "s/:/ /g"`
+ do
+ f="${p}/$1";
+ if test -f "$f" && test -x "$f"
+ then
+ echo1 "$f";
+ return;
+ fi;
+ done;
+}
+
+
+########################################################################
+
+export NULL_DEV;
+if test -c /dev/null
+then
+ NULL_DEV='/dev/null';
+else
+ NULL_DEV='NUL';
+fi;
+
+name="$(echo1 "$0" | sed 's|^.*//*\([^/]*\)$|\1|')";
+
+case "$name" in
+roff2[a-z]*)
+ mode="$(echo1 "$name" | sed 's/^roff2//')";
+ ;;
+*)
+ echo2 "wrong program name: $name";
+ exit 1;
+ ;;
+esac;
+
+groff_version="$(groff --version 2>$NULL_DEV)";
+if test $? -gt 0
+then
+ echo2 "$name error: groff does not work.";
+ exit 1;
+fi;
+groffer_version="$(groffer --version 2>$NULL_DEV)";
+if test $? -gt 0
+then
+ has_groffer='no';
+else
+ has_groffer='yes';
+fi;
+
+if test _"${has_groffer}" = _yes
+then
+ for i
+ do
+ case $i in
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo1 "$name in $groffer_version";
+ exit 0;
+ ;;
+ -h|--h|--he|--hel|--help)
+ usage_with_groffer;
+ exit 0;
+ ;;
+ esac;
+ done;
+ groffer --to-stdout --$mode "$@";
+else # not has_groffer
+ reset=no;
+ double_minus=no;
+ for i
+ do
+ if test _"${reset}" = _no
+ then
+ set --;
+ reset=yes;
+ fi;
+ if test _"${double_minus}" = _yes
+ then
+ set -- "$@" "$i";
+ continue;
+ fi;
+ case "$i" in
+ --)
+ double_minus=yes;
+ continue;
+ ;;
+ -)
+ set -- "$@" '-';
+ continue;
+ ;;
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo1 "$name in $groff_version";
+ exit 0;
+ ;;
+ -h|--h|--he|--hel|--help)
+ usage_without_groffer;
+ exit 0;
+ ;;
+ -*)
+ error_no_groffer;
+ error_no_options;
+ ;;
+ *)
+ if test -f "$i" && test -r "$i"
+ then
+ set -- "$@" "$i";
+ else
+ error_no_groffer;
+ echo2 "$i is not an existing, readable file.";
+ fi;
+ continue;
+ ;;
+ esac;
+ done; # for i
+
+ if test $# -eq 0
+ then
+ set -- '-';
+ fi;
+ has_stdin=no;
+ for i
+ do
+ case "$i" in
+ -)
+ has_stdin=yes;
+ break;
+ ;;
+ esac;
+ done;
+
+ if test _$has_stdin = _yes
+ then
+ umask 0077;
+ tempdir='';
+ for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
+ "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
+ do
+ if test _"$d" = _ || ! test -d "$d" || ! test -w "$d"
+ then
+ continue;
+ fi;
+ case "$d" in
+ */)
+ tempdir="$d";
+ ;;
+ *)
+ tempdir="$d"'/';
+ ;;
+ esac;
+ done;
+ if test _$tempdir = _
+ then
+ echo2 "${name}: could not find a temporary directory."
+ exit 1;
+ fi;
+ stdin=${tempdir}${name}_$$;
+ if test -e "$stdin"
+ then
+ rm -f "$stdin";
+ n=0;
+ f="${stdin}_$n";
+ while test -e "$f"
+ do
+ rm -f "$f";
+ if ! test -e "$f"
+ then
+ break;
+ fi;
+ n="$(expr $n + 1)";
+ f="${stdin}_$n";
+ done;
+ stdin="$f";
+ fi;
+ reset=no;
+ for i
+ do
+ if test _"${reset}" = _no
+ then
+ set --;
+ reset=yes;
+ fi;
+ case "$i" in
+ -)
+ set -- "$@" "$stdin";
+ ;;
+ *)
+ set -- "$@" "$i";
+ ;;
+ esac;
+ done;
+ cat>"$stdin";
+ fi; # if has_stdin
+
+ case "$mode" in
+ x)
+ groff_options='-TX75-12 -Z';
+ ;;
+ text)
+ groff_options='-Tlatin1';
+ ;;
+ pdf)
+ ps2pdf="$(where_is_prog ps2pdf)";
+ if test _"$ps2pdf" = _
+ then
+ ps2pdf="$(where_is_prog gs)";
+ if test _"$ps2pdf" = _
+ then
+ echo2 "$name: cannot transform to pdf format.";
+ exit 1;
+ fi;
+ ps2pdf="$ps2pdf -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite '-sOutputFile=- -c save pop -f -";
+ else
+ ps2pdf="$ps2pdf -";
+ fi;
+ grog="$(grog -Tps "$@")";
+ eval $grog | ${ps2pdf};
+ exit $?;
+ ;;
+ *)
+ groff_options="-T$mode";
+ ;;
+ esac;
+ grog="$(grog $groff_options "$@")";
+ eval $grog;
+ exit $?;
+fi; # not has_groffer