Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

v29i097: zsh2.2 - The Z shell, Part01/17

37 views
Skip to first unread message

Paul Falstad

unread,
May 13, 1992, 11:52:04 AM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 97
Archive-name: zsh2.2/part01
Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# This is zsh2.2, a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 05/12/1992 04:14 UTC by pfalstad@phoenix
# Source directory /n/homeserver/g/pfalstad
#
# existing files will NOT be overwritten unless -c is specified
#
# This is part 1 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 2684 -rw-r--r-- zsh2.2/FEATURES
# 505 -rw-r--r-- zsh2.2/NOTES
# 17490 -rw-r--r-- zsh2.2/README
# 58603 -rw-r--r-- zsh2.2/doc/intro.txt
# 247 -rw-r--r-- zsh2.2/dots/zlogin
# 2291 -rw-r--r-- zsh2.2/dots/zshrc
# 123 -rw-r--r-- zsh2.2/dots/zshenv
# 104 -rwxr-xr-x zsh2.2/func/acx
# 109 -rwxr-xr-x zsh2.2/func/cx
# 97 -rwxr-xr-x zsh2.2/func/harden
# 84 -rwxr-xr-x zsh2.2/func/mere
# 412 -rwxr-xr-x zsh2.2/func/namedir
# 194 -rwxr-xr-x zsh2.2/func/proto
# 80 -rwxr-xr-x zsh2.2/func/randline
# 29 -rwxr-xr-x zsh2.2/func/yp
# 35 -rwxr-xr-x zsh2.2/func/yu
# 112852 -rw-r--r-- zsh2.2/man/man1/zsh.1
# 755 -rwxr-xr-x zsh2.2/scripts/aproto
# 173 -rwxr-xr-x zsh2.2/scripts/fproto
# 1137 -rw-r--r-- zsh2.2/scripts/ctoz
# 2958 -rw-r--r-- zsh2.2/scripts/fooz
# 3299 -rwxr-xr-x zsh2.2/scripts/c2z
# 2736 -rwxr-xr-x zsh2.2/scripts/c2z.orig
# 11626 -rwxr-xr-x zsh2.2/src/buildzsh
# 61945 -rw-r--r-- zsh2.2/src/builtin.c
# 4064 -rw-r--r-- zsh2.2/src/cond.c
# 35818 -rw-r--r-- zsh2.2/src/exec.c
# 1185 -rw-r--r-- zsh2.2/src/funcs.h
# 24554 -rw-r--r-- zsh2.2/src/glob.c
# 23511 -rw-r--r-- zsh2.2/src/hist.c
# 11807 -rw-r--r-- zsh2.2/src/init.c
# 16421 -rw-r--r-- zsh2.2/src/jobs.c
# 15554 -rw-r--r-- zsh2.2/src/lex.c
# 4752 -rw-r--r-- zsh2.2/src/loop.c
# 10185 -rw-r--r-- zsh2.2/src/math.c
# 4948 -rw-r--r-- zsh2.2/src/mem.c
# 24577 -rw-r--r-- zsh2.2/src/params.c
# 14912 -rw-r--r-- zsh2.2/src/subst.c
# 6810 -rw-r--r-- zsh2.2/src/table.c
# 8584 -rw-r--r-- zsh2.2/src/text.c
# 32116 -rw-r--r-- zsh2.2/src/utils.c
# 7149 -rw-r--r-- zsh2.2/src/watch.c
# 8371 -rw-r--r-- zsh2.2/src/zle.h
# 17212 -rw-r--r-- zsh2.2/src/zle_bindings.c
# 14597 -rw-r--r-- zsh2.2/src/zle_main.c
# 12058 -rw-r--r-- zsh2.2/src/zle_refresh.c
# 4690 -rw-r--r-- zsh2.2/src/zle_utils.c
# 31883 -rw-r--r-- zsh2.2/src/zsh.h
# 4793 -rw-r--r-- zsh2.2/src/zle_vi.c
# 1486 -rw-r--r-- zsh2.2/src/ztype.h
# 26002 -rw-r--r-- zsh2.2/src/zle_tricky.c
# 4239 -rw-r--r-- zsh2.2/src/builtin.pro
# 235 -rw-r--r-- zsh2.2/src/cond.pro
# 2306 -rw-r--r-- zsh2.2/src/exec.pro
# 1511 -rw-r--r-- zsh2.2/src/glob.pro
# 1989 -rw-r--r-- zsh2.2/src/hist.pro
# 395 -rw-r--r-- zsh2.2/src/init.pro
# 892 -rw-r--r-- zsh2.2/src/jobs.pro
# 309 -rw-r--r-- zsh2.2/src/lex.pro
# 206 -rw-r--r-- zsh2.2/src/loop.pro
# 291 -rw-r--r-- zsh2.2/src/math.pro
# 510 -rw-r--r-- zsh2.2/src/mem.pro
# 3478 -rw-r--r-- zsh2.2/src/params.pro
# 619 -rw-r--r-- zsh2.2/src/subst.pro
# 941 -rw-r--r-- zsh2.2/src/table.pro
# 371 -rw-r--r-- zsh2.2/src/text.pro
# 3277 -rw-r--r-- zsh2.2/src/utils.pro
# 371 -rw-r--r-- zsh2.2/src/watch.pro
# 0 -rw-r--r-- zsh2.2/src/zle_bindings.pro
# 686 -rw-r--r-- zsh2.2/src/zle_main.pro
# 596 -rw-r--r-- zsh2.2/src/zle_refresh.pro
# 761 -rw-r--r-- zsh2.2/src/zle_vi.pro
# 1036 -rw-r--r-- zsh2.2/src/parse.pro
# 1817 -rw-r--r-- zsh2.2/src/zle_tricky.pro
# 18760 -rw-r--r-- zsh2.2/src/parse.c
# 684 -rw-r--r-- zsh2.2/src/zle_utils.pro
# 1429 -rw-r--r-- zsh2.2/src/signals.h.sample
# 5181 -rw-r--r-- zsh2.2/src/zle_move.c
# 14519 -rw-r--r-- zsh2.2/src/zle_misc.c
# 6019 -rw-r--r-- zsh2.2/src/zle_word.c
# 10080 -rw-r--r-- zsh2.2/src/zle_hist.c
# 1119 -rw-r--r-- zsh2.2/src/zle_hist.pro
# 1478 -rw-r--r-- zsh2.2/src/zle_misc.pro
# 909 -rw-r--r-- zsh2.2/src/zle_move.pro
# 733 -rw-r--r-- zsh2.2/src/zle_word.pro
# 2607 -rw-r--r-- zsh2.2/src/config.h
# 1322 -rw-r--r-- zsh2.2/src/signals.h
# 921 -rw-r--r-- zsh2.2/src/Makefile
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= zsh2.2/FEATURES ==============
if test ! -d 'zsh2.2'; then
echo 'x - creating directory zsh2.2'
mkdir 'zsh2.2'
fi
if test -f 'zsh2.2/FEATURES' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/FEATURES (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.2/FEATURES (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/FEATURES' &&
Xvery close to ksh/sh grammar, with csh additions
Xmost features of ksh, bash, and tcsh
X75 builtins, 73 options, 144 key bindings
Xshort for loops, ex: for i (*.c) echo $i
Xselect
Xshell functions
Xconditional expressions (test builtin, [ ... ], and ksh-style [[ ... ]])
Xglobal aliases (may be expanded anywhere on the line)
Xdirectory stack access with =num
Xprocess substitution (vi =(cmd) edits the output of cmd)
Xgeneralized pipes (ls foo >>(cmd1) 2>>(cmd2) pipes stdout to cmd1
X and stderr to cmd2)
Xarithmetic expressions
Xadvanced globbing:
X ls **/file searches recursively for "file" in subdirectories
X ls file<20-> matches file20, file30, file100, etc.
X ls *.(c|pro) matches *.c and *.pro
X ls *(R) matches only world-readable files
X ls *.c~lex.c matches all .c files except lex.c
Xnull command shorthands:
X "< file" is same as "more <file"
X "> file" is same as "cat >file"
X ">> file" is same as "cat >>file"
Xksh-style coprocesses
Xautomatic file stream teeing (ls >foo >bar puts output in two places)
Xchpwd() function run every time you change directory (useful for
X updating the status line)
Xjob control
Xcsh-style history
Xfull vi line editing, including "c2w" and "y$" and such things
Xfull emacs line editing
Xincremental history search
Xmagic-space history
Xspelling correction
Xarray parameters
X$HOSTTYPE, $LINENO, $RANDOM, $SECONDS, $cdpath, $COLUMNS, $fignore,
X $HISTCHARS, $mailpath
Xwith autocd option, typing a directory name by itself is the same as
X typing "cd dirname"
Xmenu completion: pressing TAB repeatedly cycles through the possible matches
Xincremental path hashing
Xautomatic process time reporting for commands that run over a certain limit
Xfull tcsh-style prompt substitution
Xutmp login/logout reporting
Xwith histverify option, performing csh-style history expansions causes the
X input line to be brought up for editing instead of being executed
Xwith sunkeyboardhack option, accidently typed trailing ` characters
X are removed from the input line (for those of you with Sun keyboards :-) )
Xautoloaded functions (loaded from a file when they are first referenced)
X"cd old new" replaces "old" with "new" in directory string
Xgeneralized argument completion, including:
X - command name completion
X - filename and path completion
X - hostname completion
X - key binding completion
X - option completion
X - variable name completion
X - user-specified keyword completion
Xprompt on right side of screen
Xdirectory stacks
Xhistory datestamps and execution time records
Xcommand scheduling (like at(1), but in the shell's context)
Xtty mode freezing
Xup to 9 startup files (but you only need 1 or 2)
X8-bit clean
Xwhich -a cmd lists all occurences of "cmd" in the path
SHAR_EOF
chmod 0644 zsh2.2/FEATURES ||
echo 'restore of zsh2.2/FEATURES failed'
Wc_c="`wc -c < 'zsh2.2/FEATURES'`"
test 2684 -eq "$Wc_c" ||
echo 'zsh2.2/FEATURES: original size 2684, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/NOTES ==============
if test -f 'zsh2.2/NOTES' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/NOTES (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.2/NOTES (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/NOTES' &&
XImportant notes:
X
X1. Stuff like "ls *.sdofij 2>/dev/null" to suppress error messages
X produced by the shell don't work anymore. Filename generation is
X done BEFORE redirection. To avoid the error message, use the
X nonomatch option, or do "( ls *.sdofij ) 2>/dev/null".
X
X2. History substitution is no longer done inside startup files. If you
X have sequences like \! or !" in your startup files, they will break.
X (Especially !"). So check for those; remove the !", and change the
X \! to !.
SHAR_EOF
chmod 0644 zsh2.2/NOTES ||
echo 'restore of zsh2.2/NOTES failed'
Wc_c="`wc -c < 'zsh2.2/NOTES'`"
test 505 -eq "$Wc_c" ||
echo 'zsh2.2/NOTES: original size 505, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/README ==============
if test -f 'zsh2.2/README' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/README (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.2/README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/README' &&
XYou have permission to copy the zsh distribution in whole or in part
Xas long as you don't try to make money off of it, or pretend that you
Xwrote it.
X
XThis is zsh 2.2.0.
X
XTo get this shell running, cd into the src directory and type
X"buildzsh". I tested it on the following machines, where it compiled
Xjust by running this script:
X
XSun SPARCServer 4/690 running SunOS 4.1.2
XNeXTstation running Mach 2.0
XDECStation-5000 running ULTRIX 4.2
XIris 4D/20 running IRIX 4.0.1
XHP 9000/834 running HP-UX 7.00
XIBM RS6000 running AIX 3.2
X(rumored to work on a Pyramid)
X
XIn general, the more BSD-like your system, the more likely it will work.
X
XTabstops are 3 spaces. If you're going to look at my code, run it
Xthough "expand -3" first, or set your tab stops to the same as mine.
X
XThere is a zsh mailing list, "zsh-...@cs.uow.edu.au". To have yourself
Xadded to the list, send a request to "zsh-r...@cs.uow.edu.au".
X
XThe author can be reached via email to one of the following addresses:
X"pfal...@phoenix.princeton.edu", "pfal...@cs.ucsd.edu", "p...@ttisms.com",
X"p...@gnu.ai.mit.edu".
X
XThanks to the following people for help, ideas, accounts, comments,
Xpatches, etc.:
X
XCharles Hannum
XDavid Dobkin
XJim Mattson
XCarlos Carvalho
XBart Schaefer
XPeter Gray
XPure Software, Inc.
XChris P. Ross
XGary Oberbrunner
XJonathan Hardwick
XJohn Navarra
XMichael Lamoureux
XRick Lyons
XDuncan Sinclair
XMark R. Rubin
XJohn Guthrie
XJames Bonfield
XChris Moore
XThomas Winder
XDavid J. MacKenzie
XCharles Rendleman
XRichard Ohnemus
XNik Gervae
XGottfried Necker
XGoran Larsson
XPaul E. Maisano
XNorbert Kiesel
XJosh Diamond
XBill Miskovetz
XPeter Moore
XGeoff Wing
XKent Dickey
XJean-Jacques Moreau
XMichael Brown
XBruce Anderson
XStephen Dum
XLars E. Thon
XMichael Brennan
XXev Gittler
XJarkko Hietaniemi
XZbigniew J Tyrlik
XPierre Racz
XRick Ohnemus
XRichard Dean
XGary D. Kline
XRobert A. Fabian
XByron Rakitzis
XDan Bernstein
XJonathan Kamens
XVincent Granet
XDavid Wilson
XGreg Noel
XPaul Lew
XDan Esbensen
XKartik Subbarao
XRoss Bunker
XMichael Marucheck
XChristopher Pirazzi
XSteve Giovanetti
XKennedy Lemke
XEmin Gun Sirer
XKazuo Itoh
Xlots of other people, I'm sure
X
XModification history:
X
X2.2.0-2.1.0:
Xo should be faster in general
Xo fewer compilation warnings
Xo SPROMPT now uses %R instead of %s for the incorrect string
Xo no longer tries to create FIFOs on NeXTs (thereby causing a panic)
Xo now gets usernames from NIS on irises without crashing (SGI's getpwnam()
X called my strdup(), the pricks. Took me forever to find that. :-) )
Xo fewer 7-bit assumptions
Xo which/whence/type have new options:
X -a = all (find all occurences of command in path)
X -c = csh-style which (default for "which" command)
Xo error message for cd str1 str2 is fixed
Xo relative paths (including .) in cdpath now work
Xo exclusion patterns in glob: ls *.c~lex.c prints all .c files but lex.c
Xo bug with command substitution in chpwd fixed (buffers flushed twice)
Xo relative paths in $path now work
Xo "kill -9 -FOO" no longer kills shell
Xo new options to history/fc:
X -d = prints date commands were entered
X -D = prints running time of commands
Xo "history <num>" prints all commands SINCE <num> as well
Xo history stored differently - should be more efficient
Xo bg'ing a suspended zsh no longer causes problems
Xo "set" no longer prints ONLY exported params (duh)
Xo functions +t now allowed
Xo redirection is done AFTER filename generation
Xo print changes:
X o print -u# prints to fd #
X o print -p prints to coproc
X o -D and -P perform \ substitution first
X o print -0 changed to print -N
Xo read changes:
X o read -u# reads from fd #
X o read -p reads from coproc
X o read -z waits for input if nothing on buffer stack
X o no longer reads from fd 0 if shell is getting input from there
X o echo -n foo | read x now works
Xo getopts is now POSIX conformant
Xo compctl builtin added, replacing hostcmds, foocmds, etc. Controls
X completion of various commands in zle.
X format: compctl -options cmdnams ...
X options tell where to get possible matches from, and include:
X -c = command names
X -f = filenames
X -h = hostnames ($hosts)
X -o = options
X -v = vars
X -b = bindings
X -k name = elements of $name array
X Any number of these options may be used together.
X In addition, compctl -C -options will set the default completion
X names when in command position (by default -c), and compctl -D -options
X will set the default completion names used after unrecognized commands
X or after redirections (by default -f).
Xo foo && bar || fuu now works
Xo ttyctl builtin added
X ttyctl -f freezes the tty. no changes made to the tty settings by
X external programs will be honored when this command is in effect.
X ttyctl -u unfreezes the tty.
X typically, "ttyctl -f" would be used in a zlogin or zshrc script after
X "stty" has been called to set up the terminal.
Xo [[ -e file ]] is now equivalent to [[ -a file ]]
Xo [[ -h file ]] is now equivalent to [[ -L file ]]
Xo the path is now hashed incrementally.
X o if the HASHCMDS option is unset, path hashing is not done at all.
X o if the HASHCMDS option is set but HASHDIRS is unset, commands are placed
X in the hash table when first executed.
X o if the HASHCMDS and HASHDIRS options are both set, commands are placed
X in the hash table when first executed, along with all commands in
X the directory that command was found in (and all directories earlier
X in the path). This is the default situation.
Xo "for i (*.c) do /bin/echo $i ; done | more" no longer hangs
Xo coprocesses now work properly
Xo READNULLCMD is now used instead of NULLCMD for "< file"
Xo POSTEDIT is printed whenever the editor exits
Xo rm path/path/* is now reported by checkrmall()
Xo cmd >&- works
Xo cmd >>! file works
Xo time cmd no longer forks an extra process
Xo setopt printexitvalue ; echo `false` no longer prints anything
Xo here documents work inside eval, etc.
Xo $(...) works inside here documents
Xo "time" by itself prints the shell timings
Xo locals in precmd() or chpwd() work
Xo new glob qualifiers
X o pat(M) sets markdirs, pat(^M) unsets it
X o pat(N) sets nullglob, ...
X o pat(D) sets globdots, ...
Xo ls * only sorts numeric filenames specially if NUMERICGLOBSORT is set
Xo setopt braceccl lets "echo {a-zA-Z}" work
Xo new options: pushdignoredups nohistbeep overstrike
Xo ls **/file is now equivalent to ls ****/file
Xo !'s in history are now escaped when you return to them
Xo history substitution is not done in script files
Xo echo $(!-2) works
Xo histverify and correct 'e' no longer put the edit line in the history
Xo the :x, :q, and :gs modifiers work properly now
Xo zsh -c 'ls =(ls)' no longer hangs
Xo VSWTCH is now set to ^Z on the irises
Xo zsh & no longer causes havoc
Xo USERNAME and LOGNAME are kept separate
Xo $manpath has been added for easy access to the $MANPATH components
Xo zsh now realizes if it is running under emacs, and resigns itself to
X the fact rather than panicking
Xo SIGQUIT is ignored in the PRODUCTION version of zsh, and kills the shell
X in the DEBUG version, rather than vice versa.
Xo GLOBALZSHENV has been added, and GLOBALZPROFILE is sourced in the
X proper place
Xo "kill %" no longer causes the prompt to be printed 3 times if notify
X is set on a NeXT
Xo REPORTTIME has been added; if a job runs longer than this many seconds,
X timing statistics are reported
Xo timing statistics now include a job name (%J)
Xo no longer talks about SIGHUPed jobs if the kill failed
Xo no longer talks about running jobs which don't exist if you do eval exit
X or if you have notify unset
Xo foo=bar comman[tab], for/select/foreach i (*.c[tab] both work
Xo [base]num inside $[...] works
Xo foo=pat(n|ern) works
Xo cd - prints the new directory
Xo l[tab] works if l is an alias
Xo select foo ; ... works (in $argv is assumed)
Xo select reads from the right input
Xo math identifiers can now contain numbers and _'s.
Xo lots of serious memory heap trashing and leaks fixed
Xo echo $HOME[*] no longer crashes the shell
Xo SIGWINCH now changes LINES and COLUMNS in the environment
Xo typeset +r TTY; TTY=foo no longer causes problems
Xo ~ substitution is no longer done in FIGNORE
Xo assignment to SECONDS works
Xo "else if" is no longer a synonym for "elif" <thud>
Xo lots of problems with null lists in flow constructs fixed
Xo no correction done for >file
Xo echo ${foo%bar is no longer weird
Xo modifying array substitutions works
Xo ^O can be bound to something
Xo command substitution in signal handlers no longer causes problems
Xo spelling correction is better ($PAHT is corrected), and SPROMPT
X allows all the regular PROMPT escapes
Xo new prompt escape sequence: %D{...} formats ... part using strftime
Xo shell input no longer butchered using IFS
Xo vi cmd mode has 's' bound to visubstitute, as it should be
Xo you can use ^XS and ^XR in i-search mode
Xo bindings to ^Z and ^@ work now on the irises
Xo ^V{^S,^Q,^Z,etc} now works on sgttyb victims
Xo nopromptclobber changed to nopromptcr
Xo vi 'u' undo works a little better (?)
Xo ESC-key bindings aren't screwed up if VISUAL is set to vi
Xo newline in prompt now works reliably
Xo vi change and delete work with forward-word/search, etc.
Xo somewhat suboptimal screen refresh on irises fixed (several seconds
X per character inserted when TERM=xterm??)
Xo select list printing slightly different
Xo magic-space's handling of hatchars "fixed"
X
X0.03-1.0:
X - "..../" is now "****/". I know this isn't backward compatible,
X but I had no choice; the string "..../" was unquotable.
X - parser was rewritten and improved
X - completion was improved, several bugs fixed (including
X the "$([tab]" bug)
X - vi mode editing is improved
X - the value of PWD and OLDPWD in the environment now change
X - the PROMPT formatting strings %W and %D now print the month
X correctly
X - >&2 echo "error message" no longer prints "bad file number"
X - ${foo%pat} no longer alters the value of foo
X - $_ works
X - ALL_EXPORT no longer causes let statements to crash the shell
X - continue works
X - echo $MAIL no longer dumps core if MAIL is null
X - the new tty driver is selected by default
X - the s modifier no longer complains if it can't find the string
X to substitute
X - list-choices no longer fignores files
X - cd is now smarter about symlinks
X - negative subscripts other than -1 now work
X - $(<filename) works better if filename contains $, ~, or =
X - rehash no longer wastes memory
X - with name=value assignments, name is checked to see if it is
X a valid identifier
X - !1; !2 no longer eats the semicolon
X - $foo:h never returns the empty string if foo starts with /
X - select crashed with some compilers
X - problems with aliases in <(...) constructs have been fixed
X - links pointing to nowhere are denoted with an '&' in listtypes
X - negative arguments are supported
X - the shell does not screw around with the tty so much
X - lots of other stuff
X
X0.02-0.03:
X - two stupid bugs that were introduced in the last patch were fixed:
X - multiple command substitution on a line failed
X - a file descriptor leak caused the shell to crash after a while
X - added 'An Introduction to the Z Shell'
X - behaves properly when the tty session dies suddenly
X - had a serious memory leak on some systems
X - the test and [ builtins have been added, although [[...]]
X is more efficient
X - in your prompt, %m2 now prints foo.bar, %m3 prints foo.bar.com, etc.
X - the -D and -P options to print have been added
X - the NULLCMD and ZDOTDIR parameters have been added
X - ${*:-foo} works
X - "$@" and "$arr[@]" work like ksh
X - .zprofile is sourced before .zshrc in login shells
X - the CSHJUNKIEQUOTES and PUSHDMINUS options have been added
X - REAL_TTY compilation switch added
X - aliases beginning with a space cause the history line to be junked
X if HISTIGNORESPACE is set
X - echo prints bad options instead of complaining about them
X - "set -o" no longer dumps core
X - "alias a=alias; date >a" no longer creates a file called "alias"
X - "function foo() \n { date }" is now legal (the () and the newline
X are allowed)
X - nested brace expressions work properly
X - disabled commands stay disabled after a rehash (or after the shell
X finishes sourcing your .zshrc)
X - corrected aliases work
X - executables in the currect directory are now completed
X - in "case foo", "foo" is not interpreted as a directory name with autocd
X - aliases were not always interpreted properly after a completion
X - bindkey '^?' didn't work
X - echo ${HOST:-{bar}} didn't work
X - editor update is more efficient in some cases
X - menucomplete works even better
X - assign to an array element "foo[1]=bar" didn't always work
X - doesn't print directories like "~tmp" if HOME=/
X - quotes in case statement patterns caused problems
X - pressing ^C right after typing "fc" caused the editor to share
X the tty with the shell
X - echo $(echo 2) produced no output, but echo $(echo x) worked fine (weird)
X
X0.01-0.02:
X - added script to convert most csh aliases to zsh aliases or functions
X - fc -l (history) now appears in the history itself; HISTNOSTORE
X option added to get old behavior
X - the POSIX process group race has been fixed; so 'w | more' should
X no longer hang
X - FCEDIT added, to match the documentation
X - %{...%} in the prompt added
X - execute-named-cmd and execute-last-named-cmd bindings added
X - sources ~/.zshenv in all shells, even if not interactive, unless
X -f is given
X - ^ and # are no longer `magic' by default; use EXTENDEDGLOB option
X to use them
X - now checks for tty sanity before each command
X - if the right side of a variable assignment expands to more than
X one word, array assignment is assumed; so foo=*.c now works
X - ~foo is no longer expanded in completion
X - select now works even if the argument list is not sorted
X - menucompletebeep option added
X - emacs mode is now 8-bit clean by default; use bindkey -em
X to get your meta key back
X - fc -R, fc -W added
X - nocorrect added
X - lines from history file are now split into words at spaces
X - glob-complete, accept-and-menu-complete,
X beginning-of-line-hist, end-of-line-hist bindings added
X - insert-last-word bound to M-. in emacs mode by default; now moves
X back through the history if run repeatedly
X - J and K now bound to history search in vi mode
X - delete-char no longer core dumps on an empty line
X - menu-complete works better
X - the editor checks the settings of VISUAL and EDITOR to set
X default bindings
X - using [[ ... ]] expressions on a symbolic link works as expected
X - various problems with globbing were fixed
X - xx is now the same as !! if HISTCHARS=x
X - added config.h entry for compilers that don't know about void *
X - lexical analysis made more efficient
X - "if echo $? ; then : ; fi" no longer always prints 0
X - removed all enums, '\x7f's from code
X - in "case foo in bar) xxx ;; esac", foo and bar are no longer subject
X to command alias expansion
X - works on platforms where toupper('A') != 'A'
X - \e sequence added to echo
X - + options now work with set
X - AUTORESUME and AUTOCD work better
X - getopts works better (?)
X - spell checking works better
X - "let 2+3=" no longer crashes the shell
X - "foo=bar; echo ${=foo}" no longer crashes the shell
X - "zsh -c" or "zsh -o" no longer causes a core dump
X - "unset MAIL; echo $MAIL" no longer causes a core dump
X - "(xterm&xterm&)&" no longer causes a core dump
X - "echo $HOM[tab]" beeps instead of deleting "$HOM"
X - incremental history search works better
X - the pwd of a fg'd job is now printed _before_ resuming it
X - rv=`echo -n foo` no longer puts garbage in $rv
X - "=1/*" now works as expected
X - ^Z can now be bound to something
X - the STTY parameter and the builtin builtin are now documented
X - IFS=x; foo=`echo foo` no longer puts a newline in $foo
X - $status added for csh compatibility
X - arrays are automatically expanded if you say 'foo[1234]=x'
X - shell now ignores SIGQUIT (it was commented out before :-)
X - the times builtin works on systems where times() returns > 0
X - no longer hangs the terminal if you ^S before flow control
X is turned off
X - "date ; read foo" now works in interactive shells
X - <<-foo is now parsed as <<- foo, not << -foo
X - fixed various errors in the documentation
X
X0.00-0.01:
X - %M and %m now work as documented.
X - bad things no longer happen if COLUMNS is set to 0
X - SH_WORD_SPLIT and ${=foo} now work
X - the default value of WORDCHARS includes more characters
X - if the cursor is at the end of the line, vi-cmd-mode
X moves it back one position.
X - delete-char now acts more like x in vi.
X - a "prompt" parameter has been added, which is equivalent to
X PROMPT and PS1.
X - zsh no longer expands symbolic links. The CHASELINKS option
X has been provided to get the old behavior.
X - history searches ignore lines that are the same as the line
X in the buffer.
X - you can get a literal ! in your prompt now with \!.
X - -z, -n, and != in [[ ... ]] expressions work.
X - the shell no longer hangs when inputting "[[ ]\n"
X - the "menu-complete" and "menu-expand-or-complete" bindings have
X been added.
X - menu-complete no longer beeps.
X - reverse-menu-complete no longer dumps core if it gets called before
X a normal completion.
X - typeahead lines are no longer thrown away on machines with sgttyb.
X - !foo no longer matches lines with 'foo' in them (not at the beginning)
X - kill -9 % no longer kills the shell
X - no longer sources .zshrc from shell scripts or with -c
X - no longer needs limits.h, strtol
X - exporting HOSTTYPE, etc. works
X - fixed serious bugs related to . in path
X - numbers in weird bases now work
X
XKnown Bugs
X - terminal acts weird under OpenWindows cmdtool
X - xterm run in background inherits bad terminal modes
X
SHAR_EOF
chmod 0644 zsh2.2/README ||
echo 'restore of zsh2.2/README failed'
Wc_c="`wc -c < 'zsh2.2/README'`"
test 17490 -eq "$Wc_c" ||
echo 'zsh2.2/README: original size 17490, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/doc/intro.txt ==============
if test ! -d 'zsh2.2/doc'; then
echo 'x - creating directory zsh2.2/doc'
mkdir 'zsh2.2/doc'
fi
if test -f 'zsh2.2/doc/intro.txt' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/doc/intro.txt (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.2/doc/intro.txt (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/doc/intro.txt' &&
X
X
X
X
X
X
X An Introduction to the Z Shell
X
X
X Paul Falstad
X pfal...@phoenix.princeton.edu
X
X
X
X
X
X
Xzsh is a shell designed for interactive use, although it is
Xalso a powerful scripting language. Many of the useful
Xfeatures of bash, ksh, and tcsh were incorporated into zsh;
Xmany original features were added. This document details
Xsome of the unique features of zsh. It assumes basic
Xknowledge of the standard UNIX shells; the intent is to show
Xa reader already familiar with one of the other major shells
Xwhat makes zsh more useful or more powerful. This document
Xis not at all comprehensive; read the manual entry for a
Xdescription of the shell that is complete and concise,
Xalthough somewhat overwhelming and devoid of examples.
X
XFilename Generation
X
XOtherwise known as globbing, filename generation is quite
Xextensive in zsh. Of course, it has all the basics:
X
X% ls
XMakefile file.pro foo.o main.o q.c run234 stuff
Xbar.o foo link morestuff run123 run240 sub
Xfile.h foo.c main.h pipe run2 run303
X% ls *.c
Xfoo.c q.c
X% ls *.[co]
Xbar.o foo.c foo.o main.o q.c
X% ls foo.?
Xfoo.c foo.o
X% ls *.[^c]
Xbar.o file.h foo.o main.h main.o
X% ls *.[^oh]
Xfoo.c q.c
X
X
XAlso, if the EXTENDEDGLOB option is set, some new features
Xare activated. For example, the ^ character negates the
Xpattern following it:
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 2 -
X
X% setopt extendedglob
X% ls -d ^*.c
XMakefile file.pro link morestuff run2 run303
Xbar.o foo main.h pipe run234 stuff
Xfile.h foo.o main.o run123 run240 sub
X% ls -d ^*.*
XMakefile link pipe run2 run240 stuff
Xfoo morestuff run123 run234 run303 sub
X% ls -d ^Makefile
Xbar.o foo link morestuff run123 run240 sub
Xfile.h foo.c main.h pipe run2 run303
Xfile.pro foo.o main.o q.c run234 stuff
X% ls -d *.^c
X.rhosts bar.o file.h file.pro foo.o main.h main.o
X
X
XAn expression of the form <x-y> matches a range of integers:
X
X% ls run<200-300>
Xrun234 run240
X% ls run<300-400>
Xrun303
X% ls run<-200>
Xrun123 run2
X% ls run<300->
Xrun303
X% ls run<>
Xrun123 run2 run234 run240 run303
X
X
XGrouping is possible:
X
X% ls (foo|bar).*
Xbar.o foo.c foo.o
X% ls *.(c|o|pro)
Xbar.o file.pro foo.c foo.o main.o q.c
X
X
XAlso, the string ****/ forces a recursive search of sub-
Xdirectories:
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 3 -
X
X% ls -R
XMakefile file.pro foo.o main.o q.c run234 stuff
Xbar.o foo link morestuff run123 run240 sub
Xfile.h foo.c main.h pipe run2 run303
X
Xmorestuff:
X
Xstuff:
Xfile xxx yyy
X
Xstuff/xxx:
Xfoobar
X
Xstuff/yyy:
Xfrobar
X% ls ****/*bar
Xstuff/xxx/foobar stuff/yyy/frobar
X% ls ****/f*
Xfile.h foo foo.o stuff/xxx/foobar
Xfile.pro foo.c stuff/file stuff/yyy/frobar
X% ls *bar*
Xbar.o
X% ls ****/*bar*
Xbar.o stuff/xxx/foobar stuff/yyy/frobar
X% ls stuff/****/*bar*
Xstuff/xxx/foobar stuff/yyy/frobar
X
X
X
XIt is possible to exclude certain files from the patterns
Xusing the ~ character. A pattern of the form *.c~bar.c
Xlists all files matching *.c, except for the file bar.c.
X
X% ls *.c
Xfoo.c foob.c bar.c
X% ls *.c~bar.c
Xfoo.c foob.c
X% ls *.c~f*
Xbar.c
X
X
X
XOne can add a number of qualifiers to the end of any of
Xthese patterns, to restrict matches to certain file types.
XA qualified pattern is of the form
X
X pattern(...)
X
X
Xwith single-letter qualifiers inside the parentheses.
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 4 -
X
X% alias l='ls -dF'
X% l *
XMakefile foo* main.h q.c run240
Xbar.o foo.c main.o run123 run303
Xfile.h foo.o morestuff/ run2 stuff/
Xfile.pro link@ pipe run234 sub
X% l *(/)
Xmorestuff/ stuff/
X% l *(@)
Xlink@
X% l *(*)
Xfoo* link@ morestuff/ stuff/
X% l *(x)
Xfoo* link@ morestuff/ stuff/
X% l *(X)
Xfoo* link@ morestuff/ stuff/
X% l *(R)
Xbar.o foo* link@ morestuff/ run123 run240
Xfile.h foo.c main.h pipe run2 run303
Xfile.pro foo.o main.o q.c run234 stuff/
X
X
XNote that *(x) and *(*) both match executables. *(X)
Xmatches files executable by others, as opposed to *(x),
Xwhich matches files executable by the owner. *(R) and *(r)
Xmatch readable files; *(W) and *(w), which checks for writ-
Xable files. *(W) is especially important, since it checks
Xfor world-writable files:
X
X% l *(w)
Xbar.o foo* link@ morestuff/ run123 run240
Xfile.h foo.c main.h pipe run2 run303
Xfile.pro foo.o main.o q.c run234 stuff/
X% l *(W)
Xlink@ run240
X% l -l link run240
Xlrwxrwxrwx 1 pfalstad 10 May 23 18:12 link -> /bin/false*
X-rw-rw-rw- 1 pfalstad 0 May 23 18:12 run240
X
X
XYou can filter out the symbolic links with the ^ character:
X
X% l *(W^@)
Xrun240
X% l *(x)
Xfoo* link@ morestuff/ stuff/
X% l *(x^@/)
Xfoo*
X
X
XTo find all plain files, you can use .:
X
X
X
X
X
X
X
X
X
X
X
X
X
X - 5 -
X
X% l *(.)
XMakefile file.h foo* foo.o main.o run123 run234 run303
Xbar.o file.pro foo.c main.h q.c run2 run240 sub
X% l *(^.)
Xlink@ morestuff/ pipe stuff/
X% l s*(.)
Xstuff/ sub
X% l *(p)
Xpipe
X% l -l *(p)
Xprw-r--r-- 1 pfalstad 0 May 23 18:12 pipe
X
X
X*(U) matches all files owned by you. To search for all
Xfiles not owned by you, use *(^U):
X
X% l -l *(^U)
X-rw------- 1 subbarao 29 May 23 18:13 sub
X
X
XThis searches for setuid files:
X
X% l -l *(s)
X-rwsr-xr-x 1 pfalstad 16 May 23 18:12 foo*
X
X
XThis checks for a certain user's files:
X
X% ypmatch subbarao passwd
Xsubbarao:*:3338:35:Kartik Subbarao:/u/subbarao:/usr/princeton/bin/zsh
X% l -l *(u3338)
X-rw------- 1 subbarao 29 May 23 18:13 sub
X
X
X
XStartup Files
X
XThere are five startup files that zsh will read commands
Xfrom:
X
X$ZDOTDIR/.zshenv
X$ZDOTDIR/.zprofile
X$ZDOTDIR/.zshrc
X$ZDOTDIR/.zlogin
X$ZDOTDIR/.zlogout
X
X
XIf ZDOTDIR is not set, then the value of HOME is used; this
Xis the usual case.
X
X.zshenv is sourced on all invocations of the shell, unless
Xthe -f option is set. It should contain commands to set the
Xcommand search path, plus other important environment vari-
Xables. .zshenv should not contain commands that produce
Xoutput or assume the shell is attached to a tty.
X
X.zshrc is sourced in interactive shells. It should contain
Xcommands to set up aliases, functions, options, key bind-
Xings, etc.
X
X
X
X
X
X - 6 -
X.zlogin is sourced in login shells. It should contain com-
Xmands that should be executed only in login shells. .zlo-
Xgout is sourced when login shells exit. .zprofile is simi-
Xlar to .zlogin, except that it is sourced before .zshrc.
X.zprofile is meant as an alternative to .zlogin for ksh
Xfans; the two are not intended to be used together, although
Xthis could certainly be done if desired. .zlogin is not the
Xplace for alias definitions, options, environment variable
Xsettings, etc.; as a general rule, it should not change the
Xshell environment at all. Rather, it should be used to set
Xthe terminal type and run a series of external commands
X(fortune, msgs, etc).
X
XShell Functions
X
Xzsh also allows you to create your own commands by defining
Xshell functions. For example:
X
X% yp () {
X> ypmatch $1 passwd.byname
X> }
X% yp pfalstad
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X
X
XThis function looks up a user in the NIS password map. The
X$1 expands to the first argument to yp. The function could
Xhave been equivalently defined in one of the following ways:
X
X% function yp {
X> ypmatch $1 passwd.byname
X> }
X% function yp () {
X> ypmatch $1 passwd.byname
X> }
X% function yp () ypmatch $1 passwd.byname
X
X
XNote that aliases are expanded when the function definition
Xis parsed, not when the function is executed. For example:
X
X% alias ypmatch=echo
X% yp pfalstad
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X
X
XSince the alias was defined after the function was parsed,
Xit has no effect on the function's execution. However, if
Xwe define the function again with the alias in place:
X
X% function yp () { ypmatch $1 passwd.byname }
X% yp pfalstad
Xpfalstad passwd.byname
X
X
Xit is parsed with the new alias definition in place. There-
Xfore, in general you must define aliases before functions.
X
XWe can make the function take multiple arguments:
X
X
X
X
X
X
X - 7 -
X
X% unalias ypmatch
X% yp () {
X> for i
X> do ypmatch $i passwd.byname
X> done
X> }
X% yp pfalstad subbarao sukthnkr
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
Xsubbarao:*:3338:35:Kartik Subbarao:/u/subbarao:/usr/princeton/bin/zsh
Xsukthnkr:*:1267:35:Rahul Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh
X
X
XThe for i loops through each of the function's arguments,
Xsetting i equal to each of them in turn. We can also make
Xthe function do something sensible if no arguments are
Xgiven:
X
X% yp () {
X> if (( $# == 0 ))
X> then echo usage: yp name ...; fi
X> for i; do ypmatch $i passwd.byname; done
X> }
X% yp
Xusage: yp name ...
X% yp pfalstad sukthnkr
Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
Xsukthnkr:*:1267:35:Rahul Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh
X
X
X$# is the number of arguments supplied to the function. If
Xit is equal to zero, we print a usage message; otherwise, we
Xloop through the arguments, and ypmatch all of them.
X
XHere's a function that selects a random line from a file:
X
X% randline () {
X> integer z=$(wc -l <$1)
X> sed -n $[RANDOM % z + 1]p $1
X> }
X% randline /etc/motd
XPHOENIX WILL BE DOWN briefly Friday morning, 5/24/91 from 8 AM to
X% randline /etc/motd
XSunOS Release 4.1.1 (PHOENIX) #19: Tue May 14 19:03:15 EDT 1991
X% randline /etc/motd
X| Please use the "msgs" command to read announcements. Refer to the |
X% echo $z
X
X%
X
X
Xrandline has a local variable, z, that holds the number of
Xlines in the file. $[RANDOM % z + 1] expands to a random
Xnumber between 1 and z. An expression of the form $[...]
Xexpands to the value of the arithmetic expression within the
Xbrackets, and the RANDOM variable returns a random number
Xeach time it is referenced. % is the modulus operator, as
Xin C. Therefore, sed -n $[RANDOM%z+1]p picks a random line
Xfrom its input, from 1 to z.
X
X
X
X
X
X
X - 8 -
XFunction definitions can be viewed with the functions buil-
Xtin:
X
X% functions randline
Xrandline () {
X integer z=$(wc -l <$1)
X sed -n $[RANDOM % z + 1]p $1
X
X}
X% functions
Xyp () {
X if let $# == 0
X
X then
X echo usage: yp name ...
X
X fi
X for i
X do
X ypmatch $i passwd.byname
X
X done
X
X}
Xrandline () {
X integer z=$(wc -l <$1)
X sed -n $[RANDOM % z + 1]p $1
X
X}
X
X
XHere's another one:
X
X% cx () { chmod +x $* }
X% ls -l foo bar
X-rw-r--r-- 1 pfalstad 29 May 24 04:38 bar
X-rw-r--r-- 1 pfalstad 29 May 24 04:38 foo
X% cx foo bar
X% ls -l foo bar
X-rwxr-xr-x 1 pfalstad 29 May 24 04:38 bar
X-rwxr-xr-x 1 pfalstad 29 May 24 04:38 foo
X
X
XNote that this could also have been implemented as an alias:
X
X% chmod 644 foo bar
X% alias cx='chmod +x'
X% cx foo bar
X% ls -l foo bar
X-rwxr-xr-x 1 pfalstad 29 May 24 04:38 bar
X-rwxr-xr-x 1 pfalstad 29 May 24 04:38 foo
X
X
X
XInstead of defining a lot of functions in your .zshrc, all
Xof which you may not use, it is often better to use the
Xautoload builtin. The idea is, you create a directory where
Xfunction definitions are stored, declare the names in your
X.zshrc, and tell the shell where to look for them. Whenever
Xyou reference a function, the shell will automatically load
X
X
X
X
X
X - 9 -
Xit into memory.
X
X% mkdir /tmp/funs
X% cat >/tmp/funs/yp
Xypmatch $1 passwd.byname
X^D
X% cat >/tmp/funs/cx
Xchmod +x $*
X^D
X% FPATH=/tmp/funs
X% autoload cx yp
X% functions cx yp
Xundefined cx ()
Xundefined yp ()
X% chmod 755 /tmp/funs/{cx,yp}
X% yp egsirer
Xegsirer:*:3214:35:Emin Gun Sirer:/u/egsirer:/bin/sh
X% functions yp
Xyp () {
X ypmatch $1 passwd.byname
X}
X
X
XThis idea has other benefits. By adding a #! header to the
Xfiles, you can make them double as shell scripts. (Although
Xit is faster to use them as functions, since a separate pro-
Xcess is not created.)
X
X% ed /tmp/funs/yp
X25
Xi
X#! /usr/local/bin/zsh
Xw
X42
Xq
X% </tmp/funs/yp
X#! /usr/local/bin/zsh
Xypmatch $1 passwd.byname
X% /tmp/funs/yp sukthnkr
Xsukthnkr:*:1267:35:Rahul Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh
X
X
XNow other people, who may not use zsh, or who don't want to
Xcopy all of your .zshrc, may use these functions as shell
Xscripts.
X
XDirectories
X
XOne nice feature of zsh is the way it prints directories.
XFor example, if we set the prompt like this:
X
Xphoenix% PROMPT='%~> '
X~> cd src
X~/src>
X
X
Xthe shell will print the current directory in the prompt,
Xusing the ~ character. However, zsh is smarter than most
Xother shells in this respect:
X
X
X
X
X
X
X - 10 -
X
X~/src> cd ~subbarao
X~subbarao> cd ~maruchck
X~maruchck> cd lib
X~maruchck/lib> cd fun
X~maruchck/lib/fun> foo=/usr/princeton/common/src
X~maruchck/lib/fun> cd ~foo
X~foo> cd ..
X/usr/princeton/common> cd src
X~foo> cd news/nntp
X~foo/news/nntp> cd inews
X~foo/news/nntp/inews>
X
X
XNote that zsh prints other users' directories in the form
X~user. Also note that you can set a parameter and use it as
Xa directory name; zsh will act as if foo is a user with the
Xlogin directory /usr/princeton/common/src. This is con-
Xvenient, especially if you're sick of seeing prompts like
Xthis:
X
Xphoenix:/usr/princeton/common/src/X.V11R4/contrib/clients/xv/docs>
X
X
XIf you get stuck in this position, you can give the current
Xdirectory a short name, like this:
X
X/usr/princeton/common/src/news/nntp/inews> inews=$PWD
X/usr/princeton/common/src/news/nntp/inews> echo ~inews
X/usr/princeton/common/src/news/nntp/inews
X~inews>
X
X
XWhen you reference a directory in the form ~inews, the shell
Xassumes that you want the directory displayed in this form;
Xthus simply typing echo ~inews or cd ~inews causes the
Xprompt to be shortened. You can define a shell function for
Xthis purpose:
X
X~inews> namedir () { $1=$PWD ; : ~$1 }
X~inews> cd /usr/princeton/bin
X/usr/princeton/bin> namedir pbin
X~pbin> cd /var/spool/mail
X/var/spool/mail> namedir spool
X~spool> cd .msgs
X~spool/.msgs>
X
X
XYou may want to add this one-line function to your .zshrc.
X
Xzsh can also put the current directory in your title bar, if
Xyou are using a windowing system. One way to do this is
Xwith the chpwd function, which is automatically executed by
Xthe shell whenever you change directory. If you are using
Xxterm, this will work:
X
Xchpwd () { print -Pn '^[]2;%~^G' }
X
X
XThe -P option tells print to treat its arguments like a
X
X
X
X
X
X - 11 -
Xprompt string; otherwise the %~ would not be expanded. The
X-n option suppresses the terminating newline, as with echo.
X
XIf you are using an IRIS wsh, do this:
X
Xchpwd () { print -Pn '^[P1.y%~^[' }
X
X
XThe print -D command has other uses. For example, to print
Xthe current directory to standard output in short form, you
Xcan do this:
X
X% print -D $PWD
X~subbarao/src
X
X
Xand to print each component of the path in short form:
X
X% print -D $path
X/bin /usr/bin ~locbin ~locbin/X11 ~/bin
X
X
X
XDirectory Stacks
X
XIf you use csh, you may know about directory stacks. The
Xpushd command puts the current directory on the stack, and
Xchanges to a new directory; the popd command pops a direc-
Xtory off the stack and changes to it.
X
Xphoenix% cd
Xphoenix% PROMPT='Z %~> '
XZ ~> pushd /tmp
X/tmp ~
XZ /tmp> pushd /usr/etc
X/usr/etc /tmp ~
XZ /usr/etc> pushd /usr/bin
X/usr/bin /usr/etc /tmp ~
XZ /usr/bin> popd
X/usr/etc /tmp ~
XZ /usr/etc> popd
X/tmp ~
XZ /tmp> pushd /etc
X/etc /tmp ~
XZ /etc> popd
X/tmp ~
X
X
Xzsh's directory stack commands work similarly. One differ-
Xence is the way pushd is handled if no arguments are given.
XAs in csh, this exchanges the top two elements of the direc-
Xtory stack:
X
XZ /tmp> dirs
X/tmp ~
XZ /tmp> pushd
X~ /tmp
X
X
Xunless the stack only has one entry:
X
X
X
X
X
X - 12 -
X
XZ ~> popd
X/tmp
XZ /tmp> dirs
X/tmp
XZ /tmp> pushd
X~ /tmp
X
X
Xor unless the PUSHDTOHOME option is set:
X
XZ ~> setopt pushdtohome
XZ ~> pushd
X~ ~ /tmp
X
X
X
XAs an alternative to using directory stacks in this manner,
Xwe can get something like a directory history by setting a
Xfew more options and parameters:
X
X~> DIRSTACKSIZE=8
X~> setopt autopushd pushdminus pushdsilent pushdtohome
X~> alias dh='dirs -v'
X~> cd /tmp
X/tmp> cd /usr
X/usr> cd bin
X/usr/bin> cd ../pub
X/usr/pub> dh
X0 /usr/pub
X1 /usr/bin
X2 /usr
X3 /tmp
X4 ~
X/usr/pub> cd -3
X/tmp> dh
X0 /tmp
X1 /usr/pub
X2 /usr/bin
X3 /usr
X4 ~
X/tmp> ls =2/df
X/usr/bin/df
X/tmp> cd -4
X~>
X
X
XNote that =2 expanded to the second directory in the history
Xlist, and that cd -3 recalled the third directory in the
Xlist.
X
XYou may be wondering what all those options do. AUTOPUSHD
Xmade cd act like pushd. (alias cd=pushd is not sufficient,
Xfor various reasons.) PUSHDMINUS swapped the meaning of cd
X+1 and cd -1; we want them to mean the opposite of what they
Xmean in csh, because it makes more sense in this scheme, and
Xit's easier to type:
X
X
X
X
X
X
X
X
X - 13 -
X
X~> dh
X0 ~
X1 /tmp
X2 /usr/pub
X3 /usr/bin
X4 /usr
X~> unsetopt pushdminus
X~> cd +1
X/tmp> dh
X0 /tmp
X1 ~
X2 /usr/pub
X3 /usr/bin
X4 /usr
X/tmp> cd +2
X/usr/pub>
X
X
XPUSHDSILENT keeps the shell from printing the directory
Xstack each time we do a cd, and PUSHDTOHOME we mentioned
Xearlier:
X
X/usr/pub> unsetopt pushdsilent
X/usr/pub> cd /etc
X/etc /usr/pub /tmp ~ /usr/bin /usr
X/etc> cd
X~ /etc /usr/pub /tmp ~ /usr/bin /usr
X~> unsetopt pushdtohome
X~> cd
X/etc ~ /usr/pub /tmp ~ /usr/bin /usr
X/etc>
X
X
XDIRSTACKSIZE keeps the directory stack from getting too
Xlarge, much like HISTSIZE:
X
X/etc> setopt pushdsilent
X/etc> cd /
X/> cd /
X/> cd /
X/> cd /
X/> cd /
X/> cd /
X/> cd /
X/> cd /
X/> dh
X0 /
X1 /
X2 /
X3 /
X4 /
X5 /
X6 /
X7 /
X
X
X
X
X
X
X
X
X
X
X - 14 -
XCommand/Process Substitution
X
XCommand substitution in zsh can take two forms. In the
Xtraditional form, a command enclosed in backquotes (`...`)
Xis replaced on the command line with its output. This is
Xthe form used by the older shells. Newer shells (like zsh)
Xalso provide another form, $(...). This form is much easier
Xto nest.
X
X% ls -l `echo /vmunix`
X-rwxr-xr-x 1 root 1209702 May 14 19:04 /vmunix
X% ls -l $(echo /vmunix)
X-rwxr-xr-x 1 root 1209702 May 14 19:04 /vmunix
X% who | grep mad
Xsubbarao ttyt7 May 23 15:02 (mad55sx15.Prince)
Xpfalstad ttyu1 May 23 16:25 (mad55sx14.Prince)
Xsubbarao ttyu6 May 23 15:04 (mad55sx15.Prince)
Xpfalstad ttyv3 May 23 16:25 (mad55sx14.Prince)
X% who | grep mad | awk '{print $2}'
Xttyt7
Xttyu1
Xttyu6
Xttyv3
X% cd /dev; ls -l $(who |
X> grep $(echo mad) |
X> awk '{ print $2 }')
Xcrwx-w---- 1 subbarao 20, 71 May 23 18:35 ttyt7
Xcrw--w---- 1 pfalstad 20, 81 May 23 18:42 ttyu1
Xcrwx-w---- 1 subbarao 20, 86 May 23 18:38 ttyu6
Xcrw--w---- 1 pfalstad 20, 99 May 23 18:41 ttyv3
X
X
XMany common uses of command substitution, however, are
Xsuperseded by other mechanisms of zsh:
X
X% ls -l `tty`
Xcrw-rw-rw- 1 root 20, 28 May 23 18:35 /dev/ttyqc
X% ls -l $TTY
Xcrw-rw-rw- 1 root 20, 28 May 23 18:35 /dev/ttyqc
X% ls -l `which rn`
X-rwxr-xr-x 1 root 172032 Mar 6 18:40 /usr/princeton/bin/rn
X% ls -l =rn
X-rwxr-xr-x 1 root 172032 Mar 6 18:40 /usr/princeton/bin/rn
X
X
XA command name with a = prepended is replaced with its full
Xpathname. This can be very convenient. If it's not con-
Xvenient for you, you can turn it off:
X
X% ls
X=foo =bar
X% ls =foo =bar
Xzsh: foo not found
X% setopt noequals
X% ls =foo =bar
X=foo =bar
X
X
X
XAnother nice feature is process substitution:
X
X
X
X
X
X - 15 -
X
X% who | fgrep -f =(print -l root lemke shgchan subbarao)
Xroot console May 19 10:41
Xlemke ttyq0 May 22 10:05 (narnia:0.0)
Xlemke ttyr7 May 22 10:05 (narnia:0.0)
Xlemke ttyrd May 22 10:05 (narnia:0.0)
Xshgchan ttys1 May 23 16:52 (gaudi.Princeton.)
Xsubbarao ttyt7 May 23 15:02 (mad55sx15.Prince)
Xsubbarao ttyu6 May 23 15:04 (mad55sx15.Prince)
Xshgchan ttyvb May 23 16:51 (gaudi.Princeton.)
X
X
XA command of the form =(...) is replaced with the name of a
Xfile containing its output. (A command substitution, on the
SHAR_EOF
true || echo 'restore of zsh2.2/doc/intro.txt failed'
fi
echo 'End of zsh2.2 part 1'
echo 'File zsh2.2/doc/intro.txt is continued in part 2'
echo 2 > _shar_seq_.tmp
exit 0

exit 0 # Just in case...

Paul Falstad

unread,
May 13, 1992, 11:53:28 AM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 98
Archive-name: zsh2.2/part02

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.02 (part 2 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/doc/intro.txt continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 2; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping zsh2.2/doc/intro.txt'
else
echo 'x - continuing file zsh2.2/doc/intro.txt'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/doc/intro.txt' &&

Xother hand, is replaced with the output itself.) print -l is
Xlike echo, excepts that it prints its arguments one per
Xline, the way fgrep expects them:
X
X% print -l foo bar
Xfoo
Xbar
X
X
XWe could also have written:
X
X% who | fgrep -f =(echo 'root
X> lemke
X> shgchan
X> subbarao')
X
X
XUsing process substitution, you can edit the output of a
Xcommand:
X
X% ed =(who | fgrep -f ~/.friends)
X355
Xg/lemke/d
Xw /tmp/filbar
X226
Xq
X% cat /tmp/filbar


Xroot console May 19 10:41

Xshgchan ttys1 May 23 16:52 (gaudi.Princeton.)
Xsubbarao ttyt7 May 23 15:02 (mad55sx15.Prince)
Xsubbarao ttyu6 May 23 15:04 (mad55sx15.Prince)
Xshgchan ttyvb May 23 16:51 (gaudi.Princeton.)
X
X

Xor easily read archived mail:


X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X

X - 16 -
X
X% mail -f =(zcat ~/mail/oldzshmail.Z)
X"/tmp/zsha06024": 84 messages, 0 new, 43 unread
X> 1 U TO: pfalstad, zsh (10)
X 2 U nytim!t...@uunet.uu.net, Re: Zsh on Sparc1 /SunOS 4.0.3
X 3 U JAM%T...@utrcgw.utc.com, zsh fix (15)
X 4 U d...@eng.umd.edu, way to find out if running zsh? (25)
X 5 U d...@eng.umd.edu, Re: way to find out if running zsh? (17)
X 6 r d...@eng.umd.edu, Meta . (18)
X 7 U ja...@cs.glasgow.ac.uk, Re: problem building zsh (147)
X 8 U nytim!t...@uunet.uu.net, Re: Zsh on Sparc1 /SunOS 4.0.3
X 9 ursa!jmd, Another fix... (61)
X 10 U ppla...@bbn.com, Re: v18i084: Zsh 2.00 - A small complaint (36)
X 11 U lub...@cs.rochester.edu, POSIX job control (34)
X 12 U yale!bronson!t...@uunet.UU.NET
X 13 U br...@rpi.edu, zsh (36)
X 14 S subbarao, zsh sucks!!!! (286)
X 15 U snibru!d241s008!d241s013!a...@relay.EU.net, zsh (165)
X 16 U nytim!t...@uunet.UU.NET, Re: Zsh on Sparc1 /SunOS 4.0.3
X 17 U subbarao, zsh is a junk shell (43)
X 18 U amar...@vela.acs.oakland.edu, zsh (33)
X43u/84 1: x
X% ls -l /tmp/zsha06024
X/tmp/zsha06024 not found
X
X
XNote that the shell creates a temporary file, and deletes it
Xwhen the command is finished.
X
X% diff =(ls) =(ls -F)
X3c3
X< fortune
X---
X> fortune*
X10c10
X< strfile
X---
X> strfile*
X
X
XIf you read zsh's man page, you may notice that <(...) is
Xanother form of process substitution which is similar to
X=(...). There is an important difference between the two.
XIn the <(...) case, the shell creates a named pipe (FIFO)
Xinstead of a file. This is better, since it does not fill
Xup the file system; but it does not work in all cases. In
Xfact, if we had replaced =(...) with <(...) in the examples
Xabove, all of them would have stopped working except for
Xfgrep -f <(...). You can not edit a pipe, or open it as a
Xmail folder; fgrep, however, has no problem with reading a
Xlist of words from a pipe. You may wonder why diff <(foo)
Xbar doesn't work, since foo | diff - bar works; this is
Xbecause diff creates a temporary file if it notices that one
Xof its arguments is -, and then copies its standard input to
Xthe temporary file.
X
XAliasing
X
XOften-used commands can be abbreviated with an alias:


X
X
X
X
X
X

X - 17 -
X
X% alias uc=uncompress
X% ls
Xhanoi.Z
X% uc hanoi
X% ls
Xhanoi
X
X
Xor commands with certain desired options:
X
X% alias fm='finger -m'
X% fm root
XLogin name: root In real life: Operator
XDirectory: / Shell: /bin/csh
XOn since May 19 10:41:15 on console 3 days 5 hours Idle Time
XNo unread mail
XNo Plan.
X
X% alias lock='lock -p -60000'
X% lock
Xlock: /dev/ttyr4 on phoenix. timeout in 60000 minutes
Xtime now is Fri May 24 04:23:18 EDT 1991
XKey:
X
X% alias l='ls -AF'
X% l /
X.bash_history kadb*
X.bashrc lib@
X.cshrc licensed/
X.exrc lost+found/
X.login macsyma
X
X
XAliases can also be used to replace old commands:
X
X% alias grep=egrep ps=sps make=gmake
X% alias whoami='echo root'
X% whoami
Xroot
X
X
Xor to define new ones:


X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X

X - 18 -
X
X% cd /
X% alias sz='ls -l | sort -n +3 | tail -10'
X% sz
Xdrwxr-sr-x 7 bin 3072 May 23 11:59 etc
Xdrwxrwxrwx 26 root 5120 May 24 04:20 tmp
Xdrwxr-xr-x 2 root 8192 Dec 26 19:34 lost+found
Xdrwxr-sr-x 2 bin 14848 May 23 18:48 dev
X-r--r--r-- 1 root 140520 Dec 26 20:08 boot
X-rwxr-xr-x 1 root 311172 Dec 26 20:08 kadb
X-rwxr-xr-x 1 root 1209695 Apr 16 15:33 vmunix.old
X-rwxr-xr-x 1 root 1209702 May 14 19:04 vmunix
X-rwxr-xr-x 1 root 1209758 May 21 12:23 vmunix.new.kernelmap.old
X-rwxr-xr-x 1 root 1711848 Dec 26 20:08 vmunix.org
X% cd
X% alias rable='ls -AFtrd *(R)' nrable='ls -AFtrd *(^R)'
X% rable
XREADME func/ bin/ pub/ News/ src/
Xnicecolors etc/ scr/ tmp/ iris/ zsh*
X% nrable
XMailboxes/ mail/ notes
X
X
X(The pattern *(R) matches all readable files in the current
Xdirectory, and *(^R) matches all unreadable files.)
X
XMost other shells have aliases of this kind (command
Xaliases). However, zsh also has global aliases, which are
Xsubstituted anywhere on a line. Global aliases can be used
Xto abbreviate frequently-typed usernames, hostnames, etc.
X
X% alias -g me=pfalstad gun=egsirer mjm=maruchck
X% who | grep me
Xpfalstad ttyp0 May 24 03:39 (mickey.Princeton)
Xpfalstad ttyp5 May 24 03:42 (mickey.Princeton)
X% fm gun
XLogin name: egsirer In real life: Emin Gun Sirer
XDirectory: /u/egsirer Shell: /bin/sh
XLast login Thu May 23 19:05 on ttyq3 from bow.Princeton.ED
XNew mail received Fri May 24 02:30:28 1991;
X unread since Fri May 24 02:30:27 1991
X% alias -g phx=phoenix.princeton.edu warc=wuarchive.wustl.edu
X% ftp warc
XConnected to wuarchive.wustl.edu.
X
X
XHere are some more interesting uses.
X
X% alias -g M='| more' GF='| fgrep -f ~/.friends'
X% who M # pipes the output of who through more
X% who GF # see if your friends are on
X% w GF # see what your friends are doing
X
X
XAnother example makes use of zsh's process substitution. If
Xyou run NIS, and you miss being able to do this:
X
X% grep pfalstad /etc/passwd


X
X
X
X
X
X
X

X - 19 -
Xyou can define an alias that will seem more natural than
Xypmatch pfalstad passwd:
X
X% alias -g PASS='<(ypcat passwd)'
X% grep pfalstad PASS


Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X
X

XIf you're really crazy, you can even call it /etc/passwd:
X
X% alias -g /etc/passwd='<(ypcat passwd)'
X% grep pfalstad /etc/passwd


Xpfalstad:*:3564:35:Paul John Falstad:/u/pfalstad:/usr/princeton/bin/zsh
X
X

XThe last example shows one of the perils of global aliases;
Xthey have a lot of potential to cause confusion. For exam-
Xple, if you defined a global alias called | (which is possi-
Xble), zsh would begin to act very strangely; every pipe sym-
Xbol would be replaced with the text of your alias. To some
Xextent, global aliases are like macros in C; discretion is
Xadvised in using them and in choosing names for them. Using
Xnames in all caps is not a bad idea, especially for aliases
Xwhich introduce shell metasyntax (like M and GF above).
X
XNote that zsh aliases are not like csh aliases. The syntax
Xfor defining them is different, and they do not have argu-
Xments. All your favorite csh aliases will probably not work
Xunder zsh. For example, if you try:
X
Xalias rm mv '\!* /tmp/wastebasket'
X
X
Xno aliases will be defined, but zsh will not report an
Xerror. In csh, this line defines an alias that makes rm
Xsafe---files that are rm'd will be moved to a temporary
Xdirectory instead of instantly destroyed. In zsh's syntax,
Xhowever, this line asks the shell to print any existing
Xalias definitions for rm, mv, or !* /tmp/wastebasket. Since
Xthere are none, most likely, the shell will not print any-
Xthing, although alias will return a nonzero exit code. The
Xproper syntax is this:
X
Xalias rm='mv \!* /tmp/wastebasket'
X
X
XHowever, this won't work either:
X
X% rm foo.dvi
Xzsh: no matches found: !*
X
X
XWhile this makes rm safe, it is certainly not what the user
Xintended. In zsh, you must use a shell function for this:
X
X% unalias rm
X% rm () { mv $* /tmp/wastebasket }
X% rm foo.dvi
X% ls /tmp/wastebasket
Xfoo.dvi


X
X
X
X
X

X - 20 -
XWhile this is much cleaner and easier to read (I hope you
Xwill agree), it is not csh-compatible. Therefore, a script
Xto convert csh aliases and variables has been provided. You
Xshould only need to use it once, to convert all your csh
Xaliases and parameters to zsh format:
X
X% csh
Xcsh> alias
Xl ls -AF
Xmore less
Xon last -2 !:1 ; who | grep !:1
Xcsh> exit
X% c2z >neat_zsh_aliases
X% cat neat_zsh_aliases
Xalias l='ls -AF'
Xalias more='less'
Xon () { last -2 $1 ; who | grep $1 }
X...
X
X
XThe first two aliases were converted to regular zsh aliases,
Xwhile the third, since it needed to handle arguments, was
Xconverted to a function. c2z can convert most aliases to
Xzsh format without any problems. However, if you're using
Xsome really arcane csh tricks, or if you have an alias with
Xa name like do (which is reserved in zsh), you may have to
Xfix some of the aliases by hand.
X
XThe c2z script checks your csh setup, and produces a list of
Xzsh commands which replicate your aliases and parameter set-
Xtings as closely as possible. You could include its output
Xin your startup file, .zshrc.
X
XHistory
X
XThere are several ways to manipulate history in zsh. One
Xway is to use csh-style ! history:
X
X% /usr/local/bin/!:0 !-2*:s/foo/bar/ >>!$
X
X
XIf you don't want to use this, you can turn it off by typing
Xsetopt nobanghist.
X
XAnother way is to use the fc command. For example, if you
Xtype an erroneous command:
X
X% for i in `cat /etc/clients`
X do
X rpu $i
X done
Xzsh: command not found: rpu
Xzsh: command not found: rpu
Xzsh: command not found: rpu
X
X
Xtyping fc will execute an editor on this command, allowing
Xyou to fix it. (The default editor is vi, by the way, not
Xed).


X
X
X
X
X
X

X - 21 -
X
X% fc
X49
X/rpu/s//rup/p
X rup $i
Xw
X49
Xq
Xfor i in `cat /etc/clients`
X do
X rup $i
X done
X beam up 2 days, 10:17, load average: 0.86, 0.80, 0.50
X bow up 4 days, 8:41, load average: 0.91, 0.80, 0.50
X burn up 17:18, load average: 0.91, 0.80, 0.50
X burst up 9 days, 1:49, load average: 0.95, 0.80, 0.50
X tan up 11:14, load average: 0.91, 0.80, 0.50
X bathe up 3 days, 17:49, load average: 1.84, 1.79, 1.50
X bird up 1 day, 9:13, load average: 1.95, 1.82, 1.51
X bonnet up 2 days, 21:18, load average: 0.93, 0.80, 0.50
X
X
XA variant of the fc command is r, which redoes the last com-
Xmand, with optional changes:
X
X% echo foo
Xfoo
X% r
Xecho foo
Xfoo
X
X% echo foo
Xfoo
X% r foo=bar
Xecho bar
Xbar
X
X
X
XCommand Line Editing
X
Xzsh's command line editor, ZLE, is quite powerful. It is
Xdesigned to emulate either emacs or vi; the default is
Xemacs. To set the bindings for vi mode, type bindkey -v.
X
XIn addition to basic editing, the shell allows you to recall
Xprevious lines in the history. In emacs mode, this is done
Xwith ^P (control-P):
X
X% ls ~
X- README file mail pub tmp
XMailboxes bin func nicecolors scr zsh
XNews etc iris notes src
X% echo foobar
Xfoobar
X% ^P
X% echo foobar^P
X% ls ~_


X
X
X
X
X
X
X

X - 22 -
XPressing ^P once brings up the previous line (echo foobar);
Xpressing it again brings up the line before that (ls ~).
XThe cursor is left at the end of the line, allowing you to
Xedit the line if desired before executing it. In many
Xcases, ZLE eliminates the need for the fc command, since it
Xis powerful enough to handle even multiline commands:
X
X% for i in a b c d e
X> do
X> echo $i
X> done
Xa
Xb
Xc
Xd
Xe
X% ^P
X% for i in a b c d e
X do
X echo $i
X done_
X
X
XNow you can just move up to the part you want to change...
X
X% for i in _ b c d e
X do
X echo $i
X done
X
X
Xchange it, and execute the new command.
X
X% for i in f g h i j
X do
X echo $i
X done
Xf
Xg
Xh
Xi
Xj
X
X
XAlso, you can search the history for a certain command using
XESC-P:
X
X% set ESC-P
X% setopt autolist ESC-P
X% setopt nocorrect_
X
X
XAnother way is to do an incremental search, emacs-style:


X
X
X
X
X
X
X
X
X
X
X
X

X - 23 -
X
X% ^R
X% _
Xi-search:
X
X% l_ /usr/bin
Xi-search: l
X
X% date > foofile_c
Xi-search: le
X
X
XAnother useful feature of the editor is command and filename
Xcompletion.
X
X% compTAB
X% compress _
X
X% ls /nicTAB
X% ls /nicecolors _
X
X% ls /usr/prTAB
X% ls /usr/princeton/_
X
X% ls -l =comTAB
X% ls -l =compress _
X
X
XIf the completion is ambiguous, the editor will beep. You
Xcan list possible completions by pressing ^D:
X
X% ls /vmuTAB -beep-
X% ls /vmunix_
X% ls /vmunix^D
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X
X
XOr, you could just set the AUTOLIST option:
X
X% setopt autolist
X% ls /vmuTAB -beep-
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X% ls /vmunix_
X
X
XAnother option you could set is RECEXACT, which causes exact
Xmatches to be accepted, even if there are other possible
Xcompletions:
X
X% setopt recexact
X% ls /vmuTAB -beep-
Xvmunix vmunix.old
Xvmunix.new.kernelmap.old vmunix.org
X% ls /vmunix_TAB
X% ls /vmunix _
X
X
XThe fignore variable lists suffixes of files to ignore


X
X
X
X
X

X - 24 -
Xduring completion.
X
X% ls fooTAB -beep-
Xfoofile.c foofile.o
X% fignore=( .o \~ .bak .junk )
X% ls fooTAB
X% ls foofile.c _
X
X
XSince foofile.o has a suffix that is in the fignore list, it
Xwas not considered a possible completion of foo.
X
XUsername completion is also supported:
X
X% ls ~pfalTAB
X% ls ~pfalstad/_
X
X
Xand parameter name completion:
X
X% echo $ORGTAB
X% echo $ORGANIZATION _
X
X
Xand hostname completion, if you give the shell a list of
Xhosts to complete:
X
X% hosts=( phoenix.princeton.edu uunet.uu.net nic.ddn.mil
X> diskfarm.princeton.edu gnu.ai.mit.edu
X> eniac.seas.upenn.edu )
X% telnet diskTAB
X% telnet diskfarm.princeton.edu _
X
X% ftp uuTAB
X% ftp uunet.uu.net _
X
X% mail subbarao@phTAB
X% mail subb...@phoenix.princeton.edu _
X
X
Xand option completion:
X
X% setopt noclTAB
X% setopt noclobber _
X
X
Xand binding completion:
X
X% bindkey '^X^X' puTAB
X% bindkey '^X^X' push-line _
X
X
X
XThe compctl command is used to control how completion works.
XFor example, to specify that certain commands show take com-
Xmands as arguments, you use compctl -c:
X
X% compctl -c man nohup
X% man uptTAB
X% man uptime _


X
X
X
X
X

X - 25 -
XTo specify that a command should complete filenames, you
Xshould use compctl -f. This is the default. It can be com-
Xbined with -c, as well.
X
X% compctl -cf echo
X% echo uptTAB
X% echo uptime _
X
X% echo foTAB
X% echo foo.c
X
X
XSimilarly, use -h to specify hostnames, -o to specify
Xoptions, -v to specify variables, and -b to specify bind-
Xings.
X
X% compctl -h rlogin
X% compctl -hfc rsh
X% compctl -b bindkey
X
X
XYou can also use -k to specify a custom list of keywords to
Xuse in completion.
X
X% ftphosts=(ftp.uu.net wuarchive.wustl.edu)
X% compctl -k ftphosts ftp
X% ftp wuTAB
X% ftp wuarchive.wustl.edu _
X
X% friends=(cpirazzi subbarao sukthnkr)
X% compctl -k friends mail finger su
X% finger cpTAB
X% finger cpirazzi _
X
X
X
XIn addition to completion, TAB performs expansion if possi-
Xble.
X
X% ls *.cTAB
X% ls foofile.c fortune.c rnd.c strfile.c unstr.c_
X
X
XFor example, suppose you have a bunch of weird files in an
Ximportant directory:
X
X% ls
X * * * ; & % $??foo dspfok foo.c
X !"foo"! ` \ ` foo rrr
X
X
XYou want to remove them, but you don't want to damage foo.c.
XHere is one way to do this:
X
X% rm *TAB
X% rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$'
X'foo \`\ \\\ \` dspfok foo foo.c rrr_
X
X
XWhen you expand *, zsh inserts the names of all the files


X
X
X
X
X

X - 26 -
Xinto the editing buffer, with proper shell quoting. Now,
Xjust move back and remove foo.c from the buffer:
X
X% rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$'
X'foo \`\ \\\ \` dspfok foo _rr
X
X
Xand press return. Everything except foo.c will be deleted
Xfrom the directory.
X
XHere's another trick; let's say you have typed this command
Xin:
X
X% gcc -o x.out foob.c -g -Wpointer-arith -Wtrigraphs_
X
X
Xand you forget which library you want. You need to escape
Xout for a minute and check by typing ls /usr/lib, or some
Xother such command; but you don't want to retype the whole
Xcommand again, and you can't press return now because the
Xcurrent command is incomplete. In zsh, you can put the line
Xon the buffer stack, using ESC-Q, and type some other com-
Xmands. The next time a prompt is printed, the gcc line will
Xbe popped off the stack and put in the editing buffer
Xautomatically; you can then enter the proper library name
Xand press return (or, ESC-Q again and look for some other
Xlibraries whose names you forgot).
X
XA similar situation: what if you forget the option to gcc
Xthat finds bugs using AI techniques? You could either use
XESC-Q again, and type man gcc, or you could press ESC-H,
Xwhich essentially does the same thing; it puts the current
Xline on the buffer stack, and executes the command run-help
Xgcc, where run-help is an alias for man.
X
XAnother interesting command is ESC-A. This executes the
Xcurrent line, but retains it in the buffer, so that it
Xappears again when the next prompt is printed. Also, the
Xcursor stays in the same place. This is useful for execut-
Xing a series of similar commands:
X
X% cc grok.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out
X% cc fubar.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out
X% cc fooble.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out
X
X
X
XThe ESC-' command is useful for managing the shell's quoting
Xconventions. Let's say you want to print this string:
X
Xdon't do that; type 'rm -rf \*', with a \ before the *.
X
X
XAll that is necessary is to type it into the editing buffer:
X
X% don't do that; type 'rm -rf \*', with a \ before the *.
X
X
Xpress ESC-' (escape-quote):


X
X
X
X
X
X

X - 27 -
X
X% 'don'\''t do that; type '\''rm -rf \*'\'', with a \ before the *.'
X
X
Xthen move to the beginning and add the echo command.
X
X% echo 'don'\''t do that; type '\''rm -rf \*'\'', with a \ before the *.'
Xdon't do that; type 'rm -rf \*', with a \ before the *.
X
X
XLet's say you want to create an alias to do this echo com-
Xmand. This can be done by recalling the line with ^P and
Xpressing ESC-' again:
X
X% 'echo '\''don'\''\'\'''\''t do that; type '\''\'\'''\''rm -rf
X\*'\''\'\'''\'', with a \ before the *.'\'''
X
X
Xand then move to the beginning and add the command to create
Xan alias.
X
X% alias zoof='echo '\''don'\''\'\'''\''t do that; type '\''\'\'''\''rm
X-rf \*'\''\'\'''\'', with a \ before the *.'\'''
X% zoof
Xdon't do that; type 'rm -rf \*', with a \ before the *.
X
X
X
XAnother interesting option is MENUCOMPLETE. This affects
Xthe way TAB works. Let's look at the /vmunix example again:
X
X% setopt menucomplete
X% ls /vmuTAB
X% ls /vmunixTAB
X% ls /vmunix.new.kernelmap.oldTAB
X% ls /vmunix.old_
X
X
XEach time you press TAB, it displays the next possible com-
Xpletion. In this way, you can cycle through the possible
Xcompletions until you find the one you want.
X
XThe AUTOMENU option makes a nice compromise between this
Xmethod of completion and the regular method. If you set
Xthis option, pressing the TAB key repeatedly after an ambi-
Xguous completion will cycle through the possible comple-
Xtions.
X
XBindings
X
XEach of the above editor commands was actually a function
Xbound by default to a certain key. The real names of the
Xcommands are:
X
Xexpand-or-complete TAB
Xpush-line ESC-Q
Xrun-help ESC-H
Xaccept-and-hold ESC-A
Xquote-line ESC-'


X
X
X
X
X
X

X - 28 -
XThese bindings are arbitrary; you could change them if you
Xwant. For example, to bind accept-line to ^Z:
X
X% bindkey '^Z' accept-line
X
X
XAnother idea would be to bind the delete key to delete-char;
Xthis might be convenient if you use ^H for backspace.
X
X% bindkey '^?' delete-char
X
X
XOr, you could bind ^X^H to run-help:
X
X% bindkey '^X^H' run-help
X
X
XOther examples:
X
X% bindkey '^X^Z' universal-argument
X% bindkey ' ' magic-space
X% bindkey -s '^T' 'uptime
X> '
X
X
Xuniversal-argument multiplies the next command by 4. Thus
X^X^Z^W might delete the last four words on the line. If you
Xbind space to magic-space, then csh-style history expansion
Xis done on the line whenever you press the space bar.
X
XThe -s flag to bindkey specifies that you are binding the
Xkey to a string, not a command. Thus bindkey -s '^T'
X'uptime\n' lets you VMS lovers get the load average whenever
Xyou press ^T.
X
XIf you have a NeXT keyboard, the one with the | and \ keys
Xvery inconveniently placed, the following bindings may come
Xin handy:
X
X% bindkey -s '\e/' '\\'
X% bindkey -s '\e=' '|'
X
X
XNow you can type ALT-/ to get a backslash, and ALT-= to get
Xa vertical bar. This only works inside zsh, of course;
Xbindkey has no effect on the key mappings inside talk or
Xmail, etc.
X
XAnother use of the editor is to edit the value of variables.
XFor example, an easy way to change your path is to use the
Xvared command:
X
X% vared PATH
X> /u/pfalstad/scr:/u/pfalstad/bin/sun4:/u/maruchck/scr:/u/subbarao/bin:/u/maruc
Xhck/bin:/u/subbarao/scripts:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:/usr/host
Xs:/usr/princeton/bin/X11:/./usr/lang:/./usr/etc:/./etc
X
X
XYou can now edit the path. When you press return, the con-
Xtents of the edit buffer will be assigned to PATH.


X
X
X
X
X

X - 29 -
XParameter Substitution
X
XIn zsh, parameters are set like this:
X
X% foo=bar
X% echo $foo
Xbar
X
X
XSpaces before or after the = are frowned upon:
X
X% foo = bar
Xzsh: command not found: foo
X
X
XAlso, set doesn't work for setting parameters:
X
X% set foo=bar
X% set foo = bar
X% echo $foo
X
X%
X
X
XNote that no error message was printed. This is because
Xboth of these commands were perfectly valid; the set builtin
Xassigns its arguments to the positional parameters ($1, $2,
Xetc.).
X
X% set foo=bar
X% echo $1
Xfoo=bar
X% set foo = bar
X% echo $3 $2
Xbar =
X
X
XIf you're really intent on using the csh syntax, define a
Xfunction like this:
X
X% set () {
X> eval "$1$2$3"
X> }
X% set foo = bar
X% set fuu=brrr
X% echo $foo $fuu
Xbar brrr
X
X
XBut then, of course you can't use the form of set with
Xoptions, like set -F (which turns off filename generation).
XAlso, the set command by itself won't list all the parame-
Xters like it should. To get around that you need a case
Xstatement:


X
X
X
X
X
X
X
X
X
X
X

X - 30 -
X
X% set () {
X> case $1 in
X> -*|+*|'') builtin set $* ;;
X> *) eval "$1$2$3" ;;
X> esac
X> }
X
X
XFor the most part, this should make csh users happy.
X
XThe following sh-style operators are supported in zsh:
X
X% unset null
X% echo ${foo-xxx}
Xbar
X% echo ${null-xxx}
Xxxx
X% unset null
X% echo ${null=xxx}
Xxxx
X% echo $null
Xxxx
X% echo ${foo=xxx}
Xbar
X% echo $foo
Xbar
X% unset null
X% echo ${null+set}
X
X% echo ${foo+set}
Xset
X
X
XAlso, csh-style : modifiers may be appended to a parameter
Xsubstitution.
X
X% echo $PWD
X/home/learning/pf/zsh/zsh2.00/src
X% echo $PWD:h
X/home/learning/pf/zsh/zsh2.00
X% echo $PWD:h:h
X/home/learning/pf/zsh
X% echo $PWD:t
Xsrc
X% name=foo.c
X% echo $name
Xfoo.c
X% echo $name:r
Xfoo
X% echo $name:e
Xc
X
X
XThe equivalent constructs in ksh (which are also supported
Xin zsh) are a bit more general and easier to remember. When
Xthe shell expands ${foo#pat}, it checks to see if pat
Xmatches a substring at the beginning of the value of foo.
XIf so, it removes that portion of foo, using the shortest
Xpossible match. With ${foo##pat}, the longest possible


X
X
X
X
X

X - 31 -
Xmatch is removed. ${foo%pat} and ${foo%%pat} remove the
Xmatch from the end. Here are the ksh equivalents of the :
Xmodifiers:
X
X% echo ${PWD%/*}
X/home/learning/pf/zsh/zsh2.00
X% echo ${PWD%/*/*}
X/home/learning/pf/zsh
X% echo ${PWD##*/}
Xsrc
X% echo ${name%.*}
Xfoo
X% echo ${name#*.}
Xc
X
X
Xzsh also has upper/lowercase modifiers:
X
X% xx=Test
X% echo $xx:u
XTEST
X% echo $xx:l
Xtest
X
X
Xand a substitution modifier:
X
X% echo $name:s/foo/bar/
Xbar.c
X% ls
Xfoo.c foo.h foo.o foo.pro
X% for i in foo.*; mv $i $i:s/foo/bar/
X% ls
Xbar.c bar.h bar.o bar.pro
X
X
XOne possible source of confusion is the fact that in zsh,
Xthe result of parameter substitution is not split into
Xwords. Thus, this will not work:
X
X% srcs='glob.c exec.c init.c'
X% ls $srcs
Xglob.c exec.c init.c not found
X
X
XThis is considered a feature, not a bug. If splitting were
Xdone by default, as it is in most other shells, functions
Xlike this would not work properly:
X
X$ ll () { ls -F $* }
X$ ll 'fuu bar'
Xfuu not found
Xbar not found
X
X% ll 'fuu bar'
Xfuu bar not found
X
X
XOf course, a hackish workaround is available in sh (and
Xzsh):


X
X
X
X
X

X - 32 -
X
X% setopt shwordsplit
X% ll () { ls -F "$@" }
X% ll 'fuu bar'
Xfuu bar not found
X
X
XIf you like the sh behaviour, zsh can accomodate you:
X
X% ls ${=srcs}
Xexec.c glob.c init.c
X% setopt shwordsplit
X% ls $srcs
Xexec.c glob.c init.c
X
X
XAnother way to get the $srcs trick to work is to use an
Xarray:
X
X% unset srcs
X% srcs=( glob.c exec.c init.c )
X% ls $srcs
Xexec.c glob.c init.c
X
X
Xor an alias:
X
X% alias -g SRCS='exec.c glob.c init.c'
X% ls SRCS
Xexec.c glob.c init.c
X
X
XAnother option that modifies parameter expansion is RCEX-
XPANDPARAM:
X
X% echo foo/$srcs
Xfoo/glob.c exec.c init.c
X% setopt rcexpandparam
X% echo foo/$srcs
Xfoo/glob.c foo/exec.c foo/init.c
X% echo foo/${^srcs}
Xfoo/glob.c foo/exec.c foo/init.c
X% echo foo/$^srcs
Xfoo/glob.c foo/exec.c foo/init.c
X
X
X
XShell Parameters
X
XThe shell has many predefined parameters that may be
Xaccessed. Here are some examples:


X
X
X
X
X
X
X
X
X
X
X
X
X
X

X - 33 -
X
X% sleep 10 &
X[1] 3820
X% echo $!
X3820
X% set a b c
X% echo $#
X3
X% echo $ARGC
X3
X% ( exit 20 ) ; echo $?
X20
X% false; echo $status
X1
X
X
X($? and $status are equivalent.)
X
X% echo $HOST $HOSTTYPE
Xdendrite sun4
X% echo $UID $GID
X701 60
X% cd /tmp
X% cd /home
X% echo $PWD $OLDPWD
X/home /tmp
X% ls $OLDPWD/.getwd
X/tmp/.getwd
X
X
X~+ and ~- are short for $PWD and $OLDPWD, respectively.
X
X% ls ~-/.getwd
X/tmp/.getwd
X% ls -d ~+/learning
X/home/learning
X% echo $RANDOM
X4880
X% echo $RANDOM
X11785
X% echo $RANDOM
X2062
X% echo $TTY
X/dev/ttyp4
X% echo $VERSION
Xzsh v2.00.03
X% echo $USERNAME
Xpf
X
X
X
XThe cdpath variable sets the search path for the cd command.
XIf you do not specify . somewhere in the path, it is assumed
Xto be the first component.


X
X
X
X
X
X
X
X
X
X
X

X - 34 -
X
X% cdpath=( /usr ~ ~/zsh )
X% ls /usr
X5bin dict lang net sccs sys
X5include etc lector nserve services tmp
X5lib export lib oed share ucb
Xadm games local old skel ucbinclude
Xbin geac lost+found openwin spool ucblib
Xboot hosts macsyma_417 pat src xpg2bin
Xdemo include man princeton stand xpg2include
Xdiag kvm mdec pub swap xpg2lib
X% cd spool
X/usr/spool
X% cd bin
X/usr/bin
X% cd func
X~/func
X% cd
X% cd pub
X% pwd
X/u/pfalstad/pub
X% ls -d /usr/pub
X/usr/pub
X
X
XPATH and path both set the search path for commands. These
Xtwo variables are equivalent, except that one is a string
Xand one is an array. If the user modifies PATH, the shell
Xchanges path as well, and vice versa.
X
X% PATH=/bin:/usr/bin:/tmp:.
X% echo $path
X/bin /usr/bin /tmp .
X% path=( /usr/bin . /usr/local/bin /usr/ucb )
X% echo $PATH
X/usr/bin:.:/usr/local/bin:/usr/ucb
X
X
XThe same is true of CDPATH and cdpath:
X
X% echo $CDPATH
X/usr:/u/pfalstad:/u/pfalstad/zsh
X% CDPATH=/u/subbarao:/usr/src:/tmp
X% echo $cdpath
X/u/subbarao /usr/src /tmp
X
X
XIn general, parameters with names in all lowercase are
Xarrays; assignments to them take the form:
X
Xname=( elem ... )
X
X
XParameters with names in all uppercase are strings. If
Xthere is both an array and a string version of the same
Xparameter, the string version is a colon-separated list,
Xlike PATH.
X
XHISTFILE is the name of the history file, where the history
Xis saved when a shell exits.


X
X
X
X
X

X - 35 -
X
X% zsh
Xphoenix% HISTFILE=/tmp/history
Xphoenix% SAVEHIST=20
Xphoenix% echo foo
Xfoo
Xphoenix% date
XFri May 24 05:39:35 EDT 1991
Xphoenix% uptime
X 5:39am up 4 days, 20:02, 40 users, load average: 2.30, 2.20, 2.00
Xphoenix% exit
X% cat /tmp/history
XHISTFILE=/tmp/history
XSAVEHIST=20
Xecho foo
Xdate
Xuptime
Xexit
X% HISTSIZE=3
X% history
X 28 rm /tmp/history
X 29 HISTSIZE=3
X 30 history
X
X
X
XIn zsh, if you say
X
X% >file
X
X
Xthe command cat is normally assumed:
X
X% >file
Xfoo!
X^D
X% cat file
Xfoo!
X
X
XThus, you can view a file simply by typing:
X
X% <file
Xfoo!
X
X
XHowever, this is not csh or sh compatible. To correct this,
Xchange the value of the parameter NULLCMD, which is cat by
Xdefault.
X
X% NULLCMD=:
X% >file
X% ls -l file
X-rw-r--r-- 1 pfalstad 0 May 24 05:41 file
X
X
XIf NULLCMD is unset, the shell reports an error if no com-
Xmand is specified (like csh).


X
X
X
X
X
X
X

X - 36 -
X
X% unset NULLCMD
X% >file
Xzsh: redirection with no command
X
X
XActually, READNULLCMD is used whenever you have a null com-
Xmand reading input from a single file. Thus, you can set
XREADNULLCMD to more or less rather than cat. Also, if you
Xset NULLCMD to : for sh compatibility, you can still read
Xfiles with < file if you leave READNULLCMD set to more.
X
XPrompting
X
XThe default prompt for zsh is:
X
Xphoenix% echo $PROMPT
X%m%#
X
X
XThe %m stands for the short form of the current hostname,
Xand the %# stands for a % or a #, depending on whether the
Xshell is running as root or not. zsh supports many other
Xcontrol sequences in the PROMPT variable.
X
X% PROMPT='%/> '
X/u/pfalstad/etc/TeX/zsh>
X
X% PROMPT='%~> '
X~/etc/TeX/zsh>
X
X% PROMPT='%h %~> '
X6 ~/etc/TeX/zsh>
X
X
X%h represents the number of current history event.
X
X% PROMPT='%h %~ %M> '
X10 ~/etc/TeX/zsh apple-gunkies.gnu.ai.mit.edu>
X
X% PROMPT='%h %~ %m> '
X11 ~/etc/TeX/zsh apple-gunkies>
X
X% PROMPT='%h %t> '
X12 6:11am>
X
X% PROMPT='%n %w tty%l>'
Xpfalstad Fri 24 ttyp0>
X
X
XAlso available is the RPROMPT parameter. If this is set,
Xthe shell puts a prompt on the right side of the screen.


X
X
X
X
X
X
X
X
X
X
X
X
X

X - 37 -
X
X% RPROMPT='%t'
X% 6:14am
X
X% RPROMPT='%~'
X% ~/etc/TeX/zsh
X
X% PROMPT='%l %T %m[%h] ' RPROMPT=' %~'
Xp0 6:15 phoenix[5] ~/etc/TeX/zsh
X
X
XThese special escape sequences can also be used with the -P
Xoption to print:
X
X% print -P %h tty%l
X15 ttyp1
X
X
X
XThe POSTEDIT parameter is printed whenever the editor exits.
XThis can be useful for termcap tricks. To highlight the
Xprompt and command line while leaving command output
Xunhighlighted, try this:
X
X% POSTEDIT=`echotc se`
X% PROMPT='%S%% '
X
X
X
XLogin/logout watching
X
XYou can specify login or logout events to monitor by setting
Xthe watch variable. Normally, this is done by specifying a
Xlist of usernames.
X
X% watch=( pfalstad subbarao sukthnkr egsirer )
X
X
XThe log command reports all people logged in that you are
Xwatching for.
X
X% log
Xpfalstad has logged on p0 from mickey.
Xpfalstad has logged on p5 from mickey.
X% ...
Xsubbarao has logged on p8 from phoenix.
X% ...
Xsubbarao has logged off p8 from phoenix.
X% ...
Xsukthnkr has logged on p8 from dew.
X% ...
Xsukthnkr has logged off p8 from dew.
X
X
XIf you specify hostnames with an @ prepended, the shell will
Xwatch for all users logging in from the specified host.


X
X
X
X
X
X
X
X
X

X - 38 -
X
X% watch=( @mickey @phoenix )
X% log
Xdjthongs has logged on q2 from phoenix.
Xpfalstad has logged on p0 from mickey.
Xpfalstad has logged on p5 from mickey.
X
X
XIf you give a tty name with a % prepended, the shell will
Xwatch for all users logging in on that tty.
X
X% watch=( %ttyp0 %console )
X% log
Xroot has logged on console from .
Xpfalstad has logged on p0 from mickey.
X
X
XThe format of the reports may also be changed.

X - 39 -
X
X% watch=( pfalstad gettes eps djthongs jcorr bdavis )
X% log
Xjcorr has logged on tf from 128.112.176.3:0.
Xjcorr has logged on r0 from 128.112.176.3:0.
Xgettes has logged on p4 from yo:0.0.
Xdjthongs has logged on pe from grumpy:0.0.
Xdjthongs has logged on q2 from phoenix.
Xbdavis has logged on qd from BRUNO.
Xeps has logged on p3 from csx30:0.0.
Xpfalstad has logged on p0 from mickey.
Xpfalstad has logged on p5 from mickey.
X% WATCHFMT='%n on tty%l from %M'
X% log
Xjcorr on ttytf from 128.112.176.3:0.
Xjcorr on ttyr0 from 128.112.176.3:0.
Xgettes on ttyp4 from yo:0.0
Xdjthongs on ttype from grumpy:0.0
Xdjthongs on ttyq2 from phoenix.Princeto
Xbdavis on ttyqd from BRUNO.pppl.gov
Xeps on ttyp3 from csx30:0.0
Xpfalstad on ttyp0 from mickey.Princeton
Xpfalstad on ttyp5 from mickey.Princeton
X% WATCHFMT='%n fm %m'
X% log
Xjcorr fm 128.112.176.3:0
Xjcorr fm 128.112.176.3:0
Xgettes fm yo:0.0
Xdjthongs fm grumpy:0.0
Xdjthongs fm phoenix
Xbdavis fm BRUNO
Xeps fm csx30:0.0
Xpfalstad fm mickey
Xpfalstad fm mickey
X% WATCHFMT='%n %a at %t %w.'
X% log
Xjcorr logged on at 3:15pm Mon 20.
Xjcorr logged on at 3:16pm Wed 22.
Xgettes logged on at 6:54pm Wed 22.
Xdjthongs logged on at 7:19am Thu 23.
Xdjthongs logged on at 7:20am Thu 23.
Xbdavis logged on at 12:40pm Thu 23.
Xeps logged on at 4:19pm Thu 23.
Xpfalstad logged on at 3:39am Fri 24.
Xpfalstad logged on at 3:42am Fri 24.
X
X
XIf you have a .friends file in your home directory, a con-
Xvenient way to make zsh watch for all your friends is to do
Xthis:
X
X% watch=( $(< ~/.friends) )
X% echo $watch
Xsubbarao maruchck root sukthnkr ...
X
X
XIf watch is set to all, then all users logging in or out
Xwill be reported.


X
X
X
X
X
X
X

X - 40 -
XOptions
X
XSome options have already been mentioned; here are a few
Xmore:
X
X% cd /
X% setopt autocd
X% bin
X% pwd
X/bin
X% ../etc
X% pwd
X/etc
X
X
XUsing the AUTOCD option, you can simply type the name of a
Xdirectory, and it will become the current directory.
X
X% setopt cdablevars
X% foo=/tmp
X% cd foo
X/tmp
X
X
XWith CDABLEVARS, if the argument to cd is the name of a
Xparameter whose value is a valid directory, it will become
Xthe current directory.
X
XCORRECT turns on spelling correction for commands, and the
XCORRECTALL option turns on spelling correction for all argu-
Xments.
X
X% setopt correct
X% sl
Xzsh: correct `sl' to `ls' [nyae]? y
X% setopt correctall
X% ls x.v11r4
Xzsh: correct `x.v11r4' to `X.V11R4' [nyae]? n
X/usr/princton/src/x.v11r4 not found
X% ls /etc/paswd
Xzsh: correct to `/etc/paswd' to `/etc/passwd' [nyae]? y
X/etc/passwd
X
X
XIf you press y when the shell asks you if you want to
Xcorrect a word, it will be corrected. If you press n, it
Xwill be left alone. Pressing a aborts the command, and
Xpressing e brings the line up for editing again, in case you
Xagree the word is spelled wrong but you don't like the
Xcorrection.
X
XNormally, a quoted expression may contain a newline:
X
X% echo '
X> foo
X> '
X
Xfoo
X
X%


X
X
X
X
X

X - 41 -
XWith CSHJUNKIEQUOTES set, this is illegal, as it is in csh.
X
X% setopt cshjunkiequotes
X% ls 'foo
Xzsh: unmatched '
X
X
XGLOBDOTS lets files beginning with a . be matched without
Xexplicitly specifying the dot.
X
X% ls -d *x*
XMailboxes
X% setopt globdots
X% ls -d *x*
X.exrc .pnewsexpert .xserverrc
X.mushexpert .xinitrc Mailboxes
X
X
XHISTIGNOREDUPS prevents the current line from being saved in
Xthe history if it is the same as the previous one; HISTIG-
XNORESPACE prevents the current line from being saved if it
Xbegins with a space.
X
X% PROMPT='%h> '
X39> setopt histignoredups
X40> echo foo
Xfoo
X41> echo foo
Xfoo
X41> echo foo
Xfoo
X41> echo bar
Xbar
X42> setopt histignorespace
X43> echo foo
Xfoo
X43> echo fubar
Xfubar
X43> echo fubar
Xfubar
X
X
XIGNOREBRACES turns off csh-style brace expansion.
X
X% echo x{y{z,a},{b,c}d}e
Xxyze xyae xbde xcde
X% setopt ignorebraces
X% echo x{y{z,a},{b,c}d}e
Xx{y{z,a},{b,c}d}e
X
X
XIGNOREEOF forces the user to type exit or logout, instead of
Xjust pressing ^D.
X
X% setopt ignoreeof
X% ^D
Xzsh: use 'exit' to exit.
X
X
XINTERACTIVECOMMENTS turns on interactive comments; comments


X
X
X
X
X

X - 42 -
Xbegin with a #.
X
X% setopt interactivecomments
X% date # this is a comment
XFri May 24 06:54:14 EDT 1991
X
X
XNOCLOBBER prevents you from accidentally overwriting an
Xexisting file.
X
X% setopt noclobber
X% cat /dev/null >~/.zshrc
Xzsh: file exists: /u/pfalstad/.zshrc
X
X
XIf you really do want to clobber a file, you can use the >!
Xoperator. To make things easier in this case, the > is
Xstored in the history list as a >!:
X
X% cat /dev/null >! ~/.zshrc
X% cat /etc/motd > ~/.zshrc
Xzsh: file exists: /u/pfalstad/.zshrc
X% !!
Xcat /etc/motd >! ~/.zshrc
X% ...
X
X
XRCQUOTES lets you use a more elegant method for including
Xsingle quotes in a singly quoted string:
X
X% echo '"don'\''t do that."'
X"don't do that."
X% echo '"don''t do that."'
X"dont do that."
X% setopt rcquotes
X% echo '"don''t do that."'
X"don't do that."
X
X
XFinally, SUNKEYBOARDHACK wins the award for the strangest
Xoption. If a line ends with `, and there are an odd number
Xof them on the line, the shell will ignore the trailing `.
XThis is provided for keyboards whose RETURN key is too
Xsmall, and too close to the ` key.
X
X% setopt sunkeyboardhack
X% date`
XFri May 24 06:55:38 EDT 1991
X
X
X
XClosing Comments
X
XI would be happy to receive mail if anyone has any tricks or
Xideas to add to this document, or if there are some points
Xthat could be made clearer or covered more thoroughly.
XPlease notify me of any errors in this document.


X
X
X
X
X
X

SHAR_EOF
echo 'File zsh2.2/doc/intro.txt is complete' &&
chmod 0644 zsh2.2/doc/intro.txt ||


echo 'restore of zsh2.2/doc/intro.txt failed'

Wc_c="`wc -c < 'zsh2.2/doc/intro.txt'`"
test 58603 -eq "$Wc_c" ||
echo 'zsh2.2/doc/intro.txt: original size 58603, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/dots/zlogin ==============
if test ! -d 'zsh2.2/dots'; then
echo 'x - creating directory zsh2.2/dots'
mkdir 'zsh2.2/dots'
fi
if test -f 'zsh2.2/dots/zlogin' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/dots/zlogin (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/dots/zlogin (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/dots/zlogin' &&
Xclear
Xcd
Xstty dec new cr0 -tabs
Xttyctl -f # freeze the terminal modes... can't change without a ttyctl -u
Xumask 022
Xexport MAIL=/usr/spool/mail/$USER
XMAILCHECK=60
Xmesg y
Xuptime
Xfortune
Xlog
Xfrom 2>/dev/null
Xcat notes
Xunlimit
Xlimit core 0
Xmsgs -fp
SHAR_EOF
chmod 0644 zsh2.2/dots/zlogin ||
echo 'restore of zsh2.2/dots/zlogin failed'
Wc_c="`wc -c < 'zsh2.2/dots/zlogin'`"
test 247 -eq "$Wc_c" ||
echo 'zsh2.2/dots/zlogin: original size 247, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/dots/zshrc ==============
if test -f 'zsh2.2/dots/zshrc' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/dots/zshrc (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/dots/zshrc (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/dots/zshrc' &&
X#
X# my rc file for zsh 2.2
X# all this runs in interactive shells only
X#
X
X# search path for the cd command
Xcdpath=(. ~ ~/src/cs320 ~/src)
X
X# where to look for function definitions
X# fpath=(~/func)
X
X# useful directory
Xcsrc=/usr/princeton/common/src
X
X# use hard limits, except for a smaller stack and no core dumps
Xunlimit
Xlimit stack 8192
Xlimit core 0
Xlimit -s
X
Xumask 022
X
X# define some aliases
Xalias a=alias
Xa a.out=./a.out sendmail=/usr/lib/sendmail c=cp 0=vi 09='vi -t' 00=r
Xa d=dirs en='enscript -2rGh' fm='finger -m' grep=egrep h=history
Xa hinfo='host -t hinfo' j=jobs l='ls -AF' lock='lock -p -60000'
Xa lsd='ls -d */' m=make mm=less
Xa nrable='ls -AFltrd *(^R)' sz='ls -l | sort -n +3 | tail -20'
Xa sn='sed -n' nw='l -ltr | tail' pd=pushd pop=popd mroe=more
Xa rable='ls -AFltrd *(R)' strings='strings -' t=cat
Xa v=mv where='hostname; echo >/dev/null' k9='kill -9' whoami='echo root'
Xa find='noglob find' bindkey='noglob bindkey' dh='dirs -v'
Xa mv='nocorrect mv' z=suspend
X
X# global aliases
Xa -g 'GF'='| fgrep -f ~/.friends' G='| grep' M='| less' cex='/u/pup/centrex'
X
X# setenv for csh junkies (including tset)
Xsetenv() { export $1=$2 }
X
Xmanpath=(/usr/man /usr/princeton/man /u/cad/man /usr/lang/man)
Xexport MANPATH
X
X# filename completion suffixes to ignore
Xfignore=(.o .pro .old)
X
X# hosts to use for completion
Xhosts=(uunet.uu.net `hostname` wuarchive.wustl.edu quiche.cs.mcgill.ca)
X
XPROMPT='%l %T %m[%h] '
X
X# prompt on the right side of the screen
XRPROMPT=' %~'
X
X# some environment variables
Xexport MAILCALL='NEW MAIL! '
Xexport YOUSAID='In %C you wrote:'
Xexport ATTRIBUTION='%f wrote:'
X
X# functions to autoload
X# autoload cx acx mere yu yp randline proto namedir ilogin
X
XMAILCHECK=30
XHISTSIZE=600
XDIRSTACKSIZE=50
X
X# lots of options
Xsetopt notify globdots correct pushdtohome cdablevars autolist \
X sunkeyboardhack correctall autocd recexact longlistjobs mailwarning \
X autoresume histignoredups pushdsilent noclobber \
X autopushd pushdminus extendedglob rcquotes
Xunsetopt bgnice
X
X# watch for my friends
Xwatch=($(cat ~/.friends))
XWATCHFMT='%n %a %l from %m at %t.'
XLOGCHECK=0
X
Xexport LESS=-ainx3
Xunhash p
X
X# some nice bindings
Xbindkey '^X^Z' universal-argument ' ' magic-space
Xbindkey '^X^A' vi-find-prev-char-skip
Xbindkey '^Z' accept-and-hold
Xbindkey -s '\M-/' \\\\
Xbindkey -s '\M-=' \|
SHAR_EOF
chmod 0644 zsh2.2/dots/zshrc ||
echo 'restore of zsh2.2/dots/zshrc failed'
Wc_c="`wc -c < 'zsh2.2/dots/zshrc'`"
test 2291 -eq "$Wc_c" ||
echo 'zsh2.2/dots/zshrc: original size 2291, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/dots/zshenv ==============
if test -f 'zsh2.2/dots/zshenv' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/dots/zshenv (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/dots/zshenv (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/dots/zshenv' &&
Xpath=(~/scr ~/bin/$HOSTTYPE
X /usr/princeton/bin /usr/ucb /usr/bin /bin
X /usr/hosts /usr/princeton/bin/X11 /usr/etc /etc .)
SHAR_EOF
chmod 0644 zsh2.2/dots/zshenv ||
echo 'restore of zsh2.2/dots/zshenv failed'
Wc_c="`wc -c < 'zsh2.2/dots/zshenv'`"
test 123 -eq "$Wc_c" ||
echo 'zsh2.2/dots/zshenv: original size 123, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/acx ==============
if test ! -d 'zsh2.2/func'; then
echo 'x - creating directory zsh2.2/func'
mkdir 'zsh2.2/func'
fi
if test -f 'zsh2.2/func/acx' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/acx (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/acx (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/acx' &&
X#! /bin/sh
X#
X# zsh shell function to make its arguments 755
X# also works as an sh script
X#
Xchmod 755 $*
SHAR_EOF
chmod 0755 zsh2.2/func/acx ||
echo 'restore of zsh2.2/func/acx failed'
Wc_c="`wc -c < 'zsh2.2/func/acx'`"
test 104 -eq "$Wc_c" ||
echo 'zsh2.2/func/acx: original size 104, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/cx ==============
if test -f 'zsh2.2/func/cx' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/cx (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/cx (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/cx' &&
X#! /bin/sh
X#
X# zsh shell function to make its arguments executable
X# also works as a sh script
X#
Xchmod +x $*
SHAR_EOF
chmod 0755 zsh2.2/func/cx ||
echo 'restore of zsh2.2/func/cx failed'
Wc_c="`wc -c < 'zsh2.2/func/cx'`"
test 109 -eq "$Wc_c" ||
echo 'zsh2.2/func/cx: original size 109, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/harden ==============
if test -f 'zsh2.2/func/harden' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/harden (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/harden (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/harden' &&
X#! /bin/sh
X# harden a link (convert it to a singly linked file)
Xcp $1 $1.foo
Xrm $1
Xmv $1.foo $1
X
SHAR_EOF
chmod 0755 zsh2.2/func/harden ||
echo 'restore of zsh2.2/func/harden failed'
Wc_c="`wc -c < 'zsh2.2/func/harden'`"
test 97 -eq "$Wc_c" ||
echo 'zsh2.2/func/harden: original size 97, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/mere ==============
if test -f 'zsh2.2/func/mere' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/mere (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/mere (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/mere' &&
X#! /bin/sh
X# read a man page in the current directory
Xnroff -man -Tman $1 | less -s
SHAR_EOF
chmod 0755 zsh2.2/func/mere ||
echo 'restore of zsh2.2/func/mere failed'
Wc_c="`wc -c < 'zsh2.2/func/mere'`"
test 84 -eq "$Wc_c" ||
echo 'zsh2.2/func/mere: original size 84, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/namedir ==============
if test -f 'zsh2.2/func/namedir' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/namedir (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/namedir (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/namedir' &&
X# give a name to a directory
X
X$1=~+
X: ~$1
X
X# for example, if we say: namedir foo
X# where the current directory is /usr/princeton/common/src/news/nntp/inews
X# this will do:
X#
X# foo=/usr/princeton/common/src/news/nntp/inews
X# : ~foo
X#
X# The : ~foo just evaluates ~foo, which declares foo as a named directory.
X# The first time a parameter is used with tilde expansion, it is declared
X# as the name of a named dir.
SHAR_EOF
chmod 0755 zsh2.2/func/namedir ||
echo 'restore of zsh2.2/func/namedir failed'
Wc_c="`wc -c < 'zsh2.2/func/namedir'`"
test 412 -eq "$Wc_c" ||
echo 'zsh2.2/func/namedir: original size 412, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/proto ==============
if test -f 'zsh2.2/func/proto' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/proto (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/proto (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/proto' &&
X#! /bin/sh
X# generate prototypes, if your style is the same as mine
Xfor i
Xdo
X rm $i:r.pro 2>/dev/null
X grep -v '[{};:#]' $i | grep '^[A-Za-z]' |
X grep -v static | sed 's/$/;/' >! $i:r.pro
Xdone
SHAR_EOF
chmod 0755 zsh2.2/func/proto ||
echo 'restore of zsh2.2/func/proto failed'
Wc_c="`wc -c < 'zsh2.2/func/proto'`"
test 194 -eq "$Wc_c" ||
echo 'zsh2.2/func/proto: original size 194, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/randline ==============
if test -f 'zsh2.2/func/randline' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/randline (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/randline (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/randline' &&
X# get a random line from a file
SHAR_EOF
true || echo 'restore of zsh2.2/func/randline failed'
fi
echo 'End of zsh2.2 part 2'
echo 'File zsh2.2/func/randline is continued in part 3'
echo 3 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 11:55:07 AM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 99
Archive-name: zsh2.2/part03

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.03 (part 3 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/func/randline continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 3; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/func/randline'
else
echo 'x - continuing file zsh2.2/func/randline'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/func/randline' &&

Xinteger z=$(wc -l <$1)
Xsed -n $[RANDOM%z+1]p $1
SHAR_EOF
echo 'File zsh2.2/func/randline is complete' &&
chmod 0755 zsh2.2/func/randline ||


echo 'restore of zsh2.2/func/randline failed'

Wc_c="`wc -c < 'zsh2.2/func/randline'`"
test 80 -eq "$Wc_c" ||
echo 'zsh2.2/func/randline: original size 80, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/yp ==============
if test -f 'zsh2.2/func/yp' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/yp (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/yp (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/yp' &&
X#! /bin/sh
Xypmatch $1 passwd
SHAR_EOF
chmod 0755 zsh2.2/func/yp ||
echo 'restore of zsh2.2/func/yp failed'
Wc_c="`wc -c < 'zsh2.2/func/yp'`"
test 29 -eq "$Wc_c" ||
echo 'zsh2.2/func/yp: original size 29, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/func/yu ==============
if test -f 'zsh2.2/func/yu' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/func/yu (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/func/yu (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/func/yu' &&
X#! /bin/sh
Xypmatch $1 passwd.byuid
SHAR_EOF
chmod 0755 zsh2.2/func/yu ||
echo 'restore of zsh2.2/func/yu failed'
Wc_c="`wc -c < 'zsh2.2/func/yu'`"
test 35 -eq "$Wc_c" ||
echo 'zsh2.2/func/yu: original size 35, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/man/man1/zsh.1 ==============
if test ! -d 'zsh2.2/man'; then
echo 'x - creating directory zsh2.2/man'
mkdir 'zsh2.2/man'
fi
if test ! -d 'zsh2.2/man/man1'; then
echo 'x - creating directory zsh2.2/man/man1'
mkdir 'zsh2.2/man/man1'
fi
if test -f 'zsh2.2/man/man1/zsh.1' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/man/man1/zsh.1 (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/man/man1/zsh.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/man/man1/zsh.1' &&
X.\"
X.TH ZSH 1 "1992 May 2"
X.SH NAME
Xzsh \- the Z shell
X.SH SYNOPSIS
X\fBzsh\fP [ \(+-\fIoptions\fP ] [ \(+-\fBo\fP \fIoption\fP ] ... [ \-\fBc\fP \fIstring\fP ] [ \fIarg\fP ... ]
X.SH "SHELL GRAMMAR"
XA \fIsimple command\fP is a sequence of optional parameter
Xassignments followed by blank-separated words,
Xwith optional redirections interspersed.
XThe first word is the command to be executed, and the remaining
Xwords, if any, are arguments to the command.
XIf a command name is given, the parameter assignments modify
Xthe environment of the command when it is executed.
XThe value of a simple command is its exit status,
Xor 128 plus the signal number if terminated by a signal.
X.PP
XIf a simple command is preceded by the word \fBexec\fP,
Xit is executed in the parent shell without forking.
XIf preceded by \fBcommand\fP, the command word is taken
Xto be the name of an external command, rather than a
Xshell function or builtin.
XIf preceded by \fBnoglob\fP, filename generation is not performed
Xon any of the words. If preceded by a \-, the command
Xis executed with a \- prepended to its \fBargv[0]\fP string.
XIf preceded by \fBnocorrect\fP, spelling correction is not
Xdone on any of the words.
X.PP
XA \fIpipeline\fP is a sequence of one or more commands
Xseparated by \fB|\fP or \fB|&\fP. \fB|&\fP is shorthand
Xfor \fB2>&1 |\fP. The standard output of each command is
Xconnected to the standard input of the next command in the
Xpipeline.
X.PP
XThe value of a pipeline is the value of the last command.
XIf a pipeline is preceded by a \fB!\fP, the value
Xof that pipeline is the logical NOT of the value of the last
Xcommand.
X.PP
XIf a pipeline is preceded by \fBcoproc\fP, it is
Xexecuted as a coprocess; a two-way pipe is established
Xbetween it and the parent shell. The shell can read from or write to
Xthe coprocess by means of the \fB>&p\fP and \fB<&p\fP
Xredirection operators.
X.PP
XA \fIsublist\fP is a sequence of one or more pipelines
Xseparated by \fB&&\fP or \fB|\||\fP. If two pipelines
Xare separated by \fB&&\fP, the second pipeline is executed
Xonly if the first is successful (returns a zero value).
XIf two pipelines are separated by \fB|\||\fP, the second is executed
Xonly if the first is unsuccessful (returns a nonzero value).
X.PP
XA \fIlist\fP is a sequence of one or more sublists
Xseparated by, and optionally terminated by, \fB;\fP, \fB&\fP,
Xor a newline.
XNormally the shell waits for each list to finish before executing
Xthe next one.
XIf a list is terminated by a \fB&\fP, the shell executes
Xit in the background, and does not wait for it to finish.
X.PP
XA \fIcomplex command\fP is one of the following:
X.PP
X.RS
X.PD 0
X.TP
X\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ... ]
X.TP
X\fBdo\fP \fIlist\fP
X.TP
X\fBdone\fP
X.PD
XExpand the list of \fIword\fPs, and set the parameter
X\fIname\fP to each of them in turn, executing
X\fIlist\fP each time. If the \fBin\fP \fIword\fP is omitted,
Xuse the positional parameters instead of the \fIword\fPs.
X.TP
X\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ... ] ; \fIsublist\fP
XThis is a shorthand for \fBfor\fP.
XThough it may cause confusion, it is included for convenience;
Xits use in scripts is discouraged,
Xunless \fIsublist\fP is a command of the form { \fIlist\fP }.
X.PP
X.PD 0
X.TP
X\fBforeach\fP \fIname\fP \fB(\fP \fIword\fP ... \fB)\fP
X.TP
X\fIlist\fP
X.TP
X\fBend\fP
X.PD
XAnother form of \fBfor\fP.
X.PP
X.PD 0
X.TP
X\fBfor\fP \fIname\fP \fBin\fP \fIword\fP ...
X.TP
X\fB{\fP
X.TP
X\fIlist\fP
X.TP
X\fB}\fP
X.PD
XAnother form of \fBfor\fP.
X.PP
X.PD 0
X.TP
X\fBfor\fP \fIname\fP \fB(\fP \fIword\fP ... \fB) {\fP
X.TP
X\fIlist\fP
X.TP
X\fB}\fP
X.PD
XAnother form of \fBfor\fP.
X.PP
X.PD 0
X.TP
X\fBfor\fP \fIname\fP \fB(\fP \fIword\fP ... \fB) \fIsublist\fP
X.PD
XAnother form of \fBfor\fP.
X.PP
X.PD 0
X.TP
X\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ... ]
X.TP
X\fBdo\fP \fIlist\fP
X.TP
X\fBdone\fP
X.PD
XPrint the set of \fIword\fPs, each preceded by a number.
XIf the \fBin\fP \fIword\fP is omitted, use the positional parameters.
XThe \fBPROMPT3\fP prompt is printed and a line is read from standard
Xinput. If this line consists of the number of one of the listed
X\fIword\fPs, then the parameter \fIname\fP
Xis set to the \fIword\fP corresponding to this number.
XIf this line is empty, the selection list is printed again.
XOtherwise, the value of the parameter \fIname\fP is set to null.
XThe contents of the line read from standard input is saved
Xin the parameter \fBREPLY\fP. \fIlist\fP is executed
Xfor each selection until a break or end-of-file is encountered.
X.TP
X\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ] ; \fIsublist\fP
XA short form of \fBselect\fP.
X.TP
X\fBcase\fP \fIword\fP \fBin\fP [ \fIpattern\fP ) \fIlist\fP ;; ] ... \fBesac\fP
XExecute the \fIlist\fP associated with the first \fIpattern\fP
Xthat matches \fIword\fP, if any. The form of the patterns
Xis the same as that used for filename generation. See
X\fIFilename Generation\fP below.
X.TP
X\fBcase\fP \fIword\fP \fB{\fP [ \fIpattern\fP ) \fIlist\fP ;; ] ... \fB}\fP
XAnother form of \fBcase\fP.
X.TP
X.PD 0
X\fBif\fP \fIlist\fP
X.TP
X\fBthen\fP \fIlist\fP
X.TP
X[ \fBelif\fP \fIlist\fP ; \fBthen\fP \fIlist\fP ] ...
X.TP
X[ \fBelse\fP \fIlist\fP ]
X.TP
X\fBfi\fP
X.PD
XThe \fBif\fP \fIlist\fP is executed, and,
Xif it returns a zero exit status,
Xthe \fBthen\fP \fIlist\fP is executed.
XOtherwise, the \fBelif\fP \fIlist\fP is
Xexecuted and, if its value is zero,
Xthe \fBthen\fP \fIlist\fP is executed.
XIf each \fBelif\fP \fIlist\fP returns
Xnonzero, the \fBelse\fP \fIlist\fP is executed.
X.TP
X\fBif (\fP \fIlist\fP \fB)\fP \fIsublist\fP
XA short form of \fBif\fP.
X.PP
X.PD 0
X.TP
X\fBif\fP \fB(\fP \fIlist\fP \fB) {\fP
X.TP
X\fIlist\fP
X.TP
X\fB} elif (\fP \fIlist\fP \fB) {\fP
X.TP
X\fIlist\fP
X.TP
X\fB} ... else {\fP
X.TP
X\fIlist\fP
X.TP
X\fB}\fP
X.PD
XAn alternate form of \fBif\fP.
X.TP
X.PD 0
X\fBwhile\fP \fIlist\fP
X.TP
X\fBdo\fP \fIlist\fP
X.TP
X\fBdone\fP
X.PD
XExecute the \fBdo\fP \fIlist\fP as long as the \fBwhile\fP \fIlist\fP
Xreturns a zero exit status.
X.PP
X.PD 0
X.TP
X\fBwhile (\fP \fIlist\fP \fB) {\fP
X.TP
X\fIlist\fP
X.TP
X\fB}\fP
X.PD
XAn alternate form of \fBwhile\fP.
X.TP
X.PD 0
X\fBuntil\fP \fIlist\fP
X.TP
X\fBdo\fP \fIlist\fP
X.TP
X\fBdone\fP
X.PD
XExecute the \fBdo\fP \fIlist\fP as long as \fBuntil\fP \fIlist\fP
Xreturns a nonzero exit status.
X.TP
X.PD 0
X\fBrepeat\fP \fIword\fP
X.TP
X\fBdo\fP \fIlist\fP
X.TP
X\fBdone\fP
X.PD
X\fIword\fP is expanded and treated as an arithmetic expression,
Xwhich must evaluate to a number \fIn\fP.
X\fIlist\fP is then executed \fBn\fP times.
X.TP
X\fBrepeat\fP \fIword\fP \fIsublist\fP
XThis is a short form of \fBrepeat\fP.
X.TP
X( \fIlist\fP )
XExecute \fIlist\fP in a subshell.
X.TP
X{ \fIlist\fP }
XExecute \fIlist\fP.
X.TP
X.PD 0
X\fBfunction\fP \fIword\fP [ (\|) ] ... { \fIlist\fP }
X.TP
X\fIword\fP ... (\|) { \fIlist\fP }
X.TP
X\fIword\fP ... (\|) \fIsublist\fP
X.PD
XDefine a function which is referenced by any one of \fIword\fP.
XNormally, only one \fIword\fP is provided; multiple \fIword\fPs
Xare usually only useful for setting traps.
XThe body of the function is the \fIlist\fP between
Xthe { and }.
XSee \fBFUNCTIONS\fP below.
X.TP
X\fBtime\fP [ \fIpipeline\fP ]
XThe \fIpipeline\fP is executed, and timing statistics are
Xreported on the standard error in the form specified
Xby the \fBTIMEFMT\fP parameter.
XIf \fIpipeline\fP is omitted, print statistics about the
Xshell process and its children.
X.TP
X[[ \fIexp\fP ]]
XEvaluates the conditional expression \fIexp\fP
Xand return a zero exit status if it is true.
XSee \fBConditional Expressions\fP below for a description
Xof \fIexp\fP.
X.SH "RESERVED WORDS"
XThe following words are recognized as reserved words when used
Xas the first word of a command
Xunless quoted or removed using the \fBunalias\fP builtin:
X.RS
X.PP
X\fBdo done esac then elif else fi for case
Xif while function repeat time until exec command
Xselect coproc noglob \- nocorrect foreach end\fP
X.RE
X.SH COMMENTS
XIn noninteractive shells, or in interactive shells with the
X\fBINTERACTIVE_COMMENTS\fP option set, a word beginning
Xwith the third character of the \fBHISTCHARS\fP parameter
X(`#' by default) causes that word and all the following
Xcharacters up to a newline to be ignored.
X.SH ALIASING
XEvery token in the shell input is checked to see if there
Xis an alias defined for it.
XIf so, it is replaced by the text of the alias if it is in command
Xposition (if it could be the first word of a simple command),
Xor if the alias is global.
XIf the text ends with a space, the next word in the shell input
Xis treated as though it were in command position for purposes of alias
Xexpansion.
XAn alias is defined using the \fBalias\fP builtin; global aliases
Xmay be defined using the \-\fBg\fP option to that bulitin.
X.PP
XAlias substitution is done on the shell input before any
Xother substitution except history substitution. Therefore,
Xif an alias is defined for the word \fBfoo\fP, alias substitution
Xmay be avoided by quoting part of the word, e.g. \fB\efoo\fP.
XBut there is nothing to prevent an alias being defined
Xfor \fB\efoo\fP as well.
X.SH QUOTING
XA character may be \fIquoted\fP (that is, made
Xto stand for itself) by preceding it with a \e\|.
X\e followed by a newline is ignored.
XAll characters enclosed between a pair of single quotes ('')
Xare quoted.
XA single quote cannot appear within single quotes.
XInside double quotes (""), parameter and command substitution
Xoccurs, and \e quotes the characters \e\|, `, ", and $.
X.SH EXPANSION
XExpansion is performed on the command line after it has been
Xparsed. The types of expansions performed are
X\fIfilename expansion\fP,
X\fIprocess substitution\fP,
X\fIparameter expansion\fP,
X\fIcommand substitution\fP,
X\fIarithmetic expansion\fP,
X\fIbrace expansion\fP,
Xand \fIfilename generation\fP.
X.SS Filename Expansion
XEach word is checked to see if it begins with an unquoted ~.
XIf it does, then the word up to a / is checked to see if it matches
Xthe name of a named directory. If so, then the ~ and the matched portion
Xare replaced with the value of the named directory.
XA ~ by itself or followed by a / is replaced by the value of the
X\fBHOME\fP parameter.
XA ~ followed by a + or a \- is replaced by the value of
X\fBPWD\fP or \fBOLDPWD\fP, respectively.
X.PP
XNamed directories are typically login directories for users on the system.
XThey may also be defined if the text after the ~ is the name
Xof a shell parameter whose value begins with a /.
XIn certain circumstances (in prompts, for instance), when the shell
Xprints a path, the path is checked to see if it has a named
Xdirectory as its prefix. If so, then the prefix portion
Xis replaced with a ~ followed by the name of the directory.
XThe longest match is preferred.
X.PP
XIf a word begins with an unquoted \fB=\fP and the
X\fBNO_EQUALS\fP option is not set,
Xthe remainder of the word is taken as the
Xname of a command or alias. If a command
Xexists by that name, the word is replaced
Xby the full pathname of the command.
XIf an alias exists by that name, the word
Xis replaced with the text of the alias.
XOtherwise the word is checked up to a /
Xto see if it is a number or a \-. If so,
Xthe matched portion is replaced with
Xthe \fIn\fPth directory in the directory stack,
Xwhere \fIn\fP is the number matched, or
Xthe last directory in the directory stack
Xif a \- is matched.
X.SS Process Substitution
XEach command argument of the form
X\fB<(\fIlist\^\fB)\fR
Xor
X\fB>(\fIlist\^\fB)\fR
Xor
X\fB=(\fIlist\^\fB)\fR
Xis subject to process substitution.
XIn the case of the
X.B <
Xor
X.B >
Xforms, the shell will run process
X.I list
Xasynchronously connected to a named pipe (FIFO).
XThe name of this pipe will become the argument to the command.
XIf the form with
X.B >
Xis selected then writing on this file will provide input for
X.IR list .
XIf
X.B <
Xis used,
Xthen the file passed as an argument will
Xbe a named pipe connected to the output of the
X.I list
Xprocess.
XFor example,
X.RS
X.PP
X\fBpaste <(cut \-f1\fP \fIfile1\fB) <(cut \-f3\fP \fIfile2\fB) | tee >(\fIprocess1\fB) >(\fIprocess2\fB)\fR >/dev/null
X.RE
X.PP
X.BR cut s
Xfields 1 and 3 from
Xthe files
X.I file1
Xand
X.I file2
Xrespectively,
X.BR paste s
Xthe results together, and sends it to the processes
X.I process1
Xand
X.IR process2 .
XNote that the file, which is passed as an argument to the command,
Xis a system
Xpipe
Xso programs that expect to
X.BR lseek (2)
Xon the file will not work.
XAlso note that the previous example can be more compactly and
Xefficiently written as:
X.RS
X.PP
X\fBpaste <(cut \-f1\fP \fIfile1\fB) <(cut \-f3\fP \fIfile2\fB) > >(\fIprocess1\fB) > >(\fIprocess2\fB)\fR
X.RE
X.PP
Xthe shell uses pipes instead of a FIFOs to implement the latter
Xtwo process substitutions in the above example.
X.PP
XIf
X.B =
Xis used,
Xthen the file passed as an argument will be the name
Xof a temporary file containing
Xthe output of the
X.I list
Xprocess. This may be used instead of the
X.B <
Xform for a program that expects to \fBlseek\fP(2) on the input file.
X.SS Parameter Expansion
XThe character \fB$\fP is used to introduce parameter expansions.
XSee \fBPARAMETERS\fP below for a description of parameters.
X.PD
X.RS
X.TP
X\fB${\fIname\fB}\fR
XThe value, if any, of the parameter \fIname\fP is substituted.
XThe braces are required with \fIname\fP is followed by
Xa letter, digit, or underscore that is not to be interpreted
Xas part of its name.
XIf \fIname\fP is an array parameter, then the values of each
Xelement of \fIname\fP is substituted, one element per word.
XOtherwise, the expansion results in one word only; no
Xword splitting is done on the result.
X.TP
X\fB${\fIname\fB:\-\fIword\fB}\fR
XIf \fIname\fP is set and is non-null then substitute its
Xvalue; otherwise substitute \fIword\fP.
X.TP
X\fB${\fIname\fB:=\fIword\fB}\fR
XIf \fIname\fP is unset and is null then
Xset it to \fIword\fP; the value of the parameter is then
Xsubstituted.
X.TP
X\fB${\fIname\fB:?\fIword\fB}\fR
XIf \fIname\fP is set and is non-null, then substitute
Xits value; otherwise, print \fIword\fP and exit from the shell.
XIf \fIword\fP is omitted, then a standard message is printed.
X.TP
X\fB${\fIname\fB:+\fIword\fB}\fR
XIf \fIname\fP is set and is non-null then substitute
X\fIword\fP; otherwise substitute nothing.
X.PD 0
X.TP
X\fB${\fIname\fB#\fIpattern\fB}\fR
X.TP
X\fB${\fIname\fB##\fIpattern\fB}\fR
X.PD
XIf the \fIpattern\fP matches the beginning of the value of
X\fIname\fP, then substitute the value of \fIname\fP with
Xthe matched portion deleted; otherwise, just
Xsubstitute the value of \fIname\fP. In the first
Xform, the smallest matching pattern is preferred;
Xin the second form, the largest matching pattern is preferred.
X.PD 0
X.TP
X${\fIname\fB%\fIpattern\fR}
X.TP
X${\fIname\fB%%\fIpattern\fR}
X.PD
XIf the \fIpattern\fP matches the end of the value of
X\fIname\fP, then substitute the value of \fIname\fP with
Xthe matched portion deleted; otherwise, just
Xsubstitute the value of \fIname\fP. In the first
Xform, the smallest matching pattern is preferred;
Xin the second form, the largest matching pattern is preferred.
X.TP
X${\fB#\fIspec\fR}
XIf \fIspec\fP is one of the above substitutions, substitute
Xthe length in characters of the result instead of
Xthe result itself. If \fIspec\fP is an array expression,
Xsubstitute the number of elements of the result.
X.TP
X${\fB^\fIspec\fR}
XToggle the value of the \fBRC_EXPAND_PARAM\fP option for the
Xevaluation of \fIspec\fP.
XWhen this option is set, array expansions of the form
X\fIfoo\fB${\fIxx\fB}\fIbar\fR, where the parameter
X\fIxx\fP is set to (\fIa b c\fP), are substituted with
X\fIfooabar foobbar foocbar\fP instead of the default
X\fIfooa b cbar\fP.
X.TP
X${\fB=\fIspec\fR}
XToggle the value of the \fBSH_WORD_SPLIT\fP option for the
Xevaluation of \fIspec\fP.
XWhen this option is set, parameter values are split into
Xseparate words using \fBIFS\fP as a delimiter
Xbefore substitution.
XThis is done by default in most other shells.
X.PD
X.RE
X.PP
XIf the colon is omitted from one of the above expressions
Xcontaining a colon, then the shell only checks whether
X\fIname\fP is set or not, not whether it is null.
X.SS Command Substitution
XA command enclosed in parentheses
Xpreceded by a dollar sign, like so: $(...) or quoted with grave
Xaccents: `...` is replaced with its standard output.
XIf the substitution is not enclosed in double quotes, the
Xoutput is broken into words using the \fBIFS\fP parameter.
XThe substitution \fB$(cat foo)\fP may be replaced
Xby the equivalent but faster \fB$(<foo)\fP.
X.SS Arithmetic Expansion
XA string of the form \fB$[\fIexp\fB]\fR is substituted
Xwith the value of the arithmetic expression \fIexp\fP.
X\fIexp\fP is treated as if it were within single quotes.
XSee \fBARITHMETIC EVALUATION\fP below.
X.SS Brace Expansion
XA string of the form
X\fIfoo\fB{\fIxx\fB,\fIyy\fB,\fIzz\fB}\fIbar\fR
Xis expanded to the individual words
X\fIfooxxbar\fP, \fIfooyybar\fP, and \fIfoozzbar\fP.
XLeft-to-right order is preserved. This construct
Xmay be nested. Malformed brace expansion expressions,
Xincluding expressions without a comma, are left unchanged
Xby the shell.
X.PP


XAn expression of the form

X\fB{\fIx\fB\-\fIy\fB}\fR,
Xwhere \fIx\fP and \fIy\fP are single characters,
Xis expanded to every character between
X\fIx\fP and \fIy\fP, inclusive.
X.SS Filename Generation
XIf a word contains an unquoted instance of one of the characters
X*, |, <, [, or ?, it is regarded
Xas a pattern for filename generation, unless the \fBNOGLOB\fP option is set.
XIf the \fBEXTENDED_GLOB\fP option is set, the
X^ and # characters also denote a pattern; otherwise
Xthey are not treated specially by the shell.
XThe word is replaced with a list of sorted filenames that match
Xthe pattern. If no matching pattern is found, the shell gives
Xan error message, unless the \fBNULLGLOB\fP option is set,
Xin which case the word is deleted; or unless the \fBNO_NOMATCH\fP
Xoption is set, in which case the word is left unchanged.
XIn filename generation,
Xthe character / must be matched explicitly; also, a . must be matched
Xexplicitly at the beginning of a pattern or after a /, unless the
X\fBGLOBDOTS\fP option is set. No filename generation pattern
Xmatches the files "." or "..". In other instances of pattern
Xmatching, the / and . are not treated specially.
X.PP
X.RS
X.PD 0
X.TP
X.B *
Xmatches any string, including the null string.
X.TP
X.B ?
Xmatches any character.
X.TP
X\fB[ ... ]\fP
Xmatches any of the enclosed characters.
X.TP
X\fB[^ ... ]\fP
Xmatches any character except the enclosed characters.
X.TP
X\fB<x\-y>\fP
Xmatches any number in the range x to y, inclusive.
XIf x is omitted, the number must be less than or equal to y.
XIf y is omitted, the number must be greater than or equal to x.
XA pattern of the form \fB<\->\fP or
Xsimply \fB<>\fP matches any number.
X.TP
X\fB^x\fP
Xmatches anything except the pattern x.
X.TP
X\fBx|y\fP
Xmatches either x or y.
X.TP
X\fBx#\fP
Xmatches zero or more occurrences of the pattern x.
X.TP
X\fBx##\fP
Xmatches one or more occurrences of the pattern x.
X.RE
X.PD
X.PP
XParentheses may be used for grouping. Note that the \fB|\fP character
Xmust be within parentheses, so that the lexical analyzer does
Xnot think it is a pipe character. Also note that "/" has a
Xhigher precedence than "^"; that is:
X.RS
X.PP
Xls
X.BI ^ foo / bar
X.RE
X.PP
Xwill search directories in "." except "./foo" for a file named bar.
X.PP
XA pathname component of the form
X.BI ( foo /)#
Xmatches a path consisting of zero or more directories
Xmatching the pattern foo.
XAs a shorthand,
X.B **/
Xis equivalent to
X.BR (*/)# .
XThus:
X.RS
X.PP
Xls
X.BI (*/)# bar
X.RE
X.PP
Xor
X.RS
X.PP
Xls
X.BI **/ bar
X.RE
X.PP
Xdoes a recursive directory search for files named bar.
X.PP
XIf used for filename generation, a pattern may contain an exclusion
Xspecifier. Such patterns are of the form \fIpat1\fB~\fIpat2\fR.
XThis pattern will generate all files matching \fIpat1\fP, but which
Xdo not match \fIpat2\fP. For example, \fB*.c~lex.c\fP will match
Xall files ending in .c, except the file \fBlex.c\fP.
X.PP
XPatterns used for filename generation may also end in a
Xlist of qualifiers enclosed in parentheses.
XThe qualifiers
Xspecify which filenames that otherwise match the given pattern
Xwill be inserted in the argument list.
XA qualifier may be any one of the following:
X.PD 0
X.RS
X.TP
X.B /
Xdirectories
X.TP
X.B .
Xplain files
X.TP
X.B @
Xsymbolic links
X.TP
X.B =
Xsockets
X.TP
X.B p
Xnamed pipes (FIFOs)
X.TP
X.B *
Xexecutable plain files (0100)
X.TP
X.B %
Xdevice files (character or block special)
X.TP
X.B r
Xreadable files (0400)
X.TP
X.B w
Xwritable files (0200)
X.TP
X.B x
Xexecutable files (0100)
X.TP
X.B R
Xworld-readable files (0004)
X.TP
X.B W
Xworld-writable files (0002)
X.TP
X.B X
Xworld-executable files (0001)
X.TP
X.B s
Xsetuid files (04000)
X.TP
X.B S
Xsetgid files (02000)
X.TP
X\fBd\fIdev\fR
Xfiles on the device \fIdev\fP
X.TP
X\fBl\fIct\fR
Xfiles having a link count of \fIct\fP
X.TP
X\fBU\fP
Xfiles owned by the effective user id
X.TP
X\fBG\fP
Xfiles owned by the effective group id
X.TP
X\fBu\fInum\fR
Xfiles owned by user id \fInum\fP
X.TP
X\fBg\fInum\fR
Xfiles owned by group id \fInum\fP
X.TP
X\fB^\fP
Xnegates all qualifiers following it
X.TP
X\fBM\fP
Xsets the \fBMARKDIRS\fP option for the current pattern
X.TP
X\fBN\fP
Xsets the \fBNULLGLOB\fP option for the current pattern
X.TP
X\fBD\fP
Xsets the \fBGLOBDOTS\fP option for the current pattern
X.PD
X.RE
X.PP
XThus:
X.RS
X.PP
Xls
X.B
X*(%W)
X.RE
X.PP
Xlists all world-writable device files in the current directory,
Xand
X.RS
X.PP
Xls
X.B /tmp/foo*(u0^@)
X.RE
X.PP
Xlists all root-owned files beginning with the string
X"foo" in /tmp, ignoring symlinks, and
X.RS
X.PP
Xls
X.B *.*~(lex|parse).[ch](^D^l1)
X.RE
X.PP
Xlists all files having a link count of one whose names contain a dot
X(but not those starting with a dot, since \fBGLOBDOTS\fP is explicitly
Xswitched off) except for lex.c, lex.h, parse.c, and parse.h.
XA "/" at the end of a pattern
Xis equivalent to "(\|/\|)".
X.SH REDIRECTION
XBefore a command is executed, its input and output
Xmay be redirected.
XThe following may appear anywhere in a simple-command
Xor may precede or follow a complex command.
XSubstitution occurs before
X.I word
Xis used except as noted below.
XIf the result of substitution on
X.I word
Xproduces more than one filename,
Xredirection occurs for each
Xseparate filename in turn.
X.TP
X.BI < word
XOpen file
X.I word
Xas standard input.
X.TP
X.BI > word
XOpen file
X.I word
Xas standard output.
XIf the file does not exist then it is created.
XIf the file exists, and the
X.B NOCLOBBER
Xoption is set,
Xthis causes an error;
Xotherwise, it is truncated to zero length.
X.TP
X.BI >! " word"
XSame as
X.BR > ,
Xexcept that the file is truncated to zero length
Xif it exists, even if
X.B NOCLOBBER
Xis set.
X.TP
X.BI >> word
XOpen file
X.I word
Xas standard output.
XIf the file exists then output is appended to it.
XIf the file does not exist, and the
X.B NOCLOBBER
Xoption is set,
Xthis causes an error;
Xotherwise, the file is created.
X.TP
X.BI >>! " word"
XSame as
X.BR >> ,
Xexcept that the file is created if it does not
Xexist, even if
X.B NOCLOBBER
Xis set.
X.TP
X\fB<<\fP[\-] \fIword\fP
XThe shell input is read up to a line that is the same as
X.IR word ,
Xor to an end-of-file.
XNo parameter substitution, command substitution or
Xfilename generation is performed on
X.IR word .
XThe resulting document,
Xcalled a
X.IR here-document ,
Xbecomes
Xthe standard input.
XIf any character of \fIword\fP is quoted with
Xsingle or double quotes (a \e alone is \fInot\fP sufficient),
Xno interpretation
Xis placed upon the characters of the document.
XOtherwise, parameter and command substitution
Xoccurs, \e followed by a newline is removed,
Xand \e must be used to quote the characters
X\e, $, `, and the first character of \fIword\fP.
XIf <<\- is used, then all leading
Xtabs are stripped from \fIword\fP and from the document.
X.TP
X.BI <<< word
XOpen a file containing \fIword\fP, after expansion,
Xas standard input.
X.TP
X.BI <& digit
XThe standard input
Xis duplicated from file descriptor
X.I digit
X(see
X.IR dup (2)).
XSimilarly for standard output using
X\fB>&\fIdigit\fP.
X.TP
X.BI >& word
XSame as
X.BI > word
X\fB2>&\fP1.
X.TP
X.BI >>& word
XSame as
X.BI >> word
X\fB2>&\fP1.
X.TP
X.BI <&\-
XClose the standard input.
X.TP
X.BI >&\-
XClose the standard output.
X.TP
X.BI <&p
XThe input from the coprocess is moved to the standard input.
X.TP
X.BI >&p
XThe output to the coprocess is moved to the standard output.
X.PP
XIf one of the above is preceded by a digit, then the file
Xdescriptor referred to is that specified by the digit
X(instead of the default 0 or 1).
XThe order in which redirections are specified is significant.
Xthe shell evaluates each redirection in terms of the
X.RI ( "file descriptor" ", " file )
Xassociation at the time of evaluation.
XFor example:
X.RS
X.PP
X\&.\|.\|. \|1>\fIfname\^\fP 2>&1
X.RE
X.PP
Xfirst associates file descriptor 1 with file
X.IR fname .
XIt then associates file descriptor 2 with the file associated with file
Xdescriptor 1 (that is,
X.IR fname ).
XIf the order of redirections were reversed, file descriptor 2 would be associated
Xwith the terminal (assuming file descriptor 1 had been) and then file descriptor
X1 would be associated with file
X.IR fname .
X.PP
XIf the user tries to open a file descriptor for writing more than once,
Xthe shell opens the file descriptor as a pipe to a process that copies
Xits input to all the specified outputs, similar to tee(1). Thus:
X.RS
X.PP
X.B date >foo >bar
X.RE
X.PP
Xwrites the date to two files, named "foo" and "bar".
XNote that a pipe is an implicit indirection; thus
X.RS
X.PP
X.B date >foo | cat
X.RE
X.PP
Xwrites the date to the file "foo", and also pipes it to cat.
X.PP
XIf the user tries to open a file descriptor for reading more than once,
Xthe shell opens the file descriptor as a pipe to a process that copies
Xall the specified inputs to its output in the order
Xspecified, similar to cat(1). Thus
X.RS
X.PP
X.B sort <foo <fubar
X.RE
X.PP
Xor even
X.RS
X.PP
X.B sort <f{oo,ubar}
X.RE
X.PP
Xis equivalent to "cat foo bar | sort". Note that
Xa pipe is in implicit indirection; thus
X.RS
X.PP
X.B cat bar | sort <foo
X.RE
X.PP
Xis equivalent to "cat bar foo | sort" (note the order of the inputs).
X.PP
XIf a simple command consists of one or more redirection operators
Xand zero or more parameter assignments, but no command name,
Xthe command \fBcat\fP is assumed. Thus
X.RS
X.PP
X.B < file
X.RE
X.PP
Xprints the contents of \fBfile\fP.
X.PP
XIf a command is followed by
X.B &
Xand job control is not active,
Xthen the default standard input
Xfor the command
Xis the empty file
X.BR /dev/null .
XOtherwise, the environment for the execution of a command contains the
Xfile descriptors of the invoking shell as modified by
Xinput/output specifications.
X.SH "COMMAND EXECUTION"
XIf a command name contains no slashes, the shell attempts to locate
Xit. If there exists a shell function by that name, the function
Xis invoked as described below in \fBFUNCTIONS\fP. If there exists
Xa shell builtin by that name, the builtin is invoked.
X.PP
XOtherwise, the shell searches each element of \fBpath\fP for a
Xdirectory containing an executable file by that name. If the
Xsearch is unsuccessful, the shell prints an error message and returns
Xa nonzero exit status.
X.PP
XIf execution fails because the file is not in executable format,
Xand the file is not a directory, it is assumed to be a shell
Xscript. /bin/sh is spawned to execute it. If the program
Xis a file beginning with \fB#!\fP, the remainder of the first line
Xspecifies an interpreter for the program. The shell will
Xexecute the specified interpreter on operating systems that do
Xnot handle this executable format in the kernel.
X.SH FUNCTIONS
X.PP
XThe
X.B function
Xreserved word is used to define shell functions.
XShell functions are read in and stored internally.
XAlias names are resolved when the function is read.
XFunctions are executed like commands with the arguments
Xpassed as positional parameters.
X(See
X.I Execution
Xbelow).
X.PP
XFunctions execute in the same process as the caller and
Xshare all files
Xand present working directory with the
Xcaller.
XA trap on
X.B EXIT
Xset inside a function
Xis executed after the function completes in the environment
Xof the caller.
X.PP
XThe
X.B return
Xbuiltin is used to return
Xfrom function calls.
X.PP
XFunction identifiers
Xcan be listed with the
X.B functions
Xbuiltin.
XFunctions can be undefined with the
X.B unfunction
Xbuiltin.
X.PP
XThe following functions, if defined, have special meaning to
Xthe shell:
X.PP
X.PD 0
X.TP
X\fBchpwd\fP
XExecuted whenever the current working directory is changed.
X.TP
X\fBprecmd\fP
XExecuted before each prompt.
X.TP
X\fBperiodic\fP
XIf the parameter
X.B PERIOD
Xis set, this function is executed every
X.B PERIOD
Xseconds, just before a prompt.
X.TP
X\fBTRAPxxx\fP
XIf defined and non-null,
Xthis function will be executed whenever the shell
Xcatches a signal \fBSIGxxx\fP, where \fBxxx\fP is a signal
Xname as specified for the \fBkill\fP builtin (see below).
XIn addition, \fBTRAPERR\fP is executed whenever a command has a non-zero
Xexit status, \fBTRAPDEBUG\fP is executed after each command, and
X\fBTRAPEXIT\fP
Xis executed when the shell exits,
Xor when the current function exits if defined
Xinside a function.
XIf a function of this form is defined and null,
Xthe shell and processes spawned by it will ignore \fBSIGxxx\fP.
X.PD
X.SH JOBS
X.PP
XIf the
X.B MONITOR
Xoption is set,
Xan interactive shell associates a \fIjob\fR with each pipeline.
XIt keeps
Xa table of current jobs, printed by the
X.B jobs
Xcommand, and assigns them small integer numbers.
XWhen a job is started asynchronously with
X.BR & ,
Xthe shell prints a line which looks
Xlike:
X.PP
X.DT
X [1] 1234
X.PP
Xindicating that the job which was started asynchronously was job number
X1 and had one (top-level) process, whose process id was 1234.
X.PP
XIf you are running a job and wish to do something else you may hit the key
X\fB^Z\fR (control-Z) which sends a STOP signal to the current job.
Xthe shell will then normally indicate that the job has been `suspended',
Xand print another prompt.
XYou can then manipulate the state of this job,
Xputting it in the background with the
X.B bg
Xcommand, or run some other
Xcommands and then eventually bring the job back into the foreground with
Xthe foreground command
X.BR fg .
XA \fB^Z\fR takes effect immediately and
Xis like an interrupt in that pending output and unread input are discarded
Xwhen it is typed.
X.PP
XA job being run in the background will suspend if it tries to read
Xfrom the terminal.
XBackground jobs are normally allowed to produce output,
Xbut this can be disabled by giving the command ``stty tostop''.
XIf you set this
Xtty option, then background jobs will suspend when they try to produce
Xoutput like they do when they try to read input.
X.PP
XThere are several ways to refer to jobs in the shell.
XA job can be referred to by the process id of any process of the job
Xor by one of the following:
X.PD 0
X.TP
X.BI % number
XThe job with the given number.
X.TP
X.BI % string
XAny job whose command line begins with
X.IR string .
X.TP
X.BI %? string
XAny job whose command line contains
X.IR string .
X.TP
X.BI %%
XCurrent job.
X.TP
X.BI %+
XEquivalent to
X.BR %% .
X.TP
X.BI %\-
XPrevious job.
X.PD
X.PP
XThe shell learns immediately whenever a process changes state.
XIt normally informs you whenever a job becomes blocked so that
Xno further progress is possible. If
X.B notify
Xis not set, it waits until
Xjust before it prints
Xa prompt before it informs you.
X.PP
XWhen the monitor mode is on, each background job that completes
Xtriggers any trap set for
X.BR CHLD .
X.PP
XWhen you try to leave the shell while jobs are running or suspended, you will
Xbe warned that `You have suspended (running) jobs.'
XYou may use the
X.B jobs
Xcommand to see what they are.
XIf you do this or immediately try to
Xexit again, the shell will not warn you a second time; the suspended
Xjobs will be terminated, and the running jobs will be sent
Xa \fBSIGHUP\fP signal.
XTo avoid having the shell terminate the running jobs, either
Xuse the \fBnohup\fP(1) command or the \fBdisown\fP builtin (see below).
X.SH SIGNALS
XThe INT and QUIT signals for an invoked
Xcommand are ignored if the command is followed by
X.B &
Xand job
X.B monitor
Xoption is not active.
XOtherwise, signals have the values
Xinherited by the shell from its parent
X(but see the \fBTRAPxxx\fP special function above).
X.SH HISTORY
XHistory substitution allows you to use words from previous command
Xlines in the command line you are typing. This simplifies spelling
Xcorrections and the repetition of complicated commands or arguments.
XCommand lines are saved in the history list, the size of which
Xis controlled by the
X.B HISTSIZE
Xvariable. The most recent command is retained in any case.
XA history substitution begins with a
X.B !
Xand may occur anywhere on the command line; history
Xsubstitutions do not nest. The
X.B !
Xcan be escaped with
X.B \e
Xto suppress its special meaning.
XSingle or double quotes will \fInot\fP work for this.
X.PP
XInput lines containing history substitutions are echoed on the
Xterminal after being expanded, but before any other
Xsubstitutions take place or the command gets executed.
X.SS Event Designators
X.PP
XAn event designator is a reference to a command-line entry in
Xthe history list.
X.RS
X.PD 0
X.TP
X.B !
XStart a history substitution, except when followed by a blank, newline,
X.BR = ,
Xor
X.BR ( .
X.TP
X.B !!
XRefer to the previous command.
XBy itself, this substitution
Xrepeats the previous command.
X.TP
X.BI ! n
XRefer to command-line
X.IR n .
X.TP
X.BI ! \-n
XRefer to the current command-line minus
X.IR n .
X.TP
X.BI ! str
XRefer to the most recent command starting with
X.IR str .
X.TP
X.BI !? str\fR[\fP ? \fR]\fP
XRefer to the most recent command containing
X.IR str .
X.TP
X.B !#
XRefer to the current command line typed in so far.
X.TP
X.BR !{ .\|.\|. }
XInsulate a history reference from adjacent characters (if necessary).
X.PD
X.RE
X.SS Word Designators
X.PP
XA
X.RB ` : '
Xseparates the event specification from the word designator.
XIt can be omitted if the word designator begins with a
X.BR \*^ ,
X.BR $ ,
X.BR * ,
X.B \-
Xor
X.BR % .
XIf the word is to be selected from the previous command, the second
X.B !
Xcharacter can be omitted from the event specification. For instance,
X.B !!:1
Xand
X.B !:1
Xboth refer to the first word of the previous command, while
X.B !!$
Xand
X.B !$
Xboth refer to the last word in the previous command.
XWord designators include:
X.RS
X.PD 0
X.TP
X.B 0
XThe first input word (command).
X.TP
X.I n
XThe
X.IR n 'th
Xargument.
X.TP
X.B ^
XThe first argument, that is,
X.BR 1 .
X.TP
X.B $
XThe last argument.
X.TP
X.B %
XThe word matched by (the most recent)
X.BI ? s
Xsearch.
X.TP
X.IB x \- y
XA range of words;
X.BI \- y
Xabbreviates
X.BI 0\- y\fR.
X.TP
X.B *
XAll the arguments, or a null value if there is just
Xone word in the event.
X.TP
X.IB x *
XAbbreviates
X.IB x \-$ .
X.TP
X.IB x \-
XLike
X.I x*
Xbut omitting word
X.BR $ .
X.PD
X.RE
X.SS Modifiers
X.PP
XAfter the optional word designator, you can add
Xa sequence of one or more of the following modifiers,
Xeach preceded by a
X.BR : .
XThese modifiers also work on the result
Xof filename and parameter expansion.
X.RS
X.TP
X.B h
XRemove a trailing pathname component, leaving the head.
X.PD 0
X.TP
X.B r
XRemove a trailing suffix of the form
X.RB ` "\&.\fIxxx" ',
Xleaving the basename.
X.TP
X.B e
XRemove all but the suffix.
X.TP
X.B t
XRemove all leading pathname components, leaving the tail.
X.TP
X.B &
XRepeat the previous substitution.
X.TP
X.B g
XApply the change to the first occurrence of a match in each word,
Xby prefixing the above (for example,
X.BR g& ).
X.TP
X.B p
XPrint the new command but do not execute it.
X.TP
X.B q
XQuote the substituted words, escaping further substitutions.
X.TP
X.B x
XLike
X.BR q ,
Xbut break into words at each blank.
X.TP
X.B l
XConvert the words to all lowercase.
X.TP
X.B u
XConvert the words to all uppercase.
X.TP
X.BI s/ l / r\fR[\fP / \fR]\fP
XSubstitute
X.I r
Xfor
X.IR l .
X.PD
X.RE
X.PP
XUnless preceded by a
X.BR g ,
Xthe substitution is done only for the
Xfirst string that matches
X.IR l .
X.PP
XThe left-hand side of substitutions are not regular expressions,
Xbut character strings.
XAny character can be used as the delimiter in place of
X.BR / .
XA backslash quotes the delimiter character.
XThe character
X.BR & ,
Xin the right hand side, is replaced by the text
Xfrom the left-hand-side.
XThe
X.B &
Xcan be quoted with a backslash.
XA null
X.I l
Xuses the previous string either from a
X.I l
Xor from a contextual scan string
X.I s
Xfrom
X.BI !? s\fR.
XYou can omit the rightmost delimiter if a newline
Ximmediately follows
X.IR r ;
Xthe rightmost
X.B ?
Xin a context scan can similarly be omitted.
X.PP
XWithout an event specification, a history reference refers either to the
Xprevious command, or to a previous history reference on the command line
X(if any).
X.PP
XThe character sequence
X.BI ^ foo ^ bar
Xrepeats the last command, replacing the string "foo" with the
Xstring "bar".
X.PP
XIf the shell encounters the character sequence
X\fB!"\fP
Xin the input, the history mechanism is temporarily disabled until
Xthe current list is fully parsed. The
X\fB!"\fP
Xis removed from the input, and any subsequent
X.B !
Xcharacters have no special significance.
X.PP
XA less convenient but more comprehensible
Xform of command history support
Xis provided by the
X.B fc
Xbuiltin (see below).
X.SH "ARITHMETIC EVALUATION"
XAn ability to perform integer arithmetic
Xis provided with the builtin
X.BR let .
XEvaluations are performed using
X.I long
Xarithmetic.
XConstants are of the form
X[\fIbase\fB#\^\fR]\fIn\^\fP
Xwhere
X.I base
Xis a decimal number between two and thirty-six
Xrepresenting the arithmetic base
Xand
X.I n
Xis a number in that base.
XIf
X.I base
Xis omitted
Xthen base 10 is used.
X.PP
XAn arithmetic expression uses nearly the same syntax, precedence, and
Xassociativity of
Xexpressions in C.
XThe following operators are supported (listed in decreasing order
Xof precedence):
X.PP
X.PD 0
X.RS
X.TP
X.B + \- ! \(ap ++ \-\|\-
Xunary plus/minus, logical NOT, complement, {pre,post}{in,de}crement
X.TP
X.B &
Xlogical AND
X.TP
X.B ^
Xlogical XOR
X.TP
X.B |
Xlogical OR
X.TP
X.B * / %
Xmultiplication, division, remainder
X.TP
X.B + \-
Xaddition, subtraction
X.TP
X.B << >>
Xlogical shift left, shift right
X.TP
X.B < > <= >=
Xcomparison
X.TP
X.B == !=
Xequality and inequality
X.TP
X.B &&
Xboolean AND
X.TP
X.B |\|| ^^
Xboolean OR, XOR
X.TP
X.B ? :
Xternary operator
X.TP
X.B
X= += \-= *= /= %= &= ^= |= <<= >>= &&= |\||= ^^=
Xassignment
X.TP
X.B ,
Xcomma operator
X.PD
X.RE
X.PP
XThe operators &&, |\||, &&=, and |\||= are short-circuiting,
Xand only one of the latter two expressions in a ternary operator
Xis evaluated. Note the precedence of the logical AND, OR,
Xand XOR operators.
X.PP
XNamed parameters can be referenced by name within an arithmetic expression
Xwithout using the parameter substitution syntax.
X.PP
XAn internal integer representation of a named parameter
Xcan be specified with the
X.B integer
Xbuiltin.
XArithmetic evaluation is performed on the value of each
Xassignment to a named parameter declared integer
Xin this manner.
X.PP
XSince many of the arithmetic operators require
Xquoting, an alternative form of the
X.B let
Xcommand is provided.
XFor any command which begins with a
X.BR (( ,
Xall the characters until a matching
X.B ))
Xare treated as a quoted expression.
XMore precisely,
X.BR (( ... ))
Xis equivalent to
X.B let
X\fB"\fP...\fB"\fP.
X.SH "CONDITIONAL EXPRESSIONS"
XA \fIconditional expression\fP is used with the
X.B [[
Xcompound command to test attributes of files and to compare strings.
XEach expression can be constructed from one or more
Xof the following unary or binary expressions:
X.PD 0
X.TP
X\fB\-a\fP \fIfile\fP
Xtrue if
X.I file
Xexists.
X.TP
X\fB\-b\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is a block special file.
X.TP
X\fB\-c\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is a character special file.
X.TP
X\fB\-d\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is a directory.
X.TP
X\fB\-e\fP \fIfile\fP
Xtrue if
X.I file
Xexists.
X.TP
X\fB\-f\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is an ordinary file.
X.TP
X\fB\-g\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is has its setgid bit set.
X.TP
X\fB\-h\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is a symbolic link.
X.TP
X\fB\-k\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is has its sticky bit set.
X.TP
X\fB\-n\fP \fIstring\fP
Xtrue if length of
X.I string
Xis non-zero.
X.TP
X\fB\-o\fP \fIoption\fP
Xtrue if option named
X.I option
Xis on.
X.TP
X\fB\-p\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is a fifo special file or a pipe.
X.TP
X\fB\-r\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is readable by current process.
X.TP
X\fB\-s\fP \fIfile\fP
Xtrue if
X.I file
Xexists and has size greater than zero.
X.TP
X\fB\-t\fP \fIfd\fP
Xtrue if file descriptor number
X.I fd
Xis open and associated with a terminal device.
X(note: \fIfd\fP is not optional)
X.TP
X\fB\-u\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is has its setuid bit set.
X.TP
X\fB\-w\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is writable by current process.
X.TP
X\fB\-x\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is executable by current process.
XIf
X.I file
Xexists and is a directory, then the current process
Xhas permission to search in the directory.
X.TP
X\fB\-z\fP \fIstring\fP
Xtrue if length of
X.I string
Xis zero.
X.TP
X\fB\-L\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is a symbolic link.
X.TP
X\fB\-O\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is owned by the effective user id of this process.
X.TP
X\fB\-G\fP \fIfile\fP
Xtrue if
X.I file
Xexists and its group matches the effective group id of this process.
X.TP
X\fB\-S\fP \fIfile\fP
Xtrue if
X.I file
Xexists and is a socket.
X.TP
X\fIfile1\fP \fB\-nt\fP \fIfile2\fP
Xtrue if
X.I file1
Xexists and is newer than
X.IR file2 .
X.TP
X\fIfile1\fP \fB\-ot\fP \fIfile2\fP
Xtrue if
X.I file1
Xexists and is older than
X.IR file2 .
X.TP
X\fIfile1\fP \fB\-ef\fP \fIfile2\fP
Xtrue if
X.I file1
Xand
X.I file2
Xexist and refer to the same file.
X.TP
X\fIstring\fP \fB=\fP \fIpattern\fP
Xtrue if
X.I string
Xmatches
X.IR pattern .
X.TP
X\fIstring\fP \fB!=\fP \fIpattern\fP
Xtrue if
X.I string
Xdoes not match
X.IR pattern .
X.TP
X\fIstring1\fP \fB<\fP \fIstring2\fP
Xtrue if
X.I string1
Xcomes before
X.I string2
Xbased on ASCII value of their characters.
X.TP
X\fIstring1\fP \fB>\fP \fIstring2\fP
Xtrue if
X.I string1
Xcomes after
X.I string2
Xbased on ASCII value of their characters.
X.TP
X\fIexp1\fP \fB\-eq\fP \fIexp2\fP
Xtrue if
X.I exp1
Xis equal to
X.IR exp2.
X.TP
X\fIexp1\fP \fB\-ne\fP \fIexp2\fP
Xtrue if
X.I exp1
Xis not equal to
X.IR exp2.
X.TP
X\fIexp1\fP \fB\-lt\fP \fIexp2\fP
Xtrue if
X.I exp1
Xis less than
X.IR exp2.
X.TP
X\fIexp1\fP \fB\-gt\fP \fIexp2\fP
Xtrue if
X.I exp1
Xis greater than
X.IR exp2.
X.TP
X\fIexp1\fP \fB\-le\fP \fIexp2\fP
Xtrue if
X.I exp1
Xis less than or equal to
X.IR exp2.
X.TP
X\fIexp1\fP \fB\-ge\fP \fIexp2\fP
Xtrue if
X.I exp1
Xis greater than or equal to
X.IR exp2.
X.TP
X\fB(\fP \fIexp\fP \fB)\fP
Xtrue if \fIexp\fP is true.
X.TP
X\fB!\fP \fIexp\fP
Xtrue if \fIexp\fP is false.
X.TP
X\fIexp1\fP \fB&&\fP \fIexp2\fP
Xtrue if \fIexp1\fP and \fIexp2\fP are both true.
X.TP
X\fIexp1\fP \fB|\||\fP \fIexp2\fP
Xtrue if either \fIexp1\fP or \fIexp2\fP is true.
X.PD
X.PP
XIn each of the above expressions, if
X.I file
Xis of the form
X\fB/dev/fd/\fP\fIn\fR,
Xwhere
X.I n
Xis an integer,
Xthen the test applied to the open file whose
Xdescriptor number is
X.IR n ,
Xeven if the underlying system does not support
Xthe \fB/dev/fd\fP directory.
X.PD
X.SH "ZSH LINE EDITOR"
XIf the \fBZLE\fP option is set (it is by default)
Xand the shell input is attached to the terminal, the user
Xis allowed to edit command lines.
X.PP
XThere are two display modes. The first, multiline mode, is the default.
XIt only works if the \fBTERM\fP parameter is set to a valid
Xterminal type that can move the cursor up. The second,
Xsingle line mode, is used if \fBTERM\fP is invalid or incapable
Xof moving the cursor up, or if the \fBSINGLE_LINE_ZLE\fP
Xoption is set. This mode is similar to ksh, and uses no
Xtermcap sequences.
X.SS Bindings
XCommand bindings may be set using the \fBbindkey\fP builtin.
XThere are two keymaps\-the main keymap and the alternate keymap.
XThe alternate keymap is bound to vi command mode.
XThe main keymap is bound to emacs mode by default.
XTo bind the main keymap to vi insert mode, use
X\fBbindkey \-v\fP, or set one of the \fBVISUAL\fP or \fBEDITOR\fP
Xenvironment variables to a string containing \fBvi\fP.
X.PP
XThe following is a list of all the key commands
Xand their default bindings in emacs and vi command mode.
X.SS Movement
X.TP
X\fBvi-backward-blank-word\fP (unbound) (B)
XMove backward one word, where a word is defined as a series of
Xnon-blank characters.
X.TP
X\fBbackward-char\fP (^B ESC-[D) (\|)
XMove backward one character.
X.TP
X\fBvi-backward-char\fP (\|) (h)
XMove backward one character, without changing lines.
X.TP
X\fBbackward-word\fP (ESC-B ESC-b) (unbound)
XMove to the beginning of the previous word.
X.TP
X\fBemacs-backward-word\fP
XMove to the beginning of the previous word.
X.TP
X\fBvi-backward-word\fP (unbound) (b)
XMove to the beginning of the previous word, vi-style.
X.TP
X\fBbeginning-of-line\fP (^A) (0)
XMove to the beginning of the line. If already at the beginning
Xof the line, move to the beginning of the previous line, if any.
X.TP
X\fBvi-beginning-of-line\fP
XMove to the beginning of the line, without changing lines.
X.TP
X\fBend-of-line\fP (^E)
XMove to the end of the line. If already at the end
Xof the line, move to the end of the next line, if any.
X.TP
X\fBvi-end-of-line\fP (unbound) ($)
XMove to the end of the line.
X.TP
X\fBvi-forward-blank-word\fP (unbound) (W)
XMove forward one word, where a word is defined as a series of
Xnon-blank characters.
X.TP
X\fBvi-forward-blank-word-end\fP (unbound) (E)
XMove to the end of the current word,
Xor, if at the end of the current word,
Xto the end of the next word,
Xwhere a word is defined as a series of
Xnon-blank characters.
X.TP
X\fBforward-char\fP (^F ESC-[C)
XMove forward one character.
X.TP
X\fBvi-forward-char\fP (unbound) (space l)
XMove forward one character.
X.TP
X\fBvi-find-next-char\fP (^X^F) (f)
XRead a character from the keyboard, and move to
Xthe next occurrence of it in the line.
X.TP
X\fBvi-find-next-char-skip\fP (unbound) (t)
SHAR_EOF
true || echo 'restore of zsh2.2/man/man1/zsh.1 failed'
fi
echo 'End of zsh2.2 part 3'
echo 'File zsh2.2/man/man1/zsh.1 is continued in part 4'
echo 4 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 11:55:49 AM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 100
Archive-name: zsh2.2/part04

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.04 (part 4 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/man/man1/zsh.1 continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 4; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/man/man1/zsh.1'
else
echo 'x - continuing file zsh2.2/man/man1/zsh.1'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/man/man1/zsh.1' &&

XRead a character from the keyboard, and move to

Xthe position just before the next occurrence of it in the line.
X.TP
X\fBvi-find-prev-char\fP (unbound) (F)


XRead a character from the keyboard, and move to

Xthe previous occurrence of it in the line.
X.TP
X\fBvi-find-prev-char-skip\fP (unbound) (T)


XRead a character from the keyboard, and move to

Xthe position just after the previous occurrence of it in the line.
X.TP
X\fBvi-first-non-blank\fP (unbound) (^)
XMove to the first non-blank character in the line.
X.TP
X\fBvi-forward-word\fP (unbound) (w)
XMove forward one word, vi-style.
X.TP
X\fBforward-word\fP (ESC-F ESC-f) (unbound)
XMove to the beginning of the next word.
XThe editor's idea of a word is specified with the \fBWORDCHARS\fP
Xparameter.
X.TP
X\fBemacs-forward-word\fP
XMove to the end of the next word.
X.TP
X\fBvi-forward-word-end\fP (unbound) (e)
XMove to the end of the next word.
X.TP
X\fBvi-goto-column\fP (ESC-|) (|)
XMove to the column specified by the numeric argument.
X.TP
X\fBvi-goto-mark\fP (unbound) (`)
XMove to the specified mark.
X.TP
X\fBvi-goto-mark-line\fP (unbound) (')
XMove to beginning of the line containing the specified mark.
X.TP
X\fBvi-repeat-find\fP (unbound) (;)
XRepeat the last \fBvi-find\fP command.
X.TP
X\fBvi-rev-repeat-find\fP (unbound) (,)
XRepeat the last \fBvi-find\fP command in the opposite direction.
X.SS History
X.TP
X\fBbeginning-of-buffer-or-history\fP (ESC-<)
XMove to the beginning of the buffer, or if already there,
Xmove to the first event in the history list.
X.TP
X\fBbeginning-of-line-hist\fP


XMove to the beginning of the line. If already at the

Xbeginning of the buffer, move to the previous history line.
X.TP
X\fBbeginning-of-history\fP
XMove to the first event in the history list.
X.TP
X\fBdown-line-or-history\fP (^N ESC-[B) (+ j)
XMove down a line in the buffer, or if already at the bottom line,
Xmove to the next event in the history list.
X.TP
X\fBdown-history\fP (unbound) (^N)
XMove to the next event in the history list.
X.TP
X\fBend-of-buffer-or-history\fP (ESC->)
XMove to the end of the buffer, or if already there,
Xmove to the last event in the history list.
X.TP
X\fBend-of-line-hist\fP
XMove to the end of the line. If already at the end of
Xthe buffer, move to the next history line.
X.TP
X\fBend-of-history\fP
XMove to the last event in the history list.
X.TP
X\fBvi-fetch-history\fP (unbound) (G)
XFetch the history line specified by the numeric argument.
X.TP
X\fBhistory-incremental-search-backward\fP (^R ^Xr)
XSearch backward incrementally for a specified string.
XThe string may begin with `^' to anchor the search to the
Xbeginning of the line.
X.TP
X\fBhistory-incremental-search-forward\fP (^Xs)
XSearch forward incrementally for a specified string.
XThe string may begin with `^' to anchor the search to the
Xbeginning of the line.
X.TP
X\fBhistory-search-backward\fP (ESC-P ESC-p) (K)
XSearch backward in the history for a line beginning with the first
Xword in the buffer.
X.TP
X\fBvi-history-search-backward\fP (unbound) (/)
XSearch backward in the history for a specified string.
XThe string may begin with `^' to anchor the search to the
Xbeginning of the line.
X.TP
X\fBhistory-search-forward\fP (ESC-N ESC-n) (J)
XSearch forward in the history for a line beginning with the first
Xword in the buffer.
X.TP
X\fBvi-history-search-forward\fP (unbound) (?)
XSearch forward in the history for a specified string.
XThe string may begin with `^' to anchor the search to the
Xbeginning of the line.
X.TP
X\fBinfer-next-history\fP (^X^N)
XSearch in the history list for a line matching the current one and
Xfetch the event following it.
X.TP
X\fBinsert-last-word\fP (ESC-_ ESC-.)
XInsert the last word from the previous history event at the
Xcursor position.
X.TP
X\fBvi-repeat-search\fP (unbound) (n)
XRepeat the last vi history search.
X.TP
X\fBvi-rev-repeat-search\fP (unbound) (N)
XRepeat the last vi history search, but in reverse.
X.TP
X\fBtoggle-literal-history\fP (ESC-R ESC-r)
XToggle between literal and lexical history. The default is
Xlexical history unless the \fBHISTLIT\fP option is set.
X.TP
X\fBup-line-or-history\fP (^P ESC-[A) (- k)
XMove up a line in the buffer, or if already at the top line,
Xmove to the previous event in the history list.
X.TP
X\fBup-history\fP (unbound) (^P)
XMove to the previous event in the history list.
X.SS Modifying Text
X.TP
X\fBvi-add-eol\fP (unbound) (A)
XMove to the end of the line and enter insert mode.
X.TP
X\fBvi-add-next\fP (unbound) (a)
XMove forward one character and enter insert mode.
X.TP
X\fBbackward-delete-char\fP (^H ^?) (^?)
XDelete the character behind the cursor.
X.TP
X\fBvi-backward-delete-char\fP (unbound) (X)
XDelete the character behind the cursor, without changing lines.
X.TP
X\fBbackward-delete-word\fP
XDelete the word behind the cursor.
X.TP
X\fBbackward-kill-line\fP
XKill from the beginning of the line to the cursor position.
X.TP
X\fBbackward-kill-word\fP (^W ESC-^H ESC-^?)
XKill the word behind the cursor.
X.TP
X\fBvi-backward-kill-word\fP (unbound) (^W)
XKill the word behind the cursor.
X.TP
X\fBcapitalize-word\fP (ESC-C ESC-c)
XCapitalize the current word and move past it.
X.TP
X\fBvi-change\fP (unbound) (c)
XRead a movement command from the keyboard, and kill
Xfrom the cursor position to the endpoint of the movement.
XThen enter insert mode.
XIf the command is \fBvi-change\fP, kill the current line.
X.TP
X\fBvi-change-eol\fP (unbound) (C)
XKill to the end of the line and enter insert mode.
X.TP
X\fBvi-change-whole-line\fP (unbound) (S s)
XKill the current line and enter insert mode.
X.TP
X\fBcopy-region-as-kill\fP (ESC-W ESC-w)
XCopy the area from the cursor to the mark to the kill buffer.
X.TP
X\fBcopy-prev-word\fP (ESC-^_)
XDuplicate the word behind the cursor.
X.TP
X\fBvi-delete\fP (unbound) (d)
XRead a movement command from the keyboard, and kill
Xfrom the cursor position to the endpoint of the movement.
XIf the command is \fBvi-delete\fP, kill the current line.
X.TP
X\fBdelete-char\fP (unbound) (x)
XDelete the character under the cursor.
X.TP
X\fBvi-delete-char\fP (unbound) (x)
XDelete the character under the cursor.
X.TP
X\fBdelete-word\fP (ESC-D ESC-d)
XDelete the current word.
X.TP
X\fBdown-case-word\fP (ESC-L ESC-l)
XConvert the current word to all lowercase and move past it.
X.TP
X\fBkill-word\fP
XKill the current word.
X.TP
X\fBgosmacs-transpose-chars\fP
XExchange the two characters behind the cursor.
X.TP
X\fBvi-indent\fP (unbound) (>)
XIndent a number of lines.
X.TP
X\fBvi-insert\fP (unbound) (i)
XEnter insert mode.
X.TP
X\fBvi-insert-bol\fP (unbound) (I)
XMove to the beginning of the line and enter insert mode.\fP
X.TP
X\fBvi-join\fP (^X^J)
XJoin the current line with the next one.
X.TP
X\fBkill-line\fP (^K) (D)
XKill from the cursor to the end of the line.
X.TP
X\fBkill-region\fP
XKill from the cursor to the mark.
X.TP
X\fBkill-buffer\fP (^X^U) (^U)
XKill the entire buffer.
X.TP
X\fBkill-whole-line\fP (^U) (unbound)
XKill the current line.
X.TP
X\fBvi-match-bracket\fP (^X^B) (%)
XMove to the bracket character (one of {\|}, (\|), or [\|]) that
Xmatches the one under the cursor.
X.TP
X\fBvi-open-line-above\fP (unbound) (O)
XOpen a line above the cursor and enter insert mode.
X.TP
X\fBvi-open-line-below\fP (unbound) (o)
XOpen a line below the cursor and enter insert mode.
X.TP
X\fBvi-oper-swap-case\fP
XRead a movement command from the keyboard, and swap
Xthe case of all characters
Xfrom the cursor position to the endpoint of the movement.
XIf the movement command is \fBvi-oper-swap-case\fP,
Xswap the case of all characters on the current line.
X.TP
X\fBoverwrite-mode\fP (^X^O)
XToggle between overwrite mode and insert mode.
X.TP
X\fBvi-put-after\fP (unbound) (p)
XInsert the contents of the kill buffer after the cursor.
X.TP
X\fBquoted-insert\fP (^V)
XInsert the next character typed into the buffer literally.
X.TP
X\fBquote-line\fP (ESC-')
XQuote the current line; that is, put a ' character at the
Xbeginning and the end, and convert all ' characters
Xto '\e''.
X.TP
X\fBquote-region\fP (ESC-")
XQuote the region from the cursor to the mark.
X.TP
X\fBvi-replace\fP (unbound) (R)
XEnter overwrite mode.
X.TP
X\fBvi-repeat-change\fP (unbound) (.)
XRepeat the last vi mode text modification.
X.TP
X\fBvi-replace-chars\fP (unbound) (r)
XReplace the character under the cursor with a character
Xread from the keyboard.
X.TP
X\fBself-insert\fP (printable characters)
XPut a character in the buffer at the cursor position.
X.TP
X\fBself-insert-unmeta\fP (ESC-^I ESC-^J ESC-^M)
XPut a character in the buffer after stripping the meta bit
Xand converting \fB^M\fP to \fB^J\fP.
X.TP
X\fBvi-substitute\fP (unbound) (s)
XSubstitute the next character(s).
X.TP
X\fBvi-swap-case\fP (unbound) (~)
XSwap the case of the character under the cursor and move past it.
X.TP
X\fBtranspose-chars\fP (^T)
XExchange the two characters to the left of the
Xcursor if at end of line, else exchange the
Xcharacter under the cursor with the character
Xto the left.
X.TP
X\fBtranspose-words\fP (ESC-T ESC-t)
XExchange the current word with the one before it.
X.TP
X\fBvi-unindent\fP (unbound) (<)
XUnindent a number of lines.
X.TP
X\fBup-case-word\fP (ESC-U ESC-u)
XConvert the current word to all caps and move past it.
X.TP
X\fByank\fP (^Y) (P)
XInsert the contents of the kill buffer at the cursor position.
X.TP
X\fByank-pop\fP (ESC-y) (unbound)
XRemove the text just yanked, rotate the kill\-ring,
Xand yank the new top. Only works following
X\fByank\fP or \fByank-pop\fP.
X.TP
X\fBvi-yank\fP (unbound) (y)
XRead a movement command from the keyboard, and copy the region
Xfrom the cursor position to the endpoint of the movement
Xinto the kill buffer.
XIf the command is \fBvi-yank\fP, copy the current line.
X.TP
X\fBvi-yank-eol\fP (unbound) (Y)
XCopy the region from the cursor position to the end of the line
Xinto the kill buffer.
X.SS Arguments
X.TP
X\fBdigit-argument\fP (ESC-0..ESC-9) (0-9)
XStart a new numeric argument, or add to the current one.
X.TP
X\fBuniversal-argument\fP
XMultiply the argument of the next command by 4.
X.SS Completion
X.TP
X\fBaccept-and-menu-complete\fP
XIn a menu completion, insert the current completion into the buffer,
Xand advance to the next possible completion.
X.TP
X\fBcomplete-word\fP (unbound) (\|\e\|)
XAttempt completion on the current word.
X.TP
X\fBdelete-char-or-list\fP (^D)
XDelete the character under the cursor. If the cursor
Xis at the end of the line, list possible completions for the
Xcurrent word.
X.TP
X\fBexecute-named-cmd\fP (ESC-x)
XRead the name of a editor command and execute it.
X.TP
X\fBexecute-last-named-cmd\fP (ESC-z)
XRedo the last function executed with \fBexecute-named-cmd\fP.
X.TP
X\fBexpand-cmd-path\fP
XExpand the current command to its full pathname.
X.TP
X\fBexpand-or-complete\fP (TAB) (TAB ^X)
XAttempt shell expansion on the current word.
XIf that fails,
Xattempt completion.
X.TP
X\fBexpand-history\fP (ESC-space ESC-!)
XPerform history expansion on the edit buffer.
X.TP
X\fBexpand-word\fP (^X*)
XAttempt shell expansion on the current word.
X.TP
X\fBlist-choices\fP (ESC-^D) (^D =)
XList possible completions for the current word.
X.TP
X\fBlist-expand\fP (^Xg ^XG) (^G)
XList the expansion of the current word.
X.TP
X\fBmagic-space\fP
XPerform history expansion and insert a space into the
Xbuffer. This is intended to be bound to space.
X.TP
X\fBmenu-complete\fP
XLike \fBcomplete-word\fP, except that menu completion is used.
XSee the \fBMENU_COMPLETE\fP option below.
X.TP
X\fBmenu-expand-or-complete\fP
XLike \fBexpand-or-complete\fP, except that menu completion is used.
X.TP
X\fBreverse-menu-complete\fP
XSee the \fBMENU_COMPLETE\fP option below.
X.SS Miscellaneous
X.TP
X\fBaccept-and-hold\fP (ESC-A ESC-a)
XPush the contents of the buffer on the buffer stack
Xand execute it.
X.TP
X\fBaccept-and-infer-next-history\fP
XExecute the contents of the buffer.
XThen search the history list for a line matching the current one
Xand push the event following onto the buffer stack.
X.TP
X\fBaccept-line\fP (^J ^M)
XExecute the contents of the buffer.
X.TP
X\fBaccept-line-and-down-history\fP (^O)
XExecute the current line, and push the next history
Xevent on the the buffer stack.
X.TP
X\fBvi-cmd-mode\fP (^X^V) (^[)
XEnter command mode; that is, use the alternate keymap.
XYes, this is bound by default in emacs mode.
X.TP
X\fBvi-caps-lock-panic\fP (unbound) (H K)
XHang until any lowercase key is pressed.
XThis is for vi users without the mental capacity to keep
Xtrack of their caps lock key (like the author).
X.TP
X\fBclear-screen\fP (^L ESC-^L)
XClear the screen and redraw the prompt.
X.TP
X\fBexchange-point-and-mark\fP (^X^X)
XExchange the cursor position with the position of the mark.
X.TP
X\fBget-line\fP (ESC-G ESC-g)
XPop the top line off the buffer stack and insert it at the
Xcursor position.
X.TP
X\fBpound-insert\fP (unbound) (#)
XIf there is no # character at the beginning of the current line,
Xadd one. If there is one, remove it. In either case, accept the
Xcurrent line. The \fBINTERACTIVE_COMMENTS\fP option must be set
Xfor this to have any usefulness.
X.TP
X\fBpush-line\fP (^Q ESC-Q ESC-q)
XPush the current buffer onto the buffer stack and clear
Xthe buffer.
XNext time the editor starts up, the buffer will be popped
Xoff the top of the buffer stack and loaded into the editing
Xbuffer.
X.TP
X\fBredisplay\fP (unbound) (^R)
XRedisplays the edit buffer.
X.TP
X\fBrun-help\fP (ESC-H ESC-h)
XPush the buffer onto the buffer stack, and execute the
Xcommand "\fBrun-help\fP \fIcmd\fP", where \fIcmd\fP is the current
Xcommand. \fBrun-help\fP is normally aliased to \fBman\fP.
X.TP
X\fBsend-break\fP (^C)
XAbort the parsing of the current line.
X.TP
X\fBvi-set-buffer\fP (unbound) (")
XSpecify a buffer to be used in the following command.
X.TP
X\fBvi-set-mark\fP (unbound) (m)
XSet the specified mark at the cursor position.
X.TP
X\fBset-mark-command\fP (^@)
XSet the mark at the cursor position.
X.TP
X\fBspell-word\fP (ESC-$ ESC-S ESC-s)
XAttempt spelling correction on the current word.
X.TP
X\fBundefined-key\fP
XBeep.
X.TP
X\fBundo\fP (^_ ^X^U) (u)
XIncrementally undo the last text modification.
X.TP
X\fBwhich-command\fP (ESC-?)
XPush the buffer onto the buffer stack, and execute the
Xcommand "\fBwhich-command\fP \fIcmd\fP", where \fIcmd\fP is the current
Xcommand. \fBwhich-command\fP is normally aliased to \fBwhence\fP.
X.SH PARAMETERS
XA parameter has a name, a value, and a number of attributes.
XA name may be any sequence of alphanumeric
Xcharacters and _'s, or the single characters
X*, @, #, ?, \-, $, or !.
XThe value may be either a \fIscalar\fP (a string),
Xan integer, or an array.
XTo assign a scalar or integer value to a parameter,
Xuse the \fBtypeset\fP builtin.
XTo assign an array value, use \fBset \-A\fP \fIname\fP \fIvalue\fP ....
XThe value of a parameter may also be assigned by writing:
X.RS
X.PP
X\fIname\fP=\fIvalue\fP ...
X.RE
X.PP
XIf the integer attribute, \-\fBi\fP, is set for \fIname\fP,
Xthe \fIvalue\fP is subject to arithmetic evaluation.
X.PP
XThe value of an array parameter may be assigned by writing:
X.RS
X.PP
X\fIname\fP=(\fIvalue\fP ...) ...
X.RE
XIndividual elements of an array may be selected using a
Xsubscript. A subscript of the form \fB[\fIexp\fB]\fR
Xselects the single element \fIexp\fP, where \fIexp\fP is
Xan arithmetic expression. The elements are numbered
Xbeginning with 1.
XA subscript of the form \fB[*]\fP or \fB[@]\fP evaluates to all
Xelements of an array; there is no difference between the two
Xexcept when they appear within double quotes.
X"$foo[*]" evaluates to "$foo[1] $foo[2] ...", while
X"$foo[@]" evaluates to "$foo[1]" "$foo[2]", etc.
XA subscript of the form \fB[\fIexp1\fP,\fIexp2\fB]\fR
Xselects all elements in the range \fIexp1\fP to \fIexp2\fP,
Xinclusive.
XIf one of the subscripts evaluates to a negative number,
Xsay \-\fIn\fP, then the \fIn\fPth element from the end
Xof the array is used. Thus "$foo[-3]" is the third element
Xfrom the end of the array \fIfoo\fP, and
X"$foo[1,-1]" is the same as "$foo[*]".
X.PP
XSubscripting may also be performed on non-array values, in which
Xcase the subscripts specify a substring to be extracted.
XFor example, if \fBFOO\fP is set to \fBfoobar\fP, then
X\fBecho $FOO[2,5]\fP prints \fBooba\fP.
X.SS Positional Parameters
XPositional parameters are set by the shell on invocation,
Xby the \fBset\fP builtin, or by direct assignment.
XThe parameter \fIn\fP, where \fIn\fP is a number,
Xis the \fIn\fPth positional parameter.
XThe parameters \fB*\fP, \fB@\fP, and \fBargv\fP are
Xarrays containing all the positional parameters;
Xthus \fBargv\fP[\fIn\fP], etc. is equivalent to simply \fIn\fP.
X.SS Special Parameters
XThe following parameters are automatically set by the shell:


X.PP
X.RS
X.PD 0
X.TP

X.B !
XThe process id of the last background command invoked.
X.TP
X.B #
XThe number of positional parameters in decimal.
X.TP
X.B ARGC
XSame as \fB#\fP.
X.TP
X.B $
XThe process id of this shell.
X.TP
X.B \-
XFlags supplied to the shell on invocation or by the \fBset\fP
Xor \fBsetopt\fP commands.
X.TP
X.B *
XAn array containing the positional parameters.
X.TP
X.B argv
XSame as \fB*\fP.
X.TP
X.B @
XSame as \fBargv[@]\fP.
X.TP
X.B ?
XThe exit value returned by the last command.
X.TP
X.B status
XSame as \fB?\fP.
X.TP
X.B _
XThe last argument of the previous command.
XAlso, this parameter is set in the environment of every command
Xexecuted to the full pathname of the command.
X.TP
X.B ERRNO
XThe value of errno as set by the most recently failed system call.
XThis value is system dependent and is intended for debugging
Xpurposes.
X.TP
X.B GID
XThe group id of the shell process.
X.TP
X.B HOST
XThe current hostname.
X.TP
X.B HOSTTYPE
XA string corresponding to the type of the host the shell
Xis running on.
X.TP
X.B LINENO
XThe line number of the current line within the current script
Xbeing executed.
X.TP
X.B OLDPWD
XThe previous working directory.
X.TP
X.B OPTARG
XThe value of the last option argument processed by the \fBgetopts\fP
Xcommand.
X.TP
X.B OPTIND
XThe index of the last option argument processed by the \fBgetopts\fP
Xcommand.
X.TP
X.B PPID
XThe process id of the parent of the shell.
X.TP
X.B PWD
XThe present working directory.
X.TP
X.B RANDOM
XA random integer from 0 to 32767, newly generated each time
Xthis parameter is referenced. The random number generator
Xcan be seeded by assigning a numeric value to \fBRANDOM\fP.
X.TP
X.B SECONDS
XThe number of seconds since shell invocation. If this parameter
Xis assigned a value, then the value returned upon reference
Xwill be the value that was assigned plus the number of seconds
Xsince the assignment.
X.TP
X.B SHLVL
XIncremented by one each time a new shell is started.
X.TP
X.B signals
XAn array containing the names of the signals.
X.TP
X.B TTY
XThe name of the tty associated with the shell, if any.
X.TP
X.B UID
XThe user id of the shell process.
X.TP
X.B USERNAME
X.TP
X.B LOGNAME
XThe username corresponding to the user id of the shell process.
X.TP
X.B VERSION
XThe version number of this \fBzsh\fP.
X.PD
X.RE
X.PP
XThe following parameters are used by the shell:


X.PP
X.RS
X.PD 0
X.TP

X.B BAUD
XThe baud rate of the current connection. Used by the line editor
Xupdate mechanism to compensate for a slow terminal by delaying
Xupdates until necessary. This may be profitably set to a lower value
Xin some circumstances, e.g.
Xfor slow modems dialing into a communications server which is connected
Xto a host via a fast link; in this case, this variable
Xwould be set by default to the speed of the fast link, and not
Xthe modem.
XThis parameter should be set to the baud
Xrate of the slowest part of the link for best performance.
X.TP
X.B bindcmds
XAn write-only array
Xof command names which take line editor function names
Xas arguments, and which therefore should allow binding
Xcompletion.
X.TP
X.B cdpath (CDPATH)
XAn array (colon-separated list)
Xof directories specifying the search path for the \fBcd\fP command.
X.TP
X.B COLUMNS
XThe number of columns for this terminal session.
XUsed for printing select lists and for the line editor.
X.TP
X.B DIRSTACKSIZE
XThe maximum size of the directory stack. If the
Xstack gets larger than this, it will be truncated automatically.
XThis is useful with the \fBAUTO_PUSHD\fP option.
X.TP
X.B FCEDIT
XThe default editor for the \fBfc\fP builtin.
X.TP
X.B fignore (FIGNORE)
XAn array (colon separated list)
Xcontaining the suffixes of files to be ignored
Xduring filename completion.
X.TP
X.B fpath (FPATH)
XAn array (colon separated list)
Xof directories specifying the search path for
Xfunction definitions. This path is searched when a function
Xwith the \-\fBu\fP attribute is referenced. If an executable
Xfile is found, then it is read and executed in the current environment.
X.TP
X.B HISTCHARS
XThree characters used by the shell's history and lexical analysis
Xmechanism. The first character signals the start of a history
Xsubstitution (default `!'). The second character signals the
Xstart of a quick history substitution (default `^'). The third
Xcharacter is the comment character (default `#').
X.TP
X.B HISTFILE
XThe file to save the history in when an interactive shell exits.
XIf unset, the history is not saved.
X.TP
X.B HISTSIZE
XThe maximum size of the history list.
X.TP
X.B HOME
XThe default argument for the \fBcd\fP command.
X.TP
X.B hostcmds
XAn write-only array of command names which
Xtake hostnames as arguments, and which should therefore
Xallow hostname completion. This sort of completion is also
Xused in words containing a \fB@\fP character.
X.TP
X.B hosts (HOSTS)
XAn array (colon separated list) of hostnames to use
Xfor hostname completion.
X.TP
X.B IFS
XInternal field separators, normally space, tab, and newline, that
Xare used to separate words which result from
Xcommand or parameter substitution and words read by
Xthe \fBread\fP builtin.
X.TP
X.B LINES
XThe number of lines for this terminal session.
XUsed for printing select lists and for the line editor.
X.TP
X.B LISTMAX
XIn the line editor,
Xthe number of filenames to list without asking first.
X.TP
X.B LITHISTSIZE
XThe maximum size of the literal history list (before history expansion).
X.TP
X.B LOGCHECK
XThe interval in seconds between checks for login/logout activity
Xusing the \fBwatch\fP parameter.
X.TP
X.B MAIL
XIf this parameter is set and \fBmailpath\fP is not set,
Xthe shell looks for mail in the specified file.
X.TP
X.B MAILCHECK
XThe interval in seconds between checks for new mail.
X.TP
X.B mailpath (MAILPATH)
XAn array (colon-separated list)
Xof filenames to check for new mail. Each filename can
Xbe followed by a ? and a message that will be printed.
XThe sequence $_ in the message will be replaced by the name
Xof the mail file.
XThe default message is "You have new mail."
X.TP
X.B manpath (MANPATH)
XAn array (colon-separated list)
Xwhose value is not used by the shell. The \fBmanpath\fP
Xarray can be useful, however, since setting it also sets
X\fBMANPATH\fP, and vice versa.
X.TP
X.B NULLCMD
XThe command name to assume if a redirection is specified
Xwith no command. Defaults to \fBcat\fP. For sh/ksh-like
Xbehavior, change this to \fB:\fP. For csh-like
Xbehavior, unset this parameter; the shell will print an
Xerror message if null commands are entered.
X.TP
X.B optcmds
XAn write-only array of
Xcommands which take options as arguments, and which
Xtherefore should allow option completion.
X.TP
X.B path (PATH)
XAn array (colon-separated list)
Xof directories to search for commands.
XWhen this parameter is set, each directory is scanned
Xand all files found are put in a hash table.
X.TP
X.B POSTEDIT
XThis string is output whenever the line editor exits.
XIt usually contains termcap strings to reset the terminal.
X.TP
X.B PROMPT
XThe primary prompt string, printed before a command is read;
Xthe default is "%m%# ".
XThe following escape sequences are recognized:
X.PD


X.PP
X.PD 0
X.RS
X.TP

X.B %d
X.TP
X.B %/
XPresent working directory ($PWD).
X.TP
X.B %~
X$PWD.
XIf it has a named directory as its prefix, that part is replaced
Xby a ~ followed by the name of the directory.
XIf it starts with $HOME, that part is
Xreplaced by a ~.
X.TP
X.B %c
X.TP
X.B %.
X.TP
X.B %C
XTrailing component of $PWD.
XMay be followed by a digit to get more than one component.
XUnless \fB%C\fP is used, tilde expansion is performed first.
X.TP
X.B !
X.TP
X.B %h
X.TP
X.B %!
XCurrent history event number
X.TP
X.B %M
XThe full machine hostname.
X.TP
X.B %m
XThe hostname up to the first '.'.
XMay be followed by a digit to specify
Xhow many components of the hostname are desired.
X.TP
X.B %S (%s)
XStart (stop) standout mode.
X.TP
X.B %U (%u)
XStart (stop) underline mode.
X.TP
X.B %B (%b)
XStart (stop) boldface mode.
X.TP
X.B %t
X.TP
X.B %@
XCurrent time of day, in 12-hour, am/pm format.
X.TP
X.B %T
XCurrent time of day, in 24-hour format.
X.TP
X.B %*
XCurrent time of day in 24-hour format, with seconds.
X.TP
X.B %n
X\fB$USERNAME\fP.
X.TP
X.B %w
XThe date in day\-dd format.
X.TP
X.B %W
XThe date in mm/dd/yy format.
X.TP
X.B %D
XThe date in yy\-mm\-dd format.
X.TP
X.B %D{\fIstring\fP}
X\fIstring\fP is formatted using the \fBstrftime\fP function.
XSee \fBstrftime(3)\fP for more details, if your system has it.
X.TP
X.B %l
XThe line (tty) the user is logged in on.
X.TP
X.B %?
XThe return code of the last command executed just before the prompt.
X.TP
X.B %#
XA '#' if the shell is running as root, a '%' if not.
X.TP
X\fB%{\fP...\fB%}\fP
XInclude a string as a literal escape sequence.
XThe string within the braces should not change the cursor
Xposition.
X.RE
X.PD
X.PP
X.PD 0
X.TP
X.B PROMPT2
XThe secondary prompt, printed when the shell needs more information
Xto complete a command.
XRecognizes the same escape sequences as \fB$PROMPT\fP.
XThe default is "> ".
X.TP
X.B PROMPT3
XSelection prompt used within a \fBselect\fP loop.
XRecognizes the same escape sequences as \fB$PROMPT\fP.
XThe default is "?# ".
X.TP
X.B PROMPT4
XThe execution trace prompt. Default is "+ ".
X.TP
X.B PS1
X.TP
X.B PS2
X.TP
X.B PS3
X.TP
X.B PS4
XSame as \fBPROMPT\fP, \fBPROMPT2\fP, \fBPROMPT3\fP, and \fBPROMPT4\fP,
Xrespectively.
X.TP
X.B prompt
XSame as \fBPROMPT\fP.
X.TP
X.B READNULLCMD
XThe command name to assume if a single input redirection
Xis specified with no command. Defaults to \fBmore\fP.
X.TP
X.B REPORTTIME
XIf nonzero, commands whose combined user and system execution times
X(measured in seconds) are greater than this value have timing
Xstatistics printed for them.
X.TP
X.B RPROMPT
X.TP
X.B RPS1
XThis prompt is displayed on the right-hand side of the screen
Xwhen the primary prompt is being displayed on the left.
XThis does not work if the \fBSINGLELINEZLE\fP option is set.
XRecognizes the same escape sequences as \fBPROMPT\fP,
Xexcept that termcap sequences like \fB%s\fP, etc. will not work.
X.TP
X.B SAVEHIST
XThe maximum number of history events to save in the history file.
X.TP
X.B SPROMPT
XThe prompt used for spelling correction. The sequence
X\fB%R\fP expands to the string which presumably needs spelling
Xcorrection, and \fB%r\fP expands to the proposed correction.
XAll other \fBPROMPT\fP escapes are also allowed.
X.TP
X.B STTY
XIf this parameter is set in a command's environment, the shell
Xruns the \fBstty\fP command with the value of this parameter as arguments
Xin order to set up the terminal before executing the command.
X.TP
X.B TIMEFMT
XThe format of process time reports with the \fBtime\fP keyword.
XThe default is "%E real %U user %S system %P".
XRecognizes the following escape sequences:
X.PD


X.PP
X.PD 0
X.RS
X.TP

X.B %U
XCPU seconds spent in user mode.
X.TP
X.B %S
XCPU seconds spent in kernel mode.
X.TP
X.B %E
XElapsed time in seconds.
X.TP
X.B %P
XThe CPU percentage, computed as (%U+%S)/%E.
X.TP
X.B %W
XNumber of times the process was swapped.
X.TP
X.B %X
XThe average amount in (shared) text space used in Kbytes.
X.TP
X.B %D
XThe average amount in (unshared) data/stack space used in Kbytes.
X.TP
X.B %K
XThe total space used (%X+%D) in Kbytes.
X.TP
X.B %M
XThe maximum memory the process had in use at any time in Kbytes.
X.TP
X.B %F
XThe number of major page faults (page needed to be brought from disk).
X.TP
X.B %R
XThe number of minor page faults.
X.TP
X.B %I
XThe number of input operations.
X.TP
X.B %O
XThe number of output operations.
X.TP
X.B %r
XThe number of socket messages received.
X.TP
X.B %s
XThe number of socket messages sent.
X.TP
X.B %k
XThe number of signals received.
X.TP
X.B %w
XNumber of voluntary context switches (waits).
X.TP
X.B %c
XNumber of involuntary context switches.
X.TP
X.B %J
XThe name of this job.
X.RE
X.PD
X.PP
X.PD 0
X.TP
X.B TMOUT
XIf this parameter is nonzero, the shell will terminate if a command is not
Xentered within the specified number of seconds after issuing
Xa prompt.
X.TP
X.B TMPPREFIX
XA pathname prefix which the shell will use for all temporary files.
X.TP
X.B varcmds
XAn write-only array
Xof command names which take parameter names
Xas arguments, and which therefore should allow parameter
Xcompletion.
X.TP
X.B watch (WATCH)
XAn array (colon-separated list) of login/logout events to report.
XIf it contains the single word "all", then all login/logout events
Xare reported.
XAn entry in this list may consist of a username,
Xan `@' followed by a remote hostname,
Xand a `%' followed by a line (tty).
XAny or all of these components may be present in an entry;
Xif a login/logout event matches all of them,
Xit is reported.
X.TP
X.B WATCHFMT
XThe format of login/logout reports if the \fBwatch\fP parameter is set.
XDefault is "%n has %a %l from %m."
XRecognizes the following escape sequences:
X.PD


X.PP
X.PD 0
X.RS
X.TP

X.B %n
XThe name of the user that logged in/out.
X.TP
X.B %a
XThe observed action, i.e. "logged on" or "logged off".
X.TP
X.B %l
XThe line (tty) the user is logged in on.
X.TP
X.B %M
XThe full hostname of the remote host.
X.TP
X.B %m
XThe hostname up to the first ".". If only the
Xip address is available or the utmp field contains
Xthe name of an X-windows display, the whole name is printed.
X.TP
X.B %S (%s)
XStart (stop) standout mode.
X.TP
X.B %U (%u)
XStart (stop) underline mode.
X.TP
X.B %B (%b)
XStart (stop) boldface mode.
X.TP
X.B %t
X.TP
X.B %@
XThe time, in 12-hour, am/pm format.
X.TP
X.B %T
XThe time, in 24-hour format.
X.TP
X.B %w
XThe date in day\-dd format.
X.TP
X.B %W
XThe date in mm/dd/yy format.
X.TP
X.B %D
XThe date in yy\-mm\-dd format.
X.RE
X.PD
X.PP
X.PD 0
X.TP
X.B WORDCHARS
XA list of nonalphanumeric characters considered part of a word
Xby the line editor.
X.TP
X.B ZDOTDIR
XThe directory to search for shell startup files (.zshrc, etc),
Xif not \fB$HOME\fP.
X.PD
X.RE
X.PP
X.SH OPTIONS
XThe following options may be set upon invocation of the shell,
Xor with the \fBset\fP or \fBsetopt\fP builtins:
X.RS
X.PD 0
X.TP
X\fBALLEXPORT\fP (\-\fBa\fP)
XAll parameters subsequently defined are automatically exported.
X.TP
X\fBAUTO_CD\fP (\-\fBJ\fP)
XIf a command is not in the hash table, and there exists an
Xexecutable directory by that name, perform the \fBcd\fP
Xcommand to that directory.
X.TP
X\fBAUTOLIST\fP (\-\fB9\fP)
XAutomatically list choices on an ambiguous completion.
X.TP
X\fBAUTOMENU\fP
XAutomatically use menu completion if the \fPTAB\fP
Xkey is pressed repeatedly.
X.TP
X\fBAUTO_PUSHD\fP (\-\fBN\fP)
XMake \fBcd\fP act like \fBpushd\fP.
X.TP
X\fBAUTO_RESUME\fP (\-\fBW\fP)
XTreat single word simple commands without redirection
Xas candidates for resumption of an existing job.
X.TP
X\fBBGNICE\fP (\-\fB6\fP)
XRun all background jobs at a lower priority. This option
Xis set by default.
X.TP
X\fBBRACECCL\fP
XAllow brace expansions of the form \fB{a-zA-Z}\fP, etc.
X.TP
X\fBCDABLEVARS\fP (\-\fBT\fP)
XIf the argument to a \fBcd\fP command is not a directory,
Xbut a parameter exists by the same name whose value
Xbegins with a /, try to change to the directory
Xspecified by the parameter's value.
X.TP
X\fBCHASELINKS\fP (\-\fBw\fP)
XResolve symbolic links to their true values.
X.TP
X\fBCORRECT\fP (\-\fB0\fP)
XTry to correct the spelling of commands.
X.TP
X\fBCORRECT_ALL\fP (\-\fBO\fP)
XTry to correct the spelling of all arguments in a line.
X.TP
X\fBCSH_JUNKIE_LOOPS\fP
XAllow loop bodies to take the form
X"\fIlist\fP; \fBend\fP" instead of
X"\fBdo\fP \fIlist\fP; \fBdone\fP".
X.TP
X\fBCSH_JUNKIE_QUOTES\fP
XComplain if a quoted expression runs off the end of a line;
Xprevent quoted expressions from containing unescaped newlines.
X.TP
X\fBCSH_NULL_GLOB\fP
XIf a pattern for filename generation has no matches,
Xdelete the pattern from the argument list;
Xdo not report an error unless all the patterns
Xin a command have no matches.
XOverrides \fBNULLGLOB\fP.
X.TP
X\fBERREXIT\fP (\-\fBe\fP)
XIf a command has a non-zero exit status, execute the \fBERR\fP
Xtrap, if set, and exit.
X.TP
X\fBEXTENDED_GLOB\fP
XTreat the # and ^ characters as part of patterns for filename
Xgeneration, etc.
X.TP
X\fBGLOB_COMPLETE\fP
XLike \fBMENU_COMPLETE\fP, except that the current word
Xis expanded using normal shell expansion instead of completion.
XIf no matches are found, a * is added to the end of the word, and expansion
Xis attempted again.
X.TP
X\fBGLOB_DOTS\fP (\-\fB4\fP)
XDo not require a leading . in a filename to be matched explicitly.
X.TP
X\fBHASH_CMDS\fP
XPlace the location of each command in the hash table the first
Xtime it is executed. If this option is unset, no path hashing
Xwill be done at all.
X.TP
X\fBHASH_DIRS\fP
XWhenever a command is executed, hash the directory containing it,
Xas well as all directories that occur earlier in the path.
XHas no effect if \fBHASH_CMDS\fP is unset.
X.TP
X\fBHASH_LIST_ALL\fP
XWhenever a command completion is attempted, make sure the entire
Xcommand path is hashed first. This makes the first completion slower.
X.TP
X\fBHIST_IGNORE_DUPS\fP (\-\fBh\fP)
XDo not enter command lines into the history list
Xif they are duplicates of the previous event.
X.TP
X\fBHIST_IGNORE_SPACE\fP (\-\fBg\fP)
XDo not enter command lines into the history list
Xif they begin with a blank.
X.TP
X\fBHISTLIT\fP (\-\fBj\fP)
XUse literal (unparsed) versions of the history lines
Xin the editor.
X.TP
X\fBHIST_NO_STORE\fP
XRemove the \fBhistory\fP (\fBfc\fP \-\fBl\fP) command from
Xthe history when invoked.
X.TP
X\fBHIST_VERIFY\fP
XWhenever the user enters a line with history substitution,
Xdon't execute the line directly; instead, perform
Xhistory substitution and reload the line into the editing buffer.
X.TP
X\fBIGNORE_BRACES\fP (\-\fBI\fP)
XDo not perform brace expansion.
X.TP
X\fBIGNOREEOF\fP (\-\fB7\fP)
XDo not exit on end-of-file. Require the use
Xof \fBexit\fP or \fBlogout\fP instead.
X.TP
X\fBINTERACTIVE\fP (\-\fBi\fP)
XThis is an interactive shell.
X.TP
X\fBINTERACTIVE_COMMENTS\fP (\-\fBk\fP)
XAllow comments even in interactive shells.
X.TP
X\fBKSH_OPTION_PRINT\fP
XAlters the way options settings are printed.
X.TP
X\fBLIST_TYPES\fP (\-\fBX\fP)
XWhen listing files that are possible completions, show the
Xtype of each file with a trailing identifying mark.
X.TP
X\fBLOGIN\fP (\-\fBl\fP)
XThis is a login shell.
X.TP
X\fBLONG_LIST_JOBS\fP (\-\fBR\fP)
XList jobs in the long format by default.
X.TP
X\fBMAIL_WARNING\fP (\-\fBU\fP)
XPrint a warning message if a mail file has been
Xaccessed since the shell last checked.
X.TP
X\fBMARKDIRS\fP (\-\fB8\fP)
XAppend a trailing / to all directory
Xnames resulting from filename generation (globbing).
X.TP
X\fBMENU_COMPLETE\fP (\-\fBY\fP)
XOn an ambiguous completion, instead of listing possibilities,
Xinsert the first match. Then when completion is requested
Xagain, remove the first match and insert the second match, etc.
XWhen there are no more matches, go back to the first one again.
X\fBreverse-menu-complete\fP may be used to loop through the list
Xin the other direction.
X.TP
X\fBMENU_COMPLETE_BEEP\fP
XBeep on an ambiguous menu completion.
X.TP
X\fBMONITOR\fP (\-\fBm\fP)
XAllow job control. Set by default in interactive shells.
X.TP
X\fBNO_BAD_PATTERN\fP (\-\fB2\fP)
XIf a pattern for filename generation is badly formed,
Xleave it unchanged in the argument list instead of
Xprinting an error.
X.TP
X\fBNO_BANG_HIST\fP (\-\fBK\fP)
XDo not perform textual history substitution. Do not
Xtreat the ! character specially.
X.TP
X\fBNOBEEP\fP (\-\fBB\fP)
XDo not beep.
X.TP
X\fBNO_CLOBBER\fP (\-\fB1\fP)
XPrevents \fB>\fP redirection from truncating existing files.
X\fB>!\fP may be used to truncate a file instead.
XAlso prevents \fB>>\fP from creating files.
X\fB>>!\fP may be used instead.
X.TP
X\fBNO_EQUALS\fP
XDon't perform \fB=\fP filename substitution.
X.TP
X\fBNOEXEC\fP (\-\fBn\fP)
XRead commands and check them for syntax errors, but do not execute them.
X.TP
X\fBNOGLOB\fP (\-\fBF\fP)
XDisable filename generation.
X.TP
X\fBNO_HIST_BEEP\fP
XDon't beep when an attempt is made to access a history entry which
Xisn't there.
X.TP
X\fBNOHUP\fP
XDon't send the \fBHUP\fP signal to running jobs when the
Xshell exits.
X.TP
X\fBNO_LIST_BEEP\fP
XDon't beep on an ambiguous completion.
X.TP
X\fBNO_NOMATCH\fP (\-\fB3\fP)
XIf a pattern for filename generation has no matches,
Xleave it unchanged in the argument list instead of
Xprinting an error.
X.TP
X\fBNO_PROMPT_CR\fP (\-\fBV\fP)
XDon't print a carriage return just before printing
Xa prompt in the line editor.
X.TP
X\fBNO_RCS\fP (\-\fBf\fP)
XDo not source the .zshenv, .zshrc, .zlogin, .zlogout, or .zprofile files.
X.TP
X\fBNO_SHORT_LOOPS\fP
XDisallow the short forms of \fBfor\fP, \fBselect\fP,
X\fBif\fP, and \fBfunction\fP constructs.
X.TP
X\fBNOTIFY\fP (\-\fB5\fP)
XReport the status of background jobs immediately, rather than
Xwaiting until just before printing a prompt.
X.TP
X\fBNOUNSET\fP (\-\fBu\fP)
XTreat unset parameters as an error when substituting.
X.TP
X\fBNULLGLOB\fP (\-\fBG\fP)
XIf a pattern for filename generation has no matches,
Xdelete the pattern from the argument list instead
Xof reporting an error. Overrides \fBNO_NOMATCH\fP.
X.TP
X\fBNUMERICGLOBSORT\fP
XIf numeric filenames are matched by a filename generation pattern,
Xsort the filenames numerically rather than lexicographically.
X.TP
X\fBOVERSTRIKE\fP
XStart up the line editor in overstrike mode.
X.TP
X\fBPATH_DIRS\fP (\-\fBQ\fP)
XPerform a path search even on command names with slashes in them.
XThus if "/usr/local/bin" is in the user's path, and he types
X"X11/xinit", the command "/usr/local/bin/X11/xinit" will be executed
X(assuming it exists).
X.TP
X\fBPRINT_EXIT_VALUE\fP (\-\fBC\fP)
XPrint the exit value of programs with non-zero exit status.
X.TP
X\fBPUSHD_IGNORE_DUPS\fP
XDon't push multiple copies of the same directory onto the directory stack.
X.TP
X\fBPUSHD_MINUS\fP
XSee \fBpopd\fP below.
X.TP
X\fBPUSHD_SILENT\fP (\-\fBE\fP)
XDo not print the directory stack after \fBpushd\fP
Xor \fBpopd\fP.
X.TP
X\fBPUSHD_TO_HOME\fP (\-\fBD\fP)
XHave \fBpushd\fP with no arguments act like
X\fBpushd\fP $HOME.
X.TP
X\fBRC_EXPAND_PARAM\fP (\-\fBP\fP)
XSee \fIParameter Expansion\fP.
X.TP
X\fBRC_QUOTES\fP
XAllow the character sequence \fB''\fP to signify a single quote
Xwithin singly quoted strings.
X.TP
X\fBRECEXACT\fP (\-\fBS\fP)
XIn completion, recognize exact matches even
Xif they are ambiguous.
X.TP
X\fBRMSTARSILENT\fP (\-\fBH\fP)
XDo not query the user before executing "rm *" or "rm path/*".
X.TP
X\fBSHINSTDIN\fP (\-\fBs\fP)
XRead commands from the standard input.
X.TP
X\fBSH_WORD_SPLIT\fP (\-\fBy\fP)
XSee \fIParameter Expansion\fP.
X.TP
X\fBSINGLE_LINE_ZLE\fP (\-\fBM\fP)
XUse single-line command line editing instead of multi-line.
X.TP
X\fBSUN_KEYBOARD_HACK\fP (\-\fBL\fP)
XIf a line ends with a backquote, and there are an odd number
Xof backquotes on the line, ignore the trailing backquote.
XThis is useful on some keyboards where the return key is
Xtoo small, and the backquote key lies annoyingly close to it.
X.TP
X\fBVERBOSE\fP (\-\fBv\fP)
XPrint shell input lines as they are read.
X.TP
X\fBXTRACE\fP (\-\fBx\fP)
XPrint commands and their arguments as they are executed.
X.TP
X\fBZLE\fP (\-\fBZ\fP)
XUse the zsh line editor.
X.RE
X.PD
X.SH "SHELL BUILTIN COMMANDS"
X.TP
X\fB\&.\fP \fIfile\fP [ \fIarg\fP ... ]
XRead and execute commands from \fIfile\fP in the current shell
Xenvironment.
XIf \fIfile\fP does not contain a slash, the shell
Xlooks in the components of \fBpath\fP to find the directory
Xcontaining \fIfile\fP.
XIf any arguments \fIarg\fP are given,
Xthey become the positional parameters; the old positional
Xparameters are restored when the \fIfile\fP is done executing.
XThe exit status is the exit status of the last command executed.
X.TP
X\fB:\fP [ \fIarg\fP ... ]
XThis command only expands parameters. A zero exit code is returned.
X.TP
X\fBalias\fP [ \-\fBg\fP ] [ \fIname\fP[=\fIvalue\fP] ] ...
XWith no arguments, print the list of aliases in the form
X\fIname\fP=\fBvalue\fP on the standard output.
XFor each \fIname\fP with a corresponding \fIvalue\fP, define an alias
Xwith that value.
XA trailing space in \fIvalue\fP causes the next
Xword to be checked for alias substitution.
XIf the \-\fBg\fP flag is present, define a global alias; global aliases
Xare expanded even if they do not occur in command position.
XFor each \fIname\fP with no \fIvalue\fP, print the value of \fIname\fP,
Xif any.
XThe exit status is nonzero if a \fIname\fP (with no \fIvalue\fP)
Xgiven for which no alias has been defined.
X.TP
X\fBautoload\fP [ \fIname\fP ... ]
XFor each of the \fIname\fPs (which are names of functions),
Xcreate a function marked undefined.
XThe \fBfpath\fP variable will be searched to find the
Xactual function definition when the function is first referenced.
X.TP
X.PD 0
X\fBbg\fP [ \fIjob\fP ... ]
X.TP
X\fIjob\fP ... \fB&\fP
X.PD
XPut each specified \fIjob\fP in the background,
Xor the current job if none is specified.
X.TP
X.PD 0
X\fBbindkey\fP \-\fBmevd
X.TP
X\fBbindkey\fP \-\fBr\fP \fIin-string\fP ...
X.TP
X\fBbindkey\fP [ \-\fBa\fP ] \fIin-string\fP [ \fIcommand\fP ] ...
X.TP
X\fBbindkey\fP \-\fBs\fP [ \-\fBa\fP ] \fIin-string\fP \fIout-string\fP ...
X.PD
XIf one of the \-\fBe\fP, \-\fBv\fP, or \-\fBd\fP options is given,
Xreset the keymaps for emacs mode, vi mode, or the default mode,
Xrespectively; if the \-\fBm\fP option is also given,
Xallow the use of a meta key.
XIf the \-\fBr\fP option is given, remove any binding for each \fIin-string\fP.
XIf the \-\fBs\fP option is not specified, bind each \fIin-string\fP
Xto a specified \fIcommand\fP. If no \fIcommand\fP is specified,
Xprint the binding of \fIin-string\fP if it is bound, or return
Xa nonzero exit code if it is not bound.
XIf the \-\fBs\fP option is specified, bind each \fIin-string\fP
Xto each specified \fIout-string\fP. When \fIin-string\fP is typed,
X\fIout-string\fP will be pushed back and treated as input to the
Xline editor.
XIf the \-\fBa\fP option is specified, bind the \fIin-string\fPs in the
Xalternative keymap instead of the standard one. The alternative
Xkeymap is used in vi command mode.
X.RS
X.PP
XFor either \fIin-string\fP or \fIout-string\fP, control characters
Xmay be specified in the form \fB^X\fP, and the backslash may
Xbe used to introduce one of the following escape sequences:
X.RS
X.PD 0
X.TP
X.B \ea
Xbell character
X.TP
X.B \en
Xlinefeed (newline)
X.TP
X.B \eb
Xbackspace
X.TP
X.B \et
Xhorizontal tab
X.TP
X.B \ev
Xvertical tab
X.TP
X.B \ef
Xform feed
X.TP
X.B \er
Xcarriage return
X.TP
X.B \ee
Xescape
X.TP
X.B \ennn
Xcharacter code in octal
X.TP
X.B \eM\-xxx
Xcharacter or escape sequence with meta bit set
X.PD
X.PP
X.RE
XIn all other cases, \e escapes the following character. Delete is
Xwritten as `\fB^?\fP'.
X.RE
X.TP
X\fBbreak\fP [ \fIn\fP ]
XExit from an enclosing \fBfor\fP, \fBwhile\fP,
X\fBuntil\fP, \fBselect\fP, or \fBrepeat\fP loop. If \fIn\fP
Xis specified, then break \fIn\fP levels instead of just one.
X.TP
X\fBbuiltin\fP \fIname\fP [ \fIargs\fP ] ...
XExecutes the builtin \fIname\fP, with the given \fIargs\fP.
X.TP
X\fBbye\fP
XSame as \fBexit\fP.
X.TP
X.PD 0
X\fBcd\fP [ \fIarg\fP ]
X.TP
X\fBcd\fP \fIold\fP \fInew\fP
X.TP
X\fBcd\fP \(+-\fBn\fP
X.PD
XChange the current directory. In the first form, change the
Xcurrent directory to \fIarg\fP, or to the value of \fBHOME\fP if
X\fIarg\fP is not specified. If \fIarg\fP is \-, change to the
Xvalue of \fBOLDPWD\fP, the previous directory.
XIf a directory named \fIarg\fP is not found in the current directory
Xand \fIarg\fP does not begin with a slash,
Xsearch each component of the shell parameter \fBcdpath\fP.
XIf the option \fBCDABLEVARS\fP is set, and a parameter named \fIarg\fP
Xexists whose value begins with a slash, treat its value as
Xthe directory.
X.RS
X.PP
XThe second form of \fBcd\fP substitutes the string \fInew\fP
Xfor the string \fIold\fP in the name of the current directory,
Xand tries to change to this new directory.
X.PP
XThe third form of \fBcd\fP is equivalent to \fBpopd\fP.
X.RE
X.TP
X\fBchdir\fP
XSame as \fBcd\fP.
X.TP
X\fBcompctl\fP [ \-\fBcfhovbCD\fP ] [ \-\fBk\fP \fIname\fP ] [ \fIarg\fP ... ]
XControl the editor's completion behavior when one of \fIarg\fP is the current
Xcommand. With the \-\fBD\fP flag, control default completion behavior
Xfor commands not assigned any special behavior; with \-\fBC\fP, control
Xcompletion when there is no current command. The remaining options
Xspecify the type of command arguments to look for during completion.
XFor example, \fBcompctl\fP \-\fBhf\fP \fBrlogin\fP is equivalent
Xto \fBhostcmds=(rlogin)\fP.
X.RS
X.PD 0
X.TP
X\-\fBc\fP
XExpect command names.
X.TP
X\-\fBf\fP
XExpect filenames and filesystem paths.
X.TP
X\-\fBh\fP
XExpect hostnames taken from the \fB$hosts\fP variable.
X.TP
X\-\fBo\fP
XExpect option names.
X.TP
X\-\fBv\fP
XExpect variable names.
X.TP
X\-\fBb\fP
XExpect key binding names.
X.TP
X\-\fBk\fP \fIname\fP
XExpect names taken from the elements of \fB$name\fP.
X.PD
X.RE
X.TP
X\fBcontinue\fP [ \fInum\fP ]
XResume the next iteration of the enclosing
X\fBfor\fP, \fBwhile\fP, \fBuntil\fP, \fBselect\fP, or
X\fBrepeat\fP loop. If \fIn\fP is specified, break out of
X\fIn\fP \- 1 loops and resume at the \fIn\fPth enclosing loop.
X.TP
X\fBdeclare\fP [ \fIarg\fP ... ]
XSame as \fBtypeset\fP.
X.TP
X\fBdirs\fP [ \-\fBv\fP ] [ \fIarg\fP ... ]
XWith no arguments, print the contents of the directory stack.
XIf the \-\fBv\fP option is given, number the directories
Xin the stack when printing.
XDirectories are added to this stack with the \fBpushd\fP command,
Xand removed with the \fBcd\fP or \fBpopd\fP commands.
XIf arguments are specified, load them onto the directory stack,
Xreplacing anything that was there, and push the current directory
Xonto the stack.
X.TP
X\fBdisable\fP \fIarg\fP ...
XDisable the builtin \fIarg\fP temporarily. This allows you to use
Xan external command with the same name as a shell builtin.
XActually the same as \fBunhash\fP.
XBuiltins can be enabled with the \fBenable\fP command.
X.TP
X\fBdisown\fP \fIjob\fP ...
XRemove the specified jobs from the job table; the shell will
Xno longer report their status, and will not complain if you
Xtry to exit an interactive shell with them running or stopped.
X.TP
X\fBecho\fP [ \-\fBn\fP ] [ \fIarg\fP ... ]
XWrite each \fIarg\fP on the standard output, with a space separating
Xeach one.
XIf the \-\fBn\fP flag is not present, print a newline at the end.
X\fBecho\fP recognizes the following escape sequences:
X.RS
X.PD 0
X.TP
X.B \eb
Xbackspace
X.TP
X.B \ec
Xdon't print an ending newline
X.TP
X.B \ee
Xescape
X.TP
X.B \ef
Xform feed
X.TP
X.B \en
Xnewline
X.TP
X.B \er
Xcarriage return
X.TP
X.B \et
Xhorizontal tab
X.TP
X.B \ev
Xvertical tab
X.TP
X.B \e\e
Xbackslash
X.TP
X.B \exxx
Xcharacter code in octal
X.PD
X.RE
X.TP
X\fBechotc\fP \fIcap\fP [ \fIarg\fP ... ]
XOutput the termcap string corresponding to the capability
X\fIcap\fP, with optional arguments.
X.TP
X\fBenable\fP \fIarg\fP ...
XEnable the specified builtin commands, presumably disabled earlier
Xwith \fBdisable\fP.
X.TP
X\fBeval\fP [ \fIarg\fP ... ]
XRead the arguments as input to the shell and execute the resulting
Xcommand(s) in the current shell process.
X.TP
X\fBexit\fP [ \fIn\fP ]
XExit the shell with the exit code specified by \fIn\fP; if none
Xis specified, use the exit code from the last command executed.
XAn EOF condition will also cause the shell to exit, unless
Xthe \fBIGNOREEOF\fP option is set.
X.TP
X\fBexport\fP [ \fIname\fP[=\fIvalue\fP] ... ]
XThe specified \fIname\fPs are marked for automatic export
Xto the environment of subsequently executed commands.
X.TP
X\fBfalse\fP
XDo nothing and return an exit code of 1.
X.TP
X.PD 0
X\fBfc\fP [ \-\fBe\fP \fIename\fP ] [ \-\fBnlrdD\fP ] [ \fIold\fP=\fInew\fP ... ] [ \fIfirst\fP [ \fIlast\fP ] ]
X.TP
X\fBfc\fP \-\fBARW\fP [ \fIfilename\fP ]
X.PD
XSelect a range of commands from \fIfirst\fP to \fIlast\fP from the
Xhistory list.
XThe arguments \fIfirst\fP and \fIlast\fP may be specified as a
Xnumber or as a string. A negative number is used as an offset
Xto the current history event number.
XA string specifies the most recent event
Xbeginning with the given string.
XAll substitutions \fIold\fP=\fInew\fP, if any, are then performed
SHAR_EOF
true || echo 'restore of zsh2.2/man/man1/zsh.1 failed'
fi
echo 'End of zsh2.2 part 4'
echo 'File zsh2.2/man/man1/zsh.1 is continued in part 5'
echo 5 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 11:58:55 AM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 101
Archive-name: zsh2.2/part05

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.05 (part 5 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/man/man1/zsh.1 continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 5; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping zsh2.2/man/man1/zsh.1'
else
echo 'x - continuing file zsh2.2/man/man1/zsh.1'
sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/man/man1/zsh.1' &&

Xon the commands.
XIf the \-\fBl\fP flag is given, the resulting commands are listed on
Xstandard output.
XOtherwise the editor program \fIename\fP is invoked on a file containing
Xthese history events. If \fIename\fP is not given, the value
Xof the parameter \fBFCEDIT\fP is used. If \fIename\fP is "\-",
Xno editor is invoked. When editing is complete, the edited
Xcommand(s) is executed.
XIf \fIfirst\fP is not specified, it will be set to \-1 (the most recent
Xevent), or to -16 if the \-\fBl\fP flag is given.
XIf \fIlast\fP is not specified, it will be set to \fIfirst\fP,
Xor to \-1 if the \-\fBl\fP flag is given.
XThe flag \-\fBr\fP reverses the order of the commands and the
Xflag \-\fBn\fP suppresses command numbers when listing.
XAlso when listing, \-\fBd\fP prints datestamps for each command,
Xand \-\fBD\fP prints real execution times.
X.RS
X.PP
X\fBfc\fP \-\fBR\fP reads the history from the given file,
X\fBfc\fP \-\fBW\fP writes the history out to the given file,
Xand \fBfc\fP \-\fBA\fP appends the history out to the given file.
X.RE
X.TP
X.PD 0
X\fBfg\fP [ \fIjob\fP ... ]


X.TP
X\fIjob\fP ...

X.PD
XBring the specified \fIjob\fPs to the foreground.
XIf no \fIjob\fP is specified, use the current job.
X.TP
X\fBfunctions\fP [ \(+-\fBtu\fP ] [ \fIname\fP ... ]
XEquivalent to \fBtypeset\fP \-\fBf\fP.
X.TP
X\fBgetln\fP \fIname\fP ...
XRead the top value from the buffer stack and put it in
Xthe shell parameter \fIname\fP. Equivalent to
X\fBread\fP \-\fBzr\fP.
X.TP
X\fBgetopts\fP \fIoptstring\fP \fIname\fP [ \fIarg\fP ... ]
XChecks \fBarg\fP for legal options. If \fIarg\fP is omitted,
Xuse the positional parameters. A valid option argument
Xbegins with a + or a \-. An argument not beginning with
Xa + or a \-, or the argument \-\-, ends the options.
X\fIoptstring\fP contains the letters that \fBgetopts\fP
Xrecognizes. If a letter is followed by a `:', that option
Xis expected to have an argument. The options can be
Xseparated from the argument by blanks.
X.RS
X.PP
XEach time it is invoked, \fBgetopts\fP places the option letter it finds
Xin the shell parameter \fIname\fP, prepended with a + when
X\fIarg\fP begins with a +. The index of the next \fIarg\fP
Xis stored in \fBOPTIND\fP. The option argument, if any,
Xis stored in \fBOPTARG\fP.
X.PP
XA leading : in \fIoptstring\fP causes \fBgetopts\fP to store the
Xletter of the invalid option in \fBOPTARG\fP, and to set \fIname\fP
Xto `?' for an unknown option and to `:' when a required option
Xis missing. Otherwise, \fBgetopts\fP prints an error
Xmessage. The exit status is nonzero when there are no more options.
X.RE
X.TP
X\fBhash\fP \fIname\fP \fIpath\fP
XPuts \fIname\fP in the command hash table, associating it with
Xthe pathname \fIpath\fP. Whenever \fIname\fP is used as a command
Xargument, the shell will try to execute the file given by \fIpath\fP.
X.TP
X\fBhistory\fP [ \-\fBnr\fP ] [ \fIfirst\fP [ \fIlast\fP ] ]
XSame as \fBfc\fP \-\fBl\fP.
X.TP
X\fBinteger\fP
XSame as \fBtypeset\fP \-\fBi\fP.
X.TP
X\fBjobs\fP [ \-\fBlp\fP ] [ \fIjob\fP ... ]
XLists information about each given job, or all jobs
Xif \fIjob\fP is omitted. The \-\fBl\fP flag lists process
Xids, and the \-\fBp\fP flag lists process groups.
X.TP
X.PD 0
X\fBkill\fP [ \-\fIsig\fP ] \fIjob\fP ...
X.TP
X\fBkill\fP \-\fBl\fP
X.PD
XSends either SIGTERM or the specified signal to the given
Xjobs or processes.
XSignals are given by number or by names
X(with the prefix "SIG" removed).
XIf the signal being sent is not KILL or CONT, then the job
Xwill be sent a CONT signal if it is stopped.
XThe argument \fIjob\fP can be the process id of a job
Xnot in the job list.
XIn the second form, \fBkill\fP \-\fBl\fP, the signal names
Xare listed.
X.TP
X\fBlet\fP \fIarg\fP ...
XEvaluate each \fIarg\fP as an arithmetic expression.
XSee \fBARITHMETIC EVALUATION\fP above for a description
Xof arithmetic expressions. The exit status is 0 if the
Xvalue of the last expression is nonzero, and 1 otherwise.
X.TP
X.PD 0
X\fBlimit\fP [ \-\fBh\fP ] [ \fIresource\fP [ \fIlimit\fP ] ] ...
X.TP
X\fBlimit\fP \-\fBs\fP
X.PD
XLimit the resource consumption of children of the current shell.
XIf \fIlimit\fP is not specified, print the current limit placed
Xon \fIresource\fP; otherwise
Xset the limit to the specified value. If the \-\fBh\fP flag
Xis given, use hard limits instead of soft limits.
XIf no \fIresource\fP is given, print all limits.
X.RS
X.PP
X\fIresource\fP is one of:
X.PP
X.PD 0
X.TP
X.B cputime
XMaximum CPU seconds per process.
X.TP
X.B filesize
XLargest single file allowed.
X.TP
X.B datasize
XMaximum data size (including stack) for each process.
X.TP
X.B stacksize
XMaximum stack size for each process.
X.TP
X.B coredumpsize
XMaximum size of a core dump.
X.TP
X.B resident
XMaximum resident set size.
X.TP
X.B descriptors
XMaximum value for a file descriptor.
X.PD
X.PP
X\fIlimit\fP is a number, with an optional scaling factor, as follows:
X.PP
X.PD 0
X.TP
X\fIn\fPh
Xhours.
X.TP
X\fIn\fPk
Xkilobytes.
XThis is the default for all but cputime.
X.TP
X\fIn\fPm
Xmegabytes or minutes.
X.TP
X\fImm\fP:\fBss\fP
Xminutes and seconds.
X.PD
X.RE
X.TP
X\fBlocal\fP


XSame as \fBtypeset\fP.
X.TP

X\fBlog\fP
XList all users currently logged in who are affected by
Xthe current setting of the \fBwatch\fP parameter.
X.TP
X\fBlogout\fP
XExit the shell, if this is a login shell.
X.TP
X\fBpopd\fP [ \(+-\fIn\fP ]
XRemoves entries from the directory stack. With no arguments,
Xremoves the top directory from the stack, and performs a \fBcd\fP
Xto the new top directory. With an argument of the form +\fIn\fP,
Xremove the \fIn\fPth entry counting from the left of the list
Xshown by the \fBdirs\fP command, starting with zero, and change
Xto that directory. With an argument of the form \-\fIn\fP,
Xremove the \fIn\fPth entry counting from the right.
XIf the \fBPUSHD_MINUS\fP option is set, the meanings of +
Xand \- in this context are swapped.
X.TP
X\fBprint\fP [ \-\fBRnrslzpNDP\fP ] [ \-\fBu\fP\fIn\fP ] [ \fIarg\fP ... ]
XWith no flags or with flag \-, the arguments are printed on
Xthe standard output as described by \fBecho\fP.
X.RS
X.PD 0
X.TP
X\-\fBR\fP, \-\fBr\fP
Xignore the escape conventions of \fBecho\fP.
XThe \-\fBR\fP option will print all subsequent
Xarguments and options.
X.TP
X\-\fBs\fP
Xplace the results in the history list instead of on the standard output.
X.TP
X\-\fBn\fP
Xdo not add a newline to the output.
X.TP
X\-\fBl\fP
Xprint the arguments separated by newlines instead of spaces.
X.TP
X\-\fBN\fP
Xprint the arguments separated and terminated by nulls.
X.TP
X\-\fBu\fP\fIn\fP
Xprint the arguments to file descriptor \fIn\fP.
X.TP
X\-\fBp\fP
Xprint the arguments to the input of the coprocess.
X.TP
X\-\fBz\fP
Xpush the arguments onto the editing buffer stack, separated by spaces;
Xno escape sequences are recognized.
X.TP
X\-\fBD\fP
Xtreat the arguments as directory names, replacing prefixes with ~
Xexpressions, as appropriate.
X.TP
X\-\fBP\fP
Xrecognize the same escape sequences as in the \fBPROMPT\fP parameter.
X.PD
X.RE
X.TP
X.PD 0
X\fBpushd\fP [ \fIarg\fP ]
X.TP
X\fBpushd\fP \fIold\fP \fInew\fP
X.TP
X\fBpushd\fP \(+-\fBn\fP
X.PD
XChange the current directory, and push the old current directory
Xonto the directory stack. In the first form, change the
Xcurrent directory to \fIarg\fP.
XIf \fIarg\fP is not specified, change to the second directory
Xon the stack (that is, exchange the top two entries), or
Xchange to the value of \fBHOME\fP if the \fBPUSHD_TO_HOME\fP
Xoption is set or if there is only one entry on the stack.
XIf \fIarg\fP is \-, change to the


Xvalue of \fBOLDPWD\fP, the previous directory.
XIf a directory named \fIarg\fP is not found in the current directory

Xand \fIarg\fP does not contain a slash,


Xsearch each component of the shell parameter \fBcdpath\fP.
XIf the option \fBCDABLEVARS\fP is set, and a parameter named \fIarg\fP
Xexists whose value begins with a slash, treat its value as
Xthe directory.

XIf the option \fBPUSHD_SILENT\fP is not set, the directory
Xstack will be printed after a \fBpushd\fP is performed.
X.RS
X.PP
XThe second form of \fBpushd\fP substitutes the string \fInew\fP


Xfor the string \fIold\fP in the name of the current directory,
Xand tries to change to this new directory.
X.PP

XThe third form of \fBpushd\fP is equivalent to \fBpopd\fP.
X.RE
X.TP
X\fBpwd\fP
XEquivalent to \fBprint \-R $PWD\fP.
X.TP
X\fBr\fP
XEquivalent to \fBfc \-e \-\fP.
X.TP
X\fBread\fP [ \-\fBrzp\fP ] [ \-\fBu\fIn\fR ] [ \fIname\fP?\fIprompt\fP ] [ \fIname\fP ... ]
XRead one line and break it into fields using the characters
Xin \fBIFS\fP as separators. In raw mode, \-\fBr\fP, a \e
Xat the end of a line does not signify line continuation.
XIf the \-\fBz\fP flag is set, read from the editor buffer stack.
XThe first field is assigned to the first \fIname\fP, the second field
Xto the second \fIname\fP, etc., with leftover
Xfields assigned to the last \fIname\fP.
XIf \fIname\fP is omitted then \fBREPLY\fP is used.
XIf \-\fBu\fIn\fR is specified, then input is read from file
Xdescriptor \fIn\fP; if \-\fBp\fP is specified, then input is
Xread from the coprocess.
XThe exit status is 0 unless end-of-file is encountered.
XIf the first argument contains a \fB?\fP, the remainder of this
Xword is used as a \fIprompt\fP on standard error when the shell
Xis interactive. The exit status is 0 unless an end-of-file
Xis encountered.
X.TP
X\fBreadonly\fP [ \fIname\fP[=\fIvalue\fP] ] ...
XThe given \fInames\fP are marked readonly; these names
Xcannot be changed by subsequent assignment.
X.TP
X\fBrehash\fP [ \-\fBf\fP ]
XThrow out the command hash table and start over.
XIf the \-\fBf\fP option is set, rescan the command path
Ximmediately, instead of rebuilding the hash table incrementally.
X.TP
X\fBreturn\fP [ \fIn\fP ]
XCauses a shell function or \fB\&.\fP script to return to
Xthe invoking script
Xwith the return status specified by \fIn\fP. If \fIn\fP
Xis omitted then the return status is that of the last command
Xexecuted.
X.TP
X.PD 0
X\fBsched\fP [+]\fIhh\fP:\fImm\fP \fIcommand\fP ...
X.TP
X\fBsched\fP [ \-\fIitem\fP ]
X.PD
XMake an entry in the scheduled list of commands to execute.
XThe time may be specified in either absolute or relative time.
XWith no arguments, prints the list of scheduled commands.
XWith the argument \-\fIitem\fP, removes the given item
Xfrom the list.
X.TP
X\fBset\fP [ \(+-\fIoptions\fP ] [ \(+-\fBo\fP \fIoption name\fP ] ... [ \-\fBA\fP \fIname\fP ] [ \fIarg\fP ] ...
XSet the options for the shell and/or set the positional parameters, or
Xdeclare an array. For the meaning of the flags, see
X\fBOPTIONS\fP above.
XFlags may be specified by name using the \-\fBo\fP option.
XIf the \-\fBA\fP flag is specified, \fIname\fP is set to an
Xarray containing the given \fIarg\fPs.
XOtherwise the positional parameters are set.
XIf no arguments are given, then the names and values
Xof all parameters are printed on the standard output.
XIf the only argument is +, the names of all parameters are printed.
X.TP
X\fBsetopt\fP [ \(+-\fIoptions\fP ] [ \fIname\fP ... ]
XSet the options for the shell. All options specified either
Xwith flags or by name are set. If no arguments are supplied,
Xthe names of all options currently set are printed.
XIn option names, case is insignificant, and all underscore
Xcharacters are ignored.
X.TP
X\fBshift\fP [ \fIn\fP ]
XThe positional parameters from $\fIn\fP+\fB1\fP ... are renamed
X$\fB1\fP, where \fIn\fP is an arithmetic expression that
Xdefaults to 1.
X.TP
X\fBsource\fP
XSame as \fB.\fP.
X.TP
X\fBsuspend\fP [ \-\fBf\fP ]
XSuspend the execution of the shell (send it a \fBSIGTSTP\fP)
Xuntil it receives a \fBSIGCONT\fP.
XIf the \-\fBf\fP option is not given, complain if this is a login shell.
X.TP
X.PD 0
X\fBtest\fP \fIarg\fP ...
X.TP
X\fB[\fP \fIarg\fP ... \fB]\fP
X.PD
XLike the system version of \fBtest\fP. Added for compatibility;
Xuse conditional expressions instead.
X.TP
X\fBtimes\fP
XPrint the accumulated user and system times for the shell
Xand for processes run from the shell.
X.TP
X\fBtrap\fP [ \fIarg\fP ] [ \fIsig\fP ] ...
X\fIarg\fP is a command to be read and executed when the shell
Xreceives \fIsig\fP. Each \fIsig\fP can be given as a number
Xor as the name of a signal.
XIf \fIarg\fP is \-, then all traps \fIsig\fP are reset to their
Xdefault values. If \fIarg\fP is the null string, then this signal
Xis ignored by the shell and by the commands it invokes.
XIf \fIsig\fP is \fBERR\fP then \fIarg\fP will be executed
Xafter each command.
XIf \fIsig\fP is \fB0\fP or \fBEXIT\fP
Xand the \fBtrap\fP statement is executed inside the body of a function,
Xthen the command \fIarg\fP is executed after the function completes.
XIf \fIsig\fP is \fB0\fP or \fBEXIT\fP
Xand the \fBtrap\fP statement is not executed inside the body of a function,
Xthen the command \fIarg\fP is executed when the shell terminates.
XThe \fBtrap\fP command with no arguments prints a list of commands
Xassociated with each signal.
X.TP
X\fBtrue\fP
XDo nothing and return an exit code of 0.
X.TP
X\fBttyctl\fP \-\fBfu\fP
XThe \-\fBf\fP option freezes the tty, and \-\fBu\fP unfreezes it.
XWhen the tty is frozen, no changes made to the tty settings by
Xexternal programs will be honored by the shell; the shell will
Xsimply reset the settings to their previous values as soon as each
Xcommand exits. Thus, \fBstty\fP and similar programs have no
Xeffect when the tty is frozen.
X.TP
X\fBtype\fP
XSame as \fBwhence\fP \-\fBv\fP.
X.TP
X\fBtypeset\fP [ \(+-\fBLRZfilrtux [\fIn\fP]] [ \fIname\fP[=\fIvalue\fP] ] ...
XSet attributes and values for shell parameters.
XWhen invoked inside a function, if \fIname\fP is not already
Xdefined, a new parameter is created which will be unset when the
Xfunction completes.
XThe following attributes are valid:
X.RS
X.PD 0
X.TP
X\-\fBL\fP
XLeft justify and remove leading blanks from \fIvalue\fP.
XIf \fIn\fP is nonzero, it defines the width of the field;
Xotherwise it is determined by the width of the value of the first
Xassignment.
XWhen the parameter is printed, it is filled on the right with
Xblanks or truncated if necessary to fit the field.
XLeading zeros are removed if the \-\fBZ\fP flag is also set.
X.TP
X\-\fBR\fP
XRight justify and fill with leading blanks. If \fIn\fP is nonzero
Xif defines the width of the field;
Xotherwise it is determined by the width of the value of the first
Xassignment.
XWhen the parameter is printed, the field is left filled with
Xblanks or truncated from the end.
X.TP
X\-\fBZ\fP
XRight justify and fill with leading zeros if the first non-blank
Xcharacter is a digit and the \-\fBL\fP flag has not been set.
XIf \fIn\fP is nonzero it defines the width of the field;
Xotherwise it is determined by the width of the value of the
Xfirst assignment.


X.TP
X\-\fBf\fP

XThe names refer to functions rather than parameters. No assignments
Xcan be made, and the only other valid flags are \-\fBt\fP
Xand \-\fBu\fP. The flag \-\fBt\fP turns on execution tracing for this
Xfunction. The flag \-\fBu\fP causes this function to be marked
Xfor autoloading. The \fBfpath\fP parameter will be searched to find the
Xfunction definition when the function is first referenced.
X.TP
X\-\fBi\fP
XUse an internal integer representation. If \fBi\fP is nonzero
Xit defines the output arithmetic base, otherwise it is determined by the first
Xassignment.
X.TP
X\-\fBl\fP
XConvert to lower case.
X.TP
X\-\fBr\fP
XThe given \fIname\fPs are marked readonly.
X.TP
X\-\fBt\fP
XTags the named parameters. Tags have no special meaning to the shell.
X.TP
X\-\fBu\fP
XConvert to upper case.
X.TP
X\-\fBx\fP
XMark for automatic export to the environment of subsequently
Xexecuted commands.
X.RE
X.PD
X.PP
XUsing + rather than \- causes these flags to be turned off.
XIf no arguments are given but flags are specified,
Xa list of named parameters which have these flags set is printed.
XUsing + instead of \- keeps their values from being printed.
XIf no arguments or options are given, the names and attributes
Xof all parameters are printed.
X.TP
X\fBulimit\fP [ \-\fBHSacdfmnt\fP ] [ \fIlimit\fP ]
XSet or display a resource limit. The value of limit can be a number
Xin the unit specified below or the value \fBunlimited\fP.
XThe \fBH\fP and \fBS\fP flags specify whether the hard limit
Xor the soft limit for the given resource is set.
X.RS
X.PD 0
X.TP
X\-\fBa\fP
XLists all of the current resource limits.


X.TP
X\-\fBc\fP

XThe number of 512-byte blocks on the size of core dumps.
X.TP
X\-\fBd\fP
XThe number of K-bytes on the size of the data segment.


X.TP
X\-\fBf\fP

XThe number of 512-byte blocks on the size of files written.
X.TP
X\-\fBm\fP
XThe number of K-bytes on the size of physical memory.
X.TP
X\-\fBn\fP
XThe number of file descriptors.
X.TP
X\-\fBs\fP
XThe number of K-bytes on the size of the stack.
X.TP
X\-\fBt\fP
XThe number of CPU seconds to be used.
X.RE
X.PD
X.TP
X\fBumask\fP [ \fImask\fP ]
XThe umask is set to \fImask\fP. \fImask\fP can be either
Xan octal number or a symbolic value as described in \fBchmod\fP(1).
XIf \fImask\fP is omitted, the current value is printed.
X.TP
X\fBunalias\fP \fIname\fP ...
XThe alias definition, if any, for each \fIname\fP is removed.
X.TP
X\fBunfunction\fP \fIname\fP ...
XThe function definition, if any, for each \fIname\fP is removed.
X.TP
X\fBunhash\fP \fIname\fP ...
XThe entry in the command hash table, if any, for each \fIname\fP
Xis removed.
X.TP
X\fBunlimit\fP [ \-\fBh\fP ] \fIresource\fP ...
XThe resource limit for each \fIresource\fP is set to the hard limit.
XIf the \-\fBh\fP flag is given and the shell is running as root,
Xthe hard resource limit for each \fIresource\fP is removed.
X.TP
X\fBunset\fP \fIname\fP ...
XEach named parameter is unset.
X.TP
X\fBunsetopt\fP [ \(+-\fIoptions\fP ] [ \fIname\fP ... ]
XUnset the options for the shell. All options specified either
Xwith flags or by name are unset.
X.TP
X\fBvared\fP \fIname\fP
XThe value of the parameter \fIname\fP is loaded into the edit
Xbuffer, and the line editor is invoked. When the editor exits,
X\fIname\fP is set to the string value returned by the editor.
X.TP
X\fBwait\fP [ \fIjob\fP ... ]
XWait for the specified jobs or processes. If \fIjob\fP is not given
Xthen all currently active child processes are waited for.
XEach \fIjob\fP can be either a job specification or the process-id
Xof a job in the job table.
XThe exit status from this command is that of the job waited for.
X.TP
X\fBwhence\fP [ \-\fBacpv\fP ] \fIname\fP ...
XFor each name, indicate how it would be interpreted if used
Xas a command name. The \-\fBv\fP flag produces a more verbose
Xreport. The \-\fBp\fP flag does a path search for \fIname\fP
Xeven if it is a shell function, alias, or reserved word.
XThe \-\fBc\fP flag prints the results in a csh-like format.
XThe \-\fBa\fP flag does a search for all occurences of \fIname\fP
Xthroughout the command path.
X.TP
X\fBwhich\fP
XSame as \fBwhence \-c\fP.
X.RE
X.SH INVOCATION
XCommands are first read from /etc/zshenv.
XThen, if the \fBNO_RCS\fP option is unset, commands are read
Xfrom $ZDOTDIR/.zshenv.
X(If \fBZDOTDIR\fP is unset, \fBHOME\fP is used instead).
XThen, if the shell is interactive and
Xthe \fBNO_RCS\fP option is unset, commands are read
Xfrom /etc/zshrc and $ZDOTDIR/.zshrc, in that order, if either file
Xexists.
XIf the first character of argument zero passed to the shell
Xis \-, then the shell is assumed to be a login shell, and commands
Xare read from /etc/zprofile and $ZDOTDIR/.zprofile before .zshrc is read,
Xthen /etc/zlogin and $ZDOTDIR/.zlogin after .zshrc is read.
XIf the \fBNO_RCS\fP option is set, only /etc/zshrc
X/etc/zlogin, and /etc/zprofile may be read.
XIf the \-\fBs\fP flag is not present and an argument is given,
Xthe first argument is taken to be the pathname of a script to
Xexecute. The remaining arguments are assigned to the positional
Xparameters. The following flags are interpreted by the shell
Xwhen invoked:
X.TP
X.PD 0
X\-\fBc\fP \fIstring\fP
XRead commands from \fIstring\fP.
X.TP
X\-\fBs\fP
XRead command from the standard input.
X.TP
X\-\fBi\fP
XIf this flag is present or the shell input and output
Xare attached to a terminal, this shell is interactive.
X.PD
X.SH "SEE ALSO"
Xsh(1),
Xcsh(1),
Xtcsh(1),
Xitcsh(1),
Xrc(1),
Xbash(1),
Xash(1),
Xksh(1),
Xclam(1),
Xstrftime(3).
X.SH FILES
X$ZDOTDIR/.zshenv
X.br
X$ZDOTDIR/.zshrc
X.br
X$ZDOTDIR/.zlogin
X.br
X$ZDOTDIR/.zlogout
X.br
X$ZDOTDIR/.zprofile
X.br
X/tmp/zsh*
X.br
X/etc/zshenv
X.br
X/etc/zprofile
X.br
X/etc/zshrc
X.br
X/etc/zlogin
X.SH AUTHOR
XPaul Falstad (pfal...@phoenix.princeton.edu)
X.SH "UNDOCUMENTED FEATURES"
XNone known, but many suspected.
XPlease mail the author if you find any.
SHAR_EOF
echo 'File zsh2.2/man/man1/zsh.1 is complete' &&
chmod 0644 zsh2.2/man/man1/zsh.1 ||


echo 'restore of zsh2.2/man/man1/zsh.1 failed'

Wc_c="`wc -c < 'zsh2.2/man/man1/zsh.1'`"
test 112852 -eq "$Wc_c" ||
echo 'zsh2.2/man/man1/zsh.1: original size 112852, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/scripts/aproto ==============
if test ! -d 'zsh2.2/scripts'; then
echo 'x - creating directory zsh2.2/scripts'
mkdir 'zsh2.2/scripts'
fi
if test -f 'zsh2.2/scripts/aproto' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/scripts/aproto (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/scripts/aproto (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/scripts/aproto' &&
X#! /bin/sh
Xfproto builtin.c >builtin.pro
Xfproto cond.c >cond.pro
Xfproto exec.c >exec.pro
Xfproto glob.c >glob.pro
Xfproto hist.c >hist.pro
Xfproto init.c >init.pro
Xfproto jobs.c >jobs.pro
Xfproto lex.c >lex.pro
Xfproto loop.c >loop.pro
Xfproto math.c >math.pro
Xfproto mem.c >mem.pro
Xfproto params.c >params.pro
Xfproto subst.c >subst.pro
Xfproto table.c >table.pro
Xfproto text.c >text.pro
Xfproto utils.c >utils.pro
Xfproto watch.c >watch.pro
Xfproto parse.c >parse.pro
Xfproto zle_hist.c >zle_hist.pro
Xfproto zle_main.c >zle_main.pro
Xfproto zle_misc.c >zle_misc.pro
Xfproto zle_move.c >zle_move.pro
Xfproto zle_refresh.c >zle_refresh.pro
Xfproto zle_tricky.c >zle_tricky.pro
Xfproto zle_utils.c >zle_utils.pro
Xfproto zle_vi.c >zle_vi.pro
Xfproto zle_word.c >zle_word.pro
SHAR_EOF
chmod 0755 zsh2.2/scripts/aproto ||
echo 'restore of zsh2.2/scripts/aproto failed'
Wc_c="`wc -c < 'zsh2.2/scripts/aproto'`"
test 755 -eq "$Wc_c" ||
echo 'zsh2.2/scripts/aproto: original size 755, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/scripts/fproto ==============
if test -f 'zsh2.2/scripts/fproto' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/scripts/fproto (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/scripts/fproto (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/scripts/fproto' &&
X#! /bin/sh
X# prototype generator
Xsed -n '/\/\*\*\/$/{N;s/^\([^(]*\).*\/\*\*\/.\(.*\)/\1 DCLPROTO((\2))/p;}' $1 | sed -e 's/;/,/g' -e 's/,))$/));/' -e 's/(({))$/((void));/'
X
SHAR_EOF
chmod 0755 zsh2.2/scripts/fproto ||
echo 'restore of zsh2.2/scripts/fproto failed'
Wc_c="`wc -c < 'zsh2.2/scripts/fproto'`"
test 173 -eq "$Wc_c" ||
echo 'zsh2.2/scripts/fproto: original size 173, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/scripts/ctoz ==============
if test -f 'zsh2.2/scripts/ctoz' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/scripts/ctoz (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/scripts/ctoz (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/scripts/ctoz' &&
X#! /bin/sh
X#
X# ctoz - alias conversion tool
X# This file is part of zsh, the Z shell.
X# (c) 1991 Paul Falstad
X#
X# This is a quick script to convert csh aliases to zsh aliases/functions.
X# Pipe the output of csh's alias command through this; it will generate
X# a series of alias/function definitions on stdout, suitable for
X# processing by zsh (probably also ksh or bash).
X#
X# This is not perfect, but it gets most common aliases; it should manage to
X# cut down a lot of the busy work.
X#
Xsed -e 's/ (\(.*\))/ \1/' >/tmp/cz$$.1
Xgrep ! /tmp/cz$$.1 >/tmp/cz$$.2
Xgrep -v ! /tmp/cz$$.1 >/tmp/cz$$.3
Xsed -e "s/'/'"\\\\"''"/g -e 's/^\([^ ]*\) \(.*\)$/alias \1='"'\2'/" \
X /tmp/cz$$.3
Xsed -e 's/![:#]*/$/g' -e 's/^\([^ ]*\) \(.*\)$/\1 () { \2 }/' /tmp/cz$$.2
Xrm /tmp/cz$$.?
X#
X# in case your mailer eats tabs, here it is again, with the tabs
X# marked with a T:
X#
X#sed -e 's/T(\(.*\))/T\1/' >/tmp/cz$$.1
X#grep ! /tmp/cz$$.1 >/tmp/cz$$.2
X#grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3
X#sed -e "s/'/'"\\\\"''"/g -e 's/^\([^T]*\)T\(.*\)$/alias \1='"'\2'/" \
X# /tmp/cz$$.3
X#sed -e 's/![:#]*/$/g' -e 's/^\([^T]*\)T\(.*\)$/\1 () { \2 }/' /tmp/cz$$.2
X#rm /tmp/cz$$.?
SHAR_EOF
chmod 0644 zsh2.2/scripts/ctoz ||
echo 'restore of zsh2.2/scripts/ctoz failed'
Wc_c="`wc -c < 'zsh2.2/scripts/ctoz'`"
test 1137 -eq "$Wc_c" ||
echo 'zsh2.2/scripts/ctoz: original size 1137, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/scripts/fooz ==============
if test -f 'zsh2.2/scripts/fooz' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/scripts/fooz (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/scripts/fooz (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/scripts/fooz' &&
Xalias -- 0='vi'
Xalias -- a='alias'
Xalias -- a.out='./a.out'
Xalias -- c='cp'
Xalias -- gnu='telnet gnu.ai.mit.edu'
Xalias -- grep='egrep'
Xalias -- gz='gdb zsh'
Xalias -- j='jobs -l'
Xalias -- k='kill'
Xalias -- l='ls -AF'
Xalias -- lock='lock -p -600'
Xalias -- lsd='ls -d */'
Xalias -- m='make'
Xalias -- main='./main'
Xalias -- man='woman'
Xalias -- mm='less'
Xalias -- more='less'
Xalias -- nw='l -ltr | tail'
Xalias -- pd='pushd'
Xalias -- pop='popd'
Xalias -- ps='sps'
Xalias -- pwrite='talk'
Xalias -- rn='h /usr/princeton/bin/rn.4.1'
Xalias -- rtfm='man'
Xalias -- strings='strings -'
Xalias -- t='cat'
Xalias -- talk='h talk'
Xalias -- v='mv'
Xalias -- where='hostname; echo >/dev/null'
Xalias -- whm='who | mm'
Xalias -- wm='w | mm'
X320 () { $* | fgrep -f /u/pfalstad/src/cs320/cs320list }
Xacx () { chmod 755 $* }
Xcx () { chmod +x $* }
Xf () { $* | fgrep -f /u/pfalstad/.friends }
Xk9 () { kill -9 $* }
Xmere () { nroff <$1 -man -Tman | less -s }
Xnrable () { ls -AFltr $* | grep -v r..r.. }
Xrable () { ls -AFltr $* | grep r..r.. }
Xexport ATTRIBUTION='%f wrote:'
Xexport CAD_HOME='/u/cad/magic'
Xexport COSMOS='/u/cad/cosmos'
Xexport HOME='/u/pfalstad'
Xexport LESS='-ainx3'
Xexport LM_LICENSE_FILE='/u/cs475/Mentor/etc/license_file'
Xexport LOGNAME='pfalstad'
Xexport MAIL='/usr/spool/mail/pfalstad'
Xexport MAILCALL='NEW MAIL! '
Xexport MANPATH='/usr/man:/usr/princeton/man:/u/cad/man'
Xexport NAME='Paul Falstad'
Xexport OCTTOOLS='/u/cad/octtools'
Xexport ORGANIZATION='The E. Henry Thripshaw Fan Club'
Xexport PATH='/u/pfalstad/scr:/u/pfalstad/bin/sun4:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:/u/maruchck/scr:/u/cs320/bin:/u/subbarao/bin:/u/maruchck/bin:/usr/hosts:/usr/princeton/bin/X11:/usr/etc:/etc'
Xexport PRINTER='dod'
Xexport PWD='/n/homeserver/c/pfalstad/zsh2.1/scripts'
Xexport RNINIT='/u/pfalstad/.rninit'
Xexport SCS='/u/cs475/Mentor'
Xexport SCS_LICENSE_CLASS='2'
Xexport SHELL='/u/pfalstad/bin/sun4/zsh'
Xexport TERM='vt100'
Xexport TERMCAP='d0|vt100|vt100-am|vt100am|dec-vt100:do=^J:co#80:li#24:cl=50\E[;H\E[2J:sf=5\ED:le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E>\E[?1l\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:rf=/usr/share/lib/tabset/vt100:rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=5\EM:vt#3:xn:sc=\E7:rc=\E8:cs=\E[%i%d;%dr:'
Xexport USER='pfalstad'


Xexport YOUSAID='In %C you wrote:'

Xexport _='/u/pfalstad/zsh2.1/scripts/c2z'
XDISPLAY='phoenix:0.0'
XHOSTTYPE='sun4'
Xcdpath=(/u/pfalstad /u/pfalstad/src/cs320 /u/pfalstad/src)
Xedit=
XHISTSIZE='200'
XHOME='/u/pfalstad'
Xmail=(30 /usr/spool/mail/pfalstad)
Xpath=(/u/pfalstad/scr /u/pfalstad/bin/sun4 /usr/princeton/bin /usr/ucb /usr/bin /bin /u/maruchck/scr /u/cs320/bin /u/subbarao/bin /u/maruchck/bin /usr/hosts /usr/princeton/bin/X11 /usr/etc /etc)
Xprompt='c phoenix% '
Xshell='/bin/csh'
Xsetopt globdots
Xterm='vt100'
Xuser='pfalstad'
Xvi=
SHAR_EOF
chmod 0644 zsh2.2/scripts/fooz ||
echo 'restore of zsh2.2/scripts/fooz failed'
Wc_c="`wc -c < 'zsh2.2/scripts/fooz'`"
test 2958 -eq "$Wc_c" ||
echo 'zsh2.2/scripts/fooz: original size 2958, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/scripts/c2z ==============
if test -f 'zsh2.2/scripts/c2z' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/scripts/c2z (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/scripts/c2z (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/scripts/c2z' &&
X#! /bin/sh
X#
X# c2z - environment conversion tool
X# Contributed by Bart Schaefer
X# (Tweaked a bit by Paul Falstad)
X#
X# This is a quick script to convert csh aliases to zsh aliases/functions.
X# It also converts the csh environment and local variables to zsh. c2z
X# uses the csh to parse its own dot-files, then processes csh output to
X# convert the csh settings to zsh.
X#
X# When run as a zsh fuction, c2z runs csh as if it were an interactive
X# shell whenever the parent zsh is interactive. When run as a shell
X# script, the -i switch can be used to force this behavior.
X#
X# The -l (login) switch causes csh to run as if it were a login shell.
X# This is done "properly" if c2z is used as a zsh function, otherwise
X# it's faked by explicitly sourcing .login. Use with caution if your
X# .login initializes an X server or does other one-time-only startup
X# procedures.
X#
X# usage:
X# c2z [-i] [-l]
X#
X# You can use this script in your .zshrc or .zlogin files to load your
X# regular csh environment into zsh; for example, in .zlogin:
X#
X# . =(c2z -l)
X#
X# This is not perfect, but it gets most common aliases and variables.
X# It's also rather time-consuming to do this every time you log in.
X# However, if you're moving from csh to zsh for the first time, this
X# can get you started with a familiar environment right away.
X#
X# In case your mailer eats tabs, $T is set to expand to a tab.
X#
XT="`echo x | tr x '\011'`"
X
X# If we're zsh, we can run "- csh" to get the complete environment.
X#
XMINUS=""
XLOGIN=""
XINTERACT=""
Xcase "$VERSION" in
Xzsh*)
X case $1 in
X -l*) MINUS="-" ;;
X -i*) INTERACT="-i" ;;
X esac
X if [[ -o INTERACTIVE ]]; then INTERACT="-i"; fi
X setopt nobanghist
X ;;
X*)
X case $1 in
X -l*) LOGIN="source ~/.login" ;;
X -i*) INTERACT="-i" ;;
X esac
X ;;
Xesac
X
X( eval $MINUS csh $INTERACT ) <<EOF 2>&1 >/dev/null
X$LOGIN
Xalias >! /tmp/cz$$.a
Xsetenv >! /tmp/cz$$.e
Xset >! /tmp/cz$$.v
XEOF
X
X# save stdin
Xexec 9<&0
X
X# First convert aliases
Xexec < /tmp/cz$$.a
X
X# Taken straight from ctoz except for $T and "alias --"
Xsed -e 's/'"$T"'(\(.*\))/'"$T"'\1/' >/tmp/cz$$.1
Xgrep ! /tmp/cz$$.1 >/tmp/cz$$.2
Xgrep -v ! /tmp/cz$$.1 >/tmp/cz$$.3
Xsed -e "s/'/'"\\\\"''"/g \
X -e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/alias -- \1='"'\2'/" \
X /tmp/cz$$.3
Xsed -e 's/![:#]*/$/g' \
X -e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/\1 () { \2 }/' \
X /tmp/cz$$.2
X
X# Next, convert environment variables
Xexec < /tmp/cz$$.e
X
X# Would be nice to deal with embedded newlines, e.g. in TERMCAP, but ...
Xsed -e '/^SHLVL/d' \
X -e "s/'/'"\\\\"''"/g \
X -e "s/^\([A-Za-z0-9_]*=\)/export \1'/" \
X -e "s/$/'/"
X
X# Finally, convert local variables
Xexec < /tmp/cz$$.v
X
Xsed -e 's/'"$T"'/=/' \
X -e "s/'/'"\\\\"''"/g \
X -e '/^[A-Za-z0-9_]*=[^(]/{
X s/=/='"'/"'
X s/$/'"'/"'
X }' |
Xsed -e '/^argv=/d' -e '/^cwd=/d' -e '/^filec=/d' -e '/^status=/d' \
X -e '/^histchars=/s//HISTCHARS=/' \
X -e '/^history=/s//HISTSIZE=/' \
X -e '/^home=/s//HOME=/' \
X -e '/^ignoreeof=/s/.*/setopt ignoreeof/' \
X -e '/^noclobber=/s/.*/setopt noclobber/' \
X -e '/^notify=/d' \
X -e '/^showdots=/s/.*/setopt globdots/' \
X -e '/^savehist=/s//HISTFILE=\~\/.zhistory SAVEHIST=/' \
X -e '/^autolist=/s/.*/setopt autolist/' \
X -e '/^correct=[cmd]*/s//setopt autocorrect/' \
X -e '/^who=/s//WATCHFMT=/'
X
X
Xexec 0<&9
X
Xrm /tmp/cz$$.?
Xexit
SHAR_EOF
chmod 0755 zsh2.2/scripts/c2z ||
echo 'restore of zsh2.2/scripts/c2z failed'
Wc_c="`wc -c < 'zsh2.2/scripts/c2z'`"
test 3299 -eq "$Wc_c" ||
echo 'zsh2.2/scripts/c2z: original size 3299, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/scripts/c2z.orig ==============
if test -f 'zsh2.2/scripts/c2z.orig' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/scripts/c2z.orig (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/scripts/c2z.orig (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/scripts/c2z.orig' &&
X#! /bin/sh
X#
X# c2z - environment conversion tool
X# Contributed by Bart Schaefer
X#
X# This is a quick script to convert csh aliases to zsh aliases/functions.
X# It also converts the csh environment and local variables to zsh. c2z
X# uses the csh to parse its own dot-files, then processes csh output to
X# convert the csh settings to zsh.
X#
X# When run as a zsh fuction, c2z runs csh as if it were an interactive
X# shell whenever the parent zsh is interactive. When run as a shell
X# script, the -i switch can be used to force this behavior.
X#
X# The -l (login) switch causes csh to run as if it were a login shell.
X# This is done "properly" if c2z is used as a zsh function, otherwise
X# it's faked by explicitly sourcing .login. Use with caution if your
X# .login initializes an X server or does other one-time-only startup
X# procedures.
X#
X# usage:
X# c2z [-i] [-l]
X#
X# You can use this script in your .zshrc or .zlogin files to load your
X# regular csh environment into zsh; for example, in .zlogin:
X#
X# . =(c2z -l)
X#
X# This is not perfect, but it gets most common aliases and variables.
X# It's also rather time-consuming to do this every time you log in.
X# However, if you're moving from csh to zsh for the first time, this
X# can get you started with a familiar environment right away.
X#
X# In case your mailer eats tabs, $T is set to expand to a tab.
X#
XT="`echo x | tr x '\011'`"
X
X# If we're zsh, we can run "- csh" to get the complete environment.
X#
XMINUS=""
XLOGIN=""
XINTERACT=""
Xcase "$VERSION" in
Xzsh*)
X case $1 in
X -l*) MINUS="-" ;;
X -i*) INTERACT="-i" ;;
X esac
X if [[ -o INTERACTIVE ]]; then INTERACT="-i"; fi
X setopt nobanghist
X ;;
X*)
X case $1 in
X -l*) LOGIN="source ~/.login" ;;
X -i*) INTERACT="-i" ;;
X esac
X ;;
Xesac
X
X( eval $MINUS csh $INTERACT ) <<EOF 2>&1 >/dev/null
X$LOGIN
Xalias >! /tmp/cz$$.a
Xsetenv >! /tmp/cz$$.e
Xset >! /tmp/cz$$.v
XEOF
X
X# First convert aliases
Xexec < /tmp/cz$$.a
X
X# Taken straight from ctoz except for $T and "alias --"
Xsed -e 's/'"$T"'(\(.*\))/'"$T"'\1/' >/tmp/cz$$.1
Xgrep ! /tmp/cz$$.1 >/tmp/cz$$.2
Xgrep -v ! /tmp/cz$$.1 >/tmp/cz$$.3
Xsed -e "s/'/'"\\\\"''"/g \
X -e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/alias -- \1='"'\2'/" \
X /tmp/cz$$.3
Xsed -e 's/![:#]*/$/g' \
X -e 's/^\([^'"$T"']*\)'"$T"'\(.*\)$/\1 () { \2 }/' \
X /tmp/cz$$.2
X
X# Next, convert environment variables
Xexec < /tmp/cz$$.e
X
X# Would be nice to deal with embedded newlines, e.g. in TERMCAP, but ...
Xsed -e '/^SHLVL/d' \
X -e "s/'/'"\\\\"''"/g \
X -e "s/^\([A-Za-z0-9_]*=\)/export \1'/" \
X -e "s/$/'/"
X
X# Finally, convert local variables
Xsed -e '
Xexec < /tmp/cz$$.v
X
Xsed -e 's/'"$T"'/=/' \
X -e "s/'/'"\\\\"''"/g \
X -e '/^[A-Za-z0-9_]*=[^(]/{
X s/=/='"'/"'
X s/$/'"'/"'
X }'
X
Xrm /tmp/cz$$.?
Xexit
SHAR_EOF
chmod 0755 zsh2.2/scripts/c2z.orig ||
echo 'restore of zsh2.2/scripts/c2z.orig failed'
Wc_c="`wc -c < 'zsh2.2/scripts/c2z.orig'`"
test 2736 -eq "$Wc_c" ||
echo 'zsh2.2/scripts/c2z.orig: original size 2736, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/buildzsh ==============
if test ! -d 'zsh2.2/src'; then
echo 'x - creating directory zsh2.2/src'
mkdir 'zsh2.2/src'
fi
if test -f 'zsh2.2/src/buildzsh' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/buildzsh (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/buildzsh (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/buildzsh' &&
X#! /bin/sh
Xecho
Xecho 'Building config.h...
X'
Xexec >config.h
Xcat <<'foo'
X/* this file is created automatically by buildzsh */
X
X/* define this if you are sysvish */
Xfoo
Xif test -f /usr/include/sys/resource.h
Xthen echo '/* #define SYSV */'; echo 'looks like a BSDish system...' >&2
Xelse echo '#define SYSV'; echo 'looks like a SYSVish system...' >&2
Xfi
Xecho
Xif grep ULTRIX /usr/include/stdio.h >/dev/null 2>&1
Xthen echo '/* ULTRIX termios is weird... */
X/* #define TERMIOS */'; echo 'using sgttyb...' >&2
Xelse
Xif test -f /usr/include/termios.h && test ! -f /hp-ux
Xthen echo '#define TERMIOS
X/* #define TTY_NEEDS_DRAINING */
X/* #define CLOBBERS_TYPEAHEAD */'
Xecho 'using termios...' >&2
Xelse
Xif grep sgttyb /usr/include/sys/ioctl.h >/dev/null 2>&1
Xthen echo '/* #define TERMIO */'
Xelse echo '#define TERMIO'
Xecho 'using termio...' >&2
Xfi
Xecho '#define TTY_NEEDS_DRAINING
X#define CLOBBERS_TYPEAHEAD'
Xecho 'using sgttyb...' >&2
Xfi
Xfi
Xecho
Xif test -f /usr/include/stdlib.h
Xthen echo '#define HAS_STDLIB'; echo 'using <stdlib.h>...' >&2
Xelse echo '/*#define HAS_STDLIB*/'; echo 'not using <stdlib.h>...' >&2
Xfi
Xecho
Xif test -f /usr/include/string.h
Xthen echo '#define HAS_STRING'; echo 'using <string.h>...' >&2
Xelse echo '/*#define HAS_STRING*/'; echo 'using <strings.h>...' >&2
Xecho '#define strchr index
X#define strrchr rindex
X#define memcpy(dst, src, n) bcopy(src, dst, n)
X#define memset(dst, ch, n) bfill(dst, n, ch)
X#define memcmp(s1, s2, n) bcopy(s1, s2, n)'
Xfi
Xecho
Xif test -f /usr/include/locale.h
Xthen echo '#define HAS_LOCALE'; echo 'using <locale.h>...' >&2
Xelse echo '/*#define HAS_LOCALE*/'; echo 'not using <locale.h>...' >&2
Xfi
Xecho
Xecho '/* define this if you have a host field in utmp */'
Xif grep ut_host /usr/include/utmp.h >/dev/null
Xthen echo '#define UTMP_HOST'; echo 'host field in utmp...' >&2
Xelse echo '/* #define UTMP_HOST */'; echo 'no host field in utmp...' >&2
Xfi
Xecho
Xecho '/* define this if you have WAITPID */'
Xif man 2 wait 2>/dev/null | sed 's/_.//g' | grep waitpid >/dev/null
Xthen echo '#define WAITPID'; echo 'using waitpid()...' >&2
Xelse echo '/* #define WAITPID */'; echo 'not using waitpid()...' >&2
Xfi
Xecho
Xecho '/* define this if you have SELECT */'
Xif grep FD_SET /usr/include/sys/types.h >/dev/null ||
X test -f /usr/include/sys/select.h
Xthen echo '#define HAS_SELECT'; echo 'using select()...' >&2
Xelse echo '/* #define HAS_SELECT */'; echo 'not using select()...' >&2
Xfi
Xecho
Xecho '/* define this if you have <sys/select.h> */'
Xif test -f /usr/include/sys/select.h
Xthen echo '#define HAS_SYS_SELECT'
Xelse echo '/* #define HAS_SYS_SELECT */'
Xfi
Xecho "
X/* we can't just test for S_IFIFO or check to see if the mknod worked,
X because the NeXTs sold by a vendor which will remain nameless will
X happily create the FIFO for you, and then panic when you try to do
X something weird with them, because they aren't supported by the OS. */
X"
Xif test -f /mach
Xthen echo '#define NO_FIFOS'; echo 'no FIFOs...' >&2
Xelse echo '/* #define NO_FIFOS */'; echo 'using FIFOs...' >&2
Xfi
Xecho
Xecho '/* define this if you have strftime() */'
Xif man 3 strftime 2>/dev/null | grep return >/dev/null
Xthen echo '#define HAS_STRFTIME'; echo 'using strftime()...' >&2
Xelse echo '/* #define HAS_STRFTIME */'; echo 'not using strftime()...' >&2
Xfi
Xecho
Xif man tcsetpgrp 2>/dev/null | grep process >/dev/null
Xthen echo '#define HAS_TCSETPGRP'; echo 'using tcsetpgrp()...' >&2
Xelse echo '/* #define HAS_TCSETPGRP */'; echo 'not using tcsetpgrp()...' >&2
Xfi
Xecho
Xif grep tcgetattr /usr/include/termios.h >/dev/null 2>/dev/null ||
X grep tcgetattr /usr/include/sys/termios.h >/dev/null 2>/dev/null ||
X grep tcgetattr /usr/include/sys/termio.h >/dev/null 2>/dev/null
Xthen echo '#define HAS_TCCRAP'; echo 'using tcgetattr() and friends...' >&2
Xelse echo '/* #define HAS_TCCRAP */'; echo 'not using tcgetattr()...' >&2
Xfi
Xecho
Xif test -f /bin/hinv
Xthen echo '/* SGI setpgid() is weird... setpgrp() is better anyway */
X/* #define HAS_SETPGID */'; echo 'using setpgrp()...' >&2
Xelif man setpgid 2>/dev/null | grep process >/dev/null
Xthen echo '#define HAS_SETPGID'; echo 'using setpgid()...' >&2
Xelse echo '/* #define HAS_SETPGID */'; echo 'using setpgrp()...' >&2
Xfi
Xecho
Xif test ! -f /hp-ux && man sigrelse 2>/dev/null | grep signal >/dev/null
Xthen echo '#define HAS_SIGRELSE'; echo 'using sigrelse()...' >&2
Xelse echo '/* #define HAS_SIGRELSE */'; echo 'using sigblock()...' >&2
Xfi
Xecho
Xecho '/* define this if you have RFS */'
Xif test -d /../.CONTROL
Xthen echo '#define HAS_RFS'; echo 'you seem to have RFS...' >&2
Xelse echo '/* #define HAS_RFS */'; echo 'no RFS, it seems...' >&2
Xfi
Xecho
Xecho '/* define this if you have a working getrusage and wait3 */'
Xif test -f /hp-ux
Xthen echo '/* #define HAS_RUSAGE */'; echo 'no getrusage...' >&2
Xelif test -f /usr/include/sys/resource.h
Xthen echo '#define HAS_RUSAGE'; echo 'has getrusage...' >&2
Xelse echo '/* #define HAS_RUSAGE */'; echo 'no getrusage...' >&2
Xfi
Xecho '
X/* define this if your signal handlers return void */'
Xif grep SIG_DFL /usr/include/signal.h /usr/include/sys/signal.h |
X grep void >/dev/null
Xthen echo '#define SIGVOID'; echo 'signal handlers return void...' >&2
Xelse echo '/* #define SIGVOID */'; echo 'signal handlers return int...' >&2
Xfi
Xcat <<'foo'
X#ifdef sgi
X#undef SIGVOID
X#endif
Xfoo
Xecho
Xecho '/* define this if signal handlers need to be reset each time */'
Xif grep SIGTSTP /usr/include/signal.h /usr/include/sys/signal.h >/dev/null
Xthen echo '/* #define RESETHANDNEEDED */'
Xecho 'signal handlers need no resetting...' >&2
Xelse echo '#define RESETHANDNEEDED'
Xecho 'signal handlers need to be reset...' >&2
Xfi
Xecho
Xcat <<'foo'
X#ifdef SIGVOID
X#define HANDTYPE void
X#else
X#define HANDTYPE int
X#define INTHANDTYPE
X#endif
X
X/* a string corresponding to the host type */
Xfoo
Xecho '#define HOSTTYPE "' | tr -d '\012'
Xhost=`(tcsh -fc 'echo $HOSTTYPE' || arch) 2>/dev/null`
Xcase $host in
X'') if grep ULTRIX /usr/include/stdio.h >/dev/null 2>&1
X then host=ultrix
X elif test -f /bin/hinv
X then host=iris
X elif test -d /NextApps
X then host=next
X elif test $machine
X then host=$machine
X else
X echo 1>&2 '
X
XI cannot figure out what sort of host this is. Please enter one
Xshort alphanumeric string describing this host. (This will be used
Xto set the $HOSTTYPE variable, so '"you don't have to be very
Xaccurate if you're not in a multivendor environment.)
X"
X echo "? " | tr -d '\012' 1>&2
X read host
X echo ' ' 1>&2
X fi
X ;;
Xesac
Xecho $host'"'
Xecho "using host type $host..." >&2
Xecho
Xecho '/* the default editor for the fc builtin */'
Xecho '#define DEFFCEDIT "vi"'
Xecho
Xif grep UTMP_FILE /usr/include/utmp.h >/dev/null
Xthen :
Xelse
Xecho '/* the path of wtmp */'
Xecho '#define WTMP_FILE "' | tr -d '\012'
Xif test -f /etc/wtmp
Xthen echo /etc/wtmp
Xelif test -f /usr/etc/wtmp
Xthen echo /usr/etc/wtmp
Xelif test -f /var/adm/wtmp
Xthen echo /var/adm/wtmp
Xelif test -f /usr/adm/wtmp
Xthen echo /usr/adm/wtmp
Xelse echo /dev/null
Xfi | tr -d '\012'
Xecho '"
X
X/* the path of utmp */
X#define UTMP_FILE "/etc/utmp"
X'
Xfi
Xcat <<'foo'
X/* default prefix for temporary files */
X#define DEFTMPPREFIX "/tmp/zsh"
X
X/* define if you prefer "suspended" to "stopped" */
X#define USE_SUSPENDED
X
X/* the file to source whenever zsh is run; if undefined, don't source
X anything */
X#define GLOBALZSHRC "/etc/zshrc"
X
X/* the file to source whenever zsh is run as a login shell; if
X undefined, don't source anything */
X#define GLOBALZLOGIN "/etc/zlogin"
X
X/* the file to source whenever zsh is run as a login shell, before
X zshrc is read; if undefined, don't source anything */
X#define GLOBALZPROFILE "/etc/zprofile"
X
X/* the default HISTSIZE */
X#define DEFAULT_HISTSIZE 30
X
X#define _BSD_SIGNALS /* this could be an iris, you never know */
X#define _BSD /* this could be HP-UX, you never know */
X#define _BSD_INCLUDES /* this could be AIX, you never know */
X
X/* if your compiler doesn't like void *, change this to char *
X and ignore all the warnings.
X*/
X
Xtypedef void *vptr;
X
X#define JOB_CONTROL
Xfoo
Xexec 1>&2
Xecho
Xecho 'Building signals.h...' | tr -d '\012'
Xecho `csh -fc 'kill -l'` | tr ' ' '\012' >signals.h
Xlct=`wc -l < signals.h`
Xcp signals.h signams.h
X(
Xecho '/* this file is created automatically by buildzsh */
X/* if all this is wrong, blame csh ;-) */
X
X#define SIGCOUNT '"$lct"'
X
X#ifdef GLOBALS
X
Xchar *sigmsg[SIGCOUNT+2] = {
X "done",'
Xsed -e 's/^/SIG/' -e '/SIGHUP/s//hangup/
X/SIGINT/s//interrupt/
X/SIGQUIT/s//quit/
X/SIGILL/s//illegal instruction/
X/SIGTRAP/s//trace trap/
X/SIGIOT/s//IOT instruction/
X/SIGABRT/s//abort/
X/SIGEMT/s//EMT instruction/
X/SIGFPE/s//floating point exception/
X/SIGKILL/s//killed/
X/SIGBUS/s//bus error/
X/SIGSEGV/s//segmentation fault/
X/SIGSYS/s//bad system call/
X/SIGPIPE/s//broken pipe/
X/SIGTERM/s//terminated/
X/SIGPWR/s//power fail/
X/SIGVTALRM/s//virtual time alarm/
X/SIGCONT/s//continued/
X/SIGXCPU/s//cpu limit exceeded/
X/SIGXFSZ/s//filesize limit exceeded/' -e 's/.*/ "&",/' signals.h
Xecho ' NULL
X};
X
Xchar *sigs[SIGCOUNT+4] = {
X "EXIT",' ) >sigtmp.h
Xmv sigtmp.h signals.h
Xif grep SIGSTOP signals.h >/dev/null
Xthen ed signals.h <<'foo' >/dev/null 2>&1
X/SIGSTOP/c
X#ifdef USE_SUSPENDED
X "suspended (signal)",
X#else
X "stopped (signal)",
X#endif
X.
X/SIGTSTP/c
X#ifdef USE_SUSPENDED
X "suspended",
X#else
X "stopped",
X#endif
X.
X/SIGTTIN/c
X#ifdef USE_SUSPENDED
X "suspended (tty input)",
X#else
X "stopped (tty input)",
X#endif
X.
X/SIGTTOU/c
X#ifdef USE_SUSPENDED
X "suspended (tty output)",
X#else
X "stopped (tty output)",
X#endif
X.
Xw
Xq
Xfoo
Xfi
X(sed 's/.*/ "&",/' signams.h
Xecho ' "ERR",
X "DEBUG",
X NULL
X};
X
X#else
X
Xextern char *sigs[SIGCOUNT+4],*sigmsg[SIGCOUNT+2];
X
X#endif') >>signals.h
Xrm signams.h
Xecho done
Xecho 'Building Makefile...' | tr -d '\012'
Xexec >Makefile
Xcat <<'foo'
X#! /bin/make -f
X# Makefile for zsh
X# generated by buildzsh
X
XOBJS=builtin.o cond.o exec.o glob.o hist.o init.o jobs.o lex.o loop.o \
Xmath.o mem.o params.o parse.o subst.o table.o text.o utils.o watch.o \
Xzle_bindings.o zle_hist.o zle_main.o zle_misc.o zle_move.o zle_refresh.o \
Xzle_tricky.o zle_utils.o zle_vi.o zle_word.o
X
XBINDIR=/usr/local/bin
XMANDIR=/usr/local/man/man1
X
X# debugging flags
X#CFLAGS=-g -Wreturn-type -Wunused -Wpointer-arith -DQDEBUG
X#CC=gcc -traditional
X
XCC=cc
Xfoo
Xif test -f /usr/include/ndir.h -a ! -f /usr/lib/libBSD.a
Xthen echo 'CFLAGS= -O -Aa'
Xelif strings /usr/bin/cc 2>/dev/null | grep cckr >/dev/null 2>&1
Xthen echo 'CFLAGS= -O -cckr'
Xelse echo 'CFLAGS= -O'
Xfi
Xif test -f /bin/hinv
Xthen
Xif grep '^\+' /etc/passwd >/dev/null
Xthen echo 'LIBS= -lcurses -lmalloc -lbsd -lsun'
Xelse echo 'LIBS= -lcurses -lmalloc -lbsd'
Xfi
Xelif test -f /usr/lib/libcposix.a
Xthen echo 'LIBS= -lcposix -ltermcap'
Xelif test -f /usr/lib/libBSD.a
Xthen echo 'LIBS= -ltermcap -lBSD'
Xelif test -f /usr/lib/libtermcap.a || test -f /usr/ucblib/libtermcap.a
Xthen
X if grep 'Property of IBM' /usr/include/stdio.h >/dev/null 2>&1
X then echo 'LIBS= -lcurses'
X else echo 'LIBS= -ltermcap'
X fi
Xelse echo 'LIBS= -lcurses'
Xfi
Xcat <<'foo'
X
XZSHPATH=zsh
X
X.c.o:
X $(CC) $(CFLAGS) -c $<
X
Xall: $(ZSHPATH)
X
X$(ZSHPATH): $(OBJS)
X $(CC) -o $(ZSHPATH) $(OBJS) $(LIBS) $(LFLAGS)
X
Xtags: /tmp
X ctags *.[cy]
X
X# I hate this next line
X$(OBJS): config.h zsh.h zle.h signals.h ztype.h funcs.h
X
Xclean:
X rm -f *.o zsh core
X
Xcleanall:
X rm -f *.o zsh core Makefile signals.h config.h
X
Xinstall: zsh
X install -s -m 755 zsh $(BINDIR)
X install -m 444 ../man/man1/zsh.1 $(MANDIR)
Xfoo
Xexec 1>&2
Xcat <<'foo'
Xdone
X
XYou may want to look at the files I just created (config.h, Makefile,
Xand signals.h) to make sure they are correct. Or you may just want
Xto go ahead and try running make now to see what happens.
X
Xfoo
Xecho 'Shall I execute make now?' | tr -d '\012'
Xread reply
Xecho
Xcase "$reply" in
X[yY]*) exec make ;;
Xesac
X
SHAR_EOF
chmod 0755 zsh2.2/src/buildzsh ||
echo 'restore of zsh2.2/src/buildzsh failed'
Wc_c="`wc -c < 'zsh2.2/src/buildzsh'`"
test 11626 -eq "$Wc_c" ||
echo 'zsh2.2/src/buildzsh: original size 11626, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/builtin.c ==============
if test -f 'zsh2.2/src/builtin.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/builtin.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/builtin.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/builtin.c' &&
X/*
SHAR_EOF
true || echo 'restore of zsh2.2/src/builtin.c failed'
fi
echo 'End of zsh2.2 part 5'
echo 'File zsh2.2/src/builtin.c is continued in part 6'
echo 6 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 11:59:47 AM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 102
Archive-name: zsh2.2/part06

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.06 (part 6 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/builtin.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 6; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/builtin.c'
else
echo 'x - continuing file zsh2.2/src/builtin.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/builtin.c' &&

X *
X * builtin.c - builtin commands
X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X#include <sys/errno.h>
X
X#define makecond() allocnode(N_COND)
X
X/* builtin flags */
X
X#define BINF_PLUSOPTS 1 /* +xyz legal */
X#define BINF_R 2 /* this is r (fc -e -) */
X#define BINF_PRINTOPTS 4
X#define BINF_SETOPTS 8
X#define BINF_FCOPTS 16
X#define BINF_TYPEOPT 32
X#define BINF_TYPEOPTS (BINF_TYPEOPT|BINF_PLUSOPTS)
X#define BINF_ECHOPTS 64
X
X/* builtin funcs */
X
X#define BIN_TYPESET 0
X#define BIN_BG 1
X#define BIN_FG 2
X#define BIN_JOBS 3
X#define BIN_WAIT 4
X#define BIN_DISOWN 5
X#define BIN_BREAK 6
X#define BIN_CONTINUE 7
X#define BIN_EXIT 8
X#define BIN_RETURN 9
X#define BIN_SHIFT 10
X#define BIN_CD 11
X#define BIN_POPD 12
X#define BIN_PUSHD 13
X#define BIN_PRINT 14
X#define BIN_EVAL 15
X#define BIN_SCHED 16
X#define BIN_FC 17
X#define BIN_PUSHLINE 18
X#define BIN_LOGOUT 19
X#define BIN_BUILTIN 20
X#define BIN_TEST 21
X#define BIN_BRACKET 22
X
Xstruct bincmd {
X char *name;
X int (*handlerfunc) DCLPROTO((char *,char **,char *,int));
X int minargs; /* min # of args */
X int maxargs; /* max # of args, or -1 for no limit */
X int flags; /* BINF_flags (see above) */
X int funcid; /* xbins (see above) for overloaded handlerfuncs */
X char *optstr; /* string of legal options */
X char *defopts; /* options set by default for overloaded handlerfuncs */
X };
X
X/* structure for foo=bar assignments */
X
Xstruct asgment {
X struct asgment *next;
X char *name,*value;
X };
X
Xstatic char *auxdata;
Xstatic int auxlen;
Xstatic int showflag = 0,showflag2 = 0;
X
Xstruct bincmd builtins[] = {
X "[",bin_test,0,-1,0,BIN_BRACKET,NULL,NULL,
X ".",bin_dot,1,-1,0,0,NULL,NULL,
X ":",bin_colon,0,-1,0,0,NULL,NULL,
X "alias",bin_alias,0,-1,0,0,"ga",NULL,
X "autoload",bin_typeset,0,-1,BINF_TYPEOPTS,0,"tx","fu",
X "bg",bin_fg,0,-1,0,BIN_BG,NULL,NULL,
X "bindkey",bin_bindkey,0,-1,0,0,"asvemdrl",NULL,
X "break",bin_break,0,1,0,BIN_BREAK,NULL,NULL,
X "builtin",NULL,0,0,0,BIN_BUILTIN,NULL,NULL,
X "bye",bin_break,0,1,0,BIN_EXIT,NULL,NULL,
X "cd",bin_cd,0,2,0,BIN_CD,NULL,NULL,
X "chdir",bin_cd,0,2,0,BIN_CD,NULL,NULL,
X "compctl",bin_compctl,0,-1,0,0,NULL,NULL,
X "continue",bin_break,0,1,0,BIN_CONTINUE,NULL,NULL,
X "declare",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL,
X "dirs",bin_dirs,0,-1,0,0,"v",NULL,
X "disable",bin_disable,1,-1,0,0,NULL,NULL,
X "disown",bin_fg,1,-1,0,BIN_DISOWN,NULL,NULL,
X "echo",bin_print,0,-1,BINF_PRINTOPTS|BINF_ECHOPTS,BIN_PRINT,"n","-",
X "echotc",bin_echotc,1,-1,0,0,NULL,NULL,
X "enable",bin_enable,1,-1,0,0,NULL,NULL,
X "eval",bin_eval,0,-1,0,BIN_EVAL,NULL,NULL,
X "exit",bin_break,0,1,0,BIN_EXIT,NULL,NULL,
X "export",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtu","x",
X "false",bin_let,0,0,0,0,NULL,NULL,
X "fc",bin_fc,0,-1,BINF_FCOPTS,BIN_FC,"nlreRWAdD",NULL,
X "fg",bin_fg,0,-1,0,BIN_FG,NULL,NULL,
X "functions",bin_typeset,0,-1,BINF_TYPEOPTS,0,"tu","f",
X "getln",bin_read,0,-1,0,0,NULL,"zr",
X "getopts",bin_getopts,2,-1,0,0,NULL,NULL,
X "hash",bin_hash,2,2,0,0,"r",NULL,
X "history",bin_fc,0,-1,0,BIN_FC,"nrdD","l",
X "integer",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZlrtux","i",
X "jobs",bin_fg,0,-1,0,BIN_JOBS,"lpZ",NULL,
X "kill",bin_kill,0,-1,0,0,NULL,NULL,
X "let",bin_let,1,-1,0,0,NULL,NULL,
X "limit",bin_limit,0,-1,0,0,"sh",NULL,
X "local",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL,
X "log",bin_log,0,0,0,0,NULL,NULL,
X "logout",bin_break,0,1,0,BIN_LOGOUT,NULL,NULL,
X "popd",bin_cd,0,2,0,BIN_POPD,NULL,NULL,
X "print",bin_print,0,-1,BINF_PRINTOPTS,BIN_PRINT,"RDPnrslzNu0123456789p-",NULL,
X "pushd",bin_cd,0,2,0,BIN_PUSHD,NULL,NULL,
X "pushln",bin_print,0,-1,BINF_PRINTOPTS,BIN_PRINT,NULL,"-nz",
X "pwd",bin_pwd,0,0,0,0,NULL,NULL,
X "r",bin_fc,0,-1,BINF_R,BIN_FC,"nrl",NULL,
X "read",bin_read,0,-1,0,0,"rzu0123456789p",NULL,
X "readonly",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfiltux","r",
X "rehash",bin_rehash,0,0,0,0,"f",NULL,
X "return",bin_break,0,1,0,BIN_RETURN,NULL,NULL,
X "sched",bin_sched,0,-1,0,0,NULL,NULL,
X "set",bin_set,0,-1,BINF_SETOPTS|BINF_PLUSOPTS,0,"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZaefghijklnosuvwxy",NULL,
X "setopt",bin_setopt,0,-1,BINF_PLUSOPTS,0,"0123456789BCDEFGHIJKLMNOPQRSTUVWXYZaefghijklmnosuvwxy",NULL,
X "shift",bin_break,0,1,0,BIN_SHIFT,NULL,NULL,
X "source",bin_dot,1,-1,0,0,NULL,NULL,
X "suspend",bin_suspend,0,0,0,0,"f",NULL,
X "test",bin_test,0,-1,0,BIN_TEST,NULL,NULL,
X "ttyctl",bin_ttyctl,0,0,0,0,"fu",NULL,
X "times",bin_times,0,0,0,0,NULL,NULL,
X "trap",bin_trap,0,-1,0,0,NULL,NULL,
X "true",bin_colon,0,0,0,0,NULL,NULL,
X "type",bin_whence,0,-1,0,0,"pfa","v",
X "typeset",bin_typeset,0,-1,BINF_TYPEOPTS,0,"LRZfilrtux",NULL,
X "ulimit",bin_ulimit,0,1,0,0,"HSacdfmnt",NULL,
X "umask",bin_umask,0,1,0,0,NULL,NULL,
X "unalias",bin_unalias,1,-1,0,0,NULL,NULL,
X "unfunction",bin_unhash,1,-1,0,0,NULL,NULL,
X "unhash",bin_unhash,1,-1,0,0,NULL,NULL,
X "unlimit",bin_unlimit,0,-1,0,0,"h",NULL,
X "unset",bin_unset,1,-1,0,0,NULL,NULL,
X "unsetopt",bin_setopt,0,-1,BINF_PLUSOPTS,1,"0123456789BCDEFGHIJKLMNOPQRSTUWXYZabefghijklmnosuvwxy",NULL,
X "vared",bin_vared,1,1,0,0,NULL,NULL,
X "wait",bin_fg,0,-1,0,BIN_WAIT,NULL,NULL,
X "whence",bin_whence,0,-1,0,0,"pvcfa",NULL,
X "which",bin_whence,0,-1,0,0,"pa","c",
X NULL,NULL,0,0,0,0,NULL,NULL
X };
X
X/* print options */
X
Xstatic void prtopt()
X{
Xstruct option *opp;
X
X if (isset(KSHOPTIONPRINT)) {
X printf("Current option settings\n");
X for (opp = optns; opp->name; opp++)
X printf("%-20s%s\n", opp->name,
X (opts[opp->id] == OPT_SET) ? "on" : "off");
X } else
X for (opp = optns; opp->name; opp++)
X if (opts[opp->id] == OPT_SET)
X puts(opp->name);
X}
X
X/* add builtins to the command hash table */
X
Xvoid addbuiltins() /**/
X{
Xstruct cmdnam *c;
Xstruct bincmd *b;
Xint t0;
X
X for (t0 = 0, b = builtins; b->name; b++,t0++)
X {
X c = (Cmdnam) zcalloc(sizeof *c);
X c->type = BUILTIN;
X c->u.binnum = t0;
X addhperm(b->name,c,cmdnamtab,freecmdnam);
X }
X}
X
X/* enable */
X
Xint bin_enable(name,argv,ops,whocares) /**/
Xchar *name;char **argv;char *ops;int whocares;
X{
Xstruct cmdnam *c;
Xstruct bincmd *b;
Xint t0,ret = 0;
X
X for (; *argv; argv++)
X {
X for (t0 = 0, b = builtins; b->name; b++,t0++)
X if (!strcmp(*argv,b->name))
X break;
X if (!b->name)
X {
X zerrnam(name,"no such builtin: %s",*argv,0);
X ret = 1;
X }
X else
X {
X c = (Cmdnam) zcalloc(sizeof *c);
X c->type = BUILTIN;
X c->u.binnum = t0;
X addhperm(b->name,c,cmdnamtab,freecmdnam);
X }
X }
X return ret;
X}
X
X/* :, true */
X
Xint bin_colon(name,argv,ops,whocares) /**/
Xchar *name;char **argv;char *ops;int whocares;
X{
X return 0;
X}
X
X/* break, bye, continue, exit, logout, return, shift */
X
Xint bin_break(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xint num = -1;
X
X if (*argv)
X num = matheval(*argv);
X if ((func == BIN_BREAK || func == BIN_CONTINUE) && !loops)
X {
X if (func == BIN_CONTINUE)
X zerrnam(name,"not in loop",NULL,0);
X return 1;
X }
X switch (func)
X {
X case BIN_CONTINUE:
X contflag = 1;
X case BIN_BREAK:
X breaks = (num == -1) ? 1 : num;
X if (breaks > loops) breaks = loops;
X break;
X case BIN_LOGOUT:
X if (!islogin)
X {
X zerrnam(name,"not login shell",NULL,0);
X return 1;
X }
X case BIN_EXIT:
X zexit((num == -1) ? lastval : num);
X break;
X case BIN_RETURN:
X retflag = 1;
X return lastval = (num == -1) ? lastval : num;
X case BIN_SHIFT:
X {
X char **s;
X
X if (num == -1)
X num = 1;
X if (num > arrlen(pparams))
X num = arrlen(pparams);
X permalloc();
X s = arrdup(pparams+num);
X heapalloc();
X freearray(pparams);
X pparams = s;
X break;
X }
X }
X return 0;
X}
X
X/* bg, disown, fg, jobs, wait */
X
Xint bin_fg(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xint job,lng,firstjob = -1,retval = 0;
X
X if (ops['Z']) { if (*argv) strcpy(hackzero,*argv); return 0; }
X lng = (ops['l']) ? 1 : (ops['p']) ? 2 : 0;
X if ((func == BIN_FG || func == BIN_BG) && !jobbing)
X {
X zerrnam(name,"no job control in this shell.",NULL,0);
X return 1;
X }
X if (unset(NOTIFY)) scanjobs();
X if (!(jobtab[curjob].stat & STAT_INUSE))
X {
X curjob = prevjob; setprevjob();
X if (!(jobtab[curjob].stat & STAT_INUSE))
X curjob = prevjob; setprevjob();
X }
X if (func == BIN_JOBS)
X stopmsg = 2;
X if (!*argv)
X if (func == BIN_FG || func == BIN_BG)
X {
X if (curjob == -1 || curjob == thisjob)
X {
X zerrnam(name,"no current job",NULL,0);
X return 1;
X }
X firstjob = curjob;
X }
X else if (func == BIN_JOBS)
X {
X for (job = 0; job != MAXJOB; job++)
X if (job != thisjob && jobtab[job].stat)
X printjob(job+jobtab,lng);
X return 0;
X }
X else
X {
X for (job = 0; job != MAXJOB; job++)
X if (job != thisjob && jobtab[job].stat)
X waitjob(job);
X return lastval;
X }
X for (; (firstjob != -1) || *argv; ( void ) (*argv && argv++))
X {
X int stopped,ocj = thisjob;
X
X if (func == BIN_WAIT && isanum(*argv)) {
X waitforpid((long) atoi(*argv));
X retval = lastval;
X thisjob = ocj;
X continue;
X }
X job = (*argv) ? getjob(*argv,name) : firstjob;
X firstjob = -1;
X if (job == -1)
X break;
X if (!(jobtab[job].stat & STAT_INUSE))
X {
X zerrnam(name,"no such job: %d",0,job);
X return 1;
X }
X switch (func)
X {
X case BIN_FG:
X case BIN_BG:
X if (stopped = (jobtab[job].stat & STAT_STOPPED))
X makerunning(jobtab+job);
X else if (func == BIN_BG)
X {
X zerrnam(name,"job already in background",NULL,0);
X thisjob = ocj;
X return 1;
X }
X if (curjob == job)
X {
X curjob = prevjob;
X prevjob = (func == BIN_BG) ? -1 : job;
X }
X if (prevjob == job)
X prevjob = -1;
X if (prevjob == -1)
X setprevjob();
X if (curjob == -1)
X {
X curjob = prevjob;
X setprevjob();
X }
X printjob(jobtab+job,(stopped) ? -1 : 0);
X if (func == BIN_FG)
X {
X thisjob = job;
X if (strcmp(jobtab[job].pwd,pwd))
X {
X printf("(pwd : ");
X printdir(jobtab[job].pwd);
X printf(")\n");
X }
X fflush(stdout);
X attachtty(jobtab[job].gleader);
X }
X if (stopped)
X killpg(jobtab[job].gleader,SIGCONT);
X if (func == BIN_FG)
X waitjobs();
X break;
X case BIN_JOBS:
X printjob(job+jobtab,lng);
X break;
X case BIN_WAIT:
X waitjob(job);
X retval = lastval;
X break;
X case BIN_DISOWN:
X {
X static struct job zero;
X jobtab[job] = zero;
X break;
X }
X }
X thisjob = ocj;
X }
X return retval;
X}
X
X/* false, let */
X
Xint bin_let(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xlong val = 0;
X
X while (*argv)
X val = matheval(*argv++);
X return !val;
X}
X
X/* print the directory stack */
X
Xstatic void pdstack()
X{
XLknode node;
X
X printdir(pwd);
X for (node = firstnode(dirstack); node; incnode(node))
X {
X putchar(' ');
X printdir(getdata(node));
X }
X putchar('\n');
X}
X
X/* exit the shell */
X
Xint zexit(val) /**/
Xint val;
X{
X if (isset(MONITOR))
X if (!stopmsg) {
X checkjobs();
X if (stopmsg) {
X stopmsg = 2;
X return 1;
X }
X } else killrunjobs();
X savehistfile(getsparam("HISTFILE"),0,0);
X if (islogin && unset(NORCS))
X sourcehome(".zlogout");
X if (sigtrapped[SIGEXIT])
X dotrap(SIGEXIT);
X exit(val); return 0;
X}
X
X/* identify an option name */
X
Xint optlookup(s) /**/
Xchar *s;
X{
Xchar *t;
Xstruct option *o;
X
X t = s = strdup(s);
X while (*t)
X if (*t == '_')
X chuck(t);
X else {
X *t = tulower(*t);
X t++;
X }
X for (o = optns; o->name; o++)
X if (!strcmp(o->name,s))
X return o->id;
X return -1;
X}
X
X/* setopt, unsetopt */
X
Xint bin_setopt(nam,args,ops,isun) /**/
Xchar *nam;char **args;char *ops;int isun;
X{
Xstruct option *opp;
Xint c;
X
X if (!ops['@'] && !*args) {
X if (!isun)
X prtopt();
X return 0;
X }
X for (opp = optns; opp->name; opp++)
X if (ops[opp->id] == 1+isun)
X opts[opp->id] = OPT_SET;
X else if (ops[opp->id] == 2-isun)
X opts[opp->id] = OPT_UNSET;
X while (*args) {
X c = optlookup(*args++);
X if (c != -1) {
X if (c == INTERACTIVE || c == MONITOR)
X zerrnam(nam,"can't change that option",NULL,0);
X else
X opts[c] = (isun) ? OPT_UNSET : OPT_SET;
X } else {
X zerrnam(nam,"no such option: %s",args[-1],0);
X return 1;
X }
X }
X return 0;
X}
X
X/* execute func on each member of the hash table ht */
X
Xvoid listhtable(ht,func) /**/
XHashtab ht;HFunc func;
X{
Xint t0;
Xstruct hashnode *hn;
X
X for (t0 = ht->hsize-1; t0 >= 0; t0--)
X for (hn = ht->nodes[t0]; hn; hn = hn->next)
X func(hn->nam,(char *) hn);
X}
X
X/* print a shell function (used with listhtable) */
X
Xvoid pshfunc(s,cc) /**/
Xchar *s;Cmdnam cc;
X{
Xchar *t;
X
X if (cc->type != SHFUNC)
X return;
X if (showflag && (cc->flags & showflag2) != showflag2)
X return;
X if (cc->flags & PMFLAG_u)
X printf("undefined ");
X if (cc->flags & PMFLAG_t)
X printf("traced ");
X if (!cc->u.list || !showflag) {
X printf("%s ()\n",s);
X return;
X }
X t = getpermtext((vptr) (cc->u.list));
X printf("%s () {\n\t%s\n}\n",s,t);
X free(t);
X}
X
Xvoid niceprint(s) /**/
Xchar *s;
X{
X niceprintf(s,stdout);
X}
X
Xvoid niceprintf(s,f) /**/
Xchar *s;FILE *f;
X{
X for (; *s; s++)
X {
X if (isprint(*s))
X fputc(*s,f);
X else if (*s == '\n')
X {
X putc('\\',f);
X putc('n',f);
X }
X else
X {
X putc('^',f);
X fputc(*s | 0x40,f);
X }
X }
X}
X
Xint bin_umask(nam,args,ops,func) /**/
Xchar *nam;char **args;char *ops;int func;
X{
Xint um;
Xchar *s = *args;
X
X um = umask(0);
X umask(um);
X if (!s)
X {
X printf("%03o\n",um);
X return 0;
X }
X if (idigit(*s))
X {
X um = zstrtol(s,&s,8);
X if (*s)
X {
X zerrnam(nam,"bad umask",NULL,0);
X return 1;
X }
X }
X else
X {
X int whomask,op,mask;
X
X for (;;)
X {
X if (*s == 'u')
X s++, whomask = 0100;
X else if (*s == 'g')
X s++, whomask = 0010;
X else if (*s == 'o')
X s++, whomask = 0001;
X else
X whomask = 0111;
X op = *s++;
X if (!(op == '+' || op == '-' || op == '='))
X {
X zerrnam(nam,"bad symbolic mode operator: %c",NULL,op);
X return 1;
X }
X mask = whomask;
X if (*s == 'r')
X mask *= 04;
X else if (*s == 'w')
X mask *= 02;
X else if (*s != 'x')
X {
X zerrnam(nam,"bad symbolic mode permission: %c",NULL,*s);
X return 1;
X }
X if (op == '+')
X um |= mask;
X else if (op == '-')
X um &= ~mask;
X else /* op == '=' */
X um = (um & ~(whomask*07)) | mask;
X if (*++s == ',')
X s++;
X else
X break;
X }
X if (*s)
X {
X zerrnam(nam,"bad character in symbolic mode: %c",NULL,*s);
X return 1;
X }
X }
X umask(um);
X return 0;
X}
X
X/* type, whence, which */
X
Xint bin_whence(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
Xstruct cmdnam *chn;
Xstruct alias *a;
Xint retval = 0;
Xint csh = ops['c'],all = ops['a'];
Xint v = ops['v'] || csh;
Xchar *cnam;
X
X for (; *argv; argv++) {
X if (!ops['p'] && (a = (Alias) gethnode(*argv,aliastab))) {
X if (a->cmd < 0)
X printf((csh) ? "%s: shell reserved word\n" :
X (v) ? "%s is a reserved word\n" : "%s\n",*argv);
X else if (!v)
X puts(a->text);
X else if (a->cmd)
X printf((csh) ? "%s: aliased to %s\n" :
X "%s is an alias for %s\n",*argv,a->text);
X else
X printf((csh) ? "%s: globally aliased to %s\n" :
X "%s is a global alias for %s\n",*argv,a->text);
X retval = 0;
X if (!all) continue;
X }
X if (!ops['p'] && (chn = (Cmdnam) gethnode(*argv,cmdnamtab)) &&
X (chn->type == SHFUNC || chn->type == BUILTIN)) {
X if (chn->type == SHFUNC) {
X if (csh || ops['f']) {
X showflag = 1; showflag2 = 0;
X pshfunc(*argv,chn);
X } else {
X printf((v) ? "%s is a function\n" : "%s\n",*argv);
X }
X } else
X printf((csh) ? "%s: shell built-in command\n" :
X (v) ? "%s is a shell builtin\n" : "%s\n",*argv);
X retval = 0;
X if (!all) continue;
X }
X if (all) {
X char **pp,buf[MAXPATHLEN],*z;
X for (pp = path; *pp; pp++) {
X z = buf;
X strucpy(&z,*pp);
X *z++ = '/';
X strcpy(z,*argv);
X if (iscom(buf)) {
X if (v && !csh) printf("%s is %s\n",*argv,buf);
X else puts(buf);
X retval = 0;
X }
X }
X } else if (!(cnam = findcmd(*argv))) {
X if (v) printf("%s not found\n",*argv);
X retval = 1;
X break;
X } else {
X if (v && !csh) printf("%s is %s\n",*argv,cnam);
X else puts(cnam);
X retval = 0;
X }
X }
X return retval;
X}
X
X/* cd, chdir, pushd, popd */
X
Xint bin_cd(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
Xchar *dest;
X
X if (func == BIN_CD && isset(AUTOPUSHD))
X func = BIN_PUSHD;
X dest = cd_get_dest(nam,argv,ops,func);
X if (!dest) return 1;
X dest = cd_do_chdir(nam,dest);
X if (!dest) return 1;
X cd_new_pwd(func,dest);
X return 0;
X}
X
Xchar *cd_get_dest(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
Xchar *dest;
X
X if (!argv[0])
X if (func == BIN_CD || (func == BIN_PUSHD && isset(PUSHDTOHOME)
X || !full(dirstack)))
X dest = home;
X else
X dest = getnode(dirstack);
X else if (!argv[1]) {
X Lknode n;
X int dd;
X
X if (argv[0][1] && argv[0][0] == (isset(PUSHDMINUS) ? '-' : '+')) {
X dd = atoi(argv[0]+1)-1;
X if (dd < 0) {
X zerrnam(nam,"bad directory specification",NULL,0);
X return NULL;
X }
X for (n = firstnode(dirstack); n && dd; dd--, incnode(n));
X if (!n) {
X zerrnam(nam,"no such entry in dir stack",NULL,0);
X return NULL;
X }
X dest = remnode(dirstack,n);
X } else if (argv[0][1] && argv[0][0] == (isset(PUSHDMINUS) ? '+' : '-')) {
X dd = atoi(argv[0]+1);
X for (n = lastnode(dirstack); n != (Lknode) dirstack && dd;
X dd--, n = prevnode(n));
X if (n == (Lknode) dirstack) {
X zerrnam(nam,"no such entry in dir stack",NULL,0);
X return NULL;
X }
X dest = remnode(dirstack,n);
X } else {
X if (!strcmp(argv[0],"-")) printdircr(dest = oldpwd);
X else dest = argv[0];
X }
X } else {
X char *u;
X int len1,len2,len3;
X
X if (!(u = ztrstr(pwd,argv[0]))) {
X zerrnam(nam,"string not in pwd: %s",argv[0],0);
X return NULL;
X }
X len1 = strlen(argv[0]);
X len2 = strlen(argv[1]);
X len3 = u-pwd;
X dest = alloc(len3+len2+strlen(u+len1)+1);
X strncpy(dest,pwd,len3);
X strcpy(dest+len3,argv[1]);
X strcat(dest,u+len1);
X printdircr(dest);
X }
X return dest;
X}
X
Xchar *cd_do_chdir(cnam,dest) /**/
Xchar *cnam; char *dest;
X{
Xint hasdot = 0, eno = ENOENT;
Xchar **pp,*ret;
X
X if (*dest == '/') {
X if (ret = cd_try_chdir(NULL,dest)) return ret;
X zerrnam(cnam,"%e: %s",dest,errno);
X return NULL;
X }
X for (pp = cdpath; *pp; pp++)
X if ((*pp)[0] == '.' && (*pp)[1] == '\0') hasdot = 1;
X if (!hasdot) {
X if (ret = cd_try_chdir(NULL,dest)) return ret;
X if (errno != ENOENT) eno = errno;
X }
X for (pp = cdpath; *pp; pp++) {
X if (ret = cd_try_chdir(*pp,dest)) {
X if (strcmp(*pp,".")) {
X printdircr(ret);
X }
X return ret;
X }
X if (errno != ENOENT) eno = errno;
X }
X if (isset(CDABLEVARS)) {
X char *s = getsparam(dest);
X if (s && *s == '/' && chdir(s) != -1) {
X printdircr(s);
X return s;
X }
X if (errno != ENOENT) eno = errno;
X }
X zerrnam(cnam,"%e: %s",dest,eno);
X return NULL;
X}
X
Xchar *cd_try_chdir(pfix,dest) /**/
Xchar *pfix; char *dest;
X{
Xstatic char buf[MAXPATHLEN], buf2[MAXPATHLEN];
Xchar *s;
Xint dotsct;
X
X if (pfix) sprintf(buf,"%s/%s",(!strcmp("/",pfix)) ? "" : pfix,dest);
X else strcpy(buf,dest);
X dotsct = fixdir(buf2,buf);
X if (buf2[0] == '/') return (chdir(buf2) == -1) ? NULL : buf2;
X if (!dotsct) {
X if (chdir((*buf2) ? buf2 : ".") == -1) return NULL;
X if (*buf2) sprintf(buf,"%s/%s",(!strcmp("/",pwd)) ? "" : pwd,buf2);
X else strcpy(buf,pwd);
X return buf;
X }
X strcpy(buf,pwd);
X s = buf+strlen(buf)-1;
X while (dotsct--) while (s != buf) if (*--s == '/') break;
X if (s == buf || *buf2) s++;
X strcpy(s,buf2);
X if (chdir(buf) != -1 || chdir(dest) != -1) return buf;
X return NULL;
X}
X
Xint fixdir(d,s) /**/
Xchar *d; char *s;
X{
Xint ct = 0;
Xchar *d0 = d;
X
X#ifdef HAS_RFS
X if (*s == '/' && s[1] == '.' && s[2] == '.') {
X *d++ = '/'; *d++ = '.'; *d++ = '.';
X s += 3;
X }
X#endif
X for (;;) {
X if (*s == '/') {
X *d++ = *s++;
X while (*s == '/') s++;
X }
X if (!*s) {
X while (d > d0+1 && d[-1] == '/') d--;
X *d = '\0';
X return ct;
X }
X if (s[0] == '.' && s[1] == '.' && (s[2] == '\0' || s[2] == '/')) {
X if (d > d0+1) {
X for (d--; d > d0+1 && d[-1] != '/'; d--);
X } else ct++;
X s += 2; if (*s) s++;
X } else if (s[0] == '.' && (s[1] == '/' || s[1] == '\0')) {
X s++; if (*s) s++;
X } else {
X while (*s != '/' && *s != '\0') *d++ = *s++;
X }
X }
X}
X
Xvoid cd_new_pwd(func,s) /**/
Xint func; char *s;
X{
XParam pm;
XList l;
X
X oldpwd = pwd;
X if (isset(CHASELINKS))
X pwd = findpwd(s);
X else
X pwd = ztrdup(s);
X if ((pm = gethnode("PWD", paramtab)) &&
X (pm->flags & PMFLAG_x) && pm->env)
X pm->env = replenv(pm->env,pwd);
X if ((pm = gethnode("OLDPWD", paramtab)) &&
X (pm->flags & PMFLAG_x) && pm->env)
X pm->env = replenv(pm->env,oldpwd);
X if (func == BIN_PUSHD) {
X permalloc();
X if (isset(PUSHDIGNOREDUPS)) {
X Lknode n;
X for (n = firstnode(dirstack); n; incnode(n))
X if (!strcmp(oldpwd,getdata(n))) {
X free(remnode(dirstack,n)); break;
X }
X }
X pushnode(dirstack,oldpwd);
X heapalloc();
X }
X if (unset(PUSHDSILENT) && func != BIN_CD && isset(INTERACTIVE))
X pdstack();
X if (l = getshfunc("chpwd")) {
X fflush(stdout); fflush(stderr);
X doshfuncnoval(dupstruct(l),NULL,0);
X }
X if (dirstacksize != -1 && countnodes(dirstack) >= dirstacksize) {
X if (dirstacksize < 2)
X dirstacksize = 2;
X else
X free(remnode(dirstack,lastnode(dirstack)));
X }
X}
X
Xvoid convertwd(s,t,off) /**/
Xchar *s; char *t; int off;
X{
Xchar *u,*start;
X
X *t++ = '/';
X start = t;
X while (off--) *t++ = *s++;
X for (;;) {
X while (*s == '/') s++;
X for (u = s; *u && *u != '/'; u++);
X if (!strncmp(s,".",u-s)) {
X ;
X } else if (!strncmp(s,"..",u-s)) {
X while (t != start && *--t != '/');
X } else {
X if (t != start) *t++ = '/';
X struncpy(&t,s,u-s);
X }
X if (!*u) break;
X s = u;
X }
X *t = '\0';
X}
X
Xint bin_rehash(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
X newcmdnamtab();
X if (ops['f']) fullhash();
X return 0;
X}
X
Xint bin_hash(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xstruct cmdnam *chn;
X
X chn = (Cmdnam) zcalloc(sizeof *chn);
X chn->type = EXCMD;
X chn->pcomp = NULL; /* this is probably a bug ! */
X chn->u.nam = ztrdup(argv[1]);
X addhnode(ztrdup(argv[0]),chn,cmdnamtab,freecmdnam);
X return 0;
X}
X
X/* != 0 if s is a prefix of t */
X
Xint prefix(s,t) /**/
Xchar *s;char *t;
X{
X while (*s && *t && *s == *t) s++,t++;
X return (!*s);
X}
X
X/* convert %%, %1, %foo, %?bar? to a job number */
X
Xint getjob(s,prog) /**/
Xchar *s;char *prog;
X{
Xint t0,retval;
X
X if (*s != '%')
X goto jump;
X s++;
X if (*s == '%' || *s == '+' || !*s)
X {
X if (curjob == -1)
X {
X zerrnam(prog,"no current job",NULL,0);
X retval = -1; goto done;
X }
X retval = curjob; goto done;
X }
X if (*s == '-')
X {
X if (prevjob == -1)
X {
X zerrnam(prog,"no previous job",NULL,0);
X retval = -1; goto done;
X }
X retval = prevjob; goto done;
X }
X if (idigit(*s))
X {
X t0 = atoi(s);
X if (t0 && t0 < MAXJOB && jobtab[t0].stat && t0 != thisjob)
X { retval = t0; goto done; }
X zerrnam(prog,"no such job",NULL,0);
X retval = -1; goto done;
X }
X if (*s == '?')
X {
X struct process *pn;
X
X for (t0 = MAXJOB-1; t0 >= 0; t0--)
X if (jobtab[t0].stat && t0 != thisjob)
X for (pn = jobtab[t0].procs; pn; pn = pn->next)
X if (ztrstr(pn->text,s+1))
X { retval = t0; goto done; }
X zerrnam(prog,"job not found: %s",s,0);
X retval = -1; goto done;
X }
Xjump:
X if ((t0 = findjobnam(s)) != -1)
X { retval = t0; goto done; }
X zerrnam(prog,"job not found: %s",s,0);
X retval = -1;
Xdone:
X return retval;
X}
X
X/* find a job named s */
X
Xint findjobnam(s) /**/
Xchar *s;
X{
Xint t0;
X
X for (t0 = MAXJOB-1; t0 >= 0; t0--)
X if (jobtab[t0].stat && jobtab[t0].procs && t0 != thisjob &&
X jobtab[t0].procs->text && prefix(s,jobtab[t0].procs->text))
X return t0;
X return -1;
X}
X
Xint isanum(s) /**/
Xchar *s;
X{
X while (*s == '-' || idigit(*s)) s++;
X return *s == '\0';
X}
X
Xint bin_kill(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
Xint sig = SIGTERM;
Xint retval = 0;
X
X if (*argv && **argv == '-') {
X if (idigit((*argv)[1]))
X sig = atoi(*argv+1);
X else {
X if ((*argv)[1] == 'l' && (*argv)[2] == '\0') {
X printf("%s",sigs[1]);
X for (sig = 2; sig != SIGCOUNT; sig++)
X printf(" %s",sigs[sig]);
X putchar('\n');
X return 0;
X }
X for (sig = 0; sig != SIGCOUNT; sig++)
X if (!strcmp(sigs[sig],*argv+1)) break;
X if (sig == SIGCOUNT) {
X zerrnam(nam,"unknown signal: SIG%s",*argv+1,0);
X zerrnam(nam,"type kill -l for a List of signals",NULL,0);
X return 1;
X }
X }
X argv++;
X }
X for (; *argv; argv++) {
X if (**argv == '%') {
X int p = getjob(*argv,"kill");
X
X if (p == -1) {
X retval = 1;
X continue;
X }
X if (killjb(jobtab+p,sig) == -1) {
X zerrnam("kill","kill failed: %e",NULL,errno);
X retval = 1;
X continue;
X }
X if (jobtab[p].stat & STAT_STOPPED) {
X if (sig == SIGCONT)
X jobtab[p].stat &= ~STAT_STOPPED;
X if (sig != SIGKILL && sig != SIGCONT && sig != SIGTSTP
X && sig != SIGTTOU && sig != SIGTTIN && sig != SIGSTOP)
X killjb(jobtab+p,SIGCONT);
X }
X } else if (!isanum(*argv)) {
X zerrnam("kill","illegal pid: %s",*argv,0);
X } else if (kill(atoi(*argv),sig) == -1) {
X zerrnam("kill","kill failed: %e",NULL,errno);
X retval = 1;
X }
X }
X return 0;
X}
X
Xstatic char *recs[] = {
X "cputime","filesize","datasize","stacksize","coredumpsize",
X "resident","descriptors"
X };
X
Xint bin_limit(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
X#ifndef RLIM_INFINITY
X zerrnam(nam,"not available on this system",NULL,0);
X return 1;
X#else
Xchar *s;
Xint hard = ops['h'],t0,lim;
Xlong val;
X
X if (ops['s'])
X {
X if (*argv)
X zerrnam(nam,"arguments after -s ignored",NULL,0);
X for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
X if (setrlimit(t0,limits+t0) < 0)
X zerrnam(nam,"setrlimit failed: %e",NULL,errno);
X return 0;
X }
X if (!*argv)
X {
X showlimits(hard,-1);
X return 0;
X }
X while (s = *argv++)
X {
X for (lim = -1, t0 = 0; t0 != RLIM_NLIMITS; t0++)
X if (!strncmp(recs[t0],s,strlen(s)))
X {
X if (lim != -1)
X lim = -2;
X else
X lim = t0;
X }
X if (lim < 0)
X {
X zerrnam("limit",
X (lim == -2) ? "ambiguous resource specification: %s"
X : "no such resource: %s",s,0);
X return 1;
X }
X if (!(s = *argv++))
X {
X showlimits(hard,lim);
X return 0;
X }
X if (!lim)
X {
X val = zstrtol(s,&s,10);
X if (*s)
X if ((*s == 'h' || *s == 'H') && !s[1])
X val *= 3600L;
X else if ((*s == 'm' || *s == 'M') && !s[1])
X val *= 60L;
X else if (*s == ':')
X val = val*60+zstrtol(s+1,&s,10);
X else
X {
X zerrnam("limit","unknown scaling factor: %s",s,0);
X return 1;
X }
X }
X#ifdef RLIMIT_NOFILE
X else if (lim == RLIMIT_NOFILE)
X val = zstrtol(s,&s,10);
X#endif
X else
X {
X val = zstrtol(s,&s,10);
X if (!*s || ((*s == 'k' || *s == 'K') && !s[1]))
X val *= 1024L;
X else if ((*s == 'M' || *s == 'm') && !s[1])
X val *= 1024L*1024;
X else
X {
X zerrnam("limit","unknown scaling factor: %s",s,0);
X return 1;
X }
X }
X if (hard)
X if (val > limits[lim].rlim_max && geteuid())
X {
X zerrnam("limit","can't raise hard limits",NULL,0);
X return 1;
X }
X else
X {
X limits[lim].rlim_max = val;
X if (limits[lim].rlim_max < limits[lim].rlim_cur)
X limits[lim].rlim_cur = limits[lim].rlim_max;
X }
X else
X if (val > limits[lim].rlim_max)
X {
X zerrnam("limit","limit exceeds hard limit",NULL,0);
X return 1;
X }
X else
X limits[lim].rlim_cur = val;
X }
X return 0;
X#endif
X}
X
Xint bin_unlimit(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
X#ifndef RLIM_INFINITY
X zerrnam(nam,"not available on this system",NULL,0);
X return 1;
X#else
Xint hard = ops['h'],t0,lim;
X
X if (hard && geteuid())
X {
X zerrnam(nam,"can't remove hard limits",NULL,0);
X return 1;
X }
X if (!*argv)
X {
X for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
X {
X if (hard)
X limits[t0].rlim_max = RLIM_INFINITY;
X else
X limits[t0].rlim_cur = limits[t0].rlim_max;
X }
X return 0;
X }
X for (; *argv; argv++)
X {
X for (lim = -1, t0 = 0; t0 != RLIM_NLIMITS; t0++)
X if (!strncmp(recs[t0],*argv,strlen(*argv)))
X {
X if (lim != -1)
X lim = -2;
X else
X lim = t0;
X }
X if (lim < 0)
X {
X zerrnam(nam,
X (lim == -2) ? "ambiguous resource specification: %s"
X : "no such resource: %s",*argv,0);
X return 1;
X }
X if (hard)
X limits[lim].rlim_max = RLIM_INFINITY;
X else
X limits[lim].rlim_cur = limits[lim].rlim_max;
X }
X return 0;
X#endif
X}
X
Xvoid showlimits(hard,lim) /**/
Xint hard;int lim;
X{
Xint t0;
Xlong val;
X
X#ifdef RLIM_INFINITY
X for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
X if (t0 == lim || lim == -1)
X {
X printf("%-16s",recs[t0]);
X val = (hard) ? limits[t0].rlim_max : limits[t0].rlim_cur;
X if (val == RLIM_INFINITY)
X printf("unlimited\n");
X else if (!t0)
X printf("%d:%02d:%02d\n",(int) (val/3600),
X (int) (val/60) % 60,(int) (val % 60));
X#ifdef RLIMIT_NOFILE
X else if (t0 == RLIMIT_NOFILE)
X printf("%d\n",(int) val);
X#endif
X else if (val >= 1024L*1024L)
X printf("%ldMb\n",val/(1024L*1024L));
X else
X printf("%ldKb\n",val/1024L);
X }
X#endif
X}
X
Xint bin_sched(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
Xchar *s = *argv++;
Xtime_t t;
Xlong h,m;
Xstruct tm *tm;
Xstruct schedcmd *sch,*sch2,*schl;
Xint t0;
X
X if (s && *s == '-')
X {
X t0 = atoi(s+1);
X
X if (!t0)
X {
X zerrnam("sched","usage for delete: sched -<item#>.",NULL,0);
X return 1;
X }
X for (schl = (struct schedcmd *) &schedcmds, sch = schedcmds, t0--;
X sch && t0; sch = (schl = sch)->next, t0--);
X if (!sch)
X {
X zerrnam("sched","not that many entries",NULL,0);
X return 1;
X }
X schl->next = sch->next;
X free(sch->cmd);
X free(sch);
X return 0;
X }
X if (!s)
X {
X char tbuf[40];
X
X for (t0 = 1, sch = schedcmds; sch; sch = sch->next,t0++)
X {
X t = sch->time;
X tm = localtime(&t);
X ztrftime(tbuf,20,"%a %b %e %k:%M:%S",tm);
X printf("%3d %s %s\n",t0,tbuf,sch->cmd);
X }
X return 0;
X }
X else if (!*argv)
X {
X zerrnam("sched","not enough arguments",NULL,0);
X return 1;
X }
X if (*s == '+')
X {
X h = zstrtol(s+1,&s,10);
X if (*s != ':')
X {
X zerrnam("sched","bad time specifier",NULL,0);
X return 1;
X }
X m = zstrtol(s+1,&s,10);
X if (*s)
X {
X zerrnam("sched","bad time specifier",NULL,0);
X return 1;
X }
X t = time(NULL)+h*3600+m*60;
X }
X else
X {
X h = zstrtol(s,&s,10);
X if (*s != ':')
X {
X zerrnam("sched","bad time specifier",NULL,0);
X return 1;
X }
X m = zstrtol(s+1,&s,10);
X if (*s && *s != 'a' && *s != 'p')
X {
X zerrnam("sched","bad time specifier",NULL,0);
X return 1;
X }
X t = time(NULL);
X tm = localtime(&t);
X t -= tm->tm_sec+tm->tm_min*60+tm->tm_hour*3600;
X if (*s == 'p')
X h += 12;
X t += h*3600+m*60;
X if (t < time(NULL))
X t += 3600*24;
X }
X sch = zcalloc(sizeof *sch);
X sch->time = t;
X sch->cmd = ztrdup(spacejoin(argv));
X sch->next = NULL;
X for (sch2 = (struct schedcmd *) &schedcmds; sch2->next; sch2 = sch2->next);
X sch2->next = sch;
X return 0;
X}
X
Xint bin_eval(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
Xchar *s = ztrdup(spacejoin(argv));
XList list;
X
X hungets(s);
X free(s);
X strinbeg();
X if (!(list = parse_list()))
X {
X hflush();
X strinend();
X return 1;
X }
X strinend();
X runlist(list);
X return lastval;
X}
X
X/* get the history event associated with s */
X
Xint fcgetcomm(s) /**/
Xchar *s;
X{
Xint cmd;
X
X if (cmd = atoi(s))
X {
X if (cmd < 0)
X cmd = curhist+cmd+1;
X return cmd;
X }
X cmd = hcomsearch(s);
X if (cmd == -1)
X zerrnam("fc","event not found: %s",s,0);
X return cmd;
X}
X
X/* perform old=new substituion */
X
Xint fcsubs(sp,sub) /**/
Xchar **sp;struct asgment *sub;
X{
Xchar *s1,*s2,*s3,*s4,*s = *sp,*s5;
Xint subbed = 0;
X
X while (sub)
X {
X s1 = sub->name;
X s2 = sub->value;
X sub = sub->next;
X s5 = s;
X while (s3 = (char *) ztrstr(s5,s1))
X {
X s4 = alloc(1+(s3-s)+strlen(s2)+strlen(s3+strlen(s1)));
X ztrncpy(s4,s,s3-s);
X strcat(s4,s2);
X s5 = s4+strlen(s4);
X strcat(s4,s3+strlen(s1));
X s = s4;
X subbed = 1;
X }
X }
X *sp = s;
X return subbed;
X}
X
X/* print a series of history events to a file */
X
Xint fclist(f,n,r,D,d,first,last,subs) /**/
XFILE *f;int n;int r;int D;int d;int first;int last;struct asgment *subs;
X{
Xint done = 0;
Xchar *s,*hs;
XHistent ent;
X
X if (!subs) done = 1;
X for (;;) {
X hs = quietgetevent(first);
X if (!hs) {
X zerrnam("fc","no such event: %d",NULL,first);
X return 1;
X }
X s = makehstr(hs);
X done |= fcsubs(&s,subs);
X if (n) fprintf(f,"%5d ",first);
X ent = NULL;
X if (d) {
X struct tm *ltm;
X
X if (!ent) ent = gethistent(first);
X ltm = localtime(&ent->stim);
X fprintf(f,"%2d:%02d ",ltm->tm_hour,ltm->tm_min);
X }
X if (D) {
X long diff;
X
X if (!ent) ent = gethistent(first);
X diff = (ent->ftim) ? ent->ftim-ent->stim : 0;
X fprintf(f,"%d:%02d ",diff/60,diff%60);
X }
X if (f == stdout) {
X niceprintf(s,f);
X putc('\n',f);
X } else fprintf(f,"%s\n",s);
X if (first == last) break;
X (r) ? first-- : first++;
X }
X if (f != stdout) fclose(f);
X if (!done) {
X zerrnam("fc","no substitutions performed",NULL,0);
X return 1;
X }
X return 0;
X}
X
Xint fcedit(ename,fn) /**/
Xchar *ename;char *fn;
X{
X if (!strcmp(ename,"-"))
X return 1;
X return !zyztem(ename,fn);
X}
X
X/* fc, history, r */
X
Xint bin_fc(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
Xint first = -1,last = -1,retval,minflag = 0;
Xchar *s;
Xstruct asgment *asgf = NULL,*asgl = NULL;
X
X if (!interact) {
X zerrnam(nam,"not interactive shell",NULL,0);
X return 1;
X }
X if (!(ops['l'] && unset(HISTNOSTORE))) remhist();
X if (ops['R']) {
X readhistfile(*argv ? *argv : getsparam("HISTFILE"),1);
X return 0;
X }
X if (ops['W']) {
X savehistfile(*argv ? *argv : getsparam("HISTFILE"),1,0);
X return 0;
X }
X if (ops['A']) {
X savehistfile(*argv ? *argv : getsparam("HISTFILE"),1,1);
X return 0;
X }
X while (*argv && equalsplit(*argv,&s)) {
X struct asgment *a = (struct asgment *) alloc(sizeof *a);
X
X if (!asgf) asgf = asgl = a;
X else {
X asgl->next = a;
X asgl = a;
X }
X a->name = *argv;
X a->value = s;
X argv++;
X }
X if (*argv) {
X minflag = **argv == '-';
X first = fcgetcomm(*argv);
X if (first == -1) return 1;
X argv++;
X }
X if (*argv) {
X last = fcgetcomm(*argv);
X if (last == -1) return 1;
X argv++;
X }
X if (*argv) {
X zerrnam("fc","too many arguments",NULL,0);
X return 1;
X }
X if (first == -1) first = (ops['l']) ? curhist-16 : curhist;
X if (last == -1) last = (ops['l']) ? curhist : first;
X if (first < firsthist()) first = firsthist();
X if (last == -1) last = (minflag) ? curhist : first;
X if (ops['l'])
X retval = fclist(stdout,!ops['n'],ops['r'],ops['D'],ops['d'],
X first,last,asgf);
X else {
X FILE *out;
X char *fil = gettemp();
X
X out = fopen(fil,"w");
X if (!out)
X zerrnam("fc","can't open temp file: %e",NULL,errno);
X else {
X retval = 1;
X if (!fclist(out,0,ops['r'],0,0,first,last,asgf))
X if (fcedit(auxdata ? auxdata : fceditparam,fil))
X if (stuff(fil))
X zerrnam("fc","%e: %s",s,errno);
X else
X retval = 0;
X }
X unlink(fil);
X }
X return retval;
X}
X
Xint bin_suspend(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
X if (islogin && !ops['f']) {
X zerrnam(name,"can't suspend login shell",NULL,0);
X return 1;
X }
X if (jobbing) {
X signal(SIGPIPE,SIG_DFL);
X signal(SIGTTIN,SIG_DFL);
X signal(SIGTSTP,SIG_DFL);
X signal(SIGTTOU,SIG_DFL);
X }
X kill(0,SIGTSTP);
X if (jobbing) {
X while (gettygrp() != mypgrp) {
X sleep(1);
X if (gettygrp() != mypgrp) kill(0,SIGTTIN);
X }
X signal(SIGTTOU,SIG_IGN);
X signal(SIGTSTP,SIG_IGN);
X signal(SIGTTIN,SIG_IGN);
X signal(SIGPIPE,SIG_IGN);
X }
X return 0;
X}
X
Xint bin_alias(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xstruct alias *an;
Xstruct asgment *asg;
Xint incm = !(ops['a'] || ops['g']),ret = 0;
X
X showflag = !incm;
X if (!*argv)
X listhtable(aliastab,(HFunc) printalias);
X else while (asg = getasg(*argv++))
X {
X if (asg->value)
X addhnode(ztrdup(asg->name),mkanode(ztrdup(asg->value),incm),
X aliastab,freeanode);
X else if (an = (Alias) gethnode(asg->name,aliastab))
X printalias(asg->name,an);
X else
X ret = 1;
X }
X return ret;
X}
X
X/* print an alias; used with listhtable */
X
Xvoid printalias(s,a) /**/
Xchar *s;struct alias *a;
X{
X if (a->cmd >= 0 && !(showflag && a->cmd))
X printf("%s=%s\n",s,a->text);
X}
X
X/* print a param; used with listhtable */
X
Xvoid printparam(s,p) /**/
Xchar *s;Param p;
X{
X if (showflag > 0 && !(p->flags & showflag))
X return;
X if (!showflag)
X {
X int fgs = p->flags;
X
X if (fgs & PMFLAG_i) printf("integer ");
X if (fgs & PMFLAG_A) printf("array ");
X if (fgs & PMFLAG_L) printf("left justified %d ",p->ct);
X if (fgs & PMFLAG_R) printf("right justified %d ",p->ct);
X if (fgs & PMFLAG_Z) printf("zero filled %d ",p->ct);
X if (fgs & PMFLAG_l) printf("lowercase ");
X if (fgs & PMFLAG_u) printf("uppercase ");
X if (fgs & PMFLAG_r) printf("readonly ");
X if (fgs & PMFLAG_t) printf("tagged ");
X if (fgs & PMFLAG_x) printf("exported ");
X }
X if (showflag2)
X printf("%s\n",s);
X else
X {
X char *t,**u;
X
X printf("%s=",s);
X switch (p->flags & PMTYPE)
X {
X case PMFLAG_s:
X if (p->gets.cfn && (t = p->gets.cfn(p)))
X puts(t);
X else
X putchar('\n');
X break;
X case PMFLAG_i: printf("%ld\n",p->gets.ifn(p)); break;
X case PMFLAG_A:
X putchar('(');
X u = p->gets.afn(p);
X if (!*u)
X printf(")\n");
X else
X {
X while (u[1])
X printf("%s ",*u++);
X printf("%s)\n",*u);
X }
X break;
X }
X }
X}
X
X/* autoload, declare, export, functions, integer, local, readonly, typeset */
X
Xint bin_typeset(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xint on = 0,off = 0,roff,bit = 1,retcode = 0;
Xchar *optstr = "LRZilurtx";
Xstruct param *pm;
Xstruct asgment *asg;
X
X for (; *optstr; optstr++,bit <<= 1)
X if (ops[*optstr] == 1)
X on |= bit;
X else if (ops[*optstr] == 2)
X off |= bit;
X roff = off;
X if (ops['f']) {
X on &= PMFLAG_t|PMFLAG_u;
X off &= PMFLAG_t|PMFLAG_u;
X showflag = (ops['f'] == 1);
X if (ops['@'] && ((off & ~PMFLAG_t) || (on & ~(PMFLAG_u|PMFLAG_t)))) {
X zerrnam(name,"invalid option(s)",NULL,0);
X return 1;
X }
X showflag2 = 0;
X if (!*argv) {
X showflag2 = off|on;
X listhtable(cmdnamtab,(HFunc) pshfunc);
X } else for (; *argv; argv++) {
X Cmdnam cc;
X
X if ((cc = (Cmdnam) gethnode(*argv,cmdnamtab)) && cc->type == SHFUNC)
X if (on|off) cc->flags = (cc->flags | on) & (~off);
X else pshfunc(*argv,cc);
X else if (on & PMFLAG_u) {
X cc = (Cmdnam) zcalloc(sizeof *cc);
X cc->type = SHFUNC;
X cc->flags = on;
X addhnode(ztrdup(*argv),cc,cmdnamtab,freecmdnam);
X } else
X retcode = 1;
X }
X return retcode;
X }
X if (on & PMFLAG_L)
X off |= PMFLAG_R;
X if (on & PMFLAG_R)
X off |= PMFLAG_L;
X if (on & PMFLAG_u)
X off |= PMFLAG_l;
X if (on & PMFLAG_l)
X off |= PMFLAG_u;
X on &= ~off;
X showflag = showflag2 = 0;
X if (!*argv) {
X showflag = on|off;
X showflag2 = roff;
X listhtable(paramtab,(HFunc) printparam);
X } else while (asg = getasg(*argv++)) {
X if (asg->value && *asg->value == '~') {
X *asg->value = Tilde;
X singsub(&asg->value);
X }
X pm = (Param) gethnode(asg->name,paramtab);
X if (pm) {
X if (!on && !roff && !asg->value) {
X printparam(asg->name,pm);
X continue;
X }
X pm->flags = (pm->flags | on) & ~off;
X if ((on & (PMFLAG_L | PMFLAG_R | PMFLAG_Z | PMFLAG_i))
X && (pmtype(pm) != PMFLAG_A))
X pm->ct = auxlen;
X if (pmtype(pm) != PMFLAG_A) {
X if (pm->flags & PMFLAG_x) {
X if (!pm->env)
X pm->env = addenv(asg->name,
X (asg->value) ? asg->value : getsparam(asg->name));
X } else if (pm->env) {
X delenv(pm->env);
X free(pm->env);
X pm->env = NULL;
X }
X if (asg->value)
X setsparam(asg->name,ztrdup(asg->value));
X }
X } else {
X if (locallist && !(on & PMFLAG_x)) {
X permalloc();
X addnode(locallist,ztrdup(asg->name));
X heapalloc();
X }
X createparam(ztrdup(asg->name),
X ztrdup((asg->value) ? asg->value : ""),on);
X pm = (Param) gethnode(asg->name,paramtab);
X pm->ct = auxlen;
X }
X }
X return 0;
X}
X
X/* convert s with escape sequences */
X
Xchar *escsubst(s,nnl) /**/
Xchar *s; int *nnl;
X{
Xchar *t = alloc(strlen(s)+1),*ret = t;
X
X for (; *s; s++)
X if (*s == '\\' && s[1])
X switch (*++s) {
X case 'b': *t++ = '\b'; break;
X case 'c': *nnl |= 1; break;
X case 'e': *t++ = '\033'; break;
X case 'f': *t++ = '\f'; break;
X case 'n': *t++ = '\n'; break;
X case 'r': *t++ = '\r'; break;
X case 't': *t++ = '\t'; break;
X case 'v': *t++ = '\v'; break;
X case '\\': *t++ = '\\'; break;
X case '0': *t++ = zstrtol(s,&s,8); s--; break;
X default: *t++ = '\\'; *t++ = *s; break;
X }
X else *t++ = *s;
X *t = '\0';
X return ret;
X}
X
X/* echo, print, pushln */
X
Xint bin_print(name,args,ops,func) /**/
Xchar *name;char **args;char *ops;int func;
X{
Xint nnl = 0, fd;
XHistent ent;
XFILE *fout = stdout;
X
X if (ops['z']) {
X permalloc();
X pushnode(bufstack,ztrdup(spacejoin(args)));
X heapalloc();
X return 0;
X }
X if (ops['s']) {
X permalloc();
X ent = gethistent(++curhist);
X ent->lex = ztrdup(join(args,HISTSPACE));
X ent->lit = ztrdup(join(args,' '));
X ent->stim = ent->ftim = time(NULL);
X heapalloc();
X return 0;
X }
X if (ops['R'])
X ops['r'] = 1;
X if (ops['u'] || ops['p']) {
X if (ops['u']) {
X for (fd = 0; fd < 10; fd++) if (ops[fd+'0']) break;
X if (fd == 10) fd = 0;
X } else fd = coprocout;
X if ((fd = dup(fd)) < 0) {
X zerrnam(name,"bad file number",NULL,0);
X return 1;
X }
X if ((fout = fdopen(fd,"w")) == 0) {
X zerrnam(name,"bad mode on fd",NULL,0);
X return 1;
X }
X }
X for (; *args; args++) {
X if (!ops['r']) *args = escsubst(*args,&nnl);
X if (ops['D']) fprintdir(*args,fout);
X else if (ops['P']) {
X int junk;
X fputs(putprompt(*args,&junk),fout);
X } else fputs(*args,fout);
X if (args[1]) fputc(ops['l'] ? '\n' : ops['0'] ? '\0' : ' ',fout);
X }
X if (!(ops['n'] || nnl)) fputc(ops['N'] ? '\0' : '\n',fout);
X if (fout != stdout) fclose(fout);
X return 0;
X}
X
Xint bin_dirs(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
XLklist l;
X
X if (ops['v'])
X {
X Lknode node;
X int t0 = 1;
X
X printf("0\t");
X printdir(pwd);
X for (node = firstnode(dirstack); node; incnode(node))
X {
X printf("\n%d\t",t0++);
X printdir(getdata(node));
X }
X putchar('\n');
X return 0;
X }
X if (!*argv)
X {
X pdstack();
X return 0;
X }
X permalloc();
X l = newlist();
X if (!*argv)
X {
X heapalloc();
X return 0;
X }
X while (*argv)
X addnode(l,ztrdup(*argv++));
X freetable(dirstack,freestr);
X dirstack = l;
X heapalloc();
X return 0;
X}
X
Xint bin_unalias(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xint ret = 0;
Xvptr dat;
X
X while (*argv)
X {
X if (dat = remhnode(*argv++,aliastab))
X freeanode(dat);
X else
X ret = 1;
X }
X return ret;
X}
X
Xint bin_disable(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
XCmdnam chn;
X
X while (*argv) {
X if (!strncmp(*argv,"TRAP",4))
X unsettrap(getsignum(*argv+4));
X chn = zalloc(sizeof *chn);
X chn->type = DISABLED;
X addhnode(ztrdup(*argv++),chn,cmdnamtab,freecmdnam);
X }
X return 0;
X}
X
Xint bin_unhash(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xvptr dat;
X
X while (*argv) {
X if (!strncmp(*argv,"TRAP",4)) unsettrap(getsignum(*argv+4));
X if (dat = remhnode(*argv++,cmdnamtab)) freecmdnam(dat);
X }
X return 0;
X}
X
Xint bin_unset(name,argv,ops,func) /**/
Xchar *name;char **argv;char *ops;int func;
X{
Xint retval = 0;
Xchar *s;
X
X while (s = *argv++)
X if (gethnode(s,paramtab))
X unsetparam(s);
X else
X retval = 1;
X return retval;
X}
X
Xstatic char *zbuf;
Xstatic int readfd;
X
Xint zread() /**/
X{
Xchar cc;
X
X if (zbuf)
X return (*zbuf) ? *zbuf++ : EOF;
X if (read(readfd,&cc,1) != 1)
X return EOF;
X return cc;
X}
X
Xint bin_read(name,args,ops,func) /**/
Xchar *name;char **args;char *ops;int func;
X{
Xchar *reply,*pmpt;
Xint bsiz,c,gotnl = 0;
Xchar *buf,*bptr;
X
X reply = (*args) ? *args++ : "REPLY";
X if (ops['u'] && !ops['p']) {
X for (readfd = 0; readfd < 10; ++readfd) if (ops[readfd+'0']) break;
X if (readfd == 10) readfd = 0;
X } else if (ops['p']) readfd = coprocin;
X else {
X attachtty((jobtab[thisjob].gleader) ? jobtab[thisjob].gleader : mypgrp);
X readfd = 0;
X if (isatty(0)) {
X for (pmpt = reply; *pmpt && *pmpt != '?'; pmpt++);
X if (*pmpt++) {
X write(2,pmpt,strlen(pmpt));
X pmpt[-1] = '\0';
X }
X }
X#if 0
X else if (isset(SHINSTDIN) && unset(INTERACTIVE)) {
X if (isatty(1)) readfd = 1;
X else if (isatty(2)) readfd = 2;
X }
X#endif
X }
X zbuf = (!ops['z']) ? NULL :
X (full(bufstack)) ? (char *) getnode(bufstack) : NULL;
X while (*args) {
X buf = bptr = zalloc(bsiz = 64);
Xredo:
X for(;;) {
X if (gotnl) break;
X c = zread();
X if (!ops['r'] && c == '\n' && bptr != buf && bptr[-1] == '\\') {
X bptr--;
X continue;
X }
X if (c == EOF || isep(c) || c == '\n') break;
X *bptr++ = c;
X if (bptr == buf+bsiz) {
X buf = realloc(buf,bsiz *= 2);
X bptr = buf+(bsiz/2);
X }
X }
X if (c == EOF) {
X if (readfd == coprocin) {
X close(coprocin);
X close(coprocout);
X coprocin = coprocout = -1;
X }
X return 1;
X }
X if (c == '\n') gotnl = 1;
X if (bptr == buf) goto redo;
X *bptr = '\0';
X setsparam(reply,buf);
X reply = *args++;
X }
X buf = bptr = zalloc(bsiz = 64);
X if (!gotnl)
X for (;;) {
X c = zread();
X if (!ops['r'] && c == '\n' && bptr != buf && bptr[-1] == '\\') {
X bptr--;
X continue;
X }
X if (c == EOF || (c == '\n' && !zbuf)) break;
X *bptr++ = c;
X if (bptr == buf+bsiz) {
X buf = realloc(buf,bsiz *= 2);
X bptr = buf+(bsiz/2);
X }
X }
X *bptr = '\0';
X setsparam(reply,buf);
X if (c == EOF) {
X if (readfd == coprocin) {
X close(coprocin);
X close(coprocout);
X coprocin = coprocout = -1;
X }
X return 1;
X }
X return 0;
X}
X
Xint bin_vared(name,args,ops,func) /**/
Xchar *name;char **args;char *ops;int func;
X{
Xchar *s;char *t;
Xstruct param *pm;
X
X if (!(s = getsparam(args[0]))) {
X zerrnam(name,"no such variable: %s",args[0],0);
X return 1;
X }
X permalloc();
X pushnode(bufstack,ztrdup(s));
X heapalloc();
X t = (char *) zleread((unsigned char *)"> ",NULL,2);
X if (!t || errflag)
X return 1;
X if (t[strlen(t)-1] == '\n')
X t[strlen(t)-1] = '\0';
X pm = gethnode(args[0],paramtab);
X if (pmtype(pm) == PMFLAG_A)
X setaparam(args[0],spacesplit(t));
X else
X setsparam(args[0],t);
X return 0;
X}
X
X#define fset(X) (flags & X)
X
X/* execute a builtin handler function after parsing the arguments */
X
Xint execbin(args,cnode) /**/
XLklist args;Cmdnam cnode;
X{
Xstruct bincmd *b;
Xchar ops[128],*arg,*pp,*name,**argv,**oargv,*optstr;
Xint t0,flags,sense,argc = 0,op;
XLknode n;
X
X auxdata = NULL;
X auxlen = 0;
X for (t0 = 0; t0 != 128; t0++)
X ops[t0] = 0;
X name = ugetnode(args);
X b = builtins+cnode->u.binnum;
X
X/* the 'builtin' builtin is handled specially */
X
X if (b->funcid == BIN_BUILTIN)
X {
X if (!(name = ugetnode(args)))
X {
X zerrnam("builtin","command name expected",NULL,0);
X return 1;
X }
X for (t0 = 0, b = builtins; b->name; b++,t0++)
X if (!strcmp(name,b->name))
X break;
X if (!b->name)
X {
X zerrnam("builtin","no such builtin: %s",name,0);
X return 1;
X }
X }
X flags = b->flags;
X arg = ugetnode(args);
X optstr = b->optstr;
SHAR_EOF
true || echo 'restore of zsh2.2/src/builtin.c failed'
fi
echo 'End of zsh2.2 part 6'
echo 'File zsh2.2/src/builtin.c is continued in part 7'
echo 7 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:00:14 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 103
Archive-name: zsh2.2/part07

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.07 (part 7 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/builtin.c continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 7; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping zsh2.2/src/builtin.c'
else
echo 'x - continuing file zsh2.2/src/builtin.c'
sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/builtin.c' &&

X if (flags & BINF_ECHOPTS && arg && strcmp(arg,"-n"))
X optstr = NULL;
X if (optstr)
X while (arg &&
X ((sense = *arg == '-') || fset(BINF_PLUSOPTS) && *arg == '+') &&
X (fset(BINF_PLUSOPTS) || !atoi(arg)))
X {
X pp = arg;
X if (arg[1] == '-')
X arg++;
X if (!arg[1])
X {
X ops['-'] = 1;
X if (!sense)
X ops['+'] = 1;
X }
X else
X ops['@'] = 1;
X op = -1;
X while (*++arg)
X if (strchr(b->optstr,op = *arg))
X ops[*arg] = (sense) ? 1 : 2;
X else
X break;
X if (*arg)
X {
X zerr("bad option: %c",NULL,*arg);
X return 1;
X }
X arg = ugetnode(args);
X if (fset(BINF_SETOPTS) && op == 'o')
X {
X int c;
X
X if (!arg)
X prtopt();
X else
X {
X c = optlookup(arg);
X if (c == -1)
X {
X zerr("bad option: %s",arg,0);


X return 1;
X }
X else
X {

X ops[c] = ops['o'];


X arg = ugetnode(args);
X }

X }
X }
X if ((fset(BINF_PRINTOPTS) && ops['R']) || ops['-'])
X break;
X if (fset(BINF_SETOPTS) && ops['A'])
X {
X auxdata = arg;
X arg = ugetnode(args);
X break;
X }
X if (fset(BINF_FCOPTS) && op == 'e')
X {
X auxdata = arg;


X arg = ugetnode(args);
X }

X if (fset(BINF_TYPEOPT) && (op == 'L' || op == 'R' ||
X op == 'Z' || op == 'i') && arg && idigit(*arg))
X {
X auxlen = atoi(arg);


X arg = ugetnode(args);
X }

X }
X if (fset(BINF_R))
X auxdata = "-";
X if (pp = b->defopts)
X while (*pp)
X ops[*pp++] = 1;
X if (arg)
X {
X argc = 1;
X n = firstnode(args);
X while (n)
X argc++,incnode(n);
X }
X oargv = argv = (char **) ncalloc(sizeof(char **) * (argc+1));
X if (*argv++ = arg)
X while (*argv++ = ugetnode(args));
X argv = oargv;
X if (errflag)
X return 1;
X if (argc < b->minargs || (argc > b->maxargs && b->maxargs != -1)) {
X zerrnam(name,(argc < b->minargs)
X ? "not enough arguments" : "too many arguments",NULL,0);
X return 1;
X }
X if (isset(XTRACE)) {
X char **pp = argv;
X fprintf(stderr,"%s%s",(prompt4) ? prompt4 : "",name);
X while (*pp) fprintf(stderr," %s",*pp++);
X fputc('\n',stderr);
X fflush(stderr);
X }
X return (*(b->handlerfunc))(name,argv,ops,b->funcid);
X}
X
Xstruct asgment *getasg(s) /**/
Xchar *s;
X{
Xstatic struct asgment asg;
X
X if (!s)
X return NULL;
X if (*s == '=')
X {
X zerr("bad assignment",NULL,0);
X return NULL;
X }
X asg.name = s;
X for (; *s && *s != '='; s++);
X if (*s)
X {
X *s = '\0';
X asg.value = s+1;
X }
X else
X asg.value = NULL;
X return &asg;
X}
X
X/* ., source */
X
Xint bin_dot(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

Xchar **old,*old0;
Xint ret;
Xchar buf[MAXPATHLEN];
Xchar *s,**t,*enam;
X
X if (!*argv)
X return 0;
X old = pparams;
X old0 = argzero;
X if (argv[1]) {
X permalloc();
X pparams = arrdup(argv+1);
X heapalloc();
X }
X enam = argzero = ztrdup(*argv);
X errno = ENOENT;
X ret = 1;
X for (s = argzero; *s; s++)
X if (*s == '/') {
X ret = source(argzero);
X break;
X }
X if (!*s) {
X for (t = path; *t; t++)
X if ((*t)[0] == '.' && !(*t)[1]) {
X ret = source(argzero);
X break;
X } else {
X sprintf(buf,"%s/%s",*t,argzero);
X if (access(buf,F_OK) == 0) {
X ret = source(enam = buf);
X break;
X }
X }
X if (!*t && access(argzero,F_OK) == 0)
X ret = source(enam = argzero);
X }
X if (argv[1]) {
X freearray(pparams);
X pparams = old;
X }
X if (ret) zerrnam(name,"%e: %s",enam,errno);
X free(argzero);
X argzero = old0;


X return ret;
X}
X

Xint bin_set(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

Xstruct option *opp;
Xchar **x;
X
X if (((ops['+'] && ops['-']) || !ops['-']) && !ops['@'] && !*argv)
X {
X showflag = ~0;
X showflag2 = ops['+'];
X listhtable(paramtab,(HFunc) printparam);


X }
X for (opp = optns; opp->name; opp++)

X if (ops[opp->id] == 1)


X opts[opp->id] = OPT_SET;

X else if (ops[opp->id] == 2)


X opts[opp->id] = OPT_UNSET;

X if (!*argv && !ops['-'])
X return 0;
X permalloc();
X x = arrdup(argv);
X heapalloc();


X if (ops['A'])

X setaparam(auxdata,x);
X else {
X freearray(pparams);
X pparams = x;


X }
X return 0;
X}
X

X#define pttime(X) printf("%dm%ds",(X)/3600,(X)/60%60)
X
Xint bin_times(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

Xstruct tms buf;
X
X if (times(&buf) == -1)
X return 1;
X pttime(buf.tms_utime);
X putchar(' ');
X pttime(buf.tms_stime);
X putchar('\n');
X pttime(buf.tms_cutime);
X putchar(' ');
X pttime(buf.tms_cstime);


X putchar('\n');
X return 0;
X}
X

Xint bin_getopts(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

Xchar *optstr = *argv++,*var = *argv++;
Xchar **args = (*argv) ? argv : pparams;
Xstatic int optcind = 1,quiet;
Xchar *str,optbuf[3],*opch = optbuf+1;
X
X if (zoptind < 1) zoptind = 1;
X optbuf[0] = '+'; optbuf[1] = optbuf[2] = '\0';
X if (optarg) free(optarg);
X optarg = ztrdup("");
X setsparam(var,ztrdup(""));
X if (*optstr == ':') {
X quiet = 1;
X optstr++;
X }
X if (zoptind > arrlen(args)) return 1;
X str = args[zoptind-1];
X if (*str != '+' && *str != '-' || optcind >= strlen(str) ||
X !strcmp("--",str)) {
X if (*str == '+' || *str == '-')
X zoptind++;
X optcind = 0;
X return 1;
X }
X if (!optcind)
X optcind = 1;
X *opch = str[optcind++];
X if (!args[zoptind-1][optcind]) {
X zoptind++;
X optcind = 0;
X }
X for (; *optstr; optstr++)
X if (*opch == *optstr)
X break;
X if (!*optstr) {
X setsparam(var,ztrdup("?"));
X if (quiet) {
X free(optarg); optarg = ztrdup(opch);
X return 0;
X }
X zerr("bad option: %c",NULL,*opch); errflag = 0;
X return 0;
X }
X setsparam(var,ztrdup(opch-(*str == '+')));
X if (optstr[1] == ':') {
X if (!args[zoptind-1]) {
X if (quiet) {
X free(optarg); optarg = ztrdup(opch);
X setsparam(var,ztrdup(":"));
X return 0;
X }
X setsparam(var,ztrdup("?"));
X zerr("argument expected after %c option",NULL,*opch); errflag = 0;
X return 0;
X }
X free(optarg);
X optarg = ztrdup(args[zoptind-1]+optcind);
X zoptind++;
X optcind = 0;


X }
X return 0;
X}
X

X/* get a signal number from a string */
X
Xint getsignum(s) /**/
Xchar *s;
X{
Xint x = atoi(s),t0;
X
X if (idigit(*s) && x >= 0 && x < VSIGCOUNT)
X return x;
X for (t0 = 0; t0 != VSIGCOUNT; t0++)
X if (!strcmp(s,sigs[t0]))


X return t0;
X return -1;
X}
X

Xint bin_trap(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

XList l;
Xchar *arg;
X
X if (!*argv) {
X int t0;
X
X for (t0 = 0; t0 != VSIGCOUNT; t0++)
X if (sigtrapped[t0])
X if (!sigfuncs[t0])
X printf("TRAP%s () {}\n",sigs[t0]);
X else {
X char *s = getpermtext((vptr) sigfuncs[t0]);
X printf("TRAP%s () {\n\t%s\n}\n",sigs[t0],s);
X free(s);


X }
X return 0;
X }

X if (!strcmp(*argv,"-")) {
X int t0;
X
X argv++;
X if (!*argv)
X for (t0 = 0; t0 != VSIGCOUNT; t0++) unsettrap(t0);
X else
X while (*argv) unsettrap(getsignum(*argv++));
X return 0;
X }
X arg = *argv++;
X if (!*arg) l = NULL;
X else if (!(l = parselstring(arg))) {
X zerrnam(name,"couldn't parse trap command",NULL,0);
X popheap();
X return 1;
X }
X for (; *argv; argv++) {
X int sg = getsignum(*argv);
X if (sg == -1) {
X zerrnam(name,"undefined signal: %s",*argv,0);
X break;
X }
X settrap(sg,l);
X }
X if (l) popheap();
X return errflag;
X}
X
Xvoid printulimit(lim,hard) /**/
Xint lim;int hard;
X{
Xlong t0;
X
X#ifdef RLIM_INFINITY
X t0 = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur;
X switch (lim)
X {
X case RLIMIT_CPU: printf("cpu time (seconds) "); break;
X case RLIMIT_FSIZE: printf("file size (blocks) "); t0 /= 512; break;
X case RLIMIT_DATA: printf("data seg size (kbytes) "); t0 /= 1024; break;
X case RLIMIT_STACK: printf("stack size (kbytes) "); t0 /= 1024; break;
X case RLIMIT_CORE: printf("core file size (blocks) "); t0 /= 512; break;
X#ifdef RLIMIT_RSS
X case RLIMIT_RSS: printf("resident set size (kbytes) "); t0 /= 1024; break;
X#endif
X#ifdef RLIMIT_NOFILE
X case RLIMIT_NOFILE: printf("file descriptors "); break;
X#endif
X }
X printf("%ld\n",t0);
X#endif
X}
X
Xint bin_ulimit(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

Xint res,hard;
X
X#ifndef RLIM_INFINITY
X zerrnam(name,"not available on this system",NULL,0);
X return 1;
X#else
X hard = ops['H'];
X if (ops['a'] || !ops['@'])
X res = -1;
X else if (ops['t'])
X res = RLIMIT_CPU;
X else if (ops['f'])
X res = RLIMIT_FSIZE;
X else if (ops['d'])
X res = RLIMIT_DATA;
X else if (ops['s'])
X res = RLIMIT_STACK;
X else if (ops['c'])
X res = RLIMIT_CORE;
X#ifdef RLIMIT_RSS
X else if (ops['m'])
X res = RLIMIT_RSS;
X#endif
X#ifdef RLIMIT_NOFILE
X else if (ops['n'])
X res = RLIMIT_NOFILE;
X#endif
X else
X {
X zerrnam(name,"no such limit",NULL,0);
X return 1;
X }
X if (res == -1)
X if (*argv)
X {
X zerrnam(name,"no arguments required after -a",NULL,0);


X return 1;
X }
X else
X {

X int t0;
X


X for (t0 = 0; t0 != RLIM_NLIMITS; t0++)

X printulimit(t0,hard);


X return 0;
X }
X if (!*argv)

X printulimit(res,hard);
X else if (strcmp(*argv,"unlimited"))
X {
X long t0;
X
X t0 = atol(*argv);
X switch(res)
X {
X case RLIMIT_FSIZE: case RLIMIT_CORE: t0 *= 512; break;
X case RLIMIT_DATA: case RLIMIT_STACK:
X#ifdef RLIMIT_RSS
X case RLIMIT_RSS:
X#endif
X t0 *= 1024; break;
X }
X if (hard)
X {
X if (t0 > limits[res].rlim_max && geteuid())
X {
X zerrnam(name,"can't raise hard limits",NULL,0);
X return 1;
X }
X limits[res].rlim_max = t0;
X }
X else
X {
X if (t0 > limits[res].rlim_max)
X {
X if (geteuid())
X {
X zerrnam(name,"value exceeds hard limit",NULL,0);
X return 1;
X }
X limits[res].rlim_max = limits[res].rlim_cur = t0;
X }
X else
X limits[res].rlim_cur = t0;


X }
X }
X else
X {

X if (hard)
X {
X if (geteuid())
X {
X zerrnam(name,"can't remove hard limits",NULL,0);
X return 1;
X }
X limits[res].rlim_max = RLIM_INFINITY;
X }
X else
X limits[res].rlim_cur = limits[res].rlim_max;


X }
X return 0;
X#endif
X}
X

Xint putraw(c) /**/
Xint c;
X{
X putchar(c);


X return 0;
X}
X

Xint bin_echotc(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

Xchar *s,buf[2048],*t,*u;
Xint num,argct,t0;
X
X s = *argv++;
X if (!termok)
X return 1;
X if ((num = tgetnum(s)) != -1)
X {
X printf("%d\n",num);
X return 0;
X }
X u = buf;
X t = tgetstr(s,&u);
X if (!t || !*t)
X {
X zerrnam(name,"no such capability: %s",s,0);
X return 1;
X }
X for (argct = 0, u = t; *u; u++)
X if (*u == '%')
X {
X if (u++, (*u == 'd' || *u == '2' || *u == '3' || *u == '.' ||
X *u == '+'))
X argct++;
X }
X if (arrlen(argv) != argct)
X {
X zerrnam(name,(arrlen(argv) < argct) ? "not enough arguments" :
X "too many arguments",NULL,0);
X return 1;
X }
X if (!argct)
X tputs(t,1,putraw);
X else
X {
X t0 = (argv[1]) ? atoi(argv[1]) : atoi(*argv);
X tputs(tgoto(t,atoi(*argv),t0),t0,putraw);


X }
X return 0;
X}
X

Xint bin_pwd(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

X printf("%s\n",pwd);


X return 0;
X}
X

X#define TEST_END 0
X#define TEST_INPAR 1
X#define TEST_OUTPAR 2
X#define TEST_STR 3
X#define TEST_AND 4
X#define TEST_OR 5
X#define TEST_NOT 6
X
Xstatic char **tsp;
Xstatic int *tip;
X
Xint bin_test(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

Xchar **s;
Xint cnt,*arr,*ap;
XCond c;
X
X if (func == BIN_BRACKET)
X {
X for (s = argv; *s; s++);
X if (s == argv || strcmp(s[-1],"]"))
X {
X zerrnam(name,"']' expected",NULL,0);
X return 1;
X }
X s[-1] = NULL;
X }
X for (s = argv, cnt = 0; *s; s++,cnt++);
X ap = arr = alloc((cnt+1)*sizeof *arr);
X for (s = argv; *s; s++,ap++)
X if (!strcmp(*s,"("))
X *ap = TEST_INPAR;
X else if (!strcmp(*s,")"))
X *ap = TEST_OUTPAR;
X else if (!strcmp(*s,"-a"))
X *ap = TEST_AND;
X else if (!strcmp(*s,"-o"))
X *ap = TEST_OR;
X else if (!strcmp(*s,"!"))
X *ap = TEST_NOT;
X else
X *ap = TEST_STR;
X *ap = TEST_END;
X tsp = argv;
X tip = arr;
X c = partest(0);
X if (*tip != TEST_END || errflag)
X {
X zerrnam(name,"parse error",NULL,0);
X return 1;
X }
X return (c) ? !evalcond(c) : 1;
X}
X
XCond partest(level) /**/
Xint level;
X{
XCond a,b;
X
X switch (level)
X {
X case 0:
X a = partest(1);
X if (*tip == TEST_OR)
X {
X tip++,tsp++;
X b = makecond();
X b->left = a;
X b->right = partest(0);
X b->type = COND_OR;
X return b;
X }
X return a;
X case 1:
X a = partest(2);
X if (*tip == TEST_AND)
X {
X tip++,tsp++;
X b = makecond();
X b->left = a;
X b->right = partest(1);
X b->type = COND_AND;
X return b;
X }
X return a;
X case 2:
X if (*tip == TEST_NOT)
X {
X tip++,tsp++;
X b = makecond();
X b->left = partest(2);
X b->type = COND_NOT;
X return b;
X }
X case 3:
X if (*tip == TEST_INPAR)
X {
X tip++,tsp++;
X b = partest(0);
X if (*tip != TEST_OUTPAR)
X {
X zerrnam("test","parse error",NULL,0);
X return NULL;
X }
X tip++,tsp++;
X return b;
X }
X if (tip[0] != TEST_STR)
X {
X zerrnam("test","parse error",NULL,0);
X return NULL;
X }
X else if (tip[1] != TEST_STR)
X {
X b = makecond();
X if (!strcmp(*tsp,"-t"))
X {
X b->left = strdup("1");
X b->type = 't';
X }
X else
X {
X b->left = tsp[0];
X b->type = 'n';
X }
X tip++,tsp++;
X return b;
X }
X else if (tip[2] != TEST_STR)
X {
X b = par_cond_double(tsp[0],tsp[1]);
X tip += 2,tsp += 2;
X return b;
X }
X else
X {
X b = par_cond_triple(tsp[0],tsp[1],tsp[2]);
X tip += 3,tsp += 3;
X return b;
X }
X }


X return NULL;
X}
X

Xint bin_compctl(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

Xint flags = 0;
XCompctl cc = NULL;
Xchar *usrkeys = NULL;
X
X for (; *argv && **argv == '-'; argv++)
X while (*++(*argv)) switch(**argv) {
X case 'c': flags |= CC_COMMPATH; break;
X case 'f': flags |= CC_FILES; break;
X case 'h': flags |= CC_HOSTS; break;
X case 'o': flags |= CC_OPTIONS; break;
X case 'v': flags |= CC_VARS; break;
X case 'b': flags |= CC_BINDINGS; break;
X case 'k':
X flags |= CC_USRKEYS;
X if ((*argv)[1]) { usrkeys = (*argv)+1; *argv = ""-1; }


X else if (!argv[1]) {

X zerrnam(name,"variable name expected after -k",NULL,0);
X return 1;
X } else { usrkeys = *++argv; *argv = ""-1; }
X break;
X case 'C': cc = &cc_compos; break;
X case 'D': cc = &cc_default; break;
X default: zerrnam(name,"bad option: %c",NULL,**argv); return 1;
X }
X if (cc) {
X cc->mask = flags;
X if (cc->keyvar) free(cc->keyvar);
X cc->keyvar = ztrdup(usrkeys);
X }
X if (!*argv) {
X if (!cc) {
X showflag = flags;
X listhtable(compctltab,(HFunc) printcompctl);
X printcompctl("COMMAND",&cc_compos);
X printcompctl("DEFAULT",&cc_default);


X }
X return 0;
X }

X compctl_process(argv,flags,usrkeys);


X return 0;
X}
X

Xvoid printcompctl(s,cc) /**/
Xchar *s;Compctl cc;
X{
Xchar *css = "fchovb";
X
X if (cc->mask & showflag) {
X puts(s);
X } else if (!showflag) {
X int flags = cc->mask;
X printf("%s -",s);
X while (*css) {
X if (flags & 1) putchar(*css);
X css++; flags >>= 1;
X }
X if (flags & 1) printf("k %s",cc->keyvar);


X putchar('\n');
X }
X}
X

Xvoid compctl_process(s,mask,uk) /**/
Xchar **s;int mask;char *uk;
X{
XCompctl cc;


X
X for (;*s;s++) {

X cc = zalloc(sizeof *cc);
X cc->mask = mask; cc->keyvar = ztrdup(uk);
X addhnode(ztrdup(*s),cc,compctltab,freecompctl);
X }
X}
X
Xint bin_ttyctl(name,argv,ops,func) /**/


Xchar *name;char **argv;char *ops;int func;
X{

X if (ops['f'] || !ops['@']) ttyfrozen = 1;
X else if (ops['u']) ttyfrozen = 0;


X return 0;
X}
X

SHAR_EOF
echo 'File zsh2.2/src/builtin.c is complete' &&
chmod 0644 zsh2.2/src/builtin.c ||


echo 'restore of zsh2.2/src/builtin.c failed'

Wc_c="`wc -c < 'zsh2.2/src/builtin.c'`"
test 61945 -eq "$Wc_c" ||
echo 'zsh2.2/src/builtin.c: original size 61945, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/cond.c ==============
if test -f 'zsh2.2/src/cond.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/cond.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/cond.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/cond.c' &&
X/*
X *
X * cond.c - evaluate conditional expressions


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X

Xint evalcond(c) /**/
XCond c;
X{
Xstruct stat *st;
X
X switch (c->type)
X {
X case COND_NOT: return !evalcond(c->left);
X case COND_AND: return evalcond(c->left) && evalcond(c->right);
X case COND_OR: return evalcond(c->left) || evalcond(c->right);
X }
X singsub((char **) &c->left);
X untokenize(c->left);
X if (c->right)
X {
X singsub((char **) &c->right);
X if (c->type != COND_STREQ && c->type != COND_STRNEQ)
X untokenize(c->right);
X }
X switch (c->type)
X {
X case COND_STREQ: return matchpat(c->left,c->right);
X case COND_STRNEQ: return !matchpat(c->left,c->right);
X case COND_STRLT: return strcmp(c->left,c->right) < 0;
X case COND_STRGTR: return strcmp(c->left,c->right) > 0;
X case 'e': case 'a': return(doaccess(c->left,F_OK));
X case 'b': return(S_ISBLK(dostat(c->left)));
X case 'c': return(S_ISCHR(dostat(c->left)));
X case 'd': return(S_ISDIR(dostat(c->left)));
X case 'f': return(S_ISREG(dostat(c->left)));
X case 'g': return(!!(dostat(c->left) & S_ISGID));
X case 'k': return(!!(dostat(c->left) & S_ISVTX));
X case 'n': return(!!strlen(c->left));
X case 'o': return(optison(c->left));
X case 'p': return(S_ISFIFO(dostat(c->left)));
X case 'r': return(doaccess(c->left,R_OK));
X case 's': return((st = getstat(c->left)) && !!(st->st_size));
X case 'S': return(S_ISSOCK(dostat(c->left)));
X case 'u': return(!!(dostat(c->left) & S_ISUID));
X case 'w': return(doaccess(c->left,W_OK));
X case 'x': return(doaccess(c->left,X_OK));
X case 'z': return(!strlen(c->left));
X case 'h': case 'L': return(S_ISLNK(dolstat(c->left)));
X case 'O': return((st = getstat(c->left)) && st->st_uid == geteuid());
X case 'G': return((st = getstat(c->left)) && st->st_gid == getegid());
X case 't': return isatty(matheval(c->left));
X case COND_EQ: return matheval(c->left) == matheval(c->right);
X case COND_NE: return matheval(c->left) != matheval(c->right);
X case COND_LT: return matheval(c->left) < matheval(c->right);
X case COND_GT: return matheval(c->left) > matheval(c->right);
X case COND_LE: return matheval(c->left) <= matheval(c->right);
X case COND_GE: return matheval(c->left) >= matheval(c->right);
X case COND_NT: case COND_OT:
X {
X time_t a;
X if (!(st = getstat(c->left)))
X return 0;
X a = st->st_mtime;
X if (!(st = getstat(c->right)))
X return 0;
X return (c->type == COND_NT) ? a > st->st_mtime : a < st->st_mtime;
X }
X case COND_EF:
X {
X dev_t d;
X ino_t i;
X
X if (!(st = getstat(c->left)))
X return 0;
X d = st->st_dev;
X i = st->st_ino;
X if (!(st = getstat(c->right)))
X return 0;
X return d == st->st_dev && i == st->st_ino;
X }
X default: zerr("bad cond structure",NULL,0);


X }
X return 0;
X}
X

Xint doaccess(s,c) /**/
Xchar *s;int c;
X{
X return !access(s,c);
X}
X
Xstatic struct stat st;
X
Xstruct stat *getstat(s) /**/
Xchar *s;
X{
X if (!strncmp(s,"/dev/fd/",8))
X {
X if (fstat(atoi(s+8),&st))
X return NULL;
X }
X else if (stat(s,&st))
X return NULL;
X return &st;
X}
X
Xunsigned short dostat(s) /**/
Xchar *s;
X{
Xstruct stat *st;
X
X if (!(st = getstat(s)))
X return 0;
X return st->st_mode;
X}
X
X/* p...@aaii.oz; needed since dostat now uses "stat" */
X
Xunsigned short dolstat(s) /**/
Xchar *s;
X{
X if (lstat(s, &st) < 0)
X return 0;
X return st.st_mode;
X}
X
Xint optison(s) /**/
Xchar *s;
X{
Xint i;
X
X if (strlen(s) == 1)
X return opts[*s];
X if ((i = optlookup(s)) != -1)
X return opts[i];
X zerr("no such option: %s",s,0);


X return 0;
X}
X

SHAR_EOF
chmod 0644 zsh2.2/src/cond.c ||
echo 'restore of zsh2.2/src/cond.c failed'
Wc_c="`wc -c < 'zsh2.2/src/cond.c'`"
test 4064 -eq "$Wc_c" ||
echo 'zsh2.2/src/cond.c: original size 4064, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/exec.c ==============
if test -f 'zsh2.2/src/exec.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/exec.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/exec.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/exec.c' &&
X/*
X *
X * exec.c - command execution


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X#include <sys/errno.h>

X#ifdef __hpux
X#include <ndir.h>
X#else
X#include <sys/dir.h>
X#endif
X
X#define execerr() { if (forked) exit(1); \
X closemnodes(mfds); errflag = 1; return; }
X
Xstatic Lklist args;
Xstatic Cmdnam cn;
X
X/* parse list in a string */
X
XList parselstring(s) /**/
Xchar *s;
X{
XList l;
X
X hungets(s);
X strinbeg();
X pushheap();
X if (!(l = parse_list())) {
X strinend();
X hflush();
X popheap();
X return NULL;
X }
X strinend();
X return l;
X}
X
X/* execute a string */
X
Xvoid execstring(s) /**/
Xchar *s;
X{
XList l;
X
X if (l = parselstring(s)) {
X execlist(l);
X popheap();
X }
X}
X
X/* fork and set limits */
X
Xint phork() /**/
X{
Xint pid,t0;
X
X if (thisjob >= MAXJOB-1) {
X zerr("job table full",NULL,0);
X return -1;
X }
X pid = fork();
X if (pid == -1) {
X zerr("fork failed: %e",NULL,errno);
X return -1;
X }
X#ifdef RLIM_INFINITY
X if (!pid)


X for (t0 = 0; t0 != RLIM_NLIMITS; t0++)

X setrlimit(t0,limits+t0);
X#endif
X return pid;
X}
X
X/* execute a current shell command */
X
Xint execcursh(cmd) /**/
XCmd cmd;
X{
X runlist(cmd->u.list);
X cmd->u.list = NULL;


X return lastval;
X}
X

X/* execve after handling $_ and #! */
X
X#define POUNDBANGLIMIT 64
X
Xint zexecve(pth,argv) /**/
Xchar *pth;char **argv;
X{
Xint eno;
Xstatic char buf[MAXPATHLEN*2];
Xchar **eep;
X
X for (eep = environ; *eep; eep++)
X if (**eep == '_' && (*eep)[1] == '=') break;
X buf[0] = '_';
X buf[1] = '=';
X if (*pth == '/') strcpy(buf+2,pth);
X else sprintf(buf+2,"%s/%s",pwd,pth);
X if (!*eep) eep[1] = NULL;
X *eep = buf;
X execve(pth,argv,environ);
X if ((eno = errno) == ENOEXEC) {
X char buf[POUNDBANGLIMIT+1],*ptr,*ptr2,*argv0;
X int fd,ct,t0;
X
X if ((fd = open(pth,O_RDONLY)) >= 0) {
X argv0 = *argv;
X *argv = pth;
X ct = read(fd,buf,POUNDBANGLIMIT);
X close(fd);
X if (ct > 0) {
X if (buf[0] == '#')
X if (buf[1] == '!') {
X for (t0 = 0; t0 != ct; t0++)
X if (buf[t0] == '\n')
X buf[t0] = '\0';
X buf[POUNDBANGLIMIT] = '\0';
X for (ptr = buf+2; *ptr && *ptr == ' '; ptr++);
X for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++);
X if (*ptr) {
X *ptr = '\0';
X argv[-2] = ptr2;
X argv[-1] = ptr+1;
X execve(ptr2,argv-2,environ);
X } else {
X argv[-1] = ptr2;
X execve(ptr2,argv-1,environ);
X }
X } else {
X argv[-1] = "sh";
X execve("/bin/sh",argv-1,environ);
X }
X else {
X for (t0 = 0; t0 != ct; t0++)
X if (!buf[t0]) break;
X if (t0 == ct) {
X argv[-1] = "sh";
X execve("/bin/sh",argv-1,environ);
X }
X }
X } else eno = errno;
X *argv = argv0;
X } else eno = errno;
X }
X return eno;
X}
X
X#define MAXCMDLEN (MAXPATHLEN*4)
X
X/* execute an external command */
X
Xvoid execute(dash) /**/
Xint dash;
X{
Xchar **argv,*arg0,**pp;
Xchar *z,*s,buf[MAXCMDLEN],buf2[MAXCMDLEN];
Xint ee = 0,eno = 0;
X
X if (!full(args)) {
X zerr("no command",NULL,0);
X _exit(1);
X }
X cn = (Cmdnam) gethnode(peekfirst(args),cmdnamtab);
X if (cn && cn->type == DISABLED)
X cn = NULL;
X if (s = zgetenv("STTY"))
X zyztem("stty",s);
X arg0 = peekfirst(args);
X if (z = zgetenv("ARGV0")) {
X setdata(firstnode(args),ztrdup(z));
X delenv(z-6);
X } else if (dash) {
X sprintf(buf2,"-%s",arg0);
X setdata(firstnode(args),ztrdup(buf2));
X }
X argv = makecline(args);
X fixsigs();
X if (strlen(arg0) > MAXPATHLEN) {
X zerr("command too long: %s",arg0,0);
X _exit(1);
X }
X for (s = arg0; *s; s++)
X if (*s == '/') {
X errno = zexecve(arg0,argv);
X if (arg0 == s || unset(PATHDIRS)) {
X zerr("%e: %s",arg0,errno);
X _exit(1);
X }
X break;
X }
X if (cn && ISEXCMD(cn->type)) {
X for (pp = path; pp < cn->pcomp; pp++)
X if (**pp == '.' && (*pp)[1] == '\0') {
X ee = zexecve(arg0,argv);
X if (ee != ENOENT) eno = ee;
X } else if (**pp != '/') {


X z = buf;
X strucpy(&z,*pp);
X *z++ = '/';

X strcpy(z,arg0);
X ee = zexecve(buf,argv);
X if (ee != ENOENT) eno = ee;
X }
X ee = zexecve(cn->u.nam,argv);
X if (ee != ENOENT) eno = ee;
X }
X for (pp = path; *pp; pp++)
X if ((*pp)[0] == '.' && !(*pp)[1]) {
X ee = zexecve(arg0,argv);
X if (ee != ENOENT) eno = ee;
X } else {


X z = buf;
X strucpy(&z,*pp);
X *z++ = '/';

X strcpy(z,arg0);
X ee = zexecve(buf,argv);
X if (ee != ENOENT) eno = ee;
X }
X if (eno) zerr("%e: %s",arg0,eno);
X else zerr("command not found: %s",arg0,0);
X _exit(1);
X}
X
X#define try(X) { if (iscom(X)) return ztrdup(X); }
X
X/* get the full pathname of an external command */
X
Xchar *findcmd(arg0) /**/
Xchar *arg0;
X{
Xchar **pp;
Xchar *z,*s,buf[MAXCMDLEN];
X
X cn = (Cmdnam) gethnode(arg0,cmdnamtab);
X if (!cn && isset(HASHCMDS)) hashcmd(arg0,path);
X if (cn && cn->type == DISABLED) cn = NULL;
X if (strlen(arg0) > MAXPATHLEN) return NULL;
X for (s = arg0; *s; s++)
X if (*s == '/') {
X try(arg0);
X if (arg0 == s || unset(PATHDIRS)) {
X return NULL;
X }
X break;
X }
X if (cn && ISEXCMD(cn->type)) {
X for (pp = path; pp < cn->pcomp; pp++)
X if (**pp != '/') {


X z = buf;
X strucpy(&z,*pp);
X *z++ = '/';

X strcpy(z,arg0);
X try(buf);
X }
X try(cn->u.nam);
X }


X for (pp = path; *pp; pp++) {
X z = buf;
X strucpy(&z,*pp);
X *z++ = '/';

X strcpy(z,arg0);
X try(buf);
X }


X return NULL;
X}
X

Xint iscom(s) /**/
Xchar *s;
X{
Xstruct stat statbuf;
X
X return (access(s,X_OK) == 0 && stat(s,&statbuf) >= 0 &&
X S_ISREG(statbuf.st_mode));
X}
X
Xint isrelative(s) /**/
Xchar *s;
X{
X if (*s != '/') return 1;


X for (; *s; s++)

X if (*s == '.' && s[-1] == '/' &&
X (s[1] == '/' || s[1] == '\0' ||
X (s[1] == '.' && (s[2] == '/' || s[2] == '\0')))) return 1;


X return 0;
X}
X

Xint hashcmd(arg0,pp) /**/
Xchar *arg0;char **pp;
X{
Xchar *s,buf[MAXPATHLEN];
Xchar **pq;
XDIR *dir;
Xstruct direct *de;
X
X for (; *pp; pp++)
X if (**pp == '/') {
X s = buf;
X strucpy(&s,*pp);
X *s++ = '/';
X strcpy(s,arg0);
X if (iscom(buf)) break;
X }
X if (!*pp || isrelative(*pp)) return 0;
X cn = (Cmdnam) zcalloc(sizeof *cn);
X cn->type = EXCMD;
X cn->pcomp = pp;
X cn->u.nam = ztrdup(buf);
X addhnode(ztrdup(arg0),cn,cmdnamtab,freecmdnam);
X if (unset(HASHDIRS)) return 1;
X for (pq = pathchecked; pq <= pp; pq++) {
X if (isrelative(*pq) || !(dir = opendir(*pq))) continue;
X readdir(dir); readdir(dir);
X while (de = readdir(dir)) addhcmdnode(de->d_name,pq);
X closedir(dir);
X }
X pathchecked = pp+1;


X return 1;
X}
X

Xvoid fullhash() /**/
X{
Xchar **pq;
XDIR *dir;
Xstruct direct *de;
X
X for (pq = pathchecked; *pq; pq++) {
X if (isrelative(*pq) || !(dir = opendir(*pq))) continue;
X readdir(dir); readdir(dir);
X while (de = readdir(dir)) addhcmdnode(de->d_name,pq);
X closedir(dir);
X }
X pathchecked = pq;
X}
X
Xvoid execlist(list) /**/
XList list;
X{
X if (breaks) return;
X if (!list) return;
X simplifyright(list);
X switch(list->type) {
X case SYNC:
X case ASYNC:
X execlist2(list->left,list->type,!list->right);
X if (sigtrapped[SIGDEBUG])
X dotrap(SIGDEBUG);
X if (sigtrapped[SIGERR] && lastval)
X dotrap(SIGERR);
X if (list->right && !retflag)
X execlist(list->right);


X break;
X }
X}
X

Xvoid execlist2(list,type,last1) /**/
XSublist list;int type;int last1;
X{
X if (!list) return;
X switch(list->type) {
X case END:
X execpline(list,type,last1);
X break;
X case ORNEXT:
X if (!execpline(list,SYNC,0)) execlist2(list->right,type,last1);
X else while (list = list->right)
X if (list->type == ANDNEXT) {
X execlist2(list->right,type,last1);
X return;
X }
X break;
X case ANDNEXT:
X if (execpline(list,SYNC,0)) execlist2(list->right,type,last1);
X else while (list = list->right)
X if (list->type == ORNEXT) {
X execlist2(list->right,type,last1);
X return;


X }
X break;
X }
X}
X

Xint execpline(l,how,last1) /**/
XSublist l;int how;int last1;
X{
Xint ipipe[2],opipe[2];
X
X if (!l) return 0;
X ipipe[0] = ipipe[1] = opipe[0] = opipe[1] = 0;
X blockchld();
X if ((thisjob = getfreejob()) == -1)
X return 1;
X initjob();
X if (how == TIMED) {
X jobtab[thisjob].stat |= STAT_TIMED;
X how = SYNC;
X }
X if (l->flags & PFLAG_COPROC) {
X how = ASYNC;
X if (coprocin >= 0) {


X close(coprocin);
X close(coprocout);
X }

X mpipe(ipipe);
X mpipe(opipe);
X coprocin = ipipe[0];
X coprocout = opipe[1];
X }
X execpline2(l->left,how,opipe[0],ipipe[1],last1);
X if (how == ASYNC) {
X if (l->flags & PFLAG_COPROC) close(ipipe[1]);
X spawnjob();
X unblockchld();
X return 1;
X } else {
X waitjobs();
X unblockchld();
X if (l->flags & PFLAG_NOT) lastval = !lastval;
X return !lastval;
X }
X}
X
Xvoid execpline2(pline,how,input,output,last1) /**/
XPline pline;int how;int input;int output;int last1;
X{
Xint pid;
Xint pipes[2];
X
X if (breaks)
X return;
X if (!pline)
X return;
X if (pline->type == END) {
X execcmd(pline->left,input,output,how==ASYNC,last1);
X pline->left = NULL;
X } else {
X mpipe(pipes);
X if (pline->left->type >= CURSH && how == SYNC) {
X
X /* if we are doing "foo | bar" where foo is a current
X shell command, do foo in a subshell and do
X the rest of the pipeline in the current shell. */
X
X if (!(pid = fork())) {
X close(pipes[0]);
X entersubsh(how==ASYNC);
X exiting = 1;
X execcmd(pline->left,input,pipes[1],how==ASYNC,0);
X _exit(lastval);
X } else if (pid == -1)
X zerr("fork failed: %e",NULL,errno);
X else {
X char *text = getjobtext((vptr) pline->left);
X addproc(pid,text);
X }
X } else {
X /* otherwise just do the pipeline normally. */
X execcmd(pline->left,input,pipes[1],how==ASYNC,0);
X }
X pline->left = NULL;
X close(pipes[1]);
X if (pline->right) {
X execpline2(pline->right,how,pipes[0],output,last1);
X close(pipes[0]);
X }
X }
X}
X
X/* make the argv array */
X
Xchar **makecline(list) /**/
Xstruct lklist *list;


X{
Xint ct = 0;

XLknode node;
Xchar **argv,**ptr;
X
X if (isset(XTRACE)) {
X fprintf(stderr,"%s",(prompt4) ? prompt4 : "");
X for (node = firstnode(list); node; incnode(node),ct++);
X ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
X for (node = firstnode(list); node; incnode(node))
X if (*(char *) getdata(node)) {
X *ptr++ = getdata(node);
X untokenize(getdata(node));
X fputs(getdata(node),stderr);
X if (nextnode(node))
X fputc(' ',stderr);
X }
X *ptr = NULL;
X fputc('\n',stderr);
X fflush(stderr);
X return(argv);
X } else {
X for (node = firstnode(list); node; incnode(node),ct++);
X ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
X for (node = firstnode(list); node; incnode(node))
X if (*(char *) getdata(node)) {
X *ptr++ = getdata(node);
X untokenize(getdata(node));
X }
X *ptr = NULL;
X return(argv);
X }
X}
X
X/* untokenize the command line and remove null arguments */
X
Xvoid fixcline(l) /**/
XLklist l;
X{
XLknode node,next;
X
X for (node = firstnode(l); node; node = next) {
X next = nextnode(node);
X if (!*(char *) getdata(node)) uremnode(l,node);
X else untokenize(getdata(node));
X }
X}
X
Xvoid untokenize(s) /**/
Xchar *s;
X{


X for (; *s; s++)

X if (itok(*s))
X if (*s == Nularg) chuck(s--);
X else *s = ztokens[*s-Pound];
X}
X
X/* nonzero if we shouldn't clobber a file */
X
Xint dontclob(f) /**/
Xstruct redir *f;
X{
Xstruct stat buf;
X
X if (unset(NOCLOBBER) || f->type & 1) return 0;
X if (stat(f->name,&buf) == -1) return 1;
X return S_ISREG(buf.st_mode);
X}
X
X/* close an multio (success) */
X
Xvoid closemn(mfds,fd) /**/
Xstruct multio **mfds;int fd;
X{
X if (mfds[fd]) {
X if (mfds[fd]->ct > 1)
X if (mfds[fd]->rflag == 0)
X catproc(mfds[fd]);
X else
X teeproc(mfds[fd]);
X mfds[fd] = NULL;
X }
X}
X
X/* close all the mnodes (failure) */
X
Xvoid closemnodes(mfds) /**/
Xstruct multio **mfds;
X{
Xint t0,t1;
X
X for (t0 = 0; t0 != 10; t0++)
X if (mfds[t0]) {
X for (t1 = 0; t1 != mfds[t0]->ct; t1++)
X close(mfds[t0]->fds[t1]);
X mfds[t0] = NULL;
X }
X}
X
X/* add a fd to an multio */
X/* an multio is a list of fds associated with a certain fd.
X thus if you do "foo >bar >ble", the multio for fd 1 will have
X two fds, the result of open("bar",...), and the result of
X open("ble",....). */
X
Xvoid addfd(forked,save,mfds,fd1,fd2,rflag) /**/
Xint forked;int *save;struct multio **mfds;int fd1;int fd2;int rflag;
X{
Xint pipes[2];
X
X if (!mfds[fd1]) { /* starting a new multio */
X mfds[fd1] = (struct multio *) alloc(sizeof(struct multio));
X if (!forked && fd1 != fd2 && fd1 < 10)
X save[fd1] = movefd(fd1);
X redup(fd2,fd1);
X mfds[fd1]->ct = 1;
X mfds[fd1]->fds[0] = fd1;
X mfds[fd1]->rflag = rflag;
X } else {
X if (mfds[fd1]->rflag != rflag) {
X zerr("file mode mismatch on fd %d",NULL,fd1);
X return;
X }
X if (mfds[fd1]->ct == 1) { /* split the stream */
X mfds[fd1]->fds[0] = movefd(fd1);
X mfds[fd1]->fds[1] = movefd(fd2);
X mpipe(pipes);
X mfds[fd1]->pipe = pipes[1-rflag];
X redup(pipes[rflag],fd1);
X mfds[fd1]->ct = 2;
X } else /* add another fd to an already split stream */
X mfds[fd1]->fds[mfds[fd1]->ct++] = movefd(fd2);
X }
X}
X
Xvoid addvars(l,export) /**/
XLklist l;int export;
X{
Xstruct varasg *v;
XLklist vl;
X
X while (full(l)) {
X char **arr,**ptr;
X
X v = (struct varasg *) ugetnode(l);
X singsub(&v->name);
X if (errflag)
X return;
X untokenize(v->name);
X if (v->type == PMFLAG_s) {
X vl = newlist();
X addnode(vl,v->str);
X } else
X vl = v->arr;
X prefork(vl);
X if (errflag)
X return;
X postfork(vl,1);
X if (errflag)
X return;
X if (v->type == PMFLAG_s && (!full(vl) || !nextnode(firstnode(vl)))) {
X Param pm;
X char *val;
X
X if (!full(vl))
X pm = setsparam(v->name,val = ztrdup(""));
X else {
X untokenize(peekfirst(vl));
X pm = setsparam(v->name,val = ztrdup(ugetnode(vl)));
X }
X if (export && !(pm->flags & PMFLAG_x))
X addenv(v->name,val);
X continue;
X }
X ptr = arr = (char **) zalloc(sizeof(char **)*(countnodes(vl)+1));
X while (full(vl)) {
X char *pp;
X pp = ugetnode(vl);
X if (*pp) {
X *ptr = ztrdup(pp);
X untokenize(*ptr++);
X }
X }
X *ptr = NULL;
X setaparam(v->name,arr);
X }
X}
X
Xvoid execcmd(cmd,input,output,bkg,last1) /**/
XCmd cmd;int input;int output;int bkg;int last1;
X{
Xint type;
Xlong pid = 0;
Xint save[10],t0;
Xstruct redir *fn;
Xstruct multio *mfds[10];
Xint fil,forked = 0,iscursh = 0,nullexec = 0;
Xchar *text;
X
X args = cmd->args;
X cn = NULL;
X for (t0 = 0; t0 != 10; t0++) {
X save[t0] = 0;
X mfds[t0] = NULL;
X }
X if ((type = cmd->type) == SIMPLE && !full(args))
X if (full(cmd->redir))
X if (cmd->flags & CFLAG_EXEC) {
X nullexec = 1;
X } else if (!*nullcmd) {
X zerr("redirection with no command",NULL,0);
X errflag = lastval = 1;
X return;
X } else if (*readnullcmd &&
X ((Redir)peekfirst(cmd->redir))->type == READ &&
X !nextnode(firstnode(cmd->redir))) {
X addnode(args,strdup(readnullcmd));
X } else
X addnode(args,strdup(nullcmd));
X else {
X addvars(cmd->vars,0);
X return;
X }
X if (full(args) && *(char *) peekfirst(args) == '%') {
X insnode(args,(Lknode) args,strdup((bkg) ? "bg" : "fg"));
X bkg = 0;
X }
X if (isset(AUTORESUME) && !bkg && !full(cmd->redir) && full(args) &&
X !input && type == SIMPLE && !nextnode(firstnode(args))) {
X if (unset(NOTIFY)) scanjobs();
X if (findjobnam(peekfirst(args)) != -1)
X pushnode(args,strdup("fg"));
X }
X if (unset(RMSTARSILENT) && interact && isset(SHINSTDIN) &&
X type == SIMPLE && full(args) && nextnode(firstnode(args)) &&
X !strcmp(peekfirst(args),"rm")) {
X char *s = getdata(nextnode(firstnode(args)));
X int l = strlen(s);
X
X if (s[0] == Star && !s[1])
X checkrmall(pwd);
X else if (l > 2 && s[l-2] == '/' && s[l-1] == Star) {
X char t = s[l-2];
X s[l-2] = 0;
X checkrmall(s);
X s[l-2] = t;
X }
X }
X if (jobbing) { /* get the text associated with this command */
X char *s;
X s = text = getjobtext((vptr) cmd);
X } else text = NULL;
X prefork(args); /* do prefork substitutions */
X if (errflag) {
X lastval = 1;
X return;
X }
X if (full(args) && ((char*)peekfirst(args))[0] == Inbrack &&
X ((char*)peekfirst(args))[1] == '\0')
X ((char*)peekfirst(args))[0] = '[';
X if (type == SIMPLE && full(args) && !(cmd->flags & CFLAG_COMMAND)) {
X char *s,*t;
X cn = (Cmdnam) gethnode(t = s = peekfirst(args),cmdnamtab);
X if (!cn && isset(HASHCMDS) && strcmp(t,"..")) {
X while (*t && *t != '/') t++;
X if (!*t) hashcmd(s,pathchecked);
X }
X }
X if (type == SIMPLE && !cn && isset(AUTOCD) && isset(SHINSTDIN) &&
X full(args) && !full(cmd->redir) &&
X !nextnode(firstnode(args)) && cancd(peekfirst(args))) {
X pushnode(args,strdup("cd"));
X cn = (Cmdnam) gethnode("cd",cmdnamtab);
X }
X
X /* this is nonzero if cmd is a current shell procedure */
X
X iscursh = (type >= CURSH) || (type == SIMPLE && cn &&
X (cn->type == BUILTIN || cn->type == SHFUNC));
X
X /* if this command is backgrounded or (this is an external
X command and we are not exec'ing it) or this is a builtin
X with output piped somewhere, then fork. If this is the
X last stage in a subshell pipeline, don't fork, but make
X the rest of the function think we forked. */
X
X if (bkg || !(iscursh || (cmd->flags & CFLAG_EXEC)) ||
X (cn && (cn->type == BUILTIN || cn->type == SHFUNC) && output)) {
X int synch[2];
X
X pipe(synch);
X pid = (last1 && execok()) ? 0 : phork();
X if (pid == -1) {
X close(synch[0]);
X close(synch[1]);
X return;
X }
X if (pid) {
X close(synch[1]);
X read(synch[0],"foo",1);
X close(synch[0]);
X if (pid == -1)
X zerr("%e",NULL,errno);
X else {
X if (bkg) lastpid = pid;
X ( void ) addproc(pid,text);
X }
X return;
X }
X close(synch[0]);
X entersubsh(bkg);
X close(synch[1]);
X forked = 1;
X }
X if (bkg && isset(BGNICE))
X nice(5);
X
X /* perform postfork substitutions */
X postfork(args,!(cmd->flags & CFLAG_NOGLOB));
X if (errflag) {
X lastval = 1;
X goto err;
X } else {
X char *s;
X while (full(args) && (s = peekfirst(args)) && !*s) ugetnode(args);
X }
X
X if (input) /* add pipeline input/output to mnodes */
X addfd(forked,save,mfds,0,input,0);
X if (output)
X addfd(forked,save,mfds,1,output,1);
X spawnpipes(cmd->redir); /* do process substitutions */
X while (full(cmd->redir))
X if ((fn = (struct redir*) ugetnode(cmd->redir))->type == INPIPE) {
X if (fn->fd2 == -1)
X execerr();
X addfd(forked,save,mfds,fn->fd1,fn->fd2,0);
X } else if (fn->type == OUTPIPE) {
X if (fn->fd2 == -1)
X execerr();
X addfd(forked,save,mfds,fn->fd1,fn->fd2,1);
X } else {
X if (!(fn->type == HERESTR || fn->type == CLOSE || fn->type ==
X MERGE || fn->type == MERGEOUT))
X if (xpandredir(fn,cmd->redir))
X continue;
X if (errflag) execerr();
X if (fn->type == HERESTR) {
X fil = getherestr(fn);
X if (fil == -1) {
X if (errno != EINTR)
X zerr("%e",NULL,errno);
X execerr();
X }
X addfd(forked,save,mfds,fn->fd1,fil,0);
X } else if (fn->type == READ) {
X fil = open(fn->name,O_RDONLY);
X if (fil == -1) {
X if (errno != EINTR)
X zerr("%e: %s",fn->name,errno);
X execerr();
X }
X addfd(forked,save,mfds,fn->fd1,fil,0);
X } else if (fn->type == CLOSE) {
X if (!forked && fn->fd1 < 10)
X save[fn->fd1] = movefd(fn->fd1);
X closemn(mfds,fn->fd1);
X close(fn->fd1);
X } else if (fn->type == MERGE || fn->type == MERGEOUT) {
X if (fn->fd2 == FD_COPROC)
X fn->fd2 = (fn->type == MERGEOUT) ? coprocout : coprocin;
X if (!forked && fn->fd1 < 10)
X save[fn->fd1] = movefd(fn->fd1);
X closemn(mfds,fn->fd1);
X fil = dup(fn->fd2);
X addfd(forked,save,mfds,fn->fd1,fil,fn->type == MERGEOUT);
X } else {
X if (fn->type >= APP)
X fil = open(fn->name,
X (isset(NOCLOBBER) && !(fn->type & 1)) ?
X O_WRONLY|O_APPEND : O_WRONLY|O_APPEND|O_CREAT,0666);
X else
X fil = open(fn->name,dontclob(fn) ?
X O_WRONLY|O_CREAT|O_EXCL : O_WRONLY|O_CREAT|O_TRUNC,0666);
X if (fil == -1) {
X if (errno != EINTR)
X zerr("%e: %s",fn->name,errno);
X execerr();
X }
X addfd(forked,save,mfds,fn->fd1,fil,1);
X }
X }
X
X /* we are done with redirection. close the mnodes, spawning
X tee/cat processes as necessary. */
X for (t0 = 0; t0 != 10; t0++)
X closemn(mfds,t0);
X
X if (nullexec)
X return;
X if (unset(NOEXEC))
X if (type >= CURSH)
X {
X static int (*func[]) DCLPROTO((Cmd)) = {
X execcursh,exectime,execfuncdef,execfor,execwhile,
X execrepeat,execif,execcase,execselect,execcond };
X
X fixcline(args);
X lastval = (func[type-CURSH])(cmd);
X }
X else if (iscursh) /* builtin or shell function */
X {
X if (cmd->vars)
X addvars(cmd->vars,0);
X fixcline(args);
X if (cn && cn->type == SHFUNC)
X execshfunc(cmd,cn);
X else
X {
X if (forked) closem();
X lastval = execbin(args,cn);
X if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
X lastval && !subsh) {
X fprintf(stderr,"zsh: exit %d\n",lastval);
X }
X fflush(stdout);
X if (ferror(stdout))
X {
X zerr("write error: %e",NULL,errno);
X clearerr(stdout);
X }


X }
X }
X else
X {

X if (cmd->vars)
X addvars(cmd->vars,1);
X if (type == SIMPLE)
X {
X closem();
X execute(cmd->flags & CFLAG_DASH);
X }
X else /* ( ... ) */
X execlist(cmd->u.list);
X }
Xerr:
X if (forked)
X _exit(lastval);
X fixfds(save);
X}
X
X/* restore fds after redirecting a builtin */
X
Xvoid fixfds(save) /**/
Xint *save;
X{
Xint t0;
X
X for (t0 = 0; t0 != 10; t0++)
X if (save[t0])
X redup(save[t0],t0);
X}
X
Xvoid entersubsh(bkg) /**/
Xint bkg;
X{
X if (!jobbing)
X {
X if (bkg && isatty(0))
X {
X close(0);
X if (open("/dev/null",O_RDWR))
X {
X zerr("can't open /dev/null: %e",NULL,errno);
X _exit(1);
X }
X }
X }
X else if (!jobtab[thisjob].gleader)
X {
X jobtab[thisjob].gleader = getpid();
X setpgrp(0L,jobtab[thisjob].gleader);
X if (!bkg)
X attachtty(jobtab[thisjob].gleader);
X }
X else
X setpgrp(0L,jobtab[thisjob].gleader);
X subsh = 1;
X if (SHTTY != -1)
X {
X close(SHTTY);
X SHTTY = -1;
X }
X if (jobbing)
X {
X signal(SIGTTOU,SIG_DFL);
X signal(SIGTTIN,SIG_DFL);
X signal(SIGTSTP,SIG_DFL);
X signal(SIGPIPE,SIG_DFL);
X }
X if (interact)
X {
X signal(SIGTERM,SIG_DFL);
X if (sigtrapped[SIGINT])
X signal(SIGINT,SIG_IGN);
X }
X if (!sigtrapped[SIGQUIT])
X signal(SIGQUIT,SIG_DFL);
X opts[MONITOR] = OPT_UNSET;
X clearjobtab();
X}
X
X/* close all internal shell fds */
X
Xvoid closem() /**/
X{
Xint t0;
X
X for (t0 = 10; t0 != NOFILE; t0++)
X close(t0);
X}
X
X/* convert here document into a here string */
X
Xchar *gethere(str,typ) /**/
Xchar *str;int typ;
X{
Xchar pbuf[256];
Xint qt = 0,siz = 0,l,strip = 0;
Xchar *s,*t,*bptr;
X
X for (s = str; *s; s++)
X if (*s == Nularg)
X qt = 1;
X untokenize(str);
X if (typ == HEREDOCDASH)
X {
X strip = 1;
X while (*str == '\t')
X str++;
X }
X t = ztrdup("");
X for(;;)
X {
X char *u,*v;
X
X if (!hgets(pbuf,256))
X break;
X bptr = pbuf;
X if (strip)
X while (*bptr == '\t')
X bptr++;
X for (u = bptr, v = str; *u != '\n' && *v; u++,v++)
X if (*u != *v)
X break;
X if (!(*u == '\n' && !*v))
X {
X l = strlen(bptr);
X if (!qt && l > 1 && bptr[l-1] == '\n' && bptr[l-2] == '\\')
X bptr[l -= 2] = '\0';
X t = realloc(t,siz+l+1);
X strncpy(t+siz,bptr,l);
X siz += l;
X }


X else
X break;
X }

X t[siz] = '\0';
X if (siz && t[siz-1] == '\n')
X t[siz-1] = '\0';
X if (!qt)
X for (s = t; *s; s++)
X if (*s == '$') {
X *s = Qstring;


X } else if (*s == '`') {

X *s = Qtick;
X } else if (*s == '(') {
X *s = Inpar;
X } else if (*s == ')') {
X *s = Outpar;
X } else if (*s == '\\' &&
X (s[1] == '$' || s[1] == '`')) chuck(s);
X s = strdup(t);
X free(t);


X return s;
X}
X

X/* open here string fd */
X
Xint getherestr(fn) /**/
Xstruct redir *fn;
X{
XLklist fake;
Xchar *s = gettemp(),*t;
Xint fd;
X
X fake = newlist();
X addnode(fake,fn->name);
X prefork(fake);
X if (!errflag)
X postfork(fake,1);
X if (errflag)
X return -1;
X if ((fd = open(s,O_CREAT|O_WRONLY,0600)) == -1)
X return -1;
X while (t = ugetnode(fake))
X {
X untokenize(t);
X write(fd,t,strlen(t));
X if (full(fake))
X write(fd," ",1);
X }
X write(fd,"\n",1);
X close(fd);
X fd = open(s,O_RDONLY);
X unlink(s);
X return fd;
X}
X
Xvoid catproc(mn) /**/
Xstruct multio *mn;
X{
Xint len,t0;
Xchar *buf;
X
X if (phork())
X {
X for (t0 = 0; t0 != mn->ct; t0++)
X close(mn->fds[t0]);
X close(mn->pipe);
X return;
X }
X closeallelse(mn);
X buf = zalloc(4096);
X for (t0 = 0; t0 != mn->ct; t0++)
X while (len = read(mn->fds[t0],buf,4096))
X write(mn->pipe,buf,len);
X _exit(0);
X}
X
Xvoid teeproc(mn) /**/
Xstruct multio *mn;
X{
Xint len,t0;
Xchar *buf;
X
X if (phork())
X {
X for (t0 = 0; t0 != mn->ct; t0++)
X close(mn->fds[t0]);
X close(mn->pipe);
X return;
X }
X buf = zalloc(4096);
X closeallelse(mn);
X while ((len = read(mn->pipe,buf,4096)) > 0)
X for (t0 = 0; t0 != mn->ct; t0++)
X write(mn->fds[t0],buf,len);
X _exit(0);
X}
X
Xvoid closeallelse(mn) /**/
Xstruct multio *mn;
X{
Xint t0,t1;
X
X for (t0 = 0; t0 != NOFILE; t0++)
X if (mn->pipe != t0)
X {
X for (t1 = 0; t1 != mn->ct; t1++)
X if (mn->fds[t1] == t0)
X break;
X if (t1 == mn->ct)
X close(t0);
X }
X}
X
Xlong int zstrtol(s,t,base) /**/
Xchar *s;char **t;int base;


X{
Xint ret = 0;
X

X if (base <= 10)
X for (; *s >= '0' && *s < ('0'+base); s++)
X ret = ret*base+*s-'0';
X else
X for (; idigit(*s) || (*s >= 'a' && *s < ('a'+base-10))
X || (*s >= 'A' && *s < ('A'+base-10)); s++)
X ret = ret*base+(idigit(*s) ? (*s-'0') : (*s & 0x1f)+9);
X if (t)
X *t = (char *) s;


X return ret;
X}
X

X/* $(...) */
X
XLklist getoutput(cmd,qt) /**/
Xchar *cmd;int qt;
X{
XList list;
Xint pipes[2];
X
X if (*cmd == '<') {
X int stream;
X char *fi,*s,x;
X
X for (cmd++; *cmd == ' '; cmd++);
X for (s = cmd; *s && *s != ' '; s++)
X if (*s == '\\') s++;
X else if (*s == '$') *s = String;
X x = *s;
X *s = '\0';
X fi = strdup(cmd);
X *s = x;
X if (*fi == '~')
X *fi = Tilde;
X else if (*fi == '=')
X *fi = Equals;
X singsub(&fi);
X if (errflag)
X return NULL;
X stream = open(fi,O_RDONLY);
X if (stream == -1) {
X zerr("%e: %s",fi,errno);
X return NULL;
X }
X return readoutput(stream,qt);
X }
X if (!(list = parselstring(cmd)))
X return NULL;
X mpipe(pipes);
X if (phork())
X {
X popheap();
X close(pipes[1]);
X /* chldsuspend(); */
X return readoutput(pipes[0],qt);
X }
X subsh = 1;
X close(pipes[0]);
X redup(pipes[1],1);
X entersubsh(0);
X signal(SIGTSTP,SIG_IGN);
X exiting = 1;
X execlist(list);
X close(1);
X exit(0); return NULL;
X}
X
X/* read output of command substitution */
X
XLklist readoutput(in,qt) /**/
Xint in;int qt;
X{
XLklist ret;
Xchar *buf,*ptr;
Xint bsiz,c,cnt = 0;
XFILE *fin;
X
X fin = fdopen(in,"r");
X ret = newlist();
X ptr = buf = ncalloc(bsiz = 64);
X while ((c = fgetc(fin)) != EOF)
X if (!qt && isep(c)) {
X if (cnt) {
X *ptr = '\0';
X addnode(ret,buf);
X ptr = buf = ncalloc(bsiz = 64);
X cnt = 0;
SHAR_EOF
true || echo 'restore of zsh2.2/src/exec.c failed'
fi
echo 'End of zsh2.2 part 7'
echo 'File zsh2.2/src/exec.c is continued in part 8'
echo 8 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:02:40 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 104
Archive-name: zsh2.2/part08

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.08 (part 8 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/exec.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 8; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/exec.c'
else
echo 'x - continuing file zsh2.2/src/exec.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/exec.c' &&

X ptr = buf;
X }
X } else {
X *ptr++ = c;
X if (++cnt == bsiz) {
X char *pp = ncalloc(bsiz *= 2);
X
X memcpy(pp,buf,cnt);
X ptr = (buf = pp)+cnt;
X }
X }
X if (ptr != buf && ptr[-1] == '\n')
X ptr[-1] = '\0';
X else
X *ptr = '\0';
X if (cnt) addnode(ret,buf);
X fclose(fin);


X return ret;
X}
X

X/* =(...) */
X
Xchar *getoutputfile(cmd) /**/
Xchar *cmd;
X{
X#ifdef WAITPID
Xint pid;
X#endif
Xchar *nam = gettemp(),*str;
Xint tfil;
XList list;
X
X if (thisjob == -1)
X return NULL;
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';


X if (!(list = parselstring(cmd)))
X return NULL;

X permalloc();
X if (!jobtab[thisjob].filelist)
X jobtab[thisjob].filelist = newlist();
X addnode(jobtab[thisjob].filelist,ztrdup(nam));
X heapalloc();
X#ifdef WAITPID
X if (pid = phork())
X {
X popheap();
X waitpid(pid,NULL,WUNTRACED);
X return nam;
X }
X#else
X if (waitfork()) {
X popheap();
X return nam;
X }
X#endif
X subsh = 1;
X close(1);
X entersubsh(0);
X tfil = creat(nam,0666);


X exiting = 1;
X execlist(list);
X close(1);
X exit(0); return NULL;
X}
X

X/* get a temporary named pipe */
X
Xchar *namedpipe() /**/
X{
X#ifndef NO_FIFOS
Xchar *tnam = gettemp();
X
X if (mknod(tnam,0010666,0) < 0) return NULL;
X return tnam;
X#else
X return NULL;
X#endif
X}
X
X/* <(...) */
X
Xchar *getoutproc(cmd) /**/
Xchar *cmd;
X{
X#ifdef NO_FIFOS
X zerr("doesn't look like your system supports FIFOs.",NULL,0);
X return NULL;
X#else
XList list;
Xint fd;
Xchar *pnam,*str;
X
X if (thisjob == -1)
X return NULL;
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X pnam = namedpipe();
X if (!pnam) return NULL;
X permalloc();
X if (!jobtab[thisjob].filelist)
X jobtab[thisjob].filelist = newlist();
X addnode(jobtab[thisjob].filelist,ztrdup(pnam));
X heapalloc();


X if (!(list = parselstring(cmd)))
X return NULL;

X if (phork())
X {
X popheap();

X return pnam;
X }
X entersubsh(1);
X closem();
X fd = open(pnam,O_WRONLY);
X if (fd == -1)
X {
X zerr("can't open %s: %e",pnam,errno);
X _exit(0);
X }
X redup(fd,1);
X fd = open("/dev/null",O_RDONLY);
X redup(fd,0);


X exiting = 1;
X execlist(list);
X close(1);

X _exit(0); return NULL;
X#endif
X}
X
X/* >(...) */
X
Xchar *getinproc(cmd) /**/
Xchar *cmd;
X{
X#ifdef NO_FIFOS
X zerr("doesn't look like your system supports FIFOs.",NULL,0);
X return NULL;
X#else
XList list;
Xint pid,fd;
Xchar *pnam,*str;
X
X if (thisjob == -1)
X return NULL;
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X pnam = namedpipe();
X if (!pnam) return NULL;
X permalloc();
X if (!jobtab[thisjob].filelist)
X jobtab[thisjob].filelist = newlist();
X addnode(jobtab[thisjob].filelist,ztrdup(pnam));
X heapalloc();


X if (!(list = parselstring(cmd)))
X return NULL;

X if (pid = phork())
X {
X popheap();
X return pnam;
X }
X entersubsh(1);
X closem();
X fd = open(pnam,O_RDONLY);
X redup(fd,0);


X exiting = 1;
X execlist(list);

X _exit(0); return NULL;
X#endif
X}
X
X/* > >(...) (does not use named pipes) */
X
Xint getinpipe(cmd) /**/
Xchar *cmd;


X{
XList list;
Xint pipes[2];

Xchar *str = cmd;
X
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X if (!(list = parselstring(cmd+2)))
X return -1;


X mpipe(pipes);
X if (phork())
X {
X popheap();
X close(pipes[1]);

X return pipes[0];
X }
X close(pipes[0]);
X closem();
X entersubsh(1);
X redup(pipes[1],1);


X exiting = 1;
X execlist(list);

X _exit(0); return 0;
X}
X
X/* < <(...) */
X
Xint getoutpipe(cmd) /**/
Xchar *cmd;


X{
XList list;
Xint pipes[2];

Xchar *str;
X
X for (str = cmd; *str && *str != Outpar; str++);
X if (!*str)
X zerr("oops.",NULL,0);
X *str = '\0';
X if (!(list = parselstring(cmd+2)))
X return -1;
X strinend();


X mpipe(pipes);
X if (phork())
X {
X popheap();

X close(pipes[0]);
X return pipes[1];
X }
X close(pipes[1]);
X closem();
X entersubsh(1);
X redup(pipes[0],0);


X exiting = 1;
X execlist(list);

X _exit(0); return 0;
X}
X
X/* run a list, saving the current job num */
X
Xvoid runlist(l) /**/
XList l;
X{
Xint cj = thisjob;
X
X execlist(l);
X thisjob = cj;
X}
X
Xchar *gettemp() /**/
X{
X return mktemp(dyncat(tmpprefix,"XXXXXX"));
X}
X
X/* my getwd; all the other ones I tried confused the SIGCHLD handler */
X
Xchar *zgetwd() /**/
X{
Xstatic char buf0[MAXPATHLEN];
Xchar buf3[MAXPATHLEN],*buf2 = buf0+1;
Xstruct stat sbuf;
Xstruct direct *de;
XDIR *dir;
Xino_t ino = -1;
Xdev_t dev = -1;
X
X holdintr();
X buf2[0] = '\0';
X buf0[0] = '/';
X for(;;)
X {
X if (stat(".",&sbuf) < 0)
X {
X chdir(buf0);
X noholdintr();
X return ztrdup(".");
X }
X ino = sbuf.st_ino;
X dev = sbuf.st_dev;
X if (stat("..",&sbuf) < 0)
X {
X chdir(buf0);
X noholdintr();
X return ztrdup(".");
X }
X if (sbuf.st_ino == ino && sbuf.st_dev == dev)
X {
X chdir(buf0);
X noholdintr();
X return ztrdup(buf0);
X }
X dir = opendir("..");
X if (!dir)
X {
X chdir(buf0);
X noholdintr();
X return ztrdup(".");
X }
X chdir("..");


X readdir(dir); readdir(dir);
X while (de = readdir(dir))

X if (de->d_ino == ino)
X {
X lstat(de->d_name,&sbuf);
X if (sbuf.st_dev == dev)
X goto match;
X }
X rewinddir(dir);


X readdir(dir); readdir(dir);
X while (de = readdir(dir))

X {
X lstat(de->d_name,&sbuf);
X if (sbuf.st_dev == dev)
X goto match;
X }
X noholdintr();
X closedir(dir);
X return ztrdup(".");
Xmatch:
X strcpy(buf3,de->d_name);
X if (*buf2)
X strcat(buf3,"/");
X strcat(buf3,buf2);
X strcpy(buf2,buf3);
X closedir(dir);
X }
X}
X
X/* open pipes with fds >= 10 */
X
Xvoid mpipe(pp) /**/
Xint *pp;
X{
X pipe(pp);
X pp[0] = movefd(pp[0]);
X pp[1] = movefd(pp[1]);
X}
X
X/* do process substitution with redirection */
X
Xvoid spawnpipes(l) /**/
XLklist l;
X{
XLknode n = firstnode(l);
XRedir f;
X
X for (; n; incnode(n))
X {
X f = (Redir) getdata(n);
X if (f->type == OUTPIPE)
X {
X char *str = f->name;
X f->fd2 = getoutpipe(str);
X }
X if (f->type == INPIPE)
X {
X char *str = f->name;
X f->fd2 = getinpipe(str);
X }
X }
X}
X
X/* perform time ... command */
X
Xint exectime(cmd) /**/
XCmd cmd;
X{
Xint jb = thisjob;
X
X if (!cmd->u.pline) { shelltime(); return 0; }
X execpline(cmd->u.pline,TIMED,0);
X thisjob = jb;


X return lastval;
X}
X

X/* define a function */
X
Xint execfuncdef(cmd) /**/
XCmd cmd;
X{
XCmdnam cc;
Xchar *s;
X
X permalloc();
X while (s = ugetnode(cmd->args))
X {
X cc = (Cmdnam) zalloc(sizeof *cc);


X cc->type = SHFUNC;

X cc->flags = 0;
X if (!cmd->u.list)
X cc->u.list = NULL;
X else
X cc->u.list = (List) dupstruct(cmd->u.list);
X addhnode(ztrdup(s),cc,cmdnamtab,freecmdnam);
X if (!strncmp(s,"TRAP",4))
X {
X int t0 = getsignum(s+4);
X
X if (t0 != -1)
X settrap(t0,cmd->u.list);
X }
X }
X heapalloc();


X return 0;
X}
X

X/* evaluate a [[ ... ]] */
X
Xint execcond(cmd) /**/
XCmd cmd;
X{
X return !evalcond(cmd->u.cond);
X}
X
Xvoid execshfunc(cmd,cn) /**/
XCmd cmd;Cmdnam cn;
X{
XList l;
X
X if (errflag) return;
X l = cn->u.list;
X if (!l) {
X char *nam;
X
X if (!(cn->flags & PMFLAG_u)) return;
X if (!(l = getfpfunc(nam = peekfirst(cmd->args)))) {
X zerr("function not found: %s",nam,0);


X lastval = 1;
X return;
X }

X cn->flags &= ~PMFLAG_u;
X permalloc();
X cn->u.list = (List) dupstruct(l);
X heapalloc();
X }
X doshfunc(l,cmd->args,cn->flags);
X}
X
Xvoid doshfuncnoval(list,args,flags) /**/
XList list; Lklist args; int flags;
X{
Xint val = lastval;
X
X doshfunc(list,args,flags);
X lastval = val;
X}
X
Xvoid doshfunc(list,args,flags) /**/
XList list; Lklist args; int flags;
X{
Xchar **tab,**x,*oargv0;
Xint oxtr = opts[XTRACE],opev = opts[PRINTEXITVALUE],xexittr;
XLklist olist;
Xchar *s;
XList xexitfn;
X
X xexittr = sigtrapped[SIGEXIT];
X xexitfn = sigfuncs[SIGEXIT];
X tab = pparams;
X oargv0 = argzero;
X zoptind = 1;
X if (flags & PMFLAG_t) opts[XTRACE] = OPT_SET;
X opts[PRINTEXITVALUE] = OPT_UNSET;
X if (args) {
X pparams = x = (char **) zcalloc(((sizeof *x)*(1+countnodes(args))));
X argzero = ztrdup(ugetnode(args));
X while (*x = ugetnode(args))
X *x = ztrdup(*x), x++;
X } else {
X pparams = zcalloc(sizeof *pparams);
X argzero = ztrdup(argzero);
X }
X permalloc();
X olist = locallist;
X locallist = newlist();
X heapalloc();
X runlist(dupstruct(list));
X while (s = getnode(locallist)) unsetparam(s);
X free(locallist);
X locallist = olist;
X retflag = 0;
X freearray(pparams);
X free(argzero);
X argzero = oargv0;
X pparams = tab;
X if (sigfuncs[SIGEXIT] && sigfuncs[SIGEXIT] != xexitfn) {
X dotrap(SIGEXIT);
X freestruct(sigfuncs[SIGEXIT]);
X }
X sigtrapped[SIGEXIT] = xexittr;
X sigfuncs[SIGEXIT] = xexitfn;
X opts[XTRACE] = oxtr;
X opts[PRINTEXITVALUE] = opev;
X}
X
X/* search fpath for an undefined function */
X
XList getfpfunc(s) /**/
Xchar *s;
X{
Xchar **pp = fpath,buf[MAXPATHLEN];
Xint fd;


X
X for (; *pp; pp++)

X {
X sprintf(buf,"%s/%s",*pp,s);
X if (!access(buf,R_OK) && (fd = open(buf,O_RDONLY)) != -1)
X {
X int len = lseek(fd,0,2);
X
X if (len == -1)
X close(fd);
X else
X {
X char *d;
X
X lseek(fd,0,0);
X d = zcalloc(len+1);
X if (read(fd,d,len) != len)
X {
X free(d);
X close(fd);
X }
X else
X {
X close(fd);
X return parselstring(d);
X }
X }
X }
X }
X return NULL;
X}
X
X/* check to see if AUTOCD applies here */
X
Xint cancd(s)


Xchar *s;
X{
Xchar *t;
X

X if ((t = getsparam(s)) && *t == '/') return 1;


X if (*s != '/')

X {
X char sbuf[MAXPATHLEN],**cp;
X
X if (cancd2(s))
X return 1;
X if (access(s,X_OK) == 0)
X return 0;
X for (cp = cdpath; *cp; cp++)
X {
X sprintf(sbuf,"%s/%s",*cp,s);
X if (cancd2(sbuf))
X return 1;
X }
X return 0;
X }
X return cancd2(s);
X}
X
Xint cancd2(s)
Xchar *s;
X{
Xstruct stat buf;
X
X return !(access(s,X_OK) || stat(s,&buf) || !S_ISDIR(buf.st_mode));
X}
X
SHAR_EOF
echo 'File zsh2.2/src/exec.c is complete' &&
chmod 0644 zsh2.2/src/exec.c ||


echo 'restore of zsh2.2/src/exec.c failed'

Wc_c="`wc -c < 'zsh2.2/src/exec.c'`"
test 35818 -eq "$Wc_c" ||
echo 'zsh2.2/src/exec.c: original size 35818, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/funcs.h ==============
if test -f 'zsh2.2/src/funcs.h' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/funcs.h (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/funcs.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/funcs.h' &&
Xstruct asgment;
Xstruct utmp;
X
X#include "builtin.pro"
X#include "cond.pro"
X#include "exec.pro"
X#include "glob.pro"
X#include "hist.pro"
X#include "init.pro"
X#include "jobs.pro"
X#include "lex.pro"
X#include "loop.pro"
X#include "math.pro"
X#include "mem.pro"
X#include "params.pro"
X#include "parse.pro"
X#include "subst.pro"
X#include "table.pro"
X#include "text.pro"
X#include "utils.pro"
X#include "watch.pro"
X#include "zle_hist.pro"
X#include "zle_main.pro"
X#include "zle_misc.pro"
X#include "zle_move.pro"
X#include "zle_refresh.pro"
X#include "zle_tricky.pro"
X#include "zle_utils.pro"
X#include "zle_vi.pro"
X#include "zle_word.pro"
X
Xchar *mktemp DCLPROTO((char *));
X#ifndef HAS_STDLIB
Xchar *malloc DCLPROTO((int));
Xchar *realloc DCLPROTO((char *,int));
Xchar *calloc DCLPROTO((int,int));
X#endif
Xchar *ttyname DCLPROTO((int));
X
Xextern char PC, *BC, *UP;
Xextern short ospeed;
Xextern int tgetent DCLPROTO((char *bp, char *name));
Xextern int tgetnum DCLPROTO((char *id));
Xextern int tgetflag DCLPROTO((char *id));
Xextern char *tgetstr DCLPROTO((char *id, char **area));
Xextern char *tgoto DCLPROTO((char *cm, int destcol, int destline));
Xextern int tputs DCLPROTO((char *cp, int affcnt, int (*outc)()));
SHAR_EOF
chmod 0644 zsh2.2/src/funcs.h ||
echo 'restore of zsh2.2/src/funcs.h failed'
Wc_c="`wc -c < 'zsh2.2/src/funcs.h'`"
test 1185 -eq "$Wc_c" ||
echo 'zsh2.2/src/funcs.h: original size 1185, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/glob.c ==============
if test -f 'zsh2.2/src/glob.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/glob.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/glob.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/glob.c' &&
X/*
X *
X * glob.c - filename generation


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X

X#ifdef __hpux
X#include <ndir.h>
X#else

X#ifdef SYSV
X#define direct dirent
X#else
X#include <sys/dir.h>
X#endif
X#endif
X#include <sys/errno.h>
X
X#define exists(X) (access(X,0) == 0 || readlink(X,NULL,0) == 0)
X
Xstatic int mode; /* != 0 if we are parsing glob patterns */
Xstatic int pathpos; /* position in pathbuf */
Xstatic int matchsz; /* size of matchbuf */
Xstatic int matchct; /* number of matches found */
Xstatic char pathbuf[MAXPATHLEN]; /* pathname buffer */
Xstatic char **matchbuf; /* array of matches */
Xstatic char **matchptr; /* &matchbuf[matchct] */
Xstatic Comp exclude; /* pattern to exclude */
X
X/* max # of qualifiers */
X
X#define QUALCT 16
X
Xstatic int (*qualfuncs[QUALCT])DCLPROTO((struct stat *,long));
Xstatic long qualdata[QUALCT];
Xstatic int qualsense[QUALCT];
Xstatic int qualct;
Xstatic int gf_nullglob,gf_markdirs,gf_noglobdots;
X
X/* pathname component in filename patterns */
X
Xstruct complist {
X Complist next;
X Comp comp;
X int closure; /* 1 if this is a (foo/)# */
X };
Xstruct comp {
X Comp left,right,next;
X char *str;
X int closure,last;
X };
X
Xvoid glob(list,np) /**/
XLklist list;Lknode *np;
X{
XLknode node = prevnode(*np);
XLknode next = nextnode(*np);
Xint sl; /* length of the pattern */
Xchar *ostr; /* the pattern before the parser chops it up */
XComplist q; /* pattern after parsing */
Xchar *str = getdata(*np); /* the pattern */
X
X sl = strlen(str);
X ostr = strdup(str);
X uremnode(list,*np);
X qualct = 0;
X gf_nullglob = isset(NULLGLOB);
X gf_markdirs = isset(MARKDIRS);
X gf_noglobdots = unset(GLOBDOTS);
X if (str[sl-1] == Outpar) /* check for qualifiers */
X {
X char *s;
X int sense = 0;
X long data;
X int (*func) DCLPROTO((struct stat *,long));
X
X for (s = str+sl-2; s != str; s--)
X if (*s == Bar || *s == Outpar || *s == Inpar)
X break;
X if (*s == Inpar)
X {
X *s++ = '\0';
X func = NULL;
X while (*s != Outpar)
X {
X func = NULL;
X if (idigit(*s))
X {
X func = qualflags;
X data = 0;
X while (idigit(*s))
X data = data*010+(*s++-'0');
X }
X else switch ((int)(unsigned char)(*s++))
X {
X case (int)(unsigned char)Hat: case '^': sense = 1-sense; break;
X#ifdef S_IFLNK
X case '@': func = qualmode; data = S_IFLNK; break;
X#endif
X#ifdef S_IFSOCK
X case '=': func = qualmode; data = S_IFSOCK; break;
X#endif
X#ifdef S_IFIFO
X case 'p': func = qualmode; data = S_IFIFO; break;
X#endif
X case '/': func = qualmode; data = S_IFDIR; break;
X case '.': func = qualmode; data = S_IFREG; break;
X case '%': func = qualisdev; break;
X case (int)(unsigned char)Star: func = qualiscom; break;
X case 'R': func = qualflags; data = 0004; break;
X case 'W': func = qualflags; data = 0002; break;
X case 'X': func = qualflags; data = 0001; break;
X case 'r': func = qualflags; data = 0400; break;
X case 'w': func = qualflags; data = 0200; break;
X case 'x': func = qualflags; data = 0100; break;
X case 's': func = qualflags; data = 04000; break;
X case 'S': func = qualflags; data = 02000; break;
X case 'd': func = qualdev; data = qgetnum(&s); break;
X case 'l': func = qualnlink; data = qgetnum(&s); break;
X case 'U': func = qualuid; data = geteuid(); break;
X case 'G': func = qualgid; data = getegid(); break;
X case 'u': func = qualuid; data = qgetnum(&s); break;
X case 'g': func = qualgid; data = qgetnum(&s); break;
X case 'M': gf_markdirs = !sense; break;
X case 'N': gf_nullglob = !sense; break;
X case 'D': gf_noglobdots = sense; break;
X default: zerr("unknown file attribute",NULL,0); return;
X }
X if (func)
X {
X if (qualct == QUALCT-1)
X {
X zerr("too many qualifiers",NULL,0);
X return;
X }
X qualfuncs[qualct] = func;
X qualsense[qualct] = sense;
X qualdata[qualct] = data;
X qualct++;
X }


X if (errflag)
X return;
X }

X }
X }
X else if ((str[sl-1] == '/') && !((str[sl-2] == Star)&&
X (str[sl-3] == Star)&&(str[sl-4] == Star)&&
X (str[sl-5]==Star))) /* foo/ == foo(/) */
X {
X str[sl-1] = '\0';
X qualfuncs[0] = qualmode;
X qualdata[0] = S_IFDIR;
X qualsense[0] = 0;
X qualct = 1;
X }
X qualfuncs[qualct] = NULL;
X if (*str == '/') /* pattern has absolute path */
X {
X str++;
X pathbuf[0] = '/';
X pathbuf[pathpos = 1] = '\0';
X }
X else /* pattern is relative to pwd */
X pathbuf[pathpos = 0] = '\0';
X q = parsepat(str);
X if (!q || errflag) /* if parsing failed */
X {
X if (isset(NOBADPATTERN))
X {
X insnode(list,node,ostr);
X return;
X }
X errflag = 0;
X zerr("bad pattern: %s",ostr,0);
X return;
X }
X matchptr = matchbuf = (char **) zalloc((matchsz = 16)*sizeof(char *));
X matchct = 0;
X scanner(q); /* do the globbing */
X if (matchct)
X badcshglob |= 2;
X else if (!gf_nullglob)
X if (isset(CSHNULLGLOB)) {
X badcshglob |= 1;
X } else if (unset(NONOMATCH)) {
X zerr("no matches found: %s",ostr,0);
X free(matchbuf);
X return;
X } else {
X *matchptr++ = strdup(ostr);
X matchct = 1;
X }
X qsort(&matchbuf[0],matchct,sizeof(char *),notstrcmp);
X matchptr = matchbuf;
X while (matchct--) /* insert matches in the arg list */
X insnode(list,node,*matchptr++);
X free(matchbuf);
X *np = (next) ? prevnode(next) : lastnode(list);
X}
X
X/* get number after qualifier */
X
Xlong qgetnum(s) /**/
Xchar **s;
X{
Xlong v = 0;
X
X if (!idigit(**s))
X {
X zerr("number expected",NULL,0);
X return 0;
X }
X while (idigit(**s))
X v = v*10+*(*s)++-'0';
X return v;
X}
X
Xint notstrcmp(a,b) /**/
Xchar **a;char **b;
X{
Xchar *c = *b,*d = *a;
Xint x1,x2;
X
X for (; *c == *d && *c; c++,d++);
X x1 = atoi(c); x2 = atoi(d);
X if (x1==x2 || unset(NUMERICGLOBSORT))
X return ((int) (unsigned char) *c-(int) (unsigned char) *d);
X return x1-x2;
X}
X
Xint forstrcmp(a,b) /**/
Xchar **a;char **b;
X{
Xchar *c = *b,*d = *a;
X
X for (; *c == *d && *c; c++,d++);
X return ((int) (unsigned char) *d-(int) (unsigned char) *c);
X}
X
X/* add a match to the list */
X
Xvoid insert(s) /**/
Xchar *s;
X{
Xstruct stat buf;
Xint statted = 0;
X
X if (exclude && domatch(s,exclude,gf_noglobdots)) return;
X if (gf_markdirs && !lstat(s,&buf) && S_ISDIR(buf.st_mode)) {
X char *t;
X int ll = strlen(s);
X
X t = ncalloc(ll+2);
X strcpy(t,s);
X t[ll] = '/';
X t[ll+1] = '\0';
X s = t;
X statted = 1;
X }
X if (qualct) { /* do the (X) (^X) stuff */
X int (**fptr)DCLPROTO((struct stat *,long)) = qualfuncs;
X int *sptr = qualsense;
X long *lptr = qualdata;
X struct stat buf;
X
X if (statted || lstat(s,&buf) >= 0)
X while (*fptr) if (!(!!((*fptr++)(&buf,*lptr++)) ^ *sptr++)) return;
X }
X *matchptr++ = s;
X if (++matchct == matchsz) {
X matchbuf = (char **) realloc((char *) matchbuf,
X sizeof(char **)*(matchsz *= 2));
X matchptr = matchbuf+matchct;
X }
X}
X
X/* check to see if str is eligible for filename generation */
X
Xint haswilds(str) /**/
Xchar *str;
X{
X if ((*str == Inbrack || *str == Outbrack) && !str[1]) return 0;
X if (str[0] == '%') return 0;
X for (; *str; str++)
X if (*str == Pound || *str == Hat || *str == Star ||
X *str == Bar || *str == Inbrack || *str == Inang ||
X *str == Quest) return 1;


X return 0;
X}
X

X/* check to see if str is eligible for brace expansion */
X
Xint hasbraces(str) /**/
Xchar *str;
X{
Xint mb,bc,cmct1,cmct2;
Xchar *lbr = NULL;
X
X if (str[0] == Inbrace && str[1] == Outbrace)
X return 0;
X if (isset(BRACECCL)) {
X for (mb = bc = 0; *str; ++str)
X if (*str == Inbrace) {
X if (++bc > mb)
X mb = bc;
X }
X else if (*str == Outbrace)
X if (--bc < 0)
X return(0);
X return(mb && bc == 0);
X }
X for (mb = bc = cmct1 = cmct2 = 0; *str; str++)
X {
X if (*str == Inbrace)
X {
X if (!bc)
X lbr = str;
X bc++;
X if (str[4] == Outbrace && str[2] == '-') /* {a-z} */
X {
X cmct1++;
X if (bc == 1)
X cmct2++;
X }
X }
X else if (*str == Outbrace)
X {
X bc--;
X if (!bc)
X {
X if (!cmct2)
X {
X *lbr = '{';
X *str = '}';
X }
X cmct2 = 0;
X }
X }
X else if (*str == Comma && bc)
X {
X cmct1++;
X if (bc == 1)
X cmct2++;
X }
X if (bc > mb)
X mb = bc;
X if (bc < 0)
X return 0;
X }
X return (mb && bc == 0 && cmct1);
X}
X
X/* expand stuff like >>*.c */
X
Xint xpandredir(fn,tab) /**/
Xstruct redir *fn;Lklist tab;
X{
XLklist fake;
Xchar *nam;
Xstruct redir *ff;


Xint ret = 0;
X

X fake = newlist();
X addnode(fake,fn->name);
X prefork(fake);
X if (!errflag)
X postfork(fake,1);

X if (errflag) return 0;
X if (full(fake) && !nextnode(firstnode(fake))) {
X fn->name = peekfirst(fake);
X untokenize(fn->name);
X } else
X while (nam = ugetnode(fake)) {
X ff = alloc(sizeof *ff);
X *ff = *fn;
X ff->name = nam;
X addnode(tab,ff);


X ret = 1;
X }

X return ret;
X}
X

X/* concatenate s1 and s2 in dynamically allocated buffer */
X
Xchar *dyncat(s1,s2) /**/
Xchar *s1;char *s2;
X{
Xchar *ptr;
X
X ptr = ncalloc(strlen(s1)+strlen(s2)+1);
X strcpy(ptr,s1);
X strcat(ptr,s2);
X return ptr;
X}
X
X/* concatenate s1, s2, and s3 in dynamically allocated buffer */
X
Xchar *tricat(s1,s2,s3) /**/
Xchar *s1;char *s2;char *s3;
X{
Xchar *ptr;
X
X ptr = zalloc(strlen(s1)+strlen(s2)+strlen(s3)+1);
X strcpy(ptr,s1);
X strcat(ptr,s2);
X strcat(ptr,s3);
X return ptr;
X}
X
X/* brace expansion */
X
Xvoid xpandbraces(list,np) /**/
XLklist list;Lknode *np;
X{
XLknode node = (*np),last = prevnode(node);
Xchar *str = getdata(node),*str3 = str,*str2;
Xint prev, bc, comma;
X
X for (; *str != Inbrace; str++);
X for (str2 = str, bc = comma = 0; *str2; ++str2)
X if (*str2 == Inbrace)
X ++bc;
X else if (*str2 == Outbrace) {
X if (--bc == 0)
X break;
X }
X else if (bc == 1 && *str2 == Comma)
X ++comma;
X if (!comma && !bc && isset(BRACECCL)) { /* {a-mnop} */
X char ccl[256], *p;
X unsigned char c1,c2,lastch;
X
X uremnode(list,node);
X memset(ccl, 0, sizeof(ccl) / sizeof(ccl[0]));
X for (p = str + 1, lastch = 0; p < str2; ) {
X if (itok(c1 = *p++))
X c1 = ztokens[c1 - (unsigned char)Pound];
X if (itok(c2 = *p))
X c2 = ztokens[c2 - (unsigned char)Pound];
X if (c1 == '-' && lastch && p < str2 && lastch <= c2) {
X while (lastch < c2)
X ccl[lastch++] = 1;
X lastch = 0;
X }
X else
X ccl[lastch = c1] = 1;
X }
X strcpy(str + 1, str2 + 1);
X for (p = ccl+255; p-- > ccl; )
X if (*p) {
X *str = p - ccl;
X insnode(list, last, strdup(str3));
X }
X *np = nextnode(last);
X return;
X }
X if (str[2] == '-' && str[4] == Outbrace) /* {a-z} */
X {
X char c1,c2;
X
X uremnode(list,node);
X chuck(str);
X c1 = *str;
X chuck(str);
X chuck(str);
X c2 = *str;
X chuck(str);
X if (itok(c1))
X c1 = ztokens[c1-Pound];
X if (itok(c2))
X c2 = ztokens[c2-Pound];
X if (c1 < c2)
X for (; c2 >= c1; c2--) /* {a-z} */
X {
X *str = c2;
X insnode(list,last,strdup(str3));
X }
X else
X for (; c2 <= c1; c2++) /* {z-a} */
X {
X *str = c2;
X insnode(list,last,strdup(str3));
X }
X *np = nextnode(last);
X return;
X }
X prev = str-str3;
X str2 = getparen(str++);
X if (!str2)
X {
X zerr("how did you get this error?",NULL,0);
X return;
X }
X uremnode(list,node);
X node = last;
X for(;;)
X {
X char *zz,*str4;
X int cnt;
X
X for (str4 = str, cnt = 0; cnt || *str != Comma && *str !=
X Outbrace; str++)
X if (*str == Inbrace)
X cnt++;
X else if (*str == Outbrace)
X cnt--;
X else if (!*str)
X exit(10);
X zz = zalloc(prev+(str-str4)+strlen(str2)+1);
X ztrncpy(zz,str3,prev);
X strncat(zz,str4,str-str4);
X strcat(zz,str2);
X insnode(list,node,zz);
X incnode(node);
X if (*str != Outbrace)
X str++;


X else
X break;
X }

X *np = nextnode(last);
X}
X
X/* get closing paren, given pointer to opening paren */
X
Xchar *getparen(str) /**/
Xchar *str;
X{
Xint cnt = 1;
Xchar typein = *str++,typeout = typein+1;
X
X for (; *str && cnt; str++)
X if (*str == typein)
X cnt++;
X else if (*str == typeout)
X cnt--;
X if (!str && cnt)
X return NULL;
X return str;
X}
X
X/* check to see if a matches b (b is not a filename pattern) */
X
Xint matchpat(a,b) /**/
Xchar *a;char *b;
X{
XComp c;
Xint val,len;
Xchar *b2;
X
X remnulargs(b);
X len = strlen(b);
X b2 = alloc(len+3);
X strcpy(b2+1,b);
X b2[0] = Inpar;
X b2[len+1] = Outpar;
X b2[len+2] = '\0';
X c = parsereg(b2);
X if (!c)
X {
X zerr("bad pattern: %s",b,0);
X return 0;
X }
X val = domatch(a,c,0);
X return val;
X}
X
X/* do the ${foo%%bar}, ${foo#bar} stuff */
X/* please do not laugh at this code. */
X
Xvoid getmatch(sp,pat,dd) /**/
Xchar **sp;char *pat;int dd;
X{
XComp c;
Xchar *t,*lng = NULL,cc,*s = *sp;
X
X remnulargs(pat);
X c = parsereg(pat);
X if (!c)
X {
X zerr("bad pattern: %s",pat,0);
X return;
X }
X if (!(dd & 2))
X {
X for (t = s; t==s || t[-1]; t++)
X {
X cc = *t;
X *t = '\0';
X if (domatch(s,c,0))
X {
X if (!(dd & 1))
X {
X *t = cc;
X t = strdup(t);
X *sp = t;
X return;
X }
X lng = t;
X }
X *t = cc;
X }
X if (lng)
X {
X t = strdup(lng);
X *sp = t;
X return;


X }
X }
X else
X {

X for (t = s+strlen(s); t >= s; t--)
X {
X if (domatch(t,c,0))
X {
X if (!(dd & 1))
X {
X cc = *t;
X *t = '\0';
X *sp = strdup(*sp);
X *t = cc;
X return;
X }
X lng = t;
X }
X }
X if (lng)
X {
X cc = *lng;
X *lng = '\0';
X *sp = strdup(*sp);
X *lng = cc;
X return;
X }
X }
X}
X
X/* add a component to pathbuf */
X
Xstatic int addpath(s)
Xchar *s;
X{
X if (strlen(s)+pathpos >= MAXPATHLEN) return 0;
X while (pathbuf[pathpos++] = *s++);
X pathbuf[pathpos-1] = '/';
X pathbuf[pathpos] = '\0';


X return 1;
X}
X

Xchar *getfullpath(s) /**/
Xchar *s;
X{
Xstatic char buf[MAXPATHLEN];
X
X strcpy(buf,pathbuf);
X strcat(buf,s);


X return buf;
X}
X

X/* do the globbing */
X
Xvoid scanner(q) /**/
XComplist q;
X{
XComp c;
Xint closure;
X
X if (closure = q->closure) /* (foo/)# */
X if (q->closure == 2) /* (foo/)## */
X q->closure = 1;
X else
X scanner(q->next);
X if (c = q->comp)
X {
X if (!(c->next || c->left) && !haswilds(c->str))
X if (q->next)
X {
X int oppos = pathpos;
X


X if (errflag)
X return;

X if (q->closure && !strcmp(c->str,".")) return;
X if (!addpath(c->str)) return;
X if (!closure || exists(pathbuf))
X scanner((q->closure) ? q : q->next);
X pathbuf[pathpos = oppos] = '\0';
X }
X else
X {
X char *s;
X
X if (exists(s = getfullpath(c->str)))
X insert(strdup(s));
X }
X else
X {
X char *fn;
X int dirs = !!q->next;
X struct direct *de;
X DIR *lock = opendir((*pathbuf) ? pathbuf : ".");
X
X if (lock == NULL)
X return;
X readdir(lock); readdir(lock); /* skip . and .. */
X while (de = readdir(lock))
X {
X if (errflag)
X break;
X fn = &de->d_name[0];
X if (domatch(fn,c,gf_noglobdots))
X {
X int oppos = pathpos;
X
X if (dirs)
X {
X if (closure)
X {
X int type3;
X struct stat buf;
X
X if (lstat(getfullpath(fn),&buf) == -1)
X {
X if (errno != ENOENT && errno != EINTR &&
X errno != ENOTDIR)
X {
X zerr("%e: %s",fn,errno);
X errflag = 0;
X }
X continue;
X }
X type3 = buf.st_mode & S_IFMT;
X if (type3 != S_IFDIR)
X continue;
X }
X if (addpath(fn))
X scanner((q->closure) ? q : q->next); /* scan next level */
X pathbuf[pathpos = oppos] = '\0';
X }
X else insert(dyncat(pathbuf,fn));
X }
X }
X closedir(lock);
X }
X }
X else
X zerr("no idea how you got this error message.",NULL,0);
X}
X
X/* do the [..(foo)..] business */
X
Xint minimatch(pat,str) /**/
Xchar **pat;char **str;
X{
Xchar *pt = *pat+1,*s = *str;
X
X for (; *pt != Outpar; s++,pt++)
X if ((*pt != Quest || !*s) && *pt != *s)
X {
X *pat = getparen(*pat)-1;
X return 0;
X }
X *str = s-1;


X return 1;
X}
X

Xstatic char *pptr;
Xstatic Comp tail = 0;
Xstatic int first;
X
Xint domatch(str,c,fist) /**/
Xchar *str;Comp c;int fist;
X{
X pptr = str;
X first = fist;
X return doesmatch(c);
X}
X
X/* see if current pattern matches c */
X
Xint doesmatch(c) /**/
XComp c;
X{
Xchar *pat = c->str;
X
X if (c->closure == 1) {
X char *saves = pptr;
X
X if (first && *pptr == '.') return 0;
X if (doesmatch(c->next)) return 1;
X pptr = saves;
X first = 0;
X }
X for(;;)
X {
X if (!pat || !*pat)
X {
X char *saves;
X int savei;
X
X if (errflag)
X return 0;
X saves = pptr;
X savei = first;
X if (c->left || c->right)
X if (!doesmatch(c->left))


X if (c->right)
X {

X pptr = saves;
X first = savei;
X if (!doesmatch(c->right))
X return 0;
X }
X else
X return 0;
X if (c->closure)
X return doesmatch(c);
X if (!c->next)
X return (!c->last || !*pptr);
X return doesmatch(c->next);
X }
X if (first && *pptr == '.' && *pat != '.')
X return 0;
X if (*pat == Star) /* final * is not expanded to ?#; returns success */
X {
X while (*pptr) pptr++;
X return 1;
X }
X first = 0;
X if (*pat == Quest && *pptr)
X {
X pptr++;
X pat++;
X continue;
X }
X if (*pat == Hat)
X return 1-doesmatch(c->next);
X if (*pat == Inbrack) {
X if (!*pptr) break;
X if (pat[1] == Hat || pat[1] == '^') {
X pat[1] = Hat;
X for (pat += 2; *pat != Outbrack && *pat; pat++)
X if (*pat == '-' && pat[-1] != Hat && pat[1] != Outbrack) {
X if (pat[-1] <= *pptr && pat[1] >= *pptr)
X break;
X } else if (*pptr == *pat) break;
X if (!*pat) {
X zerr("something is very wrong.",NULL,0);
X return 0;
X }
X if (*pat != Outbrack)
X break;
X pat++;
X pptr++;
X continue;
X } else {
X for (pat++; *pat != Outbrack && *pat; pat++)
X if (*pat == Inpar) {
X if (minimatch(&pat,&pptr))
X break;
X } else if (*pat == '-' && pat[-1] != Inbrack &&
X pat[1] != Outbrack) {
X if (pat[-1] <= *pptr && pat[1] >= *pptr)
X break;
X } else if (*pptr == *pat) break;
X if (!pat || !*pat) {
X zerr("oh dear. that CAN'T be right.",NULL,0);
X return 0;
X }
X if (*pat == Outbrack)
X break;
X for (pptr++; *pat != Outbrack; pat++);
X pat++;
X continue;
X }
X }
X if (*pat == Inang)
X {
X int t1,t2,t3;
X char *ptr;
X
X if (*++pat == Outang) /* handle <> case */
X {
X ( void ) zstrtol(pptr,&ptr,10);
X if (ptr == pptr)
X break;
X pptr = ptr;
X pat++;
X }
X else
X {
X t1 = zstrtol(pptr,&ptr,10);
X if (ptr == pptr)
X break;
X pptr = ptr;
X t2 = zstrtol(pat,&ptr,10);
X if (*ptr != '-')
X exit(31);
X t3 = zstrtol(ptr+1,&pat,10);
X if (!t3)
X t3 = -1;
X if (*pat++ != Outang)
X exit(21);
X if (t1 < t2 || (t3 != -1 && t1 > t3))
X break;
X }
X continue;
X }
X if (*pptr == *pat)
X {
X pptr++;
X pat++;
X continue;
X }
X break;


X }
X return 0;
X}
X

XComplist parsepat(str) /**/
Xchar *str;
X{
Xchar *s;
X
X exclude = NULL;
X if (isset(EXTENDEDGLOB)) {
X s = str+strlen(str);
X while (s-- > str) {
X if (*s == Tilde && s[1]) {
X *s++ = '\0';
X exclude = parsereg(s);
X if (!exclude) return NULL;


X break;
X }
X }
X }

X mode = 0;
X pptr = str;
X return parsecomplist();
X}
X
XComp parsereg(str) /**/
Xchar *str;
X{
X mode = 1;
X pptr = str;
X return parsecompsw();
X}
X
XComplist parsecomplist() /**/
X{
XComp c1;
XComplist p1;
X
X if (pptr[0] == Star && pptr[1] == Star &&
X (pptr[2] == '/' ||
X (pptr[2] == Star && pptr[3] == Star && pptr[4] == '/'))) {
X pptr += 3;
X if (pptr[-1] == Star) pptr += 2;
X p1 = (Complist) alloc(sizeof *p1);
X p1->next = parsecomplist();
X p1->comp = (Comp) alloc(sizeof *p1->comp);
X p1->comp->last = 1;
X p1->comp->str = strdup("*");
X *p1->comp->str = Star;
X p1->closure = 1;
X return p1;
X }
X if (*pptr == Inpar)
X {
X char *str;
X int pars = 1;
X
X for (str = pptr+1; *str && pars; str++)
X if (*str == Inpar)
X pars++;
X else if (*str == Outpar)
X pars--;
X if (str[0] != Pound || str[-1] != Outpar || str[-2] != '/')
X goto kludge;
X pptr++;
X if (!(c1 = parsecompsw()))
X return NULL;
X if (pptr[0] == '/' && pptr[1] == Outpar && pptr[2] == Pound)
X {
X int pdflag = 0;
X
X pptr += 3;
X if (*pptr == Pound)
X {
X pdflag = 1;
X pptr++;
X }
X p1 = (Complist) alloc(sizeof *p1);
X p1->comp = c1;
X p1->closure = 1+pdflag;
X p1->next = parsecomplist();
X return (p1->comp) ? p1 : NULL;


X }
X }
X else
X {

Xkludge:
X if (!(c1 = parsecompsw()))
X return NULL;
X if (*pptr == '/' || !*pptr)
X {
X int ef = *pptr == '/';
X
X p1 = (Complist) alloc(sizeof *p1);
X p1->comp = c1;
X p1->closure = 0;
X p1->next = (*pptr == '/') ? (pptr++,parsecomplist()) : NULL;
X return (ef && !p1->next) ? NULL : p1;
X }
X }
X errflag = 1;


X return NULL;
X}
X

XComp parsecomp() /**/
X{
XComp c = (Comp) alloc(sizeof *c),c1,c2;
Xchar *s = c->str = alloc(MAXPATHLEN*2),*ls = NULL;
X
X c->next = tail;
X
X while (*pptr && (mode || *pptr != '/') && *pptr != Bar &&
X *pptr != Outpar)
X {
X if (*pptr == Hat)
X {
X *s++ = Hat;
X *s++ = '\0';
X pptr++;
X if (!(c->next = parsecomp()))
X return NULL;
X return c;
X }
X if (*pptr == Star && pptr[1] && (mode || pptr[1] != '/'))
X {
X *s++ = '\0';
X pptr++;
X c1 = (Comp) alloc(sizeof *c1);
X *(c1->str = strdup("?")) = Quest;
X c1->closure = 1;
X if (!(c2 = parsecomp())) return NULL;
X c1->next = c2;
X c->next = c1;
X return c;
X }
X if (*pptr == Inpar)
X {
X int pars = 1;
X char *startp = pptr, *endp;
X Comp stail = tail;
X int dpnd = 0;
X
X for (pptr = pptr+1; *pptr && pars; pptr++)
X if (*pptr == Inpar)
X pars++;
X else if (*pptr == Outpar)
X pars--;
X if (pptr[-1] != Outpar)
X {
X errflag = 1;
X return NULL;
X }
X if (*pptr == Pound)
X {
X dpnd = 1;
X pptr++;
X if (*pptr == Pound)
X {
X pptr++;
X dpnd = 2;
X }
X }
X if (!(c1 = parsecomp())) return NULL;
X tail = c1;
X endp = pptr;
X pptr = startp;
X pptr++;
X *s++ = '\0';
X c->next = (Comp) alloc(sizeof *c);
X c->next->left = parsecompsw();
X c->next->closure = dpnd;
X c->next->next = (Comp) alloc(sizeof *c);
X pptr = endp;
X tail = stail;
X return c;
X }
X if (*pptr == Pound)


X {
X *s = '\0';

X pptr++;
X if (!ls)
X return NULL;
X if (*pptr == Pound)
X {
X pptr++;
X c->next = c1 = (Comp) alloc(sizeof *c);
X c1->str = strdup(ls);
X }
X else
X c1 = c;
X c1->next = c2 = (Comp) alloc(sizeof *c);
X c2->str = strdup(ls);
X c2->closure = 1;
X c2->next = parsecomp();
X if (!c2->next)
X return NULL;
X *ls++ = '\0';
X return c;
X }
X ls = s;
X if (*pptr == Inang)
X {
X int dshct;
X
X dshct = (pptr[1] == Outang);
X *s++ = *pptr++;
X while (*pptr && (*s++ = *pptr++) != Outang)
X if (s[-1] == '-')
X dshct++;
X else if (!idigit(s[-1]))
X break;
X if (s[-1] != Outang || dshct != 1)
X return NULL;
X }
X else if (*pptr == Inbrack)
X {
X while (*pptr && (*s++ = *pptr++) != Outbrack);
X if (s[-1] != Outbrack)
X return NULL;
X }
X else if (itok(*pptr) && *pptr != Star && *pptr != Quest)
X *s++ = ztokens[*pptr++-Pound];
X else
X *s++ = *pptr++;
X }
X if (*pptr == '/' || !*pptr)
X c->last = 1;
X *s++ = '\0';
X return c;
X}
X
XComp parsecompsw() /**/
X{
XComp c1,c2,c3;
X
X c1 = parsecomp();
X if (!c1)
X return NULL;
X if (*pptr == Bar)
X {
X c2 = (Comp) alloc(sizeof *c2);
X pptr++;
X c3 = parsecompsw();
X if (!c3)
X return NULL;
X c2->str = strdup("");
X c2->left = c1;
X c2->right = c3;
X return c2;
X }
X return c1;
X}
X
X/* tokenize and see if ss matches tt */
X
Xint patmatch(ss,tt) /**/
Xchar *ss;char *tt;
X{
Xchar *s = ss,*t;


X
X for (; *s; s++)

X if (*s == '\\')
X chuck(s);
X else
X for (t = ztokens; *t; t++)
X if (*t == *s)
X {
X *s = (t-ztokens)+Pound;
X break;
X }
X return matchpat(ss,tt);
X}
X
X/* remove unnecessary Nulargs */
X
Xvoid remnulargs(s) /**/
Xchar *s;
X{
Xint nl = *s;
Xchar *t = s;
X
X while (*s)


X if (*s == Nularg)

X chuck(s);
X else
X s++;
X if (!*t && nl)
X {
X t[0] = Nularg;
X t[1] = '\0';
X }
X}
X
X/* qualifier functions */
X
Xint qualdev(buf,dv) /**/
Xstruct stat *buf;long dv;
X{
X return buf->st_dev == dv;
X}
X
Xint qualnlink(buf,ct) /**/
Xstruct stat *buf;long ct;
X{
X return buf->st_nlink == ct;
X}
X
Xint qualuid(buf,uid) /**/
Xstruct stat *buf;long uid;
X{
X return buf->st_uid == uid;
X}
X
Xint qualgid(buf,gid) /**/
Xstruct stat *buf;long gid;
X{
X return buf->st_gid == gid;
X}
X
Xint qualisdev(buf,junk) /**/
Xstruct stat *buf;long junk;
X{
X junk = buf->st_mode & S_IFMT;
X return junk == S_IFBLK || junk == S_IFCHR;
X}
X
Xint qualmode(buf,mod) /**/
Xstruct stat *buf;long mod;
X{
X return (buf->st_mode & S_IFMT) == mod;
X}
X
Xint qualflags(buf,mod) /**/
Xstruct stat *buf;long mod;
X{
X return buf->st_mode & mod;
X}
X
Xint qualiscom(buf,mod) /**/
Xstruct stat *buf;long mod;
X{
X return (buf->st_mode & (S_IFMT|S_IEXEC)) == (S_IFREG|S_IEXEC);
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/glob.c ||
echo 'restore of zsh2.2/src/glob.c failed'
Wc_c="`wc -c < 'zsh2.2/src/glob.c'`"
test 24554 -eq "$Wc_c" ||
echo 'zsh2.2/src/glob.c: original size 24554, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/hist.c ==============
if test -f 'zsh2.2/src/hist.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/hist.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/hist.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/hist.c' &&
X/*
X *
X * hist.c - history expansion


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X

X#define HEAPSIZE 4096
X
Xstruct hp {
X Hp next;
X char *pool,*ptr;
X int free,histno;
X};
X
Xstatic Hp hp_lit, hp_lex;
Xstatic Histent curhistent;
X
Xstatic int lastc;
X
X/* add a character to the current history word */
X
Xvoid hwaddc(c) /**/
Xint c;
X{
X if (hlastw && hline && (!(errflag || lexstop) || c == HISTSPACE)) {
X if (c == '!' && unset(NOBANGHIST)) hwaddc('\\');
X *hptr++ = c;
X if (hptr-hline >= hlinesz) {
X int ll,flag = 0,oldsiz = hlinesz;
X
X ll = hptr-hlastw;
X if (curhistent->lex == hline) flag = 1;
X hline = hp_realloc(&hp_lex,hline,oldsiz,hlinesz = oldsiz+16);
X if (flag) curhistent->lex = hline;
X hptr = hline+oldsiz;
X hlastw = hptr-ll;
X }
X }
X}
X
X#define habort() { errflag = lexstop = 1; return ' '; }
X
X/* get a character after performing history substitution */
X
Xint hgetc() /**/
X{
Xint c,ev,farg,larg,argc,marg = -1,cflag = 0,bflag = 0;
Xchar buf[256],*ptr;
Xchar *sline,*eline;
X
Xtailrec:
X c = hgetch();
X if (stophist || alstackind)
X {
X hwaddc(c);
X return c;
X }
X if (isfirstch && c == hatchar)
X {
X isfirstch = 0;
X hungetch(hatchar);
X hungets(":s");
X c = bangchar;
X goto hatskip;
X }
X if (c != ' ')
X isfirstch = 0;
X if (c == '\\') {
X int g = hgetch();
X
X if (g != bangchar)
X hungetch(g);
X else {
X hwaddc(bangchar);
X return bangchar;
X }
X }
X if (c != bangchar)
X {
X hwaddc(c);
X return c;
X }
Xhatskip:
X *hptr = '\0';
X if ((c = hgetch()) == '{')
X {
X bflag = cflag = 1;
X c = hgetch();
X }
X if (c == '\"')
X {
X stophist = 1;
X goto tailrec;
X }
X if (!cflag && inblank(c) || c == '=' || c == '(' || lexstop)
X {
X if (lexstop)
X lexstop = 0;
X else
X hungetch(c);
X hwaddc(bangchar);
X return bangchar;
X }
X cflag = 0;
X ptr = buf;
X
X /* get event number */
X
X if (c == '?')
X {
X for(;;)
X {
X c = hgetch();
X if (c == '?' || c == '\n' || lexstop)
X break;
X else
X *ptr++ = c;
X }
X if (c != '\n' && !lexstop)
X c = hgetch();
X *ptr = '\0';
X ev = hconsearch(hsubl = ztrdup(buf),&marg);
X if (ev == -1)
X {
X herrflush();
X zerr("no such event: %s",buf,0);
X habort();


X }
X }
X else
X {

X int t0;
X

X for (;;)
X {

X if (inblank(c) || c == ';' || c == ':' || c == '^' || c == '$' ||
X c == '*' || c == '%' || c == '}' || lexstop)
X break;
X if (ptr != buf) {
X if (c == '-') break;
X if ((idigit(buf[0]) || buf[0] == '-') && !idigit(c)) break;
X }
X *ptr++ = c;
X if (c == '#' || c == bangchar)
X {
X c = hgetch();
X break;
X }
X c = hgetch();
X }
X *ptr = 0;
X if (!*buf)
X ev = defev;
X else if (t0 = atoi(buf))
X ev = (t0 < 0) ? curhist+t0 : t0;
X else if (*buf == bangchar)
X ev = curhist-1;
X else if (*buf == '#')
X ev = curhist;
X else if ((ev = hcomsearch(buf)) == -1)
X {
X zerr("event not found: %s",buf,0);
X while (c != '\n' && !lexstop)
X c = hgetch();
X habort();
X }
X }
X
X /* get the event */
X
X if (!(eline = getevent(defev = ev)))
X habort();
X
X /* extract the relevant arguments */
X
X argc = getargc(eline);
X if (c == ':')
X {
X cflag = 1;
X c = hgetch();
X }
X if (c == '*')
X {
X farg = 1;
X larg = argc;
X cflag = 0;
X }
X else
X {
X hungetch(c);
X larg = farg = getargspec(argc,marg);
X if (larg == -2)
X habort();
X if (farg != -1)
X cflag = 0;
X c = hgetch();
X if (c == '*')
X {
X cflag = 0;
X larg = argc;
X }
X else if (c == '-')
X {
X cflag = 0;
X larg = getargspec(argc,marg);
X if (larg == -2)
X habort();
X if (larg == -1)
X larg = argc-1;
X }
X else
X hungetch(c);
X }
X if (farg == -1)
X farg = 0;
X if (larg == -1)
X larg = argc;
X if (!(sline = getargs(eline,farg,larg)))
X habort();
X
X /* do the modifiers */
X
X for(;;)
X {
X c = (cflag) ? ':' : hgetch();
X cflag = 0;
X if (c == ':')
X {
X int gbal = 0;
X
X if ((c = hgetch()) == 'g')
X {
X gbal = 1;
X c = hgetch();
X }
X switch(c)
X {
X case 'p':
X histdone = HISTFLAG_DONE|HISTFLAG_NOEXEC;
X break;
X case 'h':
X if (!remtpath(&sline))
X {
X herrflush();
X zerr("modifier failed: h",NULL,0);
X habort();
X }
X break;
X case 'e':
X if (!rembutext(&sline))
X {
X herrflush();
X zerr("modifier failed: e",NULL,0);
X habort();
X }
X break;
X case 'r':
X if (!remtext(&sline))
X {
X herrflush();
X zerr("modifier failed: r",NULL,0);
X habort();
X }
X break;
X case 't':
X if (!remlpaths(&sline))
X {
X herrflush();
X zerr("modifier failed: t",NULL,0);
X habort();
X }
X break;
X case 's':
X {
X int del;
X char *ptr1,*ptr2;
X
X del = hgetch();
X ptr1 = hdynread2(del);
X if (!ptr1)
X habort();
X ptr2 = hdynread2(del);
X if (strlen(ptr1))
X {
X if (hsubl)
X free(hsubl);
X hsubl = ptr1;
X }
X if (hsubr)
X free(hsubr);
X hsubr = ptr2;
X }
X case '&':
X if (hsubl && hsubr)
X subst(&sline,hsubl,hsubr,gbal);
X else
X {
X herrflush();
X zerr("no previous substitution with &",NULL,0);
X habort();
X }
X break;
X case 'q':
X quote(&sline);
X break;
X case 'x':
X quotebreak(&sline);
X break;
X case 'l':
X downcase(&sline);
X break;
X case 'u':
X upcase(&sline);
X break;
X default:
X herrflush();
X zerr("illegal modifier: %c",NULL,c);
X habort();
X break;
X }
X }
X else
X {
X if (c != '}' || !bflag)
X hungetch(c);
X if (c != '}' && bflag)
X {
X zerr("'}' expected",NULL,0);
X habort();


X }
X break;
X }
X }
X

X /* stuff the resulting string in the input queue and start over */
X
X lexstop = 0;
X if (alstackind != MAXAL)
X {
X hungets(HISTMARK);
X alstack[alstackind++] = NULL;
X }
X for (ptr = sline; *ptr; ptr++) {
X if (ptr[0] == '\\' && ptr[1] == '!') chuck(ptr);
X }
X hungets(sline);
X histdone |= HISTFLAG_DONE;
X if (isset(HISTVERIFY)) histdone |= HISTFLAG_NOEXEC|HISTFLAG_RECALL;
X goto tailrec;
X}
X
X/* reset the alias stack for lexrestore () */
X
Xvoid clearalstack() /**/
X{
XAlias ix;
X
X while (alstackind)
X {
X ix = alstack[--alstackind];
X ix->inuse = 0;
X }
X}
X
X/* get a character without history expansion */
X
Xint hgetch() /**/
X{
Xunsigned char *line,*pmpt,*pmpt2 = NULL;
Xint plen;
X
Xstart:
X if (inbufct)
X {
X inbufct--;
X if ((lastc = *inbufptr++) == ALPOP)
X {
X Alias ix;
X char *t;
X
X if (!alstackind)
X {
X zerr("alias stack underflow",NULL,0);
X errflag = lexstop = 1;
X return lastc = ' ';
X }
X ix = alstack[--alstackind];
X if (ix)
X {
X ix->inuse = 0;
X t = ix->text;
X if (*t && t[strlen(t)-1] == ' ')
X alstat = ALSTAT_MORE;
X else
X alstat = ALSTAT_JUNK;
X }
X goto start;
X }
X if (itok(lastc))
X goto start;
X return lastc;
X }
X if (strin || errflag)
X {
X lexstop = 1;
X return lastc = ' ';
X }
X if (interact && isset(SHINSTDIN))
X if (!isfirstln)
X pmpt = (unsigned char *)putprompt(prompt2,&plen);
X else
X {
X int foo;
X
X pmpt = (unsigned char *)putprompt(prompt,&plen);
X pmpt2 = (unsigned char *)((rprompt) ? putprompt(rprompt,&foo) : NULL);
X }
X if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
X char *lbuf;
X if (interact && isset(SHINSTDIN))
X write(2,pmpt,strlen((char *) pmpt));
X line = (unsigned char *)fgets(lbuf = zalloc(256),256,bshin);
X if (!line) free(lbuf);
X } else
X line = zleread(pmpt,pmpt2,plen);
X if (!line) {
X lexstop = 1;
X return lastc = ' ';
X }
X if (errflag) {
X free(line);
X lexstop = errflag = 1;
X return lastc = ' ';
X }
X if (interact && isset(SHINSTDIN)) {
X char *s = curhistent->lit;
X curhistent->lit = hp_concat(s,(char*)line);
X }
X if (isfirstln) spaceflag = *line == ' ';
X if (isset(VERBOSE)) {
X fputs((char *) line,stderr);
X fflush(stderr);
X }
X if (*line && line[strlen((char *) line)-1] == '\n')
X {
X lineno++;
X if (interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) &&
X SHTTY != -1 && *line && line[1] &&
X line[strlen((char *) line)-2] == '`')
X {
X int ct;
X unsigned char *ptr;
X
X for (ct = 0, ptr = line; *ptr; ptr++)
X if (*ptr == '`')
X ct++;
X if (ct & 1)
X {
X ptr[-2] = '\n';
X ptr[-1] = '\0';
X }
X }
X }
X isfirstch = 1;
X hungets((char*)line);
X free(line);
X goto start;
X}
X
X/* Read one line of at most n-1 chars from the input queue */
X
Xchar *hgets(buf, n) /**/
Xchar *buf;int n;
X{
Xint l;
X
X for (l = 0; l < n-1; l++)
X if ((buf[l] = hgetch()) == '\n' || lexstop)
X break;
X buf[l+(lexstop?0:1)] = 0;
X
X return (!lexstop || l) ? buf : NULL;
X}
X
X/* put a string in the input queue */
X
Xvoid hungets(str) /**/
Xchar *str;
X{
Xint slen = strlen(str);
X
X/* shrink inbuf if it gets too big */
X
X if (!inbufct && inbufsz > 65536)
X {
X free(inbuf);
X inbuf = zalloc(inbufsz = 256);
X inbufptr = inbuf+inbufsz;
X inbufct = 0;
X }
X if (slen+inbufct > inbufsz)
X {
X char *x;
X
X while (slen+inbufct > inbufsz)
X inbufsz *= 4;
X x = zalloc(inbufsz);
X memcpy(x+inbufsz-inbufct,inbufptr,inbufct);
X inbufptr = x+inbufsz-inbufct;
X free(inbuf);
X inbuf = x;
X }
X memcpy(inbufptr -= slen,str,slen);
X inbufct += slen;
X}
X
X/* unget a char and remove it from hline */
X
Xvoid hungetc(c) /**/
Xint c;
X{
X if (lexstop)
X return;
X if (hlastw) {
SHAR_EOF
true || echo 'restore of zsh2.2/src/hist.c failed'
fi
echo 'End of zsh2.2 part 8'
echo 'File zsh2.2/src/hist.c is continued in part 9'
echo 9 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:04:04 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 105
Archive-name: zsh2.2/part09

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.09 (part 9 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/hist.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 9; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/hist.c'
else
echo 'x - continuing file zsh2.2/src/hist.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/hist.c' &&

X if (hlastw == hptr)
X zerr("hungetc attempted at buffer start",NULL,0);
X else {
X hptr--;
X if (*hptr == '!' && unset(NOBANGHIST)) hptr--;
X }
X }
X hungetch(c);
X}
X
Xvoid hungetch(c) /**/


Xint c;
X{
X if (lexstop)
X return;

X if (inbufct == inbufsz)
X {
X hungets(" ");
X *inbufptr = c;
X }
X else
X {
X *--inbufptr = c;
X inbufct++;
X }
X}
X
X/* begin reading a string */
X
Xvoid strinbeg() /**/
X{
X strin = 1;
X hbegin();
X lexinit();
X}
X
X/* done reading a string */
X
Xvoid strinend() /**/
X{
X strin = 0;
X isfirstch = 1;
X histdone = 0;
X hend();
X}
X
X/* stuff a whole file into the input queue and print it */
X
Xint stuff(fn) /**/
Xchar *fn;
X{
XFILE *in;
Xchar *buf;
Xint len;
X
X if (!(in = fopen(fn,"r")))
X {
X zerr("can't open %s",fn,0);
X return 1;
X }
X fseek(in,0,2);
X len = ftell(in);
X fseek(in,0,0);
X buf = alloc(len+1);
X if (!(fread(buf,len,1,in)))
X {
X zerr("read error on %s",fn,0);
X fclose(in);
X free(buf);
X return 1;
X }
X fclose(in);
X buf[len] = '\0';
X fwrite(buf,len,1,stdout);
X hungets(buf);


X return 0;
X}
X

X/* flush input queue */
X
Xvoid hflush() /**/
X{
X inbufptr += inbufct;


X inbufct = 0;
X}
X

X/* initialize the history mechanism */
X
Xvoid hbegin() /**/
X{
X isfirstln = isfirstch = 1;
X histremmed = errflag = histdone = spaceflag = 0;
X stophist = isset(NOBANGHIST) || unset(SHINSTDIN);
X lithist = isset(HISTLIT);
X hline = hptr = hp_alloc(&hp_lex,hlinesz = 16);
X curhistent = gethistent(curhist);
X if (!curhistent->ftim) curhistent->ftim = time(NULL);
X if (interact && isset(SHINSTDIN) && !strin) {
X inittty();
X defev = curhist++;
X if (curhist-histsiz >= 0) gethistent(curhist-histsiz)->lex = NULL;
X if (curhist-lithistsiz >= 0) gethistent(curhist-lithistsiz)->lit = NULL;
X curhistent = gethistent(curhist);
X hp_purge(hp_lex,curhist-histsiz);
X hp_purge(hp_lit,curhist-lithistsiz);
X curhistent->lex = hline;
X *(curhistent->lit = hp_alloc(&hp_lit,1)) = '\0';
X } else
X histremmed = 1;
X}
X
Xvoid inittty() /**/
X{
X attachtty(mypgrp);
X}
X
X/* say we're done using the history mechanism */
X
Xint hend() /**/
X{
Xint flag,save = 1;
XHistent he;
X
X if (!hline)
X return 1;
X if (!interact || strin || unset(SHINSTDIN)) {
X hp_free(hp_lex,hline,hlinesz);
X return 1;
X }
X flag = histdone;
X histdone = 0;
X if (hptr < hline+2)
X save = 0;
X else {
X char *s,*t;
X
X s = curhistent->lit;
X if (*s && *(t = s+strlen(s)-1) == HISTSPACE) *t = '\0';
X hptr[-1] = '\0';
X if (hptr[-2] == '\n')
X if (hline[1]) {
X if (hptr[-3] == HISTSPACE) hptr[-3] = '\0';
X } else save = 0;
X he = gethistent(curhist-1);
X if (!strcmp(hline,"\n") ||
X (isset(HISTIGNOREDUPS) && he->lex && !strcmp(he->lex,hline)) ||
X (isset(HISTIGNORESPACE) && spaceflag))
X save = 0;
X }
X if (flag & (HISTFLAG_DONE|HISTFLAG_RECALL)) {
X char *ptr,*p;
X p = ptr = ztrdup(hline);
X for (;*p;p++) if (*p == HISTSPACE) *p = ' ';
X if ((flag & (HISTFLAG_DONE|HISTFLAG_RECALL)) == HISTFLAG_DONE) {
X fprintf(stderr,"%s\n",ptr);
X fflush(stderr);
X }
X if (flag & HISTFLAG_RECALL) {
X permalloc();
X pushnode(bufstack,ptr);
X lastalloc();
X save = 0;
X } else free(ptr);
X }
X curhistent->stim = time(NULL);
X curhistent->ftim = 0L;
X if (!save) remhist();
X if (hline && !curhistent->lex) hp_free(hp_lex,hline,hlinesz);
X hline = NULL;
X return !(flag & HISTFLAG_NOEXEC || errflag);
X}
X
X/* remove the current line from the history List */
X
Xvoid remhist() /**/
X{
X if (!histremmed) { histremmed = 1; curhist--; }
X}
X
X/* begin a word */
X
Xvoid hwbegin() /**/
X{
X hlastw = hptr;
X}
X
X/* add a word to the history List */
X
Xchar *hwadd() /**/
X{
Xchar *ret = hlastw;
X
X if (hlastw && hline)
X {
X hwaddc(HISTSPACE);
X if (alstackind || strin)
X if (!(alstackind == 1 && !alstack[0]))
X hptr = hlastw;
X }
X if (alstat == ALSTAT_JUNK)
X alstat = 0;


X return ret;
X}
X

X/* get an argument specification */
X
Xint getargspec(argc,marg) /**/
Xint argc;int marg;
X{
Xint c,ret = -1;
X
X if ((c = hgetch()) == '0')
X return 0;
X if (idigit(c))
X {
X ret = 0;
X while (idigit(c))
X {
X ret = ret*10+c-'0';


X c = hgetch();
X }

X hungetch(c);
X }
X else if (c == '^')
X ret = 1;
X else if (c == '$')
X ret = argc;
X else if (c == '%')
X {
X if (marg == -1)
X {
X herrflush();
X zerr("%% with no previous word matched",NULL,0);
X return -2;
X }
X ret = marg;


X }
X else
X hungetch(c);

X return ret;
X}
X

X/* do ?foo? search */
X
Xint hconsearch(str,marg) /**/
Xchar *str;int *marg;
X{
Xint t0,t1 = 0;
Xchar *s,*hs;
X
X for (t0 = curhist-1; hs = quietgetevent(t0); t0--)
X if (s = ztrstr(hs,str)) {
X while (s != hs) if (*s-- == HISTSPACE) t1++;
X *marg = t1;
X return t0;
X }


X return -1;
X}
X

X/* do !foo search */
X
Xint hcomsearch(str) /**/
Xchar *str;
X{
Xint t0;
Xchar *hs;
X
X for (t0 = curhist-1; hs = quietgetevent(t0); t0--)
X if (!strncmp(hs,str,strlen(str))) return t0;


X return -1;
X}
X

X/* various utilities for : modifiers */
X
Xint remtpath(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr,*cut;
X
X if (cut = strrchr(str,'/')) {
X if (str != cut) *cut = '\0';
X else str[1] = '\0';
X return 1;
X }


X return 0;
X}
X

Xint remtext(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr,*cut;
X
X if ((cut = strrchr(str,'.')) && cut != str)
X {
X *cut = '\0';
X return 1;
X }


X return 0;
X}
X

Xint rembutext(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr,*cut;
X
X if ((cut = strrchr(str,'.')) && cut != str)
X {
X *junkptr = strdup(cut+1); /* .xx or xx? */


X return 1;
X }
X return 0;
X}
X

Xint remlpaths(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr,*cut;
X
X if (cut = strrchr(str,'/'))
X {
X *cut = '\0';
X *junkptr = strdup(cut+1);


X return 1;
X }
X return 0;
X}
X

Xint makeuppercase(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr;
X
X for (; *str; str++)
X *str = tuupper(*str);


X return 1;
X}
X

Xint makelowercase(junkptr) /**/
Xchar **junkptr;
X{
Xchar *str = *junkptr;
X
X for (; *str; str++)
X *str = tulower(*str);


X return 1;
X}
X

Xvoid subst(strptr,in,out,gbal) /**/
Xchar **strptr;char *in;char *out;int gbal;
X{
Xchar *str = *strptr,*cut,*sptr;
Xint off;
X
X while (cut = (char *) ztrstr(str,in)) {
X *cut = '\0';
X sptr = convamps(out,in);
X off = cut-*strptr+strlen(sptr);
X cut += strlen(in);
X *strptr = tricat(*strptr,sptr,cut);
X if (gbal) {
X str = (char *) *strptr+off;


X continue;
X }
X break;
X }
X}

X
Xchar *convamps(out,in) /**/
Xchar *out;char *in;
X{
Xchar *ptr,*ret,*pp;
Xint slen,inlen = strlen(in);
X
X for (ptr = out, slen = 0; *ptr; ptr++,slen++)


X if (*ptr == '\\')

X ptr++;
X else if (*ptr == '&')
X slen += inlen-1;
X ret = pp = alloc(slen+1);
X for (ptr = out; *ptr; ptr++)


X if (*ptr == '\\')

X *pp++ = *++ptr;
X else if (*ptr == '&')
X {
X strcpy(pp,in);
X pp += inlen;
X }
X else
X *pp++ = *ptr;
X *pp = '\0';


X return ret;
X}
X

Xchar *makehstr(s) /**/
Xchar *s;
X{
Xchar *t;


X
X t = s = strdup(s);

X for (; *t; t++)
X if (*t == HISTSPACE)
X *t = ' ';


X return s;
X}
X

Xchar *quietgetevent(ev) /**/
Xint ev;
X{
XHistent ent;
X
X if (ev < firsthist()) return NULL;
X ent = gethistent(ev);
X return (lithist) ? ent->lit : ent->lex;
X}
X
Xchar *getevent(ev) /**/
Xint ev;
X{
Xchar *ret;
X
X ret = quietgetevent(ev);
X if (!ret) {
X herrflush();
X zerr("no such event: %d",NULL,ev);


X }
X return ret;
X}
X

Xint getargc(list) /**/
Xchar *list;
X{
Xint argc = 0;
X
X for (; *list; list++) if (*list == HISTSPACE) argc++;
X return argc;
X}
X
Xchar *getargs(elist,arg1,arg2) /**/
Xchar *elist;int arg1;int arg2;
X{
Xchar *ret = elist,*retn;
Xint acnt = arg2-arg1+1;
X
X while (arg1--)
X while (*ret && *ret++ != HISTSPACE);
X if (!*ret)
X {
X herrflush();
X zerr("no such word in event",NULL,0);
X return NULL;
X }
X retn = ret = strdup(ret);
X while (acnt > 0)
X {
X while (*ret && *ret != HISTSPACE)
X ret++;
X if (*ret == HISTSPACE)
X *ret = ' ';
X else
X break;
X acnt--;
X }
X if (acnt > 1 && !*ret)
X {
X herrflush();
X zerr("no such word in event",NULL,0);
X return NULL;
X }
X *ret = '\0';
X return retn;
X}
X
Xvoid upcase(x) /**/
Xchar **x;
X{
Xchar *pp = *(char **) x;


X
X for (; *pp; pp++)

X *pp = tuupper(*pp);
X}
X
Xvoid downcase(x) /**/
Xchar **x;
X{
Xchar *pp = *(char **) x;


X
X for (; *pp; pp++)

X *pp = tulower(*pp);
X}
X
Xint quote(tr) /**/
Xchar **tr;
X{
Xchar *ptr,*rptr,**str = (char **) tr;
Xint len = 3;
X
X for (ptr = *str; *ptr; ptr++,len++)
X if (*ptr == '\'') len += 3;
X ptr = *str;
X *str = rptr = alloc(len);
X *rptr++ = '\'';
X for (; *ptr; ptr++)


X if (*ptr == '\'') {

X *rptr++ = '\''; *rptr++ = '\\'; *rptr++ = '\''; *rptr++ = '\'';
X } else
X *rptr++ = *ptr;
X *rptr++ = '\'';
X *rptr++ = 0;
X str[1] = NULL;


X return 0;
X}
X

Xint quotebreak(tr) /**/
Xchar **tr;
X{
Xchar *ptr,*rptr,**str = (char **) tr;
Xint len = 3;
X
X for (ptr = *str; *ptr; ptr++,len++)


X if (*ptr == '\'')

X len += 3;
X else if (inblank(*ptr))
X len += 2;
X ptr = *str;
X *str = rptr = alloc(len);
X *rptr++ = '\'';
X for (; *ptr; )


X if (*ptr == '\'') {

X *rptr++ = '\''; *rptr++ = '\\'; *rptr++ = '\''; *rptr++ = '\'';
X ptr++;
X } else if (inblank(*ptr)) {
X *rptr++ = '\''; *rptr++ = *ptr++; *rptr++ = '\'';
X } else
X *rptr++ = *ptr++;
X *rptr++ = '\'';
X *rptr++ = '\0';


X return 0;
X}
X

Xvoid herrflush() /**/
X{
X if (strin)
X hflush();
X else while (lastc != '\n' && !lexstop)
X hgetch();
X}
X
X/* read an arbitrary amount of data into a buffer until stop is found */
X
Xchar *hdynread(stop) /**/
Xint stop;
X{
Xint bsiz = 256,ct = 0,c;
Xchar *buf = zalloc(bsiz),*ptr;
X
X ptr = buf;
X while ((c = hgetch()) != stop && c != '\n' && !lexstop)
X {


X if (c == '\\')

X c = hgetch();
X *ptr++ = c;
X if (++ct == bsiz)
X {


X buf = realloc(buf,bsiz *= 2);

X ptr = buf+ct;
X }


X }
X *ptr = 0;

X if (c == '\n')
X {
X hungetch('\n');
X zerr("delimiter expected",NULL,0);
X free(buf);
X return NULL;
X }
X return buf;
X}
X
Xchar *hdynread2(stop) /**/
Xint stop;
X{
Xint bsiz = 256,ct = 0,c;
Xchar *buf = zalloc(bsiz),*ptr;
X
X ptr = buf;
X while ((c = hgetch()) != stop && c != '\n' && !lexstop)
X {
X if (c == '\n')
X {
X hungetch(c);
X break;


X }
X if (c == '\\')

X c = hgetch();
X *ptr++ = c;
X if (++ct == bsiz)
X {


X buf = realloc(buf,bsiz *= 2);

X ptr = buf+ct;
X }


X }
X *ptr = 0;

X if (c == '\n')
X hungetch('\n');


X return buf;
X}
X

Xvoid inithist() /**/
X{
X hp_lit = zalloc(sizeof *hp_lit);
X hp_lit->next = NULL;
X hp_lit->ptr = hp_lit->pool = zalloc(HEAPSIZE);
X hp_lit->free = HEAPSIZE;
X hp_lex = zalloc(sizeof *hp_lex);
X hp_lex->next = NULL;
X hp_lex->ptr = hp_lex->pool = zalloc(HEAPSIZE);
X hp_lex->free = HEAPSIZE;
X histentct = (lithistsiz > histsiz) ? lithistsiz : histsiz;
X histentarr = zcalloc(histentct*sizeof *histentarr);
X}
X
Xvoid resizehistents() /**/
X{
Xint newentct,t0,t1,firstlit,firstlex;
XHistent newarr;
X
X newentct = (lithistsiz > histsiz) ? lithistsiz : histsiz;
X newarr = zcalloc(newentct*sizeof *newarr);
X firstlex = curhist-histsiz+1;
X firstlit = curhist-lithistsiz+1;
X t0 = firsthist();
X if (t0 < curhist-newentct) t0 = curhist-newentct;
X t1 = t0 % newentct;
X for (; t0 <= curhist; t0++) {
X newarr[t1] = *gethistent(t0);
X if (t0 < firstlex) newarr[t1].lex = NULL;
X if (t0 < firstlit) newarr[t1].lit = NULL;
X t1++; if (t1 == newentct) t1 = 0;
X }
X free(histentarr);
X histentarr = newarr;
X histentct = newentct;
X}
X
Xchar *hp_alloc(hp,siz) /**/
XHp *hp; int siz;
X{
Xchar *ret;
XHp h = *hp;
X
X if (h->free >= siz) {
X ret = h->ptr;
X h->ptr += siz;
X h->free -= siz;
X return ret;
X }
X#ifdef MEMDEBUG
X fprintf(stderr,"new heap (siz = %d, curhist = %d)\n",siz,curhist);
X#endif
X permalloc();
X h = zalloc(sizeof *h);
X h->next = *hp;
X h->free = (siz > HEAPSIZE) ? siz : HEAPSIZE;
X h->ptr = h->pool = zalloc(h->free);
X h->histno = curhist;
X *hp = h;
X heapalloc();
X return hp_alloc(hp,siz);
X}
X
Xchar *hp_realloc(hp,ptr,oldsiz,newsiz) /**/
XHp *hp; char *ptr; int oldsiz; int newsiz;
X{
XHp h = *hp;
Xint delta = newsiz-oldsiz;
Xchar *ret;
X
X if (h->ptr-oldsiz == ptr && h->free >= delta) {
X h->free -= delta;
X h->ptr += delta;
X return ptr;
X }
X#ifdef MEMDEBUG
X fprintf(stderr,"realloc copy\n");
X#endif
X memcpy(ret = hp_alloc(hp,newsiz),ptr,oldsiz);


X return ret;
X}
X

Xvoid hp_free(h,ptr,siz) /**/
XHp h; char *ptr; int siz;
X{
X if (h->ptr-siz == ptr) {
X h->free += siz;
X h->ptr -= siz;
X }
X}
X
Xchar *hp_concat(old,new) /**/
Xchar *old; char *new;
X{
Xint oldlen,newlen;
X
X oldlen = strlen(old); newlen = strlen(new);
X old = hp_realloc(&hp_lit,old,oldlen+1,oldlen+newlen+1);
X strcpy(old+oldlen,new);
X return old;
X}
X
Xvoid hp_purge(h,lim) /**/
XHp h; int lim;
X{
XHp hlast;
X
X if (!h->next) return;
X while (h->next) { hlast = h; h = h->next; }
X if (h->histno <= lim || h->histno == 0) {
X#ifdef MEMDEBUG
X fprintf(stderr,"purging %d\n",lim);
X#endif
X free(h->pool);
X free(h);
X hlast->next = NULL;
X }
X}
X
Xvoid readhistfile(s,err) /**/
Xchar *s;int err;
X{
Xchar buf[1024];
XFILE *in;
XHistent ent;
Xtime_t tim = time(NULL);
X
X if (!s) return;
X if (in = fopen(s,"r")) {
X while (fgets(buf,1024,in)) {
X int l = strlen(buf);
X char *pt = buf;
X
X while (l && buf[l-1] == '\n') {
X buf[l-1] = '\0';
X if (l > 1 && buf[l-2] == '\\') {
X buf[l-2] = '\n';
X fgets(buf+l-1,1024-(l-1),in);
X l = strlen(buf);
X } else break;
X }
X for (;*pt;pt++) if (*pt == ' ') *pt = HISTSPACE;
X
X ent = gethistent(++curhist);
X ent->lex = hp_alloc(&hp_lex,strlen(buf)+1);
X strcpy(ent->lex,buf);
X ent->lit = hp_alloc(&hp_lit,strlen(buf)+1);
X strcpy(ent->lit,buf);
X ent->ftim = ent->stim = tim;
X }
X fclose(in);
X } else if (err)
X zerr("can't read history file",s,0);
X}
X
Xvoid savehistfile(s,err,app) /**/
Xchar *s;int err;int app;
X{
Xchar *t;
XFILE *out;
Xint ev,flag;
X
X if (!s || !interact) return;
X ev = curhist-savehist+1;
X flag = (app) ? O_APPEND : O_TRUNC;
X if (ev < firsthist()) ev = firsthist();
X if (out = fdopen(open(s,O_CREAT|O_WRONLY|flag,0600),"w")) {
X for (; ev <= curhist; ev++) {
X t = quietgetevent(ev);
X for (; *t; t++)
X if (*t == HISTSPACE) fputc(' ',out);
X else {
X if (*t == '\n') fputc('\\',out);
X fputc(*t,out);
X }
X fputc('\n',out);
X }
X fclose(out);
X } else if (err) zerr("can't write history file: %s",s,0);
X}
X
Xint firsthist() /**/
X{
Xint ev;
XHistent ent;
X
X ev = curhist-histentct+1;
X if (ev < 1) ev = 1;
X do {
X ent = gethistent(ev);
X if ((lithist) ? ent->lit : ent->lex) break;
X ev++;
X } while (ev < curhist);
X return ev;
X}
X
SHAR_EOF
echo 'File zsh2.2/src/hist.c is complete' &&
chmod 0644 zsh2.2/src/hist.c ||


echo 'restore of zsh2.2/src/hist.c failed'

Wc_c="`wc -c < 'zsh2.2/src/hist.c'`"
test 23511 -eq "$Wc_c" ||
echo 'zsh2.2/src/hist.c: original size 23511, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/init.c ==============
if test -f 'zsh2.2/src/init.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/init.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/init.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/init.c' &&
X/*
X *
X * init.c - main loop and initialization routines


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#define GLOBALS
X#include "zsh.h"
X#include <pwd.h>
X
Xvoid main(argc,argv,envp) /**/
Xint argc; char **argv; char **envp;
X{
Xint notect = 0;
X
X#ifdef LC_ALL
X setlocale(LC_ALL, "");
X#endif
X environ = envp;
X meminit();
X setflags();
X parseargs(argv);
X setmoreflags();
X setupvals();
X initialize();
X heapalloc();
X runscripts();
X for(;;)
X {
X do
X loop();
X while (tok != ENDINPUT);
X if (!(isset(IGNOREEOF) && interact))
X {
X#if 0
X if (interact)
X fputs(islogin ? "logout\n" : "exit\n",stderr);
X#endif
X zexit(NULL);
X continue;
X }
X zerrnam("zsh",(!islogin) ? "use 'exit' to exit."
X : "use 'logout' to logout.",NULL,0);
X notect++;
X if (notect == 10)
X zexit(NULL);
X }
X}
X
X/* keep executing lists until EOF found */
X
Xvoid loop() /**/
X{
XList list;
XHeap h = (Heap) peekfirst(heaplist);
X
X pushheap();
X for(;;)
X {
X freeheap();


X if (interact && isset(SHINSTDIN))

X preprompt();
X hbegin(); /* init history mech */
X intr(); /* interrupts on */
X ainit(); /* init alias mech */
X lexinit();
X errflag = 0;
X if (!(list = parse_event()))
X { /* if we couldn't parse a list */
X hend();
X if (tok == ENDINPUT && !errflag)
X break;
X continue;
X }
X if (hend())
X {
X if (stopmsg) /* unset 'you have stopped jobs' flag */
X stopmsg--;
X execlist(list);
X }
X if (ferror(stderr))
X {
X zerr("write error",NULL,0);
X clearerr(stderr);
X }
X if (subsh) /* how'd we get this far in a subshell? */
X exit(lastval);
X if ((!interact && errflag) || retflag)
X break;
X if ((opts['t'] == OPT_SET) || (lastval && opts[ERREXIT] == OPT_SET))
X {


X if (sigtrapped[SIGEXIT])
X dotrap(SIGEXIT);

X exit(lastval);
X }
X }
X while ((Heap) peekfirst(heaplist) != h)
X popheap();
X}
X
Xvoid setflags() /**/
X{
Xint c;
X
X for (c = 0; c != 32; c++) opts[c] = OPT_UNSET;
X for (c = 32; c != 128; c++) opts[c] = OPT_INVALID;
X for (c = 'a'; c <= 'z'; c++) opts[c] = opts[c-'a'+'A'] = OPT_UNSET;
X for (c = '0'; c <= '9'; c++) opts[c] = OPT_UNSET;
X opts['A'] = OPT_INVALID;
X opts['i'] = (isatty(0)) ? OPT_SET : OPT_UNSET;
X opts[BGNICE] = opts[NOTIFY] = OPT_SET;
X opts[USEZLE] = (interact && SHTTY != -1) ? OPT_SET : OPT_UNSET;
X opts[HASHCMDS] = opts[HASHLISTALL] = opts[HASHDIRS] = OPT_SET;
X}
X
Xstatic char *cmd;
X
Xvoid parseargs(argv) /**/
Xchar **argv;
X{
Xchar **x;
Xint bk = 0,action;
XLklist paramlist;
X
X hackzero = argzero = *argv;
X opts[LOGINSHELL] = (**(argv++) == '-') ? OPT_SET : OPT_UNSET;
X SHIN = 0;
X while (!bk && *argv && (**argv == '-' || **argv == '+'))
X {
X action = (**argv == '-') ? OPT_SET : OPT_UNSET;
X while (*++*argv) {
X if (opts[**argv] == OPT_INVALID) {
X zerr("bad option: -%c",NULL,**argv);
X exit(1);
X }
X if (bk = **argv == 'b') break;
X if (**argv == 'c') { /* -c command */


X argv++;
X if (!*argv) {

X zerr("string expected after -c",NULL,0);
X exit(1);
X }
X cmd = *argv;
X opts[INTERACTIVE] = OPT_UNSET;
X opts['c'] = OPT_SET;
X break;
X } else if (**argv == 'o') {
X int c;
X
X if (!*++*argv)


X argv++;
X if (!*argv) {

X zerr("string expected after -o",NULL,0);
X exit(1);
X }
X c = optlookup(*argv);


X if (c == -1)

X zerr("no such option: %s",*argv,0);
X else
X opts[c] = action;
X break;
X } else opts[**argv] = action;
X }
X argv++;
X }
X paramlist = newlist();
X if (*argv)
X {
X if (opts[SHINSTDIN] == OPT_UNSET)
X {
X SHIN = movefd(open(argzero = *argv,O_RDONLY));
X if (SHIN == -1)
X {
X zerr("can't open input file: %s",*argv,0);
X exit(1);
X }
X opts[INTERACTIVE] = OPT_UNSET;
X argv++;
X }
X while (*argv)
X addnode(paramlist,ztrdup(*argv++));
X }
X else
X opts[SHINSTDIN] = OPT_SET;
X pparams = x = zcalloc((countnodes(paramlist)+1)*sizeof(char *));
X while (*x++ = getnode(paramlist));
X free(paramlist);


X argzero = ztrdup(argzero);
X}
X

Xvoid setmoreflags() /**/
X{
Xint t0;
Xlong ttpgrp;
X
X /* stdout,stderr fully buffered */
X#ifdef _IOFBF
X setvbuf(stdout,malloc(BUFSIZ),_IOFBF,BUFSIZ);
X setvbuf(stderr,malloc(BUFSIZ),_IOFBF,BUFSIZ);
X#else
X setbuffer(stdout,malloc(BUFSIZ),BUFSIZ);
X setbuffer(stderr,malloc(BUFSIZ),BUFSIZ);
X#endif
X subsh = 0;
X#ifndef NOCLOSEFUNNYFDS
X /* this works around a bug in some versions of in.rshd */
X for (t0 = 3; t0 != 10; t0++)
X close(t0);
X#endif
X#ifdef JOB_CONTROL
X opts[MONITOR] = (interact) ? OPT_SET : OPT_UNSET;
X if (jobbing) {
X SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty",O_RDWR));
X if (SHTTY == -1)


X opts[MONITOR] = OPT_UNSET;

X else {
X#ifdef TIOCSETD
X#ifdef NTTYDISC
X int ldisc = NTTYDISC;
X ioctl(SHTTY, TIOCSETD, &ldisc);
X#endif
X#endif
X gettyinfo(&shttyinfo); /* get tty state */
X#ifdef sgi
X if (shttyinfo.tio.c_cc[VSWTCH] <= 0) /* hack for irises */
X shttyinfo.tio.c_cc[VSWTCH] = CSWTCH;
X#endif
X savedttyinfo = shttyinfo;
X }
X#ifdef sgi
X setpgrp(0,getpgrp(0));
X#endif
X if ((mypgrp = getpgrp(0)) <= 0)


X opts[MONITOR] = OPT_UNSET;

X else while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) {
X sleep(1);
X mypgrp = getpgrp(0);
X if (mypgrp == gettygrp()) break;
X killpg(mypgrp,SIGTTIN);
X mypgrp = getpgrp(0);
X }
X } else
X SHTTY = -1;
X#else


X opts[MONITOR] = OPT_UNSET;

X SHTTY = movefd((isatty(0)) ? dup(0) : open("/dev/tty",O_RDWR));


X if (SHTTY != -1) {

X gettyinfo(&shttyinfo);
X savedttyinfo = shttyinfo;
X }
X#endif
X}
X
Xvoid setupvals() /**/
X{
Xstruct passwd *pswd;
Xchar *ptr,*s;
Xstatic long bauds[] = {
X 0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400
X };
X
X curhist = 0;
X histsiz = DEFAULT_HISTSIZE;
X lithistsiz = 5;
X inithist();
X mailcheck = logcheck = 60;
X dirstacksize = -1;
X listmax = 100;
X reporttime = -1;
X bangchar = '!';
X hashchar = '#';
X hatchar = '^';
X termok = 0;
X curjob = prevjob = coprocin = coprocout = -1;
X shtimer = time(NULL); /* init $SECONDS */
X srand((unsigned int) shtimer);
X /* build various hash tables; argument to newhtable is table size */
X aliastab = newhtable(37);
X addreswords();
X paramtab = newhtable(151);
X cmdnamtab = newhtable(37);
X compctltab = newhtable(13);
X initxbindtab();
X nullcmd = ztrdup("cat");
X readnullcmd = ztrdup("more");
X prompt = ztrdup("%m%# ");
X prompt2 = ztrdup("> ");
X prompt3 = ztrdup("?# ");
X prompt4 = ztrdup("+ ");
X sprompt = ztrdup("zsh: correct `%R' to `%r' [nyae]? ");
X term = ztrdup("");
X ppid = getppid();
X#ifdef TIO
X#ifdef HAS_TCCRAP
X baud = cfgetospeed(&shttyinfo.tio);
X if (baud < 100) baud = bauds[baud]; /* aren't "standards" great?? */
X#else
X baud = bauds[shttyinfo.tio.c_cflag & CBAUD];
X#endif
X#else
X baud = bauds[shttyinfo.sgttyb.sg_ospeed];
X#endif
X#ifdef TIOCGWINSZ
X if (!(columns = shttyinfo.winsize.ws_col))
X columns = 80;
X if (!(lines = shttyinfo.winsize.ws_row))
X lines = 24;
X#else
X columns = 80;
X lines = 24;
X#endif
X ifs = ztrdup(" \t\n");
X if (pswd = getpwuid(getuid())) {
X username = ztrdup(pswd->pw_name);
X home = ztrdup(pswd->pw_dir);
X } else {
X username = ztrdup("");
X home = ztrdup("/");
X }
X if (ptr = zgetenv("LOGNAME"))
X logname = ztrdup(ptr);
X else
X logname = ztrdup(username);
X timefmt = ztrdup(DEFTIMEFMT);
X watchfmt = ztrdup(DEFWATCHFMT);
X if (!(ttystrname = ztrdup(ttyname(SHTTY))))
X ttystrname = ztrdup("");
X wordchars = ztrdup(DEFWORDCHARS);
X fceditparam = ztrdup(DEFFCEDIT);
X tmpprefix = ztrdup(DEFTMPPREFIX);
X postedit = ztrdup("");
X if (ispwd(home)) pwd = ztrdup(home);
X else if ((ptr = zgetenv("PWD")) && ispwd(ptr)) pwd = ztrdup(ptr);
X else pwd = zgetwd();
X oldpwd = ztrdup(pwd);
X hostnam = zalloc(256);
X underscore = ztrdup("");
X gethostname(hostnam,256);
X mypid = getpid();
X cdpath = mkarray(NULL);
X manpath = mkarray(NULL);
X fignore = mkarray(NULL);
X fpath = mkarray(NULL);
X mailpath = mkarray(NULL);
X watch = mkarray(NULL);
X hosts = mkarray(NULL);
X compctlsetup();
X userdirs = (char **) zcalloc(sizeof(char *)*2);
X usernames = (char **) zcalloc(sizeof(char *)*2);
X userdirsz = 2;
X userdirct = 0;


X optarg = ztrdup("");

X zoptind = 1;
X schedcmds = NULL;
X path = (char **) zalloc(4*sizeof *path);
X path[0] = ztrdup("/bin"); path[1] = ztrdup("/usr/bin");
X path[2] = ztrdup("/usr/ucb"); path[3] = NULL;
X inittyptab();
X initlextabs();
X setupparams();
X setparams();
X inittyptab();
X if ((s = zgetenv("EMACS")) && !strcmp(s,"t") && !strcmp(term,"emacs"))
X opts[USEZLE] = OPT_UNSET;
X#ifndef HAS_RUSAGE
X times(&shtms);
X#endif
X}
X
Xvoid compctlsetup() /**/
X{
Xstatic char
X *hs[] = {"telnet","rlogin","ftp","rup","rusers","rsh",NULL},
X *os[] = {"setopt","unsetopt",NULL},
X *vs[] = {"export","typeset","vared","unset",NULL},
X *cs[] = {"which","builtin",NULL},
X *bs[] = {"bindkey",NULL};
X
X compctl_process(hs,CC_HOSTS|CC_FILES,NULL);
X compctl_process(os,CC_OPTIONS,NULL);
X compctl_process(vs,CC_VARS,NULL);
X compctl_process(bs,CC_BINDINGS,NULL);
X compctl_process(cs,CC_COMMPATH,NULL);
X cc_compos.mask = CC_COMMPATH;
X cc_default.mask = CC_FILES;
X}
X
Xvoid initialize() /**/
X{
Xint t0;
X
X breaks = loops = 0;
X lastmailcheck = time(NULL);
X locallist = NULL;
X dirstack = newlist();
X bufstack = newlist();
X newcmdnamtab();


X inbuf = zalloc(inbufsz = 256);
X inbufptr = inbuf+inbufsz;
X inbufct = 0;

X#ifndef QDEBUG
X signal(SIGQUIT,SIG_IGN);
X#endif
X#ifdef RLIM_INFINITY


X for (t0 = 0; t0 != RLIM_NLIMITS; t0++)

X getrlimit(t0,limits+t0);
X#endif
X hsubl = hsubr = NULL;
X lastpid = 0;
X bshin = fdopen(SHIN,"r");
X signal(SIGCHLD,handler);
X if (jobbing)
X {
X int ttypgrp;


X for (;;)
X {

X#ifdef TIOCGPGRP
X ioctl(SHTTY, TIOCGPGRP, &ttypgrp);
X#else
X ttypgrp = tcgetpgrp(SHTTY);
X#endif
X if (ttypgrp == mypgrp)
X break;
X kill(0,SIGTTIN);


X }
X signal(SIGTTOU,SIG_IGN);
X signal(SIGTSTP,SIG_IGN);
X signal(SIGTTIN,SIG_IGN);
X signal(SIGPIPE,SIG_IGN);

X attachtty(mypgrp);


X }
X if (interact)
X {

X signal(SIGTERM,SIG_IGN);
X#ifdef SIGWINCH
X signal(SIGWINCH,handler);
X#endif
X signal(SIGALRM,handler);
X intr();
X }
X}
X
Xvoid addreswords() /**/
X{
Xstatic char *reswds[] = {
X "do", "done", "esac", "then", "elif", "else", "fi", "for", "case",
X "if", "while", "function", "repeat", "time", "until", "exec", "command",
X "select", "coproc", "noglob", "-", "nocorrect", "foreach", "end", NULL
X };
Xint t0;
X
X for (t0 = 0; reswds[t0]; t0++)
X addhperm(reswds[t0],mkanode(NULL,-1-t0),aliastab,NULL);
X}
X
Xvoid runscripts() /**/
X{
X#ifdef GLOBALZSHENV
X source(GLOBALZSHENV);
X#endif
X if (opts[NORCS] == OPT_SET) {
X#ifdef GLOBALZPROFILE
X if (islogin) source(GLOBALZPROFILE);
X#endif
X#ifdef GLOBALZSHRC
X source(GLOBALZSHRC);
X#endif
X#ifdef GLOBALZLOGIN
X if (islogin) source(GLOBALZLOGIN);
X#endif
X } else {
X sourcehome(".zshenv");
X if (opts[NORCS] == OPT_SET)
X return;
X if (interact) {
X if (islogin) {
X sourcehome(".zprofile");
X#ifdef GLOBALZPROFILE
X source(GLOBALZPROFILE);
X#endif
X }
X#ifdef GLOBALZSHRC
X source(GLOBALZSHRC);
X#endif
X sourcehome(".zshrc");
X if (islogin) {
X#ifdef GLOBALZLOGIN
X source(GLOBALZLOGIN);
X#endif
X sourcehome(".zlogin");
X }
X }
X }
X if (interact)
X readhistfile(getsparam("HISTFILE"),0);
X if (opts['c'] == OPT_SET)
X {
X if (SHIN >= 10)
X close(SHIN);
X SHIN = movefd(open("/dev/null",O_RDONLY));
X execstring(cmd);
X stopmsg = 1;
X zexit(NULL);
X }
X#ifdef TIOCSWINSZ
X if (!(columns = shttyinfo.winsize.ws_col))
X columns = 80;
X if (!(lines = shttyinfo.winsize.ws_row))
X lines = 24;
X#endif
X}
X
Xvoid ainit() /**/
X{
X alstackind = 0; /* reset alias stack */
X alstat = 0;
X isfirstln = 1;
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/init.c ||
echo 'restore of zsh2.2/src/init.c failed'
Wc_c="`wc -c < 'zsh2.2/src/init.c'`"
test 11807 -eq "$Wc_c" ||
echo 'zsh2.2/src/init.c: original size 11807, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/jobs.c ==============
if test -f 'zsh2.2/src/jobs.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/jobs.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/jobs.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/jobs.c' &&
X/*
X *
X * jobs.c - job control


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"

X#include <sys/errno.h>
X
X/* != 0 means the handler is active */
X
Xstatic int handling = 0;
X
X#ifdef INTHANDTYPE
X#define RETURN return 0
X#else
X#define RETURN return
X#endif
X
X/* the signal handler */
X
XHANDTYPE handler(sig,code) /**/
Xint sig;int code;
X{
Xlong pid;
Xint statusp;
XJob jn;
Xstruct process *pn;
X#ifdef HAS_RUSAGE
Xstruct rusage ru;
X#else
Xlong chlds,chldu;
X#endif
X
X#ifdef RESETHANDNEEDED
X signal(sig,handler);
X#endif
X if (sig == SIGINT)
X {


X if (sigtrapped[SIGINT])

X dotrap(SIGINT);
X else
X errflag = 1;
X RETURN;
X }
X#ifdef SIGWINCH
X if (sig == SIGWINCH)
X adjustwinsize();
X#endif
X if (sig != SIGCHLD)
X {
X dotrap(sig);
X if (sig == SIGALRM && !sigtrapped[SIGALRM])
X {
X zerr("timeout",NULL,0);
X exit(1);
X }
X RETURN;


X }
X for (;;)
X {

X#ifdef HAS_RUSAGE
X pid = wait3((vptr) &statusp,WNOHANG|WUNTRACED,&ru);
X#else
X#ifndef WNOHANG
X pid = wait(&statusp);
X#else
X pid = wait3((vptr) &statusp,WNOHANG|WUNTRACED,NULL);
X#endif
X chlds = shtms.tms_cstime;
X chldu = shtms.tms_cutime;
X times(&shtms);
X#endif
X if (pid == -1)
X {
X if (errno != ECHILD)
X zerr("wait failed: %e",NULL,errno);
X RETURN;
X }
X if (!pid)
X RETURN;
X findproc(pid,&jn,&pn); /* find the process of this pid */
X if (jn)
X {
X pn->statusp = statusp;
X handling = 1;
X#ifdef HAS_RUSAGE
X pn->ti.ru = ru;
X#else
X pn->ti.st = shtms.tms_cstime-chlds;
X pn->ti.ut = shtms.tms_cutime-chldu;
X#endif
X pn->endtime = time(NULL);
X updatestatus(jn);
X handling = 0;
X }
X#if 0
X else if (WIFSTOPPED(statusp))
X kill(pid,SIGKILL); /* kill stopped untraced children */
X#endif
X }
X}
X
X/* change job table entry from stopped to running */
X
Xvoid makerunning(jn) /**/
XJob jn;
X{
Xstruct process *pn;
X
X jn->stat &= ~STAT_STOPPED;
X for (pn = jn->procs; pn; pn = pn->next)
X if (WIFSTOPPED(pn->statusp))
X pn->statusp = SP_RUNNING;
X}
X
X/* update status of job, possibly printing it */
X
Xvoid updatestatus(jn) /**/
XJob jn;
X{
Xstruct process *pn;
Xint notrunning = 1,alldone = 1,val,job = jn-jobtab,somestopped = 0;
X
X for (pn = jn->procs; pn; pn = pn->next)
X {
X if (pn->statusp == SP_RUNNING)
X notrunning = 0;
X if (pn->statusp == SP_RUNNING || WIFSTOPPED(pn->statusp))
X alldone = 0;
X if (WIFSTOPPED(pn->statusp))
X somestopped = 1;
X if (!pn->next && jn)
X val = (WIFSIGNALED(pn->statusp)) ?
X 0200 | WTERMSIG(pn->statusp) : WEXITSTATUS(pn->statusp);
X }
X if (!notrunning)
X return;
X if (somestopped && (jn->stat & STAT_STOPPED))
X return;
X jn->stat |= (alldone) ? STAT_CHANGED|STAT_DONE :
X STAT_CHANGED|STAT_STOPPED;
X if (alldone && job == thisjob)
X {
X if (!ttyfrozen && !val) {
X gettyinfo(&shttyinfo);
X if (interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))
X sanetty(&shttyinfo);
X#ifdef TIOCSWINSZ
X if (!(columns = shttyinfo.winsize.ws_col))
X columns = 80;
X lines = shttyinfo.winsize.ws_row;
X#endif
X } else
X settyinfo(&shttyinfo);


X lastval = val;
X }

X if ((jn->stat & (STAT_DONE|STAT_STOPPED)) == STAT_STOPPED) {
X prevjob = curjob;
X curjob = job;
X }
X if ((isset(NOTIFY) || job == thisjob) && jn->stat & STAT_LOCKED) {
X printjob(jn,!!isset(LONGLISTJOBS));
X if (zleactive) refresh();
X }
X if (sigtrapped[SIGCHLD] && job != thisjob)
X dotrap(SIGCHLD);
X}
X
X/* find process and job associated with pid */
X
Xvoid findproc(pid,jptr,pptr) /**/
Xint pid;Job *jptr;struct process **pptr;
X{
Xstruct process *pn;
Xint jn;
X
X for (jn = 1; jn != MAXJOB; jn++)
X for (pn = jobtab[jn].procs; pn; pn = pn->next)
X if (pn->pid == pid)
X {
X *pptr = pn;
X *jptr = jobtab+jn;
X return;
X }
X *pptr = NULL;
X *jptr = NULL;
X}
X
X/*
X lng = 0 means jobs
X lng = 1 means jobs -l
X lng = 2 means jobs -p
X*/
X
Xvoid printjob(jn,lng) /**/
XJob jn;int lng;
X{
Xint job = jn-jobtab,len = 9,sig = -1,sflag = 0,llen,printed = 0;
Xint conted = 0,lineleng = getlineleng(),skip = 0,doputnl = 0;
Xstruct process *pn;
X
X if (lng < 0)
X {
X conted = 1;
X lng = 0;
X }
X
X /* find length of longest signame, check to see if we
X really need to print this job */
X
X for (pn = jn->procs; pn; pn = pn->next)
X {
X if (pn->statusp != SP_RUNNING)
X if (WIFSIGNALED(pn->statusp))
X {
X sig = WTERMSIG(pn->statusp);
X llen = strlen(sigmsg[sig]);
X if (WCOREDUMPED(pn->statusp))
X llen += 14;
X if (llen > len)
X len = llen;
X if (sig != SIGINT && sig != SIGPIPE)
X sflag = 1;
X else if (sig == SIGINT)
X errflag = 1;
X if (job == thisjob && sig == SIGINT)
X doputnl = 1;
X }
X else if (WIFSTOPPED(pn->statusp))
X {
X sig = WSTOPSIG(pn->statusp);
X if (strlen(sigmsg[sig]) > len)
X len = strlen(sigmsg[sig]);
X if (job == thisjob && sig == SIGTSTP)
X doputnl = 1;
X }
X else if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
X WEXITSTATUS(pn->statusp))
X sflag = 1;
X }
X
X /* print if necessary */
X
X if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag ||
X job != thisjob))
X {
X int len2,fline = 1;
X struct process *qn;
X
X trashzle();
X if (doputnl)
X putc('\n',stderr);
X for (pn = jn->procs; pn;)
X {
X len2 = ((job == thisjob) ? 5 : 10)+len; /* 2 spaces */
X if (lng)
X qn = pn->next;
X else for (qn = pn->next; qn; qn = qn->next)
X {
X if (qn->statusp != pn->statusp)
X break;
X if (strlen(qn->text)+len2+((qn->next) ? 3 : 0) > lineleng)
X break;
X len2 += strlen(qn->text)+2;
X }
X if (job != thisjob)
X if (fline)
X fprintf(stderr,"[%d] %c ",jn-jobtab,(job == curjob) ? '+' :
X (job == prevjob) ? '-' : ' ');
X else
X fprintf(stderr,(job > 9) ? " " : " ");
X else
X fprintf(stderr,"zsh: ");
X if (lng)
X if (lng == 1)
X fprintf(stderr,"%d ",pn->pid);
X else
X {
X int x = jn->gleader;
X
X fprintf(stderr,"%d ",x);
X do skip++; while (x /= 10);
X skip++;
X lng = 0;
X }
X else
X fprintf(stderr,"%*s",skip,"");
X if (pn->statusp == SP_RUNNING)
X if (!conted)
X fprintf(stderr,"running%*s",len-7+2,"");
X else
X fprintf(stderr,"continued%*s",len-9+2,"");
X else if (WIFEXITED(pn->statusp))
X if (WEXITSTATUS(pn->statusp))
X fprintf(stderr,"exit %-4d%*s",WEXITSTATUS(pn->statusp),
X len-9+2,"");
X else
X fprintf(stderr,"done%*s",len-4+2,"");
X else if (WIFSTOPPED(pn->statusp))
X fprintf(stderr,"%-*s",len+2,sigmsg[WSTOPSIG(pn->statusp)]);
X else if (WCOREDUMPED(pn->statusp))
X fprintf(stderr,"%s (core dumped)%*s",
X sigmsg[WTERMSIG(pn->statusp)],
X len-14+2-strlen(sigmsg[WTERMSIG(pn->statusp)]),"");
X else
X fprintf(stderr,"%-*s",len+2,sigmsg[WTERMSIG(pn->statusp)]);
X for (; pn != qn; pn = pn->next)
X fprintf(stderr,(pn->next) ? "%s | " : "%s",pn->text);
X putc('\n',stderr);
X fline = 0;
X }
X printed = 1;
X }
X else if (doputnl && interact)
X putc('\n',stderr);
X fflush(stderr);
X
X /* print "(pwd now: foo)" messages */
X
X if (interact && job==thisjob && strcmp(jn->pwd,pwd))
X {
X printf("(pwd now: ");
X printdir(pwd);


X printf(")\n");

X fflush(stdout);
X }
X
X /* delete job if done */
X
X if (jn->stat & STAT_DONE)


X {
X static struct job zero;

X struct process *nx;
X char *s;
X
X if ((jn->stat & STAT_TIMED) || (reporttime != -1 && report(jn))) {
X dumptime(jn);
X printed = 1;
X }
X for (pn = jn->procs; pn; pn = nx)
X {
X nx = pn->next;
X free(pn);
X }
X free(jn->pwd);
X if (jn->filelist)
X {
X while (s = getnode(jn->filelist))
X {
X unlink(s);
X free(s);
X }
X free(jn->filelist);
X }
X *jn = zero;
X if (job == curjob)


X {
X curjob = prevjob;

X prevjob = job;
X }
X if (job == prevjob)
X setprevjob();
X }
X else
X jn->stat &= ~STAT_CHANGED;
X}
X
X/* set the previous job to something reasonable */
X
Xvoid setprevjob() /**/
X{
Xint t0;
X
X for (t0 = MAXJOB-1; t0; t0--)
X if ((jobtab[t0].stat & STAT_INUSE) && (jobtab[t0].stat & STAT_STOPPED) &&
X t0 != curjob && t0 != thisjob)
X break;
X if (!t0)
X for (t0 = MAXJOB-1; t0; t0--)
X if ((jobtab[t0].stat & STAT_INUSE) && t0 != curjob && t0 != thisjob)
X break;
X prevjob = (t0) ? t0 : -1;
X}
X
X/* initialize a job table entry */
X
Xvoid initjob() /**/
X{
X jobtab[thisjob].pwd = ztrdup(pwd);
X jobtab[thisjob].stat = STAT_INUSE;
X jobtab[thisjob].gleader = 0;
X}
X
X/* add a process to the current job */
X
Xstruct process *addproc(pid,text) /**/
Xlong pid;char *text;
X{
Xstruct process *process;
X
X if (!jobtab[thisjob].gleader) jobtab[thisjob].gleader = pid;
X process = zcalloc(sizeof *process);
X process->pid = pid;
X if (text) strcpy(process->text,text);
X else *process->text = '\0';
X process->next = NULL;
X process->statusp = SP_RUNNING;
X process->bgtime = time(NULL);
X if (jobtab[thisjob].procs) {
X struct process *n;
X for (n = jobtab[thisjob].procs; n->next; n = n->next);
X process->next = NULL;
X n->next = process;
X } else jobtab[thisjob].procs = process;
X return process;
X}
X
X/* determine if it's all right to exec a command without
X forking in last component of subshells; it's not ok if we have files
X to delete */
X
Xint execok() /**/
X{
XJob jn;
X
X if (!exiting)
X return 0;
X for (jn = jobtab+1; jn != jobtab+MAXJOB; jn++)
X if (jn->stat && jn->filelist)
X return 0;


X return 1;
X
X}
X

Xvoid waitforpid(pid) /**/
Xlong pid;
X{
X while (!errflag && (kill(pid,0) >= 0 || errno != ESRCH)) chldsuspend();
X}
X
X/* wait for a job to finish */
X
Xvoid waitjob(job) /**/
Xint job;
X{
Xstatic struct job zero;
XJob jn;
X
X if (jobtab[job].procs) /* if any forks were done */
X {
X jobtab[job].stat |= STAT_LOCKED;
X if (jobtab[job].stat & STAT_CHANGED)
X printjob(jobtab+job,!!isset(LONGLISTJOBS));
X while (jobtab[job].stat &&
X !(jobtab[job].stat & (STAT_DONE|STAT_STOPPED)))
X chldsuspend();
X }
X else /* else do what printjob() usually does */


X {
X char *s;
X

X jn = jobtab+job;
X free(jn->pwd);
X if (jn->filelist)
X {
X while (s = getnode(jn->filelist))
X {
X unlink(s);
X free(s);
X }
X free(jn->filelist);
X }
X *jn = zero;
X }
X}
X
X/* wait for running job to finish */
X
Xvoid waitjobs() /**/
X{
X waitjob(thisjob);
X thisjob = -1;
X}
X
X/* clear job table when entering subshells */
X
Xvoid clearjobtab() /**/
X{
Xstatic struct job zero;
Xint t0;
X
X for (t0 = 1; t0 != MAXJOB; t0++)
X jobtab[thisjob] = zero;
X}
X
X/* get a free entry in the job table to use */
X
Xint getfreejob() /**/
X{
Xint t0;
X
X for (t0 = 1; t0 != MAXJOB; t0++)
X if (!jobtab[t0].stat) {
X jobtab[t0].stat |= STAT_INUSE;
X return t0;
X }
X zerr("job table full or recursion limit exceeded",NULL,0);


X return -1;
X}
X

X/* print pids for & */
X
Xvoid spawnjob() /**/
X{
Xstruct process *pn;
X
X if (!subsh)
X {
X if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED))
X {
X curjob = thisjob;
X setprevjob();
X }
X else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED))
X prevjob = thisjob;
X if (interact && jobbing && jobtab[thisjob].procs)
X {
X fprintf(stderr,"[%d]",thisjob);
X for (pn = jobtab[thisjob].procs; pn; pn = pn->next)
X fprintf(stderr," %d",pn->pid);
X fprintf(stderr,"\n");
X fflush(stderr);
X }
X }
X if (!jobtab[thisjob].procs)
X {
X char *s;


X static struct job zero;

X struct job *jn;
X
X jn = jobtab+thisjob;
X free(jn->pwd);
X if (jn->filelist)
X {
X while (s = getnode(jn->filelist))
X {
X unlink(s);
X free(s);
X }
X free(jn->filelist);
X }
X *jn = zero;
X }
X else
X jobtab[thisjob].stat |= STAT_LOCKED;
X thisjob = -1;
X}
X
Xvoid fixsigs() /**/
X{
X unblockchld();
X}
X
Xint report(j) /**/
XJob j;
X{
X if (!j->procs) return 0;
X#ifdef HAS_RUSAGE
X return (j->procs->ti.ru.ru_utime.tv_sec+j->procs->ti.ru.ru_stime.tv_sec)
X >= reporttime;
X#else
X return (j->procs->ti.ut+j->procs->ti.st)/HZ >= reporttime;
X#endif
X}
X
Xvoid printtime(real,ti,desc) /**/
Xtime_t real;struct timeinfo *ti;char *desc;
X{
Xchar *s;
X#ifdef sun
Xlong ticks = 1;
Xint pk = getpagesize()/1024;
X#else
Xlong sec;
X#endif
X#ifdef HAS_RUSAGE
Xstruct rusage *ru = &ti->ru;
X#endif
X
X if (!desc) desc = "";
X#ifdef HAS_RUSAGE
X#ifdef sun
X ticks = (ru->ru_utime.tv_sec+ru->ru_stime.tv_sec)*HZ+
X (ru->ru_utime.tv_usec+ru->ru_stime.tv_usec)*HZ/1000000;
X if (!ticks) ticks = 1;
X#else
X sec = ru->ru_utime.tv_sec + ru->ru_stime.tv_sec;
X if (!sec) sec = 1;
X#endif
X#endif
X for (s = timefmt; *s; s++)
X if (*s == '%')
X switch(s++,*s)
X {
X case 'E': fprintf(stderr,"%lds",real); break;
X#ifndef HAS_RUSAGE
X case 'U': fprintf(stderr,"%ld.%03lds",
X ti->ut/HZ,ti->ut*1000/60%1000); break;
X case 'S': fprintf(stderr,"%ld.%03lds",
X ti->st/HZ,ti->st*1000/60%1000); break;
X case 'P':
X if (real)
X fprintf(stderr,"%d%%",
X (int) (100*((ti->ut+ti->st)/HZ))/real);
X break;
X#else
X case 'U': fprintf(stderr,"%ld.%03lds",
X ru->ru_utime.tv_sec,ru->ru_utime.tv_usec/1000); break;
X case 'S': fprintf(stderr,"%ld.%03lds",
X ru->ru_stime.tv_sec,ru->ru_stime.tv_usec/1000); break;
X case 'P':
X if (real)
X fprintf(stderr,"%d%%",
X (int) (100*(ru->ru_utime.tv_sec+ru->ru_stime.tv_sec))
X / real);
X break;
X case 'W': fprintf(stderr,"%ld",ru->ru_nswap); break;
X#ifdef sun
X case 'K': case 'D':
X fprintf(stderr,"%ld",ru->ru_idrss/ticks*pk); break;
X case 'M': fprintf(stderr,"%ld",ru->ru_maxrss*pk); break;
X#else
X case 'X': fprintf(stderr,"%ld",ru->ru_ixrss/sec); break;
X case 'D': fprintf(stderr,"%ld",
X (ru->ru_idrss+ru->ru_isrss)/sec); break;
X case 'K': fprintf(stderr,"%ld",
X (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss)/sec); break;
X case 'M': fprintf(stderr,"%ld",ru->ru_maxrss/1024); break;
X#endif
X case 'F': fprintf(stderr,"%ld",ru->ru_majflt); break;
X case 'R': fprintf(stderr,"%ld",ru->ru_minflt); break;
X case 'I': fprintf(stderr,"%ld",ru->ru_inblock); break;
X case 'O': fprintf(stderr,"%ld",ru->ru_oublock); break;
X case 'r': fprintf(stderr,"%ld",ru->ru_msgrcv); break;
X case 's': fprintf(stderr,"%ld",ru->ru_msgsnd); break;
X case 'k': fprintf(stderr,"%ld",ru->ru_nsignals); break;
X case 'w': fprintf(stderr,"%ld",ru->ru_nvcsw); break;
X case 'c': fprintf(stderr,"%ld",ru->ru_nivcsw); break;
X#endif
X case 'J': fprintf(stderr,"%s",desc); break;
X default: fprintf(stderr,"%%%c",*s); break;
X }
X else
X putc(*s,stderr);
X putc('\n',stderr);
X fflush(stderr);
X}
X
Xvoid dumptime(jn) /**/
XJob jn;
X{
Xstruct process *pn = jn->procs;
X
X if (!jn->procs)
X return;
X for (pn = jn->procs; pn; pn = pn->next)
X printtime(pn->endtime-pn->bgtime,&pn->ti,pn->text);
X}
X
Xvoid shelltime() /**/
X{
Xstruct timeinfo ti;
X#ifdef HAS_RUSAGE
Xstruct rusage ru;
X
X getrusage(RUSAGE_SELF,&ru);
X memcpy(&ti.ru,&ru,sizeof(ru));
X printtime(time(NULL)-shtimer,&ti,"shell");
X
X getrusage(RUSAGE_CHILDREN,&ru);
X memcpy(&ti.ru,&ru,sizeof(ru));
X printtime(time(NULL)-shtimer,&ti,"children");
X#else
Xstruct tms buf;
X
X times(&buf);
X ti.ut = buf.tms_utime;
X ti.st = buf.tms_stime;
X printtime(time(NULL)-shtimer,&ti,"shell");
X ti.ut = buf.tms_cutime;
X ti.st = buf.tms_cstime;
X printtime(time(NULL)-shtimer,&ti,"children");
X#endif
X}
X
X/* SIGHUP any jobs left running */
X
Xvoid killrunjobs() /**/
X{
Xint t0,killed = 0;
X
X if (isset(NOHUP)) return;
X for (t0 = 1; t0 != MAXJOB; t0++)
X if (t0 != thisjob && (jobtab[t0].stat & STAT_LOCKED) &&
X !(jobtab[t0].stat & STAT_STOPPED)) {
X if (killpg(jobtab[t0].gleader,SIGHUP) != -1) killed++;
X }
X if (killed) zerr("warning: %d jobs SIGHUPed",NULL,killed);
X}
X
X/* check to see if user has jobs running/stopped */
X
Xvoid checkjobs() /**/
X{
Xint t0;
X
X scanjobs();
X for (t0 = 1; t0 != MAXJOB; t0++)
X if (t0 != thisjob && jobtab[t0].stat & STAT_LOCKED)
X break;
X if (t0 != MAXJOB) {
X if (jobtab[t0].stat & STAT_STOPPED) {
X#ifdef USE_SUSPENDED
X zerr("you have suspended jobs.",NULL,0);
X#else
X zerr("you have stopped jobs.",NULL,0);
X#endif
X } else
X zerr("you have running jobs.",NULL,0);
X stopmsg = 1;
X }
X}
X
X/* send a signal to a job (simply involves kill if monitoring is on) */
X
Xint killjb(jn,sig) /**/
XJob jn;int sig;
X{
Xstruct process *pn;
Xint err;
X
X if (jobbing)
X return(killpg(jn->gleader,sig));
X for (pn = jn->procs; pn; pn = pn->next)
X if ((err = kill(pn->pid,sig)) == -1 && errno != ESRCH)
X return -1;
X return err;
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/jobs.c ||
echo 'restore of zsh2.2/src/jobs.c failed'
Wc_c="`wc -c < 'zsh2.2/src/jobs.c'`"
test 16421 -eq "$Wc_c" ||
echo 'zsh2.2/src/jobs.c: original size 16421, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/lex.c ==============
if test -f 'zsh2.2/src/lex.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/lex.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/lex.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/lex.c' &&
X/*
X *
X * lex.c - lexical analysis


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X

X/* lexical state */
X
Xstatic int xincmdpos,xincond,xincasepat,dbparens,xdbparens,xalstat;
Xstatic char *xhlastw;
X
Xstatic int xisfirstln, xisfirstch, xhistremmed, xhistdone,
X xspaceflag, xstophist, xlithist, xalstackind,xhlinesz;
Xstatic char *xhline, *xhptr;
X
X/* save the lexical state */
X
X/* is this a hack or what? */
X
Xvoid lexsave() /**/
X{
X xincmdpos = incmdpos;
X xincond = incond;
X xincasepat = incasepat;
X xdbparens = dbparens;
X xalstat = alstat;
X xalstackind = alstackind;
X xisfirstln = isfirstln;
X xisfirstch = isfirstch;
X xhistremmed = histremmed;
X xhistdone = histdone;
X xspaceflag = spaceflag;
X xstophist = stophist;
X xlithist = lithist;
X xhline = hline;
X xhptr = hptr;
X xhlastw = hlastw;
X xhlinesz = hlinesz;
X inredir = 0;
X}
X
X/* restore lexical state */
X
Xvoid lexrestore() /**/
X{
X incmdpos = xincmdpos;
X incond = xincond;
X incasepat = xincasepat;
X dbparens = xdbparens;
X alstat = xalstat;
X isfirstln = xisfirstln;
X isfirstch = xisfirstch;
X histremmed = xhistremmed;
X histdone = xhistdone;
X spaceflag = xspaceflag;
X stophist = xstophist;
X lithist = xlithist;
X hline = xhline;
X hptr = xhptr;
X hlastw = xhlastw;
X clearalstack();
X alstackind = xalstackind;
X hlinesz = xhlinesz;
X lexstop = errflag = 0;
X}
X
Xvoid yylex() /**/
X{
X if (tok == LEXERR) return;
X do
X tok = gettok();
X while (tok != ENDINPUT && exalias());
X if (tok != NEWLIN) isnewlin = 0;
X else isnewlin = (inbufct) ? -1 : 1;
X if (tok == SEMI || tok == NEWLIN) tok = SEPER;
X}
X
Xvoid ctxtlex() /**/
X{
Xstatic int oldpos;
X
X yylex();
X switch (tok) {
X case SEPER: case NEWLIN: case SEMI: case DSEMI: case AMPER:
X case INPAR: case INBRACE: case DBAR: case DAMPER: case BAR:
X case BARAMP: case INOUTPAR: case DO: case THEN: case ELIF:
X case ELSE: incmdpos = 1; break;
X case STRING: /* case ENVSTRING: */ case ENVARRAY: case OUTPAR:
X case CASE: incmdpos = 0; break;
X }
X if (IS_REDIROP(tok) || tok == FOR || tok == FOREACH || tok == SELECT) {
X inredir = 1;
X oldpos = incmdpos;
X incmdpos = 0;
X } else if (inredir) {
X incmdpos = oldpos;
X inredir = 0;
X }
X}
X
X#define LX1_BKSLASH 0
X#define LX1_COMMENT 1
X#define LX1_NEWLIN 2
X#define LX1_SEMI 3
X#define LX1_BANG 4
X#define LX1_AMPER 5
X#define LX1_BAR 6
SHAR_EOF
true || echo 'restore of zsh2.2/src/lex.c failed'
fi
echo 'End of zsh2.2 part 9'
echo 'File zsh2.2/src/lex.c is continued in part 10'
echo 10 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:05:05 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 106
Archive-name: zsh2.2/part10

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.10 (part 10 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/lex.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 10; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/lex.c'
else
echo 'x - continuing file zsh2.2/src/lex.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/lex.c' &&

X#define LX1_INPAR 7
X#define LX1_OUTPAR 8
X#define LX1_INBRACE 9
X#define LX1_OUTBRACE 10
X#define LX1_INBRACK 11
X#define LX1_OUTBRACK 12
X#define LX1_INANG 13
X#define LX1_OUTANG 14
X#define LX1_OTHER 15
X
X#define LX2_BREAK 0
X#define LX2_OUTPAR 1
X#define LX2_BAR 2
X#define LX2_STRING 3
X#define LX2_INBRACK 4
X#define LX2_OUTBRACK 5
X#define LX2_TILDE 6
X#define LX2_INPAR 7
X#define LX2_INBRACE 8
X#define LX2_OUTBRACE 9
X#define LX2_OUTANG 10
X#define LX2_INANG 11
X#define LX2_EQUALS 12
X#define LX2_BKSLASH 13
X#define LX2_QUOTE 14
X#define LX2_DQUOTE 15
X#define LX2_BQUOTE 16
X#define LX2_OTHER 17
X
Xunsigned char lexact1[256],lexact2[256],lextok2[256];
X
Xvoid initlextabs() /**/
X{
Xint t0;
Xstatic char *lx1 = "\\q\n;!&|(){}[]<>xx";
Xstatic char *lx2 = "x)|$[]~({}><=\\\'\"`x";
X
X for (t0 = 0; t0 != 256; t0++) {
X lexact1[t0] = LX1_OTHER;
X lexact2[t0] = LX2_OTHER;
X lextok2[t0] = t0;
X }
X for (t0 = 0; lx1[t0]; t0++)
X if (lx1[t0] != 'x')
X lexact1[lx1[t0]] = t0;
X for (t0 = 0; lx2[t0]; t0++)
X if (lx2[t0] != 'x')
X lexact2[lx2[t0]] = t0;
X lexact2[';'] = LX2_BREAK;
X lexact2['&'] = LX2_BREAK;
X lextok2[','] = Comma;
X lextok2['*'] = Star;
X lextok2['?'] = Quest;
X lextok2['{'] = Inbrace;
X lextok2['['] = Inbrack;
X lextok2['$'] = String;
X}
X
X/* initialize lexical state */
X
Xvoid lexinit() /**/
X{
X incond = incasepat = nocorrect =
X dbparens = alstat = lexstop = 0;
X incmdpos = 1;
X tok = ENDINPUT;
X if (isset(EXTENDEDGLOB))
X {
X lextok2['#'] = Pound;
X lextok2['^'] = Hat;
X }
X else
X {
X lextok2['#'] = '#';
X lextok2['^'] = '^';
X }
X}
X
Xint len = 0,bsiz = 256;
Xchar *bptr;
X
X/* add a char to the string buffer */
X
Xvoid add(c) /**/
Xint c;
X{
X *bptr++ = c;
X if (bsiz == ++len)
X {
X int newbsiz;
X
X newbsiz = bsiz * 8;
X while (newbsiz < inbufct)
X newbsiz *= 2;
X bptr = len+(tokstr = hrealloc(tokstr,bsiz,newbsiz));
X bsiz = newbsiz;
X }
X}
X
Xstatic void unadd()
X{
X bptr--; len--;
X}
X
Xint gettok() /**/
X{
Xint bct = 0,pct = 0,brct = 0;
Xint c,d,intpos = 1;
Xint peekfd = -1,peek,ninbracks;
X
Xbeginning:
X hlastw = NULL;
X tokstr = NULL;
X parbegin = -1;
X while (iblank(c = hgetc()) && !lexstop);
X isfirstln = 0;
X wordbeg = inbufct;
X hwbegin();
X hwaddc(c);
X if (dbparens) /* handle ((...)) */
X {
X pct = 2;
X peek = STRING;
X len = dbparens = 0;
X bptr = tokstr = ncalloc(bsiz = 256);


X for (;;)
X {

X if (c == '(')
X pct++;
X else if (c == ')')
X pct--;
X else if (c == '\n')
X {
X zerr("parse error: )) expected",NULL,0);
X peek = LEXERR;
X return peek;
X }
X else if (c == '$')
X c = Qstring;
X if (pct >= 2)
X add(c);
X if (pct)
X c = hgetc();


X else
X break;
X }

X *bptr = '\0';
X return peek;
X }
X if (idigit(c)) /* handle 1< foo */
X {
X d = hgetc();
X hungetc(d);
X lexstop = 0;
X if (d == '>' || d == '<')
X {
X peekfd = c-'0';
X c = hgetc();
X }
X }
X
X /* chars in initial position in word */
X
X if (c == hashchar &&
X (isset(INTERACTIVECOMMENTS) ||
X (!zleparse && (!interact || unset(SHINSTDIN) || strin))))
X {
X /* changed hgetch to hgetc so comments appear in history */
X stophist = 1;
X while ((c = hgetc()) != '\n' && !lexstop);
X if (c == '\n') {
X hwaddc('\n');
X peek = NEWLIN;
X } else {
X peek = (errflag) ? LEXERR : ENDINPUT;


X errflag = 1;
X }

X return peek;
X }
X if (lexstop)
X return (errflag) ? LEXERR : ENDINPUT;
X switch (lexact1[(unsigned char) c])
X {
X case LX1_BKSLASH:
X d = hgetc();
X if (d == '\n')
X goto beginning;
X hungetc(d);
X break;
X case LX1_NEWLIN: return NEWLIN;
X case LX1_SEMI:
X d = hgetc();
X if (d != ';')
X {
X hungetc(d);
X return SEMI;
X }
X return DSEMI;
X case LX1_BANG:
X d = hgetc();
X hungetc(d);
X if (!inblank(d))
X break;
X if (incmdpos || incond)
X return BANG;
X break;
X case LX1_AMPER:
X d = hgetc();
X if (d != '&')
X {
X hungetc(d);
X return AMPER;
X }
X return DAMPER;
X case LX1_BAR:
X d = hgetc();
X if (d == '|')
X return DBAR;
X else if (d == '&')
X return BARAMP;
X hungetc(d);
X return BAR;
X case LX1_INPAR:
X d = hgetc();
X if (d == '(' && incmdpos)
X {
X tokstr = strdup("let");
X dbparens = 1;
X return STRING;
X }
X else if (d == ')')
X return INOUTPAR;
X hungetc(d);
X if (!(incond || incmdpos))
X break;
X return INPAR;
X case LX1_OUTPAR: return OUTPAR;
X case LX1_INBRACE: if (!incmdpos) break; return INBRACE;
X case LX1_OUTBRACE: return OUTBRACE;
X case LX1_INBRACK:
X if (!incmdpos)
X break;
X d = hgetc();
X if (d == '[')
X return DINBRACK;
X hungetc(d);
X break;
X case LX1_OUTBRACK:
X if (!incond)
X break;
X d = hgetc();
X if (d == ']')
X return DOUTBRACK;
X hungetc(d);
X break;
X case LX1_INANG:
X d = hgetc();
X if ((!incmdpos && d == '(') || incasepat) {
X hungetc(d);
X break;
X } else if (d == '<') {
X int e = hgetc();
X
X if (e == '(') {
X hungetc(e);
X hungetc(d);
X peek = INANG;
X } else if (e == '<')
X peek = TRINANG;
X else if (e == '-')
X peek = DINANGDASH;
X else {
X hungetc(e);
X peek = DINANG;
X }
X } else if (d == '&')
X peek = INANGAMP;
X else {
X peek = INANG;
X hungetc(d);
X }
X tokfd = peekfd;
X return peek;
X case LX1_OUTANG:
X d = hgetc();
X if (d == '(')
X {
X hungetc(d);
X break;
X }
X else if (d == '&')
X {
X d = hgetc();
X if (d == '!')
X peek = OUTANGAMPBANG;
X else
X {
X hungetc(d);
X peek = OUTANGAMP;
X }
X }
X else if (d == '!')
X peek = OUTANGBANG;
X else if (d == '>')
X {
X d = hgetc();
X if (d == '&')
X {
X d = hgetc();
X if (d == '!')
X peek = DOUTANGAMPBANG;
X else
X {
X hungetc(d);
X peek = DOUTANGAMP;
X }
X }
X else if (d == '!')
X peek = DOUTANGBANG;
X else if (d == '(')
X {
X hungetc(d);
X hungetc('>');
X peek = OUTANG;
X }
X else
X {
X hungetc(d);
X peek = DOUTANG;
X if (isset(NOCLOBBER)) hwaddc('!');
X }
X }
X else
X {
X hungetc(d);
X peek = OUTANG;
X if (isset(NOCLOBBER)) hwaddc('!');
X }
X tokfd = peekfd;
X return peek;
X }
X
X /* we've started a string, now get the rest of it, performing
X tokenization */
X
X peek = STRING;
X len = 0;
X bptr = tokstr = ncalloc(bsiz = 256);
X for(;;)
X {
X int act;
X int d;
X
X if (inblank(c))
X act = LX2_BREAK;
X else
X {
X act = lexact2[(unsigned char) c];
X c = lextok2[(unsigned char) c];
X }
X switch (act)
X {
X case LX2_BREAK: goto brk;
X case LX2_OUTPAR:
X if (!pct)
X goto brk;
X c = Outpar;
X pct--;
X break;
X case LX2_BAR:
X if (!pct && !incasepat)
X goto brk;
X c = Bar;
X break;
X case LX2_STRING:
X d = hgetc();
X if (d == '[')
X {
X add(String);
X add(Inbrack);
X ninbracks = 1;
X while (ninbracks && (c = hgetc()) && !lexstop) {
X if (c == '[') ninbracks++;
X else if (c == ']') ninbracks--;
X if (ninbracks) add(c);
X }
X c = Outbrack;
X }
X else if (d == '(')
X {
X add(String);
X if (skipcomm()) { peek = LEXERR; goto brk; }
X c = Outpar;
X }
X else
X hungetc(d);
X break;
X case LX2_INBRACK: brct++; break;
X case LX2_OUTBRACK:
X if (incond && !brct)
X goto brk;
X brct--;
X c = Outbrack;
X break;
X case LX2_TILDE: /* if (intpos) */ c = Tilde; break;
X case LX2_INPAR:
X d = hgetc();
X hungetc(d);
X if (d == ')' || (incmdpos && peek != ENVSTRING))
X goto brk;
X pct++;
X c = Inpar;
X break;
X case LX2_INBRACE: bct++; break;
X case LX2_OUTBRACE:
X if (!bct)
X goto brk;
X bct--;
X c = Outbrace;
X break;
X case LX2_OUTANG:
X d = hgetc();
X if (d != '(')
X {
X hungetc(d);
X goto brk;
X }
X add(Outang);
X if (skipcomm()) { peek = LEXERR; goto brk; }
X c = Outpar;
X break;
X case LX2_INANG:
X d = hgetc();
X if (!(idigit(d) || d == '-' || d == '>' || d == '(' || d == ')'))
X {
X hungetc(d);
X goto brk;
X }
X c = Inang;
X if (d == '(')
X {
X add(c);
X if (skipcomm()) { peek = LEXERR; goto brk; }
X c = Outpar;
X }
X else if (d == ')')
X hungetc(d);
X else
X {
X add(c);
X c = d;
X while (c != '>' && !lexstop)
X add(c),c = hgetc();
X c = Outang;
X }
X break;
X case LX2_EQUALS:
X if (intpos)
X {
X d = hgetc();
X if (d != '(')
X {
X hungetc(d);
X c = Equals;
X }
X else
X {
X add(Equals);
X if (skipcomm()) { peek = LEXERR; goto brk; }
X c = Outpar;
X }
X }
X else if (peek != ENVSTRING && incmdpos)
X {
X d = hgetc();
X if (d == '(' && incmdpos)


X {
X *bptr = '\0';

X return ENVARRAY;
X }
X hungetc(d);
X peek = ENVSTRING;
X intpos = 2;
X }
X break;
X case LX2_BKSLASH:
X c = hgetc();


X if (c == '\n')
X {

X c = hgetc();
X continue;
X }
X add(c);
X c = hgetc();
X continue;
X case LX2_QUOTE:
X add(Nularg);
X
X /* we add the Nularg to prevent this:
X
X echo $PA'TH'
X
X from printing the path. */


X
X for (;;) {

X while ((c = hgetc()) != '\'' && !lexstop) {
X if (isset(CSHJUNKIEQUOTES) && c == '\n') {
X if (bptr[-1] == '\\') unadd(); else break;
X }
X add(c);


X }
X if (c != '\'') {

X zerr("unmatched \'",NULL,0);
X peek = LEXERR;
X goto brk;
X }
X d = hgetc();
X if (d != '\'' || unset(RCQUOTES)) break;
X add(c);
X }
X hungetc(d);
X c = Nularg;
X break;
X case LX2_DQUOTE:
X add(Nularg);
X while ((c = hgetc()) != '\"' && !lexstop)


X if (c == '\\')

X {
X c = hgetc();
X if (c != '\n')
X {
X if (c != '$' && c != '\\' && c != '\"' && c != '`')
X add('\\');
X add(c);
X }
X }
X else {
X if (isset(CSHJUNKIEQUOTES) && c == '\n') {
X if (bptr[-1] == '\\') unadd(); else break;
X }
X if (c == '$') {
X d = hgetc();
X if (d == '(') {
X add(Qstring);
X if (skipcomm()) { peek = LEXERR; goto brk; }
X c = Outpar;
X } else if (d == '[') {
X add(String);
X add(Inbrack);
X while ((c = hgetc()) != ']' && !lexstop)
X add(c);
X c = Outbrack;
X } else {
X c = Qstring;
X hungetc(d);
X }
X } else if (c == '`')
X c = Qtick;
X add(c);


X }
X if (c != '\"') {

X zerr("unmatched \"",NULL,0);
X peek = LEXERR;
X goto brk;
X }
X c = Nularg;
X break;
X case LX2_BQUOTE:
X add(Tick);
X parbegin = inbufct;
X while ((c = hgetc()) != '`' && !lexstop)


X if (c == '\\')

X {
X c = hgetc();
X if (c != '\n')
X {
X if (c != '`' && c != '\\' && c != '$')
X add('\\');
X add(c);
X }
X }
X else {
X if (isset(CSHJUNKIEQUOTES) && c == '\n') {
X if (bptr[-1] == '\\') unadd(); else break;
X }
X add(c);


X }
X if (c != '`') {

X if (!zleparse) zerr("unmatched `",NULL,0);
X peek = LEXERR;
X goto brk;
X }
X c = Tick;
X parbegin = -1;
X break;
X }
X add(c);
X c = hgetc();
X if (intpos)
X intpos--;
X if (lexstop)
X break;
X }
Xbrk:
X hungetc(c);
X *bptr = '\0';
X return peek;
X}
X
X/* expand aliases, perhaps */
X
Xint exalias() /**/
X{
Xstruct alias *an;
Xchar *s,*t;
X
X s = yytext = hwadd();
X for (t = s; *t && *t != HISTSPACE; t++);
X if (!*t)
X t = NULL;
X else
X *t = '\0';
X if (interact && isset(SHINSTDIN) && !strin && !incasepat && tok == STRING &&
X (isset(CORRECTALL) || (isset(CORRECT) && incmdpos)) && !nocorrect)
X spckword(&tokstr,&s,&t,!incmdpos,1);
X if (zleparse && !alstackind) {
X int zp = zleparse;
X gotword(s);
X if (zp && !zleparse) {
X if (t) *t = HISTSPACE;


X return 0;
X }
X }

X an = gethnode(s,aliastab);
X if (t) *t = HISTSPACE;
X if (alstackind != MAXAL && an && !an->inuse)
X if (!(an->cmd && !incmdpos && alstat != ALSTAT_MORE)) {
X if (an->cmd < 0) {
X tok = DO-an->cmd-1;
X return 0;
X } else {
X an->inuse = 1;
X hungets(ALPOPS);
X hungets((alstack[alstackind++] = an)->text);
X alstat = 0;
X /* remove from history if it begins with space */
X if (isset(HISTIGNORESPACE) && an->text[0] == ' ') remhist();
X lexstop = 0;


X return 1;
X }
X }

X return 0;
X}
X

X/* skip (...) */
X
Xint skipcomm() /**/
X{
Xint pct = 1,c;
X
X parbegin = inbufct;
X c = Inpar;
X do
X {
X add(c);
X c = hgetc();
X if (itok(c) || lexstop)
X break;
X else if (c == '(') pct++;
X else if (c == ')') pct--;
X else if (c == '\\')
X {
X add(c);
X c = hgetc();
X }
X else if (c == '\'')
X {
X add(c);
X while ((c = hgetc()) != '\'' && !lexstop)
X add(c);
X }
X else if (c == '\"')
X {
X add(c);
X while ((c = hgetc()) != '\"' && !lexstop)


X if (c == '\\')

X {
X add(c);
X add(hgetc());
X }
X else add(c);
X }
X else if (c == '`')
X {
X add(c);
X while ((c = hgetc()) != '`' && !lexstop)
X if (c == '\\') add(c), add(hgetc());
X else add(c);
X }
X }
X while(pct);
X if (!lexstop) parbegin = -1;
X return lexstop;
X}
X
SHAR_EOF
echo 'File zsh2.2/src/lex.c is complete' &&
chmod 0644 zsh2.2/src/lex.c ||


echo 'restore of zsh2.2/src/lex.c failed'

Wc_c="`wc -c < 'zsh2.2/src/lex.c'`"
test 15554 -eq "$Wc_c" ||
echo 'zsh2.2/src/lex.c: original size 15554, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/loop.c ==============
if test -f 'zsh2.2/src/loop.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/loop.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/loop.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/loop.c' &&
X/*
X *
X * loop.c - loop execution


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X

Xint execfor(cmd) /**/
XCmd cmd;
X{
XList list;
Xstruct forcmd *node;
Xchar *str;
XLklist args;


Xint cj = thisjob;
X

X loops++;
X exiting = 0;
X node = cmd->u.forcmd;


X args = cmd->args;

X if (!node->inflag)
X {
X char **x;
X
X args = newlist();
X for (x = pparams; *x; x++)
X addnode(args,ztrdup(*x));
X }
X pushheap();
X while (str = ugetnode(args))
X {
X setsparam(node->name,ztrdup(str));
X list = dupstruct(node->list);
X execlist(list);
X if (breaks)
X {
X breaks--;
X if (breaks || !contflag)
X break;
X contflag = 0;
X }
X if (errflag)
X {
X lastval = 1;
X break;
X }
X freeheap();
X }
X popheap();
X thisjob = cj;
X loops--;


X return lastval;
X}
X

Xint execselect(cmd) /**/
XCmd cmd;
X{
XList list;
Xstruct forcmd *node;
Xchar *str,*s;
XLklist args;
XLknode n;
Xint cj = thisjob,t0;
XFILE *inp;
X
X node = cmd->u.forcmd;


X args = cmd->args;

X if (!node->inflag) {
X char **x;
X
X args = newlist();
X for (x = pparams; *x; x++)
X addnode(args,ztrdup(*x));
X }
X if (!full(args))
X return 1;
X loops++;
X exiting = 0;
X pushheap();
X inp = fdopen(dup((SHTTY==-1)?0:SHTTY),"r");


X for (;;)
X {

X do
X {
X int pl;
X selectlist(args);
X str = putprompt(prompt3,&pl);
X if (full(bufstack)) str = (char *) getnode(bufstack);
X else if (interact && SHTTY != -1 && isset(USEZLE)) {
X str = (char *)zleread(str,NULL,pl);
X } else {
X fprintf(stderr,"%s",str);
X fflush(stderr);
X str = fgets(zalloc(256),256,inp);
X }
X if (!str || errflag)
X {


X fprintf(stderr,"\n");
X fflush(stderr);

X goto done;
X }
X if (s = strchr(str,'\n'))


X *s = '\0';
X }

X while (!*str);
X setsparam("REPLY",ztrdup(str));
X t0 = atoi(str);
X if (!t0)
X str = "";
X else
X {
X for (t0--,n = firstnode(args); n && t0; incnode(n),t0--);
X if (n)
X str = getdata(n);
X else
X str = "";
X }
X setsparam(node->name,ztrdup(str));
X list = dupstruct(node->list);
X execlist(list);
X freeheap();
X if (breaks)
X {
X breaks--;
X if (breaks || !contflag)
X break;
X contflag = 0;
X }
X if (errflag)
X break;
X }
Xdone:
X popheap();
X fclose(inp);
X thisjob = cj;
X loops--;


X return lastval;
X}
X

Xint execwhile(cmd) /**/
XCmd cmd;
X{
XList list;
Xstruct whilecmd *node;


Xint cj = thisjob;
X

X node = cmd->u.whilecmd;
X exiting = 0;
X pushheap();
X loops++;
X for(;;)
X {
X list = dupstruct(node->cont);
X execlist(list);
X if (!((lastval == 0) ^ node->cond))
X break;
X list = dupstruct(node->loop);
X execlist(list);
X if (breaks)
X {
X breaks--;
X if (breaks || !contflag)
X break;
X contflag = 0;
X }
X freeheap();
X if (errflag)
X {
X lastval = 1;
X break;
X }
X }
X popheap();
X thisjob = cj;
X loops--;


X return lastval;
X}
X

Xint execrepeat(cmd) /**/
XCmd cmd;
X{
XList list;
Xint cj = thisjob,count;
X
X exiting = 0;
X if (!full(cmd->args) || nextnode(firstnode(cmd->args)))
X {
X zerr("bad argument for repeat",NULL,0);
X return 1;
X }
X count = atoi(peekfirst(cmd->args));
X pushheap();
X loops++;
X while (count--)
X {
X list = dupstruct(cmd->u.list);
X execlist(list);
X freeheap();
X if (breaks)
X {
X breaks--;
X if (breaks || !contflag)
X break;
X contflag = 0;
X }
X if (lastval)
X break;
X if (errflag)
X {
X lastval = 1;
X break;
X }
X }
X popheap();
X thisjob = cj;
X loops--;


X return lastval;
X}
X

Xint execif(cmd) /**/
XCmd cmd;
X{
Xstruct ifcmd *node;


Xint cj = thisjob;
X

X node = cmd->u.ifcmd;
X exiting = 0;
X while (node)
X {
X if (node->ifl)
X {
X execlist(node->ifl);
X if (lastval)
X {
X node = node->next;
X continue;
X }
X }
X execlist(node->thenl);
X break;
X }
X thisjob = cj;
X return lastval;
X}
X
Xint execcase(cmd) /**/
XCmd cmd;
X{
Xstruct casecmd *node;
Xchar *word;
XLklist args;


Xint cj = thisjob;
X

X node = cmd->u.casecmd;


X args = cmd->args;

X exiting = 0;
X if (firstnode(args) && nextnode(firstnode(args)))
X {
X zerr("too many arguments to case",NULL,0);
X errflag = 1;
X return 1;
X }
X if (!full(args))
X word = strdup("");
X else
X word = peekfirst(args);
X while (node)
X {
X singsub(&(node->pat));
X if (matchpat(word,node->pat))
X break;
X else
X node = node->next;
X }
X if (node && node->list)
X execlist(node->list);
X thisjob = cj;
X return lastval;
X}
SHAR_EOF
chmod 0644 zsh2.2/src/loop.c ||
echo 'restore of zsh2.2/src/loop.c failed'
Wc_c="`wc -c < 'zsh2.2/src/loop.c'`"
test 4752 -eq "$Wc_c" ||
echo 'zsh2.2/src/loop.c: original size 4752, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/math.c ==============
if test -f 'zsh2.2/src/math.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/math.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/math.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/math.c' &&
X/*
X *
X * math.c - mathematical expression evaluation


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X

Xstatic char *ptr;
X
Xtypedef int LV;
X
Xstatic long yyval;
Xstatic LV yylval;
X
X/* nonzero means we are not evaluating, just parsing */
X
Xstatic int noeval = 0;
X
X/* != 0 means recognize unary plus, minus, etc. */
X
Xstatic int unary = 1;
X
Xvoid mathparse DCLPROTO((int));
X
X/* LR = left-to-right associativity
X RL = right-to-left associativity
X BOO = short-circuiting boolean */
X
X#define LR 0
X#define RL 1
X#define BOOL 2
X
X#define M_INPAR 0
X#define M_OUTPAR 1
X#define NOT 2
X#define COMP 3
X#define POSTPLUS 4
X#define POSTMINUS 5
X#define UPLUS 6
X#define UMINUS 7
X#define AND 8
X#define XOR 9
X#define OR 10
X#define MUL 11
X#define DIV 12
X#define MOD 13
X#define PLUS 14
X#define MINUS 15
X#define SHLEFT 16
X#define SHRIGHT 17
X#define LES 18
X#define LEQ 19
X#define GRE 20
X#define GEQ 21
X#define DEQ 22
X#define NEQ 23
X#define DAND 24
X#define DOR 25
X#define DXOR 26
X#define QUEST 27
X#define COLON 28
X#define EQ 29
X#define PLUSEQ 30
X#define MINUSEQ 31
X#define MULEQ 32
X#define DIVEQ 33
X#define MODEQ 34
X#define ANDEQ 35
X#define XOREQ 36
X#define OREQ 37
X#define SHLEFTEQ 38
X#define SHRIGHTEQ 39
X#define DANDEQ 40
X#define DOREQ 41
X#define DXOREQ 42
X#define COMMA 43
X#define EOI 44
X#define PREPLUS 45
X#define PREMINUS 46
X#define NUM 47
X#define ID 48
X#define TOKCOUNT 49
X
X/* precedences */
X
Xstatic int prec[TOKCOUNT] = {
X 1,137,2,2,2,
X 2,2,2,4,5,
X 6,7,7,7,8,
X 8,3,3,9,9,
X 9,9,10,10,11,
X 12,12,13,13,14,
X 14,14,14,14,14,
X 14,14,14,14,14,
X 14,14,14,15,200,
X 2,2,0,0,
X};
X
X#define TOPPREC 15
X#define ARGPREC (15-1)
X
Xstatic int type[TOKCOUNT] = {
X LR,LR,RL,RL,RL,
X RL,RL,RL,LR,LR,
X LR,LR,LR,LR,LR,
X LR,LR,LR,LR,LR,
X LR,LR,LR,LR,BOOL,
X BOOL,LR,RL,RL,RL,
X RL,RL,RL,RL,RL,
X RL,RL,RL,RL,RL,
X BOOL,BOOL,RL,RL,RL,
X RL,RL,LR,LR,
X};
X
X#define LVCOUNT 32
X
X/* list of lvalues (variables) */
X
Xstatic int lvc;
Xstatic char *lvals[LVCOUNT];
X
Xint zzlex() /**/
X{
X for(;;)
X switch (*ptr++)
X {
X case '+':
X if (*ptr == '+' && (unary || !ialnum(*ptr)))
X {
X ptr++;
X return (unary) ? PREPLUS : POSTPLUS;
X }
X if (*ptr == '=') { unary = 1; ptr++; return PLUSEQ; }
X return (unary) ? UPLUS : PLUS;
X case '-':
X if (*ptr == '-' && (unary || !ialnum(*ptr)))
X {
X ptr++;
X return (unary) ? PREMINUS : POSTMINUS;
X }
X if (*ptr == '=') { unary = 1; ptr++; return MINUSEQ; }
X return (unary) ? UMINUS : MINUS;
X case '(': unary = 1; return M_INPAR;
X case ')': return M_OUTPAR;
X case '!': if (*ptr == '=')
X { unary = 1; ptr++; return NEQ; }
X return NOT;
X case '~': return COMP;
X case '&': unary = 1;
X if (*ptr == '&') { if (*++ptr == '=')
X { ptr++; return DANDEQ; } return DAND; }
X else if (*ptr == '=') { ptr++; return ANDEQ; } return AND;
X case '|': unary = 1;
X if (*ptr == '|') { if (*++ptr == '=')
X { ptr++; return DOREQ; } return DOR; }
X else if (*ptr == '=') { ptr++; return OREQ; } return OR;
X case '^': unary = 1;
X if (*ptr == '^') { if (*++ptr == '=')
X { ptr++; return DXOREQ; } return DXOR; }
X else if (*ptr == '=') { ptr++; return XOREQ; } return XOR;
X case '*': unary = 1;
X if (*ptr == '=') { ptr++; return MULEQ; } return MUL;
X case '/': unary = 1;
X if (*ptr == '=') { ptr++; return DIVEQ; } return DIV;
X case '%': unary = 1;
X if (*ptr == '=') { ptr++; return MODEQ; } return MOD;
X case '<': unary = 1; if (*ptr == '<')
X { if (*++ptr == '=') { ptr++; return SHLEFTEQ; } return SHLEFT; }
X else if (*ptr == '=') { ptr++; return LEQ; } return LES;
X case '>': unary = 1; if (*ptr == '>')
X { if (*++ptr == '=') { ptr++; return SHRIGHTEQ; } return SHRIGHT; }
X else if (*ptr == '=') { ptr++; return GEQ; } return GRE;
X case '=': unary = 1; if (*ptr == '=') { ptr++; return DEQ; }
X return EQ;
X case '?': unary = 1; return QUEST;
X case ':': unary = 1; return COLON;
X case ',': unary = 1; return COMMA;
X case '\0': unary = 1; ptr--; return EOI;
X case '[': unary = 0;
X { int base = zstrtol(ptr,&ptr,10);
X if (*ptr == ']') ptr++;
X yyval = zstrtol(ptr,&ptr,lastbase = base);
X return NUM; }
X case ' ': case '\t':
X break;
X default:
X if (idigit(*--ptr))
X { unary = 0; yyval = zstrtol(ptr,&ptr,10); return NUM; }
X if (iident(*ptr) || *ptr == '$')
X {
X char *p,q;
X
X if (*ptr == '$')
X ptr++;
X p = ptr;
X if (lvc == LVCOUNT)
X {
X zerr("too many identifiers (complain to author)",NULL,0);
X return EOI;
X }
X unary = 0;
X while(iident(*++ptr));
X q = *ptr;
X *ptr = '\0';
X lvals[yylval = lvc++] = ztrdup(p);
X *ptr = q;
X return ID;
X }
X return EOI;
X }
X}
X
X/* the value stack */
X
X#define STACKSZ 100
Xint mtok; /* last token */
Xint sp = -1; /* stack pointer */
Xstruct mathvalue {
X LV lval;
X long val;
X } stack[STACKSZ];
X
Xvoid push(val,lval)
Xlong val;LV lval;
X{
X if (sp == STACKSZ-1)
X zerr("stack overflow",NULL,0);
X else
X sp++;
X stack[sp].val = val;
X stack[sp].lval = lval;
X}
X
Xlong getvar(s)
XLV s;
X{
Xlong t;
X
X if (!(t = getiparam(lvals[s])))
X return 0;
X return t;
X}
X
Xlong setvar(s,v)
XLV s;long v;
X{
X if (s == -1 || s >= lvc)
X {
X zerr("lvalue required",NULL,0);
X return 0;
X }
X if (noeval)
X return v;
X setiparam(lvals[s],v);


X return v;
X}
X

Xint notzero(a) /**/
Xint a;
X{
X if (a == 0)
X {
X zerr("division by zero",NULL,0);
X return 0;
X }
X return 1;
X}
X
X#define pop2() { b = stack[sp--].val; a = stack[sp--].val; }
X#define pop3() {c=stack[sp--].val;b=stack[sp--].val;a=stack[sp--].val;}
X#define nolval() {stack[sp].lval= -1;}
X#define pushv(X) { push(X,-1); }
X#define pop2lv() { pop2() lv = stack[sp+1].lval; }
X#define set(X) { push(setvar(lv,X),lv); }
X
Xvoid op(what) /**/
Xint what;
X{
Xlong a,b,c;
XLV lv;
X
X if (sp < 0)
X {
X zerr("bad math expression: stack empty",NULL,0);
X return;
X }
X switch(what) {
X case NOT: stack[sp].val = !stack[sp].val; nolval(); break;
X case COMP: stack[sp].val = ~stack[sp].val; nolval(); break;
X case POSTPLUS: ( void ) setvar(stack[sp].lval,stack[sp].val+1); break;
X case POSTMINUS: ( void ) setvar(stack[sp].lval,stack[sp].val-1); break;
X case UPLUS: nolval(); break;
X case UMINUS: stack[sp].val = -stack[sp].val; nolval(); break;
X case AND: pop2(); pushv(a&b); break;
X case XOR: pop2(); pushv(a^b); break;
X case OR: pop2(); pushv(a|b); break;
X case MUL: pop2(); pushv(a*b); break;
X case DIV: pop2(); if (notzero(b)) pushv(a/b); break;
X case MOD: pop2(); if (notzero(b)) pushv(a%b); break;
X case PLUS: pop2(); pushv(a+b); break;
X case MINUS: pop2(); pushv(a-b); break;
X case SHLEFT: pop2(); pushv(a<<b); break;
X case SHRIGHT: pop2(); pushv(a>>b); break;
X case LES: pop2(); pushv(a<b); break;
X case LEQ: pop2(); pushv(a<=b); break;
X case GRE: pop2(); pushv(a>b); break;
X case GEQ: pop2(); pushv(a>=b); break;
X case DEQ: pop2(); pushv(a==b); break;
X case NEQ: pop2(); pushv(a!=b); break;
X case DAND: pop2(); pushv(a&&b); break;
X case DOR: pop2(); pushv(a||b); break;
X case DXOR: pop2(); pushv(a&&!b||!a&&b); break;
X case QUEST: pop3(); pushv((a)?b:c); break;
X case COLON: break;
X case EQ: pop2lv(); set(b); break;
X case PLUSEQ: pop2lv(); set(a+b); break;
X case MINUSEQ: pop2lv(); set(a-b); break;
X case MULEQ: pop2lv(); set(a*b); break;
X case DIVEQ: pop2lv(); if (notzero(b)) set(a/b); break;
X case MODEQ: pop2lv(); if (notzero(b)) set(a%b); break;
X case ANDEQ: pop2lv(); set(a&b); break;
X case XOREQ: pop2lv(); set(a^b); break;
X case OREQ: pop2lv(); set(a|b); break;
X case SHLEFTEQ: pop2lv(); set(a<<b); break;
X case SHRIGHTEQ: pop2lv(); set(a>>b); break;
X case DANDEQ: pop2lv(); set(a&&b); break;
X case DOREQ: pop2lv(); set(a||b); break;
X case DXOREQ: pop2lv(); set(a&&!b||!a&&b); break;
X case COMMA: pop2(); pushv(b); break;
X case PREPLUS: stack[sp].val = setvar(stack[sp].lval,
X stack[sp].val+1); break;
X case PREMINUS: stack[sp].val = setvar(stack[sp].lval,
X stack[sp].val-1); break;
X default: zerr("out of integers",NULL,0); exit(1);
X }
X}
X
Xvoid bop(tk) /**/
Xint tk;
X{
X switch (tk) {
X case DAND: case DANDEQ: if (!stack[sp].val) noeval++; break;
X case DOR: case DOREQ: if (stack[sp].val) noeval++; break;
X };
X}
X
Xlong mathevall(s,prek,ep) /**/
Xchar *s;int prek;char **ep;
X{
Xint t0;
X
X lastbase = -1;
X for (t0 = 0; t0 != LVCOUNT; t0++)
X lvals[t0] = NULL;
X lvc = 0;
X ptr = s;
X sp = -1;
X unary = 1;
X mathparse(prek);
X *ep = ptr;
X if (sp)
X zerr("bad math expression: unbalanced stack",NULL,0);
X for (t0 = 0; t0 != lvc; t0++)
X free(lvals[t0]);
X return stack[0].val;
X}
X
Xlong matheval(s) /**/
Xchar *s;
X{
Xchar *junk;
Xlong x;
X
X if (!*s)
X return 0;
X x = mathevall(s,TOPPREC,&junk);
X if (*junk)
X zerr("bad math expression: illegal character: %c",NULL,*junk);
X return x;
X}
X
Xlong mathevalarg(s,ss) /**/
Xchar *s;char **ss;
X{
Xlong x;
X
X x = mathevall(s,ARGPREC,ss);
X if (mtok == COMMA)
X (*ss)--;
X return x;
X}
X
X/* operator-precedence parse the string and execute */
X
Xvoid mathparse(pc) /**/
Xint pc;


X{
X if (errflag)
X return;

X mtok = zzlex();
X while (prec[mtok] <= pc)


X {
X if (errflag)
X return;

X if (mtok == NUM)
X push(yyval,-1);
X else if (mtok == ID)
X push(getvar(yylval),yylval);
X else if (mtok == M_INPAR)
X {
X mathparse(TOPPREC);
X if (mtok != M_OUTPAR)
X exit(1);
X }
X else if (mtok == QUEST)
X {
X int q = stack[sp].val;
X if (!q) noeval++;
X mathparse(prec[QUEST]-1);
X if (!q) noeval--; else noeval++;
X mathparse(prec[QUEST]);
X if (q) noeval--;
X op(QUEST);
X continue;
X }
X else
X {
X int otok = mtok,onoeval = noeval;
X
X if (type[otok] == BOOL)
X bop(otok);
X mathparse(prec[otok]-(type[otok] != RL));
X noeval = onoeval;
X op(otok);
X continue;
X }
X mtok = zzlex();
X }
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/math.c ||
echo 'restore of zsh2.2/src/math.c failed'
Wc_c="`wc -c < 'zsh2.2/src/math.c'`"
test 10185 -eq "$Wc_c" ||
echo 'zsh2.2/src/math.c: original size 10185, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/mem.c ==============
if test -f 'zsh2.2/src/mem.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/mem.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/mem.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/mem.c' &&
X/*
X *
X * mem.c - memory management


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */

X/*
X
X mem.c - memory management
X
X This file is part of zsh, the Z shell.
X
X zsh is free software; no one can prevent you from reading the source
X code, or giving it to someone else.
X
X This file is copyrighted under the GNU General Public License, which
X can be found in the file called COPYING.
X
X Copyright (C) 1990, 1991 Paul Falstad
X
X*/
X
X#include "zsh.h"
X#define HEAPSIZE 8192
X
X/*
X
X There are two ways to allocate memory in zsh. The first way is
X to call zalloc/zcalloc, which call malloc/calloc directly. It
X is legal to call realloc() or free() on memory allocated this way.
X The second way is to call halloc/hcalloc, which allocates memory
X from one of the memory pools on the heap stack. A pool can be
X created by calling pushheap(), and destroyed by calling popheap().
X To free the memory in the pool without destroying it, call
X freeheap(); this is equivalent to { popheap(); pushheap(); }
X Memory allocated in this way does not have to be freed explicitly;
X it will all be freed when the pool is destroyed. In fact,
X attempting to free this memory may result in a core dump.
X The pair of pointers ncalloc and alloc may point to either
X zalloc & zcalloc or halloc & hcalloc; permalloc() sets them to the
X former, and heapalloc() sets them to the latter. This can be useful.
X For example, the dupstruct() routine duplicates a syntax tree,
X allocating the new memory for the tree using alloc(). If you want
X to duplicate a structure for a one-time use (i.e. to execute the list
X in a for loop), call heapalloc(), then dupstruct(). If you want
X to duplicate a structure in order to preserve it (i.e. a function
X definition), call permalloc(), then dupstruct().
X
X*/
X
X/* initialize heap stack */
X
Xvoid meminit() /**/
X{
X permalloc();
X heaplist = newlist();
X pushheap();
X}
X
X/* set default allocation to heap stack */
X
Xvoid heapalloc() /**/
X{
X alloc = hcalloc;
X ncalloc = halloc;
X useheap = 1;
X}
X
Xstatic vptr (*lastcalloc) DCLPROTO((int));
Xstatic vptr (*lastncalloc) DCLPROTO((int));
X
X/* set default allocation to malloc() */
X
Xvoid permalloc() /**/
X{
X lastcalloc = alloc;
X lastncalloc = ncalloc;
X alloc = zcalloc;
X ncalloc = zalloc;
X useheap = 0;
X}
X
X/* reset previous default allocation */
X
Xvoid lastalloc() /**/
X{
X alloc = lastcalloc;
X ncalloc = lastncalloc;
X}
X
Xstruct heap {
X char *pool,*ptr;
X int free;
X struct heap *next;
X };
X
X/* create a memory pool */
X
Xvoid pushheap() /**/
X{
XHeap h;
X
X h = (Heap) zalloc(sizeof *h);
X h->pool = h->ptr = zalloc(HEAPSIZE);
X h->free = HEAPSIZE;
X h->next = NULL;
X permalloc();
X pushnode(heaplist,h);
X lastalloc();
X}
X
X/* reset a memory pool */
X
Xvoid freeheap() /**/
X{


XHeap h = (Heap) peekfirst(heaplist);
X

X freeh(h->next);
X h->next = NULL;
X h->free += (h->ptr-h->pool);
X h->ptr = h->pool;
X}
X
X/* destroy a memory pool */
X
Xvoid popheap() /**/
X{
XHeap h = (Heap) getnode(heaplist);
X
X freeh(h);
X}
X
Xvoid freeh(h) /**/
XHeap h;
X{
X if (h)
X {
X freeh(h->next);


X free(h->pool);
X free(h);
X }

X}
X
X/* allocate memory from the current memory pool */
X
Xvptr halloc(size) /**/
Xint size;
X{
XHeap h = (Heap) peekfirst(heaplist),h2;
Xchar *ret;
X
X size = (size|7)+1;
X while (h && h->free-size < 0)
X h = h->next;
X if (!h) {
X h2 = (Heap) zalloc(sizeof *h2);
X h2->pool = h2->ptr = zalloc(h2->free =
X (size < HEAPSIZE) ? HEAPSIZE : (size|(HEAPSIZE-1))+1);
X h2->next = (Heap) peekfirst(heaplist);
X setdata(firstnode(heaplist),(vptr) h2);
X h = h2;
X }
X h->free -= size;


X ret = h->ptr;

X h->ptr += size;


X return ret;
X}
X

X/* allocate memory from the current memory pool and clear it */
X
Xvptr hcalloc(size) /**/
Xint size;
X{
Xvptr ptr;
X
X ptr = halloc(size);
X memset(ptr,0,size);


X return ptr;
X}
X

Xvptr hrealloc(p,old,new) /**/
Xchar *p;int old;int new;
X{
Xchar *ptr;
X
X ptr = halloc(new);
X memcpy(ptr,p,old);


X return ptr;
X}
X

X/* allocate permanent memory */
X
Xvptr zalloc(l) /**/
Xint l;
X{
Xvptr z;
X
X if (!l) l = 1;
X if (!(z = malloc(l)))
X {
X zerr("fatal error: out of memory",NULL,0);
X exit(1);
X }
X return z;
X}
X
Xvptr zcalloc(size) /**/
Xint size;
X{
Xvptr ptr;
X
X ptr = zalloc(size);
X memset(ptr,0,size);


X return ptr;
X}
X

Xchar *strdup(s) /**/


Xchar *s;
X{
Xchar *t;
X

X if (!s)
X return NULL;

X t = ncalloc(strlen(s)+1);
X strcpy(t,s);
X return t;
X}
X
Xchar *ztrdup(s) /**/


Xchar *s;
X{
Xchar *t;
X

X if (!s)
X return NULL;

X t = zalloc(strlen(s)+1);
X strcpy(t,s);
X return t;
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/mem.c ||
echo 'restore of zsh2.2/src/mem.c failed'
Wc_c="`wc -c < 'zsh2.2/src/mem.c'`"
test 4948 -eq "$Wc_c" ||
echo 'zsh2.2/src/mem.c: original size 4948, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/params.c ==============
if test -f 'zsh2.2/src/params.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/params.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/params.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/params.c' &&
X/*
X *
X * params.c - parameters


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"

X#include <pwd.h>
X
X#define new(X) (X=(vptr)alloc(sizeof(*(X))))
X
Xstatic Param argvparam;
X
Xstruct iparam {
X struct hashnode *next; int canfree; char *nam; /* hash data */
X void *value;
X int (*func1)(); /* set func */
X int (*func2)(); /* get func */
X int ct; /* output base or field width */
X int flags;
X vptr data; /* used by getfns */
X char *env; /* location in environment, if exported */
X char *ename; /* name of corresponding environment var */
X };
X
X#define IFN(X) ((int (*)())(X))
X
X/* put predefined params in hash table */
X
Xvoid setupparams() /**/
X{
Xstatic struct iparam pinit[] = {
X#define IPDEF1(A,B,C,D) {NULL,0,A,NULL,IFN(C),IFN(B),10,\
X PMFLAG_i|PMFLAG_SPECIAL|D,NULL,NULL,NULL}
X IPDEF1("#",poundgetfn,IFN(nullsetfn),PMFLAG_r),
X IPDEF1("ARGC",poundgetfn,IFN(nullsetfn),PMFLAG_r),
X IPDEF1("ERRNO",errnogetfn,IFN(nullsetfn),PMFLAG_r),
X IPDEF1("GID",gidgetfn,IFN(nullsetfn),PMFLAG_r),
X IPDEF1("HISTSIZE",histsizegetfn,histsizesetfn,0),
X IPDEF1("LITHISTSIZE",lithistsizegetfn,lithistsizesetfn,0),
X IPDEF1("RANDOM",randomgetfn,randomsetfn,0),
X IPDEF1("SECONDS",secondsgetfn,secondssetfn,0),
X IPDEF1("UID",uidgetfn,IFN(nullsetfn),PMFLAG_r),
X
X#define IPDEF2(A,B,C,D) {NULL,0,A,NULL,IFN(C),IFN(B),0,\
X PMFLAG_SPECIAL|D,NULL,NULL,NULL}
X IPDEF2("-",dashgetfn,IFN(nullsetfn),PMFLAG_r),
X IPDEF2("HISTCHARS",histcharsgetfn,histcharssetfn,0),
X IPDEF2("HOME",homegetfn,homesetfn,0),
X IPDEF2("TERM",termgetfn,termsetfn,0),
X IPDEF2("WORDCHARS",wordcharsgetfn,wordcharssetfn,0),
X IPDEF2("IFS",ifsgetfn,ifssetfn,0),
X IPDEF2("_",underscoregetfn,IFN(nullsetfn),PMFLAG_r),
X
X#define IPDEF3(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(strconstgetfn),0,PMFLAG_r|\
X PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
X IPDEF3("HOSTTYPE",HOSTTYPE),
X IPDEF3("VERSION",VERSIONSTR),
X
X#define IPDEF4(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(intvargetfn),10,\
X PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
X IPDEF4("!",&lastpid),
X IPDEF4("$",&mypid),
X IPDEF4("?",&lastval),
X IPDEF4("status",&lastval),
X IPDEF4("LINENO",&lineno),
X IPDEF4("PPID",&ppid),
X
X#define IPDEF5(A,B) {NULL,0,A,NULL,IFN(intvarsetfn),IFN(intvargetfn),10,\
X PMFLAG_i|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
X IPDEF5("BAUD",&baud),
X IPDEF5("COLUMNS",&columns),
X IPDEF5("DIRSTACKSIZE",&dirstacksize),
X IPDEF5("LINES",&lines),
X IPDEF5("LISTMAX",&listmax),
X IPDEF5("LOGCHECK",&logcheck),
X IPDEF5("MAILCHECK",&mailcheck),
X IPDEF5("OPTIND",&zoptind),
X IPDEF5("PERIOD",&period),
X IPDEF5("REPORTTIME",&reporttime),
X IPDEF5("SAVEHIST",&savehist),
X IPDEF5("SHLVL",&shlvl),
X IPDEF5("TMOUT",&tmout),
X
X#define IPDEF6(A,B) {NULL,0,A,NULL,IFN(nullsetfn),IFN(strvargetfn),0,\
X PMFLAG_r|PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
X IPDEF6("LOGNAME",&logname),
X IPDEF6("PWD",&pwd),
X IPDEF6("TTY",&ttystrname),
X IPDEF6("USERNAME",&username),
X
X#define IPDEF7(A,B) {NULL,0,A,NULL,IFN(strvarsetfn),IFN(strvargetfn),0,\
X PMFLAG_SPECIAL,(vptr)B,NULL,NULL}
X IPDEF7("FCEDIT",&fceditparam),
X IPDEF7("HOST",&hostnam),
X IPDEF7("OLDPWD",&oldpwd),
X IPDEF7("OPTARG",&optarg),
X IPDEF7("MAIL",&mailfile),
X IPDEF7("NULLCMD",&nullcmd),
X IPDEF7("POSTEDIT",&postedit),
X IPDEF7("prompt",&prompt),
X IPDEF7("PROMPT",&prompt),
X IPDEF7("PROMPT2",&prompt2),
X IPDEF7("PROMPT3",&prompt3),
X IPDEF7("PROMPT4",&prompt4),
X IPDEF7("READNULLCMD",&readnullcmd),
X IPDEF7("RPROMPT",&rprompt),
X IPDEF7("PS1",&prompt),
X IPDEF7("PS2",&prompt2),
X IPDEF7("PS3",&prompt3),
X IPDEF7("PS4",&prompt4),
X IPDEF7("RPS1",&rprompt),
X IPDEF7("SPROMPT",&sprompt),
X IPDEF7("TIMEFMT",&timefmt),
X IPDEF7("TMPPREFIX",&tmpprefix),
X IPDEF7("WATCHFMT",&watchfmt),
X IPDEF7("0",&argzero),
X
X#define IPDEF8(A,B,C) {NULL,0,A,NULL,IFN(colonarrsetfn),IFN(colonarrgetfn),0,\
X PMFLAG_SPECIAL,(vptr)C,NULL,B}
X IPDEF8("CDPATH","cdpath",&cdpath),
X IPDEF8("FIGNORE","fignore",&fignore),
X IPDEF8("FPATH","fpath",&fpath),
X IPDEF8("MAILPATH","mailpath",&mailpath),
X IPDEF8("MANPATH","manpath",&manpath),
X IPDEF8("WATCH","watch",&watch),
X IPDEF8("HOSTS","hosts",&hosts),
X IPDEF8("PATH",NULL,NULL),
X
X#define IPDEF9(A,B,C) {NULL,0,A,NULL,IFN(arrvarsetfn),IFN(arrvargetfn),0,\
X PMFLAG_A|PMFLAG_SPECIAL|C,(vptr)B,NULL,NULL}
X IPDEF9("cdpath",&cdpath,0),
X IPDEF9("fignore",&fignore,0),
X IPDEF9("fpath",&fpath,0),
X IPDEF9("mailpath",&mailpath,0),
X IPDEF9("manpath",&manpath,0),
X IPDEF9("watch",&watch,0),
X IPDEF9("hosts",&hosts,0),
X IPDEF9("signals",&sigptr,PMFLAG_r),
X IPDEF9("argv",&pparams,0),
X IPDEF9("*",&pparams,0),
X IPDEF9("@",&pparams,0),
X
X#define IPDEF10(A,C,D) {NULL,0,A,NULL,IFN(D),IFN(C),0,\
X PMFLAG_A|PMFLAG_SPECIAL,NULL,NULL,NULL}
X IPDEF10("path",pathgetfn,pathsetfn),
X IPDEF10("hostcmds",nullgetfn,hostcmdssetfn),
X IPDEF10("optcmds",nullgetfn,optcmdssetfn),
X IPDEF10("bindcmds",nullgetfn,bindcmdssetfn),
X IPDEF10("varcmds",nullgetfn,varcmdssetfn),
X {NULL,}
X };
Xstruct iparam *ip;
X
X for (ip = pinit; ip->nam; ip++) addhperm(ip->nam,ip,paramtab,NULL);
X argvparam = gethnode("argv",paramtab);
X}
X
Xstatic int unsetflag;
X
Xstruct param *createparam(name,value,flags) /**/
Xchar *name;vptr value;int flags;
X{
Xstruct param *pm;
Xchar buf[20];
X
X pm = zcalloc(sizeof *pm);
X if (isset(ALLEXPORT))
X flags |= PMFLAG_x;
X pm->flags = flags;
X if ((flags & PMTYPE) == PMFLAG_s) {
X pm->u.str = value;
X pm->sets.cfn = strsetfn;
X pm->gets.cfn = strgetfn;
X } else if ((flags & PMTYPE) == PMFLAG_A) {
X pm->u.arr = value;
X pm->sets.afn = arrsetfn;
X pm->gets.afn = arrgetfn;
X } else {
X pm->u.val = (value) ? matheval(value) : 0;
X pm->sets.ifn = intsetfn;
X pm->gets.ifn = intgetfn;
X sprintf(buf,"%ld",pm->u.val);
X value = buf;
X }
X if (flags & PMFLAG_x)
X pm->env = addenv(name,value);
X addhnode(ztrdup(name),pm,paramtab,freepm);
X return pm;
X}
X
Xint isident(s) /**/
Xchar *s;
X{
Xchar *ss;
X
X for (ss = s; *ss; ss++) if (!iident(*ss)) break;
X if (!*ss || *ss == '[') return 1;
X if (*s == Quest)
X *s = '?';
X else if (*s == Pound)
X *s = '#';
X else if (*s == String || *s == Qstring)
X *s = '$';
X else if (*s == Star)
X *s = '*';
X if (*s == '#' || *s == '-' || *s == '?' || *s == '$' || *s == '_' ||
X *s == '!' || *s == '@' || *s == '*')
X return 1;


X return 0;
X}
X

XValue getvalue(pptr,bracks) /**/
Xchar **pptr;int bracks;
X{
Xchar *s = *pptr,*t = *pptr;
Xchar sav;
XValue v;
X
X if (idigit(*s)) while (idigit(*s)) s++;
X else if (iident(*s)) while (iident(*s)) s++;
X else if (*s == Quest) *s++ = '?';
X else if (*s == Pound) *s++ = '#';
X else if (*s == String) *s++ = '$';
X else if (*s == Qstring) *s++ = '$';
X else if (*s == Star) *s++ = '*';
X else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' ||
X *s == '_' || *s == '!' || *s == '@' || *s == '*') s++;
X else return NULL;
X if (sav = *s) *s = '\0';
X if (idigit(*t) && *t != '0') {
X v = (Value) hcalloc(sizeof *v);
X v->pm = argvparam;
X v->a = v->b = atoi(t)-1;
X if (sav)
X *s = sav;
X } else {
X struct param *pm;
X int isvarat = !strcmp(t, "@");
X
X pm = gethnode(t,paramtab);
X if (sav)
X *s = sav;
X *pptr = s;
X if (!pm)
X return NULL;
X v = hcalloc(sizeof *v);


X if (pmtype(pm) == PMFLAG_A)

X v->isarr = isvarat ? -1 : 1;
X v->pm = pm;
X v->a = 0; v->b = -1;
X if (bracks && (*s == '[' || *s == Inbrack)) {
X int a,b;
X char *olds = s,*t;
X
X *s++ = '[';
X for (t = s; *t && *t != ']' && *t != Outbrack; t++)
X if (itok(*t))
X *t = ztokens[*t-Pound];
X if (*t == Outbrack)
X *t = ']';
X if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
X if (v->isarr) v->isarr = (s[0] == '*') ? 1 : -1;
X v->a = 0;
X v->b = -1;
X s += 2;
X } else {
X a = mathevalarg(s,&s);
X if (a > 0) a--;
X if (*s == ',' || *s == Comma) {
X s++;
X b = mathevalarg(s,&s);
X if (b > 0) b--;
X } else
X b = a;


X if (*s == ']') {

X s++;
X if (v->isarr && a == b)
X v->isarr = 0;
X v->a = a;
X v->b = b;
X } else
X s = olds;
X }
X }
X }
X if (!bracks && *s)
X return NULL;
X *pptr = s;


X return v;
X}
X

Xchar *getstrvalue(v) /**/
XValue v;
X{
Xchar *s,**ss;
Xstatic char buf[20];
X
X if (!v)
X return "";
X if (pmtype(v->pm) != PMFLAG_A) {
X if ((pmtype(v->pm) == PMFLAG_i))
X convbase(s = buf,v->pm->gets.ifn(v->pm),v->pm->ct);
X else
X s = v->pm->gets.cfn(v->pm);
X if (v->a == 0 && v->b == -1) return s;
X if (v->a < 0) v->a += strlen(s);
X if (v->b < 0) v->b += strlen(s);
X s = (v->a > strlen(s)) ? strdup("") : strdup(s+v->a);
X if (v->b < v->a) s[0] = '\0';
X else if (v->b-v->a < strlen(s)) s[v->b-v->a+1] = '\0';
X return s;
X }
X if (v->isarr) return spacejoin(v->pm->gets.afn(v->pm));
X
X ss = v->pm->gets.afn(v->pm);
X if (v->a < 0) v->a += arrlen(ss);
X s = (v->a >= arrlen(ss) || v->a < 0) ? "" : ss[v->a];


X return s;
X}
X

Xchar **getarrvalue(v) /**/
XValue v;
X{
Xchar **s;
Xstatic char *nular[] = { "", NULL };
X
X if (!v)
X return arrdup(nular);
X s = v->pm->gets.afn(v->pm);
X if (v->a == 0 && v->b == -1) return s;
X if (v->a < 0) v->a += arrlen(s);
X if (v->b < 0) v->b += arrlen(s);
X if (v->a > arrlen(s) || v->a < 0)
X s = arrdup(nular);
X else
X s = arrdup(s)+v->a;
X if (v->b < v->a) s[0] = NULL;
X else if (v->b-v->a < arrlen(s)) s[v->b-v->a+1] = NULL;


X return s;
X}
X

Xlong getintvalue(v) /**/
XValue v;
X{
Xchar **ss;
X
X if (!v || v->isarr)
X return 0;
X if (pmtype(v->pm) != PMFLAG_A) {
X if (pmtype(v->pm) == PMFLAG_i)
X return v->pm->gets.ifn(v->pm);
X return atol(v->pm->gets.cfn(v->pm));
X }
X ss = v->pm->gets.afn(v->pm);
X if (v->a < 0) v->a += arrlen(ss);
X if (v->a < 0 || v->a > arrlen(ss)) return 0;
X return atol(ss[v->a]);
X}
X
Xvoid setstrvalue(v,val) /**/
XValue v;char *val;
X{
Xchar *s;
X
X if (v->pm->flags & PMFLAG_r) {
X free(val);
X return;
X }
X if ((s = v->pm->env) && val)
X v->pm->env = replenv(v->pm->env,val);
X switch (pmtype(v->pm)) {
X case PMFLAG_s:
X if (v->a == 0 && v->b == -1)
X (v->pm->sets.cfn)(v->pm,val);
X else {
X char *z,*y,*x;
X
X z = strdup((v->pm->gets.cfn)(v->pm));
X if (v->a < 0) {
X v->a += strlen(z);
X if (v->a < 0) v->a = 0;
X }
X if (v->a > strlen(z)) v->a = strlen(z);
X if (v->b < 0) v->b += strlen(z);
X if (v->b < v->a) v->b = v->a;
X z[v->a] = '\0';
X y = z+v->b+1;
X x = zalloc(strlen(z)+strlen(y)+strlen(val)+1);
X strcpy(x,z);
X strcat(x,val);
X strcat(x,y);
X (v->pm->sets.cfn)(v->pm,x);
X }
X if (v->pm->flags & (PMFLAG_L|PMFLAG_R|PMFLAG_Z) && !v->pm->ct)
X v->pm->ct = strlen(val);


X break;
X case PMFLAG_i:

X (v->pm->sets.ifn)(v->pm,matheval(val));
X if (!v->pm->ct && lastbase != 1)
X v->pm->ct = lastbase;
X free(val);
X break;
X case PMFLAG_A:
X if (v->a != v->b)
X zerr("illegal array assignment",NULL,0);
X else {
X char **ss = (v->pm->gets.afn)(v->pm);
X int ac,ad,t0;
X
X ac = arrlen(ss);
X if (v->a < 0) {
X v->a += ac;
X if (v->a < 0) v->a = 0;
X }
X if (v->a >= ac) {
X char **st = ss;
X
X ad = v->a+1;
X ss = zalloc((ad+1)*sizeof *ss);
X memcpy(ss,st,(ad+1)*sizeof *ss);
X for (t0 = 0; t0 != ac; t0++)
X ss[t0] = ztrdup(ss[t0]);
X while (ac < ad)
X ss[ac++] = ztrdup("");
X ss[ac] = NULL;
X }
X if (ss[v->a]) free(ss[v->a]);
X ss[v->a] = val;
X (v->pm->sets.afn)(v->pm,ss);


X }
X break;
X }
X}
X

Xvoid setintvalue(v,val) /**/
XValue v;long val;
X{
Xchar buf[20];
X
X if (v->pm->flags & PMFLAG_r)
X return;
X if (v->pm->env) {
X sprintf(buf,"%ld",val);
X v->pm->env = replenv(v->pm->env,buf);
X }
X switch (pmtype(v->pm))
X {
X case PMFLAG_s:
X sprintf(buf,"%ld",val);
X (v->pm->sets.cfn)(v->pm,ztrdup(buf));


X break;
X case PMFLAG_i:

SHAR_EOF
true || echo 'restore of zsh2.2/src/params.c failed'
fi
echo 'End of zsh2.2 part 10'
echo 'File zsh2.2/src/params.c is continued in part 11'
echo 11 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:05:46 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 107
Archive-name: zsh2.2/part11

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.11 (part 11 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/params.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 11; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/params.c'
else
echo 'x - continuing file zsh2.2/src/params.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/params.c' &&

X (v->pm->sets.ifn)(v->pm,val);
X if (!v->pm->ct && lastbase != -1)


X v->pm->ct = lastbase;

X break;
X case PMFLAG_A:

X zerr("attempt to assign integer to array",NULL,0);


X break;
X }
X}
X

Xvoid setintenv(s,val) /**/
Xchar *s; long val;
X{
XParam pm;
Xchar buf[20];
X
X if ((pm = gethnode(s,paramtab)) && pm->env) {
X sprintf(buf,"%ld",val);
X pm->env = replenv(pm->env,buf);
X }
X}
X
Xvoid setarrvalue(v,val) /**/
XValue v;char **val;


X{
X if (v->pm->flags & PMFLAG_r)
X return;

X if (pmtype(v->pm) != PMFLAG_A)

X {
X zerr("attempt to assign array value to non-array",NULL,0);
X return;
X }
X (v->pm->sets.afn)(v->pm,val);
X}
X
Xchar *getsparamval(s,l) /**/
Xchar *s;int l;
X{
Xchar sav,*t = s;
XValue v;
X
X if (sav = t[l])
X t[l] = '\0';
X if (!(v = getvalue(&s,0)))
X return NULL;
X t[l] = sav;
X t = getstrvalue(v);


X return t;
X}
X

Xlong getiparam(s) /**/
Xchar *s;
X{
XValue v;
X
X if (!(v = getvalue(&s,0)))
X return 0;
X return getintvalue(v);
X}
X
Xchar *getsparam(s) /**/
Xchar *s;
X{
XValue v;
X
X if (!(v = getvalue(&s,0)))
X return NULL;
X return getstrvalue(v);
X}
X
Xchar **getaparam(s) /**/
Xchar *s;
X{
XValue v;
X
X if (!(v = getvalue(&s,0))) return NULL;
X return getarrvalue(v);
X}
X
XParam setsparam(s,val) /**/
Xchar *s;char *val;
X{
XValue v;


Xchar *t = s;
X

X if (!isident(s)) {
X zerr("not an identifier: %s",s,0);
X free(val);
X return NULL;
X }
X if (!(v = getvalue(&s,1)) || *s)
X return createparam(t,val,PMFLAG_s);
X if ((v->pm->flags & PMTYPE) != PMFLAG_s &&
X !(v->pm->flags & PMFLAG_SPECIAL)) {
X unsetparam(s);
X return createparam(t,val,PMFLAG_s);
X }
X setstrvalue(v,val);
X return v->pm;
X}
X
XParam setaparam(s,val) /**/
Xchar *s;char **val;
X{
XValue v;


Xchar *t = s;
X

X if (!isident(s))
X {
X zerr("not an identifier: %s",s,0);
X return NULL;
X }
X if (!(v = getvalue(&s,1)) || *s)
X return createparam(t,val,PMFLAG_A);
X if ((v->pm->flags & PMTYPE) != PMFLAG_A &&
X !(v->pm->flags & PMFLAG_SPECIAL)) {
X unsetparam(s);
X return createparam(t,val,PMFLAG_A);
X }
X setarrvalue(v,val);
X return v->pm;
X}
X
XParam setiparam(s,val) /**/
Xchar *s;long val;
X{
XValue v;
Xchar *t = s;
XParam pm;
X
X if (!isident(s))
X {
X zerr("not an identifier: %s",s,0);
X return NULL;
X }
X if (!(v = getvalue(&s,0)))
X {
X pm = createparam(t,NULL,PMFLAG_i);
X pm->u.val = val;
X return pm;
X }
X setintvalue(v,val);
X return v->pm;
X}
X
Xvoid unsetparam(s) /**/
Xchar *s;
X{
XParam pm;
X
X if (!(pm = gethnode(s,paramtab)))
X return;
X if (pm->flags & PMFLAG_r)
X return;
X unsetflag = 1;
X switch (pmtype(pm))
X {
X case 0:
X (pm->sets.cfn)(pm,ztrdup(""));


X break;
X case PMFLAG_i:

X (pm->sets.ifn)(pm,0);


X break;
X case PMFLAG_A:

X (pm->sets.afn)(pm,mkarray(NULL));
X break;
X }
X if (pmtype(pm) == PMFLAG_s && (pm->flags & PMFLAG_x)) {


X delenv(pm->env);
X free(pm->env);
X }

X if (!(pm->flags & PMFLAG_SPECIAL))
X freepm(remhnode(s,paramtab));
X unsetflag = 0;
X}
X
Xvoid intsetfn(pm,x) /**/
XParam pm;long x;
X{
X pm->u.val = x;
X}
X
Xlong intgetfn(pm) /**/
XParam pm;
X{
X return pm->u.val;
X}
X
Xvoid strsetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (x)
X {
X if (pm->u.str)
X free(pm->u.str);
X pm->u.str = x;
X }
X}
X
Xchar *strgetfn(pm) /**/
XParam pm;
X{
X return pm->u.str;
X}
X
Xvoid nullsetfn(pm,x) /**/
XParam pm; char *x;
X{
X free(x);
X}
X
Xvoid arrsetfn(pm,x) /**/
XParam pm;char **x;
X{
Xint ct;
X
X if (x)
X {
X if (pm->u.arr && pm->u.arr != x)
X freearray(pm->u.arr);
X pm->u.arr = x;
X for (ct = 0; *x; x++,ct++);
X pm->ct = ct;
X }
X}
X
Xchar **arrgetfn(pm) /**/
XParam pm;
X{
X return pm->u.arr;
X}
X
Xvoid intvarsetfn(pm,x) /**/
XParam pm;long x;
X{
X *((long *) pm->data) = x;
X}
X
Xlong intvargetfn(pm) /**/
XParam pm;
X{
X return *((long *) pm->data);
X}
X
Xvoid strvarsetfn(pm,x) /**/
XParam pm;char *x;
X{
Xchar **q = ((char **) pm->data);
X
X if (*q) free(*q);
X *q = x;
X}
X
Xvoid strvarnonullsetfn(pm,x) /**/
XParam pm;char *x;
X{
Xchar **q = ((char **) pm->data);
X
X if (*q) free(*q);
X *q = (x) ? x : ztrdup("");
X}
X
Xchar *strvargetfn(pm) /**/
XParam pm;
X{
Xchar *s;
X
X s = *((char **) pm->data);
X if (!s) return "";


X return s;
X}
X

Xchar *strconstgetfn(pm) /**/
XParam pm;
X{
X return (char *) pm->data;
X}
X
Xvoid colonarrsetfn(pm,x) /**/
XParam pm;char *x;
X{
Xchar **s,**t,*u,*up;
X
X s = colonsplit(x);
X free(x);
X if (pm->data != &fignore)
X for (t = s; *t; t++) {
X u = *t;
X if (*u == '~') *u = Tilde;
X if (*u == '=') *u = Equals;
X up = hcalloc(strlen(u)+1);
X strcpy(up,u);
X u = up;
X filesub(&u);
X if (!*u) u = ".";
X *t = ztrdup(u);
X }
X if (pm->data) {
X freearray(*((char ***) pm->data));
X *((char ***) pm->data) = s;
X if (pm->ename)
X arrfixenv(pm->ename,s);
X } else {
X freearray(path);
X path = s;
X newcmdnamtab();
X arrfixenv("PATH",s);
X }
X}
X
Xchar *colonarrgetfn(pm) /**/
XParam pm;
X{
X if ((char **) pm->data)
X return colonjoin(*(char ***) pm->data);
X else
X return colonjoin(path);
X}
X
Xchar **arrvargetfn(pm) /**/
XParam pm;
X{
X return *((char ***) pm->data);
X}
X
Xvoid arrvarsetfn(pm,x) /**/
XParam pm;char **x;
X{
X if ((*(char ***) pm->data) != x)
X freearray(*(char ***) pm->data);
X *((char ***) pm->data) = x;
X if (pm->ename)
X arrfixenv(pm->ename,x);
X}
X
Xchar **pathgetfn(pm) /**/
XParam pm;
X{
X return path;
X}
X
Xvoid pathsetfn(pm,x) /**/
XParam pm;char **x;
X{
X if (path != x) freearray(path);
X path = x;
X newcmdnamtab();
X arrfixenv("PATH",x);
X}
X
Xvoid hostcmdssetfn(pm,x) /**/
XParam pm;char **x;
X{
X compctl_process(x,CC_HOSTS|CC_FILES,NULL);
X freearray(x);
X}
X
Xvoid optcmdssetfn(pm,x) /**/
XParam pm;char **x;
X{
X compctl_process(x,CC_OPTIONS,NULL);
X freearray(x);
X}
X
Xvoid bindcmdssetfn(pm,x) /**/
XParam pm;char **x;
X{
X compctl_process(x,CC_BINDINGS,NULL);
X freearray(x);
X}
X
Xvoid varcmdssetfn(pm,x) /**/
XParam pm;char **x;
X{
X compctl_process(x,CC_VARS,NULL);
X freearray(x);
X}
X
Xchar **nullgetfn(pm) /**/
XParam pm;
X{
Xstatic char *nl = NULL; return &nl;
X}
X
Xvoid unsettablesetfn(pm,x) /**/
XParam pm;char *x;
X{ ; }
X
Xlong poundgetfn(pm) /**/
XParam pm;
X{
X return arrlen(pparams);
X}
X
Xlong randomgetfn(pm) /**/
XParam pm;
X{
X return rand() & 0x7fff;
X}
X
Xvoid randomsetfn(pm,v) /**/
XParam pm;long v;
X{
X srand((unsigned int) v);
X}
X
Xlong secondsgetfn(pm) /**/
XParam pm;
X{
X return time(NULL)-shtimer;
X}
X
Xvoid secondssetfn(pm,x) /**/
XParam pm;long x;
X{
X shtimer = time(NULL)-x;
X}
X
Xlong uidgetfn(pm) /**/
XParam pm;
X{
X return getuid();
X}
X
Xlong gidgetfn(pm) /**/
XParam pm;
X{
X return getegid();
X}
X
Xchar *usernamegetfn(pm) /**/
XParam pm;
X{
Xstruct passwd *pwd;
X
X pwd = getpwuid(getuid());
X return pwd->pw_name;
X}
X
Xchar *hostgetfn(pm) /**/
XParam pm;
X{
Xstatic char hostnam[65];
Xstatic int got = 0;
X
X if (!got)
X {
X gethostname(hostnam,64);
X hostnam[64] = '\0';
X got = 1;
X }
X return hostnam;
X}
X
Xchar *ifsgetfn(pm) /**/
XParam pm;


X{
X return ifs;
X}
X

Xvoid ifssetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (x) { free(ifs); ifs = x; }
X inittyptab();
X}
X
Xvoid histsizesetfn(pm,v) /**/
XParam pm;long v;
X{
X if ((histsiz = v) <= 2) histsiz = 2;
X resizehistents();
X}
X
Xlong histsizegetfn(pm) /**/
XParam pm;
X{
X return histsiz;
X}
X
Xvoid lithistsizesetfn(pm,v) /**/
XParam pm;long v;
X{
X if ((lithistsiz = v) <= 2) lithistsiz = 2;
X resizehistents();
X}
X
Xlong lithistsizegetfn(pm) /**/
XParam pm;
X{
X return lithistsiz;
X}
X
Xvoid mailchecksetfn(pm,x) /**/
XParam pm;long x;
X{
X mailcheck = (unsetflag) ? 600 : x;
X}
X
Xvoid pathasetfn(pm,x) /**/
XParam pm;char **x;
X{
X freearray(path);
X path = x;
X newcmdnamtab();
X}
X
Xchar **pathagetfn(pm) /**/
XParam pm;
X{
X return path;
X}
X
Xlong errnogetfn(pm) /**/
XParam pm;
X{
X return errno;
X}
X
Xchar *dashgetfn(pm) /**/
XParam pm;
X{
Xstatic char buf[100];
Xchar *val = buf;
Xint t0;
X
X for (val = buf, t0 = ' ';t0 <= 'z'; t0++)
X if (opts[t0] == OPT_SET)
X *val++ = t0;
X *val = '\0';


X return buf;
X}
X

Xvoid histcharssetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (x) {
X bangchar = x[0];
X hatchar = (bangchar) ? x[1] : '\0';
X hashchar = (hatchar) ? x[2] : '\0';
X free(x);
X }
X}
X
Xchar *histcharsgetfn(pm) /**/
XParam pm;
X{
Xstatic char buf[4];
X
X buf[0] = bangchar;
X buf[1] = hatchar;
X buf[2] = hashchar;
X buf[3] = '\0';


X return buf;
X}
X

Xchar *homegetfn(pm) /**/
XParam pm;
X{
X return home;
X}
X
Xvoid homesetfn(pm,x) /**/
XParam pm;char *x;
X{
X free(home);
X if (isset(CHASELINKS) && (home = xsymlink(x))) free(x);
X else home = x;
X}
X
Xchar *wordcharsgetfn(pm) /**/
XParam pm;
X{
X return wordchars;
X}
X
Xvoid wordcharssetfn(pm,x) /**/
XParam pm;char *x;
X{
X free(wordchars);
X if (x) wordchars = x;
X else wordchars = ztrdup(DEFWORDCHARS);
X inittyptab();
X}
X
Xchar *underscoregetfn(pm) /**/
XParam pm;
X{
Xchar *s,*t;
X
X if (!(s = qgetevent(curhist-1)))
X return "";
X for (t = s+strlen(s); t > s; t--)


X if (*t == HISTSPACE)

X break;
X if (t != s)
X t++;


X return t;
X}
X

Xchar *termgetfn(pm) /**/
XParam pm;
X{
X return term;
X}
X
Xvoid termsetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (term) free(term);
X term = x;
X if (!interact || unset(USEZLE))
X return;
X if (tgetent(termbuf,term) != 1)
X {
X zerr("can't find termcap info for %s",term,0);
X errflag = 0;
X termok = 0;
X }
X else
X {
X char tbuf[1024],*pp;
X int t0;
X
X termok = 1;
X for (t0 = 0; t0 != TC_COUNT; t0++)
X {
X pp = tbuf;
X if (tcstr[t0])
X free(tcstr[t0]);
X if (!tgetstr(tccapnams[t0],&pp))
X tcstr[t0] = NULL, tclen[t0] = 0;
X else
X {
X tcstr[t0] = zalloc(tclen[t0] = pp-tbuf);
X memcpy(tcstr[t0],tbuf,tclen[t0]);
X }
X }
X
X/* if there's no termcap entry for cursor left, use \b. */
X
X if (!tccan(TCLEFT))
X {
X tcstr[TCLEFT] = ztrdup("\b");
X tclen[TCLEFT] = 1;
X }
X
X/* if there's no termcap entry for clear, use ^L. */
X
X if (!tccan(TCCLEARSCREEN))
X {
X tcstr[TCCLEARSCREEN] = ztrdup("\14");
X tclen[TCCLEARSCREEN] = 1;
X }
X
X/* if the termcap entry for down is \n, don't use it. */
X
X if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n')
X {
X tclen[TCDOWN] = 0;
X free(tcstr[TCDOWN]);
X tcstr[TCDOWN] = NULL;
X }
X
X/* if there's no termcap entry for cursor up, forget it.
X Use single line mode. */
X
X if (!tccan(TCUP))


X termok = 0;
X }

X}
X
Xvoid setparams() /**/
X{
Xchar **envp,**envp2,**envp3,*str;
Xchar buf[50];
Xstruct param *pm;
Xint ct;
X
X noerrs = 1;
X for (envp = environ, ct = 2; *envp; envp++,ct++);
X envp = environ;
X envp2 = envp3 = (char **) zalloc(sizeof(char *)*ct);
X for (; *envp; envp++)
X *envp2++ = ztrdup(*envp);
X *envp2 = NULL;
X envp = environ;
X environ = envp2 = envp3;
X for (; *envp; envp++,envp2++) {
X for (str = *envp; *str && *str != '='; str++);
X if (*str == '=') {
X char *iname;
X
X *str = '\0';
X if (isident(*envp))
X pm = setsparam(iname = *envp,ztrdup(str+1));
X if (pm) {
X pm->flags |= PMFLAG_x;
X pm->env = *envp2;
X if (pm->flags & PMFLAG_SPECIAL)
X pm->env = replenv(pm->env,getsparam(iname));
X }
X *str = '=';
X }
X }
X pm = gethnode("HOME",paramtab);
X if (!(pm->flags & PMFLAG_x)) {
X pm->flags |= PMFLAG_x;
X pm->env = addenv("HOME",home);
X }
X pm = gethnode("PWD",paramtab);
X if (!(pm->flags & PMFLAG_x)) {
X pm->flags |= PMFLAG_x;
X pm->env = addenv("PWD",pwd);
X }
X pm = gethnode("LOGNAME",paramtab);
X if (!(pm->flags & PMFLAG_x)) {
X pm->flags |= PMFLAG_x;
X pm->env = addenv("LOGNAME",logname);
X }
X pm = gethnode("SHLVL",paramtab);
X if (!(pm->flags & PMFLAG_x))
X pm->flags |= PMFLAG_x;
X sprintf(buf,"%d",++shlvl);
X pm->env = addenv("SHLVL",buf);
X noerrs = 0;
X}
X
Xchar *mkenvstr(x,y) /**/
Xchar *x;char *y;
X{
Xchar *z;
Xint xl = strlen(x),yl = strlen(y);
X
X z = zalloc(xl+yl+2);
X strcpy(z,x);
X z[xl] = '=';
X strcpy(z+xl+1,y);
X z[xl+yl+1] = '\0';


X return z;
X}
X

Xvoid arrfixenv(s,t) /**/
Xchar *s;char **t;
X{
Xchar **ep;
Xint sl = strlen(s);
X
X for (ep = environ; *ep; ep++)
X if (!strncmp(*ep,s,sl) && (*ep)[sl] == '=') {
X char *u = colonjoin(t);
X replenv(*ep,u);


X break;
X }
X}
X

Xchar *replenv(e,value) /**/
Xchar *e;char *value;
X{
Xchar **ep;
X
X for (ep = environ; *ep; ep++)
X if (*ep == e)
X {
X char *s = e;
X
X while (*s++ != '=');
X *s = '\0';
X *ep = zalloc(strlen(e)+strlen(value)+2);
X strcpy(*ep,e);
X strcat(*ep,value);
X free(e);
X return *ep;
X }


X return NULL;
X}
X

Xchar *addenv(name,value) /**/
Xchar *name;char *value;
X{
Xchar **ep,**ep2,**ep3;
Xint envct;
X
X for (ep = environ; *ep; ep++)
X {
X char *s = *ep,*t = name;
X
X while (*s && *s == *t) s++,t++;
X if (*s == '=' && !*t)
X {
X free(*ep);
X return *ep = mkenvstr(name,value);
X }
X }
X envct = arrlen(environ);
X ep = ep2 = (char **) zalloc((sizeof (char *))*(envct+3));
X for (ep3 = environ; *ep2 = *ep3; ep3++,ep2++);
X *ep2 = mkenvstr(name,value);
X ep2[1] = NULL;
X free(environ);
X environ = ep;
X return *ep2;
X}
X
Xvoid delenv(x) /**/
Xchar *x;
X{
Xchar **ep;
X
X ep = environ;
X for (; *ep; ep++)
X if (*ep == x)
X break;
X if (*ep)
X for (; ep[0] = ep[1]; ep++);
X}
X
Xvoid convbase(s,v,base) /**/
Xchar *s;long v;int base;
X{
Xint digs = 0;
Xlong x;
X
X if (base <= 1)
X base = 10;
X x = v;
X if (x < 0)
X {
X x = -x;
X digs++;
X }
X for (; x; digs++)
X x /= base;
X if (!digs)
X digs = 1;
X s[digs--] = '\0';
X x = (v < 0) ? -v : v;
X while (digs >= 0)
X {
X int dig = x%base;
X s[digs--] = (dig < 10) ? '0'+dig : dig-10+'A';
X x /= base;
X }
X if (v < 0)
X s[0] = '-';
X}
X
X
SHAR_EOF
echo 'File zsh2.2/src/params.c is complete' &&
chmod 0644 zsh2.2/src/params.c ||


echo 'restore of zsh2.2/src/params.c failed'

Wc_c="`wc -c < 'zsh2.2/src/params.c'`"
test 24577 -eq "$Wc_c" ||
echo 'zsh2.2/src/params.c: original size 24577, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/subst.c ==============
if test -f 'zsh2.2/src/subst.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/subst.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/subst.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/subst.c' &&
X/*
X *
X * subst.c - various substitutions


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X#include <pwd.h>
X

X/* do substitutions before fork */
X
Xvoid prefork(list) /**/
XLklist list;
X{
XLknode node = firstnode(list);
Xint qt;
X
X while (node)
X {
X char *str,*str3;
X
X str = str3 = getdata(node);
X if ((*str == Inang || *str == Outang || *str == Equals) &&
X str[1] == Inpar)
X {
X if (*str == Inang)
X setdata(node,getoutproc(str+2)); /* <(...) */
X else if (*str == Equals)
X setdata(node,getoutputfile(str+2)); /* =(...) */
X else
X setdata(node,getinproc(str+2)); /* >(...) */
X if (!getdata(node))
X {
X zerr("parse error in process substitution",NULL,0);
X return;
X }
X }
X else while (*str)
X {
X if ((qt = *str == Qstring) || *str == String)
X if (str[1] != Inpar)
X if (str[1] == Inbrack)
X {
X arithsubst((vptr*) &str,&str3); /* $[...] */
X setdata(node,str3);
X str = str3;


X continue;
X }
X else
X {

X paramsubst(list,node,str,str3,qt);


X if (errflag)
X return;

X str3 = str = getdata(node);
X continue;
X }
X str++;


X if (errflag)
X return;
X }

X if (*(char *) getdata(node))

X remnulargs(getdata(node));
X if (unset(IGNOREBRACES))
X while (hasbraces(getdata(node)))
X xpandbraces(list,&node);
X filesub((char **) getaddrdata(node));


X if (errflag)
X return;

X incnode(node);
X }
X}
X
Xvoid postfork(list,doglob) /**/
XLklist list;int doglob;
X{
XLknode node = firstnode(list);
Xint glb = 1;
X
X badcshglob = 0;
X if (isset(NOGLOBOPT) || !doglob)
X glb = 0;
X while (node)
X {
X char *str3,*str;
X
X str = str3 = getdata(node);
X while (*str)
X {
X if (((*str == String || *str == Qstring) && str[1] == Inpar) ||
X *str == Tick || *str == Qtick)
X {
X Lknode n = prevnode(node);
X
X commsubst(list,node,str,str3,
X (*str == Qstring || *str == Qtick)); /* `...`,$(...) */


X if (errflag)
X return;

X str = str3 = getdata(node = nextnode(n));
X }
X str++;
X }
X if (glb)
X {
X if (haswilds(getdata(node)))
X glob(list,&node);


X if (errflag)
X return;
X }

X incnode(node);
X }
X if (badcshglob == 1) zerr("no match",NULL,0);
X}
X
X/* perform substitution on a single word */
X
Xvoid singsub(s) /**/
Xchar **s;
X{
XLklist foo;
Xchar *t;
X
X for (t = *s; *t; t++)
X if (*t == String)
X *t = Qstring;
X else if (*t == Tick)
X *t = Qtick;
X foo = newlist();
X addnode(foo,*s);
X prefork(foo);


X if (errflag)
X return;

X postfork(foo,0);


X if (errflag)
X return;

X *s = ugetnode(foo);
X if (firstnode(foo))
X zerr("ambiguous: %s",*s,0);
X}
X
X/* strdup, but returns "Nularg" if this is a null string */
X
Xvptr nstrdup(s) /**/
Xvptr s;
X{
Xchar *t = s;
Xchar u[2];
X
X u[0] = Nularg; u[1] = '\0';
X if (!*t)
X return strdup(u);
X return strdup(t);
X}
X
Xchar *dynread(stop) /**/


Xint stop;
X{
Xint bsiz = 256,ct = 0,c;
Xchar *buf = zalloc(bsiz),*ptr;
X
X ptr = buf;

X while ((c = hgetc()) != stop)
X {


X *ptr++ = c;
X if (++ct == bsiz)
X {
X buf = realloc(buf,bsiz *= 2);
X ptr = buf+ct;
X }
X }

X *ptr = 0;
X return buf;
X}
X
Xint filesub(namptr) /**/
Xchar **namptr;
X{
Xchar *str = *namptr,*cnam;
X
X if (*str == Tilde && str[1] != '=')
X {
X if (str[1] == '+' && (str[2] == '/' || str[2] == '\0'))
X {
X char *foo = strdup(pwd); /* ~+ */
X
X str+=2;
X modify(&foo,&str);
X *namptr = dyncat(pwd,str);
X return 1;
X }
X else if (str[1] == '-' && (str[2] == '/' || str[2] == '\0'))
X {
X char *foo; /* ~- */
X
X if (cnam = oldpwd)
X foo = cnam;
X else
X foo = pwd;
X str += 2;
X foo = strdup(foo);
X modify(&foo,&str);
X *namptr = dyncat(foo,str);
X return 1;
X }
X if (ialpha(str[1])) /* ~foo */
X {
X char *ptr,*hom;
X
X for (ptr = ++str; *ptr && iuser(*ptr); ptr++)
X if (*ptr == '-')
X *ptr = '-';
X if (*ptr && *ptr != '/') return 0;
X if (!(hom = gethome(str,ptr-str)))
X {
X zerr("user not found: %l",str,ptr-str);
X errflag = 1;
X return 0;
X }
X modify(&hom,&ptr);
X *namptr = dyncat(hom,ptr);
X return 1;
X }
X else if (str[1] == '/') /* ~/foo */
X {
X *namptr = dyncat(home,str+1);
X return 1;
X }
X else if (!str[1]) /* ~ by itself */
X {
X *namptr = strdup(home);


X return 1;
X }
X }

X if (*str == Equals && iuser(str[1]) && unset(NOEQUALS))
X {
X char *ptr,*s,*ds;
X int val;
X
X if (ialpha(str[1])) /* =foo */
X {
X char sav,*pp;
X
X for (pp = str+1; *pp && *pp != ':'; pp++);
X sav = *pp;
X *pp = '\0';
X if (!(cnam = findcmd(str+1)))
X {
X zerr("%s not found",str+1,0);
X errflag = 1;
X return 0;
X }
X *namptr = cnam;
X if ((*pp = sav) == ':')
X {
X modify(namptr,&pp);
X s = *namptr;
X *namptr = dyncat(*namptr,pp);


X }
X return 1;
X }

X if (str[1] == '-') /* =- */
X {
X val = -1;
X ptr = str+2;
X }
X else
X val = zstrtol(str+1,&ptr,10); /* =# */
X ds = dstackent(val);
X if (!ds)
X return 1;
X s = strdup(ds);
X modify(&s,&ptr);
X *namptr = dyncat(s,ptr);


X return 1;
X }
X return 0;
X}
X

X/* get a named directory */
X
Xchar *gethome(user,len) /**/
Xchar *user;int len;
X{
Xchar sav,*str;
Xstruct passwd *pw;
X
X if (len == 0)
X return strdup(home);
X sav = user[len];
X user[len] = '\0';
X if ((str = getsparamval(user,len)) && *str == '/')
X {
X str = strdup(str);
X adduserdir(user,str);
X user[len] = sav;
X return str;
X }
X permalloc(); /* fixes iris bug--getpwnam calls strdup! */
X pw = getpwnam(user);
X lastalloc();
X if (!pw) {
X user[len] = sav;
X return NULL;
X }
X str = xsymlink(pw->pw_dir);
X adduserdir(user,str);
X user[len] = sav;


X return str;
X}
X

X/* `...`, $(...) */
X
Xvoid commsubst(l,n,str3,str,qt) /**/
XLklist l;Lknode n;char *str3;char *str;int qt;
X{
Xchar *str2;
XLknode where = prevnode(n);
XLklist pl;
X
X if (*str3 == Tick || *str3 == Qtick)
X {
X *str3 = '\0';
X for (str2 = ++str3; *str3 != Tick && *str3 != Qtick; str3++);
X *str3++ = '\0';
X }
X else
X {
X *str3++ = '\0';
X for (str2 = ++str3; *str3 != Outpar; str3++);
X *str3++ = '\0';
X }
X uremnode(l,n);
X if (!(pl = getoutput(str2,qt)))
X {
X zerr("parse error in command substitution",NULL,0);
X errflag = 1;
X return;
X }
X if (full(pl))
X {
X setdata(firstnode(pl),dyncat(str,peekfirst(pl)));
X setdata(lastnode(pl),dyncat(getdata(lastnode(pl)),str3));
X inslist(pl,where,l);
X }
X else
X insnode(l,where,dyncat(str,str3));
X}
X
X/* parameter substitution */
X
Xvoid paramsubst(l,n,aptr,bptr,qt) /**/
XLklist l;Lknode n;char *aptr;char *bptr;int qt;
X{
Xchar *s = aptr,*u,*idbeg,*idend,*ostr = bptr;
Xint brs; /* != 0 means ${...}, otherwise $... */
Xint colf; /* != 0 means we found a colon after the name */
Xint doub = 0; /* != 0 means we have %%, not %, or ##, not # */
Xint isarr = 0;
Xint wasnularr = 0;
Xint plan9 = isset(RCEXPANDPARAM);
Xint getlen = 0;
Xint vunset = 0;
Xint spbreak = isset(SHWORDSPLIT) && !qt;
Xchar *val = NULL,**aval = NULL;
Xint fwidth = 0;
XValue v;


X
X *s++ = '\0';

X if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
X *s != '!' && *s != '$' && *s != String && *s != Qstring &&
X *s != '?' && *s != Quest && *s != '_' &&
X *s != '*' && *s != Star && *s != '@' && *s != '{' &&
X *s != Inbrace && *s != '=' && *s != Hat && *s != '^') {
X s[-1] = '$';
X return;
X }
X if (brs = (*s == '{' || *s == Inbrace)) s++;
X for (;;)
X if (*s == '^' || *s == Hat)
X plan9 ^= 1,s++;
X else if (*s == '=')
X spbreak ^= 1,s++;
X else if ((*s == '#' || *s == Pound) && iident(s[1]))
X getlen = 1,s++;


X else
X break;
X

X idbeg = s;
X if (!(v = getvalue(&s,1))) {
X vunset = 1;
X idend = s;
X } else
X if (isarr = v->isarr)
X aval = getarrvalue(v);
X else {
X val = getstrvalue(v);
X fwidth = v->pm->ct;
X switch (v->pm->flags & (PMFLAG_L | PMFLAG_R | PMFLAG_Z)) {
X char *t;
X int t0;
X
X case PMFLAG_L:
X case PMFLAG_L|PMFLAG_Z:
X t = val;
X if (v->pm->flags & PMFLAG_Z)
X while (*t == '0') t++;
X else
X while (isep(*t)) t++;
X val = ncalloc(fwidth+1);
X val[fwidth] = '\0';
X if ((t0 = strlen(t)) > fwidth)
X t0 = fwidth;
X memset(val,' ',fwidth);
X strncpy(val,t,t0);
X break;
X case PMFLAG_R:
X case PMFLAG_Z:
X case PMFLAG_Z|PMFLAG_R:
X if (strlen(val) < fwidth) {
X t = ncalloc(fwidth+1);
X memset(t,(v->pm->flags & PMFLAG_R) ? ' ' : '0',fwidth);
X if ((t0 = strlen(val)) > fwidth)
X t0 = fwidth;
X strcpy(t+(fwidth-t0),val);
X val = t;
X } else {
X t = ncalloc(fwidth+1);
X t[fwidth] = '\0';
X strncpy(t,val+strlen(val)-fwidth,fwidth);
X val = t;
X }
X break;
X }
X switch (v->pm->flags & (PMFLAG_l | PMFLAG_u)) {
X char *t;
X
X case PMFLAG_l:
X t = val;


X for (;*t;t++)

X *t = tulower(*t);
X break;
X case PMFLAG_u:
X t = val;


X for (;*t;t++)

X *t = tuupper(*t);
X break;
X }
X }
X if (colf = *s == ':') s++;
X
X /* check for ${..?...} or ${..=..} or one of those. Only works
X if the name is in braces. */
X
X if (brs && (*s == '-' || *s == '=' || *s == '?' || *s == '+' || *s == '#' ||
X *s == '%' || *s == Quest || *s == Pound)) {
X if (v && v->isarr && (*s == '%' || *s == '#' || *s == Pound)) {
X zerr("operator requires a scalar",NULL,0);
X return;
X }
X if (*s == s[1]) {
X s++;
X doub = 1;
X }
X u = ++s;
X if (brs) {
X int bct = 1;


X
X for (;;) {

X if (*s == '{' || *s == Inbrace)
X bct++;
X else if (*s == '}' || *s == Outbrace)
X bct--;
X if (!bct || !*s)
X break;
X s++;
X }
X } else {
X while (*s++);
X s--;
X }
X if (*s) *s++ = '\0';
X if (colf && !vunset)
X vunset = (isarr) ? !*aval : !*val;
X switch ((int)(unsigned char)u[-1]) {
X case '-':
X if (vunset)
X val = strdup(u), isarr = 0;
X break;
X case '=':
X if (vunset) {
X char sav = *idend;
X
X *idend = '\0';
X setsparam(idbeg,ztrdup(val = strdup(u)));
X *idend = sav;
X isarr = 0;
X }
X break;
X case '?':
X case (int)(unsigned char)Quest:
X if (vunset) {
X zerr("%s",(*u) ? u : "parameter not set",0);
X if (!interact)
X exit(1);
X return;
X }
X break;
X case '+':
X if (vunset)
X val = strdup("");
X else
X val = strdup(u);
X isarr = 0;
X break;
X case '#':
X case (int)(unsigned char)Pound:
X if (vunset)
X val = strdup("");
X singsub(&u);
X getmatch(&val,u,doub);
X break;
X case '%':
X if (vunset)
X val = strdup("");
X singsub(&u);
X getmatch(&val,u,doub+2);
X break;
X }
X } else { /* no ${...=...} or anything, but possible modifiers. */
X if (vunset) {
X if (isset(NOUNSET)) {
X zerr("parameter not set",NULL,0);
X return;
X }
X val = strdup("");
X }
X if (colf) {
X s--;
X if (!isarr) modify(&val,&s);
X else {
X char *ss = s;
X char **ap = aval;
X while (*ap) {
X ss = s;
X modify(ap,&ss);
X }
X }
X }
X if (brs) {
X if (*s != '}' && *s != Outbrace) {
X zerr("closing brace expected",NULL,0);
X errflag = 1;
X return;
X }
X s++;
X }


X }
X if (errflag)
X return;

X if (getlen) {
X long len = 0;
X char buf[14];
X
X if (isarr) {
X char **ctr;
X for (ctr = aval; *ctr; ctr++,len++);
X } else
X len = strlen(val);
X sprintf(buf,"%ld",len);
X val = strdup(buf);
X isarr = 0;
X }
X if (isarr)
X if (!aval || !aval[0]) {
X if (isarr < 0)
X wasnularr = 1;
X val = strdup("");
X isarr = 0;
X } else if (!aval[1]) {
X val = aval[0];
X isarr = 0;
X }
X if (qt) {
X if (isarr > 0) {
X val = spacejoin(aval);
X isarr = 0;
X }
X } else if (spbreak) {
X if (isarr)
X val = spacejoin(aval);
X isarr = 1;
X aval = spacesplit(val);
X if (!aval || !aval[0]) {
X val = strdup("");
X isarr = 0;
X } else if (!aval[1]) {
X val = aval[0];
X isarr = 0;
X }
X /* if only one member, not really an array */
X if (!aval[1])
X isarr = 0;
X }
X if (isarr)
X if (plan9) {
X int dlen;
X char *y;
X
X y = ncalloc((dlen = (char *) aptr-bptr+strlen(s)+1)+strlen(aval[0]));
X setdata(n,y);
X strcpy(y,ostr);
X strcat(y,aval[0]);
X strcat(y,s);
X while (*++aval) {
X char *x = ncalloc(dlen+strlen(*aval));
X
X strcpy(x,ostr);
X strcat(x,*aval);
X strcat(x,s);
X insnode(l,n,x), incnode(n);
X }
X } else {
X char *zz;
X
X zz = ncalloc((char *) aptr-(bptr)+strlen(aval[0])+1);
X setdata(n,zz);
X strcpy(zz,ostr);
X strcat(zz,*aval++);
X while (aval[1])
X insnode(l,n,*aval++), incnode(n);
X zz = ncalloc(strlen(*aval)+strlen(s)+1);
X strcpy(zz,*aval);
X strcat(zz,s);
X insnode(l,n,zz);
X }
X else {
X bptr = ncalloc((char *) aptr-bptr+strlen(val)+strlen(s)+1);
X setdata(n,bptr);
X strcpy(bptr,ostr);
X strcat(bptr,val);
X strcat(bptr,s);
X }
X}
X
X/* arithmetic substitution */
X
Xvoid arithsubst(aptr,bptr) /**/
Xvptr *aptr;char **bptr;
X{
Xchar *s = *aptr,*t,buf[16];
Xlong v;
X
X *s = '\0';
X for (; *s != Outbrack; s++);
X *s++ = '\0';
X v = matheval((char *) *aptr+2);
X sprintf(buf,"%ld",v);
X t = ncalloc(strlen(*bptr)+strlen(buf)+strlen(s)+1);
X strcpy(t,*bptr);
X strcat(t,buf);
X strcat(t,s);
X *bptr = t;
X}
X
Xvoid modify(str,ptr) /**/
Xchar **str;char **ptr;
X{
Xchar *ptr1,*ptr2,*ptr3,del,*lptr;
Xint gbal;
X
X if (**ptr == ':')
X *str = strdup(*str);
X while (**ptr == ':')
X {
X lptr = *ptr;
X (*ptr)++;
X gbal = 0;
Xhere:
X switch(*(*ptr)++)
X {
X case 'h': remtpath(str); break;
X case 'r': remtext(str); break;
X case 'e': rembutext(str); break;
X case 't': remlpaths(str); break;
X case 'l': downcase(str); break;
X case 'u': upcase(str); break;
X case 's':


X if (hsubl)
X free(hsubl);

X if (hsubr)
X free(hsubr);

X ptr1 = *ptr;
X del = *ptr1++;
X for (ptr2 = ptr1; *ptr2 != del && *ptr2; ptr2++);
X if (!*ptr2)
X {
X zerr("bad subtitution",NULL,0);
X errflag = 1;
X return;
X }
X *ptr2++ = '\0';
X for (ptr3 = ptr2; *ptr3 != del && *ptr3; ptr3++);
X if (*ptr3)
X *ptr3++ = '\0';
X hsubl = ztrdup(ptr1);
X hsubr = ztrdup(ptr2);
X *ptr = ptr3;


X case '&':
X if (hsubl && hsubr)

X subst(str,hsubl,hsubr,gbal);
X break;
X case 'g': gbal = 1; goto here;
X default: *ptr = lptr; return;
X }
X }
X}
X
X/* get a directory stack entry */
X
Xchar *dstackent(val) /**/
Xint val;
X{
XLknode node;
X
X if ((val < 0 && !firstnode(dirstack)) || !val--)
X return pwd;
X if (val < 0)
X node = lastnode(dirstack);
X else
X for (node = firstnode(dirstack); node && val; val--,incnode(node));
X if (!node)
X {
X zerr("not enough dir stack entries.",NULL,0);
X errflag = 1;
X return NULL;
X }
X return getdata(node);
X}
X
X/* make an alias hash table node */
X
Xstruct alias *mkanode(txt,cmflag) /**/
Xchar *txt;int cmflag;
X{
Xstruct alias *ptr = (Alias) zcalloc(sizeof *ptr);
X
X ptr->text = txt;
X ptr->cmd = cmflag;
X ptr->inuse = 0;
X return ptr;
X}
SHAR_EOF
chmod 0644 zsh2.2/src/subst.c ||
echo 'restore of zsh2.2/src/subst.c failed'
Wc_c="`wc -c < 'zsh2.2/src/subst.c'`"
test 14912 -eq "$Wc_c" ||
echo 'zsh2.2/src/subst.c: original size 14912, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/table.c ==============
if test -f 'zsh2.2/src/table.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/table.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/table.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/table.c' &&
X/*
X *
X * table.c - linked lists and hash tables


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#define TABLE_C
X#include "zsh.h"
X
X/* get an empty linked list header */
X
XLklist newlist() /**/
X{
XLklist list;
X
X list = (Lklist) alloc(sizeof *list);
X list->first = 0;
X list->last = (Lknode) list;
X return list;
X}
X
X/* get an empty hash table */
X
XHashtab newhtable(size) /**/
Xint size;
X{
XHashtab ret;
X
X ret = (Hashtab) zcalloc(sizeof *ret);
X ret->hsize = size;
X ret->nodes = (Hashnode*) zcalloc(size*sizeof(Hashnode));


X return ret;
X}
X

X/* Peter Weinberger's hash function */
X
Xint hasher(s) /**/
Xchar *s;
X{
Xunsigned hash = 0,g;


X
X for (; *s; s++) {

X hash = (hash << 4) + *s;
X if (g = hash & 0xf0000000) {
X hash ^= g;
X hash ^= g >> 24;
X }
X }
X return hash;
X}
X
X/* add a node to a hash table */
X
Xvoid Addhnode(nam,dat,ht,freefunc,canfree) /**/
Xchar *nam;vptr dat;Hashtab ht;FFunc freefunc;int canfree;
X{
Xint hval = hasher(nam) % ht->hsize;
Xstruct hashnode **hp = ht->nodes+hval,*hn;
X
X for (; *hp; hp = &(*hp)->next)
X if (!strcmp((*hp)->nam,nam)) {
X if ((*hp)->canfree) free((*hp)->nam);
X hn = dat;
X hn->next = (*hp)->next;
X if (!freefunc) zerr("attempt to call NULL freefunc",NULL,0);
X else freefunc(*hp);
X *hp = hn;
X hn->nam = nam;
X hn->canfree = canfree;
X return;
X }
X hn = (Hashnode) dat;
X hn->nam = nam;
X hn->canfree = canfree;
X hn->next = ht->nodes[hval];
X ht->nodes[hval] = hn;
X if (++ht->ct == ht->hsize*4) expandhtab(ht);
X}
X
X/* add a node to command hash table */
X
Xvoid addhcmdnode(nam,pnam) /**/
Xchar *nam;char **pnam;
X{
Xint hval = hasher(nam) % cmdnamtab->hsize;
Xstruct hashnode *hp = cmdnamtab->nodes[hval],*hn;
XCmdnam cc;
X
X for (; hp; hp = hp->next) if (!strcmp(hp->nam,nam)) return;
X cc = (Cmdnam) zcalloc(sizeof *cc);
X cc->type = EXCMD;
X cc->u.nam = tricat(*pnam,"/",nam);
X cc->pcomp = pnam;
X hn = (Hashnode) cc;
X hn->nam = ztrdup(nam);
X hn->canfree = 1;
X hn->next = cmdnamtab->nodes[hval];
X cmdnamtab->nodes[hval] = hn;
X if (++cmdnamtab->ct == cmdnamtab->hsize*4) expandhtab(cmdnamtab);
X}
X
X/* expand hash tables when they get too many entries */
X
Xvoid expandhtab(ht) /**/
XHashtab ht;
X{
Xstruct hashnode **arr,**ha,*hn,*hp;
Xint osize = ht->hsize,nsize = osize*8;
X
X ht->hsize = nsize;
X arr = ht->nodes;
X ht->nodes = (Hashnode*) zcalloc(nsize*sizeof(struct hashnode *));
X for (ha = arr; osize; osize--,ha++)
X for (hn = *ha; hn; ) {
X hp = hn->next;
X Addhnode(hn->nam,(vptr)hn,ht,NULL,hn->canfree);
X hn = hp;
X }
X free(arr);
X}
X
X/* get an entry in a hash table */
X
Xvptr gethnode(nam,ht) /**/
Xchar *nam;Hashtab ht;
X{
Xint hval = hasher(nam) % ht->hsize;
Xstruct hashnode *hn = ht->nodes[hval];
X
X for (; hn; hn = hn->next) if (!strcmp(hn->nam,nam)) return (vptr)hn;


X return NULL;
X}
X

Xvoid freehtab(ht,freefunc) /**/
XHashtab ht;FFunc freefunc;
X{
Xint val;
Xstruct hashnode *hn,**hp = &ht->nodes[0],*next;
X
X for (val = ht->hsize; val; val--,hp++)
X for (hn = *hp; hn; ) {
X next = hn->next;
X if (hn->canfree) free(hn->nam);
X freefunc(hn);
X hn = next;
X }
X free(ht->nodes);
X free(ht);
X}
X
X/* remove a hash table entry and return a pointer to it */
X
Xvptr remhnode(nam,ht) /**/
Xchar *nam;Hashtab ht;
X{
Xint hval = hasher(nam) % ht->hsize;
Xstruct hashnode *hn = ht->nodes[hval],*hp;
X
X if (!hn) return NULL;
X if (!strcmp(hn->nam,nam)) {
X ht->nodes[hval] = hn->next;
X if (hn->canfree) free(hn->nam);
X ht->ct--;
X return (vptr)hn;
X }
X for (hp = hn, hn = hn->next; hn; hn = (hp = hn)->next)
X if (!strcmp(hn->nam,nam)) {
X hp->next = hn->next;
X if (hn->canfree) free(hn->nam);
X ht->ct--;
X return (vptr)hn;
X }


X return NULL;
X}
X

X/* insert a node in a linked list after 'llast' */
X
Xvoid insnode(list,llast,dat) /**/
XLklist list;Lknode llast;vptr dat;
X{
XLknode tmp;
X
X tmp = llast->next;
X llast->next = (Lknode) alloc(sizeof *tmp);
X llast->next->last = llast;
X llast->next->dat = dat;
X llast->next->next = tmp;
X if (tmp) tmp->last = llast->next;
X else list->last = llast->next;
X}
X
Xvoid addnodeinorder(x,dat) /**/
XLklist x; char *dat;
X{
XLknode y, l = NULL;
Xint val = 123;
X
X for (y = firstnode(x); y; incnode(y)) {
X if ((val = forstrcmp((char **) &y->dat, &dat)) >= 0) break;
X l = y;
X }
X if (!val) return;
X if (l == NULL) insnode(x, (Lknode) x, dat);
X else insnode(x, l, dat);
X}
X
X
X/* remove a node from a linked list */
X
Xvptr remnode(list,nd) /**/
XLklist list;Lknode nd;
X{
Xvptr dat;
X
X nd->last->next = nd->next;
X if (nd->next) nd->next->last = nd->last;
X else list->last = nd->last;
X dat = nd->dat;
X free(nd);
X return dat;
X}
X
X/* remove a node from a linked list */
X
Xvptr uremnode(list,nd) /**/
XLklist list;Lknode nd;
X{
Xvptr dat;
X
X nd->last->next = nd->next;
X if (nd->next) nd->next->last = nd->last;
X else list->last = nd->last;
X dat = nd->dat;
X return dat;
X}
X
X/* delete a character in a string */
X
Xvoid chuck(str) /**/
Xchar *str;
X{
X while (str[0] = str[1]) str++;
X}
X
X/* get top node in a linked list */
X
Xvptr getnode(list) /**/
XLklist list;
X{
Xvptr dat;
XLknode node = list->first;
X
X if (!node)
X return NULL;
X dat = node->dat;
X list->first = node->next;
X if (node->next)
X node->next->last = (Lknode) list;
X else
X list->last = (Lknode) list;
X free(node);
X return dat;
X}
X
X/* get top node in a linked list without freeing */
X
Xvptr ugetnode(list) /**/
XLklist list;
X{
Xvptr dat;
XLknode node = list->first;
X
X if (!node)
X return NULL;
X dat = node->dat;
X list->first = node->next;
X if (node->next)
X node->next->last = (Lknode) list;
X else
X list->last = (Lknode) list;
X return dat;
X}
X
Xvoid freetable(tab,freefunc) /**/
XLklist tab;FFunc freefunc;
X{
XLknode node = tab->first,next;
X
X while (node) {
X next = node->next;
X if (freefunc) freefunc(node->dat);
X free(node);
X node = next;
X }
X free(tab);
X}
X
Xchar *ztrstr(s,t) /**/


Xchar *s;char *t;
X{

Xchar *p1,*p2;


X
X for (; *s; s++) {

X for (p1 = s, p2 = t; *p2; p1++,p2++)
X if (*p1 != *p2) break;
X if (!*p2) return (char *) s;
X }


X return NULL;
X}
X

X/* insert a list in another list */
X
Xvoid inslist(l,where,x) /**/
XLklist l;Lknode where;Lklist x;
X{
XLknode nx = where->next;
X
X if (!l->first) return;
X where->next = l->first;
X l->last->next = nx;
X l->first->last = where;
X if (nx) nx->last = l->last;
X else x->last = l->last;
X}
X
Xint countnodes(x) /**/
XLklist x;
X{
XLknode y;
Xint ct = 0;
X
X for (y = firstnode(x); y; incnode(y),ct++);
X return ct;
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/table.c ||
echo 'restore of zsh2.2/src/table.c failed'
Wc_c="`wc -c < 'zsh2.2/src/table.c'`"
test 6810 -eq "$Wc_c" ||
echo 'zsh2.2/src/table.c: original size 6810, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/text.c ==============
if test -f 'zsh2.2/src/text.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/text.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/text.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/text.c' &&
X/*
X *
X * text.c - textual representations of syntax trees


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X

Xstatic char *tptr,*tbuf,*tlim;
Xstatic int tsiz,tindent,tnewlins;
X
X/* add a character to the text buffer */
X
Xvoid taddchr(c) /**/
Xint c;
X{
X *tptr++ = c;
X if (tptr == tlim) {
X if (!tbuf) { tptr--; return; }
X tbuf = realloc(tbuf,tsiz *= 2);
X tlim = tbuf+tsiz;
X tptr = tbuf+tsiz/2;
X }
X}
X
X/* add a string to the text buffer */
X
Xvoid taddstr(s) /**/
Xchar *s;
X{
Xint sl = strlen(s);
X
X while (tptr+sl >= tlim) {
X int x = tptr-tbuf;
X
X if (!tbuf) return;
X tbuf = realloc(tbuf,tsiz *= 2);
X tlim = tbuf+tsiz;
X tptr = tbuf+x;
X }
X strcpy(tptr,s);
X tptr += sl;
X}
X
X/* add an integer to the text buffer */
X
Xvoid taddint(x) /**/
Xint x;
X{
Xchar buf[10];
X
X sprintf(buf,"%d",x);
X taddstr(buf);
X}
X
X/* add a newline, or something equivalent, to the text buffer */
X
Xvoid taddnl() /**/
X{
Xint t0;
X
X if (tnewlins)
X {
X taddchr('\n');
X for (t0 = 0; t0 != tindent; t0++)
X taddchr('\t');
X }
X else
X taddstr("; ");
X}
X
X/* get a permanent textual representation of n */
X
Xchar *getpermtext(n) /**/
Xstruct node *n;
X{
X tnewlins = 1;
X tbuf = zalloc(tsiz = 32);
X tptr = tbuf;
X tlim = tbuf+tsiz;
X tindent = 1;
X gettext2(n);
X *tptr = '\0';
X untokenize(tbuf);
X return tbuf;
X}
X
X/* get a representation of n in a job text buffer */
X
Xchar *getjobtext(n) /**/
Xstruct node *n;
X{
Xstatic char jbuf[JOBTEXTSIZE];
X
X tnewlins = 0;
X tbuf = NULL;
X tptr = jbuf;
X tlim = tptr+JOBTEXTSIZE-1;
X tindent = 1;
X gettext2(n);
X *tptr = '\0';
X untokenize(jbuf);
X return jbuf;
X}
X
X#define gt2(X) gettext2((struct node *) (X))
X
X/*
X "gettext2" or "type checking and how to avoid it"
X an epic function by Paul Falstad
X*/
X
X#define _Cond(X) ((Cond) (X))
X#define _Cmd(X) ((Cmd) (X))
X#define _Pline(X) ((Pline) (X))
X#define _Sublist(X) ((Sublist) (X))
X#define _List(X) ((List) (X))
X#define _casecmd(X) ((struct casecmd *) (X))
X#define _ifcmd(X) ((struct ifcmd *) (X))
X#define _whilecmd(X) ((struct whilecmd *) (X))
X
Xvoid gettext2(n) /**/
Xstruct node *n;
X{
XCmd nn;
XCond nm;
X
X if (!n)
X return;
X switch (n->type)
X {
X case N_LIST:
X gt2(_List(n)->left);
X if (_List(n)->type == ASYNC)
X taddstr(" &");
X simplifyright(_List(n));
X if (_List(n)->right)
X {
X if (tnewlins)
X taddnl();
X else
X taddstr((_List(n)->type == ASYNC) ? " " : "; ");
X gt2(_List(n)->right);
X }
X break;
X case N_SUBLIST:
X if (_Sublist(n)->flags & PFLAG_NOT)
X taddstr("! ");
X if (_Sublist(n)->flags & PFLAG_COPROC)
X taddstr("coproc ");
X gt2(_Sublist(n)->left);
X if (_Sublist(n)->right)
X {
X taddstr((_Sublist(n)->type == ORNEXT) ? " || " : " && ");
X gt2(_Sublist(n)->right);
X }
X break;
X case N_PLINE:
X gt2(_Pline(n)->left);
X if (_Pline(n)->type == PIPE)
X {
X taddstr(" | ");
X gt2(_Pline(n)->right);
X }
X break;
X case N_CMD:
X nn = _Cmd(n);
X if (nn->flags & CFLAG_EXEC)
X taddstr("exec ");
X if (nn->flags & CFLAG_COMMAND)
X taddstr("command ");
X switch (nn->type)
X {
X case SIMPLE:
X getsimptext(nn);
X break;
X case SUBSH:
X taddstr("( ");
X tindent++;
X gt2(nn->u.list);
X tindent--;
X taddstr(" )");
X break;
X case ZCTIME:
X taddstr("time ");
X tindent++;
X gt2(nn->u.pline);
X tindent--;
X break;
X case FUNCDEF:
X taddlist(nn->args);
X taddstr(" () {");
X tindent++;
X taddnl();
X gt2(nn->u.list);
X tindent--;
X taddnl();
X taddstr("}");
X break;
X case CURSH:
X taddstr("{ ");
X tindent++;
X gt2(nn->u.list);
X tindent--;
X taddstr(" }");
X break;
X case CFOR:
X case CSELECT:
X taddstr((nn->type == CFOR) ? "for " : "select ");
X taddstr(nn->u.forcmd->name);
X if (nn->u.forcmd->inflag)
X {
X taddstr(" in ");
X taddlist(nn->args);
X }
X taddnl();
X taddstr("do");
X tindent++;
X taddnl();
X gt2(nn->u.forcmd->list);
X taddnl();
X tindent--;
X taddstr("done");
X break;
X case CIF:
X gt2(nn->u.ifcmd);
X taddstr("fi");
X break;
X case CCASE:
X taddstr("case ");
X taddlist(nn->args);
X taddstr(" in");
X tindent++;
X taddnl();
X gt2(nn->u.casecmd);
X tindent--;
X if (tnewlins)
X taddnl();
X else
X taddchr(' ');
X taddstr("esac");
X break;
X case COND:
X taddstr("[[ ");
X gt2(nn->u.cond);
X taddstr(" ]]");
X break;
X case CREPEAT:
X taddstr("repeat ");
X taddlist(nn->args);
X taddnl();
X taddstr("do");
X tindent++;
X taddnl();
X gt2(nn->u.list);
X tindent--;
X taddnl();
X taddstr("done");
X break;
X case CWHILE:
X gt2(nn->u.whilecmd);
X break;
X }
X getredirs(nn);
X break;
X case N_COND:
X nm = _Cond(n);
X switch (nm->type)
X {
X case COND_NOT:
X taddstr("! ");
X gt2(nm->left);
X break;
X case COND_AND:
X taddstr("( ");
X gt2(nm->left);
X taddstr(" && ");
X gt2(nm->right);
X taddstr(" )");
X break;
X case COND_OR:
X taddstr("( ");
X gt2(nm->left);
X taddstr(" || ");
X gt2(nm->right);
X taddstr(" )");
X break;
X default:
X {
X static char *c1[] = {
X " = "," != "," < "," > "," -nt "," -ot "," -ef "," -eq ",
X " -ne "," -lt "," -gt "," -le "," -ge "
X };
X if (nm->right)
X taddstr(nm->left);
X if (nm->type <= COND_GE)
X taddstr(c1[nm->type-COND_STREQ]);
X else
X {
X char c2[5];
X c2[0] = ' '; c2[1] = '-';
X c2[2] = nm->type;
X c2[3] = ' '; c2[4] = '\0';
X taddstr(c2);
X }
X taddstr((nm->right) ? nm->right : nm->left);
X }
X break;
X }
X break;
X case N_CASE:
X taddstr(_casecmd(n)->pat);
X taddstr(") ");
X tindent++;
X gt2(_casecmd(n)->list);
X tindent--;
X taddstr(";;");
X if (tnewlins)
X taddnl();
X else
X taddchr(' ');
X gt2(_casecmd(n)->next);
X break;
X case N_IF:
X if (_ifcmd(n)->ifl)
X {
X taddstr("if ");
X tindent++;
X gt2(_ifcmd(n)->ifl);
X tindent--;
X taddnl();
X taddstr("then");
X }
X else
X taddchr('e');
X tindent++;
X taddnl();
X gt2(_ifcmd(n)->thenl);
X tindent--;
X taddnl();
X if (_ifcmd(n)->next)
X {
X taddstr("els");
X gt2(_ifcmd(n)->next);
X }
X break;
X case N_WHILE:
X taddstr((_whilecmd(n)->cond) ? "until " : "while ");
X tindent++;
X gt2(_whilecmd(n)->cont);
X tindent--;
X taddnl();
X taddstr("do");
X tindent++;
X taddnl();
X gt2(_whilecmd(n)->loop);
X tindent--;
X taddnl();
X taddstr("done");


X break;
X }
X}
X

Xvoid getsimptext(cmd) /**/
XCmd cmd;
X{
XLknode n;
X
X for (n = firstnode(cmd->vars); n; incnode(n))
X {
X struct varasg *v = getdata(n);
X
X taddstr(v->name);
X taddchr('=');
X if ((v->type & PMTYPE) == PMFLAG_A)
X {
X taddchr('(');
X taddlist(v->arr);
X taddstr(") ");
X }
X else
X {
X taddstr(v->str);
X taddchr(' ');
X }
X }
X taddlist(cmd->args);
X}
X
Xvoid getredirs(cmd) /**/
XCmd cmd;
X{
XLknode n;
Xstatic char *fstr[] = {
X ">",">!",">>",">>!",">&",">&!",">>&",">>&!","<","<<",
X "<<-","<<<","<&",">&-","..",".."
X };
X
X taddchr(' ');
X for (n = firstnode(cmd->redir); n; incnode(n))
X {
X struct redir *f = getdata(n);
X
X switch(f->type)
X {
X case WRITE: case WRITENOW: case APP: case APPNOW: case READ:
X case HERESTR:
X if (f->fd1 != ((f->type == READ) ? 0 : 1))
X taddchr('0'+f->fd1);
X taddstr(fstr[f->type]);
X taddchr(' ');
X taddstr(f->name);
X taddchr(' ');
X break;
X case MERGE: case MERGEOUT:
X if (f->fd1 != ((f->type == MERGEOUT) ? 1 : 0))
X taddchr('0'+f->fd1);
X taddstr(fstr[f->type]);
X taddchr(' ');
X taddint(f->fd2);
X taddchr(' ');
X break;
X case CLOSE:
X taddchr(f->fd1+'0');
X taddstr(">&- ");
X break;
X case INPIPE:
X case OUTPIPE:
X if (f->fd1 != ((f->type == INPIPE) ? 0 : 1))
X taddchr('0'+f->fd1);
X taddstr((f->type == INPIPE) ? "< " : "> ");
X taddstr(f->name);
X taddchr(' ');
X break;
X }
X }
X tptr--;
X}
X
Xvoid taddlist(l) /**/
XLklist l;
X{
XLknode n;
X
X for (n = firstnode(l); n; incnode(n))
X {
X taddstr(getdata(n));
X taddchr(' ');
X }
X tptr--;
X}
SHAR_EOF
chmod 0644 zsh2.2/src/text.c ||
echo 'restore of zsh2.2/src/text.c failed'
Wc_c="`wc -c < 'zsh2.2/src/text.c'`"
test 8584 -eq "$Wc_c" ||
echo 'zsh2.2/src/text.c: original size 8584, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/utils.c ==============
if test -f 'zsh2.2/src/utils.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/utils.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/utils.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/utils.c' &&
X/*
X *
X * utils.c - miscellaneous utilities


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"
X#include <pwd.h>

X#include <errno.h>


X#ifdef __hpux
X#include <ndir.h>
X#else

X#ifndef SYSV
X#include <sys/dir.h>
X#endif
X#endif
X#include <fcntl.h>
X


X#ifdef SYSV
X#define direct dirent

X#undef TIOCGWINSZ
Xint readlink(s,t,z)
Xchar *s;char *t;int z;
X{
Xreturn -1;
X}
X#endif
X
X/* source a file */
X
Xint source(s) /**/
Xchar *s;
X{
Xint fd,cj = thisjob;
Xint oldlineno = lineno,oldshst;
XFILE *obshin = bshin;
X
X fd = SHIN;
SHAR_EOF
true || echo 'restore of zsh2.2/src/utils.c failed'
fi
echo 'End of zsh2.2 part 11'
echo 'File zsh2.2/src/utils.c is continued in part 12'
echo 12 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:06:17 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 108
Archive-name: zsh2.2/part12

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.12 (part 12 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/utils.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 12; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/utils.c'
else
echo 'x - continuing file zsh2.2/src/utils.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/utils.c' &&

X lineno = 0;
X oldshst = opts[SHINSTDIN];
X opts[SHINSTDIN] = OPT_UNSET;
X if ((SHIN = movefd(open(s,O_RDONLY))) == -1)
X {
X SHIN = fd;
X thisjob = cj;
X opts[SHINSTDIN] = oldshst;
X return 1;
X }


X bshin = fdopen(SHIN,"r");

X loop();
X fclose(bshin);
X bshin = obshin;
X opts[SHINSTDIN] = oldshst;
X SHIN = fd;
X thisjob = cj;
X errflag = 0;
X retflag = 0;
X lineno = oldlineno;


X return 0;
X}
X

X/* try to source a file in the home directory */
X
Xvoid sourcehome(s) /**/
Xchar *s;
X{
Xchar buf[MAXPATHLEN];
Xchar *h;
X
X if (!(h = getsparam("ZDOTDIR")))
X h = home;
X sprintf(buf,"%s/%s",h,s);
X (void) source(buf);
X}
X
X/* print an error */
X
Xvoid zerrnam(cmd,fmt,str,num) /**/
Xchar *cmd; char *fmt; char *str;int num;
X{
X if (cmd)
X {
X if (errflag || noerrs)
X return;
X errflag = 1;
X trashzle();
X if (isset(SHINSTDIN))
X fprintf(stderr,"%s: ",cmd);
X else
X fprintf(stderr,"%s: %s: ",argzero,cmd);
X }
X while (*fmt)
X if (*fmt == '%')
X {
X fmt++;
X switch(*fmt++)
X {
X case 's':
X while (*str)
X niceputc(*str++,stderr);


X break;
X case 'l':

X while (num--)
X niceputc(*str++,stderr);
X break;
X case 'd':
X fprintf(stderr,"%d",num);


X break;
X case '%':

X putc('%',stderr);
X break;
X case 'c':
X niceputc(num,stderr);


X break;
X case 'e':

X if (num == EINTR)
X {
X fputs("interrupt\n",stderr);


X errflag = 1;
X return;
X }

X if (num == EIO)
X fputs(sys_errlist[num],stderr);
X else
X {
X fputc(tulower(sys_errlist[num][0]),stderr);
X fputs(sys_errlist[num]+1,stderr);


X }
X break;
X }
X }

X else
X putc(*fmt++,stderr);
X if (unset(SHINSTDIN) && lineno)
X fprintf(stderr," [%ld]\n",lineno);
X else


X putc('\n',stderr);
X fflush(stderr);
X}
X

Xvoid zerr(fmt,str,num) /**/
Xchar *fmt; char *str;int num;
X{
X if (errflag || noerrs)
X return;
X errflag = 1;
X trashzle();
X fprintf(stderr,"%s: ",(isset(SHINSTDIN)) ? "zsh" : argzero);
X zerrnam(NULL,fmt,str,num);
X}
X
Xvoid niceputc(c,f) /**/
Xint c;FILE *f;
X{
X if (itok(c))
X {
X if (c >= Pound && c <= Comma)
X putc(ztokens[c-Pound],f);
X return;
X }
X c &= 0xff;
X if (isprint(c))
X putc(c,f);
X else if (c == '\n')
X {


X putc('\\',f);
X putc('n',f);

X }
X else
X {
X putc('^',f);
X putc(c|'@',f);
X }
X}
X
X/* enable ^C interrupts */
X
Xvoid intr() /**/
X{
X#ifdef SV_INTERRUPT
Xstatic struct sigvec vec = { handler,sigmask(SIGINT),SV_INTERRUPT };
X
X if (interact)
X sigvec(SIGINT,&vec,NULL);
X#else
X if (interact)
X signal(SIGINT,handler);
X#endif
X}
X
Xvoid noholdintr() /**/
X{
X intr();
X}
X
Xvoid holdintr() /**/
X{
X#ifdef SV_INTERRUPT
Xstatic struct sigvec vec = { handler,sigmask(SIGINT),0 };
X
X if (interact) sigvec(SIGINT,&vec,NULL);
X#else
X if (interact) signal(SIGINT,SIG_IGN);
X#endif
X}
X
Xchar *fgetline(buf,len,in) /**/
Xchar *buf;int len;FILE *in;
X{
X if (!fgets(buf,len,in))
X return NULL;


X buf[len] = '\0';

X buf[strlen(buf)-1] = '\0';


X return buf;
X}
X

X/* get a symlink-free pathname for s relative to PWD */
X
Xchar *findpwd(s) /**/


Xchar *s;
X{
Xchar *t;

X
X if (*s == '/')
X return xsymlink(s);
X s = tricat((pwd[1]) ? pwd : "","/",s);
X t = xsymlink(s);
X free(s);


X return t;
X}
X

Xstatic char xbuf[MAXPATHLEN];
X
X#if 0
Xchar *fixpwd(s) /**/
Xchar *s;
X{
Xstruct stat sbuf,tbuf;
Xchar *t;
X
X strcpy(xbuf,"");
X if (*s == '/')
X t = ztrdup(s);
X else
X t = tricat((pwd[1]) ? pwd : "","/",s);
X (void) xsymlinks(t+1,0);
X free(t);
X if (!*xbuf)
X strcpy(xbuf,"/");
X if (stat(xbuf,&sbuf) == 0 && stat(".",&tbuf) == 0)
X if (!(sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino))
X chdir(xbuf);
X return ztrdup(xbuf);
X}
X#endif
X
Xint ispwd(s) /**/
Xchar *s;
X{
Xstruct stat sbuf,tbuf;
X
X if (stat(s,&sbuf) == 0 && stat(".",&tbuf) == 0)
X if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino)
X return 1;


X return 0;
X}
X

X/* expand symlinks in s, and remove other weird things */
X
Xchar *xsymlink(s) /**/
Xchar *s;
X{
X if (unset(CHASELINKS))
X return ztrdup(s);


X if (*s != '/')

X return NULL;
X strcpy(xbuf,"");
X if (xsymlinks(s+1,1))
X return ztrdup(s);
X if (!*xbuf)
X return ztrdup("/");
X return ztrdup(xbuf);
X}
X
Xchar **slashsplit(s) /**/
Xchar *s;
X{
Xchar *t,**r,**q;
Xint t0;
X
X if (!*s)
X return (char **) zcalloc(sizeof(char **));
X for (t = s, t0 = 0; *t; t++)
X if (*t == '/')
X t0++;
X q = r = (char **) zalloc(sizeof(char **)*(t0+2));
X while (t = strchr(s,'/'))
X {
X *t = '\0';
X *q++ = ztrdup(s);
X *t = '/';
X while (*t == '/')
X t++;
X if (!*t)
X {
X *q = NULL;
X return r;
X }


X s = t;
X }

X *q++ = ztrdup(s);
X *q = NULL;
X return r;
X}
X
Xint islink(s) /**/
Xchar *s;
X{
X return readlink(s,NULL,0) == 0;
X}
X
X/* expands symlinks and .. or . expressions */
X/* if flag = 0, only expand .. and . expressions */
X
Xint xsymlinks(s,flag) /**/
Xchar *s;int flag;
X{
Xchar **pp,**opp;
Xchar xbuf2[MAXPATHLEN],xbuf3[MAXPATHLEN];
Xint t0;
X
X opp = pp = slashsplit(s);


X for (; *pp; pp++)

X {
X if (!strcmp(*pp,"."))
X {
X free(*pp);
X continue;
X }
X if (!strcmp(*pp,".."))
X {
X char *p;
X
X free(*pp);
X if (!strcmp(xbuf,"/"))
X continue;
X p = xbuf+strlen(xbuf);
X while (*--p != '/');
X *p = '\0';
X continue;
X }
X if (unset(CHASELINKS))
X {
X strcat(xbuf,"/");
X strcat(xbuf,*pp);
X free(*pp);
X continue;
X }
X sprintf(xbuf2,"%s/%s",xbuf,*pp);
X t0 = readlink(xbuf2,xbuf3,MAXPATHLEN);
X if (t0 == -1 || !flag)
X {
X strcat(xbuf,"/");
X strcat(xbuf,*pp);
X free(*pp);
X }
X else
X {
X xbuf3[t0] = '\0'; /* STUPID */
X if (*xbuf3 == '/')
X {
X strcpy(xbuf,"");
X if (xsymlinks(xbuf3+1,flag))


X return 1;
X }
X else

X if (xsymlinks(xbuf3,flag))
X return 1;
X free(*pp);
X }
X }
X free(opp);


X return 0;
X}
X

X/* print a directory */
X
Xvoid fprintdir(s, f) /**/
Xchar *s; FILE *f;
X{
Xint t0;
X
X t0 = finddir(s);
X if (t0 == -1)
X {
X if (!strncmp(s,home,t0 = strlen(home)) && t0 > 1)
X {
X putc('~', f);
X fputs(s+t0,f);
X }
X else
X fputs(s,f);
X }
X else
X {
X putc('~', f);
X fputs(usernames[t0],f);
X fputs(s+strlen(userdirs[t0]),f);
X }
X}
X
Xvoid printdir(s) /**/
Xchar *s;
X{
X fprintdir(s, stdout);
X}
X
Xvoid printdircr(s) /**/
Xchar *s;
X{
X fprintdir(s, stdout);
X putchar('\n');
X}
X
X/* see if a path has a named directory as its prefix */
X
Xint finddir(s) /**/
Xchar *s;
X{
Xint t0,t1,step;
X
X if (userdirsz)
X {
X step = t0 = userdirsz/2;
X for(;;)
X {
X t1 = (userdirs[t0]) ? dircmp(userdirs[t0],s) : 1;
X if (!t1)
X {
X while (t0 != userdirsz-1 && userdirs[t0+1] &&
X !dircmp(userdirs[t0+1],s))
X t0++;
X return t0;
X }
X if (!step)
X break;
X if (t1 > 0)
X t0 = t0-step+step/2;
X else
X t0 += step/2;
X step /= 2;
X }
X }
X return -1;
X}
X
X/* add a named directory */
X
Xvoid adduserdir(s,t) /**/


Xchar *s;char *t;
X{

Xint t0,t1;
X
X if (!interact || ((t0 = finddir(t)) != -1 && !strcmp(s,usernames[t0])))
X return;
X if (!strcmp(t,"/"))
X return;
X if ((t0 = finddir(t)) != -1 && !strcmp(s,usernames[t0]))
X return;
X if (userdirsz == userdirct)
X {
X userdirsz *= 2;
X userdirs = (char **) realloc((char *) userdirs,
X sizeof(char **)*userdirsz);
X usernames = (char **) realloc((char *) usernames,
X sizeof(char **)*userdirsz);
X for (t0 = userdirct; t0 != userdirsz; t0++)
X userdirs[t0] = usernames[t0] = NULL;
X }
X for (t0 = 0; t0 != userdirct; t0++)
X if (strcmp(userdirs[t0],t) > 0)
X break;
X for (t1 = userdirct-1; t1 >= t0; t1--)
X {
X userdirs[t1+1] = userdirs[t1];
X usernames[t1+1] = usernames[t1];
X }
X userdirs[t0] = ztrdup(t);
X usernames[t0] = ztrdup(s);
X userdirct++;
X}
X
Xint dircmp(s,t) /**/


Xchar *s;char *t;
X{

X for (; *s && *t; s++,t++)
X if (*s != *t)
X return *s-*t;
X if (!*s && (!*t || *t == '/'))
X return 0;
X return *s-*t;
X}
X
Xint ddifftime(t1,t2) /**/
Xtime_t t1;time_t t2;
X{
X return ((long) t2-(long) t1);
X}
X
X/* see if jobs need printing */
X
Xvoid scanjobs() /**/
X{
Xint t0;
X


X for (t0 = 1; t0 != MAXJOB; t0++)

X if (jobtab[t0].stat & STAT_CHANGED)
X printjob(jobtab+t0,0);
X}
X
X/* do pre-prompt stuff */
X
Xvoid preprompt() /**/
X{
Xint diff;
XList list;
Xstruct schedcmd *sch,*schl;
X
X if (unset(NOTIFY))
X scanjobs();


X if (errflag)
X return;

X if (list = getshfunc("precmd")) doshfuncnoval(list,NULL,0);


X if (errflag)
X return;

X if (period && (time(NULL) > lastperiod+period) &&
X (list = getshfunc("periodic"))) {
X doshfuncnoval(list,NULL,0);
X lastperiod = time(NULL);


X }
X if (errflag)
X return;

X if (watch)
X {
X diff = (int) ddifftime(lastwatch,time(NULL));
X if (diff > logcheck)
X {
X dowatch();
X lastwatch = time(NULL);


X }
X }
X if (errflag)
X return;

X diff = (int) ddifftime(lastmailcheck,time(NULL));
X if (diff > mailcheck)
X {
X if (mailpath && *mailpath)
X checkmailpath(mailpath);
X else if (mailfile)
X {
X char *x[2];
X
X x[0] = mailfile;
X x[1] = NULL;
X checkmailpath(x);
X }


X lastmailcheck = time(NULL);
X }

X for (schl = (struct schedcmd *) &schedcmds, sch = schedcmds; sch;
X sch = (schl = sch)->next)
X {
X if (sch->time < time(NULL))
X {
X execstring(sch->cmd);


X schl->next = sch->next;
X free(sch->cmd);
X free(sch);

X }
X if (errflag)
X return;
X }

X}
X
Xint arrlen(s) /**/
Xchar **s;
X{
Xint t0;
X
X for (t0 = 0; *s; s++,t0++);


X return t0;
X}
X

Xvoid checkmailpath(s) /**/
Xchar **s;
X{
Xstruct stat st;
Xchar *v,*u,c;
X
X while (*s)
X {
X for (v = *s; *v && *v != '?'; v++);
X c = *v;
X *v = '\0';
X if (c != '?')
X u = NULL;
X else
X u = v+1;
X if (stat(*s,&st) == -1)
X {
X if (errno != ENOENT)
X zerr("%e: %s",*s,errno);
X }
X else if (S_ISDIR(st.st_mode))
X {
X Lklist l;
X DIR *lock = opendir(*s);
X char buf[MAXPATHLEN*2],**arr,**ap;
X struct direct *de;
X int ct = 1;
X
X if (lock)
X {
X pushheap();
X heapalloc();
X l = newlist();
X readdir(lock); readdir(lock);


X while (de = readdir(lock))

X {
X if (errflag)
X break;
X if (u)
X sprintf(buf,"%s/%s?%s",*s,de->d_name,u);
X else
X sprintf(buf,"%s/%s",*s,de->d_name);
X addnode(l,strdup(buf));
X ct++;
X }
X closedir(lock);
X ap = arr = (char **) alloc(ct*sizeof(char *));
X while (*ap++ = ugetnode(l));
X checkmailpath(arr);
X popheap();
X }
X }
X else
X {
X if (st.st_size && st.st_atime <= st.st_mtime &&
X st.st_mtime > lastmailcheck)
X if (!u)
X {
X fprintf(stderr,"You have new mail.\n",*s);
X fflush(stderr);
X }
X else
X {
X char *z = u;
X
X while (*z)
X if (*z == '$' && z[1] == '_')
X {
X fprintf(stderr,"%s",*s);
X z += 2;
X }
X else
X fputc(*z++,stderr);
X fputc('\n',stderr);
X fflush(stderr);
X }
X if (isset(MAILWARNING) && st.st_atime > st.st_mtime &&
X st.st_atime > lastmailcheck && st.st_size)
X {
X fprintf(stderr,"The mail in %s has been read.\n",*s);
X fflush(stderr);
X }
X }
X *v = c;


X s++;
X }
X}
X

Xvoid saveoldfuncs(x,y) /**/
Xchar *x;Cmdnam y;
X{
XCmdnam cc;
X
X if (y->type == SHFUNC || y->type == DISABLED)
X {


X cc = (Cmdnam) zcalloc(sizeof *cc);

X *cc = *y;
X y->u.list = NULL;
X addhnode(ztrdup(x),cc,cmdnamtab,freecmdnam);
X }
X}
X
X/* create command hashtable */
X
Xvoid newcmdnamtab() /**/
X{
XHashtab oldcnt;
X
X oldcnt = cmdnamtab;
X permalloc();
X cmdnamtab = newhtable(101);
X addbuiltins();
X if (oldcnt) {
X listhtable(oldcnt,(HFunc) saveoldfuncs);
X freehtab(oldcnt,freecmdnam);
X }
X lastalloc();
X pathchecked = path;
X}
X
Xvoid freecmdnam(a) /**/
Xvptr a;
X{
Xstruct cmdnam *c = (struct cmdnam *) a;
X
X if (c->type == SHFUNC) {
X if (c->u.list)
X freestruct(c->u.list);
X } else if (c->type != BUILTIN && c->type != DISABLED)
X free(c->u.nam);
X free(c);
X}
X
Xvoid freecompctl(a) /**/
Xvptr a;
X{
XCompctl cc = (Compctl) a;
X
X free(cc);
X}
X
Xvoid freestr(a) /**/
Xvptr a;
X{
X free(a);
X}
X
Xvoid freeanode(a) /**/
Xvptr a;
X{
Xstruct alias *c = (struct alias *) a;
X
X free(c->text);
X free(c);
X}
X
Xvoid freepm(a) /**/
Xvptr a;
X{
Xstruct param *pm = (Param) a;
X
X free(pm);
X}
X
Xvoid restoretty() /**/
X{
X settyinfo(&shttyinfo);
X}
X
Xvoid gettyinfo(ti) /**/
Xstruct ttyinfo *ti;
X{


X if (SHTTY != -1)

X {
X#ifdef TERMIOS
X#ifdef HAS_TCCRAP
X if (tcgetattr(SHTTY,&ti->tio) == -1)
X#else
X if (ioctl(SHTTY,TCGETS,&ti->tio) == -1)
X#endif
X zerr("bad tcgets: %e",NULL,errno);
X#else
X#ifdef TERMIO
X ioctl(SHTTY,TCGETA,&ti->tio);
X#else
X ioctl(SHTTY,TIOCGETP,&ti->sgttyb);
X ioctl(SHTTY,TIOCLGET,&ti->lmodes);
X ioctl(SHTTY,TIOCGETC,&ti->tchars);
X ioctl(SHTTY,TIOCGLTC,&ti->ltchars);
X#endif
X#endif
X#ifdef TIOCGWINSZ
X if (ioctl(SHTTY,TIOCGWINSZ,&ti->winsize) == -1)
X /* zerr("bad tiocgwinsz: %e",NULL,errno)*/;
X#endif
X }
X}
X
Xvoid settyinfo(ti) /**/
Xstruct ttyinfo *ti;
X{


X if (SHTTY != -1)

X {
X#ifdef TERMIOS
X#ifdef HAS_TCCRAP
X#ifndef TCSADRAIN
X#define TCSADRAIN 1 /* XXX Princeton's include files are screwed up */
X#endif
X if (tcsetattr(SHTTY, TCSADRAIN, &ti->tio) == -1)
X#else
X if (ioctl(SHTTY,TCSETS,&ti->tio) == -1)
X#endif
X /* zerr("settyinfo: %e",NULL,errno)*/;
X#else
X#ifdef TERMIO
X ioctl(SHTTY,TCSETA,&ti->tio);
X#else
X ioctl(SHTTY,TIOCSETN,&ti->sgttyb);
X ioctl(SHTTY,TIOCLSET,&ti->lmodes);
X ioctl(SHTTY,TIOCSETC,&ti->tchars);
X ioctl(SHTTY,TIOCSLTC,&ti->ltchars);
X#endif
X#endif
X#ifdef TIOCGWINSZ
X signal(SIGWINCH,SIG_IGN);
X if (ioctl(SHTTY,TIOCSWINSZ,&ti->winsize) == -1)
X /* zerr("settyinfo: %e",NULL,errno)*/;
X signal(SIGWINCH,handler);
X#endif
X }
X}
X
X#define SANEKEY(X) \
X if (ti->X == -1 && savedttyinfo.X != -1) ti->X = savedttyinfo.X;
X
Xvoid sanetty(ti) /**/
Xstruct ttyinfo *ti;
X{
Xint t0;
X
X#ifdef TIO
X ti->tio.c_lflag |= ICANON|ECHO;
X#ifdef FLUSHO
X ti->tio.c_lflag &= ~FLUSHO;
X#endif


X for (t0 = 0; t0 !=

X#ifdef NCCS
X NCCS
X#else
X NCC
X#endif
X ; t0++)
X if (ti->tio.c_cc[t0] == VDISABLEVAL &&
X savedttyinfo.tio.c_cc[t0] != VDISABLEVAL)
X ti->tio.c_cc[t0] = savedttyinfo.tio.c_cc[t0];
X#else
X ti->sgttyb.sg_flags = (ti->sgttyb.sg_flags & ~CBREAK) | ECHO;
X ti->lmodes &= ~LFLUSHO;
X SANEKEY(tchars.t_quitc);
X SANEKEY(tchars.t_startc);
X SANEKEY(tchars.t_stopc);
X SANEKEY(ltchars.t_suspc);
X SANEKEY(ltchars.t_dsuspc);
X SANEKEY(ltchars.t_lnextc);
X SANEKEY(ltchars.t_flushc);
X#endif
X}
X
Xvoid adjustwinsize() /**/
X{
X#ifdef TIOCGWINSZ
X ioctl(SHTTY,TIOCGWINSZ,&shttyinfo.winsize);
X if (!(columns = shttyinfo.winsize.ws_col)) columns = 80;
X lines = shttyinfo.winsize.ws_row;
X setintenv("COLUMNS",columns);
X setintenv("LINES",lines);
X if (zleactive) refresh();
X#endif
X}
X
Xint zyztem(s,t) /**/


Xchar *s;char *t;
X{

X#ifdef WAITPID
Xint pid,statusp;


X
X if (!(pid = fork()))

X {
X s = tricat(s," ",t);
X execl("/bin/sh","sh","-c",s,(char *) 0);
X _exit(1);
X }
X while (waitpid(pid,&statusp,WUNTRACED) == -1 && errno == EINTR);
X if (WIFEXITED(statusp))
X return WEXITSTATUS(statusp);
X return 1;
X#else
X if (!waitfork())
X {
X s = tricat(s," ",t);
X execl("/bin/sh","sh","-c",s,(char *) 0);
X _exit(1);


X }
X return 0;
X#endif

X}
X
X#ifndef WAITPID
X
X/* fork a process and wait for it to complete without confusing
X the SIGCHLD handler */
X
Xint waitfork() /**/
X{
Xint pipes[2];
Xchar x;
X
X pipe(pipes);
X if (!fork())


X {
X close(pipes[0]);

X signal(SIGCHLD,SIG_DFL);
X if (!fork())
X return 0;
X wait(NULL);
X _exit(0);


X }
X close(pipes[1]);

X read(pipes[0],&x,1);
X close(pipes[0]);


X return 1;
X}
X

X#endif
X
X/* move a fd to a place >= 10 */
X
Xint movefd(fd) /**/
Xint fd;
X{
Xint fe;
X
X if (fd == -1)
X return fd;
X#ifdef F_DUPFD
X fe = fcntl(fd,F_DUPFD,10);
X#else
X if ((fe = dup(fd)) < 10)
X fe = movefd(fe);
X#endif
X close(fd);
X return fe;
X}
X
X/* move fd x to y */
X
Xvoid redup(x,y) /**/
Xint x;int y;
X{
X if (x != y)
X {
X dup2(x,y);
X close(x);
X }
X}
X
Xvoid settrap(t0,l) /**/
Xint t0;List l;
X{
XCmd c;
X
X if (l)
X {
X c = l->left->left->left;
X if (c->type == SIMPLE && !full(c->args) && !full(c->redir)
X && !full(c->vars) && !c->flags)
X l = NULL;
X }
X if (t0 == -1)
X return;
X if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
X || t0 == SIGPIPE))
X {
X zerr("can't trap SIG%s in interactive shells",sigs[t0-1],0);
X return;
X }
X if (!l)
X {
X sigtrapped[t0] = 2;
X if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
X {
X signal(t0,SIG_IGN);
X sigtrapped[t0] = 2;
X }
X }
X else
X {
X if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD)
X signal(t0,handler);
X sigtrapped[t0] = 1;
X permalloc();
X sigfuncs[t0] = (List) dupstruct(l);
X heapalloc();
X }
X}
X
Xvoid unsettrap(t0) /**/
Xint t0;
X{
X if (t0 == -1)
X return;
X if (jobbing && (t0 == SIGTTOU || t0 == SIGTSTP || t0 == SIGTTIN
X || t0 == SIGPIPE)) {
X return;
X }
X sigtrapped[t0] = 0;
X if (t0 == SIGINT) intr();
X else if (t0 && t0 < SIGCOUNT && t0 != SIGCHLD) signal(t0,SIG_DFL);
X if (sigfuncs[t0]) freestruct(sigfuncs[t0]);
X}
X
Xvoid dotrap(sig) /**/
Xint sig;
X{
Xint sav,savval;
X
X sav = sigtrapped[sig];
X savval = lastval;
X if (sav == 2)
X return;
X sigtrapped[sig] = 2;
X if (sigfuncs[sig]) {
X lexsave();
X doshfuncnoval(sigfuncs[sig],NULL,0);
X lexrestore();
X }
X sigtrapped[sig] = sav;
X lastval = savval;
X}
X
X/* copy len chars from t into s, and null terminate */
X
Xvoid ztrncpy(s,t,len) /**/
Xchar *s;char *t;int len;
X{
X while (len--) *s++ = *t++;


X *s = '\0';
X}

X
X/* copy t into *s and update s */
X
Xvoid strucpy(s,t) /**/
Xchar **s;char *t;
X{
Xchar *u = *s;
X
X while (*u++ = *t++);
X *s = u-1;
X}
X
Xvoid struncpy(s,t,n) /**/
Xchar **s;char *t;int n;
X{
Xchar *u = *s;
X
X while (n--)
X *u++ = *t++;
X *s = u;
X *u = '\0';
X}
X
Xvoid checkrmall(s) /**/
Xchar *s;
X{
X fflush(stdin);


X if (*s == '/')

X fprintf(stderr,"zsh: sure you want to delete all the files in %s? ",s);
X else
X fprintf(stderr,"zsh: sure you want to delete all the files in %s/%s? ",
X (pwd[1]) ? pwd : "",s);
X fflush(stderr);
X feep();
X errflag |= (getquery() != 'y');
X}
X
Xint getquery() /**/
X{
Xchar c;
Xlong val;
X
X setcbreak();
X#ifdef FIONREAD
X ioctl(SHTTY,FIONREAD,&val);
X if (val) { unsetcbreak(); write(2,"n\n",2); return 'n'; }
X#endif
X if (read(SHTTY,&c,1) == 1)
X if (c == 'y' || c == 'Y' || c == '\t') c = 'y';
X unsetcbreak();


X if (c != '\n')

X write(2,"\n",1);
X return (int) c;
X}
X
Xstatic int d;
Xstatic char *guess,*best;
X
Xvoid spscannodis(s,cn) /**/
Xchar *s;char *cn;
X{
X if (((Cmdnam) cn)->type != DISABLED)
X spscan(s,NULL);
X}
X
Xvoid spscan(s,junk) /**/
Xchar *s;char *junk;
X{
Xint nd;
X
X nd = spdist(s,guess,strlen(guess)/4+1);
X if (nd <= d) {
X best = s;
X d = nd;
X }
X}
X
X/* spellcheck a word */
X/* fix s and s2 ; if s2 is non-null, fix the history list too */
X
Xvoid spckword(s,s2,tptr,cmd,ask) /**/
Xchar **s;char **s2;char **tptr;int cmd;int ask;
X{
Xchar *t,*u;
Xchar firstchar;
Xint x;
Xint pram = 0;
X
X if (**s == '-' || **s == '%')
X return;
X if (!strcmp(*s,"in"))
X return;
X if (!(*s)[0] || !(*s)[1]) return;
X if (gethnode(*s,cmdnamtab) || gethnode(*s,aliastab)) return;
X t = *s;
X if (*t == Tilde || *t == Equals || *t == String) t++;
X for (; *t; t++) if (itok(*t)) return;
X best = NULL;
X for (t = *s; *t; t++) if (*t == '/') break;
X if (**s == String) {
X if (*t) return;
X pram = 1;
X guess = *s+1;
X d = 100;
X listhtable(paramtab,spscan);
X } else {
X if ((u = spname(guess = *s)) != *s)
X best = u;
X if (!*t && !cmd) {
X if (access(*s,F_OK) == 0) return;
X if (hashcmd(*s,pathchecked)) return;
X guess = *s;
X d = 100;
X listhtable(aliastab,spscan);
X listhtable(cmdnamtab,spscan);
X }
X }
X if (errflag) return;
X if (best && strlen(best) > 1 && strcmp(best,guess)) {
X if (ask) {
X char *pp;
X int junk;
X
X rstring = best; Rstring = guess;
X firstchar = *guess;
X if (*guess == Tilde) *guess = '~';
X else if (*guess == String) *guess = '$';
X else if (*guess == Equals) *guess = '=';
X pp = putprompt(sprompt,&junk);
X *guess = firstchar;
X fprintf(stderr,"%s",pp);
X fflush(stderr);
X feep();
X x = getquery();
X } else
X x = 'y';
X if (x == 'y') {
X if (!pram) {
X *s = strdup(best);
X } else {
X *s = alloc(strlen(best)+2);
X strcpy(*s+1,best);
X **s = String;
X }
X if (s2) {
X if (*tptr && !strcmp(hlastw,*s2) && hlastw < hptr) {
X char *z;
X hptr = hlastw;
X if (pram) hwaddc('$');
X for (z = best; *z; z++) hwaddc(*z);
X hwaddc(HISTSPACE);
X *tptr = hptr-1;
X **tptr = '\0';
X }
X *s2 = strdup(best);
X }
X } else if (x == 'a') {
X histdone |= HISTFLAG_NOEXEC;
X } else if (x == 'e') {
X histdone |= HISTFLAG_NOEXEC|HISTFLAG_RECALL;
X }
X }
X}
X
Xint ztrftime(buf,bufsize,fmt,tm) /**/
Xchar *buf;int bufsize;char *fmt;struct tm *tm;
X{
Xstatic char *astr[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
Xstatic char *estr[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul",
X "Aug","Sep","Oct","Nov","Dec"};
Xstatic char *lstr[] = {"12"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9",
X "10","11"};
Xchar tmp[3];
X#ifdef HAS_STRFTIME
Xchar *origbuf = buf;
X#endif
X
X tmp[0] = '%'; tmp[2] = '\0';
X while (*fmt)
X if (*fmt == '%')
X {
X fmt++;
X switch(*fmt++)
X {
X case 'a':
X strucpy(&buf,astr[tm->tm_wday]);
X break;
X case 'b':
X strucpy(&buf,estr[tm->tm_mon]);
X break;
X case 'd':
X *buf++ = '0'+tm->tm_mday/10;
X *buf++ = '0'+tm->tm_mday%10;


X break;
X case 'e':

X if (tm->tm_mday > 9)
X *buf++ = '0'+tm->tm_mday/10;
X *buf++ = '0'+tm->tm_mday%10;
X break;
X case 'k':
X if (tm->tm_hour > 9)
X *buf++ = '0'+tm->tm_hour/10;
X *buf++ = '0'+tm->tm_hour%10;


X break;
X case 'l':

X strucpy(&buf,lstr[tm->tm_hour%12]);
X break;
X case 'm':
X *buf++ = '0'+(tm->tm_mon+1)/10;
X *buf++ = '0'+(tm->tm_mon+1)%10;
X break;
X case 'M':
X *buf++ = '0'+tm->tm_min/10;
X *buf++ = '0'+tm->tm_min%10;
X break;
X case 'p':
X *buf++ = (tm->tm_hour > 11) ? 'p' : 'a';
X *buf++ = 'm';
X break;
X case 'S':
X *buf++ = '0'+tm->tm_sec/10;
X *buf++ = '0'+tm->tm_sec%10;
X break;
X case 'y':
X *buf++ = '0'+tm->tm_year/10;
X *buf++ = '0'+tm->tm_year%10;
X break;
X default:
X#ifdef HAS_STRFTIME
X *buf = '\0';
X tmp[1] = fmt[-1];
X strftime(buf,bufsize-strlen(origbuf),tmp,tm);
X buf += strlen(buf);
X#else
X *buf++ = '%';
X *buf++ = fmt[-1];
X#endif
X break;
X }
X }
X else
X *buf++ = *fmt++;
X *buf = '\0';


X return 0;
X}
X

Xchar *join(arr,delim) /**/
Xchar **arr;int delim;
X{
Xint len = 0;
Xchar **s,*ret,*ptr;
Xstatic char *lastmem = NULL;
X
X for (s = arr; *s; s++)
X len += strlen(*s)+1;
X if (!len) return "";
X if (lastmem) free(lastmem);
X lastmem = ptr = ret = zalloc(len);
X for (s = arr; *s; s++) {
X strucpy(&ptr,*s);
X *ptr++ = delim;
X }


X ptr[-1] = '\0';

X return ret;
X}
X

Xchar *spacejoin(s) /**/
Xchar **s;
X{
X return join(s,*ifs);
X}
X
Xchar *colonjoin(s) /**/
Xchar **s;
X{
X return join(s,':');
X}
X
Xchar **colonsplit(s) /**/
Xchar *s;
X{
Xint ct;
Xchar *t,**ret,**ptr;
Xchar **lastmem = NULL;
X
X for (t = s, ct = 0; *t; t++) if (*t == ':') ct++;
X if (lastmem) freearray(lastmem);
X lastmem = ptr = ret = (char **) zalloc(sizeof(char **)*(ct+2));
X t = s;
X do {
X for (s = t; *t && *t != ':'; t++);
X *ptr = zalloc((t-s)+1);
X ztrncpy(*ptr++,s,t-s);
X }
X while (*t++);
X *ptr = NULL;


X return ret;
X}
X

Xchar **spacesplit(s) /**/
Xchar *s;
X{
Xint ct;
Xchar *t,**ret,**ptr;
X
X for (t = s, ct = 0; *t; t++)
X if (isep(*t)) ct++;
X ptr = ret = (char **) zalloc(sizeof(char **)*(ct+2));
X t = s;
X do {
X for (s = t; *t && !isep(*t); t++);
X *ptr = zalloc((t-s)+1);
X ztrncpy(*ptr++,s,t-s);
X } while (*t++);
X *ptr = NULL;


X return ret;
X}
X

XList getshfunc(nam) /**/
Xchar *nam;
X{
XCmdnam x = (Cmdnam) gethnode(nam,cmdnamtab);
X
X return (x && x->type == SHFUNC) ? x->u.list : NULL;
X}
X
X/* allocate a tree element */
X
Xvptr allocnode(type) /**/
Xint type;
X{
Xint t0;
Xstruct node *n = (struct node *) alloc(sizeof *n);
Xstatic int typetab[N_COUNT][4] = {
X NT_NODE,NT_NODE,0,0,
X NT_NODE,NT_NODE,0,0,
X NT_NODE,NT_NODE,0,0,
X NT_STR|NT_LIST,NT_NODE,NT_NODE|NT_LIST,NT_NODE|NT_LIST,
X NT_STR,0,0,0,
X NT_NODE,NT_NODE,0,0,
X NT_STR,NT_NODE,0,0,
X NT_NODE,NT_STR,NT_NODE,0,
X NT_NODE,NT_NODE,NT_NODE,0,
X NT_NODE,NT_NODE,0,0,
X NT_STR,NT_STR,NT_STR|NT_LIST,0
X };
X
X n->type = type;
X for (t0 = 0; t0 != 4; t0++)
X n->types[t0] = typetab[type][t0];
X return (vptr) n;
X}
X
X/* duplicate a syntax tree */
X
Xvptr dupstruct(a) /**/
Xvptr a;
X{
Xstruct node *n = a,*m;
Xint t0;
X
X if (!a) return NULL;
X m = alloc(sizeof *m);
X *m = *n;
X for (t0 = 0; t0 != 4; t0++)
X if (m->ptrs[t0])
X switch(m->types[t0])
X {
X case NT_NODE: m->ptrs[t0] = dupstruct(m->ptrs[t0]); break;
X case NT_STR: m->ptrs[t0] =
X (useheap) ? strdup(m->ptrs[t0]) : ztrdup(m->ptrs[t0]); break;
X case NT_LIST|NT_NODE:
X m->ptrs[t0] = duplist(m->ptrs[t0],dupstruct); break;
X case NT_LIST|NT_STR:
X m->ptrs[t0] = duplist(m->ptrs[t0],(VFunc)
X ((useheap) ? strdup : ztrdup));
X break;
X }
X return (vptr) m;
X}
X
X/* free a syntax tree */
X
Xvoid freestruct(a) /**/
Xvptr a;
X{
Xstruct node *n = (struct node *) a;
Xint t0;
X
X for (t0 = 0; t0 != 4; t0++)
X if (n->ptrs[t0])
X switch(n->types[t0])
X {
X case NT_NODE: freestruct(n->ptrs[t0]); break;
X case NT_STR: free(n->ptrs[t0]); break;
X case NT_LIST|NT_STR: freetable(n->ptrs[t0],freestr); break;
X case NT_LIST|NT_NODE: freetable(n->ptrs[t0],freestruct); break;
X }
X free(n);
X}
X
XLklist duplist(l,func) /**/
XLklist l;VFunc func;
X{
XLklist ret;
XLknode node;
X
X ret = newlist();
X for (node = firstnode(l); node; incnode(node))
X addnode(ret,func(getdata(node)));


X return ret;
X}
X

Xchar **mkarray(s) /**/
Xchar *s;
X{
Xchar **t = (char **) zalloc((s) ? (2*sizeof s) : (sizeof s));
X
X if (*t = s) t[1] = NULL;


X return t;
X}
X

Xvoid feep() /**/
X{
X if (unset(NOBEEP))
X write(2,"\07",1);
X}
X
Xvoid freearray(s) /**/
Xchar **s;
X{
Xchar **t = s;
X
X while (*s)
X free(*s++);
X free(t);
X}
X
Xint equalsplit(s,t) /**/


Xchar *s;char **t;
X{

X for (; *s && *s != '='; s++);
X if (*s == '=')
X {
X *s++ = '\0';
X *t = s;


X return 1;
X }
X return 0;
X}
X

X/* see if the right side of a list is trivial */
X
Xvoid simplifyright(l) /**/
XList l;
X{
XCmd c;
X
X if (!l->right)
X return;
X if (l->right->right || l->right->left->right ||
X l->right->left->left->right)
X return;
X c = l->left->left->left;
X if (c->type != SIMPLE || full(c->args) || full(c->redir)
X || full(c->vars))
X return;
X l->right = NULL;
X return;
X}
X
X/* initialize the ztypes table */
X
Xvoid inittyptab() /**/
X{
Xint t0;
Xchar *s;
X
X for (t0 = 0; t0 != 256; t0++)
X typtab[t0] = 0;
X for (t0 = 0; t0 != 32; t0++)
X typtab[t0] = typtab[t0+128] = ICNTRL;
X typtab[127] = ICNTRL;
X for (t0 = '0'; t0 <= '9'; t0++)
X typtab[t0] = IDIGIT|IALNUM|IWORD|IIDENT|IUSER;
X for (t0 = 'a'; t0 <= 'z'; t0++)
X typtab[t0] = typtab[t0-'a'+'A'] = IALPHA|IALNUM|IIDENT|IUSER|IWORD;
X for (t0 = 0240; t0 != 0400; t0++)
X typtab[t0] = IALPHA|IALNUM|IIDENT|IUSER|IWORD;
X typtab['_'] = IIDENT|IUSER;
X typtab['-'] = IUSER;
X typtab[' '] |= IBLANK|INBLANK;
X typtab['\t'] |= IBLANK|INBLANK;
X typtab['\n'] |= INBLANK;
X for (t0 = (int) (unsigned char) ALPOP; t0 <= (int) (unsigned char) Nularg;
X t0++)
X typtab[t0] |= ITOK;
X for (s = ifs; *s; s++)
X typtab[(int) (unsigned char) *s] |= ISEP;
X for (s = wordchars; *s; s++)
X typtab[(int) (unsigned char) *s] |= IWORD;
X for (s = SPECCHARS; *s; s++)
X typtab[(int) (unsigned char) *s] |= ISPECIAL;
X}
X
Xchar **arrdup(s) /**/
Xchar **s;
X{
Xchar **x,**y;
X
X y = x = (char **) ncalloc(sizeof(char *)*(arrlen(s)+1));
X while (*x++ = strdup(*s++));
X return y;
X}
X
X/* next few functions stolen (with changes) from Kernighan & Pike */
X/* "The UNIX Programming Environment" (w/o permission) */
X
Xchar *spname (oldname) /**/
Xchar *oldname;
X{
X char *p,guess[MAXPATHLEN+1],best[MAXPATHLEN+1];
X static char newname[MAXPATHLEN+1];
X char *new = newname, *old;
X
X if (itok(*oldname)) {
X singsub(&oldname);
X if (!oldname) return NULL;
X }
X if (access(oldname,F_OK) == 0) return NULL;
X old = oldname;
X for (;;) {
X while (*old == '/') *new++ = *old++;
X *new = '\0';
X if (*old == '\0') return newname;
X p = guess;
X for (; *old != '/' && *old != '\0'; old++)
X if (p < guess+MAXPATHLEN) *p++ = *old;
X *p = '\0';
X if (mindist(newname,guess,best) >= 3) return NULL;
X for (p = best; *new = *p++; ) new++;
X }
X}
X
Xint mindist(dir,guess,best) /**/
Xchar *dir;char *guess;char *best;
X{
X int d,nd;
X DIR *dd;
X struct direct *de;
X char buf[MAXPATHLEN];
X
X if (dir[0] == '\0')
X dir = ".";
X d = 100;
X sprintf(buf,"%s/%s",dir,guess);
X if (access(buf,F_OK) == 0) { strcpy(best,guess); return 0; }
X if (!(dd = opendir(dir))) return d;
X while (de = readdir(dd)) {
X nd = spdist(de->d_name,guess,strlen(guess)/4+1);
X if (nd <= d) {
X strcpy(best,de->d_name);
X d = nd;
X if (d == 0) break;
X }
X }
X closedir(dd);
X return d;
X}
X
Xint spdist(s,t,thresh) /**/
Xchar *s;char *t;int thresh;
X{
Xchar *p,*q;
Xchar *keymap =
X"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
X\t1234567890-=\t\
X\tqwertyuiop[]\t\
X\tasdfghjkl;'\n\t\
X\tzxcvbnm,./\t\t\t\
X\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
X\t!@#$%^&*()_+\t\
X\tQWERTYUIOP{}\t\
X\tASDFGHJKL:\"\n\t\
X\tZXCVBNM<>?\n\n\t\
X\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
X
X if (!strcmp(s,t))
X return 0;
X /* any number of upper/lower mistakes allowed (dist = 1) */
X for (p = s, q = t; *p && tulower(*p) == tulower(*q); p++,q++);
X if (!*p && !*q)
X return 1;
X if (!thresh)
X return 200;
X for (p = s, q = t; *p && *q; p++,q++)
X if (*p == *q) continue; /* don't consider "aa" transposed, ash */
X else if (p[1] == q[0] && q[1] == p[0]) /* transpositions */
X return spdist(p+2,q+2,thresh-1)+1;
X else if (p[1] == q[0]) /* missing letter */
X return spdist(p+1,q+0,thresh-1)+2;
X else if (p[0] == q[1]) /* missing letter */
X return spdist(p+0,q+1,thresh-1)+2;
X else if (*p != *q)
X break;
X if ((!*p && strlen(q) == 1) || (!*q && strlen(p) == 1))
X return 2;
X for (p = s, q = t; *p && *q; p++,q++)
X if (p[0] != q[0] && p[1] == q[1])
X {
X int t0;
X char *z;
X
X /* mistyped letter */
X
X if (!(z = strchr(keymap,p[0])) || *z == '\n' || *z == '\t')
X return spdist(p+1,q+1,thresh-1)+1;
X t0 = z-keymap;
X if (*q == keymap[t0-15] || *q == keymap[t0-14] ||
X *q == keymap[t0-13] ||
X *q == keymap[t0-1] || *q == keymap[t0+1] ||
X *q == keymap[t0+13] || *q == keymap[t0+14] ||
X *q == keymap[t0+15])
X return spdist(p+1,q+1,thresh-1)+2;
X return 200;
X }
X else if (*p != *q)
X break;
X return 200;
X}
X
Xchar *zgetenv(s) /**/
Xchar *s;
X{
Xchar **av,*p,*q;
X
X for (av = environ; *av; av++)
X {
X for (p = *av, q = s; *p && *p != '=' && *q && *p == *q; p++,q++);
X if (*p == '=' && !*q)
X return p+1;


X }
X return NULL;
X}
X

Xint tulower(c) /**/
Xint c;
X{
X c &= 0xff;
X return (isupper(c) ? tolower(c) : c);
X}
X
Xint tuupper(c) /**/
Xint c;
X{
X c &= 0xff;
X return (islower(c) ? toupper(c) : c);
X}
X
X#ifdef SYSV
X#include <sys/utsname.h>
X
Xint gethostname(nameptr, maxlength)
Xchar *nameptr;
Xint maxlength;
X{
Xstruct utsname *name;
Xint result;
X
X result = uname(name);
X if (result >= 0) {
X strcpy(nameptr,name->sysname);
X return 0;
X } else return -1;
X}
X#endif
X
X/* set cbreak mode, or the equivalent */
X
Xvoid setcbreak() /**/
X{
Xstruct ttyinfo ti;
X
X ti = shttyinfo;
X#ifdef TIO
X ti.tio.c_lflag &= ~ICANON;
X ti.tio.c_cc[VMIN] = 1;
X ti.tio.c_cc[VTIME] = 0;
X#else
X ti.sgttyb.sg_flags |= CBREAK;
X#endif
X settyinfo(&ti);
X}
X
Xint getlineleng() /**/
X{
Xint z;
X
X#ifdef TIOCSWINSZ
X z = shttyinfo.winsize.ws_col;
X return (z) ? z : 80;
X#else
X return 80;
X#endif
X}
X
Xvoid unsetcbreak() /**/
X{
X settyinfo(&shttyinfo);
X}
X
X/* give the tty to some process */
X
Xvoid attachtty(pgrp) /**/
Xlong pgrp;
X{
Xstatic int ep = 0;
X
X if (jobbing) {
X#ifdef HAS_TCSETPGRP
X if (SHTTY != -1 && tcsetpgrp(SHTTY,pgrp) == -1 && !ep)
X#else
X int arg = pgrp;
X if (SHTTY != -1 && ioctl(SHTTY,TIOCSPGRP,&arg) == -1 && !ep)
X#endif
X {
X zerr("can't set tty pgrp: %e",NULL,errno);
X fflush(stderr);


X opts[MONITOR] = OPT_UNSET;

X ep =1;


X errflag = 0;
X }

X }
X}
X
X/* get the tty pgrp */
X
Xlong gettygrp() /**/
X{
Xint arg = -1;
X
X if (SHTTY == -1) return -1;
X#ifdef HAS_TCSETPGRP
X arg = tcgetpgrp(SHTTY);
X#else
X ioctl(SHTTY,TIOCGPGRP,&arg);
X#endif
X return arg;
X}
SHAR_EOF
echo 'File zsh2.2/src/utils.c is complete' &&
chmod 0644 zsh2.2/src/utils.c ||


echo 'restore of zsh2.2/src/utils.c failed'

Wc_c="`wc -c < 'zsh2.2/src/utils.c'`"
test 32116 -eq "$Wc_c" ||
echo 'zsh2.2/src/utils.c: original size 32116, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/watch.c ==============
if test -f 'zsh2.2/src/watch.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/watch.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/watch.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/watch.c' &&
X/*
X *
X * watch.c - login/logout watching


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#include "zsh.h"

X#include <utmp.h>
X
Xstatic int wtabsz;
Xstruct utmp *wtab;
X
X/* get the time of login/logout for WATCH */
X
Xtime_t getlogtime(u,inout) /**/
Xstruct utmp *u;int inout;
X{
XFILE *in;
Xstruct utmp uu;
Xint first = 1;
Xint srchlimit = 50; /* max number of wtmp records to search */
X
X if (inout)
X return u->ut_time;
X if (!(in = fopen(WTMP_FILE,"r")))
X return time(NULL);
X fseek(in,0,2);
X do
X {
X if (fseek(in,((first) ? -1 : -2)*sizeof(struct utmp),1))
X {
X fclose(in);
X return time(NULL);


X }
X first = 0;

X if (!fread(&uu,sizeof(struct utmp),1,in))
X {
X fclose(in);
X return time(NULL);
X }
X if (uu.ut_time < lastwatch || !srchlimit--)
X {
X fclose(in);
X return time(NULL);
X }
X }
X while (memcmp(&uu,u,sizeof(struct utmp)));
X do
X if (!fread(&uu,sizeof(struct utmp),1,in))
X {
X fclose(in);
X return time(NULL);
X }
X while (strncmp(uu.ut_line,u->ut_line,8));
X fclose(in);
X return uu.ut_time;
X}
X
X/* print a login/logout event */
X
Xvoid watchlog2(inout,u,fmt) /**/
Xint inout;struct utmp *u;char *fmt;
X{
Xchar *p,buf[40],*bf;
Xint i;
Xtime_t timet;
Xstruct tm *tm = NULL;
X
X while (*fmt)
X if (*fmt != '%')
X putchar(*fmt++);
X else
X {
X fmt++;
X switch(*fmt++)
X {
X case 'n':
X printf("%.*s",8,u->ut_name);
X break;
X case 'a':
X printf("%s",(!inout) ? "logged off" : "logged on");
X break;
X case 'l':
X if (u->ut_line[0] == 't')
X printf("%.*s",5,u->ut_line+3);
X else
X printf("%.*s",8,u->ut_line);
X break;
X#ifdef UTMP_HOST
X case 'm':
X for (p = u->ut_host,i = 16; i && *p;i--,p++)
X {
X if (*p == '.' && !idigit(p[1]))
X break;
X putchar(*p);
X }
X break;
X case 'M':
X printf("%.*s",16,u->ut_host);
X break;
X#endif
X case 't':
X case '@':
X timet = getlogtime(u,inout);
X tm = localtime(&timet);
X ztrftime(buf,40,"%l:%M%p",tm);
X printf("%s",(*buf == ' ') ? buf+1 : buf);
X break;
X case 'T':
X timet = getlogtime(u,inout);
X tm = localtime(&timet);
X ztrftime(buf,40,"%k:%M",tm);
X printf("%s",buf);
X break;
X case 'w':
X timet = getlogtime(u,inout);
X tm = localtime(&timet);
X ztrftime(buf,40,"%a %e",tm);
X printf("%s",buf);


X break;
X case 'W':

X timet = getlogtime(u,inout);
X tm = localtime(&timet);
X ztrftime(buf,40,"%m/%d/%y",tm);
X printf("%s",buf);
X break;
X case 'D':
X timet = getlogtime(u,inout);
X tm = localtime(&timet);
X ztrftime(buf,40,"%y-%m-%d",tm);
X printf("%s",buf);


X break;
X case '%':

X putchar('%');
X break;
X case 'S':
X bf = buf;
X if (tgetstr("so",&bf))
X fputs(buf,stdout);
X break;
X case 's':
X bf = buf;
X if (tgetstr("se",&bf))
X fputs(buf,stdout);
X break;
X case 'B':
X bf = buf;
X if (tgetstr("md",&bf))
X fputs(buf,stdout);
X break;
X case 'b':
X bf = buf;
X if (tgetstr("me",&bf))
X fputs(buf,stdout);
X break;
X case 'U':
X bf = buf;
X if (tgetstr("us",&bf))
X fputs(buf,stdout);


X break;
X case 'u':

X bf = buf;
X if (tgetstr("ue",&bf))
X fputs(buf,stdout);
X break;
X default:
X putchar('%');
X putchar(fmt[-1]);
X break;
X }
X }


X putchar('\n');
X}
X

X/* check the List for login/logouts */
X
Xvoid watchlog(inout,u,w,fmt) /**/
Xint inout;struct utmp *u;char **w;char *fmt;
X{
Xchar *v,*vv,sav;
Xint bad;
X
X if (*w && !strcmp(*w,"all"))
X {
X watchlog2(inout,u,fmt);
X return;
X }
X for (; *w; w++)
X {
X bad = 0;
X v = *w;
X if (*v != '@' && *v != '%')
X {
X for (vv = v; *vv && *vv != '@' && *vv != '%'; vv++);
X sav = *vv;
X *vv = '\0';
X if (strncmp(u->ut_name,v,8))
X bad = 1;
X *vv = sav;
X v = vv;


X }
X for (;;)

X if (*v == '%')
X {
X for (vv = ++v; *vv && *vv != '@'; vv++);
X sav = *vv;
X *vv = '\0';
X if (strncmp(u->ut_line,v,8))
X bad = 1;
X *vv = sav;
X v = vv;
X }
X#ifdef UTMP_HOST
X else if (*v == '@')
X {
X for (vv = ++v; *vv && *vv != '%'; vv++);
X sav = *vv;
X *vv = '\0';
X if (strncmp(u->ut_host,v,strlen(v)))
X bad = 1;
X *vv = sav;
X v = vv;
X }
X#endif
X else
X break;
X if (!bad)
X {
X watchlog2(inout,u,fmt);


X return;
X }
X }
X}

X
X/* compare 2 utmp entries */
X
Xint ucmp(u,v) /**/
Xstruct utmp *u;struct utmp *v;
X{
X if (u->ut_time == v->ut_time)
X return strncmp(u->ut_line,v->ut_line,8);
X return u->ut_time - v->ut_time;
X}
X
X/* initialize the user List */
X
Xvoid readwtab() /**/
X{
Xstruct utmp *uptr;
Xint wtabmax = 32;
XFILE *in;
X
X wtabsz = 0;
X if (!(in = fopen(UTMP_FILE,"r"))) return;
X uptr = wtab = (struct utmp *) zalloc(wtabmax*sizeof(struct utmp));
X while (fread(uptr,sizeof(struct utmp),1,in))
X#ifdef USER_PROCESS
X if (uptr->ut_type == USER_PROCESS)
X#else
X if (uptr->ut_name[0])
X#endif
X {
X uptr++;
X if (++wtabsz == wtabmax)
X uptr = (wtab = (struct utmp *) realloc((vptr) wtab,(wtabmax*=2)*
X sizeof(struct utmp)))+wtabsz;
X }
X fclose(in);
X if (wtabsz)
X qsort(wtab,wtabsz,sizeof(struct utmp),ucmp);
X}
X
X/* check for login/logout events; executed before each prompt
X if WATCH is set */
X
Xvoid dowatch() /**/
X{
Xchar **s = watch;
Xchar *fmt = (watchfmt) ? watchfmt : DEFWATCHFMT;
XFILE *in;
Xint utabsz = 0,utabmax = wtabsz+4,uct,wct;
Xstruct utmp *utab,*uptr,*wptr;
X
X holdintr();
X if (!fmt)
X fmt = "%n has %a %l from %m.";
X if (!wtab) {
X readwtab();
X noholdintr();
X return;
X }
X uptr = utab = (struct utmp *) zalloc(utabmax*sizeof(struct utmp));
X if (!(in = fopen(UTMP_FILE,"r"))) {
X free(utab);
X return;
X }
X while (fread(uptr,sizeof *uptr,1,in))
X#ifdef USER_PROCESS
X if (uptr->ut_type == USER_PROCESS)
X#else
X if (uptr->ut_name[0])
X#endif
X {
X uptr++;
X if (++utabsz == utabmax)
X uptr = (utab = (struct utmp *) realloc((vptr) utab,(utabmax*=2)*
X sizeof(struct utmp)))+utabsz;
X }
X fclose(in);
X noholdintr();
X if (errflag) {
X free(utab);
X return;
X }
X if (utabsz)
X qsort(utab,utabsz,sizeof(struct utmp),ucmp);
X
X wct = wtabsz; uct = utabsz;
X uptr = utab; wptr = wtab;
X if (errflag) {
X free(utab);
X return;
X }
X while ((uct || wct) && !errflag)
X if (!uct || (wct && ucmp(uptr,wptr) > 0))
X wct--,watchlog(0,wptr++,s,fmt);
X else if (!wct || (uct && ucmp(uptr,wptr) < 0))
X uct--,watchlog(1,uptr++,s,fmt);
X else
X uptr++,wptr++,wct--,uct--;
X free(wtab);
X wtab = utab;
X wtabsz = utabsz;
X fflush(stdout);
X}
X
Xint bin_log(nam,argv,ops,func) /**/
Xchar *nam;char **argv;char *ops;int func;
X{
X if (!watch)
X return 1;
X if (wtab)
X free(wtab);
X wtab = (struct utmp *) zalloc(1);
X wtabsz = 0;
X dowatch();


X return 0;
X}
X

SHAR_EOF
chmod 0644 zsh2.2/src/watch.c ||
echo 'restore of zsh2.2/src/watch.c failed'
Wc_c="`wc -c < 'zsh2.2/src/watch.c'`"
test 7149 -eq "$Wc_c" ||
echo 'zsh2.2/src/watch.c: original size 7149, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle.h ==============
if test -f 'zsh2.2/src/zle.h' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle.h (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle.h' &&
X/*
X *
X * zle.h - header file for line editor


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#ifdef ZLEGLOBALS
X#define ZLEXTERN
X#else
X#define ZLEXTERN extern
X#endif
X
X#ifdef ZLE
X
X/* cursor position */
XZLEXTERN int cs;
X
X/* line length */
XZLEXTERN int ll;
X
X/* size of line buffer */
XZLEXTERN int linesz;
X
X/* location of mark */
XZLEXTERN int mark;
X
X/* last character pressed */
XZLEXTERN int c;
X
X/* the z_ binding id for this key */
XZLEXTERN int bindk;
X
X/* command argument */
XZLEXTERN int mult;
X
X/* insert mode/overwrite mode flag */
XZLEXTERN int insmode;
X
X/* cost of last update */
XZLEXTERN int cost;
X
X/* flags associated with last command */
XZLEXTERN int lastcmd;
X
X/* column position before last LINEMOVE movement */
XZLEXTERN int lastcol;
X
X/* != 0 if we're getting a vi range */
XZLEXTERN int virangeflag;
X
X/* kludge to get cw and dw to work right */
XZLEXTERN int wordflag;
X
X#endif
X
X/* last named command done */
XZLEXTERN int lastnamed;
X
X/* != 0 if we're done editing */
XZLEXTERN int done;
X
X/* length of prompt on screen */
XZLEXTERN int pptlen;
X
X/* current history line number */
XZLEXTERN int histline;
X
XZLEXTERN int eofsent;
X
X/* != 0 if we need to call resetvideo() */
XZLEXTERN int resetneeded;
X
X/* != 0 if the line editor is active */
XZLEXTERN int zleactive;
X
X/* the line buffer */
XZLEXTERN unsigned char *line;
X
X/* the cut buffer */
XZLEXTERN char *cutbuf;
X
X/* prompt and rprompt */
XZLEXTERN char *pmpt, *pmpt2;
X
X/* the last line in the history (the current one) */
XZLEXTERN char *curhistline;
X
X/* the status line */
XZLEXTERN char *statusline;
X
X/* 1 if a complete added a slash at the end of a directory name */
XZLEXTERN int addedslash;
X
X/*
X the current history line and cursor position for the top line
X on the buffer stack
X*/
X
XZLEXTERN int stackhist,stackcs;
X
X/* != 0 if we are in the middle of a menu completion */
XZLEXTERN int menucmp;
X
X/* != 0 if we are making undo records */
XZLEXTERN int undoing;
X
X/* last vi change buffer */
XZLEXTERN int vichgbufsz,vichgbufptr,vichgflag;
XZLEXTERN char *vichgbuf;
X
XZLEXTERN int viinsbegin;
X
Xtypedef void bindfunc DCLPROTO((void));
Xtypedef bindfunc *F;
X
Xstruct key {


X struct hashnode *next; int canfree; char *nam; /* hash data */

X int func; /* function code for this key */
X char *str; /* string corresponding to this key,
X if func = z_sequenceleadin */
X int len; /* length of string */
X };
Xstruct zlecmd {
X char *name; /* name of function */
X F func; /* handler function */
X int flags;
X };
X
X/* undo event */
X
Xstruct undoent {
X int pref; /* number of initial chars unchanged */
X int suff; /* number of trailing chars unchanged */
X int len; /* length of changed chars */
X int cs; /* cursor pos before change */
X char *change; /* NOT null terminated */
X };
X
X#define UNDOCT 64
X
Xstruct undoent undos[UNDOCT];
X
X/* the line before last mod (for undo purposes) */
XZLEXTERN unsigned char *lastline;
X
X/* buffer specified with "x */
XZLEXTERN int vibufspec;
X
XZLEXTERN int undoct,lastcs;
X
XZLEXTERN char *visrchstr;
XZLEXTERN int visrchsense;
X
X#define ZLE_MOVEMENT 1
X#define ZLE_MENUCMP 2
X#define ZLE_UNDO 4
X#define ZLE_YANK 8
X#define ZLE_LINEMOVE 16
X#define ZLE_ARG 32
X#define ZLE_NAMEDBUFFER 128
X#define ZLE_KILL (64|ZLE_NAMEDBUFFER)
X#define ZLE_HISTSEARCH 256
X#define ZLE_NEGARG 512
X#define ZLE_INSERT 1024
X
Xtypedef struct key *Key;
X
XZLEXTERN int *bindtab;
Xextern int emacsbind[256];
XZLEXTERN int altbindtab[256],mainbindtab[256];
Xextern int viinsbind[],vicmdbind[];
XZLEXTERN int vimarkcs[27],vimarkline[27];
X
X#define KRINGCT 8
XZLEXTERN char *kring[KRINGCT];
XZLEXTERN int kringnum;
XZLEXTERN char *vibuf[36];
X
X#define z_acceptandhold 0
X#define z_acceptandinfernexthistory 1
X#define z_acceptandmenucomplete 2
X#define z_acceptline 3
X#define z_acceptlineanddownhistory 4
X#define z_backwardchar 5
X#define z_backwarddeletechar 6
X#define z_backwarddeleteword 7
X#define z_backwardkillline 8
X#define z_backwardkillword 9
X#define z_backwardword 10
X#define z_beginningofbufferorhistory 11
X#define z_beginningofhistory 12
X#define z_beginningofline 13
X#define z_beginningoflinehist 14
X#define z_capitalizeword 15
X#define z_clearscreen 16
X#define z_completeword 17
X#define z_copyprevword 18
X#define z_copyregionaskill 19
X#define z_deletechar 20
X#define z_deletecharorlist 21
X#define z_deleteword 22
X#define z_digitargument 23
X#define z_downcaseword 24
X#define z_downhistory 25
X#define z_downlineorhistory 26
X#define z_endofbufferorhistory 27
X#define z_endofhistory 28
X#define z_endofline 29
X#define z_endoflinehist 30
X#define z_exchangepointandmark 31
X#define z_executelastnamedcmd 32
X#define z_executenamedcmd 33
X#define z_expandhistory 34
X#define z_expandorcomplete 35
X#define z_expandword 36
X#define z_forwardchar 37
X#define z_forwardword 38
X#define z_getline 39
X#define z_gosmacstransposechars 40
X#define z_historyincrementalsearchbackward 41
X#define z_historyincrementalsearchforward 42
X#define z_historysearchbackward 43
X#define z_historysearchforward 44
X#define z_infernexthistory 45
X#define z_insertlastword 46
X#define z_killbuffer 47
X#define z_killline 48
X#define z_killregion 49
X#define z_killwholeline 50
X#define z_listchoices 51
X#define z_listexpand 52
X#define z_magicspace 53
X#define z_menucompleteword 54
X#define z_menuexpandorcomplete 55
X#define z_overwritemode 56
X#define z_pushline 57
X#define z_quotedinsert 58
X#define z_quoteline 59
X#define z_quoteregion 60
X#define z_redisplay 61
X#define z_reversemenucomplete 62
X#define z_runhelp 63
X#define z_selfinsert 64
X#define z_selfinsertunmeta 65
X#define z_sendbreak 66
X#define z_sendstring 67
X#define z_sequenceleadin 68
X#define z_setmarkcommand 69
X#define z_spellword 70
X#define z_toggleliteralhistory 71
X#define z_transposechars 72
X#define z_transposewords 73
X#define z_undefinedkey 74
X#define z_undo 75
X#define z_universalargument 76
X#define z_upcaseword 77
X#define z_uphistory 78
X#define z_uplineorhistory 79
X#define z_viaddeol 80
X#define z_viaddnext 81
X#define z_vibackwardblankword 82
X#define z_vibackwardchar 83
X#define z_vibackwarddeletechar 84
X#define z_vibeginningofline 85
X#define z_vicapslockpanic 86
X#define z_vichange 87
X#define z_vichangeeol 88
X#define z_vichangewholeline 89
X#define z_vicmdmode 90
X#define z_videlete 91
X#define z_videletechar 92
X#define z_vidigitorbeginningofline 93
X#define z_viendofline 94
X#define z_vifetchhistory 95
X#define z_vifindnextchar 96
X#define z_vifindnextcharskip 97
X#define z_vifindprevchar 98
X#define z_vifindprevcharskip 99
X#define z_vifirstnonblank 100
X#define z_viforwardblankword 101
X#define z_viforwardblankwordend 102
X#define z_viforwardchar 103
SHAR_EOF
true || echo 'restore of zsh2.2/src/zle.h failed'
fi
echo 'End of zsh2.2 part 12'
echo 'File zsh2.2/src/zle.h is continued in part 13'
echo 13 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:06:54 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 109
Archive-name: zsh2.2/part13

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.13 (part 13 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/zle.h continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 13; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/zle.h'
else
echo 'x - continuing file zsh2.2/src/zle.h'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/zle.h' &&

X#define z_viforwardwordend 104
X#define z_vigotocolumn 105
X#define z_vigotomark 106
X#define z_vigotomarkline 107
X#define z_vihistorysearchbackward 108
X#define z_vihistorysearchforward 109
X#define z_viindent 110
X#define z_viinsert 111
X#define z_viinsertbol 112
X#define z_vijoin 113
X#define z_vimatchbracket 114
X#define z_viopenlineabove 115
X#define z_viopenlinebelow 116
X#define z_vioperswapcases 117
X#define z_viputafter 118
X#define z_virepeatchange 119
X#define z_virepeatfind 120
X#define z_virepeatsearch 121
X#define z_vireplace 122
X#define z_vireplacechars 123
X#define z_virevrepeatfind 124
X#define z_virevrepeatsearch 125
X#define z_visetbuffer 126
X#define z_visetmark 127
X#define z_visubstitute 128
X#define z_viswapcase 129
X#define z_viundochange 130
X#define z_viunindent 131
X#define z_viyank 132
X#define z_viyankeol 133
X#define z_whichcommand 134
X#define z_yank 135
X#define z_yankpop 136
X#define z_emacsbackwardword 137
X#define z_emacsforwardword 138
X#define z_killword 139
X#define z_vikillline 140
X#define z_vibackwardkillword 141
X#define z_expandcmdpath 142
X#define z_negargument 143
X#define z_poundinsert 144
X#define z_viforwardword 145
X#define z_vibackwardword 146
X#define ZLECMDCOUNT 147
X
Xextern struct zlecmd zlecmds[];
X
SHAR_EOF
echo 'File zsh2.2/src/zle.h is complete' &&
chmod 0644 zsh2.2/src/zle.h ||


echo 'restore of zsh2.2/src/zle.h failed'

Wc_c="`wc -c < 'zsh2.2/src/zle.h'`"
test 8371 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle.h: original size 8371, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_bindings.c ==============
if test -f 'zsh2.2/src/zle_bindings.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_bindings.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_bindings.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_bindings.c' &&
X/*
X *
X * zle_bindings.c - commands and keymaps


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#define ZLE
X#include "zsh.h"
X
X
Xstruct zlecmd zlecmds[] = {
X"accept-and-hold",acceptandhold,0,
X"accept-and-infer-next-history",acceptandinfernexthistory,0,
X"accept-and-menu-complete", acceptandmenucomplete, ZLE_MENUCMP,
X"accept-line",acceptline,0,
X"accept-line-and-down-history",acceptlineanddownhistory,0,
X"backward-char",backwardchar,ZLE_MOVEMENT,
X"backward-delete-char",backwarddeletechar,0,
X"backward-delete-word",backwarddeleteword,0,
X"backward-kill-line",backwardkillline,ZLE_KILL,
X"backward-kill-word",backwardkillword,ZLE_KILL,
X"backward-word",backwardword,ZLE_MOVEMENT,
X"beginning-of-buffer-or-history",beginningofbufferorhistory,ZLE_MOVEMENT,
X"beginning-of-history",beginningofhistory,0,
X"beginning-of-line",beginningofline,ZLE_MOVEMENT,
X"beginning-of-line-hist",beginningoflinehist,ZLE_MOVEMENT,
X"capitalize-word",capitalizeword,0,
X"clear-screen",clearscreen,0,
X"complete-word",completeword,ZLE_MENUCMP,
X"copy-prev-word",copyprevword,0,
X"copy-region-as-kill",copyregionaskill,ZLE_KILL,
X"delete-char",deletechar,0,
X"delete-char-or-list",deletecharorlist,ZLE_MENUCMP,
X"delete-word",deleteword,0,
X"digit-argument",digitargument,ZLE_ARG,
X"down-case-word",downcaseword,0,
X"down-history",downhistory,0,
X"down-line-or-history",downlineorhistory,ZLE_MOVEMENT|ZLE_LINEMOVE,
X"end-of-buffer-or-history",endofbufferorhistory,ZLE_MOVEMENT,
X"end-of-history",endofhistory,0,
X"end-of-line",endofline,ZLE_MOVEMENT,
X"end-of-line-hist",endoflinehist,ZLE_MOVEMENT,
X"exchange-point-and-mark",exchangepointandmark,ZLE_MOVEMENT,
X"execute-last-named-cmd",NULL,0,
X"execute-named-cmd",NULL,0,
X"expand-history",expandhistory,0,
X"expand-or-complete",expandorcomplete,ZLE_MENUCMP,
X"expand-word",expandword,0,
X"forward-char",forwardchar,ZLE_MOVEMENT,
X"forward-word",forwardword,ZLE_MOVEMENT,
X"get-line",getline,0,
X"gosmacs-transpose-chars",gosmacstransposechars,0,
X"history-incremental-search-backward",historyincrementalsearchbackward,0,
X"history-incremental-search-forward",historyincrementalsearchforward,0,
X"history-search-backward",historysearchbackward,ZLE_HISTSEARCH,
X"history-search-forward",historysearchforward,ZLE_HISTSEARCH,
X"infer-next-history",infernexthistory,0,
X"insert-last-word",insertlastword,ZLE_INSERT,
X"kill-buffer",killbuffer,ZLE_KILL,
X"kill-line",killline,ZLE_KILL,
X"kill-region",killregion,ZLE_KILL,
X"kill-whole-line",killwholeline,ZLE_KILL,
X"list-choices",listchoices,0,
X"list-expand",listexpand,ZLE_MENUCMP,
X"magic-space",magicspace,0,
X"menu-complete",menucompleteword,ZLE_MENUCMP,
X"menu-expand-or-complete",menuexpandorcomplete,ZLE_MENUCMP,
X"overwrite-mode",overwritemode,0,
X"push-line",pushline,0,
X"quoted-insert",quotedinsert,ZLE_INSERT,
X"quote-line",quoteline,0,
X"quote-region",quoteregion,0,
X"redisplay",redisplay,0,
X"reverse-menu-complete",reversemenucomplete,ZLE_MENUCMP,
X"run-help",processcmd,0,
X"self-insert",selfinsert,ZLE_INSERT,
X"self-insert-unmeta",selfinsertunmeta,ZLE_INSERT,
X"send-break",sendbreak,0,
X"send-string",sendstring,0,
X"",NULL,0,
X"set-mark-command",setmarkcommand,0,
X"spell-word",spellword,0,
X"toggle-literal-history",toggleliteralhistory,0,
X"transpose-chars",transposechars,0,
X"transpose-words",transposewords,0,
X"undefined-key",undefinedkey,0,
X"undo",undo,ZLE_UNDO,
X"universal-argument",universalargument,ZLE_ARG,
X"up-case-word",upcaseword,0,
X"up-history",uphistory,0,
X"up-line-or-history",uplineorhistory,ZLE_LINEMOVE|ZLE_MOVEMENT,
X"vi-add-eol",viaddeol,0,
X"vi-add-next",viaddnext,0,
X"vi-backward-blank-word",vibackwardblankword,ZLE_MOVEMENT,
X"vi-backward-char",vibackwardchar,ZLE_MOVEMENT,
X"vi-backward-delete-char",vibackwarddeletechar,ZLE_KILL,
X"vi-beginning-of-line",vibeginningofline,ZLE_MOVEMENT,
X"vi-caps-lock-panic",vicapslockpanic,0,
X"vi-change",vichange,0,
X"vi-change-eol",vichangeeol,0,
X"vi-change-whole-line",vichangewholeline,0,
X"vi-cmd-mode",vicmdmode,0,
X"vi-delete",videlete,ZLE_KILL,
X"vi-delete-char",videletechar,ZLE_KILL,
X"vi-digit-or-beginning-of-line",NULL,0,
X"vi-end-of-line",viendofline,ZLE_MOVEMENT,
X"vi-fetch-history",vifetchhistory,0,
X"vi-find-next-char",vifindnextchar,ZLE_MOVEMENT,
X"vi-find-next-char-skip",vifindnextcharskip,ZLE_MOVEMENT,
X"vi-find-prev-char",vifindprevchar,ZLE_MOVEMENT,
X"vi-find-prev-char-skip",vifindprevcharskip,ZLE_MOVEMENT,
X"vi-first-non-blank",vifirstnonblank,ZLE_MOVEMENT,
X"vi-forward-blank-word",viforwardblankword,ZLE_MOVEMENT,
X"vi-forward-blank-word-end",viforwardblankwordend,ZLE_MOVEMENT,
X"vi-forward-char",viforwardchar,ZLE_MOVEMENT,
X"vi-forward-word-end",viforwardwordend,ZLE_MOVEMENT,
X"vi-goto-column",vigotocolumn,ZLE_MOVEMENT,
X"vi-goto-mark",vigotomark,ZLE_MOVEMENT,
X"vi-goto-mark-line",vigotomarkline,ZLE_MOVEMENT,
X"vi-history-search-backward",vihistorysearchbackward,0,
X"vi-history-search-forward",vihistorysearchforward,0,
X"vi-indent",viindent,0,
X"vi-insert",viinsert,0,
X"vi-insert-bol",viinsertbol,0,
X"vi-join",vijoin,0,
X"vi-match-bracket",vimatchbracket,ZLE_MOVEMENT,
X"vi-open-line-above",viopenlineabove,0,
X"vi-open-line-below",viopenlinebelow,0,
X"vi-oper-swap-case",vioperswapcase,0,
X"vi-put-after",viputafter,ZLE_YANK,
X"vi-repeat-change",virepeatchange,0,
X"vi-repeat-find",virepeatfind,ZLE_MOVEMENT,
X"vi-repeat-search",virepeatsearch,ZLE_MOVEMENT,
X"vi-replace",vireplace,0,
X"vi-replace-chars",vireplacechars,0,
X"vi-rev-repeat-find",virevrepeatfind,ZLE_MOVEMENT,
X"vi-rev-repeat-search",virevrepeatsearch,ZLE_MOVEMENT,
X"vi-set-buffer",visetbuffer,0,
X"vi-set-mark",visetmark,0,
X"vi-substitute",visubstitute,0,
X"vi-swap-case",viswapcase,0,
X"vi-undo-change",undo,0,
X"vi-unindent",viunindent,0,
X"vi-yank",viyank,0,
X"vi-yank-eol",viyankeol,0,
X"which-command",processcmd,0,
X"yank",yank,ZLE_YANK|ZLE_NAMEDBUFFER,
X"yank-pop",yankpop,ZLE_YANK,
X"emacs-forward-word",emacsforwardword,ZLE_MOVEMENT,
X"emacs-backward-word",emacsbackwardword,ZLE_MOVEMENT,
X"kill-word",killword,ZLE_KILL,
X"vi-kill-line",vikillline,0,
X"vi-backward-kill-word",vibackwardkillword,0,
X"expand-cmd-path",expandcmdpath,0,
X"neg-argument",negargument,ZLE_NEGARG,
X"pound-insert",poundinsert,0,
X"vi-forward-word",viforwardword,ZLE_MOVEMENT,
X"vi-backward-word",vibackwardword,ZLE_MOVEMENT,
X"",NULL,0
X};
X
Xint emacsbind[256] = {
X/* ^@ */ z_setmarkcommand,
X/* ^A */ z_beginningofline,
X/* ^B */ z_backwardchar,
X/* ^C */ z_sendbreak,
X/* ^D */ z_deletecharorlist,
X/* ^E */ z_endofline,
X/* ^F */ z_forwardchar,
X/* ^G */ z_undefinedkey,
X/* ^H */ z_backwarddeletechar,
X/* ^I */ z_expandorcomplete,
X/* ^J */ z_acceptline,
X/* ^K */ z_killline,
X/* ^L */ z_clearscreen,
X/* ^M */ z_acceptline,
X/* ^N */ z_downlineorhistory,
X/* ^O */ z_acceptlineanddownhistory,
X/* ^P */ z_uplineorhistory,
X/* ^Q */ z_pushline,
X/* ^R */ z_historyincrementalsearchbackward,
X/* ^S */ z_historyincrementalsearchforward,
X/* ^T */ z_transposechars,
X/* ^U */ z_killwholeline,
X/* ^V */ z_quotedinsert,
X/* ^W */ z_backwardkillword,
X/* ^X */ z_sequenceleadin,
X/* ^Y */ z_yank,
X/* ^Z */ z_undefinedkey,
X/* ^[ */ z_sequenceleadin,
X/* ^\ */ z_undefinedkey,
X/* ^] */ z_undefinedkey,
X/* ^^ */ z_undefinedkey,
X/* ^_ */ z_undo,
X/* */ z_selfinsert,
X/* ! */ z_selfinsert,
X/* " */ z_selfinsert,
X/* # */ z_selfinsert,
X/* $ */ z_selfinsert,
X/* % */ z_selfinsert,
X/* & */ z_selfinsert,
X/* ' */ z_selfinsert,
X/* ( */ z_selfinsert,
X/* ) */ z_selfinsert,
X/* * */ z_selfinsert,
X/* + */ z_selfinsert,
X/* , */ z_selfinsert,
X/* - */ z_selfinsert,
X/* . */ z_selfinsert,
X/* / */ z_selfinsert,
X/* 0 */ z_selfinsert,
X/* 1 */ z_selfinsert,
X/* 2 */ z_selfinsert,
X/* 3 */ z_selfinsert,
X/* 4 */ z_selfinsert,
X/* 5 */ z_selfinsert,
X/* 6 */ z_selfinsert,
X/* 7 */ z_selfinsert,
X/* 8 */ z_selfinsert,
X/* 9 */ z_selfinsert,
X/* : */ z_selfinsert,
X/* ; */ z_selfinsert,
X/* < */ z_selfinsert,
X/* = */ z_selfinsert,
X/* > */ z_selfinsert,
X/* ? */ z_selfinsert,
X/* @ */ z_selfinsert,
X/* A */ z_selfinsert,
X/* B */ z_selfinsert,
X/* C */ z_selfinsert,
X/* D */ z_selfinsert,
X/* E */ z_selfinsert,
X/* F */ z_selfinsert,
X/* G */ z_selfinsert,
X/* H */ z_selfinsert,
X/* I */ z_selfinsert,
X/* J */ z_selfinsert,
X/* K */ z_selfinsert,
X/* L */ z_selfinsert,
X/* M */ z_selfinsert,
X/* N */ z_selfinsert,
X/* O */ z_selfinsert,
X/* P */ z_selfinsert,
X/* Q */ z_selfinsert,
X/* R */ z_selfinsert,
X/* S */ z_selfinsert,
X/* T */ z_selfinsert,
X/* U */ z_selfinsert,
X/* V */ z_selfinsert,
X/* W */ z_selfinsert,
X/* X */ z_selfinsert,
X/* Y */ z_selfinsert,
X/* Z */ z_selfinsert,
X/* [ */ z_selfinsert,
X/* \ */ z_selfinsert,
X/* ] */ z_selfinsert,
X/* ^ */ z_selfinsert,
X/* _ */ z_selfinsert,
X/* ` */ z_selfinsert,
X/* a */ z_selfinsert,
X/* b */ z_selfinsert,
X/* c */ z_selfinsert,
X/* d */ z_selfinsert,
X/* e */ z_selfinsert,
X/* f */ z_selfinsert,
X/* g */ z_selfinsert,
X/* h */ z_selfinsert,
X/* i */ z_selfinsert,
X/* j */ z_selfinsert,
X/* k */ z_selfinsert,
X/* l */ z_selfinsert,
X/* m */ z_selfinsert,
X/* n */ z_selfinsert,
X/* o */ z_selfinsert,
X/* p */ z_selfinsert,
X/* q */ z_selfinsert,
X/* r */ z_selfinsert,
X/* s */ z_selfinsert,
X/* t */ z_selfinsert,
X/* u */ z_selfinsert,
X/* v */ z_selfinsert,
X/* w */ z_selfinsert,
X/* x */ z_selfinsert,
X/* y */ z_selfinsert,
X/* z */ z_selfinsert,
X/* { */ z_selfinsert,
X/* | */ z_selfinsert,
X/* } */ z_selfinsert,
X/* ~ */ z_selfinsert,
X/* ^? */ z_backwarddeletechar,
X/* M-^@ */ z_undefinedkey,
X/* M-^A */ z_undefinedkey,
X/* M-^B */ z_undefinedkey,
X/* M-^C */ z_undefinedkey,
X/* M-^D */ z_listchoices,
X/* M-^E */ z_undefinedkey,
X/* M-^F */ z_undefinedkey,
X/* M-^G */ z_undefinedkey,
X/* M-^H */ z_backwardkillword,
X/* M-^I */ z_selfinsertunmeta,
X/* M-^J */ z_selfinsertunmeta,
X/* M-^K */ z_undefinedkey,
X/* M-^L */ z_clearscreen,
X/* M-^M */ z_selfinsertunmeta,
X/* M-^N */ z_undefinedkey,
X/* M-^O */ z_undefinedkey,
X/* M-^P */ z_undefinedkey,
X/* M-^Q */ z_undefinedkey,
X/* M-^R */ z_undefinedkey,
X/* M-^S */ z_undefinedkey,
X/* M-^T */ z_undefinedkey,
X/* M-^U */ z_undefinedkey,
X/* M-^V */ z_undefinedkey,
X/* M-^W */ z_undefinedkey,
X/* M-^X */ z_undefinedkey,
X/* M-^Y */ z_undefinedkey,
X/* M-^Z */ z_undefinedkey,
X/* M-^[ */ z_undefinedkey,
X/* M-^\ */ z_undefinedkey,
X/* M-^] */ z_undefinedkey,
X/* M-^^ */ z_undefinedkey,
X/* M-^_ */ z_copyprevword,
X/* M- */ z_expandhistory,
X/* M-! */ z_expandhistory,
X/* M-" */ z_quoteregion,
X/* M-# */ z_undefinedkey,
X/* M-$ */ z_spellword,
X/* M-% */ z_undefinedkey,
X/* M-& */ z_undefinedkey,
X/* M-' */ z_quoteline,
X/* M-( */ z_undefinedkey,
X/* M-) */ z_undefinedkey,
X/* M-* */ z_undefinedkey,
X/* M-+ */ z_undefinedkey,
X/* M-, */ z_undefinedkey,
X/* M-- */ z_negargument,
X/* M-. */ z_insertlastword,
X/* M-/ */ z_undefinedkey,
X/* M-0 */ z_digitargument,
X/* M-1 */ z_digitargument,
X/* M-2 */ z_digitargument,
X/* M-3 */ z_digitargument,
X/* M-4 */ z_digitargument,
X/* M-5 */ z_digitargument,
X/* M-6 */ z_digitargument,
X/* M-7 */ z_digitargument,
X/* M-8 */ z_digitargument,
X/* M-9 */ z_digitargument,
X/* M-: */ z_undefinedkey,
X/* M-; */ z_undefinedkey,
X/* M-< */ z_beginningofbufferorhistory,
X/* M-= */ z_undefinedkey,
X/* M-> */ z_endofbufferorhistory,
X/* M-? */ z_whichcommand,
X/* M-@ */ z_undefinedkey,
X/* M-A */ z_acceptandhold,
X/* M-B */ z_backwardword,
X/* M-C */ z_capitalizeword,
X/* M-D */ z_deleteword,
X/* M-E */ z_undefinedkey,
X/* M-F */ z_forwardword,
X/* M-G */ z_getline,
X/* M-H */ z_runhelp,
X/* M-I */ z_undefinedkey,
X/* M-J */ z_undefinedkey,
X/* M-K */ z_undefinedkey,
X/* M-L */ z_downcaseword,
X/* M-M */ z_undefinedkey,
X/* M-N */ z_historysearchforward,
X/* M-O */ z_undefinedkey,
X/* M-P */ z_historysearchbackward,
X/* M-Q */ z_pushline,
X/* M-R */ z_toggleliteralhistory,
X/* M-S */ z_spellword,
X/* M-T */ z_transposewords,
X/* M-U */ z_upcaseword,
X/* M-V */ z_undefinedkey,
X/* M-W */ z_copyregionaskill,
X/* M-X */ z_undefinedkey,
X/* M-Y */ z_undefinedkey,
X/* M-Z */ z_undefinedkey,
X/* M-[ */ z_sequenceleadin,
X/* M-\ */ z_undefinedkey,
X/* M-] */ z_undefinedkey,
X/* M-^ */ z_undefinedkey,
X/* M-_ */ z_insertlastword,
X/* M-` */ z_undefinedkey,
X/* M-a */ z_acceptandhold,
X/* M-b */ z_backwardword,
X/* M-c */ z_capitalizeword,
X/* M-d */ z_deleteword,
X/* M-e */ z_undefinedkey,
X/* M-f */ z_forwardword,
X/* M-g */ z_getline,
X/* M-h */ z_runhelp,
X/* M-i */ z_undefinedkey,
X/* M-j */ z_undefinedkey,
X/* M-k */ z_undefinedkey,
X/* M-l */ z_downcaseword,
X/* M-m */ z_undefinedkey,
X/* M-n */ z_historysearchforward,
X/* M-o */ z_undefinedkey,
X/* M-p */ z_historysearchbackward,
X/* M-q */ z_pushline,
X/* M-r */ z_toggleliteralhistory,
X/* M-s */ z_spellword,
X/* M-t */ z_transposewords,
X/* M-u */ z_upcaseword,
X/* M-v */ z_undefinedkey,
X/* M-w */ z_copyregionaskill,
X/* M-x */ z_executenamedcmd,
X/* M-y */ z_yankpop,
X/* M-z */ z_executelastnamedcmd,
X/* M-{ */ z_undefinedkey,
X/* M-| */ z_vigotocolumn,
X/* M-} */ z_undefinedkey,
X/* M-~ */ z_undefinedkey,
X/* M-^? */ z_backwardkillword,
X};
X
Xint viinsbind[32] = {
X/* ^@ */ z_undefinedkey,
X/* ^A */ z_selfinsert,
X/* ^B */ z_selfinsert,
X/* ^C */ z_sendbreak,
X/* ^D */ z_listchoices,
X/* ^E */ z_selfinsert,
X/* ^F */ z_selfinsert,
X/* ^G */ z_selfinsert,
X/* ^H */ z_vibackwarddeletechar,
X/* ^I */ z_expandorcomplete,
X/* ^J */ z_acceptline,
X/* ^K */ z_killline,
X/* ^L */ z_clearscreen,
X/* ^M */ z_acceptline,
X/* ^N */ z_selfinsert,
X/* ^O */ z_selfinsert,
X/* ^P */ z_selfinsert,
X/* ^Q */ z_selfinsert,
X/* ^R */ z_redisplay,
X/* ^S */ z_selfinsert,
X/* ^T */ z_selfinsert,
X/* ^U */ z_vikillline,
X/* ^V */ z_quotedinsert,
X/* ^W */ z_vibackwardkillword,
X/* ^X */ z_selfinsert,
X/* ^Y */ z_selfinsert,
X/* ^Z */ z_selfinsert,
X/* ^[ */ z_vicmdmode,
X/* ^\ */ z_selfinsert,
X/* ^] */ z_selfinsert,
X/* ^^ */ z_selfinsert,
X/* ^_ */ z_selfinsert,
X};
X
Xint vicmdbind[128] = {
X/* ^@ */ z_undefinedkey,
X/* ^A */ z_beginningofline,
X/* ^B */ z_undefinedkey,
X/* ^C */ z_sendbreak,
X/* ^D */ z_listchoices,
X/* ^E */ z_endofline,
X/* ^F */ z_undefinedkey,
X/* ^G */ z_listexpand,
X/* ^H */ z_backwarddeletechar,
X/* ^I */ z_completeword,
X/* ^J */ z_acceptline,
X/* ^K */ z_killline,
X/* ^L */ z_clearscreen,
X/* ^M */ z_acceptline,
X/* ^N */ z_downhistory,
X/* ^O */ z_undefinedkey,
X/* ^P */ z_uphistory,
X/* ^Q */ z_undefinedkey,
X/* ^R */ z_redisplay,
X/* ^S */ z_undefinedkey,
X/* ^T */ z_undefinedkey,
X/* ^U */ z_killbuffer,
X/* ^V */ z_undefinedkey,
X/* ^W */ z_backwardkillword,
X/* ^X */ z_expandorcomplete,
X/* ^Y */ z_undefinedkey,
X/* ^Z */ z_undefinedkey,
X/* ^[ */ z_sequenceleadin,
X/* ^\ */ z_undefinedkey,
X/* ^] */ z_undefinedkey,
X/* ^^ */ z_undefinedkey,
X/* ^_ */ z_undefinedkey,
X/* */ z_viforwardchar,
X/* ! */ z_undefinedkey,
X/* " */ z_visetbuffer,
X/* # */ z_poundinsert,
X/* $ */ z_viendofline,
X/* % */ z_vimatchbracket,
X/* & */ z_undefinedkey,
X/* ' */ z_vigotomarkline,
X/* ( */ z_undefinedkey,
X/* ) */ z_undefinedkey,
X/* * */ z_undefinedkey,
X/* + */ z_downlineorhistory,
X/* , */ z_virevrepeatfind,
X/* - */ z_uplineorhistory,
X/* . */ z_virepeatchange,
X/* / */ z_vihistorysearchbackward,
X/* 0 */ z_vidigitorbeginningofline,
X/* 1 */ z_digitargument,
X/* 2 */ z_digitargument,
X/* 3 */ z_digitargument,
X/* 4 */ z_digitargument,
X/* 5 */ z_digitargument,
X/* 6 */ z_digitargument,
X/* 7 */ z_digitargument,
X/* 8 */ z_digitargument,
X/* 9 */ z_digitargument,
X/* : */ z_undefinedkey,
X/* ; */ z_virepeatfind,
X/* < */ z_viunindent,
X/* = */ z_listchoices,
X/* > */ z_viindent,
X/* ? */ z_vihistorysearchforward,
X/* @ */ z_undefinedkey,
X/* A */ z_viaddeol,
X/* B */ z_vibackwardblankword,
X/* C */ z_vichangeeol,
X/* D */ z_killline,
X/* E */ z_viforwardblankwordend,
X/* F */ z_vifindprevchar,
X/* G */ z_vifetchhistory,
X/* H */ z_vicapslockpanic,
X/* I */ z_viinsertbol,
X/* J */ z_historysearchforward,
X/* K */ z_historysearchbackward,
X/* L */ z_undefinedkey,
X/* M */ z_undefinedkey,
X/* N */ z_virevrepeatsearch,
X/* O */ z_viopenlineabove,
X/* P */ z_yank,
X/* Q */ z_undefinedkey,
X/* R */ z_vireplace,
X/* S */ z_vichangewholeline,
X/* T */ z_vifindprevcharskip,
X/* U */ z_undefinedkey,
X/* V */ z_undefinedkey,
X/* W */ z_viforwardblankword,
X/* X */ z_vibackwarddeletechar,
X/* Y */ z_viyankeol,
X/* Z */ z_undefinedkey,
X/* [ */ z_undefinedkey,
X/* \ */ z_completeword,
X/* ] */ z_undefinedkey,
X/* ^ */ z_vifirstnonblank,
X/* _ */ z_undefinedkey,
X/* ` */ z_vigotomark,
X/* a */ z_viaddnext,
X/* b */ z_vibackwardword,
X/* c */ z_vichange,
X/* d */ z_videlete,
X/* e */ z_viforwardwordend,
X/* f */ z_vifindnextchar,
X/* g */ z_undefinedkey,
X/* h */ z_vibackwardchar,
X/* i */ z_viinsert,
X/* j */ z_downlineorhistory,
X/* k */ z_uplineorhistory,
X/* l */ z_viforwardchar,
X/* m */ z_visetmark,
X/* n */ z_virepeatsearch,
X/* o */ z_viopenlinebelow,
X/* p */ z_viputafter,
X/* q */ z_undefinedkey,
X/* r */ z_vireplacechars,
X/* s */ z_visubstitute,
X/* t */ z_vifindnextcharskip,
X/* u */ z_viundochange,
X/* v */ z_undefinedkey,
X/* w */ z_viforwardword,
X/* x */ z_videletechar,
X/* y */ z_viyank,
X/* z */ z_undefinedkey,
X/* { */ z_undefinedkey,
X/* | */ z_vigotocolumn,
X/* } */ z_undefinedkey,
X/* ~ */ z_viswapcase,
X/* ^? */ z_backwarddeletechar,
X};
X
SHAR_EOF
chmod 0644 zsh2.2/src/zle_bindings.c ||
echo 'restore of zsh2.2/src/zle_bindings.c failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_bindings.c'`"
test 17212 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_bindings.c: original size 17212, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_main.c ==============
if test -f 'zsh2.2/src/zle_main.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_main.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_main.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_main.c' &&
X/*
X *
X * zle_main.c - main routines for line editor


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#define ZLEGLOBALS
X#define ZLE
X#include "zsh.h"
X#include <sys/types.h>
X#include <sys/errno.h>
X#ifdef HAS_SYS_SELECT
X#include <sys/select.h>
X#endif
X
Xstatic Key cky;
X
X/* set up terminal */
X
Xvoid setterm() /**/
X{
Xstruct ttyinfo ti;
X#ifdef FIONREAD
Xlong val;
X#endif
X
X#ifdef CLOBBERS_TYPEAHEAD
X#ifdef FIONREAD
X ioctl(SHTTY, FIONREAD, &val);
X if (val) return;
X#endif
X#endif
X inittty();


X ti = shttyinfo;
X#ifdef TIO

X ti.tio.c_lflag &= ~(ICANON|ECHO
X#ifdef FLUSHO
X |FLUSHO
X#endif
X );
X ti.tio.c_cc[VQUIT] =
X#ifdef VDISCARD
X ti.tio.c_cc[VDISCARD] =
X#endif
X#ifdef VSUSP
X ti.tio.c_cc[VSUSP] =
X#endif
X#ifdef VDSUSP
X ti.tio.c_cc[VDSUSP] =
X#endif
X#ifdef VSWTCH
X ti.tio.c_cc[VSWTCH] =
X#endif
X VDISABLEVAL;


X ti.tio.c_cc[VMIN] = 1;
X ti.tio.c_cc[VTIME] = 0;

X ti.tio.c_iflag &= ~(INLCR|ICRNL);
X#else
X ti.sgttyb.sg_flags = (ti.sgttyb.sg_flags | CBREAK) & ~ECHO;
X ti.lmodes &= ~LFLUSHO;
X ti.tchars.t_quitc =
X ti.ltchars.t_suspc =
X ti.ltchars.t_flushc =
X ti.ltchars.t_dsuspc = ti.ltchars.t_lnextc = -1;
X#endif
X#ifdef TTY_NEEDS_DRAINING
X drainoutput();


X#endif
X settyinfo(&ti);
X}
X

Xvoid unsetterm() /**/


X{
X settyinfo(&shttyinfo);
X}
X

Xstatic char *kungetbuf;
Xstatic int kungetct,kungetsz;
X
Xvoid ungetkey(ch) /**/
Xint ch;
X{
X if (kungetct == kungetsz)
X kungetbuf = realloc(kungetbuf,kungetsz *= 2);
X kungetbuf[kungetct++] = ch;
X}
X
Xvoid ungetkeys(s,len) /**/
Xchar *s;int len;
X{
X s += len;
X while (len--)
X ungetkey(*--s);
X}
X
Xunsigned int getkey(tmok) /**/
Xint tmok;
X{
Xchar cc;
Xunsigned int ret = 0;
Xint die = 0;
X#ifdef HAS_SELECT
Xfd_set foofd;
X#endif
X
X if (kungetct)
X ret = (unsigned int) (unsigned char) kungetbuf[--kungetct];
X else {
X while (
X#ifdef HAS_SELECT
X FD_SET(0,&foofd), select(1,&foofd,NULL,NULL,NULL) != 1 ||
X#endif
X read(0,&cc,1) != 1)
X if (errno == EINTR) {
X if (!errflag)
X continue;
X errflag = 0;
X if (tmok)
X return -1;
X return 3;
X } else if (errno == EWOULDBLOCK) {
X fcntl(0,F_SETFL,0);
X } else if (errno == EIO && !die) {
X ret = jobbing;
X jobbing = 1;
X attachtty(mypgrp);
X refresh(); /* kludge! */
X jobbing = ret;
X die = 1;
X } else {
X zerr("error on TTY read: %e",NULL,errno);
X exit(1);
X }
X ret = (unsigned int) (unsigned char) cc;
X }
X if (vichgflag) {
X if (vichgbufptr == vichgbufsz)
X vichgbuf = realloc(vichgbuf,vichgbufsz *= 2);
X vichgbuf[vichgbufptr++] = ret;
X }


X return ret;
X}
X

X/* read a line */
X
Xunsigned char *zleread(ppt,ppt2,plen) /**/
Xunsigned char *ppt;unsigned char *ppt2;int plen;
X{
Xint z;
Xlong costmult;
Xunsigned char *s;
X#ifdef HAS_SELECT
Xstruct timeval tv;
Xfd_set foofd;
X
X tv.tv_sec = 0;
X#endif
X fflush(stdout);
X fflush(stderr);
X intr();
X costmult = 3840000L/((baud) ? baud : 2400);
X insmode = unset(OVERSTRIKE); eofsent = 0; resetneeded =0 ;
X pmpt = (char *)ppt;
X pmpt2 = (char *)ppt2;
X permalloc();
X histline = curhist;
X pptlen = plen;
X resetneeded = 1;
X#ifdef HAS_SELECT
X FD_ZERO(&foofd);
X#endif
X undoing = 1;
X line = zalloc(linesz = 256);
X *line = '\0';
X virangeflag = lastcmd = done = cs = ll = mark = 0;
X curhistline = NULL;
X mult = 1;
X vibufspec = 0;
X bindtab = mainbindtab;
X addedslash = vichgflag = 0;
X viinsbegin = 0;
X statusline = NULL;
X if (s = getnode(bufstack))
X {
X setline((char *) s);
X free(s);
X if (stackcs != -1)
X {
X cs = stackcs;
X stackcs = -1;
X if (cs > ll)
X cs = ll;
X }
X if (stackhist != -1)
X {
X histline = stackhist;
X stackhist = -1;
X }
X }
X initundo();
X if (unset(NOPROMPTCR))
X putchar('\r');
X if (tmout)
X alarm(tmout);
X refresh();
X errflag = 0;
X while (!done && !errflag)
X {
X struct zlecmd *zc;
X
X statusline = NULL;
X bindk = getkeycmd();
X if (c == 4 && !ll)
X {
X eofsent = 1;
X break;
X }
X if (bindk != -1)
X {
X zc = zlecmds+bindk;
X if (!(lastcmd & ZLE_ARG))
X mult = 1;
X if ((lastcmd & ZLE_UNDO) != (zc->flags & ZLE_UNDO) && undoing)
X addundo();
X if (!(zc->flags & ZLE_MENUCMP)) {
X if (menucmp) freemenu();
X if (addedslash &&
X !((zc->flags & ZLE_INSERT) && c != ' ')) {
X backdel(1);
X }
X addedslash = 0;
X }
X if (zc->func)
X (*zc->func)();
X lastcmd = zc->flags;
X if (!(lastcmd & ZLE_UNDO) && undoing) addundo();
X }
X else
X {
X errflag = 1;
X break;
X }
X#ifdef HAS_SELECT
X FD_SET(0,&foofd);
X if ((tv.tv_usec = cost*costmult) > 500000)
X tv.tv_usec = 500000;
X#endif
X if (!kungetct
X#ifdef HAS_SELECT
X && select(1,&foofd,NULL,NULL,&tv) <= 0
X#endif
X )
X refresh();
X }
X if (menucmp)
X freemenu();
X statusline = NULL;
X trashzle();
X alarm(0);
X z = strlen((char *)line);
X line[z] = '\n';
X line[z+1] = 0;
X heapalloc();
X if (curhistline)
X free(curhistline);
X if (eofsent)
X {
X free(line);
X line = NULL;
X }
X zleactive = 0;
X freeundo();
X return line;
X}
X
Xint getkeycmd() /**/
X{
Xchar buf[10];
Xint t0,ret;
XKey ky;
X
X t0 = 1;
X cky = NULL;
X if ((c = getkey(1)) == -1)
X return -1;
X if ((ret = bindtab[c]) == z_sequenceleadin)
X {
X buf[0] = (c) ? c : 0x80;
X for (;;)
X {
X c = getkey(0);
X buf[t0++] = (c) ? c : 0x80;
X buf[t0] = '\0';
X if (!(ky = (Key) gethnode(buf,xbindtab)))
X return z_undefinedkey;
X if (ky->func != z_sequenceleadin)
X {
X cky = ky;
X ret = ky->func;
X break;
X }
X }
X }
X if (ret == z_vidigitorbeginningofline)
X ret = (lastcmd & ZLE_ARG) ? z_digitargument : z_beginningofline;
X else if (ret == z_executenamedcmd)
X ret = executenamedcommand();
X else if (ret == z_executelastnamedcmd)
X ret = lastnamed;


X return ret;
X}
X

Xvoid sendstring() /**/
X{
Xchar buf[2];
X
X buf[0] = c;
X buf[1] = '\0';
X if (!cky)
X cky = (Key) gethnode(buf,xbindtab);
X ungetkeys(cky->str,cky->len);
X}
X
XKey makefunckey(fun) /**/
Xint fun;
X{
XKey ky = zcalloc(sizeof *ky);
X
X ky->func = fun;
X return ky;
X}
X
X/* initialize the bindings */
X
Xvoid initxbindtab() /**/
X{
Xint t0,vi = 0;
Xchar buf[3],*s;
X
X lastnamed = z_undefinedkey;
X if (s = zgetenv("VISUAL")) {
X if (ztrstr(s,"vi"))
X vi = 1;
X }
X else if ((s = zgetenv("EDITOR")) && ztrstr(s,"vi"))
X vi = 1;
X if (vi) {


X for (t0 = 0; t0 != 32; t0++)

X mainbindtab[t0] = viinsbind[t0];
X for (t0 = 32; t0 != 256; t0++)
X mainbindtab[t0] = z_selfinsert;
X mainbindtab[127] = z_backwarddeletechar;
X } else {


X for (t0 = 0; t0 != 128; t0++)

X mainbindtab[t0] = emacsbind[t0];
X for (t0 = 128; t0 != 256; t0++)
X mainbindtab[t0] = z_selfinsert;
X }
X for (t0 = 0200; t0 != 0240; t0++)
X mainbindtab[t0] = z_undefinedkey;
X for (t0 = 0; t0 != 128; t0++)
X altbindtab[t0] = vicmdbind[t0];
X for (t0 = 128; t0 != 256; t0++)
X altbindtab[t0] = emacsbind[t0];
X bindtab = mainbindtab;
X kungetbuf = zalloc(kungetsz = 32);
X kungetct = 0;
X xbindtab = newhtable(67);
X addhperm("\33\133C",makefunckey(z_forwardchar),xbindtab,NULL);
X addhperm("\33\133D",makefunckey(z_backwardchar),xbindtab,NULL);
X addhperm("\33\133A",makefunckey(z_uplineorhistory),xbindtab,NULL);
X addhperm("\33\133B",makefunckey(z_downlineorhistory),xbindtab,NULL);
X addhperm("\30*",makefunckey(z_expandword),xbindtab,NULL);
X addhperm("\30g",makefunckey(z_listexpand),xbindtab,NULL);
X addhperm("\30G",makefunckey(z_listexpand),xbindtab,NULL);
X addhperm("\30\16",makefunckey(z_infernexthistory),xbindtab,NULL);
X addhperm("\30\13",makefunckey(z_killbuffer),xbindtab,NULL);
X addhperm("\30\6",makefunckey(z_vifindnextchar),xbindtab,NULL);
X addhperm("\30\17",makefunckey(z_overwritemode),xbindtab,NULL);
X addhperm("\30\25",makefunckey(z_undo),xbindtab,NULL);
X addhperm("\30\26",makefunckey(z_vicmdmode),xbindtab,NULL);
X addhperm("\30\12",makefunckey(z_vijoin),xbindtab,NULL);
X addhperm("\30\2",makefunckey(z_vimatchbracket),xbindtab,NULL);
X addhperm("\30s",makefunckey(z_historyincrementalsearchforward),
X xbindtab,NULL);
X addhperm("\30r",makefunckey(z_historyincrementalsearchbackward),
X xbindtab,NULL);
X addhperm("\30u",makefunckey(z_undo),xbindtab,NULL);
X addhperm("\30\30",makefunckey(z_exchangepointandmark),
X xbindtab,NULL);
X addhperm("run-help",mkanode(ztrdup("man"),1),aliastab,NULL);
X addhperm("which-command",mkanode(ztrdup("whence"),1),aliastab,NULL);
X strcpy(buf,"\33q");
X for (t0 = 128; t0 != 256; t0++)
X if (emacsbind[t0] != z_undefinedkey) {
X buf[1] = t0 & 0x7f;
X addhnode(ztrdup(buf),makefunckey(emacsbind[t0]),xbindtab,NULL);
X }
X for (t0 = 0; t0 != 36; t0++) vibuf[t0] = NULL;
X for (t0 = 0; t0 != 26; t0++) vimarkline[t0] = 0;
X stackhist = stackcs = -1;
X vichgbufsz = 0;
X vichgbuf = NULL;
X}
X
Xchar *getkeystring(s,len) /**/
Xchar *s;int *len;
X{
Xstatic char buf[512];
Xchar *t = buf;
Xint x,first = 1,metanext = 0;
X
X for (;*s;s++)
X {
X if (*s == '\\' && s[1])
X switch(*++s)
X {
X case 'a': *t++ = '\07'; break;


X case 'n': *t++ = '\n'; break;

X case 'b': *t++ = '\010'; break;


X case 't': *t++ = '\t'; break;
X case 'v': *t++ = '\v'; break;

X case 'f': *t++ = '\f'; break;

X case 'r': *t++ = '\r'; break;

X case 'e': *t++ = '\033'; break;
X case 'M':
X if (s[1] == '-')
X s++;
X metanext = 2;
X break;
X default:
X if (idigit(*s))
X {
X for (x = 0; idigit(*s); s++)
X x = x*8+(*s-'0');
X s--;
X *t++ = x;
X }
X else
X *t++ = *s;
X break;
X }
X else if (*s == '^')
X if (*++s == '?')
X *t++ = 0x7f;
X else
X *t++ = *s & 0x9f;
X else
X *t++ = *s;
X if (metanext && !(--metanext))
X {
X t[-1] |= 0x80;
X metanext = 0;
X }
X if (t > buf+500)
X break;


X first = 0;
X }

X *t = '\0';
X *len = t-buf;


X return buf;
X}
X

Xvoid printbind(s,len) /**/
Xchar *s;int len;
X{
Xint ch;
X
X while (len--)
X {
X ch = (unsigned char) *s++;
X if (ch & 0x80)
X {
X printf("\\M-");
X ch &= 0x7f;
X }
X if (icntrl(ch))
X switch(ch)
X {
X case 0x7f: printf("^?"); break;
X default: printf("^%c",(ch|0x40)); break;
X }
X else
X putchar(ch);
X }
X}
X
Xvoid printbinding(str,k) /**/
Xchar *str;Key k;
X{
X if (k->func == z_sequenceleadin)
X return;
X putchar('\"');
X printbind(str,strlen(str));
X printf("\"\t");
X if (k->func == z_sendstring)
X {
X putchar('\"');
X printbind(k->str,k->len);
X printf("\"\n");
X }
X else
X printf("%s\n",zlecmds[k->func].name);
X}
X
Xint bin_bindkey(name,argv,ops,junc) /**/
Xchar *name;char **argv;char *ops;int junc;
X{
Xint t0,len;
Xchar *s;
Xint func,*tab;
X
X tab = (ops['a']) ? altbindtab : mainbindtab;
X if (ops['v'] || ops['e'] || ops['d'])
X {
X if (*argv)
X {
X zerrnam(name,"too many arguments",NULL,0);
X return 1;
X }
X if (ops['d'] || ops['e'])
X if (ops['m'])


X for (t0 = 0; t0 != 256; t0++)

X tab[t0] = emacsbind[t0];
X else
X {
X for (t0 = 0; t0 != 128; t0++)
X tab[t0] = emacsbind[t0];
X for (t0 = 128; t0 != 256; t0++)
X tab[t0] = z_selfinsert;
X }
X else
X {


X for (t0 = 0; t0 != 32; t0++)

X mainbindtab[t0] = viinsbind[t0];
X for (t0 = 32; t0 != 256; t0++)
X mainbindtab[t0] = z_selfinsert;
X mainbindtab[127] = z_backwarddeletechar;
X }
X for (t0 = 0; t0 != 128; t0++)
X altbindtab[t0] = vicmdbind[t0];
X for (t0 = 128; t0 != 256; t0++)
X altbindtab[t0] = emacsbind[t0];
X for (t0 = 0200; t0 != 0240; t0++)
X tab[t0] = z_undefinedkey;
X return 0;
X }
X if (!*argv)
X {
X char buf[2];
X
X buf[0] = 'x'; buf[1] = '\0';
X for (t0 = 0; t0 != 256; t0++)
X {
X buf[0] = t0;
X putchar('\"');
X printbind(buf,1);
X if (t0 < 254 && tab[t0] == tab[t0+1] && tab[t0] == tab[t0+2])
X {
X printf("\" to \"");
X while (tab[t0] == tab[t0+1]) t0++;
X buf[0] = t0;
X printbind(buf,1);
X }
X printf("\"\t%s\n",zlecmds[tab[t0]].name);
X }
X listhtable(xbindtab,(HFunc) printbinding);
X return 0;
X }
X while (*argv)
X {
X s = getkeystring(*argv++,&len);
X if (len > 8)
X {
X zerrnam(name,"in-string too long",NULL,0);
X return 1;
X }
X if (!*argv || ops['r'])
X {
X Key ky;
X
X ky = gethnode(s,xbindtab);
X if (len == 1)
X func = tab[(unsigned char) *s];
X else
X func = (ky) ? ky->func : z_undefinedkey;
X if (func == z_undefinedkey)
X {
X zerrnam(name,"in-string is not bound",NULL,0);
X return 1;
X }
X if (ops['r'])
X {
X if (len == 1)
X tab[(unsigned char) *s] = z_undefinedkey;
X else
X {
X while (strlen(s) > 1)
X {
X free(remhnode(s,xbindtab));
X s[strlen(s)-1] = '\0';
X }
X }
X continue;
X }
X if (func == z_sendstring)
X {
X printbind(ky->str,ky->len);
X putchar('\n');
X return 0;
X }
X printf("%s\n",zlecmds[func].name);
X return 0;
X }
X if (!ops['s'])
X {
X for (t0 = 0; t0 != ZLECMDCOUNT; t0++)
X if (!strcmp(*argv,zlecmds[t0].name))
X break;
X if (t0 == ZLECMDCOUNT)
X {
X zerr("undefined function: %s",*argv,0);
X return 1;
X }
X func = t0;
X }
X else
X func = z_sendstring;
X if (len == 1)
X {
X Key ky;
X
X tab[(unsigned char) *s] = (ops['s']) ? z_sendstring : t0;
X if (ops['s'])
X {
X addhnode(ztrdup(s),ky = makefunckey(z_sendstring),xbindtab,freekey);
X ky->str = ztrdup(getkeystring(*argv,&ky->len));


X }
X }
X else
X {

X int t1;
X Key ky;
X
X if (tab[(unsigned char) *s] != z_undefinedkey &&
X tab[(unsigned char) *s] != z_sequenceleadin)
X {
X zerrnam(name,"in-string has already bound prefix",NULL,0);
X return 1;
X }
X tab[(unsigned char) *s] = z_sequenceleadin;
X if (!s[1])
X s[1] = 0x80;
X for (t1 = 1; t1 != len-1; t1++)
X {
X char sav;
X
X sav = s[t1+1];
X s[t1+1] = '\0';
X ky = gethnode(s,xbindtab);
X if (ky && ky->func != z_sequenceleadin)
X {
X zerrnam(name,"in-string has already bound prefix",NULL,0);
X return 1;
X }
X if (!ky)
X addhnode(ztrdup(s),makefunckey(z_sequenceleadin),xbindtab,
X freekey);
X if (!sav)
X sav = 0x80;
X s[t1+1] = sav;
X }
X addhnode(ztrdup(s),ky = makefunckey(func),xbindtab,freekey);
X if (ops['s'])
X ky->str = ztrdup(getkeystring(*argv,&ky->len));
X }
X argv++;


X }
X return 0;
X}
X

Xvoid freekey(x) /**/
Xvptr x;
X{
XKey k = x;
X
X if (k->str)
X free(k->str);
X free(k);
X}
X
X/* this is mostly stolen from bash's draino() */
X
Xvoid drainoutput() /**/
X{
Xint n = 0;
X
X if (!baud) return;
X#ifdef TIOCOUTQ
X#ifdef HAS_SELECT
X while ((ioctl(SHTTY,TIOCOUTQ,&n) >= 0) && n) {
X struct timeval tv;
X tv.tv_sec = n/baud;
X tv.tv_usec = ((n%baud)*1000000)/baud;
X select (0,(fd_set *)0,(fd_set *)0,(fd_set *)0,&tv);
X }
X#endif
X#endif
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/zle_main.c ||
echo 'restore of zsh2.2/src/zle_main.c failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_main.c'`"
test 14597 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_main.c: original size 14597, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_refresh.c ==============
if test -f 'zsh2.2/src/zle_refresh.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_refresh.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_refresh.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_refresh.c' &&
X/*
X *
X * zle_refresh.c - screen update


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#define ZLE
X#include "zsh.h"
X
Xchar **obuf = NULL,**nbuf = NULL;
Xint olnct,nlnct;
Xint winw,winh,winpos;
X
Xint vcs,vln,vmaxln;
X
Xvoid resetvideo() /**/
X{
Xint ln;
Xstatic int lwinw = -1,lwinh = -1;
X
X setterm();
X winw = columns-1;
X if (isset(SINGLELINEZLE) || !termok)
X winh = 1;
X else
X winh = (lines < 2) ? 24 : lines;
X winpos = vln = vmaxln = 0;
X if (lwinw != winw || lwinh != winh)
X {
X if (nbuf)
X {
X for (ln = 0; ln != lwinh; ln++)
X {
X free(nbuf[ln]);
X free(obuf[ln]);
X }
X free(nbuf);
X free(obuf);
X }
X nbuf = (char **) zalloc((winh+1)*sizeof(char *));
X obuf = (char **) zalloc((winh+1)*sizeof(char *));
X for (ln = 0; ln != winh+1; ln++)
X {
X nbuf[ln] = zalloc(winw+1);
X obuf[ln] = zalloc(winw+1);
X }
X lwinw = winw;
X lwinh = winh;
X }
X for (ln = 0; ln != winh+1; ln++)
X {
X *nbuf[ln] = '\0';
X *obuf[ln] = '\0';
X }
X if (!pptlen)
X nbuf[0][0] = obuf[0][0] = '\0';
X else
X {
X for (ln = 0; ln != pptlen-1; ln++)
X nbuf[0][ln] = obuf[0][ln] = ' ';
X nbuf[0][ln] = obuf[0][ln] = '>';
X nbuf[0][pptlen] = obuf[0][pptlen] = '\0';
X }
X vcs = pptlen;
X olnct = nlnct = 1;
X}
X
Xint scrollwindow() /**/
X{
Xint t0,hwinh = winh/2;
X
X for (t0 = 0; t0 != winh-hwinh; t0++)
X {
X char *s;
X
X s = nbuf[t0];
X nbuf[t0] = nbuf[t0+hwinh];
X nbuf[t0+hwinh] = s;
X }
X for (t0 = 0; t0 != pptlen-1; t0++)
X nbuf[0][t0] = ' ';
X strcpy(nbuf[0]+t0,"> ...");
X return winh-hwinh;
X}
X
X/* this is the messy part. */
X/* this define belongs where it's used!!! */
X
X#define nextline { *s = (unsigned char)'\0'; \
X if (winh == ln+1) if (nvln != -1) break; else ln = scrollwindow()-1; \
X s = (unsigned char *)nbuf[++ln]; sen = s+winw; \
X }
X
Xvoid refresh() /**/
X{
Xunsigned char *s,*t,*sen,*scs = line+cs; char **qbuf;
Xint ln = 0,nvcs,nvln = -1,t0;
X
X cost = 0;
X if (resetneeded)
X {
X resetvideo();
X resetneeded = 0;
X if (isset(SINGLELINEZLE) || !termok)
X vcs = 0;
X else
X printf("%s",pmpt);
X }
X zleactive = 1;
X if (isset(SINGLELINEZLE) || !termok)
X {
X singlerefresh();
X return;
X }
X
X/* first, we generate the video line buffers so we know what to
X put on the screen.
X
X s = ptr into the video buffer.
X t = ptr into the real buffer.
X sen = end of the video buffer (eol)
X*/
X
X s = (unsigned char *)(nbuf[ln = 0]+pptlen);
X t = line;
X sen = (unsigned char *)(*nbuf+winw);


X for (; *t; t++)

X {
X if (icntrl((char)*t))
X if (*t == '\n')
X {
X if (t == scs)
X {
X nvcs = (char *)s-nbuf[nvln = ln];
X scs = (unsigned char *)NULL;
X }
X nextline
X }
X else if ((char)*t == '\t')
X {
X int t1 = (char *)s-nbuf[ln];
X
X if ((t1|7)+1 >= winw) nextline
X else
X do
X *s++ = ' ';
X while ((++t1) & 7);
X }
X else
X {
X if (s == sen) nextline
X *s++ = '^';
X if (s == sen) nextline
X *s++ = (*t == 127) ? '?' : (*t | '@');
X }
X else
X {
X if (s == sen) nextline
X *s++ = *t;
X }
X/* if the cursor is here, remember it */
X
X if (t == scs)
X nvcs = s-(unsigned char *)nbuf[nvln = ln]-1;
X }
X if (scs == t)
X nvcs = s-(unsigned char *)nbuf[nvln = ln];
X *s = '\0';
X nlnct = ln+1;
X if (statusline)
X strcpy(nbuf[(nlnct == winh) ? winh-1 : nlnct++],statusline);
X
X/* do RPROMPT */
X
X if (pmpt2 && ln == 0 && strlen(nbuf[0])+strlen(pmpt2) < winw)
X {
X for (t0 = strlen(nbuf[0]); t0 != winw; t0++)
X nbuf[0][t0] = ' ';
X strcpy(nbuf[0]+winw-strlen(pmpt2),pmpt2);
X }
X for (ln = 0; ln < nlnct; ln++)
X {
X
X/* if old line and new line are different,
X see if we can insert/delete a line */
X
X if (ln < olnct && strncmp(nbuf[ln],obuf[ln],16))
X {
X if (tccan(TCDELLINE) && !strncmp(nbuf[ln],obuf[ln+1],16)
X && obuf[ln+1][0] && ln != olnct)


X {
X int t0;
X

X moveto(ln,0);
X tcout(TCDELLINE);
X for (t0 = ln; t0 != olnct; t0++)
X strcpy(obuf[t0],obuf[t0+1]);
X olnct--;
X }
X
X/* don't try to insert a line if olnct < vmaxln (vmaxln is the number
X of lines that have been displayed by this routine) so that we don't
X go off the end of the screen. */
X
X else if (tccan(TCINSLINE) && !strncmp(nbuf[ln+1],obuf[ln],16) &&
X olnct < vmaxln && nbuf[ln+1][0] && ln != olnct)


X {
X int t0;
X

X moveto(ln,0);
X tcout(TCINSLINE);
X for (t0 = olnct; t0 != ln; t0--)
X strcpy(obuf[t0],obuf[t0-1]);
X *obuf[ln] = '\0';
X olnct++;
X }
X }
X refreshline(ln);
X }
X
X/* if old buffer had extra lines, do a clear-end-of-display if we can,
X otherwise, just fill new buffer with blank lines and refresh them */
X
X if (olnct > nlnct)
X {
X for (ln = nlnct; ln < olnct; ln++)
X nbuf[ln][0] = '\0';
X if (tccan(TCCLEAREOD))
X {
X moveto(nlnct,0);
X tcout(TCCLEAREOD);
X }
X else
X for (ln = nlnct; ln < olnct; ln++)
X refreshline(ln);
X }
X
X/* move to the new cursor position */
X
X moveto(nvln,nvcs);
X qbuf = nbuf;
X nbuf = obuf;
X obuf = qbuf;
X olnct = nlnct;
X if (nlnct > vmaxln)
X vmaxln = nlnct;
X fflush(stdout);
X}
X
X#define tcinscost(X) (tccan(TCMULTINS) ? tclen[TCMULTINS] : (X)*tclen[TCINS])
X#define tcdelcost(X) (tccan(TCMULTDEL) ? tclen[TCMULTDEL] : (X)*tclen[TCDEL])
X#define tc_delchars(X) tcmultout(TCDEL,TCMULTDEL,(X))
X#define tc_inschars(X) tcmultout(TCINS,TCMULTINS,(X))
X#define tc_upcurs(X) tcmultout(TCUP,TCMULTUP,(X))
X#define tc_leftcurs(X) tcmultout(TCLEFT,TCMULTLEFT,(X))
X
Xvoid refreshline(ln) /**/
Xint ln;
X{
Xchar *nl = nbuf[ln],*ol = obuf[ln];
Xchar *p1;
Xchar junk,*truncptr = &junk;
Xint ccs = 0;
X
X if (ln >= olnct)
X *ol = '\0';
X for (;;)
X {
X while (*nl && *nl == *ol)
X {
X nl++,ol++,ccs++;
X }
X if (!*nl && !*ol)
X { *truncptr = '\0'; return; }
X
X/* if this is the end of the new buffer but the old buffer has stuff
X here, clear to end of line if we can, otherwise fill the new buffer
X with blanks and continue. */
X
X if (!*nl)
X {
X if (tccan(TCCLEAREOL) && strlen(ol) > tclen[TCCLEAREOL])
X {
X moveto(ln,ccs);
X tcout(TCCLEAREOL);
X *ol = '\0';
X *truncptr = '\0';
X return;
X }
X else
X {
X int x = strlen(ol);
X char *p = nl;
X
X truncptr = p;
X while (x--)
X *p++ = ' ';


X *p = '\0';
X continue;
X }
X }

X
X/* if this is the end of the old buffer, just dump the rest of the
X new buffer. */
X
X if (!*ol)
X {
X while (*nl == ' ')
X nl++,ccs++;
X if (*nl)
X {
X moveto(ln,ccs);
X fwrite(nl,strlen(nl),1,stdout);
X cost += strlen(nl);
X ccs = (vcs += strlen(nl));
X }
X *truncptr = 0;
X return;
X }
X moveto(ln,ccs);
X
X/* try to insert/delete characters */
X
X if (ol[1] != nl[1] && tccan(TCDEL))
X {
X int ct = 0;
X
X for (p1 = ol; *p1; p1++,ct++)
X if (tcdelcost(ct) < streqct(p1,nl))
X {
X tc_delchars(ct);
X ol = p1;
X break;
X }
X if (*p1)
X continue;
X }
X
X if (ol[1] != nl[1] && tccan(TCINS))
X {
X int ct = 0;
X
X for (p1 = nl; *p1; p1++,ct++)
X if (tcinscost(ct) < streqct(p1,ol)+ct)
X {
X#if 0
X/* make sure we aren't inserting characters off the end of the screen;
X if we are, jump to the end and truncate the line, if we can do
X it quickly (gee, clever idea, Paul!) */
X if (ct+ccs+strlen(ol) >= winw-1)
X {
X if (!tccan(TCMULTRIGHT) || ccs > winw-tclen[TCMULTRIGHT])
X continue;
X moveto(ln,winw-1-ct);
X if (!tccan(TCCLEAREOL) || ct < tclen[TCCLEAREOL])
X {
X int x = ct;
X
X while (vcs++,x--)
X putchar(' ');
X }
X else
X tcout(TCCLEAREOL);
X moveto(ln,ccs);
X }
X#endif
X if (ct+ccs+strlen(ol) < winw-1)
X {
X tc_inschars(ct = p1-nl);
X ccs = (vcs += p1-nl);
X cost += ct;
X fwrite(nl,ct,1,stdout);
X nl += ct;
X break;
X }
X }
X if (*p1)
X continue;
X }
X
X/* if we can't do anything fancy, just write the new character and
X keep going. */
X
X putchar(*nl);
X cost++;
X nl++,ol++,ccs = ++vcs;
X }
X}
X
Xvoid moveto(ln,cl) /**/
Xint ln;int cl;
X{
X
X/* move up */
X
X if (ln < vln)
X {
X tc_upcurs(vln-ln);
X vln = ln;
X }
X
X/* move down; if we might go off the end of the screen, use newlines
X instead of TCDOWN */
X
X while (ln > vln)
X if (cl < (vcs/2) || ln >= vmaxln || !tccan(TCLEFT))
X {
X putchar('\r');
X putchar('\n');
X cost+=2;
X vln++;
X vcs = 0;
X }
X else
X {
X tc_downcurs(ln-vln);
X vln = ln;
X }
X if (cl < (vcs/2) || !tccan(TCLEFT))
X {
X putchar('\r');
X cost++;
X vcs = 0;
X }
X if (vcs < cl)
X tc_rightcurs(cl-vcs);
X else if (vcs > cl)
X tc_leftcurs(vcs-cl);
X vcs = cl;
X}
X
Xvoid tcmultout(cap,multcap,ct) /**/
Xint cap;int multcap;int ct;
X{
X if (tccan(multcap) && (!tccan(cap) || tclen[multcap] < tclen[cap]*ct))
X tcoutarg(multcap,ct);
X else while (ct--)
X tcout(cap);
X}
X
Xvoid tc_rightcurs(ct) /**/
Xint ct;
X{
X
X/* do a multright if it's cheaper or if we're walking over the prompt. */
X
X if (tccan(TCMULTRIGHT) &&
X (ct > tclen[TCMULTRIGHT] || vln == 0 && vcs < pptlen))
X tcoutarg(TCMULTRIGHT,ct);
X
X/* if we're walking over the prompt and we can do a bunch of cursor rights,
X do them, even though they're more expensive. (We can't redraw the
X prompt very easily in general.) */
X
X else if (vln == 0 && vcs < pptlen && tccan(TCRIGHT))
X while (ct--)
X tcout(TCRIGHT);
X
X/* otherwise write the contents of the video buffer. */
X
X else
X fwrite(nbuf[vln]+vcs,ct,1,stdout);
X}
X
Xvoid tc_downcurs(ct) /**/
Xint ct;
X{
X if (tccan(TCMULTDOWN) &&
X (!tccan(TCDOWN) || tclen[TCMULTDOWN] < tclen[TCDOWN]*ct))
X tcoutarg(TCMULTDOWN,ct);
X else if (tccan(TCDOWN))
X while (ct--)
X tcout(TCDOWN);
X else
X {
X while (ct--)
X putchar('\n');
X vcs = 0;
X }
X}
X
X/* I'm NOT going to worry about padding unless anyone complains. */
X
Xvoid tcout(cap) /**/
Xint cap;
X{
X tputs(tcstr[cap],1,putraw);
X}
X
Xvoid tcoutarg(cap,arg) /**/
Xint cap;int arg;
X{
X tputs(tgoto(tcstr[cap],arg,arg),1,putraw);
X}
X
Xvoid clearscreen() /**/
X{
X tcout(TCCLEARSCREEN);
X resetneeded = 1;
X}
X
Xvoid redisplay() /**/
X{
X trashzle();
X}
X
Xvoid trashzle() /**/
X{
X if (zleactive)
X {
X refresh();
X moveto(nlnct,0);
X printf("%s",postedit);
X fflush(stdout);
X unsetterm();
X resetneeded = 1;
X }
X}
X
Xvoid singlerefresh() /**/
X{
Xchar *vbuf,*vp,**qbuf,*op;
Xint t0,vsiz,nvcs;
X
X for (vsiz = 1+pptlen, t0 = 0; t0 != ll; t0++,vsiz++)
X if (line[t0] == '\t')
X vsiz += 7;
X else if (icntrl(line[t0]))
X vsiz++;
X vbuf = zalloc(vsiz);
X strcpy(vbuf,pmpt);
X vp = vbuf+pptlen;
X for (t0 = 0; t0 != ll; t0++)
X {
X if (line[t0] == '\t')
X do
X *vp++ = ' ';
X while ((vp-vbuf) & 7);
X else if (line[t0] == '\n')
X {
X *vp++ = '\\';
X *vp++ = 'n';
X }
X else if (line[t0] == 0x7f)
X {
X *vp++ = '^';
X *vp++ = '?';
X }
X else if (icntrl(line[t0]))
X {
X *vp++ = '^';
X *vp++ = line[t0] | '@';
X }
X else
X *vp++ = line[t0];
X if (t0 == cs)
X nvcs = vp-vbuf-1;
X }
X if (t0 == cs)
X nvcs = vp-vbuf;
X *vp = '\0';
X if ((winpos && nvcs < winpos+1) || (nvcs > winpos+winw-1))
X {
X if ((winpos = nvcs-(winw/2)) < 0)
X winpos = 0;
X }
X if (winpos)
X vbuf[winpos] = '<';
X if (strlen(vbuf+winpos) > winw)
X {
X vbuf[winpos+winw-1] = '>';
X vbuf[winpos+winw] = '\0';
X }
X strcpy(nbuf[0],vbuf+winpos);
X free(vbuf);
X nvcs -= winpos;
X for (t0 = 0,vp = *nbuf,op = *obuf; *vp; t0++,vp++)
X {
X if (*vp != *op && !(*vp == ' ' && !*op))
X {
X singmoveto(t0);
X putchar(*vp);
X vcs++;
X }
X if (*op)
X op++;
X }
X if (*op)
X {
X singmoveto(t0);
X for (; *op; op++)
X {
X putchar(' ');
X vcs++;
X }
X }
X singmoveto(nvcs);
X qbuf = nbuf;
X nbuf = obuf;
X obuf = qbuf;
X fflush(stdout);
X}
X
Xvoid singmoveto(pos) /**/
Xint pos;
X{
X while (pos < vcs)
X {
X vcs--;
X putchar('\b');
X }
X while (pos > vcs)
X {
X putchar(nbuf[0][vcs]);
X vcs++;
X }
X}
X
Xint streqct(s,t) /**/


Xchar *s;char *t;
X{

Xint ct = 0;
X

X while (*s && *s == *t) s++,t++,ct++;
SHAR_EOF
true || echo 'restore of zsh2.2/src/zle_refresh.c failed'
fi
echo 'End of zsh2.2 part 13'
echo 'File zsh2.2/src/zle_refresh.c is continued in part 14'
echo 14 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:09:36 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 110
Archive-name: zsh2.2/part14

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.14 (part 14 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/zle_refresh.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 14; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/zle_refresh.c'
else
echo 'x - continuing file zsh2.2/src/zle_refresh.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/zle_refresh.c' &&

X return ct;
X}
X
SHAR_EOF

echo 'File zsh2.2/src/zle_refresh.c is complete' &&
chmod 0644 zsh2.2/src/zle_refresh.c ||


echo 'restore of zsh2.2/src/zle_refresh.c failed'

Wc_c="`wc -c < 'zsh2.2/src/zle_refresh.c'`"
test 12058 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_refresh.c: original size 12058, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_utils.c ==============
if test -f 'zsh2.2/src/zle_utils.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_utils.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_utils.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_utils.c' &&
X/*
X *
X * zle_utils.c - miscellaneous line editor utilities


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#define ZLE
X#include "zsh.h"
X

X/* make sure that the line buffer has at least sz chars */
X
Xvoid sizeline(sz) /**/
Xint sz;
X{
X while (sz > linesz)
X line = (unsigned char *)realloc(line,(linesz *= 4)+1);
X}
X
X/* insert space for ct chars at cursor position */
X
Xvoid spaceinline(ct) /**/
Xint ct;
X{
Xint i;
X
X while (ct+ll > linesz)
X line = (unsigned char *)realloc(line,(linesz *= 4)+1);
X for (i = ll; i >= cs; i--)
X line[i+ct] = line[i];
X ll += ct;
X line[ll] = '\0';
X}
X
Xvoid backkill(ct,dir) /**/
Xint ct;int dir;
X{
Xint i = (cs -= ct);
X
X cut(i,ct,dir);
X while (line[i] = line[i+ct])
X i++;
X ll -= ct;
X}
X
Xvoid forekill(ct,dir) /**/
Xint ct;int dir;
X{
Xint i = cs;
X
X cut(i,ct,dir);
X while (line[i] = line[i+ct])
X i++;
X ll -= ct;
X}
X
Xvoid cut(i,ct,dir) /**/
Xint i;int ct;int dir;
X{
X if (vibufspec) {
X int owrite = 1;
X if (vibufspec >= 'A' && vibufspec <= 'Z') {
X owrite = 0; vibufspec = tolower(vibufspec);
X }
X vibufspec += (idigit(vibufspec)) ? - '1' +26 : - 'a';
X if (owrite || !vibuf[vibufspec]) {
X if (vibuf[vibufspec]) free(vibuf[vibufspec]);
X vibuf[vibufspec] = zalloc(ct+1);
X ztrncpy(vibuf[vibufspec],line+i,ct);
X } else {
X int len = strlen(vibuf[vibufspec]);
X vibuf[vibufspec] = realloc(vibuf[vibufspec],ct+len);
X ztrncpy(vibuf[vibufspec]+len,line+i,ct);
X }
X vibufspec = 0;
X return;
X }
X if (!cutbuf)
X cutbuf = ztrdup("");
X else if (!(lastcmd & ZLE_KILL)) {
X kringnum = (kringnum+1)&(KRINGCT-1);
X if (kring[kringnum])
X free(kring[kringnum]);
X kring[kringnum] = cutbuf;
X cutbuf = ztrdup("");
X }
X if (dir) {
X char *s = zalloc(strlen(cutbuf)+ct+1);
X strncpy(s,(char *) line+i,ct);
X strcpy(s+ct,cutbuf);
X free(cutbuf);
X cutbuf = s;
X } else {
X int x;
X
X cutbuf = realloc(cutbuf,(x = strlen(cutbuf))+ct+1);
X ztrncpy(cutbuf+x,line+i,ct);
X }
X}
X
Xvoid backdel(ct) /**/
Xint ct;
X{
Xint i = (cs -= ct);
X
X while (line[i] = line[i+ct])
X i++;
X ll -= ct;
X}
X
Xvoid foredel(ct) /**/
Xint ct;
X{
Xint i = cs;
X
X while (line[i] = line[i+ct])
X i++;
X ll -= ct;
X}
X
Xvoid setline(s) /**/
Xchar *s;
X{
X sizeline(strlen(s));
X strcpy((char *) line,s);
X cs = ll = strlen(s);
X if (cs && bindtab == altbindtab) cs--;
X}
X
Xvoid sethistline(s) /**/
Xunsigned char *s;
X{
X setline(s);
X for (s = line; *s; s++)
X if (*s == (unsigned char)HISTSPACE)
X *s = ' ';
X}
X
Xint findbol() /**/
X{
Xint x = cs;
X
X while (x > 0 && line[x-1] != '\n') x--;


X return x;
X}
X

Xint findeol() /**/
X{
Xint x = cs;
X
X while (x != ll && line[x] != '\n') x++;


X return x;
X}
X

Xvoid findline(a,b) /**/
Xint *a;int *b;
X{
X *a = findbol();
X *b = findeol();
X}
X
Xstatic int lastlinelen;
X
Xvoid initundo() /**/
X{
Xint t0;
X
X for (t0 = 0; t0 != UNDOCT; t0++)
X undos[t0].change = NULL;
X undoct = 0;
X lastline = zalloc(lastlinelen = (ll+1 < 32) ? 32 : ll+1);
X strcpy((char *) lastline,(char *) line);
X lastcs = cs;
X}
X
Xvoid addundo() /**/
X{
Xint pf,sf;
Xunsigned char *s,*s2,*t,*t2;
Xstruct undoent *ue;
X
X for (s = line, t = lastline; *s && *s==*t; s++,t++);
X if (!*s && !*t)
X return;
X pf = s-line;
X for (s2 = (unsigned char *)line+strlen((char *) line),
X t2 = lastline+strlen((char *) lastline);
X s2 > s && t > t2 && s2[-1] == t2[-1]; s2--,t2--);
X sf = strlen((char *) s2);
X ue = undos+(undoct = (UNDOCT-1) & (undoct+1));
X ue->pref = pf;
X ue->suff = sf;
X ue->len = t2-t;
X ue->cs = lastcs;
X strncpy(ue->change = halloc(ue->len),(char *) t,ue->len);
X while (ll+1 > lastlinelen)
X {
X free(lastline);
X lastline = zalloc(lastlinelen *= 2);
X }
X strcpy((char *) lastline,(char *) line);
X lastcs = cs;
X}
X
Xvoid freeundo() /**/
X{
X free(lastline);
X}
X
Xint hstrncmp(s,t,len) /**/


Xchar *s;char *t;int len;
X{

X while (len && *s && (*s == *t || (*s == ' ' && *t == HISTSPACE) ||
X (*s == HISTSPACE && *t == ' ')))
X s++,t++,len--;
X return len;
X}
X
Xint hstrcmp(s,t) /**/


Xchar *s;char *t;
X{

X while (*s && (*s == *t || (*s == ' ' && *t == HISTSPACE) ||
X (*s == HISTSPACE && *t == ' ')))
X s++,t++;
X return !(*s == '\0' && *t == '\0');
X}
X
Xchar *hstrnstr(s,t,len) /**/
Xchar *s;char *t;int len;


X{
X for (; *s; s++)

X if (!hstrncmp(t,s,len))
X return s;
X return NULL;
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/zle_utils.c ||
echo 'restore of zsh2.2/src/zle_utils.c failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_utils.c'`"
test 4690 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_utils.c: original size 4690, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zsh.h ==============
if test -f 'zsh2.2/src/zsh.h' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zsh.h (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zsh.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zsh.h' &&
X/*
X *
X * zsh.h - standard header file


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#include "config.h"
X
X#include <stdio.h>
X#include <ctype.h>
X
X#ifdef HAS_STRING
X#include <string.h>
X#else
X#include <strings.h>
X#endif
X
X#ifdef HAS_LOCALE
X#include <locale.h>
X#endif
X
X#ifdef HAS_STDLIB
X#include <stdlib.h>
X#endif
X
X#ifdef SYSV
X#include <sys/bsdtypes.h>
X#define _POSIX_SOURCE
X#include <sys/limits.h>
X#include <sys/sioctl.h>
X#define MAXPATHLEN PATH_MAX
X#define lstat stat
Xextern int gethostname();
X#define sigmask(m) m
X#include <sys/dirent.h>
X#else
X#include <sys/types.h> /* this is the key to the whole thing */
X#endif
X
X#ifdef _IBMR2
X#undef _BSD /* union wait SUCKS! */
X#include <sys/wait.h>
X#define _BSD
X#else
X#include <sys/wait.h>
X#endif
X
X#include <sys/time.h>
X
X#ifndef SYSV
X#include <sys/resource.h>
X#endif
X
X#include <sys/file.h>
X#include <signal.h>
X
X#ifdef TERMIO
X#define VDISABLEVAL -1
X#define TIO 1
X#include <sys/termio.h>
X#else
X#ifdef TERMIOS
X#define VDISABLEVAL 0
X#define TIO 1
X#include <termios.h>
X#else
X#include <sgtty.h>
X#endif
X#endif
X
X#ifdef SYSV
X#undef TIOCGWINSZ
X#endif
X
X#include <sys/param.h>
X#include <sys/times.h>
X
X#ifdef SYSV
X#undef _POSIX_SOURCE
X#endif
X
X#ifdef __hp9000s800
X#include <sys/bsdtty.h>
X#endif
X
X#ifndef sun
X#include <sys/ioctl.h>
X#else
X#include <sys/filio.h>
X#endif
X
X#define VERSIONSTR "zsh v2.2.0"
X
X#if 0 /* __STDC__ */
X#include <unistd.h>
X#include <fcntl.h>
X#include <stat.h>
X#define DCLPROTO(X) X
X#undef NULL
X#define NULL ((void *)0)
X#else /* not __STDC__ */
X#include <sys/stat.h>
X#define DCLPROTO(X) ()
X#ifndef NULL
X#define NULL 0
X#endif
X#endif /* __STDC__ */
X
X#ifdef QDEBUG
X#define DCLPROTO(X) X
X#endif
X
X#define DEFWORDCHARS "*?_-.[]~=/&;!#$%^(){}<>"
X#define DEFTIMEFMT "%E real %U user %S system %P %J"
X#ifdef UTMP_HOST
X#define DEFWATCHFMT "%n has %a %l from %m."
X#else
X#define DEFWATCHFMT "%n has %a %l."
X#endif
X
X#ifdef GLOBALS
X#define EXTERN
X#else
X#define EXTERN extern
X#endif
X
X#ifdef HAS_STRING
X#define killpg(pgrp,sig) kill(-(pgrp),sig)
X#endif
X
X#ifndef F_OK
X#define F_OK 00
X#define R_OK 04
X#define W_OK 02
X#define X_OK 01
X#endif
X
X#include "zle.h"
X
X/* size of job list */
X
X#define MAXJOB 80
X
X/* memory allocation routines - changed with permalloc()/heapalloc() */
X
Xvptr (*alloc)DCLPROTO((int));
Xvptr (*ncalloc)DCLPROTO((int));
X
X#define addhnode(A,B,C,D) Addhnode(A,B,C,D,1)
X#define addhperm(A,B,C,D) Addhnode(A,B,C,D,0)
X
X/* character tokens */
X
X#define ALPOP ((char) 0x81)
X#define HISTSPACE ((char) 0x83)
X#define Pound ((char) 0x84)
X#define String ((char) 0x85)
X#define Hat ((char) 0x86)
X#define Star ((char) 0x87)
X#define Inpar ((char) 0x88)
X#define Outpar ((char) 0x89)
X#define Qstring ((char) 0x8a)
X#define Equals ((char) 0x8b)
X#define Bar ((char) 0x8c)
X#define Inbrace ((char) 0x8d)
X#define Outbrace ((char) 0x8e)
X#define Inbrack ((char) 0x8f)
X#define Outbrack ((char) 0x90)
X#define Tick ((char) 0x91)
X#define Inang ((char) 0x92)
X#define Outang ((char) 0x93)
X#define Quest ((char) 0x94)
X#define Tilde ((char) 0x95)
X#define Qtick ((char) 0x96)
X#define Comma ((char) 0x97)
X#define Nularg ((char) 0x98)
X
X/* chars that need to be quoted if meant literally */
X
X#define SPECCHARS "#$^*()$=|{}[]`<>?~;&!\n\t \\\'\""
X
X/* ALPOP in the form of a string */
X
X#define ALPOPS " \201"
X#define HISTMARK "\201"
X
X#define SEPER 1
X#define NEWLIN 2
X#define LEXERR 3
X#define SEMI 4
X#define DSEMI 5
X#define AMPER 6
X#define INPAR 7
X#define INBRACE 8
X#define OUTPAR 9
X#define DBAR 10
X#define DAMPER 11
X#define BANG 12
X#define OUTBRACE 13
X#define OUTANG 14
X#define OUTANGBANG 15
X#define DOUTANG 16
X#define DOUTANGBANG 17
X#define INANG 18
X#define DINANG 19
X#define DINANGDASH 20
X#define INANGAMP 21
X#define OUTANGAMP 22
X#define OUTANGAMPBANG 23
X#define DOUTANGAMP 24
X#define DOUTANGAMPBANG 25
X#define TRINANG 26
X#define BAR 27
X#define BARAMP 28
X#define DINBRACK 29
X#define DOUTBRACK 30
X#define STRING 31
X#define ENVSTRING 32
X#define ENVARRAY 33
X#define ENDINPUT 34
X#define INOUTPAR 35
X#define DO 36
X#define DONE 37
X#define ESAC 38
X#define THEN 39
X#define ELIF 40
X#define ELSE 41
X#define FI 42
X#define FOR 43
X#define CASE 44
X#define IF 45
X#define WHILE 46
X#define FUNC 47
X#define REPEAT 48
X#define TIME 49
X#define UNTIL 50
X#define EXEC 51
X#define COMMAND 52
X#define SELECT 53
X#define COPROC 54
X#define NOGLOB 55
X#define DASH 56
X#define NOCORRECT 57
X#define FOREACH 58
X#define ZEND 59
X
X#define WRITE 0
X#define WRITENOW 1
X#define APP 2
X#define APPNOW 3
X#define MERGEOUT 4
X#define MERGEOUTNOW 5
X#define ERRAPP 6
X#define ERRAPPNOW 7
X#define READ 8
X#define HEREDOC 9
X#define HEREDOCDASH 10
X#define HERESTR 11
X#define MERGE 12
X#define CLOSE 13
X#define INPIPE 14
X#define OUTPIPE 15
X#define NONE 16
X
X#ifdef GLOBALS
Xint redirtab[TRINANG-OUTANG+1] = {
X WRITE,
X WRITENOW,
X APP,
X APPNOW,
X READ,
X HEREDOC,
X HEREDOCDASH,
X MERGE,
X MERGEOUT,
X MERGEOUTNOW,
X ERRAPP,
X ERRAPPNOW,
X HERESTR,
X};
X#else
Xint redirtab[TRINANG-OUTANG+1];
X#endif
X
X#define IS_READFD(X) ((X)>=READ && (X)<=MERGE)
X#define IS_REDIROP(X) ((X)>=OUTANG && (X)<=TRINANG)
X#define IS_ERROR_REDIR(X) ((X)>=MERGEOUT && (X)<=ERRAPPNOW)
X#define UN_ERROR_REDIR(X) ((X)-MERGEOUT+WRITE)
X
X#define FD_WORD -1
X#define FD_COPROC -2
X#define FD_CLOSE -3
X
XEXTERN char **environ;
X
Xtypedef struct hashtab *Hashtab;
Xtypedef struct hashnode *Hashnode;
Xtypedef struct schedcmd *Schedcmd;
Xtypedef struct alias *Alias;
Xtypedef struct process *Process;
Xtypedef struct job *Job;
Xtypedef struct value *Value;
Xtypedef struct arrind *Arrind;
Xtypedef struct varasg *Varasg;
Xtypedef struct param *Param;
Xtypedef struct cmdnam *Cmdnam;
Xtypedef struct cond *Cond;
Xtypedef struct cmd *Cmd;
Xtypedef struct pline *Pline;
Xtypedef struct sublist *Sublist;
Xtypedef struct list *List;
Xtypedef struct lklist *Lklist;
Xtypedef struct lknode *Lknode;
Xtypedef struct comp *Comp;
Xtypedef struct redir *Redir;
Xtypedef struct complist *Complist;
Xtypedef struct heap *Heap;
Xtypedef struct histent *Histent;
Xtypedef struct hp *Hp;
Xtypedef struct compctl *Compctl;
Xtypedef void (*FFunc)DCLPROTO((vptr));
Xtypedef vptr (*VFunc)DCLPROTO((vptr));
Xtypedef void (*HFunc)DCLPROTO((char *,char *));
X
X/* linked list abstract data type */
X
Xstruct lknode;
Xstruct lklist;
X
Xstruct lknode {
X Lknode next,last;
X vptr dat;
X };
Xstruct lklist {
X Lknode first,last;
X };
X
X#define addnode(X,Y) insnode(X,(X)->last,Y)
X#define full(X) ((X)->first != NULL)
X#define firstnode(X) ((X)->first)
X#define getaddrdata(X) (&((X)->dat))
X#define getdata(X) ((X)->dat)
X#define setdata(X,Y) ((X)->dat = (Y))
X#define lastnode(X) ((X)->last)
X#define nextnode(X) ((X)->next)
X#define prevnode(X) ((X)->last)
X#define peekfirst(X) ((X)->first->dat)
X#define pushnode(X,Y) insnode(X,(Lknode) X,Y)
X#define incnode(X) (X = nextnode(X))
X#define gethistent(X) (histentarr+((X)%histentct))
X
X/* node structure for syntax trees */
X
X/* struct list, struct sublist, struct pline, etc. all fit the form
X of this structure and are used interchangably
X*/
X
Xstruct node {
X int data[4]; /* arbitrary integer data */
X vptr ptrs[4]; /* arbitrary pointer data */
X int types[4]; /* what ptrs[] are pointing to */
X int type; /* node type */
X };
X
X#define N_LIST 0
X#define N_SUBLIST 1
X#define N_PLINE 2
X#define N_CMD 3
X#define N_REDIR 4
X#define N_COND 5
X#define N_FOR 6
X#define N_CASE 7
X#define N_IF 8
X#define N_WHILE 9
X#define N_VARASG 10
X#define N_COUNT 11
X
X/* values for types[4] */
X
X#define NT_EMPTY 0
X#define NT_NODE 1
X#define NT_STR 2
X#define NT_LIST 4
X#define NT_MALLOC 8
X
X/* tree element for lists */
X
Xstruct list {
X int type;
X int ifil[3]; /* to fit struct node */
X Sublist left;
X List right;
X };
X
X#define SYNC 0 /* ; */
X#define ASYNC 1 /* & */
X#define TIMED 2
X
X/* tree element for sublists */
X
Xstruct sublist {
X int type;
X int flags; /* see PFLAGs below */
X int ifil[2];
X Pline left;
X Sublist right;
X };
X
X#define ORNEXT 10 /* || */
X#define ANDNEXT 11 /* && */
X
X#define PFLAG_NOT 1 /* ! ... */
X#define PFLAG_COPROC 32 /* coproc ... */
X
X/* tree element for pipes */
X
Xstruct pline {
X int type;
X int ifil[3];
X Cmd left;
X Pline right;
X };
X
X#define END 0 /* pnode *right is null */
X#define PIPE 1 /* pnode *right is the rest of the pipeline */
X
X/* tree element for commands */
X
Xstruct cmd {
X int type;
X int flags; /* see CFLAGs below */
X int ifil[2];
X Lklist args; /* command & argmument List (char *'s) */
X union {
X List list; /* for SUBSH/CURSH/SHFUNC */
X struct forcmd *forcmd;
X struct casecmd *casecmd;
X struct ifcmd *ifcmd;
X struct whilecmd *whilecmd;
X Sublist pline;
X Cond cond;
X } u;
X Lklist redir; /* i/o redirections (struct redir *'s) */
X Lklist vars; /* param assignments (struct varasg *'s) */
X };
X
X#define SIMPLE 0
X#define SUBSH 1
X#define CURSH 2
X#define ZCTIME 3
X#define FUNCDEF 4
X#define CFOR 5
X#define CWHILE 6
X#define CREPEAT 7
X#define CIF 8
X#define CCASE 9
X#define CSELECT 10
X#define COND 11
X
X#define CFLAG_EXEC 1 /* exec ... */
X#define CFLAG_COMMAND 2 /* command ... */
X#define CFLAG_NOGLOB 4 /* noglob ... */
X#define CFLAG_DASH 8 /* - ... */
X
X/* tree element for redirection lists */
X
Xstruct redir {
X int type,fd1,fd2,ifil;
X char *name;
X };
X
X/* tree element for conditionals */
X
Xstruct cond {
X int type; /* can be cond_type, or a single letter (-a, -b, ...) */
X int ifil[3];
X vptr left,right,vfil[2];
X int types[4],typ; /* from struct node. DO NOT REMOVE */
X };
X
X#define COND_NOT 0
X#define COND_AND 1
X#define COND_OR 2
X#define COND_STREQ 3
X#define COND_STRNEQ 4
X#define COND_STRLT 5
X#define COND_STRGTR 6
X#define COND_NT 7
X#define COND_OT 8
X#define COND_EF 9
X#define COND_EQ 10
X#define COND_NE 11
X#define COND_LT 12
X#define COND_GT 13
X#define COND_LE 14
X#define COND_GE 15
X
Xstruct forcmd { /* for/select */
X /* Cmd->args contains list of words to loop thru */
X int inflag; /* if there is an in ... clause */
X int ifil[3];
X char *name; /* parameter to assign values to */
X List list; /* list to look through for each name */
X };
Xstruct casecmd {
X /* Cmd->args contains word to test */
X int ifil[4];
X struct casecmd *next;
X char *pat;
X List list; /* list to execute */
X };
X
X/*
X
X a command like "if foo then bar elif baz then fubar else fooble"
X generates a tree like:
X
X struct ifcmd a = { next = &b, ifl = "foo", thenl = "bar" }
X struct ifcmd b = { next = &c, ifl = "baz", thenl = "fubar" }
X struct ifcmd c = { next = NULL, ifl = NULL, thenl = "fooble" }
X
X*/
X
Xstruct ifcmd {
X int ifil[4];
X struct ifcmd *next;
X List ifl;
X List thenl;
X };
X
Xstruct whilecmd {
X int cond; /* 0 for while, 1 for until */
X int ifil[3];
X List cont; /* condition */
X List loop; /* list to execute until condition met */
X };
X
X/* structure used for multiple i/o redirection */
X/* one for each fd open */
X
Xstruct multio {
X int ct; /* # of redirections on this fd */
X int rflag; /* 0 if open for reading, 1 if open for writing */
X int pipe; /* fd of pipe if ct > 1 */
X int fds[NOFILE]; /* list of src/dests redirected to/from this fd */
X };
X
X/* node used in command path hash table (cmdnamtab) */
X
Xstruct cmdnam
X{


X struct hashnode *next; int canfree; char *nam; /* hash data */

X int type,flags;
X union {
X char *nam; /* full pathname if type != BUILTIN */
X int binnum; /* func to exec if type == BUILTIN */
X List list; /* list to exec if type == SHFUNC */
X } u;
X char **pcomp; /* location in path for EXCMD's */
X };
X
X#define EXCMD 0
X#define BUILTIN 2
X#define SHFUNC 3
X#define DISABLED 4
X#define ISEXCMD(X) ((X)==EXCMD)
X
X/* node used in parameter hash table (paramtab) */
X
Xstruct param {


X struct hashnode *next; int canfree; char *nam; /* hash data */

X union {
X char **arr; /* value if declared array */
X char *str; /* value if declared string (scalar) */
X long val; /* value if declared integer */
X } u;
X union { /* functions to call to set value */
X void (*cfn)DCLPROTO((Param,char *));
X void (*ifn)DCLPROTO((Param,long));
X void (*afn)DCLPROTO((Param,char **));
X } sets;
X union { /* functions to call to get value */
X char *(*cfn)DCLPROTO((Param));
X long (*ifn)DCLPROTO((Param));
X char **(*afn)DCLPROTO((Param));
X } gets;
X int ct; /* output base or field width */
X int flags;


X vptr data; /* used by getfns */
X char *env; /* location in environment, if exported */
X char *ename; /* name of corresponding environment var */
X };
X

X#define PMFLAG_s 0 /* scalar */
X#define PMFLAG_L 1 /* left justify and remove leading blanks */
X#define PMFLAG_R 2 /* right justify and fill with leading blanks */
X#define PMFLAG_Z 4 /* right justify and fill with leading zeros */
X#define PMFLAG_i 8 /* integer */
X#define PMFLAG_l 16 /* all lower case */
X#define PMFLAG_u 32 /* all upper case */
X#define PMFLAG_r 64 /* readonly */
X#define PMFLAG_t 128 /* tagged */
X#define PMFLAG_x 256 /* exported */
X#define PMFLAG_A 512 /* array */
X#define PMFLAG_SPECIAL 1024
X#define PMTYPE (PMFLAG_i|PMFLAG_A)
X#define pmtype(X) ((X)->flags & PMTYPE)
X
X/* variable assignment tree element */
X
Xstruct varasg {
X int type; /* nonzero means array */
X int ifil[3];
X char *name;
X char *str; /* should've been a union here. oh well */
X Lklist arr;
X };
X
X/* lvalue for variable assignment/expansion */
X
Xstruct value {
X int isarr;
X struct param *pm; /* parameter node */
X int a; /* first element of array slice, or -1 */
X int b; /* last element of array slice, or -1 */
X };
X
Xstruct fdpair {
X int fd1,fd2;
X };
X
X/* tty state structure */
X
Xstruct ttyinfo {
X#ifdef TERMIOS
X struct termios tio;
X#else
X#ifdef TERMIO
X struct termio tio;
X#else
X struct sgttyb sgttyb;
X int lmodes;
X struct tchars tchars;
X struct ltchars ltchars;
X#endif
X#endif
X#ifdef TIOCGWINSZ
X struct winsize winsize;
X#endif
X };
X
XEXTERN struct ttyinfo savedttyinfo;
X
X/* entry in job table */
X
Xstruct job {
X long gleader; /* process group leader of this job */
X int stat;
X char *pwd; /* current working dir of shell when
X this job was spawned */
X struct process *procs; /* list of processes */
X Lklist filelist; /* list of files to delete when done */
X };
X
X#define STAT_CHANGED 1 /* status changed and not reported */
X#define STAT_STOPPED 2 /* all procs stopped or exited */
X#define STAT_TIMED 4 /* job is being timed */
X#define STAT_DONE 8
X#define STAT_LOCKED 16 /* shell is finished creating this job,
X may be deleted from job table */
X#define STAT_INUSE 64 /* this job entry is in use */
X
X#define SP_RUNNING -1 /* fake statusp for running jobs */
X
X#ifndef RUSAGE_CHILDREN
X#undef HAS_RUSAGE
X#endif
X
Xstruct timeinfo {
X#ifdef HAS_RUSAGE
X struct rusage ru;
X#else
X long ut, st;
X#endif
X};
X
X/* node in job process lists */
X
X#define JOBTEXTSIZE 80
X
Xstruct process {
X struct process *next;
X long pid;
X char text[JOBTEXTSIZE]; /* text to print when 'jobs' is run */
X int statusp; /* return code from wait3() */
X struct timeinfo ti;
X time_t bgtime; /* time job was spawned */
X time_t endtime; /* time job exited */
X };
X
X/* node in alias hash table */
X
Xstruct alias {


X struct hashnode *next; int canfree; char *nam; /* hash data */

X char *text; /* expansion of alias */
X int cmd; /* one for regular aliases,
X zero for global aliases,
X negative for reserved words */
X int inuse; /* alias is being expanded */
X };
X
X/* node in sched list */
X
Xstruct schedcmd {
X struct schedcmd *next;
X char *cmd; /* command to run */
X time_t time; /* when to run it */
X };
X
X#define MAXAL 20 /* maximum number of aliases expanded at once */
X
X/* hash table node */
X
Xstruct hashnode {
X struct hashnode *next;
X int canfree; /* nam is free()able */


X char *nam;
X };
X

X/* hash table */
X
Xstruct hashtab {
X int hsize; /* size of nodes[] */
X int ct; /* # of elements */
X struct hashnode **nodes; /* array of size hsize */
X };
X
X/* history entry */
X
Xstruct histent {
X char *lex; /* lexical history line */
X char *lit; /* literal history line */
X time_t stim; /* command started time (datestamp) */
X time_t ftim; /* command finished time */
X };
X
X/* completion control */
X
Xstruct compctl {


X struct hashnode *next; int canfree; char *nam; /* hash data */

X int mask;
X char *keyvar;
X };
X
X#define CC_FILES 1
X#define CC_COMMPATH 2
X#define CC_HOSTS 4
X#define CC_OPTIONS 8
X#define CC_VARS 16
X#define CC_BINDINGS 32
X#define CC_USRKEYS 64
X
Xextern char *sys_errlist[];
Xextern int errno;
X
X/* values in opts[] array */
X
X#define OPT_INVALID 1 /* opt is invalid, like -$ */
X#define OPT_UNSET 0
X#define OPT_SET 2
X
X/* the options */
X
Xstruct option {
X char *name;
X char id; /* corresponding letter */
X };
X
X#define CORRECT '0'
X#define NOCLOBBER '1'
X#define NOBADPATTERN '2'
X#define NONOMATCH '3'
X#define GLOBDOTS '4'
X#define NOTIFY '5'
X#define BGNICE '6'
X#define IGNOREEOF '7'
X#define MARKDIRS '8'
X#define AUTOLIST '9'
X#define NOBEEP 'B'
X#define PRINTEXITVALUE 'C'
X#define PUSHDTOHOME 'D'
X#define PUSHDSILENT 'E'
X#define NOGLOBOPT 'F'
X#define NULLGLOB 'G'
X#define RMSTARSILENT 'H'
X#define IGNOREBRACES 'I'
X#define AUTOCD 'J'
X#define NOBANGHIST 'K'
X#define SUNKEYBOARDHACK 'L'
X#define SINGLELINEZLE 'M'
X#define AUTOPUSHD 'N'
X#define CORRECTALL 'O'
X#define RCEXPANDPARAM 'P'
X#define PATHDIRS 'Q'
X#define LONGLISTJOBS 'R'
X#define RECEXACT 'S'
X#define CDABLEVARS 'T'
X#define MAILWARNING 'U'
X#define NOPROMPTCR 'V'
X#define AUTORESUME 'W'
X#define LISTTYPES 'X'
X#define MENUCOMPLETE 'Y'
X#define USEZLE 'Z'
X#define ALLEXPORT 'a'
X#define ERREXIT 'e'
X#define NORCS 'f'
X#define HISTIGNORESPACE 'g'
X#define HISTIGNOREDUPS 'h'
X#define INTERACTIVE 'i'
X#define HISTLIT 'j'
X#define INTERACTIVECOMMENTS 'k'
X#define LOGINSHELL 'l'
X#define MONITOR 'm'
X#define NOEXEC 'n'
X#define SHINSTDIN 's'
X#define NOUNSET 'u'
X#define VERBOSE 'v'
X#define CHASELINKS 'w'
X#define XTRACE 'x'
X#define SHWORDSPLIT 'y'
X#define MENUCOMPLETEBEEP '\2'
X#define HISTNOSTORE '\3'
X#define EXTENDEDGLOB '\5'
X#define GLOBCOMPLETE '\6'
X#define CSHJUNKIEQUOTES '\7'
X#define PUSHDMINUS '\10'
X#define CSHJUNKIELOOPS '\11'
X#define RCQUOTES '\12'
X#define KSHOPTIONPRINT '\13'
X#define NOSHORTLOOPS '\14'
X#define LASTMENU '\15'
X#define AUTOMENU '\16'
X#define HISTVERIFY '\17'
X#define NOLISTBEEP '\20'
X#define NOHUP '\21'
X#define NOEQUALS '\22'
X#define CSHNULLGLOB '\23'
X#define HASHCMDS '\24'
X#define HASHDIRS '\25'
X#define NUMERICGLOBSORT '\26'
X#define BRACECCL '\27'
X#define HASHLISTALL '\30'
X#define OVERSTRIKE '\31'
X#define NOHISTBEEP '\32'
X#define PUSHDIGNOREDUPS '\33'
X#define AUTOREMOVESLASH '\34'
X
X#ifndef GLOBALS
Xextern struct option optns[];
X#else
Xstruct option optns[] = {
X "correct",CORRECT,
X "noclobber",NOCLOBBER,
X "nobadpattern",NOBADPATTERN,
X "nonomatch",NONOMATCH,
X "globdots",GLOBDOTS,
X "notify",NOTIFY,
X "bgnice",BGNICE,
X "ignoreeof",IGNOREEOF,
X "markdirs",MARKDIRS,
X "autolist",AUTOLIST,
X "nobeep",NOBEEP,
X "printexitvalue",PRINTEXITVALUE,
X "pushdtohome",PUSHDTOHOME,
X "pushdsilent",PUSHDSILENT,
X "noglob",NOGLOBOPT,
X "nullglob",NULLGLOB,
X "rmstarsilent",RMSTARSILENT,
X "ignorebraces",IGNOREBRACES,
X "braceccl",BRACECCL,
X "autocd",AUTOCD,
X "nobanghist",NOBANGHIST,
X "sunkeyboardhack",SUNKEYBOARDHACK,
X "singlelinezle",SINGLELINEZLE,
X "autopushd",AUTOPUSHD,
X "correctall",CORRECTALL,
X "rcexpandparam",RCEXPANDPARAM,
X "pathdirs",PATHDIRS,
X "longlistjobs",LONGLISTJOBS,
X "recexact",RECEXACT,
X "cdablevars",CDABLEVARS,
X "mailwarning",MAILWARNING,
X "nopromptcr",NOPROMPTCR,
X "autoresume",AUTORESUME,
X "listtypes",LISTTYPES,
X "menucomplete",MENUCOMPLETE,
X "zle",USEZLE,
X "allexport",ALLEXPORT,
X "errexit",ERREXIT,
X "norcs",NORCS,
X "histignorespace",HISTIGNORESPACE,
X "histignoredups",HISTIGNOREDUPS,
X "interactive",INTERACTIVE,
X "histlit",HISTLIT,
X "interactivecomments",INTERACTIVECOMMENTS,
X "login",LOGINSHELL,
X "monitor",MONITOR,
X "noexec",NOEXEC,
X "shinstdin",SHINSTDIN,
X "nounset",NOUNSET,
X "verbose",VERBOSE,
X "chaselinks",CHASELINKS,
X "xtrace",XTRACE,
X "shwordsplit",SHWORDSPLIT,
X "menucompletebeep",MENUCOMPLETEBEEP,
X "histnostore",HISTNOSTORE,
X "extendedglob",EXTENDEDGLOB,
X "globcomplete",GLOBCOMPLETE,
X "cshjunkiequotes",CSHJUNKIEQUOTES,
X "pushdminus",PUSHDMINUS,
X "cshjunkieloops",CSHJUNKIELOOPS,
X "rcquotes",RCQUOTES,
X "noshortloops",NOSHORTLOOPS,
X "lastmenu",LASTMENU,
X "automenu",AUTOMENU,
X "histverify",HISTVERIFY,
X "nolistbeep",NOLISTBEEP,
X "nohup",NOHUP,
X "noequals",NOEQUALS,
X "kshoptionprint",KSHOPTIONPRINT,
X "cshnullglob",CSHNULLGLOB,
X "hashcmds",HASHCMDS,
X "hashdirs",HASHDIRS,
X "numericglobsort",NUMERICGLOBSORT,
X "hashlistall",HASHLISTALL,
X "overstrike",OVERSTRIKE,
X "nohistbeep",NOHISTBEEP,
X "pushdignoredups",PUSHDIGNOREDUPS,
X "autoremoveslash",AUTOREMOVESLASH,
X NULL,0
X};
X#endif
X
X#define ALSTAT_MORE 1 /* last alias ended with ' ' */
X#define ALSTAT_JUNK 2 /* don't put word in history List */
X
X#undef isset
X#define isset(X) (opts[X])
X#define unset(X) (!opts[X])
X#define interact (isset(INTERACTIVE))
X#define jobbing (isset(MONITOR))
X#define nointr() signal(SIGINT,SIG_IGN)
X#define islogin (isset(LOGINSHELL))
X
X#ifndef _IBMR2
X#undef WIFSTOPPED
X#undef WIFSIGNALED
X#undef WIFEXITED
X#undef WEXITSTATUS
X#undef WTERMSIG
X#undef WSTOPSIG
X#undef WCOREDUMPED
X
X#define WIFSTOPPED(X) (((X)&0377)==0177)
X#define WIFSIGNALED(X) (((X)&0377)!=0&&((X)&0377)!=0177)
X#define WIFEXITED(X) (((X)&0377)==0)
X#define WEXITSTATUS(X) (((X)>>8)&0377)
X#define WTERMSIG(X) ((X)&0177)
X#define WSTOPSIG(X) (((X)>>8)&0377)
X#endif
X#define WCOREDUMPED(X) ((X)&0200)
X
X#ifndef S_ISBLK
X#define _IFMT 0170000
X#define _IFDIR 0040000
X#define _IFCHR 0020000
X#define _IFBLK 0060000
X#define _IFREG 0100000
X#define _IFIFO 0010000
X#define S_ISBLK(m) (((m)&_IFMT) == _IFBLK)
X#define S_ISCHR(m) (((m)&_IFMT) == _IFCHR)
X#define S_ISDIR(m) (((m)&_IFMT) == _IFDIR)
X#define S_ISFIFO(m) (((m)&_IFMT) == _IFIFO)
X#define S_ISREG(m) (((m)&_IFMT) == _IFREG)
X#endif
X
X#ifndef S_ISSOCK
X#ifndef _IFMT
X#define _IFMT 0170000
X#endif
X#define _IFLNK 0120000
X#define _IFSOCK 0140000
X#define S_ISLNK(m) (((m)&_IFMT) == _IFLNK)
X#define S_ISSOCK(m) (((m)&_IFMT) == _IFSOCK)
X#endif
X
X#if S_IFIFO == S_IFSOCK
X#undef S_IFIFO
X#endif
X
X#ifndef S_IFIFO
X#define NO_FIFOS
X#endif
X
X/* buffered shell input for non-interactive shells */
X
XEXTERN FILE *bshin;
X
X/* NULL-terminated arrays containing path, cdpath, etc. */
X
XEXTERN char **path,**cdpath,**fpath,**watch,**mailpath;
XEXTERN char **manpath,**tildedirs,**fignore;
XEXTERN char **hosts;
X
X/* named directories */
X
XEXTERN char **userdirs,**usernames;
X
X/* size of userdirs[], # of userdirs */
X
XEXTERN int userdirsz,userdirct;
X
XEXTERN char *mailfile;
X
XEXTERN char *yytext;
X
X/* error/break flag */
X
XEXTERN int errflag;
X
XEXTERN char *tokstr;
XEXTERN int tok, tokfd;
X
X/* lexical analyzer error flag */
X
XEXTERN int lexstop;
X
X/* suppress error messages */
X
XEXTERN int noerrs;
X
X/* current history event number */
X
XEXTERN int curhist;
X
X/* if != 0, this is the first line of the command */
X
XEXTERN int isfirstln;
X
X/* if != 0, this is the first char of the command (not including
X white space */
X
XEXTERN int isfirstch;
X
X/* number of history entries */
X
XEXTERN int histentct;
X
X/* array of history entries */
X
XEXTERN Histent histentarr;
X
X/* capacity of history lists */
X
XEXTERN int histsiz,lithistsiz;
X
X/* if = 1, we have performed history substitution on the current line
X if = 2, we have used the 'p' modifier */
X
XEXTERN int histdone;
X
X/* default event (usually curhist-1, that is, "!!") */
X
XEXTERN int defev;
X
X/* != 0 if we are about to read a command word */
X
XEXTERN int incmdpos;
X
X/* != 0 if we are in the middle of a [[ ... ]] */
X
XEXTERN int incond;
X
X/* != 0 if we are after a redirection (for ctxtlex only) */
X
XEXTERN int inredir;
X
X/* != 0 if we are about to read a case pattern */
X
XEXTERN int incasepat;
X
X/* != 0 if we just read FUNCTION */
X
XEXTERN int infunc;
X
X/* != 0 if we just read a newline */
X
XEXTERN int isnewlin;
X
X/* the lists of history events */
X
XEXTERN Lklist histlist,lithistlist;
X
X/* the directory stack */
X
XEXTERN Lklist dirstack;
X
X/* the zle buffer stack */
X
XEXTERN Lklist bufstack;
X
X/* the input queue (stack?)
X
X inbuf = start of buffer
X inbufptr = location in buffer (= inbuf for a FULL buffer)
X (= inbuf+inbufsz for an EMPTY buffer)
X inbufct = # of chars in buffer (inbufptr+inbufct == inbuf+inbufsz)
X inbufsz = max size of buffer
X*/
X
XEXTERN char *inbuf,*inbufptr;
XEXTERN int inbufct,inbufsz;
X
XEXTERN char *ifs; /* $IFS */
X
XEXTERN char *oldpwd; /* $OLDPWD */
X
XEXTERN char *underscore; /* $_ */
X
X/* != 0 if this is a subshell */
X
XEXTERN int subsh;
X
X/* # of break levels */
X
XEXTERN int breaks;
X
X/* != 0 if we have a return pending */
X
XEXTERN int retflag;
X
X/* how far we've hashed the PATH so far */
X
XEXTERN char **pathchecked;
X
X/* # of nested loops we are in */
X
XEXTERN int loops;
X
X/* # of continue levels */
X
XEXTERN int contflag;
X
X/* the job we are working on */
X
XEXTERN int thisjob;
X
X/* the current job (+) */
X
XEXTERN int curjob;
X
X/* the previous job (-) */
X
XEXTERN int prevjob;
X
X/* hash table containing the aliases and reserved words */
X
XEXTERN Hashtab aliastab;
X
X/* hash table containing the parameters */
X
XEXTERN Hashtab paramtab;
X
X/* hash table containing the builtins/shfuncs/hashed commands */
X
XEXTERN Hashtab cmdnamtab;
X
X/* hash table containing the zle multi-character bindings */
X
XEXTERN Hashtab xbindtab;
X
X/* hash table for completion info for commands */
X
XEXTERN Hashtab compctltab;
X
X/* default completion infos */
X
XEXTERN struct compctl cc_compos, cc_default;
X
X/* the job table */
X
XEXTERN struct job jobtab[MAXJOB];
X
X/* shell timings */
X
X#ifndef HAS_RUSAGE
XEXTERN struct tms shtms;
X#endif
X
X/* the list of sched jobs pending */
X
XEXTERN struct schedcmd *schedcmds;
X
X/* the last l for s/l/r/ history substitution */
X
XEXTERN char *hsubl;
X
X/* the last r for s/l/r/ history substitution */
X
XEXTERN char *hsubr;
X
XEXTERN char *username; /* $USERNAME */
XEXTERN char *logname; /* $LOGNAME */
XEXTERN long lastval; /* $? */
XEXTERN long baud; /* $BAUD */
XEXTERN long columns; /* $COLUMNS */
XEXTERN long lines; /* $LINES */
XEXTERN long reporttime; /* $REPORTTIME */
X
X/* input fd from the coprocess */
X
XEXTERN int coprocin;
X
X/* output fd from the coprocess */
X
XEXTERN int coprocout;
X
XEXTERN long mailcheck; /* $MAILCHECK */
XEXTERN long logcheck; /* $LOGCHECK */
X
X/* the last time we checked mail */
X
XEXTERN time_t lastmailcheck;
X
X/* the last time we checked the people in the WATCH variable */
X
XEXTERN time_t lastwatch;
X
X/* the last time we did the periodic() shell function */
X
XEXTERN time_t lastperiod;
X
X/* $SECONDS = time(NULL) - shtimer */
X
XEXTERN time_t shtimer;
X
XEXTERN long mypid; /* $$ */
XEXTERN long lastpid; /* $! */
XEXTERN long ppid; /* $PPID */
X
X/* the process group of the shell */
X
XEXTERN long mypgrp;
X
XEXTERN char *pwd; /* $PWD */
XEXTERN char *optarg; /* $OPTARG */
XEXTERN long zoptind; /* $OPTIND */
XEXTERN char *prompt; /* $PROMPT */
XEXTERN char *rprompt; /* $RPROMPT */
XEXTERN char *prompt2; /* etc. */
XEXTERN char *prompt3;
XEXTERN char *prompt4;
XEXTERN char *sprompt;
XEXTERN char *timefmt;
XEXTERN char *watchfmt;
XEXTERN char *wordchars;
XEXTERN char *fceditparam;
XEXTERN char *tmpprefix;
XEXTERN char *rstring, *Rstring;
XEXTERN char *postedit;
X
XEXTERN char *argzero; /* $0 */
X
XEXTERN char *hackzero;
X
X/* the hostname */
X
XEXTERN char *hostnam;
X
XEXTERN char *home; /* $HOME */
XEXTERN char **pparams; /* $argv */
X
X/* the default command for null commands */
X
XEXTERN char *nullcmd;
XEXTERN char *readnullcmd;
X
X/* the List of local variables we have to destroy */
X
XEXTERN Lklist locallist;
X
X/* the shell input fd */
X
XEXTERN int SHIN;
X
X/* the shell tty fd */
X
XEXTERN int SHTTY;
X
X/* the stack of aliases we are expanding */
X
XEXTERN struct alias *alstack[MAXAL];
X
X/* the alias stack pointer; also, the number of aliases currently
X being expanded */
X
XEXTERN int alstackind;
X
X/* != 0 means we are reading input from a string */
X
XEXTERN int strin;
X
X/* period between periodic() commands, in seconds */
X
XEXTERN long period;
X
X/* != 0 means history substitution is turned off */
X
XEXTERN int stophist;
X
XEXTERN int lithist;
X
X/* this line began with a space, so junk it if HISTIGNORESPACE is on */
X
XEXTERN int spaceflag;
X
X/* don't do spelling correction */
X
XEXTERN int nocorrect;
X
X/* != 0 means we have removed the current event from the history List */
X
XEXTERN int histremmed;
X
X/* the options; e.g. if opts['a'] == OPT_SET, -a is turned on */
X
XEXTERN int opts[128];
X
XEXTERN long lineno; /* LINENO */
XEXTERN long listmax; /* LISTMAX */
XEXTERN long savehist; /* SAVEHIST */
XEXTERN long shlvl; /* SHLVL */
XEXTERN long tmout; /* TMOUT */
XEXTERN long dirstacksize; /* DIRSTACKSIZE */
X
X/* != 0 means we have called execlist() and then intend to exit(),
X so don't fork if not necessary */


X
XEXTERN int exiting;
X

XEXTERN int lastbase; /* last input base we used */
X
X/* the limits for child processes */
X
X#ifdef RLIM_INFINITY
XEXTERN struct rlimit limits[RLIM_NLIMITS];
X#endif
X
X/* the current word in the history List */
X
XEXTERN char *hlastw;
X
X/* pointer into the history line */
X
XEXTERN char *hptr;
X
X/* the current history line */
X
XEXTERN char *hline;
X
X/* the termcap buffer */
X
XEXTERN char termbuf[1024];
X
X/* $TERM */
X
XEXTERN char *term;
X
X/* != 0 if this $TERM setup is usable */
X
XEXTERN int termok;
X
X/* flag for CSHNULLGLOB */
X
XEXTERN int badcshglob;
X
X/* max size of hline */
X
XEXTERN int hlinesz;
X
X/* the alias expansion status - if == ALSTAT_MORE, we just finished
X expanding an alias ending with a space */
X
XEXTERN int alstat;
X
X/* we have printed a 'you have stopped (running) jobs.' message */
X
XEXTERN int stopmsg;
X
X/* the default tty state */
X
XEXTERN struct ttyinfo shttyinfo;
X
X/* $TTY */
X
XEXTERN char *ttystrname;
X
X/* 1 if ttyctl -f has been executed */
X
XEXTERN int ttyfrozen;
X
X/* list of memory heaps */
X
XEXTERN Lklist heaplist;
X
X/* != 0 if we are allocating in the heaplist */
X
XEXTERN int useheap;
X
X#include "signals.h"
X
X#ifdef GLOBALS
X
X/* signal names */
Xchar **sigptr = sigs;
X
X/* tokens */
Xchar *ztokens = "#$^*()$=|{}[]`<>?~`,";
X
X#else
Xextern char *ztokens,**sigptr;
X#endif
X
X#define SIGERR (SIGCOUNT+1)
X#define SIGDEBUG (SIGCOUNT+2)
X#define VSIGCOUNT (SIGCOUNT+3)
X#define SIGEXIT 0
X
X/* signals that are trapped = 1, signals ignored =2 */
X
XEXTERN int sigtrapped[VSIGCOUNT];
X
X/* trap functions for each signal */
X
XEXTERN List sigfuncs[VSIGCOUNT];
X
X/* $HISTCHARS */
X
XEXTERN char bangchar,hatchar,hashchar;
X
XEXTERN int eofseen;
X
X/* we are parsing a line sent to use by the editor */
X
XEXTERN int zleparse;
X
XEXTERN int wordbeg;
X
XEXTERN int parbegin;
X
X/* interesting termcap strings */
X
X#define TCCLEARSCREEN 0
X#define TCLEFT 1
X#define TCMULTLEFT 2
X#define TCRIGHT 3
X#define TCMULTRIGHT 4
X#define TCUP 5
X#define TCMULTUP 6
X#define TCDOWN 7
X#define TCMULTDOWN 8
X#define TCDEL 9
X#define TCMULTDEL 10
X#define TCINS 11
X#define TCMULTINS 12
X#define TCCLEAREOD 13
X#define TCCLEAREOL 14
X#define TCINSLINE 15
X#define TCDELLINE 16
X#define TC_COUNT 17
X
X/* lengths of each string */
X
XEXTERN int tclen[TC_COUNT];
X
XEXTERN char *tcstr[TC_COUNT];
X
X#ifdef GLOBALS
X
X/* names of the strings we want */
X
Xchar *tccapnams[TC_COUNT] = {
X "cl","le","LE","nd","RI","up","UP","do",
X "DO","dc","DC","ic","IC","cd","ce","al","dl"
X };
X
X#else
Xextern char *tccapnams[TC_COUNT];
X#endif
X
X#define tccan(X) (!!tclen[X])
X
X#define HISTFLAG_DONE 1
X#define HISTFLAG_NOEXEC 2
X#define HISTFLAG_RECALL 4
X
X#include "ztype.h"
X#include "funcs.h"
X
X#ifdef HAS_SETPGID
X#define setpgrp setpgid
X#endif
X
X#define _INCLUDE_POSIX_SOURCE
X#define _INCLUDE_XOPEN_SOURCE
X#define _INCLUDE_HPUX_SOURCE
X
X#ifdef SV_BSDSIG
X#define SV_INTERRUPT SV_BSDSIG
X#endif
X
X#ifdef HAS_SIGRELSE
X#define blockchld() sighold(SIGCHLD)
X#define unblockchld() sigrelse(SIGCHLD)
X#define chldsuspend() sigpause(SIGCHLD)
X#else
X#define blockchld() sigblock(sigmask(SIGCHLD))
X#define unblockchld() sigsetmask(0)
X#define chldsuspend() sigpause(0)
X#endif
SHAR_EOF
chmod 0644 zsh2.2/src/zsh.h ||
echo 'restore of zsh2.2/src/zsh.h failed'
Wc_c="`wc -c < 'zsh2.2/src/zsh.h'`"
test 31883 -eq "$Wc_c" ||
echo 'zsh2.2/src/zsh.h: original size 31883, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_vi.c ==============
if test -f 'zsh2.2/src/zle_vi.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_vi.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_vi.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_vi.c' &&
X/*
X *
X * zle_vi.c - vi-specific functions


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#define ZLE
X#include "zsh.h"
X
X

Xstatic void startvichange(im)
Xint im;
X{
X insmode = im;
X if (vichgbuf) free(vichgbuf);
X vichgbuf = zalloc(vichgbufsz = 16);
X vichgbuf[0] = c;
X vichgbufptr = 1;
X vichgflag = 1;
X viinsbegin = cs;
X}
X
Xstatic void startvitext(im)
X{
X startvichange(im);
X bindtab = mainbindtab;
X undoing = 0;
X}
X
Xint vigetkey() /**/
X{
Xint ch;
X
X if ((ch = getkey(0)) == -1)
X return 0;
X if (ch == 22)
X {
X if ((ch = getkey(0)) == -1)
X return 0;
X return ch;
X }
X else if (ch == 27)
X return 0;
X return ch;
X}
X
Xint getvirange(wf) /**/
Xint wf;
X{
Xint k2,t0,startline,endline;
X
X startline = findbol();
X endline = findeol();
X for (;;) {
X k2 = getkeycmd();
X if (k2 == -1) {
X feep();
X return -1;
X }
X if (zlecmds[k2].flags & ZLE_ARG)
X (*zlecmds[k2].func)();
X else
X break;
X }
X if (k2 == bindk) {
X findline(&cs,&t0);
X return (t0 == ll) ? t0 : t0+1;
X }
X if (!(zlecmds[k2].flags & ZLE_MOVEMENT)) {
X feep();
X return -1;
X }
X t0 = cs;
X
X virangeflag = 1;
X wordflag = wf;
X (*zlecmds[k2].func)();
X wordflag = virangeflag = 0;
X if (cs == t0) {
X feep();
X return -1;
X }
X if (startline != findbol()) {
X if (zlecmds[k2].flags & ZLE_LINEMOVE) {
X if (cs < t0) {
X cs = startline;
X t0 = findeol()+1;
X } else {
X t0 = startline;
X cs = findeol()+1;
X }
X } else {
X if (cs < startline) cs = startline;
X else if (cs >= endline) cs = endline-1;
X }
X }
X if (cs > t0) {
X k2 = cs;
X cs = t0;
X t0 = k2;
X }


X return t0;
X}
X

Xvoid viaddnext() /**/
X{
X if (cs != ll)
X cs++;
X startvitext(1);
X}
X
Xvoid viaddeol() /**/
X{
X cs = findeol();
X startvitext(1);
X}
X
Xvoid viinsert() /**/
X{
X startvitext(1);
X}
X
Xvoid viinsertbol() /**/
X{
X cs = findbol();
X startvitext(1);
X}
X
Xvoid videlete() /**/
X{
Xint c2;
X
X startvichange(1);
X if ((c2 = getvirange(0)) == -1)
X { vichgflag = 0; return; }
X forekill(c2-cs,0);
X vichgflag = 0;
X}
X
Xvoid vichange() /**/
X{
Xint c2;
X
X startvichange(1);
X if ((c2 = getvirange(1)) == -1)
X { vichgflag = 0; return; }
X forekill(c2-cs,0);
X bindtab = mainbindtab;
X undoing = 0;
X}
X
Xvoid visubstitute() /**/
X{
X if (mult < 0) return;
X if (findeol()-cs < mult) mult = findeol()-cs;
X if (mult) {
X foredel(mult);
X startvitext(1);
X }
X}
X
Xvoid vichangeeol() /**/
X{
X killline();
X startvitext(1);
X}
X
Xvoid vichangewholeline() /**/
X{
Xint cq;
X
X findline(&cs,&cq);
X foredel(cq-cs);
X startvitext(1);
X}
X
Xvoid viyank() /**/
X{
Xint c2;
X
X if ((c2 = getvirange(0)) == -1) return;
X cut(cs,c2-cs,0);
X}
X
Xvoid viyankeol() /**/
X{
Xint x = findeol();
X
X if (x == cs)
X feep();
X else
X cut(cs,x-cs,0);
X}
X
Xvoid vireplace() /**/
X{
X startvitext(0);
X}
X
Xvoid vireplacechars() /**/
X{
Xint ch;
X
X if (mult < 0) return;
X if (mult+cs > ll) {
X feep();
X return;
X }
X startvichange(1);
X if (ch = vigetkey()) while (mult--) line[cs++] = ch;
X vichgflag = 0;
X cs--;
X}
X
Xvoid vicmdmode() /**/
X{
X bindtab = altbindtab;
X if (cs) cs--;
X undoing = 1;
X if (vichgflag) vichgflag = 0;
X}
X
Xvoid viopenlinebelow() /**/
X{
X cs = findeol();
X spaceinline(1);
X line[cs++] = '\n';
X startvitext(1);
X}
X
Xvoid viopenlineabove() /**/
X{
X cs = findbol();
X spaceinline(1);
X line[cs] = '\n';
X startvitext(1);
X}
X
Xvoid vioperswapcase() /**/
X{
Xint c2;
X
X if ((c2 = getvirange(0)) == -1)
X return;
X while (cs < c2)
X {
X int ch = line[cs];
X
X if (islower(ch))
X ch = tuupper(ch);
X else if (isupper(ch))
X ch = tulower(ch);
X line[cs++] = ch;
X }
X}
X
Xvoid virepeatchange() /**/
X{
X if (!vichgbuf || bindtab == mainbindtab || vichgflag) feep();
X else ungetkeys(vichgbuf,vichgbufptr);
X}
X
Xvoid viindent() /**/
X{
Xint c2,endcs,t0,rmult;
X
X if (mult < 0) { mult = -mult; viunindent(); return; }
X rmult = mult;
X if ((c2 = getvirange(0)) == -1)
X return;
X if (cs != findbol()) { feep(); return; }
X endcs = cs+rmult;
X while (cs < c2) {
X spaceinline(rmult);
X for (t0 = 0; t0 != rmult; t0++) line[cs++] = '\t';
X cs = findeol()+1;
X }
X cs = endcs;
X}
X
Xvoid viunindent() /**/
X{
Xint c2,endcs,t0,rmult;
X
X rmult = mult;
X if (mult < 0) { mult = -mult; viindent(); return; }
X if ((c2 = getvirange(0)) == -1)
X return;
X if (cs != findbol()) { feep(); return; }
X endcs = cs;
X while (cs < c2) {
X for (t0 = 0; t0 != rmult && line[cs] == '\t'; t0++) foredel(1);
X cs = findeol()+1;
X }
X cs = endcs;
X}
SHAR_EOF
chmod 0644 zsh2.2/src/zle_vi.c ||
echo 'restore of zsh2.2/src/zle_vi.c failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_vi.c'`"
test 4793 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_vi.c: original size 4793, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/ztype.h ==============
if test -f 'zsh2.2/src/ztype.h' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/ztype.h (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/ztype.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/ztype.h' &&
X/*
X *
X * ztype.h - character classification macros


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#define IDIGIT 1
X#define IALNUM 2
X#define IBLANK 4
X#define INBLANK 8
X#define ITOK 16
X#define ISEP 32
X#define IALPHA 64
X#define IIDENT 128
X#define IUSER 256
X#define ICNTRL 512
X#define IWORD 1024
X#define ISPECIAL 2048
X#define _icom(X,Y) (typtab[(int) (unsigned char) (X)] & Y)
X#define idigit(X) _icom(X,IDIGIT)
X#define ialnum(X) _icom(X,IALNUM)
X#define iblank(X) _icom(X,IBLANK) /* blank, not including \n */
X#define inblank(X) _icom(X,INBLANK) /* blank or \n */
X#define itok(X) _icom(X,ITOK)
X#define isep(X) _icom(X,ISEP)
X#define ialpha(X) _icom(X,IALPHA)
X#define iident(X) _icom(X,IIDENT)
X#define iuser(X) _icom(X,IUSER) /* username char */
X#define icntrl(X) _icom(X,ICNTRL)
X#define iword(X) _icom(X,IWORD)
X#define ispecial(X) _icom(X,ISPECIAL)
X
XEXTERN short int typtab[256];
X
SHAR_EOF
chmod 0644 zsh2.2/src/ztype.h ||
echo 'restore of zsh2.2/src/ztype.h failed'
Wc_c="`wc -c < 'zsh2.2/src/ztype.h'`"
test 1486 -eq "$Wc_c" ||
echo 'zsh2.2/src/ztype.h: original size 1486, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_tricky.c ==============
if test -f 'zsh2.2/src/zle_tricky.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_tricky.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_tricky.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_tricky.c' &&
X/*
X *
X * zle_tricky.c - expansion and completion


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#define ZLE
X#include "zsh.h"

X#ifdef __hpux
X#include <ndir.h>
X#else

X#ifdef SYSV
X#define direct dirent

X#else
X#include <sys/dir.h>
X#endif
X#endif
X#include <pwd.h>
X
Xstatic int we,wb,usemenu,useglob;
X
Xstatic int menub,menue,menuw;
SHAR_EOF
true || echo 'restore of zsh2.2/src/zle_tricky.c failed'
fi
echo 'End of zsh2.2 part 14'
echo 'File zsh2.2/src/zle_tricky.c is continued in part 15'
echo 15 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:10:13 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 111
Archive-name: zsh2.2/part15

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.15 (part 15 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/zle_tricky.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 15; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/zle_tricky.c'
else
echo 'x - continuing file zsh2.2/src/zle_tricky.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/zle_tricky.c' &&

Xstatic Lklist menulist;
Xstatic Lknode menunode;
X
X#define inststr(X) inststrlen((X),-1)
X
Xint usetab() /**/
X{
Xunsigned char *s = line+cs-1;
X
X for (; s >= line && *s != '\n'; s--)
X if (*s != '\t' && *s != ' ')
X return 0;
X return 1;
X}
X
X#define COMP_COMPLETE 0
X#define COMP_LIST_COMPLETE 1
X#define COMP_SPELL 2
X#define COMP_EXPAND 3
X#define COMP_EXPAND_COMPLETE 4
X#define COMP_LIST_EXPAND 5
X#define COMP_ISEXPAND(X) ((X) >= COMP_EXPAND)
X
Xvoid completeword() /**/
X{
X usemenu = isset(MENUCOMPLETE) || (useglob = isset(GLOBCOMPLETE));
X if (c == '\t' && usetab())
X selfinsert();
X else
X docomplete(COMP_COMPLETE);
X}
X
Xvoid menucompleteword() /**/
X{
X usemenu = 1; useglob = isset(GLOBCOMPLETE);
X if (c == '\t' && usetab())
X selfinsert();
X else
X docomplete(COMP_COMPLETE);
X}
X
Xvoid listchoices() /**/
X{
X usemenu = isset(MENUCOMPLETE) || (useglob = isset(GLOBCOMPLETE));
X docomplete(COMP_LIST_COMPLETE);
X}
X
Xvoid spellword() /**/
X{
X usemenu = useglob = 0;
X docomplete(COMP_SPELL);
X}
X
Xvoid deletecharorlist() /**/
X{
X usemenu = isset(MENUCOMPLETE) || (useglob = isset(GLOBCOMPLETE));


X if (cs != ll)

X deletechar();
X else
X docomplete(COMP_LIST_COMPLETE);
X}
X
Xvoid expandword() /**/
X{
X usemenu = useglob = 0;
X if (c == '\t' && usetab())
X selfinsert();
X else
X docomplete(COMP_EXPAND);
X}
X
Xvoid expandorcomplete() /**/
X{
X usemenu = isset(MENUCOMPLETE) || (useglob = isset(GLOBCOMPLETE));
X if (c == '\t' && usetab())
X selfinsert();
X else
X docomplete(COMP_EXPAND_COMPLETE);
X}
X
Xvoid menuexpandorcomplete() /**/
X{
X usemenu = 1; useglob = isset(GLOBCOMPLETE);
X if (c == '\t' && usetab())
X selfinsert();
X else
X docomplete(COMP_EXPAND_COMPLETE);
X}
X
Xvoid listexpand() /**/
X{
X usemenu = isset(MENUCOMPLETE); useglob = isset(GLOBCOMPLETE);
X docomplete(COMP_LIST_EXPAND);
X}
X
Xvoid reversemenucomplete() /**/
X{
Xchar *s;
X
X if (!menucmp)
X menucompleteword(); /* better than just feep'ing, pem */
X if (!menucmp) return;
X cs = menub;
X foredel(menue-menub);
X if (menunode == firstnode(menulist))
X menunode = lastnode(menulist);
X else
X menunode = prevnode(menunode);
X inststr(s = menunode->dat);
X menue = cs;
X}
X
X/*
X * Accepts the current completion and starts a new arg,
X * with the next completions. This gives you a way to accept
X * several selections from the list of matches.
X */
Xvoid acceptandmenucomplete() /**/
X{
Xint t0,t1;
X
X if (!menucmp) {


X feep();
X return;
X }

X spaceinline(1);
X line[cs++] = ' ';
X spaceinline(menub-menuw);
X t1 = cs;
X for (t0 = menuw; t0 != menub; t0++)
X line[cs++] = line[t0];
X menue = menub = cs;
X menuw = t1;
X menucompleteword();
X}
X
Xstatic char *lastmenu = NULL;
Xstatic int lastmenupos = -1;
Xstatic int lincmd,linredir,lastambig;
Xstatic char *cmdstr;
X
Xvoid docomplete(lst) /**/
Xint lst;
X{
Xchar *s;
X
X if (isset(AUTOMENU) && !menucmp && c == '\t' &&
X (lastcmd & ZLE_MENUCMP) && lastambig) usemenu = 1;
X if (menucmp) { do_menucmp(lst); return; }
X if (doexpandhist()) return;
X s = get_comp_string();
X if (s) {
X if (lst == COMP_EXPAND_COMPLETE) {
X char *q = s;
X
X if (*q == Tilde) q++;
X else if (*q == Equals) {
X q = s+1;
X if (gethnode(q,cmdnamtab) || hashcmd(q,pathchecked))
X lst = COMP_EXPAND;
X } else {
X for (; *q && *q != String; q++);
X if (*q == String && q[1] != Inpar) {
X if (getsparam(q+1)) lst = COMP_EXPAND;
X else lst = COMP_COMPLETE;
X }
X q = s;
X }
X if (lst == COMP_EXPAND_COMPLETE) {
X for (; *q; q++)
X if (itok(*q))
X break;
X if (!*q)
X lst = COMP_COMPLETE;
X }
X }
X if (lst == COMP_SPELL) {
X char **x = &s;
X untokenize(s);
X cs = wb;
X foredel(we-wb);
X /* call the real spell checker, a...@aaii.oz.zu */
X spckword(x, NULL, NULL, !lincmd, 0);
X inststr(*x);
X } else if (COMP_ISEXPAND(lst))
X doexpansion(s,lst,lincmd);
X else {
X docompletion(s,lst,lincmd);
X }
X free(s);
X }
X popheap();
X lexrestore();
X}
X
Xvoid do_menucmp(lst) /**/
Xint lst;
X{
Xchar *s;
X
X if (isset(LASTMENU) && lastmenu) {
X if (COMP_ISEXPAND(lst) || cs != lastmenupos ||
X strcmp((char *) line, lastmenu) != 0) {
X free(lastmenu);
X lastmenu = NULL;
X lastmenupos = -1;
X freemenu();
X }
X }
X if (lst == COMP_LIST_COMPLETE) {
X listmatches(menulist, NULL);
X return;
X }
X cs = menub;
X foredel(menue-menub);
X incnode(menunode);
X if (!menunode)
X menunode = firstnode(menulist);
X s = menunode->dat;
X if (*s == '~' || *s == '=' || *s == '$') {
X spaceinline(1);
X line[cs++] = *s++;
X }
X inststr(s = menunode->dat);
X if (isset(LASTMENU)) {
X if (lastmenu) free(lastmenu);
X lastmenu = ztrdup(line);
X lastmenupos = cs;
X }
X menue = cs;
X}
X
Xchar *get_comp_string() /**/
X{
Xint t0;
Xunsigned char *s,*linptr;
X
X linptr = line;
Xstart:
X lincmd = incmdpos;
X linredir = inredir;
X cmdstr = NULL;
X zleparse = 1;
X lexsave();
X hungets(" "); /* KLUDGE! */
X hungets(linptr);
X strinbeg();
X pushheap();
X do {
X lincmd = incmdpos;
X linredir = inredir;
X ctxtlex();
X if (tok == ENDINPUT) break;
X if (lincmd && tok == STRING) cmdstr = strdup(tokstr);
X } while (tok != ENDINPUT && zleparse);
X t0 = tok;
X if (t0 == ENDINPUT) {
X s = (unsigned char *)ztrdup("");
X we = wb = cs;
X t0 = STRING;
X } else if (t0 == STRING) {
X s = (unsigned char *)ztrdup(tokstr);
X } else if (t0 == ENVSTRING) {
X for (s = (unsigned char *)tokstr; *s && *s != (unsigned char)'='; s++, wb++);
X if (*s) { s++; wb++; t0 = STRING; s = (unsigned char *)ztrdup(s); }
X lincmd = 1;


X }
X hflush();
X strinend();

X errflag = zleparse = 0;
X if (we > ll) we = ll;
X if (t0 == LEXERR && parbegin != -1) {
X linptr += ll+1-parbegin;
X popheap();
X lexrestore();
X goto start;
X }
X if (t0 != STRING) { feep(); return NULL; }
X return (char *)s;
X}
X
Xvoid doexpansion(s,lst,lincmd) /**/
Xchar *s;int lst;int lincmd;
X{
XLklist vl = newlist();
Xchar *ss;
X
X pushheap();
X addnode(vl,s);


X prefork(vl);
X if (errflag)

X goto end;


X postfork(vl,1);
X if (errflag)

X goto end;
X if (!full(vl) || !*(char *) peekfirst(vl)) {
X feep();
X goto end;
X }
X if (lst == COMP_LIST_EXPAND) {
X listmatches(vl,NULL);
X goto end;
X } else if (peekfirst(vl) == s) {
X if (lst == COMP_EXPAND_COMPLETE) {
X docompletion(s,COMP_COMPLETE,lincmd);
X } else
X feep();
X goto end;
X }
X cs = wb;
X foredel(we-wb);
X while (ss = ugetnode(vl)) {
X untokenize(ss);
X inststr(ss);
X#if 0
X if (full(vl)) {
X spaceinline(1);
X line[cs++] = ' ';
X }
X#endif
X spaceinline(1);
X line[cs++] = ' ';
X }
Xend:
X popheap();
X setterm();
X}
X
Xvoid gotword(s) /**/
Xchar *s;
X{
X we = ll+1-inbufct;
X if (cs <= we)
X {
X wb = ll-wordbeg;
X zleparse = 0;
X /* major hack ahead */
X if (wb && line[wb] == '!' && line[wb-1] == '\\')
X wb--;
X }
X}
X
Xvoid inststrlen(s,l) /**/


Xchar *s;int l;
X{

Xchar *t,*u,*v;
X
X t = halloc(strlen(s)*2+2);
X u = s;
X v = t;
X for (; *u; u++)
X {
X if (l != -1 && !l--)
X break;
X if (ispecial(*u))
X if (*u == '\n')
X {
X *v++ = '\'';
X *v++ = '\n';
X *v++ = '\'';


X continue;
X }
X else

X *v++ = '\\';
X *v++ = *u;
X }
X *v = '\0';
X spaceinline(strlen(t));
X strncpy((char *) line+cs,t,strlen(t));
X cs += strlen(t);
X}
X
Xstatic int ambig,haspath,exact;
Xstatic Lklist matches;
Xstatic char *pat,*exactstr;
Xstatic int typechar;
X
Xvoid addmatch(s) /**/
Xchar *s;
X{
X if (full(matches))
X {
X int y = pfxlen(peekfirst(matches),s);
X
X if (y < ambig)
X ambig = y;
X }
X else
X ambig = strlen(s);
X if (!strcmp(pat,s)) { exact = 1; exactstr = pat; }
X addnodeinorder(matches,strdup(s));
X}
X
X
Xvoid addcmdmatch(s,t) /**/


Xchar *s;char *t;
X{

X if (strpfx(pat,s)) addmatch(s);
X}
X
Xvoid addcmddirparam(s,t) /**/


Xchar *s;char *t;
X{

XParam pm = (Param) t;
X
X if (strpfx(pat,s) && pmtype(pm) == PMFLAG_s) {
X t = pm->gets.cfn(pm);
X if (t && *t == '/') addmatch(s);
X }
X}
X
Xvoid addcmdnodis(s,t) /**/


Xchar *s;char *t;
X{

X if (strpfx(pat,s) && ((Cmdnam) t)->type != DISABLED) addmatch(s);
X}
X
Xvoid maketildelist(s) /**/
Xchar *s;
X{
X struct passwd *pwd;
X int len;
X
X s++;
X len = strlen(s);
X if (len < 1) {
X addmatch(s);
X *s = 0;
X return;
X }
X while ((pwd = getpwent()) != NULL && !errflag)
X if (strncmp(pwd->pw_name, s, len) == 0)
X addmatch(pwd->pw_name);
X endpwent();


X *s = 0;
X}

X
X/*
X * opendir that handles '~' and '=' and '$'.
X * orig. by a...@aaii.oz.au, mod. by pf
X */
XDIR *OPENDIR(s)
Xchar *s;
X{
X if (*s != '~' && *s != '=' && *s != '$')
X return(opendir(s));
X s = strdup(s);
X *s = (*s == '=') ? Equals : (*s == '~') ? Tilde : String;
X singsub(&s);
X return(opendir(s));
X}
Xchar *dirname(s)
Xchar *s;
X{
X if (*s == '~' || *s == '=' || *s == '$') {
X s = strdup(s);
X *s = (*s == '=') ? Equals : (*s == '~') ? Tilde : String;
X singsub(&s);
X }
X return(s);
X}
X
Xint Isdir(s) /**/
Xchar *s;
X{
Xstruct stat sbuf;
X
X if (!*s) return 0;
X if (stat(s,&sbuf) == -1) return 0;
X return S_ISDIR(sbuf.st_mode);
X}
X
X/* this will work whether s is tokenized or not */
Xint isdir(t,s) /**/
Xchar *t;char *s;


X{
Xchar buf[MAXPATHLEN];
X

X if (typechar != '$')
X sprintf(buf,"%s/%s",(s) ? s : ".",t);
X else
X sprintf(buf,"$%s",t);
X s = buf;
X if (*s != '~' && *s != '=' && *s != Tilde && *s != Equals &&
X *s != '$' && *s != String)
X return(Isdir(s));
X s = strdup(s);
X if (*s == '~' || *s == '=' || *s == '$')
X *s = (*s == '=') ? Equals : (*s == '~') ? Tilde : String;
X singsub(&s);
X return(Isdir(s));
X}
X
X#define SLASH_YES 0
X#define SLASH_NO 1
X#define SLASH_MAYBE 2
X
Xint slashflag;
Xint addedstar;
Xchar *pathprefix;
X
Xvoid docompletion(s,lst,incmd) /**/
Xchar *s;int lst;int incmd;
X{
Xchar *tokorigs;
Xchar *origs;
XCompctl cc;
Xchar *pfx = s;
X
X slashflag = SLASH_MAYBE;
X addedstar = 0;
X lastambig = 0;
X
X heapalloc();
X pushheap();
X if (useglob)
X tokorigs = strdup(s);
X untokenize(s);
X origs = strdup(s);
X matches = newlist();
X if (incmd)
X cc = &cc_compos;
X else if (linredir || !(cmdstr && (cc = gethnode(cmdstr,compctltab))))
X cc = &cc_default;
X exact = 0;
X if (cc->mask & CC_COMMPATH) gen_matches_reg(s,1,(cc->mask & CC_FILES));
X else if (cc->mask & CC_FILES) gen_matches_reg(s,0,1);
X else {
X haspath = 0;
X slashflag = SLASH_NO;
X }
X if (cc->mask & (CC_FILES|CC_COMMPATH)) {
X /* only do "globbed" completion if regular completion fails.
X pem, 7Oct91 */
X if ((!full(matches) || errflag) && useglob) {
X gen_matches_glob(tokorigs,incmd);
X /*
X * gen_matches_glob changes the insert line to be correct up
X * to the match, so the prefix string must be "". ash, 7Oct91
X */


X *s = 0;
X }

X }
X pat = s;
X if ((cc->mask & CC_HOSTS) && !haspath) {
X char **x;
X for (x = hosts; *x; x++) addcmdmatch(*x,NULL);
X }
X if ((cc->mask & CC_OPTIONS) && !haspath) {
X struct option *o;
X for (o = optns; o->name; o++) addcmdmatch(o->name,NULL);
X }
X if ((cc->mask & CC_VARS) && !haspath) listhtable(paramtab,addcmdmatch);
X if ((cc->mask & CC_BINDINGS) && !haspath) {
X int t0;
X for (t0 = 0; t0 != ZLECMDCOUNT; t0++)
X if (*zlecmds[t0].name) addcmdmatch(zlecmds[t0].name,NULL);
X }
X if (cc->mask & CC_USRKEYS) {
X char **usr = get_user_var(cc->keyvar);
X if (usr) while (*usr) addcmdmatch(*usr++,NULL);
X }
X if (lst != COMP_LIST_COMPLETE) do_fignore(origs);
X if (!full(matches) || errflag) {
X feep();
X } else if (lst == COMP_LIST_COMPLETE) {
X listmatches(matches,
X unset(LISTTYPES) ? NULL :
X (haspath) ? pathprefix : "./");
X } else if (nextnode(firstnode(matches))) {
X do_ambiguous(pfx);
X } else {
X do_single(pfx);
X }
X ll = strlen((char *) line);
X setterm();
X popheap();
X permalloc();
X}
X
Xchar **get_user_var(nam) /**/
Xchar *nam;
X{
X return (nam) ? getaparam(nam) : NULL;
X}
X
Xvoid gen_matches_glob(s,incmd) /**/
Xchar *s;int incmd;
X{
Xchar *pt,*u;
Xint hasp = 0;
XDIR *d;
Xstruct direct *de;
X
X /*
X * Find the longest prefix string without any
X * chars special to glob - ash.
X */
X for (pt = s; *pt; pt++) {
X if (pt == s && (*pt == Tilde || *pt == Equals)) continue;
X if (ispecial(*pt) || itok(*pt)) break;
X }
X for (; pt > s && *pt != '/'; pt--) ;
X if (*pt == '/') {
X *pt = 0;
X u = pt + 1;
X wb += strlen(s);
X hasp = 1;
X } else u = s;
X if (!hasp && (*s == Tilde || *s == Equals)) {
X /* string contains only ~xx, so do tilde expansion */
X maketildelist(s);
X wb++;
X pathprefix = s;
X slashflag = SLASH_YES;
X } else if (incmd && !hasp) {
X slashflag = SLASH_NO;
X pat = s;
X listhtable(aliastab ,addcmdmatch);
X if (isset(HASHLISTALL)) fullhash();
X listhtable(cmdnamtab,addcmdnodis);
X if (isset(AUTOCD)) listhtable(paramtab ,addcmddirparam);
X if (d = opendir(".")) {
X char *q;
X
X readdir(d); readdir(d);
X while ((de = readdir(d)) && !errflag)
X if (strpfx(pat,q = de->d_name) &&
X (*q != '.' || *u == '.' || isset(GLOBDOTS)))
X addmatch(q);
X closedir(d);
X }
X } else {
X int commonprefix = 0;
X char *prefix;
X Lknode n;
X int nonomatch = isset(NONOMATCH);
X
X opts[NONOMATCH] = 1;
X if (hasp) {
X /* Find the longest common prefix string
X * after globbing the input. All expansions
X * ~foo/bar/* will turn into something like
X * /tmp_mnt/hosts/somehost/home/foo/...
X * We will remove this common prefix from the matches.
X * ash, 7 May '91
X */
X pathprefix = s;
X addnode(matches,s);
X prefork(matches);
X if (!errflag) postfork(matches,1);
X if (!errflag) {
X prefix = peekfirst(matches);
X if (prefix) commonprefix = strlen(prefix) + 1;
X *pt = '/';
X }
X }
X if (s[strlen(s) - 1] == '/') {
X /* if strings ends in a '/' always add a '*' */
X s = dyncat(s,"x");
X s[strlen(s)-1] = Star;
X addedstar = 1;
X }
X matches = newlist();
X addnode(matches,s);
X prefork(matches);
X if (!errflag) postfork(matches,1);
X opts[NONOMATCH] = nonomatch;
X if (errflag || !full(matches) || !nextnode(firstnode(matches))) {
X /* if there were no matches (or only one)
X add a trailing * and try again */
X s = dyncat(s,"x");
X s[strlen(s)-1] = Star;
X addedstar = 1;
X matches = newlist();
X addnode(matches,s);
X prefork(matches);
X if (errflag) return;
X postfork(matches,1);


X if (errflag) return;
X }

X /* remove the common prefix from all the matches */
X if (commonprefix)
X for (n = firstnode(matches); n; incnode(n))
X n->dat = (char *) n->dat+commonprefix;
X s = pt;


X *s = 0;
X }

X}
X
Xvoid gen_matches_reg(s,incmd,regfiles) /**/
Xchar *s;int incmd;int regfiles;
X{
Xchar *u;
XDIR *d;
Xstruct direct *de;
X
X haspath = 0;
X for (u = s+strlen(s); u >= s; u--)
X if (*u == '/' || *u == '@' || *u == '$') break;
X if (u >= s) {
X typechar = *u;
X *u++ = '\0';
X haspath = 1;
X } else if (*s == '=') {
X typechar = '=';
X *s = '\0'; u = s+1;
X haspath = 1;
X } else u = s;
X pat = u;
X if (typechar == '$' && haspath) {
X /* slashflag = SLASH_NO; */
X listhtable(paramtab,addcmdmatch);
X } else if (typechar == '=' && haspath) {
X slashflag = SLASH_NO;
X if (isset(HASHLISTALL)) fullhash();
X listhtable(cmdnamtab,addcmdnodis);
X } else if (typechar == '@' && haspath) {
X char **x;
X slashflag = SLASH_NO;
X for (x = hosts; *x; x++) addcmdmatch(*x,NULL);
X } else if (*s == '~' && !haspath) {
X maketildelist(s);
X pathprefix = s;
X slashflag = SLASH_YES;
X } else if (incmd && !haspath) {
X slashflag = SLASH_NO;
X listhtable(aliastab ,addcmdmatch);
X if (isset(HASHLISTALL)) fullhash();
X listhtable(cmdnamtab,addcmdnodis);
X if (isset(AUTOCD) && isset(CDABLEVARS))
X listhtable(paramtab ,addcmddirparam);
X if (d = opendir(".")) {
X char *q;


X struct stat buf;
X

X readdir(d); readdir(d);
X if (regfiles) {
X while ((de = readdir(d)) && !errflag)
X if (strpfx(pat,q = de->d_name) &&
X (*q != '.' || *u == '.' || isset(GLOBDOTS))) addmatch(q);
X } else if (isset(AUTOCD)) {
X while ((de = readdir(d)) && !errflag)
X if (strpfx(pat,q = de->d_name) &&
X (*q != '.' || *u == '.' || isset(GLOBDOTS)) &&
X stat(q,&buf) >= 0 &&
X (buf.st_mode & S_IEXEC) == S_IEXEC) addmatch(q);
X } else {
X while ((de = readdir(d)) && !errflag)
X if (strpfx(pat,q = de->d_name) &&
X (*q != '.' || *u == '.' || isset(GLOBDOTS)) &&
X stat(q,&buf) >= 0 &&
X (buf.st_mode & (S_IFMT|S_IEXEC)) == (S_IFREG|S_IEXEC))
X addmatch(q);
X }
X closedir(d);
X }
X } else if (d = OPENDIR(pathprefix =
X ((haspath || *s == '~') ? ((*s) ? s : "/") : "."))) {
X char *q,buf2[MAXPATHLEN];
X struct stat buf;
X char dn[MAXPATHLEN];
X
X strcpy(dn,dirname(pathprefix));
X readdir(d); readdir(d);
X while ((de = readdir(d)) && !errflag)
X if (strpfx(pat,q = de->d_name) &&
X (*q != '.' || *u == '.' || isset(GLOBDOTS))) {
X if (incmd) {
X sprintf(buf2,"%s/%s",dn,q);
X if (stat(buf2,&buf) < 0 ||
X (buf.st_mode & S_IEXEC) == S_IEXEC) {
X addmatch(q);
X }
X } else {
X addmatch(q);
X }
X }
X closedir(d);
X }
X}
X
Xvoid do_fignore(origstr) /**/
Xchar *origstr;
X{
X if (full(matches) && nextnode(firstnode(matches))) {
X Lknode z,zn;
X
X z = firstnode(matches);
X ambig = 1000;
X for (z = firstnode(matches); z; z = zn) {
X char *q = getdata(z);
X int namlen = strlen(q);
X int slen = strlen(origstr);
X int slpt;
X char **pt = fignore;
X
X zn = nextnode(z);
X for (; *pt; pt++) {
X /* We try to be smart here and override the
X fignore variable if the user has explicity
X used the ignored prefix, pem, 7 May 1991 */
X slpt = strlen(*pt);
X if (!addedstar && slen > slpt &&
X strcmp(origstr+slen-slpt, *pt) == 0)
X continue;
X if (slpt < namlen && !strcmp(q+namlen-slpt,*pt)) {
X uremnode(matches,z);
X break;
X }
X }
X if (!*pt) {
X int y = pfxlen(peekfirst(matches),q);
X if (y < ambig) ambig = y;


X }
X }
X }
X}
X

Xvoid do_ambiguous(s) /**/
Xchar *s;
X{
X lastambig = 1;
X if (usemenu) { do_ambig_menu(s); return; }
X if (useglob) {
X feep();
X if (isset(AUTOLIST))
X listmatches(matches,
X unset(LISTTYPES) ? NULL : (haspath) ? pathprefix : "./");
X return;
X }
X cs = wb;
X foredel(we-wb);
X if (*s == '~' || *s == '=' || *s == '$') {
X spaceinline(1);
X line[cs++] = *s++;
X }
X if (haspath) {
X inststr(s);
X spaceinline(1);
X line[cs++] = typechar;
X }
X if (isset(RECEXACT) && exact) {
X lastambig = 0;
X if ((*pat == '~' || *pat == '=' || *pat == '$') && !haspath) {
X spaceinline(1);
X line[cs++] = *s++;
X }
X inststr(exactstr);
X spaceinline(1);
X switch (slashflag) {
X case SLASH_YES: line[cs++] = '/'; break;
X case SLASH_NO : line[cs++] = ' '; break;
X case SLASH_MAYBE: line[cs++] =
X isdir(exactstr,pathprefix) ? '/' : ' '; break;
X }
X return;
X }
X s = peekfirst(matches);
X if ((*s == '~' || *s == '=' || *s == '$') && !haspath) {
X spaceinline(1);
X line[cs++] = *s++;
X ambig--;
X }
X inststrlen(s,ambig);
X refresh();
X if (isset(AUTOLIST)) {
X if (unset(NOLISTBEEP)) feep();
X listmatches(matches,
X unset(LISTTYPES) ? NULL : (haspath) ? pathprefix : "./");
X } else feep();
X}
X
Xvoid do_single(s) /**/
Xchar *s;
X{
X cs = wb;
X foredel(we-wb);
X if (*s == '~' || *s == '=' || *s == '$') {
X spaceinline(1);
X line[cs++] = *s++;
X }
X if (haspath) {
X inststr(s);
X spaceinline(1);
X line[cs++] = typechar;
X }
X s = peekfirst(matches);
X if ((*s == '~' || *s == '=' || *s == '$') && !haspath) {
X spaceinline(1);
X line[cs++] = *s++;
X }
X inststr(s);
X spaceinline(1);
X switch (slashflag) {
X case SLASH_YES: line[cs++] = '/'; break;
X case SLASH_NO : line[cs++] = ' '; break;
X case SLASH_MAYBE: line[cs++] = isdir(s,pathprefix) ? '/' : ' '; break;
X }
X if (isset(AUTOREMOVESLASH) && line[cs-1] == '/') addedslash = 1;
X}
X
Xvoid do_ambig_menu(s) /**/
Xchar *s;
X{
X menucmp = 1;
X if (isset(MENUCOMPLETEBEEP)) feep();
X cs = wb;
X menuw = cs;
X foredel(we-wb);
X if (*s == '~' || *s == '=' || *s == '$') {
X spaceinline(1);
X line[cs++] = *s++;
X }
X if (haspath) {
X inststr(s);
X spaceinline(1);
X line[cs++] = typechar;
X }
X menub = cs;
X s = peekfirst(matches);
X if ((*s == '~' || *s == '=' || *s == '$') && !haspath) {
X spaceinline(1);
X line[cs++] = *s++;
X }
X inststr(s);
X menue = cs;
X permalloc();
X menulist = duplist(matches,(VFunc)ztrdup);
X heapalloc();
X menunode = firstnode(menulist);
X permalloc();
X if (isset(LASTMENU)) {
X if (lastmenu)
X free(lastmenu);
X lastmenu = ztrdup(line);
X lastmenupos = cs;
X }
X}
X
Xint strpfx(s,t) /**/


Xchar *s;char *t;
X{

X while (*s && *s == *t) s++,t++;

X return !*s;
X}
X
Xint pfxlen(s,t) /**/


Xchar *s;char *t;
X{

Xint i = 0;
X
X while (*s && *s == *t) s++,t++,i++;
X return i;
X}
X
Xvoid listmatches(l,apps) /**/
XLklist l;char *apps;
X{
Xint longest = 1,fct,fw = 0,colsz,t0,t1,ct;
XLknode n;
Xchar **arr,**ap;
X
X trashzle();
X ct = countnodes(l);
X if (listmax && ct > listmax)
X {
X fprintf(stdout,"zsh: do you wish to see all %d possibilities? ",ct);
X fflush(stdout);
X if (getquery() != 'y')
X return;
X }
X ap = arr = alloc((countnodes(l)+1)*sizeof(char **));


X for (n = firstnode(l); n; incnode(n))

X *ap++ = getdata(n);
X *ap = NULL;
X for (ap = arr; *ap; ap++)
X if (strlen(*ap) > longest)
X longest = strlen(*ap);
X if (apps)
X {
X apps = strdup(apps);
X if (*apps == '~')
X *apps = Tilde;
X else if (*apps == '=')
X *apps = Equals;
X else if (*apps == '$')
X *apps = String;
X singsub(&apps);
X longest++;
X }
X qsort(arr,ct,sizeof(char *),forstrcmp);
X fct = (columns-1)/(longest+2);
X if (fct == 0)
X fct = 1;
X else
X fw = (columns-1)/fct;
X colsz = (ct+fct-1)/fct;
X for (t1 = 0; t1 != colsz; t1++)
X {
X ap = arr+t1;
X if (apps)
X {
X do
X {
X int t2 = strlen(*ap)+1;
X char pbuf[MAXPATHLEN];


X struct stat buf;
X

X printf("%s",*ap);
X sprintf(pbuf,"%s/%s",apps,*ap);
X if (lstat(pbuf,&buf)) putchar(' ');
X else switch (buf.st_mode & S_IFMT) /* screw POSIX */
X {
X case S_IFDIR: putchar('/'); break;
X#ifdef S_IFIFO
X case S_IFIFO: putchar('|'); break;
X#endif
X case S_IFCHR: putchar('%'); break;
X case S_IFBLK: putchar('#'); break;
X#ifdef S_IFLNK
X case S_IFLNK: putchar(
X (access(pbuf,F_OK) == -1) ? '&' : '@'); break;
X#endif
X#ifdef S_IFSOCK
X case S_IFSOCK: putchar('='); break;
X#endif
X default:
X if (buf.st_mode & 0111)
X putchar('*');
X else
X putchar(' ');
X break;
X }
X for (; t2 < fw; t2++) putchar(' ');
X for (t0 = colsz; t0 && *ap; t0--,ap++);
X }
X while (*ap);
X }
X else
X do
X {
X int t2 = strlen(*ap);
X
X printf("%s",*ap);
X for (; t2 < fw; t2++) putchar(' ');
X for (t0 = colsz; t0 && *ap; t0--,ap++);
X }
X while (*ap);


X putchar('\n');
X }

X resetneeded = 1;
X fflush(stdout);
X}
X
Xvoid selectlist(l) /**/
XLklist l;
X{
Xint longest = 1,fct,fw = 0,colsz,t0,t1,ct;
XLknode n;
Xchar **arr,**ap;
X
X trashzle();
X ct = countnodes(l);
X ap = arr = alloc((countnodes(l)+1)*sizeof(char **));


X for (n = firstnode(l); n; incnode(n))

X *ap++ = getdata(n);
X *ap = NULL;
X for (ap = arr; *ap; ap++)
X if (strlen(*ap) > longest)
X longest = strlen(*ap);
X t0 = ct;
X longest++;
X while (t0)
X t0 /= 10, longest++;
X fct = (columns-1)/(longest+3); /* to compensate for added ')' */
X if (fct == 0)
X fct = 1;
X else
X fw = (columns-1)/fct;
X colsz = (ct+fct-1)/fct;
X for (t1 = 0; t1 != colsz; t1++) {
X ap = arr+t1;
X do {
X int t2 = strlen(*ap)+2,t3;
X
X fprintf(stderr,"%d) %s",t3 = ap-arr+1,*ap);
X while (t3) t2++,t3 /= 10;
X for (; t2 < fw; t2++) fputc(' ',stderr);
X for (t0 = colsz; t0 && *ap; t0--,ap++);
X } while (*ap);


X fputc('\n',stderr);
X }

X
X/* Below is a simple attempt at doing it the Korn Way..
X ap = arr;
X t0 = 0;
X do
X {
X t0++;
X fprintf(stderr,"%d) %s\n",t0,*ap);
X ap++;
X }
X while (*ap);*/
X resetneeded = 1;
X fflush(stderr);
X}
X
Xint doexpandhist() /**/
X{
Xunsigned char *cc,*ce;
Xint t0,oldcs,oldll;
X
X for (cc = line, ce = line+ll; cc < ce; cc++)
X if (*cc == '\\' && cc[1])
X cc++;
X else if (*cc == bangchar ||
X (*cc == hatchar && *line == hatchar && cc != line))
X break;
X if (*cc == bangchar && cc[1] == '"') return 0;
X if (cc == ce) return 0;
X oldcs = cs;
X oldll = ll;
X zleparse = 1;
X lexsave();
X hungets(line);
X strinbeg();
X pushheap();
X ll = cs = 0;
X for(;;)
X {
X t0 = hgetc();


X if (lexstop)
X break;

X spaceinline(1);
X line[cs++] = t0;
X }
X hflush();
X popheap();
X strinend();
X errflag = zleparse = 0;
X t0 = histdone;
X lexrestore();
X line[ll = cs] = '\0';
X if (ll == oldll) cs = oldcs;


X return t0;
X}
X

Xvoid magicspace() /**/
X{
X c = ' ';
X selfinsert();
X doexpandhist();
X}
X
Xvoid expandhistory() /**/
X{
X if (!doexpandhist())
X feep();
X}
X
Xstatic int cmdwb,cmdwe;
X
Xchar *getcurcmd() /**/
X{
Xint lincmd = incmdpos;
Xchar *s = NULL;
X
X zleparse = 1;
X lexsave();
X hungets(" "); /* KLUDGE! */
X hungets(line);
X strinbeg();
X pushheap();
X do {
X lincmd = incmdpos;
X ctxtlex();
X if (tok == ENDINPUT) break;
X if (tok == STRING && lincmd) {
X if (s) free(s);
X s = ztrdup(tokstr);
X cmdwb = ll-wordbeg; cmdwe = ll+1-inbufct;
X }
X lincmd = incmdpos;
X } while (tok != ENDINPUT && zleparse);
X hflush();
X popheap();
X strinend();
X errflag = zleparse = 0;
X lexrestore();


X return s;
X}
X

Xvoid processcmd() /**/
X{
Xchar *s,*t;
X
X s = getcurcmd();
X if (!s) { feep(); return; }
X t = zlecmds[bindk].name;
X mult = 1;
X pushline();
X sizeline(strlen(s)+strlen(t)+1);
X strcpy((char *) line,t);
X strcat((char *) line," ");
X cs = ll = strlen((char *) line);
X inststr(s);
X free(s);
X done = 1;
X}
X
Xvoid expandcmdpath() /**/
X{
Xint oldcs = cs;
Xchar *s,*str;
X
X s = getcurcmd();
X if (!s) { feep(); return; }
X str = findcmd(s);
X free(s);
X if (!str) { feep(); return; }
X cs = cmdwb;
X foredel(cmdwe-cmdwb);
X spaceinline(strlen(str));
X strncpy((char *) line+cs,str,strlen(str));
X cs = oldcs;
X if (cs >= cmdwe) cs += cmdwe-cmdwb+strlen(str);
X if (cs > ll) cs = ll;
X free(str);
X}
X
Xvoid freemenu() /**/
X{
X if (menucmp && (unset(LASTMENU) || lastmenu == NULL)) {
X menucmp = 0;
X freetable(menulist,freestr);
X }
X}
X
Xint inarray(s,a) /**/
Xchar *s; char **a;
X{
X for (; *a; a++) if (!strcmp(*a,s)) return 1;
X return 0;
X}
X
SHAR_EOF
echo 'File zsh2.2/src/zle_tricky.c is complete' &&
chmod 0644 zsh2.2/src/zle_tricky.c ||


echo 'restore of zsh2.2/src/zle_tricky.c failed'

Wc_c="`wc -c < 'zsh2.2/src/zle_tricky.c'`"
test 26002 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_tricky.c: original size 26002, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/builtin.pro ==============
if test -f 'zsh2.2/src/builtin.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/builtin.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/builtin.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/builtin.pro' &&
Xvoid addbuiltins DCLPROTO((void));
Xint bin_enable DCLPROTO((char *name,char **argv,char *ops,int whocares));
Xint bin_colon DCLPROTO((char *name,char **argv,char *ops,int whocares));
Xint bin_break DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_fg DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_let DCLPROTO((char *name,char **argv,char *ops,int func));
Xint zexit DCLPROTO((int val));
Xint optlookup DCLPROTO((char *s));
Xint bin_setopt DCLPROTO((char *nam,char **args,char *ops,int isun));
Xvoid listhtable DCLPROTO((Hashtab ht,HFunc func));
Xvoid pshfunc DCLPROTO((char *s,Cmdnam cc));
Xvoid niceprint DCLPROTO((char *s));
Xvoid niceprintf DCLPROTO((char *s,FILE *f));
Xint bin_umask DCLPROTO((char *nam,char **args,char *ops,int func));
Xint bin_whence DCLPROTO((char *nam,char **argv,char *ops,int func));
Xint bin_cd DCLPROTO((char *nam,char **argv,char *ops,int func));
Xchar *cd_get_dest DCLPROTO((char *nam,char **argv,char *ops,int func));
Xchar *cd_do_chdir DCLPROTO((char *cnam, char *dest));
Xchar *cd_try_chdir DCLPROTO((char *pfix, char *dest));
Xint fixdir DCLPROTO((char *d, char *s));
Xvoid cd_new_pwd DCLPROTO((int func, char *s));
Xvoid convertwd DCLPROTO((char *s, char *t, int off));
Xint bin_rehash DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_hash DCLPROTO((char *name,char **argv,char *ops,int func));
Xint prefix DCLPROTO((char *s,char *t));
Xint getjob DCLPROTO((char *s,char *prog));
Xint findjobnam DCLPROTO((char *s));
Xint isanum DCLPROTO((char *s));
Xint bin_kill DCLPROTO((char *nam,char **argv,char *ops,int func));
Xint bin_limit DCLPROTO((char *nam,char **argv,char *ops,int func));
Xint bin_unlimit DCLPROTO((char *nam,char **argv,char *ops,int func));
Xvoid showlimits DCLPROTO((int hard,int lim));
Xint bin_sched DCLPROTO((char *nam,char **argv,char *ops,int func));
Xint bin_eval DCLPROTO((char *nam,char **argv,char *ops,int func));
Xint fcgetcomm DCLPROTO((char *s));
Xint fcsubs DCLPROTO((char **sp,struct asgment *sub));
Xint fclist DCLPROTO((FILE *f,int n,int r,int D,int d,int first,int last,struct asgment *subs));
Xint fcedit DCLPROTO((char *ename,char *fn));
Xint bin_fc DCLPROTO((char *nam,char **argv,char *ops,int func));
Xint bin_suspend DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_alias DCLPROTO((char *name,char **argv,char *ops,int func));
Xvoid printalias DCLPROTO((char *s,struct alias *a));
Xvoid printparam DCLPROTO((char *s,Param p));
Xint bin_typeset DCLPROTO((char *name,char **argv,char *ops,int func));
Xchar *escsubst DCLPROTO((char *s, int *nnl));
Xint bin_print DCLPROTO((char *name,char **args,char *ops,int func));
Xint bin_dirs DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_unalias DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_disable DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_unhash DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_unset DCLPROTO((char *name,char **argv,char *ops,int func));
Xint zread DCLPROTO((void));
Xint bin_read DCLPROTO((char *name,char **args,char *ops,int func));
Xint bin_vared DCLPROTO((char *name,char **args,char *ops,int func));
Xint execbin DCLPROTO((Lklist args,Cmdnam cnode));
Xstruct asgment *getasg DCLPROTO((char *s));
Xint bin_dot DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_set DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_times DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_getopts DCLPROTO((char *name,char **argv,char *ops,int func));
Xint getsignum DCLPROTO((char *s));
Xint bin_trap DCLPROTO((char *name,char **argv,char *ops,int func));
Xvoid printulimit DCLPROTO((int lim,int hard));
Xint bin_ulimit DCLPROTO((char *name,char **argv,char *ops,int func));
Xint putraw DCLPROTO((int c));
Xint bin_echotc DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_pwd DCLPROTO((char *name,char **argv,char *ops,int func));
Xint bin_test DCLPROTO((char *name,char **argv,char *ops,int func));
XCond partest DCLPROTO((int level));
Xint bin_compctl DCLPROTO((char *name,char **argv,char *ops,int func));
Xvoid printcompctl DCLPROTO((char *s,Compctl cc));
Xvoid compctl_process DCLPROTO((char **s,int mask,char *uk));
Xint bin_ttyctl DCLPROTO((char *name,char **argv,char *ops,int func));
SHAR_EOF
chmod 0644 zsh2.2/src/builtin.pro ||
echo 'restore of zsh2.2/src/builtin.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/builtin.pro'`"
test 4239 -eq "$Wc_c" ||
echo 'zsh2.2/src/builtin.pro: original size 4239, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/cond.pro ==============
if test -f 'zsh2.2/src/cond.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/cond.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/cond.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/cond.pro' &&
Xint evalcond DCLPROTO((Cond c));
Xint doaccess DCLPROTO((char *s,int c));
Xstruct stat *getstat DCLPROTO((char *s));
Xunsigned short dostat DCLPROTO((char *s));
Xunsigned short dolstat DCLPROTO((char *s));
Xint optison DCLPROTO((char *s));
SHAR_EOF
chmod 0644 zsh2.2/src/cond.pro ||
echo 'restore of zsh2.2/src/cond.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/cond.pro'`"
test 235 -eq "$Wc_c" ||
echo 'zsh2.2/src/cond.pro: original size 235, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/exec.pro ==============
if test -f 'zsh2.2/src/exec.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/exec.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/exec.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/exec.pro' &&
XList parselstring DCLPROTO((char *s));
Xvoid execstring DCLPROTO((char *s));
Xint phork DCLPROTO((void));
Xint execcursh DCLPROTO((Cmd cmd));
Xint zexecve DCLPROTO((char *pth,char **argv));
Xvoid execute DCLPROTO((int dash));
Xchar *findcmd DCLPROTO((char *arg0));
Xint iscom DCLPROTO((char *s));
Xint isrelative DCLPROTO((char *s));
Xint hashcmd DCLPROTO((char *arg0,char **pp));
Xvoid fullhash DCLPROTO((void));
Xvoid execlist DCLPROTO((List list));
Xvoid execlist2 DCLPROTO((Sublist list,int type,int last1));
Xint execpline DCLPROTO((Sublist l,int how,int last1));
Xvoid execpline2 DCLPROTO((Pline pline,int how,int input,int output,int last1));
Xchar **makecline DCLPROTO((struct lklist *list));
Xvoid fixcline DCLPROTO((Lklist l));
Xvoid untokenize DCLPROTO((char *s));
Xint dontclob DCLPROTO((struct redir *f));
Xvoid closemn DCLPROTO((struct multio **mfds,int fd));
Xvoid closemnodes DCLPROTO((struct multio **mfds));
Xvoid addfd DCLPROTO((int forked,int *save,struct multio **mfds,int fd1,int fd2,int rflag));
Xvoid addvars DCLPROTO((Lklist l,int export));
Xvoid execcmd DCLPROTO((Cmd cmd,int input,int output,int bkg,int last1));
Xvoid fixfds DCLPROTO((int *save));
Xvoid entersubsh DCLPROTO((int bkg));
Xvoid closem DCLPROTO((void));
Xchar *gethere DCLPROTO((char *str,int typ));
Xint getherestr DCLPROTO((struct redir *fn));
Xvoid catproc DCLPROTO((struct multio *mn));
Xvoid teeproc DCLPROTO((struct multio *mn));
Xvoid closeallelse DCLPROTO((struct multio *mn));
Xlong int zstrtol DCLPROTO((char *s,char **t,int base));
XLklist getoutput DCLPROTO((char *cmd,int qt));
XLklist readoutput DCLPROTO((int in,int qt));
Xchar *getoutputfile DCLPROTO((char *cmd));
Xchar *namedpipe DCLPROTO((void));
Xchar *getoutproc DCLPROTO((char *cmd));
Xchar *getinproc DCLPROTO((char *cmd));
Xint getinpipe DCLPROTO((char *cmd));
Xint getoutpipe DCLPROTO((char *cmd));
Xvoid runlist DCLPROTO((List l));
Xchar *gettemp DCLPROTO((void));
Xchar *zgetwd DCLPROTO((void));
Xvoid mpipe DCLPROTO((int *pp));
Xvoid spawnpipes DCLPROTO((Lklist l));
Xint exectime DCLPROTO((Cmd cmd));
Xint execfuncdef DCLPROTO((Cmd cmd));
Xint execcond DCLPROTO((Cmd cmd));
Xvoid execshfunc DCLPROTO((Cmd cmd,Cmdnam cn));
Xvoid doshfuncnoval DCLPROTO((List list, Lklist args, int flags));
Xvoid doshfunc DCLPROTO((List list, Lklist args, int flags));
XList getfpfunc DCLPROTO((char *s));
SHAR_EOF
chmod 0644 zsh2.2/src/exec.pro ||
echo 'restore of zsh2.2/src/exec.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/exec.pro'`"
test 2306 -eq "$Wc_c" ||
echo 'zsh2.2/src/exec.pro: original size 2306, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/glob.pro ==============
if test -f 'zsh2.2/src/glob.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/glob.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/glob.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/glob.pro' &&
Xvoid glob DCLPROTO((Lklist list,Lknode *np));
Xlong qgetnum DCLPROTO((char **s));
Xint notstrcmp DCLPROTO((char **a,char **b));
Xint forstrcmp DCLPROTO((char **a,char **b));
Xvoid insert DCLPROTO((char *s));
Xint haswilds DCLPROTO((char *str));
Xint hasbraces DCLPROTO((char *str));
Xint xpandredir DCLPROTO((struct redir *fn,Lklist tab));
Xchar *dyncat DCLPROTO((char *s1,char *s2));
Xchar *tricat DCLPROTO((char *s1,char *s2,char *s3));
Xvoid xpandbraces DCLPROTO((Lklist list,Lknode *np));
Xchar *getparen DCLPROTO((char *str));
Xint matchpat DCLPROTO((char *a,char *b));
Xvoid getmatch DCLPROTO((char **sp,char *pat,int dd));
Xchar *getfullpath DCLPROTO((char *s));
Xvoid scanner DCLPROTO((Complist q));
Xint minimatch DCLPROTO((char **pat,char **str));
Xint domatch DCLPROTO((char *str,Comp c,int fist));
Xint doesmatch DCLPROTO((Comp c));
XComplist parsepat DCLPROTO((char *str));
XComp parsereg DCLPROTO((char *str));
XComplist parsecomplist DCLPROTO((void));
XComp parsecomp DCLPROTO((void));
XComp parsecompsw DCLPROTO((void));
Xint patmatch DCLPROTO((char *ss,char *tt));
Xvoid remnulargs DCLPROTO((char *s));
Xint qualdev DCLPROTO((struct stat *buf,long dv));
Xint qualnlink DCLPROTO((struct stat *buf,long ct));
Xint qualuid DCLPROTO((struct stat *buf,long uid));
Xint qualgid DCLPROTO((struct stat *buf,long gid));
Xint qualisdev DCLPROTO((struct stat *buf,long junk));
Xint qualmode DCLPROTO((struct stat *buf,long mod));
Xint qualflags DCLPROTO((struct stat *buf,long mod));
Xint qualiscom DCLPROTO((struct stat *buf,long mod));
SHAR_EOF
chmod 0644 zsh2.2/src/glob.pro ||
echo 'restore of zsh2.2/src/glob.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/glob.pro'`"
test 1511 -eq "$Wc_c" ||
echo 'zsh2.2/src/glob.pro: original size 1511, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/hist.pro ==============
if test -f 'zsh2.2/src/hist.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/hist.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/hist.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/hist.pro' &&
Xvoid hwaddc DCLPROTO((int c));
Xint hgetc DCLPROTO((void));
Xvoid clearalstack DCLPROTO((void));
Xint hgetch DCLPROTO((void));
Xchar *hgets DCLPROTO((char *buf,int n));
Xvoid hungets DCLPROTO((char *str));
Xvoid hungetc DCLPROTO((int c));
Xvoid hungetch DCLPROTO((int c));
Xvoid strinbeg DCLPROTO((void));
Xvoid strinend DCLPROTO((void));
Xint stuff DCLPROTO((char *fn));
Xvoid hflush DCLPROTO((void));
Xvoid hbegin DCLPROTO((void));
Xvoid inittty DCLPROTO((void));
Xint hend DCLPROTO((void));
Xvoid remhist DCLPROTO((void));
Xvoid hwbegin DCLPROTO((void));
Xchar *hwadd DCLPROTO((void));
Xint getargspec DCLPROTO((int argc,int marg));
Xint hconsearch DCLPROTO((char *str,int *marg));
Xint hcomsearch DCLPROTO((char *str));
Xint remtpath DCLPROTO((char **junkptr));
Xint remtext DCLPROTO((char **junkptr));
Xint rembutext DCLPROTO((char **junkptr));
Xint remlpaths DCLPROTO((char **junkptr));
Xint makeuppercase DCLPROTO((char **junkptr));
Xint makelowercase DCLPROTO((char **junkptr));
Xvoid subst DCLPROTO((char **strptr,char *in,char *out,int gbal));
Xchar *convamps DCLPROTO((char *out,char *in));
Xchar *makehstr DCLPROTO((char *s));
Xchar *quietgetevent DCLPROTO((int ev));
Xchar *getevent DCLPROTO((int ev));
Xint getargc DCLPROTO((char *list));
Xchar *getargs DCLPROTO((char *elist,int arg1,int arg2));
Xvoid upcase DCLPROTO((char **x));
Xvoid downcase DCLPROTO((char **x));
Xint quote DCLPROTO((char **tr));
Xint quotebreak DCLPROTO((char **tr));
Xvoid herrflush DCLPROTO((void));
Xchar *hdynread DCLPROTO((int stop));
Xchar *hdynread2 DCLPROTO((int stop));
Xvoid inithist DCLPROTO((void));
Xvoid resizehistents DCLPROTO((void));
Xchar *hp_alloc DCLPROTO((Hp *hp, int siz));
Xchar *hp_realloc DCLPROTO((Hp *hp, char *ptr, int oldsiz, int newsiz));
Xvoid hp_free DCLPROTO((Hp h, char *ptr, int siz));
Xchar *hp_concat DCLPROTO((char *old, char *new));
Xvoid hp_purge DCLPROTO((Hp h, int lim));
Xvoid readhistfile DCLPROTO((char *s,int err));
Xvoid savehistfile DCLPROTO((char *s,int err,int app));
Xint firsthist DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/hist.pro ||
echo 'restore of zsh2.2/src/hist.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/hist.pro'`"
test 1989 -eq "$Wc_c" ||
echo 'zsh2.2/src/hist.pro: original size 1989, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/init.pro ==============
if test -f 'zsh2.2/src/init.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/init.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/init.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/init.pro' &&
Xvoid main DCLPROTO((int argc, char **argv, char **envp));
Xvoid loop DCLPROTO((void));
Xvoid setflags DCLPROTO((void));
Xvoid parseargs DCLPROTO((char **argv));
Xvoid setmoreflags DCLPROTO((void));
Xvoid setupvals DCLPROTO((void));
Xvoid compctlsetup DCLPROTO((void));
Xvoid initialize DCLPROTO((void));
Xvoid addreswords DCLPROTO((void));
Xvoid runscripts DCLPROTO((void));
Xvoid ainit DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/init.pro ||
echo 'restore of zsh2.2/src/init.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/init.pro'`"
test 395 -eq "$Wc_c" ||
echo 'zsh2.2/src/init.pro: original size 395, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/jobs.pro ==============
if test -f 'zsh2.2/src/jobs.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/jobs.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/jobs.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/jobs.pro' &&
XHANDTYPE handler DCLPROTO((int sig,int code));
Xvoid makerunning DCLPROTO((Job jn));
Xvoid updatestatus DCLPROTO((Job jn));
Xvoid findproc DCLPROTO((int pid,Job *jptr,struct process **pptr));
Xvoid printjob DCLPROTO((Job jn,int lng));
Xvoid setprevjob DCLPROTO((void));
Xvoid initjob DCLPROTO((void));
Xstruct process *addproc DCLPROTO((long pid,char *text));
Xint execok DCLPROTO((void));
Xvoid waitforpid DCLPROTO((long pid));
Xvoid waitjob DCLPROTO((int job));
Xvoid waitjobs DCLPROTO((void));
Xvoid clearjobtab DCLPROTO((void));
Xint getfreejob DCLPROTO((void));
Xvoid spawnjob DCLPROTO((void));
Xvoid fixsigs DCLPROTO((void));
Xint report DCLPROTO((Job j));
Xvoid printtime DCLPROTO((time_t real,struct timeinfo *ti,char *desc));
Xvoid dumptime DCLPROTO((Job jn));
Xvoid shelltime DCLPROTO((void));
Xvoid killrunjobs DCLPROTO((void));
Xvoid checkjobs DCLPROTO((void));
Xint killjb DCLPROTO((Job jn,int sig));
SHAR_EOF
chmod 0644 zsh2.2/src/jobs.pro ||
echo 'restore of zsh2.2/src/jobs.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/jobs.pro'`"
test 892 -eq "$Wc_c" ||
echo 'zsh2.2/src/jobs.pro: original size 892, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/lex.pro ==============
if test -f 'zsh2.2/src/lex.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/lex.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/lex.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/lex.pro' &&
Xvoid lexsave DCLPROTO((void));
Xvoid lexrestore DCLPROTO((void));
Xvoid yylex DCLPROTO((void));
Xvoid ctxtlex DCLPROTO((void));
Xvoid initlextabs DCLPROTO((void));
Xvoid lexinit DCLPROTO((void));
Xvoid add DCLPROTO((int c));
Xint gettok DCLPROTO((void));
Xint exalias DCLPROTO((void));
Xint skipcomm DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/lex.pro ||
echo 'restore of zsh2.2/src/lex.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/lex.pro'`"
test 309 -eq "$Wc_c" ||
echo 'zsh2.2/src/lex.pro: original size 309, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/loop.pro ==============
if test -f 'zsh2.2/src/loop.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/loop.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/loop.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/loop.pro' &&
Xint execfor DCLPROTO((Cmd cmd));
Xint execselect DCLPROTO((Cmd cmd));
Xint execwhile DCLPROTO((Cmd cmd));
Xint execrepeat DCLPROTO((Cmd cmd));
Xint execif DCLPROTO((Cmd cmd));
Xint execcase DCLPROTO((Cmd cmd));
SHAR_EOF
chmod 0644 zsh2.2/src/loop.pro ||
echo 'restore of zsh2.2/src/loop.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/loop.pro'`"
test 206 -eq "$Wc_c" ||
echo 'zsh2.2/src/loop.pro: original size 206, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/math.pro ==============
if test -f 'zsh2.2/src/math.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/math.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/math.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/math.pro' &&
Xint zzlex DCLPROTO((void));
Xint notzero DCLPROTO((int a));
Xvoid op DCLPROTO((int what));
Xvoid bop DCLPROTO((int tk));
Xlong mathevall DCLPROTO((char *s,int prek,char **ep));
Xlong matheval DCLPROTO((char *s));
Xlong mathevalarg DCLPROTO((char *s,char **ss));
Xvoid mathparse DCLPROTO((int pc));
SHAR_EOF
chmod 0644 zsh2.2/src/math.pro ||
echo 'restore of zsh2.2/src/math.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/math.pro'`"
test 291 -eq "$Wc_c" ||
echo 'zsh2.2/src/math.pro: original size 291, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/mem.pro ==============
if test -f 'zsh2.2/src/mem.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/mem.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/mem.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/mem.pro' &&
Xvoid meminit DCLPROTO((void));
Xvoid heapalloc DCLPROTO((void));
Xvoid permalloc DCLPROTO((void));
Xvoid lastalloc DCLPROTO((void));
Xvoid pushheap DCLPROTO((void));
Xvoid freeheap DCLPROTO((void));
Xvoid popheap DCLPROTO((void));
Xvoid freeh DCLPROTO((Heap h));
Xvptr halloc DCLPROTO((int size));
Xvptr hcalloc DCLPROTO((int size));
Xvptr hrealloc DCLPROTO((char *p,int old,int new));
Xvptr zalloc DCLPROTO((int l));
Xvptr zcalloc DCLPROTO((int size));
Xchar *strdup DCLPROTO((char *s));
Xchar *ztrdup DCLPROTO((char *s));
SHAR_EOF
chmod 0644 zsh2.2/src/mem.pro ||
echo 'restore of zsh2.2/src/mem.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/mem.pro'`"
test 510 -eq "$Wc_c" ||
echo 'zsh2.2/src/mem.pro: original size 510, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/params.pro ==============
if test -f 'zsh2.2/src/params.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/params.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/params.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/params.pro' &&
Xvoid setupparams DCLPROTO((void));
Xstruct param *createparam DCLPROTO((char *name,vptr value,int flags));
Xint isident DCLPROTO((char *s));
XValue getvalue DCLPROTO((char **pptr,int bracks));
Xchar *getstrvalue DCLPROTO((Value v));
Xchar **getarrvalue DCLPROTO((Value v));
Xlong getintvalue DCLPROTO((Value v));
Xvoid setstrvalue DCLPROTO((Value v,char *val));
Xvoid setintvalue DCLPROTO((Value v,long val));
Xvoid setintenv DCLPROTO((char *s, long val));
Xvoid setarrvalue DCLPROTO((Value v,char **val));
Xchar *getsparamval DCLPROTO((char *s,int l));
Xlong getiparam DCLPROTO((char *s));
Xchar *getsparam DCLPROTO((char *s));
Xchar **getaparam DCLPROTO((char *s));
XParam setsparam DCLPROTO((char *s,char *val));
XParam setaparam DCLPROTO((char *s,char **val));
XParam setiparam DCLPROTO((char *s,long val));
Xvoid unsetparam DCLPROTO((char *s));
Xvoid intsetfn DCLPROTO((Param pm,long x));
Xlong intgetfn DCLPROTO((Param pm));
Xvoid strsetfn DCLPROTO((Param pm,char *x));
Xchar *strgetfn DCLPROTO((Param pm));
Xvoid nullsetfn DCLPROTO((Param pm, char *x));
Xvoid arrsetfn DCLPROTO((Param pm,char **x));
Xchar **arrgetfn DCLPROTO((Param pm));
Xvoid intvarsetfn DCLPROTO((Param pm,long x));
Xlong intvargetfn DCLPROTO((Param pm));
Xvoid strvarsetfn DCLPROTO((Param pm,char *x));
Xvoid strvarnonullsetfn DCLPROTO((Param pm,char *x));
Xchar *strvargetfn DCLPROTO((Param pm));
Xchar *strconstgetfn DCLPROTO((Param pm));
Xvoid colonarrsetfn DCLPROTO((Param pm,char *x));
Xchar *colonarrgetfn DCLPROTO((Param pm));
Xchar **arrvargetfn DCLPROTO((Param pm));
Xvoid arrvarsetfn DCLPROTO((Param pm,char **x));
Xchar **pathgetfn DCLPROTO((Param pm));
Xvoid pathsetfn DCLPROTO((Param pm,char **x));
Xvoid hostcmdssetfn DCLPROTO((Param pm,char **x));
Xvoid optcmdssetfn DCLPROTO((Param pm,char **x));
Xvoid bindcmdssetfn DCLPROTO((Param pm,char **x));
Xvoid varcmdssetfn DCLPROTO((Param pm,char **x));
Xchar **nullgetfn DCLPROTO((Param pm));
Xvoid unsettablesetfn DCLPROTO((Param pm,char *x));
Xlong poundgetfn DCLPROTO((Param pm));
Xlong randomgetfn DCLPROTO((Param pm));
Xvoid randomsetfn DCLPROTO((Param pm,long v));
Xlong secondsgetfn DCLPROTO((Param pm));
Xvoid secondssetfn DCLPROTO((Param pm,long x));
Xlong uidgetfn DCLPROTO((Param pm));
Xlong gidgetfn DCLPROTO((Param pm));
Xchar *usernamegetfn DCLPROTO((Param pm));
Xchar *hostgetfn DCLPROTO((Param pm));
Xchar *ifsgetfn DCLPROTO((Param pm));
Xvoid ifssetfn DCLPROTO((Param pm,char *x));
Xvoid histsizesetfn DCLPROTO((Param pm,long v));
Xlong histsizegetfn DCLPROTO((Param pm));
SHAR_EOF
true || echo 'restore of zsh2.2/src/params.pro failed'
fi
echo 'End of zsh2.2 part 15'
echo 'File zsh2.2/src/params.pro is continued in part 16'
echo 16 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:10:48 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 112
Archive-name: zsh2.2/part16

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.16 (part 16 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/params.pro continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 16; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/params.pro'
else
echo 'x - continuing file zsh2.2/src/params.pro'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/params.pro' &&

Xvoid lithistsizesetfn DCLPROTO((Param pm,long v));
Xlong lithistsizegetfn DCLPROTO((Param pm));
Xvoid mailchecksetfn DCLPROTO((Param pm,long x));
Xvoid pathasetfn DCLPROTO((Param pm,char **x));
Xchar **pathagetfn DCLPROTO((Param pm));
Xlong errnogetfn DCLPROTO((Param pm));
Xchar *dashgetfn DCLPROTO((Param pm));
Xvoid histcharssetfn DCLPROTO((Param pm,char *x));
Xchar *histcharsgetfn DCLPROTO((Param pm));
Xchar *homegetfn DCLPROTO((Param pm));
Xvoid homesetfn DCLPROTO((Param pm,char *x));
Xchar *wordcharsgetfn DCLPROTO((Param pm));
Xvoid wordcharssetfn DCLPROTO((Param pm,char *x));
Xchar *underscoregetfn DCLPROTO((Param pm));
Xchar *termgetfn DCLPROTO((Param pm));
Xvoid termsetfn DCLPROTO((Param pm,char *x));
Xvoid setparams DCLPROTO((void));
Xchar *mkenvstr DCLPROTO((char *x,char *y));
Xvoid arrfixenv DCLPROTO((char *s,char **t));
Xchar *replenv DCLPROTO((char *e,char *value));
Xchar *addenv DCLPROTO((char *name,char *value));
Xvoid delenv DCLPROTO((char *x));
Xvoid convbase DCLPROTO((char *s,long v,int base));
SHAR_EOF
echo 'File zsh2.2/src/params.pro is complete' &&
chmod 0644 zsh2.2/src/params.pro ||


echo 'restore of zsh2.2/src/params.pro failed'

Wc_c="`wc -c < 'zsh2.2/src/params.pro'`"
test 3478 -eq "$Wc_c" ||
echo 'zsh2.2/src/params.pro: original size 3478, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/subst.pro ==============
if test -f 'zsh2.2/src/subst.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/subst.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/subst.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/subst.pro' &&
Xvoid prefork DCLPROTO((Lklist list));
Xvoid postfork DCLPROTO((Lklist list,int doglob));
Xvoid singsub DCLPROTO((char **s));
Xvptr nstrdup DCLPROTO((vptr s));
Xchar *dynread DCLPROTO((int stop));
Xint filesub DCLPROTO((char **namptr));
Xchar *gethome DCLPROTO((char *user,int len));
Xvoid commsubst DCLPROTO((Lklist l,Lknode n,char *str3,char *str,int qt));
Xvoid paramsubst DCLPROTO((Lklist l,Lknode n,char *aptr,char *bptr,int qt));
Xvoid arithsubst DCLPROTO((vptr *aptr,char **bptr));
Xvoid modify DCLPROTO((char **str,char **ptr));
Xchar *dstackent DCLPROTO((int val));
Xstruct alias *mkanode DCLPROTO((char *txt,int cmflag));
SHAR_EOF
chmod 0644 zsh2.2/src/subst.pro ||
echo 'restore of zsh2.2/src/subst.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/subst.pro'`"
test 619 -eq "$Wc_c" ||
echo 'zsh2.2/src/subst.pro: original size 619, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/table.pro ==============
if test -f 'zsh2.2/src/table.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/table.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/table.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/table.pro' &&
XLklist newlist DCLPROTO((void));
XHashtab newhtable DCLPROTO((int size));
Xint hasher DCLPROTO((char *s));
Xvoid Addhnode DCLPROTO((char *nam,vptr dat,Hashtab ht,FFunc freefunc,int canfree));
Xvoid addhcmdnode DCLPROTO((char *nam,char **pnam));
Xvoid expandhtab DCLPROTO((Hashtab ht));
Xvptr gethnode DCLPROTO((char *nam,Hashtab ht));
Xvoid freehtab DCLPROTO((Hashtab ht,FFunc freefunc));
Xvptr remhnode DCLPROTO((char *nam,Hashtab ht));
Xvoid insnode DCLPROTO((Lklist list,Lknode llast,vptr dat));
Xvoid addnodeinorder DCLPROTO((Lklist x, char *dat));
Xvptr remnode DCLPROTO((Lklist list,Lknode nd));
Xvptr uremnode DCLPROTO((Lklist list,Lknode nd));
Xvoid chuck DCLPROTO((char *str));
Xvptr getnode DCLPROTO((Lklist list));
Xvptr ugetnode DCLPROTO((Lklist list));
Xvoid freetable DCLPROTO((Lklist tab,FFunc freefunc));
Xchar *ztrstr DCLPROTO((char *s,char *t));
Xvoid inslist DCLPROTO((Lklist l,Lknode where,Lklist x));
Xint countnodes DCLPROTO((Lklist x));
SHAR_EOF
chmod 0644 zsh2.2/src/table.pro ||
echo 'restore of zsh2.2/src/table.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/table.pro'`"
test 941 -eq "$Wc_c" ||
echo 'zsh2.2/src/table.pro: original size 941, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/text.pro ==============
if test -f 'zsh2.2/src/text.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/text.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/text.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/text.pro' &&
Xvoid taddchr DCLPROTO((int c));
Xvoid taddstr DCLPROTO((char *s));
Xvoid taddint DCLPROTO((int x));
Xvoid taddnl DCLPROTO((void));
Xchar *getpermtext DCLPROTO((struct node *n));
Xchar *getjobtext DCLPROTO((struct node *n));
Xvoid gettext2 DCLPROTO((struct node *n));
Xvoid getsimptext DCLPROTO((Cmd cmd));
Xvoid getredirs DCLPROTO((Cmd cmd));
Xvoid taddlist DCLPROTO((Lklist l));
SHAR_EOF
chmod 0644 zsh2.2/src/text.pro ||
echo 'restore of zsh2.2/src/text.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/text.pro'`"
test 371 -eq "$Wc_c" ||
echo 'zsh2.2/src/text.pro: original size 371, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/utils.pro ==============
if test -f 'zsh2.2/src/utils.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/utils.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/utils.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/utils.pro' &&
Xint source DCLPROTO((char *s));
Xvoid sourcehome DCLPROTO((char *s));
Xvoid zerrnam DCLPROTO((char *cmd, char *fmt, char *str,int num));
Xvoid zerr DCLPROTO((char *fmt, char *str,int num));
Xvoid niceputc DCLPROTO((int c,FILE *f));
Xvoid intr DCLPROTO((void));
Xvoid noholdintr DCLPROTO((void));
Xvoid holdintr DCLPROTO((void));
Xchar *fgetline DCLPROTO((char *buf,int len,FILE *in));
Xchar *findpwd DCLPROTO((char *s));
Xchar *fixpwd DCLPROTO((char *s));
Xint ispwd DCLPROTO((char *s));
Xchar *xsymlink DCLPROTO((char *s));
Xchar **slashsplit DCLPROTO((char *s));
Xint islink DCLPROTO((char *s));
Xint xsymlinks DCLPROTO((char *s,int flag));
Xvoid fprintdir DCLPROTO((char *s, FILE *f));
Xvoid printdir DCLPROTO((char *s));
Xvoid printdircr DCLPROTO((char *s));
Xint finddir DCLPROTO((char *s));
Xvoid adduserdir DCLPROTO((char *s,char *t));
Xint dircmp DCLPROTO((char *s,char *t));
Xint ddifftime DCLPROTO((time_t t1,time_t t2));
Xvoid scanjobs DCLPROTO((void));
Xvoid preprompt DCLPROTO((void));
Xint arrlen DCLPROTO((char **s));
Xvoid checkmailpath DCLPROTO((char **s));
Xvoid saveoldfuncs DCLPROTO((char *x,Cmdnam y));
Xvoid newcmdnamtab DCLPROTO((void));
Xvoid freecmdnam DCLPROTO((vptr a));
Xvoid freecompctl DCLPROTO((vptr a));
Xvoid freestr DCLPROTO((vptr a));
Xvoid freeanode DCLPROTO((vptr a));
Xvoid freepm DCLPROTO((vptr a));
Xvoid restoretty DCLPROTO((void));
Xvoid gettyinfo DCLPROTO((struct ttyinfo *ti));
Xvoid settyinfo DCLPROTO((struct ttyinfo *ti));
Xvoid sanetty DCLPROTO((struct ttyinfo *ti));
Xvoid adjustwinsize DCLPROTO((void));
Xint zyztem DCLPROTO((char *s,char *t));
Xint waitfork DCLPROTO((void));
Xint movefd DCLPROTO((int fd));
Xvoid redup DCLPROTO((int x,int y));
Xvoid settrap DCLPROTO((int t0,List l));
Xvoid unsettrap DCLPROTO((int t0));
Xvoid dotrap DCLPROTO((int sig));
Xvoid ztrncpy DCLPROTO((char *s,char *t,int len));
Xvoid strucpy DCLPROTO((char **s,char *t));
Xvoid struncpy DCLPROTO((char **s,char *t,int n));
Xvoid checkrmall DCLPROTO((char *s));
Xint getquery DCLPROTO((void));
Xvoid spscannodis DCLPROTO((char *s,char *cn));
Xvoid spscan DCLPROTO((char *s,char *junk));
Xvoid spckword DCLPROTO((char **s,char **s2,char **tptr,int cmd,int ask));
Xint ztrftime DCLPROTO((char *buf,int bufsize,char *fmt,struct tm *tm));
Xchar *join DCLPROTO((char **arr,int delim));
Xchar *spacejoin DCLPROTO((char **s));
Xchar *colonjoin DCLPROTO((char **s));
Xchar **colonsplit DCLPROTO((char *s));
Xchar **spacesplit DCLPROTO((char *s));
XList getshfunc DCLPROTO((char *nam));
Xvptr allocnode DCLPROTO((int type));
Xvptr dupstruct DCLPROTO((vptr a));
Xvoid freestruct DCLPROTO((vptr a));
XLklist duplist DCLPROTO((Lklist l,VFunc func));
Xchar **mkarray DCLPROTO((char *s));
Xvoid feep DCLPROTO((void));
Xvoid freearray DCLPROTO((char **s));
Xint equalsplit DCLPROTO((char *s,char **t));
Xvoid simplifyright DCLPROTO((List l));
Xvoid inittyptab DCLPROTO((void));
Xchar **arrdup DCLPROTO((char **s));
Xchar *spname DCLPROTO((char *oldname));
Xint mindist DCLPROTO((char *dir,char *guess,char *best));
Xint spdist DCLPROTO((char *s,char *t,int thresh));
Xchar *zgetenv DCLPROTO((char *s));
Xint tulower DCLPROTO((int c));
Xint tuupper DCLPROTO((int c));
Xvoid setcbreak DCLPROTO((void));
Xint getlineleng DCLPROTO((void));
Xvoid unsetcbreak DCLPROTO((void));
Xvoid attachtty DCLPROTO((long pgrp));
Xlong gettygrp DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/utils.pro ||
echo 'restore of zsh2.2/src/utils.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/utils.pro'`"
test 3277 -eq "$Wc_c" ||
echo 'zsh2.2/src/utils.pro: original size 3277, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/watch.pro ==============
if test -f 'zsh2.2/src/watch.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/watch.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/watch.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/watch.pro' &&
Xtime_t getlogtime DCLPROTO((struct utmp *u,int inout));
Xvoid watchlog2 DCLPROTO((int inout,struct utmp *u,char *fmt));
Xvoid watchlog DCLPROTO((int inout,struct utmp *u,char **w,char *fmt));
Xint ucmp DCLPROTO((struct utmp *u,struct utmp *v));
Xvoid readwtab DCLPROTO((void));
Xvoid dowatch DCLPROTO((void));
Xint bin_log DCLPROTO((char *nam,char **argv,char *ops,int func));
SHAR_EOF
chmod 0644 zsh2.2/src/watch.pro ||
echo 'restore of zsh2.2/src/watch.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/watch.pro'`"
test 371 -eq "$Wc_c" ||
echo 'zsh2.2/src/watch.pro: original size 371, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_bindings.pro ==============
if test -f 'zsh2.2/src/zle_bindings.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_bindings.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_bindings.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_bindings.pro' &&
SHAR_EOF
chmod 0644 zsh2.2/src/zle_bindings.pro ||
echo 'restore of zsh2.2/src/zle_bindings.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_bindings.pro'`"
test 0 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_bindings.pro: original size 0, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_main.pro ==============
if test -f 'zsh2.2/src/zle_main.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_main.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_main.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_main.pro' &&
Xvoid setterm DCLPROTO((void));
Xvoid unsetterm DCLPROTO((void));
Xvoid ungetkey DCLPROTO((int ch));
Xvoid ungetkeys DCLPROTO((char *s,int len));
Xunsigned int getkey DCLPROTO((int tmok));
Xunsigned char *zleread DCLPROTO((unsigned char *ppt,unsigned char *ppt2,int plen));
Xint getkeycmd DCLPROTO((void));
Xvoid sendstring DCLPROTO((void));
XKey makefunckey DCLPROTO((int fun));
Xvoid initxbindtab DCLPROTO((void));
Xchar *getkeystring DCLPROTO((char *s,int *len));
Xvoid printbind DCLPROTO((char *s,int len));
Xvoid printbinding DCLPROTO((char *str,Key k));
Xint bin_bindkey DCLPROTO((char *name,char **argv,char *ops,int junc));
Xvoid freekey DCLPROTO((vptr x));
Xvoid drainoutput DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_main.pro ||
echo 'restore of zsh2.2/src/zle_main.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_main.pro'`"
test 686 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_main.pro: original size 686, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_refresh.pro ==============
if test -f 'zsh2.2/src/zle_refresh.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_refresh.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_refresh.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_refresh.pro' &&
Xvoid resetvideo DCLPROTO((void));
Xint scrollwindow DCLPROTO((void));
Xvoid refresh DCLPROTO((void));
Xvoid refreshline DCLPROTO((int ln));
Xvoid moveto DCLPROTO((int ln,int cl));
Xvoid tcmultout DCLPROTO((int cap,int multcap,int ct));
Xvoid tc_rightcurs DCLPROTO((int ct));
Xvoid tc_downcurs DCLPROTO((int ct));
Xvoid tcout DCLPROTO((int cap));
Xvoid tcoutarg DCLPROTO((int cap,int arg));
Xvoid clearscreen DCLPROTO((void));
Xvoid redisplay DCLPROTO((void));
Xvoid trashzle DCLPROTO((void));
Xvoid singlerefresh DCLPROTO((void));
Xvoid singmoveto DCLPROTO((int pos));
Xint streqct DCLPROTO((char *s,char *t));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_refresh.pro ||
echo 'restore of zsh2.2/src/zle_refresh.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_refresh.pro'`"
test 596 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_refresh.pro: original size 596, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_vi.pro ==============
if test -f 'zsh2.2/src/zle_vi.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_vi.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_vi.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_vi.pro' &&
Xint vigetkey DCLPROTO((void));
Xint getvirange DCLPROTO((int wf));
Xvoid viaddnext DCLPROTO((void));
Xvoid viaddeol DCLPROTO((void));
Xvoid viinsert DCLPROTO((void));
Xvoid viinsertbol DCLPROTO((void));
Xvoid videlete DCLPROTO((void));
Xvoid vichange DCLPROTO((void));
Xvoid visubstitute DCLPROTO((void));
Xvoid vichangeeol DCLPROTO((void));
Xvoid vichangewholeline DCLPROTO((void));
Xvoid viyank DCLPROTO((void));
Xvoid viyankeol DCLPROTO((void));
Xvoid vireplace DCLPROTO((void));
Xvoid vireplacechars DCLPROTO((void));
Xvoid vicmdmode DCLPROTO((void));
Xvoid viopenlinebelow DCLPROTO((void));
Xvoid viopenlineabove DCLPROTO((void));
Xvoid vioperswapcase DCLPROTO((void));
Xvoid virepeatchange DCLPROTO((void));
Xvoid viindent DCLPROTO((void));
Xvoid viunindent DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_vi.pro ||
echo 'restore of zsh2.2/src/zle_vi.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_vi.pro'`"
test 761 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_vi.pro: original size 761, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/parse.pro ==============
if test -f 'zsh2.2/src/parse.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/parse.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/parse.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/parse.pro' &&
XList parse_event DCLPROTO((void));
XList par_event DCLPROTO((void));
XList parse_list DCLPROTO((void));
XList par_list DCLPROTO((void));
XList par_list1 DCLPROTO((void));
XSublist par_sublist DCLPROTO((void));
XSublist par_sublist2 DCLPROTO((void));
XPline par_pline DCLPROTO((void));
XCmd par_cmd DCLPROTO((void));
Xvoid par_for DCLPROTO((Cmd c));
Xvoid par_case DCLPROTO((Cmd c));
Xvoid par_if DCLPROTO((Cmd c));
Xvoid par_while DCLPROTO((Cmd c));
Xvoid par_repeat DCLPROTO((Cmd c));
Xvoid par_subsh DCLPROTO((Cmd c));
Xvoid par_funcdef DCLPROTO((Cmd c));
Xvoid par_time DCLPROTO((Cmd c));
Xvoid par_dinbrack DCLPROTO((Cmd c));
XCmd par_simple DCLPROTO((Cmd c));
XCond par_cond DCLPROTO((void));
XCond par_cond_1 DCLPROTO((void));
XCond par_cond_2 DCLPROTO((void));
Xvoid par_redir DCLPROTO((Lklist l));
XLklist par_wordlist DCLPROTO((void));
XLklist par_nl_wordlist DCLPROTO((void));
Xint getfdstr DCLPROTO((char *s));
XCond par_cond_double DCLPROTO((char *a,char *b));
XCond par_cond_triple DCLPROTO((char *a,char *b,char *c));
Xvoid yyerror DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/parse.pro ||
echo 'restore of zsh2.2/src/parse.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/parse.pro'`"
test 1036 -eq "$Wc_c" ||
echo 'zsh2.2/src/parse.pro: original size 1036, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_tricky.pro ==============
if test -f 'zsh2.2/src/zle_tricky.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_tricky.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_tricky.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_tricky.pro' &&
Xint usetab DCLPROTO((void));
Xvoid completeword DCLPROTO((void));
Xvoid menucompleteword DCLPROTO((void));
Xvoid listchoices DCLPROTO((void));
Xvoid spellword DCLPROTO((void));
Xvoid deletecharorlist DCLPROTO((void));
Xvoid expandword DCLPROTO((void));
Xvoid expandorcomplete DCLPROTO((void));
Xvoid menuexpandorcomplete DCLPROTO((void));
Xvoid listexpand DCLPROTO((void));
Xvoid reversemenucomplete DCLPROTO((void));
Xvoid acceptandmenucomplete DCLPROTO((void));
Xvoid docomplete DCLPROTO((int lst));
Xvoid do_menucmp DCLPROTO((int lst));
Xchar *get_comp_string DCLPROTO((void));
Xvoid doexpansion DCLPROTO((char *s,int lst,int lincmd));
Xvoid gotword DCLPROTO((char *s));
Xvoid inststrlen DCLPROTO((char *s,int l));
Xvoid addmatch DCLPROTO((char *s));
Xvoid addcmdmatch DCLPROTO((char *s,char *t));
Xvoid addcmddirparam DCLPROTO((char *s,char *t));
Xvoid addcmdnodis DCLPROTO((char *s,char *t));
Xvoid maketildelist DCLPROTO((char *s));
Xint Isdir DCLPROTO((char *s));
Xint isdir DCLPROTO((char *t,char *s));
Xvoid docompletion DCLPROTO((char *s,int lst,int incmd));
Xchar **get_user_var DCLPROTO((char *nam));
Xvoid gen_matches_glob DCLPROTO((char *s,int incmd));
Xvoid gen_matches_reg DCLPROTO((char *s,int incmd,int regfiles));
Xvoid do_fignore DCLPROTO((char *origstr));
Xvoid do_ambiguous DCLPROTO((char *s));
Xvoid do_single DCLPROTO((char *s));
Xvoid do_ambig_menu DCLPROTO((char *s));
Xint strpfx DCLPROTO((char *s,char *t));
Xint pfxlen DCLPROTO((char *s,char *t));
Xvoid listmatches DCLPROTO((Lklist l,char *apps));
Xvoid selectlist DCLPROTO((Lklist l));
Xint doexpandhist DCLPROTO((void));
Xvoid magicspace DCLPROTO((void));
Xvoid expandhistory DCLPROTO((void));
Xchar *getcurcmd DCLPROTO((void));
Xvoid processcmd DCLPROTO((void));
Xvoid expandcmdpath DCLPROTO((void));
Xvoid freemenu DCLPROTO((void));
Xint inarray DCLPROTO((char *s, char **a));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_tricky.pro ||
echo 'restore of zsh2.2/src/zle_tricky.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_tricky.pro'`"
test 1817 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_tricky.pro: original size 1817, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/parse.c ==============
if test -f 'zsh2.2/src/parse.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/parse.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/parse.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/parse.c' &&
X/*
X *
X * parse.c - parser


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X

X#include "zsh.h"
X#include "funcs.h"
X
X#define YYERROR { tok = LEXERR; return NULL; }
X#define YYERRORV { tok = LEXERR; return; }
X
X#define make_list() allocnode(N_LIST)
X#define make_sublist() allocnode(N_SUBLIST)
X#define make_pline() allocnode(N_PLINE)
X#define make_cmd() allocnode(N_CMD)
X#define make_forcmd() allocnode(N_FOR)
X#define make_casecmd() allocnode(N_CASE)
X#define make_ifcmd() allocnode(N_IF)
X#define make_whilecmd() allocnode(N_WHILE)
X#define make_varnode() allocnode(N_VARASG)
X#define make_cond() allocnode(N_COND)
X
X/*
X * event : ENDINPUT
X * | SEPER
X * | sublist [ SEPER | AMPER ]
X */
XList parse_event() /**/
X{
X tok = ENDINPUT;
X incmdpos = 1;
X yylex();
X return par_event();
X}
X
XList par_event() /**/
X{
XSublist sl;
XList l = NULL;
X
X while (tok == SEPER) {
X if (isnewlin > 0) return NULL;
X yylex();
X }
X if (tok == ENDINPUT) return NULL;
X if (sl = par_sublist())
X if (tok == ENDINPUT) {
X l = make_list();
X l->type = SYNC; l->left = sl;
X } else if (tok == SEPER) {
X l = make_list();
X l->type = SYNC; l->left = sl;
X if (isnewlin <= 0) yylex();
X } else if (tok == AMPER) {
X l = make_list();
X l->type = ASYNC; l->left = sl;
X yylex();
X } else
X l = NULL;
X if (!l) {
X if (errflag) { yyerror(); return NULL; }
X yyerror();
X errflag = 0;
X if (isnewlin <= 0) {
X int c;
X
X hwbegin();
X while ((c = hgetc()) != '\n' && !lexstop);
X if (c == '\n') hungetc('\n');
X hwaddc(HISTSPACE);
X hwadd();


X }
X errflag = 1;

X return NULL;
X } else {
X l->right = par_event();
X }


X return l;
X}
X

XList parse_list() /**/
X{
X tok = ENDINPUT;
X incmdpos = 1;
X yylex();
X return par_list();
X}
X
X/*
X * list : { SEPER } [ sublist [ { SEPER | AMPER } list ] ]
X */
XList par_list() /**/
X{
XSublist sl;
XList l = NULL;
X
X while (tok == SEPER) yylex();
X if (sl = par_sublist())
X if (tok == SEPER || tok == AMPER) {
X l = make_list();
X l->left = sl;
X l->type = (tok == SEPER) ? SYNC : ASYNC;
X incmdpos = 1;
X while (tok == SEPER || tok == AMPER) yylex();
X l->right = par_list();
X } else {
X l = make_list();
X l->left = sl;
X l->type = SYNC;
X }


X return l;
X}
X

XList par_list1() /**/
X{
XSublist sl;
XList l = NULL;
X
X if (sl = par_sublist()) {
X l = make_list();
X l->type = SYNC;
X l->left = sl;
X }
X return l;
X}
X
X/*
X * sublist : sublist2 [ ( DBAR | DAMPER ) { SEPER } sublist ]
X */
XSublist par_sublist() /**/
X{
XSublist sl;
X
X if (sl = par_sublist2())
X if (tok == DBAR || tok == DAMPER) {
X int qtok = tok;
X yylex();
X while (tok == SEPER) yylex();
X sl->right = par_sublist();
X sl->type = (qtok == DBAR) ? ORNEXT : ANDNEXT;
X }
X return sl;
X}
X
X/*
X * sublist2 : [ COPROC | BANG ] pline
X */
XSublist par_sublist2() /**/
X{
XSublist sl;
XPline p;
X
X sl = make_sublist();
X if (tok == COPROC) { sl->flags |= PFLAG_COPROC; yylex(); }
X else if (tok == BANG) { sl->flags |= PFLAG_NOT; yylex(); }
X if (!(p = par_pline()) && !sl->flags)
X return NULL;
X sl->left = p;
X return sl;
X}
X
X/*
X * pline : cmd [ ( BAR | BARAMP ) { SEPER } pline ]
X */
XPline par_pline() /**/
X{
XCmd c;
XPline p,p2;
X
X if (!(c = par_cmd()))
X return NULL;
X if (tok == BAR) {
X yylex();
X while (tok == SEPER) yylex();
X p2 = par_pline();
X p = make_pline();
X p->left = c; p->right = p2; p->type = PIPE;
X return p;
X } else if (tok == BARAMP) {
X struct redir *rdr = alloc(sizeof *rdr);
X rdr->type = MERGE; rdr->fd1 = 2; rdr->fd2 = 1;
X addnode(c->redir,rdr);
X
X yylex();
X p2 = par_pline();
X p = make_pline();
X p->left = c; p->right = p2; p->type = PIPE;
X return p;
X } else {
X p = make_pline();
X p->left = c; p->type = END;
X return p;
X }
X}
X
X/*
X * cmd : { redir } ( for | case | if | while | repeat |
X * subsh | funcdef | time | dinbrack | simple ) { redir }
X */
XCmd par_cmd() /**/
X{
XCmd c;
X
X c = make_cmd();
X c->args = newlist();
X c->redir = newlist();
X c->vars = newlist();
X while (IS_REDIROP(tok))
X par_redir(c->redir);
X switch (tok) {
X case FOR: case FOREACH: case SELECT: par_for(c); break;
X case CASE: par_case(c); break;
X case IF: par_if(c); break;
X case WHILE: case UNTIL: par_while(c); break;
X case REPEAT: par_repeat(c); break;
X case INPAR: case INBRACE: par_subsh(c); break;
X case FUNC: par_funcdef(c); break;
X case TIME: par_time(c); break;
X case DINBRACK: par_dinbrack(c); break;
X default: if (!par_simple(c)) return NULL; break;
X }
X while (IS_REDIROP(tok))
X par_redir(c->redir);
X incmdpos = 1;
X incasepat = 0;
X incond = 0;
X return c;
X}
X
X/*
X * for : ( FOR[EACH] | SELECT ) name ( "in" wordlist | INPAR wordlist OUTPAR )
X { SEPER } ( DO list DONE | INBRACE list OUTBRACE |
X list ZEND | list1 )
X */
Xvoid par_for(c) /**/
XCmd c;
X{
Xstruct forcmd *f;
Xint csh = (tok == FOREACH || isset(CSHJUNKIELOOPS));
X
X f = make_forcmd();
X c->type = (tok == SELECT) ? CSELECT : CFOR;
X incmdpos = 0;
X yylex();
X if (tok != STRING) YYERRORV;
X f->name = tokstr;
X incmdpos = 1;
X yylex();
X if (tok == STRING && !strcmp(tokstr,"in")) {
X f->inflag = 1;
X incmdpos = 0;
X yylex();
X c->args = par_wordlist();
X if (tok != SEPER) YYERRORV;
X } else if (tok == INPAR) {
X f->inflag = 1;
X incmdpos = 0;
X yylex();
X c->args = par_nl_wordlist();
X if (tok != OUTPAR) YYERRORV;
X incmdpos = 1;
X yylex();
X }
X incmdpos = 1;
X while (tok == SEPER) yylex();
X if (tok == DO) {
X yylex();
X f->list = par_list();
X if (tok != DONE) YYERRORV;
X yylex();
X } else if (tok == INBRACE) {
X yylex();
X f->list = par_list();
X if (tok != OUTBRACE) YYERRORV;
X yylex();
X } else if (csh) {
X f->list = par_list();
X if (tok != ZEND) YYERRORV;
X yylex();
X } else if (isset(NOSHORTLOOPS)) {
X YYERRORV;
X } else
X f->list = par_list1();
X c->u.forcmd = f;
X}
X
X/*
X * case : CASE STRING { SEPER } ( "in" | INBRACE )
X { { SEPER } STRING { BAR STRING } OUTPAR list [ DSEMI ] }
X { SEPER } ( "esac" | OUTBRACE )
X */
Xvoid par_case(c) /**/
XCmd c;
X{
Xstruct casecmd **ccp;
Xint brflag;
X
X c->type = CCASE;
X incmdpos = 0;
X yylex();
X if (tok != STRING) YYERRORV;
X addnode(c->args,tokstr);
X incmdpos = 1;
X yylex();
X while (tok == SEPER) yylex();
X if (!(tok == STRING && !strcmp(tokstr,"in")) && tok != INBRACE) YYERRORV;
X brflag = (tok == INBRACE);
X incasepat = 1;
X incmdpos = 0;
X yylex();
X ccp = &c->u.casecmd;
X for (;;) {
X char *str;
X struct casecmd *cc;
X
X *ccp = cc = make_casecmd();
X while (tok == SEPER) yylex();
X if (tok == OUTBRACE) {
X yylex();
X break;
X }
X if (tok != STRING) YYERRORV;
X if (!strcmp(tokstr,"esac")) {
X yylex();
X break;
X }
X str = tokstr;
X yylex();
X while (tok == BAR) {
X char *str2;
X int sl = strlen(str);
X
X yylex();
X if (tok != STRING) YYERRORV;
X str2 = alloc(sl+strlen(tokstr)+1);
X strcpy(str2,str);
X str2[sl] = Bar;
X strcpy(str2+sl+1,tokstr);
X str = str2;
X yylex();
X }
X if (tok != OUTPAR) YYERRORV;
X incasepat = 0;
X incmdpos = 1;
X yylex();
X cc->pat = str;
X cc->list = par_list();
X ccp = &cc->next;
X if ((tok == ESAC && !brflag) || (tok == OUTBRACE && brflag)) {
X yylex();
X break;
X }
X if (tok != DSEMI) YYERRORV;
X incasepat = 1;
X incmdpos = 0;
X yylex();
X }
X *ccp = NULL;
X}
X
X/*
X * if : { ( IF | ELIF ) { SEPER } ( INPAR list OUTPAR | list )
X { SEPER } ( THEN list | INBRACE list OUTBRACE | list1 ) }
X [ FI | ELSE list FI | ELSE { SEPER } INBRACE list OUTBRACE ]
X (you get the idea...?)
X */
Xvoid par_if(c) /**/
XCmd c;
X{
Xstruct ifcmd *i,**ip;
Xint xtok;
X
X c->type = CIF;
X ip = &c->u.ifcmd;
X for (;;) {
X xtok = tok;
X yylex();
X if (xtok == FI)
X break;
X while (tok == SEPER) yylex();
X if (xtok == ELSE)
X break;
X if (!(xtok == IF || xtok == ELIF)) YYERRORV;
X *ip = i = make_ifcmd();
X ip = &i->next;
X if (tok == INPAR) {
X yylex();
X i->ifl = par_list();
X if (tok != OUTPAR) YYERRORV;
X incmdpos = 1;
X yylex();
X } else {
X i->ifl = par_list();


X incmdpos = 1;
X }

X while (tok == SEPER) yylex();
X xtok = FI;
X if (tok == THEN) {
X yylex();
X i->thenl = par_list();
X incmdpos = 1;
X } else if (tok == INBRACE) {
X yylex();
X i->thenl = par_list();
X if (tok != OUTBRACE) YYERRORV;
X yylex();
X incmdpos = 1;
X if (tok == SEPER) break;
X } else if (isset(NOSHORTLOOPS)) {
X YYERRORV;
X } else {
X i->thenl = par_list1();
X incmdpos = 1;
X break;
X }
X }
X if (xtok == ELSE) {
X *ip = i = make_ifcmd();
X if (tok == INBRACE) {
X yylex();
X i->thenl = par_list();
X if (tok != OUTBRACE) YYERRORV;
X yylex();
X } else {
X i->thenl = par_list();
X if (tok != FI) YYERRORV;
X yylex();
X }
X }
X}
X
X/*
X * while : ( WHILE | UNTIL ) ( INPAR list OUTPAR | list ) { SEPER }
X ( DO list DONE | INBRACE list OUTBRACE | list ZEND )
X */
Xvoid par_while(c) /**/
XCmd c;
X{
Xstruct whilecmd *w;
X
X c->type = CWHILE;
X w = c->u.whilecmd = make_whilecmd();
X w->cond = (tok == UNTIL);
X yylex();
X if (tok == INPAR) {
X yylex();
X w->cont = par_list();
X if (tok != OUTPAR) YYERRORV;
X yylex();
X } else {
X w->cont = par_list();
X }
X incmdpos = 1;
X while (tok == SEPER) yylex();
X if (tok == DO) {
X yylex();
X w->loop = par_list();
X if (tok != DONE) YYERRORV;
X yylex();
X } else if (tok == INBRACE) {
X yylex();
X w->loop = par_list();
X if (tok != OUTBRACE) YYERRORV;
X yylex();
X } else if (isset(CSHJUNKIELOOPS)) {
X w->loop = par_list();
X if (tok != ZEND) YYERRORV;
X yylex();
X } else
X YYERRORV;
X}
X
X/*
X * repeat : REPEAT STRING { SEPER } ( DO list DONE | list1 )
X */
Xvoid par_repeat(c) /**/
XCmd c;
X{
X c->type = CREPEAT;
X incmdpos = 0;
X yylex();
X if (tok != STRING) YYERRORV;
X addnode(c->args,tokstr);
X incmdpos = 1;
X yylex();
X while (tok == SEPER) yylex();
X if (tok == DO) {
X yylex();
X c->u.list = par_list();
X if (tok != DONE) YYERRORV;
X yylex();
X } else {
X c->u.list = par_list1();
X }
X}
X
X/*
X * subsh : ( INPAR | INBRACE ) list ( OUTPAR | OUTBRACE )
X */
Xvoid par_subsh(c) /**/
XCmd c;
X{
X c->type = (tok == INPAR) ? SUBSH : CURSH;
X yylex();
X c->u.list = par_list();
X if (tok != ((c->type == SUBSH) ? OUTPAR : OUTBRACE)) YYERRORV;
X yylex();
X}
X
X/*
X * funcdef : FUNCTION wordlist [ INOUTPAR ] { SEPER }
X * ( list1 | INBRACE list OUTBRACE )
X */
Xvoid par_funcdef(c) /**/
XCmd c;
X{
X nocorrect = 1;
X incmdpos = 0;
X yylex();
X c->type = FUNCDEF;
X c->args = newlist();
X while (tok == STRING) {
X if (*tokstr == Inbrace && !tokstr[1]) { tok = INBRACE; break; }
X addnode(c->args,tokstr);
X yylex();
X }
X nocorrect = 0;
X incmdpos = 1;
X if (tok == INOUTPAR) yylex();
X while (tok == SEPER) yylex();
X if (tok == INBRACE) {
X yylex();
X c->u.list = par_list();
X if (tok != OUTBRACE) YYERRORV;
X yylex();
X } else if (isset(NOSHORTLOOPS)) {
X YYERRORV;
X } else
X c->u.list = par_list1();
X}
X
X/*
X * time : TIME sublist2
X */
Xvoid par_time(c) /**/
XCmd c;
X{
X yylex();
X c->type = ZCTIME;
X c->u.pline = par_sublist2();
X}
X
X/*
X * dinbrack : DINBRACK cond DOUTBRACK
X */
Xvoid par_dinbrack(c) /**/
XCmd c;
X{
X c->type = COND;
X incond = 1;
X incmdpos = 0;
X yylex();
X c->u.cond = par_cond();
X if (tok != DOUTBRACK) YYERRORV;
X incond = 0;
X incmdpos = 1;
X yylex();
X}
X
X/*
X * simple : { COMMAND | EXEC | NOGLOB | NOCORRECT | DASH }
X { STRING | ENVSTRING | ENVARRAY wordlist OUTPAR | redir }
X [ INOUTPAR { SEPER } ( list1 | INBRACE list OUTBRACE ) ]
X */
XCmd par_simple(c) /**/
XCmd c;
X{
Xint isnull = 1;
X
X c->type = SIMPLE;
X for (;;) {
X if (tok == COMMAND) c->flags |= CFLAG_COMMAND;
X else if (tok == EXEC) c->flags |= CFLAG_EXEC;
X else if (tok == NOGLOB) c->flags |= CFLAG_NOGLOB;
X else if (tok == NOCORRECT) nocorrect = 1;
X else if (tok == DASH) c->flags = CFLAG_DASH;
X else break;
X yylex();
X }
X if (tok == AMPER) YYERROR;
X for (;;) {
X if (tok == STRING) {
X incmdpos = 0;
X addnode(c->args,tokstr);
X yylex();
X } else if (tok == ENVSTRING) {
X struct varasg *v = make_varnode();
X v->type = PMFLAG_s;
X equalsplit(v->name = tokstr,&v->str);
X addnode(c->vars,v);
X yylex();
X } else if (tok == ENVARRAY) {
X struct varasg *v = make_varnode();
X int oldcmdpos = incmdpos;
X v->type = PMFLAG_A;
X incmdpos = 0;
X v->name = tokstr;
X yylex();
X v->arr = par_nl_wordlist();
X if (tok != OUTPAR) YYERROR;
X incmdpos = oldcmdpos;
X yylex();
X addnode(c->vars,v);
X } else if (IS_REDIROP(tok)) {
X par_redir(c->redir);
X } else if (tok == INOUTPAR) {
X incmdpos = 1;
X yylex();
X while (tok == SEPER) yylex();
X if (tok == INBRACE) {
X yylex();
X c->u.list = par_list();
X if (tok != OUTBRACE) YYERROR;
X yylex();
X } else if (isset(NOSHORTLOOPS)) {
X YYERROR;
X } else
X c->u.list = par_list1();
X c->type = FUNCDEF;
X } else break;
X isnull = 0;
X }
X if (isnull && !full(c->redir)) return NULL;
X if (full(c->args)) {
X if (underscore)
X free(underscore);
X underscore = ztrdup(getdata(lastnode(c->args)));
X untokenize(underscore);
X }
X incmdpos = 1;
X return c;
X}
X
X/*
X * cond : cond_1 { SEPER } [ DBAR { SEPER } cond ]
X */
XCond par_cond() /**/
X{
XCond c,c2;
X
X c = par_cond_1();
X while (tok == SEPER) yylex();
X if (tok == DBAR) {
X yylex();
X while (tok == SEPER) yylex();
X c2 = make_cond();
X c2->left = c;
X c2->right = par_cond();
X c2->type = COND_OR;
X return c2;
X }
X return c;
X}
X
X/*
X * cond_1 : cond_2 { SEPER } [ DAMPER { SEPER } cond_1 ]
X */
XCond par_cond_1() /**/
X{
XCond c,c2;
X
X c = par_cond_2();
X while (tok == SEPER) yylex();
X if (tok == DAMPER) {
X yylex();
X while (tok == SEPER) yylex();
X c2 = make_cond();
X c2->left = c;
X c2->right = par_cond_1();
X c2->type = COND_AND;
X return c2;
X }
X return c;
X}
X
X/*
X * cond_2 : BANG cond_2
X | INPAR { SEPER } cond_2 { SEPER } OUTPAR
X | STRING STRING STRING
X | STRING STRING
X | STRING ( INANG | OUTANG ) STRING
X */
XCond par_cond_2() /**/
X{
XCond c,c2;
Xchar *s1,*s2,*s3;
Xint xtok;
X
X if (tok == BANG) {
X yylex();
X c = par_cond_2();
X c2 = make_cond();
X c2->left = c;
X c2->type = COND_NOT;
X return c2;
X }
X if (tok == INPAR) {
X yylex();
X while (tok == SEPER) yylex();
X c = par_cond();
X while (tok == SEPER) yylex();
X if (tok != OUTPAR) YYERROR;
X yylex();
X return c;
X }
X if (tok != STRING) YYERROR;
X s1 = tokstr;
X yylex();
X xtok = tok;
X if (tok == INANG || tok == OUTANG) {
X yylex();
X if (tok != STRING) YYERROR;
X s3 = tokstr;
X yylex();
X c = make_cond();
X c->left = s1;
X c->right = s3;
X c->type = (xtok == INANG) ? COND_STRLT : COND_STRGTR;
X c->types[0] = c->types[1] = NT_STR;
X return c;
X }
X if (tok != STRING) YYERROR;
X s2 = tokstr;
X yylex();
X if (tok == STRING) {
X s3 = tokstr;
X yylex();
X return par_cond_triple(s1,s2,s3);
X } else
X return par_cond_double(s1,s2);
X}
X
X/*
X * redir : ( OUTANG | ... | TRINANG ) STRING
X */
Xvoid par_redir(l) /**/
XLklist l;
X{
Xchar *toks;
Xstruct redir *fn = allocnode(N_REDIR);
Xint mergerror = 0;
Xint oldcmdpos,oldnc;
X
X oldcmdpos = incmdpos;
X incmdpos = 0;
X oldnc = nocorrect;
X if (tok != INANG) nocorrect = 1;
X fn->type = redirtab[tok-OUTANG];
X fn->fd1 = tokfd;
X yylex();
X if (tok != STRING && tok != ENVSTRING) YYERRORV;
X toks = tokstr;
X incmdpos = oldcmdpos;
X nocorrect = oldnc;
X yylex();
X
X/* assign default fd */
X
X if (fn->fd1 == -1)
X fn->fd1 = IS_READFD(fn->type) ? 0 : 1;
X
X/* > >(...) or < <(...) */
X
X if ((*toks == Inang || *toks == Outang) && toks[1] == Inpar) {
X if ((fn->type & ~1) == WRITE) fn->type = OUTPIPE;
X else if (fn->type == READ) fn->type = INPIPE;
X else YYERRORV;
X fn->name = toks;
X
X/* <<[-] name */
X
X } else if (fn->type == HEREDOC || fn->type == HEREDOCDASH) {
X char tbuf[256], *tlin;
X int tsiz = 0, l;
X /* Save the rest of the current line for later tokenization */
X if (!isnewlin) {
X while (hgets(tbuf, 256) != NULL) {
X l = strlen(tbuf);
X if (tsiz == 0) {
X tlin = ztrdup(tbuf); /* Test for failure? */
X tsiz = l;
X } else {
X tlin = realloc(tlin,tsiz+l+1); /* Test for failure? */
X strcpy(&tlin[tsiz], tbuf);
X tsiz += l;
X }
X if (tbuf[l-1] == '\n') break;
X }
X }
X /* Now grab the document */
X fn->name = gethere(toks,fn->type);
X fn->type = HERESTR;
X /* Put back the saved line to resume tokenizing */
X if (tsiz > 0) {
X hungets(tlin);
X free(tlin);
X }
X
X/* >& name or >>& name */
X
X } else if (IS_ERROR_REDIR(fn->type) && getfdstr(toks) == FD_WORD) {
X mergerror = 1;
X fn->name = toks;
X fn->type = UN_ERROR_REDIR(fn->type);
X
X/* >>& and >>&! are only valid with a name after them */
X
X } else if (fn->type == ERRAPP || fn->type == ERRAPPNOW) {
X YYERRORV;
X
X/* >& # */
X


X } else if (fn->type == MERGE || fn->type == MERGEOUT) {

X fn->fd2 = getfdstr(toks);
X if (fn->fd2 == FD_CLOSE) fn->type = CLOSE;
X else if (fn->fd2 == FD_WORD) fn->fd2 = (fn->type==MERGEOUT) ? 1 : 0;
X } else
X fn->name = toks;
X addnode(l,fn);
X if (mergerror)
X {
X struct redir *fe = allocnode(N_REDIR);
X
X fe->fd1 = 2;
X fe->fd2 = fn->fd1;
X fe->type = MERGEOUT;
X addnode(l,fe);
X }
X}
X
X/*
X * wordlist : { STRING }
X */
XLklist par_wordlist() /**/
X{
XLklist l;
X
X l = newlist();
X while (tok == STRING) {
X addnode(l,tokstr);
X yylex();
X }
X return l;
X}
X
X/*
X * nl_wordlist : { STRING | SEPER }
X */
XLklist par_nl_wordlist() /**/
X{
XLklist l;
X
X l = newlist();
X while (tok == STRING || tok == SEPER) {
X if (tok != SEPER)
X addnode(l,tokstr);
X yylex();
X }


X return l;
X}
X

X/* get fd associated with str */
X
Xint getfdstr(s) /**/
Xchar *s;
X{
X if (s[1]) return FD_WORD;
X if (idigit(*s)) return *s-'0';
X if (*s == 'p') return FD_COPROC;
X if (*s == '-') return FD_CLOSE;
X return FD_WORD;
X}
X
XCond par_cond_double(a,b) /**/


Xchar *a;char *b;
X{

XCond n = make_cond();
X
X if (a[0] != '-' || !a[1] || a[2])
X {
X zerr("parse error: condition expected: %s",a,0);
X return NULL;
X }
X n->left = b;
X n->type = a[1];
X n->types[0] = n->types[1] = NT_STR;
X return n;
X}
X
XCond par_cond_triple(a,b,c) /**/
Xchar *a;char *b;char *c;
X{
XCond n = make_cond();
Xstatic char *condstrs[] = {
X "nt","ot","ef","eq","ne","lt","gt","le","ge",NULL
X };
Xint t0;
X
X if ((b[0] == Equals || b[0] == '=') && !b[1])
X n->type = COND_STREQ;
X else if (b[0] == '!' && b[1] == '=' && !b[2])
X n->type = COND_STRNEQ;
X else if (b[0] == '-')
X {
X for (t0 = 0; condstrs[t0]; t0++)
X if (!strcmp(condstrs[t0],b+1))
X break;
X if (condstrs[t0])
X n->type = t0+COND_NT;
X else
X zerr("unrecognized condition: %s",b,0);
X }
X else
X zerr("condition expected: %s",b,0);
X n->left = a;
X n->right = c;
X n->types[0] = n->types[1] = NT_STR;
X return n;
X}
X
Xvoid yyerror() /**/
X{
Xint t0;
X
X for (t0 = 0; t0 != 20; t0++)
X if (!yytext[t0] || yytext[t0] == '\n' || yytext[t0] == HISTSPACE)
X break;
X if (t0 == 20)
X zerr("parse error near `%l...'",yytext,20);
X else if (t0)
X zerr("parse error near `%l'",yytext,t0);
X else
X zerr("parse error",NULL,0);
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/parse.c ||
echo 'restore of zsh2.2/src/parse.c failed'
Wc_c="`wc -c < 'zsh2.2/src/parse.c'`"
test 18760 -eq "$Wc_c" ||
echo 'zsh2.2/src/parse.c: original size 18760, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_utils.pro ==============
if test -f 'zsh2.2/src/zle_utils.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_utils.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_utils.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_utils.pro' &&
Xvoid sizeline DCLPROTO((int sz));
Xvoid spaceinline DCLPROTO((int ct));
Xvoid backkill DCLPROTO((int ct,int dir));
Xvoid forekill DCLPROTO((int ct,int dir));
Xvoid cut DCLPROTO((int i,int ct,int dir));
Xvoid backdel DCLPROTO((int ct));
Xvoid foredel DCLPROTO((int ct));
Xvoid setline DCLPROTO((char *s));
Xvoid sethistline DCLPROTO((unsigned char *s));
Xint findbol DCLPROTO((void));
Xint findeol DCLPROTO((void));
Xvoid findline DCLPROTO((int *a,int *b));
Xvoid initundo DCLPROTO((void));
Xvoid addundo DCLPROTO((void));
Xvoid freeundo DCLPROTO((void));
Xint hstrncmp DCLPROTO((char *s,char *t,int len));
Xint hstrcmp DCLPROTO((char *s,char *t));
Xchar *hstrnstr DCLPROTO((char *s,char *t,int len));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_utils.pro ||
echo 'restore of zsh2.2/src/zle_utils.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_utils.pro'`"
test 684 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_utils.pro: original size 684, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/signals.h.sample ==============
if test -f 'zsh2.2/src/signals.h.sample' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/signals.h.sample (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/signals.h.sample (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/signals.h.sample' &&
XYour signals.h file should look something like this. If it doesn't,
Xperhaps your csh or ed is different.
X


X/* this file is created automatically by buildzsh */

X/* if all this is wrong, blame csh ;-) */
X

X#define SIGCOUNT 31


X
X#ifdef GLOBALS
X
Xchar *sigmsg[SIGCOUNT+2] = {
X "done",

X "hangup",
X "interrupt",
X "quit",
X "illegal instruction",
X "trace trap",
X "abort",
X "EMT instruction",
X "floating point exception",
X "killed",
X "bus error",
X "segmentation fault",
X "bad system call",
X "broken pipe",
X "SIGALRM",
X "terminated",
X "SIGURG",


X#ifdef USE_SUSPENDED
X "suspended (signal)",
X#else
X "stopped (signal)",
X#endif

X#ifdef USE_SUSPENDED
X "suspended",
X#else
X "stopped",
X#endif
X "continued",
X "SIGCHLD",


X#ifdef USE_SUSPENDED
X "suspended (tty input)",
X#else
X "stopped (tty input)",
X#endif

X#ifdef USE_SUSPENDED
X "suspended (tty output)",
X#else
X "stopped (tty output)",
X#endif

X "SIGIO",
X "cpu limit exceeded",
X "filesize limit exceeded",
X "virtual time alarm",
X "SIGPROF",
X "SIGWINCH",
X "SIGLOST",
X "SIGUSR1",
X "SIGUSR2",
X NULL
X};
X
Xchar *sigs[SIGCOUNT+4] = {
X "EXIT",
X "HUP",
X "INT",
X "QUIT",
X "ILL",
X "TRAP",
X "ABRT",
X "EMT",
X "FPE",
X "KILL",
X "BUS",
X "SEGV",
X "SYS",
X "PIPE",
X "ALRM",
X "TERM",
X "URG",
X "STOP",
X "TSTP",
X "CONT",
X "CHLD",
X "TTIN",
X "TTOU",
X "IO",
X "XCPU",
X "XFSZ",
X "VTALRM",
X "PROF",
X "WINCH",
X "LOST",
X "USR1",
X "USR2",
X "ERR",


X "DEBUG",
X NULL
X};
X
X#else
X
Xextern char *sigs[SIGCOUNT+4],*sigmsg[SIGCOUNT+2];
X
X#endif

SHAR_EOF
chmod 0644 zsh2.2/src/signals.h.sample ||
echo 'restore of zsh2.2/src/signals.h.sample failed'
Wc_c="`wc -c < 'zsh2.2/src/signals.h.sample'`"
test 1429 -eq "$Wc_c" ||
echo 'zsh2.2/src/signals.h.sample: original size 1429, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_move.c ==============
if test -f 'zsh2.2/src/zle_move.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_move.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_move.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_move.c' &&
X/*
X *
X * zle_move.c - editor movement


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#define ZLE
X#include "zsh.h"
X

Xvoid beginningofline() /**/
X{
X if (mult < 0) { mult = -mult; endofline(); return; }
X while (mult--) {
X if (cs == 0)
X return;
X if (line[cs-1] == '\n')
X if (!--cs)
X return;
X while (cs && line[cs-1] != '\n') cs--;
X }
X}
X
Xvoid endofline() /**/
X{
X if (mult < 0) { mult = -mult; beginningofline(); return; }
X while (mult--) {
X if (cs >= ll) {
X cs = ll;
X return;
X }
X if (line[cs] == '\n')
X if (++cs == ll)
X return;
X while (cs != ll && line[cs] != '\n') cs++;
X }
X}
X
Xvoid beginningoflinehist() /**/
X{
X if (mult < 0) { mult = -mult; endoflinehist(); return; }
X while (mult) {
X if (cs == 0)
X break;
X if (line[cs-1] == '\n')
X if (!--cs)
X break;
X while (cs && line[cs-1] != '\n') cs--;
X mult--;
X }
X if (mult) {
X uphistory();
X cs = 0;
X }
X}
X
Xvoid endoflinehist() /**/
X{
X if (mult < 0) { mult = -mult; beginningoflinehist(); return; }
X while (mult) {
X if (cs >= ll) {
X cs = ll;
X break;
X }
X if (line[cs] == '\n')
X if (++cs == ll)
X break;
X while (cs != ll && line[cs] != '\n') cs++;
X mult--;
X }
X if (mult)
X downhistory();
X}
X
Xvoid forwardchar() /**/
X{
X cs += mult;


X if (cs > ll) cs = ll;

X if (cs < 0) cs = 0;
X}
X
Xvoid backwardchar() /**/
X{
X cs -= mult;


X if (cs > ll) cs = ll;

X if (cs < 0) cs = 0;
X}
X
Xvoid setmarkcommand() /**/
X{
X mark = cs;
X}
X
Xvoid exchangepointandmark() /**/
X{
Xint x;
X
X x = mark;
X mark = cs;
X cs = x;


X if (cs > ll)
X cs = ll;
X}
X

Xvoid vigotocolumn() /**/
X{
Xint x,y,ocs = cs;
X
X if (mult > 0) mult--;
X findline(&x,&y);
X if (mult >= 0) cs = x+mult; else cs = y+mult;
X if (cs < x || cs > y) {
X feep();
X cs = ocs;
X }
X}
X
Xvoid vimatchbracket() /**/
X{
Xint ocs = cs,dir,ct;
Xchar oth,me;
X
Xotog:
X if (cs == ll)
X {
X feep();
X cs = ocs;
X return;
X }
X switch(me = line[cs])
X {
X case '{': dir = 1; oth = '}'; break;
X case '}': dir = -1; oth = '{'; break;
X case '(': dir = 1; oth = ')'; break;
X case ')': dir = -1; oth = '('; break;
X case '[': dir = 1; oth = ']'; break;
X case ']': dir = -1; oth = '['; break;
X default: cs++; goto otog;
X }
X ct = 1;
X while (cs >= 0 && cs < ll && ct)
X {
X cs += dir;
X if (line[cs] == oth)
X ct--;
X else if (line[cs] == me)
X ct++;
X }
X if (cs < 0 || cs >= ll)
X {
X feep();
X cs = ocs;
X }
X}
X
Xvoid viforwardchar() /**/
X{
X if (mult < 0) { mult = -mult; vibackwardchar(); return; }
X while (mult--) {
X cs++;
X if (cs >= ll || line[cs] == '\n') {
X cs--;


X break;
X }
X }
X}

X
Xvoid vibackwardchar() /**/
X{
X if (mult < 0) { mult = -mult; viforwardchar(); return; }
X while (mult--) {
X cs--;
X if (cs < 0 || line[cs] == '\n') {
X cs++;


X break;
X }
X }
X}

X
Xvoid viendofline() /**/


X{
X cs = findeol();

X if (!virangeflag && cs != 0 && line[cs-1] != '\n') cs--;
X}
X
Xvoid vibeginningofline() /**/


X{
X cs = findbol();
X}

X
X
Xstatic int vfindchar,vfinddir,tailadd;
X
Xvoid vifindnextchar() /**/
X{
X if (vfindchar = vigetkey())
X {
X vfinddir = 1;
X tailadd = 0;
X virepeatfind();
X }
X}
X
Xvoid vifindprevchar() /**/
X{
X if (vfindchar = vigetkey())
X {
X vfinddir = -1;
X tailadd = 0;
X virepeatfind();
X }
X}
X
Xvoid vifindnextcharskip() /**/
X{
X if (vfindchar = vigetkey())
X {
X vfinddir = 1;
X tailadd = -1;
X virepeatfind();
X }
X}
X
Xvoid vifindprevcharskip() /**/
X{
X if (vfindchar = vigetkey())
X {
X vfinddir = -1;
X tailadd = 1;
X virepeatfind();
X }
X}
X
Xvoid virepeatfind() /**/
X{
Xint ocs = cs;
X
X if (!vfinddir) { feep(); return; }
X if (mult < 0) { mult = -mult; virevrepeatfind(); return; }
X while (mult--)
X {
X do
X cs += vfinddir;
X while (cs >= 0 && cs < ll && line[cs] != vfindchar && line[cs] != '\n');
X if (cs < 0 || cs >= ll || line[cs] == '\n')
X {
X feep();
X cs = ocs;
X return;
X }
X }
X cs += tailadd;
X if (vfinddir == 1 && virangeflag) cs++;
X}
X
Xvoid virevrepeatfind() /**/
X{
X if (mult < 0) { mult = -mult; virepeatfind(); return; }
X vfinddir = -vfinddir;
X virepeatfind();
X vfinddir = -vfinddir;
X}
X
Xvoid vifirstnonblank() /**/


X{
X cs = findbol();

X while (cs != ll && iblank(line[cs]))
X cs++;
X}
X
Xvoid visetmark() /**/
X{
Xint ch;
X
X ch = getkey(1);
X if (ch < 'a' || ch > 'z') {


X feep();
X return;
X }

X ch -= 'a';
X vimarkcs[ch] = cs;
X vimarkline[ch] = histline;
X}
X
Xvoid vigotomark() /**/
X{
Xint ch;
X
X ch = getkey(1);
X if (ch == c) ch = 26;
X else {
X if (ch < 'a' || ch > 'z') {


X feep();
X return;
X }

X ch -= 'a';
X }
X if (!vimarkline[ch]) {


X feep();
X return;
X }

X if (curhist != vimarkline[ch]) {
X mult = vimarkline[ch];
X vifetchhistory();
X if (curhist != vimarkline[ch]) return;
X }
X cs = vimarkcs[ch];
X if (cs > ll) ch = ll;
X}
X
Xvoid vigotomarkline() /**/
X{
X vigotomark();


X cs = findbol();
X}

SHAR_EOF
chmod 0644 zsh2.2/src/zle_move.c ||
echo 'restore of zsh2.2/src/zle_move.c failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_move.c'`"
test 5181 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_move.c: original size 5181, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_misc.c ==============
if test -f 'zsh2.2/src/zle_misc.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_misc.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_misc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_misc.c' &&
X/*
X *
X * zle_misc.c - miscellaneous editor routines


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad

SHAR_EOF
true || echo 'restore of zsh2.2/src/zle_misc.c failed'
fi
echo 'End of zsh2.2 part 16'
echo 'File zsh2.2/src/zle_misc.c is continued in part 17'
echo 17 > _shar_seq_.tmp

Paul Falstad

unread,
May 13, 1992, 12:11:22 PM5/13/92
to
Submitted-by: pfal...@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 29, Issue 113
Archive-name: zsh2.2/part17

Environment: BSD
Supersedes: zsh2.1: Volume 24, Issue 1-19

#!/bin/sh
# this is aa.17 (part 17 of zsh2.2)


# do not concatenate these parts, unpack them in order with /bin/sh

# file zsh2.2/src/zle_misc.c continued


#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 17; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then

echo 'x - still skipping zsh2.2/src/zle_misc.c'
else
echo 'x - continuing file zsh2.2/src/zle_misc.c'


sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.2/src/zle_misc.c' &&

X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#define ZLE
X#include "zsh.h"
X
X

Xvoid selfinsert() /**/
X{
Xint ncs = cs+mult;
X
X if (mult < 0) { mult = -mult; ncs = cs; }
X if (insmode || ll == cs)
X spaceinline(mult);
X else if (mult+cs > ll)
X spaceinline(ll-(mult+cs));
X while (mult--)
X line[cs++] = c;
X cs = ncs;
X}
X
Xvoid selfinsertunmeta() /**/
X{
X c &= 0x7f;
X if (c == '\r') c = '\n';
X selfinsert();
X}
X
Xvoid deletechar() /**/
X{
X if (mult < 0) { mult = -mult; backwarddeletechar(); return; }


X if (c == 4 && !ll)
X {
X eofsent = 1;

X return;
X }
X if (!(cs+mult > ll || line[cs] == '\n'))


X {
X cs += mult;

X backdel(mult);
X }


X else
X feep();
X}

X
Xvoid backwarddeletechar() /**/
X{
X if (mult < 0) { mult = -mult; deletechar(); return; }
X if (mult > cs)
X mult = cs;
X backdel(mult);
X}
X
Xvoid videletechar() /**/
X{
X if (mult < 0) { mult = -mult; vibackwarddeletechar(); return; }


X if (c == 4 && !ll) {

X eofsent = 1;
X return;
X }
X if (!(cs+mult > ll || line[cs] == '\n')) {
X cs += mult;
X backkill(mult,0);
X if (cs && (cs == ll || line[cs] == '\n')) cs--;


X } else
X feep();
X}

X
Xvoid vibackwarddeletechar() /**/
X{
X if (mult < 0) { mult = -mult; videletechar(); return; }
X if (mult > cs)
X mult = cs;
X if (cs-mult < viinsbegin) { feep(); return; }
X backkill(mult,1);
X}
X
Xvoid vikillline() /**/
X{
X if (viinsbegin > cs) { feep(); return; }
X backdel(cs-viinsbegin);
X}
X
Xvoid killwholeline() /**/
X{
Xint i,fg;
X
X if (mult < 0) return;
X while (mult--)
X {
X if (fg = (cs && cs == ll))
X cs--;


X while (cs && line[cs-1] != '\n') cs--;

X for (i = cs; i != ll && line[i] != '\n'; i++);
X forekill(i-cs+(i != ll),fg);
X }
X}
X
Xvoid killbuffer() /**/
X{
X cs = 0;
X forekill(ll,0);
X}
X
Xvoid backwardkillline() /**/
X{
Xint i = 0;
X
X if (mult < 0) { mult = -mult; killline(); return; }
X while (mult--)
X {
X while (cs && line[cs-1] != '\n') cs--,i++;
X if (mult && cs && line[cs-1] == '\n')
X cs--,i++;
X }
X forekill(i,1);
X}
X
Xvoid gosmacstransposechars() /**/
X{
Xint cc;
X
X if (cs < 2 || line[cs-1] == '\n' || line[cs-2] == '\n')
X {
X if (line[cs] == '\n' || line[cs+1] == '\n')
X {
X feep();
X return;
X }
X cs += (cs == 0 || line[cs-1] == '\n') ? 2 : 1;
X }
X cc = line[cs-2];
X line[cs-2] = line[cs-1];
X line[cs-1] = cc;
X}
X
Xvoid transposechars() /**/
X{
Xint cc;
Xint neg = mult < 0;
X
X if (neg) mult = -mult;
X while (mult--) {
X if (cs == 0 || line[cs-1] == '\n') {
X if (ll == cs || line[cs] == '\n' || line[cs+1] == '\n') {


X feep();
X return;
X }

X cs++;
X }
X if (!neg) {
X if (cs != ll && line[cs] != '\n') cs++;
X } else {
X if (cs != 0 && line[cs-1] != '\n') cs--;
X }
X cc = line[cs-2];
X line[cs-2] = line[cs-1];
X line[cs-1] = cc;
X }
X}
X
Xvoid poundinsert() /**/
X{
X if (*line != '#') {
X cs = 0;
X spaceinline(1);
X *line = '#';
X } else {
X cs = 0;
X foredel(1);
X }


X done = 1;
X}
X

Xvoid acceptline() /**/
X{


X done = 1;
X}
X

Xvoid acceptandhold() /**/
X{
X pushnode(bufstack,ztrdup((char *) line));
X stackcs = cs;


X done = 1;
X}
X

Xvoid killline() /**/
X{
Xint i = 0;
X
X if (mult < 0) { mult = -mult; backwardkillline(); return; }
X while (mult--) {


X if (line[cs] == '\n')

X cs++,i++;
X while (cs != ll && line[cs] != '\n') cs++,i++;
X }
X backkill(i,0);
X}
X
Xvoid killregion() /**/
X{
X if (mark > ll)
X mark = ll;
X if (mark > cs)
X forekill(mark-cs,0);
X else
X backkill(cs-mark,1);
X}
X
Xvoid copyregionaskill() /**/
X{
X if (mark > ll)
X mark = ll;
X if (mark > cs)
X cut(cs,mark-cs,0);
X else
X cut(mark,cs-mark,1);
X}
X
Xstatic int kct,yankb,yanke;
X
Xvoid yank() /**/
X{
Xint cc;
Xchar *buf = cutbuf;
X
X if (!cutbuf) {


X feep();
X return;
X }

X if (mult < 0) return;

X if (vibufspec) {
X vibufspec = tolower(vibufspec);


X vibufspec += (idigit(vibufspec)) ? -'1'+26 : -'a';

X if (!(buf = vibuf[vibufspec])) {
X feep();
X vibufspec = 0;
X return;
X }
X vibufspec = 0;
X }
X yankb = cs;
X while (mult--) {
X kct = kringnum;
X cc = strlen(buf);
X spaceinline(cc);
X strncpy((char *) line+cs,buf,cc);
X cs += cc;
X yanke = cs;
X }
X}
X
Xvoid viputafter() /**/
X{
Xint cc;
Xchar *buf = cutbuf;
X
X if (!cutbuf) {


X feep();
X return;
X }

X if (mult < 0) return;

X if (vibufspec) {
X vibufspec = tolower(vibufspec);


X vibufspec += (idigit(vibufspec)) ? -'1'+26 : -'a';

X if (!(buf = vibuf[vibufspec])) {
X feep();
X vibufspec = 0;
X return;
X }
X vibufspec = 0;
X }
X if (strchr(buf,'\n')) {
X cs = findeol();
X if (cs == ll) { spaceinline(1); line[cs] = '\n'; }
X }
X if (cs != ll) cs++;
X yankb = cs;
X while (mult--) {
X kct = kringnum;
X cc = strlen(buf);
X spaceinline(cc);
X strncpy((char *) line+cs,buf,cc);
X cs += cc;
X yanke = cs;
X }
X cs = yankb;
X}
X
Xvoid yankpop() /**/
X{
Xint cc;
X
X if (!(lastcmd & ZLE_YANK) || !kring[kct]) {


X feep();
X return;
X }

X cs = yankb;
X foredel(yanke-yankb);
X cc = strlen(kring[kct]);
X spaceinline(cc);
X strncpy((char *) line+cs,kring[kct],cc);
X cs += cc;
X yanke = cs;
X kct = (kct-1) & (KRINGCT-1);
X}
X
Xvoid overwritemode() /**/
X{
X insmode ^= 1;
X}
X
Xvoid undefinedkey() /**/
X{
X feep();
X}
X
Xvoid quotedinsert() /**/
X{
X#ifndef TIO
Xstruct sgttyb sob;
X sob = shttyinfo.sgttyb;
X sob.sg_flags = (sob.sg_flags|RAW) & ~ECHO;
X ioctl(SHTTY,TIOCSETN,&sob);
X#endif
X c = getkey(0);
X#ifndef TIO
X setterm();
X#endif
X if (c) selfinsert(); else feep();
X}
X
Xvoid digitargument() /**/
X{


X if (!(lastcmd & ZLE_ARG))

X mult = 0;
X mult = mult*10+(c&0xf);
X if (lastcmd & ZLE_NEGARG) mult = -mult;
X}
X
Xvoid negargument() /**/
X{
X if (lastcmd & ZLE_ARG) feep();
X}
X
Xvoid universalargument() /**/
X{


X if (!(lastcmd & ZLE_ARG))

X mult = 4;
X else
X mult *= 4;
X}
X
Xvoid copyprevword() /**/
X{
Xint len,t0;
X
X for (t0 = cs-1; t0 >= 0; t0--)
X if (iword(line[t0]))
X break;
X for (; t0 >= 0; t0--)
X if (!iword(line[t0]))
X break;
X if (t0)
X t0++;
X len = cs-t0;
X spaceinline(len);
X strncpy((char *) line+cs,(char *) line+t0,len);
X cs += len;
X}
X
Xvoid sendbreak() /**/
X{
X errflag = done = 1;
X}
X
Xvoid undo() /**/
X{
Xchar *s;
Xstruct undoent *ue;
X
X ue = undos+undoct;
X if (!ue->change)
X {


X feep();
X return;
X }

X line[ll] = '\0';

X s = ztrdup((char *) line+ll-ue->suff);
X sizeline((ll = ue->pref+ue->suff+ue->len)+1);
X strncpy((char *) line+ue->pref,ue->change,ue->len);
X strcpy((char *) line+ue->pref+ue->len,s);
X free(s);
X ue->change = NULL;
X undoct = (undoct-1) & (UNDOCT-1);
X cs = ue->cs;
X}
X
Xvoid quoteregion() /**/
X{
Xchar *s,*t;
Xint x,y;
X
X if (mark > ll)
X mark = ll;
X if (mark < cs)


X {
X x = mark;
X mark = cs;
X cs = x;
X }

X s = hcalloc((y = mark-cs)+1);
X strncpy(s,(char *) line+cs,y);
X s[y] = '\0';
X foredel(mark-cs);
X t = makequote(s);
X spaceinline(x = strlen(t));
X strncpy((char *) line+cs,t,x);
X mark = cs;
X cs += x;
X}
X
Xvoid quoteline() /**/
X{
Xchar *s;
X


X line[ll] = '\0';

X s = makequote((char *) line);
X setline(s);
X}
X
Xchar *makequote(s) /**/
Xchar *s;
X{
Xint qtct = 0;
Xchar *l,*ol;
X
X for (l = s; *l; l++)
X if (*l == '\'')
X qtct++;
X l = ol = halloc((qtct*3)+3+strlen(s));
X *l++ = '\'';


X for (; *s; s++)

X if (*s == '\'')
X {
X *l++ = '\'';
X *l++ = '\\';
X *l++ = '\'';
X *l++ = '\'';
X }
X else
X *l++ = *s;
X *l++ = '\'';
X *l = '\0';
X return ol;
X}
X
X#define NAMLEN 70
X
Xint executenamedcommand() /**/
X{
Xchar buf[NAMLEN],*ptr;
Xint len,ch,t0;
X
X strcpy(buf,"execute: ");
X ptr = buf+9;
X len = 0;
X statusline = buf;
X refresh();
X for (;ch = getkey(1);refresh())
X {
X switch (ch)
X {
X case 8: case 127:
X if (len)
X {
X len--;
X *--ptr = '\0';
X }
X break;
X case 23:
X while (len && (len--, *--ptr != '-'))
X *ptr = '\0';
X break;
X case 21:
X len = 0;
X ptr = buf+9;
X *ptr = '\0';
X break;
X case 10: case 13: goto brk;
X case 7: case -1: statusline = NULL; return z_undefinedkey;
X case 9: case 32:
X {
X Lklist ll;
X int ambig = 100;
X
X heapalloc();
X ll = newlist();
X for (t0 = 0; t0 != ZLECMDCOUNT; t0++)
X if (strpfx(buf+9,zlecmds[t0].name))
X {
X int xx;
X
X addnode(ll,zlecmds[t0].name);
X xx = pfxlen(peekfirst(ll),zlecmds[t0].name);
X if (xx < ambig)
X ambig = xx;
X }
X permalloc();
X if (!full(ll))
X feep();
X else if (!nextnode(firstnode(ll)))
X {
X strcpy(buf+9,peekfirst(ll));
X ptr = buf+(len = strlen(buf));
X }
X else
X {
X strcpy(buf+9,peekfirst(ll));
X len = ambig;
X ptr = buf+9+len;
X *ptr = '\0';
X feep();
X listmatches(ll,NULL);
X }
X break;
X }
X default:
X if (len == NAMLEN-10 || icntrl(ch))
X feep();
X else
X *ptr++ = ch, *ptr = '\0', len++;
X break;
X }
X }
Xbrk:
X statusline = NULL;
X ptr = buf+9;
X for (t0 = 0; t0 != ZLECMDCOUNT; t0++)
X if (!strcmp(ptr,zlecmds[t0].name))
X break;
X if (t0 != ZLECMDCOUNT)
X return lastnamed = t0;
X else
X return z_undefinedkey;
X}
X
Xvoid vijoin() /**/
X{
Xint x;
X
X if ((x = findeol()) == ll)
X {
X feep();
X return;
X }
X cs = x+1;
X for (x = 1; cs != ll && iblank(line[cs]); cs++,x++);
X backdel(x);
X spaceinline(1);
X line[cs] = ' ';
X}
X
Xvoid viswapcase() /**/
X{
X if (cs < ll)


X {
X int ch = line[cs];
X
X if (islower(ch))
X ch = tuupper(ch);
X else if (isupper(ch))
X ch = tulower(ch);
X line[cs++] = ch;
X }
X}
X

Xvoid vicapslockpanic() /**/
X{
Xchar ch;
X
X statusline = "press a lowercase key to continue";
X refresh();
X do
X ch = getkey(0);
X while (!islower(ch));
X}
X
Xvoid visetbuffer() /**/


X{
Xint ch;
X
X ch = getkey(1);

X if (!ialnum(ch)) {


X feep();
X return;
X }

X vibufspec = ch;
X}
X
Xstatic char *bp;
Xstatic int lensb,countp;
X
Xvoid stradd(d) /**/
Xchar *d;
X{
X while (*bp++ = *d++);
X bp--;
X}
X
Xint putstr(d) /**/
Xint d;
X{
X *bp++ = d;
X if (countp)
X lensb++;


X return 0;
X}
X

X#define tstradd(X) \
X if (termok && unset(SINGLELINEZLE)) { \
X char tbuf[2048],*tptr = tbuf; \
X if (tgetstr(X,&tptr)) \
X tputs(tbuf,1,putstr); \
X } \
X break
X
X/* get a prompt string */
X
Xchar *putprompt(fm,lenp) /**/
Xchar *fm;int *lenp;
X{
Xchar *ss,*bl0;
Xstatic char buf1[256],buf2[256],*buf;
Xchar buf3[MAXPATHLEN];
Xint t0,bracepos = 0;


Xstruct tm *tm = NULL;

Xtime_t timet;
X
X lensb = 0; countp = 1;
X if (!fm) { *lenp = 0; return ""; }
X /* kludge alert! */
X buf = (buf == buf1) ? buf2 : buf1;
X bp = bl0 = buf;
X if (!columns) columns = 80;
X clearerr(stdin);
X for(;*fm;fm++) {
X if (bp-buf >= 220)
X break;
X if (*fm == '%')
X switch (*++fm) {
X case '~':
X t0 = finddir(pwd);


X if (t0 != -1) {

X *bp++ = '~';
X stradd(usernames[t0]);
X stradd(pwd+strlen(userdirs[t0]));
X break;
X }
X if (!strncmp(pwd,home,t0 = strlen(home)) && t0 > 1) {
X *bp++ = '~';
X stradd(pwd+t0);
X break;
X }
X case 'd': case '/': stradd(pwd); break;
X case 'c': case '.':
X t0 = finddir(pwd);


X if (t0 != -1) {

X sprintf(buf3,"~%s%s",usernames[t0],
X pwd+strlen(userdirs[t0]));
X } else if (!strncmp(pwd,home,t0 = strlen(home)) && t0 > 1) {
X sprintf(buf3,"~%s",pwd+t0);
X } else {
X strcpy(buf3,pwd);


X }
X t0 = 1;

X if (idigit(fm[1])) { t0 = fm[1]-'0'; fm++; }
X for (ss = buf3+strlen(buf3); ss > buf3; ss--)
X if (*ss == '/' && !--t0) {
X ss++;
X break;
X }
X if (*ss == '/' && ss[1] && (ss != buf3)) ss++;
X stradd(ss);


X break;
X case 'C':

X strcpy(buf3,pwd);
X t0 = 1;
X if (idigit(fm[1])) { t0 = fm[1]-'0'; fm++; }
X for (ss = buf3+strlen(buf3); ss > buf3; ss--)
X if (*ss == '/' && !--t0) {
X ss++;
X break;
X }
X if (*ss == '/' && ss[1] && (ss != buf3)) ss++;
X stradd(ss);
X break;
X case 'h': case '!':
X sprintf(bp,"%d",curhist);
X bp += strlen(bp);
X break;
X case 'M': stradd(hostnam); break;
X case 'm':
X if (idigit(fm[1]))
X t0 = (*++fm)-'0';
X else
X t0 = 1;
X for (ss = hostnam; *ss; ss++)
X if (*ss == '.' && !--t0)
X break;
X t0 = *ss;
X *ss = '\0';
X stradd(hostnam);
X *ss = t0;
X break;
X case 'S': tstradd("so"); /* <- this is a macro */
X case 's': tstradd("se");
X case 'B': tstradd("md");
X case 'b': tstradd("me");
X case 'U': tstradd("us");
X case 'u': tstradd("ue");
X case '{': bracepos = bp-buf; countp = 0; break;
X case '}': lensb += (bp-buf)-bracepos; countp = 1; break;
X case 't': case '@':
X timet = time(NULL);
X tm = localtime(&timet);
X ztrftime(bp,16,"%l:%M%p",tm);
X if (*bp == ' ')
X chuck(bp);
X bp += strlen(bp);


X break;
X case 'T':

X timet = time(NULL);
X tm = localtime(&timet);
X ztrftime(bp,16,"%k:%M",tm);
X bp += strlen(bp);
X break;
X case '*':
X timet = time(NULL);
X tm = localtime(&timet);
X ztrftime(bp,16,"%k:%M:%S",tm);
X bp += strlen(bp);
X break;
X case 'n': stradd(username); break;
X case 'w':
X timet = time(NULL);
X tm = localtime(&timet);
X ztrftime(bp,16,"%a %e",tm);
X bp += strlen(bp);


X break;
X case 'W':

X timet = time(NULL);
X tm = localtime(&timet);
X ztrftime(bp,16,"%m/%d/%y",tm);
X bp += strlen(bp);


X break;
X case 'D':

X strcpy(buf3, "%y-%m-%d");
X if (fm[1] == '{') {
X for (ss = fm + 1, t0 = 0; *ss; ++ss)
X if (*ss == '{')
X ++t0;
X else if (*ss == '}')
X if (--t0 == 0)
X break;
X if (*ss == '}' && t0 == 0) {
X t0 = (ss - 1) - (fm + 1);
X strncpy(buf3, fm + 2, t0);
X buf3[t0] = 0;
X fm = ss;
X }
X }
X timet = time(NULL);
X tm = localtime(&timet);
X ztrftime(bp,16,buf3,tm);
X bp += strlen(bp);


X break;
X case 'l':

X if (*ttystrname) stradd((strncmp(ttystrname,"/dev/tty",8) ?
X ttystrname+5 : ttystrname+8));
X else stradd("()");
X break;
X case '?':
X sprintf(bp,"%d",lastval);
X bp += strlen(bp);
X break;
X case '%': *bp++ = '%'; break;
X case '#': *bp++ = (geteuid()) ? '%' : '#'; break;
X case 'r': stradd(rstring); break;
X case 'R': stradd(Rstring); break;
X default: *bp++ = '%'; *bp++ = *fm; break;
X }
X else if (*fm == '!') {
X sprintf(bp,"%d",curhist);
X bp += strlen(bp);
X } else {
X if (fm[0] == '\\' && fm[1])
X fm++;
X if ((*bp++ = *fm) == '\n')
X bl0 = bp, lensb = 0;
X }
X }
X *lenp = (bp-bl0)-lensb;
X *lenp %= columns;
X if (*lenp == columns-1) {
X *lenp = 0;
X *bp++ = ' ';
X }
X *bp = '\0';
X return buf;
X}
X
SHAR_EOF
echo 'File zsh2.2/src/zle_misc.c is complete' &&
chmod 0644 zsh2.2/src/zle_misc.c ||


echo 'restore of zsh2.2/src/zle_misc.c failed'

Wc_c="`wc -c < 'zsh2.2/src/zle_misc.c'`"
test 14519 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_misc.c: original size 14519, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_word.c ==============
if test -f 'zsh2.2/src/zle_word.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_word.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_word.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_word.c' &&
X/*
X *
X * zle_word.c - word-related editor functions


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#define ZLE
X#include "zsh.h"
X
X

Xvoid forwardword() /**/
X{
X if (mult < 0) { mult = -mult; backwardword(); return; }
X while (mult--) {
X while (cs != ll && iword(line[cs])) cs++;
X if (wordflag && !mult) return;
X while (cs != ll && !iword(line[cs])) cs++;
X }
X}
X
Xvoid viforwardword() /**/
X{
X if (mult < 0) { mult = -mult; backwardword(); return; }
X while (mult--) {
X if (iident(line[cs])) while (cs != ll && iident(line[cs])) cs++;
X else while (cs != ll && !iident(line[cs]) && !iblank(line[cs])) cs++;
X if (wordflag && !mult) return;
X while (cs != ll && iblank(line[cs])) cs++;
X }
X}
X
Xvoid viforwardblankword() /**/
X{
X if (mult < 0) { mult = -mult; vibackwardblankword(); return; }
X while (mult--) {
X while (cs != ll && !iblank(line[cs])) cs++;
X if (wordflag && !mult) return;
X while (cs != ll && iblank(line[cs])) cs++;
X }
X}
X
Xvoid emacsforwardword() /**/
X{
X if (mult < 0) { mult = -mult; emacsbackwardword(); return; }
X while (mult--)
X {
X while (cs != ll && !iword(line[cs])) cs++;
X if (wordflag && !mult) return;
X while (cs != ll && iword(line[cs])) cs++;
X }
X}
X
Xvoid viforwardblankwordend() /**/
X{
X if (mult < 0) return;
X while (mult--) {
X while (cs != ll && iblank(line[cs+1])) cs++;
X while (cs != ll && !iblank(line[cs+1])) cs++;
X }
X if (cs != ll && virangeflag) cs++;
X}
X
Xvoid viforwardwordend() /**/
X{
X if (mult < 0) { mult = -mult; backwardword(); return; }
X while (mult--) {
X if (iblank(line[cs+1])) while (cs != ll && iblank(line[cs+1])) cs++;
X if (iident(line[cs+1])) while (cs != ll && iident(line[cs+1])) cs++;
X else while (cs != ll && !iident(line[cs+1]) && !iblank(line[cs+1])) cs++;
X }
X if (cs != ll && virangeflag) cs++;
X}
X
Xvoid backwardword() /**/
X{
X if (mult < 0) { mult = -mult; forwardword(); return; }
X while (mult--) {
X while (cs && !iword(line[cs-1])) cs--;
X while (cs && iword(line[cs-1])) cs--;
X }
X}
X
Xvoid vibackwardword() /**/
X{
X if (mult < 0) { mult = -mult; backwardword(); return; }
X while (mult--) {
X while (cs && iblank(line[cs-1])) cs--;
X if (iident(line[cs-1])) while (cs && iident(line[cs-1])) cs--;
X else while (cs && !iident(line[cs-1]) && !iblank(line[cs-1])) cs--;
X }
X}
X
Xvoid vibackwardblankword() /**/
X{
X if (mult < 0) { mult = -mult; viforwardblankword(); return; }
X while (mult--) {
X while (cs && iblank(line[cs-1])) cs--;
X while (cs && !iblank(line[cs-1])) cs--;
X }
X}
X
Xvoid emacsbackwardword() /**/
X{
X if (mult < 0) { mult = -mult; emacsforwardword(); return; }
X while (mult--) {
X while (cs && !iword(line[cs-1])) cs--;
X while (cs && iword(line[cs-1])) cs--;
X }
X}
X
Xvoid backwarddeleteword() /**/
X{
Xint x = cs;
X
X if (mult < 0) { mult = -mult; deleteword(); return; }
X while (mult--) {
X while (x && !iword(line[x-1])) x--;
X while (x && iword(line[x-1])) x--;
X }
X backdel(cs-x);
X}
X
Xvoid vibackwardkillword() /**/
X{
Xint x = cs;
X
X if (mult < 0) { feep(); return; }
X while (mult--) {
X while (x > viinsbegin && !iword(line[x-1])) x--;
X while (x > viinsbegin && iword(line[x-1])) x--;
X }
X backkill(cs-x,1);
X}
X
Xvoid backwardkillword() /**/
X{
Xint x = cs;
X
X if (mult < 0) { mult = -mult; killword(); return; }
X while (mult--) {
X while (x && !iword(line[x-1])) x--;
X while (x && iword(line[x-1])) x--;
X }
X backkill(cs-x,1);
X}
X
Xvoid upcaseword() /**/
X{
Xint neg = mult < 0, ocs = cs;
X
X if (neg) mult = -mult;
X while (mult--) {
X while (cs != ll && !iword(line[cs])) cs++;
X while (cs != ll && iword(line[cs])) {
X line[cs] = tuupper(line[cs]);
X cs++;
X }
X }
X if (neg) cs = ocs;
X}
X
Xvoid downcaseword() /**/
X{
Xint neg = mult < 0, ocs = cs;
X
X if (neg) mult = -mult;
X while (mult--) {
X while (cs != ll && !iword(line[cs])) cs++;
X while (cs != ll && iword(line[cs])) {
X line[cs] = tulower(line[cs]);
X cs++;
X }
X }
X if (neg) cs = ocs;
X}
X
Xvoid capitalizeword() /**/
X{
Xint first;
Xint neg = mult < 0, ocs = cs;
X
X if (neg) mult = -mult;
X while (mult--) {
X first = 1;
X while (cs != ll && !iword(line[cs])) cs++;
X while (cs != ll && iword(line[cs])) {
X line[cs] = (first) ? tuupper(line[cs]) : tulower(line[cs]);
X first = 0;
X cs++;
X }
X }
X if (neg) cs = ocs;
X}
X
Xvoid deleteword() /**/
X{
Xint x = cs;
X
X if (mult < 0) { mult = -mult; backwarddeleteword(); return; }
X while (mult--) {
X while (x != ll && !iword(line[x])) x++;
X while (x != ll && iword(line[x])) x++;
X }
X foredel(x-cs);
X}
X
Xvoid killword() /**/
X{
Xint x = cs;
X
X if (mult < 0) { mult = -mult; backwardkillword(); return; }
X while (mult--) {
X while (x != ll && !iword(line[x])) x++;
X while (x != ll && iword(line[x])) x++;
X }
X forekill(x-cs,0);
X}
X
Xvoid transposewords() /**/
X{
Xint p1,p2,p3,p4,x = cs;
Xchar *temp,*pp;
Xint neg = mult < 0, ocs = cs;
X
X if (neg) mult = -mult;
X while (mult--) {
X while (x != ll && line[x] != '\n' && !iword(line[x]))
X x++;
X if (x == ll || line[x] == '\n') {
X x = cs;
X while (x && line[x-1] != '\n' && !iword(line[x]))
X x--;
X if (!x || line[x-1] == '\n') {


X feep();
X return;
X }
X }

X for (p4 = x; p4 != ll && iword(line[p4]); p4++);
X for (p3 = p4; p3 && iword(line[p3-1]); p3--);
X if (!p3) {


X feep();
X return;
X }

X for (p2 = p3; p2 && !iword(line[p2-1]); p2--);
X if (!p2) {


X feep();
X return;
X }

X for (p1 = p2; p1 && iword(line[p1-1]); p1--);
X pp = temp = halloc(p4-p1+1);
X struncpy(&pp,line+p3,p4-p3);
X struncpy(&pp,line+p2,p3-p2);
X struncpy(&pp,line+p1,p2-p1);
X strncpy((char *) line+p1,temp,p4-p1);
X cs = p4;
X }
X if (neg) cs = ocs;
X}
SHAR_EOF
chmod 0644 zsh2.2/src/zle_word.c ||
echo 'restore of zsh2.2/src/zle_word.c failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_word.c'`"
test 6019 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_word.c: original size 6019, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_hist.c ==============
if test -f 'zsh2.2/src/zle_hist.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_hist.c (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_hist.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_hist.c' &&
X/*
X *
X * zle_hist.c - history editing


X *
X * This file is part of zsh, the Z shell.
X *
X * This software is Copyright 1992 by Paul Falstad
X *
X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
X * use this software as long as: there is no monetary profit gained
X * specifically from the use or reproduction of this software, it is not
X * sold, rented, traded or otherwise marketed, and this copyright notice is
X * included prominently in any copy made.
X *
X * The author make no claims as to the fitness or correctness of this software
X * for any use whatsoever, and it is provided as is. Any use of this software
X * is at the user's own risk.
X *
X */
X
X#define ZLE
X#include "zsh.h"
X

Xvoid toggleliteralhistory() /**/
X{
Xchar *s;
X
X if (histline == curhist)
X {


X if (curhistline)
X free(curhistline);

X curhistline = ztrdup(line);
X }
X lithist ^= 1;
X if (!(s = qgetevent(histline)))
X feep();
X else
X sethistline(s);
X}
X
Xvoid uphistory() /**/
X{
Xchar *s;
X
X if (mult < 0) { mult = -mult; downhistory(); return; }
X if (histline == curhist)
X {


X if (curhistline)
X free(curhistline);

X curhistline = ztrdup(line);
X }
X histline -= mult;
X if (!(s = qgetevent(histline)))
X {
X if (unset(NOHISTBEEP)) feep();
X histline += mult;
X }
X else
X sethistline(s);
X}
X
Xvoid uplineorhistory() /**/


X{
Xint ocs = cs;
X

X if (mult < 0) { mult = -mult; downlineorhistory(); return; }
X if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
X lastcol = cs-findbol();
X cs = findbol();
X while (mult) {
X if (!cs)
X break;
X cs--;
X cs = findbol();


X mult--;
X }
X if (mult) {

X cs = ocs;
X if (virangeflag) {


X feep();
X return;
X }

X uphistory();
X } else {
X int x = findeol();
X if ((cs += lastcol) > x)


X cs = x;
X }

X}
X
Xvoid downlineorhistory() /**/


X{
Xint ocs = cs;
X

X if (mult < 0) { mult = -mult; uplineorhistory(); return; }
X if ((lastcmd & ZLE_LINEMOVE) != ZLE_LINEMOVE)
X lastcol = cs-findbol();
X while (mult) {
X int x = findeol();
X if (x == ll)
X break;
X cs = x+1;


X mult--;
X }
X if (mult) {

X cs = ocs;
X if (virangeflag) {


X feep();
X return;
X }

X downhistory();
X } else {
X int x = findeol();
X if ((cs += lastcol) > x)


X cs = x;
X }

X}
X
Xvoid acceptlineanddownhistory() /**/
X{
Xchar *s,*t;
X
X if (!(s = qgetevent(histline+1)))
X {


X feep();
X return;
X }

X pushnode(bufstack,t = ztrdup(s));


X for (; *t; t++)

X if (*t == HISTSPACE)

X *t = ' ';
X done = 1;
X stackhist = histline+1;
X}
X
Xvoid downhistory() /**/
X{
Xchar *s;
X
X if (mult < 0) { mult = -mult; uphistory(); return; }
X histline += mult;
X if (!(s = qgetevent(histline)))
X {
X if (unset(NOHISTBEEP)) feep();
X histline -= mult;
X return;
X }
X sethistline(s);
X}
X
Xstatic int histpos;
X
Xvoid historysearchbackward() /**/
X{
Xint t0,ohistline = histline;
Xchar *s;
X
X if (histline == curhist)
X {


X if (curhistline)
X free(curhistline);

X curhistline = ztrdup(line);
X }
X if (lastcmd & ZLE_HISTSEARCH) t0 = histpos;
X else for (t0 = 0; line[t0] && iword(line[t0]); t0++);
X histpos = t0;
X for (;;)
X {
X histline--;
X if (!(s = qgetevent(histline)))
X {
X feep();
X histline = ohistline;
X return;
X }
X if (!hstrncmp(s,line,t0) && hstrcmp(s,line))
X break;
X }
X sethistline(s);
X}
X
Xvoid historysearchforward() /**/
X{
Xint t0,ohistline = histline;
Xchar *s;
X
X if (histline == curhist)
X {


X if (curhistline)
X free(curhistline);

X curhistline = ztrdup(line);
X }
X if (lastcmd & ZLE_HISTSEARCH) t0 = histpos;
X else for (t0 = 0; line[t0] && iword(line[t0]); t0++);
X histpos = t0;
X for (;;)
X {
X histline++;
X if (!(s = qgetevent(histline)))
X {
X feep();
X histline = ohistline;
X return;
X }
X if (!hstrncmp(s,line,t0) && hstrcmp(s,line))
X break;
X }
X sethistline(s);
X}
X
Xvoid beginningofbufferorhistory() /**/
X{
X if (findbol())
X cs = 0;
X else
X beginningofhistory();
X}
X
Xvoid beginningofhistory() /**/
X{
Xchar *s;
X
X if (histline == curhist)
X {


X if (curhistline)
X free(curhistline);

X curhistline = ztrdup(line);
X }
X if (!(s = qgetevent(firsthist())))
X {
X if (unset(NOHISTBEEP)) feep();
X return;
X }
X histline = firsthist();
X sethistline(s);
X}
X
Xvoid endofbufferorhistory() /**/
X{
X if (findeol() != ll)
X cs = ll;
X else
X endofhistory();
X}
X
Xvoid endofhistory() /**/
X{
X if (histline == curhist) {
X if (unset(NOHISTBEEP)) feep();
X } else
X {
X histline = curhist;
X sethistline(curhistline);
X }
X}
X
Xvoid insertlastword() /**/
X{
Xchar *s,*t;
Xint len,z = lithist;
X
X /* multiple calls will now search back through the history, pem */
X static char *lastinsert;
X static int lasthist, lastpos;
X int evhist = curhist - 1;
X
X if (lastinsert) {
X int len = strlen(lastinsert);
X int pos = cs;
X if ( lastpos <= pos &&
X len == pos - lastpos &&
X strncmp(lastinsert, (char *) &line[lastpos], len) == 0) {
X evhist = --lasthist;
X cs = lastpos;
X foredel(pos-cs);
X }
X free(lastinsert);
X lastinsert = NULL;
X }
X lithist = 0;
X if (!(s = qgetevent(evhist), lithist = z, s))
X {


X feep();
X return;
X }

X for (t = s+strlen(s); t > s; t--)

X if (*t == HISTSPACE)
X break;


X if (t != s)
X t++;

X lasthist = evhist;
X lastpos = cs;
X lastinsert = ztrdup(t);
X spaceinline(len = strlen(t));
X strncpy((char *) line+cs,t,len);
X cs += len;
X}
X
Xchar *qgetevent(ev) /**/
Xint ev;
X{
X if (ev > curhist)
X return NULL;
X return ((ev == curhist) ? curhistline : quietgetevent(ev));
X}
X
Xvoid pushline() /**/
X{
X if (mult < 0) return;
X pushnode(bufstack,ztrdup(line));
X while (--mult)
X pushnode(bufstack,ztrdup(""));
X stackcs = cs;
X *line = '\0';
X ll = cs = 0;
X}
X
Xvoid getline() /**/
X{
Xchar *s = getnode(bufstack);
X
X if (!s)
X feep();
X else
X {
X int cc;
X
X cc = strlen(s);
X spaceinline(cc);
X strncpy((char *) line+cs,s,cc);
X cs += cc;
X free(s);
X }
X}
X
Xvoid historyincrementalsearchbackward() /**/
X{
X doisearch(-1);
X}
X
Xvoid historyincrementalsearchforward() /**/
X{
X doisearch(1);
X}
X
Xvoid doisearch(dir) /**/
Xint dir;
X{
Xchar *s,*oldl;
Xchar ibuf[256],*sbuf = ibuf+10;
Xint sbptr = 0,ch,ohl = histline,ocs = cs;
Xint nomatch = 0,chequiv = 0;
X
X strcpy(ibuf,"i-search: ");
X statusline = ibuf;
X oldl = ztrdup(line);
X if (histline == curhist)
X {


X if (curhistline)
X free(curhistline);

X curhistline = ztrdup(line);
X }
X for (;;)
X {
X nomatch = 0;
X if (sbptr > 1 || (sbptr == 1 && sbuf[0] != '^'))
X {
X int ohistline = histline;
X
X for (;;)
X {
X char *t;
X
X if (!(s = qgetevent(histline)))
X {
X feep();
X nomatch = 1;
X histline = ohistline;
X break;
X }
X if ((sbuf[0] == '^') ?
X (t = (hstrncmp(s,sbuf+1,sbptr-1)) ? NULL : s) :
X (t = hstrnstr(s,sbuf,sbptr)))
X if (!(chequiv && !hstrcmp(line,s)))
X {
X sethistline(s);
X cs = t-s+sbptr-(sbuf[0] == '^');
X break;
X }
X histline += dir;
X }
X chequiv = 0;
X }
X refresh();
X if ((ch = getkey(1)) == -1)
X break;
X if (ch == 22 || ch == 17) {
X if ((ch = getkey(1)) == -1)
X break;
X } else if (ch == 24) { /* ^XS and ^XR */
X if ((ch = getkey(1)) == -1)
X break;
X if (ch != 's' && ch != 'r') {
X ungetkey(24);
X ungetkey(ch);
X break;
X }
X ungetkey(ch & 0x1f);
X continue;
X } else if (ch == 8 || ch == 127) {
X if (sbptr)
X sbuf[--sbptr] = '\0';
X else
X feep();
X histline = ohl;
X continue;
X } else if (ch == 7 || ch == 3) {
X setline(oldl);
X cs = ocs;
X histline = ohl;
X statusline = NULL;
X break;


X } else if (ch == 27)

X break;
X else if (ch == 10 || ch == 13) {
X ungetkey(ch);
X break;
X } else if (ch == 18) {
X ohl = (histline += (dir = -1));
X chequiv = 1;
X continue;
X } else if (ch == 19) {
X ohl = (histline += (dir = 1));
X chequiv = 1;
X continue;
X } else if (!(ch & 0x60)) {
X ungetkey(ch);
X break;
X }
X if (!nomatch && sbptr != 39 && !icntrl(ch)) {
X sbuf[sbptr++] = ch;
X sbuf[sbptr] = '\0';
X }
X }
X free(oldl);


X statusline = NULL;
X}

X
Xvoid acceptandinfernexthistory() /**/
X{
Xint t0;
Xchar *s,*t;
X
X done = 1;
X for (t0 = histline-2;;t0--)
X {
X if (!(s = qgetevent(t0)))
X return;
X if (!hstrncmp(s,line,ll))
X break;
X }
X if (!(s = qgetevent(t0+1)))
X return;
X pushnode(bufstack,t = ztrdup(s));


X for (; *t; t++)

X if (*t == HISTSPACE)

X *t = ' ';
X stackhist = t0+1;
X}
X
Xvoid infernexthistory() /**/
X{
Xint t0;
Xchar *s,*t;
X
X if (!(t = qgetevent(histline-1)))
X {


X feep();
X return;
X }

X for (t0 = histline-2;;t0--)
X {
X if (!(s = qgetevent(t0)))
X {


X feep();
X return;
X }

X if (!strcmp(s,t))
X break;
X }
X if (!(s = qgetevent(t0+1)))
X {


X feep();
X return;
X }

X histline = t0+1;
X sethistline(s);
X}
X
Xvoid vifetchhistory() /**/
X{
Xchar *s;
X
X if (mult < 0) return;
X if (histline == curhist) {
X if (!(lastcmd & ZLE_ARG)) {
X cs = ll;
X cs = findbol();
X return;
X }
X if (curhistline)
X free(curhistline);
X curhistline = ztrdup(line);
X }
X if (!(lastcmd & ZLE_ARG)) mult = curhist;
X if (!(s = qgetevent(mult)))
X feep();
X else {
X histline = mult;
X sethistline(s);
X }
X}
X
Xint getvisrchstr() /**/
X{
Xchar sbuf[80];
Xint sptr = 1;
X
X if (visrchstr)
X {
X free(visrchstr);
X visrchstr = NULL;
X }
X statusline = sbuf;
X sbuf[0] = c;
X sbuf[1] = '\0';
X while (sptr)
X {
X refresh();
X c = getkey(0);
X if (c == '\r' || c == '\n' || c == '\033')
X {
X visrchstr = ztrdup(sbuf+1);
X return 1;
X }
X if (c == '\b' || c == 127)
X {
X sbuf[--sptr] = '\0';
X continue;
X }
X if (sptr != 79)
X {
X sbuf[sptr++] = c;
X sbuf[sptr] = '\0';
X }
X }


X return 0;
X}
X

Xvoid vihistorysearchforward() /**/
X{
X visrchsense = 1;
X if (getvisrchstr())
X virepeatsearch();
X}
X
Xvoid vihistorysearchbackward() /**/
X{
X visrchsense = -1;
X if (getvisrchstr())
X virepeatsearch();
X}
X
Xvoid virepeatsearch() /**/
X{
Xint ohistline = histline,t0;
Xchar *s;
X
X if (!visrchstr)
X {


X feep();
X return;
X }

X t0 = strlen(visrchstr);
X if (histline == curhist)
X {


X if (curhistline)
X free(curhistline);

X curhistline = ztrdup(line);
X }
X for (;;)
X {
X histline += visrchsense;
X if (!(s = qgetevent(histline)))
X {
X feep();
X histline = ohistline;
X return;
X }
X if (!hstrcmp(line,s))
X continue;
X if (*visrchstr == '^')
X {
X if (!hstrncmp(s,visrchstr+1,t0-1))
X break;
X }
X else
X if (hstrnstr(s,visrchstr,t0))
X break;
X }
X sethistline(s);
X}
X
Xvoid virevrepeatsearch() /**/
X{
X visrchsense = -visrchsense;
X virepeatsearch();
X visrchsense = -visrchsense;
X}
X
SHAR_EOF
chmod 0644 zsh2.2/src/zle_hist.c ||
echo 'restore of zsh2.2/src/zle_hist.c failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_hist.c'`"
test 10080 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_hist.c: original size 10080, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_hist.pro ==============
if test -f 'zsh2.2/src/zle_hist.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_hist.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_hist.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_hist.pro' &&
Xvoid toggleliteralhistory DCLPROTO((void));
Xvoid uphistory DCLPROTO((void));
Xvoid uplineorhistory DCLPROTO((void));
Xvoid downlineorhistory DCLPROTO((void));
Xvoid acceptlineanddownhistory DCLPROTO((void));
Xvoid downhistory DCLPROTO((void));
Xvoid historysearchbackward DCLPROTO((void));
Xvoid historysearchforward DCLPROTO((void));
Xvoid beginningofbufferorhistory DCLPROTO((void));
Xvoid beginningofhistory DCLPROTO((void));
Xvoid endofbufferorhistory DCLPROTO((void));
Xvoid endofhistory DCLPROTO((void));
Xvoid insertlastword DCLPROTO((void));
Xchar *qgetevent DCLPROTO((int ev));
Xvoid pushline DCLPROTO((void));
Xvoid getline DCLPROTO((void));
Xvoid historyincrementalsearchbackward DCLPROTO((void));
Xvoid historyincrementalsearchforward DCLPROTO((void));
Xvoid doisearch DCLPROTO((int dir));
Xvoid acceptandinfernexthistory DCLPROTO((void));
Xvoid infernexthistory DCLPROTO((void));
Xvoid vifetchhistory DCLPROTO((void));
Xint getvisrchstr DCLPROTO((void));
Xvoid vihistorysearchforward DCLPROTO((void));
Xvoid vihistorysearchbackward DCLPROTO((void));
Xvoid virepeatsearch DCLPROTO((void));
Xvoid virevrepeatsearch DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_hist.pro ||
echo 'restore of zsh2.2/src/zle_hist.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_hist.pro'`"
test 1119 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_hist.pro: original size 1119, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_misc.pro ==============
if test -f 'zsh2.2/src/zle_misc.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_misc.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_misc.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_misc.pro' &&
Xvoid selfinsert DCLPROTO((void));
Xvoid selfinsertunmeta DCLPROTO((void));
Xvoid deletechar DCLPROTO((void));
Xvoid backwarddeletechar DCLPROTO((void));
Xvoid videletechar DCLPROTO((void));
Xvoid vibackwarddeletechar DCLPROTO((void));
Xvoid vikillline DCLPROTO((void));
Xvoid killwholeline DCLPROTO((void));
Xvoid killbuffer DCLPROTO((void));
Xvoid backwardkillline DCLPROTO((void));
Xvoid gosmacstransposechars DCLPROTO((void));
Xvoid transposechars DCLPROTO((void));
Xvoid poundinsert DCLPROTO((void));
Xvoid acceptline DCLPROTO((void));
Xvoid acceptandhold DCLPROTO((void));
Xvoid killline DCLPROTO((void));
Xvoid killregion DCLPROTO((void));
Xvoid copyregionaskill DCLPROTO((void));
Xvoid yank DCLPROTO((void));
Xvoid viputafter DCLPROTO((void));
Xvoid yankpop DCLPROTO((void));
Xvoid overwritemode DCLPROTO((void));
Xvoid undefinedkey DCLPROTO((void));
Xvoid quotedinsert DCLPROTO((void));
Xvoid digitargument DCLPROTO((void));
Xvoid negargument DCLPROTO((void));
Xvoid universalargument DCLPROTO((void));
Xvoid copyprevword DCLPROTO((void));
Xvoid sendbreak DCLPROTO((void));
Xvoid undo DCLPROTO((void));
Xvoid quoteregion DCLPROTO((void));
Xvoid quoteline DCLPROTO((void));
Xchar *makequote DCLPROTO((char *s));
Xint executenamedcommand DCLPROTO((void));
Xvoid vijoin DCLPROTO((void));
Xvoid viswapcase DCLPROTO((void));
Xvoid vicapslockpanic DCLPROTO((void));
Xvoid visetbuffer DCLPROTO((void));
Xvoid stradd DCLPROTO((char *d));
Xint putstr DCLPROTO((int d));
Xchar *putprompt DCLPROTO((char *fm,int *lenp));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_misc.pro ||
echo 'restore of zsh2.2/src/zle_misc.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_misc.pro'`"
test 1478 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_misc.pro: original size 1478, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_move.pro ==============
if test -f 'zsh2.2/src/zle_move.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_move.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_move.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_move.pro' &&
Xvoid beginningofline DCLPROTO((void));
Xvoid endofline DCLPROTO((void));
Xvoid beginningoflinehist DCLPROTO((void));
Xvoid endoflinehist DCLPROTO((void));
Xvoid forwardchar DCLPROTO((void));
Xvoid backwardchar DCLPROTO((void));
Xvoid setmarkcommand DCLPROTO((void));
Xvoid exchangepointandmark DCLPROTO((void));
Xvoid vigotocolumn DCLPROTO((void));
Xvoid vimatchbracket DCLPROTO((void));
Xvoid viforwardchar DCLPROTO((void));
Xvoid vibackwardchar DCLPROTO((void));
Xvoid viendofline DCLPROTO((void));
Xvoid vibeginningofline DCLPROTO((void));
Xvoid vifindnextchar DCLPROTO((void));
Xvoid vifindprevchar DCLPROTO((void));
Xvoid vifindnextcharskip DCLPROTO((void));
Xvoid vifindprevcharskip DCLPROTO((void));
Xvoid virepeatfind DCLPROTO((void));
Xvoid virevrepeatfind DCLPROTO((void));
Xvoid vifirstnonblank DCLPROTO((void));
Xvoid visetmark DCLPROTO((void));
Xvoid vigotomark DCLPROTO((void));
Xvoid vigotomarkline DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_move.pro ||
echo 'restore of zsh2.2/src/zle_move.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_move.pro'`"
test 909 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_move.pro: original size 909, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/zle_word.pro ==============
if test -f 'zsh2.2/src/zle_word.pro' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/zle_word.pro (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/zle_word.pro (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/zle_word.pro' &&
Xvoid forwardword DCLPROTO((void));
Xvoid viforwardword DCLPROTO((void));
Xvoid viforwardblankword DCLPROTO((void));
Xvoid emacsforwardword DCLPROTO((void));
Xvoid viforwardblankwordend DCLPROTO((void));
Xvoid viforwardwordend DCLPROTO((void));
Xvoid backwardword DCLPROTO((void));
Xvoid vibackwardword DCLPROTO((void));
Xvoid vibackwardblankword DCLPROTO((void));
Xvoid emacsbackwardword DCLPROTO((void));
Xvoid backwarddeleteword DCLPROTO((void));
Xvoid vibackwardkillword DCLPROTO((void));
Xvoid backwardkillword DCLPROTO((void));
Xvoid upcaseword DCLPROTO((void));
Xvoid downcaseword DCLPROTO((void));
Xvoid capitalizeword DCLPROTO((void));
Xvoid deleteword DCLPROTO((void));
Xvoid killword DCLPROTO((void));
Xvoid transposewords DCLPROTO((void));
SHAR_EOF
chmod 0644 zsh2.2/src/zle_word.pro ||
echo 'restore of zsh2.2/src/zle_word.pro failed'
Wc_c="`wc -c < 'zsh2.2/src/zle_word.pro'`"
test 733 -eq "$Wc_c" ||
echo 'zsh2.2/src/zle_word.pro: original size 733, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/config.h ==============
if test -f 'zsh2.2/src/config.h' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/config.h (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/config.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/config.h' &&


X/* this file is created automatically by buildzsh */

X
X/* define this if you are sysvish */

X/* #define SYSV */
X
X#define TERMIOS


X/* #define TTY_NEEDS_DRAINING */
X/* #define CLOBBERS_TYPEAHEAD */

X
X#define HAS_STDLIB
X
X#define HAS_STRING
X
X#define HAS_LOCALE
X
X/* define this if you have a host field in utmp */
X#define UTMP_HOST
X
X/* define this if you have WAITPID */
X#define WAITPID
X
X/* define this if you have SELECT */
X#define HAS_SELECT
X
X/* define this if you have <sys/select.h> */
X/* #define HAS_SYS_SELECT */
X


X/* we can't just test for S_IFIFO or check to see if the mknod worked,
X because the NeXTs sold by a vendor which will remain nameless will
X happily create the FIFO for you, and then panic when you try to do
X something weird with them, because they aren't supported by the OS. */
X

X/* #define NO_FIFOS */
X
X/* define this if you have strftime() */
X#define HAS_STRFTIME
X
X#define HAS_TCSETPGRP
X
X#define HAS_TCCRAP
X
X#define HAS_SETPGID
X
X/* #define HAS_SIGRELSE */
X
X/* define this if you have RFS */
X/* #define HAS_RFS */
X
X/* define this if you have a working getrusage and wait3 */
X#define HAS_RUSAGE
X


X/* define this if your signal handlers return void */

X#define SIGVOID


X#ifdef sgi
X#undef SIGVOID
X#endif

X
X/* define this if signal handlers need to be reset each time */
X/* #define RESETHANDNEEDED */
X


X#ifdef SIGVOID
X#define HANDTYPE void
X#else
X#define HANDTYPE int
X#define INTHANDTYPE
X#endif
X
X/* a string corresponding to the host type */

X#define HOSTTYPE "sun4"
X
X/* the default editor for the fc builtin */
X#define DEFFCEDIT "vi"
X
X/* the path of wtmp */
X#define WTMP_FILE "/var/adm/wtmp"


X
X/* the path of utmp */
X#define UTMP_FILE "/etc/utmp"
X

X/* default prefix for temporary files */

X#define DEFTMPPREFIX "/tmp/zsh"
X

SHAR_EOF
chmod 0644 zsh2.2/src/config.h ||
echo 'restore of zsh2.2/src/config.h failed'
Wc_c="`wc -c < 'zsh2.2/src/config.h'`"
test 2607 -eq "$Wc_c" ||
echo 'zsh2.2/src/config.h: original size 2607, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/signals.h ==============
if test -f 'zsh2.2/src/signals.h' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/signals.h (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/signals.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/signals.h' &&

echo 'restore of zsh2.2/src/signals.h failed'
Wc_c="`wc -c < 'zsh2.2/src/signals.h'`"
test 1322 -eq "$Wc_c" ||
echo 'zsh2.2/src/signals.h: original size 1322, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.2/src/Makefile ==============
if test -f 'zsh2.2/src/Makefile' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.2/src/Makefile (File already exists)'


rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp

echo 'x - extracting zsh2.2/src/Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.2/src/Makefile' &&


X#! /bin/make -f
X# Makefile for zsh
X# generated by buildzsh
X
XOBJS=builtin.o cond.o exec.o glob.o hist.o init.o jobs.o lex.o loop.o \
Xmath.o mem.o params.o parse.o subst.o table.o text.o utils.o watch.o \
Xzle_bindings.o zle_hist.o zle_main.o zle_misc.o zle_move.o zle_refresh.o \
Xzle_tricky.o zle_utils.o zle_vi.o zle_word.o
X
XBINDIR=/usr/local/bin
XMANDIR=/usr/local/man/man1
X
X# debugging flags
X#CFLAGS=-g -Wreturn-type -Wunused -Wpointer-arith -DQDEBUG
X#CC=gcc -traditional
X
XCC=cc

XCFLAGS= -O
XLIBS= -ltermcap

SHAR_EOF
chmod 0644 zsh2.2/src/Makefile ||
echo 'restore of zsh2.2/src/Makefile failed'
Wc_c="`wc -c < 'zsh2.2/src/Makefile'`"
test 921 -eq "$Wc_c" ||
echo 'zsh2.2/src/Makefile: original size 921, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo You have unpacked the last part

0 new messages