README_SH

Special description for the shell version of `groffer'


The files related to the shell version are

shell/groffer.sh	starting script of groffer
shell/groffer2.sh	main script of groffer
shell/groffer.man	manual page of groffer
shell/README_SH		description of the shell version of the program
shell/ChangeLog.0	information on all changements of groffer versions 0.*
version.sh		script that handles the version information


Scripts

The shell version of `groffer' contains two files, `groffer.sh' and
`groffer2.sh'.

`groffer.sh' is a short introductory script without any functions.  I
can be run with a very poor Bourne shell.  It just contains some basic
variables, the reading of the configuration files, and the
determination of the shell for `groffer2.sh'.  This script is
transformed by `make' into `groffer' which will be installed into
@bindir@, which is usually /usr/local/bin.

`groffer2.sh' is a long main script with all functions; it is called
by `groffer.sh' (`groffer' after installation).  It is installed
unchanged into @libdir@/groff/groffer, which is usually
/usr/local/lib/groff/groffer.  This script can be called with a
different shell, using the `groffer' option `--shell'.


Options

The `groffer' script provides its own option parser.  It is compatible
to the usual GNU style command line This includes long option names
with two signs such as `--option', clusters of short options, the
mixing of options and non-option file names, the option `--' to close
the option handling, and it is possible to abbreviate the long option
names.  The abbreviation of long options is enhanced by letting each
internal `-' sign generate a new center of abbreviation.  So each
command line argument starting with `--' can represent a multiple set
of abbreviations.

The flexible mixing of options and file names in GNU style is always
possible, even if the environment variable `$POSIXLY_CORRECT' is set
to a non-empty value.  This disables the rather wicked POSIX behavior
to terminate option parsing when the first non-option command line
argument is found.


Error Handling

Error handling and exit behavior is complicated by the fact that
`exit' can only escape from the current shell; trouble occurs in
subshells.  This was solved by adding a temporary error file that is
tested by function exit_test() and by replacing `var=$(...)' by
function obj_from_output().


Function Definitions in `groffer2.sh'

Each funtion in groffer2.sh has a description that starts with the
function name and symbols for its arguments in paranthesis `()'.  Each
`<>' construction gives an argument name that just gives a hint on
what the argument is meant to be; these argument names are otherwise
irrelevant.  The `>' sign can be followed by another character that
shows how many of these arguments are possible.

<arg>      exactly 1 of this argument
<arg>?     0 or 1 of these arguments
<arg>*     arbitrarily many such arguments, incl. none
<arg>+     one or more such arguments
<arg>...   one or more such arguments
[...]      optional arguments

A function that starts with an underscore `_' is an internal function
for some other function.  The internal functions are defined just
after their corresponding function.


External Environment Variables

The groffer.sh script uses the following external system variables.
It is supposed that these variables are already exported outside of
groffer.sh; otherwise they do not have a value within the script.

external system environment variables that are explicitly used
$DISPLAY:		Presets the X display.
$LANG:			For language specific man pages.
$LC_ALL:		For language specific man pages.
$LC_MESSAGES:		For language specific man pages.
$PAGER:			Paging program for tty mode.
$PATH:			Path for the programs called (`:' separated list).

groffer native environment variables
$GROFFER_OPT		preset options for groffer.

all groff environment variables are used, see groff(1)
$GROFF_BIN_PATH:	Path for all groff programs.
$GROFF_COMMAND_PREFIX:	'' (normally) or 'g' (several troffs).
$GROFF_FONT_PATH:	Path to non-default groff fonts.
$GROFF_TMAC_PATH:	Path to non-default groff macro files.
$GROFF_TMPDIR:		Directory for groff temporary files.
$GROFF_TYPESETTER:	Preset default device.

all GNU man environment variables are used, see man(1).
$MANOPT:		Preset options for man pages.
$MANPATH:		Search path for man pages (: list).
$MANROFFSEQ:		Ignored because of grog guessing.
$MANSECT:		Search man pages only in sections (:).
$SYSTEM:		Man pages for different OS's (, list).


Object-oriented Functions

The groffer script provides an object-oriented construction (OOP).  In
object-oriented terminology, a type of object is called a `class'; a
function that handles objects from a class is named `method'.

In the groffer script, the object is a variable name whose content is
the object's data.  Methods are functions that have an object as first
argument.

The basic functions for object handling are obj_*().

