Home | History | Annotate | Line # | Download | only in groffer
      1 #! /bin/sh
      2 
      3 # groffer - display groff files
      4 
      5 # Source file position: <groff-source>/contrib/groffer/groffer2.sh
      6 # Installed position: <prefix>/lib/groff/groffer/groffer2.sh
      7 
      8 # This file should not be run independently.  It is called by
      9 # `groffer.sh' in the source or by the installed `groffer' program.
     10 
     11 # Copyright (C) 2001,2002,2003,2004,2005
     12 # Free Software Foundation, Inc.
     13 # Written by Bernd Warken
     14 
     15 # Last update: 22 August 2005
     16 
     17 # This file is part of `groffer', which is part of `groff'.
     18 
     19 # `groff' is free software; you can redistribute it and/or modify it
     20 # under the terms of the GNU General Public License as published by
     21 # the Free Software Foundation; either version 2, or (at your option)
     22 # any later version.
     23 
     24 # `groff' is distributed in the hope that it will be useful, but
     25 # WITHOUT ANY WARRANTY; without even the implied warranty of
     26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     27 # General Public License for more details.
     28 
     29 # You should have received a copy of the GNU General Public License
     30 # along with `groff'; see the files COPYING and LICENSE in the top
     31 # directory of the `groff' source.  If not, write to the Free Software
     32 # Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301,
     33 # USA.
     34 
     35 
     36 ########################################################################
     37 #             Test of rudimentary shell functionality
     38 ########################################################################
     39 
     40 
     41 ########################################################################
     42 # Test of `unset'
     43 #
     44 export _UNSET;
     45 export _foo;
     46 _foo=bar;
     47 _res="$(unset _foo 2>&1)";
     48 if unset _foo >${_NULL_DEV} 2>&1 && \
     49    test _"${_res}"_ = __ && test _"${_foo}"_ = __
     50 then
     51   _UNSET='unset';
     52   eval "${_UNSET}" _foo;
     53   eval "${_UNSET}" _res;
     54 else
     55   _UNSET=':';
     56 fi;
     57 
     58 
     59 ########################################################################
     60 # Test of `test'.
     61 #
     62 if test a = a && test a != b && test -f "${_GROFFER_SH}"
     63 then
     64   :;
     65 else
     66   echo '"test" did not work.' >&2;
     67   exit "${_ERROR}";
     68 fi;
     69 
     70 
     71 ########################################################################
     72 # Test of `echo' and the `$()' construct.
     73 #
     74 if echo '' >${_NULL_DEV}
     75 then
     76   :;
     77 else
     78   echo '"echo" did not work.' >&2;
     79   exit "${_ERROR}";
     80 fi;
     81 if test _"$(t1="$(echo te)" &&
     82             t2="$(echo '')" &&
     83             t3="$(echo 'st')" &&
     84             echo "${t1}${t2}${t3}")"_ \
     85      != _test_
     86 then
     87   echo 'The "$()" construct did not work' >&2;
     88   exit "${_ERROR}";
     89 fi;
     90 
     91 
     92 ########################################################################
     93 # Test of sed program; test in groffer.sh is not valid here.
     94 #
     95 if test _"$(echo red | sed -e 's/r/s/')"_ != _sed_
     96 then
     97   echo 'The sed program did not work.' >&2;
     98   exit "${_ERROR}";
     99 fi;
    100 
    101 
    102 ########################################################################
    103 # Test of function definitions.
    104 #
    105 _t_e_s_t_f_u_n_c_()
    106 {
    107   return 0;
    108 }
    109 
    110 if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV}
    111 then
    112   :;
    113 else
    114   echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2;
    115   exit "${_ERROR}";
    116 fi;
    117 
    118 
    119 ########################################################################
    120 #                    debug - diagnostic messages
    121 ########################################################################
    122 
    123 export _DEBUG_STACKS;
    124 _DEBUG_STACKS='no';		# disable stack output in each function
    125 #_DEBUG_STACKS='yes';		# enable stack output in each function
    126 
    127 export _DEBUG_LM;
    128 _DEBUG_LM='no';			# disable landmark messages
    129 #_DEBUG_LM='yes';		# enable landmark messages
    130 
    131 export _DEBUG_KEEP_FILES;
    132 _DEBUG_KEEP_FILES='no'		# disable file keeping in temporary dir
    133 #_DEBUG_KEEP_FILES='yes'	# enable file keeping in temporary dir
    134 
    135 export _DEBUG_PRINT_PARAMS;
    136 _DEBUG_PRINT_PARAMS='no';	# disable printing of all parameters
    137 #_DEBUG_PRINT_PARAMS='yes';	# enable printing of all parameters
    138 
    139 export _DEBUG_PRINT_SHELL;
    140 _DEBUG_PRINT_SHELL='no';	# disable printing of the shell name
    141 #_DEBUG_PRINT_SHELL='yes';	# enable printing of the shell name
    142 
    143 export _DEBUG_PRINT_TMPDIR;
    144 _DEBUG_PRINT_TMPDIR='no';	# disable printing of the temporary dir
    145 #_DEBUG_PRINT_TMPDIR='yes';	# enable printing of the temporary dir
    146 
    147 export _DEBUG_USER_WITH_STACK;
    148 _DEBUG_USER_WITH_STACK='no';	# disable stack dump in error_user()
    149 #_DEBUG_USER_WITH_STACK='yes';	# enable stack dump in error_user()
    150 
    151 # determine all --debug* options
    152 case " $*" in
    153 *\ --debug*)
    154   case " $* " in
    155   *' --debug '*)
    156     # _DEBUG_STACKS='yes';
    157     # _DEBUG_LM='yes';
    158     _DEBUG_KEEP_FILES='yes';
    159     _DEBUG_PRINT_PARAMS='yes';
    160     _DEBUG_PRINT_SHELL='yes';
    161     _DEBUG_PRINT_TMPDIR='yes';
    162     _DEBUG_USER_WITH_STACK='yes';
    163     ;;
    164   esac;
    165   d=' --debug-all --debug-keep --debug-lm --debug-params --debug-shell '\
    166 '--debug-stacks --debug-tmpdir --debug-user ';
    167   for i
    168   do
    169     case "$i" in
    170     --debug-s)
    171       echo 'The abbreviation --debug-s has multiple options: '\
    172 '--debug-shell and --debug-stacks.' >&2
    173       exit "${_ERROR}";
    174       ;;
    175     esac;
    176     case "$d" in
    177     *\ ${i}*)
    178       # extract whole word of abbreviation $i
    179       s="$(cat <<EOF | sed -n -e 's/^.* \('"$i"'[^ ]*\) .*/\1/p'
    180 $d
    181 EOF
    182 )"
    183       case "$s" in
    184       '') continue; ;;
    185       --debug-all)
    186         _DEBUG_STACKS='yes';
    187         _DEBUG_LM='yes';
    188         _DEBUG_KEEP_FILES='yes';
    189         _DEBUG_PRINT_PARAMS='yes';
    190         _DEBUG_PRINT_SHELL='yes';
    191         _DEBUG_PRINT_TMPDIR='yes';
    192         _DEBUG_USER_WITH_STACK='yes';
    193         ;;
    194       --debug-keep)
    195         _DEBUG_PRINT_TMPDIR='yes';
    196         _DEBUG_KEEP_FILES='yes';
    197         ;;
    198       --debug-lm)
    199         _DEBUG_LM='yes';
    200         ;;
    201       --debug-params)
    202         _DEBUG_PRINT_PARAMS='yes';
    203         ;;
    204       --debug-shell)
    205         _DEBUG_PRINT_SHELL='yes';
    206         ;;
    207       --debug-stacks)
    208         _DEBUG_STACKS='yes';
    209         ;;
    210       --debug-tmpdir)
    211         _DEBUG_PRINT_TMPDIR='yes';
    212         ;;
    213       --debug-user)
    214         _DEBUG_USER_WITH_STACK='yes';
    215         ;;
    216       esac;
    217       ;;
    218     esac;
    219   done
    220   ;;
    221 esac;
    222 
    223 if test _"${_DEBUG_PRINT_PARAMS}"_ = _yes_
    224 then
    225   echo "parameters: $@" >&2;
    226 fi;
    227 
    228 if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_
    229 then
    230   if test _"${_SHELL}"_ = __
    231   then
    232     if test _"${POSIXLY_CORRECT}"_ = _y_
    233     then
    234       echo 'shell: bash as /bin/sh (none specified)' >&2;
    235     else
    236       echo 'shell: /bin/sh (none specified)' >&2;
    237     fi;
    238   else
    239     echo "shell: ${_SHELL}" >&2;
    240   fi;
    241 fi;
    242 
    243 
    244 ########################################################################
    245 #                       Environment Variables
    246 ########################################################################
    247 
    248 # Environment variables that exist only for this file start with an
    249 # underscore letter.  Global variables to this file are written in
    250 # upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
    251 # start with an underline and use only lower case letters and
    252 # underlines, e.g.  $_local_variable .
    253 
    254 #   [A-Z]*     system variables,      e.g. $MANPATH
    255 #   _[A-Z_]*   global file variables, e.g. $_MAN_PATH
    256 #   _[a-z_]*   temporary variables,   e.g. $_manpath
    257 
    258 # Due to incompatibilities of the `ash' shell, the name of loop
    259 # variables in `for' must be single character
    260 #   [a-z]      local loop variables,   e.g. $i
    261 
    262 
    263 ########################################################################
    264 # read-only variables (global to this file)
    265 ########################################################################
    266 
    267 # function return values; `0' means ok; other values are error codes
    268 export _ALL_EXIT;
    269 export _BAD;
    270 export _GOOD;
    271 export _NO;
    272 export _OK;
    273 export _YES;
    274 
    275 _GOOD='0';			# return ok
    276 _BAD='1';			# return negatively, error code `1'
    277 # $_ERROR was already defined as `7' in groffer.sh.
    278 
    279 _NO="${_BAD}";
    280 _YES="${_GOOD}";
    281 _OK="${_GOOD}";
    282 
    283 # quasi-functions, call with `eval', e.g `eval "${return_ok}"'
    284 export return_ok;
    285 export return_good;
    286 export return_bad;
    287 export return_yes;
    288 export return_no;
    289 export return_error;
    290 export return_var;
    291 return_ok="func_pop; return ${_OK}";
    292 return_good="func_pop; return ${_GOOD}";
    293 return_bad="func_pop; return ${_BAD}";
    294 return_yes="func_pop; return ${_YES}";
    295 return_no="func_pop; return ${_NO}";
    296 return_error="func_pop; return ${_ERROR}";
    297 return_var="func_pop; return";	# add number, e.g. `eval "${return_var} $n'
    298 
    299 
    300 export _DEFAULT_MODES;
    301 _DEFAULT_MODES='x,ps,tty';
    302 export _DEFAULT_RESOLUTION;
    303 _DEFAULT_RESOLUTION='75';
    304 
    305 export _DEFAULT_TTY_DEVICE;
    306 _DEFAULT_TTY_DEVICE='latin1';
    307 
    308 # _VIEWER_* viewer programs for different modes (only X is necessary)
    309 # _VIEWER_* a comma-separated list of viewer programs (with options)
    310 export _VIEWER_DVI;		# viewer program for dvi mode
    311 export _VIEWER_HTML_TTY;	# viewer program for html mode in tty
    312 export _VIEWER_HTML_X;		# viewer program for html mode in X
    313 export _VIEWER_PDF;		# viewer program for pdf mode
    314 export _VIEWER_PS;		# viewer program for ps mode
    315 export _VIEWER_X;		# viewer program for X mode
    316 _VIEWER_DVI='kdvi,xdvi,dvilx';
    317 _VIEWER_HTML_TTY='lynx';
    318 _VIEWER_HTML_X='konqueror,mozilla,netscape,galeon,opera,amaya,arena';
    319 _VIEWER_PDF='kghostview --scale 1.45,ggv,xpdf,acroread,kpdf';
    320 _VIEWER_PS='kghostview --scale 1.45,ggv,gv,ghostview,gs_x11,gs';
    321 _VIEWER_X='gxditview,xditview';
    322 
    323 # Search automatically in standard sections `1' to `8', and in the
    324 # traditional sections `9', `n', and `o'.  On many systems, there
    325 # exist even more sections, mostly containing a set of man pages
    326 # special to a specific program package.  These aren't searched for
    327 # automatically, but must be specified on the command line.
    328 export _MAN_AUTO_SEC_LIST;
    329 _MAN_AUTO_SEC_LIST="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'";
    330 export _MAN_AUTO_SEC_CHARS;
    331 _MAN_AUTO_SEC_CHARS='[123456789no]';
    332 
    333 export _SPACE_SED;
    334 _SPACE_SED='['"${_SP}${_TAB}"']';
    335 
    336 export _SPACE_CASE;
    337 _SPACE_CASE='[\'"${_SP}"'\'"${_TAB}"']';
    338 
    339 export _PROCESS_ID;		# for shutting down the program
    340 _PROCESS_ID="$$";
    341 
    342 
    343 ############ the command line options of the involved programs
    344 #
    345 # The naming scheme for the options environment names is
    346 # $_OPTS_<prog>_<length>[_<argspec>]
    347 #
    348 # <prog>:    program name GROFFER, GROFF, or CMDLINE (for all
    349 #            command line options)
    350 # <length>:  LONG (long options) or SHORT (single character options)
    351 # <argspec>: ARG for options with argument, NA for no argument;
    352 #            without _<argspec> both the ones with and without arg.
    353 #
    354 # Each option that takes an argument must be specified with a
    355 # trailing : (colon).
    356 
    357 # exports
    358 export _OPTS_GROFFER_SHORT_NA;
    359 export _OPTS_GROFFER_SHORT_ARG;
    360 export _OPTS_GROFFER_LONG_NA;
    361 export _OPTS_GROFFER_LONG_ARG;
    362 export _OPTS_GROFF_SHORT_NA;
    363 export _OPTS_GROFF_SHORT_ARG;
    364 export _OPTS_GROFF_LONG_NA;
    365 export _OPTS_GROFF_LONG_ARG;
    366 export _OPTS_X_SHORT_ARG;
    367 export _OPTS_X_SHORT_NA;
    368 export _OPTS_X_LONG_ARG;
    369 export _OPTS_X_LONG_NA;
    370 export _OPTS_MAN_SHORT_ARG;
    371 export _OPTS_MAN_SHORT_NA;
    372 export _OPTS_MAN_LONG_ARG;
    373 export _OPTS_MAN_LONG_NA;
    374 export _OPTS_MANOPT_SHORT_ARG;
    375 export _OPTS_MANOPT_SHORT_NA;
    376 export _OPTS_MANOPT_LONG_ARG;
    377 export _OPTS_MANOPT_LONG_NA;
    378 export _OPTS_CMDLINE_SHORT_NA;
    379 export _OPTS_CMDLINE_SHORT_ARG;
    380 export _OPTS_CMDLINE_LONG_NA;
    381 export _OPTS_CMDLINE_LONG_ARG;
    382 
    383 ###### groffer native options
    384 
    385 _OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
    386 _OPTS_GROFFER_SHORT_ARG="'T'";
    387 
    388 _OPTS_GROFFER_LONG_NA="'auto' \
    389 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
    390 'debug' 'debug-all' 'debug-keep' 'debug-lm' 'debug-params' 'debug-shell' \
    391 'debug-stacks' 'debug-tmpdir' 'debug-user' 'default' 'do-nothing' 'dvi' \
    392 'groff' 'help' 'intermediate-output' 'html' 'man' \
    393 'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \
    394 'text' 'text-device' \
    395 'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
    396 
    397 _OPTS_GROFFER_LONG_ARG="\
    398 'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \
    399 'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \
    400 'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \
    401 'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \
    402 'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'";
    403 
    404 ##### groffer options inhereted from groff
    405 
    406 _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
    407 'R' 's' 'S' 't' 'U' 'z'";
    408 _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
    409 'w' 'W'";
    410 _OPTS_GROFF_LONG_NA="";
    411 _OPTS_GROFF_LONG_ARG="";
    412 
    413 ##### groffer options inhereted from the X Window toolkit
    414 
    415 _OPTS_X_SHORT_NA="";
    416 _OPTS_X_SHORT_ARG="";
    417 
    418 _OPTS_X_LONG_NA="'iconic' 'rv'";
    419 
    420 _OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
    421 'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \
    422 'resolution' 'title' 'xrm'";
    423 
    424 ###### groffer options inherited from man
    425 
    426 _OPTS_MAN_SHORT_NA="";
    427 _OPTS_MAN_SHORT_ARG="";
    428 
    429 _OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'ditroff' \
    430 'local-file' 'location' 'troff' 'update'";
    431 
    432 _OPTS_MAN_LONG_ARG="'locale' 'manpath' \
    433 'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
    434 
    435 ###### additional options for parsing $MANOPT only
    436 
    437 _OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
    438 'V' 'w' 'Z'";
    439 _OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
    440 
    441 _OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
    442 'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \
    443 'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'";
    444 
    445 _OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
    446 'config_file' 'encoding' 'extension' 'locale'";
    447 
    448 ###### collections of command line options
    449 
    450 _OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA} \
    451 ${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
    452 _OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \
    453 ${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
    454 
    455 _OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
    456 ${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
    457 _OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
    458 ${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
    459 
    460 
    461 ########################################################################
    462 # read-write variables (global to this file)
    463 ########################################################################
    464 
    465 export _ALL_PARAMS;		# All options and file name parameters
    466 export _ADDOPTS_GROFF;		# Transp. options for groff (`eval').
    467 export _ADDOPTS_POST;		# Transp. options postproc (`eval').
    468 export _ADDOPTS_X;		# Transp. options X postproc (`eval').
    469 export _APROPOS_PROG;		# Program to run apropos.
    470 export _APROPOS_SECTIONS;	# Sections for different --apropos-*.
    471 export _DEFAULT_MODES;		# Set default modes.
    472 export _DISPLAY_MODE;		# Display mode.
    473 export _DISPLAY_PROG;		# Viewer program to be used for display.
    474 export _DISPLAY_ARGS;		# X resources for the viewer program.
    475 export _FILEARGS;		# Stores filespec parameters.
    476 export _FILESPEC_ARG;		# Stores the actual filespec parameter.
    477 export _FUNC_STACK;		# Store debugging information.
    478 export _REGISTERED_TITLE;	# Processed file names.
    479 # _HAS_* from availability tests
    480 export _HAS_COMPRESSION;	# `yes' if gzip compression is available
    481 export _HAS_BZIP;		# `yes' if bzip2 compression is available
    482 # _MAN_* finally used configuration of man searching
    483 export _MAN_ALL;		# search all man pages per filespec
    484 export _MAN_ENABLE;		# enable search for man pages
    485 export _MAN_EXT;		# extension for man pages
    486 export _MAN_FORCE;		# force file parameter to be man pages
    487 export _MAN_IS_SETUP;		# setup man variables only once
    488 export _MAN_LANG;		# language for man pages
    489 export _MAN_LANG2;		# language for man pages
    490 export _MAN_LANG_DONE;		# language dirs added to man path
    491 export _MAN_PATH;		# search path for man pages
    492 export _MAN_SEC;		# sections for man pages; sep. `:'
    493 export _MAN_SEC_DONE;		# sections added to man path
    494 export _MAN_SYS;		# system names for man pages; sep. `,'
    495 export _MAN_SYS;		# system names added to man path
    496 # _MANOPT_* as parsed from $MANOPT
    497 export _MANOPT_ALL;		# $MANOPT --all
    498 export _MANOPT_EXTENSION;	# $MANOPT --extension
    499 export _MANOPT_LANG;		# $MANOPT --locale
    500 export _MANOPT_PATH;		# $MANOPT --manpath
    501 export _MANOPT_PAGER;		# $MANOPT --pager
    502 export _MANOPT_SEC;		# $MANOPT --sections
    503 export _MANOPT_SYS;		# $MANOPT --systems
    504 # _OPT_* as parsed from groffer command line
    505 export _OPT_ALL;		# display all suitable man pages.
    506 export _OPT_APROPOS;		# call `apropos' program.
    507 export _OPT_BD;			# set border color in some modes.
    508 export _OPT_BG;			# set background color in some modes.
    509 export _OPT_BW;			# set border width in some modes.
    510 export _OPT_DEFAULT_MODES;	# `,'-list of modes when no mode given.
    511 export _OPT_DEVICE;		# device option.
    512 export _OPT_DO_NOTHING;		# do nothing in main_display().
    513 export _OPT_DISPLAY;		# set X display.
    514 export _OPT_FG;			# set foreground color in some modes.
    515 export _OPT_FN;			# set font in some modes.
    516 export _OPT_GEOMETRY;		# set size and position of viewer in X.
    517 export _OPT_ICONIC;		# -iconic option for X viewers.
    518 export _OPT_LANG;		# set language for man pages
    519 export _OPT_LOCATION;		# print processed file names to stderr
    520 export _OPT_MODE;		# values: X, tty, Q, Z, ""
    521 export _OPT_MANPATH;		# manual setting of path for man-pages
    522 export _OPT_PAGER;		# specify paging program for tty mode
    523 export _OPT_RESOLUTION;		# set X resolution in dpi
    524 export _OPT_RV;			# reverse fore- and background colors.
    525 export _OPT_SECTIONS;		# sections for man page search
    526 export _OPT_SYSTEMS;		# man pages of different OS's
    527 export _OPT_TITLE;		# title for gxditview window
    528 export _OPT_TEXT_DEVICE;	# set device for tty mode.
    529 export _OPT_V;			# groff option -V.
    530 export _OPT_VIEWER_DVI;		# viewer program for dvi mode
    531 export _OPT_VIEWER_PDF;		# viewer program for pdf mode
    532 export _OPT_VIEWER_PS;		# viewer program for ps mode
    533 export _OPT_VIEWER_HTML;	# viewer program for html mode
    534 export _OPT_VIEWER_X;		# viewer program for x mode
    535 export _OPT_WHATIS;		# print the man description
    536 export _OPT_XRM;		# specify X resource.
    537 export _OPT_Z;			# groff option -Z.
    538 export _OUTPUT_FILE_NAME;	# output generated, see main_set_res..()
    539 export _VIEWER_TERMINAL;	# viewer options for terminal (--*-viewer-tty)
    540 # _TMP_* temporary directory and files
    541 export _TMP_DIR;		# groffer directory for temporary files
    542 export _TMP_CAT;		# stores concatenation of everything
    543 export _TMP_STDIN;		# stores stdin, if any
    544 
    545 # these variables are preset in section `Preset' after the rudim. test
    546 
    547 
    548 ########################################################################
    549 # Preset and reset of read-write global variables
    550 ########################################################################
    551 
    552 
    553 export _START_DIR;		# directory at start time of the script
    554 _START_DIR="$(pwd)";
    555 
    556 # For variables that can be reset by option `--default', see reset().
    557 
    558 _FILEARGS='';
    559 
    560 # _HAS_* from availability tests
    561 _HAS_COMPRESSION='';
    562 _HAS_BZIP='';
    563 
    564 # _TMP_* temporary files
    565 _TMP_DIR='';
    566 _TMP_CAT='';
    567 _TMP_CONF='';
    568 _TMP_STDIN='';
    569 
    570 
    571 ########################################################################
    572 # reset ()
    573 #
    574 # Reset the variables that can be affected by options to their default.
    575 #
    576 reset()
    577 {
    578   if test "$#" -ne 0
    579   then
    580     error "reset() does not have arguments.";
    581   fi;
    582 
    583   _ADDOPTS_GROFF='';
    584   _ADDOPTS_POST='';
    585   _ADDOPTS_X='';
    586   _APROPOS_PROG='';
    587   _APROPOS_SECTIONS='';
    588   _DISPLAY_ARGS='';
    589   _DISPLAY_MODE='';
    590   _DISPLAY_PROG='';
    591   _REGISTERED_TITLE='';
    592 
    593   # _MAN_* finally used configuration of man searching
    594   _MAN_ALL='no';
    595   _MAN_ENABLE='yes';		# do search for man-pages
    596   _MAN_EXT='';
    597   _MAN_FORCE='no';		# first local file, then search man page
    598   _MAN_IS_SETUP='no';
    599   _MAN_LANG='';
    600   _MAN_LANG2='';
    601   _MAN_PATH='';
    602   _MAN_SEC='';
    603   _MAN_SEC_DONE='no';
    604   _MAN_SYS='';
    605   _MAN_SYS_DONE='no';
    606 
    607   # _MANOPT_* as parsed from $MANOPT
    608   _MANOPT_ALL='no';
    609   _MANOPT_EXTENSION='';
    610   _MANOPT_LANG='';
    611   _MANOPT_PATH='';
    612   _MANOPT_PAGER='';
    613   _MANOPT_SEC='';
    614   _MANOPT_SYS='';
    615 
    616   # _OPT_* as parsed from groffer command line
    617   _OPT_ALL='no';
    618   _OPT_APROPOS='no';
    619   _OPT_BD='';
    620   _OPT_BG='';
    621   _OPT_BW='';
    622   _OPT_DEFAULT_MODES='';
    623   _OPT_DEVICE='';
    624   _OPT_DISPLAY='';
    625   _OPT_DO_NOTHING='no';
    626   _OPT_FG='';
    627   _OPT_FN='';
    628   _OPT_GEOMETRY='';
    629   _OPT_ICONIC='no';
    630   _OPT_LANG='';
    631   _OPT_LOCATION='no';
    632   _OPT_MODE='';
    633   _OPT_MANPATH='';
    634   _OPT_PAGER='';
    635   _OPT_RESOLUTION='';
    636   _OPT_RV='no';
    637   _OPT_SECTIONS='';
    638   _OPT_SYSTEMS='';
    639   _OPT_TITLE='';
    640   _OPT_TEXT_DEVICE='';
    641   _OPT_V='no';
    642   _OPT_VIEWER_DVI='';
    643   _OPT_VIEWER_PDF='';
    644   _OPT_VIEWER_PS='';
    645   _OPT_VIEWER_HTML='';
    646   _OPT_VIEWER_X='';
    647   _OPT_WHATIS='no';
    648   _OPT_XRM='';
    649   _OPT_Z='no';
    650   _VIEWER_TERMINAL='no';
    651 }
    652 
    653 reset;
    654 
    655 
    656 ########################################################################
    657 #          Functions for error handling and debugging
    658 ########################################################################
    659 
    660 
    661 ##############
    662 # echo1 (<text>*)
    663 #
    664 # Output to stdout.
    665 #
    666 # Arguments : arbitrary text including `-'.
    667 #
    668 echo1()
    669 {
    670   cat <<EOF
    671 $@
    672 EOF
    673 }
    674 
    675 
    676 ##############
    677 # echo2 (<text>*)
    678 #
    679 # Output to stderr.
    680 #
    681 # Arguments : arbitrary text.
    682 #
    683 echo2()
    684 {
    685   cat >&2 <<EOF
    686 $@
    687 EOF
    688 }
    689 
    690 
    691 ##############
    692 # landmark (<text>)
    693 #
    694 # Print <text> to standard error as a debugging aid.
    695 #
    696 # Globals: $_DEBUG_LM
    697 #
    698 landmark()
    699 {
    700   if test _"${_DEBUG_LM}"_ = _yes_
    701   then
    702     echo2 "LM: $*";
    703   fi;
    704 }
    705 
    706 landmark "1: debugging functions";
    707 
    708 
    709 ##############
    710 # clean_up ()
    711 #
    712 # Clean up at exit.
    713 #
    714 clean_up()
    715 {
    716   cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1;
    717   if test _${_DEBUG_KEEP_FILES}_ = _yes_
    718   then
    719     echo2 "Kept temporary directory ${_TMP_DIR}."
    720   else
    721     if test _"${_TMP_DIR}"_ != __
    722     then
    723       if test -d "${_TMP_DIR}" || test -f "${_TMP_DIR}"
    724       then
    725         rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1;
    726       fi; 
    727     fi;
    728   fi;
    729 }
    730 
    731 
    732 #############
    733 # diag (text>*)
    734 #
    735 # Output a diagnostic message to stderr
    736 #
    737 diag()
    738 {
    739   echo2 '>>>>>'"$*";
    740 }
    741 
    742 
    743 #############
    744 # error (<text>*)
    745 #
    746 # Print an error message to standard error, print the function stack,
    747 # exit with an error condition.  The argument should contain the name
    748 # of the function from which it was called.  This is for system errors.
    749 #
    750 error()
    751 {
    752   case "$#" in
    753     1) echo2 'groffer error: '"$1"; ;;
    754     *) echo2 'groffer error: wrong number of arguments in error().'; ;;
    755   esac;
    756   func_stack_dump;
    757   if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
    758   then
    759     : >"${_TMP_DIR}"/,error;
    760   fi;
    761   exit "${_ERROR}";
    762 }
    763 
    764 
    765 #############
    766 # error_user (<text>*)
    767 #
    768 # Print an error message to standard error; exit with an error condition.
    769 # The error is supposed to be produce by the user.  So the funtion stack
    770 # is omitted.
    771 #
    772 error_user()
    773 {
    774   case "$#" in
    775     1)
    776       echo2 'groffer error: '"$1";
    777        ;;
    778     *)
    779       echo2 'groffer error: wrong number of arguments in error_user().';
    780       ;;
    781   esac;
    782   if test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_
    783   then
    784     func_stack_dump;
    785   fi;
    786   if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
    787   then
    788     : >"${_TMP_DIR}"/,error;
    789   fi;
    790   exit "${_ERROR}";
    791 }
    792 
    793 
    794 #############
    795 # exit_test ()
    796 #
    797 # Test whether the former command ended with error().  Exit again.
    798 #
    799 # Globals: $_ERROR
    800 #
    801 exit_test()
    802 {
    803   if test "$?" = "${_ERROR}"
    804   then
    805     exit ${_ERROR};
    806   fi;
    807   if test _"${_TMP_DIR}"_ != __ && test -f "${_TMP_DIR}"/,error
    808   then
    809     exit ${_ERROR};
    810   fi;
    811 }
    812 
    813 
    814 #############
    815 # func_check (<func_name> <rel_op> <nr_args> "$@")
    816 #
    817 # Check number of arguments and register to _FUNC_STACK.
    818 #
    819 # Arguments: >=3
    820 #   <func_name>: name of the calling function.
    821 #   <rel_op>:    a relational operator: = != < > <= >=
    822 #   <nr_args>:   number of arguments to be checked against <operator>
    823 #   "$@":        the arguments of the calling function.
    824 #
    825 # Variable prefix: fc
    826 #
    827 func_check()
    828 {
    829   if test "$#" -lt 3
    830   then
    831     error 'func_check() needs at least 3 arguments.';
    832   fi;
    833   fc_fname="$1";
    834   case "$3" in
    835     1)
    836       fc_nargs="$3";
    837       fc_s='';
    838       ;;
    839     0|[2-9])
    840       fc_nargs="$3";
    841       fc_s='s';
    842       ;;
    843     *)
    844       error "func_check(): third argument must be a digit.";
    845       ;;
    846   esac;
    847   case "$2" in
    848     '='|'-eq')
    849       fc_op='-eq';
    850       fc_comp='exactly';
    851       ;;
    852     '>='|'-ge')
    853       fc_op='-ge';
    854       fc_comp='at least';
    855       ;;
    856     '<='|'-le')
    857       fc_op='-le';
    858       fc_comp='at most';
    859       ;;
    860     '<'|'-lt')
    861       fc_op='-lt';
    862       fc_comp='less than';
    863       ;;
    864     '>'|'-gt')
    865       fc_op='-gt';
    866       fc_comp='more than';
    867       ;;
    868     '!='|'-ne')
    869       fc_op='-ne';
    870       fc_comp='not';
    871       ;;
    872     *)
    873       error \
    874         'func_check(): second argument is not a relational operator.';
    875       ;;
    876   esac;
    877   shift;
    878   shift;
    879   shift;
    880   if test "$#" "${fc_op}" "${fc_nargs}"
    881   then
    882     do_nothing;
    883   else
    884     error "func_check(): \
    885 ${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
    886   fi;
    887   func_push "${fc_fname}";
    888   if test _"${_DEBUG_STACKS}"_ = _yes_
    889   then
    890     echo2 '+++ '"${fc_fname} $@";
    891     echo2 '>>> '"${_FUNC_STACK}";
    892   fi;
    893   eval ${_UNSET} fc_comp;
    894   eval ${_UNSET} fc_fname;
    895   eval ${_UNSET} fc_nargs;
    896   eval ${_UNSET} fc_op;
    897   eval ${_UNSET} fc_s;
    898 }
    899 
    900 
    901 #############
    902 # func_pop ()
    903 #
    904 # Retrieve the top element from the stack.
    905 #
    906 # The stack elements are separated by `!'; the popped element is
    907 # identical to the original element, except that all `!' characters
    908 # were removed.
    909 #
    910 # Arguments: 1
    911 #
    912 func_pop()
    913 {
    914   if test "$#" -ne 0
    915   then
    916     error 'func_pop() does not have arguments.';
    917   fi;
    918   case "${_FUNC_STACK}" in
    919   '')
    920     if test _"${_DEBUG_STACKS}"_ = _yes_
    921     then
    922       error 'func_pop(): stack is empty.';
    923     fi;
    924     ;;
    925   *!*)
    926     # split at first bang `!'.
    927     _FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')";
    928     exit_test;
    929     ;;
    930   *)
    931     _FUNC_STACK='';
    932     ;;
    933   esac;
    934   if test _"${_DEBUG_STACKS}"_ = _yes_
    935   then
    936     echo2 '<<< '"${_FUNC_STACK}";
    937   fi;
    938 }
    939 
    940 
    941 #############
    942 # func_push (<element>)
    943 #
    944 # Store another element to stack.
    945 #
    946 # The stack elements are separated by `!'; if <element> contains a `!'
    947 # it is removed first.
    948 #
    949 # Arguments: 1
    950 #
    951 # Variable prefix: fp
    952 #
    953 func_push()
    954 {
    955   if test "$#" -ne 1
    956   then
    957     error 'func_push() needs 1 argument.';
    958   fi;
    959   case "$1" in
    960   *'!'*)
    961     # remove all bangs `!'.
    962     fp_element="$(echo1 "$1" | sed -e 's/!//g')";
    963     exit_test;
    964     ;;
    965   *)
    966     fp_element="$1";
    967     ;;
    968   esac;
    969   if test _"${_FUNC_STACK}"_ = __
    970   then
    971     _FUNC_STACK="${fp_element}";
    972   else
    973     _FUNC_STACK="${fp_element}!${_FUNC_STACK}";
    974   fi;
    975   eval ${_UNSET} fp_element;
    976 }
    977 
    978 
    979 #############
    980 # func_stack_dump ()
    981 #
    982 # Print the content of the stack.  Ignore the arguments.
    983 #
    984 func_stack_dump()
    985 {
    986   diag 'call stack: '"${_FUNC_STACK}";
    987 }
    988 
    989 
    990 ########################################################################
    991 #                        System Test
    992 ########################################################################
    993 
    994 landmark "2: system test";
    995 
    996 # Test the availability of the system utilities used in this script.
    997 
    998 
    999 ########################################################################
   1000 # Test of function `sed'.
   1001 #
   1002 
   1003 if test _"$(echo xTesTx \
   1004            | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
   1005            | sed -e 's|T|t|g')"_ != _test_
   1006 then
   1007   error 'Test of "sed" command failed.';
   1008 fi;
   1009 
   1010 
   1011 ########################################################################
   1012 # Test of function `cat'.
   1013 #
   1014 if test _"$(echo test | cat)"_ != _test_
   1015 then
   1016   error 'Test of "cat" command failed.';
   1017 fi;
   1018 
   1019 
   1020 ########################################################################
   1021 # Test for compression.
   1022 #
   1023 if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_
   1024 then
   1025   _HAS_COMPRESSION='yes';
   1026   if echo1 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \
   1027      && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
   1028                              | bzip2 -d -c 2>${_NULL_DEV})"_ \
   1029              = _test_
   1030   then
   1031     _HAS_BZIP='yes';
   1032   else
   1033     _HAS_BZIP='no';
   1034   fi;
   1035 else
   1036   _HAS_COMPRESSION='no';
   1037   _HAS_BZIP='no';
   1038 fi;
   1039 
   1040 
   1041 ########################################################################
   1042 #       Definition of normal Functions in alphabetical order
   1043 ########################################################################
   1044 landmark "3: functions";
   1045 
   1046 ########################################################################
   1047 # apropos_filespec ()
   1048 #
   1049 # Setup for the --apropos* options
   1050 #
   1051 apropos_filespec()
   1052 {
   1053 
   1054   func_check apropos_filespec '=' 0 "$@";
   1055   if obj _OPT_APROPOS is_yes
   1056   then
   1057     eval to_tmp_line \
   1058       "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
   1059     exit_test;
   1060     if obj _APROPOS_PROG is_empty
   1061     then
   1062       error 'apropos_filespec: apropos_setup() must be run first.';
   1063     fi;
   1064     if obj _APROPOS_SECTIONS is_empty
   1065     then
   1066       if obj _OPT_SECTIONS is_empty
   1067       then
   1068         s='^.*(.*).*$';
   1069       else
   1070         s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/://g')"']';
   1071       fi;
   1072     else
   1073       s='^.*(['"${_APROPOS_SECTIONS}"']';
   1074     fi;
   1075     eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \
   1076       sed -n -e '
   1077 /^'"${_FILESPEC_ARG}"': /p
   1078 /'"$s"'/p
   1079 ' | \
   1080       sort |\
   1081       sed -e '
   1082 s/^\(.* (..*)\)  *-  *\(.*\)$/\.br\n\.TP 15\n\.BR \1\n\2/
   1083 ' >>"${_TMP_CAT}";
   1084   fi;
   1085   eval "${return_ok}";
   1086 }
   1087 
   1088 
   1089 ########################################################################
   1090 # apropos_setup ()
   1091 #
   1092 # Setup for the --apropos* options
   1093 #
   1094 apropos_setup()
   1095 {
   1096   func_check apropos_setup '=' 0 "$@";
   1097   if obj _OPT_APROPOS is_yes
   1098   then
   1099     if is_prog apropos
   1100     then
   1101       _APROPOS_PROG='apropos';
   1102     elif is_prog man
   1103     then
   1104       if man --apropos man >${_NULL_DEV} 2>${_NULL_DEV}
   1105       then
   1106         _APROPOS_PROG='man --apropos';
   1107       elif man -k man >${_NULL_DEV} 2>${_NULL_DEV}
   1108       then
   1109         _APROPOS_PROG='man -k';
   1110       fi;
   1111     fi;
   1112     if obj _APROPOS_PROG is_empty
   1113     then
   1114       error 'apropos_setup: no apropos program available.';
   1115     fi;
   1116     to_tmp_line '.TH GROFFER APROPOS';
   1117   fi;
   1118   eval "${return_ok}";
   1119 }
   1120 
   1121 
   1122 ########################################################################
   1123 # base_name (<path>)
   1124 #
   1125 # Get the file name part of <path>, i.e. delete everything up to last
   1126 # `/' from the beginning of <path>.  Remove final slashes, too, to get a
   1127 # non-empty output.
   1128 #
   1129 # Arguments : 1
   1130 # Output    : the file name part (without slashes)
   1131 #
   1132 # Variable prefix: bn
   1133 #
   1134 base_name()
   1135 {
   1136   func_check base_name = 1 "$@";
   1137   bn_name="$1";
   1138   case "${bn_name}" in
   1139     */)
   1140       # delete all final slashes
   1141       bn_name="$(echo1 "${bn_name}" | sed -e 's|//*$||')";
   1142       exit_test;
   1143       ;;
   1144   esac;
   1145   case "${bn_name}" in
   1146     /|'')
   1147       eval ${_UNSET} bn_name;
   1148       eval "${return_bad}";
   1149       ;;
   1150     */*)
   1151       # delete everything before and including the last slash `/'.
   1152       echo1 "${bn_name}" | sed -e 's|^.*//*\([^/]*\)$|\1|';
   1153       ;;
   1154     *)
   1155       obj bn_name echo1;
   1156       ;;
   1157   esac;
   1158   eval ${_UNSET} bn_name;
   1159   eval "${return_ok}";
   1160 }
   1161 
   1162 
   1163 ########################################################################
   1164 # cat_z (<file>)
   1165 #
   1166 # Decompress if possible or just print <file> to standard output.
   1167 #
   1168 # gzip, bzip2, and .Z decompression is supported.
   1169 #
   1170 # Arguments: 1, a file name.
   1171 # Output: the content of <file>, possibly decompressed.
   1172 #
   1173 if test _"${_HAS_COMPRESSION}"_ = _yes_
   1174 then
   1175   cat_z()
   1176   {
   1177     func_check cat_z = 1 "$@";
   1178     case "$1" in
   1179       '')
   1180         error 'cat_z(): empty file name';
   1181         ;;
   1182       '-')
   1183         error 'cat_z(): for standard input use save_stdin()';
   1184         ;;
   1185     esac;
   1186     if obj _HAS_BZIP is_yes
   1187     then
   1188       if bzip2 -t "$1" 2>${_NULL_DEV}
   1189       then
   1190         bzip2 -c -d "$1" 2>${_NULL_DEV};
   1191         eval "${return_ok}";
   1192       fi;
   1193     fi;
   1194     gzip -c -d -f "$1" 2>${_NULL_DEV};
   1195     eval "${return_ok}";
   1196   }
   1197 else
   1198   cat_z()
   1199   {
   1200     func_check cat_z = 1 "$@";
   1201     cat "$1";
   1202     eval "${return_ok}";
   1203   }
   1204 fi;
   1205 
   1206 
   1207 ########################################################################
   1208 # clean_up ()
   1209 #
   1210 # Do the final cleaning up before exiting; used by the trap calls.
   1211 #
   1212 # defined above
   1213 
   1214 
   1215 ########################################################################
   1216 # diag (<text>*)
   1217 #
   1218 # Print marked message to standard error; useful for debugging.
   1219 #
   1220 # defined above
   1221 
   1222 
   1223 ########################################################################
   1224 landmark '4: dirname()*';
   1225 ########################################################################
   1226 
   1227 #######################################################################
   1228 # dirname_append (<dir> <name>)
   1229 #
   1230 # Append `name' to `dir' with clean handling of `/'.
   1231 #
   1232 # Arguments : 2
   1233 # Output    : the generated new directory name <dir>/<name>
   1234 #
   1235 dirname_append()
   1236 {
   1237   func_check dirname_append = 2 "$@";
   1238   if is_empty "$1"
   1239   then
   1240     error "dir_append(): first argument is empty.";
   1241   fi;
   1242   if is_empty "$2"
   1243   then
   1244     echo1 "$1";
   1245   else
   1246     dirname_chop "$1"/"$2";
   1247   fi;
   1248   eval "${return_ok}";
   1249 }
   1250 
   1251 
   1252 ########################################################################
   1253 # dirname_chop (<name>)
   1254 #
   1255 # Remove unnecessary slashes from directory name.
   1256 #
   1257 # Argument: 1, a directory name.
   1258 # Output:   path without double, or trailing slashes.
   1259 #
   1260 # Variable prefix: dc
   1261 #
   1262 dirname_chop()
   1263 {
   1264   func_check dirname_chop = 1 "$@";
   1265   # replace all multiple slashes by a single slash `/'.
   1266   dc_res="$(echo1 "$1" | sed -e 's|///*|/|g')";
   1267   exit_test;
   1268   case "${dc_res}" in
   1269   ?*/)
   1270     # remove trailing slash '/';
   1271     echo1 "${dc_res}" | sed -e 's|/$||';
   1272     ;;
   1273   *)
   1274     obj dc_res echo1
   1275     ;;
   1276   esac;
   1277   eval ${_UNSET} dc_res;
   1278   eval "${return_ok}";
   1279 }
   1280 
   1281 
   1282 ########################################################################
   1283 # do_filearg (<filearg>)
   1284 #
   1285 # Append the file, man-page, or standard input corresponding to the
   1286 # argument to the temporary file.  If this is compressed in the gzip
   1287 # or Z format it is decompressed.  A title element is generated.
   1288 #
   1289 # Argument either:
   1290 #   - name of an existing file.
   1291 #   - `-' to represent standard input (several times allowed).
   1292 #   - `man:name.(section)' the man-page for `name' in `section'.
   1293 #   - `man:name.section' the man-page for `name' in `section'.
   1294 #   - `man:name' the man-page for `name' in the lowest `section'.
   1295 #   - `name.section' the man-page for `name' in `section'.
   1296 #   - `name' the man-page for `name' in the lowest `section'.
   1297 # Globals :
   1298 #   $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
   1299 #
   1300 # Output  : none
   1301 # Return  : $_GOOD if found, ${_BAD} otherwise.
   1302 #
   1303 # Variable prefix: df
   1304 #
   1305 do_filearg()
   1306 {
   1307   func_check do_filearg = 1 "$@";
   1308   df_filespec="$1";
   1309   # store sequence into positional parameters
   1310   case "${df_filespec}" in
   1311   '')
   1312     eval ${_UNSET} df_filespec;
   1313     eval "${return_good}";
   1314     ;;
   1315   '-')
   1316     register_file '-';
   1317     eval ${_UNSET} df_filespec;
   1318     eval "${return_good}";
   1319     ;;
   1320   */*)			       # with directory part; so no man search
   1321     set 'File';
   1322     ;;
   1323   *)
   1324     if obj _MAN_ENABLE is_yes
   1325     then
   1326       if obj _MAN_FORCE is_yes
   1327       then
   1328         set 'Manpage' 'File';
   1329       else
   1330         set 'File' 'Manpage';
   1331       fi;
   1332       else
   1333       set 'File';
   1334     fi;
   1335     ;;
   1336   esac;
   1337   for i
   1338   do
   1339     case "$i" in
   1340     File)
   1341       if test -f "${df_filespec}"
   1342       then
   1343         if test -r "${df_filespec}"
   1344         then
   1345           register_file "${df_filespec}";
   1346           eval ${_UNSET} df_filespec;
   1347           eval ${_UNSET} df_no_man;
   1348           eval "${return_good}";
   1349         else
   1350           echo2 "could not read \`${df_filespec}'";
   1351           eval ${_UNSET} df_filespec;
   1352           eval ${_UNSET} df_no_man;
   1353           eval "${return_bad}";
   1354         fi;
   1355       else
   1356         if obj df_no_man is_not_empty
   1357         then
   1358           if obj _OPT_WHATIS is_yes
   1359           then
   1360             to_tmp_line "This is neither a file nor a man page."
   1361           else
   1362             echo2 "\`${df_filespec}' is neither a file nor a man page."
   1363           fi;
   1364         fi;
   1365         df_no_file=yes;
   1366         continue;
   1367       fi;
   1368       ;;
   1369     Manpage)			# parse filespec as man page
   1370       if obj _MAN_IS_SETUP is_not_yes
   1371       then
   1372         man_setup;
   1373       fi;
   1374       if man_do_filespec "${df_filespec}"
   1375       then
   1376         eval ${_UNSET} df_filespec;
   1377         eval ${_UNSET} df_no_file;
   1378         eval "${return_good}";
   1379       else
   1380         if obj df_no_file is_not_empty
   1381         then
   1382           if obj _OPT_WHATIS is_yes
   1383           then
   1384             to_tmp_line "This is neither a file nor a man page."
   1385           else
   1386             echo2 "\`${df_filespec}' is neither a file nor a man page."
   1387           fi;
   1388         fi;
   1389         df_no_man=yes;
   1390         continue;
   1391       fi;
   1392       ;;
   1393     esac;
   1394   done;
   1395   eval ${_UNSET} df_filespec;
   1396   eval ${_UNSET} df_no_file;
   1397   eval ${_UNSET} df_no_man;
   1398   eval "${return_bad}";
   1399 } # do_filearg()
   1400 
   1401 
   1402 ########################################################################
   1403 # do_nothing ()
   1404 #
   1405 # Dummy function.
   1406 #
   1407 do_nothing()
   1408 {
   1409   eval return "${_OK}";
   1410 }
   1411 
   1412 
   1413 ########################################################################
   1414 # echo2 (<text>*)
   1415 #
   1416 # Print to standard error with final line break.
   1417 #
   1418 # defined above
   1419 
   1420 
   1421 ########################################################################
   1422 # error (<text>*)
   1423 #
   1424 # Print error message and exit with error code.
   1425 #
   1426 # defined above
   1427 
   1428 
   1429 ########################################################################
   1430 # exit_test ()
   1431 #
   1432 # Test whether the former command ended with error().  Exit again.
   1433 #
   1434 # defined above
   1435 
   1436 
   1437 ########################################################################
   1438 # func_check (<func_name> <rel_op> <nr_args> "$@")
   1439 #
   1440 # Check number of arguments and register to _FUNC_STACK.
   1441 #
   1442 # Arguments: >=3
   1443 #   <func_name>: name of the calling function.
   1444 #   <rel_op>:    a relational operator: = != < > <= >=
   1445 #   <nr_args>:   number of arguments to be checked against <operator>
   1446 #   "$@":        the arguments of the calling function.
   1447 #
   1448 # defined above
   1449 
   1450 #########################################################################
   1451 # func_pop ()
   1452 #
   1453 # Delete the top element from the function call stack.
   1454 #
   1455 # defined above
   1456 
   1457 
   1458 ########################################################################
   1459 # func_push (<element>)
   1460 #
   1461 # Store another element to function call stack.
   1462 #
   1463 # defined above
   1464 
   1465 
   1466 ########################################################################
   1467 # func_stack_dump ()
   1468 #
   1469 # Print the content of the stack.
   1470 #
   1471 # defined above
   1472 
   1473 
   1474 ########################################################################
   1475 # get_first_essential (<arg>*)
   1476 #
   1477 # Retrieve first non-empty argument.
   1478 #
   1479 # Return  : `1' if all arguments are empty, `0' if found.
   1480 # Output  : the retrieved non-empty argument.
   1481 #
   1482 # Variable prefix: gfe
   1483 #
   1484 get_first_essential()
   1485 {
   1486   func_check get_first_essential '>=' 0 "$@";
   1487   if is_equal "$#" 0
   1488   then
   1489     eval "${return_ok}";
   1490   fi;
   1491   for i
   1492   do
   1493     gfe_var="$i";
   1494     if obj gfe_var is_not_empty
   1495     then
   1496       obj gfe_var echo1;
   1497       eval ${_UNSET} gfe_var;
   1498       eval "${return_ok}";
   1499     fi;
   1500   done;
   1501   eval ${_UNSET} gfe_var;
   1502   eval "${return_bad}";
   1503 }
   1504 
   1505 
   1506 ########################################################################
   1507 landmark '5: is_*()';
   1508 ########################################################################
   1509 
   1510 ########################################################################
   1511 # is_dir (<name>)
   1512 #
   1513 # Test whether `name' is a directory.
   1514 #
   1515 # Arguments : 1
   1516 # Return    : `0' if arg1 is a directory, `1' otherwise.
   1517 #
   1518 is_dir()
   1519 {
   1520   func_check is_dir '=' 1 "$@";
   1521   if test _"$1"_ != __ && test -d "$1" && test -r "$1"
   1522   then
   1523     eval "${return_yes}";
   1524   fi;
   1525   eval "${return_no}";
   1526 }
   1527 
   1528 
   1529 ########################################################################
   1530 # is_empty (<string>)
   1531 #
   1532 # Test whether `string' is empty.
   1533 #
   1534 # Arguments : <=1
   1535 # Return    : `0' if arg1 is empty or does not exist, `1' otherwise.
   1536 #
   1537 is_empty()
   1538 {
   1539   func_check is_empty '=' 1 "$@";
   1540   if test _"$1"_ = __
   1541   then
   1542     eval "${return_yes}";
   1543   fi;
   1544   eval "${return_no}";
   1545 }
   1546 
   1547 
   1548 ########################################################################
   1549 # is_equal (<string1> <string2>)
   1550 #
   1551 # Test whether `string1' is equal to <string2>.
   1552 #
   1553 # Arguments : 2
   1554 # Return    : `0' both arguments are equal strings, `1' otherwise.
   1555 #
   1556 is_equal()
   1557 {
   1558   func_check is_equal '=' 2 "$@";
   1559   if test _"$1"_ = _"$2"_
   1560   then
   1561     eval "${return_yes}";
   1562   fi;
   1563   eval "${return_no}";
   1564 }
   1565 
   1566 
   1567 ########################################################################
   1568 # is_existing (<name>)
   1569 #
   1570 # Test whether `name' is an existing file or directory.  Solaris 2.5 does
   1571 # not have `test -e'.
   1572 #
   1573 # Arguments : 1
   1574 # Return    : `0' if arg1 exists, `1' otherwise.
   1575 #
   1576 is_existing()
   1577 {
   1578   func_check is_existing '=' 1 "$@";
   1579   if test _"$1"_ = __
   1580   then
   1581     eval "${return_no}";
   1582   fi;
   1583   if test -f "$1" || test -d "$1" || test -c "$1"
   1584   then
   1585     eval "${return_yes}";
   1586   fi;
   1587   eval "${return_no}";
   1588 }
   1589 
   1590 
   1591 ########################################################################
   1592 # is_file (<name>)
   1593 #
   1594 # Test whether `name' is a readable file.
   1595 #
   1596 # Arguments : 1
   1597 # Return    : `0' if arg1 is a readable file, `1' otherwise.
   1598 #
   1599 is_file()
   1600 {
   1601   func_check is_file '=' 1 "$@";
   1602   if is_not_empty "$1" && test -f "$1" && test -r "$1"
   1603   then
   1604     eval "${return_yes}";
   1605   fi;
   1606   eval "${return_no}";
   1607 }
   1608 
   1609 
   1610 ########################################################################
   1611 # is_non_empty_file (<file_name>)
   1612 #
   1613 # Test whether `file_name' is a non-empty existing file.
   1614 #
   1615 # Arguments : <=1
   1616 # Return    :
   1617 #   `0' if arg1 is a non-empty existing file
   1618 #   `1' otherwise
   1619 #
   1620 is_non_empty_file()
   1621 {
   1622   func_check is_non_empty_file '=' 1 "$@";
   1623   if is_file "$1" && test -s "$1"
   1624   then
   1625     eval "${return_yes}";
   1626   fi;
   1627   eval "${return_no}";
   1628 }
   1629 
   1630 
   1631 ########################################################################
   1632 # is_not_dir (<name>)
   1633 #
   1634 # Test whether `name' is not a readable directory.
   1635 #
   1636 # Arguments : 1
   1637 # Return    : `0' if arg1 is a directory, `1' otherwise.
   1638 #
   1639 is_not_dir()
   1640 {
   1641   func_check is_not_dir '=' 1 "$@";
   1642   if is_dir "$1"
   1643   then
   1644     eval "${return_no}";
   1645   fi;
   1646   eval "${return_yes}";
   1647 }
   1648 
   1649 
   1650 ########################################################################
   1651 # is_not_empty (<string>)
   1652 #
   1653 # Test whether `string' is not empty.
   1654 #
   1655 # Arguments : <=1
   1656 # Return    : `0' if arg1 exists and is not empty, `1' otherwise.
   1657 #
   1658 is_not_empty()
   1659 {
   1660   func_check is_not_empty '=' 1 "$@";
   1661   if is_empty "$1"
   1662   then
   1663     eval "${return_no}";
   1664   fi;
   1665   eval "${return_yes}";
   1666 }
   1667 
   1668 
   1669 ########################################################################
   1670 # is_not_equal (<string1> <string2>)
   1671 #
   1672 # Test whether `string1' differs from `string2'.
   1673 #
   1674 # Arguments : 2
   1675 #
   1676 is_not_equal()
   1677 {
   1678   func_check is_not_equal '=' 2 "$@";
   1679   if is_equal "$1" "$2"
   1680   then
   1681     eval "${return_no}";
   1682   fi
   1683   eval "${return_yes}";
   1684 }
   1685 
   1686 
   1687 ########################################################################
   1688 # is_not_file (<filename>)
   1689 #
   1690 # Test whether `name' is a not readable file.
   1691 #
   1692 # Arguments : 1 (empty allowed)
   1693 #
   1694 is_not_file()
   1695 {
   1696   func_check is_not_file '=' 1 "$@";
   1697   if is_file "$1"
   1698   then
   1699     eval "${return_no}";
   1700   fi;
   1701   eval "${return_yes}";
   1702 }
   1703 
   1704 
   1705 ########################################################################
   1706 # is_not_prog ([<name> [<arg>*]])
   1707 #
   1708 # Verify that arg is a not program in $PATH.
   1709 #
   1710 # Arguments : >=0 (empty allowed)
   1711 #   more args are ignored, this allows to specify progs with arguments
   1712 #
   1713 is_not_prog()
   1714 {
   1715   func_check is_not_prog '>=' 0 "$@";
   1716   case "$#" in
   1717   0)
   1718     eval "${return_yes}";
   1719     ;;
   1720   *)
   1721     if where_is "$1" >${_NULL_DEV}
   1722     then
   1723       eval "${return_no}";
   1724     fi;
   1725     ;;
   1726   esac
   1727   eval "${return_yes}";
   1728 }
   1729 
   1730 
   1731 ########################################################################
   1732 # is_not_writable (<name>)
   1733 #
   1734 # Test whether `name' is a not a writable file or directory.
   1735 #
   1736 # Arguments : >=1 (empty allowed), more args are ignored
   1737 #
   1738 is_not_writable()
   1739 {
   1740   func_check is_not_writable '>=' 1 "$@";
   1741   if is_writable "$1"
   1742   then
   1743     eval "${return_no}";
   1744   fi;
   1745   eval "${return_yes}";
   1746 }
   1747 
   1748 
   1749 ########################################################################
   1750 # is_not_X ()
   1751 #
   1752 # Test whether not running in X Window by checking $DISPLAY
   1753 #
   1754 is_not_X()
   1755 {
   1756   func_check is_X '=' 0 "$@";
   1757   if obj DISPLAY is_empty
   1758   then
   1759     eval "${return_yes}";
   1760   fi;
   1761   eval "${return_no}";
   1762 }
   1763 
   1764 
   1765 ########################################################################
   1766 # is_not_yes (<string>)
   1767 #
   1768 # Test whether `string' is not "yes".
   1769 #
   1770 # Arguments : 1
   1771 #
   1772 is_not_yes()
   1773 {
   1774   func_check is_not_yes = 1 "$@";
   1775   if is_yes "$1"
   1776   then
   1777     eval "${return_no}";
   1778   fi;
   1779   eval "${return_yes}";
   1780 }
   1781 
   1782 
   1783 ########################################################################
   1784 # is_prog ([<name> [<arg>*]])
   1785 #
   1786 # Determine whether <name> is a program in $PATH
   1787 #
   1788 # Arguments : >=0 (empty allowed)
   1789 #   <arg>* are ignored, this allows to specify progs with arguments.
   1790 #
   1791 is_prog()
   1792 {
   1793   func_check is_prog '>=' 0 "$@";
   1794   case "$#" in
   1795   0)
   1796     eval "${return_no}";
   1797     ;;
   1798   *)
   1799     if where_is "$1" >${_NULL_DEV}
   1800     then
   1801       eval "${return_yes}";
   1802     fi;
   1803     ;;
   1804   esac
   1805   eval "${return_no}";
   1806 }
   1807 
   1808 
   1809 ########################################################################
   1810 # is_writable (<name>)
   1811 #
   1812 # Test whether `name' is a writable file or directory.
   1813 #
   1814 # Arguments : >=1 (empty allowed), more args are ignored
   1815 #
   1816 is_writable()
   1817 {
   1818   func_check is_writable '>=' 1 "$@";
   1819   if test _"$1"_ = __
   1820   then
   1821     eval "${return_no}";
   1822   fi;
   1823   if test -r "$1"
   1824   then
   1825     if test -w "$1"
   1826     then
   1827       eval "${return_yes}";
   1828     fi;
   1829   fi;
   1830   eval "${return_no}";
   1831 }
   1832 
   1833 
   1834 ########################################################################
   1835 # is_X ()
   1836 #
   1837 # Test whether running in X Window by checking $DISPLAY
   1838 #
   1839 is_X()
   1840 {
   1841   func_check is_X '=' 0 "$@";
   1842   if obj DISPLAY is_not_empty
   1843   then
   1844     eval "${return_yes}";
   1845   fi;
   1846   eval "${return_no}";
   1847 }
   1848 
   1849 
   1850 ########################################################################
   1851 # is_yes (<string>)
   1852 #
   1853 # Test whether `string' has value "yes".
   1854 #
   1855 # Return    : `0' if arg1 is `yes', `1' otherwise.
   1856 #
   1857 is_yes()
   1858 {
   1859   func_check is_yes '=' 1 "$@";
   1860   if is_equal "$1" 'yes'
   1861   then
   1862     eval "${return_yes}";
   1863   fi;
   1864   eval "${return_no}";
   1865 }
   1866 
   1867 
   1868 ########################################################################
   1869 # landmark ()
   1870 #
   1871 # Print debugging information on standard error if $_DEBUG_LM is `yes'.
   1872 #
   1873 # Globals: $_DEBUG_LM
   1874 #
   1875 # Defined in section `Debugging functions'.
   1876 
   1877 
   1878 ########################################################################
   1879 # leave ([<code>])
   1880 #
   1881 # Clean exit without an error or with <code>.
   1882 #
   1883 leave()
   1884 {
   1885   clean_up;
   1886   if test $# = 0
   1887   then
   1888     exit "${_OK}";
   1889   else
   1890     exit "$1";
   1891   fi;
   1892 }
   1893 
   1894 
   1895 ########################################################################
   1896 landmark '6: list_*()';
   1897 ########################################################################
   1898 #
   1899 # `list' is an object class that represents an array or list.  Its
   1900 # data consists of space-separated single-quoted elements.  So a list
   1901 # has the form "'first' 'second' '...' 'last'".  See list_append() for
   1902 # more details on the list structure.  The array elements of `list'
   1903 # can be get by `eval set x "$list"; shift`.
   1904 
   1905 
   1906 ########################################################################
   1907 # list_append (<list> <element>...)
   1908 #
   1909 # Arguments: >=2
   1910 #   <list>: a variable name for a list of single-quoted elements
   1911 #   <element>:  some sequence of characters.
   1912 # Output: none, but $<list> is set to
   1913 #   if <list> is empty:  "'<element>' '...'"
   1914 #   otherwise:           "$list '<element>' ..."
   1915 #
   1916 # Variable prefix: la
   1917 #
   1918 list_append()
   1919 {
   1920   func_check list_append '>=' 2 "$@";
   1921   la_name="$1";
   1922   eval la_list='"${'$1'}"';
   1923   shift;
   1924   for s
   1925   do
   1926     la_s="$s";
   1927     case "${la_s}" in
   1928     *\'*)
   1929       # escape each single quote by replacing each
   1930       # "'" (squote) by "'\''" (squote bslash squote squote);
   1931       # note that the backslash must be doubled in the following `sed'
   1932       la_element="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')";
   1933       exit_test;
   1934       ;;
   1935     '')
   1936       la_element="";
   1937       ;;
   1938     *)
   1939       la_element="${la_s}";
   1940       ;;
   1941     esac;
   1942     if obj la_list is_empty
   1943     then
   1944       la_list="'${la_element}'";
   1945     else
   1946       la_list="${la_list} '${la_element}'";
   1947     fi;
   1948   done;
   1949   eval "${la_name}"='"${la_list}"';
   1950   eval ${_UNSET} la_element;
   1951   eval ${_UNSET} la_list;
   1952   eval ${_UNSET} la_name;
   1953   eval ${_UNSET} la_s;
   1954   eval "${return_ok}";
   1955 }
   1956 
   1957 
   1958 ########################################################################
   1959 # list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
   1960 #
   1961 # Transform command line arguments into a normalized form.
   1962 #
   1963 # Options, option arguments, and file parameters are identified and
   1964 # output each as a single-quoted argument of its own.  Options and
   1965 # file parameters are separated by a '--' argument.
   1966 #
   1967 # Arguments: >=1
   1968 #   <pre_name>: common part of a set of 4 environment variable names:
   1969 #     $<pre_name>_SHORT_NA:  list of short options without an arg.
   1970 #     $<pre_name>_SHORT_ARG: list of short options that have an arg.
   1971 #     $<pre_name>_LONG_NA:   list of long options without an arg.
   1972 #     $<pre_name>_LONG_ARG:  list of long options that have an arg.
   1973 #   <cmdline_arg>...: the arguments from a command line, such as "$@",
   1974 #                     the content of a variable, or direct arguments.
   1975 #
   1976 # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
   1977 #
   1978 # Example:
   1979 #   list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
   1980 # If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
   1981 # none-empty option lists, this will result in printing:
   1982 #     '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
   1983 #
   1984 #   Use this function in the following way:
   1985 #     eval set x "$(args_norm PRE_NAME "$@")";
   1986 #     shift;
   1987 #     while test "$1" != '--'; do
   1988 #       case "$1" in
   1989 #       ...
   1990 #       esac;
   1991 #       shift;
   1992 #     done;
   1993 #     shift;         #skip '--'
   1994 #     # all positional parameters ("$@") left are file name parameters.
   1995 #
   1996 # Variable prefix: lfc
   1997 #
   1998 list_from_cmdline()
   1999 {
   2000   func_check list_from_cmdline '>=' 1 "$@";
   2001   lfc_short_n="$(obj_data "$1"_SHORT_NA)";  # short options, no argument
   2002   lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
   2003   lfc_long_n="$(obj_data "$1"_LONG_NA)";    # long options, no argument
   2004   lfc_long_a="$(obj_data "$1"_LONG_ARG)";   # long options, with argument
   2005   exit_test;
   2006   if obj lfc_short_n is_empty
   2007   then
   2008     error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
   2009   fi;
   2010   if obj lfc_short_a is_empty
   2011   then
   2012     error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
   2013   fi;
   2014   if obj lfc_long_n is_empty
   2015   then
   2016     error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
   2017   fi;
   2018   if obj lfc_long_a is_empty
   2019   then
   2020     error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
   2021   fi;
   2022 
   2023   shift;
   2024   if is_equal "$#" 0
   2025   then
   2026     echo1 --
   2027     eval ${_UNSET} lfc_fparams;
   2028     eval ${_UNSET} lfc_short_a;
   2029     eval ${_UNSET} lfc_short_n;
   2030     eval ${_UNSET} lfc_long_a;
   2031     eval ${_UNSET} lfc_long_n;
   2032     eval ${_UNSET} lfc_result;
   2033     eval "${return_ok}";
   2034   fi;
   2035 
   2036   lfc_fparams='';
   2037   lfc_result='';
   2038   while test "$#" -ge 1
   2039   do
   2040     lfc_arg="$1";
   2041     shift;
   2042     case "${lfc_arg}" in
   2043     --) break; ;;
   2044     --*=*)
   2045       # delete leading '--';
   2046       lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
   2047       lfc_with_equal="${lfc_abbrev}";
   2048       # extract option by deleting from the first '=' to the end
   2049       lfc_abbrev="$(echo1 "${lfc_with_equal}" | \
   2050                     sed -e 's/^\([^=]*\)=.*$/\1/')";
   2051       lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
   2052       exit_test;
   2053       if obj lfc_opt is_empty
   2054       then
   2055         error_user "--${lfc_abbrev} is not an option.";
   2056       else
   2057         # get the option argument by deleting up to first `='
   2058         lfc_optarg="$(echo1 "${lfc_with_equal}" | sed -e 's/^[^=]*=//')";
   2059         exit_test;
   2060         list_append lfc_result "--${lfc_opt}" "${lfc_optarg}";
   2061         continue;
   2062       fi;
   2063       ;;
   2064     --*)
   2065       # delete leading '--';
   2066       lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
   2067       if list_has lfc_long_n "${lfc_abbrev}"
   2068       then
   2069         lfc_opt="${lfc_abbrev}";
   2070       else
   2071         exit_test;
   2072         lfc_opt="$(list_single_from_abbrev lfc_long_n "${lfc_abbrev}")";
   2073         exit_test;
   2074         if obj lfc_opt is_not_empty && is_not_equal "$#" 0
   2075         then
   2076           a="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
   2077           exit_test;
   2078           if obj a is_not_empty
   2079           then
   2080             error_user "The abbreviation ${lfc_arg} \
   2081 has multiple options: --${lfc_opt} and --${a}.";
   2082           fi;
   2083         fi;
   2084       fi;
   2085       if obj lfc_opt is_not_empty
   2086       then
   2087         # long option, no argument
   2088         list_append lfc_result "--${lfc_opt}";
   2089         continue;
   2090       fi;
   2091       lfc_opt="$(list_single_from_abbrev lfc_long_a "${lfc_abbrev}")";
   2092       exit_test;
   2093       if obj lfc_opt is_not_empty
   2094       then
   2095         # long option with argument
   2096         if test "$#" -le 0
   2097         then
   2098           error_user "no argument for option --${lfc_opt}."
   2099         fi;
   2100         list_append lfc_result "--${lfc_opt}" "$1";
   2101         shift;
   2102         continue;
   2103       fi;
   2104       error_user "${lfc_arg} is not an option.";
   2105       ;;
   2106     -?*)			# short option (cluster)
   2107       # delete leading `-';
   2108       lfc_rest="$(echo1 "${lfc_arg}" | sed -e 's/^-//')";
   2109       exit_test;
   2110       while obj lfc_rest is_not_empty
   2111       do
   2112         # get next short option from cluster (first char of $lfc_rest)
   2113         lfc_optchar="$(echo1 "${lfc_rest}" | sed -e 's/^\(.\).*$/\1/')";
   2114         # remove first character from ${lfc_rest};
   2115         lfc_rest="$(echo1 "${lfc_rest}" | sed -e 's/^.//')";
   2116         exit_test;
   2117         if list_has lfc_short_n "${lfc_optchar}"
   2118         then
   2119           list_append lfc_result "-${lfc_optchar}";
   2120           continue;
   2121         elif list_has lfc_short_a "${lfc_optchar}"
   2122         then
   2123           if obj lfc_rest is_empty
   2124           then
   2125             if test "$#" -ge 1
   2126             then
   2127               list_append lfc_result "-${lfc_optchar}" "$1";
   2128               shift;
   2129               continue;
   2130             else
   2131               error_user "no argument for option -${lfc_optchar}.";
   2132             fi;
   2133           else			# rest is the argument
   2134             list_append lfc_result "-${lfc_optchar}" "${lfc_rest}";
   2135             lfc_rest='';
   2136             continue;
   2137           fi;
   2138         else
   2139           error_user "unknown option -${lfc_optchar}.";
   2140         fi;
   2141       done;
   2142       ;;
   2143     *)
   2144       # Here, $lfc_arg is not an option, so a file parameter.
   2145       list_append lfc_fparams "${lfc_arg}";
   2146 
   2147       # Ignore the strange POSIX option handling to end option
   2148       # parsing after the first file name argument.  To reuse it, do
   2149       # a `break' here if $POSIXLY_CORRECT of `bash' is not empty.
   2150       # When `bash' is called as `sh' $POSIXLY_CORRECT is set
   2151       # automatically to `y'.
   2152       ;;
   2153     esac;
   2154   done;
   2155   list_append lfc_result '--';
   2156   if obj lfc_fparams is_not_empty
   2157   then
   2158     lfc_result="${lfc_result} ${lfc_fparams}";
   2159   fi;
   2160   if test "$#" -gt 0
   2161   then
   2162     list_append lfc_result "$@";
   2163   fi;
   2164   obj lfc_result echo1;
   2165   eval ${_UNSET} lfc_abbrev;
   2166   eval ${_UNSET} lfc_fparams;
   2167   eval ${_UNSET} lfc_short_a;
   2168   eval ${_UNSET} lfc_short_n;
   2169   eval ${_UNSET} lfc_long_a;
   2170   eval ${_UNSET} lfc_long_n;
   2171   eval ${_UNSET} lfc_result;
   2172   eval ${_UNSET} lfc_arg;
   2173   eval ${_UNSET} lfc_opt;
   2174   eval ${_UNSET} lfc_opt_arg;
   2175   eval ${_UNSET} lfc_opt_char;
   2176   eval ${_UNSET} lfc_with_equal;
   2177   eval ${_UNSET} lfc_rest;
   2178   eval "${return_ok}";
   2179 } # list_from_cmdline()
   2180 
   2181 
   2182 ########################################################################
   2183 # list_from_split (<string> <separator>)
   2184 #
   2185 # In <string>, escape all white space characters and replace each
   2186 # <separator> by space.
   2187 #
   2188 # Arguments: 2: a <string> that is to be split into parts divided by
   2189 #               <separator>
   2190 # Output:    the resulting list string
   2191 #
   2192 # Variable prefix: lfs
   2193 #
   2194 list_from_split()
   2195 {
   2196   func_check list_from_split = 2 "$@";
   2197 
   2198   # precede each space or tab by a backslash `\' (doubled for `sed')
   2199   lfs_s="$(echo1 "$1" | sed -e 's/\('"${_SPACE_SED}"'\)/\\\1/g')";
   2200   exit_test;
   2201 
   2202   # replace split character of string by the list separator ` ' (space).
   2203   case "$2" in
   2204     /)				# cannot use normal `sed' separator
   2205       echo1 "${lfs_s}" | sed -e 's|'"$2"'| |g';
   2206       ;;
   2207     ?)				# use normal `sed' separator
   2208       echo1 "${lfs_s}" | sed -e 's/'"$2"'/ /g';
   2209       ;;
   2210     ??*)
   2211       error 'list_from_split(): separator must be a single character.';
   2212       ;;
   2213   esac;
   2214   eval ${_UNSET} lfs_s;
   2215   eval "${return_ok}";
   2216 }
   2217 
   2218 
   2219 ########################################################################
   2220 # list_get (<list>)
   2221 #
   2222 # Check whether <list> is a space-separated list of '-quoted elements.
   2223 #
   2224 # If the test fails an error is raised.
   2225 # If the test succeeds the argument is echoed.
   2226 #
   2227 # Testing criteria:
   2228 #   A list has the form "'first' 'second' '...' 'last'".  So it has a
   2229 #   leading and a final quote and the elements are separated by "' '"
   2230 #   constructs.  If these are all removed there should not be any
   2231 #   unescaped single-quotes left.  Watch out for escaped single
   2232 #   quotes; they have the form '\'' (sq bs sq sq).
   2233 
   2234 # Arguments: 1
   2235 # Output: the argument <list> unchanged, if the check succeeded.
   2236 #
   2237 # Variable prefix: lg
   2238 #
   2239 list_get()
   2240 {
   2241   func_check list_get = 1 "$@";
   2242   eval lg_list='"${'$1'}"';
   2243   # remove leading and final space characters
   2244   lg_list="$(echo1 "${lg_list}" | sed -e '
   2245 s/^'"${_SPACE_SED}"'*//
   2246 s/'"${_SPACE_SED}"'*$//
   2247 ')";
   2248   exit_test;
   2249   case "${lg_list}" in
   2250   '')
   2251     eval ${_UNSET} lg_list;
   2252     eval "${return_ok}";
   2253     ;;
   2254   \'*\')
   2255     obj lg_list echo1;
   2256     eval ${_UNSET} lg_list;
   2257     eval "${return_ok}";
   2258     ;;
   2259   *)
   2260     error "list_get(): bad list: $1"
   2261     ;;
   2262   esac;
   2263   eval ${_UNSET} lg_list;
   2264   eval "${return_ok}";
   2265 }
   2266 
   2267 
   2268 ########################################################################
   2269 # list_has (<var_name> <element>)
   2270 #
   2271 # Test whether the list <var_name> has the element <element>.
   2272 #
   2273 # Arguments: 2
   2274 #   <var_name>: a variable name for a list of single-quoted elements
   2275 #   <element>:  some sequence of characters.
   2276 #
   2277 # Variable prefix: lh
   2278 #
   2279 list_has()
   2280 {
   2281   func_check list_has = 2 "$@";
   2282   eval lh_list='"${'$1'}"';
   2283   if obj lh_list is_empty
   2284   then
   2285     eval "${_UNSET}" lh_list;
   2286     eval "${return_no}";
   2287   fi;
   2288   case "$2" in
   2289     \'*\')  lh_element=" $2 "; ;;
   2290     *)      lh_element=" '$2' "; ;;
   2291   esac;
   2292   if string_contains " ${lh_list} " "${lh_element}"
   2293   then
   2294     eval "${_UNSET}" lh_list;
   2295     eval "${_UNSET}" lh_element;
   2296     eval "${return_yes}";
   2297   else
   2298     eval "${_UNSET}" lh_list;
   2299     eval "${_UNSET}" lh_element;
   2300     eval "${return_no}";
   2301   fi;
   2302 }
   2303 
   2304 
   2305 ########################################################################
   2306 # list_has_abbrev (<var_name> <abbrev>)
   2307 #
   2308 # Test whether the list <var_name> has an element starting with <abbrev>.
   2309 #
   2310 # Arguments: 2
   2311 #   <var_name>: a variable name for a list of single-quoted elements
   2312 #   <abbrev>:   some sequence of characters.
   2313 #
   2314 # Variable prefix: lha
   2315 #
   2316 list_has_abbrev()
   2317 {
   2318   func_check list_has_abbrev = 2 "$@";
   2319   eval lha_list='"${'$1'}"';
   2320   if obj lha_list is_empty
   2321   then
   2322     eval "${_UNSET}" lha_list;
   2323     eval "${return_no}";
   2324   fi;
   2325   case "$2" in
   2326     \'*)
   2327       lha_element="$(echo1 "$2" | sed -e 's/'"${_SQ}"'$//')";
   2328       exit_test;
   2329       ;;
   2330     *) lha_element="'$2"; ;;
   2331   esac;
   2332   if string_contains " ${lha_list}" " ${lha_element}"
   2333   then
   2334     eval "${_UNSET}" lha_list;
   2335     eval "${_UNSET}" lha_element;
   2336     eval "${return_yes}";
   2337   else
   2338     eval "${_UNSET}" lha_list;
   2339     eval "${_UNSET}" lha_element;
   2340     eval "${return_no}";
   2341   fi;
   2342   eval "${return_ok}";
   2343 }
   2344 
   2345 
   2346 ########################################################################
   2347 # list_has_not (<list> <element>)
   2348 #
   2349 # Test whether <list> has no <element>.
   2350 #
   2351 # Arguments: 2
   2352 #   <list>:    a space-separated list of single-quoted elements.
   2353 #   <element>: some sequence of characters.
   2354 #
   2355 # Variable prefix: lhn
   2356 #
   2357 list_has_not()
   2358 {
   2359   func_check list_has_not = 2 "$@";
   2360   eval lhn_list='"${'$1'}"';
   2361   if obj lhn_list is_empty
   2362   then
   2363     eval "${_UNSET}" lhn_list;
   2364     eval "${return_yes}";
   2365   fi;
   2366   case "$2" in
   2367     \'*\') lhn_element=" $2 "; ;;
   2368     *)     lhn_element=" '$2' "; ;;
   2369   esac;
   2370   if string_contains " ${lhn_list} " "${lhn_element}"
   2371   then
   2372     eval "${_UNSET}" lhn_list;
   2373     eval "${_UNSET}" lhn_element;
   2374     eval "${return_no}";
   2375   else
   2376     eval "${_UNSET}" lhn_list;
   2377     eval "${_UNSET}" lhn_element;
   2378     eval "${return_yes}";
   2379   fi;
   2380 }
   2381 
   2382 
   2383 ########################################################################
   2384 # list_single_from_abbrev (<list> <abbrev>)
   2385 #
   2386 # Check whether the list has an element starting with <abbrev>.  If
   2387 # there are more than a single element an error is created.
   2388 #
   2389 # Arguments: 2
   2390 #   <list>:   a variable name for a list of single-quoted elements
   2391 #   <abbrev>: some sequence of characters.
   2392 #
   2393 # Output: the found element.
   2394 #
   2395 # Variable prefix: lsfa
   2396 #
   2397 list_single_from_abbrev()
   2398 {
   2399   func_check list_single_from_abbrev = 2 "$@";
   2400   eval lsfa_list='"${'$1'}"';
   2401   if obj lsfa_list is_empty
   2402   then
   2403     eval "${_UNSET}" lsfa_list;
   2404     eval "${return_no}";
   2405   fi;
   2406   lsfa_abbrev="$2";
   2407   if list_has lsfa_list "${lsfa_abbrev}"
   2408   then
   2409     obj lsfa_abbrev echo1;
   2410     eval "${_UNSET}" lsfa_abbrev;
   2411     eval "${_UNSET}" lsfa_list;
   2412     eval "${return_yes}";
   2413   fi;
   2414   if list_has_abbrev lsfa_list "${lsfa_abbrev}"
   2415   then
   2416     lsfa_element='';
   2417     eval set x "${lsfa_list}";
   2418     shift;
   2419     for i
   2420     do
   2421       case "$i" in
   2422       ${lsfa_abbrev}*)
   2423         if obj lsfa_element is_not_empty
   2424         then
   2425           error_user "The abbreviation --${lsfa_abbrev} \
   2426 has multiple options: --${lsfa_element} and --${i}.";
   2427         fi;
   2428         lsfa_element="$i";
   2429         ;;
   2430       esac;
   2431     done;
   2432     obj lsfa_element echo1;
   2433     eval "${_UNSET}" lsfa_abbrev;
   2434     eval "${_UNSET}" lsfa_element;
   2435     eval "${_UNSET}" lsfa_list;
   2436     eval "${return_yes}";
   2437   else
   2438     eval "${_UNSET}" lsfa_abbrev;
   2439     eval "${_UNSET}" lsfa_element;
   2440     eval "${_UNSET}" lsfa_list;
   2441     eval "${return_no}";
   2442   fi;
   2443 }
   2444 
   2445 
   2446 ########################################################################
   2447 landmark '7: man_*()';
   2448 ########################################################################
   2449 
   2450 ########################################################################
   2451 # man_do_filespec (<filespec>)
   2452 #
   2453 # Print suitable man page(s) for filespec to $_TMP_CAT.
   2454 #
   2455 # Arguments : 2
   2456 #   <filespec>: argument of the form `man:name.section', `man:name',
   2457 #               `man:name(section)', `name.section', `name'.
   2458 #
   2459 # Globals   : $_OPT_ALL
   2460 #
   2461 # Output    : none.
   2462 # Return    : `0' if man page was found, `1' else.
   2463 #
   2464 # Only called from do_fileargs(), checks on $MANPATH and $_MAN_ENABLE
   2465 # are assumed (see man_setup()).
   2466 #
   2467 # Variable prefix: mdf
   2468 #
   2469 man_do_filespec()
   2470 {
   2471   func_check man_do_filespec = 1 "$@";
   2472   if obj _MAN_PATH is_empty
   2473   then
   2474     eval "${return_bad}";
   2475   fi;
   2476   if is_empty "$1"
   2477   then
   2478     eval "${return_bad}";
   2479   fi;
   2480   mdf_spec="$1";
   2481   mdf_name='';
   2482   mdf_section='';
   2483   case "${mdf_spec}" in
   2484   */*)				# not a man spec with containing '/'
   2485     eval ${_UNSET} mdf_got_one;
   2486     eval ${_UNSET} mdf_name;
   2487     eval ${_UNSET} mdf_section;
   2488     eval ${_UNSET} mdf_spec;
   2489     eval "${return_bad}";
   2490     ;;
   2491   man:?*\(?*\))			# man:name(section)
   2492     mdf_name="$(echo1 "${mdf_spec}" \
   2493                 | sed -e 's/^man:\(..*\)(\(..*\))$/\1/')";
   2494     mdf_section="$(echo1 "${mdf_spec}" \
   2495                    | sed -e 's/^man:\(..*\)(\(..*\))$/\2/')";
   2496     exit_test;
   2497     ;;
   2498   man:?*.${_MAN_AUTO_SEC_CHARS}) # man:name.section
   2499     mdf_name="$(echo1 "${mdf_spec}" \
   2500                 | sed -e 's/^man:\(..*\)\..$/\1/')";
   2501     mdf_section="$(echo1 "${mdf_spec}" \
   2502                    | sed -e 's/^.*\(.\)$/\1/')";
   2503     exit_test;
   2504     ;;
   2505   man:?*)			# man:name
   2506     mdf_name="$(echo1 "${mdf_spec}" | sed -e 's/^man://')";
   2507     exit_test;
   2508     ;;
   2509   ?*\(?*\))			# name(section)
   2510     mdf_name="$(echo1 "${mdf_spec}" \
   2511                 | sed -e 's/^\(..*\)(\(..*\))$/\1/')";
   2512     mdf_section="$(echo1 "${mdf_spec}" \
   2513                    | sed -e 's/^\(..*\)(\(..*\))$/\2/')";
   2514     exit_test;
   2515     ;;
   2516   ?*.${_MAN_AUTO_SEC_CHARS})	# name.section
   2517     mdf_name="$(echo1 "${mdf_spec}" \
   2518                 | sed -e 's/^\(..*\)\..$/\1/')";
   2519     mdf_section="$(echo1 "${mdf_spec}" \
   2520                    | sed -e 's/^.*\(.\)$/\1/')";
   2521     exit_test;
   2522     ;;
   2523   ?*)
   2524     mdf_name="${mdf_spec}";
   2525     ;;
   2526   esac;
   2527   if obj mdf_name is_empty
   2528   then
   2529     eval ${_UNSET} mdf_got_one;
   2530     eval ${_UNSET} mdf_name;
   2531     eval ${_UNSET} mdf_section;
   2532     eval ${_UNSET} mdf_spec;
   2533     eval "${return_bad}";
   2534   fi;
   2535   mdf_got_one='no';
   2536   if obj mdf_section is_empty
   2537   then
   2538     if obj _OPT_SECTIONS is_empty
   2539     then
   2540       eval set x "${_MAN_AUTO_SEC_LIST}";
   2541     else
   2542       # use --sections when no section is given to filespec
   2543       eval set x "$(echo1 "${_OPT_SECTIONS}" | sed -e 's/:/ /g')";
   2544     fi;
   2545     shift;
   2546     for s
   2547     do
   2548       mdf_s="$s";
   2549       if man_search_section "${mdf_name}" "${mdf_s}"
   2550       then			# found
   2551         if obj _MAN_ALL is_yes
   2552         then
   2553           mdf_got_one='yes';
   2554         else
   2555           eval ${_UNSET} mdf_got_one;
   2556           eval ${_UNSET} mdf_name;
   2557           eval ${_UNSET} mdf_s;
   2558           eval ${_UNSET} mdf_section;
   2559           eval ${_UNSET} mdf_spec;
   2560           eval "${return_good}";
   2561         fi;
   2562       fi;
   2563     done;
   2564   else
   2565     if man_search_section "${mdf_name}" "${mdf_section}"
   2566     then
   2567       eval ${_UNSET} mdf_got_one;
   2568       eval ${_UNSET} mdf_name;
   2569       eval ${_UNSET} mdf_s;
   2570       eval ${_UNSET} mdf_section;
   2571       eval ${_UNSET} mdf_spec;
   2572       eval "${return_good}";
   2573     else
   2574       eval ${_UNSET} mdf_got_one;
   2575       eval ${_UNSET} mdf_name;
   2576       eval ${_UNSET} mdf_section;
   2577       eval ${_UNSET} mdf_spec;
   2578       eval "${return_bad}";
   2579     fi;
   2580   fi;
   2581   if obj _MAN_ALL is_yes && obj mdf_got_one is_yes
   2582   then
   2583     eval ${_UNSET} mdf_got_one;
   2584     eval ${_UNSET} mdf_name;
   2585     eval ${_UNSET} mdf_s;
   2586     eval ${_UNSET} mdf_section;
   2587     eval ${_UNSET} mdf_spec;
   2588     eval "${return_good}";
   2589   fi;
   2590   eval ${_UNSET} mdf_got_one;
   2591   eval ${_UNSET} mdf_name;
   2592   eval ${_UNSET} mdf_s;
   2593   eval ${_UNSET} mdf_section;
   2594   eval ${_UNSET} mdf_spec;
   2595   eval "${return_bad}";
   2596 } # man_do_filespec()
   2597 
   2598 
   2599 ########################################################################
   2600 # man_register_file (<file> <name> [<section>])
   2601 #
   2602 # Write a found man page file and register the title element.
   2603 #
   2604 # Arguments: 1, 2, or 3; maybe empty
   2605 # Output: none
   2606 #
   2607 man_register_file()
   2608 {
   2609   func_check man_register_file '>=' 2 "$@";
   2610   case "$#" in
   2611     2|3) do_nothing; ;;
   2612     *)
   2613       error "man_register_file() expects 2 or 3 arguments.";
   2614       ;;
   2615   esac;
   2616   if is_empty "$1"
   2617   then
   2618     error 'man_register_file(): file name is empty';
   2619   fi;
   2620   to_tmp "$1";
   2621   case "$#" in
   2622     2)
   2623        register_title "man:$2";
   2624        eval "${return_ok}";
   2625        ;;
   2626     3)
   2627        register_title "$2.$3";
   2628        eval "${return_ok}";
   2629        ;;
   2630   esac;
   2631   eval "${return_ok}";
   2632 }
   2633 
   2634 
   2635 ########################################################################
   2636 # man_search_section (<name> <section>)
   2637 #
   2638 # Retrieve man pages.
   2639 #
   2640 # Arguments : 2
   2641 # Globals   : $_MAN_PATH, $_MAN_EXT
   2642 # Return    : 0 if found, 1 otherwise
   2643 #
   2644 # Variable prefix: mss
   2645 #
   2646 man_search_section()
   2647 {
   2648   func_check man_search_section = 2 "$@";
   2649   if obj _MAN_PATH is_empty
   2650   then
   2651     eval "${return_bad}";
   2652   fi;
   2653   if is_empty "$1"
   2654   then
   2655     eval "${return_bad}";
   2656   fi;
   2657   if is_empty "$2"
   2658   then
   2659     eval "${return_bad}";
   2660   fi;
   2661   mss_name="$1";
   2662   mss_section="$2";
   2663   eval set x "$(path_split "${_MAN_PATH}")";
   2664   exit_test;
   2665   shift;
   2666   mss_got_one='no';
   2667   if obj _MAN_EXT is_empty
   2668   then
   2669     for d
   2670     do
   2671       mss_dir="$(dirname_append "$d" "man${mss_section}")";
   2672       exit_test;
   2673       if obj mss_dir is_dir
   2674       then
   2675         mss_prefix="$(\
   2676           dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
   2677         if obj _OPT_WHATIS is_yes
   2678         then
   2679           mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
   2680                        sed -e '\| found|s|.*||'
   2681                        )";
   2682         else
   2683           mss_files="$(eval ls "'${mss_prefix}'"'*' 2>${_NULL_DEV} |
   2684                        sed -e '\| found|s|.*||'
   2685                        )";
   2686         fi;
   2687         exit_test;
   2688         if obj mss_files is_not_empty
   2689         then
   2690           # for f in $mss_files
   2691           for f in $(eval set x ${mss_files}; shift; echo1 "$@")
   2692           do
   2693             exit_test;
   2694             mss_f="$f";
   2695             if obj mss_f is_file
   2696             then
   2697               if is_yes "${mss_got_one}"
   2698               then
   2699                 register_file "${mss_f}";
   2700               elif obj _MAN_ALL is_yes
   2701               then
   2702                 man_register_file "${mss_f}" "${mss_name}";
   2703               else
   2704                 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
   2705                 eval ${_UNSET} mss_dir;
   2706                 eval ${_UNSET} mss_ext;
   2707                 eval ${_UNSET} mss_f;
   2708                 eval ${_UNSET} mss_files;
   2709                 eval ${_UNSET} mss_got_one;
   2710                 eval ${_UNSET} mss_name;
   2711                 eval ${_UNSET} mss_prefix;
   2712                 eval ${_UNSET} mss_section;
   2713                 eval "${return_good}";
   2714               fi;
   2715               mss_got_one='yes';
   2716             fi;
   2717           done;
   2718         fi;
   2719       fi;
   2720     done;
   2721   else
   2722     mss_ext="${_MAN_EXT}";
   2723     # check for directory name having trailing extension
   2724     for d
   2725     do
   2726       mss_dir="$(dirname_append $d man${mss_section}${mss_ext})";
   2727       exit_test;
   2728       if obj mss_dir is_dir
   2729       then
   2730         mss_prefix=\
   2731           "$(dirname_append "${mss_dir}" "${mss_name}.${mss_section}")";
   2732         mss_files="$( eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
   2733                      sed -e '\|not found|s|.*||'
   2734                      )";
   2735         exit_test;
   2736         if obj mss_files is_not_empty
   2737         then
   2738           # for f in $mss_files
   2739           for f in $(eval set x ${mss_files}; shift; echo1 "$@")
   2740           do
   2741             mss_f="$f";
   2742             if obj mss_f is_file
   2743             then
   2744               if is_yes "${mss_got_one}"
   2745               then
   2746                 register_file "${mss_f}";
   2747               elif obj _MAN_ALL is_yes
   2748               then
   2749                 man_register_file "${mss_f}" "${mss_name}";
   2750               else
   2751                 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
   2752                 eval ${_UNSET} mss_dir;
   2753                 eval ${_UNSET} mss_ext;
   2754                 eval ${_UNSET} mss_f;
   2755                 eval ${_UNSET} mss_files;
   2756                 eval ${_UNSET} mss_got_one;
   2757                 eval ${_UNSET} mss_name;
   2758                 eval ${_UNSET} mss_prefix;
   2759                 eval ${_UNSET} mss_section;
   2760                 eval "${return_good}";
   2761               fi;
   2762               mss_got_one='yes';
   2763             fi;
   2764           done;
   2765         fi;
   2766       fi;
   2767     done;
   2768     # check for files with extension in directories without extension
   2769     for d
   2770     do
   2771       mss_dir="$(dirname_append "$d" "man${mss_section}")";
   2772       exit_test;
   2773       if obj mss_dir is_dir
   2774       then
   2775         mss_prefix="$(dirname_append "${mss_dir}" \
   2776                         "${mss_name}.${mss_section}${mss_ext}")";
   2777         mss_files="$(eval ls "${mss_prefix}"'*' 2>${_NULL_DEV} |
   2778                      sed -e '\|not found|s|.*||'
   2779                      )";
   2780         exit_test;
   2781         if obj mss_files is_not_empty
   2782         then
   2783           # for f in $mss_files
   2784           for f in $(eval set x ${mss_files}; shift; echo1 "$@")
   2785           do
   2786             mss_f="$f";
   2787             if obj mss_f is_file
   2788             then
   2789               if is_yes "${mss_got_one}"
   2790               then
   2791                 register_file "${mss_f}";
   2792               elif obj _MAN_ALL is_yes
   2793               then
   2794                 man_register_file "${mss_f}" "${mss_name}";
   2795               else
   2796                 man_register_file "${mss_f}" "${mss_name}" "${mss_section}";
   2797                 eval ${_UNSET} mss_dir;
   2798                 eval ${_UNSET} mss_ext;
   2799                 eval ${_UNSET} mss_f;
   2800                 eval ${_UNSET} mss_files;
   2801                 eval ${_UNSET} mss_got_one;
   2802                 eval ${_UNSET} mss_name;
   2803                 eval ${_UNSET} mss_prefix;
   2804                 eval ${_UNSET} mss_section;
   2805                 eval "${return_good}";
   2806               fi;
   2807               mss_got_one='yes';
   2808             fi;
   2809           done;
   2810         fi;
   2811       fi;
   2812     done;
   2813   fi;
   2814   if obj _MAN_ALL is_yes && is_yes "${mss_got_one}"
   2815   then
   2816     eval ${_UNSET} mss_dir;
   2817     eval ${_UNSET} mss_ext;
   2818     eval ${_UNSET} mss_f;
   2819     eval ${_UNSET} mss_files;
   2820     eval ${_UNSET} mss_got_one;
   2821     eval ${_UNSET} mss_name;
   2822     eval ${_UNSET} mss_prefix;
   2823     eval ${_UNSET} mss_section;
   2824     eval "${return_good}";
   2825   fi;
   2826   eval ${_UNSET} mss_dir;
   2827   eval ${_UNSET} mss_ext;
   2828   eval ${_UNSET} mss_f;
   2829   eval ${_UNSET} mss_files;
   2830   eval ${_UNSET} mss_got_one;
   2831   eval ${_UNSET} mss_name;
   2832   eval ${_UNSET} mss_prefix;
   2833   eval ${_UNSET} mss_section;
   2834   eval "${return_bad}";
   2835 } # man_search_section()
   2836 
   2837 
   2838 ########################################################################
   2839 # man_setup ()
   2840 #
   2841 # Setup the variables $_MAN_* needed for man page searching.
   2842 #
   2843 # Globals:
   2844 #   in:     $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
   2845 #           $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
   2846 #   out:    $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
   2847 #           $_MAN_SEC, $_MAN_ALL
   2848 #   in/out: $_MAN_ENABLE
   2849 #
   2850 # The precedence for the variables related to `man' is that of GNU
   2851 # `man', i.e.
   2852 #
   2853 # $LANG; overridden by
   2854 # $LC_MESSAGES; overridden by
   2855 # $LC_ALL; this has the same precedence as
   2856 # $MANPATH, $MANROFFSEQ, $MANSEC, $PAGER, $SYSTEM; overridden by
   2857 # $MANOPT; overridden by
   2858 # the groffer command line options.
   2859 #
   2860 # Variable prefix: ms
   2861 #
   2862 man_setup()
   2863 {
   2864   func_check main_man_setup = 0 "$@";
   2865 
   2866   if obj _MAN_IS_SETUP is_yes
   2867   then
   2868     eval "${return_ok}";
   2869   fi;
   2870   _MAN_IS_SETUP='yes';
   2871 
   2872   if obj _MAN_ENABLE is_not_yes
   2873   then
   2874     eval "${return_ok}";
   2875   fi;
   2876 
   2877   # determine basic path for man pages
   2878   _MAN_PATH="$(get_first_essential \
   2879                "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}")";
   2880   exit_test;
   2881   if obj _MAN_PATH is_empty
   2882   then
   2883     manpath_set_from_path;
   2884   else
   2885     _MAN_PATH="$(path_clean "${_MAN_PATH}")";
   2886     exit_test;
   2887   fi;
   2888   if obj _MAN_PATH is_empty
   2889   then
   2890     if is_prog 'manpath'
   2891     then
   2892       _MAN_PATH="$(manpath 2>${_NULL_DEV})"; # not always available
   2893       exit_test;
   2894     fi;
   2895   fi;
   2896   if obj _MAN_PATH is_empty
   2897   then
   2898     _MAN_ENABLE="no";
   2899     eval "${return_ok}";
   2900   fi;
   2901 
   2902   _MAN_ALL="$(get_first_essential "${_OPT_ALL}" "${_MANOPT_ALL}")";
   2903   exit_test;
   2904   if obj _MAN_ALL is_empty
   2905   then
   2906     _MAN_ALL='no';
   2907   fi;
   2908 
   2909   _MAN_SYS="$(get_first_essential \
   2910               "${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
   2911   ms_lang="$(get_first_essential \
   2912            "${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}")";
   2913   exit_test;
   2914   case "${ms_lang}" in
   2915     C|POSIX)
   2916       _MAN_LANG="";
   2917       _MAN_LANG2="";
   2918       ;;
   2919     ?)
   2920       _MAN_LANG="${ms_lang}";
   2921       _MAN_LANG2="";
   2922       ;;
   2923     *)
   2924       _MAN_LANG="${ms_lang}";
   2925       # get first two characters of $ms_lang
   2926       _MAN_LANG2="$(echo1 "${ms_lang}" | sed -e 's/^\(..\).*$/\1/')";
   2927       exit_test;
   2928       ;;
   2929   esac;
   2930   # from now on, use only $_LANG, forget about $_OPT_LANG, $LC_*.
   2931 
   2932   manpath_add_lang_sys;		# this is very slow
   2933 
   2934   _MAN_SEC="$(get_first_essential \
   2935               "${_OPT_SECT}" "${_MANOPT_SEC}" "${MANSEC}")";
   2936   exit_test;
   2937   if obj _MAN_PATH is_empty
   2938   then
   2939     _MAN_ENABLE="no";
   2940     eval ${_UNSET} ms_lang;
   2941     eval "${return_ok}";
   2942   fi;
   2943 
   2944   _MAN_EXT="$(get_first_essential \
   2945               "${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}")";
   2946   exit_test;
   2947   eval ${_UNSET} ms_lang;
   2948   eval "${return_ok}";
   2949 } # man_setup()
   2950 
   2951 
   2952 ########################################################################
   2953 landmark '8: manpath_*()';
   2954 ########################################################################
   2955 
   2956 ########################################################################
   2957 # manpath_add_lang_sys ()
   2958 #
   2959 # Add language and operating system specific directories to man path.
   2960 #
   2961 # Arguments : 0
   2962 # Output    : none
   2963 # Globals:
   2964 #   in:     $_MAN_SYS: has the form `os1,os2,...', a comma separated
   2965 #             list of names of operating systems.
   2966 #           $_MAN_LANG and $_MAN_LANG2: each a single name
   2967 #   in/out: $_MAN_PATH: has the form `dir1:dir2:...', a colon
   2968 #             separated list of directories.
   2969 #
   2970 # Variable prefix: mals
   2971 #
   2972 manpath_add_lang_sys()
   2973 {
   2974   func_check manpath_add_lang_sys = 0 "$@";
   2975   if obj _MAN_PATH is_empty
   2976   then
   2977     eval "${return_ok}";
   2978   fi;
   2979   # twice test both sys and lang
   2980   eval set x "$(path_split "${_MAN_PATH}")";
   2981   shift;
   2982   exit_test;
   2983   mals_mp='';
   2984   for p
   2985   do				# loop on man path directories
   2986     mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
   2987     exit_test;
   2988   done;
   2989   eval set x "$(path_split "${mals_mp}")";
   2990   shift;
   2991   exit_test;
   2992   for p
   2993   do				# loop on man path directories
   2994     mals_mp="$(_manpath_add_lang_sys_single "${mals_mp}" "$p")";
   2995     exit_test;
   2996   done;
   2997   _MAN_PATH="$(path_chop "${mals_mp}")";
   2998   exit_test;
   2999   eval ${_UNSET} mals_mp;
   3000   eval "${return_ok}";
   3001 }
   3002 
   3003 
   3004 # To the directory in $1 append existing sys/lang subdirectories
   3005 # Function is necessary to split the OS list.
   3006 #
   3007 # globals: in: $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2
   3008 # argument: 2: `man_path' and `dir'
   3009 # output: colon-separated path of the retrieved subdirectories
   3010 #
   3011 # Variable prefix: _mals
   3012 #
   3013 _manpath_add_lang_sys_single()
   3014 {
   3015   func_check _manpath_add_lang_sys_single = 2 "$@";
   3016   _mals_res="$1";
   3017   _mals_parent="$2";
   3018   eval set x "$(list_from_split "${_MAN_SYS}" ',')";
   3019   shift;
   3020   exit_test;
   3021   for d in "$@" "${_MAN_LANG}" "${_MAN_LANG2}"
   3022   do
   3023     _mals_dir="$(dirname_append "${_mals_parent}" "$d")";
   3024     exit_test;
   3025     if obj _mals_res path_not_contains "${_mals_dir}" && \
   3026        obj _mals_dir is_dir
   3027     then
   3028       _mals_res="${_mals_res}:${_mals_dir}";
   3029     fi;
   3030   done;
   3031   if path_not_contains "${_mals_res}" "${_mals_parent}"
   3032   then
   3033     _mals_res="${_mals_res}:${_mals_parent}";
   3034   fi;
   3035   path_chop "${_mals_res}";
   3036   eval ${_UNSET} _mals_dir;
   3037   eval ${_UNSET} _mals_parent;
   3038   eval ${_UNSET} _mals_res;
   3039   eval "${return_ok}";
   3040 }
   3041 
   3042 # end manpath_add_lang_sys ()
   3043 
   3044 
   3045 ########################################################################
   3046 # manpath_set_from_path ()
   3047 #
   3048 # Determine basic search path for man pages from $PATH.
   3049 #
   3050 # Return:    `0' if a valid man path was retrieved.
   3051 # Output:    none
   3052 # Globals:
   3053 #   in:  $PATH
   3054 #   out: $_MAN_PATH
   3055 #
   3056 # Variable prefix: msfp
   3057 #
   3058 manpath_set_from_path()
   3059 {
   3060   func_check manpath_set_from_path = 0 "$@";
   3061 
   3062   msfp_manpath='';
   3063 
   3064   # get a basic man path from $PATH
   3065   if obj PATH is_not_empty
   3066   then
   3067     eval set x "$(path_split "${PATH}")";
   3068     shift;
   3069     exit_test;
   3070     for d
   3071     do
   3072       # delete the final `/bin' part
   3073       msfp_base="$(echo1 "$d" | sed -e 's|//*bin/*$||')";
   3074       exit_test;
   3075       for e in /share/man /man
   3076       do
   3077         msfp_mandir="${msfp_base}$e";
   3078         if test -d "${msfp_mandir}" && test -r "${msfp_mandir}"
   3079         then
   3080           msfp_manpath="${msfp_manpath}:${msfp_mandir}";
   3081         fi;
   3082       done;
   3083     done;
   3084   fi;
   3085 
   3086   # append some default directories
   3087   for d in /usr/local/share/man /usr/local/man \
   3088            /usr/share/man /usr/man \
   3089            /usr/X11R6/man /usr/openwin/man \
   3090            /opt/share/man /opt/man \
   3091            /opt/gnome/man /opt/kde/man
   3092   do
   3093     msfp_d="$d";
   3094     if obj msfp_manpath path_not_contains "${msfp_d}" && obj mfsp_d is_dir
   3095     then
   3096       msfp_manpath="${msfp_manpath}:${mfsp_d}";
   3097     fi;
   3098   done;
   3099 
   3100   _MAN_PATH="${msfp_manpath}";
   3101   eval ${_UNSET} msfp_base;
   3102   eval ${_UNSET} msfp_d;
   3103   eval ${_UNSET} msfp_mandir;
   3104   eval ${_UNSET} msfp_manpath;
   3105   eval "${return_ok}";
   3106 } # manpath_set_from_path()
   3107 
   3108 
   3109 ########################################################################
   3110 landmark '9: obj_*()';
   3111 ########################################################################
   3112 
   3113 ########################################################################
   3114 # obj (<object> <call_name> <arg>...)
   3115 #
   3116 # This works like a method (object function) call for an object.
   3117 # Run "<call_name> $<object> <arg> ...".
   3118 #
   3119 # The first argument represents an object whose data is given as first
   3120 # argument to <call_name>().
   3121 #
   3122 # Argument: >=2
   3123 #           <object>: variable name
   3124 #           <call_name>: a program or function name
   3125 #
   3126 # Variable prefix: o
   3127 #
   3128 obj()
   3129 {
   3130   func_check obj '>=' 2 "$@";
   3131   eval o_arg1='"${'$1'}"';
   3132   if is_empty "$2"
   3133   then
   3134     error "obj(): function name is empty."
   3135   else
   3136     o_func="$2";
   3137   fi;
   3138   shift;
   3139   shift;
   3140   eval "${o_func}"' "${o_arg1}" "$@"';
   3141   n="$?";
   3142   eval ${_UNSET} o_arg1;
   3143   eval ${_UNSET} o_func;
   3144   eval "${return_var} $n";
   3145 } # obj()
   3146 
   3147 
   3148 ########################################################################
   3149 # obj_data (<object>)
   3150 #
   3151 # Print the data of <object>, i.e. the content of $<object>.
   3152 # For possible later extensions.
   3153 #
   3154 # Arguments: 1
   3155 #            <object>: a variable name
   3156 # Output:    the data of <object>
   3157 #
   3158 # Variable prefix: od
   3159 #
   3160 obj_data()
   3161 {
   3162   func_check obj '=' 1 "$@";
   3163   if is_empty "$1"
   3164   then
   3165     error "obj_data(): object name is empty."
   3166   fi;
   3167   eval od_res='"${'$1'}"';
   3168   obj od_res echo1;
   3169   eval ${_UNSET} od_res;
   3170   eval "${return_ok}";
   3171 }
   3172 
   3173 
   3174 ########################################################################
   3175 # obj_from_output (<object> <call_name> <arg>...)
   3176 #
   3177 # Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
   3178 # function call to a global variable.
   3179 #
   3180 # Arguments: >=2
   3181 #            <object>: a variable name
   3182 #            <call_name>: the name of a function or program
   3183 #            <arg>: optional argument to <call_name>
   3184 # Output:    none
   3185 #
   3186 # Variable prefix: ofo
   3187 #
   3188 obj_from_output()
   3189 {
   3190   func_check obj_from_output '>=' 2 "$@";
   3191   if is_empty "$1"
   3192   then
   3193     error "res(): variable name is empty.";
   3194   elif is_empty "$2"
   3195   then
   3196     error "res(): function name is empty."
   3197   else
   3198     ofo_result_name="$1";
   3199   fi;
   3200   shift;
   3201   eval "${ofo_result_name}"'="$('"$@"')"';
   3202   exit_test;
   3203   eval "${return_ok}";
   3204 }
   3205 
   3206 
   3207 ########################################################################
   3208 # obj_set (<object> <data>)
   3209 #
   3210 # Set the data of <object>, i.e. call "$<object>=<data>".
   3211 #
   3212 # Arguments: 2
   3213 #            <object>: a variable name
   3214 #            <data>: a string
   3215 # Output::   none
   3216 #
   3217 obj_set()
   3218 {
   3219   func_check obj_set '=' 2 "$@";
   3220   if is_empty "$1"
   3221   then
   3222     error "obj_set(): object name is empty."
   3223   fi;
   3224   eval "$1"='"$2"';
   3225   eval "${return_ok}";
   3226 }
   3227 
   3228 
   3229 ########################################################################
   3230 # path_chop (<path>)
   3231 #
   3232 # Remove unnecessary colons from path.
   3233 #
   3234 # Argument: 1, a colon separated path.
   3235 # Output:   path without leading, double, or trailing colons.
   3236 #
   3237 path_chop()
   3238 {
   3239   func_check path_chop = 1 "$@";
   3240 
   3241   # replace multiple colons by a single colon `:'
   3242   # remove leading and trailing colons
   3243   echo1 "$1" | sed -e '
   3244 s/^:*//
   3245 s/:::*/:/g
   3246 s/:*$//
   3247 ';
   3248   eval "${return_ok}";
   3249 }
   3250 
   3251 
   3252 ########################################################################
   3253 # path_clean (<path>)
   3254 #
   3255 # Remove non-existing directories from a colon-separated list.
   3256 #
   3257 # Argument: 1, a colon separated path.
   3258 # Output:   colon-separated list of existing directories.
   3259 #
   3260 # Variable prefix: pc
   3261 #
   3262 path_clean()
   3263 {
   3264   func_check path_clean = 1 "$@";
   3265   if is_not_equal "$#" 1
   3266   then
   3267     error 'path_clean() needs 1 argument.';
   3268   fi;
   3269   pc_arg="$1";
   3270   eval set x "$(path_split "${pc_arg}")";
   3271   exit_test;
   3272   shift;
   3273   pc_res="";
   3274   for i
   3275   do
   3276     pc_i="$i";
   3277     if obj pc_i is_not_empty \
   3278        && obj pc_res path_not_contains "${pc_i}" \
   3279        && obj pc_i is_dir
   3280     then
   3281       case "${pc_i}" in
   3282       ?*/)
   3283         pc_res="${pc_res}$(dirname_chop "${pc_i}")";
   3284         exit_test;
   3285         ;;
   3286       *)
   3287         pc_res="${pc_res}:${pc_i}";
   3288         exit_test;
   3289         ;;
   3290       esac;
   3291     fi;
   3292   done;
   3293   eval ${_UNSET} pc_arg;
   3294   eval ${_UNSET} pc_i;
   3295   eval ${_UNSET} pc_res;
   3296   if path_chop "${pc_res}"
   3297   then
   3298     eval "${return_ok}";
   3299   else
   3300     eval "${return_bad}";
   3301   fi;
   3302 }
   3303 
   3304 
   3305 ########################################################################
   3306 # path_contains (<path> <dir>)
   3307 #-
   3308 # Test whether `dir' is contained in `path', a list separated by `:'.
   3309 #
   3310 # Arguments : 2 arguments.
   3311 # Return    : `0' if arg2 is substring of arg1, `1' otherwise.
   3312 #
   3313 path_contains()
   3314 {
   3315   func_check path_contains = 2 "$@";
   3316   case ":$1:" in
   3317     *":$2:"*)
   3318       eval "${return_yes}";
   3319       ;;
   3320     *)
   3321       eval "${return_no}";
   3322       ;;
   3323   esac;
   3324   eval "${return_ok}";
   3325 }
   3326 
   3327 
   3328 ########################################################################
   3329 # path_not_contains (<path> <dir>)
   3330 #
   3331 # Test whether `dir' is not contained in colon separated `path'.
   3332 #
   3333 # Arguments : 2 arguments.
   3334 #
   3335 path_not_contains()
   3336 {
   3337   func_check path_not_contains = 2 "$@";
   3338   if path_contains "$1" "$2"
   3339   then
   3340     eval "${return_no}";
   3341   else
   3342     eval "${return_yes}";
   3343   fi;
   3344   eval "${return_ok}";
   3345 }
   3346 
   3347 
   3348 ########################################################################
   3349 # path_split (<path>)
   3350 #
   3351 # In `path' escape white space and replace each colon by a space.
   3352 #
   3353 # Arguments: 1: a colon-separated path
   3354 # Output:    the resulting list, process with `eval set'
   3355 #
   3356 path_split()
   3357 {
   3358   func_check path_split = 1 "$@";
   3359   list_from_split "$1" ':';
   3360   eval "${return_ok}";
   3361 }
   3362 
   3363 
   3364 ########################################################################
   3365 landmark '10: register_*()';
   3366 ########################################################################
   3367 
   3368 ########################################################################
   3369 # register_file (<filename>)
   3370 #
   3371 # Write a found file and register the title element.
   3372 #
   3373 # Arguments: 1: a file name
   3374 # Output: none
   3375 #
   3376 register_file()
   3377 {
   3378   func_check register_file = 1 "$@";
   3379   if is_empty "$1"
   3380   then
   3381     error 'register_file(): file name is empty';
   3382   fi;
   3383   if is_equal "$1" '-'
   3384   then
   3385     to_tmp "${_TMP_STDIN}";
   3386     register_title 'stdin';
   3387   else
   3388     to_tmp "$1";
   3389     register_title "$(base_name "$1")";
   3390     exit_test;
   3391   fi;
   3392   eval "${return_ok}";
   3393 } # register_file()
   3394 
   3395 
   3396 ########################################################################
   3397 # register_title (<filespec>)
   3398 #
   3399 # Create title element from <filespec> and append to $_REGISTERED_TITLE
   3400 #
   3401 # Globals: $_REGISTERED_TITLE (rw)
   3402 #
   3403 # Variable prefix: rt
   3404 #
   3405 register_title()
   3406 {
   3407   func_check register_title '=' 1 "$@";
   3408   if is_empty "$1"
   3409   then
   3410     eval "${return_ok}";
   3411   fi;
   3412 
   3413   case "${_REGISTERED_TITLE}" in
   3414   *\ *\ *\ *)
   3415     eval "${return_ok}";
   3416     ;;
   3417   esac;
   3418 
   3419   # remove directory part
   3420   rt_title="$(base_name "$1")";
   3421   # replace space characters by `_'
   3422   rt_title="$(echo1 "${rt_title}" | sed -e 's/[ 	]/_/g')";
   3423   # remove extension `.bz2'
   3424   rt_title="$(echo1 "${rt_title}" | sed -e 's/\.bz2$//')";
   3425   # remove extension `.gz'
   3426   rt_title="$(echo1 "${rt_title}" | sed -e 's/\.gz$//')";
   3427   # remove extension `.Z'
   3428   rt_title="$(echo1 "${rt_title}" | sed -e 's/\.Z$//')";
   3429   exit_test;
   3430 
   3431   if obj rt_title is_empty
   3432   then
   3433     eval ${_UNSET} rt_title;
   3434     eval "${return_ok}";
   3435   fi;
   3436   if obj _REGISTERED_TITLE is_empty
   3437   then
   3438     _REGISTERED_TITLE="${rt_title}";
   3439   else
   3440     _REGISTERED_TITLE="${_REGISTERED_TITLE} ${rt_title}";
   3441   fi;
   3442   eval ${_UNSET} rt_title;
   3443   eval "${return_ok}";
   3444 } # register_title()
   3445 
   3446 
   3447 ########################################################################
   3448 # reset ()
   3449 #
   3450 # Reset the variables that can be affected by options to their default.
   3451 #
   3452 #
   3453 # Defined in section `Preset' after the rudimentary shell tests.
   3454 
   3455 
   3456 ########################################################################
   3457 # rm_file (<file_name>)
   3458 #
   3459 # Remove file if $_DEBUG_KEEP_FILES allows it.
   3460 #
   3461 # Globals: $_DEBUG_KEEP_FILES
   3462 #
   3463 rm_file()
   3464 {
   3465   func_check rm_file '=' 1 "$@";
   3466   if is_file "$1"
   3467   then
   3468     rm -f "$1" >${_NULL_DEV} 2>&1;
   3469   fi;
   3470   if is_existing "$1"
   3471   then
   3472     eval "${return_bad}";
   3473   else
   3474     eval "${return_good}";
   3475   fi;
   3476 }
   3477 
   3478 
   3479 ########################################################################
   3480 # rm_file_with_debug (<file_name>)
   3481 #
   3482 # Remove file if $_DEBUG_KEEP_FILES allows it.
   3483 #
   3484 # Globals: $_DEBUG_KEEP_FILES
   3485 #
   3486 rm_file_with_debug()
   3487 {
   3488   func_check rm_file_with_debug '=' 1 "$@";
   3489   if obj _DEBUG_KEEP_FILES is_not_yes
   3490   then
   3491     if is_file "$1"
   3492     then
   3493       rm -f "$1" >${_NULL_DEV} 2>&1;
   3494     fi;
   3495   fi;
   3496   if is_existing "$1"
   3497   then
   3498     eval "${return_bad}";
   3499   else
   3500     eval "${return_good}";
   3501   fi;
   3502 }
   3503 
   3504 
   3505 ########################################################################
   3506 # rm_tree (<dir_name>)
   3507 #
   3508 # Remove file if $_DEBUG_KEEP_FILES allows it.
   3509 #
   3510 # Globals: $_DEBUG_KEEP_FILES
   3511 #
   3512 rm_tree()
   3513 {
   3514   func_check rm_tree '=' 1 "$@";
   3515   if is_existing "$1"
   3516   then
   3517     rm -f -r "$1" >${_NULL_DEV} 2>&1;
   3518   fi; 
   3519   if is_existing "$1"
   3520   then
   3521     eval "${return_bad}";
   3522   else
   3523     eval "${return_good}";
   3524   fi;
   3525 }
   3526 
   3527 
   3528 ########################################################################
   3529 # save_stdin ()
   3530 #
   3531 # Store standard input to temporary file (with decompression).
   3532 #
   3533 # Variable prefix: ss
   3534 #
   3535 if obj _HAS_COMPRESSION is_yes
   3536 then
   3537   save_stdin()
   3538   {
   3539     func_check save_stdin '=' 0 "$@";
   3540     ss_f="${_TMP_DIR}"/INPUT;
   3541     cat >"${ss_f}";
   3542     cat_z "${ss_f}" >"${_TMP_STDIN}";
   3543     rm_file "${ss_f}";
   3544     eval ${_UNSET} ss_f;
   3545     eval "${return_ok}";
   3546   }
   3547 else
   3548   save_stdin()
   3549   {
   3550     func_check save_stdin = 0 "$@";
   3551     cat >"${_TMP_STDIN}";
   3552     eval "${return_ok}";
   3553   }
   3554 fi;
   3555 
   3556 
   3557 ########################################################################
   3558 # special_filespec ()
   3559 #
   3560 # Handle special modes like whatis and apropos.
   3561 #
   3562 special_filespec()
   3563 {
   3564   func_check special_setup '=' 0 "$@";
   3565   if obj _OPT_APROPOS is_yes
   3566   then
   3567     if obj _OPT_WHATIS is_yes
   3568     then
   3569       error \
   3570         'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
   3571     fi;
   3572     apropos_filespec;
   3573     eval "${return_ok}";
   3574   fi;
   3575   if obj _OPT_WHATIS is_yes
   3576   then
   3577     whatis_filespec;
   3578   fi;
   3579   eval "${return_ok}";
   3580 }
   3581 
   3582 
   3583 ########################################################################
   3584 # special_setup ()
   3585 #
   3586 # Handle special modes like whatis and apropos.
   3587 #
   3588 special_setup()
   3589 {
   3590   func_check special_setup '=' 0 "$@";
   3591   if obj _OPT_APROPOS is_yes
   3592   then
   3593     if obj _OPT_WHATIS is_yes
   3594     then
   3595       error \
   3596         'special_setup: $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
   3597     fi;
   3598     apropos_setup;
   3599     eval "${return_ok}";
   3600   fi;
   3601   if obj _OPT_WHATIS is_yes
   3602   then
   3603     whatis_header;
   3604   fi;  
   3605   eval "${return_ok}";
   3606 }
   3607 
   3608 
   3609 ########################################################################
   3610 landmark '11: stack_*()';
   3611 ########################################################################
   3612 
   3613 ########################################################################
   3614 # string_contains (<string> <part>)
   3615 #
   3616 # Test whether `part' is contained in `string'.
   3617 #
   3618 # Arguments : 2 text arguments.
   3619 # Return    : `0' if arg2 is substring of arg1, `1' otherwise.
   3620 #
   3621 string_contains()
   3622 {
   3623   func_check string_contains '=' 2 "$@";
   3624   case "$1" in
   3625     *"$2"*)
   3626       eval "${return_yes}";
   3627       ;;
   3628     *)
   3629       eval "${return_no}";
   3630       ;;
   3631   esac;
   3632   eval "${return_ok}";
   3633 }
   3634 
   3635 
   3636 ########################################################################
   3637 # string_not_contains (<string> <part>)
   3638 #
   3639 # Test whether `part' is not substring of `string'.
   3640 #
   3641 # Arguments : 2 text arguments.
   3642 # Return    : `0' if arg2 is substring of arg1, `1' otherwise.
   3643 #
   3644 string_not_contains()
   3645 {
   3646   func_check string_not_contains '=' 2 "$@";
   3647   if string_contains "$1" "$2"
   3648   then
   3649     eval "${return_no}";
   3650   else
   3651     eval "${return_yes}";
   3652   fi;
   3653   eval "${return_ok}";
   3654 }
   3655 
   3656 
   3657 ########################################################################
   3658 landmark '12: tmp_*()';
   3659 ########################################################################
   3660 
   3661 ########################################################################
   3662 # tmp_cat ()
   3663 #
   3664 # output the temporary cat file (the concatenation of all input)
   3665 #
   3666 tmp_cat()
   3667 {
   3668   func_check tmp_cat '=' 0 "$@";
   3669   cat "${_TMP_CAT}";
   3670   eval "${return_var}" "$?";
   3671 }
   3672 
   3673 
   3674 ########################################################################
   3675 # tmp_create (<suffix>?)
   3676 #
   3677 # Create temporary file.
   3678 #
   3679 # It's safe to use the shell process ID together with a suffix to
   3680 # have multiple temporary files.
   3681 #
   3682 # Globals: $_TMP_DIR
   3683 #
   3684 # Output : name of created file
   3685 #
   3686 # Variable prefix: tc
   3687 #
   3688 tmp_create()
   3689 {
   3690   func_check tmp_create '<=' 1 "$@";
   3691   # the output file does not have `,' as first character, so these are
   3692   # different names from the output file.
   3693   tc_tmp="${_TMP_DIR}/,$1";
   3694   : >"${tc_tmp}"
   3695   obj tc_tmp echo1;
   3696   eval ${_UNSET} tc_tmp;
   3697   eval "${return_ok}";
   3698 }
   3699 
   3700 
   3701 ########################################################################
   3702 # to_tmp (<filename>)
   3703 #
   3704 # print file (decompressed) to the temporary cat file
   3705 #
   3706 to_tmp()
   3707 {
   3708   func_check to_tmp '=' 1 "$@";
   3709   if obj _TMP_CAT is_empty
   3710   then
   3711     error 'to_tmp_line: $_TMP_CAT is not yet set';
   3712   fi;
   3713   if is_file "$1"
   3714   then
   3715     if obj _OPT_LOCATION is_yes
   3716     then
   3717       echo2 "$1";
   3718     fi;
   3719     if obj _OPT_WHATIS is_yes
   3720     then
   3721       whatis_filename "$1" >>"${_TMP_CAT}";
   3722     else
   3723       cat_z "$1" >>"${_TMP_CAT}";
   3724     fi;
   3725   else
   3726     error "to_tmp(): could not read file \`$1'.";
   3727   fi;
   3728   eval "${return_ok}";
   3729 }
   3730 
   3731 
   3732 ########################################################################
   3733 # to_tmp_line ([<text>])
   3734 #
   3735 # print line to the temporary cat file
   3736 #
   3737 to_tmp_line()
   3738 {
   3739   func_check to_tmp '>=' 0 "$@";
   3740   if obj _TMP_CAT is_empty
   3741   then
   3742     error 'to_tmp_line: $_TMP_CAT is not yet set';
   3743   fi;
   3744   echo1 "$*" >>"${_TMP_CAT}";
   3745   eval "${return_ok}";
   3746 }
   3747 
   3748 
   3749 ########################################################################
   3750 # trap_set
   3751 #
   3752 # call function on signal 0
   3753 #
   3754 trap_set()
   3755 {
   3756   func_check trap_set '=' 0 "$@";
   3757   trap 'clean_up' 0 2>${_NULL_DEV} || :;
   3758   eval "${return_ok}";
   3759 }
   3760 
   3761 
   3762 ########################################################################
   3763 # trap_unset ()
   3764 #
   3765 # disable trap on signal 0.
   3766 #
   3767 trap_unset()
   3768 {
   3769   func_check trap_unset '=' 0 "$@";
   3770   trap '' 0 2>${_NULL_DEV} || :;
   3771   eval "${return_ok}";
   3772 }
   3773 
   3774 
   3775 ########################################################################
   3776 # usage ()
   3777 #
   3778 # print usage information to stderr; for groffer option --help.
   3779 #
   3780 usage()
   3781 {
   3782   func_check usage = 0 "$@";
   3783   echo;
   3784   version;
   3785   echo1 'Usage: groffer [option]... [filespec]...';
   3786   cat <<EOF
   3787 
   3788 Display roff files, standard input, and/or Unix manual pages with a X
   3789 Window viewer or in several text modes.  All input is decompressed
   3790 on-the-fly with all formats that gzip can handle.
   3791 
   3792 "filespec" is one of
   3793   "filename"       name of a readable file
   3794   "-"              for standard input
   3795   "man:name.n"     man page "name" in section "n"
   3796   "man:name"       man page "name" in first section found
   3797   "name.n"         man page "name" in section "n"
   3798   "name"           man page "name" in first section found
   3799 and some more (see groffer(1) for details).
   3800 
   3801 -h --help         print this usage message.
   3802 -Q --source       output as roff source.
   3803 -T --device=name  pass to groff using output device "name".
   3804 -v --version      print version information.
   3805 -V                display the groff execution pipe instead of formatting.
   3806 -X                display with "gxditview" using groff -X.
   3807 -Z --ditroff --intermediate-output
   3808                   generate groff intermediate output without
   3809                   post-processing and viewing, like groff -Z.
   3810 All other short options are interpreted as "groff" formatting options.
   3811 
   3812 The most important groffer long options are
   3813 
   3814 --apropos=name    start man's "apropos" program for "name".
   3815 --apropos-data=name
   3816                   "apropos" for "name" in man's data sections 4, 5, 7.
   3817 --apropos-devel=name
   3818                   "apropos" for "name" in development sections 2, 3, 9.
   3819 --apropos-progs=name
   3820                   "apropos" for "name" in man's program sections 1, 6, 8.
   3821 --auto            choose mode automatically from the default mode list.
   3822 --default         reset all options to the default value.
   3823 --default-modes=mode1,mode2,...
   3824                   set sequence of automatically tried modes.
   3825 --dvi             display in a viewer for TeX device independent format.
   3826 --dvi-viewer=prog choose the viewer program for dvi mode.
   3827 --groff           process like groff, disable viewing features.
   3828 --help            display this helping output.
   3829 --html            display in a web browser.
   3830 --html-viewer=program
   3831                   choose the web browser for html mode.
   3832 --man             check file parameters first whether they are man pages.
   3833 --mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
   3834                   choose display mode.
   3835 --no-man          disable man-page facility.
   3836 --no-special      disable --all, --apropos*, and --whatis
   3837 --pager=program   preset the paging program for tty mode.
   3838 --pdf             display in a PDF viewer.
   3839 --pdf-viewer=prog choose the viewer program for pdf mode.
   3840 --ps              display in a Postscript viewer.
   3841 --ps-viewer=prog  choose the viewer program for ps mode.
   3842 --shell=program   specify a shell under which to run groffer2.sh.
   3843 --text            output in a text device without a pager.
   3844 --tty             display with a pager on text terminal even when in X.
   3845 --tty-viewer=prog select a pager for tty mode; same as --pager.
   3846 --whatis          display the file name and description of man pages
   3847 --www             same as --html.
   3848 --www-viewer=prog same as --html-viewer
   3849 --x --X           display with "gxditview" using an X* device.
   3850 --x-viewer=prog   choose viewer program for x mode (X mode).
   3851 --X-viewer=prog   same as "--xviewer".
   3852 
   3853 Development options that are not useful for normal usage:
   3854 --debug, --debug-all, --debug-keep, --debug-lm, --debug-params,
   3855 --debug-shell, --debug-stacks, --debug-tmpdir, --debug-user,
   3856 --do-nothing, --print=text
   3857 
   3858 Viewer programs for the different modes that run on the terminal:
   3859 --dvi-viewer-tty=prog, --html-viewer-tty=prog, --pdf-viewer-tty=prog,
   3860 --ps-viewer-tty=prog, --tty-viewer-tty, --X-viewer-tty=prog,
   3861 --x-viewer-tty=prog, --www-viewer-tty=prog
   3862 
   3863 The usual X Windows toolkit options transformed into GNU long options:
   3864 --background=color, --bd=size, --bg=color, --bordercolor=color,
   3865 --borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
   3866 --fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
   3867 --resolution=dpi, --rv, --title=text, --xrm=resource
   3868 
   3869 Long options of GNU "man":
   3870 --all, --ascii, --ditroff, --extension=suffix, --locale=language,
   3871 --local-file=name, --location, --manpath=dir1:dir2:...,
   3872 --sections=s1:s2:..., --systems=s1,s2,..., --where, ...
   3873 
   3874 EOF
   3875   eval "${return_ok}";
   3876 }
   3877 
   3878 
   3879 ########################################################################
   3880 # version ()
   3881 #
   3882 # print version information to stderr
   3883 #
   3884 version()
   3885 {
   3886   func_check version = 0 "$@";
   3887   echo1 "groffer ${_PROGRAM_VERSION} of ${_LAST_UPDATE}";
   3888   # also display groff's version, but not the called subprograms
   3889   groff -v 2>&1 | sed -e '/^ *$/q' | sed -e '1s/^/is part of /';
   3890   eval "${return_ok}";
   3891 }
   3892 
   3893 
   3894 ########################################################################
   3895 # warning (<string>)
   3896 #
   3897 # Print warning to stderr
   3898 #
   3899 warning()
   3900 {
   3901   echo2 "warning: $*";
   3902 }
   3903 
   3904 
   3905 ########################################################################
   3906 # whatis_filename (<filename>)
   3907 #
   3908 # Interpret <filename> as a man page and display its `whatis'
   3909 # information as a fragment written in the groff language.
   3910 #
   3911 # Variable prefix: wf
   3912 #
   3913 whatis_filename()
   3914 {
   3915   func_check whatis_filename = 1 "$@";
   3916   wf_arg="$1";
   3917   if obj wf_arg is_not_file
   3918   then
   3919     error "whatis_filename(): argument is not a readable file."
   3920   fi;
   3921   wf_dot='^\.'"${_SPACE_SED}"'*';
   3922   if obj _FILESPEC_ARG is_equal '-'
   3923   then
   3924     wf_arg='stdin';
   3925   fi;
   3926   cat <<EOF
   3927 \f[CR]${wf_arg}\f[]:
   3928 .br
   3929 EOF
   3930 
   3931   # get the parts of the file name
   3932   wf_name="$(base_name $1)";
   3933   wf_section="$(echo1 $1 | sed -n -e '
   3934 s|^.*/man\('"${_MAN_AUTO_SEC_CHARS}"'\).*$|\1|p
   3935 ')";
   3936   if obj wf_section is_not_empty
   3937   then
   3938     case "${wf_name}" in
   3939     *.${wf_section}*)
   3940       s='yes';
   3941       ;;
   3942     *)
   3943       s='';
   3944       wf_section='';
   3945       ;;
   3946     esac
   3947     if obj s is_yes
   3948     then
   3949       wf_name="$(echo1 ${wf_name} | sed -e '
   3950 s/^\(.*\)\.'${wf_section}'.*$/\1/
   3951 ')";
   3952     fi;
   3953   fi;
   3954 
   3955   # traditional man style; grep the line containing `.TH' macro, if any
   3956   wf_res="$(cat_z "$1" | sed -e '
   3957 /'"${wf_dot}"'TH /p
   3958 d
   3959 ')";
   3960   exit_test;
   3961   if obj wf_res is_not_empty
   3962   then				# traditional man style
   3963     # get the first line after the first `.SH' macro, by
   3964     # - delete up to first .SH;
   3965     # - print all lines before the next .SH;
   3966     # - quit.
   3967     wf_res="$(cat_z "$1" | sed -n -e '
   3968 1,/'"${wf_dot}"'SH/d
   3969 /'"${wf_dot}"'SH/q
   3970 p
   3971 ')";
   3972 
   3973     if obj wf_section is_not_empty
   3974     then
   3975       case "${wf_res}" in
   3976       ${wf_name}${_SPACE_CASE}*-${_SPACE_CASE}*)
   3977         s='yes';
   3978         ;;
   3979       *)
   3980         s='';
   3981         ;;
   3982       esac;
   3983       if obj s is_yes
   3984       then
   3985         wf_res="$(obj wf_res echo1 | sed -e '
   3986 s/^'"${wf_name}${_SPACE_SED}"'[^-]*-'"${_SPACE_SED}"'*\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/
   3987 ')";
   3988       fi;
   3989     fi;
   3990     obj wf_res echo1;
   3991     echo;
   3992     eval ${_UNSET} wf_arg;
   3993     eval ${_UNSET} wf_dot;
   3994     eval ${_UNSET} wf_name;
   3995     eval ${_UNSET} wf_res;
   3996     eval ${_UNSET} wf_section;
   3997     eval "${return_ok}";
   3998   fi;
   3999 
   4000   # mdoc style (BSD doc); grep the line containing `.Nd' macro, if any
   4001   wf_res="$(cat_z "$1" | sed -n -e '/'"${wf_dot}"'Nd /s///p')";
   4002   exit_test;
   4003   if obj wf_res is_not_empty
   4004   then				# BSD doc style
   4005     if obj wf_section is_not_empty
   4006     then
   4007       wf_res="$(obj wf_res echo1 | sed -n -e '
   4008 s/^\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/p
   4009 ')";
   4010     fi;
   4011     obj wf_res echo1;
   4012     echo;
   4013     eval ${_UNSET} wf_arg;
   4014     eval ${_UNSET} wf_dot;
   4015     eval ${_UNSET} wf_name;
   4016     eval ${_UNSET} wf_res;
   4017     eval ${_UNSET} wf_section;
   4018     eval "${return_ok}";
   4019   fi;
   4020   echo1 'is not a man page';
   4021   echo;
   4022   eval ${_UNSET} wf_arg;
   4023   eval ${_UNSET} wf_dot;
   4024   eval ${_UNSET} wf_name;
   4025   eval ${_UNSET} wf_res;
   4026   eval ${_UNSET} wf_section;
   4027   eval "${return_bad}";
   4028 }
   4029 
   4030 
   4031 ########################################################################
   4032 # whatis_filespec ()
   4033 #
   4034 # Print the filespec name as .SH to the temporary cat file.
   4035 #
   4036 whatis_filespec()
   4037 {
   4038   func_check whatis_filespec '=' 0 "$@";
   4039   if obj _OPT_WHATIS is_yes
   4040   then
   4041     eval to_tmp_line \
   4042       "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
   4043     exit_test;
   4044   fi;
   4045   eval "${return_ok}";
   4046 }
   4047 
   4048 
   4049 ########################################################################
   4050 # whatis_header ()
   4051 #
   4052 # Print the whatis header to the temporary cat file.
   4053 #
   4054 whatis_header()
   4055 {
   4056   func_check whatis_header '=' 0 "$@";
   4057   if obj _OPT_WHATIS is_yes
   4058   then
   4059      to_tmp_line '.TH GROFFER WHATIS';
   4060   fi;
   4061   eval "${return_ok}";
   4062 }
   4063 
   4064 
   4065 ########################################################################
   4066 # where_is (<program>)
   4067 #
   4068 # Output path of a program if in $PATH.
   4069 #
   4070 # Arguments : >=1 (empty allowed)
   4071 #   more args are ignored, this allows to specify progs with arguments
   4072 # Return    : `0' if arg1 is a program in $PATH, `1' otherwise.
   4073 #
   4074 # Variable prefix: w
   4075 #
   4076 where_is()
   4077 {
   4078   func_check where_is '>=' 1 "$@";
   4079   w_arg="$1";
   4080   if obj w_arg is_empty
   4081   then
   4082     eval ${_UNSET} w_arg;
   4083     eval "${return_bad}";
   4084   fi;
   4085   case "${w_arg}" in
   4086     /*)
   4087       eval ${_UNSET} w_arg;
   4088       eval ${_UNSET} w_file;
   4089       if test -f "${w_arg}" && test -x "${w_arg}"
   4090       then
   4091         eval "${return_ok}";
   4092       else
   4093         eval "${return_bad}";
   4094       fi;
   4095       ;;
   4096   esac;
   4097   eval set x "$(path_split "${PATH}")";
   4098   exit_test;
   4099   shift;
   4100   for p
   4101   do
   4102     case "$p" in
   4103       */) w_file=${p}${w_arg}; ;;
   4104       *)  w_file=${p}/${w_arg}; ;;
   4105     esac;
   4106     if test -f "${w_file}" && test -x "${w_file}"
   4107     then
   4108       obj w_file echo1;
   4109       eval ${_UNSET} w_arg;
   4110       eval ${_UNSET} w_file;
   4111       eval "${return_ok}";
   4112     fi;
   4113   done;
   4114   eval ${_UNSET} w_arg;
   4115   eval ${_UNSET} w_file;
   4116   eval "${return_bad}";
   4117 }
   4118 
   4119 
   4120 ########################################################################
   4121 #                        main* Functions
   4122 ########################################################################
   4123 
   4124 # The main area contains the following parts:
   4125 # - main_init(): initialize temporary files and set exit trap
   4126 # - main_parse_MANOPT(): parse $MANOPT
   4127 # - main_parse_args(): argument parsing
   4128 # - main_set_mode (): determine the display mode
   4129 # - main_do_fileargs(): process filespec arguments
   4130 # - main_set_resources(): setup X resources
   4131 # - main_display(): do the displaying
   4132 # - main(): the main function that calls all main_*()
   4133 
   4134 
   4135 #######################################################################
   4136 # main_init ()
   4137 #
   4138 # set exit trap and create temporary files
   4139 #
   4140 # Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
   4141 #
   4142 # Variable prefix: mi
   4143 #
   4144 main_init()
   4145 {
   4146   func_check main_init = 0 "$@";
   4147   # call clean_up() on shell termination.
   4148   trap_set;
   4149 
   4150   # create temporary directory
   4151   umask 0022;
   4152   _TMP_DIR='';
   4153   for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
   4154            "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
   4155   do
   4156     mi_dir="$d";
   4157     if obj mi_dir is_empty || obj mi_dir is_not_dir || \
   4158        obj mi_dir is_not_writable
   4159     then
   4160       continue;
   4161     fi;
   4162 
   4163     case "${mi_dir}" in
   4164     */)
   4165       _TMP_DIR="${mi_dir}";
   4166       ;;
   4167     *)
   4168       _TMP_DIR="${mi_dir}"'/';
   4169       ;;
   4170     esac;
   4171     _TMP_DIR="${_TMP_DIR}groffer${_PROCESS_ID}";
   4172     if obj _TMP_DIR rm_tree
   4173     then
   4174       :
   4175     else
   4176       mi_tdir_="${_TMP_DIR}"_;
   4177       mi_n=1;
   4178       mi_tdir_n="${mi_tdir_}${mi_n}";
   4179       while obj mi_tdir_n is_existing
   4180       do
   4181         if obj mi_tdir_n rm_tree
   4182         then
   4183           # directory could not be removed
   4184           mi_n="$(expr "${mi_n}" + 1)";
   4185           mi_tdir_n="${mi_tdir_}${mi_n}";
   4186           continue;
   4187         fi;
   4188       done;
   4189       _TMP_DIR="${mi_tdir_n}";
   4190     fi;
   4191     eval mkdir "${_TMP_DIR}";
   4192     if is_not_equal "$?" 0
   4193     then
   4194       obj _TMP_DIR rm_tree;
   4195       _TMP_DIR='';
   4196       continue;
   4197     fi;
   4198     if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable
   4199     then
   4200       # $_TMP_DIR can now be used as temporary directory
   4201       break;
   4202     fi;
   4203     obj _TMP_DIR rm_tree;
   4204     _TMP_DIR='';
   4205     continue;
   4206   done;
   4207   if obj _TMP_DIR is_empty
   4208   then
   4209     error "main_init: \
   4210 Couldn't create a directory for storing temporary files.";
   4211   fi;
   4212   if obj _DEBUG_PRINT_TMPDIR is_yes
   4213   then
   4214     echo2 "temporary directory: ${_TMP_DIR}";
   4215   fi;
   4216 
   4217   _TMP_CAT="$(tmp_create groffer_cat)";
   4218   _TMP_STDIN="$(tmp_create groffer_input)";
   4219   exit_test;
   4220 
   4221   eval ${_UNSET} mi_dir;
   4222   eval ${_UNSET} mi_n;
   4223   eval ${_UNSET} mi_tdir_;
   4224   eval ${_UNSET} mi_tdir_n;
   4225   eval "${return_ok}";
   4226 } # main_init()
   4227 
   4228 
   4229 ########################################################################
   4230 # main_parse_MANOPT ()
   4231 #
   4232 # Parse $MANOPT to retrieve man options, but only if it is a non-empty
   4233 # string; found man arguments can be overwritten by the command line.
   4234 #
   4235 # Globals:
   4236 #   in: $MANOPT, $_OPTS_MANOPT_*
   4237 #   out: $_MANOPT_*
   4238 #
   4239 # Variable prefix: mpm
   4240 #
   4241 main_parse_MANOPT()
   4242 {
   4243   func_check main_parse_MANOPT = 0 "$@";
   4244 
   4245   if obj MANOPT is_not_empty
   4246   then
   4247     # Delete leading and final spaces
   4248     MANOPT="$(echo1 "${MANOPT}" | sed -e '
   4249 s/^'"${_SPACE_SED}"'*//
   4250 s/'"${_SPACE_SED}"'*$//
   4251 ')";
   4252   exit_test;
   4253   fi;
   4254   if obj MANOPT is_empty
   4255   then
   4256     eval "${return_ok}";
   4257   fi;
   4258 
   4259   mpm_list='';
   4260   # add arguments in $MANOPT by mapping them to groffer options
   4261   eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
   4262   exit_test;
   4263   shift;
   4264   until test "$#" -le 0 || is_equal "$1" '--'
   4265   do
   4266     mpm_opt="$1";
   4267     shift;
   4268     case "${mpm_opt}" in
   4269     -7|--ascii)
   4270       list_append mpm_list '--ascii';
   4271       ;;
   4272     -a|--all)
   4273       list_append mpm_list '--all';
   4274       ;;
   4275     -c|--catman)
   4276       do_nothing;
   4277       shift;
   4278       ;;
   4279     -d|--debug)
   4280       do_nothing;
   4281       ;;
   4282     -D|--default)
   4283       # undo all man options so far
   4284       mpm_list='';
   4285       ;;
   4286     -e|--extension)
   4287       list_append mpm_list '--extension';
   4288       shift;
   4289       ;;
   4290     -f|--whatis)
   4291       list_append mpm_list '--whatis';
   4292       shift;
   4293       ;;
   4294     -h|--help)
   4295       do_nothing;
   4296       shift;
   4297       ;;
   4298     -k|--apropos)
   4299       # groffer's --apropos takes an argument, but man's does not, so
   4300       do_nothing;
   4301       ;;
   4302     -l|--local-file)
   4303       do_nothing;
   4304       ;;
   4305     -L|--locale)
   4306       list_append mpm_list '--locale' "$1";
   4307       shift;
   4308       ;;
   4309     -m|--systems)
   4310       list_append mpm_list '--systems' "$1";
   4311       shift;
   4312       ;;
   4313     -M|--manpath)
   4314       list_append mpm_list '--manpath' "$1";
   4315       shift;
   4316       ;;
   4317     -p|--preprocessor)
   4318       do_nothing;
   4319       shift;
   4320       ;;
   4321     -P|--pager)
   4322       list_append mpm_list '--pager' "$1";
   4323       shift;
   4324       ;;
   4325     -r|--prompt)
   4326       do_nothing;
   4327       shift;
   4328       ;;
   4329     -S|--sections)
   4330       list_append mpm_list '--sections' "$1";
   4331       shift;
   4332       ;;
   4333     -t|--troff)
   4334       do_nothing;
   4335       shift;
   4336       ;;
   4337     -T|--device)
   4338       list_append mpm_list '-T' "$1";
   4339       shift;
   4340       ;;
   4341     -u|--update)
   4342       do_nothing;
   4343       shift;
   4344       ;;
   4345     -V|--version)
   4346       do_nothing;
   4347       ;;
   4348     -w|--where|--location)
   4349       list_append mpm_list '--location';
   4350       ;;
   4351     -Z|--ditroff)
   4352       do_nothing;
   4353       ;;
   4354     # ignore all other options
   4355     esac;
   4356   done;
   4357 
   4358   # prepend $mpm_list to the command line
   4359   if obj mpm_list is_not_empty
   4360   then
   4361     eval set x "${mpm_list}" '"$@"';
   4362     shift;
   4363   fi;
   4364 
   4365   eval ${_UNSET} mpm_list;
   4366   eval ${_UNSET} mpm_opt;
   4367   eval "${return_ok}";
   4368 } # main_parse_MANOPT()
   4369 
   4370 
   4371 ########################################################################
   4372 # main_parse_args (<command_line_args>*)
   4373 #
   4374 # Parse arguments; process options and filespec parameters
   4375 #
   4376 # Arguments: pass the command line arguments unaltered.
   4377 # Globals:
   4378 #   in:  $_OPTS_*
   4379 #   out: $_OPT_*, $_ADDOPTS, $_FILEARGS
   4380 #
   4381 # Variable prefix: mpa
   4382 #
   4383 main_parse_args()
   4384 {
   4385   func_check main_parse_args '>=' 0 "$@";
   4386   _ALL_PARAMS="$(list_from_cmdline _OPTS_CMDLINE "$@")";
   4387   exit_test;
   4388   if obj _DEBUG_PRINT_PARAMS is_yes
   4389   then
   4390     echo2 "parameters: ${_ALL_PARAMS}";
   4391   fi;
   4392   eval set x "${_ALL_PARAMS}";
   4393   shift;
   4394 
   4395   # By the call of `eval', unnecessary quoting was removed.  So the
   4396   # positional shell parameters ($1, $2, ...) are now guaranteed to
   4397   # represent an option or an argument to the previous option, if any;
   4398   # then a `--' argument for separating options and
   4399   # parameters; followed by the filespec parameters if any.
   4400 
   4401   # Note, the existence of arguments to options has already been checked.
   4402   # So a check for `$#' or `--' should not be done for arguments.
   4403 
   4404   until test "$#" -le 0 || is_equal "$1" '--'
   4405   do
   4406     mpa_opt="$1";		# $mpa_opt is fed into the option handler
   4407     shift;
   4408     case "${mpa_opt}" in
   4409     -h|--help)
   4410       usage;
   4411       leave;
   4412       ;;
   4413     -Q|--source)		# output source code (`Quellcode').
   4414       _OPT_MODE='source';
   4415       ;;
   4416     -T|--device|--troff-device) # device; arg
   4417       _OPT_DEVICE="$1";
   4418       _check_device_with_mode;
   4419       shift;
   4420       ;;
   4421     -v|--version)
   4422       version;
   4423       leave;
   4424       ;;
   4425     -V)
   4426       _OPT_V='yes';
   4427       ;;
   4428     -Z|--ditroff|--intermediate-output) # groff intermediate output
   4429       _OPT_Z='yes';
   4430       ;;
   4431     -X)
   4432       if is_X
   4433       then
   4434         _OPT_MODE=X;
   4435       fi;
   4436       ;;
   4437     -?)
   4438       # delete leading `-'
   4439       mpa_optchar="$(echo1 "${mpa_opt}" | sed -e 's/^-//')";
   4440       exit_test;
   4441       if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}"
   4442       then
   4443         list_append _ADDOPTS_GROFF "${mpa_opt}";
   4444       elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}"
   4445       then
   4446         list_append _ADDOPTS_GROFF "${mpa_opt}" "$1";
   4447         shift;
   4448       else
   4449         error "main_parse_args(): Unknown option : \`$1'";
   4450       fi;
   4451       ;;
   4452     --all)
   4453         _OPT_ALL='yes';
   4454         ;;
   4455     --apropos)			# run `apropos'
   4456       _OPT_APROPOS='yes';
   4457       _APROPOS_SECTIONS='';
   4458       _OPT_WHATIS='no';
   4459       ;;
   4460     --apropos-data)		# run `apropos' for data sections
   4461       _OPT_APROPOS='yes';
   4462       _APROPOS_SECTIONS='457';
   4463       _OPT_WHATIS='no';
   4464       ;;
   4465     --apropos-devel)		# run `apropos' for development sections
   4466       _OPT_APROPOS='yes';
   4467       _APROPOS_SECTIONS='239';
   4468       _OPT_WHATIS='no';
   4469       ;;
   4470     --apropos-progs)		# run `apropos' for program sections
   4471       _OPT_APROPOS='yes';
   4472       _APROPOS_SECTIONS='168';
   4473       _OPT_WHATIS='no';
   4474       ;;
   4475     --ascii)
   4476       list_append _ADDOPTS_GROFF '-mtty-char';
   4477       if obj _OPT_MODE is_empty
   4478       then
   4479         _OPT_MODE='text';
   4480       fi;
   4481       ;;
   4482     --auto)			# the default automatic mode
   4483       _OPT_MODE='';
   4484       ;;
   4485     --bd)			# border color for viewers, arg;
   4486       _OPT_BD="$1";
   4487       shift;
   4488       ;;
   4489     --bg|--backgroud)		# background color for viewers, arg;
   4490       _OPT_BG="$1";
   4491       shift;
   4492       ;;
   4493     --bw)			# border width for viewers, arg;
   4494       _OPT_BW="$1";
   4495       shift;
   4496       ;;
   4497     --debug|--debug-all|--debug-keep|--debug-lm|--debug-params|\
   4498 --debug-shell|--debug-stacks|--debug-tmpdir|--debug-user)
   4499       # debug is handled at the beginning
   4500       :;
   4501       ;;
   4502     --default)			# reset variables to default
   4503       reset;
   4504       ;;
   4505     --default-modes)		# sequence of modes in auto mode; arg
   4506       _OPT_DEFAULT_MODES="$1";
   4507       shift;
   4508       ;;
   4509     --display)			# set X display, arg
   4510       _OPT_DISPLAY="$1";
   4511       shift;
   4512       ;;
   4513     --do-nothing)
   4514       _OPT_DO_NOTHING='yes';
   4515       ;;
   4516     --dvi)
   4517       if is_X
   4518       then
   4519         _OPT_MODE='dvi';
   4520       fi;
   4521       ;;
   4522     --dvi-viewer)		# viewer program for dvi mode; arg
   4523       _VIEWER_TERMINAL='no';
   4524       _OPT_VIEWER_DVI="$1";
   4525       shift;
   4526       ;;
   4527     --dvi-viewer-tty)		# viewer program for dvi mode in tty; arg
   4528       _VIEWER_TERMINAL='yes';
   4529       _OPT_VIEWER_DVI="$1";
   4530       shift;
   4531       ;;
   4532     --extension)		# the extension for man pages, arg
   4533       _OPT_EXTENSION="$1";
   4534       shift;
   4535       ;;
   4536     --fg|--foreground)		# foreground color for viewers, arg;
   4537       _OPT_FG="$1";
   4538       shift;
   4539       ;;
   4540     --fn|--font)		# set font for viewers, arg;
   4541       _OPT_FN="$1";
   4542       shift;
   4543       ;;
   4544     --geometry)			# window geometry for viewers, arg;
   4545       _OPT_GEOMETRY="$1";
   4546       shift;
   4547       ;;
   4548     --groff)
   4549       _OPT_MODE='groff';
   4550       ;;
   4551     --html|--www)		# display with web browser
   4552       _OPT_MODE=html;
   4553       ;;
   4554     --html-viewer|--www-viewer) # viewer program for html mode; arg
   4555       _VIEWER_TERMINAL='no';
   4556       _OPT_VIEWER_HTML="$1";
   4557       shift;
   4558       ;;
   4559     --html-viewer-tty|--www-viewer-tty) # viewer for html mode in tty; arg
   4560       _VIEWER_TERMINAL='yes';
   4561       _OPT_VIEWER_HTML="$1";
   4562       shift;
   4563       ;;
   4564     --iconic)			# start viewers as icons
   4565       _OPT_ICONIC='yes';
   4566       ;;
   4567     --locale)			# set language for man pages, arg
   4568       # argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
   4569       _OPT_LANG="$1";
   4570       shift;
   4571       ;;
   4572     --local-file)		# force local files; same as `--no-man'
   4573       _MAN_FORCE='no';
   4574       _MAN_ENABLE='no';
   4575       ;;
   4576     --location|--where)		# print file locations to stderr
   4577       _OPT_LOCATION='yes';
   4578       ;;
   4579     --man)		       # force all file params to be man pages
   4580       _MAN_ENABLE='yes';
   4581       _MAN_FORCE='yes';
   4582       ;;
   4583     --manpath)		      # specify search path for man pages, arg
   4584       # arg is colon-separated list of directories
   4585       _OPT_MANPATH="$1";
   4586       shift;
   4587       ;;
   4588     --mode)			# display mode
   4589       mpa_arg="$1";
   4590       shift;
   4591       case "${mpa_arg}" in
   4592       auto|'')		     # search mode automatically among default
   4593         _OPT_MODE='';
   4594         ;;
   4595       groff)			# pass input to plain groff
   4596         _OPT_MODE='groff';
   4597         ;;
   4598       html|www)			# display with a web browser
   4599         _OPT_MODE='html';
   4600         ;;
   4601       dvi)			# display with xdvi viewer
   4602         if is_X
   4603         then
   4604           _OPT_MODE='dvi';
   4605         fi;
   4606         ;;
   4607       pdf)			# display with PDF viewer
   4608         if is_X
   4609         then
   4610           _OPT_MODE='pdf';
   4611         fi;
   4612         ;;
   4613       ps)			# display with Postscript viewer
   4614         if is_X
   4615         then
   4616           _OPT_MODE='ps';
   4617         fi;
   4618         ;;
   4619       text)			# output on terminal
   4620         _OPT_MODE='text';
   4621         ;;
   4622       tty)			# output on terminal
   4623         _OPT_MODE='tty';
   4624         ;;
   4625       X|x)			# output on X roff viewer
   4626         if is_X
   4627         then
   4628           _OPT_MODE='x';
   4629         fi;
   4630         ;;
   4631       Q|source)			# display source code
   4632         _OPT_MODE="source";
   4633         ;;
   4634       *)
   4635         error "main_parse_args(): unknown mode ${mpa_arg}";
   4636         ;;
   4637       esac;
   4638       ;;
   4639     --no-location)		# disable former call to `--location'
   4640       _OPT_LOCATION='yes';
   4641       ;;
   4642     --no-man)			# disable search for man pages
   4643       # the same as --local-file
   4644       _MAN_FORCE='no';
   4645       _MAN_ENABLE='no';
   4646       ;;
   4647     --no-special)		# disable some special former calls
   4648       _OPT_ALL='no'
   4649       _OPT_APROPOS='no'
   4650       _OPT_WHATIS='no'
   4651       ;;
   4652     --pager|--tty-viewer|--tty-viewer-tty)
   4653       # set paging program for tty mode, arg
   4654       _VIEWER_TERMINAL='yes';
   4655       _OPT_PAGER="$1";
   4656       shift;
   4657       ;;
   4658     --pdf)
   4659       if is_X
   4660       then
   4661         _OPT_MODE='pdf';
   4662       fi;
   4663       ;;
   4664     --pdf-viewer)		# viewer program for ps mode; arg
   4665       _VIEWER_TERMINAL='no';
   4666       _OPT_VIEWER_PDF="$1";
   4667       shift;
   4668       ;;
   4669     --pdf-viewer-tty)		# viewer program for ps mode in tty; arg
   4670       _VIEWER_TERMINAL='yes';
   4671       _OPT_VIEWER_PDF="$1";
   4672       shift;
   4673       ;;
   4674     --print)			# for argument test
   4675       echo2 "$1";
   4676       shift;
   4677       ;;
   4678     --ps)
   4679       if is_X
   4680       then
   4681         _OPT_MODE='ps';
   4682       fi;
   4683       ;;
   4684     --ps-viewer)		# viewer program for ps mode; arg
   4685       _VIEWER_TERMINAL='no';
   4686       _OPT_VIEWER_PS="$1";
   4687       shift;
   4688       ;;
   4689     --ps-viewer-tty)		# viewer program for ps mode in tty; arg
   4690       _VIEWER_TERMINAL='yes';
   4691       _OPT_VIEWER_PS="$1";
   4692       shift;
   4693       ;;
   4694     --resolution)		# set resolution for X devices, arg
   4695       mpa_arg="$1";
   4696       shift;
   4697       case "${mpa_arg}" in
   4698       75|75dpi)
   4699         mpa_dpi=75;
   4700         ;;
   4701       100|100dpi)
   4702         mpa_dpi=100;
   4703         ;;
   4704       *)
   4705         error "main_parse_args(): \
   4706 only resoutions of 75 or 100 dpi are supported";
   4707         ;;
   4708       esac;
   4709       _OPT_RESOLUTION="${mpa_dpi}";
   4710       ;;
   4711     --rv)
   4712       _OPT_RV='yes';
   4713       ;;
   4714     --sections)			# specify sections for man pages, arg
   4715       # arg is colon-separated list of section names
   4716       _OPT_SECTIONS="$1";
   4717       shift;
   4718       ;;
   4719     --shell)
   4720       # already done during the first run; so ignore the argument
   4721       shift;
   4722       ;;
   4723     --systems)			# man pages for different OS's, arg
   4724       # argument is a comma-separated list
   4725       _OPT_SYSTEMS="$1";
   4726       shift;
   4727       ;;
   4728     --text)			# text mode without pager
   4729       _OPT_MODE=text;
   4730       ;;
   4731     --title)			# title for X viewers; arg
   4732       _OPT_TITLE="$1";
   4733       shift;
   4734       ;;
   4735     --tty)			# tty mode, text with pager
   4736       _OPT_MODE=tty;
   4737       ;;
   4738     --text-device|--tty-device) # device for tty mode; arg
   4739       _OPT_TEXT_DEVICE="$1";
   4740       shift;
   4741       ;;
   4742     --whatis)
   4743       _OPT_WHATIS='yes';
   4744       _OPT_ALL='yes';
   4745       _OPT_APROPOS='no';
   4746       ;;
   4747     --X|--x)
   4748       if is_X
   4749       then
   4750         _OPT_MODE=x;
   4751       fi;
   4752       ;;
   4753     --xrm)			# pass X resource string, arg;
   4754       list_append _OPT_XRM "$1";
   4755       shift;
   4756       ;;
   4757     --x-viewer|--X-viewer)	# viewer program for x mode; arg
   4758       _VIEWER_TERMINAL='no';
   4759       _OPT_VIEWER_X="$1";
   4760       shift;
   4761       ;;
   4762     --x-viewer-tty|--X-viewer-tty) # viewer program for x mode in tty; arg
   4763       _VIEWER_TERMINAL='yes';
   4764       _OPT_VIEWER_X="$1";
   4765       shift;
   4766       ;;
   4767     *)
   4768       error 'main_parse_args(): error on argument parsing : '"\`$*'";
   4769       ;;
   4770     esac;
   4771   done;
   4772   shift;			# remove `--' argument
   4773 
   4774   if obj _OPT_DO_NOTHING is_yes
   4775   then
   4776     leave;
   4777   fi;
   4778 
   4779   # Remaining arguments are file names (filespecs).
   4780   # Save them to list $_FILEARGS
   4781   if is_equal "$#" 0
   4782   then				# use "-" for standard input
   4783     set x '-';
   4784     shift;
   4785   fi;
   4786   _FILEARGS='';
   4787   list_append _FILEARGS "$@";
   4788   if list_has _FILEARGS '-'
   4789   then
   4790     save_stdin;
   4791   fi;
   4792   # $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'
   4793   eval ${_UNSET} mpa_arg;
   4794   eval ${_UNSET} mpa_dpi;
   4795   eval ${_UNSET} mpa_opt;
   4796   eval ${_UNSET} mpa_optchar;
   4797   eval "${return_ok}";
   4798 } # main_parse_args()
   4799 
   4800 
   4801 # Called from main_parse_args() because double `case' is not possible.
   4802 # Globals: $_OPT_DEVICE, $_OPT_MODE
   4803 _check_device_with_mode()
   4804 {
   4805   func_check _check_device_with_mode = 0 "$@";
   4806   case "${_OPT_DEVICE}" in
   4807   dvi)
   4808     _OPT_MODE=dvi;
   4809     eval "${return_ok}";
   4810     ;;
   4811   html)
   4812     _OPT_MODE=html;
   4813     eval "${return_ok}";
   4814     ;;
   4815   lbp|lj4)
   4816     _OPT_MODE=groff;
   4817     eval "${return_ok}";
   4818     ;;
   4819   ps)
   4820     _OPT_MODE=ps;
   4821     eval "${return_ok}";
   4822     ;;
   4823   ascii|cp1047|latin1|utf8)
   4824     if obj _OPT_MODE is_not_equal text
   4825     then
   4826       _OPT_MODE=tty;		# default text mode
   4827     fi;
   4828     eval "${return_ok}";
   4829     ;;
   4830   X*)
   4831     _OPT_MODE=x;
   4832     eval "${return_ok}";
   4833     ;;
   4834   *)				# unknown device, go to groff mode
   4835     _OPT_MODE=groff;
   4836     eval "${return_ok}";
   4837     ;;
   4838   esac;
   4839   eval "${return_error}";
   4840 } # _check_device_with_mode() of main_parse_args()
   4841 
   4842 
   4843 ########################################################################
   4844 # main_set_mode ()
   4845 #
   4846 # Determine the display mode.
   4847 #
   4848 # Globals:
   4849 #   in:  $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
   4850 #   out: $_DISPLAY_MODE
   4851 #
   4852 # Variable prefix: msm
   4853 #
   4854 main_set_mode()
   4855 {
   4856   func_check main_set_mode = 0 "$@";
   4857 
   4858   # set display
   4859   if obj _OPT_DISPLAY is_not_empty
   4860   then
   4861     DISPLAY="${_OPT_DISPLAY}";
   4862   fi;
   4863 
   4864   if obj _OPT_V is_yes
   4865   then
   4866     list_append _ADDOPTS_GROFF '-V';
   4867   fi;
   4868   if obj _OPT_Z is_yes
   4869   then
   4870     _DISPLAY_MODE='groff';
   4871     list_append _ADDOPTS_GROFF '-Z';
   4872   fi;
   4873   if obj _OPT_MODE is_equal 'groff'
   4874   then
   4875     _DISPLAY_MODE='groff';
   4876   fi;
   4877   if obj _DISPLAY_MODE is_equal 'groff'
   4878   then
   4879     eval ${_UNSET} msm_modes;
   4880     eval ${_UNSET} msm_viewer;
   4881     eval ${_UNSET} msm_viewers;
   4882     eval "${return_ok}";
   4883   fi;
   4884 
   4885   if obj _OPT_MODE is_equal 'source'
   4886   then
   4887     _DISPLAY_MODE='source';
   4888     eval ${_UNSET} msm_modes;
   4889     eval ${_UNSET} msm_viewer;
   4890     eval ${_UNSET} msm_viewers;
   4891     eval "${return_ok}";
   4892   fi;
   4893 
   4894   case "${_OPT_MODE}" in
   4895   '')				# automatic mode
   4896     case "${_OPT_DEVICE}" in
   4897     X*)
   4898      if is_not_X
   4899       then
   4900         error_user "no X display found for device ${_OPT_DEVICE}";
   4901       fi;
   4902       _DISPLAY_MODE='x';
   4903       eval ${_UNSET} msm_modes;
   4904       eval ${_UNSET} msm_viewer;
   4905       eval ${_UNSET} msm_viewers;
   4906       eval "${return_ok}";
   4907       ;;
   4908     ascii|cp1047|latin1|utf8)
   4909       if obj _DISPLAY_MODE is_not_equal 'text'
   4910       then
   4911         _DISPLAY_MODE='tty';
   4912       fi;
   4913       eval ${_UNSET} msm_modes;
   4914       eval ${_UNSET} msm_viewer;
   4915       eval ${_UNSET} msm_viewers;
   4916       eval "${return_ok}";
   4917       ;;
   4918     esac;
   4919     if is_not_X
   4920     then
   4921       _DISPLAY_MODE='tty';
   4922       eval ${_UNSET} msm_modes;
   4923       eval ${_UNSET} msm_viewer;
   4924       eval ${_UNSET} msm_viewers;
   4925       eval "${return_ok}";
   4926     fi;
   4927 
   4928     if obj _OPT_DEFAULT_MODES is_empty
   4929     then
   4930       msm_modes="${_DEFAULT_MODES}";
   4931     else
   4932       msm_modes="${_OPT_DEFAULT_MODES}";
   4933     fi;
   4934     ;;
   4935   text)
   4936     _DISPLAY_MODE='text';
   4937     eval ${_UNSET} msm_modes;
   4938     eval ${_UNSET} msm_viewer;
   4939     eval ${_UNSET} msm_viewers;
   4940     eval "${return_ok}";
   4941     ;;
   4942   tty)
   4943     _DISPLAY_MODE='tty';
   4944     eval ${_UNSET} msm_modes;
   4945     eval ${_UNSET} msm_viewer;
   4946     eval ${_UNSET} msm_viewers;
   4947     eval "${return_ok}";
   4948     ;;
   4949   html)
   4950     _DISPLAY_MODE='html';
   4951     msm_modes="${_OPT_MODE}";
   4952     ;;
   4953   *)				# display mode was given
   4954     if is_not_X
   4955     then
   4956       error_user "You must be in X Window for ${_OPT_MODE} mode.";
   4957     fi;
   4958     msm_modes="${_OPT_MODE}";
   4959     ;;
   4960   esac;
   4961 
   4962   # only viewer modes are left
   4963   eval set x "$(list_from_split "${msm_modes}" ',')";
   4964   exit_test;
   4965   shift;
   4966   while test "$#" -gt 0
   4967   do
   4968     m="$1";
   4969     shift;
   4970     case "$m" in
   4971     dvi)
   4972       if obj _OPT_VIEWER_DVI is_not_empty
   4973       then
   4974         msm_viewer="${_OPT_VIEWER_DVI}";
   4975       else
   4976         msm_viewer="$(_get_first_prog "$_VIEWER_DVI}")";
   4977         exit_test;
   4978       fi;
   4979       if obj msm_viewer is_empty
   4980       then
   4981         error 'No viewer for dvi mode available.';
   4982       fi;
   4983       if is_not_equal "$?" 0
   4984       then
   4985         continue;
   4986       fi;
   4987       _DISPLAY_PROG="${msm_viewer}";
   4988       _DISPLAY_MODE="dvi";
   4989       eval ${_UNSET} msm_modes;
   4990       eval ${_UNSET} msm_viewer;
   4991       eval ${_UNSET} msm_viewers;
   4992       eval "${return_ok}";
   4993       ;;
   4994     html)
   4995       if obj _OPT_VIEWER_HTML is_not_empty
   4996       then
   4997         msm_viewer="${_OPT_VIEWER_HTML}";
   4998       else
   4999         if is_X
   5000         then
   5001           msm_viewers="${_VIEWER_HTML_X}";
   5002         else
   5003           msm_viewers="${_VIEWER_HTML_TTY}";
   5004         fi;
   5005         msm_viewer="$(_get_first_prog "${msm_viewers}")";
   5006         exit_test;
   5007       fi;
   5008       if obj msm_viewer is_empty
   5009       then
   5010         error 'No viewer for html mode available.';
   5011       fi;
   5012       if is_not_equal "$?" 0
   5013       then
   5014         continue;
   5015       fi;
   5016       _DISPLAY_PROG="${msm_viewer}";
   5017       _DISPLAY_MODE=html;
   5018       eval ${_UNSET} msm_modes;
   5019       eval ${_UNSET} msm_viewer;
   5020       eval ${_UNSET} msm_viewers;
   5021       eval "${return_ok}";
   5022       ;;
   5023     pdf)
   5024       if obj _OPT_VIEWER_PDF is_not_empty
   5025       then
   5026         msm_viewer="${_OPT_VIEWER_PDF}";
   5027       else
   5028         msm_viewer="$(_get_first_prog "${_VIEWER_PDF}")";
   5029         exit_test;
   5030       fi;
   5031       if obj msm_viewer is_empty
   5032       then
   5033         error 'No viewer for pdf mode available.';
   5034       fi;
   5035       if is_not_equal "$?" 0
   5036       then
   5037         continue;
   5038       fi;
   5039       _DISPLAY_PROG="${msm_viewer}";
   5040       _DISPLAY_MODE="pdf";
   5041       eval ${_UNSET} msm_modes;
   5042       eval ${_UNSET} msm_viewer;
   5043       eval ${_UNSET} msm_viewers;
   5044       eval "${return_ok}";
   5045       ;;
   5046     ps)
   5047       if obj _OPT_VIEWER_PS is_not_empty
   5048       then
   5049         msm_viewer="${_OPT_VIEWER_PS}";
   5050       else
   5051         msm_viewer="$(_get_first_prog "${_VIEWER_PS}")";
   5052         exit_test;
   5053       fi;
   5054       if obj msm_viewer is_empty
   5055       then
   5056         error 'No viewer for ps mode available.';
   5057       fi;
   5058       if is_not_equal "$?" 0
   5059       then
   5060         continue;
   5061       fi;
   5062       _DISPLAY_PROG="${msm_viewer}";
   5063       _DISPLAY_MODE="ps";
   5064      eval ${_UNSET} msm_modes;
   5065       eval ${_UNSET} msm_viewer;
   5066       eval ${_UNSET} msm_viewers;
   5067       eval "${return_ok}";
   5068       ;;
   5069     text)
   5070       _DISPLAY_MODE='text';
   5071       eval ${_UNSET} msm_modes;
   5072       eval ${_UNSET} msm_viewer;
   5073       eval ${_UNSET} msm_viewers;
   5074       eval "${return_ok}";
   5075       ;;
   5076     tty)
   5077       _DISPLAY_MODE='tty';
   5078       eval ${_UNSET} msm_modes;
   5079       eval ${_UNSET} msm_viewer;
   5080       eval ${_UNSET} msm_viewers;
   5081       eval "${return_ok}";
   5082       ;;
   5083     x)
   5084       if obj _OPT_VIEWER_X is_not_empty
   5085       then
   5086         msm_viewer="${_OPT_VIEWER_X}";
   5087       else
   5088         msm_viewer="$(_get_first_prog "${_VIEWER_X}")";
   5089         exit_test;
   5090       fi;
   5091       if obj msm_viewer is_empty
   5092       then
   5093         error 'No viewer for x mode available.';
   5094       fi;
   5095       if is_not_equal "$?" 0
   5096       then
   5097         continue;
   5098       fi;
   5099       _DISPLAY_PROG="${msm_viewer}";
   5100       _DISPLAY_MODE='x';
   5101       eval ${_UNSET} msm_modes;
   5102       eval ${_UNSET} msm_viewer;
   5103       eval ${_UNSET} msm_viewers;
   5104       eval "${return_ok}";
   5105       ;;
   5106     X)
   5107       _DISPLAY_MODE='X';
   5108       eval ${_UNSET} msm_modes;
   5109       eval ${_UNSET} msm_viewer;
   5110       eval ${_UNSET} msm_viewers;
   5111       eval "${return_ok}";
   5112       ;;
   5113     esac;
   5114   done;
   5115   eval ${_UNSET} msm_modes;
   5116   eval ${_UNSET} msm_viewer;
   5117   eval ${_UNSET} msm_viewers;
   5118   error_user "No suitable display mode found.";
   5119 } # main_set_mode()
   5120 
   5121 
   5122 # _get_first_prog (<proglist>)
   5123 #
   5124 # Retrieve first argument that represents an existing program in $PATH.
   5125 # Local function for main_set_mode().
   5126 #
   5127 # Arguments: 1; a comma-separated list of commands (with options),
   5128 #               like $_VIEWER_*.
   5129 #
   5130 # Return  : `1' if none found, `0' if found.
   5131 # Output  : the argument that succeded.
   5132 #
   5133 # Variable prefix: _gfp
   5134 #
   5135 _get_first_prog()
   5136 {
   5137   if is_equal "$#" 0
   5138   then
   5139     error "_get_first_prog() needs 1 argument.";
   5140   fi;
   5141   if is_empty "$1"
   5142   then
   5143     return "${_BAD}";
   5144   fi;
   5145   eval set x "$(list_from_split "$1" ',')";
   5146   exit_test;
   5147   shift;
   5148   for i
   5149   do
   5150     _gfp_i="$i";
   5151     if obj _gfp_i is_empty
   5152     then
   5153       continue;
   5154     fi;
   5155     if eval is_prog "$(get_first_essential ${_gfp_i})"
   5156     then
   5157       exit_test;
   5158       obj _gfp_i echo1;
   5159       eval ${_UNSET} _gfp_i;
   5160       return "${_GOOD}";
   5161     fi;
   5162   done;
   5163   eval ${_UNSET} _gfp_i;
   5164   return "${_BAD}";
   5165 } # _get_first_prog() of main_set_mode()
   5166 
   5167 
   5168 #######################################################################
   5169 # main_do_fileargs ()
   5170 #
   5171 # Process filespec arguments in $_FILEARGS.
   5172 #
   5173 # Globals:
   5174 #   in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
   5175 #
   5176 # Variable prefix: mdfa
   5177 #
   5178 main_do_fileargs()
   5179 {
   5180   func_check main_do_fileargs = 0 "$@";
   5181   special_setup;
   5182   eval set x "${_FILEARGS}";
   5183   shift;
   5184   eval ${_UNSET} _FILEARGS;
   5185   # temporary storage of all input to $_TMP_CAT
   5186   while test "$#" -ge 2
   5187   do
   5188     # test for `s name' arguments, with `s' a 1-char standard section
   5189     mdfa_filespec="$1";
   5190     _FILESPEC_ARG="$1";
   5191     shift;
   5192     case "${mdfa_filespec}" in
   5193     '')
   5194       continue;
   5195       ;;
   5196     '-')
   5197       special_filespec;
   5198       if obj _OPT_APROPOS is_yes
   5199       then
   5200         continue;
   5201       fi;
   5202       register_file '-'
   5203       continue;
   5204       ;;
   5205     ?)
   5206       if obj _OPT_APROPOS is_yes
   5207       then
   5208         special_filespec;
   5209         continue;
   5210       fi;
   5211       if list_has_not _MAN_AUTO_SEC_LIST "${mdfa_filespec}"
   5212       then
   5213         special_filespec;
   5214         do_filearg "${mdfa_filespec}"
   5215         continue;
   5216       fi;
   5217       mdfa_name="$1";
   5218       _FILESPEC_ARG="${_FILESPEC_ARG} $1";
   5219       special_filespec;
   5220       case "${mdfa_name}" in
   5221       */*|man:*|*\(*\)|*."${mdfa_filespec}")
   5222         do_filearg "${mdfa_filespec}"
   5223         continue;
   5224         ;;
   5225       esac;
   5226       shift;
   5227       if do_filearg "man:${mdfa_name}(${mdfa_filespec})"
   5228       then
   5229         continue;
   5230       else
   5231         do_filearg "${mdfa_filespec}"
   5232         continue;
   5233       fi;
   5234       ;;
   5235     *)
   5236       special_filespec;
   5237       if obj _OPT_APROPOS is_yes
   5238       then
   5239         continue;
   5240       fi;
   5241       do_filearg "${mdfa_filespec}"
   5242       continue;
   5243       ;;
   5244     esac;
   5245   done;				# end of `s name' test
   5246   while test "$#" -gt 0
   5247   do
   5248     mdfa_filespec="$1";
   5249     _FILESPEC_ARG="$1";
   5250     shift;
   5251     special_filespec;
   5252     if obj _OPT_APROPOS is_yes
   5253     then
   5254       continue;
   5255     fi;
   5256     do_filearg "${mdfa_filespec}"
   5257   done;
   5258   obj _TMP_STDIN rm_file_with_debug;
   5259   eval ${_UNSET} mdfa_filespec;
   5260   eval ${_UNSET} mdfa_name;
   5261   eval "${return_ok}";
   5262 } # main_do_fileargs()
   5263 
   5264 
   5265 ########################################################################
   5266 # main_set_resources ()
   5267 #
   5268 # Determine options for setting X resources with $_DISPLAY_PROG.
   5269 #
   5270 # Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
   5271 #
   5272 # Variable prefix: msr
   5273 #
   5274 main_set_resources()
   5275 {
   5276   func_check main_set_resources = 0 "$@";
   5277   # $msr_prog   viewer program
   5278   # $msr_rl     resource list
   5279   msr_title="$(get_first_essential \
   5280                  "${_OPT_TITLE}" "${_REGISTERED_TITLE}")";
   5281   exit_test;
   5282   _OUTPUT_FILE_NAME='';
   5283   eval set x "${msr_title}";
   5284   shift;
   5285   until is_equal "$#" 0
   5286   do
   5287     msr_n="$1";
   5288     case "${msr_n}" in
   5289     '')
   5290       continue;
   5291       ;;
   5292     ,*)
   5293       msr_n="$(echo1 "$1" | sed -e 's/^,,*//')";
   5294       exit_test;
   5295       ;;
   5296     esac
   5297     if obj msr_n is_empty
   5298     then
   5299       continue;
   5300     fi;
   5301     if obj _OUTPUT_FILE_NAME is_not_empty
   5302     then
   5303       _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"',';
   5304     fi;
   5305     _OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}";
   5306     shift;
   5307   done;
   5308   case "${_OUTPUT_FILE_NAME}" in
   5309   '')
   5310     _OUTPUT_FILE_NAME='-';
   5311     ;;
   5312   ,*)
   5313     error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";
   5314     ;;
   5315   esac;
   5316   _OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
   5317 
   5318   if obj _DISPLAY_PROG is_empty
   5319   then				# for example, for groff mode
   5320     _DISPLAY_ARGS='';
   5321     eval ${_UNSET} msr_n;
   5322     eval ${_UNSET} msr_prog;
   5323     eval ${_UNSET} msr_rl;
   5324     eval ${_UNSET} msr_title;
   5325     eval "${return_ok}";
   5326   fi;
   5327 
   5328   eval set x "${_DISPLAY_PROG}";
   5329   shift;
   5330   msr_prog="$(base_name "$1")";
   5331   exit_test;
   5332   shift;
   5333   if test $# != 0
   5334   then
   5335     if obj _DISPLAY_PROG is_empty
   5336     then
   5337       _DISPLAY_ARGS="$*";
   5338     else
   5339       _DISPLAY_ARGS="$* ${_DISPLAY_ARGS}";
   5340     fi;
   5341   fi;
   5342   msr_rl='';
   5343   if obj _OPT_BD is_not_empty
   5344   then
   5345     case "${msr_prog}" in
   5346     ghostview|gv|gxditview|xditview|xdvi)
   5347       list_append msr_rl '-bd' "${_OPT_BD}";
   5348       ;;
   5349     esac;
   5350   fi;
   5351   if obj _OPT_BG is_not_empty
   5352   then
   5353     case "${msr_prog}" in
   5354     ghostview|gv|gxditview|xditview|xdvi)
   5355       list_append msr_rl '-bg' "${_OPT_BG}";
   5356       ;;
   5357     kghostview)
   5358       list_append msr_rl '--bg' "${_OPT_BG}";
   5359       ;;
   5360     xpdf)
   5361       list_append msr_rl '-papercolor' "${_OPT_BG}";
   5362       ;;
   5363     esac;
   5364   fi;
   5365   if obj _OPT_BW is_not_empty
   5366   then
   5367     case "${msr_prog}" in
   5368     ghostview|gv|gxditview|xditview|xdvi)
   5369       _list_append msr_rl '-bw' "${_OPT_BW}";
   5370       ;;
   5371     esac;
   5372   fi;
   5373   if obj _OPT_FG is_not_empty
   5374   then
   5375     case "${msr_prog}" in
   5376     ghostview|gv|gxditview|xditview|xdvi)
   5377       list_append msr_rl '-fg' "${_OPT_FG}";
   5378       ;;
   5379     kghostview)
   5380       list_append msr_rl '--fg' "${_OPT_FG}";
   5381       ;;
   5382     esac;
   5383   fi;
   5384   if is_not_empty "${_OPT_FN}"
   5385   then
   5386     case "${msr_prog}" in
   5387     ghostview|gv|gxditview|xditview|xdvi)
   5388       list_append msr_rl '-fn' "${_OPT_FN}";
   5389       ;;
   5390     kghostview)
   5391       list_append msr_rl '--fn' "${_OPT_FN}";
   5392       ;;
   5393     esac;
   5394   fi;
   5395   if is_not_empty "${_OPT_GEOMETRY}"
   5396   then
   5397     case "${msr_prog}" in
   5398     ghostview|gv|gxditview|xditview|xdvi|xpdf)
   5399       list_append msr_rl '-geometry' "${_OPT_GEOMETRY}";
   5400       ;;
   5401     kghostview)
   5402       list_append msr_rl '--geometry' "${_OPT_GEOMETRY}";
   5403       ;;
   5404     esac;
   5405   fi;
   5406   if is_empty "${_OPT_RESOLUTION}"
   5407   then
   5408     _OPT_RESOLUTION="${_DEFAULT_RESOLUTION}";
   5409     case "${msr_prog}" in
   5410     gxditview|xditview)
   5411       list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}";
   5412       ;;
   5413     xpdf)
   5414       case "${_DEFAULT_RESOLUTION}" in
   5415       75)
   5416         # 72dpi is '100'
   5417         list_append msr_rl '-z' '104';
   5418         ;;
   5419       100)
   5420         list_append msr_rl '-z' '139';
   5421         ;;
   5422       esac;
   5423       ;;
   5424     esac;
   5425   else
   5426     case "${msr_prog}" in
   5427     ghostview|gv|gxditview|xditview|xdvi)
   5428       list_append msr_rl '-resolution' "${_OPT_RESOLUTION}";
   5429       ;;
   5430     xpdf)
   5431       case "${_OPT_RESOLUTION}" in
   5432       75)
   5433         list_append msr_rl '-z' '104';
   5434         # '100' corresponds to 72dpi
   5435         ;;
   5436       100)
   5437         list_append msr_rl '-z' '139';
   5438         ;;
   5439       esac;
   5440       ;;
   5441     esac;
   5442   fi;
   5443   if is_yes "${_OPT_ICONIC}"
   5444   then
   5445     case "${msr_prog}" in
   5446     ghostview|gv|gxditview|xditview|xdvi)
   5447       list_append msr_rl '-iconic';
   5448       ;;
   5449     esac;
   5450   fi;
   5451   if is_yes "${_OPT_RV}"
   5452   then
   5453     case "${msr_prog}" in
   5454     ghostview|gv|gxditview|xditview|xdvi)
   5455       list_append msr_rl '-rv';
   5456       ;;
   5457     esac;
   5458   fi;
   5459   if is_not_empty "${_OPT_XRM}"
   5460   then
   5461     case "${msr_prog}" in
   5462     ghostview|gv|gxditview|xditview|xdvi|xpdf)
   5463       eval set x "${_OPT_XRM}";
   5464       shift;
   5465       for i
   5466       do
   5467         list_append msr_rl '-xrm' "$i";
   5468       done;
   5469       ;;
   5470     esac;
   5471   fi;
   5472   if is_not_empty "${msr_title}"
   5473   then
   5474     case "${msr_prog}" in
   5475     gxditview|xditview)
   5476       list_append msr_rl '-title' "${msr_title}";
   5477       ;;
   5478     esac;
   5479   fi;
   5480   _DISPLAY_ARGS="${msr_rl}";
   5481   eval ${_UNSET} msr_n;
   5482   eval ${_UNSET} msr_prog;
   5483   eval ${_UNSET} msr_rl;
   5484   eval ${_UNSET} msr_title;
   5485   eval "${return_ok}";
   5486 } # main_set_resources
   5487 
   5488 
   5489 ########################################################################
   5490 # main_display ()
   5491 #
   5492 # Do the actual display of the whole thing.
   5493 #
   5494 # Globals:
   5495 #   in: $_DISPLAY_MODE, $_OPT_DEVICE,
   5496 #       $_ADDOPTS_GROFF, $_ADDOPTS_POST, $_ADDOPTS_X,
   5497 #       $_TMP_CAT, $_OPT_PAGER, $PAGER, $_MANOPT_PAGER,
   5498 #       $_OUTPUT_FILE_NAME
   5499 #
   5500 # Variable prefix: md
   5501 #
   5502 main_display()
   5503 {
   5504   func_check main_display = 0 "$@";
   5505 
   5506   export md_addopts;
   5507   export md_groggy;
   5508   export md_modefile;
   5509 
   5510   if obj _TMP_CAT is_non_empty_file
   5511   then
   5512     md_modefile="${_OUTPUT_FILE_NAME}";
   5513   else
   5514     echo2 'groffer: empty input.';
   5515     clean_up;
   5516     eval ${_UNSET} md_modefile;
   5517     eval "${return_ok}";
   5518   fi;
   5519 
   5520   # go to the temporary directory to be able to access internal data files
   5521   cd "${_TMP_DIR}" >"${_NULL_DEV}" 2>&1;
   5522 
   5523   case "${_DISPLAY_MODE}" in
   5524   groff)
   5525     _ADDOPTS_GROFF="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
   5526     if obj _OPT_DEVICE is_not_empty
   5527     then
   5528       _ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
   5529     fi;
   5530     md_groggy="$(tmp_cat | eval grog "${md_options}")";
   5531     exit_test;
   5532     _do_opt_V;
   5533 
   5534     obj md_modefile rm_file;
   5535     mv "${_TMP_CAT}" "${md_modefile}";
   5536     trap_unset;
   5537     cat "${md_modefile}" | \
   5538     {
   5539       trap_set;
   5540       eval "${md_groggy}" "${_ADDOPTS_GROFF}";
   5541     } &
   5542     ;;
   5543   text|tty)
   5544     case "${_OPT_DEVICE}" in
   5545     '')
   5546       md_device="$(get_first_essential \
   5547                      "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}")";
   5548       exit_test;
   5549       ;;
   5550     ascii|cp1047|latin1|utf8)
   5551       md_device="${_OPT_DEVICE}";
   5552       ;;
   5553     *)
   5554       warning "main_display(): \
   5555 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
   5556       ;;
   5557     esac;
   5558     md_addopts="${_ADDOPTS_GROFF} ${_ADDOPTS_POST}";
   5559     md_groggy="$(tmp_cat | grog -T${md_device})";
   5560     exit_test;
   5561     if obj _DISPLAY_MODE is_equal 'text'
   5562     then
   5563       _do_opt_V;
   5564       tmp_cat | eval "${md_groggy}" "${md_addopts}";
   5565     else
   5566       md_pager='';
   5567       for p in "${_OPT_PAGER}" "${PAGER}" "${_MANOPT_PAGER}" \
   5568                'less -r -R' 'more' 'pager' 'cat'
   5569       do
   5570         md_p="$p";
   5571         if eval is_prog ${md_p}
   5572         then		      # no "" for is_prog() allows args for $p
   5573           md_pager="${md_p}";
   5574           break;
   5575         fi;
   5576       done;
   5577       if obj md_pager is_empty
   5578       then
   5579         error 'main_display(): no pager program found for tty mode';
   5580       fi;
   5581       _do_opt_V;
   5582       tmp_cat | eval "${md_groggy}" "${md_addopts}" | \
   5583                 eval "${md_pager}";
   5584     fi;
   5585     clean_up;
   5586     ;;
   5587   source)
   5588     tmp_cat;
   5589     clean_up;
   5590     ;;
   5591 
   5592   #### viewer modes
   5593 
   5594   dvi)
   5595     case "${_OPT_DEVICE}" in
   5596     ''|dvi) do_nothing; ;;
   5597     *)
   5598       warning "main_display(): \
   5599 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"
   5600       ;;
   5601     esac;
   5602     md_modefile="${md_modefile}".dvi;
   5603     md_groggy="$(tmp_cat | grog -Tdvi)";
   5604     exit_test;
   5605     _do_display;
   5606     ;;
   5607   html)
   5608     case "${_OPT_DEVICE}" in
   5609     ''|html) do_nothing; ;;
   5610     *)
   5611       warning "main_display(): \
   5612 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
   5613       ;;
   5614     esac;
   5615     md_modefile="${md_modefile}".html;
   5616     md_groggy="$(tmp_cat | grog -Thtml)";
   5617     exit_test;
   5618     _do_display;
   5619     ;;
   5620   pdf)
   5621     case "${_OPT_DEVICE}" in
   5622     ''|ps)
   5623       do_nothing;
   5624       ;;
   5625     *)
   5626       warning "main_display(): \
   5627 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
   5628       ;;
   5629     esac;
   5630     md_groggy="$(tmp_cat | grog -Tps)";
   5631     exit_test;
   5632     _do_display _make_pdf;
   5633     ;;
   5634   ps)
   5635     case "${_OPT_DEVICE}" in
   5636     ''|ps)
   5637       do_nothing;
   5638       ;;
   5639     *)
   5640       warning "main_display(): \
   5641 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
   5642       ;;
   5643     esac;
   5644     md_modefile="${md_modefile}".ps;
   5645     md_groggy="$(tmp_cat | grog -Tps)";
   5646     exit_test;
   5647     _do_display;
   5648     ;;
   5649   x)
   5650     case "${_OPT_DEVICE}" in
   5651     X*)
   5652       md_device="${_OPT_DEVICE}"
   5653       ;;
   5654     *)
   5655       case "${_OPT_RESOLUTION}" in
   5656       100)
   5657         md_device='X100';
   5658         if obj _OPT_GEOMETRY is_empty
   5659         then
   5660           case "${_DISPLAY_PROG}" in
   5661           gxditview|xditview)
   5662             # add width of 800dpi for resolution of 100dpi to the args
   5663             list_append _DISPLAY_ARGS '-geometry' '800';
   5664             ;;
   5665           esac;
   5666         fi;
   5667         ;;
   5668       *)
   5669         md_device='X75-12';
   5670         ;;
   5671       esac
   5672     esac;
   5673     md_groggy="$(tmp_cat | grog -T${md_device} -Z)";
   5674     exit_test;
   5675     _do_display;
   5676     ;;
   5677   X)
   5678     case "${_OPT_DEVICE}" in
   5679     '')
   5680       md_groggy="$(tmp_cat | grog -X)";
   5681       exit_test;
   5682       ;;
   5683     X*|dvi|html|lbp|lj4|ps)
   5684       # these devices work with 
   5685       md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
   5686       exit_test;
   5687       ;;
   5688     *)
   5689       warning "main_display(): \
   5690 wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
   5691       md_groggy="$(tmp_cat | grog -Z)";
   5692       exit_test;
   5693       ;;
   5694     esac;
   5695     _do_display;
   5696     ;;
   5697   *)
   5698     error "main_display(): unknown mode \`${_DISPLAY_MODE}'";
   5699     ;;
   5700   esac;
   5701   eval ${_UNSET} md_addopts;
   5702   eval ${_UNSET} md_device;
   5703   eval ${_UNSET} md_groggy;
   5704   eval ${_UNSET} md_modefile;
   5705   eval ${_UNSET} md_options;
   5706   eval ${_UNSET} md_p;
   5707   eval ${_UNSET} md_pager;
   5708   eval "${return_ok}";
   5709 } # main_display()
   5710 
   5711 
   5712 ########################
   5713 # _do_display ([<prog>])
   5714 #
   5715 # Perform the generation of the output and view the result.  If an
   5716 # argument is given interpret it as a function name that is called in
   5717 # the midst (actually only for `pdf').
   5718 #
   5719 # Globals: $md_modefile, $md_groggy (from main_display())
   5720 #
   5721 _do_display()
   5722 {
   5723   func_check _do_display '>=' 0 "$@";
   5724   _do_opt_V;
   5725   if obj _DISPLAY_PROG is_empty
   5726   then
   5727     trap_unset;
   5728     {
   5729       trap_set;
   5730       eval "${md_groggy}" "${_ADDOPTS_GROFF}" "${_TMP_CAT}";
   5731     } &
   5732   else
   5733     obj md_modefile rm_file;
   5734     cat "${_TMP_CAT}" | \
   5735       eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}";
   5736     if is_not_empty "$1"
   5737     then
   5738       eval "$1";
   5739     fi;
   5740     obj _TMP_CAT rm_file_with_debug;
   5741     if obj _VIEWER_TERMINAL is_yes # for programs that run on tty
   5742     then
   5743       eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
   5744     else
   5745       case "${_DISPLAY_PROG}" in
   5746 #      lynx\ *|less\ *|more\ *) # programs known to run on the terminal
   5747 #        eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
   5748 #        ;;
   5749       *)
   5750         trap_unset;
   5751         {
   5752           trap_set;
   5753           eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
   5754         } &
   5755         ;;
   5756       esac;
   5757     fi;
   5758   fi;
   5759   eval "${return_ok}";
   5760 } # _do_display() of main_display()
   5761 
   5762 
   5763 #############
   5764 # _do_opt_V ()
   5765 #
   5766 # Check on option `-V'; if set print the corresponding output and leave.
   5767 #
   5768 # Globals: $_ALL_PARAMS, $_ADDOPTS_GROFF, $_DISPLAY_MODE, $_DISPLAY_PROG,
   5769 #          $_DISPLAY_ARGS, $md_groggy,  $md_modefile
   5770 #
   5771 # Variable prefix: _doV
   5772 #
   5773 _do_opt_V()
   5774 {
   5775   func_check _do_opt_V '=' 0 "$@";
   5776   if obj _OPT_V is_yes
   5777   then
   5778     _OPT_V='no';
   5779     echo1 "Parameters:     ${_ALL_PARAMS}";
   5780     echo1 "Display mode:   ${_DISPLAY_MODE}";
   5781     echo1 "Output file:    ${md_modefile}";
   5782     echo1 "Display prog:   ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
   5783     a="$(eval echo1 "'${_ADDOPTS_GROFF}'")";
   5784     exit_test;
   5785     echo1 "Output of grog: ${md_groggy} $a";
   5786     _doV_res="$(eval "${md_groggy}" "${_ADDOPTS_GROFF}")";
   5787     exit_test;
   5788     echo1 "groff -V:       ${_doV_res}"
   5789     leave;
   5790   fi;
   5791   eval "${return_ok}";
   5792 } # _do_opt_V() of main_display()
   5793 
   5794 
   5795 ##############
   5796 # _make_pdf ()
   5797 #
   5798 # Transform to pdf format; for pdf mode in _do_display().
   5799 #
   5800 # Globals: $md_modefile (from main_display())
   5801 # 
   5802 # Variable prefix: _mp
   5803 #
   5804 _make_pdf()
   5805 {
   5806   func_check _do_display '=' 0 "$@";
   5807   _mp_psfile="${md_modefile}";
   5808   md_modefile="${md_modefile}.pdf";
   5809   obj md_modefile rm_file;
   5810   if gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
   5811         -sOutputFile="${md_modefile}" -c save pop -f "${_mp_psfile}"
   5812   then
   5813     :;
   5814   else
   5815     error '_make_pdf: could not transform into pdf format.';
   5816   fi;
   5817   obj _mp_psfile rm_file_with_debug;
   5818   eval ${_UNSET} _mp_psfile;
   5819   eval "${return_ok}";
   5820 } # _make_pdf() of main_display()
   5821 
   5822 
   5823 ########################################################################
   5824 # main (<command_line_args>*)
   5825 #
   5826 # The main function for groffer.
   5827 #
   5828 # Arguments:
   5829 #
   5830 main()
   5831 {
   5832   func_check main '>=' 0 "$@";
   5833   # Do not change the sequence of the following functions!
   5834   landmark '13: main_init()';
   5835   main_init;
   5836   landmark '14: main_parse_MANOPT()';
   5837   main_parse_MANOPT;
   5838   landmark '15: main_parse_args()';
   5839   main_parse_args "$@";
   5840   landmark '16: main_set_mode()';
   5841   main_set_mode;
   5842   landmark '17: main_do_fileargs()';
   5843   main_do_fileargs;
   5844   landmark '18: main_set_resources()';
   5845   main_set_resources;
   5846   landmark '19: main_display()';
   5847   main_display;
   5848   eval "${return_ok}";
   5849 }
   5850 
   5851 
   5852 ########################################################################
   5853 
   5854 main "$@";
   5855