PageRenderTime 12ms CodeModel.GetById 17ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/groff/contrib/groffer/groffer2.sh

https://bitbucket.org/freebsd/freebsd-head/
Shell | 5854 lines | 4370 code | 361 blank | 1123 comment | 359 complexity | 56f108a0a126ad0a9df7a8b9539c98fa MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1#! /bin/sh
   2
   3# groffer - display groff files
   4
   5# Source file position: <groff-source>/contrib/groffer/groffer2.sh
   6# Installed position: <prefix>/lib/groff/groffer/groffer2.sh
   7
   8# This file should not be run independently.  It is called by
   9# `groffer.sh' in the source or by the installed `groffer' program.
  10
  11# Copyright (C) 2001,2002,2003,2004,2005
  12# Free Software Foundation, Inc.
  13# Written by Bernd Warken
  14
  15# Last update: 22 August 2005
  16
  17# This file is part of `groffer', which is part of `groff'.
  18
  19# `groff' is free software; you can redistribute it and/or modify it
  20# under the terms of the GNU General Public License as published by
  21# the Free Software Foundation; either version 2, or (at your option)
  22# any later version.
  23
  24# `groff' is distributed in the hope that it will be useful, but
  25# WITHOUT ANY WARRANTY; without even the implied warranty of
  26# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  27# General Public License for more details.
  28
  29# You should have received a copy of the GNU General Public License
  30# along with `groff'; see the files COPYING and LICENSE in the top
  31# directory of the `groff' source.  If not, write to the Free Software
  32# Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301,
  33# USA.
  34
  35
  36########################################################################
  37#             Test of rudimentary shell functionality
  38########################################################################
  39
  40
  41########################################################################
  42# Test of `unset'
  43#
  44export _UNSET;
  45export _foo;
  46_foo=bar;
  47_res="$(unset _foo 2>&1)";
  48if unset _foo >${_NULL_DEV} 2>&1 && \
  49   test _"${_res}"_ = __ && test _"${_foo}"_ = __
  50then
  51  _UNSET='unset';
  52  eval "${_UNSET}" _foo;
  53  eval "${_UNSET}" _res;
  54else
  55  _UNSET=':';
  56fi;
  57
  58
  59########################################################################
  60# Test of `test'.
  61#
  62if test a = a && test a != b && test -f "${_GROFFER_SH}"
  63then
  64  :;
  65else
  66  echo '"test" did not work.' >&2;
  67  exit "${_ERROR}";
  68fi;
  69
  70
  71########################################################################
  72# Test of `echo' and the `$()' construct.
  73#
  74if echo '' >${_NULL_DEV}
  75then
  76  :;
  77else
  78  echo '"echo" did not work.' >&2;
  79  exit "${_ERROR}";
  80fi;
  81if test _"$(t1="$(echo te)" &&
  82            t2="$(echo '')" &&
  83            t3="$(echo 'st')" &&
  84            echo "${t1}${t2}${t3}")"_ \
  85     != _test_
  86then
  87  echo 'The "$()" construct did not work' >&2;
  88  exit "${_ERROR}";
  89fi;
  90
  91
  92########################################################################
  93# Test of sed program; test in groffer.sh is not valid here.
  94#
  95if test _"$(echo red | sed -e 's/r/s/')"_ != _sed_
  96then
  97  echo 'The sed program did not work.' >&2;
  98  exit "${_ERROR}";
  99fi;
 100
 101
 102########################################################################
 103# Test of function definitions.
 104#
 105_t_e_s_t_f_u_n_c_()
 106{
 107  return 0;
 108}
 109
 110if _t_e_s_t_f_u_n_c_ 2>${_NULL_DEV}
 111then
 112  :;
 113else
 114  echo 'Shell '"${_SHELL}"' does not support function definitions.' >&2;
 115  exit "${_ERROR}";
 116fi;
 117
 118
 119########################################################################
 120#                    debug - diagnostic messages
 121########################################################################
 122
 123export _DEBUG_STACKS;
 124_DEBUG_STACKS='no';		# disable stack output in each function
 125#_DEBUG_STACKS='yes';		# enable stack output in each function
 126
 127export _DEBUG_LM;
 128_DEBUG_LM='no';			# disable landmark messages
 129#_DEBUG_LM='yes';		# enable landmark messages
 130
 131export _DEBUG_KEEP_FILES;
 132_DEBUG_KEEP_FILES='no'		# disable file keeping in temporary dir
 133#_DEBUG_KEEP_FILES='yes'	# enable file keeping in temporary dir
 134
 135export _DEBUG_PRINT_PARAMS;
 136_DEBUG_PRINT_PARAMS='no';	# disable printing of all parameters
 137#_DEBUG_PRINT_PARAMS='yes';	# enable printing of all parameters
 138
 139export _DEBUG_PRINT_SHELL;
 140_DEBUG_PRINT_SHELL='no';	# disable printing of the shell name
 141#_DEBUG_PRINT_SHELL='yes';	# enable printing of the shell name
 142
 143export _DEBUG_PRINT_TMPDIR;
 144_DEBUG_PRINT_TMPDIR='no';	# disable printing of the temporary dir
 145#_DEBUG_PRINT_TMPDIR='yes';	# enable printing of the temporary dir
 146
 147export _DEBUG_USER_WITH_STACK;
 148_DEBUG_USER_WITH_STACK='no';	# disable stack dump in error_user()
 149#_DEBUG_USER_WITH_STACK='yes';	# enable stack dump in error_user()
 150
 151# determine all --debug* options
 152case " $*" in
 153*\ --debug*)
 154  case " $* " in
 155  *' --debug '*)
 156    # _DEBUG_STACKS='yes';
 157    # _DEBUG_LM='yes';
 158    _DEBUG_KEEP_FILES='yes';
 159    _DEBUG_PRINT_PARAMS='yes';
 160    _DEBUG_PRINT_SHELL='yes';
 161    _DEBUG_PRINT_TMPDIR='yes';
 162    _DEBUG_USER_WITH_STACK='yes';
 163    ;;
 164  esac;
 165  d=' --debug-all --debug-keep --debug-lm --debug-params --debug-shell '\
 166'--debug-stacks --debug-tmpdir --debug-user ';
 167  for i
 168  do
 169    case "$i" in
 170    --debug-s)
 171      echo 'The abbreviation --debug-s has multiple options: '\
 172'--debug-shell and --debug-stacks.' >&2
 173      exit "${_ERROR}";
 174      ;;
 175    esac;
 176    case "$d" in
 177    *\ ${i}*)
 178      # extract whole word of abbreviation $i
 179      s="$(cat <<EOF | sed -n -e 's/^.* \('"$i"'[^ ]*\) .*/\1/p'
 180$d
 181EOF
 182)"
 183      case "$s" in
 184      '') continue; ;;
 185      --debug-all)
 186        _DEBUG_STACKS='yes';
 187        _DEBUG_LM='yes';
 188        _DEBUG_KEEP_FILES='yes';
 189        _DEBUG_PRINT_PARAMS='yes';
 190        _DEBUG_PRINT_SHELL='yes';
 191        _DEBUG_PRINT_TMPDIR='yes';
 192        _DEBUG_USER_WITH_STACK='yes';
 193        ;;
 194      --debug-keep)
 195        _DEBUG_PRINT_TMPDIR='yes';
 196        _DEBUG_KEEP_FILES='yes';
 197        ;;
 198      --debug-lm)
 199        _DEBUG_LM='yes';
 200        ;;
 201      --debug-params)
 202        _DEBUG_PRINT_PARAMS='yes';
 203        ;;
 204      --debug-shell)
 205        _DEBUG_PRINT_SHELL='yes';
 206        ;;
 207      --debug-stacks)
 208        _DEBUG_STACKS='yes';
 209        ;;
 210      --debug-tmpdir)
 211        _DEBUG_PRINT_TMPDIR='yes';
 212        ;;
 213      --debug-user)
 214        _DEBUG_USER_WITH_STACK='yes';
 215        ;;
 216      esac;
 217      ;;
 218    esac;
 219  done
 220  ;;
 221esac;
 222
 223if test _"${_DEBUG_PRINT_PARAMS}"_ = _yes_
 224then
 225  echo "parameters: $@" >&2;
 226fi;
 227
 228if test _"${_DEBUG_PRINT_SHELL}"_ = _yes_
 229then
 230  if test _"${_SHELL}"_ = __
 231  then
 232    if test _"${POSIXLY_CORRECT}"_ = _y_
 233    then
 234      echo 'shell: bash as /bin/sh (none specified)' >&2;
 235    else
 236      echo 'shell: /bin/sh (none specified)' >&2;
 237    fi;
 238  else
 239    echo "shell: ${_SHELL}" >&2;
 240  fi;
 241fi;
 242
 243
 244########################################################################
 245#                       Environment Variables
 246########################################################################
 247
 248# Environment variables that exist only for this file start with an
 249# underscore letter.  Global variables to this file are written in
 250# upper case letters, e.g. $_GLOBAL_VARIABLE; temporary variables
 251# start with an underline and use only lower case letters and
 252# underlines, e.g.  $_local_variable .
 253
 254#   [A-Z]*     system variables,      e.g. $MANPATH
 255#   _[A-Z_]*   global file variables, e.g. $_MAN_PATH
 256#   _[a-z_]*   temporary variables,   e.g. $_manpath
 257
 258# Due to incompatibilities of the `ash' shell, the name of loop
 259# variables in `for' must be single character
 260#   [a-z]      local loop variables,   e.g. $i
 261
 262
 263########################################################################
 264# read-only variables (global to this file)
 265########################################################################
 266
 267# function return values; `0' means ok; other values are error codes
 268export _ALL_EXIT;
 269export _BAD;
 270export _GOOD;
 271export _NO;
 272export _OK;
 273export _YES;
 274
 275_GOOD='0';			# return ok
 276_BAD='1';			# return negatively, error code `1'
 277# $_ERROR was already defined as `7' in groffer.sh.
 278
 279_NO="${_BAD}";
 280_YES="${_GOOD}";
 281_OK="${_GOOD}";
 282
 283# quasi-functions, call with `eval', e.g `eval "${return_ok}"'
 284export return_ok;
 285export return_good;
 286export return_bad;
 287export return_yes;
 288export return_no;
 289export return_error;
 290export return_var;
 291return_ok="func_pop; return ${_OK}";
 292return_good="func_pop; return ${_GOOD}";
 293return_bad="func_pop; return ${_BAD}";
 294return_yes="func_pop; return ${_YES}";
 295return_no="func_pop; return ${_NO}";
 296return_error="func_pop; return ${_ERROR}";
 297return_var="func_pop; return";	# add number, e.g. `eval "${return_var} $n'
 298
 299
 300export _DEFAULT_MODES;
 301_DEFAULT_MODES='x,ps,tty';
 302export _DEFAULT_RESOLUTION;
 303_DEFAULT_RESOLUTION='75';
 304
 305export _DEFAULT_TTY_DEVICE;
 306_DEFAULT_TTY_DEVICE='latin1';
 307
 308# _VIEWER_* viewer programs for different modes (only X is necessary)
 309# _VIEWER_* a comma-separated list of viewer programs (with options)
 310export _VIEWER_DVI;		# viewer program for dvi mode
 311export _VIEWER_HTML_TTY;	# viewer program for html mode in tty
 312export _VIEWER_HTML_X;		# viewer program for html mode in X
 313export _VIEWER_PDF;		# viewer program for pdf mode
 314export _VIEWER_PS;		# viewer program for ps mode
 315export _VIEWER_X;		# viewer program for X mode
 316_VIEWER_DVI='kdvi,xdvi,dvilx';
 317_VIEWER_HTML_TTY='lynx';
 318_VIEWER_HTML_X='konqueror,mozilla,netscape,galeon,opera,amaya,arena';
 319_VIEWER_PDF='kghostview --scale 1.45,ggv,xpdf,acroread,kpdf';
 320_VIEWER_PS='kghostview --scale 1.45,ggv,gv,ghostview,gs_x11,gs';
 321_VIEWER_X='gxditview,xditview';
 322
 323# Search automatically in standard sections `1' to `8', and in the
 324# traditional sections `9', `n', and `o'.  On many systems, there
 325# exist even more sections, mostly containing a set of man pages
 326# special to a specific program package.  These aren't searched for
 327# automatically, but must be specified on the command line.
 328export _MAN_AUTO_SEC_LIST;
 329_MAN_AUTO_SEC_LIST="'1' '2' '3' '4' '5' '6' '7' '8' '9' 'n' 'o'";
 330export _MAN_AUTO_SEC_CHARS;
 331_MAN_AUTO_SEC_CHARS='[123456789no]';
 332
 333export _SPACE_SED;
 334_SPACE_SED='['"${_SP}${_TAB}"']';
 335
 336export _SPACE_CASE;
 337_SPACE_CASE='[\'"${_SP}"'\'"${_TAB}"']';
 338
 339export _PROCESS_ID;		# for shutting down the program
 340_PROCESS_ID="$$";
 341
 342
 343############ the command line options of the involved programs
 344#
 345# The naming scheme for the options environment names is
 346# $_OPTS_<prog>_<length>[_<argspec>]
 347#
 348# <prog>:    program name GROFFER, GROFF, or CMDLINE (for all
 349#            command line options)
 350# <length>:  LONG (long options) or SHORT (single character options)
 351# <argspec>: ARG for options with argument, NA for no argument;
 352#            without _<argspec> both the ones with and without arg.
 353#
 354# Each option that takes an argument must be specified with a
 355# trailing : (colon).
 356
 357# exports
 358export _OPTS_GROFFER_SHORT_NA;
 359export _OPTS_GROFFER_SHORT_ARG;
 360export _OPTS_GROFFER_LONG_NA;
 361export _OPTS_GROFFER_LONG_ARG;
 362export _OPTS_GROFF_SHORT_NA;
 363export _OPTS_GROFF_SHORT_ARG;
 364export _OPTS_GROFF_LONG_NA;
 365export _OPTS_GROFF_LONG_ARG;
 366export _OPTS_X_SHORT_ARG;
 367export _OPTS_X_SHORT_NA;
 368export _OPTS_X_LONG_ARG;
 369export _OPTS_X_LONG_NA;
 370export _OPTS_MAN_SHORT_ARG;
 371export _OPTS_MAN_SHORT_NA;
 372export _OPTS_MAN_LONG_ARG;
 373export _OPTS_MAN_LONG_NA;
 374export _OPTS_MANOPT_SHORT_ARG;
 375export _OPTS_MANOPT_SHORT_NA;
 376export _OPTS_MANOPT_LONG_ARG;
 377export _OPTS_MANOPT_LONG_NA;
 378export _OPTS_CMDLINE_SHORT_NA;
 379export _OPTS_CMDLINE_SHORT_ARG;
 380export _OPTS_CMDLINE_LONG_NA;
 381export _OPTS_CMDLINE_LONG_ARG;
 382
 383###### groffer native options
 384
 385_OPTS_GROFFER_SHORT_NA="'h' 'Q' 'v' 'V' 'X' 'Z'";
 386_OPTS_GROFFER_SHORT_ARG="'T'";
 387
 388_OPTS_GROFFER_LONG_NA="'auto' \
 389'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
 390'debug' 'debug-all' 'debug-keep' 'debug-lm' 'debug-params' 'debug-shell' \
 391'debug-stacks' 'debug-tmpdir' 'debug-user' 'default' 'do-nothing' 'dvi' \
 392'groff' 'help' 'intermediate-output' 'html' 'man' \
 393'no-location' 'no-man' 'no-special' 'pdf' 'ps' 'rv' 'source' \
 394'text' 'text-device' \
 395'tty' 'tty-device' 'version' 'whatis' 'where' 'www' 'x' 'X'";
 396
 397_OPTS_GROFFER_LONG_ARG="\
 398'default-modes' 'device' 'dvi-viewer' 'dvi-viewer-tty' 'extension' 'fg' \
 399'fn' 'font' 'foreground' 'html-viewer' 'html-viewer-tty' 'mode' \
 400'pdf-viewer' 'pdf-viewer-tty' 'print' 'ps-viewer' 'ps-viewer-tty' 'shell' \
 401'title' 'tty-viewer' 'tty-viewer-tty' 'www-viewer' 'www-viewer-tty' \
 402'x-viewer' 'x-viewer-tty' 'X-viewer' 'X-viewer-tty'";
 403
 404##### groffer options inhereted from groff
 405
 406_OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
 407'R' 's' 'S' 't' 'U' 'z'";
 408_OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
 409'w' 'W'";
 410_OPTS_GROFF_LONG_NA="";
 411_OPTS_GROFF_LONG_ARG="";
 412
 413##### groffer options inhereted from the X Window toolkit
 414
 415_OPTS_X_SHORT_NA="";
 416_OPTS_X_SHORT_ARG="";
 417
 418_OPTS_X_LONG_NA="'iconic' 'rv'";
 419
 420_OPTS_X_LONG_ARG="'background' 'bd' 'bg' 'bordercolor' 'borderwidth' \
 421'bw' 'display' 'fg' 'fn' 'font' 'foreground' 'ft' 'geometry' \
 422'resolution' 'title' 'xrm'";
 423
 424###### groffer options inherited from man
 425
 426_OPTS_MAN_SHORT_NA="";
 427_OPTS_MAN_SHORT_ARG="";
 428
 429_OPTS_MAN_LONG_NA="'all' 'ascii' 'catman' 'ditroff' \
 430'local-file' 'location' 'troff' 'update'";
 431
 432_OPTS_MAN_LONG_ARG="'locale' 'manpath' \
 433'pager' 'preprocessor' 'prompt' 'sections' 'systems' 'troff-device'";
 434
 435###### additional options for parsing $MANOPT only
 436
 437_OPTS_MANOPT_SHORT_NA="'7' 'a' 'c' 'd' 'D' 'f' 'h' 'k' 'l' 't' 'u' \
 438'V' 'w' 'Z'";
 439_OPTS_MANOPT_SHORT_ARG="'e' 'L' 'm' 'M' 'p' 'P' 'r' 'S' 'T'";
 440
 441_OPTS_MANOPT_LONG_NA="${_OPTS_MAN_LONG_NA} \
 442'apropos' 'debug' 'default' 'help' 'html' 'ignore-case' 'location-cat' \
 443'match-case' 'troff' 'update' 'version' 'whatis' 'where' 'where-cat'";
 444
 445_OPTS_MANOPT_LONG_ARG="${_OPTS_MAN_LONG_NA} \
 446'config_file' 'encoding' 'extension' 'locale'";
 447
 448###### collections of command line options
 449
 450_OPTS_CMDLINE_SHORT_NA="${_OPTS_GROFFER_SHORT_NA} \
 451${_OPTS_GROFF_SHORT_NA} ${_OPTS_X_SHORT_NA} ${_OPTS_MAN_SHORT_NA}";
 452_OPTS_CMDLINE_SHORT_ARG="${_OPTS_GROFFER_SHORT_ARG} \
 453${_OPTS_GROFF_SHORT_ARG} ${_OPTS_X_SHORT_ARG} ${_OPTS_MAN_SHORT_ARG}";
 454
 455_OPTS_CMDLINE_LONG_NA="${_OPTS_GROFFER_LONG_NA} \
 456${_OPTS_GROFF_LONG_NA} ${_OPTS_X_LONG_NA} ${_OPTS_MAN_LONG_NA}";
 457_OPTS_CMDLINE_LONG_ARG="${_OPTS_GROFFER_LONG_ARG} \
 458${_OPTS_GROFF_LONG_ARG} ${_OPTS_MAN_LONG_ARG} ${_OPTS_X_LONG_ARG}";
 459
 460
 461########################################################################
 462# read-write variables (global to this file)
 463########################################################################
 464
 465export _ALL_PARAMS;		# All options and file name parameters
 466export _ADDOPTS_GROFF;		# Transp. options for groff (`eval').
 467export _ADDOPTS_POST;		# Transp. options postproc (`eval').
 468export _ADDOPTS_X;		# Transp. options X postproc (`eval').
 469export _APROPOS_PROG;		# Program to run apropos.
 470export _APROPOS_SECTIONS;	# Sections for different --apropos-*.
 471export _DEFAULT_MODES;		# Set default modes.
 472export _DISPLAY_MODE;		# Display mode.
 473export _DISPLAY_PROG;		# Viewer program to be used for display.
 474export _DISPLAY_ARGS;		# X resources for the viewer program.
 475export _FILEARGS;		# Stores filespec parameters.
 476export _FILESPEC_ARG;		# Stores the actual filespec parameter.
 477export _FUNC_STACK;		# Store debugging information.
 478export _REGISTERED_TITLE;	# Processed file names.
 479# _HAS_* from availability tests
 480export _HAS_COMPRESSION;	# `yes' if gzip compression is available
 481export _HAS_BZIP;		# `yes' if bzip2 compression is available
 482# _MAN_* finally used configuration of man searching
 483export _MAN_ALL;		# search all man pages per filespec
 484export _MAN_ENABLE;		# enable search for man pages
 485export _MAN_EXT;		# extension for man pages
 486export _MAN_FORCE;		# force file parameter to be man pages
 487export _MAN_IS_SETUP;		# setup man variables only once
 488export _MAN_LANG;		# language for man pages
 489export _MAN_LANG2;		# language for man pages
 490export _MAN_LANG_DONE;		# language dirs added to man path
 491export _MAN_PATH;		# search path for man pages
 492export _MAN_SEC;		# sections for man pages; sep. `:'
 493export _MAN_SEC_DONE;		# sections added to man path
 494export _MAN_SYS;		# system names for man pages; sep. `,'
 495export _MAN_SYS;		# system names added to man path
 496# _MANOPT_* as parsed from $MANOPT
 497export _MANOPT_ALL;		# $MANOPT --all
 498export _MANOPT_EXTENSION;	# $MANOPT --extension
 499export _MANOPT_LANG;		# $MANOPT --locale
 500export _MANOPT_PATH;		# $MANOPT --manpath
 501export _MANOPT_PAGER;		# $MANOPT --pager
 502export _MANOPT_SEC;		# $MANOPT --sections
 503export _MANOPT_SYS;		# $MANOPT --systems
 504# _OPT_* as parsed from groffer command line
 505export _OPT_ALL;		# display all suitable man pages.
 506export _OPT_APROPOS;		# call `apropos' program.
 507export _OPT_BD;			# set border color in some modes.
 508export _OPT_BG;			# set background color in some modes.
 509export _OPT_BW;			# set border width in some modes.
 510export _OPT_DEFAULT_MODES;	# `,'-list of modes when no mode given.
 511export _OPT_DEVICE;		# device option.
 512export _OPT_DO_NOTHING;		# do nothing in main_display().
 513export _OPT_DISPLAY;		# set X display.
 514export _OPT_FG;			# set foreground color in some modes.
 515export _OPT_FN;			# set font in some modes.
 516export _OPT_GEOMETRY;		# set size and position of viewer in X.
 517export _OPT_ICONIC;		# -iconic option for X viewers.
 518export _OPT_LANG;		# set language for man pages
 519export _OPT_LOCATION;		# print processed file names to stderr
 520export _OPT_MODE;		# values: X, tty, Q, Z, ""
 521export _OPT_MANPATH;		# manual setting of path for man-pages
 522export _OPT_PAGER;		# specify paging program for tty mode
 523export _OPT_RESOLUTION;		# set X resolution in dpi
 524export _OPT_RV;			# reverse fore- and background colors.
 525export _OPT_SECTIONS;		# sections for man page search
 526export _OPT_SYSTEMS;		# man pages of different OS's
 527export _OPT_TITLE;		# title for gxditview window
 528export _OPT_TEXT_DEVICE;	# set device for tty mode.
 529export _OPT_V;			# groff option -V.
 530export _OPT_VIEWER_DVI;		# viewer program for dvi mode
 531export _OPT_VIEWER_PDF;		# viewer program for pdf mode
 532export _OPT_VIEWER_PS;		# viewer program for ps mode
 533export _OPT_VIEWER_HTML;	# viewer program for html mode
 534export _OPT_VIEWER_X;		# viewer program for x mode
 535export _OPT_WHATIS;		# print the man description
 536export _OPT_XRM;		# specify X resource.
 537export _OPT_Z;			# groff option -Z.
 538export _OUTPUT_FILE_NAME;	# output generated, see main_set_res..()
 539export _VIEWER_TERMINAL;	# viewer options for terminal (--*-viewer-tty)
 540# _TMP_* temporary directory and files
 541export _TMP_DIR;		# groffer directory for temporary files
 542export _TMP_CAT;		# stores concatenation of everything
 543export _TMP_STDIN;		# stores stdin, if any
 544
 545# these variables are preset in section `Preset' after the rudim. test
 546
 547
 548########################################################################
 549# Preset and reset of read-write global variables
 550########################################################################
 551
 552
 553export _START_DIR;		# directory at start time of the script
 554_START_DIR="$(pwd)";
 555
 556# For variables that can be reset by option `--default', see reset().
 557
 558_FILEARGS='';
 559
 560# _HAS_* from availability tests
 561_HAS_COMPRESSION='';
 562_HAS_BZIP='';
 563
 564# _TMP_* temporary files
 565_TMP_DIR='';
 566_TMP_CAT='';
 567_TMP_CONF='';
 568_TMP_STDIN='';
 569
 570
 571########################################################################
 572# reset ()
 573#
 574# Reset the variables that can be affected by options to their default.
 575#
 576reset()
 577{
 578  if test "$#" -ne 0
 579  then
 580    error "reset() does not have arguments.";
 581  fi;
 582
 583  _ADDOPTS_GROFF='';
 584  _ADDOPTS_POST='';
 585  _ADDOPTS_X='';
 586  _APROPOS_PROG='';
 587  _APROPOS_SECTIONS='';
 588  _DISPLAY_ARGS='';
 589  _DISPLAY_MODE='';
 590  _DISPLAY_PROG='';
 591  _REGISTERED_TITLE='';
 592
 593  # _MAN_* finally used configuration of man searching
 594  _MAN_ALL='no';
 595  _MAN_ENABLE='yes';		# do search for man-pages
 596  _MAN_EXT='';
 597  _MAN_FORCE='no';		# first local file, then search man page
 598  _MAN_IS_SETUP='no';
 599  _MAN_LANG='';
 600  _MAN_LANG2='';
 601  _MAN_PATH='';
 602  _MAN_SEC='';
 603  _MAN_SEC_DONE='no';
 604  _MAN_SYS='';
 605  _MAN_SYS_DONE='no';
 606
 607  # _MANOPT_* as parsed from $MANOPT
 608  _MANOPT_ALL='no';
 609  _MANOPT_EXTENSION='';
 610  _MANOPT_LANG='';
 611  _MANOPT_PATH='';
 612  _MANOPT_PAGER='';
 613  _MANOPT_SEC='';
 614  _MANOPT_SYS='';
 615
 616  # _OPT_* as parsed from groffer command line
 617  _OPT_ALL='no';
 618  _OPT_APROPOS='no';
 619  _OPT_BD='';
 620  _OPT_BG='';
 621  _OPT_BW='';
 622  _OPT_DEFAULT_MODES='';
 623  _OPT_DEVICE='';
 624  _OPT_DISPLAY='';
 625  _OPT_DO_NOTHING='no';
 626  _OPT_FG='';
 627  _OPT_FN='';
 628  _OPT_GEOMETRY='';
 629  _OPT_ICONIC='no';
 630  _OPT_LANG='';
 631  _OPT_LOCATION='no';
 632  _OPT_MODE='';
 633  _OPT_MANPATH='';
 634  _OPT_PAGER='';
 635  _OPT_RESOLUTION='';
 636  _OPT_RV='no';
 637  _OPT_SECTIONS='';
 638  _OPT_SYSTEMS='';
 639  _OPT_TITLE='';
 640  _OPT_TEXT_DEVICE='';
 641  _OPT_V='no';
 642  _OPT_VIEWER_DVI='';
 643  _OPT_VIEWER_PDF='';
 644  _OPT_VIEWER_PS='';
 645  _OPT_VIEWER_HTML='';
 646  _OPT_VIEWER_X='';
 647  _OPT_WHATIS='no';
 648  _OPT_XRM='';
 649  _OPT_Z='no';
 650  _VIEWER_TERMINAL='no';
 651}
 652
 653reset;
 654
 655
 656########################################################################
 657#          Functions for error handling and debugging
 658########################################################################
 659
 660
 661##############
 662# echo1 (<text>*)
 663#
 664# Output to stdout.
 665#
 666# Arguments : arbitrary text including `-'.
 667#
 668echo1()
 669{
 670  cat <<EOF
 671$@
 672EOF
 673}
 674
 675
 676##############
 677# echo2 (<text>*)
 678#
 679# Output to stderr.
 680#
 681# Arguments : arbitrary text.
 682#
 683echo2()
 684{
 685  cat >&2 <<EOF
 686$@
 687EOF
 688}
 689
 690
 691##############
 692# landmark (<text>)
 693#
 694# Print <text> to standard error as a debugging aid.
 695#
 696# Globals: $_DEBUG_LM
 697#
 698landmark()
 699{
 700  if test _"${_DEBUG_LM}"_ = _yes_
 701  then
 702    echo2 "LM: $*";
 703  fi;
 704}
 705
 706landmark "1: debugging functions";
 707
 708
 709##############
 710# clean_up ()
 711#
 712# Clean up at exit.
 713#
 714clean_up()
 715{
 716  cd "${_START_DIR}" >"${_NULL_DEV}" 2>&1;
 717  if test _${_DEBUG_KEEP_FILES}_ = _yes_
 718  then
 719    echo2 "Kept temporary directory ${_TMP_DIR}."
 720  else
 721    if test _"${_TMP_DIR}"_ != __
 722    then
 723      if test -d "${_TMP_DIR}" || test -f "${_TMP_DIR}"
 724      then
 725        rm -f -r "${_TMP_DIR}" >${_NULL_DEV} 2>&1;
 726      fi; 
 727    fi;
 728  fi;
 729}
 730
 731
 732#############
 733# diag (text>*)
 734#
 735# Output a diagnostic message to stderr
 736#
 737diag()
 738{
 739  echo2 '>>>>>'"$*";
 740}
 741
 742
 743#############
 744# error (<text>*)
 745#
 746# Print an error message to standard error, print the function stack,
 747# exit with an error condition.  The argument should contain the name
 748# of the function from which it was called.  This is for system errors.
 749#
 750error()
 751{
 752  case "$#" in
 753    1) echo2 'groffer error: '"$1"; ;;
 754    *) echo2 'groffer error: wrong number of arguments in error().'; ;;
 755  esac;
 756  func_stack_dump;
 757  if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
 758  then
 759    : >"${_TMP_DIR}"/,error;
 760  fi;
 761  exit "${_ERROR}";
 762}
 763
 764
 765#############
 766# error_user (<text>*)
 767#
 768# Print an error message to standard error; exit with an error condition.
 769# The error is supposed to be produce by the user.  So the funtion stack
 770# is omitted.
 771#
 772error_user()
 773{
 774  case "$#" in
 775    1)
 776      echo2 'groffer error: '"$1";
 777       ;;
 778    *)
 779      echo2 'groffer error: wrong number of arguments in error_user().';
 780      ;;
 781  esac;
 782  if test _"${_DEBUG_USER_WITH_STACK}"_ = _yes_
 783  then
 784    func_stack_dump;
 785  fi;
 786  if test _"${_TMP_DIR}"_ != __ && test -d "${_TMP_DIR}"
 787  then
 788    : >"${_TMP_DIR}"/,error;
 789  fi;
 790  exit "${_ERROR}";
 791}
 792
 793
 794#############
 795# exit_test ()
 796#
 797# Test whether the former command ended with error().  Exit again.
 798#
 799# Globals: $_ERROR
 800#
 801exit_test()
 802{
 803  if test "$?" = "${_ERROR}"
 804  then
 805    exit ${_ERROR};
 806  fi;
 807  if test _"${_TMP_DIR}"_ != __ && test -f "${_TMP_DIR}"/,error
 808  then
 809    exit ${_ERROR};
 810  fi;
 811}
 812
 813
 814#############
 815# func_check (<func_name> <rel_op> <nr_args> "$@")
 816#
 817# Check number of arguments and register to _FUNC_STACK.
 818#
 819# Arguments: >=3
 820#   <func_name>: name of the calling function.
 821#   <rel_op>:    a relational operator: = != < > <= >=
 822#   <nr_args>:   number of arguments to be checked against <operator>
 823#   "$@":        the arguments of the calling function.
 824#
 825# Variable prefix: fc
 826#
 827func_check()
 828{
 829  if test "$#" -lt 3
 830  then
 831    error 'func_check() needs at least 3 arguments.';
 832  fi;
 833  fc_fname="$1";
 834  case "$3" in
 835    1)
 836      fc_nargs="$3";
 837      fc_s='';
 838      ;;
 839    0|[2-9])
 840      fc_nargs="$3";
 841      fc_s='s';
 842      ;;
 843    *)
 844      error "func_check(): third argument must be a digit.";
 845      ;;
 846  esac;
 847  case "$2" in
 848    '='|'-eq')
 849      fc_op='-eq';
 850      fc_comp='exactly';
 851      ;;
 852    '>='|'-ge')
 853      fc_op='-ge';
 854      fc_comp='at least';
 855      ;;
 856    '<='|'-le')
 857      fc_op='-le';
 858      fc_comp='at most';
 859      ;;
 860    '<'|'-lt')
 861      fc_op='-lt';
 862      fc_comp='less than';
 863      ;;
 864    '>'|'-gt')
 865      fc_op='-gt';
 866      fc_comp='more than';
 867      ;;
 868    '!='|'-ne')
 869      fc_op='-ne';
 870      fc_comp='not';
 871      ;;
 872    *)
 873      error \
 874        'func_check(): second argument is not a relational operator.';
 875      ;;
 876  esac;
 877  shift;
 878  shift;
 879  shift;
 880  if test "$#" "${fc_op}" "${fc_nargs}"
 881  then
 882    do_nothing;
 883  else
 884    error "func_check(): \
 885${fc_fname}"'() needs '"${fc_comp} ${fc_nargs}"' argument'"${fc_s}"'.';
 886  fi;
 887  func_push "${fc_fname}";
 888  if test _"${_DEBUG_STACKS}"_ = _yes_
 889  then
 890    echo2 '+++ '"${fc_fname} $@";
 891    echo2 '>>> '"${_FUNC_STACK}";
 892  fi;
 893  eval ${_UNSET} fc_comp;
 894  eval ${_UNSET} fc_fname;
 895  eval ${_UNSET} fc_nargs;
 896  eval ${_UNSET} fc_op;
 897  eval ${_UNSET} fc_s;
 898}
 899
 900
 901#############
 902# func_pop ()
 903#
 904# Retrieve the top element from the stack.
 905#
 906# The stack elements are separated by `!'; the popped element is
 907# identical to the original element, except that all `!' characters
 908# were removed.
 909#
 910# Arguments: 1
 911#
 912func_pop()
 913{
 914  if test "$#" -ne 0
 915  then
 916    error 'func_pop() does not have arguments.';
 917  fi;
 918  case "${_FUNC_STACK}" in
 919  '')
 920    if test _"${_DEBUG_STACKS}"_ = _yes_
 921    then
 922      error 'func_pop(): stack is empty.';
 923    fi;
 924    ;;
 925  *!*)
 926    # split at first bang `!'.
 927    _FUNC_STACK="$(echo1 "${_FUNC_STACK}" | sed -e 's/^[^!]*!//')";
 928    exit_test;
 929    ;;
 930  *)
 931    _FUNC_STACK='';
 932    ;;
 933  esac;
 934  if test _"${_DEBUG_STACKS}"_ = _yes_
 935  then
 936    echo2 '<<< '"${_FUNC_STACK}";
 937  fi;
 938}
 939
 940
 941#############
 942# func_push (<element>)
 943#
 944# Store another element to stack.
 945#
 946# The stack elements are separated by `!'; if <element> contains a `!'
 947# it is removed first.
 948#
 949# Arguments: 1
 950#
 951# Variable prefix: fp
 952#
 953func_push()
 954{
 955  if test "$#" -ne 1
 956  then
 957    error 'func_push() needs 1 argument.';
 958  fi;
 959  case "$1" in
 960  *'!'*)
 961    # remove all bangs `!'.
 962    fp_element="$(echo1 "$1" | sed -e 's/!//g')";
 963    exit_test;
 964    ;;
 965  *)
 966    fp_element="$1";
 967    ;;
 968  esac;
 969  if test _"${_FUNC_STACK}"_ = __
 970  then
 971    _FUNC_STACK="${fp_element}";
 972  else
 973    _FUNC_STACK="${fp_element}!${_FUNC_STACK}";
 974  fi;
 975  eval ${_UNSET} fp_element;
 976}
 977
 978
 979#############
 980# func_stack_dump ()
 981#
 982# Print the content of the stack.  Ignore the arguments.
 983#
 984func_stack_dump()
 985{
 986  diag 'call stack: '"${_FUNC_STACK}";
 987}
 988
 989
 990########################################################################
 991#                        System Test
 992########################################################################
 993
 994landmark "2: system test";
 995
 996# Test the availability of the system utilities used in this script.
 997
 998
 999########################################################################
