diff options
author | wl <wl> | 2013-08-11 08:28:23 +0000 |
---|---|---|
committer | wl <wl> | 2013-08-11 08:28:23 +0000 |
commit | 2e4ed555a4ce1fcb09d45c9b829de0480390fe67 (patch) | |
tree | 21ccbb826607eeaac8d8b3bc2b0bcd4457f39c96 | |
parent | 8375908f83748c8ed9a611f49da8e973f19badbc (diff) | |
download | groff-2e4ed555a4ce1fcb09d45c9b829de0480390fe67.tar.gz |
Revert accidental removal in previous commit.
-rw-r--r-- | contrib/groffer/shell/ChangeLog.0 | 2122 | ||||
-rw-r--r-- | contrib/groffer/shell/README_SH | 297 | ||||
-rw-r--r-- | contrib/groffer/shell/groffer.man | 4124 | ||||
-rwxr-xr-x | contrib/groffer/shell/groffer.sh | 384 | ||||
-rw-r--r-- | contrib/groffer/shell/groffer2.sh | 7312 | ||||
-rwxr-xr-x | contrib/groffer/shell/roff2.sh | 339 |
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 |