The class `list' represents an array structure, see list_*().


Speed

The major speed gain is the disabling of all debug features.  This is
the default for the installed version of `groffer'.  Before the run of
`make', the debug feature of $_DEBUG_FUNC_CHECK, corresponding to
option --debug-func, is enabled by default.  The resulting heavy
slowing down should be regarded as a temporary feature.

Another increase of speed was the replacement of the many `ls' calls
by analysing a `find' of manpath with `grep'.


Shell Compatibility

The `groffer' shell scripts are compatible to both the GNU and the
POSIX shell and utilities.  Care was taken to restrict the programming
technics used here in order to achieve POSIX compatibility as far back
as POSIX P1003.2 Draft 11.2 of September 1991.  This draft is
available at http://www.funet.fi/pub/doc/posix/p1003.2/d11.2 in the
internet.

The POSIX draft does not include `local' variables for functions.  So
this concept was replaced by global variables with a prefix that
differs for each function.  The prefix is chosen from the function
name.  These quasi-local variables are unset before each return of the
function.

For shell compatiblity, see also Autobook, chapter 22.

The `groffer' scripts were tested under the shells `ash', `bash',
`bash-minimal', `dash', 'ksh', `mksh', `pdksh', 'posh', and `zsh'
without problems in Linux Debian.  A shell can be tested by the
`groffer' option `--shell', but that will run only with groffer2.sh.
To start it directly from the beginning under this shell the following
command can be used.

  <shell-name> groffer.sh --shell=<shell-name> <argument>...


Some shells are not fully POSIX compatible.  For them the following
restrictions were done.  For more information look at the
documentation `Portable shells' in the `info' page of `autoconf'
(look-up in Emacs-Help-Manuals_Info).

- The command parts `then', `else', and `do' must be written each on a
  line of their own.

- Replace `for i in "$@"' by `for i' and remove internal `;' (kah).

- Replace `set -- ...' by `set x ...; shift'.  After the first
  non-option argument, all arguments including those starting with `-'
  are accepted as non-option.  For variables or `$()' constructs with
  line-breaks, use `eval set' without quotes.  That transforms a
  line-break within a variable to a space.

- The name of the variable in `for' is chosen as a single character
  (old ash).  The content of such variables is not safe because it can
  also occur in other functions.  So it is often stored in an
  additional quasi-local variable.

- `echo' is not portable on options; some `echo' commands have many
  options, others have none.  So `echo -n' cannot be used, such that
  the output of each function has complete lines.  There are two
  methods to avoid having `-' as the first character of any argument.
  Either a character such as `x' can be prepended to the argument;
  this must later on be removed by `sed'.  Otherwise, `echo' can be
  replaced by `cat <<EOF'.

- `ls' has problems.  Old UNIX systems echoed the error message to
  standard output.  So handle the output with `sed'.  If the output
  contains `not found' map it to an empty string.

- As `test -e' is not available in Solaris 2.5 replace it by
  `test -f || test -d'.

- As `unset' is not supported by all shells replace it by `eval
  ${_UNSET}' where this variable is `unset' if it exists and `:'
  otherwise.

- Some shells have problems with options in `eval'.  So quoting must
  be done right to hide the options from `eval'.

- In backquote calls `` avoid the backquote ` in comments.

- Replace `true' by `:', `false' isn't used.

- Do not redefine builtins as functions (ash).

- Avoid `[^...]' in `case' patterns (ash).

- `trap' does not allow error code 127.

The scripts call the following commands with all options used:
.
:
apropos
break
bzip2 -c -d -t
cat
catz
cd
continue
echo
eval
expr
grep
groff -v
grog -T -X -Z
gs -c -d -f -q -s
gzip -c -d -f
less -r -R
ls
man -k --apropos
mkdir
mv
pwd
return
rm -f -r
rmdir
sed -e -n
set -e
sh -c
shift
test -c -d -f -r -s -w -x
trap
umask
unset


Bugs

If the `groffer' run is interrupted by Crtl-C the clean up is not done
by all shells.  The `trap' commands work for the shells `bash',
`bash-minimal', and 'ksh'; they do not work for `ash', `dash',
`pdksh', `posh', and `zsh'.


####### License

Last update: 5 Jan 2009

Copyright (C) 2003, 2004, 2005, 2006, 2009
  Free Software Foundation, Inc.
Written by Bernd Warken

This file is part of `groffer', which is part of `groff'.

`groff' is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

`groff' is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.


####### Emacs settings

Local Variables:
mode: text
End:
