#!/bin/ksh
\: # shadoe - debugger for k/sh scripts
#*TAG:58910 81:Apr 17 1997:0755:sh.d/shadoe:shadoe:
# @(#)shadoe.sh 1.0A 1997/03 bsh29256@atc.fhda.edu (Brian S. Hiles)
# shadoe - "SHell And Debugger Observing Environment"
#  display and/or modify the environment in a running shell prog
# Author: bsh20858@atc.fhda.edu (Brian S. Hiles)
# Copyright: (c) 1996, 1997. All rights reserved for this ALPHA version
# Usage: shadoe [shadoe-options...] -- shprog [shprog-options...]
#
# A component of my SHell Integrated Development Environment ("shide") project.
# Advisor: instructor Roberta Harvey of Foothill Coll., Los Altos Hills, CA.

# example: shadoe -ox shprog [opts]
# Track all changed variables and their attributes, showing old values
# when they change. Shprog commands are displayed as they are executed.
#
# example: shadoe -e -t var1,var2 shprog [opts]
# Track variables var1 and var2 and their attributes, displaying
# any changed environment on an error.
#
# example: shadoe -aaev -g 100 -r 2+_qlnnodisp,120 shprog [opts]
# On the occurrence of any error from the second line to the 20th
# line of script "shprog <opts>", show the complete environment if
# it has changed. Commands are displayed to stderr as they are read.
#
# The above options may be placed into variable SHADOERC or file
# .shadoerc for automatic inclusion into each "shadoe" command line.
# Also, optional files shadoe.pre, shadoe.trans, and shadoe.post will
# be sourced before, at each trap, and at termination of the shprog.
#
# Shadoe will display the current environment with the program spec-
# ified with the variable VISUAL, or if that is unset or null, var-
# iable EDITOR, or if that is unset or null, variable PAGER, else
# "pg". To modify the environment dynamically, edit the displayed
# environment file if using an editor, or if using a pager use the
# shell escape mechanism to edit either file "~/<shprog>.env" or
# file "~/<shprog>.denv". The changes will be automatic in the run-
# ning shell program when returning. A trap on ERR will only display
# upon a changed environment; set _qcontrol<0 to force a display.
#
# Shadoe purposely doesn't track variables, aliases, and functions
# with names beginning with "_q", and the special variables LINENO,
# PS4, RANDOM, SECONDS, and (unless option -u is specified) _, due
# to the fact that their values would necessarily change from line
# to line. Shadoe (may) subsume variable PS4, the tagged attribute
# on variables, aliases for "exit" and "limit", the traced and
# autoloaded attributes on functions, and the DEBUG and/or ERR trap.
#
# One "-a" option is made default, as shadoe runs a "quick and
# dirty" variable trace without any. For additional caveats,
# search on the strings "Diagnostic", "Ksh Bug", and "Warning".
# Try running shadoe on itself to discern more of its internals.

#01 FILES
#
# significant if present:
# .shadoerc  - optional file of default command line options(*)
# shadoe.pre  - optional file of code to source before execution(*)
# shadoe.trans  - optional file of code to source on each trap
# shadoe.post  - optional file of code to source after execution(*)
# (*) sourced/read in the environment of the debugger, not the shprog.
#
# created in directory $TMPDIR/_q$$.d:
# _qcenv  - current environment state after current execution
# ~/<shprog>.env - file alias of the above
# _qe2disp.sed  - sed script to create env display
# _qdenv  - holds difference between old and current environment
# ~/<shprog>.denv - file alias of the above
# _qoenv  - old environment state from last execution
# _qshadoe  - autoloaded debugger function
# _qstatus  - file holding termination status prompt of shprog
# _qtmp
#
# files left after termination:
# <shprog>.env  - file copy of last env
# shadoe.out  - file of all stderr output of shprog and debugger
# shadoe.sa  - standalone version of munged shprog (-z option)

#02 USAGE REPORT
# default options are: -ad -g0 -r1,   (and, only for ksh88: -k)
_USAGE=\
'shadoe [-d|-e] [-acikmouvwxz] [-fpt <string>] [-glnr <expr>] shprog [opts]
-a              - print out addition information, not just variable values(*)
-c              - execute shprog within a cleared environment
-d              - display the environment when it changes (default)
-e              - display the environment only when an error occurs
-f fn[,...]     - apply -x option to comma-separated list of function names(*)
-g expr         - globally offset LINENO by <expr> in shprog (default: 0)
-i              - attempt to ignore trap 0 (EXIT) in shprog
-k              - if exists, source the per-process ENV script (default)
-l expr[,...]   - set debug trap at comma-separated list of line numbers(*)
-m              - "manual" mode: script itself expected to invoke debugging
-n expr[,...]   - like -l option, except force display of environment(*)
-o              - show old values of reassigned variables/aliases/traps also
-p file         - use file <file> as previous environment display
-r expr[,expr]  - specify range of lines to begin [and end] debugging
-s shell        - force the use of shell <shell> (default: $SHELL)
-t var[,...]    - track only vars specified by the comma-separated list(*)
-u              - track variable underscore ("_") also (default: ignored)
-v              - print shell input lines as they are read
-w              - source shadoe.trans when at trap (default: only when diff env)
-x              - print commands as they are executed
-z              - at termination, create standalone shprog version "shadoe.sa"
-?              - show this usage report
(*) option may be specified multiple times to increase scope of option.'

#03 LOAD RC OPTIONS
# introduce one '-a' option; it may be overruled by an explicit '+a' option.
# if desiring to suppress initializing from .shadoerc, set SHADOERC=' '.
if [[ -n $SHADOERC ]]
then \set -- -a $SHADOERC "$@"
elif [[ -f .shadoerc && -r .shadoerc ]]
then \set -- -a $(<.shadoerc) "$@"
elif [[ -f ~/.shadoerc && -r ~/.shadoerc ]]
then \set -- -a $(<~/.shadoerc) "$@"
else \set -- -a "$@"
fi