1000# Test of function `sed'.
1001#
1002
1003if test _"$(echo xTesTx \
1004           | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
1005           | sed -e 's|T|t|g')"_ != _test_
1006then
1007  error 'Test of "sed" command failed.';
1008fi;
1009
1010
1011########################################################################
1012# Test of function `cat'.
1013#
1014if test _"$(echo test | cat)"_ != _test_
1015then
1016  error 'Test of "cat" command failed.';
1017fi;
1018
1019
1020########################################################################
1021# Test for compression.
1022#
1023if test _"$(echo 'test' | gzip -c -d -f - 2>${_NULL_DEV})"_ = _test_
1024then
1025  _HAS_COMPRESSION='yes';
1026  if echo1 'test' | bzip2 -c 2>${_NULL_DEV} | bzip2 -t 2>${_NULL_DEV} \
1027     && test _"$(echo 'test' | bzip2 -c 2>${_NULL_DEV} \
1028                             | bzip2 -d -c 2>${_NULL_DEV})"_ \
1029             = _test_
1030  then
1031    _HAS_BZIP='yes';
1032  else
1033    _HAS_BZIP='no';
1034  fi;
1035else
1036  _HAS_COMPRESSION='no';
1037  _HAS_BZIP='no';
1038fi;
1039
1040
1041########################################################################
1042#       Definition of normal Functions in alphabetical order
1043########################################################################
1044landmark "3: functions";
1045
1046########################################################################
1047# apropos_filespec ()
1048#
1049# Setup for the --apropos* options
1050#
1051apropos_filespec()
1052{
1053
1054  func_check apropos_filespec '=' 0 "$@";
1055  if obj _OPT_APROPOS is_yes
1056  then
1057    eval to_tmp_line \
1058      "'.SH $(echo1 "${_FILESPEC_ARG}" | sed 's/[^\\]-/\\-/g')'";
1059    exit_test;
1060    if obj _APROPOS_PROG is_empty
1061    then
1062      error 'apropos_filespec: apropos_setup() must be run first.';
1063    fi;
1064    if obj _APROPOS_SECTIONS is_empty
1065    then
1066      if obj _OPT_SECTIONS is_empty
1067      then
1068        s='^.*(.*).*$';
1069      else
1070        s='^.*(['"$(echo1 "${_OPT_SECTIONS}" | sed -e 's/://g')"']';
1071      fi;
1072    else
1073      s='^.*(['"${_APROPOS_SECTIONS}"']';
1074    fi;
1075    eval "${_APROPOS_PROG}" "'${_FILESPEC_ARG}'" | \
1076      sed -n -e '
1077/^'"${_FILESPEC_ARG}"': /p
1078/'"$s"'/p
1079' | \
1080      sort |\
1081      sed -e '
1082s/^\(.* (..*)\)  *-  *\(.*\)$/\.br\n\.TP 15\n\.BR \1\n\2/
1083' >>"${_TMP_CAT}";
1084  fi;
1085  eval "${return_ok}";
1086}
1087
1088
1089########################################################################
1090# apropos_setup ()
1091#
1092# Setup for the --apropos* options
1093#
1094apropos_setup()
1095{
1096  func_check apropos_setup '=' 0 "$@";
1097  if obj _OPT_APROPOS is_yes
1098  then
1099    if is_prog apropos
1100    then
1101      _APROPOS_PROG='apropos';
1102    elif is_prog man
1103    then
1104      if man --apropos man >${_NULL_DEV} 2>${_NULL_DEV}
1105      then
1106        _APROPOS_PROG='man --apropos';
1107      elif man -k man >${_NULL_DEV} 2>${_NULL_DEV}
1108      then
1109        _APROPOS_PROG='man -k';
1110      fi;
1111    fi;
1112    if obj _APROPOS_PROG is_empty
1113    then
1114      error 'apropos_setup: no apropos program available.';
1115    fi;
1116    to_tmp_line '.TH GROFFER APROPOS';
1117  fi;
1118  eval "${return_ok}";
1119}
1120
1121
1122########################################################################
1123# base_name (<path>)
1124#
1125# Get the file name part of <path>, i.e. delete everything up to last
1126# `/' from the beginning of <path>.  Remove final slashes, too, to get a
1127# non-empty output.
1128#
1129# Arguments : 1
1130# Output    : the file name part (without slashes)
1131#
1132# Variable prefix: bn
1133#
1134base_name()
1135{
1136  func_check base_name = 1 "$@";
1137  bn_name="$1";
1138  case "${bn_name}" in
1139    */)
1140      # delete all final slashes
1141      bn_name="$(echo1 "${bn_name}" | sed -e 's|//*$||')";
1142      exit_test;
1143      ;;
1144  esac;
1145  case "${bn_name}" in
1146    /|'')
1147      eval ${_UNSET} bn_name;
1148      eval "${return_bad}";
1149      ;;
1150    */*)
1151      # delete everything before and including the last slash `/'.
1152      echo1 "${bn_name}" | sed -e 's|^.*//*\([^/]*\)$|\1|';
1153      ;;
1154    *)
1155      obj bn_name echo1;
1156      ;;
1157  esac;
1158  eval ${_UNSET} bn_name;
1159  eval "${return_ok}";
1160}
1161
1162
1163########################################################################
1164# cat_z (<file>)
1165#
1166# Decompress if possible or just print <file> to standard output.
1167#
1168# gzip, bzip2, and .Z decompression is supported.
1169#
1170# Arguments: 1, a file name.
1171# Output: the content of <file>, possibly decompressed.
1172#
1173if test _"${_HAS_COMPRESSION}"_ = _yes_
1174then
1175  cat_z()
1176  {
1177    func_check cat_z = 1 "$@";
1178    case "$1" in
1179      '')
1180        error 'cat_z(): empty file name';
1181        ;;
1182      '-')
1183        error 'cat_z(): for standard input use save_stdin()';
1184        ;;
1185    esac;
1186    if obj _HAS_BZIP is_yes
1187    then
1188      if bzip2 -t "$1" 2>${_NULL_DEV}
1189      then
1190        bzip2 -c -d "$1" 2>${_NULL_DEV};
1191        eval "${return_ok}";
1192      fi;
1193    fi;
1194    gzip -c -d -f "$1" 2>${_NULL_DEV};
1195    eval "${return_ok}";
1196  }
1197else
1198  cat_z()
1199  {
1200    func_check cat_z = 1 "$@";
1201    cat "$1";
1202    eval "${return_ok}";
1203  }
1204fi;
1205
1206
1207########################################################################
1208# clean_up ()
1209#
1210# Do the final cleaning up before exiting; used by the trap calls.
1211#
1212# defined above
1213
1214
1215########################################################################
1216# diag (<text>*)
1217#
1218# Print marked message to standard error; useful for debugging.
1219#
1220# defined above
1221
1222
1223########################################################################
1224landmark '4: dirname()*';
1225########################################################################
1226
1227#######################################################################
1228# dirname_append (<dir> <name>)
1229#
1230# Append `name' to `dir' with clean handling of `/'.
1231#
1232# Arguments : 2
1233# Output    : the generated new directory name <dir>/<name>
1234#
1235dirname_append()
1236{
1237  func_check dirname_append = 2 "$@";
1238  if is_empty "$1"
1239  then
1240    error "dir_append(): first argument is empty.";
1241  fi;
1242  if is_empty "$2"
1243  then
1244    echo1 "$1";
1245  else
1246    dirname_chop "$1"/"$2";
1247  fi;
1248  eval "${return_ok}";
1249}
1250
1251
1252########################################################################
1253# dirname_chop (<name>)
1254#
1255# Remove unnecessary slashes from directory name.
1256#
1257# Argument: 1, a directory name.
1258# Output:   path without double, or trailing slashes.
1259#
1260# Variable prefix: dc
1261#
1262dirname_chop()
1263{
1264  func_check dirname_chop = 1 "$@";
1265  # replace all multiple slashes by a single slash `/'.
1266  dc_res="$(echo1 "$1" | sed -e 's|///*|/|g')";
1267  exit_test;
1268  case "${dc_res}" in
1269  ?*/)
1270    # remove trailing slash '/';
1271    echo1 "${dc_res}" | sed -e 's|/$||';
1272    ;;
1273  *)
1274    obj dc_res echo1
1275    ;;
1276  esac;
1277  eval ${_UNSET} dc_res;
1278  eval "${return_ok}";
1279}
1280
1281
1282########################################################################
1283# do_filearg (<filearg>)
1284#
1285# Append the file, man-page, or standard input corresponding to the
1286# argument to the temporary file.  If this is compressed in the gzip
1287# or Z format it is decompressed.  A title element is generated.
1288#
1289# Argument either:
1290#   - name of an existing file.
1291#   - `-' to represent standard input (several times allowed).
1292#   - `man:name.(section)' the man-page for `name' in `section'.
1293#   - `man:name.section' the man-page for `name' in `section'.
1294#   - `man:name' the man-page for `name' in the lowest `section'.
1295#   - `name.section' the man-page for `name' in `section'.
1296#   - `name' the man-page for `name' in the lowest `section'.
1297# Globals :
1298#   $_TMP_STDIN, $_MAN_ENABLE, $_MAN_IS_SETUP, $_OPT_MAN
1299#
1300# Output  : none
1301# Return  : $_GOOD if found, ${_BAD} otherwise.
1302#
1303# Variable prefix: df
1304#
1305do_filearg()
1306{
1307  func_check do_filearg = 1 "$@";
1308  df_filespec="$1";
1309  # store sequence into positional parameters
1310  case "${df_filespec}" in
1311  '')
1312    eval ${_UNSET} df_filespec;
1313    eval "${return_good}";
1314    ;;
1315  '-')
1316    register_file '-';
1317    eval ${_UNSET} df_filespec;
1318    eval "${return_good}";
1319    ;;
1320  */*)			       # with directory part; so no man search
1321    set 'File';
1322    ;;
1323  *)
1324    if obj _MAN_ENABLE is_yes
1325    then
1326      if obj _MAN_FORCE is_yes
1327      then
1328        set 'Manpage' 'File';
1329      else
1330        set 'File' 'Manpage';
1331      fi;
1332      else
1333      set 'File';
1334    fi;
1335    ;;
1336  esac;
1337  for i
1338  do
1339    case "$i" in
1340    File)
1341      if test -f "${df_filespec}"
1342      then
1343        if test -r "${df_filespec}"
1344        then
1345          register_file "${df_filespec}";
1346          eval ${_UNSET} df_filespec;
1347          eval ${_UNSET} df_no_man;
1348          eval "${return_good}";
1349        else
1350          echo2 "could not read \`${df_filespec}'";
1351          eval ${_UNSET} df_filespec;
1352          eval ${_UNSET} df_no_man;
1353          eval "${return_bad}";
1354        fi;
1355      else
1356        if obj df_no_man is_not_empty
1357        then
1358          if obj _OPT_WHATIS is_yes
1359          then
1360            to_tmp_line "This is neither a file nor a man page."
1361          else
1362            echo2 "\`${df_filespec}' is neither a file nor a man page."
1363          fi;
1364        fi;
1365        df_no_file=yes;
1366        continue;
1367      fi;
1368      ;;
1369    Manpage)			# parse filespec as man page
1370      if obj _MAN_IS_SETUP is_not_yes
1371      then
1372        man_setup;
1373      fi;
1374      if man_do_filespec "${df_filespec}"
1375      then
1376        eval ${_UNSET} df_filespec;
1377        eval ${_UNSET} df_no_file;
1378        eval "${return_good}";
1379      else
1380        if obj df_no_file is_not_empty
1381        then
1382          if obj _OPT_WHATIS is_yes
1383          then
1384            to_tmp_line "This is neither a file nor a man page."
1385          else
1386            echo2 "\`${df_filespec}' is neither a file nor a man page."
1387          fi;
1388        fi;
1389        df_no_man=yes;
1390        continue;
1391      fi;
1392      ;;
1393    esac;
1394  done;
1395  eval ${_UNSET} df_filespec;
1396  eval ${_UNSET} df_no_file;
1397  eval ${_UNSET} df_no_man;
1398  eval "${return_bad}";
1399} # do_filearg()
1400
1401
1402########################################################################
1403# do_nothing ()
1404#
1405# Dummy function.
1406#
1407do_nothing()
1408{
1409  eval return "${_OK}";
1410}
1411
1412
1413########################################################################
1414# echo2 (<text>*)
1415#
1416# Print to standard error with final line break.
1417#
1418# defined above
1419
1420
1421########################################################################
1422# error (<text>*)
1423#
1424# Print error message and exit with error code.
1425#
1426# defined above
1427
1428
1429########################################################################
1430# exit_test ()
1431#
1432# Test whether the former command ended with error().  Exit again.
1433#
1434# defined above
1435
1436
1437########################################################################
1438# func_check (<func_name> <rel_op> <nr_args> "$@")
1439#
1440# Check number of arguments and register to _FUNC_STACK.
1441#
1442# Arguments: >=3
1443#   <func_name>: name of the calling function.
1444#   <rel_op>:    a relational operator: = != < > <= >=
1445#   <nr_args>:   number of arguments to be checked against <operator>
1446#   "$@":        the arguments of the calling function.
1447#
1448# defined above
1449
1450#########################################################################
1451# func_pop ()
1452#
1453# Delete the top element from the function call stack.
1454#
1455# defined above
1456
1457
1458########################################################################
1459# func_push (<element>)
1460#
1461# Store another element to function call stack.
1462#
1463# defined above
1464
1465
1466########################################################################
1467# func_stack_dump ()
1468#
1469# Print the content of the stack.
1470#
1471# defined above
1472
1473
1474########################################################################
1475# get_first_essential (<arg>*)
1476#
1477# Retrieve first non-empty argument.
1478#
1479# Return  : `1' if all arguments are empty, `0' if found.
1480# Output  : the retrieved non-empty argument.
1481#
1482# Variable prefix: gfe
1483#
1484get_first_essential()
1485{
1486  func_check get_first_essential '>=' 0 "$@";
1487  if is_equal "$#" 0
1488  then
1489    eval "${return_ok}";
1490  fi;
1491  for i
1492  do
1493    gfe_var="$i";
1494    if obj gfe_var is_not_empty
1495    then
1496      obj gfe_var echo1;
1497      eval ${_UNSET} gfe_var;
1498      eval "${return_ok}";
1499    fi;
1500  done;
1501  eval ${_UNSET} gfe_var;
1502  eval "${return_bad}";
1503}
1504
1505
1506########################################################################
1507landmark '5: is_*()';
1508########################################################################
1509
1510########################################################################
1511# is_dir (<name>)
1512#
1513# Test whether `name' is a directory.
1514#
1515# Arguments : 1
1516# Return    : `0' if arg1 is a directory, `1' otherwise.
1517#
1518is_dir()
1519{
1520  func_check is_dir '=' 1 "$@";
1521  if test _"$1"_ != __ && test -d "$1" && test -r "$1"
1522  then
1523    eval "${return_yes}";
1524  fi;
1525  eval "${return_no}";
1526}
1527
1528
1529########################################################################
1530# is_empty (<string>)
1531#
1532# Test whether `string' is empty.
1533#
1534# Arguments : <=1
1535# Return    : `0' if arg1 is empty or does not exist, `1' otherwise.
1536#
1537is_empty()
1538{
1539  func_check is_empty '=' 1 "$@";
1540  if test _"$1"_ = __
1541  then
1542    eval "${return_yes}";
1543  fi;
1544  eval "${return_no}";
1545}
1546
1547
1548########################################################################
1549# is_equal (<string1> <string2>)
1550#
1551# Test whether `string1' is equal to <string2>.
1552#
1553# Arguments : 2
1554# Return    : `0' both arguments are equal strings, `1' otherwise.
1555#
1556is_equal()
1557{
1558  func_check is_equal '=' 2 "$@";
1559  if test _"$1"_ = _"$2"_
1560  then
1561    eval "${return_yes}";
1562  fi;
1563  eval "${return_no}";
1564}
1565
1566
1567########################################################################
1568# is_existing (<name>)
1569#
1570# Test whether `name' is an existing file or directory.  Solaris 2.5 does
1571# not have `test -e'.
1572#
1573# Arguments : 1
1574# Return    : `0' if arg1 exists, `1' otherwise.
1575#
1576is_existing()
1577{
1578  func_check is_existing '=' 1 "$@";
1579  if test _"$1"_ = __
1580  then
1581    eval "${return_no}";
1582  fi;
1583  if test -f "$1" || test -d "$1" || test -c "$1"
1584  then
1585    eval "${return_yes}";
1586  fi;
1587  eval "${return_no}";
1588}
1589
1590
1591########################################################################
1592# is_file (<name>)
1593#
1594# Test whether `name' is a readable file.
1595#
1596# Arguments : 1
1597# Return    : `0' if arg1 is a readable file, `1' otherwise.
1598#
1599is_file()
1600{
1601  func_check is_file '=' 1 "$@";
1602  if is_not_empty "$1" && test -f "$1" && test -r "$1"
1603  then
1604    eval "${return_yes}";
1605  fi;
1606  eval "${return_no}";
1607}
1608
1609
1610########################################################################
1611# is_non_empty_file (<file_name>)
1612#
1613# Test whether `file_name' is a non-empty existing file.
1614#
1615# Arguments : <=1
1616# Return    :
1617#   `0' if arg1 is a non-empty existing file
1618#   `1' otherwise
1619#
1620is_non_empty_file()
1621{
1622  func_check is_non_empty_file '=' 1 "$@";
1623  if is_file "$1" && test -s "$1"
1624  then
1625    eval "${return_yes}";
1626  fi;
1627  eval "${return_no}";
1628}
1629
1630
1631########################################################################
1632# is_not_dir (<name>)
1633#
1634# Test whether `name' is not a readable directory.
1635#
1636# Arguments : 1
1637# Return    : `0' if arg1 is a directory, `1' otherwise.
1638#
1639is_not_dir()
1640{
1641  func_check is_not_dir '=' 1 "$@";
1642  if is_dir "$1"
1643  then
1644    eval "${return_no}";
1645  fi;
1646  eval "${return_yes}";
1647}
1648
1649
1650########################################################################
1651# is_not_empty (<string>)
1652#
1653# Test whether `string' is not empty.
1654#
1655# Arguments : <=1
1656# Return    : `0' if arg1 exists and is not empty, `1' otherwise.
1657#
1658is_not_empty()
1659{
1660  func_check is_not_empty '=' 1 "$@";
1661  if is_empty "$1"
1662  then
1663    eval "${return_no}";
1664  fi;
1665  eval "${return_yes}";
1666}
1667
1668
1669########################################################################
1670# is_not_equal (<string1> <string2>)
1671#
1672# Test whether `string1' differs from `string2'.
1673#
1674# Arguments : 2
1675#
1676is_not_equal()
1677{
1678  func_check is_not_equal '=' 2 "$@";
1679  if is_equal "$1" "$2"
1680  then
1681    eval "${return_no}";
1682  fi
1683  eval "${return_yes}";
1684}
1685
1686
1687########################################################################
1688# is_not_file (<filename>)
1689#
1690# Test whether `name' is a not readable file.
1691#
1692# Arguments : 1 (empty allowed)
1693#
1694is_not_file()
1695{
1696  func_check is_not_file '=' 1 "$@";
1697  if is_file "$1"
1698  then
1699    eval "${return_no}";
1700  fi;
1701  eval "${return_yes}";
1702}
1703
1704
1705########################################################################
1706# is_not_prog ([<name> [<arg>*]])
1707#
1708# Verify that arg is a not program in $PATH.
1709#
1710# Arguments : >=0 (empty allowed)
1711#   more args are ignored, this allows to specify progs with arguments
1712#
1713is_not_prog()
1714{
1715  func_check is_not_prog '>=' 0 "$@";
1716  case "$#" in
1717  0)
1718    eval "${return_yes}";
1719    ;;
1720  *)
1721    if where_is "$1" >${_NULL_DEV}
1722    then
1723      eval "${return_no}";
1724    fi;
1725    ;;
1726  esac
1727  eval "${return_yes}";
1728}
1729
1730
1731########################################################################
1732# is_not_writable (<name>)
1733#
1734# Test whether `name' is a not a writable file or directory.
1735#
1736# Arguments : >=1 (empty allowed), more args are ignored
1737#
1738is_not_writable()
1739{
1740  func_check is_not_writable '>=' 1 "$@";
1741  if is_writable "$1"
1742  then
1743    eval "${return_no}";
1744  fi;
1745  eval "${return_yes}";
1746}
1747
1748
1749########################################################################
1750# is_not_X ()
1751#
1752# Test whether not running in X Window by checking $DISPLAY
1753#
1754is_not_X()
1755{
1756  func_check is_X '=' 0 "$@";
1757  if obj DISPLAY is_empty
1758  then
1759    eval "${return_yes}";
1760  fi;
1761  eval "${return_no}";
1762}
1763
1764
1765########################################################################
1766# is_not_yes (<string>)
1767#
1768# Test whether `string' is not "yes".
1769#
1770# Arguments : 1
1771#
1772is_not_yes()
1773{
1774  func_check is_not_yes = 1 "$@";
1775  if is_yes "$1"
1776  then
1777    eval "${return_no}";
1778  fi;
1779  eval "${return_yes}";
1780}
1781
1782
1783########################################################################
1784# is_prog ([<name> [<arg>*]])
1785#
1786# Determine whether <name> is a program in $PATH
1787#
1788# Arguments : >=0 (empty allowed)
1789#   <arg>* are ignored, this allows to specify progs with arguments.
1790#
1791is_prog()
1792{
1793  func_check is_prog '>=' 0 "$@";
1794  case "$#" in
1795  0)
1796    eval "${return_no}";
1797    ;;
1798  *)
1799    if where_is "$1" >${_NULL_DEV}
1800    then
1801      eval "${return_yes}";
1802    fi;
1803    ;;
1804  esac
1805  eval "${return_no}";
1806}
1807
1808
1809########################################################################
1810# is_writable (<name>)
1811#
1812# Test whether `name' is a writable file or directory.
1813#
1814# Arguments : >=1 (empty allowed), more args are ignored
1815#
1816is_writable()
1817{
1818  func_check is_writable '>=' 1 "$@";
1819  if test _"$1"_ = __
1820  then
1821    eval "${return_no}";
1822  fi;
1823  if test -r "$1"
1824  then
1825    if test -w "$1"
1826    then
1827      eval "${return_yes}";
1828    fi;
1829  fi;
1830  eval "${return_no}";
1831}
1832
1833
1834########################################################################
1835# is_X ()
1836#
1837# Test whether running in X Window by checking $DISPLAY
1838#
1839is_X()
1840{
1841  func_check is_X '=' 0 "$@";
1842  if obj DISPLAY is_not_empty
1843  then
1844    eval "${return_yes}";
1845  fi;
1846  eval "${return_no}";
1847}
1848
1849
1850########################################################################
1851# is_yes (<string>)
1852#
1853# Test whether `string' has value "yes".
1854#
1855# Return    : `0' if arg1 is `yes', `1' otherwise.
1856#
1857is_yes()
1858{
1859  func_check is_yes '=' 1 "$@";
1860  if is_equal "$1" 'yes'
1861  then
1862    eval "${return_yes}";
1863  fi;
1864  eval "${return_no}";
1865}
1866
1867
1868########################################################################
1869# landmark ()
1870#
1871# Print debugging information on standard error if $_DEBUG_LM is `yes'.
1872#
1873# Globals: $_DEBUG_LM
1874#
1875# Defined in section `Debugging functions'.
1876
1877
1878########################################################################
1879# leave ([<code>])
1880#
1881# Clean exit without an error or with <code>.
1882#
1883leave()
1884{
1885  clean_up;
1886  if test $# = 0
1887  then
1888    exit "${_OK}";
1889  else
1890    exit "$1";
1891  fi;
1892}
1893
1894
1895########################################################################
1896landmark '6: list_*()';
1897########################################################################
1898#
1899# `list' is an object class that represents an array or list.  Its
1900# data consists of space-separated single-quoted elements.  So a list
1901# has the form "'first' 'second' '...' 'last'".  See list_append() for
1902# more details on the list structure.  The array elements of `list'
1903# can be get by `eval set x "$list"; shift`.
1904
1905
1906########################################################################
1907# list_append (<list> <element>...)
1908#
1909# Arguments: >=2
1910#   <list>: a variable name for a list of single-quoted elements
1911#   <element>:  some sequence of characters.
1912# Output: none, but $<list> is set to
1913#   if <list> is empty:  "'<element>' '...'"
1914#   otherwise:           "$list '<element>' ..."
1915#
1916# Variable prefix: la
1917#
1918list_append()
1919{
1920  func_check list_append '>=' 2 "$@";
1921  la_name="$1";
1922  eval la_list='"${'$1'}"';
1923  shift;
1924  for s
1925  do
1926    la_s="$s";
1927    case "${la_s}" in
1928    *\'*)
1929      # escape each single quote by replacing each
1930      # "'" (squote) by "'\''" (squote bslash squote squote);
1931      # note that the backslash must be doubled in the following `sed'
1932      la_element="$(echo1 "${la_s}" | sed -e 's/'"${_SQ}"'/&\\&&/g')";
1933      exit_test;
1934      ;;
1935    '')
1936      la_element="";
1937      ;;
1938    *)
1939      la_element="${la_s}";
1940      ;;
1941    esac;
1942    if obj la_list is_empty
1943    then
1944      la_list="'${la_element}'";
1945    else
1946      la_list="${la_list} '${la_element}'";
1947    fi;
1948  done;
1949  eval "${la_name}"='"${la_list}"';
1950  eval ${_UNSET} la_element;
1951  eval ${_UNSET} la_list;
1952  eval ${_UNSET} la_name;
1953  eval ${_UNSET} la_s;
1954  eval "${return_ok}";
1955}
1956
1957
1958########################################################################
1959# list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
1960#
1961# Transform command line arguments into a normalized form.
1962#
1963# Options, option arguments, and file parameters are identified and
1964# output each as a single-quoted argument of its own.  Options and
1965# file parameters are separated by a '--' argument.
1966#
1967# Arguments: >=1
1968#   <pre_name>: common part of a set of 4 environment variable names:
1969#     $<pre_name>_SHORT_NA:  list of short options without an arg.
1970#     $<pre_name>_SHORT_ARG: list of short options that have an arg.
1971#     $<pre_name>_LONG_NA:   list of long options without an arg.
1972#     $<pre_name>_LONG_ARG:  list of long options that have an arg.
1973#   <cmdline_arg>...: the arguments from a command line, such as "$@",
1974#                     the content of a variable, or direct arguments.
1975#
1976# Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
1977#
1978# Example:
1979#   list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
1980# If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
1981# none-empty option lists, this will result in printing:
1982#     '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
1983#
1984#   Use this function in the following way:
1985#     eval set x "$(args_norm PRE_NAME "$@")";
1986#     shift;
1987#     while test "$1" != '--'; do
1988#       case "$1" in
1989#       ...
1990#       esac;
1991#       shift;
1992#     done;
1993#     shift;         #skip '--'
1994#     # all positional parameters ("$@") left are file name parameters.
1995#
1996# Variable prefix: lfc
1997#
1998list_from_cmdline()
1999{
2000  func_check list_from_cmdline '>=' 1 "$@";
2001  lfc_short_n="$(obj_data "$1"_SHORT_NA)";  # short options, no argument
2002  lfc_short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
2003  lfc_long_n="$(obj_data "$1"_LONG_NA)";    # long options, no argument
2004  lfc_long_a="$(obj_data "$1"_LONG_ARG)";   # long options, with argument
2005  exit_test;
2006  if obj lfc_short_n is_empty
2007  then
2008    error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
2009  fi;
2010  if obj lfc_short_a is_empty
2011  then
2012    error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
2013  fi;
2014  if obj lfc_long_n is_empty
2015  then
2016    error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
2017  fi;
2018  if obj lfc_long_a is_empty
2019  then
2020    error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
2021  fi;
2022
2023  shift;
2024  if is_equal "$#" 0
2025  then
2026    echo1 --
2027    eval ${_UNSET} lfc_fparams;
2028    eval ${_UNSET} lfc_short_a;
2029    eval ${_UNSET} lfc_short_n;
2030    eval ${_UNSET} lfc_long_a;
2031    eval ${_UNSET} lfc_long_n;
2032    eval ${_UNSET} lfc_result;
2033    eval "${return_ok}";
2034  fi;
2035
2036  lfc_fparams='';
2037  lfc_result='';
2038  while test "$#" -ge 1
2039

Large files files are truncated, but you can click here to view the full file