/[groff]/groff/contrib/groffer/groffer.sh
ViewVC logotype

Diff of /groff/contrib/groffer/groffer.sh

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.30 by wl, Thu Jul 7 20:03:13 2005 UTC revision 1.31 by wl, Sun Jul 31 07:53:15 2005 UTC
# Line 4  Line 4 
4    
5  # Source file position: <groff-source>/contrib/groffer/groffer.sh  # Source file position: <groff-source>/contrib/groffer/groffer.sh
6    
7  # Copyright (C) 2001,2002,2003,2004,2005 Free Software Foundation,  # Copyright (C) 2001,2002,2003,2004,2005
8  # Inc.  # Free Software Foundation, Inc.
9  # Written by Bernd Warken  # Written by Bernd Warken
10    
11  # This file is part of groff version @VERSION@ (eventually 1.19.2).  # This file is part of groff version @VERSION@ (eventually 1.19.2).
# Line 26  Line 26 
26  # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.  # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
27    
28  _PROGRAM_NAME='groffer';  _PROGRAM_NAME='groffer';
29  _PROGRAM_VERSION='0.9.19';  _PROGRAM_VERSION='0.9.20';
30  _LAST_UPDATE='7 July 2005';  _LAST_UPDATE='30 July 2005';
31    
32    
33  ########################################################################  ########################################################################
# Line 174  EOF Line 174  EOF
174      eval ${_UNSET} _all;      eval ${_UNSET} _all;
175    fi;    fi;
176    
177      export _GROFFER2_SH;            # file name of the script that follows up
178      _GROFFER2_SH='@libdir@/groff/groffer/groffer2.sh';
179    
180    # restart the script with the last found $_shell, if it is a shell    # restart the script with the last found $_shell, if it is a shell
181    if _test_on_shell "${_shell}";    if _test_on_shell "${_shell}";
182    then    then
183      _GROFFER_RUN='second';      _GROFFER_RUN='second';
184      # do not quote $_shell to allow arguments      # do not quote $_shell to allow arguments
185      eval exec ${_shell} "'${_GROFFER_SH}'" '"$@"';      eval exec ${_shell} "'${_GROFFER2_SH}'" '"$@"';
186      exit;      exit;
187    fi;    fi;
188    
189    _GROFFER_RUN='second';    _GROFFER_RUN='second';
190    eval ${_UNSET} _shell;    eval ${_UNSET} _shell;
191      eval exec "'${_GROFFER2_SH}'" '"$@"';
192    
193  fi; # end of first run  fi; # end of first run
194    
# Line 195  then Line 199  then
199  fi;  fi;
200    
201  eval ${_UNSET} _GROFFER_RUN  eval ${_UNSET} _GROFFER_RUN
   
   
 ########################################################################  
 # diagnostic messages  
 #  
 export _DEBUG;  
 _DEBUG='no';                    # disable debugging information  
 #_DEBUG='yes';                  # enable debugging information  
   
 export _DEBUG_LM;  
 _DEBUG_LM='no';                 # disable landmark messages  
 #_DEBUG_LM='yes';               # enable landmark messages  
   
 export _DEBUG_KEEP_FILES;  
 _DEBUG_KEEP_FILES='no'          # disable file keeping in temporary dir  
 _DEBUG_KEEP_FILES='yes'         # enable file keeping in temporary dir  
   
 # test of $* on --debug  
 case " $* " in  
 *' --debug '*)  
   _DEBUG='yes';  
   _DEBUG_LM='yes';  
   _DEBUG_KEEP_FILES='yes';  
   ;;  
 esac;  
   
   
 ########################################################################  
 #                       Environment Variables  
 ########################################################################  
   
 # Environment variables that exist only for this file start with an  
 # underscore letter.  Global variables to this file are written in  
 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables  
 # start with an underline and use only lower case letters and  
 # underlines, e.g.  $_local_variable .  
   
 #   [A-Z]*     system variables,      e.g. $MANPATH  
 #   _[A-Z_]*   global file variables, e.g. $_MAN_PATH  
 #   _[a-z_]*   temporary variables,   e.g. $_manpath  
   
 # Due to incompatibilities of the `ash' shell, the name of loop  
 # variables in `for' must be single character  
 #   [a-z]      local loop variables,   e.g. $i  
   
   
 ########################################################################  
 # read-only variables (global to this file)  
 ########################################################################  
   
 # characters  
   
 export _SPACE;  
 export _SQUOTE;  
 export _TAB;  
   
 _SPACE=' ';  
 _SQUOTE="'";  
 _TAB='  ';  
   
 # function return values; `0' means ok; other values are error codes  
 export _ALL_EXIT;  
 export _BAD;  
 export _ERROR;  
 export _GOOD;  
 export _NO;  
 export _OK;  
 export _YES;  
   
 _GOOD='0';                      # return ok  
 _BAD='1';                       # return negatively, error code `1'  
 _ERROR='7';                     # for syntax errors; no `-1' in `ash'  
   
 _ALL_EXIT="${_GOOD} ${_BAD} ${_ERROR}"; # all exit codes (for `trap_set')  
   
 _NO="${_BAD}";  
 _YES="${_GOOD}";  
 _OK="${_GOOD}";  
   
 # quasi-functions, call with `eval', e.g `eval "${return_ok}"'  
 export return_ok;  
 export return_good;  
 export return_bad;  
 export return_yes;  
 export return_no;  
 export return_error;  
 export return_var;  
 return_ok="func_pop; return ${_OK}";  
 return_good="func_pop; return ${_GOOD}";  
 return_bad="func_pop; return ${_BAD}";  
 return_yes="func_pop; return ${_YES}";  
 return_no="func_pop; return ${_NO}";  
 return_error="func_pop; return ${_ERROR}";  
 return_var="func_pop; return";  # add number, e.g. `eval "${return_var} $n'  
   
   
 export _DEFAULT_MODES;  
 _DEFAULT_MODES='x,ps,tty';  
 export _DEFAULT_RESOLUTION;  
 _DEFAULT_RESOLUTION='75';  
   
 export _DEFAULT_TTY_DEVICE;  
 _DEFAULT_TTY_DEVICE='latin1';  
   
 # _VIEWER_* viewer programs for different modes (only X is necessary)  
 # _VIEWER_* a comma-separated list of viewer programs (with options)  
 export _VIEWER_DVI;             # viewer program for dvi mode  
 export _VIEWER_PS;              # viewer program for ps mode  
 export _VIEWER_HTML_X;          # viewer program for html mode in X  
 export _VIEWER_HTML_TTY;        # viewer program for html mode in tty  
 _VIEWER_DVI='kdvi,xdvi,dvilx';  
 _VIEWER_PDF='kghostview,ggv,xpdf,acroread,kpdf';  
 _VIEWER_PS='kghostview,ggv,gv,ghostview,gs_x11,gs';  
 _VIEWER_HTML='konqueror,mozilla,netscape,opera,amaya,arena,lynx';  
 _VIEWER_X='gxditview,xditview';  
   
 # Search automatically in standard sections `1' to `8', and in the  
 # traditional sections `9', `n', and `o'.  On many systems, there  
 # exist even more sections, mostly containing a set of man pages  
 # special to a specific program package.  These aren't searched for  
 # automatically, but must be specified on the command line.  
 export _MAN_AUTO_SEC;  
 _MAN_AUTO_SEC="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'"  
   
 export _PROCESS_ID;             # for shutting down the program  
 _PROCESS_ID="$$";  
   
   
 ############ the command line options of the involved programs  
 #  
 # The naming scheme for the options environment names is  
 # $_OPTS_<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' 'debug' 'default' 'dvi' \  
 'groff' 'help' 'intermediate-output' 'html' 'man' \  
 'no-location' 'no-man' 'pdf' 'ps' 'rv' 'source' 'text' 'text-device' \  
 'title' 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";  
   
 _OPTS_GROFFER_LONG_ARG="\  
 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \  
 'default-modes' 'device' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \  
 'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \  
 'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'";  
   
 ##### groffer options inhereted from groff  
   
 _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \  
 'R' 's' 'S' 't' 'U' 'z'";  
 _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \  
 'w' 'W'";  
 _OPTS_GROFF_LONG_NA="";  
 _OPTS_GROFF_LONG_ARG="";  
   
 ##### groffer options inhereted from the X Window toolkit  
   
 _OPTS_X_SHORT_NA="";  
 _OPTS_X_SHORT_ARG="";  
   
 _OPTS_X_LONG_NA="'iconic' 'rv'";  
   
 _OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \  
 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft', 'geometry'  
 'resolution' 'title' 'xrm'";  
   
 ###### groffer options inherited from man  
   
 _OPTS_MAN_SHORT_NA="";  
 _OPTS_MAN_SHORT_ARG="";  
   
 _OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'debug' 'ditroff' 'help' \  
 'local-file' 'location' 'pager' 'troff' 'update' 'version' \  
 'whatis' 'where'";  
   
 _OPTS_MAN_LONG_ARG="'extension' 'locale' 'manpath' \  
 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";  
   
 ###### additional options for parsing $MANOPT only  
   
 _OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \  
 'V' 'w' 'Z'";  
 _OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";  
   
 _OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \  
 'apropos' 'debug' 'default' 'html' 'ignore-case' 'location-cat' \  
 'match-case' 'troff' 'update' 'version' 'where-cat'";  
   
 _OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \  
 'config_file' 'encoding' 'locale'";  
   
 ###### collections of command line options  
   
 _OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA}\  
 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";  
 _OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \  
 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";  
   
 _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \  
 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";  
 _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \  
 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";  
   
   
 ########################################################################  
 # read-write variables (global to this file)  
 ########################################################################  
   
 export _ADDOPTS_GROFF;          # Transp. options for groff (`eval').  
 export _ADDOPTS_POST;           # Transp. options postproc (`eval').  
 export _ADDOPTS_X;              # Transp. options X postproc (`eval').  
 export _DEFAULT_MODES;          # Set default modes.  
 export _DISPLAY_MODE;           # Display mode.  
 export _DISPLAY_PROG;           # Viewer program to be used for display.  
 export _DISPLAY_ARGS;           # X resources for the viewer program.  
 export _FILEARGS;               # Stores filespec parameters.  
 export _FUNC_STACK;             # Store debugging information.  
 export _REGISTERED_TITLE;       # Processed file names.  
 # _HAS_* from availability tests  
 export _HAS_COMPRESSION;        # `yes' if gzip compression is available  
 export _HAS_BZIP;               # `yes' if bzip2 compression is available  
 # _MAN_* finally used configuration of man searching  
 export _MAN_ALL;                # search all man pages per filespec  
 export _MAN_ENABLE;             # enable search for man pages  
 export _MAN_EXT;                # extension for man pages  
 export _MAN_FORCE;              # force file parameter to be man pages  
 export _MAN_IS_SETUP;           # setup man variables only once  
 export _MAN_LANG;               # language for man pages  
 export _MAN_LANG2;              # language for man pages  
 export _MAN_LANG_DONE;          # language dirs added to man path  
 export _MAN_PATH;               # search path for man pages  
 export _MAN_SEC;                # sections for man pages; sep. `:'  
 export _MAN_SEC_DONE;           # sections added to man path  
 export _MAN_SYS;                # system names for man pages; sep. `,'  
 export _MAN_SYS;                # system names added to man path  
 # _MANOPT_* as parsed from $MANOPT  
 export _MANOPT_ALL;             # $MANOPT --all  
 export _MANOPT_EXTENSION;       # $MANOPT --extension  
 export _MANOPT_LANG;            # $MANOPT --locale  
 export _MANOPT_PATH;            # $MANOPT --manpath  
 export _MANOPT_PAGER;           # $MANOPT --pager  
 export _MANOPT_SEC;             # $MANOPT --sections  
 export _MANOPT_SYS;             # $MANOPT --systems  
 # _OPT_* as parsed from groffer command line  
 export _OPT_ALL;                # display all suitable man pages.  
 export _OPT_APROPOS;            # call `apropos' program.  
 export _OPT_APROPOS_DATA;       # `apropos' for man sections 4, 5, 7  
 export _OPT_APROPOS_DEVEL;      # `apropos' for man sections 2, 3, 9  
 export _OPT_APROPOS_PROGS;      # `apropos' for man sections 1, 6, 8  
 export _OPT_BD;                 # set border color in some modes.  
 export _OPT_BG;                 # set background color in some modes.  
 export _OPT_BW;                 # set border width in some modes.  
 export _OPT_DEBUG;              # print debugging information on stderr.  
 export _OPT_DEFAULT_MODES;      # `,'-list of modes when no mode given.  
 export _OPT_DEVICE;             # device option.  
 export _OPT_DISPLAY;            # set X display.  
 export _OPT_FG;                 # set foreground color in some modes.  
 export _OPT_FN;                 # set font in some modes.  
 export _OPT_GEOMETRY;           # set size and position of viewer in X.  
 export _OPT_ICONIC;             # -iconic option for X viewers.  
 export _OPT_LANG;               # set language for man pages  
 export _OPT_LOCATION;           # print processed file names to stderr  
 export _OPT_MODE;               # values: X, tty, Q, Z, ""  
 export _OPT_MANPATH;            # manual setting of path for man-pages  
 export _OPT_PAGER;              # specify paging program for tty mode  
 export _OPT_RESOLUTION;         # set X resolution in dpi  
 export _OPT_RV;                 # reverse fore- and background colors.  
 export _OPT_SECTIONS;           # sections for man page search  
 export _OPT_SYSTEMS;            # man pages of different OS's  
 export _OPT_TITLE;              # title for gxditview window  
 export _OPT_TEXT_DEVICE;        # set device for tty mode.  
 export _OPT_V;                  # groff option -V.  
 export _OPT_VIEWER_DVI;         # viewer program for dvi mode  
 export _OPT_VIEWER_PDF;         # viewer program for pdf mode  
 export _OPT_VIEWER_PS;          # viewer program for ps mode  
 export _OPT_VIEWER_HTML;        # viewer program for html mode  
 export _OPT_VIEWER_X;           # viewer program for x mode  
 export _OPT_WHATIS;             # print the one-liner man info  
 export _OPT_XRM;                # specify X resource.  
 export _OPT_Z;                  # groff option -Z.  
 # _TMP_* temporary files  
 export _TMP_DIR;                # groffer directory for temporary files  
 export _TMP_CAT;                # stores concatenation of everything  
 export _TMP_STDIN;              # stores stdin, if any  
   
 # these variables are preset in section `Preset' after the rudim. test  
   
   
 ########################################################################  
 #             Test of rudimentary shell functionality  
 ########################################################################  
   
   
 ########################################################################  
 # Test of `test'.  
 #  
 test "a" = "a" || exit 1;  
   
   
 ########################################################################  
 # Test of `echo' and the `$()' construct.  
 #  
 echo '' >${_NULL_DEV} || exit "${_ERROR}";  
 if test _"$(t1="$(echo te)" &&  
             t2="$(echo '')" &&  
             t3="$(echo 'st')" &&  
             echo "${t1}${t2}${t3}")"_ \  
      != _test_;  
 then  
   exit "${_ERROR}";  
 fi;  
   
   
 ########################################################################  
 # Test of function definitions.  
 #  
 _t_e_s_t_f_u_n_c_()  
 {  
   return "${_OK}";  
 }  
   
 if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV};  
 then  
   :  
 else  
   echo 'shell does not support function definitions.' >&2;  
   exit "${_ERROR}";  
 fi;  
   
   
 ########################################################################  
 # Preset and reset of read-write global variables  
 ########################################################################  
   
   
 # For variables that can be reset by option `--default', see reset().  
   
 _FILEARGS='';  
   
 # _HAS_* from availability tests  
 _HAS_COMPRESSION='';  
 _HAS_BZIP='';  
   
 # _TMP_* temporary files  
 _TMP_DIR='';  
 _TMP_CAT='';  
 _TMP_STDIN='';  
   
   
 ########################################################################  
 # reset ()  
 #  
 # Reset the variables that can be affected by options to their default.  
 #  
 reset()  
 {  
   if test "$#" -ne 0;  
   then  
     error "reset() does not have arguments.";  
   fi;  
   
   _ADDOPTS_GROFF='';  
   _ADDOPTS_POST='';  
   _ADDOPTS_X='';  
   _DISPLAY_ARGS='';  
   _DISPLAY_MODE='';  
   _DISPLAY_PROG='';  
   _REGISTERED_TITLE='';  
   
   # _MAN_* finally used configuration of man searching  
   _MAN_ALL='no';  
   _MAN_ENABLE='yes';            # do search for man-pages  
   _MAN_EXT='';  
   _MAN_FORCE='no';              # first local file, then search man page  
   _MAN_IS_SETUP='no';  
   _MAN_LANG='';  
   _MAN_LANG2='';  
   _MAN_PATH='';  
   _MAN_SEC='';  
   _MAN_SEC_DONE='no';  
   _MAN_SYS='';  
   _MAN_SYS_DONE='no';  
   
   # _MANOPT_* as parsed from $MANOPT  
   _MANOPT_ALL='no';  
   _MANOPT_EXTENSION='';  
   _MANOPT_LANG='';  
   _MANOPT_PATH='';  
   _MANOPT_PAGER='';  
   _MANOPT_SEC='';  
   _MANOPT_SYS='';  
   
   # _OPT_* as parsed from groffer command line  
   _OPT_ALL='no';  
   _OPT_APROPOS='';  
   _OPT_APROPOS_DATA='';  
   _OPT_APROPOS_DEVEL='';  
   _OPT_APROPOS_PROGS='';  
   _OPT_BD='';  
   _OPT_BG='';  
   _OPT_BW='';  
   _OPT_DEBUG='no';  
   _OPT_DEFAULT_MODES='';  
   _OPT_DEVICE='';  
   _OPT_DISPLAY='';  
   _OPT_FG='';  
   _OPT_FN='';  
   _OPT_GEOMETRY='';  
   _OPT_ICONIC='no';  
   _OPT_LANG='';  
   _OPT_LOCATION='no';  
   _OPT_MODE='';  
   _OPT_MANPATH='';  
   _OPT_PAGER='';  
   _OPT_RESOLUTION='';  
   _OPT_RV='no';  
   _OPT_SECTIONS='';  
   _OPT_SYSTEMS='';  
   _OPT_TITLE='';  
   _OPT_TEXT_DEVICE='';  
   _OPT_V='no';  
   _OPT_VIEWER_DVI='';  
   _OPT_VIEWER_PDF='';  
   _OPT_VIEWER_PS='';  
   _OPT_VIEWER_HTML='';  
   _OPT_VIEWER_X='';  
   _OPT_WHATIS='no';  
   _OPT_XRM='';  
   _OPT_Z='no';  
   
 }  
   
 reset;  
   
   
 ########################################################################  
 #          Functions for error handling and debugging  
 ########################################################################  
   
   
 ##############  
 # echo2 (<text>*)  
 #  
 # Output to stderr.  
 #  
 # Arguments : arbitrary text.  
 #  
 echo2()  
 {  
   cat >&2 <<EOF  
 $*  
 EOF  
 }  
   
   
 ##############  
 # landmark (<text>)  
 #  
 # Print <text> to standard error as a debugging aid.  
 #  
 # Globals: $_DEBUG_LM  
 #  
 landmark()  
 {  
   if test _"${_DEBUG_LM}"_ = _yes_;  
   then  
     echo2 "LM: $*" >&2;  
   fi;  
 }  
   
 landmark "1: debugging functions";  
   
   
 ##############  
 # clean_up ()  
 #  
 # Clean up at exit.  
 #  
 clean_up()  
 {  
   if test -d "${_TMP_DIR}";  
   then  
     eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;  
   fi;  
 }  
   
   
 #############  
 # diag (text>*)  
 #  
 # Output a diagnostic message to stderr  
 #  
 diag()  
 {  
   echo2 '>>>>>'"$*";  
 }  
   
   
 #############  
 # error (<text>*)  
 #  
 # Print an error message to standard error; exit with an error condition  
 #  
 # Variable prefix: err  
 #  
 error()  
 {  
   err_code="${_ERROR}";  
   case "$#" in  
     0) :; ;;  
     1) echo2 'groffer error: '"$1"; ;;  
     2)  
       echo2 'groffer error: '"$1";  
       err_code="$2";  
       ;;  
     *) echo2 'groffer error: wrong number of arguments in error().'; ;;  
   esac;  
   func_stack_dump;  
   clean_up;  
   kill "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;  
   kill -9 "${_PROCESS_ID}" >${_NULL_DEV} 2>&1;  
   n="${err_code}";  
   eval ${_UNSET} err_code;  
   exit "$n";  
 }  
   
   
 #############  
 # abort (<text>*)  
 #  
 # Terminate program with error condition  
 #  
 abort()  
 {  
   error "abort(): Program aborted.";  
   exit 1;  
 }  
   
   
 #############  
 # func_check (<func_name> <rel_op> <nr_args> "$@")  
 #  
 # Check number of arguments and register 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;  
   case "$2" in  
     '='|'-eq')  
       fc_op='-eq';  
       fc_comp='exactly';  
       ;;  
     '>='|'-ge')  
       fc_op='-ge';  
       fc_comp='at least';  
       ;;  
     '<='|'-le')  
       fc_op='-le';  
       fc_comp='at most';  
       ;;  
     '<'|'-lt')  
       fc_op='-lt';  
       fc_comp='less than';  
       ;;  
     '>'|'-gt')  
       fc_op='-gt';  
       fc_comp='more than';  
       ;;  
     '!='|'-ne')  
       fc_op='-ne';  
       fc_comp='not';  
       ;;  
     *)  
       error \  
         'func_check(): second argument is not a relational operator.';  
       ;;  
   esac;  
   shift;  
   shift;  
   shift;  
   if test "$#" "${fc_op}" "${fc_nargs}";  
   then  
     do_nothing;  
   else  
     error "func_check(): \  
 ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';  
   fi;  
   func_push "${fc_fname}";  
   if test _"${_DEBUG}"_ = _yes_;  
   then  
     echo2 '+++ '"${fc_fname} $@";  
     echo2 '>>> '"${_FUNC_STACK}";  
   fi;  
   eval ${_UNSET} fc_comp;  
   eval ${_UNSET} fc_fname;  
   eval ${_UNSET} fc_nargs;  
   eval ${_UNSET} fc_op;  
   eval ${_UNSET} fc_s;  
 }  
   
   
 #############  
 # func_pop ()  
 #  
 # Retrieve the top element from the stack.  
 #  
 # The stack elements are separated by `!'; the popped element is  
 # identical to the original element, except that all `!' characters  
 # were removed.  
 #  
 # Arguments: 1  
 #  
 func_pop()  
 {  
   if test "$#" -ne 0;  
   then  
     error 'func_pop() does not have arguments.';  
   fi;  
   case "${_FUNC_STACK}" in  
   '')  
     if test _"${_DEBUG}"_ = _yes_;  
     then  
       error 'func_pop(): stack is empty.';  
     fi;  
     ;;  
   *!*)  
     # split at first bang `!'.  
    _FUNC_STACK="$(echo x"${_FUNC_STACK}" | sed -e '  
 s/^x//  
 s/^[^!]*!//  
 ')";  
     ;;  
   *)  
     _FUNC_STACK='';  
     ;;  
   esac;  
   if test _"${_DEBUG}"_ = _yes_;  
   then  
     echo2 '<<< '"${_FUNC_STACK}";  
   fi;  
 }  
   
   
 #############  
 # func_push (<element>)  
 #  
 # Store another element to stack.  
 #  
 # 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="$(echo x"$1" | sed -e '  
 s/^x//  
 s/!//g  
 ')";  
     ;;  
   *)  
     fp_element="$1";  
     ;;  
   esac;  
   if test _"${_FUNC_STACK}"_ = __;  
   then  
     _FUNC_STACK="${fp_element}";  
   else  
     _FUNC_STACK="${fp_element}!${_FUNC_STACK}";  
   fi;  
   eval ${_UNSET} fp_element;  
 }  
   
   
 #############  
 # func_stack_dump ()  
 #  
 # Print the content of the stack.  Ignore the arguments.  
 #  
 func_stack_dump()  
 {  
   diag 'call stack: '"${_FUNC_STACK}";  
 }  
   
   
 ########################################################################  
 #                        System Test  
 ########################################################################  
   
 landmark "2: system test";  
   
 # Test the availability of the system utilities used in this script.  
   
   
 ########################################################################  
 # Test of function `sed'.  
 #  
   
 if test _"$(echo xTesTx \  
            | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \  
            | sed -e 's|T|t|g')"_ != _test_;  
 then  
   error 'Test of "sed" command failed.';  
 fi;  
   
   
 ########################################################################  
 # Test of function `cat'.  
 #  
 if test _"$(echo test | cat)"_ != _test_;  
 then  
   error 'Test of "cat" command failed.';  
 fi;  
   
   
 ########################################################################  
 # Test for compression.  
 #  
 if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_;  
 then  
   _HAS_COMPRESSION='yes';  
   if 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;  
   
   
 ########################################################################  
 #       Definition of normal Functions in alphabetical order  
 ########################################################################  
 landmark "3: functions";  
   
 ########################################################################  
 # abort (<text>*)  
 #  
 # Unconditionally terminate the program with error code;  
 # useful for debugging.  
 #  
 # defined above  
   
   
 ########################################################################  
 # apropos_run (<name>)  
 #  
 #  
 apropos_run() {  
   func_check apropos_run = 1 "$@";  
   if apropos apropos >${_NULL_DEV} 2>${_NULL_DEV};  
   then  
     apropos "$1";  
   elif man --apropos man >${_NULL_DEV} 2>${_NULL_DEV};  
   then  
     man --apropos "$1";  
   elif man -k man >${_NULL_DEV} 2>${_NULL_DEV};  
   then  
     man -k "$1";  
   fi;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # 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.  
 #  
 # 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="$(echo x"${bn_name}" | sed -e '  
 s/^x//  
 s|//*$||  
 ')";  
       ;;  
   esac;  
   case "${bn_name}" in  
     /|'')  
       eval ${_UNSET} bn_name;  
       eval "${return_bad}";  
       ;;  
     */*)  
       # delete everything before and including the last slash `/'.  
       echo x"${bn_name}" | sed -e '  
 s/^x//  
 s|^.*//*\([^/]*\)$|\1|  
 ';  
       ;;  
     *)  
       cat <<EOF  
 ${bn_name}  
 EOF  
       ;;  
   esac;  
   eval ${_UNSET} bn_name;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # 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.  
 #  
 if test _"${_HAS_COMPRESSION}"_ = _yes_;  
 then  
   cat_z()  
   {  
     func_check cat_z = 1 "$@";  
     case "$1" in  
       '')  
         error 'cat_z(): empty file name';  
         ;;  
       '-')  
         error 'cat_z(): for standard input use save_stdin()';  
         ;;  
     esac;  
     if obj _HAS_BZIP is_yes;  
     then  
       if bzip2 -t "$1" 2>${_NULL_DEV};  
       then  
         bzip2 -c -d "$1" 2>${_NULL_DEV};  
         eval "${return_ok}";  
       fi;  
     fi;  
     gzip -c -d -f "$1" 2>${_NULL_DEV};  
     eval "${return_ok}";  
   }  
 else  
   cat_z()  
   {  
     func_check cat_z = 1 "$@";  
     cat "$1";  
     eval "${return_ok}";  
   }  
 fi;  
   
   
 ########################################################################  
 # clean_up ()  
 #  
 # Do the final cleaning up before exiting; used by the trap calls.  
 #  
 # defined above  
   
   
 ########################################################################  
 # diag (<text>*)  
 #  
 # Print marked message to standard error; useful for debugging.  
 #  
 # defined above  
   
   
 ########################################################################  
 landmark '4: dirname()*';  
 ########################################################################  
   
 #######################################################################  
 # dirname_append (<dir> <name>)  
 #  
 # Append `name' to `dir' with clean handling of `/'.  
 #  
 # Arguments : 2  
 # Output    : the generated new directory name <dir>/<name>  
 #  
 dirname_append()  
 {  
   func_check dirname_append = 2 "$@";  
   if is_empty "$1";  
   then  
     error "dir_append(): first argument is empty.";  
   fi;  
   if is_empty "$2";  
   then  
     cat <<EOF  
 $1  
 EOF  
   else  
     dirname_chop "$1"/"$2";  
   fi;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # dirname_chop (<name>)  
 #  
 # Remove unnecessary slashes from directory name.  
 #  
 # Argument: 1, a directory name.  
 # Output:   path without double, or trailing slashes.  
 #  
 # Variable prefix: dc  
 #  
 dirname_chop()  
 {  
   func_check dirname_chop = 1 "$@";  
   # replace all multiple slashes by a single slash `/'.  
   dc_res="$(echo x"$1" | sed -e '  
 s/^x//  
 s|///*|/|g  
 ')";  
   case "${dc_res}" in  
     ?*/)  
       # remove trailing slash '/';  
       echo x"${dc_res}" | sed -e '  
 s/^x//  
 s|/$||  
 ';  
       ;;  
     *) cat <<EOF  
 ${dc_res}  
 EOF  
   ;;  
   esac;  
   eval ${_UNSET} dc_res;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # do_filearg (<filearg>)  
 #  
 # Append the file, man-page, or standard input corresponding to the  
 # argument to the temporary file.  If this is compressed in the gzip  
 # or Z format it is decompressed.  A title element is generated.  
 #  
 # Argument either:  
 #   - name of an existing files.  
 #   - `-' to represent standard input (several times allowed).  
 #   - `man:name.(section)' the man-page for `name' in `section'.  
 #   - `man:name.section' the man-page for `name' in `section'.  
 #   - `man:name' the man-page for `name' in the lowest `section'.  
 #   - `name.section' the man-page for `name' in `section'.  
 #   - `name' the man-page for `name' in the lowest `section'.  
 # Globals :  
 #   $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN  
 #  
 # Output  : none  
 # Return  : $_GOOD if found, ${_BAD} otherwise.  
 #  
 # Variable prefix: df  
 #  
 do_filearg()  
 {  
   func_check do_filearg = 1 "$@";  
   df_filespec="$1";  
   # store sequence into positional parameters  
   case "${df_filespec}" in  
     '')  
        eval ${_UNSET} df_filespec;  
        eval "${return_good}";  
        ;;  
     '-')  
       register_file '-';  
       eval ${_UNSET} df_filespec;  
       eval "${return_good}";  
       ;;  
     */*)                        # with directory part; so no man search  
       set 'File';  
       ;;  
     *)  
       if obj _MAN_ENABLE is_yes;  
       then  
         if obj _MAN_FORCE is_yes;  
         then  
           set 'Manpage' 'File';  
         else  
           set 'File' 'Manpage';  
         fi;  
       else  
         set 'File';  
       fi;  
       ;;  
   esac;  
   for i  
   do  
     case "$i" in  
       File)  
         if test -f "${df_filespec}";  
         then  
           if test -r "${df_filespec}";  
           then  
             register_file "${df_filespec}";  
             eval ${_UNSET} df_filespec;  
             eval "${return_good}";  
           else  
             echo2 "could not read \`${df_filespec}'";  
             eval ${_UNSET} df_filespec;  
             eval "${return_bad}";  
           fi;  
         else  
           continue;  
         fi;  
         ;;  
       Manpage)                  # parse filespec as man page  
         if obj _MAN_IS_SETUP is_not_yes;  
         then  
           man_setup;  
         fi;  
         if man_do_filespec "${df_filespec}";  
         then  
           eval ${_UNSET} df_filespec;  
           eval "${return_good}";  
         else  
           continue;  
         fi;  
         ;;  
     esac;  
   done;  
   eval ${_UNSET} df_filespec;  
   eval "${return_bad}";  
 } # do_filearg()  
   
   
 ########################################################################  
 # do_nothing ()  
 #  
 # Dummy function.  
 #  
 do_nothing()  
 {  
   eval return "${_OK}";  
 }  
   
   
 ########################################################################  
 # echo2 (<text>*)  
 #  
 # Print to standard error with final line break.  
 #  
 # defined above  
   
   
 ########################################################################  
 # error (<text>*)  
 #  
 # Print error message and exit with error code.  
 #  
 # defined above  
   
   
 ########################################################################  
 # func_check (<func_name> <rel_op> <nr_args> "$@")  
 #  
 # Check number of arguments and register 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.  
 #  
 # defined above  
   
 #########################################################################  
 # func_pop ()  
 #  
 # Delete the top element from the function call stack.  
 #  
 # defined above  
   
   
 ########################################################################  
 # func_push (<element>)  
 #  
 # Store another element to function call stack.  
 #  
 # defined above  
   
   
 ########################################################################  
 # func_stack_dump ()  
 #  
 # Print the content of the stack.  
 #  
 # defined above  
   
   
 ########################################################################  
 # 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  
       cat <<EOF  
 ${gfe_var}  
 EOF  
       eval ${_UNSET} gfe_var;  
       eval "${return_ok}";  
     fi;  
   done;  
   eval ${_UNSET} gfe_var;  
   eval "${return_bad}";  
 }  
   
   
 ########################################################################  
 landmark '5: is_*()';  
 ########################################################################  
   
 ########################################################################  
 # is_dir (<name>)  
 #  
 # Test whether `name' is a directory.  
 #  
 # Arguments : 1  
 # Return    : `0' if arg1 is a directory, `1' otherwise.  
 #  
 is_dir()  
 {  
   func_check is_dir = 1 "$@";  
   if test -d "$1" && test -r "$1";  
   then  
     eval "${return_yes}";  
   fi;  
   eval "${return_no}";  
 }  
   
   
 ########################################################################  
 # is_empty (<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_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_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 test -f "$1" || test -d "$1";  
   then  
     eval "${return_yes}";  
   fi;  
   eval "${return_no}";  
 }  
   
   
 ########################################################################  
 # 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 test -f "$1" && test -r "$1";  
   then  
     eval "${return_yes}";  
   fi;  
   eval "${return_no}";  
 }  
   
   
 ########################################################################  
 # is_non_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_non_empty_file()  
 {  
   func_check is_non_empty_file = 1 "$@";  
   if is_file "$1" && test -s "$1";  
   then  
     eval "${return_yes}";  
   fi;  
   eval "${return_no}";  
 }  
   
   
 ########################################################################  
 # is_not_dir (<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_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_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_file (<filename>)  
 #  
 # Test whether `name' is a not readable file.  
 #  
 # Arguments : >=1 (empty allowed), more args are ignored  
 #  
 is_not_file()  
 {  
   func_check is_not_file '>=' 1 "$@";  
   if is_file "$1";  
   then  
     eval "${return_no}";  
   fi;  
   eval "${return_yes}";  
 }  
   
   
 ########################################################################  
 # is_not_prog (<name>)  
 #  
 # Verify that arg is a not program in $PATH.  
 #  
 # Arguments : >=1 (empty allowed)  
 #   more args are ignored, this allows to specify progs with arguments  
 #  
 is_not_prog()  
 {  
   func_check is_not_prog '>=' 1 "$@";  
   if where_is "$1" >${_NULL_DEV};  
   then  
     eval "${return_no}";  
   fi;  
   eval "${return_yes}";  
 }  
   
   
 ########################################################################  
 # is_not_writable (<name>)  
 #  
 # Test whether `name' is a not a writable file or directory.  
 #  
 # Arguments : >=1 (empty allowed), more args are ignored  
 #  
 is_not_writable()  
 {  
   func_check is_not_writable '>=' 1 "$@";  
   if is_writable "$1";  
   then  
     eval "${return_no}";  
   fi;  
   eval "${return_yes}";  
 }  
   
   
 ########################################################################  
 # is_not_yes (<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_prog (<name> [<arg>*])  
 #  
 # Determine whether <name> is a program in $PATH  
 #  
 # Arguments : >=0 (empty allowed)  
 #   <arg>* are ignored, this allows to specify progs with arguments.  
 #  
 is_prog()  
 {  
   func_check is_prog '>=' 0 "$@";  
   case "$#" in  
   0)  
     eval "${return_no}";  
     ;;  
   *)  
     if where_is "$1" >${_NULL_DEV};  
     then  
       eval "${return_yes}";  
     fi;  
     ;;  
   esac  
   eval "${return_no}";  
 }  
   
   
 ########################################################################  
 # is_writable (<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 test -r "$1";  
   then  
     if test -w "$1";  
     then  
       eval "${return_yes}";  
     fi;  
   fi;  
   eval "${return_no}";  
 }  
   
   
 ########################################################################  
 # is_yes (<string>)  
 #  
 # Test whether `string' has value "yes".  
 #  
 # Arguments : <=1  
 # Return    : `0' if arg1 is `yes', `1' otherwise.  
 #  
 is_yes()  
 {  
   func_check is_yes = 1 "$@";  
   if is_equal "$1" 'yes';  
   then  
     eval "${return_yes}";  
   fi;  
   eval "${return_no}";  
 }  
   
   
 ########################################################################  
 # landmark ()  
 #  
 # Print debugging information on standard error if $_DEBUG_LM is `yes'.  
 #  
 # Globals: $_DEBUG_LM  
 #  
 # Defined in section `Debugging functions'.  
   
   
 ########################################################################  
 # leave ()  
 #  
 # Clean exit without an error.  
 #  
 leave()  
 {  
   clean_up;  
   exit "${_OK}";  
 }  
   
   
 ########################################################################  
 landmark '6: list_*()';  
 ########################################################################  
 #  
 # `list' is an object class that represents an array or list.  Its  
 # data consists of space-separated single-quoted elements.  So a list  
 # has the form "'first' 'second' '...' 'last'".  See list_append() for  
 # more details on the list structure.  The array elements of `list'  
 # can be get by `set x $list; shift`.  
   
   
 ########################################################################  
 # list_append (<list> <element>...)  
 #  
 # 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="$(echo x"${la_s}" | sed -e '  
 s/^x//  
 s/'"${_SQUOTE}"'/&\\&&/g  
 ')";  
       ;;  
     '')  
       la_element="";  
       ;;  
     *)  
       la_element="${la_s}";  
       ;;  
     esac;  
     if obj la_list is_empty;  
     then  
       la_list="'${la_element}'";  
     else  
       la_list="${la_list} '${la_element}'";  
     fi;  
   done;  
   eval "${la_name}"='"${la_list}"';  
   eval ${_UNSET} la_element;  
   eval ${_UNSET} la_list;  
   eval ${_UNSET} la_name;  
   eval ${_UNSET} la_s;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # list_from_cmdline (<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 b' 'c' '' 'long' -a f1 -bcarg --long=larg f2  
 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are  
 # none-empty option lists, this will result in printing:  
 #     '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'  
 #  
 #   Use this function in the following way:  
 #     eval set x "$(args_norm PRE_NAME "$@")";  
 #     shift;  
 #     while test "$1" != '--'; do  
 #       case "$1" in  
 #       ...  
 #       esac;  
 #       shift;  
 #     done;  
 #     shift;         #skip '--'  
 #     # all positional parameters ("$@") left are file name parameters.  
 #  
 # Variable prefix: lfc  
 #  
 list_from_cmdline()  
 {  
   func_check list_from_cmdline '>=' 1 "$@";  
   lfc_short_n="$(obj_data "$1"_SHORT_NA)";  # short options, no argument  
   lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument  
   lfc_long_n="$(obj_data "$1"_LONG_NA)";    # long options, no argument  
   lfc_long_a="$(obj_data "$1"_LONG_ARG)";   # long options, with argument  
   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;  
   lfc_fn='list_from_cmdline():';         # for error messages  
   if is_equal "$#" 0;  
   then  
     cat <<EOF  
 --  
 EOF  
     eval ${_UNSET} lfc_fparams;  
     eval ${_UNSET} lfc_fn;  
     eval ${_UNSET} lfc_short_a;  
     eval ${_UNSET} lfc_short_n;  
     eval ${_UNSET} lfc_long_a;  
     eval ${_UNSET} lfc_long_n;  
     eval ${_UNSET} lfc_result;  
     eval "${return_ok}";  
   fi;  
   lfc_fparams='';  
   lfc_result='';  
   while test "$#" -ge 1;  
   do  
     lfc_arg="$1";  
     shift;  
     case "${lfc_arg}" in  
       --) break; ;;  
       --?*)  
         # delete leading '--';  
         lfc_opt="$(echo x"${lfc_arg}" | sed -e 's/^x--//')";  
         if list_has lfc_long_n "${lfc_opt}";  
         then  
           # long option, no argument  
           list_append lfc_result "--${lfc_opt}";  
           continue;  
         fi;  
         # test on `--opt=arg'  
         if string_contains "${lfc_opt}" '=';  
         then  
           # extract option by deleting from the first '=' to the end  
           lfc_lopt="$(echo x"${lfc_opt}" | sed -e '  
 s/^x//  
 s/=.*$//  
 ')";  
           if list_has lfc_long_a "${lfc_lopt}";  
           then  
             # get the option argument by deleting up to first `='  
             lfc_optarg="$(echo x"${lfc_opt}" | sed -e '  
 s/^x//  
 s/^[^=]*=//  
 ')";  
             list_append lfc_result "--${lfc_lopt}" "${lfc_optarg}";  
             continue;  
           fi;  
         fi;  
         if list_has lfc_long_a "${lfc_opt}";  
         then  
           # long option with argument  
           if test "$#" -le 0;  
           then  
             error "list_from_cmdline(): \  
 ${lfc_fn} no argument for option --${lfc_opt}."  
           fi;  
           list_append lfc_result "--${lfc_opt}" "$1";  
           shift;  
           continue;  
         fi;  
         error "list_from_cmdline(): ${lfc_fn} --${lfc_opt} is not an option."  
         ;;  
       -?*)                      # short option (cluster)  
         # delete leading `-';  
         lfc_rest="$(echo x"${lfc_arg}" | sed -e 's/^x-//')";  
         while obj lfc_rest is_not_empty;  
         do  
           # get next short option from cluster (first char of $lfc_rest)  
           lfc_optchar="$(echo x"${lfc_rest}" | sed -e 's/^x\(.\).*$/\1/')";  
           # remove first character from ${lfc_rest};  
           lfc_rest="$(echo x"${lfc_rest}" | sed -e 's/^x.//')";  
           if list_has lfc_short_n "${lfc_optchar}";  
           then  
             list_append lfc_result "-${lfc_optchar}";  
             continue;  
           elif list_has lfc_short_a "${lfc_optchar}";  
           then  
             if obj lfc_rest is_empty;  
             then  
               if test "$#" -ge 1;  
               then  
                 list_append lfc_result "-${lfc_optchar}" "$1";  
                 shift;  
                 continue;  
               else  
                 error "list_from_cmdline(): \  
 ${lfc_fn}"' no argument for option -'"${lfc_optchar}."  
               fi;  
             else                # rest is the argument  
               list_append lfc_result "-${lfc_optchar}" "${lfc_rest}";  
               lfc_rest='';  
               continue;  
             fi;  
           else  
             error "list_from_cmdline(): \  
 ${lfc_fn} unknown option -${lfc_optchar}."  
           fi;  
         done;  
         ;;  
       *)  
         # Here, $lfc_arg is not an option, so a file parameter.  
         list_append lfc_fparams "${lfc_arg}";  
   
         # Ignore the strange option handling of $POSIXLY_CORRECT to  
         # end option parsing after the first file name argument.  To  
         # reuse it, do a `break' here if $POSIXLY_CORRECT is  
         # non-empty.  
         ;;  
     esac;  
   done;  
   list_append lfc_result '--';  
   if obj lfc_fparams is_not_empty;  
   then  
     lfc_result="${lfc_result} ${lfc_fparams}";  
   fi;  
   if test "$#" -gt 0;  
   then  
     list_append lfc_result "$@";  
   fi;  
   cat <<EOF  
 ${lfc_result}  
 EOF  
   eval ${_UNSET} lfc_fparams;  
   eval ${_UNSET} lfc_fn;  
   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_lopt;  
   eval ${_UNSET} lfc_rest;  
   eval "${return_ok}";  
 } # list_from_cmdline()  
   
   
 ########################################################################  
 # list_from_split (<string> <separator>)  
 #  
 # In <string>, escape all white space characters and replace each  
 # <separator> by space.  
 #  
 # Arguments: 2: a <string> that is to be split into parts divided by  
 #               <separator>  
 # Output:    the resulting list string  
 #  
 # Variable prefix: lfs  
 #  
 list_from_split()  
 {  
   func_check list_from_split = 2 "$@";  
   
   # precede each space or tab by a backslash `\' (doubled for `sed')  
   lfs_s="$(echo x"$1" | sed -e '  
 s/^x//  
 s/\(['"${_SPACE}${_TAB}"']\)/\\\1/g  
 ')";  
   
   # replace split character of string by the list separator ` ' (space).  
   case "$2" in  
     /)                          # cannot use normal `sed' separator  
       echo x"${lfs_s}" | sed -e '  
 s/^x//  
 s|'"$2"'| |g  
 ';  
       ;;  
     ?)                          # use normal `sed' separator  
       echo x"${lfs_s}" | sed -e '  
 s/^x//  
 s/'"$2"'/ /g  
 ';  
       ;;  
     ??*)  
       error 'list_from_split(): separator must be a single character.';  
       ;;  
   esac;  
   eval ${_UNSET} lfs_s;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # list_get (<list>)  
 #  
 # Check whether <list> is a space-separated list of '-quoted elements.  
 #  
 # If the test fails an error is raised.  
 # If the test succeeds the argument is echoed.  
 #  
 # Testing criteria:  
 #   A list has the form "'first' 'second' '...' 'last'".  So it has a  
 #   leading and a final quote and the elements are separated by "' '"  
 #   constructs.  If these are all removed there should not be any  
 #   unescaped single-quotes left.  Watch out for escaped single  
 #   quotes; they have the form '\'' (sq bs sq sq).  
   
 # Arguments: 1  
 # Output: the argument <list> unchanged, if the check succeeded.  
 #  
 # Variable prefix: lg  
 #  
 list_get()  
 {  
   func_check list_get = 1 "$@";  
   eval lg_list='"${'$1'}"';  
   # remove leading and final space characters  
   lg_list="$(echo x"${lg_list}" | sed -e '  
 s/^x['"${_SPACE}${_TAB}"']*//  
 s/['"${_SPACE}${_TAB}"']*$//  
 ')";  
   case "${lg_list}" in  
   '')  
     eval ${_UNSET} lg_list;  
     eval "${return_ok}";  
     ;;  
   \'*\')  
     cat <<EOF  
 ${lg_list}  
 EOF  
     eval ${_UNSET} lg_list;  
     eval "${return_ok}";  
     ;;  
   *)  
     error "list_get(): bad list: $1"  
     ;;  
   esac;  
   eval ${_UNSET} lg_list;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # list_has (<var_name> <element>)  
 #  
 # Arguments: 2  
 #   <var_name>: a variable name for a list of single-quoted elements  
 #   <element>:  some sequence of characters.  
 # Output:  
 #   if <list> is empty:  "'<element>' '...'"  
 #   otherwise:           "list '<element>' ..."  
 #  
 list_has()  
 {  
   func_check list_has = 2 "$@";  
   eval _list='"${'$1'}"';  
   if obj _list is_empty;  
   then  
     eval "${return_no}";  
   fi;  
   _element="$2";  
   case "$2" in  
     \'*\')  _element="$2"; ;;  
     *)      _element="'$2'"; ;;  
   esac;  
   if string_contains "${_list}" "${_element}";  
   then  
     eval "${return_yes}";  
   else  
     eval "${return_no}";  
   fi;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # list_has_not (<list> <element>)  
 #  
 # Arguments: 2  
 #   <list>:    a space-separated list of single-quoted elements.  
 #   <element>: some sequence of characters.  
 # Output:  
 #   if <list> is empty:  "'<element>' '...'"  
 #   otherwise:           "<list> '<element>' ..."  
 #  
 list_has_not()  
 {  
   func_check list_has_not = 2 "$@";  
   eval _list='"${'$1'}"';  
   if obj _list is_empty;  
   then  
     eval "${return_yes}";  
   fi;  
   _element="$2";  
   case "$2" in  
     \'*\')  _element="$2"; ;;  
     *)      _element="'$2'"; ;;  
   esac;  
   if string_contains "${_list}" "${_element}";  
   then  
     eval "${return_no}";  
   else  
     eval "${return_yes}";  
   fi;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 landmark '7: man_*()';  
 ########################################################################  
   
 ########################################################################  
 # man_do_filespec (<filespec>)  
 #  
 # Print suitable man page(s) for filespec to $_TMP_CAT.  
 #  
 # Arguments : 2  
 #   <filespec>: argument of the form `man:name.section', `man:name',  
 #               `man:name(section)', `name.section', `name'.  
 #  
 # Globals   : $_OPT_ALL  
 #  
 # Output    : none.  
 # Return    : `0' if man page was found, `1' else.  
 #  
 # Only called from do_fileargs(), checks on $MANPATH and  
 # $_MAN_ENABLE are assumed.  
 #  
 # Variable prefix: mdf  
 #  
 man_do_filespec()  
 {  
   func_check man_do_filespec = 1 "$@";  
   if obj _MAN_PATH is_empty;  
   then  
     eval "${return_bad}";  
   fi;  
   if is_empty "$1";  
   then  
     eval "${return_bad}";  
   fi;  
   mdf_spec="$1";  
   mdf_name='';  
   mdf_section='';  
   case "${mdf_spec}" in  
     */*)                        # not a man spec when it contains '/'  
       eval ${_UNSET} mdf_got_one;  
       eval ${_UNSET} mdf_name;  
       eval ${_UNSET} mdf_section;  
       eval ${_UNSET} mdf_spec;  
       eval "${return_bad}";  
       ;;  
     man:?*\(?*\))               # man:name(section)  
       mdf_name="$(echo x"${mdf_spec}" \  
                | sed -e 's/^xman:\(..*\)(\(..*\))$/\1/')";  
       mdf_section="$(echo x"${mdf_spec}" \  
                | sed -e 's/^xman:\(..*\)(\(..*\))$/\2/')";  
       ;;  
     man:?*.[0-9on])                     # man:name.section  
       mdf_name="$(echo x"${mdf_spec}" \  
                | sed -e 's/^xman:\(..*\)\..$/\1/')";  
       mdf_section="$(echo x"${mdf_spec}" \  
                | sed -e 's/^x.*\(.\)$/\1/')";  
       ;;  
     man:?*)                     # man:name  
       mdf_name="$(echo x"${mdf_spec}" | sed -e 's/^xman://')";  
       ;;  
     ?*\(?*\))                   # name(section)  
       mdf_name="$(echo x"${mdf_spec}" \  
                | sed -e 's/^x\(..*\)(\(..*\))$/\1/')";  
       mdf_section="$(echo x"${mdf_spec}" \  
                | sed -e 's/^x\(..*\)(\(..*\))$/\2/')";  
       ;;  
     ?*.[0-9on])                 # name.section  
       mdf_name="$(echo x"${mdf_spec}" \  
                | sed -e 's/^x\(..*\)\..$/\1/')";  
       mdf_section="$(echo x"${mdf_spec}" \  
                | sed -e 's/^x.*\(.\)$/\1/')";  
       ;;  
     ?*)  
       mdf_name="${mdf_spec}";  
       ;;  
   esac;  
   if obj mdf_name is_empty;  
   then  
     eval ${_UNSET} mdf_got_one;  
     eval ${_UNSET} mdf_name;  
     eval ${_UNSET} mdf_section;  
     eval ${_UNSET} mdf_spec;  
     eval "${return_bad}";  
   fi;  
   mdf_got_one='no';  
   if obj mdf_section is_empty;  
   then  
     eval set x "${_MAN_AUTO_SEC}";  
     shift;  
     for s  
     do  
       mdf_s="$s";  
       if man_search_section "${mdf_name}" "${mdf_s}";  
       then                      # found  
         if obj _MAN_ALL is_yes;  
         then  
           mdf_got_one='yes';  
         else  
           eval ${_UNSET} mdf_got_one;  
           eval ${_UNSET} mdf_name;  
           eval ${_UNSET} mdf_s;  
           eval ${_UNSET} mdf_section;  
           eval ${_UNSET} mdf_spec;  
           eval "${return_good}";  
         fi;  
       fi;  
     done;  
   else  
     if man_search_section "${mdf_name}" "${mdf_section}";  
     then  
       eval ${_UNSET} mdf_got_one;  
       eval ${_UNSET} mdf_name;  
       eval ${_UNSET} mdf_s;  
       eval ${_UNSET} mdf_section;  
       eval ${_UNSET} mdf_spec;  
       eval "${return_good}";  
     else  
       eval ${_UNSET} mdf_got_one;  
       eval ${_UNSET} mdf_name;  
       eval ${_UNSET} mdf_section;  
       eval ${_UNSET} mdf_spec;  
       eval "${return_bad}";  
     fi;  
   fi;  
   if obj _MAN_ALL is_yes && is_yes "${mdf_got_one}";  
   then  
     eval ${_UNSET} mdf_got_one;  
     eval ${_UNSET} mdf_name;  
     eval ${_UNSET} mdf_s;  
     eval ${_UNSET} mdf_section;  
     eval ${_UNSET} mdf_spec;  
     eval "${return_good}";  
   fi;  
   eval ${_UNSET} mdf_got_one;  
   eval ${_UNSET} mdf_name;  
   eval ${_UNSET} mdf_s;  
   eval ${_UNSET} mdf_section;  
   eval ${_UNSET} mdf_spec;  
   eval "${return_bad}";  
 } # man_do_filespec()  
   
   
 ########################################################################  
 # man_register_file (<file> <name> [<section>])  
 #  
 # Write a found man page file and register the title element.  
 #  
 # Arguments: 1, 2, or 3; maybe empty  
 # Output: none  
 #  
 man_register_file()  
 {  
   func_check man_register_file '>=' 2 "$@";  
   case "$#" in  
     2|3) do_nothing; ;;  
     *)  
       error "man_register_file() expects 2 or 3 arguments.";  
       ;;  
   esac;  
   if is_empty "$1";  
   then  
     error 'man_register_file(): file name is empty';  
   fi;  
   to_tmp "$1";  
   case "$#" in  
     2)  
        register_title "man:$2";  
        eval "${return_ok}";  
        ;;  
     3)  
        register_title "$2.$3";  
        eval "${return_ok}";  
        ;;  
   esac;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # man_search_section (<name> <section>)  
 #  
 # Retrieve man pages.  
 #  
 # Arguments : 2  
 # Globals   : $_MAN_PATH, $_MAN_EXT  
 # Return    : 0 if found, 1 otherwise  
 #  
 # Variable prefix: mss  
 #  
 man_search_section()  
 {  
   func_check man_search_section = 2 "$@";  
   if obj _MAN_PATH is_empty;  
   then  
     eval "${return_bad}";  
   fi;  
   if is_empty "$1";  
   then  
     eval "${return_bad}";  
   fi;  
   if is_empty "$2";  
   then  
     eval "${return_bad}";  
   fi;  
   mss_name="$1";  
   mss_section="$2";  
   eval set x "$(path_split "${_MAN_PATH}")";  
   shift;  
   mss_got_one='no';  
   if obj _MAN_EXT is_empty;  
   then  
     for d  
     do  
       mss_dir="$(dirname_append "$d" "man${mss_section}")";  
       if obj mss_dir is_dir;  
       then  
         mss_prefix="$(\  
           dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";  
         mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |  
                      sed -e '\| found|s|.*||'  
                      )";  
         if obj mss_files is_not_empty;  
         then  
           # for f in $mss_files  
           for f in $(eval set x ${mss_files}; shift; echo "$@")  
           do  
             mss_f="$f";  
             if obj mss_f is_file;  
             then  
               if is_yes "${mss_got_one}";  
               then  
                 register_file "${mss_f}";  
               elif obj _MAN_ALL is_yes;  
               then  
                 man_register_file "${mss_f}" "${mss_name}";  
               else  
                 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";  
                 eval ${_UNSET} mss_dir;  
                 eval ${_UNSET} mss_ext;  
                 eval ${_UNSET} mss_f;  
                 eval ${_UNSET} mss_files;  
                 eval ${_UNSET} mss_got_one;  
                 eval ${_UNSET} mss_name;  
                 eval ${_UNSET} mss_prefix;  
                 eval ${_UNSET} mss_section;  
                 eval "${return_good}";  
               fi;  
               mss_got_one='yes';  
             fi;  
           done;  
         fi;  
       fi;  
     done;  
   else  
     mss_ext="${_MAN_EXT}";  
     # check for directory name having trailing extension  
     for d  
     do  
       mss_dir="$(dirname_append $d man${mss_section}${mss_ext})";  
       if obj mss_dir is_dir;  
       then  
         mss_prefix=\  
           "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";  
         mss_files="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |  
                      sed -e '\|not found|s|.*||'  
                      )";  
         if obj mss_files is_not_empty;  
         then  
           # for f in $mss_files  
           for f in $(eval set x ${mss_files}; shift; echo "$@")  
           do  
             mss_f="$f";  
             if obj mss_f is_file;  
             then  
               if is_yes "${mss_got_one}";  
               then  
                 register_file "${mss_f}";  
               elif obj _MAN_ALL is_yes;  
               then  
                 man_register_file "${mss_f}" "${mss_name}";  
               else  
                 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";  
                 eval ${_UNSET} mss_dir;  
                 eval ${_UNSET} mss_ext;  
                 eval ${_UNSET} mss_f;  
                 eval ${_UNSET} mss_files;  
                 eval ${_UNSET} mss_got_one;  
                 eval ${_UNSET} mss_name;  
                 eval ${_UNSET} mss_prefix;  
                 eval ${_UNSET} mss_section;  
                 eval "${return_good}";  
               fi;  
               mss_got_one='yes';  
             fi;  
           done;  
         fi;  
       fi;  
     done;  
     # check for files with extension in directories without extension  
     for d  
     do  
       mss_dir="$(dirname_append "$d" "man${mss_section}")";  
       if obj mss_dir is_dir;  
       then  
         mss_prefix="$(dirname_append "${mss_dir}" \  
                         "${mss_name}.${mss_section}${mss_ext}")";  
         mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |  
                      sed -e '\|not found|s|.*||'  
                      )";  
         if obj mss_files is_not_empty;  
         then  
           # for f in $mss_files  
           for f in $(eval set x ${mss_files}; shift; echo "$@")  
           do  
             mss_f="$f";  
             if obj mss_f is_file;  
             then  
               if is_yes "${mss_got_one}";  
               then  
                 register_file "${mss_f}";  
               elif obj _MAN_ALL is_yes;  
               then  
                 man_register_file "${mss_f}" "${mss_name}";  
               else  
                 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";  
                 eval ${_UNSET} mss_dir;  
                 eval ${_UNSET} mss_ext;  
                 eval ${_UNSET} mss_f;  
                 eval ${_UNSET} mss_files;  
                 eval ${_UNSET} mss_got_one;  
                 eval ${_UNSET} mss_name;  
                 eval ${_UNSET} mss_prefix;  
                 eval ${_UNSET} mss_section;  
                 eval "${return_good}";  
               fi;  
               mss_got_one='yes';  
             fi;  
           done;  
         fi;  
       fi;  
     done;  
   fi;  
   if obj _MAN_ALL is_yes && is_yes "${mss_got_one}";  
   then  
     eval ${_UNSET} mss_dir;  
     eval ${_UNSET} mss_ext;  
     eval ${_UNSET} mss_f;  
     eval ${_UNSET} mss_files;  
     eval ${_UNSET} mss_got_one;  
     eval ${_UNSET} mss_name;  
     eval ${_UNSET} mss_prefix;  
     eval ${_UNSET} mss_section;  
     eval "${return_good}";  
   fi;  
   eval ${_UNSET} mss_dir;  
   eval ${_UNSET} mss_ext;  
   eval ${_UNSET} mss_f;  
   eval ${_UNSET} mss_files;  
   eval ${_UNSET} mss_got_one;  
   eval ${_UNSET} mss_name;  
   eval ${_UNSET} mss_prefix;  
   eval ${_UNSET} mss_section;  
   eval "${return_bad}";  
 } # man_search_section()  
   
   
 ########################################################################  
 # man_setup ()  
 #  
 # Setup the variables $_MAN_* needed for man page searching.  
 #  
 # Globals:  
 #   in:     $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,  
 #           $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.  
 #   out:    $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,  
 #           $_MAN_SEC, $_MAN_ALL  
 #   in/out: $_MAN_ENABLE  
 #  
 # The precedence for the variables related to `man' is that of GNU  
 # `man', i.e.  
 #  
 # $LANG; overridden by  
 # $LC_MESSAGES; overridden by  
 # $LC_ALL; this has the same precedence as  
 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by  
 # $MANOPT; overridden by  
 # the groffer command line options.  
 #  
 # Variable prefix: ms  
 #  
 man_setup()  
 {  
   func_check main_man_setup = 0 "$@";  
   
   if obj _MAN_IS_SETUP is_yes;  
   then  
     eval "${return_ok}";  
   fi;  
   _MAN_IS_SETUP='yes';  
   
   if obj _MAN_ENABLE is_not_yes;  
   then  
     eval "${return_ok}";  
   fi;  
   
   # determine basic path for man pages  
   _MAN_PATH="$(get_first_essential \  
                "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";  
   if obj _MAN_PATH is_empty;  
   then  
     manpath_set_from_path;  
   else  
     _MAN_PATH="$(path_clean "${_MAN_PATH}")";  
   fi;  
   if obj _MAN_PATH is_empty;  
   then  
     if is_prog 'manpath';  
     then  
       _MAN_PATH="$(manpath 2>${_NULL_DEV})"; # not always available  
     fi;  
   fi;  
   if obj _MAN_PATH is_empty;  
   then  
     _MAN_ENABLE="no";  
     eval "${return_ok}";  
   fi;  
   
   _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";  
   if obj _MAN_ALL is_empty;  
   then  
     _MAN_ALL='no';  
   fi;  
   
   _MAN_SYS="$(get_first_essential \  
               "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";  
   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}";  
       # get first two characters of $ms_lang  
       _MAN_LANG2="$(echo x"${ms_lang}" | sed -e 's/^x\(..\).*$/\1/')";  
       ;;  
   esac;  
   # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.  
   
   manpath_add_lang_sys;         # this is very slow  
   
   _MAN_SEC="$(get_first_essential \  
               "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";  
   if obj _MAN_PATH is_empty;  
   then  
     _MAN_ENABLE="no";  
     eval ${_UNSET} ms_lang;  
     eval "${return_ok}";  
   fi;  
   
   _MAN_EXT="$(get_first_essential \  
               "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";  
   eval ${_UNSET} ms_lang;  
   eval "${return_ok}";  
 } # man_setup()  
   
   
 ########################################################################  
 landmark '8: manpath_*()';  
 ########################################################################  
   
 ########################################################################  
 # manpath_add_lang_sys ()  
 #  
 # Add language and operating system specific directories to man path.  
 #  
 # Arguments : 0  
 # Output    : none  
 # Globals:  
 #   in:     $_MAN_SYS: has the form `os1,os2,...', a comma separated  
 #             list of names of operating systems.  
 #           $_MAN_LANG and $_MAN_LANG2: each a single name  
 #   in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon  
 #             separated list of directories.  
 #  
 # Variable prefix: mals  
 #  
 manpath_add_lang_sys()  
 {  
   func_check manpath_add_lang_sys = 0 "$@";  
   if obj _MAN_PATH is_empty;  
   then  
     eval "${return_ok}";  
   fi;  
   # twice test both sys and lang  
   eval set x "$(path_split "${_MAN_PATH}")";  
   shift;  
   mals_mp='';  
   for p  
   do                            # loop on man path directories  
     mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";  
   done;  
   eval set x "$(path_split "${mals_mp}")";  
   shift;  
   for p  
   do                            # loop on man path directories  
     mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";  
   done;  
   _MAN_PATH="$(path_chop "${mals_mp}")";  
   eval ${_UNSET} mals_mp;  
   eval "${return_ok}";  
 }  
   
   
 # To the directory in $1 append existing sys/lang subdirectories  
 # Function is necessary to split the OS list.  
 #  
 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2  
 # argument: 2: `man_path' and `dir'  
 # output: colon-separated path of the retrieved subdirectories  
 #  
 # Variable prefix: _mals  
 #  
 _manpath_add_lang_sys_single()  
 {  
   func_check _manpath_add_lang_sys_single = 2 "$@";  
   _mals_res="$1";  
   _mals_parent="$2";  
   eval set x "$(list_from_split "${_MAN_SYS}" ',')";  
   shift;  
   for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"  
   do  
     _mals_dir="$(dirname_append "${_mals_parent}" "$d")";  
     if obj _mals_res path_not_contains "${_mals_dir}" && \  
        obj _mals_dir is_dir;  
     then  
       _mals_res="${_mals_res}:${_mals_dir}";  
     fi;  
   done;  
   if path_not_contains "${_mals_res}" "${_mals_parent}";  
   then  
     _mals_res="${_mals_res}:${_mals_parent}";  
   fi;  
   path_chop "${_mals_res}";  
   eval ${_UNSET} _mals_dir;  
   eval ${_UNSET} _mals_parent;  
   eval ${_UNSET} _mals_res;  
   eval "${return_ok}";  
 }  
   
 # end manpath_add_lang_sys ()  
   
   
 ########################################################################  
 # manpath_set_from_path ()  
 #  
 # Determine basic search path for man pages from $PATH.  
 #  
 # Return:    `0' if a valid man path was retrieved.  
 # Output:    none  
 # Globals:  
 #   in:  $PATH  
 #   out: $_MAN_PATH  
 #  
 # Variable prefix: msfp  
 #  
 manpath_set_from_path()  
 {  
   func_check manpath_set_from_path = 0 "$@";  
   
   msfp_manpath='';  
   
   # get a basic man path from $PATH  
   if obj PATH is_not_empty;  
   then  
     eval set x "$(path_split "${PATH}")";  
     shift;  
     for d  
     do  
       # delete the final `/bin' part  
       msfp_base="$(echo x"$d" | sed -e '  
 s/^x//  
 s|//*bin/*$||  
 ')";  
       for e in /share/man /man  
       do  
         msfp_mandir="${msfp_base}$e";  
         if test -d "${msfp_mandir}" && test -r "${msfp_mandir}";  
         then  
           msfp_manpath="${msfp_manpath}:${msfp_mandir}";  
         fi;  
       done;  
     done;  
   fi;  
   
   # append some default directories  
   for d in /usr/local/share/man /usr/local/man \  
            /usr/share/man /usr/man \  
            /usr/X11R6/man /usr/openwin/man \  
            /opt/share/man /opt/man \  
            /opt/gnome/man /opt/kde/man  
   do  
     msfp_d="$d";  
     if obj msfp_manpath path_not_contains "${msfp_d}" && obj mfsp_d is_dir;  
     then  
       msfp_manpath="${msfp_manpath}:${mfsp_d}";  
     fi;  
   done;  
   
   _MAN_PATH="${msfp_manpath}";  
   eval ${_UNSET} msfp_base;  
   eval ${_UNSET} msfp_d;  
   eval ${_UNSET} msfp_mandir;  
   eval ${_UNSET} msfp_manpath;  
   eval "${return_ok}";  
 } # manpath_set_from_path()  
   
   
 ########################################################################  
 landmark '9: obj_*()';  
 ########################################################################  
   
 ########################################################################  
 # obj (<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 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 "$@";  
   if is_empty "$2";  
   then  
     error "obj(): function name is empty."  
   else  
     o_func="$2";  
   fi;  
   eval o_arg1='"${'$1'}"';  
   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 '=' 1 "$@";  
   if is_empty "$1";  
   then  
     error "obj_data(): object name is empty."  
   fi;  
   eval od_res='"${'$1'}"';  
   cat <<EOF  
 ${od_res}  
 EOF  
   eval ${_UNSET} od_res;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # obj_from_output (<object> <call_name> <arg>...)  
 #  
 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a  
 # function call to a global variable.  
 #  
 # 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 "res(): variable name is empty.";  
   elif is_empty "$2";  
   then  
     error "res(): function name is empty."  
   else  
     ofo_result_name="$1";  
   fi;  
   shift;  
   eval "${ofo_result_name}"'="$('"$@"')"';  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # 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}";  
 }  
   
   
 ########################################################################  
 # 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  
   echo x"$1" | sed -e '  
 s/^x:*//  
 s/:::*/:/g  
 s/:*$//  
 ';  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # 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_split "${pc_arg}")";  
   shift;  
   pc_res="";  
   for i  
   do  
     pc_i="$i";  
     if obj pc_i is_not_empty \  
        && obj pc_res path_not_contains "${pc_i}" \  
        && obj pc_i is_dir;  
     then  
       case "${pc_i}" in  
         ?*/) pc_res="${pc_res}$(dirname_chop "${pc_i}")"; ;;  
         *)  pc_res="${pc_res}:${pc_i}";  
       esac;  
     fi;  
   done;  
   eval ${_UNSET} pc_arg;  
   eval ${_UNSET} pc_i;  
   eval ${_UNSET} pc_res;  
   if path_chop "${pc_res}";  
   then  
     eval "${return_ok}";  
   else  
     eval "${return_bad}";  
   fi;  
 }  
   
   
 ########################################################################  
 # path_contains (<path> <dir>)  
 #-  
 # Test whether `dir' is contained in `path', a list separated by `:'.  
 #  
 # Arguments : 2 arguments.  
 # Return    : `0' if arg2 is substring of arg1, `1' otherwise.  
 #  
 path_contains()  
 {  
   func_check path_contains = 2 "$@";  
   case ":$1:" in  
     *":$2:"*)  
       eval "${return_yes}";  
       ;;  
     *)  
       eval "${return_no}";  
       ;;  
   esac;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # path_not_contains (<path> <dir>)  
 #  
 # Test whether `dir' is not contained in colon separated `path'.  
 #  
 # Arguments : 2 arguments.  
 #  
 path_not_contains()  
 {  
   func_check path_not_contains = 2 "$@";  
   if path_contains "$1" "$2";  
   then  
     eval "${return_no}";  
   else  
     eval "${return_yes}";  
   fi;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # path_split (<path>)  
 #  
 # In `path' escape white space and replace each colon by a space.  
 #  
 # Arguments: 1: a colon-separated path  
 # Output:    the resulting list, process with `eval set'  
 #  
 path_split()  
 {  
   func_check path_split = 1 "$@";  
   list_from_split "$1" ':';  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 landmark '10: register_*()';  
 ########################################################################  
   
 ########################################################################  
 # register_file (<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 "$(base_name "$1")";  
   fi;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # register_title (<filespec>)  
 #  
 # Create title element from <filespec> and append to $_REGISTERED_TITLE  
 #  
 # Globals: $_REGISTERED_TITLE (rw)  
 #  
 # Variable prefix: rt  
 #  
 register_title()  
 {  
   func_check register_title = 1 "$@";  
   if is_empty "$1";  
   then  
     eval "${return_ok}";  
   fi;  
   rt_title="$(base_name "$1")"; # remove directory part  
   
   # remove extension `.gz'  
   rt_title="$(echo x"${rt_title}" | sed -e '  
 s/^x//  
 s/\.gz$//  
 ')";  
   # remove extension `.Z'  
   rt_title="$(echo x"${rt_title}" | sed -e '  
 s/^x//  
 s/\.Z$//  
 ')";  
   
   if obj rt_title is_empty;  
   then  
     eval "${return_ok}";  
   fi;  
   _REGISTERED_TITLE="${_REGISTERED_TITLE} ${rt_title}";  
   eval ${_UNSET} rt_title;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # reset ()  
 #  
 # Reset the variables that can be affected by options to their default.  
 #  
 #  
 # Defined in section `Preset' after the rudimentary shell tests.  
   
   
 ########################################################################  
 # save_stdin ()  
 #  
 # Store standard input to temporary file (with decompression).  
 #  
 # 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 -f "${ss_f}";  
     eval ${_UNSET} ss_f;  
     eval "${return_ok}";  
   }  
 else  
   save_stdin()  
   {  
     func_check save_stdin = 0 "$@";  
     cat >"${_TMP_STDIN}";  
     eval "${return_ok}";  
   }  
 fi;  
   
   
 ########################################################################  
 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_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}";  
 }  
   
   
 ########################################################################  
 landmark '12: tmp_*()';  
 ########################################################################  
   
 ########################################################################  
 # tmp_cat ()  
 #  
 # output the temporary cat file (the concatenation of all input)  
 #  
 tmp_cat()  
 {  
   func_check tmp_cat '=' 0 "$@";  
   cat "${_TMP_CAT}";  
   eval "${return_var}" "$?";  
 }  
   
   
 ########################################################################  
 # tmp_create (<suffix>?)  
 #  
 # Create temporary file.  
 #  
 # It's safe to use the shell process ID together with a suffix to  
 # have multiple temporary files.  
 #  
 # Globals: $_TMP_DIR  
 #  
 # Output : name of created file  
 #  
 # Variable prefix: tc  
 #  
 tmp_create()  
 {  
   func_check tmp_create '<=' 1 "$@";  
   # the output file does not have `,' as first character, so these are  
   # different names from the output file.  
   tc_tmp="${_TMP_DIR}/,$1";  
   : >"${tc_tmp}"  
   cat <<EOF  
 ${tc_tmp}  
 EOF  
   eval ${_UNSET} tc_tmp;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # to_tmp (<filename>)  
 #  
 # print file (decompressed) to the temporary cat file  
 #  
 to_tmp()  
 {  
   func_check to_tmp = 1 "$@";  
   if is_file "$1";  
   then  
     if obj _OPT_LOCATION is_yes;  
     then  
       echo2 "$1";  
     fi;  
     if obj _OPT_WHATIS is_yes;  
     then  
       what_is "$1" >>"${_TMP_CAT}";  
     else  
       cat_z "$1" >>"${_TMP_CAT}";  
     fi;  
   else  
     error "to_tmp(): could not read file \`$1'.";  
   fi;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # trap_clean ()  
 #  
 # disable trap on all exit codes ($_ALL_EXIT)  
 #  
 # Arguments: 0  
 # Globals:   $_ALL_EXIT  
 #  
 trap_clean()  
 {  
   func_check trap_clean = 0 "$@";  
   # for i in $_ALL_EXIT  
   for i in $(eval set x ${_ALL_EXIT}; shift; echo "$@")  
   do  
     trap "" "$i" 2>${_NULL_DEV} || :;  
   done;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # trap_set (<functionname>)  
 #  
 # call function on all exit codes ($_ALL_EXIT)  
 #  
 # Arguments: 1 (name of a shell function)  
 # Globals:   $_ALL_EXIT  
 #  
 trap_set()  
 {  
   func_check trap_set = 1 "$@";  
   # for i in $_ALL_EXIT  
   for i in $(eval set x ${_ALL_EXIT}; shift; echo "$@")  
   do  
     trap "$1" "$i" 2>${_NULL_DEV} || :;  
   done;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # usage ()  
 #  
 # print usage information to stderr; for groffer option --help.  
 #  
 usage()  
 {  
   func_check usage = 0 "$@";  
   echo;  
   version;  
   echo 'Usage: '"${_PROGRAM_NAME}"' [option]... [filespec]...';  
   cat <<EOF  
   
 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"       man page "name" in first section found  
   "name.n"         man page "name" in section "n"  
   "name"           man page "name" in first section found  
 and some more (see groffer(1) for details).  
   
 -h --help        print this usage message.  
 -Q --source      output as roff source.  
 -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 --X --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     choose the viewer program for dvi mode.  
 --groff          process like groff, disable viewing features.  
 --help           display this helping output.  
 --html --www     display in a web browser.  
 --html-viewer    choose the web browser for www 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.  
 --pager=program  preset the paging program for tty mode.  
 --pdf            display in a PDF viewer.  
 --pdf-viewer     choose the viewer program for pdf mode.  
 --ps             display in a Postscript viewer.  
 --ps-viewer      choose the viewer program for ps mode.  
 --shell          specify shell under which to run this program.  
 --text           output in a text device without a pager.  
 --tty            display with a pager on text terminal even when in X.  
 --www-viewer     same as --html-viewer  
 --x-viewer       choose viewer program for x mode (X mode).  
 --X-viewer       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,..., --whatis, --where, ...  
   
 EOF  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # version ()  
 #  
 # print version information to stderr  
 #  
 version()  
 {  
   func_check version = 0 "$@";  
   echo2 "${_PROGRAM_NAME} ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";  
   # also display groff's version, but not the called subprograms  
   groff -v 2>&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /' >&2;  
   eval "${return_ok}";  
 }  
   
   
 ########################################################################  
 # warning (<string>)  
 #  
 # Print warning to stderr  
 #  
 warning()  
 {  
   echo2 "warning: $*";  
 }  
   
   
 ########################################################################  
 # what_is (<filename>)  
 #  
 # Interpret <filename> as a man page and display its `whatis'  
 # information as a fragment written in the groff language.  
 #  
 # Variable prefix: wi  
 #  
 what_is()  
 {  
   func_check what_is = 1 "$@";  
   if is_not_file "$1";  
   then  
     error "what_is(): argument is not a readable file."  
   fi;  
   wi_dot='^\.['"${_SPACE}${_TAB}"']*';  
   cat <<EOF  
 .br  
   $1:  
 .br  
 EOF  
   # grep the line containing `.TH' macro, if any  
   wi_res="$(cat_z "$1" | sed -e '/'"${wi_dot}"'TH /p  
 d')";  
   if obj wi_res is_not_empty;  
   then                          # traditional man style  
     # get the text between the first and the second `.SH' macro, by  
     # - delete up to first .SH;  
     # - of this, print everything up to next .SH, and delete the rest;  
     # - of this, delete the final .SH line;  
     cat_z "$1" | sed -e '1,/'"${wi_dot}"'SH/d' \  
               | sed -e '1,/'"${wi_dot}"'SH/p  
 d' \  
               | sed -e '/'"${wi_dot}"'SH/d';  
     eval ${_UNSET} wi_dot;  
     eval ${_UNSET} wi_res;  
     eval "${return_ok}";  
   fi;  
   # grep the line containing `.Dd' macro, if any  
   wi_res="$(cat_z "$1" | sed -e '/'"${wi_dot}"'Dd /p  
 d')";  
   if obj wi_res is_not_empty;  
   then                          # BSD doc style  
     # get the text between the first and the second `.Nd' macro, by  
     # - delete up to first .Nd;  
     # - of this, print everything up to next .Nd, and delete the rest;  
     # - of this, delete the final .Nd line;  
     cat_z "$1" | sed -e '1,/'"${wi_dot}"'Nd/d' \  
               | sed -e '1,/'"${wi_dot}"'Nd/p  
 d' \  
               | sed -e '/'"${wi_dot}"'Nd/d';  
     eval ${_UNSET} wi_dot;  
     eval ${_UNSET} wi_res;  
     eval "${return_ok}";  
   fi;  
   echo 'is not a man page.';  
   eval ${_UNSET} wi_dot;  
   eval ${_UNSET} wi_res;  
   eval "${return_bad}";  
 }  
   
   
 ########################################################################  
 # where_is (<program>)  
 #  
 # Output path of a program if in $PATH.  
 #  
 # Arguments : >=1 (empty allowed)  
 #   more args are ignored, this allows to specify progs with arguments  
 # Return    : `0' if arg1 is a program in $PATH, `1' otherwise.  
 #  
 # Variable prefix: w  
 #  
 where_is()  
 {  
   func_check where_is '>=' 1 "$@";  
   w_arg="$1";  
   if obj w_arg is_empty;  
   then  
     eval ${_UNSET} w_arg;  
     eval "${return_bad}";  
   fi;  
   case "${w_arg}" in  
     /*)  
       eval ${_UNSET} w_arg;  
       eval ${_UNSET} w_file;  
       if test -f "${w_arg}" && test -x "${w_arg}";  
       then  
         eval "${return_ok}";  
       else  
         eval "${return_bad}";  
       fi;  
       ;;  
   esac;  
   eval set x "$(path_split "${PATH}")";  
   shift;  
   for p  
   do  
     case "$p" in  
       */) w_file=${p}${w_arg}; ;;  
       *)  w_file=${p}/${w_arg}; ;;  
     esac;  
     if test -f "${w_file}" && test -x "${w_file}";  
     then  
       cat <<EOF  
 ${w_file}  
 EOF  
       eval ${_UNSET} w_arg;  
       eval ${_UNSET} w_file;  
       eval "${return_ok}";  
     fi;  
   done;  
   eval ${_UNSET} w_arg;  
   eval ${_UNSET} w_file;  
   eval "${return_bad}";  
 }  
   
   
 ########################################################################  
 #                        main* Functions  
 ########################################################################  
   
 # The main area contains the following parts:  
 # - main_init(): initialize temporary files and set exit trap  
 # - main_parse_MANOPT(): parse $MANOPT  
 # - main_parse_args(): argument parsing  
 # - main_set_mode (): determine the display mode  
 # - main_do_fileargs(): process filespec arguments  
 # - main_set_resources(): setup X resources  
 # - main_display(): do the displaying  
 # - main(): the main function that calls all main_*()  
   
 # These parts are implemented as functions, being defined below in the  
 # sequence they are called in the main() function.  
   
   
 landmark '13: main_init()';  
 #######################################################################  
 # main_init ()  
 #  
 # set exit trap and create temporary files  
 #  
 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN  
 #  
 # Variable prefix: mi  
 #  
 main_init()  
 {  
   func_check main_init = 0 "$@";  
   # call clean_up() on any signal  
   trap_set clean_up;  
   
   # create temporary directory  
   umask 0022;  
   _TMP_DIR='';  
   for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \  
            "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'  
   do  
     mi_dir="$d";  
     if obj mi_dir is_empty || obj mi_dir is_not_dir || \  
        obj mi_dir is_not_writable;  
     then  
       continue;  
     fi;  
   
     case "${mi_dir}" in  
     */)  
       _TMP_DIR="${mi_dir}";  
       ;;  
     *)  
       _TMP_DIR="${mi_dir}"'/';  
       ;;  
     esac;  
     _TMP_DIR="${_TMP_DIR}${_PROGRAM_NAME}${_PROCESS_ID}";  
     if obj _TMP_DIR is_existing;  
     then  
       eval rm -f -r  "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;  
       if obj _TMP_DIR is_existing;  
       then  
         mi_tdir_="${_TMP_DIR}"_;  
         mi_n=1;  
         mi_tdir_n="${mi_tdir_}${mi_n}";  
         while obj mi_tdir_n is_existing;  
         do  
           eval rm -f -r "'${mi_tdir_n}'" >${_NULL_DEV} 2>&1;  
           if obj mi_tdir_n is_existing;  
           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;  
     fi;  
     eval mkdir "${_TMP_DIR}";  
     if is_not_equal "$?" 0;  
     then  
       if obj _TMP_DIR is_existing;  
       then  
         eval rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;  
       fi;  
       _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;  
     if obj _TMP_DIR is_existing;  
     then  
       rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1;  
     fi;  
     _TMP_DIR='';  
     continue;  
   done;  
   if obj _TMP_DIR is_empty;  
   then  
     error "main_init: \  
 Couldn't create a directory for storing temporary files.";  
   fi;  
   
   _TMP_CAT="$(tmp_create groffer_cat)";  
   _TMP_STDIN="$(tmp_create groffer_input)";  
   
   # groffer configuration files  
   # for f in $_CONF_FILES  
   for f in $(eval set x ${_CONF_FILES}; shift; echo "$@")  
   do  
     mi_file="$f";  
     if obj mi_file is_file;  
     then  
       echo '_groffer_opt=""' >>${_TMP_CAT};  
       # collect the lines starting with a minus  
       cat "$mi_file" | sed -e '  
 /^[      ]*#/d  
 s/^[     ]*\(-.*\)$/_groffer_opt="${_groffer_opt} \1"/  
 ' >>${_TMP_CAT};  
       # prepend the collected information to $GROFFER_OPT  
       echo 'GROFFER_OPT="${_groffer_opt} ${GROFFER_OPT}"' >>${_TMP_CAT};  
     fi;  
   done;  
   eval . "${_TMP_CAT}";  
   _TMP_CAT="$(tmp_create groffer_cat)";  
   
   eval ${_UNSET} mi_dir;  
   eval ${_UNSET} mi_file;  
   eval ${_UNSET} mi_n;  
   eval ${_UNSET} mi_tdir_;  
   eval ${_UNSET} mi_tdir_n;  
   eval "${return_ok}";  
 } # main_init()  
   
   
 landmark '14: main_parse_MANOPT()';  
 ########################################################################  
 # main_parse_MANOPT ()  
 #  
 # Parse $MANOPT to retrieve man options, but only if it is a non-empty  
 # string; found man arguments can be overwritten by the command line.  
 #  
 # Globals:  
 #   in: $MANOPT, $_OPTS_MANOPT_*  
 #   out: $_MANOPT_*  
 #   in/out: $GROFFER_OPT  
 #  
 # Variable prefix: mpm  
 #  
 main_parse_MANOPT()  
 {  
   func_check main_parse_MANOPT = 0 "$@";  
   mpm_list='';  
   if obj MANOPT is_not_empty;  
   then  
     MANOPT="$(echo x"${MANOPT}" | sed -e 's/^x'"${_SPACE}${_SPACE}"'*//')";  
   fi;  
   if obj MANOPT is_empty;  
   then  
     eval ${_UNSET} mpm_list;  
     eval ${_UNSET} mpm_opt;  
     eval "${return_ok}";  
   fi;  
   # add arguments in $MANOPT by mapping them to groffer options  
   eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";  
   shift;  
   until test "$#" -le 0 || is_equal "$1" '--';  
   do  
     mpm_opt="$1";  
     shift;  
     case "${mpm_opt}" in  
       -7|--ascii)  
         list_append mpm_list '--ascii';  
         ;;  
       -a|--all)  
         list_append mpm_list '--all';  
         ;;  
       -c|--catman)  
         do_nothing;  
         shift;  
         ;;  
       -d|--debug)  
         list_append mpm_list '--debug';  
         ;;  
       -D|--default)  
         # undo all man options so far  
         mpm_list='';  
         ;;  
       -e|--extension)  
         list_append mpm_list '--extension';  
         shift;  
         ;;  
       -f|--whatis)  
         list_append mpm_list '--whatis';  
         shift;  
         ;;  
       -h|--help)  
         do_nothing;  
         shift;  
         ;;  
       -k|--apropos)  
         # groffer's --apropos takes an argument, but man's does not, so  
         do_nothing;  
         shift;  
         ;;  
       -l|--local-file)  
         list_append mpm_list '--local-file';  
         ;;  
       -L|--locale)  
         list_append mpm_list '--locale' "$1";  
         shift;  
         ;;  
       -m|--systems)  
         list_append mpm_list '--systems' "$1";  
         shift;  
         ;;  
       -M|--manpath)  
         list_append mpm_list '--manpath' "$1";  
         shift;  
         ;;  
       -p|--preprocessor)  
         do_nothing;  
         shift;  
         ;;  
       -P|--pager|--tty-viewer)  
         list_append mpm_list '--pager' "$1";  
         shift;  
         ;;  
       -r|--prompt)  
         do_nothing;  
         shift;  
         ;;  
       -S|--sections)  
         list_append mpm_list '--sections' "$1";  
         shift;  
         ;;  
       -t|--troff)  
         do_nothing;  
         shift;  
         ;;  
       -T|--device)  
         list_append mpm_list '-T' "$1";  
         shift;  
         ;;  
       -u|--update)  
         do_nothing;  
         shift;  
         ;;  
       -V|--version)  
         do_nothing;  
         ;;  
       -w|--where|--location)  
         list_append mpm_list '--location';  
         ;;  
       -Z|--ditroff)  
         list_append mpm_list '-Z' "$1";  
         shift;  
         ;;  
       # ignore all other options  
     esac;  
   done;  
   # append the 2 lists in $mpm_list and $GROFFER_OPT to $GROFFER_OPT  
   if obj GROFFER_OPT is_empty;  
   then  
     GROFFER_OPT="${mpm_list}";  
   elif obj mpm_list is_not_empty;  
   then  
     GROFFER_OPT="${mpm_list} ${GROFFER_OPT}";  
   fi;  
   eval ${_UNSET} mpm_list;  
   eval ${_UNSET} mpm_opt;  
   eval "${return_ok}";  
 } # main_parse_MANOPT()  
   
   
 landmark '15: main_parse_args()';  
 ########################################################################  
 # 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 "$@";  
   
   eval set x "${GROFFER_OPT}" '"$@"';  
   shift;  
   
   eval set x "$(list_from_cmdline _OPTS_CMDLINE "$@")";  
   shift;  
   
   # By the call of `eval', unnecessary quoting was removed.  So the  
   # positional shell parameters ($1, $2, ...) are now guaranteed to  
   # represent an option or an argument to the previous option, if any;  
   # then a `--' argument for separating options and  
   # parameters; followed by the filespec parameters if any.  
   
   # Note, the existence of arguments to options has already been checked.  
   # So a check for `$#' or `--' should not be done for arguments.  
   
   until test "$#" -le 0 || is_equal "$1" '--';  
   do  
     mpa_opt="$1";               # $mpa_opt is fed into the option handler  
     shift;  
     case "${mpa_opt}" in  
       -h|--help)  
         usage;  
         leave;  
         ;;  
       -Q|--source)              # output source code (`Quellcode').  
         _OPT_MODE='source';  
         ;;  
       -T|--device|--troff-device) # device; arg  
         _OPT_DEVICE="$1";  
         _check_device_with_mode;  
         shift;  
         ;;  
       -v|--version)  
         version;  
         leave;  
         ;;  
       -V)  
         _OPT_V='yes';  
         ;;  
       -Z|--ditroff|--intermediate-output) # groff intermediate output  
         _OPT_Z='yes';  
         ;;  
       -X)  
         _OPT_MODE=X;  
         ;;  
       -?)  
         # delete leading `-'  
         mpa_optchar="$(echo x"${mpa_opt}" | sed -e 's/^x-//')";  
         if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}";  
         then  
           list_append _ADDOPTS_GROFF "${mpa_opt}";  
         elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}";  
         then  
           list_append _ADDOPTS_GROFF "${mpa_opt}" "$1";  
           shift;  
         else  
           error "main_parse_args(): Unknown option : \`$1'";  
         fi;  
         ;;  
       --all)  
           _OPT_ALL="yes";  
           ;;  
       --apropos)                # run `apropos'  
         apropos_run "$1";  
         mpa_code="$?";  
         clean_up;  
         exit "${mpa_code}";  
         ;;  
       --apropos-data)           # run `apropos' for data sections  
         apropos_run "$1" | grep '^[^(]*([457][^)]*)';  
         mpa_code="$?";  
         clean_up;  
         exit "${mpa_code}";  
         ;;  
       --apropos-devel)          # run `apropos' for development sections  
         apropos_run "$1" | grep '^[^(]*([239][^)]*)';  
         mpa_code="$?";  
         clean_up;  
         exit "${mpa_code}";  
         ;;  
       --apropos-progs)          # run `apropos' for program sections  
         apropos_run "$1" | grep '^[^(]*([168][^)]*)';  
         mpa_code="$?";  
         clean_up;  
         exit "${mpa_code}";  
         ;;  
       --ascii)  
         list_append _ADDOPTS_GROFF '-mtty-char';  
         if obj _OPT_MODE is_empty;  
         then  
          _OPT_MODE='text';  
         fi;  
         ;;  
       --auto)                   # the default automatic mode  
         _OPT_MODE='';  
         ;;  
       --bd)                     # border color for viewers, arg;  
         _OPT_BD="$1";  
         shift;  
         ;;  
       --bg|--backgroud)         # background color for viewers, arg;  
         _OPT_BG="$1";  
         shift;  
         ;;  
       --bw)                     # border width for viewers, arg;  
         _OPT_BW="$1";  
         shift;  
         ;;  
       --default)                # reset variables to default  
         reset;  
         ;;  
       --default-modes)          # sequence of modes in auto mode; arg  
         _OPT_DEFAULT_MODES="$1";  
         shift;  
         ;;  
       --debug)                  # only for development  
         _OPT_DEBUG='yes';  
         ;;  
       --display)                # set X display, arg  
         _OPT_DISPLAY="$1";  
         shift;  
         ;;  
       --dvi)  
         _OPT_MODE='dvi';  
         ;;  
       --dvi-viewer)             # viewer program for dvi mode; arg  
         _OPT_VIEWER_DVI="$1";  
         shift;  
         ;;  
       --extension)              # the extension for man pages, arg  
         _OPT_EXTENSION="$1";  
         shift;  
         ;;  
       --fg|--foreground)        # foreground color for viewers, arg;  
         _OPT_FG="$1";  
         shift;  
         ;;  
       --fn|--font)              # set font for viewers, arg;  
         _OPT_FN="$1";  
         shift;  
         ;;  
       --geometry)               # window geometry for viewers, arg;  
         _OPT_GEOMETRY="$1";  
         shift;  
         ;;  
       --groff)  
         _OPT_MODE='groff';  
         ;;  
       --html|--www)             # display with web browser  
         _OPT_MODE=html;  
         ;;  
       --html-viewer|--www-viewer) # viewer program for html mode; arg  
         _OPT_VIEWER_HTML="$1";  
         shift;  
         ;;  
       --iconic)                 # start viewers as icons  
         _OPT_ICONIC='yes';  
         ;;  
       --locale)                 # set language for man pages, arg  
         # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)  
         _OPT_LANG="$1";  
         shift;  
         ;;  
       --local-file)             # force local files; same as `--no-man'  
         _MAN_FORCE='no';  
         _MAN_ENABLE='no';  
         ;;  
       --location|--where)       # print file locations to stderr  
         _OPT_LOCATION='yes';  
         ;;  
       --man)                    # force all file params to be man pages  
         _MAN_ENABLE='yes';  
         _MAN_FORCE='yes';  
         ;;  
       --manpath)                # specify search path for man pages, arg  
         # arg is colon-separated list of directories  
         _OPT_MANPATH="$1";  
         shift;  
         ;;  
       --mode)                   # display mode  
         mpa_arg="$1";  
         shift;  
         case "${mpa_arg}" in  
           auto|'')              # search mode automatically among default  
             _OPT_MODE='';  
             ;;  
           groff)                # pass input to plain groff  
             _OPT_MODE='groff';  
             ;;  
           html|www)             # display with a web browser  
             _OPT_MODE='html';  
             ;;  
           dvi)                  # display with xdvi viewer  
             _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';  
             ;;  
           Q|source)             # display source code  
             _OPT_MODE="source";  
             ;;  
           *)  
             error "main_parse_args(): unknown mode ${mpa_arg}";  
             ;;  
         esac;  
         ;;  
       --no-location)            # disable former call to `--location'  
         _OPT_LOCATION='yes';  
         ;;  
       --no-man)                 # disable search for man pages  
         # the same as --local-file  
         _MAN_FORCE="no";  
         _MAN_ENABLE="no";  
         ;;  
       --pager)                  # set paging program for tty mode, arg  
         _OPT_PAGER="$1";  
         shift;  
         ;;  
       --pdf)  
         _OPT_MODE='pdf';  
         ;;  
       --pdf-viewer)             # viewer program for ps mode; arg  
         _OPT_VIEWER_PDF="$1";  
         shift;  
         ;;  
       --ps)  
         _OPT_MODE='ps';  
         ;;  
       --ps-viewer)              # viewer program for ps mode; arg  
         _OPT_VIEWER_PS="$1";  
         shift;  
         ;;  
       --resolution)             # set resolution for X devices, arg  
         mpa_arg="$1";  
         shift;  
         case "${mpa_arg}" in  
           75|75dpi)  
             mpa_dpi=75;  
             ;;  
           100|100dpi)  
             mpa_dpi=100;  
             ;;  
           *)  
             error "main_parse_args(): \  
 only resoutions of 75 or 100 dpi are supported";  
             ;;  
         esac;  
         _OPT_RESOLUTION="${mpa_dpi}";  
         ;;  
       --rv)  
         _OPT_RV='yes';  
         ;;  
       --sections)               # specify sections for man pages, arg  
         # arg is colon-separated list of section names  
         _OPT_SECTIONS="$1";  
         shift;  
         ;;  
       --shell)  
         # already done during the first run; so ignore the argument  
         shift;  
         ;;  
       --systems)                # man pages for different OS's, arg  
         # argument is a comma-separated list  
         _OPT_SYSTEMS="$1";  
         shift;  
         ;;  
       --text)                   # text mode without pager  
         _OPT_MODE=text;  
         ;;  
       --title)                  # title for X viewers; arg  
         _OPT_TITLE="$1";  
         shift;  
         ;;  
       --tty)                    # tty mode, text with pager  
         _OPT_MODE=tty;  
         ;;  
       --text-device|--tty-device) # device for tty mode; arg  
         _OPT_TEXT_DEVICE="$1";  
         shift;  
         ;;  
       --whatis)  
         _OPT_WHATIS='yes';  
         ;;  
       --X|--x)  
         _OPT_MODE=x;  
         ;;  
       --xrm)                    # pass X resource string, arg;  
         list_append _OPT_XRM "$1";  
         shift;  
         ;;  
       --x-viewer|--X-viewer)    # viewer program for x mode; arg  
         _OPT_VIEWER_X="$1";  
         shift;  
         ;;  
       *)  
         error 'main_parse_args(): error on argument parsing : '"\`$*'";  
         ;;  
     esac;  
   done;  
   shift;                        # remove `--' argument  
   
   if obj _DEBUG is_not_yes;  
   then  
     if obj _OPT_DEBUG is_yes;  
     then  
       _DEBUG='yes';  
       _DEBUG_LM='yes';  
       _DEBUG_KEEP_FILES='yes';  
     fi;  
   fi;  
   
   # Remaining arguments are file names (filespecs).  
   # Save them to list $_FILEARGS  
   if is_equal "$#" 0;  
   then                          # use "-" for standard input  
     set x '-';  
     shift;  
   fi;  
   _FILEARGS='';  
   list_append _FILEARGS "$@";  
   if list_has _FILEARGS '-';  
   then  
     save_stdin;  
   fi;  
   # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'  
   eval ${_UNSET} mpa_arg;  
   eval ${_UNSET} mpa_code;  
   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()  
   
   
 landmark '16: main_set_mode()';  
 ########################################################################  
 # main_set_mode ()  
 #  
 # Determine the display mode.  
 #  
 # Globals:  
 #   in:  $DISPLAY, $_OPT_MODE, $_OPT_DEVICE  
 #   out: $_DISPLAY_MODE  
 #  
 # Variable prefix: msm  
 #  
 main_set_mode()  
 {  
   func_check main_set_mode = 0 "$@";  
   
   # handle apropos  
   if obj _OPT_APROPOS is_not_empty;  
   then  
     apropos "${_OPT_APROPOS}";  
     msm_code="$?";  
     clean_up;  
     exit "${msm_code}";  
   fi;  
   if obj _OPT_APROPOS_DATA is_not_empty;  
   then  
     apropos "$@" | grep '^[^(]*([457])';  
     msm_code="$?";  
     clean_up;  
     exit "${msm_code}";  
   fi;  
   if obj _OPT_APROPOS_DEVEL is_not_empty;  
   then  
     apropos "$@" | grep '^[^(]*([239])';  
     msm_code="$?";  
     clean_up;  
     exit "${msm_code}";  
   fi;  
   if obj _OPT_APROPOS_PROGS is_not_empty;  
   then  
     apropos "$@" | grep '^[^(]*([168])';  
     msm_code="$?";  
     clean_up;  
     exit "${msm_code}";  
   fi;  
   
   # 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_code;  
     eval ${_UNSET} msm_modes;  
     eval ${_UNSET} msm_viewer;  
     eval ${_UNSET} msm_viewers;  
     eval "${return_ok}";  
   fi;  
   
   if obj _OPT_MODE is_equal 'source';  
   then  
     _DISPLAY_MODE='source';  
     eval ${_UNSET} msm_code;  
     eval ${_UNSET} msm_modes;  
     eval ${_UNSET} msm_viewer;  
     eval ${_UNSET} msm_viewers;  
     eval "${return_ok}";  
   fi;  
   
   case "${_OPT_MODE}" in  
     '')                         # automatic mode  
       case "${_OPT_DEVICE}" in  
         X*)  
           if obj DISPLAY is_empty;  
           then  
             error "main_set_mode(): \  
 no X display found for device ${_OPT_DEVICE}";  
           fi;  
           _DISPLAY_MODE='x';  
           eval ${_UNSET} msm_code;  
           eval ${_UNSET} msm_modes;  
           eval ${_UNSET} msm_viewer;  
           eval ${_UNSET} msm_viewers;  
           eval "${return_ok}";  
           ;;  
         ascii|cp1047|latin1|utf8)  
           if obj _DISPLAY_MODE is_not_equal 'text';  
           then  
             _DISPLAY_MODE='tty';  
           fi;  
           eval ${_UNSET} msm_code;  
           eval ${_UNSET} msm_modes;  
           eval ${_UNSET} msm_viewer;  
           eval ${_UNSET} msm_viewers;  
           eval "${return_ok}";  
           ;;  
       esac;  
       if obj DISPLAY is_empty;  
       then  
         _DISPLAY_MODE='tty';  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
       fi;  
   
       if obj _OPT_DEFAULT_MODES is_empty;  
       then  
         msm_modes="${_DEFAULT_MODES}";  
       else  
         msm_modes="${_OPT_DEFAULT_MODES}";  
       fi;  
       ;;  
     text)  
       _DISPLAY_MODE='text';  
       eval ${_UNSET} msm_code;  
       eval ${_UNSET} msm_modes;  
       eval ${_UNSET} msm_viewer;  
       eval ${_UNSET} msm_viewers;  
       eval "${return_ok}";  
       ;;  
     tty)  
       _DISPLAY_MODE='tty';  
       eval ${_UNSET} msm_code;  
       eval ${_UNSET} msm_modes;  
       eval ${_UNSET} msm_viewer;  
       eval ${_UNSET} msm_viewers;  
       eval "${return_ok}";  
       ;;  
     *)                          # display mode was given  
       if obj DISPLAY is_empty;  
       then  
         error "main_set_mode(): \  
 you must be in X Window for ${_OPT_MODE} mode.";  
       fi;  
       msm_modes="${_OPT_MODE}";  
       ;;  
   esac;  
   
   # only viewer modes are left  
   eval set x "$(list_from_split "${msm_modes}" ',')";  
   shift;  
   while test "$#" -gt 0;  
   do  
     m="$1";  
     shift;  
     case "$m" in  
       text)  
         _DISPLAY_MODE='text';  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
         ;;  
       tty)  
         _DISPLAY_MODE='tty';  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
         ;;  
       x)  
         if obj _OPT_VIEWER_X is_not_empty;  
         then  
           msm_viewers="${_OPT_VIEWER_X}";  
         else  
           msm_viewers="${_VIEWER_X}";  
         fi;  
         msm_viewer="$(_get_first_prog "${msm_viewers}")";  
         if is_not_equal "$?" 0;  
         then  
           continue;  
         fi;  
         _DISPLAY_PROG="${msm_viewer}";  
         _DISPLAY_MODE='x';  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
         ;;  
       X)  
         _DISPLAY_MODE='X';  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
         ;;  
       dvi)  
         if obj _OPT_VIEWER_DVI is_not_empty;  
         then  
           msm_viewers="${_OPT_VIEWER_DVI}";  
         else  
           msm_viewers="${_VIEWER_DVI}";  
         fi;  
         msm_viewer="$(_get_first_prog "${msm_viewers}")";  
         if is_not_equal "$?" 0;  
         then  
           continue;  
         fi;  
         _DISPLAY_PROG="${msm_viewer}";  
         _DISPLAY_MODE="dvi";  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
         ;;  
       pdf)  
         if obj _OPT_VIEWER_PDF is_not_empty;  
         then  
           msm_viewers="${_OPT_VIEWER_PDF}";  
         else  
           msm_viewers="${_VIEWER_PDF}";  
         fi;  
         msm_viewer="$(_get_first_prog "${msm_viewers}")";  
         if is_not_equal "$?" 0;  
         then  
           continue;  
         fi;  
         _DISPLAY_PROG="${msm_viewer}";  
         _DISPLAY_MODE="pdf";  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
         ;;  
       ps)  
         if obj _OPT_VIEWER_PS is_not_empty;  
         then  
           msm_viewers="${_OPT_VIEWER_PS}";  
         else  
           msm_viewers="${_VIEWER_PS}";  
         fi;  
         msm_viewer="$(_get_first_prog "${msm_viewers}")";  
         if is_not_equal "$?" 0;  
         then  
           continue;  
         fi;  
         _DISPLAY_PROG="${msm_viewer}";  
         _DISPLAY_MODE="ps";  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
         ;;  
       html)  
         if obj _OPT_VIEWER_HTML is_not_empty;  
         then  
           msm_viewers="${_OPT_VIEWER_HTML}";  
         else  
           msm_viewers="${_VIEWER_HTML}";  
         fi;  
         msm_viewer="$(_get_first_prog "${msm_viewers}")";  
         if is_not_equal "$?" 0;  
         then  
           continue;  
         fi;  
         _DISPLAY_PROG="${msm_viewer}";  
         _DISPLAY_MODE=html;  
         eval ${_UNSET} msm_code;  
         eval ${_UNSET} msm_modes;  
         eval ${_UNSET} msm_viewer;  
         eval ${_UNSET} msm_viewers;  
         eval "${return_ok}";  
         ;;  
     esac;  
   done;  
   eval ${_UNSET} msm_code;  
   eval ${_UNSET} msm_modes;  
   eval ${_UNSET} msm_viewer;  
   eval ${_UNSET} msm_viewers;  
   error "main_set_mode(): no suitable display mode found.";  
 } # main_set_mode()  
   
   
 # _get_first_prog (<proglist>)  
 #  
 # Retrieve first argument that represents an existing program in $PATH.  
 # Local function for main_set_mode().  
 #  
 # Arguments: 1; a comma-separated list of commands (with options),  
 #               like $_VIEWER_*.  
 #  
 # Return  : `1' if none found, `0' if found.  
 # Output  : the argument that succeded.  
 #  
 # Variable prefix: _gfp  
 #  
 _get_first_prog()  
 {  
   if is_equal "$#" 0;  
   then  
     error "_get_first_prog() needs 1 argument.";  
   fi;  
   if is_empty "$1";  
   then  
     return "${_BAD}";  
   fi;  
   eval set x "$(list_from_split "$1" ',')";  
   shift;  
   for i  
   do  
     _gfp_i="$i";  
     if obj _gfp_i is_empty;  
     then  
       continue;  
     fi;  
     if eval is_prog "$(get_first_essential ${_gfp_i})";  
     then  
       cat <<EOF  
 ${_gfp_i}  
 EOF  
       eval ${_UNSET} _gfp_i;  
       return "${_GOOD}";  
     fi;  
   done;  
   eval ${_UNSET} _gfp_i;  
   return "${_BAD}";  
 } # _get_first_prog() of main_set_mode()  
   
   
 landmark '17: main_do_fileargs()';  
 #######################################################################  
 # main_do_fileargs ()  
 #  
 # Process filespec arguments in $_FILEARGS.  
 #  
 # Globals:  
 #   in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')  
 #  
 # Variable prefix: mdfa  
 #  
 main_do_fileargs()  
 {  
   func_check main_do_fileargs = 0 "$@";  
   mdfa_exitcode="${_BAD}";  
   eval set x "${_FILEARGS}";  
   shift;  
   eval ${_UNSET} _FILEARGS;  
   # temporary storage of all input to $_TMP_CAT  
   while test "$#" -ge 2;  
   do  
     # test for `s name' arguments, with `s' a 1-char standard section  
     mdfa_filespec="$1";  
     shift;  
     case "${mdfa_filespec}" in  
       '')  
         continue;  
         ;;  
       '-')  
         if register_file '-';  
         then  
           mdfa_exitcode="${_GOOD}";  
         fi;  
         continue;  
         ;;  
       ?)  
         if list_has_not _MAN_AUTO_SEC "${mdfa_filespec}";  
         then  
           if do_filearg "${mdfa_filespec}";  
           then  
             mdfa_exitcode="${_GOOD}";  
           fi;  
           continue;  
         fi;  
         mdfa_name="$1";  
         case "${mdfa_name}" in  
           */*|man:*|*\(*\)|*."${mdfa_filespec}")  
             if do_filearg "${mdfa_filespec}";  
             then  
               mdfa_exitcode="${_GOOD}";  
             fi;  
             continue;  
             ;;  
         esac;  
         if do_filearg "man:${mdfa_name}(${mdfa_filespec})";  
         then  
           mdfa_exitcode="${_GOOD}";  
           shift;  
           continue;  
         else  
           if do_filearg "${mdfa_filespec}";  
           then  
             mdfa_exitcode="${_GOOD}";  
           fi;  
           continue;  
         fi;  
         ;;  
       *)  
         if do_filearg "${mdfa_filespec}";  
         then  
           mdfa_exitcode="${_GOOD}";  
         fi;  
         continue;  
         ;;  
     esac;  
   done;                         # end of `s name' test  
   while test "$#" -gt 0;  
   do  
     mdfa_filespec="$1";  
     shift;  
     if do_filearg "${mdfa_filespec}";  
     then  
       mdfa_exitcode="${_GOOD}";  
     fi;  
   done;  
   if obj _DEBUG_KEEP_FILES is_not_yes;  
   then  
     rm -f "${_TMP_STDIN}";  
   fi;  
   if is_equal "${mdfa_exitcode}" "${_BAD}";  
   then  
     eval ${_UNSET} mdfa_exitcode;  
     eval ${_UNSET} mdfa_filespec;  
     eval ${_UNSET} mdfa_name;  
     eval "${return_bad}";  
   fi;  
   eval ${_UNSET} mdfa_exitcode;  
   eval ${_UNSET} mdfa_filespec;  
   eval ${_UNSET} mdfa_name;  
   eval "${return_ok}";  
 } # main_do_fileargs()  
   
   
 landmark '18: main_set_resources()';  
 ########################################################################  
 # main_set_resources ()  
 #  
 # Determine options for setting X resources with $_DISPLAY_PROG.  
 #  
 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME  
 #  
 # Variable prefix: msr  
 #  
 main_set_resources()  
 {  
   func_check main_set_resources = 0 "$@";  
   # $msr_prog   viewer program  
   # $msr_rl     resource list  
   msr_title="$(get_first_essential \  
                  "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";  
   _OUTPUT_FILE_NAME='';  
   eval set x "${msr_title}";  
   shift;  
   until is_equal "$#" 0;  
   do  
     msr_n="$1";  
     case "${msr_n}" in  
     '')  
       continue;  
       ;;  
     ,*)  
       msr_n="$(echo x"$1" | sed -e 's/^x,,*//')";  
       ;;  
     esac  
     if obj msr_n is_empty;  
     then  
       continue;  
     fi;  
     if obj _OUTPUT_FILE_NAME is_not_empty;  
     then  
       _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"',';  
     fi;  
     _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}";  
     shift;  
   done;  
   case "${_OUTPUT_FILE_NAME}" in  
   '')  
     _OUTPUT_FILE_NAME='-';  
     ;;  
   ,*)  
     error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";  
     ;;  
   esac;  
   _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";  
   
   if obj _DISPLAY_PROG is_empty;  
   then                          # for example, for groff mode  
     _DISPLAY_ARGS='';  
     eval ${_UNSET} msr_n;  
     eval ${_UNSET} msr_prog;  
     eval ${_UNSET} msr_rl;  
     eval ${_UNSET} msr_title;  
     eval "${return_ok}";  
   fi;  
   
   eval set x "${_DISPLAY_PROG}";  
   shift;  
   msr_prog="$(base_name "$1")";  
   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}";  
         ;;  
       xpdf)  
         list_append msr_rl '-papercolor' "${_OPT_BG}";  
         ;;  
     esac;  
   fi;  
   if obj _OPT_BW is_not_empty;  
   then  
     case "${msr_prog}" in  
       ghostview|gv|gxditview|xditview|xdvi)  
         _list_append msr_rl '-bw' "${_OPT_BW}";  
         ;;  
     esac;  
   fi;  
   if obj _OPT_FG is_not_empty;  
   then  
     case "${msr_prog}" in  
       ghostview|gv|gxditview|xditview|xdvi)  
         list_append msr_rl '-fg' "${_OPT_FG}";  
         ;;  
     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}";  
         ;;  
     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}";  
         ;;  
     esac;  
   fi;  
   if is_empty "${_OPT_RESOLUTION}";  
   then  
     _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}";  
     case "${msr_prog}" in  
       gxditview|xditview)  
         list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}";  
         ;;  
       xpdf)  
         case "${_DEFAULT_RESOLUTION}" in  
           75)  
             # 72dpi is '100'  
             list_append msr_rl '-z' '104';  
             ;;  
           100)  
             list_append msr_rl '-z' '139';  
             ;;  
         esac;  
         ;;  
     esac;  
   else  
     case "${msr_prog}" in  
       ghostview|gv|gxditview|xditview|xdvi)  
         list_append msr_rl '-resolution' "${_OPT_RESOLUTION}";  
         ;;  
       xpdf)  
         case "${_OPT_RESOLUTION}" in  
           75)  
             list_append msr_rl '-z' '104';  
             # '100' corresponds to 72dpi  
             ;;  
           100)  
             list_append msr_rl '-z' '139';  
             ;;  
         esac;  
         ;;  
     esac;  
   fi;  
   if is_yes "${_OPT_ICONIC}";  
   then  
     case "${msr_prog}" in  
       ghostview|gv|gxditview|xditview|xdvi)  
         list_append msr_rl '-iconic';  
         ;;  
     esac;  
   fi;  
   if is_yes "${_OPT_RV}";  
   then  
     case "${msr_prog}" in  
       ghostview|gv|gxditview|xditview|xdvi)  
         list_append msr_rl '-rv';  
         ;;  
     esac;  
   fi;  
   if is_not_empty "${_OPT_XRM}";  
   then  
     case "${msr_prog}" in  
       ghostview|gv|gxditview|xditview|xdvi|xpdf)  
         eval set x "${_OPT_XRM}";  
         shift;  
         for i  
         do  
           list_append msr_rl '-xrm' "$i";  
         done;  
         ;;  
     esac;  
   fi;  
   if is_not_empty "${msr_title}";  
   then  
     case "${msr_prog}" in  
       gxditview|xditview)  
         list_append msr_rl '-title' "${msr_title}";  
         ;;  
     esac;  
   fi;  
   _DISPLAY_ARGS="${msr_rl}";  
   eval ${_UNSET} msr_n;  
   eval ${_UNSET} msr_prog;  
   eval ${_UNSET} msr_rl;  
   eval ${_UNSET} msr_title;  
   eval "${return_ok}";  
 } # main_set_resources  
   
   
 landmark '19: main_display()';  
 ########################################################################  
 # main_display ()  
 #  
 # Do the actual display of the whole thing.  
 #  
 # Globals:  
 #   in: $_DISPLAY_MODE, $_OPT_DEVICE,  
 #       $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,  
 #       $_REGISTERED_TITLE, $_TMP_CAT,  
 #       $_OPT_PAGER $PAGER, $_MANOPT_PAGER,  
 #       $_OUTPUT_FILE_NAME  
 #  
 # Variable prefix: md  
 #  
 main_display()  
 {  
   func_check main_display = 0 "$@";  
   
   export md_addopts;  
   export md_groggy;  
   export md_modefile;  
   
   if obj _TMP_CAT is_non_empty_file;  
   then  
     md_modefile="${_OUTPUT_FILE_NAME}";  
   else  
     clean_up;  
     echo2 'groffer: empty input.';  
     eval ${_UNSET} md_modefile;  
     eval "${return_ok}";  
   fi;  
   case "${_DISPLAY_MODE}" in  
     groff)  
       _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";  
       if obj _OPT_DEVICE is_not_empty;  
       then  
         _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";  
       fi;  
       md_groggy="$(tmp_cat | eval grog "${md_options}")";  
       trap_clean;  
       if obj _OPT_V is_yes;  
       then  
         echo "File:            ${md_modefile}";  
         echo "Mode:            ${_DISPLAY_MODE}";  
         echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";  
         eval "${md_groggy}" "${_ADDOPTS_GROFF}";  
         clean_up;  
       else  
         # start a new shell program to get another process ID.  
         /bin/sh -c '  
           set -e;  
           test -f "${md_modefile}" && rm -f "${md_modefile}";  
           mv "${_TMP_CAT}" "${md_modefile}";  
           cat "${md_modefile}" | \  
           (  
             clean_up()  
             {  
               if test -d "${_TMP_DIR}";  
               then  
                 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;  
               fi;  
             }  
             trap clean_up 0 2>${_NULL_DEV} || :;  
             eval "${md_groggy}" "${_ADDOPTS_GROFF}";  
           ) &'  
       fi;  
       ;;  
     text|tty)  
       case "${_OPT_DEVICE}" in  
         '')  
           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} ${_ADDOPTS_POST}";  
       md_groggy="$(tmp_cat | grog -T${md_device})";  
       if obj _DISPLAY_MODE is_equal 'text';  
       then  
         if obj _OPT_V is_yes;  
         then  
           echo "File:            ${md_modefile}";  
           echo "Mode:            ${_DISPLAY_MODE}";  
           echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";  
           eval "${md_groggy}" "${md_addopts}";  
         else  
           tmp_cat | eval "${md_groggy}" "${md_addopts}";  
         fi;  
       else  
         md_pager='';  
         for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \  
                  'less -r -R' 'more' 'pager' 'cat'  
         do  
           md_p="$p";  
           if eval is_prog ${md_p};  
           then                # no "" for is_prog() allows args for $p  
             md_pager="${md_p}";  
             break;  
           fi;  
         done;  
         if obj md_pager is_empty;  
         then  
           error 'main_display(): no pager program found for tty mode';  
         fi;  
         if obj _OPT_V is_yes;  
         then  
           echo "File:            ${md_modefile}";  
           echo "Mode:            ${_DISPLAY_MODE}";  
           echo "Display program: ${md_pager}";  
           eval "${md_groggy}" "${md_addopts}";  
         else  
           tmp_cat | eval "${md_groggy}" "${md_addopts}" | \  
                     eval "${md_pager}";  
         fi;  
       fi;  
       clean_up;  
       ;;  
     source)  
       tmp_cat;  
       clean_up;  
       ;;  
   
     #### viewer modes  
   
     dvi)  
       case "${_OPT_DEVICE}" in  
         ''|dvi) do_nothing; ;;  
         *)  
           warning "main_display(): \  
 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"  
           ;;  
       esac;  
       md_modefile="${md_modefile}".dvi;  
       md_groggy="$(tmp_cat | grog -Tdvi)";  
       _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)";  
       _do_display;  
       ;;  
     pdf)  
       case "${_OPT_DEVICE}" in  
         ''|ps)  
           do_nothing;  
           ;;  
         *)  
           warning "main_display(): \  
 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";  
           ;;  
       esac;  
       md_groggy="$(tmp_cat | grog -Tps)";  
       trap_clean;  
       if obj _OPT_V is_yes;  
       then  
         echo "File:            ${md_modefile}.pdf";  
         echo "Mode:            ${_DISPLAY_MODE}";  
         echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";  
         eval "${md_groggy}" "${_ADDOPTS_GROFF}";  
         clean_up;  
       else  
         # start a new shell program to get another process ID.  
         /bin/sh -c '  
           set -e;  
           _psfile="${md_modefile}.ps";  
           md_modefile="${md_modefile}.pdf";  
           test -f "${_psfile}" && rm -f "${_psfile}";  
           test -f "${md_modefile}" && rm -f "${md_modefile}";  
           cat "${_TMP_CAT}" | \  
             eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${_psfile}";  
           gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \  
              -sOutputFile="${md_modefile}" -c save pop -f "${_psfile}";  
           if test _"${_DEBUG_KEEP_FILES}"_ != _yes_;  
           then  
             test -f "${_psfile}" && rm -f "${_psfile}";  
             test -f "${_TMP_CAT}" && rm -f "${_TMP_CAT}";  
           fi;  
           (  
             clean_up() {  
               if test -d "${_TMP_DIR}";  
               then  
                 rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;  
               fi;  
             }  
             trap clean_up 0 2>${_NULL_DEV} || :;  
             eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${md_modefile}";  
           ) &'  
       fi;  
       ;;  
     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)";  
       _do_display;  
       ;;  
     x)  
       case "${_OPT_DEVICE}" in  
       X*)  
         md_device="${_OPT_DEVICE}"  
         ;;  
       *)  
         case "${_OPT_RESOLUTION}" in  
         100)  
           md_device='X100';  
           if obj _OPT_GEOMETRY is_empty  
           then  
             case "${_DISPLAY_PROG}" in  
             gxditview|xditview)  
               # add width of 800dpi for resolution of 100dpi to the args  
               list_append _DISPLAY_ARGS '-geometry' '800';  
               ;;  
             esac;  
           fi;  
           ;;  
         *)  
           md_device='X75-12';  
           ;;  
         esac  
       esac;  
       md_groggy="$(tmp_cat | grog -T${md_device} -Z)";  
       _do_display;  
       ;;  
     X)  
       case "${_OPT_DEVICE}" in  
       '')  
         md_groggy="$(tmp_cat | grog -X)";  
         ;;  
       X*|dvi|html|lbp|lj4|ps)  
         # these devices work with  
         md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";  
         ;;  
       *)  
         warning "main_display(): \  
 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";  
         md_groggy="$(tmp_cat | grog -Z)";  
         ;;  
       esac;  
       _do_display;  
       ;;  
     *)  
       error "main_display(): unknown mode \`${_DISPLAY_MODE}'";  
       ;;  
   esac;  
   eval ${_UNSET} md_addopts;  
   eval ${_UNSET} md_device;  
   eval ${_UNSET} md_groggy;  
   eval ${_UNSET} md_modefile;  
   eval ${_UNSET} md_options;  
   eval ${_UNSET} md_p;  
   eval ${_UNSET} md_pager;  
   eval "${return_ok}";  
 } # main_display()  
   
   
 # $md_modefile and $md_groggy come from main_display()  
 _do_display()  
 {  
   func_check _do_display = 0 "$@";  
   trap_clean;  
   if obj _OPT_V is_yes;  
   then  
     echo "File:            ${md_modefile}";  
     echo "Mode:            ${_DISPLAY_MODE}";  
     echo "Display program: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";  
     eval "${md_groggy}" "${_ADDOPTS_GROFF}";  
     clean_up;  
   else  
     # start a new shell program for another process ID and better  
     # cleaning-up of the temporary files.  
     /bin/sh -c '  
       set -e;  
       test -f "${md_modefile}" && rm -f "${md_modefile}";  
       cat "${_TMP_CAT}" | \  
         eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}";  
       if test _"${_DEBUG_KEEP_FILES}"_ != _yes_;  
       then  
         rm -f "${_TMP_CAT}";  
       fi;  
       (  
         clean_up() {  
           if test -d "${_TMP_DIR}";  
           then  
             rm -f -r "'${_TMP_DIR}'" >${_NULL_DEV} 2>&1 || :;  
           fi;  
         }  
         trap clean_up 0 2>${_NULL_DEV} || :;  
         eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "${md_modefile}";  
       ) &'  
   fi;  
   eval "${return_ok}";  
 } # _do_display() 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!  
   main_init;  
   main_parse_MANOPT;  
   main_parse_args "$@";  
   main_set_mode;  
   main_do_fileargs;  
   main_set_resources;  
   main_display;  
   eval "${return_ok}";  
 }  
   
 landmark '20: end of function definitions';  
   
 ########################################################################  
   
 main "$@";  

Legend:
Removed from v.1.30  
changed lines
  Added in v.1.31

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26