#! /bin/sh
# groffer - display groff files
# Source file position: <groff-source>/contrib/groffer/groffer2.sh
# Installed position: <prefix>/lib/groff/groffer/groffer2.sh
# This file should not be run independently. It is called by
# `groffer.sh' in the source or by the installed `groffer' program.
# Copyright (C) 2001,2002,2003,2004,2005,2006
# Free Software Foundation, Inc.
# Written by Bernd Warken
# Last update: 5 Oct 2006
# This file is part of `groffer', which is part of `groff'.
# `groff' is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# `groff' is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with `groff'; see the files COPYING and LICENSE in the top
# directory of the `groff' source. If not, write to the Free Software
# Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301,
# USA.
########################################################################
# Test of rudimentary shell functionality
########################################################################
########################################################################
# Test of `unset'
#
export _UNSET;
export _foo;
_foo=bar;
_res="$(unset _foo 2>&1)";
if unset _foo >${_NULL_DEV} 2>&1 && \
test _"${_res}"_ = __ && test _"${_foo}"_ = __
then
_UNSET='unset';
eval "${_UNSET}" _foo;
eval "${_UNSET}" _res;
else
_UNSET=':';
fi;
########################################################################
# Test of `test'.
#
if test a = a && test a != b && test -f "${_GROFFER_SH}"
then
:;
else
echo '"test" did not work.' >&2;
exit "${_ERROR}";
fi;
########################################################################
# Test of `echo' and the `$()' construct.
#
if echo '' >${_NULL_DEV}
then
:;
else
echo '"echo" did not work.' >&2;
exit "${_ERROR}";
fi;
if test _"$(t1="$(echo te)" &&
t2="$(echo '')" &&
t3="$(echo 'st')" &&
echo "${t1}${t2}${t3}")"_ \
!= _test_
then
echo 'The "$()" construct did not work' >&2;
exit "${_ERROR}";
fi;
########################################################################
# Test of sed program; test in groffer.sh is not valid here.
#
if test _"$(echo xTesTx \
| sed -n -e 's/^.\([Tt]e*x*sTT*\).*$/\1/p' \
| sed -e 's|T|t|g')"_ != _test_
then
echo 'The sed program did not work.' >&2;
exit "${_ERROR}";
fi;
########################################################################
# Test of `cat'.
#
if test _"$(echo test | cat)"_ != _test_
then
error 'Test of "cat" command failed.';
fi;
########################################################################
# Test of function definitions.
#
_t_e_s_t_f_u_n_c_()
{
return 0;
}
_test_func()
{
echo test;
}
if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV} && \
test _"$(_test_func 2>${_NULL_DEV})"_ = _test_
then
:;
else
echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2;
exit "${_ERROR}";
fi;
########################################################################
# landmark (<text>)
#
# Print <text> to standard error as a debugging aid.
#
# Globals: $_DEBUG_LM
#
landmark()
{
if test _"${_DEBUG_LM}"_ = _yes_
then
echo "LM: $*" >&2;
fi;
} # landmark()
########################################################################
# test for compression.
#
export _HAS_COMPRESSION;
export _HAS_BZIP;
if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_
then
_HAS_COMPRESSION='yes';
if echo 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \
&& test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
| bzip2 -d -c 2>${_NULL_DEV})"_ \
= _test_
then
_HAS_BZIP='yes';
else
_HAS_BZIP='no';
fi;
else
_HAS_COMPRESSION='no';
_HAS_BZIP='no';
fi;
########################################################################
# debug - diagnostic messages
########################################################################
export _DEBUG_FUNC_CHECK;
if test _"${_BEFORE_MAKE}"_ = _yes_
then
_DEBUG_FUNC_CHECK='yes';
else
_DEBUG_FUNC_CHECK='no';
fi;
_DEBUG_FUNC_CHECK='no'; # disable function checking
#_DEBUG_FUNC_CHECK='yes'; # enable function checking
export _DEBUG_STACKS;
_DEBUG_STACKS='no'; # disable stack output in each function
#_DEBUG_STACKS='yes'; # enable stack output in each function
export _DEBUG_USER_WITH_STACK;
_DEBUG_USER_WITH_STACK='no'; # disable stack dump in error_user()
#_DEBUG_USER_WITH_STACK='yes'; # enable stack dump in error_user()
export _DEBUG_LM;
_DEBUG_LM='no'; # disable landmark messages
#_DEBUG_LM='yes'; # enable landmark messages
export _DEBUG_KEEP_FILES;
_DEBUG_KEEP_FILES='no' # disable file keeping in temporary dir
#_DEBUG_KEEP_FILES='yes' # enable file keeping in temporary dir
export _DEBUG_PRINT_PARAMS;
_DEBUG_PRINT_PARAMS='no'; # disable printing of all parameters
#_DEBUG_PRINT_PARAMS='yes'; # enable printing of all parameters
export _DEBUG_PRINT_SHELL;
_DEBUG_PRINT_SHELL='no'; # disable printing of the shell name
#_DEBUG_PRINT_SHELL='yes'; # enable printing of the shell name
export _DEBUG_PRINT_TMPDIR;
_DEBUG_PRINT_TMPDIR='no'; # disable printing of the temporary dir
#_DEBUG_PRINT_TMPDIR='yes'; # enable printing of the temporary dir
export _DEBUG_PRINT_FILENAMES;
_DEBUG_PRINT_FILENAMES='no'; # disable printing of the found file names
#_DEBUG_PRINT_FILENAMES='yes'; # enable printing of the found file names
# determine all --debug* options
case " $*" in
*\ --deb*|*\ --d*-*)
# --debug-* options
d=' --debug-all --debug-filenames --debug-func --debug-not-func '\
'--debug-keep --debug-lm --debug-params --debug-shell --debug-stacks '\
'--debug-tmpdir --debug-user ';
# non-debug options with scheme --d*-*
n=' --do-nothing --default-modes --dvi-viewer --dvi-viewer-tty ';
for i
do
case "$i" in
--deb|--debu|--debug)
_DEBUG_FUNC_CHECK='yes';
# _DEBUG_STACKS='yes';
_DEBUG_USER_WITH_STACK='yes';
# _DEBUG_LM='yes';
_DEBUG_KEEP_FILES='yes';
_DEBUG_PRINT_PARAMS='yes';
_DEBUG_PRINT_SHELL='yes';
_DEBUG_PRINT_TMPDIR='yes';
_DEBUG_PRINT_FILENAMES='yes';
continue;
;;
--d*-*)
# before `-'
b="$(echo x"$i" | sed -e 's/^x--\([^-]*\)-.*$/\1/')";
# after `-'
a="$(echo x"$i" | sed -e 's/^x--[^-]*-\(.*\)$/\1/')";
;;
*)
continue;
;;
esac;
case "$n" in
*\ --$b*-$a*)
continue;
;;
esac;
case "$d" in
*\ --$b*-$a*)
case "$a" in
f|s) # double --debug-* options
continue;
;;
esac;
# extract whole word of double abbreviation
s="$(cat <<EOF | sed -n -e 's/^.* \(--'"$b"'[^ -]*-'"$a"'[^ ]*\) .*/\1/p'
$d
EOF
)"
case "$s" in
'') continue; ;;
--debug-all)
_DEBUG_FUNC_CHECK='yes';
_DEBUG_STACKS='yes';
_DEBUG_USER_WITH_STACK='yes';
_DEBUG_LM='yes';
_DEBUG_KEEP_FILES='yes';
_DEBUG_PRINT_PARAMS='yes';
_DEBUG_PRINT_SHELL='yes';
_DEBUG_PRINT_TMPDIR='yes';
_DEBUG_PRINT_FILENAMES='yes';
_DEBUG_PRINT_FILENAMES='yes';
;;
--debug-filenames)
_DEBUG_PRINT_FILENAMES='yes';
;;
--debug-func)
_DEBUG_FUNC_CHECK='yes';
;;
--debug-not-func)
_DEBUG_FUNC_CHECK='no';
_DEBUG_STACKS='no';
_DEBUG_USER_WITH_STACK='no';
;;
--debug-keep)
_DEBUG_PRINT_TMPDIR='yes';
_DEBUG_KEEP_FILES='yes';
;;
--debug-lm)
_DEBUG_LM='yes';
;;
--debug-params)
_DEBUG_PRINT_PARAMS='yes';
;;
--debug-shell)
_DEBUG_PRINT_SHELL='yes';
;;
--debug-stacks)
_DEBUG_STACKS='yes';
;;
--debug-tmpdir)
_DEBUG_PRINT_TMPDIR='yes';
;;
--debug-user)
_DEBUG_USER_WITH_STACK='yes';
;;
esac;
;;
esac;
done
;;
esac;
if test _"${_DEBUG_STACKS}"_ = _yes_ || \
test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_
then
_DEBUG_FUNC_CHECK='yes';
fi
if test _"${_DEBUG_PRINT_PARAMS}"_ = _yes_
then
echo "parameters: $@" >&2;
fi;
if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_
then
if test _"${_SHELL}"_ = __
then
if test _"${POSIXLY_CORRECT}"_ = _y_
then
echo 'shell: bash as /bin/sh (none specified)' >&2;
else
echo 'shell: /bin/sh (none specified)' >&2;
fi;
else
echo "shell: ${_SHELL}" >&2;
fi;
fi;
########################################################################
# Environment Variables
########################################################################
landmark "1: environment variables";
# Environment variables that exist only for this file start with an
# underscore letter. Global variables to this file are written in
# upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
# start with an underline and use only lower case letters and
# underlines, e.g. $_local_variable.
# [A-Z]* system variables, e.g. $MANPATH
# _[A-Z_]* global file variables, e.g. $_MAN_PATH
# _[a-z_]* temporary variables, e.g. $_manpath
# Due to incompatibilities of the `ash' shell, the name of loop
# variables in `for' must be a single character.
# [a-z] local loop variables, e.g. $i
# In functions, other writings are used for variables. As some shells
# do not support the `local' command a unique prefix in lower case is
# constructed for each function, most are the abbreviation of the
# function name. All variable names start with this prefix.
# ${prefix}_[a-z_]* variable name in a function, e.g. $msm_modes
########################################################################
# read-only variables (global to this file)
########################################################################
# function return values; `0' means ok; other values are error codes
export _BAD;
export _GOOD;
export _NO;
export _OK;
export _YES;
_GOOD='0'; # return ok
_BAD='1'; # return negatively, error code `1'
# $_ERROR was already defined as `7' in groffer.sh.
_NO="${_BAD}";
_YES="${_GOOD}";
_OK="${_GOOD}";
# quasi-functions, call with `eval', e.g `eval "${return_ok}"'
export return_ok;
export return_good;
export return_bad;
export return_yes;
export return_no;
export return_error;
export return_var;
return_ok="func_pop; return ${_OK}";
return_good="func_pop; return ${_GOOD}";
return_bad="func_pop; return ${_BAD}";
return_yes="func_pop; return ${_YES}";
return_no="func_pop; return ${_NO}";
return_error="func_pop; return ${_ERROR}";
return_var="func_pop; return"; # add number, e.g. `eval "${return_var} $n'
export _DEFAULT_MODES;
_DEFAULT_MODES="'pdf' 'html' 'ps' 'x' 'dvi' 'tty'";
export _DEFAULT_RESOLUTION;
_DEFAULT_RESOLUTION='75';
export _DEFAULT_TTY_DEVICE;
_DEFAULT_TTY_DEVICE='latin1';
# _VIEWER_* viewer programs for different modes constructed as lists
export _VIEWER_DVI_TTY; # viewer program for dvi mode in tty
export _VIEWER_DVI_X; # viewer program for dvi mode in X
export _VIEWER_HTML_TTY; # viewer program for html mode in tty
export _VIEWER_HTML_X; # viewer program for html mode in X
export _VIEWER_PDF_TTY; # viewer program for pdf mode in tty
export _VIEWER_PDF_X; # viewer program for pdf mode in X
export _VIEWER_PS_TTY; # viewer program for ps mode in tty
export _VIEWER_PS_X; # viewer program for ps mode in X
export _VIEWER_TTY_TTY; # viewer program for X/x mode in tty
export _VIEWER_TTY_X; # viewer program for X/x mode in X
export _VIEWER_X_TTY; # viewer program for X/x mode in tty
export _VIEWER_X_X; # viewer program for X/x mode in X
_VIEWER_DVI_TTY="";
_VIEWER_DVI_X="'kdvi' 'xdvi' 'dvilx'";
_VIEWER_HTML_TTY="'lynx' 'w3m'";
_VIEWER_HTML_X="'konqueror' 'epiphany' 'mozilla-firefox' 'firefox' 'mozilla' \
'netscape' 'galeon' 'opera' 'amaya' 'arena' 'mosaic'";
_VIEWER_PDF_TTY="";
_VIEWER_PDF_X="'kpdf' 'acroread' 'evince' 'xpdf -z 150' 'gpdf' \
'kghostview --scale 1.45' 'ggv'";
_VIEWER_PS_TTY="";
_VIEWER_PS_X="'kpdf' 'kghostview --scale 1.45' 'evince' 'ggv' 'gv' \
'ghostview' 'gs_x11,gs'";
_VIEWER_TTY_TTY="'less -r -R' 'more' 'pager'";
_VIEWER_TTY_X="'xless'";
_VIEWER_X_TTY="";
_VIEWER_X_X="'gxditview' 'xditview'";
# Search automatically in standard sections `1' to `8', and in the
# traditional sections `9', `n', and `o'. On many systems, there
# exist even more sections, mostly containing a set of man pages
# special to a specific program package. These aren't searched for
# automatically, but must be specified on the command line.
export _MAN_AUTO_SEC_LIST;
_MAN_AUTO_SEC_LIST="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'";
export _MAN_AUTO_SEC_CHARS;
_MAN_AUTO_SEC_CHARS='[123456789no]';
export _SPACE_SED;
_SPACE_SED='['"${_SP}${_TAB}"']';
export _SPACE_CASE;
_SPACE_CASE='[\'"${_SP}"'\'"${_TAB}"']';
export _PROCESS_ID; # for shutting down the program
_PROCESS_ID="$$";
export _START_DIR; # directory at start time of the script
_START_DIR="$(pwd)";
############ the command line options of the involved programs
#
# The naming scheme for the options environment names is
# $_OPTS_<prog>_<length>[_<argspec>]
#
# <prog>: program name GROFFER, GROFF, or CMDLINE (for all
# command line options)
# <length>: LONG (long options) or SHORT (single character options)
# <argspec>: ARG for options with argument, NA for no argument;
# without _<argspec> both the ones with and without arg.
#
# Each option that takes an argument must be specified with a
# trailing : (colon).
# exports
export _OPTS_GROFFER_SHORT_NA;
export _OPTS_GROFFER_SHORT_ARG;
export _OPTS_GROFFER_LONG_NA;
export _OPTS_GROFFER_LONG_ARG;
export _OPTS_GROFF_SHORT_NA;
export _OPTS_GROFF_SHORT_ARG;
export _OPTS_GROFF_LONG_NA;
export _OPTS_GROFF_LONG_ARG;
export _OPTS_X_SHORT_ARG;
export _OPTS_X_SHORT_NA;
export _OPTS_X_LONG_ARG;
export _OPTS_X_LONG_NA;
export _OPTS_MAN_SHORT_ARG;
export _OPTS_MAN_SHORT_NA;
export _OPTS_MAN_LONG_ARG;
export _OPTS_MAN_LONG_NA;
export _OPTS_MANOPT_SHORT_ARG;
export _OPTS_MANOPT_SHORT_NA;
export _OPTS_MANOPT_LONG_ARG;
export _OPTS_MANOPT_LONG_NA;
export _OPTS_CMDLINE_SHORT_NA;
export _OPTS_CMDLINE_SHORT_ARG;
export _OPTS_CMDLINE_LONG_NA;
export _OPTS_CMDLINE_LONG_ARG;
###### groffer native options
_OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
_OPTS_GROFFER_SHORT_ARG="'T'";
_OPTS_GROFFER_LONG_NA="'auto' \
'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
'debug' 'debug-all' 'debug-filenames' \
'debug-func' 'debug-not-func' 'debug-keep' 'debug-lm' \
'debug-params' 'debug-shell' 'debug-stacks' 'debug-tmpdir' 'debug-user' \
'default' 'do-nothing' 'dvi' 'groff' 'help' 'intermediate-output' 'html' \
'man' 'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \
'text' 'to-stdout' 'text-device' 'tty' 'tty-device' \
'version' 'whatis' 'www' 'x' 'X'";
_OPTS_GROFFER_LONG_ARG="\
'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \
'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \
'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \
'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \
'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'";
##### groffer options inhereted from groff
_OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'k' 'l' 'N' 'p' \
'R' 's' 'S' 't' 'U' 'z'";
_OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
'w' 'W'";
_OPTS_GROFF_LONG_NA="";
_OPTS_GROFF_LONG_ARG="";
##### groffer options inhereted from the X Window toolkit
_OPTS_X_SHORT_NA="";
_OPTS_X_SHORT_ARG="";
_OPTS_X_LONG_NA="'iconic' 'rv'";
_OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \
'resolution' 'title' 'xrm'";
###### groffer options inherited from man
_OPTS_MAN_SHORT_NA="";
_OPTS_MAN_SHORT_ARG="";
_OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'ditroff' \
'local-file' 'location' 'troff' 'update' 'where'";
_OPTS_MAN_LONG_ARG="'locale' 'manpath' \
'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
###### additional options for parsing $MANOPT only
_OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
'V' 'w' 'Z'";
_OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
_OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \
'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'";
_OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
'config_file' 'encoding' 'extension' 'locale'";
###### collections of command line options
_OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA} \
${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
_OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \
${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
_OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
_OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
########################################################################
# read-write variables (global to this file)
########################################################################
export _ALL_PARAMS; # All options and file name parameters
export _ADDOPTS_GROFF; # Transp. options for groff (`eval').
export _APROPOS_PROG; # Program to run apropos.
export _APROPOS_SECTIONS; # Sections for different --apropos-*.
export _DISPLAY_MODE; # Display mode.
export _DISPLAY_PROG; # Viewer program to be used for display.
export _DISPLAY_ARGS; # X resources for the viewer program.
export _FILE_NR; # number for temporary `,file,*'
export _FILEARGS; # Stores filespec parameters.
export _FILESPEC_ARG; # Stores the actual filespec parameter.
export _FILESPEC_IS_MAN; # filespec is for searching a man page
export _FUNC_STACK; # Store debugging information.
export _MACRO_PACKAGES; # groff's macro packages.
export _MACRO_PKG; # Macro package for each found file.
export _NO_FILESPECS; # Yes, if there are no filespec arguments.
export _OUTPUT_FILE_NAME; # output generated, see main_set_res..()
export _REG_TITLE_LIST; # Processed file names.
export _SOELIM_R; # option -r for soelim
export _SPECIAL_FILESPEC; # Filespec ran for apropos or whatis.
export _SPECIAL_SETUP; # Test on setup for apropos or whatis.
export _VIEWER_BACKGROUND; # viewer shall be run in the background or not
# _MAN_* finally used configuration of man searching
export _MAN_ALL; # search all man pages per filespec
export _MAN_ENABLE; # enable search for man pages
export _MAN_EXT; # extension for man pages
export _MAN_FORCE; # force file parameter to be man pages
export _MAN_IS_SETUP; # setup man variables only once
export _MAN_LANG; # language for man pages
export _MAN_LANG2; # language for man pages
export _MAN_PATH; # search path for man pages as a list
export _MAN_SEC; # sections for man pages; sep. `:'
export _MAN_SEC_CHARS; # sections for man pages as [] construct
export _MAN_SEC_LIST; # sections for man pages as a list
export _MAN_SYS; # system names for man pages as a list
# _MANOPT_* as parsed from $MANOPT
export _MANOPT_ALL; # $MANOPT --all
export _MANOPT_EXTENSION; # $MANOPT --extension
export _MANOPT_LANG; # $MANOPT --locale
export _MANOPT_PATH; # $MANOPT --manpath
export _MANOPT_PAGER; # $MANOPT --pager
export _MANOPT_SEC; # $MANOPT --sections
export _MANOPT_SYS; # $MANOPT --systems
# variables for mode pdf
export _PDF_DID_NOT_WORK;
export _PDF_HAS_GS;
export _PDF_HAS_PS2PDF;
# _OPT_* as parsed from groffer command line
export _OPT_ALL; # display all suitable man pages
export _OPT_APROPOS; # call `apropos' program
export _OPT_BD; # set border color in some modes
export _OPT_BG; # set background color in some modes
export _OPT_BW; # set border width in some modes
export _OPT_DEFAULT_MODES; # `,'-list of modes when no mode given
export _OPT_DEVICE; # device option
export _OPT_DO_NOTHING; # do nothing in main_display()
export _OPT_DISPLAY; # set X display
export _OPT_EXTENSION; # set extension for man page search
export _OPT_FG; # set foreground color in some modes
export _OPT_FN; # set font in some modes
export _OPT_GEOMETRY; # set size and position of viewer in X
export _OPT_ICONIC; # -iconic option for X viewers
export _OPT_LANG; # set language for man pages
export _OPT_MODE; # values: X, tty, Q, Z, ""
export _OPT_MANPATH; # manual setting of path for man-pages
export _OPT_PAGER; # specify paging program for tty mode
export _OPT_RESOLUTION; # set X resolution in dpi
export _OPT_RV; # reverse fore- and background colors
export _OPT_SECTIONS; # sections for man page search
export _OPT_STDOUT; # print mode file to standard output
export _OPT_SYSTEMS; # man pages of different OS's
export _OPT_TITLE; # title for gxditview window
export _OPT_TEXT_DEVICE; # set device for tty mode
export _OPT_V; # groff option -V
export _OPT_VIEWER_DVI; # viewer program for dvi mode
export _OPT_VIEWER_HTML; # viewer program for html mode
export _OPT_VIEWER_PDF; # viewer program for pdf mode
export _OPT_VIEWER_PS; # viewer program for ps mode
export _OPT_VIEWER_X; # viewer program for x mode
export _OPT_WHATIS; # print the man description
export _OPT_XRM; # specify X resource
export _OPT_Z; # groff option -Z
# _TMP_* temporary directory and files
export _TMP_DIR; # groffer directory for temporary files
export _TMP_CAT; # stores concatenation of everything
export _TMP_MAN; # stores find of man path
export _TMP_MANSPEC; # filters man pages with filespec
export _TMP_STDIN; # stores stdin, if any
# these variables are preset in section `Preset' after the rudim. test
########################################################################
# Preset and reset of read-write global variables
########################################################################
# For variables that can be reset by option `--default', see reset().
_FILE_NR=0;
_FILEARGS='';
_MACRO_PACKAGES="'-man' '-mdoc' '-me' '-mm' '-mom' '-ms'";
_SPECIAL_FILESPEC='no';
_SPECIAL_SETUP='no';
# _TMP_* temporary files
_TMP_DIR='';
_TMP_CAT='';
_TMP_MAN='';
_TMP_CONF='';
_TMP_STDIN='';
# variables for mode pdf
_PDF_DID_NOT_WORK='no';
_PDF_HAS_GS='no';
_PDF_HAS_PS2PDF='no';
# option -r for soelim
if echo -n '' | soelim -r 2>${_NULL_DEV} >${_NULL_DEV}
then
_SOELIM_R='-r';
else
_SOELIM_R='';
fi;
########################################################################
# reset ()
#
# Reset the variables that can be affected by options to their default.
#
reset()
{
if test "$#" -ne 0
then
error "reset() does not have arguments.";
fi;
_ADDOPTS_GROFF='';
_APROPOS_PROG='';
_APROPOS_SECTIONS='';
_DISPLAY_ARGS='';
_DISPLAY_MODE='';
_DISPLAY_PROG='';
_MACRO_PKG='';
_NO_FILESPECS='';
_REG_TITLE_LIST='';
# _MAN_* finally used configuration of man searching
_MAN_ALL='no';
_MAN_ENABLE='yes'; # do search for man-pages
_MAN_EXT='';
_MAN_FORCE='no'; # first local file, then search man page
_MAN_IS_SETUP='no';
_MAN_LANG='';
_MAN_LANG2='';
_MAN_PATH='';
_MAN_SEC='';
_MAN_SEC_CHARS='';
_MAN_SEC_LIST='';
_MAN_SYS='';
# _MANOPT_* as parsed from $MANOPT
_MANOPT_ALL='no';
_MANOPT_EXTENSION='';
_MANOPT_LANG='';
_MANOPT_PATH='';
_MANOPT_PAGER='';
_MANOPT_SEC='';
_MANOPT_SYS='';
# _OPT_* as parsed from groffer command line
_OPT_ALL='no';
_OPT_APROPOS='no';
_OPT_BD='';
_OPT_BG='';
_OPT_BW='';
_OPT_DEFAULT_MODES='';
_OPT_DEVICE='';
_OPT_DISPLAY='';
_OPT_DO_NOTHING='no';
_OPT_EXTENSION='';
_OPT_FG='';
_OPT_FN='';
_OPT_GEOMETRY='';
_OPT_ICONIC='no';
_OPT_LANG='';
_OPT_MODE='';
_OPT_MANPATH='';
_OPT_PAGER='';
_OPT_RESOLUTION='';
_OPT_RV='no';
_OPT_SECTIONS='';
_OPT_SYSTEMS='';
_OPT_STDOUT='no';
_OPT_TITLE='';
_OPT_TEXT_DEVICE='';
_OPT_V='no';
_OPT_VIEWER_DVI='';
_OPT_VIEWER_PDF='';
_OPT_VIEWER_PS='';
_OPT_VIEWER_HTML='';
_OPT_VIEWER_X='';
_OPT_WHATIS='no';
_OPT_XRM='';
_OPT_Z='no';
_VIEWER_BACKGROUND='no';
}
reset;
########################################################################
# Preliminary functions for error handling
########################################################################
landmark "2: preliminary functions";
# These functions do not have a func-check frame. Basically they could be
# moved to the functions in alphabetical order.
##############
# echo1 (<text>*)
#
# Output to stdout with final line break.
#
# Arguments : arbitrary text including `-'.
#
echo1()
{
cat <<EOF
$@
EOF
} # echo1()
##############
# echo2 (<text>*)
#
# Output to stderr with final line break.
#
# Arguments : arbitrary text including `-'.
#
echo2()
{
cat >&2 <<EOF
$@
EOF
} # echo2()
##############
# clean_up ()
#
# Clean up at exit.
#
cu_already='no';
clean_up()
{
cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1;
if test _${_DEBUG_KEEP_FILES}_ = _yes_
then
if test _"$cu_already"_ = _yes_
then
eval "${return_ok}";
fi;
cu_already=yes;
echo2 "Kept temporary directory ${_TMP_DIR}."
else
if test _"${_TMP_DIR}"_ != __
then
if test -e "${_TMP_DIR}"
then
rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1;
fi;
fi;
fi;
eval "${return_ok}";
} # clean_up()
#############
# diag (text>*)
#
# Output a diagnostic message to stderr.
#
diag()
{
echo2 '>>>>>'"$*";
} # diag()
#############
# error (<text>*)
#
# Print an error message to standard error, print the function stack,
# exit with an error condition. The argument should contain the name
# of the function from which it was called. This is for system errors.
#
error()
{
case "$#" in
1) echo2 'groffer error: '"$1"; ;;
*) echo2 'groffer error: wrong number of arguments in error().'; ;;
esac;
func_stack_dump;
if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
then
: >"${_TMP_DIR}"/,error;
fi;
exit "${_ERROR}";
} # error()
#############
# error_user (<text>*)
#
# Print an error message to standard error; exit with an error condition.
# The error is supposed to be produced by the user. So the funtion stack
# is omitted.
#
error_user()
{
case "$#" in
1)
echo2 'groffer error: '"$1";
;;
*)
echo2 'groffer error: wrong number of arguments in error_user().';
;;
esac;
if test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_
then
func_stack_dump;
fi;
if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
then
: >"${_TMP_DIR}"/,error;
fi;
exit "${_ERROR}";
} # error_user()
#############
# exit_test ()
#
# Test whether the former command ended with error(). Exit again.
#
# Globals: $_ERROR
#
exit_test()
{
if test "$?" = "${_ERROR}"
then
exit ${_ERROR};
fi;
if test _"${_TMP_DIR}"_ != __ && test -f "${_TMP_DIR}"/,error
then
exit ${_ERROR};
fi;
} # exit_test()
########################################################################
# Definition of normal Functions in alphabetical order
########################################################################
landmark "3: functions";
########################################################################
# apropos_filespec ()
#
# Compose temporary file for filspec.
#
# Globals: in: $_OPT_APROPOS, $_SPECIAL_SETUP, $_FILESPEC_ARG,
# $_APROPOS_PROG, $_APROPOS_SECTIONS, $_OPT_SECTIONS
# out: $_SPECIAL_FILESPEC
#
# Variable prefix: af
#
apropos_filespec()
{
func_check apropos_filespec '=' 0 "$@";
if obj _OPT_APROPOS is_yes
then
if obj _SPECIAL_SETUP is_not_yes
then
error 'apropos_filespec(): apropos_setup() must be run first.';
fi;
_SPECIAL_FILESPEC='yes';
if obj _NO_FILESPECS is_yes
then
to_tmp_line '.SH no filespec';
eval "${_APROPOS_PROG}" | sed -e 's/^/\\\&/' >>"${_TMP_CAT}";
eval "${return_ok}";
fi;
eval to_tmp_line \
"'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
exit_test;
if obj _APROPOS_SECTIONS is_empty
then
if obj _OPT_SECTIONS is_empty
then
s='^.*(..*).*$';
else
s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/://g')"']';
fi;
else
s='^.*(['"${_APROPOS_SECTIONS}"']';
fi;
### apropos_filespec()
af_filespec="$(echo1 "${_FILESPEC_ARG}" | sed -e '
s,/,\\/,g
s/\./\\./g
')";
eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \
sed -n -e '
/^'"${af_filespec}"': /s/^\(.*\)$/\\\&\1/p
/'"$s"'/p
' | \
sort |\
sed -e '
s/^\(.*(..*).*\) *- *\(.*\)$/\.br\n\.TP 15\n\.BR \"\1\"\n\\\&\2/
' >>"${_TMP_CAT}";
eval ${_UNSET} af_filespec;
eval "${return_ok}";
else
eval "${return_bad}";
fi;
} # apropos_filespec()
########################################################################
# apropos_setup ()
#
# Setup for the --apropos* options, just 2 global variables are set.
#
# Globals: in: $_OPT_APROPOS
# out: $_SPECIAL_SETUP, $_APROPOS_PROG
#
apropos_setup()
{
func_check apropos_setup '=' 0 "$@";
if obj _OPT_APROPOS is_yes
then
if is_prog apropos
then
_APROPOS_PROG='apropos';
elif is_prog man
then
if man --apropos man >${_NULL_DEV} 2>${_NULL_DEV}
then
_APROPOS_PROG='man --apropos';
elif man -k man >${_NULL_DEV} 2>${_NULL_DEV}
then
_APROPOS_PROG='man -k';
fi;
fi;
if obj _APROPOS_PROG is_empty
then
error 'apropos_setup(): no apropos program available.';
fi;
to_tmp_line '.TH GROFFER APROPOS';
_SPECIAL_SETUP='yes';
if obj _OPT_TITLE is_empty
then
_OPT_TITLE='apropos';
fi;
eval "${return_ok}";
else
eval "${return_bad}";
fi;
} # apropos_setup()
########################################################################
# base_name (<path>)
#
# Get the file name part of <path>, i.e. delete everything up to last
# `/' from the beginning of <path>. Remove final slashes, too, to get
# a non-empty output. The output is constructed according the shell
# program `basename'.
#
# Arguments : 1
# Output : the file name part (without slashes)
#
# Variable prefix: bn
#
base_name()
{
func_check base_name = 1 "$@";
bn_name="$1";
case "${bn_name}" in
*/)
# delete all final slashes
bn_name="$(echo1 "${bn_name}" | sed -e 's|//*$||')";
exit_test;
;;
esac;
case "${bn_name}" in
'')
eval ${_UNSET} bn_name;
eval "${return_bad}";
;;
/)
# this is like `basename' does
echo1 '/';
;;
*/*)
# delete everything before and including the last slash `/'.
echo1 "${bn_name}" | sed -e 's|^.*//*\([^/]*\)$|\1|';
;;
*)
obj bn_name echo1;
;;
esac;
eval ${_UNSET} bn_name;
eval "${return_ok}";
} # base_name()
########################################################################
# cat_z (<file>)
#
# Decompress if possible or just print <file> to standard output.
# gzip, bzip2, and .Z decompression is supported.
#
# Arguments: 1, a file name.
# Output: the content of <file>, possibly decompressed.
#
cat_z()
{
func_check cat_z = 1 "$@";
case "$1" in
'')
error 'cat_z(): empty file name.';
;;
'-')
error 'cat_z(): for standard input use save_stdin().';
;;
esac;
if is_file "$1"
then
:;
else
error 'cat_z(): argument $1 is not a file.';
fi;
if test -s "$1"
then
:;
else
eval "${return_ok}";
fi;
if obj _HAS_COMPRESSION is_yes
then
if obj _HAS_BZIP is_yes
then
# test whether being compressed with bz2
if bzip2 -t "$1" 2>${_NULL_DEV}
then
bzip2 -c -d "$1" 2>${_NULL_DEV};
eval "${return_ok}";
fi;
fi;
# if not compressed gzip acts like `cat'
gzip -c -d -f "$1" 2>${_NULL_DEV};
else
cat "$1";
fi;
eval "${return_ok}";
} # cat_z()
########################################################################
# clean_up ()
#
# Do the final cleaning up before exiting; used by the trap calls.
#
# defined above
########################################################################
# diag (<text>*)
#
# Print marked message to standard error; useful for debugging.
#
# defined above
########################################################################
landmark '4: dir_name()*';
########################################################################
#######################################################################
# dir_name (<name>)
#
# Get the directory name of <name>. The output is constructed
# according to the shell program `dirname'.
#
# Arguments : 1
# Output : the directory part of <name>
#
# Variable prefix: dn
#
dir_name()
{
func_check dir_name = 1 "$@";
obj_from_output dn_name dir_name_chop "$1";
case "${dn_name}" in
''|.)
echo1 '.';
;;
/)
echo1 '/';
;;
*/*)
echo1 "$(echo1 "${dn_name}" | sed 's#/*[^/][^/]*$##')";
;;
*)
echo1 "${dn_name}";
;;
esac;
eval "${return_ok}";
} # dir_name()
#######################################################################
# dir_name_append (<dir> <name>)
#
# Append `name' to `dir' with clean handling of `/'.
#
# Arguments : 2
# Output : the generated new directory name <dir>/<name>
#
dir_name_append()
{
func_check dir_name_append = 2 "$@";
if is_empty "$1"
then
echo1 "$2";
elif is_empty "$2"
then
echo1 "$1";
else
dir_name_chop "$1"/"$2";
fi;
eval "${return_ok}";
} # dir_name_append()
########################################################################
# dir_name_chop (<name>)
#
# Remove unnecessary slashes from directory name.
#
# Argument: 1, a directory name.
# Output: path without double, or trailing slashes.
#
# Variable prefix: dc
#
dir_name_chop()
{
func_check dir_name_chop = 1 "$@";
# replace all multiple slashes by a single slash `/'.
dc_res="$(echo1 "$1" | sed -e 's|///*|/|g')";
exit_test;
case "${dc_res}" in
?*/)
# remove trailing slash '/';
echo1 "${dc_res}" | sed -e 's|/$||';
;;
*)
obj dc_res echo1
;;
esac;
eval ${_UNSET} dc_res;
eval "${return_ok}";
} # dir_name_chop()
########################################################################
# do_nothing ()
#
# Dummy function that does nothing.
#
do_nothing()
{
eval return "${_OK}";
} # do_nothing()
########################################################################
# echo1 (<text>*)
#
# Print to standard output with final line break.
#
# defined above
########################################################################
# echo2 (<text>*)
#
# Print to standard error with final line break.
#
# defined above
########################################################################
# error (<text>*)
#
# Print error message and exit with error code.
#
# defined above
########################################################################
# exit_test ()
#
# Test whether the former command ended with error(). Exit again.
#
# defined above
if test _"${_DEBUG_FUNC_CHECK}"_ = _yes_
then
#############
# func_check (<func_name> <rel_op> <nr_args> "$@")
#
# This is called at the first line of each function. It checks the
# number of arguments of function <func_name> and registers the
# function call to _FUNC_STACK.
#
# Arguments: >=3
# <func_name>: name of the calling function.
# <rel_op>: a relational operator: = != < > <= >=
# <nr_args>: number of arguments to be checked against <operator>
# "$@": the arguments of the calling function.
#
# Variable prefix: fc
#
func_check()
{
if test "$#" -lt 3
then
error 'func_check() needs at least 3 arguments.';
fi;
fc_fname="$1";
case "$3" in
1)
fc_nargs="$3";
fc_s='';
;;
0|[2-9])
fc_nargs="$3";
fc_s='s';
;;
*)
error "func_check(): third argument must be a digit.";
;;
esac;
### func_check()
case "$2" in
'='|'-eq')
fc_op='-eq';
fc_comp='exactly';
;;
'>='|'-ge')
fc_op='-ge';
fc_comp='at least';
;;
'<='|'-le')
fc_op='-le';
fc_comp='at most';
;;
'<'|'-lt')
fc_op='-lt';
fc_comp='less than';
;;
'>'|'-gt')
fc_op='-gt';
fc_comp='more than';
;;
'!='|'-ne')
fc_op='-ne';
fc_comp='not';
;;
### func_check()
*)
error \
'func_check(): second argument is not a relational operator.';
;;
esac;
shift;
shift;
shift;
if test "$#" "${fc_op}" "${fc_nargs}"
then
do_nothing;
else
error "func_check(): \
${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
fi;
func_push "${fc_fname}";
if test _"${_DEBUG_STACKS}"_ = _yes_
then
echo2 '+++ '"${fc_fname} $@";
echo2 '>>> '"${_FUNC_STACK}";
fi;
eval ${_UNSET} fc_comp;
eval ${_UNSET} fc_fname;
eval ${_UNSET} fc_nargs;
eval ${_UNSET} fc_op;
eval ${_UNSET} fc_s;
} # func_check()
#############
# func_pop ()
#
# Retrieve the top element from the function stack. This is called
# by every return variable in each function.
#
# The stack elements are separated by `!'; the popped element is
# identical to the original element, except that all `!' characters
# were removed.
#
# Arguments: 1
#
func_pop()
{
if test "$#" -ne 0
then
error 'func_pop() does not have arguments.';
fi;
case "${_FUNC_STACK}" in
'')
if test _"${_DEBUG_STACKS}"_ = _yes_
then
error 'func_pop(): stack is empty.';
fi;
;;
*!*)
# split at first bang `!'.
_FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')";
exit_test;
;;
*)
_FUNC_STACK='';
;;
esac;
if test _"${_DEBUG_STACKS}"_ = _yes_
then
echo2 '<<< '"${_FUNC_STACK}";
fi;
} # func_pop()
#############
# func_push (<element>)
#
# Store another element to the function stack. This is called by
# func_check() at the beginning of each function.
#
# The stack elements are separated by `!'; if <element> contains a `!'
# it is removed first.
#
# Arguments: 1
#
# Variable prefix: fp
#
func_push()
{
if test "$#" -ne 1
then
error 'func_push() needs 1 argument.';
fi;
case "$1" in
*'!'*)
# remove all bangs `!'.
fp_element="$(echo1 "$1" | sed -e 's/!//g')";
exit_test;
;;
*)
fp_element="$1";
;;
esac;
if test _"${_FUNC_STACK}"_ = __
then
_FUNC_STACK="${fp_element}";
else
_FUNC_STACK="${fp_element}!${_FUNC_STACK}";
fi;
eval ${_UNSET} fp_element;
} # func_push()
#############
# func_stack_dump ()
#
# Print the content of the function stack. Ignore the arguments.
#
func_stack_dump()
{
diag 'call stack(): '"${_FUNC_STACK}";
} # func_stack_dump()
else # $_DEBUG_FUNC_CHECK is not `yes'
func_check() { return; }
func_pop() { return; }
func_push() { return; }
func_stack_dump() { return; }
fi; # test of $_DEBUG_FUNC_CHECK
########################################################################
# get_first_essential (<arg>*)
#
# Retrieve first non-empty argument.
#
# Return : `1' if all arguments are empty, `0' if found.
# Output : the retrieved non-empty argument.
#
# Variable prefix: gfe
#
get_first_essential()
{
func_check get_first_essential '>=' 0 "$@";
if is_equal "$#" 0
then
eval "${return_ok}";
fi;
for i
do
gfe_var="$i";
if obj gfe_var is_not_empty
then
obj gfe_var echo1;
eval ${_UNSET} gfe_var;
eval "${return_ok}";
fi;
done;
eval ${_UNSET} gfe_var;
eval "${return_bad}";
} # get_first_essential()
########################################################################
landmark '5: is_*()';
########################################################################
########################################################################
# is_dir (<name>)
#
# Test whether `name' is a readable directory.
#
# Arguments : 1
# Return : `0' if arg1 is a directory, `1' otherwise.
#
is_dir()
{
func_check is_dir '=' 1 "$@";
if is_not_empty "$1" && test -d "$1" && test -r "$1"
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_dir()
########################################################################
# is_empty (<string>)
#
# Test whether <string> is empty.
#
# Arguments : <=1
# Return : `0' if arg1 is empty or does not exist, `1' otherwise.
#
is_empty()
{
func_check is_empty '=' 1 "$@";
if test _"$1"_ = __
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_empty()
########################################################################
# is_empty_file (<file_name>)
#
# Test whether <file_name> is an empty existing file.
#
# Arguments : <=1
# Return :
# `0' if arg1 is an empty existing file
# `1' otherwise
#
is_empty_file()
{
func_check is_empty_file '=' 1 "$@";
if is_file "$1"
then
if test -s "$1"
then
eval "${return_no}";
else
eval "${return_yes}";
fi;
fi;
eval "${return_no}";
} # is_empty_file()
########################################################################
# is_equal (<string1> <string2>)
#
# Test whether <string1> is equal to <string2>.
#
# Arguments : 2
# Return : `0' both arguments are equal strings, `1' otherwise.
#
is_equal()
{
func_check is_equal '=' 2 "$@";
if test _"$1"_ = _"$2"_
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_equal()
########################################################################
# is_existing (<name>)
#
# Test whether <name> is an existing file or directory. Solaris 2.5 does
# not have `test -e'.
#
# Arguments : 1
# Return : `0' if arg1 exists, `1' otherwise.
#
is_existing()
{
func_check is_existing '=' 1 "$@";
if is_empty "$1"
then
eval "${return_no}";
fi;
if test -f "$1" || test -d "$1" || test -c "$1"
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_existing()
########################################################################
# is_file (<name>)
#
# Test whether <name> is a readable file.
#
# Arguments : 1
# Return : `0' if arg1 is a readable file, `1' otherwise.
#
is_file()
{
func_check is_file '=' 1 "$@";
if is_not_empty "$1" && test -f "$1" && test -r "$1"
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_file()
########################################################################
# is_greater_than (<integer1> <integer2>)
#
# Test whether <integer1> is greater than <integer2>.
#
# Arguments : 2
# Return : `0' if <integer1> is a greater integer than <integer2>,
# `1' otherwise.
#
is_greater_than()
{
func_check is_greater_than '=' 2 "$@";
if is_integer "$1" && is_integer "$2" && test "$1" -gt "$2"
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_greater_than()
########################################################################
# is_integer (<string>)
#
# Test whether `string' is an integer.
#
# Arguments : 1
# Return : `0' if argument is an integer, `1' otherwise.
#
is_integer()
{
func_check is_integer '=' 1 "$@";
if is_equal "$(echo1 "$1" | sed -n -e '
s/^[0-9][0-9]*$/ok/p
s/^[-+][0-9][0-9]*$/ok/p
')" 'ok'
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_integer()
########################################################################
# is_not_empty_file (<file_name>)
#
# Test whether <file_name> is a non-empty existing file.
#
# Arguments : <=1
# Return :
# `0' if arg1 is a non-empty existing file
# `1' otherwise
#
is_not_empty_file()
{
func_check is_not_empty_file '=' 1 "$@";
if is_file "$1" && test -s "$1"
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_not_empty_file()
########################################################################
# is_not_dir (<name>)
#
# Test whether <name> is not a readable directory.
#
# Arguments : 1
# Return : `0' if arg1 is a directory, `1' otherwise.
#
is_not_dir()
{
func_check is_not_dir '=' 1 "$@";
if is_dir "$1"
then
eval "${return_no}";
fi;
eval "${return_yes}";
} # is_not_dir()
########################################################################
# is_not_empty (<string>)
#
# Test whether <string> is not empty.
#
# Arguments : <=1
# Return : `0' if arg1 exists and is not empty, `1' otherwise.
#
is_not_empty()
{
func_check is_not_empty '=' 1 "$@";
if is_empty "$1"
then
eval "${return_no}";
fi;
eval "${return_yes}";
} # is_not_empty()
########################################################################
# is_not_equal (<string1> <string2>)
#
# Test whether <string1> differs from <string2>.
#
# Arguments : 2
#
is_not_equal()
{
func_check is_not_equal '=' 2 "$@";
if is_equal "$1" "$2"
then
eval "${return_no}";
fi
eval "${return_yes}";
} # is_not_equal()
########################################################################
# is_not_file (<filename>)
#
# Test whether <filename> is a not readable file.
#
# Arguments : 1 (empty allowed)
#
is_not_file()
{
func_check is_not_file '=' 1 "$@";
if is_file "$1"
then
eval "${return_no}";
fi;
eval "${return_yes}";
} # is_not_file()
########################################################################
# is_not_prog (<program>)
#
# Verify that <program> is not a command in $PATH.
#
# Arguments : 1, <program> can have spaces and arguments.
#
is_not_prog()
{
func_check is_not_prog '=' 1 "$@";
if where_is_prog "$1" >${_NULL_DEV}
then
eval "${return_no}";
fi;
eval "${return_yes}";
} # is_not_prog()
########################################################################
# is_not_writable (<name>)
#
# Test whether <name> is not a writable file or directory.
#
# Arguments : >=1 (empty allowed), more args are ignored
#
is_not_writable()
{
func_check is_not_writable '>=' 1 "$@";
if is_writable "$1"
then
eval "${return_no}";
fi;
eval "${return_yes}";
} # is_not_writable()
########################################################################
# is_not_X ()
#
# Test whether the script is not running in X Window by checking $DISPLAY.
#
is_not_X()
{
func_check is_not_X '=' 0 "$@";
if obj DISPLAY is_empty
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_not_X()
########################################################################
# is_not_yes (<string>)
#
# Test whether <string> is not `yes'.
#
# Arguments : 1
#
is_not_yes()
{
func_check is_not_yes = 1 "$@";
if is_yes "$1"
then
eval "${return_no}";
fi;
eval "${return_yes}";
} # is_not_yes()
########################################################################
# is_prog (<name>)
#
# Determine whether <name> is a program in $PATH.
#
# Arguments : 1, <program> can have spaces and arguments.
#
is_prog()
{
func_check is_prog '=' 1 "$@";
if where_is_prog "$1" >${_NULL_DEV}
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_prog()
########################################################################
# is_writable (<name>)
#
# Test whether <name> is a writable file or directory.
#
# Arguments : >=1 (empty allowed), more args are ignored
#
is_writable()
{
func_check is_writable '>=' 1 "$@";
if is_empty "$1"
then
eval "${return_no}";
fi;
if test -r "$1"
then
if test -w "$1"
then
eval "${return_yes}";
fi;
fi;
eval "${return_no}";
} # is_writable()
########################################################################
# is_X ()
#
# Test whether the script is running in X Window by checking $DISPLAY.
#
is_X()
{
func_check is_X '=' 0 "$@";
if obj DISPLAY is_not_empty
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_X()
########################################################################
# is_yes (<string>)
#
# Test whether <string> has value `yes'.
#
# Return : `0' if arg1 is `yes', `1' otherwise.
#
is_yes()
{
func_check is_yes '=' 1 "$@";
if is_equal "$1" 'yes'
then
eval "${return_yes}";
fi;
eval "${return_no}";
} # is_yes()
########################################################################
# landmark ()
#
# Print debugging information on standard error if $_DEBUG_LM is `yes'.
#
# Globals: $_DEBUG_LM
#
# Defined in section `Debugging functions'.
########################################################################
# leave ([<code>])
#
# Clean exit without an error or with error <code>.
#
leave()
{
clean_up;
if test $# = 0
then
exit "${_OK}";
else
exit "$1";
fi;
} # leave()
########################################################################
landmark '6: list_*()';
########################################################################
#
# `list' is an object class that represents an array or list. Its
# data consists of space-separated single-quoted elements. So a list
# has the form "'first' 'second' '...' 'last'". See list_append() for
# more details on the list structure. The array elements of `list'
# can be get by `eval set x "$list"; shift`.
########################################################################
# list_append (<list> <element>...)
#
# Add one or more elements to an existing list. <list> may also be
# empty.
#
# Arguments: >=2
# <list>: a variable name for a list of single-quoted elements
# <element>: some sequence of characters.
# Output: none, but $<list> is set to
# if <list> is empty: "'<element>' '...'"
# otherwise: "$list '<element>' ..."
#
# Variable prefix: la
#
list_append()
{
func_check list_append '>=' 2 "$@";
la_name="$1";
eval la_list='"${'"$1"'}"';
shift;
for s
do
la_s="$s";
case "${la_s}" in
*\'*)
# escape each single quote by replacing each
# "'" (squote) by "'\''" (squote bslash squote squote);
# note that the backslash must be doubled in the following `sed'
la_element="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')";
exit_test;
;;
'')
la_element="";
;;
*)
la_element="${la_s}";
;;
esac;
### list_append()
if obj la_list is_empty
then
la_list="'${la_element}'";
else
la_list="${la_list} '${la_element}'";
fi;
done;
eval "${la_name}"='"${la_list}"';
eval ${_UNSET} la_element;
eval ${_UNSET} la_list;
eval ${_UNSET} la_name;
eval ${_UNSET} la_s;
eval "${return_ok}";
} # list_append()
########################################################################
# list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
#
# Transform command line arguments into a normalized form.
#
# Options, option arguments, and file parameters are identified and
# output each as a single-quoted argument of its own. Options and
# file parameters are separated by a '--' argument.
#
# Arguments: >=1
# <pre_name>: common part of a set of 4 environment variable names:
# $<pre_name>_SHORT_NA: list of short options without an arg.
# $<pre_name>_SHORT_ARG: list of short options that have an arg.
# $<pre_name>_LONG_NA: list of long options without an arg.
# $<pre_name>_LONG_ARG: list of long options that have an arg.
# <cmdline_arg>...: the arguments from a command line, such as "$@",
# the content of a variable, or direct arguments.
#
# Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
#
# Example:
# list_from_cmdline PRE -a f1 -bcarg --lon=larg f2 low larg2
# PRE_SHORT_NA="'a' 'b'"
# PRE_SHORT_ARG="'c' 'd'"
# PRE_LONG_NA="'help' 'version'"
# PRE_LONG_ARG="'longer' 'lower'"
# This will result in printing:
# '-a' '-b' '-c' 'arg' '--longer' 'larg' '--lower' 'larg2' '--' 'f1' 'f2'
#
# Use this function in the following way:
# eval set x "$(list_from_cmdline PRE_NAME "$@")";
# shift;
# while test "$1" != '--'; do
# case "$1" in
# ...
# esac;
# shift;
# done;
# shift; #skip '--'
# # all positional parameters ("$@") left are file name parameters.
#
# Variable prefix: lfc
#
list_from_cmdline()
{
func_check list_from_cmdline '>=' 1 "$@";
# short options, no argument
obj_from_output lfc_short_n obj_data "$1"_SHORT_NA;
# short options, with argument
obj_from_output lfc_short_a obj_data "$1"_SHORT_ARG;
# long options, no argument
obj_from_output lfc_long_n obj_data "$1"_LONG_NA;
# long options, with argument
obj_from_output lfc_long_a obj_data "$1"_LONG_ARG;
if obj lfc_short_n is_empty
then
error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
fi;
if obj lfc_short_a is_empty
then
error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
fi;
if obj lfc_long_n is_empty
then
error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
fi;
if obj lfc_long_a is_empty
then
error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
fi;
shift;
if is_equal "$#" 0
then
echo1 "'--'"
eval ${_UNSET} lfc_fparams;
eval ${_UNSET} lfc_short_a;
eval ${_UNSET} lfc_short_n;
### list_from_cmdline()
eval ${_UNSET} lfc_long_a;
eval ${_UNSET} lfc_long_n;
eval ${_UNSET} lfc_result;
eval "${return_ok}";
fi;
lfc_fparams='';
lfc_result='';
while is_greater_than "$#" 0
do
lfc_arg="$1";
shift;
case "${lfc_arg}" in
--) break; ;;
--*=*)
# delete leading '--';
lfc_with_equal="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
# extract option by deleting from the first '=' to the end
lfc_abbrev="$(echo1 "${lfc_with_equal}" | \
sed -e 's/^\([^=]*\)=.*$/\1/')";
obj_from_output lfc_opt \
list_single_from_abbrev lfc_long_a "${lfc_abbrev}";
if obj lfc_opt is_empty
then
error_user "--${lfc_abbrev} is not an option.";
else
# get the option argument by deleting up to first `='
lfc_optarg="$(echo1 "${lfc_with_equal}" | sed -e 's/^[^=]*=//')";
exit_test;
list_append lfc_result "--${lfc_opt}" "${lfc_optarg}";
continue;
fi;
### list_from_cmdline()
;;
--*)
# delete leading '--';
lfc_abbrev="$(echo1 "${lfc_arg}" | sed -e 's/^--//')";
if list_has lfc_long_n "${lfc_abbrev}"
then
lfc_opt="${lfc_abbrev}";
else
obj_from_output lfc_opt \
list_single_from_abbrev lfc_long_n "${lfc_abbrev}";
if obj lfc_opt is_not_empty && is_not_equal "$#" 0
then
obj_from_output a \
list_single_from_abbrev lfc_long_a "${lfc_abbrev}";
if obj a is_not_empty
then
error_user "The abbreviation ${lfc_arg} \
has multiple options: --${lfc_opt} and --${a}.";
fi;
fi;
fi; # if list_has lfc_long_n "${lfc_abbrev}"
if obj lfc_opt is_not_empty
then
# long option, no argument
list_append lfc_result "--${lfc_opt}";
continue;
fi;
obj_from_output lfc_opt \
list_single_from_abbrev lfc_long_a "${lfc_abbrev}";
if obj lfc_opt is_not_empty
then
### list_from_cmdline()
# long option with argument
if is_equal "$#" 0
then
error_user "no argument for option --${lfc_opt}."
fi;
list_append lfc_result "--${lfc_opt}" "$1";
shift;
continue;
fi; # if obj lfc_opt is_not_empty
error_user "${lfc_arg} is not an option.";
;;
-?*) # short option (cluster)
# delete leading `-';
lfc_rest="$(echo1 "${lfc_arg}" | sed -e 's/^-//')";
exit_test;
while obj lfc_rest is_not_empty
do
# get next short option from cluster (first char of $lfc_rest)
lfc_optchar="$(echo1 "${lfc_rest}" | sed -e 's/^\(.\).*$/\1/')";
# remove first character from ${lfc_rest};
lfc_rest="$(echo1 "${lfc_rest}" | sed -e 's/^.//')";
exit_test;
if list_has lfc_short_n "${lfc_optchar}"
then
list_append lfc_result "-${lfc_optchar}";
continue;
elif list_has lfc_short_a "${lfc_optchar}"
then
if obj lfc_rest is_empty
then
if is_greater_than "$#" 0
then
### list_from_cmdline()
list_append lfc_result "-${lfc_optchar}" "$1";
shift;
continue;
else
error_user "no argument for option -${lfc_optchar}.";
fi;
else # rest is the argument
list_append lfc_result "-${lfc_optchar}" "${lfc_rest}";
lfc_rest='';
continue;
fi; # if obj lfc_rest is_empty
else
error_user "unknown option -${lfc_optchar}.";
fi; # if list_has lfc_short_n "${lfc_optchar}"
done; # while obj lfc_rest is_not_empty
;;
*)
# Here, $lfc_arg is not an option, so a file parameter.
list_append lfc_fparams "${lfc_arg}";
# Ignore the strange POSIX option handling to end option
# parsing after the first file name argument. To reuse it, do
# a `break' here if $POSIXLY_CORRECT of `bash' is not empty.
# When `bash' is called as `sh' $POSIXLY_CORRECT is set
# automatically to `y'.
;;
esac; # case "${lfc_arg}" in
done; # while is_greater_than "$#" 0
list_append lfc_result '--';
if obj lfc_fparams is_not_empty
then
lfc_result="${lfc_result} ${lfc_fparams}";
fi;
### list_from_cmdline()
if is_greater_than "$#" 0
then
list_append lfc_result "$@";
fi;
obj lfc_result echo1;
eval ${_UNSET} lfc_abbrev;
eval ${_UNSET} lfc_fparams;
eval ${_UNSET} lfc_short_a;
eval ${_UNSET} lfc_short_n;
eval ${_UNSET} lfc_long_a;
eval ${_UNSET} lfc_long_n;
eval ${_UNSET} lfc_result;
eval ${_UNSET} lfc_arg;
eval ${_UNSET} lfc_opt;
eval ${_UNSET} lfc_opt_arg;
eval ${_UNSET} lfc_opt_char;
eval ${_UNSET} lfc_with_equal;
eval ${_UNSET} lfc_rest;
eval "${return_ok}";
} # list_from_cmdline()
########################################################################
# list_from_cmdline_with_minus (<pre_name_of_opt_lists> [<cmdline_arg>...])
#
# Transform command line arguments into a normalized form with a double
# abbreviation before and after an internal `-' sign.
#
# Options, option arguments, and file parameters are identified and
# output each as a single-quoted argument of its own. Options and
# file parameters are separated by a `--' argument.
#
# Arguments: >=1
# <pre_name>: common part of a set of 4 environment variable names:
# $<pre_name>_SHORT_NA: list of short options without an arg.
# $<pre_name>_SHORT_ARG: list of short options that have an arg.
# $<pre_name>_LONG_NA: list of long options without an arg.
# $<pre_name>_LONG_ARG: list of long options that have an arg.
# <cmdline_arg>...: the arguments from a command line, such as "$@",
# the content of a variable, or direct arguments.
#
# Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
#
# Example:
# list_from_cmdline PRE -a f1 -bcarg --lon=larg --h-n f2 low larg2
# PRE_SHORT_NA="'a' 'b'"
# PRE_SHORT_ARG="'c' 'd'"
# PRE_LONG_NA="'help' 'version' 'hi-non-arg'"
# PRE_LONG_ARG="'long-arg' 'low-arg'"
# This will result in printing:
# '-a' '-b' '-c' 'arg' '--long-arg' 'larg' '--hi-non-arg' \
# '--low-arg' 'larg2' '--' 'f1' 'f2'
#
# Use this function in the following way:
# eval set x "$(list_from_cmdline_with_minus PRE_NAME "$@")";
# shift;
# while test "$1" != '--'; do
# case "$1" in
# ...
# esac;
# shift;
# done;
# shift; #skip '--'
# # all positional parameters ("$@") left are file name parameters.
#
# Variable prefix: lfcwm
#
list_from_cmdline_with_minus()
{
func_check list_from_cmdline_with_minus '>=' 1 "$@";
# short options, no argument
obj_from_output lfcwm_short_n obj_data "$1"_SHORT_NA;
# short options, with argument
obj_from_output lfcwm_short_a obj_data "$1"_SHORT_ARG;
# long options, no argument
obj_from_output lfcwm_long_n obj_data "$1"_LONG_NA;
# long options, with argument
obj_from_output lfcwm_long_a obj_data "$1"_LONG_ARG;
if obj lfcwm_short_n is_empty
then
error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
fi;
if obj lfcwm_short_a is_empty
then
error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
fi;
if obj lfcwm_long_n is_empty
then
error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
fi;
if obj lfcwm_long_a is_empty
then
error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
fi;
shift;
if is_equal "$#" 0
then
echo1 "'--'";
eval ${_UNSET} lfcwm_short_a;
eval ${_UNSET} lfcwm_short_n;
### list_from_cmdline_with_minus()
eval ${_UNSET} lfcwm_long_a;
eval ${_UNSET} lfcwm_long_n;
eval "${return_ok}";
fi;
obj_from_output lfcwm_long_both lists_combine lfcwm_long_a lfcwm_long_n;
lfcwm_fparams='';
lfcwm_result='';
while is_greater_than "$#" 0 # command line arguments
do
lfcwm_arg="$1";
shift;
lfcwm_optarg='';
case "${lfcwm_arg}" in
--)
break;
;;
--*=*)
# delete leading '--';
lfcwm_with_equal="$(echo1 "${lfcwm_arg}" | sed -e 's/^--//')";
# extract option by deleting from the first '=' to the end
lfcwm_abbrev="$(echo1 "${lfcwm_with_equal}" | \
sed -e 's/^\([^=]*\)=.*$/\1/')";
# extract option argument by deleting up to the first '='
lfcwm_optarg="$(echo1 "${lfcwm_with_equal}" | \
sed -e 's/^[^=]*=\(.*\)$/\1/')";
### list_from_cmdline_with_minus()
if list_has lfcwm_long_a "${lfcwm_abbrev}"
then
lfcwm_opt="${lfcwm_abbrev}";
else
obj_from_output lfcwm_opt \
_search_abbrev lfcwm_long_a "${lfcwm_abbrev}";
fi;
list_append lfcwm_result "--${lfcwm_opt}" "${lfcwm_optarg}";
continue;
;;
--*)
# delete leading '--';
lfcwm_abbrev="$(echo1 "${lfcwm_arg}" | sed -e 's/^--//')";
if list_has lfcwm_long_both "${lfcwm_abbrev}"
then
lfcwm_opt="${lfcwm_abbrev}";
else
obj_from_output lfcwm_opt \
_search_abbrev lfcwm_long_both "${lfcwm_abbrev}";
fi;
### list_from_cmdline_with_minus()
if list_has lfcwm_long_a "${lfcwm_opt}"
then
if is_equal "$#" 0
then
error_user "Option ${lfcwm_opt} needs an argument.";
fi;
lfcwm_optarg="$1";
shift;
list_append lfcwm_result "--${lfcwm_opt}" "${lfcwm_optarg}";
else
list_append lfcwm_result "--${lfcwm_opt}";
fi;
continue;
;;
-?*) # short option (cluster)
# delete leading '-';
lfcwm_rest="$(echo1 "${lfcwm_arg}" | sed -e 's/^-//')";
while obj lfcwm_rest is_not_empty
do
# get next short option from cluster (first char of $lfcwm_rest)
lfcwm_optchar="$(echo1 "${lfcwm_rest}" | sed -e 's/^\(.\).*$/\1/')";
# remove first character from ${lfcwm_rest};
lfcwm_rest="$(echo1 "${lfcwm_rest}" | sed -e 's/^.//')";
if list_has lfcwm_short_n "${lfcwm_optchar}"
then
list_append lfcwm_result "-${lfcwm_optchar}";
continue;
elif list_has lfcwm_short_a "${lfcwm_optchar}"
then
if obj lfcwm_rest is_empty
then
if is_greater_than "$#" 0
then
### list_from_cmdline_with_minus()
list_append lfcwm_result "-${lfcwm_optchar}" "$1";
shift;
continue;
else
error_user "no argument for option -${lfcwm_optchar}.";
fi;
else # rest is the argument
list_append lfcwm_result "-${lfcwm_optchar}" "${lfcwm_rest}";
lfcwm_rest='';
continue;
fi; # if obj lfcwm_rest is_empty
else
error_user "unknown option -${lfcwm_optchar}.";
fi; # if list_has lfcwm_short_n "${lfcwm_optchar}"
done; # while obj lfcwm_rest is_not_empty
;;
*)
# Here, $lfcwm_arg is not an option, so a file parameter.
list_append lfcwm_fparams "${lfcwm_arg}";
# Ignore the strange POSIX option handling to end option
# parsing after the first file name argument. To reuse it, do
# a `break' here if $POSIXLY_CORRECT of `bash' is not empty.
# When `bash' is called as `sh' $POSIXLY_CORRECT is set
# automatically to `y'.
;;
esac;
done;
list_append lfcwm_result '--';
if obj lfcwm_fparams is_not_empty
then
lfcwm_result="${lfcwm_result} ${lfcwm_fparams}";
fi;
### list_from_cmdline_with_minus()
if is_greater_than "$#" 0
then
list_append lfcwm_result "$@";
fi;
obj lfcwm_result echo1;
eval ${_UNSET} lfcwm_abbrev;
eval ${_UNSET} lfcwm_fparams;
eval ${_UNSET} lfcwm_short_a;
eval ${_UNSET} lfcwm_short_n;
eval ${_UNSET} lfcwm_long_a;
eval ${_UNSET} lfcwm_long_both;
eval ${_UNSET} lfcwm_long_n;
eval ${_UNSET} lfcwm_result;
eval ${_UNSET} lfcwm_arg;
eval ${_UNSET} lfcwm_opt;
eval ${_UNSET} lfcwm_optarg;
eval ${_UNSET} lfcwm_optchar;
eval ${_UNSET} lfcwm_with_equal;
eval ${_UNSET} lfcwm_rest;
eval "${return_ok}";
} # list_from_cmdline_with_minus()
# _search_abbrev (<list> <abbrev>)
#
# Check whether <list> has an element constructed from the abbreviation
# <abbrev>. All `-' in <abbrev> are replaced by `-*'. This construction
# is searched first with `<construction>[^-]*'. If there is more than a
# single element an error is created. If none is found `<construction>*'
# is searched. Again an error is created for several results.
# This function was constructed from the former function
# list_single_from_abbrev().
#
# This is a local function of list_from_cmdline_with_minus().
#
# Arguments: 2
# <list>: a variable name for a list of single-quoted elements
# <abbrev>: some sequence of characters.
#
# Output: the found element (always not empty), error when none found.
#
# Variable prefix: _sa
#
_search_abbrev()
{
func_check _search_abbrev '=' 2 "$@";
eval _sa_list='"${'$1'}"';
if obj _sa_list is_empty
then
error "_search_abbrev(): list is empty.";
fi;
_sa_abbrev="$2";
if obj _sa_abbrev is_empty
then
error "_search_abbrev(): abbreviation argument is empty.";
fi;
_sa_case="$(echo1 "${_sa_abbrev}" | sed -e 's/-/\*-/g')";
_sa_opt='';
case " ${_sa_list}" in
*\ \'${_sa_case}*) # list has the abbreviation
_sa_m1='';
_sa_m2='';
_sa_nm='';
eval set x "${_sa_list}";
shift;
for i # over the option list
do
_sa_i="$i";
### _search_abbrev() of list_from_cmdline_with_minus()
case "${_sa_i}" in
${_sa_case}*-*)
if obj _sa_m1 is_empty
then
_sa_m1="${_sa_i}";
continue;
fi;
_sa_m2="${_sa_i}";
continue;
;;
${_sa_case}*)
if obj _sa_nm is_empty
then
_sa_nm="${_sa_i}";
continue;
fi;
error_user "The abbreviation --${_sa_abbrev} has multiple options "\
"--${_sa_nm} and --${_sa_i}.";
;;
esac;
done;
if obj _sa_nm is_empty
then
if obj _sa_m2 is_not_empty
then
error_user "The abbreviation --${_sa_abbrev} has multiple options "\
"--${_sa_m1} and --${_sa_m2}.";
fi;
### _search_abbrev() of list_from_cmdline_with_minus()
if obj _sa_m1 is_not_empty
then
_sa_opt="${_sa_m1}";
fi;
else
_sa_opt="${_sa_nm}";
fi;
;;
esac;
if obj _sa_opt is_empty
then
error_user "--${_sa_abbrev} is not an option.";
fi;
obj _sa_opt echo1;
eval "${_UNSET}" _sa_abbrev;
eval "${_UNSET}" _sa_case;
eval "${_UNSET}" _sa_i;
eval "${_UNSET}" _sa_list;
eval "${_UNSET}" _sa_m1;
eval "${_UNSET}" _sa_m2;
eval "${_UNSET}" _sa_nm;
eval "${_UNSET}" _sa_opt;
eval "${return_ok}";
} # _search_abbrev() of list_from_cmdline_with_minus()
########################################################################
# list_from_file (<list_name> <file_name>)
#
# Extrect the lines from <file_name> and store them as elements to list
# <list_name>.
#
# Arguments: 2
# <list_name>: a variable name for output, a list of single-quoted elts
# <file_name>: the name of an existing file
#
# Variable prefix: lff
#
list_from_file()
{
func_check list_from_file '=' 2 "$@";
if is_not_file "$2"
then
eval "${return_bad}";
fi;
lff_n="$(wc -l "$2" | eval sed -e "'s/^[ ${_TAB}]*\([0-9]\+\).*$/\1/'")";
eval "$1"="''";
if obj lff_n is_equal 0
then
eval "${return_good}";
fi;
lff_i=0;
while obj lff_i is_not_equal "${lff_n}"
do
lff_i="$(expr "${lff_i}" + 1)";
list_append "$1" "$(eval sed -n -e "'${lff_i}p
${lff_i}q'" "'$2'")";
done;
eval "${_UNSET}" lff_i;
eval "${_UNSET}" lff_n;
eval "${return_good}";
} # list_from_file()
########################################################################
# list_from_split (<string> <separator_char>)
#
# Split <string> by <separator_char> into a list, omitting the separator.
#
# Arguments: 2: a <string> that is to be split into parts divided by
# character <separator_char>
# Output: the resulting list string
#
# Variable prefix: lfs
#
list_from_split()
{
func_check list_from_split = 2 "$@";
if is_empty "$1"
then
eval "${return_ok}";
fi;
case "$2" in
?)
lfs_splitter="$2";
;;
'\:')
lfs_splitter=':';
;;
*)
error "list_from_split(): split argument $2 must be a single character.";
;;
esac;
lfs_list='';
lfs_rest="$1";
while :
do
case "${lfs_rest}" in
*${lfs_splitter}*)
case "${lfs_splitter}" in
/)
lfs_elt="$(echo1 ${lfs_rest} | sed -e \
's|^\([^'"${lfs_splitter}"']*\)'"${lfs_splitter}"'.*|\1|')";
lfs_rest="$(echo1 ${lfs_rest} | sed -e \
's|^[^'"${lfs_splitter}"']*'"${lfs_splitter}"'\(.*\)$|\1|')";
;;
*)
### list_from_split()
lfs_elt="$(echo1 ${lfs_rest} | sed -e \
's/^\([^'"${lfs_splitter}"']*\)'"${lfs_splitter}"'.*/\1/')";
lfs_rest="$(echo1 ${lfs_rest} | sed -e \
's/^[^'"${lfs_splitter}"']*'"${lfs_splitter}"'\(.*\)$/\1/')";
;;
esac;
list_append lfs_list "${lfs_elt}"
continue;
;;
*)
list_append lfs_list "${lfs_rest}"
break
;;
esac;
done
echo1 "${lfs_list}";
eval ${_UNSET} lfs_elt;
eval ${_UNSET} lfs_list;
eval ${_UNSET} lfs_rest;
eval ${_UNSET} lfs_splitter;
eval "${return_ok}";
} # list_from_split()
########################################################################
# list_has (<list-name> <element>)
#
# Test whether the list <list-name> has the element <element>.
#
# Arguments: 2
# <list_name>: a variable name for a list of single-quoted elements
# <element>: some sequence of characters.
#
# Variable prefix: lh
#
list_has()
{
func_check list_has = 2 "$@";
eval lh_list='"${'$1'}"';
if obj lh_list is_empty
then
eval "${_UNSET}" lh_list;
eval "${return_no}";
fi;
case "$2" in
\'*\') lh_element=" $2 "; ;;
*) lh_element=" '$2' "; ;;
esac;
if string_contains " ${lh_list} " "${lh_element}"
then
eval "${_UNSET}" lh_list;
eval "${_UNSET}" lh_element;
eval "${return_yes}";
else
eval "${_UNSET}" lh_list;
eval "${_UNSET}" lh_element;
eval "${return_no}";
fi;
} # list_has()
########################################################################
# list_has_abbrev (<list_var> <abbrev>)
#
# Test whether the list of <list_var> has an element starting with
# <abbrev>.
#
# Arguments: 2
# <list_var>: a variable name for a list of single-quoted elements
# <abbrev>: some sequence of characters.
#
# Variable prefix: lha
#
list_has_abbrev()
{
func_check list_has_abbrev '=' 2 "$@";
eval lha_list='"${'$1'}"';
if obj lha_list is_empty
then
eval "${_UNSET}" lha_list;
eval "${return_no}";
fi;
case "$2" in
\'*)
lha_element="$(echo1 "$2" | sed -e 's/'"${_SQ}"'$//')";
;;
*)
lha_element="'$2";
;;
esac;
if string_contains " ${lha_list}" " ${lha_element}"
then
eval "${_UNSET}" lha_list;
eval "${_UNSET}" lha_element;
eval "${return_yes}";
else
eval "${_UNSET}" lha_list;
eval "${_UNSET}" lha_element;
eval "${return_no}";
fi;
eval "${return_ok}";
} # list_has_abbrev()
########################################################################
# list_has_not (<list> <element>)
#
# Test whether <list> has no <element>.
#
# Arguments: 2
# <list>: a space-separated list of single-quoted elements.
# <element>: some sequence of characters.
#
# Variable prefix: lhn
#
list_has_not()
{
func_check list_has_not = 2 "$@";
eval lhn_list='"${'$1'}"';
if obj lhn_list is_empty
then
eval "${_UNSET}" lhn_list;
eval "${return_yes}";
fi;
case "$2" in
\'*\') lhn_element=" $2 "; ;;
*) lhn_element=" '$2' "; ;;
esac;
if string_contains " ${lhn_list} " "${lhn_element}"
then
eval "${_UNSET}" lhn_list;
eval "${_UNSET}" lhn_element;
eval "${return_no}";
else
eval "${_UNSET}" lhn_list;
eval "${_UNSET}" lhn_element;
eval "${return_yes}";
fi;
} # list_has_not()
########################################################################
# list_single_from_abbrev (<list-var> <abbrev>)
#
# Check whether the list has an element starting with <abbrev>. If
# there are more than a single element an error is raised.
#
# Arguments: 2
# <list-var>: a variable name for a list of single-quoted elements
# <abbrev>: some sequence of characters.
#
# Output: the found element.
#
# Variable prefix: lsfa
#
list_single_from_abbrev()
{
func_check list_single_from_abbrev '=' 2 "$@";
eval lsfa_list='"${'$1'}"';
if obj lsfa_list is_empty
then
eval "${_UNSET}" lsfa_list;
eval "${return_no}";
fi;
lsfa_abbrev="$2";
if list_has lsfa_list "${lsfa_abbrev}"
then
obj lsfa_abbrev echo1;
eval "${_UNSET}" lsfa_abbrev;
eval "${_UNSET}" lsfa_list;
eval "${return_yes}";
fi;
if list_has_abbrev lsfa_list "${lsfa_abbrev}"
then
lsfa_element='';
eval set x "${lsfa_list}";
shift;
### list_single_from_abbrev()
for i
do
case "$i" in
${lsfa_abbrev}*)
if obj lsfa_element is_not_empty
then
error_user "The abbreviation --${lsfa_abbrev} \
has multiple options: --${lsfa_element} and --${i}.";
fi;
lsfa_element="$i";
;;
esac;
done;
obj lsfa_element echo1;
eval "${_UNSET}" lsfa_abbrev;
eval "${_UNSET}" lsfa_element;
eval "${_UNSET}" lsfa_list;
eval "${return_yes}";
else
eval "${_UNSET}" lsfa_abbrev;
eval "${_UNSET}" lsfa_element;
eval "${_UNSET}" lsfa_list;
eval "${return_no}";
fi;
} # list_single_from_abbrev()
########################################################################
# list_uniq (<list>)
#
# Generate a list with only unique elements.
#
# Output: the corrected list
#
# Variable prefix: lu
#
list_uniq()
{
func_check list_uniq '=' 1 "$@";
if is_empty "$1"
then
eval "${return_ok}";
fi;
eval a='"${'"$1"'}"';
if obj a is_empty
then
eval "${return_ok}";
fi;
eval set x "$a";
shift;
lu_list='';
for i
do
lu_i="$i";
if list_has lu_list "${lu_i}"
then
continue;
else
list_append lu_list ${lu_i};
fi;
done;
obj lu_list echo1;
eval "${_UNSET}" lu_i;
eval "${_UNSET}" lu_list;
eval "${return_ok}";
} # list_uniq()
########################################################################
# lists_combine (<list1> <list2> ...)
#
# Combine several lists to a single list. All arguments are list names.
#
# Output: the combined list
#
# Variable prefix: lc
#
lists_combine()
{
func_check lists_combine '>=' 2 "$@";
lc_list='';
for i
do
eval lc_arg='"${'"$i"'}"';
case "${lc_arg}" in
'') :; ;;
"'"*"'")
if obj lc_list is_empty
then
lc_list="${lc_arg}";
else
lc_list="${lc_list} ${lc_arg}";
fi;
;;
*)
error 'lists_combine(): $'"$i"' is not a list.';
;;
esac;
done;
obj lc_list echo1;
eval "${_UNSET}" lc_arg;
eval "${_UNSET}" lc_list;
eval "${return_ok}";
} # lists_combine()
########################################################################
landmark '7: man_*()';
########################################################################
########################################################################
# Information on the search of man pages in groffer
# The search of man pages is based on a set of directories. That
# starts with the so-called man path. This is determined in function
# man_setup() either by the command-line option --manpath, by $MANOPT,
# or by $MANPATH. There is also a program `manpath'. If all of this
# does not work a man path is created from $PATH with function
# manpath_set_from_path(). We now have a set of existing directories
# for the search of man pages; usually they end with `/man'.
# The directory set of the man path can be changed in 2 ways. If
# operating system names are given in $SYSTEM or by --systems on the
# command-line all man path directory will be appended by these names.
# The appended system names replace the original man path; but if no
# system name is set, the original man path is kept. In `groffer',
# this is done by the function manpath_add_lang_sys() in man_setup().
# The next addition for directories is the language. It is specified
# by --locale or by one of the environment variables $LC_ALL,
# $LC_MESSAGES, and $LANG. The language name of `C' or `POSIX' means
# the return to the default language (usually English); this deletes
# former language specifications. The language name and its
# abbreviation with 2 characters is appended to the man page
# directories. But these new arising directories are added to the man
# page, they do not replace it such as the system names did. This is
# done by function manpath_add_lang_sys() in man_setup() as well.
# Now we have the basic set of directories for the search of man pages
# for given filespec arguments. The real directories with the man
# page source files are gotten by appending `man<section>' to each
# directory, where section is a single character of the form
# `[1-9on]'.
# There you find files named according to the form
# <name>.<section>[<extension>][<compression>], where `[]' means
# optional this time. <name> is the name of the man page; <section>
# is the single character from the last paragraphe; the optional
# <extension> consists of some letters denoting special aspects for
# the section; and the optional <compression> is something like `.gz',
# `.Z', or `.bz2', meaning that the file is compressed.
# If name, section. and extension are specified on the command-line
# the file of the form <name>.<section><extension> with or without
# <compression> are handled. The first one found according to the
# directory set for the section is shown.
# If just name and section are specified on the command-line then
# first <name>.<section> with or without <compression> are searched.
# If no matching file was found, <name>.<section><extension> with or
# without <compression> are searched for all possible extensions.
# If only name is specified on the command-line then the section
# directories are searched by and by, starting with section `1', until
# a file is matched.
# The function man_is_man() determines all suitable man files for a
# command-line argument, while man_get() searches the single matching
# file for display.
########################################################################
# man_get (<man-name> [<section> [<extension>]])
#
# Write a man page to the temporary file.
#
# Globals in: $_TMP_MANSPEC, $_MAN_SEC_CHARS, $_MAN_EXT, $_MAN_ALL
#
# Arguments: 1, 2, or 3
#
# Variable prefix: mg
#
man_get()
{
func_check man_get '>=' 1 "$@";
if obj _TMP_MANSPEC is_empty
then
error 'man_get(): man_is_man() must be run first on '"$*".;
fi;
mg_name="$1";
mg_sec="$2";
if is_empty "$2"
then
mg_sec="${_MAN_SEC_CHARS}"; # take care it is not a single section
fi;
mg_ext="$3";
if is_empty "$3"
then
mg_ext="${_MAN_EXT}";
fi;
if obj _TMP_MANSPEC is_not_equal "${_TMP_DIR}/,man:$1:${mg_sec}${mg_ext}"
then
error 'man_get(): $_TMP_MANSPEC does not suit to the arguments '"$*".;
fi;
### man_get()
if obj _MAN_ALL is_yes
then
list_from_file mg_list "${_TMP_MANSPEC}";
eval set x ${mg_list};
shift;
mg_ok='no';
mg_list='';
for f
do
mg_f="$f";
if list_has mg_list "${mg_f}"
then
continue;
else
list_append mg_list "${mg_f}";
fi;
### man_get()
if obj mg_f is_file
then
to_tmp "${mg_f}" && mg_ok='yes';
fi;
done;
if obj mg_ok is_yes
then
register_title man:"${mg_name}";
fi;
eval ${_UNSET} mg_ext;
eval ${_UNSET} mg_f;
eval ${_UNSET} mg_list;
eval ${_UNSET} mg_name;
eval ${_UNSET} mg_sec;
eval "${return_ok}";
else # $_MAN_ALL is not 'yes'
if is_empty "$2"
then # no section from command line
if obj _MAN_SEC_LIST is_empty
then
m="${_MAN_AUTO_SEC_LIST}"; # list of all sections
else
m="${_MAN_SEC_LIST}"; # from --sections
fi;
### man_get()
for s in $(eval set x $m; shift; echo1 "$@")
do
mg_s="$s";
list_from_file mg_list "${_TMP_MANSPEC}";
eval set x ${mg_list};
shift;
if obj mg_ext is_empty
then
for f
do
mg_f="$f";
case "${mg_f}" in
*/man"${mg_s}"/"${mg_name}"."${mg_s}"|*/man"${mg_s}"/"${mg_name}"."${mg_s}".*)
if obj mg_f is_file
then
to_tmp "${mg_f}" && register_title "${mg_name}(${mg_s})";
eval ${_UNSET} mg_ext;
eval ${_UNSET} mg_f;
eval ${_UNSET} mg_list;
eval ${_UNSET} mg_name;
eval ${_UNSET} mg_s;
eval ${_UNSET} mg_sec;
eval "${return_ok}";
fi;
;;
esac; # "$mg_f"
done; # for f
fi; # mg_ext is_empty
### man_get()
for f
do
mg_f="$f";
case "${mg_f}" in
*/man"${mg_s}"/"${mg_name}"."${mg_s}""${mg_ext}"*)
if obj mg_f is_file
then
to_tmp "${mg_f}" && register_title "${mg_name}(${mg_s})";
eval ${_UNSET} mg_ext;
eval ${_UNSET} mg_f;
eval ${_UNSET} mg_list;
eval ${_UNSET} mg_name;
eval ${_UNSET} mg_s;
eval ${_UNSET} mg_sec;
eval "${return_ok}";
fi;
;;
esac; # "$mg_f"
done; # for f
done; # for s
else # $mg_sec is not empty, do with section
list_from_file mg_list "${_TMP_MANSPEC}";
eval set x ${mg_list};
shift;
if obj mg_ext is_empty
then
for f
do
mg_f="$f";
### man_get()
case "${mg_f}" in
*/man"${mg_sec}"/"${mg_name}"."${mg_sec}"|\
*/man"${mg_sec}"/"${mg_name}"."${mg_sec}".*)
if obj mg_f is_file
then
obj mg_f to_tmp && \
register_title "${mg_name}(${mg_sec})";
eval ${_UNSET} mg_ext;
eval ${_UNSET} mg_f;
eval ${_UNSET} mg_list;
eval ${_UNSET} mg_name;
eval ${_UNSET} mg_s;
eval ${_UNSET} mg_sec;
eval "${return_ok}";
fi;
;;
esac;
done; # for f
for f
do
mg_f="$f";
### man_get()
case "${mg_f}" in
*/man"${mg_sec}"/"${mg_name}"."${mg_sec}"*)
if obj mg_f is_file
then
obj mg_f to_tmp && \
register_title "${mg_name}(${mg_sec})";
eval ${_UNSET} mg_ext;
eval ${_UNSET} mg_f;
eval ${_UNSET} mg_list;
eval ${_UNSET} mg_name;
eval ${_UNSET} mg_s;
eval ${_UNSET} mg_sec;
eval "${return_ok}";
fi;
;;
esac;
done; # for f
else # mg_ext is not empty
for f
do
mg_f="$f";
### man_get()
case "${mg_f}" in
*/man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}"|\
*/man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}".*)
if obj mg_f is_file
then
obj mg_f to_tmp && \
register_title "${mg_name}(${mg_sec}${mg_ext})";
eval ${_UNSET} mg_ext;
eval ${_UNSET} mg_f;
eval ${_UNSET} mg_list;
eval ${_UNSET} mg_name;
eval ${_UNSET} mg_s;
eval ${_UNSET} mg_sec;
eval "${return_ok}";
fi;
;;
esac;
done; # for f
for f
do
mg_f="$f";
### man_get()
case "${mg_f}" in
*/man"${mg_sec}"/"${mg_name}"."${mg_sec}""${mg_ext}"*)
if obj mg_f is_file
then
obj mg_f to_tmp && \
register_title "${mg_name}(${mg_sec}${mg_ext})";
eval ${_UNSET} mg_ext;
eval ${_UNSET} mg_f;
eval ${_UNSET} mg_list;
eval ${_UNSET} mg_name;
eval ${_UNSET} mg_s;
eval ${_UNSET} mg_sec;
eval "${return_ok}";
fi;
;;
esac;
done; # for f
fi;
fi; # $mg_sec
fi; # $_MAN_ALL
eval ${_UNSET} mg_ext;
eval ${_UNSET} mg_f;
eval ${_UNSET} mg_list;
eval ${_UNSET} mg_name;
eval ${_UNSET} mg_sec;
eval ${_UNSET} mg_s;
eval "${return_ok}";
} # man_get()
########################################################################
# man_is_man (<man-name> [<section> [<extension>]])
#
# Test whether <man-name> exists as man page.
#
# Globals: in: $_TMP_MAN, $_MAN_SEC_CHARS, $_TMP_DIR, $_MAN_EXT,
# $_MAN_AUTO_SEC_CHARS
# out: $_TMP_MANSPEC
#
# Arguments: 1, 2, or 3
#
# Variable prefix: mim
#
man_is_man()
{
func_check man_is_man '>=' 1 "$@";
if is_empty "$1"
then
_TMP_MANSPEC='';
eval "${return_no}";
fi;
if obj _TMP_DIR is_empty
then
error 'man_is_man(): main_init() must be run first.';
fi;
if obj _MAN_IS_SETUP is_not_yes
then
error 'man_is_man(): man_setup() must be run first.';
fi;
mim_sec="$2";
if is_empty "$2"
then
mim_sec="${_MAN_SEC_CHARS}";
fi;
if is_empty "$3"
then
mim_ext="${_MAN_EXT}";
else
mim_ext="$3";
fi;
_TMP_MANSPEC="${_TMP_DIR}/,man:$1:${mim_sec}${mim_ext}";
### man_is_man()
if obj _TMP_MANSPEC is_not_file
then
if obj mim_sec is_empty
then
m="${_MAN_AUTO_SEC_CHARS}";
eval grep "'/man$m/$1\.$m${mim_ext}'" \
"${_TMP_MAN}" > "${_TMP_MANSPEC}";
else
eval grep "'/man${mim_sec}/$1\.${mim_sec}${mim_ext}'" \
"${_TMP_MAN}" > "${_TMP_MANSPEC}";
fi;
fi;
eval ${_UNSET} mim_ext;
eval ${_UNSET} mim_sec;
if obj _TMP_MANSPEC is_empty_file
then
rm_file_with_debug "${_TMP_MANSPEC}";
eval "${return_no}";
else
eval "${return_yes}";
fi;
} # man_is_man()
########################################################################
# man_setup ()
#
# Setup the variables $_MAN_* needed for man page searching.
#
# Globals:
# in: $_OPT_*, $_MANOPT_*, $LANG, $LC_MESSAGES, $LC_ALL,
# $MANPATH, $MANSEC, $PAGER, $SYSTEM, $MANOPT.
# out: $_MAN_PATH, $_MAN_LANG, $_MAN_SYS, $_MAN_LANG, $_MAN_LANG2,
# $_MAN_SEC, $_MAN_ALL, $_TMP_MAN
# in/out: $_MAN_ENABLE
#
# The precedence for the variables related to `man' is that of GNU
# `man', i.e.
#
# $LANG; overridden by
# $LC_MESSAGES; overridden by
# $LC_ALL; this has the same precedence as
# $MANPATH, $MANSEC, $PAGER, $SYSTEM; overridden by
# $MANOPT; overridden by
# the groffer command line options.
#
# $MANROFFSEQ is ignored because grog determines the preprocessors.
#
# Variable prefix: ms
#
man_setup()
{
func_check man_setup '=' 0 "$@";
if obj _MAN_IS_SETUP is_yes
then
eval "${return_ok}";
fi;
_MAN_IS_SETUP='yes';
if obj _MAN_ENABLE is_not_yes
then
eval "${return_ok}";
fi;
# determine basic path for man pages
obj_from_output ms_path \
get_first_essential "${_OPT_MANPATH}" "${_MANOPT_PATH}" "${MANPATH}";
if obj ms_path is_empty && is_prog 'manpath'
then
obj_from_output ms_path manpath 2>${_NULL_DEV}; # not always available
fi;
if obj ms_path is_empty
then
manpath_set_from_path;
else
obj_from_output _MAN_PATH path_list "${ms_path}";
fi;
if obj _MAN_PATH is_empty
then
_MAN_ENABLE="no";
echo2 "man_setup(): man path is empty";
eval ${_UNSET} ms_path;
eval "${return_ok}";
fi;
obj_from_output _MAN_PATH list_uniq _MAN_PATH;
### man_setup()
if obj _MAN_ALL is_not_yes
then
if obj _OPT_ALL is_yes || obj _MANOPT_ALL is_yes
then
_MAN_ALL='yes';
else
_MAN_ALL='no';
fi;
fi;
ms_sys="$(get_first_essential \
"${_OPT_SYSTEMS}" "${_MANOPT_SYS}" "${SYSTEM}")";
if obj ms_sys is_not_empty
then
obj_from_output _MAN_SYS list_from_split "${ms_sys}" ',';
fi;
obj_from_output ms_lang get_first_essential \
"${_OPT_LANG}" "${LC_ALL}" "${LC_MESSAGES}" "${LANG}";
case "${ms_lang}" in
C|POSIX)
_MAN_LANG="";
_MAN_LANG2="";
;;
?)
_MAN_LANG="${ms_lang}";
_MAN_LANG2="";
;;
??)
_MAN_LANG="${ms_lang}";
_MAN_LANG2="${ms_lang}";
;;
### man_setup()
*)
_MAN_LANG="${ms_lang}";
# get first two characters of $ms_lang
_MAN_LANG2="$(echo1 "${ms_lang}" | sed -e 's/^\(..\).*$/\1/')";
exit_test;
;;
esac;
# from now on, use only $_MAN_LANG*, forget about $_OPT_LANG, $LC_*.
manpath_add_lang_sys;
obj_from_output _MAN_PATH list_uniq _MAN_PATH;
obj_from_output _MAN_SEC get_first_essential \
"${_OPT_SECTIONS}" "${_MANOPT_SEC}" "${MANSEC}";
_MAN_SEC_LIST="";
_MAN_SEC_CHARS="";
case "${_MAN_SEC}" in
*:*)
eval set x "$(list_from_split "${_MAN_SEC}" :)";
shift;
for s
do
if list_has _MAN_AUTO_SEC_LIST "$s"
then
list_append _MAN_SEC_LIST "$s";
_MAN_SEC_CHARS="${_MAN_SEC_CHARS}$s";
fi;
done
if obj _MAN_SEC_CHARS is_not_empty
then
_MAN_SEC_CHARS="[${_MAN_SEC_CHARS}]";
fi;
;;
*)
if list_has _MAN_AUTO_SEC_LIST "${_MAN_SEC}"
then
list_append _MAN_SEC_LIST "${_MAN_SEC}";
_MAN_SEC_CHARS="[${_MAN_SEC}]";
fi;
;;
esac;
### man_setup()
obj_from_output _MAN_EXT get_first_essential \
"${_OPT_EXTENSION}" "${_MANOPT_EXTENSION}" "${EXTENSION}";
_TMP_MAN="$(tmp_create man)";
eval set x "${_MAN_PATH}";
shift;
if is_not_equal "$#" 0
then
for i
do
for j in "$i"/man*
do
find "$j" >>"${_TMP_MAN}";
done
done;
fi;
eval ${_UNSET} ms_lang;
eval ${_UNSET} ms_list;
eval ${_UNSET} ms_path;
eval ${_UNSET} ms_sys;
eval "${return_ok}";
} # man_setup()
########################################################################
landmark '8: manpath_*()';
########################################################################
########################################################################
# manpath_add_lang_sys ()
#
# Add language and operating system specific directories to man path.
#
# Arguments : 0
# Output : none
# Globals:
# in: $_MAN_SYS: a list of names of operating systems.
# $_MAN_LANG and $_MAN_LANG2: each a single name
# in/out: $_MAN_PATH: list of directories which shall have the `man?'
# subdirectories.
#
# Variable prefix: mals
#
manpath_add_lang_sys()
{
func_check manpath_add_lang_sys '=' 0 "$@";
if obj _MAN_PATH is_empty
then
eval "${return_ok}";
fi;
if obj _MAN_SYS is_empty
then
mals_mp="${_MAN_PATH}";
else
mals_mp='';
eval set x "${_MAN_SYS}";
shift;
for s
do
_manpath_add_sys "$s";
done;
fi;
if obj mals_mp is_not_empty
then
mals_lang_path='';
if is_equal "$_MAN_LANG" "$_MAN_LANG2"
then
mals_man_lang2='';
else
mals_man_lang2="${_MAN_LANG2}";
fi;
for i in "${_MAN_LANG}" "${mals_man_lang2}"
do
if obj i is_empty
then
continue;
fi;
### manpath_add_lang_sys()
mals_lang="$i";
eval set x "${mals_mp}";
shift;
for p
do
obj_from_output mals_dir dir_name_append "${p}" "${mals_lang}";
if obj mals_dir is_dir
then
list_append mals_lang_path "${mals_dir}";
fi;
done;
done;
obj_from_output mals_mp lists_combine mals_lang_path mals_mp;
fi;
_MAN_PATH="${mals_mp}";
eval ${_UNSET} mals_dir;
eval ${_UNSET} mals_lang;
eval ${_UNSET} mals_lang_path;
eval ${_UNSET} mals_man_lang2;
eval ${_UNSET} mals_mp;
eval "${return_ok}";
} # manpath_add_lang_sys()
# _manpath_add_sys (<system>)
#
# Append the existing subdirectories <system> of man path directories to
# the list $mals_mp.
#
# Local function to manpath_add_lang_sys().
#
# Argument: 1, a operating system name (for appending to a man path
# directory)
#
# Globals in: $_MAN_PATH
# Globals in/out: $mals_mp
#
# Variable prefix: _mas
#
_manpath_add_sys()
{
func_check _manpath_add_sys '=' 1 "$@";
case "$1" in
'')
:;
;;
man)
obj_from_output mals_mp lists_combine mals_mp _MAN_PATH;
;;
*)
_mas_sys="$1";
eval set x "${_MAN_PATH}";
shift;
for p
do
obj_from_output _mas_dir dir_name_append "${p}" "${_mas_sys}";
if obj _mas_dir is_dir
then
list_append mals_mp "${_mas_dir}";
fi;
done;
;;
esac;
eval ${_UNSET} _mas_dir;
eval ${_UNSET} _mas_sys;
eval "${return_ok}";
} # _manpath_add_sys() of manpath_add_lang_sys()
########################################################################
# manpath_set_from_path ()
#
# Determine basic search path for man pages from $PATH.
#
# Return: `0' if a valid man path was retrieved.
# Output: none
# Globals:
# in: $PATH
# out: $_MAN_PATH
#
# Variable prefix: msfp
#
manpath_set_from_path()
{
func_check manpath_set_from_path '=' 0 "$@";
msfp_manpath='';
# get a basic man path from $PATH
if obj PATH is_not_empty
then
# delete the final `/bin' part
p="$(echo1 "${PATH}" | sed -e 's|//*bin/*:|:|g')";
obj_from_output msfp_list path_list "$p";
# append some default directories
for b in /usr/local /usr/local /usr /usr \
/usr/X11R6 /usr/openwin \
/opt /opt/gnome /opt/kde
do
msfp_base="$b";
if list_has_not msfp_list "${msfp_base}" && obj msfp_base is_dir
then
list_append msfp_list "${msfp_base}";
fi;
done;
eval set x "${msfp_list}";
shift;
for d
do
# including empty for former `/bin'.
msfp_base="$d";
for e in /share/man /share/MAN /man /MAN
do
msfp_mandir="${msfp_base}$e";
if obj msfp_mandir is_dir
then
list_append msfp_manpath "${msfp_mandir}";
fi;
done;
done;
fi;
_MAN_PATH="${msfp_manpath}";
eval ${_UNSET} msfp_base;
eval ${_UNSET} msfp_list;
eval ${_UNSET} msfp_mandir;
eval ${_UNSET} msfp_manpath;
eval "${return_ok}";
} # manpath_set_from_path()
########################################################################
landmark '9: obj_*()';
########################################################################
########################################################################
# obj (<object> <call_name> <arg>...)
#
# This works like a method (object function) call for an object.
# Run "<call_name> $<object> <arg> ...".
#
# The first argument represents an object name whose data is given as
# first argument to <call_name>().
#
# Argument: >=2
# <object>: variable name
# <call_name>: a program or function name
#
# Variable prefix: o
#
obj()
{
func_check obj '>=' 2 "$@";
eval o_arg1='"${'$1'}"';
if is_empty "$2"
then
error "obj(): function name is empty."
else
o_func="$2";
fi;
shift;
shift;
eval "${o_func}"' "${o_arg1}" "$@"';
n="$?";
eval ${_UNSET} o_arg1;
eval ${_UNSET} o_func;
eval "${return_var} $n";
} # obj()
########################################################################
# obj_data (<object>)
#
# Print the data of <object>, i.e. the content of $<object>.
# For possible later extensions.
#
# Arguments: 1
# <object>: a variable name
# Output: the data of <object>
#
# Variable prefix: od
#
obj_data()
{
func_check obj_data '=' 1 "$@";
if is_empty "$1"
then
error "obj_data(): object name is empty."
fi;
eval od_res='"${'"$1"'}"';
obj od_res echo1;
eval ${_UNSET} od_res;
eval "${return_ok}";
} # obj_data()
########################################################################
# obj_from_output (<object> <call_name> <arg>...)
#
# Run '$<object>="$(<call_name> <arg>...)"' to set the result of a
# function call to a global variable. Variables are not stored.
#
# Arguments: >=2
# <object>: a variable name
# <call_name>: the name of a function or program
# <arg>: optional argument to <call_name>
# Output: none
#
# Variable prefix: ofo
#
obj_from_output()
{
func_check obj_from_output '>=' 2 "$@";
if is_empty "$1"
then
error "obj_from_output(): variable name is empty.";
fi;
if is_empty "$2"
then
error "obj_from_output(): function name is empty."
fi;
ofo_result_name="$1";
shift;
ofo_return=0;
if is_equal "$#" 0
then
eval "${ofo_result_name}"'=""';
else
ofo_list='';
for i
do
list_append ofo_list "$i";
done;
eval "${ofo_result_name}"'="$('"${ofo_list}"')"';
ofo_return="$?";
exit_test;
fi;
r="${ofo_return}";
eval ${_UNSET} ofo_list;
eval ${_UNSET} ofo_return;
eval ${_UNSET} ofo_result_name;
eval "${return_var} $r";
} # obj_from_output()
########################################################################
# obj_set (<object> <data>)
#
# Set the data of <object>, i.e. call "$<object>=<data>".
#
# Arguments: 2
# <object>: a variable name
# <data>: a string
# Output:: none
#
obj_set()
{
func_check obj_set '=' 2 "$@";
if is_empty "$1"
then
error "obj_set(): object name is empty."
fi;
eval "$1"='"$2"';
eval "${return_ok}";
} # obj_set()
########################################################################
# path_chop (<path>)
#
# Remove unnecessary colons from path.
#
# Argument: 1, a colon separated path.
# Output: path without leading, double, or trailing colons.
#
path_chop()
{
func_check path_chop = 1 "$@";
# replace multiple colons by a single colon `:'
# remove leading and trailing colons
echo1 "$1" | sed -e '
s/^:*//
s/:::*/:/g
s/:*$//
';
eval "${return_ok}";
} # path_chop()
########################################################################
# path_clean (<path>)
#
# Remove non-existing directories from a colon-separated list.
#
# Argument: 1, a colon separated path.
# Output: colon-separated list of existing directories.
#
# Variable prefix: pc
#
path_clean()
{
func_check path_clean = 1 "$@";
if is_not_equal "$#" 1
then
error 'path_clean() needs 1 argument.';
fi;
pc_arg="$1";
eval set x "$(path_list "${pc_arg}")";
exit_test;
shift;
pc_res="";
for i
do
pc_i="$i";
if obj pc_i is_not_empty \
&& obj pc_res path_not_contains "${pc_i}" \
&& obj pc_i is_dir
then
case "${pc_i}" in
?*/)
pc_res="${pc_res}:$(dir_name_chop "${pc_i}")";
exit_test;
;;
*)
pc_res="${pc_res}:${pc_i}";
;;
esac;
fi;
done;
path_chop "${pc_res}";
eval ${_UNSET} pc_arg;
eval ${_UNSET} pc_i;
eval ${_UNSET} pc_res;
eval "${return_ok}";
} # path_clean()
########################################################################
# path_contains (<path> <dir>)
#
# Test whether <dir> is contained in <path>, a list separated by `:'.
#
# Arguments : 2
# Return : `0' if arg2 is substring of arg1, `1' otherwise.
#
path_contains()
{
func_check path_contains = 2 "$@";
case ":$1:" in
*:${2}:*)
eval "${return_yes}";
;;
*)
eval "${return_no}";
;;
esac;
eval "${return_ok}";
} # path_contains()
########################################################################
# path_not_contains (<path> <dir>)
#
# Test whether <dir> is not contained in colon separated <path>.
#
# Arguments : 2
#
path_not_contains()
{
func_check path_not_contains = 2 "$@";
if path_contains "$1" "$2"
then
eval "${return_no}";
else
eval "${return_yes}";
fi;
eval "${return_ok}";
} # path_not_contains()
########################################################################
# path_list (<path>)
#
# From a `:' separated path generate a list with unique elements.
#
# Arguments: 1: a colon-separated path
# Output: the resulting list, process it with `eval set'
#
# Variable prefix: pl
#
path_list()
{
func_check path_list = 1 "$@";
eval set x "$(list_from_split "$1" '\:')";
shift;
pl_list='';
for e
do
pl_elt="$e";
if list_has pl_list "${pl_elt}"
then
continue;
else
list_append pl_list "${pl_elt}";
fi;
done;
obj pl_list echo1;
eval ${_UNSET} pl_elt;
eval ${_UNSET} pl_list;
eval "${return_ok}";
} # path_list()
########################################################################
landmark '10: register_*()';
########################################################################
########################################################################
# register_file (<filename>)
#
# Write a found file and register the title element.
#
# Arguments: 1: a file name
# Output: none
#
register_file()
{
func_check register_file = 1 "$@";
if is_empty "$1"
then
error 'register_file(): file name is empty';
fi;
if is_equal "$1" '-'
then
to_tmp "${_TMP_STDIN}" && register_title 'stdin';
else
to_tmp "$1" && register_title "$1";
exit_test;
fi;
eval "${return_ok}";
} # register_file()
########################################################################
# register_title (<filespec>)
#
# Create title element from <filespec> and append to $_REG_TITLE_LIST.
# Basename is created.
#
# Globals: $_REG_TITLE_LIST (rw)
#
# Variable prefix: rt
#
register_title()
{
func_check register_title '=' 1 "$@";
if is_empty "$1"
then
eval "${return_ok}";
fi;
if obj _DEBUG_PRINT_FILENAMES is_yes
then
if is_equal "$1" 'stdin'
then
echo2 "file: standard input";
else
if obj _FILESPEC_IS_MAN is_yes
then
echo2 "file title: $1";
else
echo2 "file: $1";
fi;
fi;
fi;
case "${_REG_TITLE_LIST}" in
*\ *\ *\ *)
eval "${return_ok}";
;;
esac;
# remove directory part
obj_from_output rt_title base_name "$1";
# replace space characters by `_'
rt_title="$(echo1 "${rt_title}" | sed -e 's/[ ]/_/g')";
# remove extension `.bz2'
rt_title="$(echo1 "${rt_title}" | sed -e 's/\.bz2$//')";
# remove extension `.gz'
rt_title="$(echo1 "${rt_title}" | sed -e 's/\.gz$//')";
# remove extension `.Z'
rt_title="$(echo1 "${rt_title}" | sed -e 's/\.Z$//')";
if obj rt_title is_empty
then
eval ${_UNSET} rt_title;
eval "${return_ok}";
fi;
list_append _REG_TITLE_LIST "${rt_title}";
eval ${_UNSET} rt_title;
eval "${return_ok}";
} # register_title()
########################################################################
# reset ()
#
# Reset the variables that can be affected by options to their default.
#
#
# Defined in section `Preset' after the rudimentary shell tests.
########################################################################
# rm_file (<file_name>)
#
# Remove file.
#
rm_file()
{
func_check rm_file '=' 1 "$@";
if is_file "$1"
then
rm -f "$1" >${_NULL_DEV} 2>&1;
fi;
if is_existing "$1"
then
eval "${return_bad}";
else
eval "${return_good}";
fi;
} # rm_file()
########################################################################
# rm_file_with_debug (<file_name>)
#
# Remove file if $_DEBUG_KEEP_FILES allows it.
#
# Globals: $_DEBUG_KEEP_FILES
#
rm_file_with_debug()
{
func_check rm_file_with_debug '=' 1 "$@";
if obj _DEBUG_KEEP_FILES is_not_yes
then
if is_file "$1"
then
rm -f "$1" >${_NULL_DEV} 2>&1;
fi;
fi;
if is_existing "$1"
then
eval "${return_bad}";
else
eval "${return_good}";
fi;
} # rm_file_with_debug()
########################################################################
# rm_tree (<dir_name>)
#
# Remove a file or a complete directory tree.
#
# Globals: $_DEBUG_KEEP_FILES
#
rm_tree()
{
func_check rm_tree '=' 1 "$@";
if is_existing "$1"
then
rm -f -r "$1" >${_NULL_DEV} 2>&1;
fi;
if is_existing "$1"
then
eval "${return_bad}";
else
eval "${return_good}";
fi;
} # rm_tree()
########################################################################
# save_stdin ()
#
# Store standard input to temporary file (with decompression).
#
# Variable prefix: ss
#
if obj _HAS_COMPRESSION is_yes
then
save_stdin()
{
func_check save_stdin '=' 0 "$@";
ss_f="${_TMP_DIR}"/INPUT;
cat >"${ss_f}";
cat_z "${ss_f}" >"${_TMP_STDIN}";
rm_file "${ss_f}";
eval ${_UNSET} ss_f;
eval "${return_ok}";
} # save_stdin()
else # no compression
save_stdin()
{
func_check save_stdin '=' 0 "$@";
cat >"${_TMP_STDIN}";
eval "${return_ok}";
} # save_stdin()
fi;
########################################################################
# special_filespec ()
#
# Handle special modes like whatis and apropos. Run their filespec
# functions if suitable.
#
# Globals: in: $_OPT_APROPOS, $_OPT_WHATIS, $_SPECIAL_SETUP
# out: $_SPECIAL_FILESPEC (internal)
#
special_filespec()
{
func_check special_filespec '=' 0 "$@";
if obj _OPT_APROPOS is_not_yes && obj _OPT_WHATIS is_not_yes
then
eval "${return_bad}";
fi;
if obj _OPT_APROPOS is_yes && obj _OPT_WHATIS is_yes
then
error \
'special_filespec(): $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
fi;
if obj _SPECIAL_SETUP is_not_yes
then
error 'special_filespec(): setup for apropos or whatis must be run first.';
fi;
if apropos_filespec || whatis_filespec;
then
eval "${return_ok}";
else
eval "${return_bad}";
fi;
} # special_filespec()
########################################################################
# special_setup ()
#
# Handle special modes like whatis and apropos. Run their setup
# functions if suitable.
#
special_setup()
{
func_check special_setup '=' 0 "$@";
if obj _OPT_APROPOS is_yes && obj _OPT_WHATIS is_yes
then
error \
'special_setup(): $_OPT_APROPOS and $_OPT_WHATIS are both "yes"';
fi;
if apropos_setup || whatis_setup
then
eval "${return_ok}";
else
eval "${return_bad}";
fi;
} # special_setup()
########################################################################
landmark '11: stack_*()';
########################################################################
########################################################################
# string_contains (<string> <part>)
#
# Test whether <part> is contained in <string>.
#
# Arguments : 2 text arguments.
# Return : `0' if arg2 is substring of arg1, `1' otherwise.
#
string_contains()
{
func_check string_contains '=' 2 "$@";
case "$1" in
*${2}*)
eval "${return_yes}";
;;
*)
eval "${return_no}";
;;
esac;
eval "${return_ok}";
} # string_contains()
########################################################################
# string_not_contains (<string> <part>)
#
# Test whether <part> is not substring of <string>.
#
# Arguments : 2 text arguments.
# Return : `0' if arg2 is substring of arg1, `1' otherwise.
#
string_not_contains()
{
func_check string_not_contains '=' 2 "$@";
if string_contains "$1" "$2"
then
eval "${return_no}";
else
eval "${return_yes}";
fi;
eval "${return_ok}";
} # string_not_contains()
########################################################################
landmark '12: tmp_*()';
########################################################################
########################################################################
# tmp_cat ()
#
# Output the temporary cat file (the concatenation of all input).
#
tmp_cat()
{
func_check tmp_cat '=' 0 "$@";
cat "${_TMP_CAT}";
eval "${return_var}" "$?";
} # tmp_cat()
########################################################################
# tmp_create (<suffix>?)
#
# Create temporary file. The generated name is `,' followed by
# <suffix>.
#
# Argument: 0 or 1
#
# Globals: $_TMP_DIR
#
# Output : name of created file
#
# Variable prefix: tc
#
tmp_create()
{
func_check tmp_create '<=' 1 "$@";
if obj _TMP_DIR is_empty || obj _TMP_DIR is_not_dir
then
error 'tmp_create(): there is no temporary directory.';
else
# the output file does not have `,' as first character, so these are
# different names from the output file.
tc_tmp="${_TMP_DIR}/,$1";
obj tc_tmp rm_file;
: >"${tc_tmp}"
obj tc_tmp echo1;
fi;
eval ${_UNSET} tc_tmp;
eval "${return_ok}";
} # tmp_create()
########################################################################
# to_tmp (<filename>)
#
# Print file (decompressed) to the temporary cat file.
#
# Variable prefix: tt
#
to_tmp()
{
func_check to_tmp '=' 1 "$@";
if obj _TMP_CAT is_empty
then
error 'to_tmp(): $_TMP_CAT is not yet set';
fi;
tt_1="$1";
tt_so_nr=0; # number for temporary `,so,*,*'
if is_file "${tt_1}"
then
tt_dir="$(dir_name "${tt_1}")";
if obj _OPT_WHATIS is_yes
then
whatis_filename "${tt_1}" >>"${_TMP_CAT}";
else
_FILE_NR="$(expr ${_FILE_NR} + 1)";
tt_file="${_TMP_DIR}/,file${_FILE_NR}";
if obj _FILESPEC_IS_MAN is_yes
then
if obj _DEBUG_PRINT_FILENAMES is_yes
then
echo2 "file: ${tt_1}";
fi;
tt_tmp="${_TMP_DIR}/,tmp";
cat_z "${tt_1}" >"${tt_file}";
grep '^\.[ ]*so[ ]' "${tt_file}" |
sed -e 's/^\.[ ]*so[ ]*//' >"${tt_tmp}";
list_from_file tt_list "${tt_tmp}";
eval set x ${tt_list};
shift;
for i in "$@"
do
tt_i="$i";
tt_so_nr="$(expr ${tt_so_nr} + 1)";
tt_sofile="${_TMP_DIR}/,so${_FILE_NR}_${tt_so_nr}";
tt_sofiles="${tt_sofiles} ${tt_sofile}";
_do_man_so "${tt_i}";
done;
rm_file "${tt_tmp}";
mv "${tt_file}" "${tt_tmp}";
cat "${tt_tmp}" | soelim -I "${tt_dir}" ${_SOELIM_R} >"${tt_file}";
for f in ${tt_sofiles}
do
rm_file_with_debug $f;
done;
rm_file "${tt_tmp}";
else # $_FILESPEC_IS_MAN ist not yes
cat_z "${tt_1}" | soelim -I "${tt_dir}" ${_SOELIM_R} >"${tt_file}";
fi;
### to_tmp()
obj_from_output tt_grog grog "${tt_file}";
case " ${tt_grog} " in
*\ -m*)
eval set x "$(echo1 " ${tt_grog} " | sed -e '
s/'"${_TAB}"'/ /g
s/ */ /g
s/ -m / -m/g
s/ -mm\([^ ]\)/ -m\1/g
')";
shift;
for i
do
tt_i="$i";
case "${tt_i}" in
-m*)
if list_has _MACRO_PACKAGES "${tt_i}"
then
case "${_MACRO_PKG}" in
'')
_MACRO_PKG="${tt_i}";
;;
${tt_i})
:;
;;
-m*)
echo2 "Ignore ${tt_1} because it needs ${tt_i} instead "\
"of ${_MACRO_PKG}."
rm_file_with_debug "${tt_file}";
eval ${_UNSET} tt_1;
eval ${_UNSET} tt_dir;
eval ${_UNSET} tt_file;
eval ${_UNSET} tt_grog;
eval ${_UNSET} tt_i;
eval ${_UNSET} tt_so_nr;
eval ${_UNSET} tt_sofile;
eval ${_UNSET} tt_sofiles;
eval ${_UNSET} tt_sofound;
eval ${_UNSET} tt_list;
eval ${_UNSET} tt_tmp;
eval "${return_bad}";
;;
### to_tmp()
*)
error \
'to_tmp(): $_MACRO_PKG does not start with -m: '"${_MACRO_PKG}";
;;
esac;
fi;
;;
esac;
done;
;;
esac;
cat "${tt_file}" >>"${_TMP_CAT}";
rm_file_with_debug "${tt_file}";
fi;
else
error "to_tmp(): could not read file \`${tt_1}'.";
fi;
eval ${_UNSET} tt_1;
eval ${_UNSET} tt_dir;
eval ${_UNSET} tt_file;
eval ${_UNSET} tt_grog;
eval ${_UNSET} tt_i;
eval ${_UNSET} tt_so_nr;
eval ${_UNSET} tt_sofile;
eval ${_UNSET} tt_sofiles;
eval ${_UNSET} tt_sofound;
eval ${_UNSET} tt_list;
eval ${_UNSET} tt_tmp;
eval "${return_ok}";
} # to_tmp()
#############
# _do_man_so (<so_arg>)
#
# Handle single .so file name for man pages.
#
# Local function to to_tmp().
#
# Globals from to_tmp(): $tt_tmp, $tt_sofile, $tt_file
# Globals: $_TMP_MAN
#
# Variable prefix: dms
#
_do_man_so() {
func_check _do_man_so '=' 1 "$@";
_dms_so="$1"; # evt. with `\ '
_dms_soname="$(echo $1 | sed -e 's/\\[ ]/ /g')"; # without `\ '
case "${_dms_soname}" in
/*) # absolute path
if test -f "${_dms_soname}"
then
eval "${return_ok}";
fi;
if test -f "${_dms_soname}"'.gz'
then
_dms_sofound="${_dms_soname}"'.gz';
elif test -f "${_dms_soname}"'.Z'
then
_dms_sofound="${_dms_soname}"'.Z';
elif test -f "${_dms_soname}"'.bz2'
then
_dms_sofound="${_dms_soname}"'.bz2';
else
eval ${_UNSET} _dms_so;
eval ${_UNSET} _dms_soname;
eval "${return_ok}";
fi;
;;
### _do_man_so() of to_tmp()
*) # relative to man path
eval grep "'/${_dms_soname}\$'" "${_TMP_MAN}" >"${tt_tmp}";
if is_empty_file "${tt_tmp}"
then
eval grep "'/${_dms_soname}.gz\$'" "${_TMP_MAN}" >"${tt_tmp}";
if is_empty_file "${tt_tmp}"
then
eval grep "'/${_dms_soname}.Z\$'" "${_TMP_MAN}" >"${tt_tmp}";
if is_empty_file "${tt_tmp}"
then
eval grep "'/${_dms_soname}.bz2\$'" "${_TMP_MAN}" >"${tt_tmp}";
fi;
fi;
fi;
if is_empty_file "${tt_tmp}"
then
eval "${return_ok}";
fi;
_dms_done='no';
list_from_file _dms_list "${tt_tmp}";
eval set x ${_dms_list};
shift;
for i
do
_dms_sofound="$i";
if obj _dms_sofound is_empty
then
continue;
fi;
_dms_done='yes';
break;
done;
### _do_man_so() of to_tmp()
if obj _dms_done is_not_yes
then
eval ${_UNSET} _dms_done;
eval ${_UNSET} _dms_sofound;
eval "${return_ok}";
fi;
;;
esac;
if obj _DEBUG_PRINT_FILENAMES is_yes
then
echo2 "file from .so: ${_dms_so}";
fi;
cat_z "${_dms_sofound}" >"${tt_sofile}";
_dms_esc="$(echo ${_dms_so} | sed -e 's/\\/\\\\/g')";
cat "${tt_file}" | eval sed -e \
"'s#^\\.[ ]*so[ ]*\(${_dms_so}\|${_dms_esc}\|${_dms_soname}\)[ ]*\$'"\
"'#.so ${tt_sofile}#'" \
>"${tt_tmp}";
rm_file "${tt_file}";
mv "${tt_tmp}" "${tt_file}";
eval ${_UNSET} _dms_done;
eval ${_UNSET} _dms_esc;
eval ${_UNSET} _dms_so;
eval ${_UNSET} _dms_sofound;
eval ${_UNSET} _dms_soname;
eval "${return_ok}";
} # _do_man_so() of to_tmp()
########################################################################
# to_tmp_line (<text>...)
#
# Print single line with <text> to the temporary cat file.
#
to_tmp_line()
{
func_check to_tmp_line '>=' 1 "$@";
if obj _TMP_CAT is_empty
then
error 'to_tmp_line(): $_TMP_CAT is not yet set';
fi;
echo1 "$*" >>"${_TMP_CAT}";
eval "${return_ok}";
} # to_tmp_line()
########################################################################
# trap_set
#
# Call function on signal 0.
#
trap_set()
{
func_check trap_set '=' 0 "$@";
trap 'clean_up' 0 2>${_NULL_DEV} || :;
eval "${return_ok}";
} # trap_set()
########################################################################
# trap_unset ()
#
# Disable trap on signal 0.
#
trap_unset()
{
func_check trap_unset '=' 0 "$@";
trap '' 0 2>${_NULL_DEV} || :;
eval "${return_ok}";
} # trap_unset()
########################################################################
# usage ()
#
# Print usage information to standard output; for groffer option --help.
#
usage()
{
func_check usage = 0 "$@";
echo;
version;
cat <<EOF
Usage: groffer [option]... [filespec]...
Display roff files, standard input, and/or Unix manual pages with a X
Window viewer or in several text modes. All input is decompressed
on-the-fly with all formats that gzip can handle.
"filespec" is one of
"filename" name of a readable file
"-" for standard input
"man:name(n)" man page "name" in section "n"
"man:name.n" man page "name" in section "n"
"man:name" man page "name" in first section found
"name(n)" man page "name" in section "n"
"name.n" man page "name" in section "n"
"n name" man page "name" in section "n"
"name" man page "name" in first section found
where `section' is a single character out of [1-9on], optionally followed
by some more letters that are called the `extension'.
-h --help print this usage message.
-T --device=name pass to groff using output device "name".
-v --version print version information.
-V display the groff execution pipe instead of formatting.
-X display with "gxditview" using groff -X.
-Z --ditroff --intermediate-output
generate groff intermediate output without
post-processing and viewing, like groff -Z.
All other short options are interpreted as "groff" formatting options.
The most important groffer long options are
--apropos=name start man's "apropos" program for "name".
--apropos-data=name
"apropos" for "name" in man's data sections 4, 5, 7.
--apropos-devel=name
"apropos" for "name" in development sections 2, 3, 9.
--apropos-progs=name
"apropos" for "name" in man's program sections 1, 6, 8.
--auto choose mode automatically from the default mode list.
--default reset all options to the default value.
--default-modes=mode1,mode2,...
set sequence of automatically tried modes.
--dvi display in a viewer for TeX device independent format.
--dvi-viewer=prog choose the viewer program for dvi mode.
--groff process like groff, disable viewing features.
--help display this helping output.
--html display in a web browser.
--html-viewer=program
choose a web browser for html mode.
--man check file parameters first whether they are man pages.
--mode=auto|dvi|groff|html|pdf|ps|source|text|tty|www|x|X
choose display mode.
--no-man disable man-page facility.
--no-special disable --all, --apropos*, and --whatis
--pager=program preset the paging program for tty mode.
--pdf display in a PDF viewer.
--pdf-viewer=prog choose the viewer program for pdf mode.
--ps display in a Postscript viewer.
--ps-viewer=prog choose the viewer program for ps mode.
--shell=program specify a shell under which to run groffer2.sh.
--source output as roff source.
--text output in a text device without a pager.
--to-stdout output the content of the mode file without display.
--tty display with a pager on text terminal even when in X.
--tty-viewer=prog select a pager for tty mode; same as --pager.
--whatis display the file name and description of man pages
--www same as --html.
--www-viewer=prog same as --html-viewer
--x --X display with "gxditview" using an X* device.
--x-viewer=prog choose viewer program for x mode (X mode).
--X-viewer=prog same as "--xviewer".
The usual X Windows toolkit options transformed into GNU long options:
--background=color, --bd=size, --bg=color, --bordercolor=color,
--borderwidth=size, --bw=size, --display=Xdisplay, --fg=color,
--fn=font, --font=font, --foreground=color, --geometry=geom, --iconic,
--resolution=dpi, --rv, --title=text, --xrm=resource
Long options of GNU "man":
--all, --ascii, --ditroff, --extension=suffix, --locale=language,
--local-file=name, --location, --manpath=dir1:dir2:...,
--sections=s1:s2:..., --systems=s1,s2,..., --where, ...
Development options that are not useful for normal usage:
--debug, --debug-all, --debug-filenames, --debug-func, --debug-not-func,
--debug-keep, --debug-lm, --debug-params, --debug-shell, --debug-stacks,
--debug-tmpdir, --debug-user, --do-nothing, --print=text, --shell=prog
EOF
eval "${return_ok}";
} # usage()
########################################################################
# version ()
#
# Print version information to standard output.
# For groffer option --version.
#
version()
{
func_check version = 0 "$@";
y="$(echo "${_LAST_UPDATE}" | sed -e 's/^.* //')";
cat <<EOF
groffer ${_PROGRAM_VERSION} of ${_LAST_UPDATE} (shell version)
is part of groff version ${_GROFF_VERSION}.
Copyright (C) $y Free Software Foundation, Inc.
GNU groff and groffer come with ABSOLUTELY NO WARRANTY.
You may redistribute copies of groff and its subprograms
under the terms of the GNU General Public License.
EOF
eval "${return_ok}";
} # version()
########################################################################
# warning (<string>)
#
# Print warning to stderr.
#
warning()
{
echo2 "warning: $*";
} # warning()
########################################################################
# whatis_filename (<filename>)
#
# Interpret <filename> as a man page and display its `whatis'
# information as a fragment written in the groff language.
#
# Globals: in: $_OPT_WHATIS, $_SPECIAL_SETUP, $_SPECIAL_FILESPEC,
# $_FILESPEC_ARG
#
# Variable prefix: wf
#
whatis_filename()
{
func_check whatis_filename = 1 "$@";
if obj _OPT_WHATIS is_not_yes
then
error 'whatis_filename(): $_OPT_WHATIS is not yes.';
fi;
if obj _SPECIAL_SETUP is_not_yes
then
error \
'whatis_filename(): setup for whatis whatis_setup() must be run first.';
fi;
if obj _SPECIAL_FILESPEC is_not_yes
then
error 'whatis_filename(): whatis_filespec() must be run first.';
fi;
wf_arg="$1";
if obj wf_arg is_not_file
then
error "whatis_filename(): argument is not a readable file."
fi;
wf_dot='^\.'"${_SPACE_SED}"'*';
### whatis_filename()
if obj _FILESPEC_ARG is_equal '-'
then
wf_arg='stdin';
fi;
cat <<EOF
\f[CR]${wf_arg}\f[]:
.br
EOF
# get the parts of the file name
wf_name="$(base_name $1)";
wf_section="$(echo1 $1 | sed -n -e '
s|^.*/man\('"${_MAN_AUTO_SEC_CHARS}"'\).*$|\1|p
')";
if obj wf_section is_not_empty
then
case "${wf_name}" in
*.${wf_section}*)
s='yes';
;;
*)
s='';
wf_section='';
;;
### whatis_filename()
esac
if obj s is_yes
then
wf_name="$(echo1 ${wf_name} | sed -e '
s/^\(.*\)\.'${wf_section}'.*$/\1/
')";
fi;
fi;
# traditional man style; grep the line containing `.TH' macro, if any
wf_res="$(cat_z "$1" | sed -e '
/'"${wf_dot}"'TH /p
d
')";
exit_test;
if obj wf_res is_not_empty
then # traditional man style
# get the first line after the first `.SH' macro, by
# - delete up to first .SH;
# - print all lines before the next .SH;
# - quit.
wf_res="$(cat_z "$1" | sed -n -e '
1,/'"${wf_dot}"'SH/d
/'"${wf_dot}"'SH/q
p
')";
if obj wf_section is_not_empty
then
case "${wf_res}" in
${wf_name}${_SPACE_CASE}*-${_SPACE_CASE}*)
s='yes';
;;
### whatis_filename()
*)
s='';
;;
esac;
if obj s is_yes
then
wf_res="$(obj wf_res echo1 | sed -e '
s/^'"${wf_name}${_SPACE_SED}"'[^-]*-'"${_SPACE_SED}"'*\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/
')";
fi;
fi;
obj wf_res echo1;
echo;
eval ${_UNSET} wf_arg;
eval ${_UNSET} wf_dot;
eval ${_UNSET} wf_name;
eval ${_UNSET} wf_res;
eval ${_UNSET} wf_section;
eval "${return_ok}";
fi;
# mdoc style (BSD doc); grep the line containing `.Nd' macro, if any
wf_res="$(cat_z "$1" | sed -n -e '/'"${wf_dot}"'Nd /s///p')";
exit_test;
if obj wf_res is_not_empty
then # BSD doc style
if obj wf_section is_not_empty
then
wf_res="$(obj wf_res echo1 | sed -n -e '
s/^\(.*\)$/'"${wf_name}"' ('"${wf_section}"') \\[em] \1/p
')";
fi;
### whatis_filename()
obj wf_res echo1;
echo;
eval ${_UNSET} wf_arg;
eval ${_UNSET} wf_dot;
eval ${_UNSET} wf_name;
eval ${_UNSET} wf_res;
eval ${_UNSET} wf_section;
eval "${return_ok}";
fi;
echo1 'is not a man page';
echo;
eval ${_UNSET} wf_arg;
eval ${_UNSET} wf_dot;
eval ${_UNSET} wf_name;
eval ${_UNSET} wf_res;
eval ${_UNSET} wf_section;
eval "${return_bad}";
} # whatis_filename()
########################################################################
# whatis_filespec ()
#
# Print the filespec name as .SH to the temporary cat file.
#
# Globals: in: $_OPT_WHATIS, $_SPECIAL_SETUP
# out: $_SPECIAL_FILESPEC
#
whatis_filespec()
{
func_check whatis_filespec '=' 0 "$@";
if obj _OPT_WHATIS is_yes
then
if obj _SPECIAL_SETUP is_not_yes
then
error 'whatis_filespec(): whatis_setup() must be run first.';
fi;
_SPECIAL_FILESPEC='yes';
eval to_tmp_line \
"'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
exit_test;
eval "${return_ok}";
else
eval "${return_bad}";
fi;
} # whatis_filespec()
########################################################################
# whatis_setup ()
#
# Print the whatis header to the temporary cat file; this is the setup
# for whatis.
#
# Globals: in: $_OPT_WHATIS
# out: $_SPECIAL_SETUP
#
whatis_setup()
{
func_check whatis_setup '=' 0 "$@";
if obj _OPT_WHATIS is_yes
then
to_tmp_line '.TH GROFFER WHATIS';
_SPECIAL_SETUP='yes';
if obj _OPT_TITLE is_empty
then
_OPT_TITLE='whatis';
fi;
eval "${return_ok}";
else
eval "${return_bad}";
fi;
} # whatis_setup()
########################################################################
# where_is_prog (<program>)
#
# Output path of a program and the given arguments if in $PATH.
#
# Arguments : 1, <program> can have spaces and arguments.
# Output : list of 2 elements: prog name (with directory) and arguments
# Return : `0' if arg1 is a program in $PATH, `1' otherwise.
#
# Variable prefix: wip
#
where_is_prog()
{
func_check where_is_prog '=' 1 "$@";
if is_empty "$1"
then
eval "${return_bad}";
fi;
# Remove disturbing multiple spaces and tabs
wip_1="$(echo1 "$1" | sed -e 's/[ ][ ]*/ /g' | \
sed -e 's/\(\\\)* / /g' | sed -e 's/^ //' | sed -e 's/ $//')";
wip_noarg="$(echo1 "${wip_1}" | sed -e 's/ -.*$//')";
exit_test;
if obj wip_noarg is_empty
then
eval ${_UNSET} wip_1;
eval ${_UNSET} wip_noarg;
eval "${return_bad}";
fi;
case "${wip_1}" in
*\ -*)
wip_args="$(echo1 "${wip_1}" |
eval sed -e "'s#^${wip_noarg} ##'")";
exit_test;
;;
*)
wip_args='';
;;
esac;
wip_result='';
### where_is_prog()
if test -f "${wip_noarg}" && test -x "${wip_noarg}"
then
list_append wip_result "${wip_noarg}" "${wip_args}";
exit_test;
obj wip_result echo1;
exit_test;
eval ${_UNSET} wip_1;
eval ${_UNSET} wip_args;
eval ${_UNSET} wip_noarg;
eval ${_UNSET} wip_result;
eval "${return_ok}";
fi;
# test whether $wip_noarg has directory, so it is not tested with $PATH
case "${wip_noarg}" in
*/*)
# now $wip_noarg (with /) is not an executable file
# test name with space
obj_from_output wip_name base_name "${wip_noarg}";
obj_from_output wip_dir dir_name "${wip_noarg}";
case "${wip_name}" in
*\ *)
wip_base="$(echo1 "${wip_name}" | sed -e 's/ .*$//')";
exit_test;
obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_base}";
exit_test;
### where_is_prog()
if test -f "${wip_file}" && test -x "${wip_file}"
then
wip_baseargs="$(echo1 "${wip_name}" |
eval sed -e "'s#^${wip_base} ##'")";
exit_test;
if obj wip_args is_empty
then
wip_args="${wip_baseargs}";
else
wip_args="${wip_baseargs} ${wip_args}";
fi;
list_append wip_result "${wip_file}" "${wip_args}";
exit_test;
obj wip_result echo1;
exit_test;
eval ${_UNSET} wip_1;
eval ${_UNSET} wip_args;
eval ${_UNSET} wip_base;
eval ${_UNSET} wip_baseargs;
eval ${_UNSET} wip_dir;
eval ${_UNSET} wip_file;
eval ${_UNSET} wip_name;
eval ${_UNSET} wip_noarg;
eval ${_UNSET} wip_result;
eval "${return_ok}";
fi; # test ${wip_file}
;;
esac; # end of test name with space
### where_is_prog()
eval ${_UNSET} wip_1;
eval ${_UNSET} wip_args;
eval ${_UNSET} wip_base;
eval ${_UNSET} wip_dir;
eval ${_UNSET} wip_name;
eval ${_UNSET} wip_noarg;
eval ${_UNSET} wip_result;
eval "${return_bad}";
;;
esac; # test of $wip_noarg on path with directory
# now $wip_noarg does not have a /, so it is checked with $PATH.
eval set x "$(path_list "${PATH}")";
exit_test;
shift;
# test path with $win_noarg, evt. with spaces
for d
do
wip_dir="$d";
obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_noarg}";
### where_is_prog()
# test $win_file on executable file
if test -f "${wip_file}" && test -x "${wip_file}"
then
list_append wip_result "${wip_file}" "${wip_args}";
exit_test;
obj wip_result echo1;
exit_test;
eval ${_UNSET} wip_1;
eval ${_UNSET} wip_dir;
eval ${_UNSET} wip_file;
eval ${_UNSET} wip_noarg;
eval ${_UNSET} wip_result;
eval "${return_ok}";
fi; # test $win_file on executable file
done; # test path with $win_prog with spaces
case "${wip_noarg}" in
*\ *)
# test on path with base name without space
wip_base="$(echo1 "${wip_noarg}" | sed -e 's/^\([^ ]*\) .*$/\1/')";
exit_test;
for d
do
wip_dir="$d";
obj_from_output wip_file dir_name_append "${wip_dir}" "${wip_base}";
exit_test;
### where_is_prog()
# test $win_file on executable file
if test -f "${wip_file}" && test -x "${wip_file}"
then
wip_baseargs="$(echo1 "${wip_noarg}" |
sed -e 's/[^ ]* \(.*\)$/\1/')";
exit_test;
if obj wip_args is_empty
then
wip_args="${wip_baseargs}";
else
wip_args="${wip_args} ${wip_baseargs}";
fi;
list_append wip_result "${wip_file}" "${wip_args}";
exit_test;
obj wip_result echo1;
exit_test;
eval ${_UNSET} wip_1;
eval ${_UNSET} wip_args;
eval ${_UNSET} wip_base;
eval ${_UNSET} wip_baseargs;
eval ${_UNSET} wip_dir;
eval ${_UNSET} wip_file;
eval ${_UNSET} wip_name;
eval ${_UNSET} wip_noarg;
eval ${_UNSET} wip_result;
eval "${return_ok}";
fi; # test of $wip_file on executable file
done; # test path with base name without space
### where_is_prog()
;;
esac; # test of $wip_noarg on space
eval ${_UNSET} wip_1;
eval ${_UNSET} wip_args;
eval ${_UNSET} wip_base;
eval ${_UNSET} wip_baseargs;
eval ${_UNSET} wip_dir;
eval ${_UNSET} wip_file;
eval ${_UNSET} wip_name;
eval ${_UNSET} wip_noarg;
eval ${_UNSET} wip_result;
eval "${return_bad}";
} # where_is_prog()
########################################################################
# main* Functions
########################################################################
# The main area contains the following parts:
# - main_init(): initialize temporary files and set exit trap
# - main_parse_MANOPT(): parse $MANOPT
# - main_parse_args(): argument parsing
# - main_set_mode (): determine the display mode
# - main_do_fileargs(): process filespec arguments
# - main_set_resources(): setup X resources
# - main_display(): do the displaying
# - main(): the main function that calls all main_*()
#######################################################################
# main_init ()
#
# Set exit trap and create temporary directory and some temporary files.
#
# Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
#
# Variable prefix: mi
#
main_init()
{
func_check main_init = 0 "$@";
# call clean_up() on shell termination.
trap_set;
# create temporary directory
umask 0077;
_TMP_DIR='';
for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
"${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.'
do
mi_dir="$d";
if obj mi_dir is_empty || obj mi_dir is_not_dir || \
obj mi_dir is_not_writable
then
continue;
fi;
case "${mi_dir}" in
*/)
_TMP_DIR="${mi_dir}";
;;
*)
_TMP_DIR="${mi_dir}"'/';
;;
esac;
_TMP_DIR="${_TMP_DIR}groffer${_PROCESS_ID}";
if obj _TMP_DIR rm_tree
then
:
else
mi_tdir_="${_TMP_DIR}"_;
mi_n=1;
mi_tdir_n="${mi_tdir_}${mi_n}";
### main_init()
while obj mi_tdir_n is_existing
do
if obj mi_tdir_n rm_tree
then
# directory could not be removed
mi_n="$(expr "${mi_n}" + 1)";
mi_tdir_n="${mi_tdir_}${mi_n}";
continue;
fi;
done;
_TMP_DIR="${mi_tdir_n}";
fi;
eval mkdir "${_TMP_DIR}";
if is_not_equal "$?" 0
then
obj _TMP_DIR rm_tree;
_TMP_DIR='';
continue;
fi;
if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable
then
# $_TMP_DIR can now be used as temporary directory
break;
fi;
obj _TMP_DIR rm_tree;
_TMP_DIR='';
continue;
done;
if obj _TMP_DIR is_empty
then
error "main_init(): \
Couldn't create a directory for storing temporary files.";
fi;
### main_init()
if obj _DEBUG_PRINT_TMPDIR is_yes
then
echo2 "temporary directory: ${_TMP_DIR}";
fi;
obj_from_output _TMP_CAT tmp_create groffer_cat;
obj_from_output _TMP_STDIN tmp_create groffer_input;
eval ${_UNSET} mi_dir;
eval ${_UNSET} mi_n;
eval ${_UNSET} mi_tdir_;
eval ${_UNSET} mi_tdir_n;
eval "${return_ok}";
} # main_init()
########################################################################
# main_parse_MANOPT ()
#
# Parse $MANOPT to retrieve man options, but only if it is a non-empty
# string; found man arguments can be overwritten by the command line.
#
# Globals:
# in: $MANOPT, $_OPTS_MANOPT_*
# out: $_MANOPT_*
#
# Variable prefix: mpm
#
main_parse_MANOPT()
{
func_check main_parse_MANOPT = 0 "$@";
if obj MANOPT is_not_empty
then
# Delete leading and final spaces
MANOPT="$(echo1 "${MANOPT}" | sed -e '
s/^'"${_SPACE_SED}"'*//
s/'"${_SPACE_SED}"'*$//
')";
exit_test;
fi;
if obj MANOPT is_empty
then
eval "${return_ok}";
fi;
mpm_list='';
# add arguments in $MANOPT by mapping them to groffer options
eval set x "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
exit_test;
shift;
until test "$#" -le 0 || is_equal "$1" '--'
do
mpm_opt="$1";
shift;
case "${mpm_opt}" in
-7|--ascii)
list_append mpm_list '--ascii';
;;
-a|--all)
list_append mpm_list '--all';
;;
### main_parse_MANOPT()
-c|--catman)
do_nothing;
shift;
;;
-d|--debug)
do_nothing;
;;
-D|--default)
# undo all man options so far
mpm_list='';
;;
-e|--extension)
list_append mpm_list '--extension';
shift;
;;
-f|--whatis)
list_append mpm_list '--whatis';
shift;
;;
-h|--help)
do_nothing;
;;
-k|--apropos)
# groffer's --apropos takes an argument, but man's does not, so
do_nothing;
;;
-l|--local-file)
do_nothing;
;;
-L|--locale)
list_append mpm_list '--locale' "$1";
shift;
;;
### main_parse_MANOPT()
-m|--systems)
list_append mpm_list '--systems' "$1";
shift;
;;
-M|--manpath)
list_append mpm_list '--manpath' "$1";
shift;
;;
-p|--preprocessor)
do_nothing;
shift;
;;
-P|--pager)
list_append mpm_list '--pager' "$1";
shift;
;;
-r|--prompt)
do_nothing;
shift;
;;
-S|--sections)
list_append mpm_list '--sections' "$1";
shift;
;;
-t|--troff)
do_nothing;
;;
-T|--device)
list_append mpm_list '-T' "$1";
shift;
;;
### main_parse_MANOPT()
-u|--update)
do_nothing;
;;
-V|--version)
do_nothing;
;;
-w|--where|--location)
list_append mpm_list '--location';
;;
-Z|--ditroff)
do_nothing;
;;
# ignore all other options
esac;
done;
# prepend $mpm_list to the command line
if obj mpm_list is_not_empty
then
eval set x "${mpm_list}" '"$@"';
shift;
fi;
eval ${_UNSET} mpm_list;
eval ${_UNSET} mpm_opt;
eval "${return_ok}";
} # main_parse_MANOPT()
########################################################################
# main_parse_args (<command_line_args>*)
#
# Parse arguments; process options and filespec parameters.
#
# Arguments: pass the command line arguments unaltered.
# Globals:
# in: $_OPTS_*
# out: $_OPT_*, $_ADDOPTS, $_FILEARGS
#
# Variable prefix: mpa
#
main_parse_args()
{
func_check main_parse_args '>=' 0 "$@";
obj_from_output _ALL_PARAMS list_from_cmdline_with_minus _OPTS_CMDLINE "$@";
if obj _DEBUG_PRINT_PARAMS is_yes
then
echo2 "parameters: ${_ALL_PARAMS}";
fi;
eval set x "${_ALL_PARAMS}";
shift;
# By the call of `eval', unnecessary quoting was removed. So the
# positional shell parameters ($1, $2, ...) are now guaranteed to
# represent an option or an argument to the previous option, if any;
# then a `--' argument for separating options and
# parameters; followed by the filespec parameters if any.
# Note, the existence of arguments to options has already been checked.
# So a check for `$#' or `--' should not be done for arguments.
until test "$#" -le 0 || is_equal "$1" '--'
do
mpa_opt="$1"; # $mpa_opt is fed into the option handler
shift;
case "${mpa_opt}" in
-h|--help)
usage;
leave;
;;
-Q|--source) # output source code (`Quellcode').
_OPT_MODE='source';
;;
### main_parse_args()
-T|--device|--troff-device) # device; arg
_OPT_DEVICE="$1";
_check_device_with_mode;
shift;
;;
-v|--version)
version;
leave;
;;
-V)
_OPT_V='yes';
;;
-Z|--ditroff|--intermediate-output) # groff intermediate output
_OPT_Z='yes';
;;
-X)
_OPT_MODE=X;
;;
-?)
# delete leading `-'
mpa_optchar="$(echo1 "${mpa_opt}" | sed -e 's/^-//')";
exit_test;
if list_has _OPTS_GROFF_SHORT_NA "${mpa_optchar}"
then
list_append _ADDOPTS_GROFF "${mpa_opt}";
elif list_has _OPTS_GROFF_SHORT_ARG "${mpa_optchar}"
then
list_append _ADDOPTS_GROFF "${mpa_opt}" "$1";
shift;
### main_parse_args()
else
error "main_parse_args(): Unknown option : \`$1'";
fi;
;;
--all)
_OPT_ALL='yes';
;;
--apropos) # run `apropos'
_OPT_APROPOS='yes';
_APROPOS_SECTIONS='';
_OPT_WHATIS='no';
;;
--apropos-data) # run `apropos' for data sections
_OPT_APROPOS='yes';
_APROPOS_SECTIONS='457';
_OPT_WHATIS='no';
;;
--apropos-devel) # run `apropos' for development sections
_OPT_APROPOS='yes';
_APROPOS_SECTIONS='239';
_OPT_WHATIS='no';
;;
--apropos-progs) # run `apropos' for program sections
_OPT_APROPOS='yes';
_APROPOS_SECTIONS='168';
_OPT_WHATIS='no';
;;
### main_parse_args()
--ascii)
list_append _ADDOPTS_GROFF '-mtty-char';
if obj _OPT_MODE is_empty
then
_OPT_MODE='text';
fi;
;;
--auto) # the default automatic mode
_OPT_MODE='';
;;
--bd|--bordercolor) # border color for viewers, arg;
_OPT_BD="$1";
shift;
;;
--bg|--backgroud) # background color for viewers, arg;
_OPT_BG="$1";
shift;
;;
--bw|--borderwidth) # border width for viewers, arg;
_OPT_BW="$1";
shift;
;;
--debug|--debug-all|--debug-filenames|--debug-func|--debug-not-func|\
--debug-keep|--debug-lm|--debug-params|--debug-shell|--debug-stacks|\
--debug-tmpdir|--debug-user)
# debug is handled at the beginning
:;
;;
--default) # reset variables to default
reset;
;;
### main_parse_args()
--default-modes) # sequence of modes in auto mode; arg
_OPT_DEFAULT_MODES="$1";
shift;
;;
--display) # set X display, arg
_OPT_DISPLAY="$1";
shift;
;;
--do-nothing)
_OPT_DO_NOTHING='yes';
;;
--dvi)
_OPT_MODE='dvi';
;;
--dvi-viewer|--dvi-viewer-tty) # viewer program for dvi mode; arg
_OPT_VIEWER_DVI="$1";
shift;
;;
--extension) # the extension for man pages, arg
_OPT_EXTENSION="$1";
shift;
;;
### main_parse_args()
--fg|--foreground) # foreground color for viewers, arg;
_OPT_FG="$1";
shift;
;;
--fn|--ft|--font) # set font for viewers, arg;
_OPT_FN="$1";
shift;
;;
--geometry) # window geometry for viewers, arg;
_OPT_GEOMETRY="$1";
shift;
;;
--groff)
_OPT_MODE='groff';
;;
--html|--www) # display with web browser
_OPT_MODE=html;
;;
--html-viewer|--www-viewer|--html-viewer-tty|--www-viewer-tty)
# viewer program for html mode; arg
_OPT_VIEWER_HTML="$1";
shift;
;;
--iconic) # start viewers as icons
_OPT_ICONIC='yes';
;;
### main_parse_args()
--locale) # set language for man pages, arg
# argument is xx[_territory[.codeset[@modifier]]] (ISO 639,...)
_OPT_LANG="$1";
shift;
;;
--local-file) # force local files; same as `--no-man'
_MAN_FORCE='no';
_MAN_ENABLE='no';
;;
--location|--where) # print file locations to stderr
_DEBUG_PRINT_FILENAMES='yes';
;;
--man) # force all file params to be man pages
_MAN_ENABLE='yes';
_MAN_FORCE='yes';
;;
--manpath) # specify search path for man pages, arg
# arg is colon-separated list of directories
_OPT_MANPATH="$1";
shift;
;;
--mode) # display mode
mpa_arg="$1";
shift;
case "${mpa_arg}" in
auto|'') # search mode automatically among default
_OPT_MODE='';
;;
groff) # pass input to plain groff
_OPT_MODE='groff';
;;
### main_parse_args()
html|www) # display with a web browser
_OPT_MODE='html';
;;
dvi) # display with xdvi viewer
_OPT_MODE='dvi';
;;
pdf) # display with PDF viewer
_OPT_MODE='pdf';
;;
ps) # display with Postscript viewer
_OPT_MODE='ps';
;;
text) # output on terminal
_OPT_MODE='text';
;;
tty) # output on terminal
_OPT_MODE='tty';
;;
X|x) # output on X roff viewer
_OPT_MODE='x';
;;
### main_parse_args()
Q|source) # display source code
_OPT_MODE="source";
;;
*)
error "main_parse_args(): unknown mode ${mpa_arg}";
;;
esac;
;;
--no-location) # disable former call to `--location'
_DEBUG_PRINT_FILENAMES='no';
;;
--no-man) # disable search for man pages
# the same as --local-file
_MAN_FORCE='no';
_MAN_ENABLE='no';
;;
--no-special) # disable some special former calls
_OPT_ALL='no'
_OPT_APROPOS='no'
_OPT_WHATIS='no'
;;
--pager|--tty-viewer|--tty-viewer-tty)
# set paging program for tty mode, arg
_OPT_PAGER="$1";
shift;
;;
--pdf)
_OPT_MODE='pdf';
;;
### main_parse_args()
--pdf-viewer|--pdf-viewer-tty) # viewer program for pdf mode; arg
_OPT_VIEWER_PDF="$1";
shift;
;;
--print) # for argument test
echo2 "$1";
shift;
;;
--ps)
_OPT_MODE='ps';
;;
--ps-viewer|--ps-viewer-tty) # viewer program for ps mode; arg
_OPT_VIEWER_PS="$1";
shift;
;;
### main_parse_args()
--resolution) # set resolution for X devices, arg
mpa_arg="$1";
shift;
case "${mpa_arg}" in
75|75dpi)
mpa_dpi=75;
;;
100|100dpi)
mpa_dpi=100;
;;
*)
error "main_parse_args(): \
only resoutions of 75 or 100 dpi are supported";
;;
esac;
_OPT_RESOLUTION="${mpa_dpi}";
;;
--rv)
_OPT_RV='yes';
;;
--sections) # specify sections for man pages, arg
# arg is colon-separated list of section names
_OPT_SECTIONS="$1";
shift;
;;
--shell)
# already done during the first run; so ignore the argument
shift;
;;
### main_parse_args()
--systems) # man pages for different OS's, arg
# argument is a comma-separated list
_OPT_SYSTEMS="$1";
shift;
;;
--text) # text mode without pager
_OPT_MODE=text;
;;
--title) # title for X viewers; arg
if is_not_empty "$1"
then
list_append _OPT_TITLE "$1";
fi;
shift;
;;
--to-stdout) # print mode file without display
_OPT_STDOUT='yes';
;;
--tty) # tty mode, text with pager
_OPT_MODE=tty;
;;
--text-device|--tty-device) # device for tty mode; arg
_OPT_TEXT_DEVICE="$1";
shift;
;;
--whatis)
_OPT_WHATIS='yes';
_OPT_APROPOS='no';
;;
--X|--x)
_OPT_MODE=x;
;;
### main_parse_args()
--xrm) # pass X resource string, arg;
list_append _OPT_XRM "$1";
shift;
;;
--x-viewer|--X-viewer|--x-viewer-tty|--X-viewer-tty)
# viewer program for x mode; arg
_OPT_VIEWER_X="$1";
shift;
;;
*)
error 'main_parse_args(): unknown option '"\`${mpa_opt}'.";
;;
esac;
done;
shift; # remove `--' argument
if obj _OPT_WHATIS is_yes
then
_MAN_ALL='yes';
_APROPOS_SECTIONS='';
fi;
if obj _OPT_DO_NOTHING is_yes
then
leave;
fi;
### main_parse_args()
case "$_OPT_DEFAULT_MODES" in
'') :; ;;
*,*)
obj_from_output _OPT_DEFAULT_MODES \
obj _OPT_DEFAULT_MODES list_from_split ',';
;;
*) :; ;;
esac;
# Remaining arguments are file names (filespecs).
# Save them to list $_FILEARGS
if is_equal "$#" 0
then # use "-" for standard input
_NO_FILESPECS='yes';
set x '-';
shift;
fi;
_FILEARGS='';
list_append _FILEARGS "$@";
# $_FILEARGS must be retrieved with `eval set x "$_FILEARGS"; shift;'
eval ${_UNSET} mpa_arg;
eval ${_UNSET} mpa_dpi;
eval ${_UNSET} mpa_opt;
eval ${_UNSET} mpa_optchar;
eval "${return_ok}";
} # main_parse_args()
# Called from main_parse_args() because double `case' is not possible.
# Globals: $_OPT_DEVICE, $_OPT_MODE
_check_device_with_mode()
{
func_check _check_device_with_mode = 0 "$@";
case "${_OPT_DEVICE}" in
dvi)
_OPT_MODE=dvi;
eval "${return_ok}";
;;
html)
_OPT_MODE=html;
eval "${return_ok}";
;;
lbp|lj4)
_OPT_MODE=groff;
eval "${return_ok}";
;;
ps)
_OPT_MODE=ps;
eval "${return_ok}";
;;
ascii|cp1047|latin1|utf8)
if obj _OPT_MODE is_not_equal text
then
_OPT_MODE=tty; # default text mode
fi;
eval "${return_ok}";
;;
X*)
_OPT_MODE=x;
eval "${return_ok}";
;;
*) # unknown device, go to groff mode
_OPT_MODE=groff;
eval "${return_ok}";
;;
esac;
eval "${return_error}";
} # _check_device_with_mode() of main_parse_args()
########################################################################
# main_set_mode ()
#
# Determine the display mode and the corresponding viewer program.
#
# Globals:
# in: $DISPLAY, $_OPT_MODE, $_OPT_DEVICE
# out: $_DISPLAY_MODE
#
# Variable prefix: msm
#
main_set_mode()
{
func_check main_set_mode = 0 "$@";
# set display
if obj _OPT_DISPLAY is_not_empty
then
DISPLAY="${_OPT_DISPLAY}";
fi;
if obj _OPT_V is_yes
then
list_append _ADDOPTS_GROFF '-V';
fi;
if obj _OPT_Z is_yes
then
_DISPLAY_MODE='groff';
list_append _ADDOPTS_GROFF '-Z';
fi;
if obj _OPT_MODE is_equal 'groff'
then
_DISPLAY_MODE='groff';
fi;
if obj _DISPLAY_MODE is_equal 'groff'
then
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
fi;
### main_set_mode()
case "${_OPT_MODE}" in
'') # automatic mode
case "${_OPT_DEVICE}" in
X*)
if is_not_X
then
error_user "no X display found for device ${_OPT_DEVICE}";
fi;
_DISPLAY_MODE='x';
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
ascii|cp1047|latin1|utf8)
if obj _DISPLAY_MODE is_not_equal 'text'
then
_DISPLAY_MODE='tty';
fi;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
### main_set_mode()
esac;
if is_not_X
then
_DISPLAY_MODE='tty';
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
fi;
if obj _OPT_DEFAULT_MODES is_empty
then
msm_modes="${_DEFAULT_MODES}";
else
msm_modes="${_OPT_DEFAULT_MODES}";
fi;
;;
source)
_DISPLAY_MODE='source';
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
text)
_DISPLAY_MODE='text';
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
tty)
_DISPLAY_MODE='tty';
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
### main_set_mode()
html)
_DISPLAY_MODE='html';
msm_modes="${_OPT_MODE}";
;;
*) # display mode was given
msm_modes="${_OPT_MODE}";
;;
esac;
eval set x "${msm_modes}";
shift;
while is_greater_than "$#" 0
do
msm_1="$1";
shift;
_VIEWER_BACKGROUND='no';
case "${msm_1}" in
dvi)
_get_prog_args DVI;
if is_not_equal "$?" 0
then
continue;
fi;
if obj _DISPLAY_PROG is_empty
then
if is_equal "$#" 0
then
error 'main_set_mode(): No viewer for dvi mode available.';
else
continue;
fi;
fi;
### main_set_mode()
_DISPLAY_MODE="dvi";
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
html)
_get_prog_args HTML;
if is_not_equal "$?" 0
then
continue;
fi;
if obj _DISPLAY_PROG is_empty
then
if is_equal "$#" 0
then
error 'main_set_mode(): No viewer for html mode available.';
else
continue;
fi;
fi;
### main_set_mode()
_DISPLAY_MODE=html;
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
pdf)
if obj _PDF_DID_NOT_WORK is_yes
then
if is_equal "$#" 0
then
error 'main_set_mode(): pdf mode did not work.';
else
continue;
fi;
fi;
if obj _PDF_HAS_PS2PDF is_not_yes
then
if is_prog ps2pdf
then
_PDF_HAS_PS2PDF='yes';
fi;
fi;
if obj _PDF_HAS_GS is_not_yes
then
if is_prog gs
then
_PDF_HAS_GS='yes';
fi;
fi;
_get_prog_args PDF;
if is_not_equal "$?" 0
then
_PDF_DID_NOT_WORK='yes';
continue;
fi;
if obj _DISPLAY_PROG is_empty
then
_PDF_DID_NOT_WORK='yes';
if is_equal "$#" 0
then
error 'main_set_mode(): No viewer for pdf mode available.';
else
continue;
fi;
fi;
_DISPLAY_MODE="pdf";
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
### main_set_mode()
ps)
_get_prog_args PS;
if is_not_equal "$?" 0
then
continue;
fi;
if obj _DISPLAY_PROG is_empty
then
if is_equal "$#" 0
then
error 'main_set_mode(): No viewer for ps mode available.';
else
continue;
fi;
fi;
_DISPLAY_MODE="ps";
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
text)
_DISPLAY_MODE='text';
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
### main_set_mode()
tty)
_DISPLAY_MODE='tty';
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
x)
_get_prog_args x;
if is_not_equal "$?" 0
then
continue;
fi;
if obj _DISPLAY_PROG is_empty
then
if is_equal "$#" 0
then
error 'main_set_mode(): No viewer for x mode available.';
else
continue;
fi;
fi;
_DISPLAY_MODE='x';
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
### main_set_mode()
X)
_DISPLAY_MODE='X';
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
eval "${return_ok}";
;;
esac;
done;
eval ${_UNSET} msm_1;
eval ${_UNSET} msm_modes;
eval ${_UNSET} msm_viewers;
error_user "No suitable display mode found.";
} # main_set_mode()
# _get_prog_args (<MODE>)
#
# Simplification for loop in main_set_mode().
#
# Globals in/out: $_VIEWER_BACKGROUND
# Globals in : $_OPT_VIEWER_<MODE>, $_VIEWER_<MODE>_X, $_VIEWER_<MODE>_TTY
#
# Variable prefix: _gpa
#
_get_prog_args()
{
func_check _get_prog_args '=' 1 "$@";
x="$(echo1 $1 | tr [a-z] [A-Z])";
eval _gpa_opt='"${_OPT_VIEWER_'"$x"'}"';
_gpa_xlist=_VIEWER_"$x"_X;
_gpa_ttylist=_VIEWER_"$x"_TTY;
if obj _gpa_opt is_empty
then
_VIEWER_BACKGROUND='no';
if is_X
then
_get_first_prog "${_gpa_xlist}";
x="$?";
if is_equal "$x" 0
then
_VIEWER_BACKGROUND='yes';
fi;
else
_get_first_prog "${_gpa_ttylist}";
x="$?";
fi;
exit_test;
eval ${_UNSET} _gpa_opt;
eval ${_UNSET} _gpa_prog;
eval ${_UNSET} _gpa_ttylist;
eval ${_UNSET} _gpa_xlist;
eval "${return_var} $x";
### _get_prog_args() of main_set_mode()
else # $_gpa_opt is not empty
obj_from_output _gpa_prog where_is_prog "${_gpa_opt}";
if is_not_equal "$?" 0 || obj _gpa_prog is_empty
then
exit_test;
echo2 "_get_prog_args(): '${_gpa_opt}' is not an existing program.";
eval ${_UNSET} _gpa_opt;
eval ${_UNSET} _gpa_prog;
eval ${_UNSET} _gpa_ttylist;
eval ${_UNSET} _gpa_xlist;
eval "${return_bad}";
fi;
exit_test;
# $_gpa_prog from opt is an existing program
### _get_prog_args() of main_set_mode()
if is_X
then
eval _check_prog_on_list ${_gpa_prog} ${_gpa_xlist};
if is_equal "$?" 0
then
_VIEWER_BACKGROUND='yes';
else
_VIEWER_BACKGROUND='no';
eval _check_prog_on_list ${_gpa_prog} ${_gpa_ttylist};
fi;
else # is not X
_VIEWER_BACKGROUND='no';
eval _check_prog_on_list ${_gpa_prog} ${_gpa_ttylist};
fi; # is_X
fi; # test of $_gpa_opt
eval ${_UNSET} _gpa_opt;
eval ${_UNSET} _gpa_prog;
eval ${_UNSET} _gpa_ttylist;
eval ${_UNSET} _gpa_xlist;
eval "${return_good}";
} # _get_prog_args() of main_set_mode()
# _get_first_prog (<prog_list_name>)
#
# Retrieve from the elements of the list in the argument the first
# existing program in $PATH.
#
# Local function for main_set_mode().
#
# Return : `1' if none found, `0' if found.
# Output : none
#
# Variable prefix: _gfp
#
_get_first_prog()
{
func_check _get_first_prog '=' 1 "$@";
eval x='"${'"$1"'}"';
eval set x "$x";
shift;
for i
do
_gfp_i="$i";
if obj _gfp_i is_empty
then
continue;
fi;
obj_from_output _gfp_result where_is_prog "${_gfp_i}";
if is_equal "$?" 0 && obj _gfp_result is_not_empty
then
exit_test;
eval set x ${_gfp_result};
shift;
_DISPLAY_PROG="$1";
_DISPLAY_ARGS="$2";
eval ${_UNSET} _gfp_i;
eval ${_UNSET} _gfp_result;
eval "${return_good}";
fi;
exit_test;
done;
eval ${_UNSET} _gfp_i;
eval ${_UNSET} _gfp_result;
eval "${return_bad}";
} # _get_first_prog() of main_set_mode()
# _check_prog_on_list (<prog> <args> <prog_list_name>)
#
# Check whether the content of <prog> is in the list <prog_list_name>.
# The globals are set correspondingly.
#
# Local function for main_set_mode().
#
# Arguments: 3
#
# Return : `1' if not a part of the list, `0' if found in the list.
# Output : none
#
# Globals in : $_VIEWER_<MODE>_X, $_VIEWER_<MODE>_TTY
# Globals in/out: $_DISPLAY_PROG, $_DISPLAY_ARGS
#
# Variable prefix: _cpol
#
_check_prog_on_list()
{
func_check _check_prog_on_list '=' 3 "$@";
_DISPLAY_PROG="$1";
_DISPLAY_ARGS="$2";
eval _cpol_3='"${'"$3"'}"';
eval set x "${_cpol_3}";
shift;
eval ${_UNSET} _cpol_3;
for i
do
_cpol_i="$i";
obj_from_output _cpol_list where_is_prog "${_cpol_i}";
if is_not_equal "$?" 0 || obj _cpol_list is_empty
then
exit_test;
continue;
fi;
exit_test;
_cpol_prog="$(eval set x ${_cpol_list}; shift; echo1 "$1")";
if is_not_equal "${_DISPLAY_PROG}" "${_cpol_prog}"
then
exit_test;
continue;
fi;
exit_test;
### _check_prog_on_list() of main_set_mode()
# equal, prog found
_cpol_args="$(eval set x ${_cpol_list}; shift; echo1 "$2")";
eval ${_UNSET} _cpol_list;
if obj _cpol_args is_not_empty
then
if obj _DISPLAY_ARGS is_empty
then
_DISPLAY_ARGS="${_cpol_args}";
else
_DISPLAY_ARGS="${_cpol_args} ${_DISPLAY_ARGS}";
fi;
fi;
eval ${_UNSET} _cpol_i;
eval ${_UNSET} _cpol_args;
eval ${_UNSET} _cpol_prog;
eval "${return_good}";
done; # for vars in list
# prog was not in the list
eval ${_UNSET} _cpol_i;
eval ${_UNSET} _cpol_args;
eval ${_UNSET} _cpol_list;
eval ${_UNSET} _cpol_prog;
eval "${return_bad}";
} # _check_prog_on_list() of main_set_mode()
#######################################################################
# main_do_fileargs ()
#
# Process filespec arguments.
#
# Globals:
# in: $_FILEARGS (process with `eval set x "$_FILEARGS"; shift;')
#
# Variable prefix: mdfa
#
main_do_fileargs()
{
func_check main_do_fileargs = 0 "$@";
special_setup;
if obj _OPT_APROPOS is_yes
then
if obj _NO_FILESPECS is_yes
then
apropos_filespec;
eval "${return_ok}";
fi;
else
if list_has _FILEARGS '-'
then
save_stdin;
fi;
fi;
eval set x "${_FILEARGS}";
shift;
eval ${_UNSET} _FILEARGS;
### main_do_fileargs()
while is_greater_than "$#" 0
do
mdfa_filespec="$1";
_FILESPEC_ARG="$1";
shift;
_FILESPEC_IS_MAN='no';
_TMP_MANSPEC='';
_SPECIAL_FILESPEC='no';
case "${mdfa_filespec}" in
'')
continue;
;;
esac;
# check for file
case "${mdfa_filespec}" in
'-')
special_filespec;
if obj _OPT_APROPOS is_yes
then
continue;
fi;
register_file '-';
continue;
;;
### main_do_fileargs()
*/*)
special_filespec;
if obj _OPT_APROPOS is_yes
then
continue;
fi;
if obj mdfa_filespec is_file
then
obj mdfa_filespec register_file;
else
echo2 "The argument ${mdfa_filespec} is not a file.";
fi;
continue;
;;
*)
if obj _OPT_APROPOS is_yes
then
special_filespec;
continue;
fi;
# check whether filespec is an existing file
if obj _MAN_FORCE is_not_yes
then
if obj mdfa_filespec is_file
then
special_filespec;
obj mdfa_filespec register_file;
continue;
fi;
fi;
;;
esac;
### main_do_fileargs()
# now it must be a man page pattern
if obj _MACRO_PKG is_not_empty && obj _MACRO_PKG is_not_equal '-man'
then
echo2 "${mdfa_filespec} is not a file, man pages are ignored "\
"due to ${_MACRO_PKG}.";
continue;
fi;
# check for man page
if obj _MAN_ENABLE is_not_yes
then
echo2 "The argument ${mdfa_filespec} is not a file.";
continue;
fi;
if obj _MAN_FORCE is_yes
then
mdfa_errmsg='is not a man page.';
else
mdfa_errmsg='is neither a file nor a man page.';
fi;
### main_do_fileargs()
man_setup;
_FILESPEC_IS_MAN='yes';
# test filespec with `man:...' or `...(...)' on man page
mdfa_name='';
mdfa_section='';
mdfa_ext='';
mdfa_names="${mdfa_filespec}";
case "${mdfa_filespec}" in
man:*)
mdfa_names="${mdfa_names} "\
"$(obj mdfa_filespec echo1 | sed -e 's/^man://')";
;;
esac;
mdfa_continue='no';
for i in ${mdfa_names}
do
mdfa_i=$i;
if obj mdfa_i man_is_man
then
special_filespec;
obj mdfa_i man_get;
mdfa_continue='yes';
break;
fi;
case "${mdfa_i}" in
*\(${_MAN_AUTO_SEC_CHARS}*\))
mdfa_section="$(obj mdfa_i echo1 | sed -e 's/^[^(]*(\(.\).*)$/\1/')";
mdfa_name="$(obj mdfa_i echo1 | sed -e 's/^\([^(]*\)(.*)$/\1/')";
mdfa_ext="$(obj mdfa_i echo1 | sed -e 's/^[^(]*(.\(.*\))$/\1/')";
if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"
then
special_filespec;
man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}";
mdfa_continue='yes';
break;
fi;
;;
*.${_MAN_AUTO_SEC_CHARS}*)
mdfa_name="$(obj mdfa_i echo1 | \
sed -e 's/^\(.*\)\.'"${_MAN_AUTO_SEC_CHARS}"'.*$/\1/')";
mdfa_section="$(obj mdfa_i echo1 | \
sed -e 's/^.*\.\('"${_MAN_AUTO_SEC_CHARS}"'\).*$/\1/')";
mdfa_ext="$(obj mdfa_i echo1 | \
sed -e 's/^.*\.'"${_MAN_AUTO_SEC_CHARS}"'\(.*\)$/\1/')";
if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"
then
special_filespec;
man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}";
mdfa_continue='yes';
break;
fi;
;;
esac;
done;
if obj mdfa_continue is_yes
then
continue;
fi;
### main_do_fileargs()
# check on "s name", where "s" is a section with or without an extension
if is_not_empty "$1"
then
mdfa_name="$1";
case "${mdfa_filespec}" in
${_MAN_AUTO_SEC_CHARS})
mdfa_section="${mdfa_filespec}";
mdfa_ext='';
;;
${_MAN_AUTO_SEC_CHARS}*)
mdfa_section="$(echo1 "${mdfa_filespec}" | \
sed -e 's/^\(.\).*$/\1/')";
mdfa_ext="$(echo1 "${mdfa_filespec}" | \
sed -e 's/^.\(.*\)$/\1/')";
;;
*)
echo2 "${mdfa_filespec} ${mdfa_errmsg}";
continue;
;;
esac;
shift;
if man_is_man "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}"
then
_FILESPEC_ARG="${mdfa_filespec} ${mdfa_name}";
special_filespec;
man_get "${mdfa_name}" "${mdfa_section}" "${mdfa_ext}";
continue;
else
echo2 "No man page for ${mdfa_name} with section ${mdfa_filespec}.";
continue;
fi;
fi;
### main_do_fileargs()
echo2 "${mdfa_filespec} ${mdfa_errmsg}";
continue;
done;
obj _TMP_STDIN rm_file_with_debug;
eval ${_UNSET} mdfa_filespec;
eval ${_UNSET} mdfa_i;
eval ${_UNSET} mdfa_name;
eval ${_UNSET} mdfa_names;
eval "${return_ok}";
} # main_do_fileargs()
########################################################################
# main_set_resources ()
#
# Determine options for setting X resources with $_DISPLAY_PROG.
#
# Globals: $_DISPLAY_PROG, $_OUTPUT_FILE_NAME
#
# Variable prefix: msr
#
main_set_resources()
{
func_check main_set_resources = 0 "$@";
# $msr_prog viewer program
# $msr_rl resource list
for f in ${_TMP_DIR}/,man*
do
rm_file_with_debug $f;
done;
obj_from_output msr_title \
get_first_essential "${_OPT_TITLE}" "${_REG_TITLE_LIST}";
_OUTPUT_FILE_NAME='';
eval set x "${msr_title}";
shift;
until is_equal "$#" 0
do
msr_n="$1";
case "${msr_n}" in
'')
continue;
;;
,*)
msr_n="$(echo1 "$1" | sed -e 's/^,,*//')";
exit_test;
;;
esac;
if obj msr_n is_empty
then
continue;
fi;
if obj _OUTPUT_FILE_NAME is_not_empty
then
_OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}"',';
fi;
_OUTPUT_FILE_NAME="${_OUTPUT_FILE_NAME}${msr_n}";
shift;
done; # until $# is 0
### main_set_resources()
case "${_OUTPUT_FILE_NAME}" in
'')
_OUTPUT_FILE_NAME='-';
;;
,*)
error "main_set_resources(): ${_OUTPUT_FILE_NAME} starts with a comma.";
;;
esac;
_OUTPUT_FILE_NAME="${_TMP_DIR}/${_OUTPUT_FILE_NAME}";
if obj _DISPLAY_PROG is_empty
then # for example, for groff mode
_DISPLAY_ARGS='';
eval ${_UNSET} msr_n;
eval ${_UNSET} msr_prog;
eval ${_UNSET} msr_rl;
eval ${_UNSET} msr_title;
eval "${return_ok}";
fi;
eval set x "${_DISPLAY_PROG}";
shift;
obj_from_output msr_prog base_name "$1";
shift;
if is_greater_than $# 0
then
if obj _DISPLAY_ARGS is_empty
then
_DISPLAY_ARGS="$*";
else
_DISPLAY_ARGS="$* ${_DISPLAY_ARGS}";
fi;
fi;
### main_set_resources()
msr_rl='';
if obj _OPT_BD is_not_empty
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi)
list_append msr_rl '-bd' "${_OPT_BD}";
;;
esac;
fi;
if obj _OPT_BG is_not_empty
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi)
list_append msr_rl '-bg' "${_OPT_BG}";
;;
kghostview)
list_append msr_rl '--bg' "${_OPT_BG}";
;;
xpdf)
list_append msr_rl '-papercolor' "${_OPT_BG}";
;;
esac;
fi;
if obj _OPT_BW is_not_empty
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi)
_list_append msr_rl '-bw' "${_OPT_BW}";
;;
esac;
fi;
### main_set_resources()
if obj _OPT_FG is_not_empty
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi)
list_append msr_rl '-fg' "${_OPT_FG}";
;;
kghostview)
list_append msr_rl '--fg' "${_OPT_FG}";
;;
esac;
fi;
if is_not_empty "${_OPT_FN}"
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi)
list_append msr_rl '-fn' "${_OPT_FN}";
;;
kghostview)
list_append msr_rl '--fn' "${_OPT_FN}";
;;
esac;
fi;
if is_not_empty "${_OPT_GEOMETRY}"
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi|xpdf)
list_append msr_rl '-geometry' "${_OPT_GEOMETRY}";
;;
kghostview)
list_append msr_rl '--geometry' "${_OPT_GEOMETRY}";
;;
esac;
fi;
### main_set_resources()
if is_empty "${_OPT_RESOLUTION}"
then
_OPT_RESOLUTION="${_DEFAULT_RESOLUTION}";
case "${msr_prog}" in
gxditview|xditview)
list_append msr_rl '-resolution' "${_DEFAULT_RESOLUTION}";
;;
xpdf)
case "${_DISPLAY_PROG}" in
*-z*)
:;
;;
*) # if xpdf does not have option -z
case "${_DEFAULT_RESOLUTION}" in
75)
# 72dpi is '100'
list_append msr_rl '-z' '104';
;;
100)
list_append msr_rl '-z' '139';
;;
esac;
;;
esac;
;;
esac;
else
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi)
list_append msr_rl '-resolution' "${_OPT_RESOLUTION}";
;;
xpdf)
case "${_DISPLAY_PROG}" in
*-z*)
:;
;;
*) # if xpdf does not have option -z
case "${_OPT_RESOLUTION}" in
75)
list_append msr_rl '-z' '104';
# '100' corresponds to 72dpi
;;
### main_set_resources()
100)
list_append msr_rl '-z' '139';
;;
esac;
;;
esac;
;;
esac;
fi;
if is_yes "${_OPT_ICONIC}"
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi)
list_append msr_rl '-iconic';
;;
esac;
fi;
if is_yes "${_OPT_RV}"
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi)
list_append msr_rl '-rv';
;;
esac;
fi;
if is_not_empty "${_OPT_XRM}"
then
case "${msr_prog}" in
ghostview|gv|gxditview|xditview|xdvi|xpdf)
eval set x "${_OPT_XRM}";
shift;
for i
do
list_append msr_rl '-xrm' "$i";
done;
### main_set_resources()
;;
esac;
fi;
if is_not_empty "${msr_title}"
then
case "${msr_prog}" in
gxditview|xditview)
list_append msr_rl '-title' "${msr_title}";
;;
esac;
fi;
if obj _DISPLAY_ARGS is_empty
then
_DISPLAY_ARGS="${msr_rl}";
else
_DISPLAY_ARGS="${msr_l} ${_DISPLAY_ARGS}";
fi;
eval ${_UNSET} msr_n;
eval ${_UNSET} msr_prog;
eval ${_UNSET} msr_rl;
eval ${_UNSET} msr_title;
eval "${return_ok}";
} # main_set_resources
########################################################################
# main_display ()
#
# Do the actual display of the whole thing.
#
# Globals:
# in: $_DISPLAY_MODE, $_OPT_DEVICE, $_ADDOPTS_GROFF,
# $_TMP_CAT, $_OPT_PAGER, $_MANOPT_PAGER, $_OUTPUT_FILE_NAME
#
# Variable prefix: md
#
main_display()
{
func_check main_display = 0 "$@";
export md_addopts;
export md_groggy;
export md_modefile;
if obj _TMP_CAT is_empty_file
then
echo2 'groffer: empty input.';
clean_up;
eval "${return_ok}";
fi;
md_modefile="${_OUTPUT_FILE_NAME}";
# go to the temporary directory to be able to access internal data files
cd "${_TMP_DIR}" >"${_NULL_DEV}" 2>&1;
case "${_DISPLAY_MODE}" in
groff)
if obj _OPT_DEVICE is_not_empty
then
_ADDOPTS_GROFF="${_ADDOPTS_GROFF} -T${_OPT_DEVICE}";
fi;
md_groggy="$(tmp_cat | eval grog)";
exit_test;
_do_opt_V;
### main_display()
obj md_modefile rm_file;
mv "${_TMP_CAT}" "${md_modefile}";
trap_unset;
cat "${md_modefile}" | \
{
trap_set;
eval "${md_groggy}" "${_ADDOPTS_GROFF}";
} &
;;
text|tty)
case "${_OPT_DEVICE}" in
'')
obj_from_output md_device \
get_first_essential "${_OPT_TEXT_DEVICE}" "${_DEFAULT_TTY_DEVICE}";
;;
ascii|cp1047|latin1|utf8)
md_device="${_OPT_DEVICE}";
;;
*)
warning "main_display(): \
wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
;;
esac;
md_addopts="${_ADDOPTS_GROFF}";
md_groggy="$(tmp_cat | grog -T${md_device})";
exit_test;
if obj _DISPLAY_MODE is_equal 'text'
then
_do_opt_V;
tmp_cat | eval "${md_groggy}" "${md_addopts}";
else # $_DISPLAY_MODE is 'tty'
### main_display()
md_pager='';
for p in "${_OPT_PAGER}" "${_MANOPT_PAGER}" "${PAGER}"
do
if obj p is_empty
then
continue;
fi;
obj_from_output md_pager where_is_prog "$p";
if is_not_equal "$?" 0 || obj md_pager is_empty
then
md_pager='';
continue;
fi;
eval set x $md_pager;
shift;
case "$1" in
*/less)
if is_empty "$2"
then
md_pager="$1"' -r -R';
else
md_pager="$1"' -r -R '"$2";
fi;
;;
### main_display()
*)
if is_empty "$2"
then
md_pager="$1";
else
md_pager="$1 $2";
fi;
;;
esac;
break;
done;
if obj md_pager is_empty
then
eval set x ${_VIEWER_TTY_TTY} ${_VIEWER_TTY_X} 'cat';
shift;
# that is: 'less -r -R' 'more' 'pager' 'xless' 'cat'
for p
do
if obj p is_empty
then
continue;
fi;
md_p="$p";
if is_prog "${md_p}"
then
md_pager="${md_p}";
break;
fi;
done;
fi;
### main_display()
if obj md_pager is_empty
then
error 'main_display(): no pager program found for tty mode';
fi;
_do_opt_V;
tmp_cat | eval "${md_groggy}" "${md_addopts}" | \
eval "${md_pager}";
fi; # $_DISPLAY_MODE
clean_up;
;; # text|tty)
source)
tmp_cat;
clean_up;
;;
#### viewer modes
### main_display()
dvi)
case "${_OPT_DEVICE}" in
''|dvi) do_nothing; ;;
*)
warning "main_display(): \
wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}"
;;
esac;
md_modefile="${md_modefile}".dvi;
md_groggy="$(tmp_cat | grog -Tdvi)";
exit_test;
_do_display;
;;
html)
case "${_OPT_DEVICE}" in
''|html) do_nothing; ;;
*)
warning "main_display(): \
wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
;;
esac;
md_modefile="${md_modefile}".html;
md_groggy="$(tmp_cat | grog -Thtml)";
exit_test;
_do_display;
;;
### main_display()
pdf)
case "${_OPT_DEVICE}" in
''|ps)
do_nothing;
;;
*)
warning "main_display(): \
wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
;;
esac;
md_groggy="$(tmp_cat | grog -Tps)";
exit_test;
_do_display _make_pdf;
;;
ps)
case "${_OPT_DEVICE}" in
''|ps)
do_nothing;
;;
*)
warning "main_display(): \
wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
;;
esac;
md_modefile="${md_modefile}".ps;
md_groggy="$(tmp_cat | grog -Tps)";
exit_test;
_do_display;
;;
### main_display()
x)
case "${_OPT_DEVICE}" in
X*)
md_device="${_OPT_DEVICE}"
;;
*)
case "${_OPT_RESOLUTION}" in
100)
md_device='X100';
if obj _OPT_GEOMETRY is_empty
then
case "${_DISPLAY_PROG}" in
gxditview|xditview)
# add width of 800dpi for resolution of 100dpi to the args
list_append _DISPLAY_ARGS '-geometry' '800';
;;
esac;
fi;
;;
*)
md_device='X75-12';
;;
esac
esac;
md_groggy="$(tmp_cat | grog -T${md_device} -Z)";
exit_test;
_do_display;
;;
### main_display()
X)
case "${_OPT_DEVICE}" in
'')
md_groggy="$(tmp_cat | grog -X)";
exit_test;
;;
X*|dvi|html|lbp|lj4|ps)
# these devices work with
md_groggy="$(tmp_cat | grog -T"${_OPT_DEVICE}" -X)";
exit_test;
;;
*)
warning "main_display(): \
wrong device for ${_DISPLAY_MODE} mode: ${_OPT_DEVICE}";
md_groggy="$(tmp_cat | grog -Z)";
exit_test;
;;
esac;
_do_display;
;;
*)
error "main_display(): unknown mode \`${_DISPLAY_MODE}'";
;;
esac;
eval ${_UNSET} md_addopts;
eval ${_UNSET} md_device;
eval ${_UNSET} md_groggy;
eval ${_UNSET} md_modefile;
eval ${_UNSET} md_p;
eval ${_UNSET} md_pager;
eval "${return_ok}";
} # main_display()
########################
# _do_display ([<prog>])
#
# Perform the generation of the output and view the result. If an
# argument is given interpret it as a function name that is called in
# the midst (actually only for `pdf').
#
# Globals: $md_modefile, $md_groggy (from main_display())
#
_do_display()
{
func_check _do_display '>=' 0 "$@";
_do_opt_V;
if obj _DISPLAY_PROG is_empty
then
trap_unset;
{
trap_set;
eval "${md_groggy}" "${_ADDOPTS_GROFF}" "${_TMP_CAT}";
} &
else
obj md_modefile rm_file;
cat "${_TMP_CAT}" | \
eval "${md_groggy}" "${_ADDOPTS_GROFF}" > "${md_modefile}";
if obj md_modefile is_empty_file
then
echo2 '_do_display(): empty output.';
clean_up;
exit;
fi;
if is_not_empty "$1"
then
eval "$1";
fi;
### _do_display() of main_display()
obj _TMP_CAT rm_file_with_debug;
if obj _OPT_STDOUT is_yes
then
cat "${md_modefile}";
clean_up;
exit;
fi;
if obj _VIEWER_BACKGROUND is_not_yes # for programs that run on tty
then
eval "'${_DISPLAY_PROG}'" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
else
trap_unset;
{
trap_set;
eval "${_DISPLAY_PROG}" ${_DISPLAY_ARGS} "\"${md_modefile}\"";
} &
fi;
fi;
eval "${return_ok}";
} # _do_display() of main_display()
#############
# _do_opt_V ()
#
# Check on option `-V'; if set print the corresponding output and leave.
#
# Globals: $_ALL_PARAMS, $_ADDOPTS_GROFF, $_DISPLAY_MODE, $_DISPLAY_PROG,
# $_DISPLAY_ARGS, $md_groggy, $md_modefile
#
# Variable prefix: _doV
#
_do_opt_V()
{
func_check _do_opt_V '=' 0 "$@";
if obj _OPT_V is_yes
then
_OPT_V='no';
echo1 "Parameters: ${_ALL_PARAMS}";
echo1 "Display mode: ${_DISPLAY_MODE}";
echo1 "Output file: ${md_modefile}";
echo1 "Display prog: ${_DISPLAY_PROG} ${_DISPLAY_ARGS}";
a="$(eval echo1 "'${_ADDOPTS_GROFF}'")";
exit_test;
echo1 "Output of grog: ${md_groggy} $a";
_doV_res="$(eval "${md_groggy}" "${_ADDOPTS_GROFF}")";
exit_test;
echo1 "groff -V: ${_doV_res}"
leave;
fi;
eval "${return_ok}";
} # _do_opt_V() of main_display()
##############
# _make_pdf ()
#
# Transform to pdf format; for pdf mode in _do_display().
#
# Globals: $md_modefile (from main_display())
#
# Variable prefix: _mp
#
_make_pdf()
{
func_check _make_pdf '=' 0 "$@";
_mp_psfile="${md_modefile}";
md_modefile="${md_modefile}.pdf";
obj md_modefile rm_file;
if obj _PDF_HAS_PS2PDF is_yes && ps2pdf "${_mp_psfile}" "${md_modefile}";
then
:;
elif obj _PDF_HAS_GS is_yes && gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
-sOutputFile="${md_modefile}" -c save pop -f "${_mp_psfile}";
then
:;
else
_PDF_DID_NOT_WORK='yes';
echo2 '_make_pdf(): Could not transform into pdf format. '\
'The Postscript mode (ps) is used instead.';
_OPT_MODE='ps';
main_set_mode;
main_set_resources;
main_display;
exit;
fi;
obj _mp_psfile rm_file_with_debug;
eval ${_UNSET} _mp_psfile;
eval "${return_ok}";
} # _make_pdf() of main_display()
########################################################################
# main (<command_line_args>*)
#
# The main function for groffer.
#
# Arguments:
#
main()
{
func_check main '>=' 0 "$@";
# Do not change the sequence of the following functions!
landmark '13: main_init()';
main_init;
landmark '14: main_parse_MANOPT()';
main_parse_MANOPT;
landmark '15: main_parse_args()';
main_parse_args "$@";
landmark '16: main_set_mode()';
main_set_mode;
landmark '17: main_do_fileargs()';
main_do_fileargs;
landmark '18: main_set_resources()';
main_set_resources;
landmark '19: main_display()';
main_display;
eval "${return_ok}";
}
########################################################################
main "$@";
Copyright 2K16 - 2K18 Indonesian Hacker Rulez