#04 PARSE OPTIONS
# Warning: in ksh93: change ":ab..." below to ":+ab..." for ksh88 compatibility
while getopts :abcdf:g:ikl:mn:op:r:s:t:uvxz _inst
do case $_inst in
 (a) _addout="$_addout,ON" ;;
 (+a) _addout=${_addout#,ON} ;;
 (c) _clearenv=ON ;;
 (+c) _clearenv= ;;
 (d) _debugtrap=ON _errtrap= ;; # mutually exclusive with -e
 (+d) _debugtrap= _errtrap=ON ;;
 (e) _debugtrap= _errtrap=ON ;; # mutually exclusive with -d
 (+e) _debugtrap=ON _errtrap= ;;
 (f) # specify option parameter "_qALL" to trace all functs.
  # option parameter "_qmain" is equivalent to -x option.
  _fntrace="$_fntrace,$OPTARG" ;;
 (g) _qlnnodisp=$OPTARG ;;
 (i) _ignexit=ON ;;
 (+i) _ignexit= ;;
 (k) # Warning: ksh93 sources $ENV file only when interactive
  _source_ENV_script=ON ;;
 (+k) _source_ENV_script= ;;
 (l) _lnnotrap=$_lnnotrap,$OPTARG ;;
 (m) _autostart= ;;
 (+m) _autostart=ON ;;
 (o) _showovalues=ON ;;
 (+o) _showovalues= ;;
 (p) # must conform to the internal format of an env file
  _oenv=$OPTARG ;;
 (r) if [[ $OPTARG = *,* ]]
  then [[ $OPTARG = *?,* ]] && _qbgnlnno=${OPTARG%%,*}
   [[ $OPTARG = *,?* ]] && _qendlnno=${OPTARG#*,}
  else _qbgnlnno=$OPTARG _qendlnno=$OPTARG
  fi ;;
 (s) # shell option(s) may be included within the option arg
  _qshell=$OPTARG ;;
 (t) _tagvars=$_tagvars,$OPTARG ;;
 (u) _uscore=ON ;;
 (+u) _uscore= ;;
 (v) _verbose=ON ;;
 (+v) _verbose= ;;
 (w) _whenenv= _whentrap=ON ;;
 (+w) _whenenv=ON _whentrap= ;;
 (x) _xtrace=ON ;;
 (+x) _xtrace= ;;
 (z) _dumpsrc=ON ;;
 (+z) _dumpsrc= ;;
 (:|\?|+\?)
  print -ru2 -- "$_USAGE"
  \exit 2 ;;
 esac
done
\shift OPTIND-1

PAGER= EDITOR= VISUAL= #XXX you will want to delete this eventually!
#05 DEFAULTS AND CHECKS
# Warning: all "_q*" variables should have no embedded newlines.
# Ksh Bug: rbrace in variable substitution is impossible, even if escaped.
_version='#. SHADOE 0.99B, ${_qshell##*/} $_src, %D, %H:%M' \
_RB=\} _TAB=' ' _showcode=$_verbose$_xtrace \eval _kshpath=$(whence -p $SHELL)
\: ${_qdir:=${TMPDIR:-/tmp}/_q$$.d/} ${_autostart=ON} \
${_debugtrap=ON} ${_profile[0]:=shadoe.pre} ${_profile[1]:=shadoe.trans} \
${_profile[2]:=shadoe.post} ${_kshpath:=/bin/ksh} ${_whenenv=ON} \
${_qprompt=$(tput -T$TERM smso)[\$1] ${0##*/}\>$(tput -T$TERM rmso) }
# advanced configuration flags: To assert, set to ON; to unassert, set to null
# example: dont_use_profiles=ON print_funct_names=ON shadoe -aa shprog opts
\: ${cvt_signames_nums=} # convert signal symbolic names to num equiv?
\: ${dont_use_profiles=} # do not use any pre/trans/post-profile files?
\: ${env_newlines=ON}  # display with _!NL!_s restored to newlines?
\: ${ignore_uscore_vars=} # ignore vars/aliases/functs with leading "_"?
\: ${print_funct_names=} # print all function names found in shprog?
\: ${skip_initial_env=}  # skip display of env inherited from parent?
\: ${trapno_cutoff=32}  # don't cvt trap names to nums >= this value.
    # Diagnostic 'sed: too many commands': set 0
if [[ -n $1 ]]
then _src=$1 \shift
 if [[ $_src = /* ]]
 then _src=/$_src
 elif [[ $_src != */* ]]
 then _src=./$_src
 fi
 \cd -- ${_src%/*} || \exit 1
 _src=${PWD%/}/${_src##*/}
 \cd - >&-
 [[ -f $_src && -r $_src && -s $_src ]] ||
 { print -ru2 "shadoe: error: \"$_src\" not a file," \
  'nonexistent, empty, or not readable'
  \exit 1
 }
else print -ru2 -- "$_USAGE"
 \exit 2
fi
${VERBOSE:+print -ru2 [ source file: $_src ]}
# Warning: set appropriate umask for security
[[ -d $_qdir ]] || /bin/mkdir -p $_qdir || \exit 3
\cd -- $_qdir || \exit 4
if [[ -n $_oenv ]]
then /bin/sed -n p $_oenv >|./_qoenv
else \: >|./_qoenv
fi
${VERBOSE:+print -ru2 [ environment file: ${_oenv:-$PWD/_qoenv} ]}
# determine if appropriate quoting implemented in "typeset -" output.
# Warning: if not implemented, need to _guess_ at var/value delimitation!
# Ksh Bug: i86 Solaris 2.x ksh[88i] fails in this respect.
\eval $(_inst='
' \typeset - | /bin/sed -n \
'/^_inst=$/q; s/.*/_quotedenv=ON/p; q')
# Diagnostic "different file systems": set variable TMPDIR
# to appropriate directory of same filesystem as your cwd.
if /bin/rm -f ./_qtmp
   /bin/ln -s /dev/null ./_qtmp
then _symlinkok=ON
 /bin/rm -f ./_qtmp
else _symlinkok=
fi 2>&-
for _inst in _addout _fntrace _tagvars
{ # strip extraneous left and right comma delimiters
 \eval $_inst=\$\{$_inst##+(,)\} $_inst=\$\{$_inst%%+(,)\}
}
IFS=" ,$IFS"
[[ -n $_addout ]] && \set -A _addout ${_addout[*]}
[[ -n $_tagvars ]] &&
{ [[ ,$_tagvars, = *,_,* ]] && _uscore=ON
 \set -A _tagvars -- $_tagvars
${VERBOSE:+print -ru2 [ tracing variables: ${_tagvars[*]} ]}
}
# Warning: if no -a option is specified, shadoe can only reliably function
# in ksh88 if no displayed variables in the shprog are multi-line.
[[ -n ${_addout[1]} || -n $cvt_signames_nums ]] &&
{ (($trapno_cutoff>0)) && [[ -n ${_addout[1]} ]] &&
 { # generate sed code to convert trap names to numbers
  _names2nums="$(
   print 't treset4\n: treset4'
   # Warning: ksh88 has arcane output format for "kill -l"
   # so /bin/kill command is used instead to list signals.
   \typeset -i _trapno=-1 idx
   for _inst in EXIT $(/bin/kill -l)
   { [[ $_inst = *[!0-9A-Z]* ]] && break
    (((_trapno+=1)>$trapno_cutoff)) && break
    { print -r "s/ $_inst$/ $_trapno/"
     \let idx+=1 idx%2 || print -r 't SH'
    }
   }
   print -r 't SH'
  )"
 }
}
[[ ,$_fntrace, = *,_qmain,* ]] && _xtrace=ON # trace "_qmain" :=: option -x
[[ ,$_fntrace, = ,+(_qmain,) ]] && _fntrace= # _qmain only "funct" to trace
[[ -n $_fntrace ]] &&
{ # technique used to trace functions will differ depending on options.
 if [[ ,$_fntrace, = *,_qALL,* ]]
 then _addout[0]=ON _addout[1]=ON _fncode='s/-fu /-ftu /' _fntrace=
 else if [[ -n ${_addout[1]} ]]
  then # You have already specified functions to be displayed,
   # so use sed technique to trace (autoloaded) functions.
   _fncode=$(
    IFS=,
    for _inst in $_fntrace
    { print -r "/${_inst}_EOF/s/-fu /-ftu /"
    }
   ) _fntrace=
${VERBOSE:+print -ru2 [ tracing functions: using _fncode=$_fncode technique ]}
  else # using 'typeset -ftu ...'  technique
   _fncode=
   \set -A _fntrace -- $_fntrace
${VERBOSE:+print -ru2 [ tracing functions: using typeset -ftu ... technique ]}
  fi
 fi
}

#06 WHICH SHELL?
if _line1=$(/bin/sed 1q $_src)
 [[ $_line1 = \#!* ]]
then \: ${_qshell:=$_line1} # won't redefine if previously set by -s option
 _qshell=${_qshell##\#!*([$_TAB ])}
fi
\: ${_qshell:=$_kshpath $-}
[[ $_qshell = *+([$_TAB ])-* ]] &&
_qshopts=${_qshell##*+([$_TAB ])-} _qshell=${_qshell%%+([$_TAB ])*}
_qshell=${_qshell%%[$_TAB ]*} _qshell=$(
 whence -p $_qshell 2>&- ||
 { print -ru2 "shadoe: error: shell \"$_qshell\" not in path"
  \exit 1
 }
) || \exit 5
${VERBOSE:+print -ru2 [ shell: _qshell=\"$_qshell\" _qshopts=\"$_qshopts\" ]}
# Warning: ksh command line options [cirs] are inappropriate as "set" options.
[[ $_qshopts = *[cirs]* ]] &&
{ print -ru2 \
 "shadoe: error: shell option(s) \"$_qshopts\" unimplementable"
 \exit 6
}
case /$_qshell in  # any other shells that I don't know about?
# Warning: some systems have ksh installed as "sh"
(*/?(r)@(|a|j|oa)sh|*/?(r)sh5|*/?(r)bash|*/?(r)old)
 # sourcing ENV script has to be explicitly enabled.
 # converting signal names has to be explicitly disabled.
 _isbourne=ON _uscore= \: ${cvt_signames_nums=ON} ;;
(*/?(r)@(@(dt|t)ksh|ksh93))
 _isbourne= _isksh93=ON \: ${_source_ENV_script=ON} ;;
(*/krsh|*/?(r)@(@(|pd|w|x)ksh|ksh-i|keysh|ksh@(86|88)|zsh))
 # sourcing ENV script has to be explicitly disabled.
 # converting signal names has to be explicitly enabled.
 _isbourne= \: ${_source_ENV_script=ON} ;;
(*/@(|h|j|nt|t)csh|*/es|*/rc|*/?(n|o)awk|*/?(i|n)make|*/perl|*/sed)
 print -ru2 "shadoe: error: cannot debug \"$_qshell\" scripts"
 \exit 7 ;;
(*) # ch, esh, itcl_sh, ish, osh, scsh, ssh, sush, tshell, vsh ...
 print -ru2 "shadoe: warning: \"$_qshell\" unknown;" \
 'assuming bourne shell'
 _isbourne=ON _uscore= \: ${cvt_signames_nums=ON}
 sleep 1 ;;
esac
$_qshell -c ': ${.sh.version}' 2>&- && _isksh93=ON
[[ -n $_isksh93 ]] && _isbourne=
${VERBOSE:+print -nru2 '[ flags: '}
for _inst in _addout _fntrace _isbourne _isksh93 _quotedenv _tagvars
{ # if variable <var> is unasserted, then assert variable _no<var>
 \eval "[[ -z \"\$$_inst\" ]] && _no${_inst#_}=ON"
${VERBOSE:+eval print -nru2 "\"$_inst=\$$_inst \""}
}
${VERBOSE:+print -ru2 ]}
${VERBOSE:+print -ru2 [ pager/editor: ${VISUAL:-${EDITOR:-${PAGER:-pg}}} ]}

#07 PROFILE FILES
for _inst in '0 pre' '1 trans' '2 post'
{ \set -A _inst $_inst
 \eval ${dont_use_profiles:+_profile[_inst]= continue}
 \eval _profile[_inst]=${_profile[_inst]} # Ksh Bug: tilde subst
 [[ ${_profile[_inst]} != */* ]] &&
 if [[ -f ${_profile[_inst]} ]]
 then _profile[_inst]=~+/${_profile[_inst]}
 elif [[ -f ~/${_profile[_inst]} ]]
 then _profile[_inst]=~/${_profile[_inst]}
 fi
 if [[ -r ${_profile[_inst]} ]]
 then print -ru2 \
  "using ${_inst[1]}-execution profile \"${_profile[_inst]}\""
 else \unset _profile[_inst]
 fi
}

#08 SED SCRIPT
[[ -n $_addout ]] && /bin/sed "1 !{ /^[$_TAB ]*#/d; }" <<-!!!! >|./_qe2disp.sed
#n - turn 'shadoe' env display into the ${_noisbourne:+k}sh${_isksh93:+93} \
code to recreate that env
# ksh93's new -p option for builtins _should_ have obsolesced all of the below!
# reserved tokens for this script: "_!NL!_", "_!SQ!_", "_!ESCSQ!_", /^#\. /.
/^#\. SHADOE /b SH
: Xpre
# Warning: function blocks _must_ be delimited by a rbrace on the left margin
/^#\. FUNCTIONS:$/,/^#\. / {
 // !{ : newfunc
  /\\n}/b endfunc
  N
  b newfunc
  : endfunc
  #${_isbourne:+s/^function \([0-9A-Z_a-z]*\)\\n/\1 ()_!NL!_/}
  ${ignore_uscore_vars:+/^function _/d}
  s/\\n/_!NL!_/gp
 } b SH
}
# special case efficiency measure:
/^_qsrcline\[/d
${_isksh93:+
# ksh93 "typeset -" already substitutes newlines as ANSI sequences:
/=$'/ s/'/_!SQ!_/g
}
# ... for other formats, conjoin any multi-line entries into one-liners first:
/'/b squote
${ignore_uscore_vars:+/^_/d}
# strip all one-liners of _q* variables and aliases:
/^_q/d
# efficiency measure: equal sign here can only mean (one-liner) var/alias/trap:
/=/b eqlsign
${_addout[2]:+
/^#\. UMASK:$/,/^#\. / {
 b SH
$_RB
}
${_addout[0]:+
/^#\. VARIABLES READONLY:$/,/^#\. / {
 //!s/^/${_isbourne:+readonly }${_noisbourne:+typeset -r }/
 b SH
$_RB
/^#\. VARIABLES EXPORTED:$/,/^#\. / {
 //!s/^/${_isbourne:+export }${_noisbourne:+typeset -x }/
 b SH
$_RB
${_isksh93:+
/^#\. VARIABLES ASSOCIATIVE:$/,/^#\. / {
 //!s/^/typeset -A /
 b KSH
$_RB
#/^#\. VARIABLES CLASS:$/,/^#\. / {
# //!s/^/typeset -C /
# b KSH
#$_RB
/^#\. VARIABLES EXPONENT:$/,/^#\. / {
 //!s/^/typeset -E /
 b KSH
$_RB
/^#\. VARIABLES FLOAT:$/,/^#\. / {
 //!s/^/typeset -F /
 b KSH
$_RB
}
${_noisbourne:+
/^#\. VARIABLES FILENAME:$/,/^#\. / {
 //!s/^/typeset -H /
 b KSH
$_RB
/^#\. VARIABLES LEFTJUST:$/,/^#\. / {
 //!s/^/typeset -L /
 b KSH
$_RB
/^#\. VARIABLES RIGHTJUST:$/,/^#\. / {
 //!s/^/typeset -R /
 b KSH
$_RB
/^#\. VARIABLES ZEROFILL:$/,/^#\. / {
 //!s/^/typeset -Z /
 b KSH
$_RB
/^#\. VARIABLES INTEGER:$/,/^#\. / {
 //!s/^/typeset -i /
 b KSH
$_RB
/^#\. VARIABLES LOWERCASE:$/,/^#\. / {
 //!s/^/typeset -l /
 b KSH
$_RB
${_isksh93:+
/^#\. VARIABLES NAMEREF:$/,/^#\. / {
 //!s/^/typeset -n /
 b KSH
$_RB
}
${_notagvars:+
/^#\. VARIABLES TAGGED:$/,/^#\. / {
 //!s/^/typeset -t /
 b KSH
$_RB
}
/^#\. VARIABLES UPPERCASE:$/,/^#\. / {
 //!s/^/typeset -u /
 b KSH
$_RB
}}
${_addout[1]:+
${_noisbourne:+
/^#\. ALIASES TRACKED:$/,/^#\. / {
 # Ksh Bug: ksh93 may omit "=<value>" in alias -p output
 // !{ /=/!d
  s/^alias //
  s/^/alias -t -- /
 $_RB
 b KSH
$_RB
/^#\. ALIASES EXPORTED:$/,/^#\. / {
 # Warning: ksh93 does not implement exported aliases
 // !{ s/^alias //
  /^exit=/d
  ${_isbourne:+/^limit=/d}
  s/^/alias -x -- /
 $_RB
 b KSH
$_RB
${_nofntrace:+
/^#\. FUNCTIONS TRACED:$/,/^#\. / {
 //!s/^/typeset -ft /
 b KSH
$_RB
}}
/^#\. FUNCTIONS AUTOLOADED:$/,/^#\. / {
 //!s/^/typeset -fu /
 b KSH
$_RB
/^#\. FUNCTIONS EXPORTED:$/,/^#\. / {
 # Warning: ksh93 does not implement exported functions
 //!s/^/typeset -fx /
 b KSH
$_RB
}
${_addout[2]:+
/^#\. LIMITS SOFT:$/,/^#\. / {
 // !{ s/u/U/g; s/Unlimited/unlimited/
  t treset1
  : treset1
  s/^time[^0-9u]*/ulimit -S -t /;  t SH
  s/^data[^0-9u]*/ulimit -S -d /
  s/^file[^0-9u]*/ulimit -S -f /;  t SH
  s/^stack[^0-9u]*/ulimit -S -s /
  s/^memory[^0-9u]*/ulimit -S -m /; t SH
  s/^core[^0-9u]*/ulimit -S -c /
  s/^v.*memory[^0-9u]*/ulimit -S -v /; t SH
  s/^.*descriptors[^0-9u]*/ulimit -S -n /
  s/^open [^0-9u]*/ulimit -S -n /; t SH
  # implemented in bash 1.x and 2.x:
  s/^pipe[^0-9u]*/ulimit -S -p /
  # implemented in bash 2.x:
  s/^.* processes[^0-9u]*/ulimit -S -u /; t SH
  d
 $_RB
$_RB
/^#\. LIMITS HARD:$/,/^#\. / {
 // !{ s/u/U/g; s/Unlimited/unlimited/
  t treset2
  : treset2
  s/^time[^0-9u]*/ulimit -H -t /;  t SH
  s/^data[^0-9u]*/ulimit -H -d /
  s/^file[^0-9u]*/ulimit -H -f /;  t SH
  s/^stack[^0-9u]*/ulimit -H -s /
  s/^memory[^0-9u]*/ulimit -H -m /; t SH
  s/^core[^0-9u]*/ulimit -H -c /
  s/^v.*memory[^0-9u]*/ulimit -H -v /; t SH
  s/^.*descriptors[^0-9u]*/ulimit -H -n /
  s/^open [^0-9u]*/ulimit -H -n /; t SH
  # implemented in bash 1.x and 2.x:
  s/^pipe[^0-9u]*/ulimit -H -p /
  # implemented in bash 2.x:
  s/^.* processes[^0-9u]*/ulimit -H -u /; t SH
  d
 $_RB
 b SH
$_RB
/^#\. SHELL OPTIONS:$/,/^#\. / {
 // !{ /^C/d
  # Warning: only ksh93 has "interactive" and "restricted" options
  ${_noisksh93:+/^interactive /d; /^restricted /d}
  s/^\([^ ]*\) \{1,\\$_RB\(.*\)$/set -o \2\1/
  s/ -o on/ -o /
  s/ -o off/ +o /
# bourne shell? convert those kornshell options in common to bourne options:
${_isbourne:+
  t treset3
  : treset3
  s/o allexport$/a/; t SH
  s/o errexit$/e/
  # Warning: trackall and -h options are only approx equivalent
  s/o trackall$/h/; t SH
  s/o keyword$/k/
  s/o noexec$/n/;  t SH
  s/o noglob$/f/
  s/o nounset$/u/; t SH
  s/o verbose$/v/
  s/o xtrace$/x/;  t SH
  d
}
 $_RB
 b KSH
$_RB
#/^#\. STTY SETTINGS:$/,/^#\. / {
# //!s/^/stty /
# b SH
#$_RB
}
: squote ${_quotedenv:+
: Xsq.0
/'/ {
 # Conjoin multi-line contents into one line, with newlines
 # replaced by the special token marker string "_!NL!_".
 : oneline
 s/'\\\\''/_!ESCSQ!_/g
 /^\\([^']*\\)'\\([^']*\\)'/ {
  s//\\1_!SQ!_\\2_!SQ!_/
  /'/!b matched
 $_RB
 \$!N
 \$!b oneline
 : matched
 s/\\n/_!NL!_/g
 s/_!ESCSQ!_/'\\\\''/g
$_RB
: Xsq.1
} #XXX _noquotedenv ??
: eqlsign
s/_!SQ!_/'/g
${ignore_uscore_vars:+/^_/d}
# strip all _q* multi-line aliases and variables:
/^_q/d
/^#\. VARIABLES:$/,/^#\. / {
 // !{ /^set --/ !{ /=/!d; $_RB
  ${_isbourne:+/^_=/d}
  ${_uscore:+/^_=_qshadoe$/d}
  ${_showcode:+/^: \$-=/ s/[${_verbose:+v}${_xtrace:+x}]//}
 $_RB
 b SH
$_RB
${_addout[1]:+
/^#\. TRAPS:$/,/^#\. / {
 # strip the DEBUG/ERR trap output
 // !{ / ${_debugtrap:+DEBUG}${_errtrap:+ERR}$/d
  # bourne shell? convert trap names to numerical equivalents:
  ${_isbourne:+$_names2nums}
 $_RB
$_RB
${_noisbourne:+
/^#\. ALIASES:$/,/^#\. / {
 // !{ s/^alias //
  /^exit=/d
  /^limit=/d
  s/^/alias -- /
 $_RB
 b KSH
$_RB
}}
: KSH
: Xkorn
# bourne shell? strip all commands specific to ksh:
${_isbourne:+/^#\. /!d}
: SH
: Xbourne
/^_q/!{ w ./_qcenv
 p
}
!!!!

#09 AUTOLOADED DEBUGGER FUNCTION
/bin/sed -n "/^[$_TAB ]*$/!p" <<!!!! >|./_qshadoe
function _qshadoe
{ # all arguments refer to the values of the calling environment.
 ((\$#==0)) &&
 { # Ksh Bug: DEBUG trap broken in i86 Solaris 2.4 ksh[88i] #XXX
  \trap "\\trap '\
${_showcode:+\\set ${_verbose:++o verbose }${_xtrace:++o xtrace}}
_qshadoe \\\$LINENO \\\$? \"\\\$-\" \"\\\$0\" \\\$# \"\\\$@\" \"\\\$_\"\
${_addout[1]:+ \"\$(\\trap)\"}' ${_debugtrap:+DEBUG}${_errtrap:+ERR}" EXIT
  \return \$?
 }
 # \$1=retval  \$2=name  \$3=\$_  [\$4=user supplied arg to exit cmd]
 ((\$#==4)) && \set -- \$4 \$2 \$3 # user-supplied arg takes precedence
 ((\$#==3)) &&
 { \trap \
"\\set +o nounset${_verbose:+ +o verbose}${_xtrace:+ +o xtrace}
_qcontrol=0 _qshadoe EOF \$1 \"\\\$-\" \"\$2\" \\\$# \"\\\$@\" \"\$3\"\
${_addout[1]:+ \"\\\$(\\trap)\"}" EXIT
  \return \$1
 }
 # \$1=lnno  \$2=retval  \$3=flags  \$4=name  \$5=argc  \$6...=argv
 # last-2=\$_  last-1=traps  [last=exit_retval]
 [[ \$1 != SOF && \$1 != EOF ]] && # bounds processing mandatory!
 {
${_showcode:+
  # default EXIT trap: turn on verbose and/or xtrace option(s)
  \trap '\set ${_verbose:+-o verbose }${_xtrace:+-o xtrace}' EXIT
}
  # Warning: as ksh93 executes the DEBUG trap _before_ each
  # line is executed, instead of _after_ as in ksh88, LINENO
  # will have been already reset before the DEBUG trap is
  # executed, _and_ LINENO will never expand to less than one.
  if ((\$1<=0))
  then # LINENO is set less than or equal to 0: 'idling' state
   \trap - EXIT
   \return \$2
  elif ((\$1<_qbgnlnno))
  then \trap - EXIT
   \return \$2
  elif ((\$1>_qendlnno))
  then \trap \
'\trap - ${_debugtrap:+DEBUG}${_errtrap:+ERR}${_ignexit:+ EXIT}' EXIT
   \return \$2
  elif ((_qcontrol<0))
  then # force a display of env and post-increment _qcontrol
   \:
  elif ((_qcontrol>0))
  then # pre-decrement _qcontrol, skip display of env?
   ((_qcontrol-=1)) && \return \$2
  fi
 }
 # if got here: within bounds of code and conditions to debug
 \typeset -x _qoldpwd=\$OLDPWD _qpwd=\$PWD
 \cd -- \$_qdir || \exit 102
 # Warning: real env ordered slightly differently than here displayed
 { \typeset -i _qnpp=\$5+1
  _qroparams=": \\\$$=\$$
: \\\$!=\${!:-''$_RB
: \\\$#=\$5
: \\\$-=\${3:-''$_RB
: \\\$?=\${2:-0$_RB
: \\\$0=\$4" \shift 5
  print -r '$(eval /bin/date "\"+$_version\"")'
  # emit cwd and positional parameters
  print -n "cd -- '\$_qpwd'\\n#. VARIABLES:\\nset --"
  while ((_qnpp-=1))
  do # Ksh Bug: necessary bec of poor quoting implemention
   if [[ \$1 = *\\'* ]]
   then _qrest=\$1
    print -nr " '"
    while \:
    do _qsub=\${_qrest%%\\'*$_RB
     print -nr -- "\$_qsub'\\''"
     _qrest=\${_qrest#\$_qsub\\'$_RB
     [[ \$_qrest != *\\'* ]] &&
     break
    done
    print -nr -- "\$_qrest'"
   else print -nr -- " '\$1'"
   fi
   \shift
  done
  # emit shell read-only special parameters
  print "\\n\$_qroparams"
  # emit variable=value pairs
  \eval "\\\\unset LINENO OLDPWD PS4 PWD RANDOM SECONDS _ _qnpp \
_qoldpwd _qpwd _qrest _qroparams _qsub
  OLDPWD='\$_qoldpwd' PWD='\$_qpwd' \
${_uscore:+_=\\\$1 }\\\\typeset -${_tagvars:+t}"
  \shift
  print -r '#. '
${_addout[0]:+
  # emit variable attributes
  print -r '#. VARIABLES READONLY:'
  \typeset +r
  print '#. \\n#. VARIABLES EXPORTED:'
  \typeset +x
  print -r '#. '
${_isksh93:+
  print -r '#. VARIABLES ASSOCIATIVE:'
  \typeset +A
#  print '#. \\n#. VARIABLES CLASS:'
#  \typeset +C
  print '#. \\n#. VARIABLES EXPONENT:'
  \typeset +E
  print '#. \\n#. VARIABLES FLOAT:'
  \typeset +F
  print -r '#. '
}
${_noisbourne:+
  print '#. VARIABLES FILENAME:'
  \typeset +H
  # use 'typeset -[LRZ] var=0000' style instead
  # of 'typeset -[LRZ]4 var' declaration style.
  print '#. \\n#. VARIABLES LEFTJUST:'
  \typeset +L
  print '#. \\n#. VARIABLES RIGHTJUST:'
  \typeset +R
  print '#. \\n#. VARIABLES ZEROFILL:'
  \typeset +Z
  print '#. \\n#. VARIABLES INTEGER:'
  \typeset +i
  print '#. \\n#. VARIABLES LOWERCASE:'
  \typeset +l
${_isksh93:+
  print '#. \\n#. VARIABLES NAMEREF:'
  \typeset +n
}
${_notagvars:+
  print '#. \\n#. VARIABLES TAGGED:'
  # Warning: showing tagged variables is contingent
  # on no option -t traced variables being specified.
  \typeset +t
}
  print '#. \\n#. VARIABLES UPPERCASE:'
  \typeset +u
} print -r '#. '
}
${_addout[1]:+
  # shell-level environment (generally user-specified):
  # traps, [aliases+attribs], functs[+attribs]
  print -r '#. TRAPS:'
  [[ -n \$1 ]] && print -r -- "\$1"
  \shift
${_noisbourne:+
  print '#. \\n#. ALIASES:'
  # Ksh Bug: ksh86/88 wrongly shows tracked
  # aliases along with those user defined.
  # Ksh Bug: ksh93 fails to implement 'alias +'!
  ${_isksh93:+\alias -p}${_noisksh93:+\alias}
  print '#. \\n#. ALIASES TRACKED:'
  # Warning: ignore tracked aliases; see above. All tracked
  # aliases will be invalidated anyway whenever PATH is reset.
  # Ksh Bug: ksh93 fails to implement 'alias +t'!
  ${_isksh93:+\alias -pt}${_noisksh93:+\alias +t}
${_noisksh93:+
  # Warning: ksh93 does not implement exported aliases
#XXX then why does "alias -x" print out more information than "alias"?!
# Ksh Bug: in ksh93, "typeset +fx" is still implemented, but "alias +x" is not!
  print '#. \\n#. ALIASES EXPORTED:'
  \alias +x
}}
  print '#. \\n#. FUNCTIONS:'
  # Ksh Bug: ksh86/88 recognises bourne-style function
  # notation, but retains the kornshell-style function
  # environment for it. Warning: function body code
  # _must_ be delimited by right brace at left margin.
  # Warning: do not name a function the same as shprog!
  if [[ \$- = *f* ]]
  then \set +o noglob -- !(${_src##*/}|_q*)
   \set -o noglob
  else \set -- !(${_src##*/}|_q*)
  fi
  [[ \$1 != !* ]] &&
  for _qinst
  { print -r "\$(<./\$_qinst)"
  $_RB
  print '#. \\n#. FUNCTIONS AUTOLOADED:'
  # Technically only a ksh feature, but necessary here
  # for the method function code is stored and accessed.
  # Warning: a function's attribs only show when defined.
  \typeset +fu
${_noisbourne:+
${_nofntrace:+
  print '#. \\n#. FUNCTIONS TRACED:'
  # Warning: showing traced functions is contingent
  # on no option -f traced functions being specified.
  \typeset +ft
}
#XXX${_noisksh93:+
  print '#. \\n#. FUNCTIONS EXPORTED:'
  # Warning: ksh93 does not implement exported functions
  \typeset +fx
#XXX}
} print -r '#. '
}
${_addout[2]:+
  # system-level environment (generally inherited):
  # umask, limits, shell options
  print -n '#. UMASK:\\numask '
  \umask
  print '#. \\n#. LIMITS SOFT:'
  \ulimit -Sa
  print '#. \\n#. LIMITS HARD:'
  \ulimit -Ha
  print '#. \\n#. SHELL OPTIONS:'
  \set -o
#  print '#. \\n#. STTY SETTINGS:'
#  stty -g
  print -r '#. '
}
 $_RB | /bin/sed -n ${_addout:+-f ./_qe2disp.sed}${_noaddout:+'/^_q/ !{
${_noquotedenv:+
#XXX NYI
}
 w ./_qcenv
 p
$_RB'
} | /bin/cmp -s - ./_qoenv >|./_qcstamp
 # end-of-subshell: the function entry environment is restored
 [[ \$? != 0 || \$_qcontrol -lt 0 ]] &&
 { # Displays the changed values of this environment
  # when value is new or changed, not when removed.
  ((_qcontrol<0)) && \let _qcontrol+=1
${_errtrap:+
  [[ \$1 != SOF && \$1 != EOF ]] &&
}
  { \: >|./_qdstamp
   /bin/diff ./_qoenv ./_qcenv | /bin/sed -n '
${_showovalues:+
   /^< \([^()=]\{1,\\$_RB\)=/ {
    s//\1 old value: /
    /^: /!s/^/: /
    b printit
   $_RB
${_addout[1]:+
   /^< trap \(.*\) \([^ ]\{1,\\$_RB\)$/ {
    s//signal \2 handler code was: \1/
    /^: /!s/^/: /
    b printit
   $_RB
}}
   /^> / { s///
    b printit
   $_RB
   d
   : printit
${env_newlines:+
   s/_!NL!_/\\
/g
}
p' >|./_qdenv
${skip_initial_env:+
   [[ \$1 != SOF ]] &&
}
   [[ -s ./_qdenv ]] &&
   if ${_whenenv:+${_profile[1]:+\: }}\let 0
   then \. ${_profile[1]:-/dev/null}
   else # default shadoe.trans:
    \eval print -r -- "\\"\$_qprompt\\""
# Warning: shprog can inadvertantly change vars VISUAL, EDITOR, and/or PAGER
# Warning: 'more' will page only on sufficient output; using 'pg' as default:
    \eval \
SHELL=$_qshell TERM=$TERM \${VISUAL:-\${EDITOR:-\${PAGER:-pg}}} ./_qdenv
    print
   fi
   # If user has modified either env file since displayed,
   # then source that environment file to set the changes.
   # Warning: NFS makes modtime synchronization problematic
   for _qinst in c d
   { [[ -s ./_q\${_qinst}env &&
    ./_q\${_qinst}stamp -ot ./_q\${_qinst}env ]] &&
    { /bin/sed "s/_!NL!_/\\\\
/g
     s/^: /\\\\\\\\&/
     s/^alias /\\\\\\\\&/
     s/^cd /\\\\\\\\&/
     s/^set /\\\\\\\\&/
     s/^trap /\\\\\\\\&/
     s/^typeset /\\\\\\\\&/
     s/^ulimit /\\\\\\\\&/
     s/^umask /\\\\\\\\&/
     \\\$a\\\\
_qcontrol=\$_qcontrol" ./_q\${_qinst}env >|./_qtmp
     _qcontrol=9999 \trap \
'time \. \$_qdir/_qtmp' EXIT #2>|/dev/null
    }
   }
  } /bin/mv ./_qcenv ./_qoenv
 }
 \cd -- \$_qoldpwd; \cd -- \$_qpwd
${_whentrap:+${_profile[1]:+
 \. ${_profile[1]}
}}
 [[ \$1 = EOF || \$1 -ge \$_qendlnno ]] 2>|/dev/null &&
 \trap \
'\trap - ${_debugtrap:+DEBUG}${_errtrap:+ERR}${_ignexit:+ EXIT}' EXIT
 if [[ \$1 = EOF ]]
 then print -r 'done:\$?' >|\$_qdir/_qstatus
  if \eval \\\\typeset _lastarg=\\\${\$((\$5+7${_addout[1]:++1}))}
     [[ -n \$_lastarg ]]
  then # user specified an argument for an exit value
   \exit \$_lastarg
  else # default exit value is return value of previous cmd
   \exit \$2
  fi
 else \return \$2  # propagate original return value
 fi
} #>&2
!!!!

#10 MUNGED SHELL SOURCE
{ print -r \
"#!${_isbourne:+$_kshpath}${_noisbourne:+$_qshell}${_qshopts:+ -$_qshopts}
\trap - ${_debugtrap:+DEBUG}${_errtrap:+ERR}
\: \${_qdir:=\${TMPDIR:-${TMPDIR:-/tmp}}/_q$$.d/}
\: \${_qprompt='$_qprompt'}
\: \${_qshell=$_qshell} \${_qshopts=$_qshopts}
\: \${_qbgnlnno=${_qbgnlnno:-1}}  # line number to begin debug
\: \${_qmaxlnno:=$(/bin/sed -n \$= $_src)} # the number of lines in shprog
\typeset -x _qdir _qprompt _qshell _qshopts
\typeset -ix _qbgnlnno _qendlnno _qlnnodisp _qmaxlnno
\typeset -ix _qcontrol=0 # if _qcontrol<0: force display and increment
    #    _qcontrol=0: normal debug trap
    #    _qcontrol>0: decrement and skip debug trap
((_qendlnno==0 || _qendlnno>_qmaxlnno-_qlnnodisp)) &&
\let _qendlnno=_qmaxlnno+_qlnnodisp
\cd -- \$_qdir 2>&- ||
{ print -nru2 \${0##*/}: error: bad or missing temporary directory
 if [[ /\$0 = */shadoe.sa ]]
 then print -ru2 ' (try using \"shadoe\" again)'
 else print -ru2
 fi
 \exit 100
}
# autoload debugger function responsible for displaying diffed environment
FPATH=\$_qdir${FPATH:+:$FPATH} \typeset -fu _qshadoe
#XXX or is it /bin/cmp? [[ $(alias -t | /bin/grep cmp) = cmp=/bin/cmp ]]
$( [[ -n $_isksh93 && -n $PATH && $(whence cmp) != /bin/cmp ]] &&
 { print -r \
  '# modify PATH to allow ksh93 to use its shell builtin versions'
  print -r "PATH=/bin:$PATH"
 }
)
${_isbourne:+
# Warning: some bourne shells do not implement the 'limit' builtin
\typeset -fx _qlimit
function _qlimit
{ # Sh 'limit' and ksh 'ulimit' commands have similar but nonetheless
 # different syntax. This translates the first into the second form.
 \typeset field1=ON newopt=-f origopt softhard=-S oargv=\"\$*\"
 [[ \$1 = -h ]] && softhard=-H \shift
 if ((!\$#))
 then newopt=-a field1=
 else \set -o noglob
  case \$1 in
  (c|d) print -ru2 limit: Ambiguous
   \return 1 ;;
  (co?(r?(e?(d?(u?(m?(p?(s?(i?(z?(e)))))))))))
   newopt=-c origopt=coredumpsize \shift ;;
  (cp?(u?(t?(i?(m?(e))))))
   newopt=-t origopt=cputime \shift ;;
  (da?(t?(a?(s?(i?(z?(e)))))))
   newopt=-d origopt=datasize \shift ;;
  (de?(s?(c?(r?(i?(p?(t?(o?(r?(s))))))))))
   newopt=-n origopt=descriptors \shift ;;
  (f?(i?(l?(e?(s?(i?(z?(e))))))))
   newopt=-f origopt=filesize \shift ;;
  (m?(e?(m?(o?(r?(y?(u?(s?(e)))))))))
   newopt=-m origopt=memoryuse \shift ;;
  (s?(t?(a?(c?(k?(s?(i?(z?(e)))))))))
   newopt=-s origopt=stacksize \shift ;;
  (v?(m?(e?(m?(o?(r?(y)))))))
   newopt=-v origopt=vmemory \shift ;;
  (*) print -ru2 limit: No such resource
   \return 1 ;;
  esac
  # default units:
  # descriptors: limit: positive int ulimit: positive int
  # time:  limit: [[hrs:]min:]sec ulimit: seconds
  # all others: limit: kbytes  ulimit: blocks
  \typeset n t1 t2
  [[ \$1 = +([0-9]) && \$2 = !([0-9])* ]] && \set \$1\$2
  if [[ \$1 = unlimited ]]
  then n=unlimited
  elif [[ \$newopt = -n ]]
  then if [[ \$1 = +([0-9]) ]]
   then n=\$1
   else print -ru2 \
    limit: Improper or unknown scale factor
    \return 1
   fi
  elif [[ \$newopt = -t ]]
  then case \$1 in
   (*([0-9])h?(o?(u?(r?(s)))))
    n=\${1%%h*$_RB
    \let n=3600*\${n:-0$_RB ;;
   (*([0-9])m?(i?(n?(u?(t?(e?(s)))))))
    n=\${1%%m*$_RB
    \let n=60*\${n:-0$_RB ;;
   (*([0-9])s?(e?(c?(o?(n?(d?(s)))))))
    n=\${1%%s*$_RB
    \let n=\${n:-0$_RB ;;
   (*:*) t1=\${1%%:*$_RB t2=\${1#*:$_RB
    \let n=60*\${t1:-0$_RB+\${t2:-0$_RB ;;
   (+([0-9]))
    \let n=\$1 ;;
   (*) print -ru2 \
    limit: Improper or unknown scale factor
    \return 1 ;;
   esac
   # Warning: not all limit builtins implement the below:
   # Apparently the cputime limit has a granularity of
   # ten seconds with a one second grace period added on.
   #\let n=\$n/10*10+1
  elif [[ \$1 = *([0-9])m?(e?(g?(a?(b?(y?(t?(e?(s)))))))) ]]
  then n=\${1%%m*$_RB
   \let n=2000*\${n:-0$_RB
  elif [[ \$1 = *([0-9])k?(i?(l?(o?(b?(y?(t?(e?(s)))))))) ||
   \$1 = *([0-9])k?(b?(y?(t?(e?(s))))) ]]
  then n=\${1%%k*$_RB
   \let n=2*\${n:-0$_RB
  elif [[ \$1 = +([0-9]) ]]
  then \let n=2*\$1
  else print -ru2 limit: Improper or unknown scale factor
   \return 1
  fi
 fi
${VERBOSE:+print -ru2 [ limit \$oargv :=: ulimit \$softhard \$newopt \$n ]}
 [[ \$n = @(unlimited|+([0-9])) ]] && field1=
 if [[ -n \$field1 ]]
 then print -nr \"\$origopt $_TAB\"
  \ulimit \$softhard \$newopt \$n
 else \ulimit \$softhard \$newopt \$n
${_addout[2]:+
  \trap '_qshadoe \$LINENO \
\$? \"\$-\" \"\$0\" \$# \"\$@\" \"\$_\" \"\$(\\trap)\"' EXIT
}
 fi
$_RB
}
# Warning: some tools (e.g. sed) will need fildes 9, else output will be null!
\exec 9>&-
#\ulimit -Sn $((($(\ulimit -Hn)+$(\ulimit -Sn))/2)) # more descriptors?
\: >|./_qcstamp >|./_qdstamp >|./_qcenv >|./_qdenv
[[ -f ./_qoenv ]] || \: >|./_qoenv
print -r 'interrupted:\$?' >|./_qstatus
#/bin/chmod u+t ./_qcenv ./_qcstamp ./_qdstamp \
./_qdenv ./_qoenv${_addout:+ ./_qe2disp.sed}  # faster disk I/O?
/bin/rm -f ~/${_src##*/}.denv ~/${_src##*/}.env
/bin/ln ${_symlinkok:+-s} \$_qdir/_qdenv ~/${_src##*/}.denv
/bin/ln ${_symlinkok:+-s} \$_qdir/_qcenv ~/${_src##*/}.env
\cd -- ~-; \cd -- ~+
${_tagvars:+\typeset -t ${_tagvars[*]}}
${_addout[1]:+${_fntrace:+
# Ksh Bug: 'typeset -fx ...' resets 'typeset -fu ...' unless specified together
\typeset -ftu ${_fntrace[*]}
}}
# Ksh Bug: parameter \"\$@\" below shouldn't, but does, set off any '-u' option.
# it is assumed for all shells that the initial value of '_' is the shell path.
_qcontrol=0 _qshadoe SOF \$? \"\$-\" \"\$0\" \$# \"\$@\" $_qshell \
${_addout[1]:+ \"\$(\\trap)\"}
${_noisksh93:+${_source_ENV_script:+${ENV:+
# Warning: ksh93 sources ENV file only when interactive.
# Warning: below may be redundantly sourced in standalone script shadoe.sa:
[[ -f \$ENV && -r \$ENV ]] && ENV=$ENV \. \$ENV
}}}
${_clearenv:+${_noisbourne:+${_noisksh93:+
# Needed for ksh88 as ksh93 doesn't read ENV file or implement exported aliases
\unalias -- \$(\alias +) # Ksh Bug: ksh93 cannot execute this command
# Ksh Bug: 'alias -- <alias_name>' fails
# Ksh Bug: ambiguous syntax possible for defining an alias for dash
# Warning: aliases reinitialized below are only those documented as standard
alias autoload='typeset -fu' functions='typeset -f' hash='alias -t -' \\
history='fc -l' integer='typeset -i' local=typeset nohup='nohup ' \\
r='fc -e -' stop='kill -STOP' suspend='kill -STOP $$' type='whence -v'
}}}
# Warning: do not use a return command outside of a function as an exit command
LINENO=0 PS4='+[\$LINENO]:$_TAB' \alias exit='_qshadoe \$? \"\$0\" \"\$_\"' \
${_isbourne:+ limit=_qlimit
LINENO=0 \unset _   # Ksh Bug: cannot unset specialness}
${_autostart:+LINENO=0 _qshadoe  # start the debugging trap}
${_qshopts:+$(
 # script is executed by a shell with option parameters
 [[ $_qshopts = *[nt]* ]] &&
 print -r 'print -r done:\$? >|\$_qdir/_qstatus'
 print -r "LINENO=0 && \set -$_qshopts || \exit 101"
)}\
LINENO=_qlnnodisp+1 \: $_qshell  # reset var '_' to shell path"
 # now copy over (modified) shprog to be executed in above env.
 # Ksh Bug: "typeset -f" is broken for non-interactive shells!
 # All this nonsense would not have been necessary if ksh did not
 # mandate the "nolog" option in a non-interactive shell. Grrr!
 # Warning: ending rbrace _must_ be left justified in funct defn.
 if [[ -n ${_addout[1]} ]]
 then /bin/sed \
"${_noisbourne:+/^function[$_TAB ]\{1,\\$_RB\([A-Z_a-z][0-9A-Z_a-z]*\)/b seefn}
/^\([A-Z_a-z][0-9A-Z_a-z]*\)[$_TAB ]*([$_TAB ]*)/b seefn
b
: seefn
/^_q/b
${_noisbourne:+/^function[$_TAB ]\{1,\\${_RB}_q/b}
${print_funct_names:+w /dev/tty}
/[$_TAB;&) ]}$/b havefn
: getbody
/\\n}/b havefn
\$!N
\$!b getbody
: havefn
t treset
: treset
${_noisbourne:+
/^function[$_TAB ]\{1,\\$_RB\([A-Z_a-z][0-9A-Z_a-z]*\).*/s//\1~&/
t procfn
}
/^\([A-Z_a-z][0-9A-Z_a-z]*\).*/s//\1~&/
: procfn
s:^\([^~]*\)~\(.*\)\$:_qcontrol=3;/bin/sed -n p<<\\\\\1_EOF\
>|\$_qdir/\1;LINENO=LINENO+1 _qcontrol=-1 \\\\typeset -fu \1\\
\2\\
\1_EOF:
$_fncode" $_src
 else /bin/sed -n p $_src
 fi
 print -r \
'_qcontrol=0 exit # shadoe: ensure updated environment display at EOF'
} >|./${_src##*/}

#11 MAIN
\trap : INT QUIT    # shprog will handle signals
\trap '\eval \\set -- "\"$(<$_qdir/_qstatus)\""
 [[ -n $_dumpsrc ]] &&
 /bin/sed -n p $_qdir/${_src##*/} >|./shadoe.sa &&
 /bin/chmod +x ./shadoe.sa
 if [[ -n ${_profile[2]} ]]
 then \. ${_profile[2]}  # sourced in env of debugger
  \exit $?
 else # default shadoe.post: ($1 is /(^interrupted|^done):$?/)
  \eval print -ru2 -- "\"$_qprompt\""
  /bin/rm -f ~/${_src##*/}.denv ~/${_src##*/}.env
  /bin/cp $_qdir/_qoenv ./${_src##*/}.env 2>&-
  /bin/rm -fr $_qdir/
  \exit 0
 fi' EXIT
# variables below are visible to the shprog to dynamically control the debugger
\typeset -x _qbgnlnno _qcontrol _qdir _qendlnno \
_qlnnodisp _qprompt _qshell _qshopts
\cd -- ~-; \cd -- ~+ # back to original directory; restore variable OLDPWD
${_profile[0]:+. ${_profile[0]}   # sourced in env of debugger}
\exec 9>&1
( # Bourne sh gives default values to PATH, PS1, PS2, MAILCHECK,
 # and IFS. In addition, ksh88 gives a default value to TMOUT and
 # ksh93 adds to this default values for FCEDIT, PS3, and PS4.
 # [LOGNAME, MAIL, SHELL,] TERM, [TZ,] and USER are set by login(1).
 # VISUAL, EDITOR, and/or PAGER shall be exported, if defined.
 # Warning: if applicable, the shprog is execed by the "#!..." shell,
 # so an -s option may be necessary for non-conforming clone shells.
 \eval "
${_clearenv:+
 /bin/env - ${_isksh93:+FCEDIT='$FCEDIT'} HOME='$HOME' \
 ${LOGNAME+LOGNAME='$LOGNAME'} ${MAIL+MAIL='$MAIL'} \
 MAILCHECK='$MAILCHECK' PATH='$PATH' PS1='$PS1' PS2='$PS2' \
 ${_isksh93:+PS3='$PS3' PS4='$PS4'} ${SHELL+SHELL='$SHELL'} \
 TERM='$TERM' ${TZ+TZ='$TZ'} USER='$USER' ${_noisbourne:+TMOUT='$TMOUT'}\
} ENV= IFS='${IFS# ,}' ${EDITOR+EDITOR='$EDITOR'} \
 ${PAGER+PAGER='$PAGER'} ${VISUAL+VISUAL='$VISUAL'} \
 ${_isbourne:+$_kshpath}${_noisbourne:+$_qshell}${_qshopts:+ -$_qshopts}\
 -- $_qdir/${_src##*/} \"\$@\""
 print -r -- $? >|$_qdir/_qtmp
) 2>&1 1>&9 9>&- |
( # Warning: file "shadoe.out" will need to be pruned every so often
 eval /bin/date "\"+%n$_version\"" >>./shadoe.out 2>&-
 /bin/tee -a ./shadoe.out 2>&-
 \exit $(<$_qdir/_qtmp)
) 1>&2 9>&-