1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-07-22 20:31:03 +02:00

zsh-3.1.5-pws-22

This commit is contained in:
Tanaka Akira 1999-06-18 10:55:45 +00:00
parent 805381040d
commit a2159285e8
77 changed files with 1651 additions and 1236 deletions

179
ChangeLog
View file

@ -1,5 +1,182 @@
1999-06-15 Peter Stephenson <pws@ibmth.difi.unipi.it>
* Oliver: 6636: Completion/Builtins/_limits: wasn't working
* Bart: 6617 + minor changes: Src/utils.c: Be more careful keeping
$COLUMNS and $LINES correct, particularly if exported.
* Sven: zsh-users/2388: Src/jobs.c: while loops etc. in shells
running without MONITOR were hard to kill.
* Bart: 6628: Src/params.c: setting slices of unset array
caused a crash.
1999-06-14 Peter Stephenson <pws@ibmth.difi.unipi.it>
* pws: 6626: Src/mem.c: in zsh's malloc, try to make sure when
sbrk'ing that it's sufficiently well aligned.
* Oliver: 6624: Completion/Builtins/_kill,
Completion/Builtins/_wait: more widely functioning process
handling
* pws: 6623: Completion/Makefile.in, Config/defs.mk.in,
Functions/Makefile.in, INSTALL, Src/init.c, Src/zsh.mdd,
configure.in: --enable-function-subdirs allows installation
into subdirectories of the function directory and sets the
initial $fpath appropriately.
* Oliver: 6620: Completion/Builtins/_jobs: handle disown, too.
* pws: 6618: Doc/Zsh/func.yo, Doc/Zsh/grammar.yo, Src/lex.c:
with SH_GLOB set, function definition parentheses after the
first word on the line allow spaces inside.
* Sven: 6614: Src/Zle/zle_tricky.c, Completion/Brace/_brace_parameter:
completion after quotes in parameters
* pws: 6610: Src/glob.c: globbing flags shouldn't be active
without extendedglob.
* Bart: 6608: Doc/Zsh files compctl.yo, compsys.yo, compwid.yo,
expn.yo, files.yo, mod_mapfile.yo, mod_zftp.yo, params.yo,
zftpsys.yo, zle.yo: spelling corrections
1999-06-12 Peter Stephenson <pws@ibmth.difi.unipi.it>
* pws: 6601: Src/Makefile.in: don't remake Makemod just
to clean up files
* pws: 6600: Doc/Zsh/arith.yo, Doc/Zsh/compctl.yo,
Doc/Zsh/compsys.yo, Doc/Zsh/compwid.yo, Doc/Zsh/expn.yo,
Doc/Zsh/guide.yo, Doc/Zsh/jobs.yo, Doc/Zsh/metafaq.yo,
Doc/Zsh/mod_compctl.yo, Doc/Zsh/mod_zftp.yo, Doc/Zsh/params.yo,
Doc/Zsh/redirect.yo, Doc/Zsh/zftpsys.yo, Doc/Zsh/zle.yo,
Doc/zman.yo, Doc/ztexi.yo, Util/zsh-development-guide:
Formatting of unfilled text now handled by three distinct
macros example(), indent(), nofill(); compctl description node
is now called `Programmable Completion Using compctl' to
distinguish it from widget completion; don't put chapters on
separate pages because many are too short.
* Wayne: 6599: Src/Zle/zle_tricky.c: unitialised variable warnings
from gcc
1999-06-11 Peter Stephenson <pws@ibmth.difi.unipi.it>
* pws: 6598: Doc/Zsh/zftpsys.yo, Functions/Zftp/zfinit,
Functions/Zftp/zfgoto, Functions/Zftp/zfmark,
Functions/Zftp/zftp_chpwd, Completion/Builtins/_zftp:
add zfmark and zfgoto implementing bookmarks (including use
ncftp bookmarks) for zftp function suite; autoload functions
from zfinit; patcomps -> _patcomps.
* pws: 6596: Doc/Zsh/arith.yo: update on size of integers and
increase in clarity of presentation
* Sven: 6589: Completion/Core/_path_files: use :h and :t instead
of pattern matching
* Sven: 6587, 6588: Src/Zle/zle_misc.c, Doc/Zsh/options.yo: < and
> shouldn't remove a suffix, but | does
* Sven: 6586: Src/exec.c, Src/lex.c, Src/loop.c: don't modify
struct cmd to insert cmd args and flags, always pass those
separately
1999-06-10 Peter Stephenson <pws@ibmth.difi.unipi.it>
* Andrej: 6581: Doc/Makefile: dependencies for manuals
* Sven: 6579: Src/exec.c: old hack of storing shell function
args in struct cmd doesn't work any more
* Sven: 6577: Src/exec.c, Src/text.c, Src/utils.c: expunge
simplifyright(), which appears no longer to have an effect
* pws: 6575: Doc/Zsh/mod_mapfile.yo: avoid mapping long files
* pws: 6571: Src/Builtins/rlimits.c: use appropriate printf()
routine in printulimit() instead of just casting to long
* pws: 6570: configure.in, INSTALL: some systems have
sizeof(off_t) or sizeof(ino_t) == 8 and sizeof(long) == 4 even
without explicit enabling, so check and if so use the
--enable-lfs code.
* pws/Sven: 6567, 6568: Completion/Base/_vars: complete assoc
array keys
* pws: 6566: Src/params.c: junk testhash assoc array
* pws: 6563: sporadic: minor changes affecting casts, sizes
of integers, unused variables; add index for subscripts in
manual
* Bart: email: Src/zsh.h: alternative definition for zulong
* Bart: 6558: Src/builtins.c: printing functions with the
UNALIASED flag
* Sven: 6557: Doc/zsh/compsys.yo: a few typos
1999-06-09 Peter Stephenson <pws@ibmth.difi.unipi.it>
* Andrej: 6556: aczsh.m4: don't disable setting variables
for --enable-lfs just because some other variables were set
* Sven: 6554: Src/Zle/zle_tricky.c: display bugs with compadd -X:
newline missing and display unnecessarily altered
* pws: 6552: configure.in, aczsh.m4, acconfig.h, Src/zsh.h:
define separate unsigned 64-bit integer; try __int64_t and
__uint64_t.
* Sven: 6548: Src/Zle/zle_tricky.c: fix `compctl -l'
* Andrej: 6544: configure displays info on function installation
* Sven: 6542: Src/builtin.c, Src/exec.c, Src/hist.c, Src/init.c,
Src/lex.c: when not using interactive history, don't allocate
history at all
* Andrej: 6541: configure.in: add missing `test'
* Sven: 6535: Completion/core/_normal: an eval was unnecessary
* Bart: 6534: Completion/Core/compdump, Completion/Core/compinit,
Doc/Zsh/builtins.yo, Src/builtin.c, Src/exec.c, Src/zsh.h:
autoload -U defines functions which don't use expand aliases
during loading; used in new completion code to protect
functions.
* Sven: 6527: Src/builtin.c, Src/cond.c, Src/exec.c, Src/glob.c,
Src/hashtable.c, Src/init.c, Src/jobs.c, Src/lex.c,
Src/linklist.c, Src/loop.c, Src/math.c, Src/mem.c, Src/params.c,
Src/parse.c, Src/signals.c, Src/text.c, Src/utils.c, Src/zsh.h:
various sets of patches:
- make zhalloc() use a pointer to the first free heap
- make zsh-mem allocators keep some memory back when freeing
- reduce the amount of allocation work done in the exec.c
execution hierarchy
- don't duplicate execution trees any more than necessary, e.g.
execute functions from stored tree
* pws: Etc/MACHINES: Danek Duvall reports --enable-dynamic OK
on Solaris 2.7, despite previous reports; Sven says on Digital
UNIX 4.0, you need special DLLD and LDFLAGS.
1999-06-08 Peter Stephenson <pws@ibmth.difi.unipi.it>
* pws: 6525: Src/lex.c (gettokstr): allow parentheses after
first character in command word
* Tanaka Akira: 6522: configure.in: help string for --enable-fndir
had wrong default directory
* pws: 6520: configure.in: --enable-fndir might be yes,
so turn it into ${datadir}/zsh/functions
* 3.1.5-pws-21 made available
* Sven: 6515: Src/Zle/zle_tricky.c: fix memory problems with 6492
@ -38,7 +215,7 @@
`compctl -h' takes a command line from inside a quoted string;
the compctl tests q[s], q[d], q[b] are true if we are in single,
double, back quotes; compset -q tests quotes and splits the word,
affecting $PREFIX, $SUFFX and setting $IQPREFIX, $IQSUFFIX for
affecting $PREFIX, $SUFFIX and setting $IQPREFIX, $IQSUFFIX for
the bits which will now be ignored.
* pws: 6490: Completion/Core/compinit: nounset workaround

View file

@ -16,4 +16,6 @@ ls="$RBUFFER[${#SUFFIX}+1,-1]"
n=${(M)#ls##\"#}
q=${(M)lp%%\"#}
[[ n -gt 0 ]] && suf=''
_parameters -s "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/'

View file

@ -1,3 +1,20 @@
#compdef getopts read unset vared
compgen -v
# This will handle completion of keys of associative arrays, e.g. at
# `vared compconfig[<TAB>'. However, in this version the [ must be
# added by hand.
if [[ $PREFIX = *\[* ]]; then
local var=${PREFIX%%\[*}
local elt="${PREFIX#*\]}${SUFFIX%\]}"
local addclose
compset -p $(( ${#var} + 1 ))
if ! compset -S \]; then
addclose=(-S ']')
fi
if [[ ${(tP)var} = assoc* ]]; then
compadd $addclose - ${(kP)var}
fi
else
compgen -v
fi

View file

@ -1,3 +1,3 @@
#compdef fg jobs
#compdef disown fg jobs
compgen -j -P '%'

View file

@ -9,7 +9,8 @@ else
compgen -P '%' -j && ret=0
list=("$(ps 2>/dev/null)")
compgen -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' && ret=0
compgen -y '$list' -s '${${${(f)"$(ps 2>/dev/null)"}[2,-1]## #}%% *}' &&
ret=0
return ret
fi

View file

@ -1,3 +1,3 @@
#compdef limit unlimit
compgen -k "(${(j: :)${(f)$(limit)}%% *})"
compgen -s '${${(f)"$(limit)"}%% *}'

View file

@ -4,6 +4,6 @@ local list ret=1
compgen -P '%' -j && ret=0
list=("$(ps 2>/dev/null)")
compgen -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' && ret=0
compgen -y '$list' -s '${${${(f)"$(ps 2>/dev/null)"}[2,-1]## #}%% *}' && ret=0
return ret

View file

@ -43,6 +43,19 @@ case $subcom in
compgen -k hosts
;;
*(goto|mark))
# complete bookmarks. First decide if ncftp mode is go.
if [[ $words[2] = -*n* ]]; then
if [[ -f ~/.ncftp/bookmarks ]]; then
compadd - $(awk -F, 'NR > 2 { print $1 }' ~/.ncftp/bookmarks)
fi
else
if [[ -f ${ZFTP_BMFILE:=${ZDOTDIR:-$HOME}/.zfbkmarks} ]]; then
compadd - $(awk '{print $1}' $ZFTP_BMFILE)
fi
fi
;;
*)
# dunno... try ordinary completion after all.
unset _compskip

View file

@ -20,7 +20,7 @@ elif [[ "$command" == */* ]]; then
cmd2="${command:t}"
else
cmd1="$command"
eval cmd2=$(whence -p $command)
cmd2=$(whence -p $command)
fi
# See if there are any matching pattern completions.

View file

@ -231,7 +231,7 @@ for prepath in "$prepaths[@]"; do
# See which of them match what's on the line.
tmp2=("$tmp1[@]")
compadd -D tmp1 "$ignore[@]" - "${(@)tmp1##*/}"
compadd -D tmp1 "$ignore[@]" - "${(@)tmp1:t}"
# If no file matches, save the expanded path and continue with
# the outer loop.
@ -240,7 +240,7 @@ for prepath in "$prepaths[@]"; do
if [[ "$tmp2[1]" = */* ]]; then
tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
if [[ "$tmp2[1]" = */* ]]; then
exppaths=( "$exppaths[@]" ${^tmp2%/*}/${tpre}${tsuf} )
exppaths=( "$exppaths[@]" ${^tmp2:h}/${tpre}${tsuf} )
else
exppaths=( "$exppaths[@]" ${tpre}${tsuf} )
fi

View file

@ -74,7 +74,7 @@ done))
# print them out: about five to a line looks neat
while (( $#_d_als )); do
print -n autoload
print -n autoload -U
for (( _i = 0; _i < 5; _i++ )); do
if (( $#_d_als )); then
print -n " $_d_als[1]"

View file

@ -194,7 +194,7 @@ compdef() {
# and probably do autoloading.
func="$1"
[[ -n "$autol" ]] && autoload "$func"
[[ -n "$autol" ]] && autoload -U "$func"
shift
case "$type" in
@ -363,7 +363,7 @@ if [[ -z "$_i_done" ]]; then
fi
;;
(\#autoload)
autoload ${_i_file:t}
autoload -U ${_i_file:t}
;;
esac
done

View file

@ -55,7 +55,14 @@ install.fns:
$(sdir_top)/mkinstalldirs $(fndir) || exit 1; \
for file in $(FUNCTIONS_INSTALL); do \
if test -f $$file; then \
$(INSTALL_DATA) $$file $(fndir) || exit 1; \
if test x$(FUNCTIONS_SUBDIRS) != x -a \
x$(FUNCTIONS_SUBDIRS) != xno; then \
subdir="`echo $$file | sed -e 's%/.*%%'`"; \
$(sdir_top)/mkinstalldirs $(fndir)/$$subdir || exit 1; \
$(INSTALL_DATA) $$file $(fndir)/$$subdir || exit 1; \
else \
$(INSTALL_DATA) $$file $(fndir) || exit 1; \
fi; \
fi; \
done; \
fi; \
@ -65,7 +72,12 @@ uninstall.fns:
if test x$(fndir) != x && test x$(fndir) != xno; then \
for file in $(FUNCTIONS_INSTALL); do \
if test -f $$file; then \
rm -f "$(fndir)/`echo $$file | sed -e 's%^.*/%%'`"; \
if test x$(FUNCTIONS_SUBDIRS) != x -a \
x$(FUNCTIONS_SUBDIRS) != xno; then \
rm -f $(fndir)/$$file; \
else \
rm -f "$(fndir)/`echo $$file | sed -e 's%^.*/%%'`"; \
fi; \
fi; \
done; \
fi; \

View file

@ -68,6 +68,7 @@ INSTALL_DATA = @INSTALL_DATA@
# variables used in determining what to install
FUNCTIONS_INSTALL = @FUNCTIONS_INSTALL@
FUNCTIONS_SUBDIRS = @FUNCTIONS_SUBDIRS@
# flags passed to recursive makes in subdirectories
MAKEDEFS = \

View file

@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the
# `=' signs.
VERSION=3.1.5-pws-21
VERSION_DATE='June 6, 1999'
VERSION=3.1.5-pws-22
VERSION_DATE='June 13, 1999'

View file

@ -57,7 +57,7 @@ Zsh/filelist.yo Zsh/files.yo Zsh/func.yo Zsh/grammar.yo Zsh/guide.yo \
Zsh/index.yo Zsh/intro.yo Zsh/invoke.yo Zsh/jobs.yo Zsh/metafaq.yo \
Zsh/modules.yo Zsh/mod_cap.yo Zsh/compwid.yo Zsh/compsys.yo \
Zsh/mod_clone.yo Zsh/mod_comp1.yo Zsh/mod_compctl.yo Zsh/mod_deltochar.yo \
Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_stat.yo \
Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_mapfile.yo Zsh/mod_stat.yo \
Zsh/mod_zle.yo Zsh/options.yo \
Zsh/params.yo Zsh/prompt.yo Zsh/redirect.yo Zsh/restricted.yo \
Zsh/seealso.yo Zsh/zftpsys.yo Zsh/zle.yo
@ -132,8 +132,8 @@ zshmisc.1: Zsh/grammar.yo Zsh/redirect.yo Zsh/exec.yo Zsh/func.yo \
zshmodules.1: Zsh/modules.yo Zsh/mod_cap.yo Zsh/mod_clone.yo \
Zsh/mod_comp1.yo Zsh/mod_compctl.yo Zsh/mod_deltochar.yo \
Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_sched.yo \
Zsh/mod_stat.yo Zsh/mod_zftp.yo Zsh/mod_zle.yo
Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_mapfile.yo \
Zsh/mod_sched.yo Zsh/mod_stat.yo Zsh/mod_zftp.yo Zsh/mod_zle.yo
zshoptions.1: Zsh/options.yo

View file

@ -5,16 +5,42 @@ sect(Arithmetic Evaluation)
)\
cindex(arithmetic evaluation)
cindex(evaluation, arithmetic)
An ability to perform integer arithmetic is provided with the builtin tt(let).
findex(let, use of)
Evaluations are performed using em(long) arithmetic.
The shell can perform integer arithmetic, either using the builtin tt(let),
or via a substitution of the form tt($((...))). Usually arithmetic is
performed with em(long) integers; however, on certain systems where a
em(long) has 4-byte precision, zsh may be compiled to use 8-byte precision
instead. This can be tested, for example, by giving the command
`tt(print - $(( 12345678901 )))'; if the number appears unchanged, the
precision is at least 8 bytes.
The tt(let) builtin command takes arithmetic expressions as arguments; each
is evaluated separately. Since many of the arithmetic operators, as well
as spaces, require quoting, an alternative form is provided: for any
command which begins with a `tt(LPAR()LPAR())', all the characters until a
matching `tt(RPAR()RPAR())' are treated as a quoted expression and
arithmetic expansion performed as for an argument of tt(let). More
precisely, `tt(LPAR()LPAR())var(...)tt(RPAR()RPAR())' is equivalent to
`tt(let ")var(...)tt(")'. For example, the following statement
example((( val = 2 + 1 )))
is equivalent to
example(let "val = 2 + 1")
both assigning the value 3 to the shell variable tt(foo) and returning a
zero status.
cindex(bases, in arithmetic)
Numbers can be in bases other than 10.
A leading `tt(0x)' or `tt(0X)' denotes hexadecimal.
Otherwise, numbers are of the form `[var(base)tt(#)]var(n)',
Numbers may also be of the form `var(base)tt(#)var(n)',
where var(base) is a decimal number between two and thirty-six
representing the arithmetic base and var(n)
is a number in that base (for example, `tt(16#ff)' is 255 in hexadecimal).
If var(base) is omitted
then base 10 is used. For backwards compatibility the form
The var(base)tt(#) may also be omitted, in which case
base 10 is used. For backwards compatibility the form
`tt([)var(base)tt(])var(n)' is also accepted.
cindex(arithmetic operators)
@ -50,10 +76,17 @@ and XOR operators.
An expression of the form `tt(#\)var(x)' where var(x) is any character
gives the ascii value of this character and an expression of the form
`tt(#)var(foo)' gives the ascii value of the first character of the value
of the parameter var(foo). Note that this is different from the expression
`tt($#)var(foo)', a standard parameter substitution which gives the length
of the parameter var(foo).
Named parameters and subscripted arrays can be referenced by name within an
arithmetic expression without using the parameter expansion syntax.
arithmetic expression without using the parameter expansion syntax. For
example,
example((((val2 = val1 * 2))))
assigns twice the value of tt($val1) to the parameter named tt(val2).
An internal integer representation of a named parameter
can be specified with the tt(integer) builtin.
@ -63,11 +96,3 @@ findex(integer, use of)
Arithmetic evaluation is performed on the value of each
assignment to a named parameter declared integer
in this manner.
Since many of the arithmetic operators require
quoting, an alternative form of the tt(let) command is provided.
For any command which begins with a tt(LPAR()LPAR()),
all the characters until a matching tt(RPAR()RPAR())
are treated as a quoted expression.
More precisely, `tt(LPAR()LPAR()) ... tt(RPAR()RPAR())'
is equivalent to `tt(let ")...tt(")'.

View file

@ -981,12 +981,13 @@ shown.
)
item(tt(-f))(
The names refer to functions rather than parameters. No assignments
can be made, and the only other valid flags are tt(-t)
and tt(-u). The flag tt(-t) turns on execution tracing for this
function. The flag tt(-u) causes this function to be marked
for autoloading. The tt(fpath) parameter will be searched to find the
function definition when the function is first referenced; see
noderef(Functions).
can be made, and the only other valid flags are tt(-t), tt(-u) and
tt(-U). The flag tt(-t) turns on execution tracing for this
function. The tt(-u) and tt(-U) flags cause the function to be
marked for autoloading; tt(-U) also causes alias expansion to be
suppressed when the function is loaded. The tt(fpath) parameter
will be searched to find the function definition when the function
is first referenced; see noderef(Functions).
)
item(tt(-i))(
Use an internal integer representation. If var(n) is nonzero it

View file

@ -1,5 +1,5 @@
texinode(Programmable Completion)(Completion Widgets)(Zsh Line Editor)(Top)
chapter(Programmable Completion)
texinode(Programmable Completion Using compctl)(Completion Widgets)(Zsh Line Editor)(Top)
chapter(Programmable Completion Using compctl)
cindex(completion, programmable)
cindex(completion, controlling)
findex(compctl)
@ -33,7 +33,7 @@ menu(Matching Control)
menu(Example)
endmenu()
texinode(Command Flags)(Option Flags)()(Programmable Completion)
texinode(Command Flags)(Option Flags)()(Programmable Completion Using compctl)
sect(Command Flags)
Completion of the arguments of a command may be different for each
command or may use the default. The behavior when completing the
@ -56,7 +56,7 @@ from immediate expansion; for example the command string tt('foo*')
arranges for completion of the words of any command beginning with
tt(foo). When completion is attempted, all pattern completions are
tried in the reverse order of their definition until one matches. By
default, completion then procedes as normal, i.e. the shell will try to
default, completion then proceeds as normal, i.e. the shell will try to
generate more matches for the specific command on the command line; this
can be overridden by including tt(-tn) in the flags for the pattern
completion.
@ -88,9 +88,7 @@ the standard behavior for all commands. For example, if your access
to the user database is too slow and/or it contains too many users (so
that completion after `tt(~)' is too slow to be usable), you can use
indent(
tt(compctl -T -x 's[~] C[0,[^/]#]' -k friends -S/ -tn)
)
example(compctl -T -x 's[~] C[0,[^/]#]' -k friends -S/ -tn)
to complete the strings in the array tt(friends) after a `tt(~)'.
The tt(C[...]) argument is necessary so that this form of ~-completion is
@ -118,7 +116,7 @@ options specified by the tt(-D) flag.
The form with tt(-M) as the first and only option defines global
matching specifications, as described below in noderef(Matching Control).
texinode(Option Flags)(Alternative Completion)(Command Flags)(Programmable Completion)
texinode(Option Flags)(Alternative Completion)(Command Flags)(Programmable Completion Using compctl)
sect(Option Flags)
startlist()
list([ tt(-fcFBdeaRGovNAIOPZEnbjrzu/) ])
@ -256,10 +254,8 @@ of space- or comma-separated values in parentheses, in which any
delimiter may be escaped with a backslash; in this case the argument
should be quoted. For example,
indent(
nofill(tt(compctl -k "(cputime filesize datasize stacksize
coredumpsize resident descriptors)" limit))
)
example(compctl -k "(cputime filesize datasize stacksize
coredumpsize resident descriptors)" limit)
)
item(tt(-g) var(globstring))(
The var(globstring) is expanded using filename globbing; it should be
@ -281,7 +277,7 @@ resulting files. Note that tt(-g) is faster for filenames.
)
item(tt(-K) var(function))(
Call the given function to get the completions. Unless the name
starts with an underscode, the function is
starts with an underscore, the function is
passed two arguments: the prefix and the suffix of the word on which
completion is to be attempted, in other words those characters before
the cursor position, and those from the cursor position onwards. The
@ -293,10 +289,8 @@ should not be made local to the function. From such a function the
command line can be accessed with the tt(-c) and tt(-l) flags to
the tt(read) builtin. For example,
indent(
nofill(tt(function whoson { reply=(`users`); }
compctl -K whoson talk))
)
example(function whoson { reply=(`users`); }
compctl -K whoson talk)
completes only logged-on users after `tt(talk)'. Note that `tt(whoson)' must
return an array, so `tt(reply=`users`)' would be incorrect.
@ -315,9 +309,7 @@ zero or negative the whole history is searched and if var(pattern) is
the empty string all words are taken (as with `tt(*)'). A typical
use is
indent(
tt(compctl -D -f PLUS() -H 0 '')
)
example(compctl -D -f PLUS() -H 0 '')
which forces completion to look back in the history list for a word if
no filename matches.
@ -345,9 +337,7 @@ The var(prefix) is inserted just before the completed string; any
initial part already typed will be completed and the whole var(prefix)
ignored for completion purposes. For example,
indent(
tt(compctl -j -P "%" kill)
)
example(compctl -j -P "%" kill)
inserts a `%' after the kill command and then completes job names.
)
@ -362,9 +352,7 @@ With directory var(file-prefix): for command, file, directory and
globbing completion (options tt(-c), tt(-f), tt(-/), tt(-g)), the file
prefix is implicitly added in front of the completion. For example,
indent(
tt(compctl -/ -W ~/Mail maildirs)
)
example(compctl -/ -W ~/Mail maildirs)
completes any subdirectories to any depth beneath the directory
tt(~/Mail), although that prefix does not appear on the command line.
@ -393,9 +381,7 @@ option. If the var(cmd) string is empty the first word in the range
is instead taken as the command name, and command name completion
performed on the first word in the range. For example,
indent(
tt(compctl -x 'r[-exec,;]' -l '' -- find)
)
example(compctl -x 'r[-exec,;]' -l '' -- find)
completes arguments between `tt(-exec)' and the following `tt(;)' (or the end
of the command line if there is no such string) as if they were
@ -419,7 +405,7 @@ tt(-K) option) which can examine the word components passed to it
use its own criteria to decide what matches. If there is no
completion, the original word is retained. Since the produced
possible completions seldom seldom have interesting common prefixes
and suffixes, menucompletion is started immediatly if tt(AUTO_MENU) is
and suffixes, menucompletion is started immediately if tt(AUTO_MENU) is
set and this flag is used.
)
item(tt(-y) var(func-or-var))(
@ -499,9 +485,7 @@ group name are stored in that group.
This can be useful with non-exclusive alternative completions. For
example, in
indent(
tt(compctl -f -J files -t+ + -v -J variables foo)
)
example(compctl -f -J files -t+ + -v -J variables foo)
both files and variables are possible completions, as the tt(-t+) forces
both sets of alternatives before and after the tt(+) to be considered at
@ -521,7 +505,7 @@ of the var(match-spec) string is described below in noderef(Matching Control).
)
enditem()
texinode(Alternative Completion)(Extended Completion)(Option Flags)(Programmable Completion)
texinode(Alternative Completion)(Extended Completion)(Option Flags)(Programmable Completion Using compctl)
sect(Alternative Completion)
startlist()
list(tt(compctl) [ tt(-CDT) ] var(options) tt(PLUS()) var(options) [ tt(PLUS()) ... ] \
@ -536,7 +520,7 @@ up to that point, default completion is tried.
If the list of flags contains a tt(-t) with a tt(PLUS()) character, the next
list of flags is used even if the current list produced matches.
texinode(Extended Completion)(Matching Control)(Alternative Completion)(Programmable Completion)
texinode(Extended Completion)(Matching Control)(Alternative Completion)(Programmable Completion Using compctl)
sect(Extended Completion)
startlist()
list(nofill(tt(compctl) [ tt(-CDT) ] var(options) \
@ -612,9 +596,7 @@ considered part of the completion, but the rest will. var(index) may
be negative to count from the end: in most cases, var(index) will be
1 or -1. For example,
indent(
tt(compctl -s '`users`' -x 'n[1,@]' -k hosts -- talk)
)
example(compctl -s '`users`' -x 'n[1,@]' -k hosts -- talk)
will usually complete usernames, but if you insert an tt(@) after the
name, names from the array var(hosts) (assumed to contain hostnames,
@ -648,7 +630,7 @@ completion is done in backticks and var(str) starts with a `b'.
)
enditem()
texinode(Matching Control)(Example)(Extended Completion)(Programmable Completion)
texinode(Matching Control)(Example)(Extended Completion)(Programmable Completion Using compctl)
sect(Matching Control)
It is possible by use of the tt(-M) var(spec) flag to specify how the
@ -732,10 +714,10 @@ following alters the matching rules so that the prefix tt(no) and any
underscore are ignored when trying to match the trial completions
generated and uppercase letters on the line match the corresponding
lowercase letters in the words:
indent(
nofill(tt(compctl -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-o setopt unsetopt))
)
example(compctl -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-o setopt unsetopt)
The first part says that the pattern `tt([nN][oO])' at the beginning
(the empty anchor before the pipe symbol) of the string on the
line matches the empty string in the list of words generated by
@ -752,14 +734,13 @@ The second example makes completion case insensitive. By using
tt(compctl) with the tt(-M) option alone this applies to every
completion. This is just the same as in the tt(setopt) example, except
here we wish to retain the characters in the list of completions:
indent(
tt(compctl -M 'm:{a-z}={A-Z}')
)
example(compctl -M 'm:{a-z}={A-Z}')
This makes lowercase letters match their uppercase counterparts.
To make uppercase letters match the lowercase forms as well:
indent(
tt(compctl -M 'm:{a-zA-Z}={A-Za-z}')
)
example(compctl -M 'm:{a-zA-Z}={A-Za-z}')
A nice example for the use of tt(*) patterns is partial word
completion. Sometimes you would like to make strings like tt(c.s.u)
@ -770,10 +751,10 @@ however, that the case where each part of the word, i.e. tt(comp),
tt(source) and tt(unix) in this example, is to be completed separately
is a different problem to be solved by extended completion. The
example can be handled by:
indent(
nofill(tt(compctl -M 'r:|.=* r:|=*' \
-k '(comp.sources.unix comp.sources.misc ...)' ngroups))
)
example(compctl -M 'r:|.=* r:|=*' \
-k '(comp.sources.unix comp.sources.misc ...)' ngroups)
The first specification says that tt(lpat) is the empty string, while
tt(anchor) is a dot; tt(tpat) is tt(*), so this can match anything
except for the `tt(.)' from the anchor in
@ -795,9 +776,9 @@ empty string at the end of the string on the line matches any characters
at the end of the trial completion.
More generally, the specification
indent(
tt(compctl -M 'r:|[.,_-]=* r:|=*')
)
example(compctl -M 'r:|[.,_-]=* r:|=*')
allows one to complete words with abbreviations before any of the
characters in the square brackets in any completion. For example, to
complete tt(veryverylongfile.c) rather than tt(veryverylongheader.h)
@ -817,9 +798,9 @@ the string on the command line as a substring, not just at the
beginning. Since this might produce more matches than we want,
we arrange for it to be tried only if the matchers described above don't
produce any matches:
indent(
tt(compctl -M 'r:|[.,_-]=* r:|=*' 'l:|=* r:|=*')
)
example(compctl -M 'r:|[.,_-]=* r:|=*' 'l:|=* r:|=*')
Here, if the string on the command line is tt(foo.bar), tt(compctl)
first tries matching tt(foo)var(anything)tt(.bar)var(anything), as
with the previous example. If that fails, the two descriptions in the
@ -828,13 +809,12 @@ and end of the string on the command line can match any set of
characters at the beginning or end of the trial completion, so it will
look for var(anything)tt(foo.bar)var(anything).
texinode(Example)()(Matching Control)(Programmable Completion)
texinode(Example)()(Matching Control)(Programmable Completion Using compctl)
sect(Example)
indent(
nofill(
tt(compctl -u -x 's[tt(PLUS())] c[-1,-f],s[-f+PLUS()]' \
-g '~/Mail/*(:t)' - 's[-f],c[-1,-f]' -f -- mail))
)
example(compctl -u -x 's[tt(PLUS())] c[-1,-f],s[-f+PLUS()]' \
-g '~/Mail/*(:t)' - 's[-f],c[-1,-f]' -f -- mail)
This is to be interpreted as follows:
If the current command is tt(mail), then

View file

@ -51,7 +51,7 @@ sect(Initialisation)
The script tt(compinstall) can be run by a user to set up the completion
system for use. It will usually insert code into tt(.zshrc), although if
that is not writeable it will save it in another file and tell you that
that is not writable it will save it in another file and tell you that
file's locations. Note that it is up to you to make sure that the lines
added to tt(.zshrc) are actually run; you may, for example, need to move
them to an earlier place in the file if tt(.zshrc) usually returns early.
@ -89,13 +89,13 @@ To speed up the running of tt(compinit), it can be made to produce a dumped
configuration which will be read in on future invocations. The easiest way
to do this is by adding the option tt(-d) whenever tt(compinit) is sourced.
In this case the dumped file will have the same name as the sourced file,
but with tt(.dump) appended to the end, or, if that is not writeable by the
but with tt(.dump) appended to the end, or, if that is not writable by the
user, the file tt(.zcompdump) in the same directory as the startup files
(i.e. tt($ZDOTDIR) or tt($HOME)); alternatively, an explicit file name can
be given following the tt(-d). On the next call to tt(compinit -d), the
dumped file will be read instead.
The other option accepted by tt(compinit) is tt(-f var(dir)), which gives
The other option accepted by tt(compinit) is tt(-f )var(dir), which gives
the directory in which tt(compinit) resides. If you source tt(compinit) by
its full pathname, and the option tt(FUNCTION_ARGZERO) is set, as it is by
default unless tt(zsh) is emulating tt(sh) or tt(ksh), this is unnecessary
@ -106,7 +106,7 @@ the completion functions (see below).
If the number of completion files changes, tt(compinit) will recognise this
and produce a new dump file. However, if the name of a function or the
arguments in the first line of a tt(#compdef) funcion (as described below)
arguments in the first line of a tt(#compdef) function (as described below)
change, it is easiest to delete the dump file by hand so that the next time
tt(compinit) will re-create it.
@ -153,7 +153,7 @@ var(pattern) (a standard globbing pattern). Note that only one
var(pattern) may be given.
)
item(tt(#compdef -k) var(style key-sequences...))(
This can be used bind special completion functions to the
This can be used to bind special completion functions to the
var(key-sequences). It creates a widget behaving like the builtin widget
var(style), which must be one of those that perform completion, namely
tt(complete-word), tt(delete-char-or-list), tt(expand-or-complete),
@ -252,9 +252,7 @@ set of functions to try is taken from the colon-separated list in the
configuration key tt(completer). For example, to use normal
completion and correction if that doesn't generate any matches:
indent(
nofill(tt(compconf completer=_complete:_correct))
)
example(compconf completer=_complete:_correct)
after sourcing tt(compinit). The default value for this configuration key
set up in tt(compinit) is `tt(_complete)', i.e. normally only ordinary
@ -355,9 +353,7 @@ counted. The resulting list of corrected and completed strings is then
presented to the user. The intended use of this completer function is to
try after the normal tt(_complete) completer by setting:
indent(
nofill(tt(compconf completer=_complete:_approximate))
)
example(compconf completer=_complete:_approximate)
This will give correcting completion if and only if
normal completion doesn't yield any possible completions. When
@ -379,9 +375,7 @@ If the value for this key contains a lower- or upper-case `tt(n)', the
completer function will take any numeric argument as the
maximum number of errors allowed. For example, with
indent(
nofill(tt(compconf approximate_accept=2n))
)
example(compconf approximate_accept=2n)
two errors will be allowed if no numeric argument is given. However,
with a numeric argument of six (as in `tt(ESC-6 TAB)'), up to six
@ -443,10 +437,8 @@ configuration parameters beginning tt(correct_) are used.
For example, with:
indent(tt(
nofill(compconf completer=_complete:_correct:_approximate)
nofill(compconf correct_accept='2n!' approximate_accept=3n))
)
example(compconf completer=_complete:_correct:_approximate
compconf correct_accept='2n!' approximate_accept=3n)
correction will accept up to two errors. If a numeric argument is
given, correction will not be performed, but correcting completion will be,
@ -464,7 +456,7 @@ generated by the tt(_correct) completer -- and probably more.
item(tt(_match))(
This completer is intended to be used after the tt(_complete)
completer. It allows one to give patterns on the command line and
to complete all strings metching these patterns from the set of possible
to complete all strings matching these patterns from the set of possible
completions for the context the cursor is in, without having to set
the tt(GLOB_COMPLETE) option.
@ -498,9 +490,7 @@ non-empty string it should be an expression usable inside a `tt($((...)))'
arithmetical expression. In this case, expansion of substitutions will
be done if the expression evaluates to `tt(1)'. For example, with
indent(
nofill(tt(compconf expand_substitute='NUMERIC != 1'))
)
example(compconf expand_substitute='NUMERIC != 1')
substitution will be performed only if given an explicit numeric
argument other than `tt(1)', as by typing `tt(ESC 2 TAB)'.
@ -556,9 +546,7 @@ should be set to an expression usable inside a `tt($((...)))'
arithmetical expression. In this case, delaying will be done if the
expression evaluates to `tt(1)'. For example, with
indent(
nofill(tt(compconf list_condition='NUMERIC != 1'))
)
example(compconf list_condition='NUMERIC != 1')
delaying will be done only if given an explicit numeric argument
other than `tt(1)'.
@ -614,6 +602,7 @@ continues with the existing list of completions. If this key is set to
tt(never), however, a new completion is started if the old list was
generated by a different completion command (the behaviour without the
tt(_oldlist) completer).
For example, suppose you type tt(^Xc) to generate a list of corrections,
and menu completion is started in one of the usual ways. Usually, typing
tt(TAB) at this point would start trying to complete the line as it now
@ -704,7 +693,7 @@ over which filenames should be ignored as done by the tt(fignore)
parameter in normal completion.
The function tt(_files) calls tt(_path_files) with all the arguments
it was passed and, if that generated no matches, call tt(_path_files) again
it was passed and, if that generated no matches, calls tt(_path_files) again
without any tt(-g) or tt(-/) option, thus generating all filenames.
These functions also accept the `tt(-J)', `tt(-V)', `tt(-X)', `tt(-P)',
@ -764,11 +753,9 @@ not start with a square bracket or parenthesis, it should be the name of a
command (probably with arguments) that should be invoked to complete
after the equal sign. Example:
indent(
nofill(tt(_long_options '*\*' '(yes no)' \))
nofill(tt( '*=FILE*' '_files' \))
nofill(tt( '*=DIR*' '_files -/'))
)
example(_long_options '*\*' '(yes no)' \
'*=FILE*' '_files' \
'*=DIR*' '_files -/')
Here, `tt(yes)' and `tt(no)' will be completed as the argument of
options whose description ends in a star, file names for options that

View file

@ -1,4 +1,4 @@
texinode(Completion Widgets)(Zsh Modules)(Programmable Completion)(Top)
texinode(Completion Widgets)(Zsh Modules)(Programmable Completion Using compctl)(Top)
chapter(Completion Widgets)
cindex(completion, widgets)
cindex(completion, programmable)
@ -10,9 +10,7 @@ ifzman(zmanref(zshzle))\
ifnzman(noderef(The zle Module))\
). For example,
indent(
nofill(tt(zle -C complete expand-or-complete completer))
)
example(zle -C complete expand-or-complete completer)
defines a widget named tt(complete). When this widget is bound to a key
using the tt(bindkey) builtin command defined in the tt(zle) module
@ -73,10 +71,8 @@ not considered part of the list of matches. Typically, a string is
transferred from the beginning of tt(PREFIX) to the end of tt(IPREFIX), for
example:
tt(indent(
nofill(IPREFIX=${PREFIX%%\=*}=)
nofill(PREFIX=${PREFIX#*=})
))
example(IPREFIX=${PREFIX%%\=*}=
PREFIX=${PREFIX#*=})
causes the part of the prefix up to and including the first equal sign not
to be treated as part of a matched string.
@ -182,9 +178,7 @@ item(tt(matcher))(
When completion is performed with a global match specification as defined
by
indent(
nofill(tt(compctl -M) var(spec1 ... specN ...))
)
indent(tt(compctl -M) var(spec1 ... specN ...))
this gives the number of the specification string currently in use.
In this case, matching is performed with each specification in turn.
@ -229,7 +223,7 @@ the tt(ALWAYS_LAST_PROMPT) option.
)
item(tt(insert))(
This controls the manner in which a match is inserted into the command
line. On entry to the widget fuction, if it is unset the command line is
line. On entry to the widget function, if it is unset the command line is
not to be changed; if set to tt(unambiguous), any prefix common to all
matches is to be inserted; if set to tt(menu) or tt(automenu) the usual
behaviour of the tt(MENU_COMPLETE) or tt(AUTO_MENU) options, respectively,
@ -262,7 +256,7 @@ item(tt(old_list))(
This is set to tt(yes) if there is still a valid list of completions
from a previous completion at the time the widget is invoked. This will
usually be the case if and only if the previous editing operation was a
completion widget or one of the builtin completion fuctions. If there is a
completion widget or one of the builtin completion functions. If there is a
valid list and it is also currently shown on the screen, the value of this
key is tt(shown).
@ -330,7 +324,7 @@ Generate matches according to the given var(flags). These can be any of
the normal option flags (not those for extended completion) supported by
the tt(compctl) builtin command (see
ifzman(zmanref(zshcompctl))\
ifnzman(noderef(Programmable Completion))\
ifnzman(noderef(Programmable Completion Using compctl))\
) except for the tt(-t) and tt(-l) flags. However, when using the tt(-K)
flag, the function given as argument to it cannot access the command
line with the tt(read) builtin command.
@ -339,7 +333,7 @@ The matches will be generated in the same way as if the completion code
generated them directly from a tt(compctl)-definition with the same
flags. The completion code will consider only those matches as
possible completions that match the prefix and suffix from the special
parameters desribed above. These strings will be compared with the
parameters described above. These strings will be compared with the
generated matches using the normal matching rules and any matching
specifications given with the tt(-M) flag to tt(compgen) and the
global matching specifications given via the tt(compctl -M )var(spec1 ...)
@ -366,9 +360,7 @@ non-zero if no matches were added.
The completion code breaks the string to complete into seven fields in
the order:
indent(
var(<ipre><apre><hpre><word><hsuf><asuf><isuf>)
)
indent(var(<ipre><apre><hpre><word><hsuf><asuf><isuf>))
The first field
is an ignored prefix taken from the command line, the contents of the
@ -620,20 +612,18 @@ testing and modification is performed as if it were not given.
)
item(tt(-q))(
If the cursor is currently inside single or double quotes, the word
currenly being completed is split in separate words at the spaces. The
currently being completed is split in separate words at the spaces. The
resulting words are stored in the tt(words) array, and tt(PREFIX),
tt(SUFFIX), tt(QIPREFIX), and tt(QISUFFIX) are modified to reflect the
word part that is completed.
)
enditem()
In all the above cases the return value is zero if the test succeded
In all the above cases the return value is zero if the test succeeded
and the parameters were modified and non-zero otherwise. This allows
one to use this builtin in tests such as:
indent(
tt(if compset -P '*\='; then ...)
)
example(if compset -P '*\='; then ...)
This forces anything up to and including the last equal sign to be
ignored by the completion code.
@ -685,21 +675,18 @@ sect(Examples)
The first step is to define the widget:
indent(nofill(
tt(zle -C complete complete-word complete-history)))
example(zle -C complete complete-word complete-history)
Then the widget can be bound to a key using the tt(bindkey) builtin
command:
indent(nofill(
tt(bindkey '^X\t' complete)))
example(bindkey '^X\t' complete)
After that the shell function tt(complete-history) will be invoked
after typing control-X and TAB. The function should then generate the
matches, e.g.:
indent(nofill(
tt(complete-history LPAR()RPAR() { compgen -H 0 '' })))
example(complete-history LPAR()RPAR() { compgen -H 0 '' })
This function will complete words from the history matching the
current word.

View file

@ -277,7 +277,8 @@ If tt(<) is used, then the file passed as an argument will
be a named pipe connected to the output of the var(list) process.
For example,
nofill(tt(paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR() | tee >LPAR())var(process1)tt(RPAR() >LPAR())var(process2)tt(RPAR() >/dev/null))
nofill(tt(paste <LPAR()cut -f1) var(file1)tt(RPAR() <LPAR()cut -f3) var(file2)tt(RPAR() |
tee >LPAR())var(process1)tt(RPAR() >LPAR())var(process2)tt(RPAR() >/dev/null))
cuts fields 1 and 3 from the files var(file1) and var(file2) respectively,
pastes the results together, and sends it to the processes
@ -427,9 +428,9 @@ the flags tt(M), tt(R), tt(B), tt(E) and tt(N) are not useful.
For example,
nofill(tt(foo="twinkle twinkle little star" sub="t*e" rep="spy")
tt(print ${foo//${~sub}/$rep})
tt(print ${(S)foo//${~sub}/$rep}))
example(foo="twinkle twinkle little star" sub="t*e" rep="spy"
print ${foo//${~sub}/$rep}
print ${(S)foo//${~sub}/$rep})
Here, the `tt(~)' ensures that the text of tt($sub) is treated as a
pattern rather than a plain string. In the first case, the longest
@ -728,7 +729,7 @@ account of whether the current value is a scalar or an array, whether the
whole substitution is in double quotes, and what flags are supplied to the
current level of substitution, just as if the nested substitution were the
outermost. The flags are not propagated up to enclosing
substitutions; the nested subsitution will return either a scalar or an
substitutions; the nested substitution will return either a scalar or an
array as determined by the flags, possibly adjusted for quoting. All the
following steps take place where applicable at all levels of substitution.
Note that, unless the `tt((P))' flag is present, the flags and any subscripts
@ -1221,11 +1222,11 @@ matching the pattern var(foo).
As a shorthand, `tt(**/)' is equivalent to `tt((*/)#)'.
Thus:
nofill(tt(ls (*/)#bar))
example(ls (*/)#bar)
or
nofill(tt(ls **/bar))
example(ls **/bar)
does a recursive directory search for files named `tt(bar)', not following
symbolic links. To follow links, use `tt(***/)'.
@ -1468,26 +1469,26 @@ name of any existing file can be followed by a modifier of the form
`tt((:..))' even if no actual filename generation is performed.
Thus:
nofill(tt(ls *(-/)))
example(ls *(-/))
lists all directories and symbolic links that point to directories,
and
nofill(tt(ls *(%W)))
example(ls *(%W))
lists all world-writable device files in the current directory, and
nofill(tt(ls *(W,X)))
example(ls *(W,X))
lists all files in the current directory that are
world-writable or world-executable, and
nofill(tt(echo /tmp/foo*(u0^@:t)))
example(echo /tmp/foo*(u0^@:t))
outputs the basename of all root-owned files beginning with the string
`tt(foo)' in tt(/tmp), ignoring symlinks, and
nofill(tt(ls *.*~(lex|parse).[ch](^D^l1)))
example(ls *.*~(lex|parse).[ch](^D^l1))
lists all files having a link count of one whose names contain a dot
(but not those starting with a dot, since tt(GLOB_DOTS) is explicitly

View file

@ -26,7 +26,7 @@ tt($ZDOTDIR/.zlogin) are read.
When a login shell exits, the files tt($ZDOTDIR/.zlogout) and then
tt(/etc/zlogout) are read. This happens with either an explicit exit
via the tt(exit) or tt(logout) commands, or an implict exit by reading
via the tt(exit) or tt(logout) commands, or an implicit exit by reading
end-of-file from the terminal. However, if the shell terminates due
to tt(exec)'ing another process, the logout files are not read.
These are also affected by the tt(RCS) and tt(GLOBAL_RCS) options.

View file

@ -5,7 +5,8 @@ sect(Functions)
)\
cindex(functions)
findex(function)
The tt(function) reserved word is used to define shell functions.
Shell functions are defined with the tt(function) reserved word or the
special syntax `var(funcname) tt(())'.
Shell functions are read in and stored internally.
Alias names are resolved when the function is read.
Functions are executed like commands with the arguments

View file

@ -203,6 +203,11 @@ Normally, only one var(word) is provided; multiple var(word)s
are usually only useful for setting traps.
The body of the function is the var(list) between
the tt({) and tt(}). See noderef(Functions).
If the option tt(SH_GLOB) is set for compatibility with other shells, then
whitespace may appear between between the left and right parentheses when
there is a single var(word); otherwise, the parentheses will be treated as
forming a globbing pattern in that case.
)
cindex(timing)
item(tt(time) [ var(pipeline) ])(

View file

@ -28,7 +28,7 @@ menu(Parameters)
menu(Options)
menu(Shell Builtin Commands)
menu(Zsh Line Editor)
menu(Programmable Completion)
menu(Programmable Completion Using compctl)
menu(Completion Widgets)
menu(Zsh Modules)
menu(Completion System)
@ -98,7 +98,7 @@ menu(Arguments)
menu(Completion)
menu(Miscellaneous)
Programmable Completion
Programmable Completion Using compctl
menu(Command Flags)
menu(Option Flags)

View file

@ -9,7 +9,7 @@ command, and assigns them small integer numbers.
When a job is started asynchronously with `tt(&)',
the shell prints a line which looks like:
nofill(tt([1] 1234))
example([1] 1234)
indicating that the job which was started asynchronously was job number
1 and had one (top-level) process, whose process ID was 1234.

View file

@ -12,7 +12,7 @@ cindex(author)
Zsh was originally written by Paul Falstad tt(<pf@zsh.org>).
Zsh is now maintained by the members of the zsh-workers mailing
list tt(<zsh-workers@sunsite.auc.dk>). The development is currently
coordinated by Andrew Main (Zefram) tt(<zefram@zsh.org>). The coordinator
coordinated by Peter Stephenson tt(<pws@zsh.org>). The coordinator
can be contacted at tt(<coordinator@zsh.org>), but matters relating to
the code should generally go to the mailing list.
texinode(Availability)(Mailing Lists)(Author)(Introduction)

View file

@ -3,7 +3,7 @@ sect(The compctl Module)
The tt(compctl) module makes available several builtin commands. tt(compctl),
is the standard way to control completions for ZLE. See
ifzman(zmanref(zshcompctl))\
ifnzman(noderef(Programmable Completion))\
ifnzman(noderef(Programmable Completion Using compctl))\
.
The other builtin commands can be used in user-defined completion widgets,
see

View file

@ -34,11 +34,13 @@ handled, zsh's internal memory management may be arbitrarily baroque. Thus
it should not automatically be assumed that use of tt(mapfile) represents a
gain in efficiency over use of other mechanisms. Note in particular that
the whole contents of the file will always reside physically in memory when
accessed (possibly multiple times, due to standard parameter subsitution
operations).
accessed (possibly multiple times, due to standard parameter substitution
operations). In particular, this means handling of sufficiently long files
(greater than the machine's swap space, or than the range of the pointer
type) will be incorrect.
No errors are printed or flagged for non-existent, unreadable, or
unwriteable files, as the parameter mechanism is too low in the shell
unwritable files, as the parameter mechanism is too low in the shell
execution hierarchy to make this convenient.
It is unfortunate that the mechanism for loading modules does not yet allow

View file

@ -80,7 +80,7 @@ will be deleted if the tt(zftp) module is unloaded.
For example,
nofill(tt(zftp params ftp.elsewhere.xx juser '?'))
example(zftp params ftp.elsewhere.xx juser '?')
will store the host tt(ftp.elsewhere.xx) and the user tt(juser) and
then prompt the user for the corresponding password.
@ -89,8 +89,8 @@ This command may also be used to set up a transfer which then takes
place completely in the background, freeing tt(zftp) for concurrent
foreground use. For example,
nofill(tt(zftp params ftp.soreeyes.ca bubble squeak))
nofill(tt(LPAR()zftp open; zftp get foo >bar; zftp close)tt(RPAR() &))
example(zftp params ftp.soreeyes.ca bubble squeak
(zftp open; zftp get foo >bar; zftp close) &)
--- here, the connection is restricted to a background subshell and
you are free to open a simultaneous connection in the foreground.
@ -110,7 +110,7 @@ supported on this system) is printed instead.
It is useful to put the code
nofill(tt([[ -n $ZFTP_HOST ]] && zftp test))
example([[ -n $ZFTP_HOST ]] && zftp test)
into the shell function tt(precmd) for testing the connection before
every prompt. However, tt(zftp) will call tt(test) at the start of any
@ -209,7 +209,7 @@ item(tt(mkdir) var(directory))(
Create a new directory var(directory) on the server.
)
item(tt(rmdir) var(directory))(
Delete the diretory var(directory) on the server.
Delete the directory var(directory) on the server.
)
item(tt(rename) var(old-name) var(new-name))(
Rename file var(old-name) to var(new-name) on the server.
@ -221,7 +221,7 @@ only need this if instructed by the server to use it.
item(tt(quote) var(args...))(
Send the raw FTP command sequence to the server. You should be
familiar with the FTP command set as defined in RFC959 before doing
this. Useful comands may include tt(STAT) and tt(HELP). Note also
this. Useful commands may include tt(STAT) and tt(HELP). Note also
the mechanism for returning messages as described for the variable
tt(ZFTP_VERBOSE) below, in particular that all messages from the
control connection are sent to standard error.
@ -335,7 +335,7 @@ digit reply code is defined by RFC959 to correspond to:
startitem()
item(1.)(
A positive prelimnary reply.
A positive preliminary reply.
)
item(2.)(
A positive completion reply.
@ -442,7 +442,7 @@ until the next call to tt(zftp). Other status changes in subshells
will not be reflected by changes to the variables (but should
be otherwise harmless).
On some operatings systems, the control connection is not valid after a
On some operating systems, the control connection is not valid after a
fork(), so that operations in subshells or on the left hand side of a
pipeline are not possible.

View file

@ -16,7 +16,7 @@ To assign an array value, use `tt(set -A) var(name) var(value) ...'.
findex(set, use of)
The value of a parameter may also be assigned by writing:
nofill(var(name)tt(=)var(value))
indent(var(name)tt(=)var(value))
If the integer attribute, tt(-i), is set for var(name), the var(value)
is subject to arithmetic evaluation. See noderef(Array Parameters)
@ -38,19 +38,19 @@ texinode(Array Parameters)(Positional Parameters)()(Parameters)
sect(Array Parameters)
The value of an array parameter may be assigned by writing:
nofill(var(name)tt(=LPAR())var(value) ...tt(RPAR()))
indent(var(name)tt(=LPAR())var(value) ...tt(RPAR()))
If no parameter var(name) exists, an ordinary array parameter is created.
Associative arrays must be declared first, by `tt(typeset -A) var(name)'.
When var(name) refers to an associative array, the parenthesized list is
interpreted as alternating keys and values:
nofill(var(name)tt(=LPAR())var(key) var(value) ...tt(RPAR()))
indent(var(name)tt(=LPAR())var(key) var(value) ...tt(RPAR()))
Every var(key) must have a var(value) in this case. To create an empty
array or associative array, use:
nofill(var(name)tt(=LPAR()RPAR()))
indent(var(name)tt(=LPAR()RPAR()))
Individual elements of an array may be selected using a
subscript. A subscript of the form `tt([)var(exp)tt(])'
@ -59,6 +59,7 @@ an arithmetic expression which will be subject to arithmetic
expansion as if it were surrounded by `tt($LPAR()LPAR())...tt(RPAR()RPAR())'.
The elements are numbered beginning with 1 unless the
tt(KSH_ARRAYS) option is set when they are numbered from zero.
cindex(subscripts)
pindex(KSH_ARRAYS, use of)
The same subscripting syntax is used for associative arrays,
@ -72,9 +73,8 @@ except when they appear within double quotes.
A subscript of the form `tt([)var(exp1)tt(,)var(exp2)tt(])'
selects all elements in the range var(exp1) to var(exp2),
inclusive.
(Associative arrays are unordered, and so do not support ranges.)
If one of the subscripts evaluates to a negative number,
inclusive. (Associative arrays are unordered, and so do not support
ranges.) If one of the subscripts evaluates to a negative number,
say tt(-)var(n), then the var(n)th element from the end
of the array is used. Thus `tt($foo[-3])' is the third element
from the end of the array tt(foo), and
@ -95,7 +95,7 @@ element or range is replaced by the expression on the right side. An
array (but not an associative array) may be created by assignment to a
range or element. Arrays do not nest, so assigning a parenthesized list
of values to an element or range changes the number of elements in the
array, shifting the other elements to accomodate the new values. (This
array, shifting the other elements to accommodate the new values. (This
is not supported for associative arrays.)
To delete an element of an ordinary array, assign `tt(LPAR()RPAR())' to
@ -180,7 +180,7 @@ values) any of the positions from 1 to var(n) that do not already have
values. Note that, because the positional parameters form an array, an
array assignment of the form `var(n)tt(=LPAR())var(value) ...tt(RPAR())' is
allowed, and has the effect of shifting all the values at positions greater
than var(n) by as many positions as necessary to accomodate the new values.
than var(n) by as many positions as necessary to accommodate the new values.
texinode(Local Parameters)(Parameters Set By The Shell)(Positional Parameters)(Parameters)
sect(Local Parameters)

View file

@ -107,7 +107,7 @@ The shell evaluates each redirection in terms of the
association at the time of evaluation.
For example:
nofill(... tt(1>)var(fname) tt(2>&1))
indent(... tt(1>)var(fname) tt(2>&1))
first associates file descriptor 1 with file var(fname).
It then associates file descriptor 2 with the file associated with file
@ -123,12 +123,12 @@ the shell opens the file descriptor as a pipe to a process that copies
its input to all the specified outputs, similar to bf(tee),
provided the tt(MULTIOS) option is set. Thus:
nofill(tt(date >foo >bar))
example(date >foo >bar)
writes the date to two files, named `tt(foo)' and `tt(bar)'.
Note that a pipe is an implicit redirection; thus
nofill(tt(date >foo | cat))
example(date >foo | cat)
writes the date to the file `tt(foo)', and also pipes it to cat.
@ -136,14 +136,14 @@ If the tt(MULTIOS)
option is set, the word after a redirection operator is also subjected
to filename generation (globbing). Thus
nofill(tt(: > *))
example(: > *)
will truncate all files in the current directory,
assuming there's at least one. (Without the tt(MULTIOS)
option, it would create an empty file called `tt(*)'.)
Similarly, you can do
nofill(tt(echo exit 0 >> *.sh))
example(echo exit 0 >> *.sh)
If the user tries to open a file descriptor for reading more than once,
the shell opens the file descriptor as a pipe to a process that copies
@ -151,17 +151,17 @@ all the specified inputs to its output in the order
specified, similar to bf(cat),
provided the tt(MULTIOS) option is set. Thus
nofill(tt(sort <foo <fubar))
example(sort <foo <fubar)
or even
nofill(tt(sort <f{oo,ubar}))
example(sort <f{oo,ubar})
is equivalent to `tt(cat foo fubar | sort)'.
Note that a pipe is an implicit redirection; thus
nofill(tt(cat bar | sort <foo))
example(cat bar | sort <foo)
is equivalent to `tt(cat bar foo | sort)' (note the order of the inputs).
@ -169,7 +169,7 @@ If the tt(MULTIOS) option is em(un)set,
each redirection replaces the previous redirection for that file descriptor.
However, all files redirected to are actually opened, so
nofill(tt(echo foo > bar > baz))
example(echo foo > bar > baz)
when tt(MULTIOS) is unset will truncate bar, and write `tt(foo)' into baz.
@ -178,6 +178,6 @@ and zero or more parameter assignments, but no command name,
the command named in the shell variable tt(READNULLCMD) is assumed.
(If tt(READNULLCMD) is empty or not set, `tt(cat)' is used.) Thus
nofill(tt(< file))
example(< file)
copies the contents of tt(file) to the standard output.

View file

@ -8,7 +8,7 @@ distribution as an interface to the tt(zftp) builtin command, allowing you
to perform FTP operations from the shell command line or within functions
or scripts. The interface is similar to a traditional FTP client (e.g. the
tt(ftp) command itself, see manref(ftp)(1)), but as it is entirely done
within the shell all the familar completion, editing and globbing features,
within the shell all the familiar completion, editing and globbing features,
and so on, are present, and macros are particularly simple to write as they
are just ordinary shell functions.
@ -45,21 +45,22 @@ You should make sure all the functions from the tt(Functions/Zftp)
directory of the source distribution are available; they all begin with the
two letters `tt(zf)'. They may already have been installed on your system;
otherwise, you will need to find them and copy them. The directory should
appear as one of the elements of the tt($fpath) array, and the functions
should be autoloaded. Finally, to initialise the use of the system you
need to call the tt(zfinit) function. The following code in your
tt(.zshrc) will arrange for this; assume the functions are stored in the
directory tt(~/myfns):
appear as one of the elements of the tt($fpath) array (this should already
be the case if they were installed), and at least the function tt(zfinit)
should be autoloaded; it will autoload the rest. Finally, to initialise
the use of the system you need to call the tt(zfinit) function. The
following code in your tt(.zshrc) will arrange for this; assume the
functions are stored in the directory tt(~/myfns):
tt(indent(
nofill(fpath=(~/myfns $fpath))
nofill(autoload ~/myfns/zf*(:t))
nofill(zfinit)
))
example(fpath=(~/myfns $fpath)
autoload zfinit
zfinit)
Note that tt(zfinit) assumes you are using the tt(zmodload) method to
load the tt(zftp) command. If it is already built into the shell, change
tt(zfinit) to tt(zfinit -n).
tt(zfinit) to tt(zfinit -n). It is helpful (though not essential) if the
call to tt(zfinit) appears after any code to initialise the new completion
system, else unnecessary tt(compctl) commands will be given.
texinode(Zftp Functions)(Miscellaneous Features)(Installation)(Zftp Function System)
sect(Functions)
@ -115,7 +116,7 @@ have many of the features of the shell builtin tt(cd).
In the first form with var(dir) present, change to the directory var(dir).
The command `tt(zfcd ..)' is treated specially, so is guaranteed to work on
non-UNIX servers (note this is handled internall by tt(zftp)). If var(dir)
non-UNIX servers (note this is handled internally by tt(zftp)). If var(dir)
is omitted, has the effect of `tt(zfcd ~)'.
The second form changes to the directory previously current.
@ -274,13 +275,48 @@ then tt(zfpcp) will retry using the second form.
)
enditem()
subsect(Closing the connectino)
subsect(Closing the connection)
startitem()
item(tt(zfclose))(
Close the connection.
)
enditem()
subsect(Bookmarks)
The two functions tt(zfmark) and tt(zfgoto) allow you to `bookmark' the
present location (host, user and directory) of the current FTP connection
for later use. The file to be used for storing and retrieving bookmarks is
given by the parameter tt($ZFTP_BMFILE); if not set when one of the two
functions is called, it will be set to the file tt(.zfbfmarks) in the
directory where your zsh startup files live (usually tt(~)).
startitem()
item(tt(zfmark [ )var(bookmark)tt( ]))(
If given an argument, mark the current host, user and directory under the
name var(bookmark) for later use by tt(zfgoto). If there is no connection
open, use the values for the last connection immediately before it was
closed; it is an error if there is none. Any existing bookmark
under the same name will be silently replaced.
If not given an argument, list the existing bookmarks and the points to
which they refer in the form var(user)tt(@)var(host)tt(:)var(directory).
)
item(tt(zfgoto [ -n ] )var(bookmark))(
Return to the location given by var(bookmark), as previously set by
tt(zfmark). If the location has user `tt(ftp)' or `tt(anonymous)', open
the connection with tt(zfanon), so that no password is required. If the
user and host parameters match those currently stored, those will be used,
and again no password is required. Otherwise a password will be prompted
for.
With the option tt(-n), the bookmark is taken to be a nickname stored by
the tt(ncftp) program in its bookmark file, which is assumed to be
tt(~/.ncftp/bookmarks). The function works identically in other ways.
Note that there is no mechanism for adding or modifying tt(ncftp) bookmarks
from the zftp functions.
)
enditem()
subsect(Other functions)
Mostly, these functions will not be called directly (apart from
tt(zfinit)), but are described here for completeness. You may wish to
@ -288,7 +324,7 @@ alter tt(zftp_chpwd) and tt(zftp_progress), in particular.
startitem()
item(tt(zfinit [ -n ]))(
As decribed above, this is used to initialise the zftp function system.
As described above, this is used to initialise the zftp function system.
The tt(-n) option should be used if the zftp command is already built into
the shell.
)
@ -320,7 +356,7 @@ var(prefix) and var(suffix) set appropriately.
item(tt(zfrglob var(varname)))(
Perform remote globbing, as describes in more detail below. var(varname)
is the name of a variable containing the pattern to be expanded; if there
were any matches, the same variable will be set to the exanded set of
were any matches, the same variable will be set to the expanded set of
filenames on return.
)
item(tt(zfrtime var(lfile) var(rfile) [ var(time) ]))(
@ -339,15 +375,13 @@ tt(xterm) or tt(sun-cmd) terminal emulator to reflect the local and remote
hostnames and current directories. It works best when combined with the
function tt(chpwd). In particular, a function of the form
tt(indent(
nofill(chpwd() {)
nofill( if [[ -n $ZFTP_USER ]]; then)
nofill( zftp_chpwd)
nofill( else)
nofill( # usual chpwd e.g put host:directory in title bar)
nofill( fi)
nofill(})
))
example(chpwd() {
if [[ -n $ZFTP_USER ]]; then
zftp_chpwd
else
# usual chpwd e.g put host:directory in title bar
fi
})
fits in well.
)
@ -378,7 +412,7 @@ remote server does not support the UNIX directory semantics, directory
handling is problematic and it is recommended that globbing only be used
within the current directory. The list of files in the current directory,
if retrieved, will be cached, so that subsequent globs in the same
directory without an interventing tt(zfcd) are fast.
directory without an intervening tt(zfcd) are fast.
If the variable tt($zfrglob) is set to a non-zero length, globbing is
instead performed on the remote host: the server is asked for a list of
@ -415,10 +449,8 @@ never close the connection automatically.
Information about the previous connection is given by the tt(zfstat)
function. So, for example, if that reports:
tt(indent(
nofill(Not connected.)
nofill(Last session: ftp.bar.com:/pub/textfiles)
))
example(Not connected.
Last session: ftp.bar.com:/pub/textfiles)
then the command tt(zfget file.txt) will attempt to reopen a connection to
tt(ftp.bar.com), retrieve the file tt(/pub/textfiles/file.txt), and
@ -427,9 +459,9 @@ will open the connection in the directory tt(/pub) and leave it open.
subsect(Completion)
Completion of remote files and directories is supported. The older,
tt(compctl)-style completion is defined when tt(zfinit) is called; support
for the new widget-based completion system is provided in the function
tt(Completion/Builtins/_zftp), which should be installed with the other
functions of the completion system and hence should automatically be
Completion of remote files, directories and bookmarks is supported. The
older, tt(compctl)-style completion is defined when tt(zfinit) is called;
support for the new widget-based completion system is provided in the
function tt(Completion/Builtins/_zftp), which should be installed with the
other functions of the completion system and hence should automatically be
available.

View file

@ -1,4 +1,4 @@
texinode(Zsh Line Editor)(Programmable Completion)(Shell Builtin Commands)(Top)
texinode(Zsh Line Editor)(Programmable Completion Using compctl)(Shell Builtin Commands)(Top)
chapter(Zsh Line Editor)
cindex(line editor)
cindex(editor, line)
@ -83,7 +83,7 @@ simply to perform some small action. The ZLE commands that key sequences
in keymaps are bound to are in fact widgets. Widgets can be user-defined
or built in.
There are 162 standard widgets built in to ZLE (see sectref(Standard Widgets)).
There are 162 standard widgets built in to ZLE (see Standard Widgets below).
Other built-in widgets can be defined by other modules (see
ifzman(zmanref(zshmodules))\
ifnzman(noderef(Zsh Modules))\
@ -157,7 +157,7 @@ vindex(keys)
item(tt(keys) (array))(
The keys typed to invoke this widget, one element per
key. Control-keys are reported with a leading `tt(^)', as in `tt(^A)',
and meta-keys are repoted with a leading `tt(M-)', as in `tt(M-a)' and
and meta-keys are reported with a leading `tt(M-)', as in `tt(M-a)' and
`tt(M-^A)'.
)
vindex(NUMERIC)

View file

@ -162,6 +162,12 @@ def(itemiz)(1)(\
COMMENT(--- special effects ---)
def(example)(1)(\
NOTRANS(.RS)NL()NOTRANS(.nf)NL()\
NOTRANS(\fB)ARG1NOTRANS(\fP)\
NL()NOTRANS(.fi)NL()NOTRANS(.RE)\
)
def(nofill)(1)(\
NOTRANS(.nf)NL()\
ARG1\
@ -169,9 +175,9 @@ def(nofill)(1)(\
)
def(indent)(1)(\
NOTRANS(.RS)\
NOTRANS(.RS)NL()NOTRANS(.nf)NL()\
ARG1\
NOTRANS(.RE)\
NL()NOTRANS(.fi)NL()NOTRANS(.RE)\
)
COMMENT(--- hyperlink menus ---)

View file

@ -17,7 +17,7 @@ def(ifzshall)(1)()\
)\
ifztexi(\
texinfo(zsh.info)(zsh)
NOTRANS(@setchapternewpage odd
NOTRANS(@setchapternewpage off
@iftex
@finalout
@afourpaper

View file

@ -11,7 +11,7 @@ def(CMT)(0)(NOTRANS(@c))
ATEXIT(\
NL()\
NOTRANS(@setchapternewpage odd)NL()\
NOTRANS(@setchapternewpage off)NL()\
NOTRANS(@contents)NL()\
NOTRANS(@bye)NL()\
)
@ -207,8 +207,16 @@ def(nofill)(1)(\
USECHARTABLE(standard)\
)
def(indent)(1)(\
def(example)(1)(\
NOTRANS(@example)NL()\
ARG1\
NL()NOTRANS(@end example)\
)
def(indent)(1)(\
NOTRANS(@display)NL()\
ARG1\
NL()NOTRANS(@end display)\
)
COMMENT(--- hyperlink menus ---)

View file

@ -38,6 +38,10 @@ DEC: OSF/1 1.2, 1.3, 2.0, 3.*, DEC Unix 4.* (Alpha)
This problem is not related to zsh. If you have such problems,
remove the bogus strip and use /bin/strip instead.
On Digital UNIX 4.0, compilation with gcc and with --enable-dynamic
apparently needs configuring with explicit flags:
DLLD=gcc LDFLAGS='-g -rpath <path-to-.so-files>' ./configure ...
FreeBSD: FreeBSD 2.2.7 [3.1.4]
Should build `out-of-the-box'.
@ -102,5 +106,7 @@ Sun: Solaris 2.*
to /usr/ucblib in your LD_LIBRARY_PATH. You can easily do this
by just unsetting LD_LIBRARY_PATH before building zsh.
Under Solaris 2.7, dynamically loaded library support with
--enable-dynamic currently does not work.
Under Solaris 2.7, problems have been reported with dynamically
loaded library support using --enable-dynamic. However, other
users have been successful with the standard Sun compiler.
More details of any problems would be appreciated.

View file

@ -55,7 +55,14 @@ install.fns:
$(sdir_top)/mkinstalldirs $(fndir) || exit 1; \
for file in $(FUNCTIONS_INSTALL); do \
if test -f $$file; then \
$(INSTALL_DATA) $$file $(fndir) || exit 1; \
if test x$(FUNCTIONS_SUBDIRS) != x -a \
x$(FUNCTIONS_SUBDIRS) != xno; then \
subdir="`echo $$file | sed -e 's%/.*%%'`"; \
$(sdir_top)/mkinstalldirs $(fndir)/$$subdir || exit 1; \
$(INSTALL_DATA) $$file $(fndir)/$$subdir || exit 1; \
else \
$(INSTALL_DATA) $$file $(fndir) || exit 1; \
fi; \
fi; \
done; \
fi; \
@ -65,7 +72,12 @@ uninstall.fns:
if test x$(fndir) != x && test x$(fndir) != xno; then \
for file in $(FUNCTIONS_INSTALL); do \
if test -f $$file; then \
rm -f "$(fndir)/`echo $$file | sed -e 's%^.*/%%'`"; \
if test x$(FUNCTIONS_SUBDIRS) != x -a \
x$(FUNCTIONS_SUBDIRS) != xno; then \
rm -f $(fndir)/$$file; \
else \
rm -f "$(fndir)/`echo $$file | sed -e 's%^.*/%%'`"; \
fi; \
fi; \
done; \
fi; \

View file

@ -1,7 +1,7 @@
DISTFILES_SRC='
.distfiles
zfanon zfautocheck zfcd zfcd_match zfcget zfclose zfcput zfdir
zfgcp zfget zfget_match zfhere zfinit zfls zfopen zfparams
zfgcp zfget zfget_match zfgoto zfhere zfinit zfls zfmark zfopen zfparams
zfpcp zfput zfrglob zfrtime zfstat zftp_chpwd zftp_progress
zftype zfuget zfuput
'

0
Functions/Zftp/zfgoto Normal file
View file

View file

@ -1,3 +1,5 @@
emulate -L zsh
[[ $1 = -n ]] || zmodload -ia zftp
alias zfcd='noglob zfcd'
@ -6,6 +8,11 @@ alias zfls='noglob zfls'
alias zfdir='noglob zfdir'
alias zfuget='noglob zfuget'
autoload -U zfanon zfautocheck zfcd zfcd_match zfcget zfclose zfcput
autoload -U zfdir zfgcp zfget zfget_match zfgoto zfhere zfinit zfls
autoload -U zfmark zfopen zfparams zfpcp zfput zfrglob zfrtime zfstat
autoload -U zftp_chpwd zftp_progress zftype zfuget zfuput
# only way of getting that noglob out of the way: this is unnecessary with
# widget-based completion and can be commented out.
setopt completealiases
@ -14,7 +21,7 @@ setopt completealiases
# zftp completions: only use these if new-style completion is not
# active.
#
if [[ ${#patcomps} -eq 0 || ${patcomps[(i)zf*]} -gt ${#patcomps} ]]; then
if [[ ${#_patcomps} -eq 0 || ${_patcomps[(i)zf*]} -gt ${#_patcomps} ]]; then
compctl -f -x 'p[1]' \
-k '(open params user login type ascii binary mode put putat
get getat append appendat ls dir local remote mkdir rmdir delete
@ -25,4 +32,9 @@ if [[ ${#patcomps} -eq 0 || ${patcomps[(i)zf*]} -gt ${#patcomps} ]]; then
compctl -K zfcd_match -S/ -q zfcd zfdir zfls
compctl -K zfget_match zfget zfgcp zfuget zfcget
compctl -k hosts zfanon zfopen zfparams
compctl -s \
'$(awk '\''{print $1}'\'' ${ZFTP_BMFILE:-${ZDOTDIR:-$HOME}/.zfbkmarks})' \
-x 'W[1,-*n*]' \
-s '$(awk -F, '\''NR > 2 { print $1 }'\'' ~/.ncftp/bookmarks)' -- \
zfgoto zfmark
fi

0
Functions/Zftp/zfmark Normal file
View file

View file

@ -24,6 +24,7 @@ if [[ -z $ZFTP_USER ]]; then
else
[[ -n $ZFTP_PWD ]] && zflastdir=$ZFTP_PWD
zflastsession="$ZFTP_HOST:$ZFTP_PWD"
zflastuser="$ZFTP_USER"
local args
if [[ -t 1 && -t 2 ]]; then
local str=$zflastsession

24
INSTALL
View file

@ -220,11 +220,12 @@ turn off both installation of functions and the setting of a default value
for $fpath/$FPATH.
You can control the functions which get installed by setting
FUNCTIONS_INSTALL, either when running configure or when running `make
install' or `make install.fns'. It includes a list of files relative to
either the Completion or Functions subdirectories. By default, all the
functions for the Completion system will be installed (see the zshcompsys
manual page), i.e.
FUNCTIONS_INSTALL, either when running configure (e.g.
`FUNCTIONS_INSTALL="..." configure ...') or when running `make install' or
`make install.fns'. It includes a list of files relative to either the
Completion or Functions subdirectories. By default, all the functions for
the Completion system will be installed (see the zshcompsys manual page),
i.e.
FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/*'
and if the --enable-dynamic option was given, the functions in
Functions/Zftp, which require the zftp module to be available (see the
@ -233,6 +234,11 @@ miscellaneous functions with documentation in comments; the complete set
of functions can be installed with
FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* Misc/* Zftp/*'
You can also set --enable-function-subdirs to allow shell
functions to be installed into subdirectories of the function directory,
i.e. `Core/*' files will be installed into `FNDIR/Core', and so on.
This also initialises $fpath/$FPATH appropriately.
Support for large files and integers
------------------------------------
@ -257,6 +263,11 @@ type; it does not require that support for large files is actually
enabled. Hence you might consider using --enable-lfs on any 32-bit system
with a suitable compiler such as gcc.
Also note that if `configure' finds out that either of the types off_t or
ino_t are 64-bit quantities, but that long integers are only 32 bits, all
the above will be enabled automatically. This is necessary to ensure
correct handling of these types.
None of this is relevant for 64-bit systems; zsh should compile and run
without problems if (sizeof(long) == 8).
@ -300,6 +311,7 @@ Features:
zlogin=pathname # the full pathname of the global zlogin script
zprofile=pathname # the full pathname of the global zprofile script
zlogout=pathname # the full pathname of the global zlogout script
fns=directory # the directory where shell functions will go
fndir=directory # the directory where shell functions will go
function-subdirs # if functions will be installed into subdirectories
dynamic # allow dynamically loaded binary modules
lfs # allow configure check for large files

View file

@ -222,8 +222,21 @@ printulimit(int lim, int hard, int head)
/* display the limit */
if (limit == RLIM_INFINITY)
printf("unlimited\n");
else
printf("%ld\n", (long)limit);
else {
# ifdef RLIM_T_IS_QUAD_T
printf("%qd\n", limit);
# else
# ifdef RLIM_T_IS_LONG_LONG
printf("%lld\n", limit);
# else
# ifdef RLIM_T_IS_UNSIGNED
printf("%lu\n", limit);
# else
printf("%ld\n", limit);
# endif /* RLIM_T_IS_UNSIGNED */
# endif /* RLIM_T_IS_LONG_LONG */
# endif /* RLIM_T_IS_QUAD_T */
}
}
/* limit: set or show resource limits. The variable hard indicates *

View file

@ -205,8 +205,12 @@ clean: clean-modules
distclean: distclean-modules
realclean: realclean-modules
mostlyclean-modules clean-modules distclean-modules realclean-modules: Makemod
@$(MAKE) -f Makemod $(MAKEDEFS) `echo $@ | sed 's/-modules//'`
# Don't remake Makemod just to delete things, even if it doesn't exist.
mostlyclean-modules clean-modules distclean-modules realclean-modules:
if test -f Makemod; then \
@$(MAKE) -f Makemod $(MAKEDEFS) `echo $@ | sed 's/-modules//'`; \
fi; \
exit 0
@CLEAN_MK@

View file

@ -230,7 +230,7 @@ static char *lastmsg, lastcodestr[4];
static int lastcode;
/* flag for remote system is UNIX --- useful to know as things are simpler */
static int zfis_unix, zfpassive_conn;
static int zfpassive_conn;
/* remote system has size, mdtm commands */
enum {
@ -1786,7 +1786,6 @@ zftp_open(char *name, char **args, int flags)
return 1;
}
zfis_unix = 0;
zfhas_size = zfhas_mdtm = ZFCP_UNKN;
zdfd = -1;
/* initial status: open, ASCII data, stream mode 'n' stuff */
@ -2039,14 +2038,12 @@ zftp_login(char *name, char **args, int flags)
/*
* Use binary for transfers. This simple test saves much
* hassle for all concerned, particularly me.
*
* We could set this based just on the UNIX part,
* but I don't really know the consequences of that.
*/
zfstatus |= ZFST_IMAG;
zfis_unix = 1;
}
/*
* we could set zfis_unix based just on the UNIX part,
* but I don't really know the consequences of that.
*/
zfsetparam("ZFTP_SYSTEM", systype, ZFPM_READONLY);
}
zfstatus |= ZFST_SYST;

View file

@ -788,9 +788,8 @@ static char *suffixfunc;
void
makesuffix(int n)
{
suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] =
suffixlen[';'] = suffixlen['|'] = suffixlen['&'] =
suffixlen['<'] = suffixlen['>'] = n;
suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] =
suffixlen[';'] = suffixlen['&'] = suffixlen['|'] = n;
}
/* Set up suffix for parameter names: the last n characters are a suffix *

View file

@ -681,12 +681,11 @@ cmphaswilds(char *str)
/* Check if we have to complete a parameter name. */
static char *
check_param(char *s, int set, char **ep)
check_param(char *s, int set, int test)
{
char *p;
int bq = 0, eq = 0, i;
if (!ep)
if (!test)
ispar = parq = eparq = 0;
/* Try to find a `$'. */
for (p = s + offs; p > s && *p != String && *p != Qstring; p--);
@ -726,9 +725,9 @@ check_param(char *s, int set, char **ep)
e = b;
if (br) {
while (*e == (ep ? Dnull : '"'))
e++, parq++, bq++;
if (!ep)
while (*e == (test ? Dnull : '"'))
e++, parq++;
if (!test)
b = e;
}
/* Find the end of the name. */
@ -749,14 +748,12 @@ check_param(char *s, int set, char **ep)
if (offs <= e - s && offs >= b - s && n <= 0) {
if (br) {
p = e;
while (*p == (ep ? Dnull : '"'))
p++, parq--, eparq++, eq++;
while (*p == (test ? Dnull : '"'))
p++, parq--, eparq++;
}
/* It is. */
if (ep) {
*ep = e;
if (test)
return b;
}
/* If we were called from makecomplistflags(), we have to set the
* global variables. */
@ -765,21 +762,12 @@ check_param(char *s, int set, char **ep)
mflags |= CMF_PARBR;
/* Get the prefix (anything up to the character before the name). */
for (i = eq, p = e; i; i--, p++)
*p = '.';
isuf = quotename(e, NULL);
for (i = eq, p = isuf; i; i--, p++)
*p = '"';
isuf = dupstring(e);
untokenize(isuf);
*e = '\0';
ripre = dupstring(s);
ripre[b - s] = '\0';
for (i = bq, p = ripre + (b - s) - 1; i; i--, p--)
*p = '.';
ipre = quotename(ripre, NULL);
for (i = bq, p = ripre + strlen(ripre) - 1; i; i--, p--)
*p = '"';
for (i = bq, p = ipre + strlen(ipre) - 1; i; i--, p--)
*p = '"';
ipre = dupstring(ripre);
untokenize(ipre);
}
else
@ -1231,8 +1219,7 @@ get_comp_string(void)
clwpos = -1;
lexsave();
inpush(dupstrspace((char *) linptr), 0, NULL);
strinbeg();
stophist = 2;
strinbeg(0);
i = tt0 = cp = rd = ins = oins = linarr = parct = ia = 0;
/* This loop is possibly the wrong way to do this. It goes through *
@ -1535,11 +1522,12 @@ get_comp_string(void)
/* This variable will hold the current word in quoted form. */
qword = ztrdup(s);
offs = cs - wb;
if ((p = check_param(s, 0, &tt))) {
for (; *p == Dnull; p++)
*p = '"';
for (; *tt == Dnull; tt++)
*tt = '"';
if ((p = check_param(s, 0, 1))) {
for (p = s; *p; p++)
if (*p == Dnull)
*p = '"';
else if (*p == Snull)
*p = '\'';
}
if (*s == Snull || *s == Dnull) {
char *q = (*s == Snull ? "'" : "\""), *n = tricat(qipre, q, "");
@ -3427,7 +3415,7 @@ add_match_data(int alt, char *str, Cline line,
Aminfo ai = (alt ? fainfo : ainfo);
int palen, salen, qipl, ipl, pl, ppl, qisl, isl, psl;
palen = salen = qipl = ipl = pl = ppl = isl = psl = 0;
palen = salen = qipl = ipl = pl = ppl = qisl = isl = psl = 0;
DPUTS(!line, "BUG: add_match_data() without cline");
@ -4369,10 +4357,10 @@ docompletion(char *s, int lst, int incmd)
invalidatelist();
/* Print the explanation strings if needed. */
if (!showinglist && validlist && nmatches != 1) {
if (!showinglist && validlist && usemenu != 2 && nmatches != 1) {
Cmgroup g = amatches;
Cexpl *e;
int up = 0, tr = 1;
int up = 0, tr = 1, nn = 0;
if (!nmatches)
feep();
@ -4385,7 +4373,12 @@ docompletion(char *s, int lst, int incmd)
trashzle();
tr = 0;
}
if (nn) {
up++;
putc('\n', shout);
}
up += printfmt((*e)->str, (*e)->count, 1);
nn = 1;
}
e++;
}
@ -4915,6 +4908,9 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
int ois = instring, oib = inbackt;
char *tmp, *p, *ns, *ol = (char *) line, sav, oaq = autoq, *qp, *qs;
swb = swe = soffs = 0;
ns = NULL;
/* Put the string in the lexer buffer and call the lexer to *
* get the words we have to expand. */
zleparse = 1;
@ -4930,8 +4926,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
inpush(dupstrspace(tmp), 0, NULL);
line = (unsigned char *) tmp;
ll = tl - 1;
strinbeg();
stophist = 2;
strinbeg(0);
noaliases = 1;
do {
ctxtlex();
@ -4979,11 +4974,21 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
ll = oll;
if (cur < 0 || i < 1)
return 1;
owb = offs;
offs = soffs;
if ((p = check_param(ns, 0, 1))) {
for (p = ns; *p; p++)
if (*p == Dnull)
*p = '"';
else if (*p == Snull)
*p = '\'';
}
offs = owb;
if (*ns == Snull || *ns == Dnull) {
instring = (*ns == Snull ? 1 : 2);
inbackt = 0;
swb++;
if (ns[strlen(ns) - 1] == *ns)
if (ns[strlen(ns) - 1] == *ns && ns[1])
swe--;
autoq = (*ns == Snull ? '\'' : '"');
} else {
@ -5028,7 +5033,8 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
char **ow = clwords, *os = cmdstr, *oqp = qipre, *oqs = qisuf;
int olws = clwsize, olwn = clwnum, olwp = clwpos;
int obr = brange, oer = erange, oof = offs;
unsigned long occ = ccont;
clwsize = clwnum = countlinknodes(foo);
clwords = (char **) zalloc((clwnum + 1) * sizeof(char *));
for (n = firstnode(foo), i = 0; n; incnode(n), i++) {
@ -5043,7 +5049,9 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
qipre = qp;
qisuf = qs;
offs = soffs;
ccont = CC_CCCONT;
makecomplistcmd(ns, !clwpos, CFN_FIRST);
ccont = occ;
offs = oof;
zsfree(cmdstr);
cmdstr = os;
@ -6341,7 +6349,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
tmpbuf = (char *)zhalloc(strlen(cc->str) + 5);
sprintf(tmpbuf, "foo %s", cc->str); /* KLUDGE! */
inpush(tmpbuf, 0, NULL);
strinbeg();
strinbeg(0);
noaliases = 1;
do {
ctxtlex();
@ -6502,7 +6510,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
int oldn = clwnum, oldp = clwpos;
unsigned long occ = ccont;
ccont = 0;
ccont = CC_CCCONT;
/* So we restrict the words-array. */
if (brange >= clwnum)
@ -8099,14 +8107,13 @@ doexpandhist(void)
lexsave();
/* We push ol as it will remain unchanged */
inpush((char *) ol, 0, NULL);
strinbeg();
strinbeg(1);
noaliases = 1;
noerrs = 1;
exlast = inbufct;
do {
ctxtlex();
} while (tok != ENDINPUT && tok != LEXERR);
stophist = 2;
while (!lexstop)
hgetc();
/* We have to save errflags because it's reset in lexrestore. Since *
@ -8178,7 +8185,7 @@ getcurcmd(void)
metafy_line();
inpush(dupstrspace((char *) line), 0, NULL);
unmetafy_line();
strinbeg();
strinbeg(1);
pushheap();
do {
curlincmd = incmdpos;

View file

@ -43,7 +43,7 @@ static struct builtin builtins[] =
BUILTIN(".", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL),
BUILTIN(":", BINF_PSPECIAL, bin_true, 0, -1, 0, NULL, NULL),
BUILTIN("alias", BINF_MAGICEQUALS, bin_alias, 0, -1, 0, "Lgmr", NULL),
BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "t", "u"),
BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "tU", "u"),
BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL),
BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL),
BUILTIN("bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
@ -64,7 +64,7 @@ static struct builtin builtins[] =
BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL),
BUILTIN("fc", BINF_FCOPTS, bin_fc, 0, -1, BIN_FC, "nlreIRWAdDfEim", NULL),
BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL),
BUILTIN("functions", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "mtu", NULL),
BUILTIN("functions", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "mtuU", NULL),
BUILTIN("getln", 0, bin_read, 0, -1, 0, "ecnAlE", "zr"),
BUILTIN("getopts", 0, bin_getopts, 2, -1, 0, NULL, NULL),
BUILTIN("hash", BINF_MAGICEQUALS, bin_hash, 0, -1, 0, "dfmrv", NULL),
@ -209,7 +209,7 @@ execbuiltin(LinkList args, Builtin bn)
LinkNode n;
char ops[MAX_OPS], *arg, *pp, *name, **argv, **oargv, *optstr;
char *oxarg, *xarg = NULL;
int flags, sense, argc = 0, execop;
int flags, sense, argc = 0, execop, xtr = isset(XTRACE), lxarg = 0;
/* initialise some static variables */
auxdata = NULL;
@ -250,12 +250,21 @@ execbuiltin(LinkList args, Builtin bn)
break;
}
/* save the options in xarg, for execution tracing */
if (xarg) {
oxarg = tricat(xarg, " ", arg);
zsfree(xarg);
xarg = oxarg;
} else
xarg = ztrdup(arg);
if (xtr) {
if (xarg) {
int l = strlen(arg) + lxarg + 1;
oxarg = zhalloc(l + 1);
strcpy(oxarg, xarg);
oxarg[lxarg] = ' ';
strcpy(oxarg + lxarg + 1, arg);
xarg = oxarg;
lxarg = l + 1;
} else {
xarg = dupstring(arg);
lxarg = strlen(xarg);
}
}
/* handle -- or - (ops['-']), and + (ops['-'] and ops['+']) */
if (arg[1] == '-')
arg++;
@ -283,7 +292,6 @@ execbuiltin(LinkList args, Builtin bn)
if(*arg == Meta)
*++arg ^= 32;
zerr("bad option: -%c", NULL, *arg);
zsfree(xarg);
return 1;
}
arg = (char *) ugetnode(args);
@ -330,7 +338,6 @@ execbuiltin(LinkList args, Builtin bn)
while ((*argv++ = (char *)ugetnode(args)));
argv = oargv;
if (errflag) {
zsfree(xarg);
errflag = 0;
return 1;
}
@ -339,12 +346,11 @@ execbuiltin(LinkList args, Builtin bn)
if (argc < bn->minargs || (argc > bn->maxargs && bn->maxargs != -1)) {
zwarnnam(name, (argc < bn->minargs)
? "not enough arguments" : "too many arguments", NULL, 0);
zsfree(xarg);
return 1;
}
/* display execution trace information, if required */
if (isset(XTRACE)) {
if (xtr) {
fprintf(stderr, "%s%s", (prompt4) ? prompt4 : "", name);
if (xarg)
fprintf(stderr, " %s", xarg);
@ -353,7 +359,6 @@ execbuiltin(LinkList args, Builtin bn)
fputc('\n', stderr);
fflush(stderr);
}
zsfree(xarg);
/* call the handler function, and return its return value */
return (*(bn->handlerfunc)) (name, argv, ops, bn->funcid);
}
@ -1824,17 +1829,18 @@ bin_functions(char *name, char **argv, char *ops, int func)
int on = 0, off = 0;
/* Do we have any flags defined? */
if (ops['u'] || ops['t']) {
if (ops['u'] == 1)
on |= PM_UNDEFINED;
else if (ops['u'] == 2)
off |= PM_UNDEFINED;
if (ops['t'] == 1)
on |= PM_TAGGED;
else if (ops['t'] == 2)
off |= PM_TAGGED;
}
if (ops['u'] == 1)
on |= PM_UNDEFINED;
else if (ops['u'] == 2)
off |= PM_UNDEFINED;
if (ops['U'] == 1)
on |= PM_UNALIASED|PM_UNDEFINED;
else if (ops['U'] == 2)
off |= PM_UNALIASED;
if (ops['t'] == 1)
on |= PM_TAGGED;
else if (ops['t'] == 2)
off |= PM_TAGGED;
if (off & PM_UNDEFINED) {
zwarnnam(name, "invalid option(s)", NULL, 0);
@ -1845,6 +1851,8 @@ bin_functions(char *name, char **argv, char *ops, int func)
* are given, we will print only functions containing these *
* flags, else we'll print them all. */
if (!*argv) {
if (ops['U'] && !ops['u'])
on &= ~PM_UNDEFINED;
scanhashtable(shfunctab, 1, on|off, DISABLED, shfunctab->printnode, 0);
return 0;
}
@ -3078,8 +3086,7 @@ bin_eval(char *nam, char **argv, char *ops, int func)
List list;
inpush(zjoin(argv, ' '), 0, NULL);
strinbeg();
stophist = 2;
strinbeg(0);
list = parse_list();
strinend();
inpop();
@ -3584,7 +3591,7 @@ bin_trap(char *name, char **argv, char *ops, int func)
if (!sigfuncs[sig])
printf("trap -- '' %s\n", sigs[sig]);
else {
s = getpermtext((void *) dupstruct((void *) sigfuncs[sig]));
s = getpermtext((void *) sigfuncs[sig]);
printf("trap -- ");
quotedzputs(s, stdout);
printf(" %s\n", sigs[sig]);

View file

@ -42,6 +42,7 @@ int
evalcond(Cond c)
{
struct stat *st;
char *left, *right = NULL;
switch (c->type) {
case COND_NOT:
@ -103,107 +104,109 @@ evalcond(Cond c)
return 0;
}
}
singsub((char **)&c->left);
untokenize(c->left);
left = dupstring((char *) c->left);
singsub(&left);
untokenize(left);
if (c->right) {
singsub((char **)&c->right);
right = dupstring((char *) c->right);
singsub(&right);
if (c->type != COND_STREQ && c->type != COND_STRNEQ)
untokenize(c->right);
untokenize(right);
}
if (tracingcond) {
if (c->type < COND_MOD) {
char *rt = (char *)c->right;
char *rt = (char *)right;
if (c->type == COND_STREQ || c->type == COND_STRNEQ) {
rt = dupstring(rt);
untokenize(rt);
}
fprintf(stderr, " %s %s %s", (char *)c->left, condstr[c->type],
fprintf(stderr, " %s %s %s", (char *)left, condstr[c->type],
rt);
} else
fprintf(stderr, " -%c %s", c->type, (char *)c->left);
fprintf(stderr, " -%c %s", c->type, (char *)left);
}
switch (c->type) {
case COND_STREQ:
return matchpat(c->left, c->right);
return matchpat(left, right);
case COND_STRNEQ:
return !matchpat(c->left, c->right);
return !matchpat(left, right);
case COND_STRLT:
return strcmp(c->left, c->right) < 0;
return strcmp(left, right) < 0;
case COND_STRGTR:
return strcmp(c->left, c->right) > 0;
return strcmp(left, right) > 0;
case 'e':
case 'a':
return (doaccess(c->left, F_OK));
return (doaccess(left, F_OK));
case 'b':
return (S_ISBLK(dostat(c->left)));
return (S_ISBLK(dostat(left)));
case 'c':
return (S_ISCHR(dostat(c->left)));
return (S_ISCHR(dostat(left)));
case 'd':
return (S_ISDIR(dostat(c->left)));
return (S_ISDIR(dostat(left)));
case 'f':
return (S_ISREG(dostat(c->left)));
return (S_ISREG(dostat(left)));
case 'g':
return (!!(dostat(c->left) & S_ISGID));
return (!!(dostat(left) & S_ISGID));
case 'k':
return (!!(dostat(c->left) & S_ISVTX));
return (!!(dostat(left) & S_ISVTX));
case 'n':
return (!!strlen(c->left));
return (!!strlen(left));
case 'o':
return (optison(c->left));
return (optison(left));
case 'p':
return (S_ISFIFO(dostat(c->left)));
return (S_ISFIFO(dostat(left)));
case 'r':
return (doaccess(c->left, R_OK));
return (doaccess(left, R_OK));
case 's':
return ((st = getstat(c->left)) && !!(st->st_size));
return ((st = getstat(left)) && !!(st->st_size));
case 'S':
return (S_ISSOCK(dostat(c->left)));
return (S_ISSOCK(dostat(left)));
case 'u':
return (!!(dostat(c->left) & S_ISUID));
return (!!(dostat(left) & S_ISUID));
case 'w':
return (doaccess(c->left, W_OK));
return (doaccess(left, W_OK));
case 'x':
if (privasserted()) {
mode_t mode = dostat(c->left);
mode_t mode = dostat(left);
return (mode & S_IXUGO) || S_ISDIR(mode);
}
return doaccess(c->left, X_OK);
return doaccess(left, X_OK);
case 'z':
return (!strlen(c->left));
return (!strlen(left));
case 'h':
case 'L':
return (S_ISLNK(dolstat(c->left)));
return (S_ISLNK(dolstat(left)));
case 'O':
return ((st = getstat(c->left)) && st->st_uid == geteuid());
return ((st = getstat(left)) && st->st_uid == geteuid());
case 'G':
return ((st = getstat(c->left)) && st->st_gid == getegid());
return ((st = getstat(left)) && st->st_gid == getegid());
case 'N':
return ((st = getstat(c->left)) && st->st_atime <= st->st_mtime);
return ((st = getstat(left)) && st->st_atime <= st->st_mtime);
case 't':
return isatty(matheval(c->left));
return isatty(matheval(left));
case COND_EQ:
return matheval(c->left) == matheval(c->right);
return matheval(left) == matheval(right);
case COND_NE:
return matheval(c->left) != matheval(c->right);
return matheval(left) != matheval(right);
case COND_LT:
return matheval(c->left) < matheval(c->right);
return matheval(left) < matheval(right);
case COND_GT:
return matheval(c->left) > matheval(c->right);
return matheval(left) > matheval(right);
case COND_LE:
return matheval(c->left) <= matheval(c->right);
return matheval(left) <= matheval(right);
case COND_GE:
return matheval(c->left) >= matheval(c->right);
return matheval(left) >= matheval(right);
case COND_NT:
case COND_OT:
{
time_t a;
if (!(st = getstat(c->left)))
if (!(st = getstat(left)))
return 0;
a = st->st_mtime;
if (!(st = getstat(c->right)))
if (!(st = getstat(right)))
return 0;
return (c->type == COND_NT) ? a > st->st_mtime : a < st->st_mtime;
}
@ -212,11 +215,11 @@ evalcond(Cond c)
dev_t d;
ino_t i;
if (!(st = getstat(c->left)))
if (!(st = getstat(left)))
return 0;
d = st->st_dev;
i = st->st_ino;
if (!(st = getstat(c->right)))
if (!(st = getstat(right)))
return 0;
return d == st->st_dev && i == st->st_ino;
}

View file

@ -139,8 +139,7 @@ parse_string(char *s)
lexsave();
inpush(s, 0, NULL);
strinbeg();
stophist = 2;
strinbeg(0);
l = parse_list();
strinend();
inpop();
@ -298,12 +297,12 @@ static char list_pipe_text[JOBTEXTSIZE];
/**/
static int
execcursh(Cmd cmd)
execcursh(Cmd cmd, LinkList args, int flags)
{
if (!list_pipe)
deletejob(jobtab + thisjob);
execlist(cmd->u.list, 1, cmd->flags & CFLAG_EXEC);
cmd->u.list = NULL;
execlist(cmd->u.list, 1, flags & CFLAG_EXEC);
return lastval;
}
@ -718,7 +717,6 @@ execlist(List list, int dont_change_job, int exiting)
/* Reset donetrap: this ensures that a trap is only *
* called once for each sublist that fails. */
donetrap = 0;
simplifyright(list);
slist = list->left;
/* Loop through code followed by &&, ||, or end of sublist. */
@ -1009,11 +1007,13 @@ execpline2(Pline pline, int how, int input, int output, int last1)
lineno = pline->left->lineno;
if (pline_level == 1)
strcpy(list_pipe_text, getjobtext((void *) pline->left));
if (pline->type == END) {
if (!sfcontext)
strcpy(list_pipe_text, getjobtext((void *) pline->left));
else
list_pipe_text[0] = '\0';
if (pline->type == END)
execcmd(pline->left, input, output, how, last1 ? 1 : 2);
pline->left = NULL;
} else {
else {
int old_list_pipe = list_pipe;
mpipe(pipes);
@ -1046,11 +1046,10 @@ execpline2(Pline pline, int how, int input, int output, int last1)
_exit(lastval);
}
} else {
/* otherwise just do the pipeline normally. */
/* otherwise just do the pipeline normally. */
subsh_close = pipes[0];
execcmd(pline->left, input, pipes[1], how, 0);
}
pline->left = NULL;
zclose(pipes[1]);
if (pline->right) {
/* if another execpline() is invoked because the command is *
@ -1102,13 +1101,17 @@ makecline(LinkList list)
void
untokenize(char *s)
{
for (; *s; s++)
if (itok(*s)) {
if (*s == Nularg)
chuck(s--);
else
*s = ztokens[*s - Pound];
}
if (*s) {
char *p = s, c;
while ((c = *s++))
if (itok(c)) {
if (c != Nularg)
*p++ = ztokens[c - Pound];
} else
*p++ = c;
*p = '\0';
}
}
/* Open a file for writing redicection */
@ -1152,34 +1155,34 @@ clobber_open(struct redir *f)
static void
closemn(struct multio **mfds, int fd)
{
struct multio *mn = mfds[fd];
char buf[TCBUFSIZE];
int len, i;
if (fd >= 0 && mfds[fd] && mfds[fd]->ct >= 2) {
struct multio *mn = mfds[fd];
char buf[TCBUFSIZE];
int len, i;
if (fd < 0 || !mfds[fd] || mfds[fd]->ct < 2)
return;
if (zfork()) {
for (i = 0; i < mn->ct; i++)
zclose(mn->fds[i]);
zclose(mn->pipe);
mn->ct = 1;
mn->fds[0] = fd;
return;
}
/* pid == 0 */
closeallelse(mn);
if (mn->rflag) {
/* tee process */
while ((len = read(mn->pipe, buf, TCBUFSIZE)) > 0)
if (zfork()) {
for (i = 0; i < mn->ct; i++)
write(mn->fds[i], buf, len);
} else {
/* cat process */
for (i = 0; i < mn->ct; i++)
while ((len = read(mn->fds[i], buf, TCBUFSIZE)) > 0)
write(mn->pipe, buf, len);
zclose(mn->fds[i]);
zclose(mn->pipe);
mn->ct = 1;
mn->fds[0] = fd;
return;
}
/* pid == 0 */
closeallelse(mn);
if (mn->rflag) {
/* tee process */
while ((len = read(mn->pipe, buf, TCBUFSIZE)) > 0)
for (i = 0; i < mn->ct; i++)
write(mn->fds[i], buf, len);
} else {
/* cat process */
for (i = 0; i < mn->ct; i++)
while ((len = read(mn->fds[i], buf, TCBUFSIZE)) > 0)
write(mn->pipe, buf, len);
}
_exit(0);
}
_exit(0);
}
/* close all the mnodes (failure) */
@ -1273,9 +1276,10 @@ static void
addvars(LinkList l, int export)
{
Varasg v;
LinkNode n;
LinkList vl;
int xtr;
char **arr, **ptr;
char **arr, **ptr, *name;
xtr = isset(XTRACE);
if (xtr && nonempty(l)) {
@ -1283,26 +1287,30 @@ addvars(LinkList l, int export)
doneps4 = 1;
}
while (nonempty(l)) {
v = (Varasg) ugetnode(l);
singsub(&v->name);
for (n = firstnode(l); n; incnode(n)) {
v = (Varasg) getdata(n);
name = dupstring(v->name);
singsub(&name);
if (errflag)
return;
untokenize(v->name);
untokenize(name);
if (xtr)
fprintf(stderr, "%s=", v->name);
fprintf(stderr, "%s=", name);
if (v->type == PM_SCALAR) {
vl = newlinklist();
addlinknode(vl, v->str);
addlinknode(vl, dupstring(v->str));
} else
vl = v->arr;
prefork(vl, v->type == PM_SCALAR ? (PF_SINGLE|PF_ASSIGN) : PF_ASSIGN);
if (errflag)
return;
if (isset(GLOBASSIGN) || v->type != PM_SCALAR)
globlist(vl);
if (errflag)
return;
vl = listdup(v->arr);
if (vl) {
prefork(vl, v->type == PM_SCALAR ? (PF_SINGLE|PF_ASSIGN) :
PF_ASSIGN);
if (errflag)
return;
if (isset(GLOBASSIGN) || v->type != PM_SCALAR)
globlist(vl);
if (errflag)
return;
}
if (v->type == PM_SCALAR && (empty(vl) || !nextnode(firstnode(vl)))) {
Param pm;
char *val;
@ -1319,7 +1327,7 @@ addvars(LinkList l, int export)
if (export) {
if (export < 0) {
/* We are going to fork so do not bother freeing this */
pm = (Param) paramtab->removenode(paramtab, v->name);
pm = (Param) paramtab->removenode(paramtab, name);
if (isset(RESTRICTED) && (pm->flags & PM_RESTRICTED)) {
zerr("%s: restricted", pm->nam, 0);
zsfree(val);
@ -1328,18 +1336,22 @@ addvars(LinkList l, int export)
}
allexp = opts[ALLEXPORT];
opts[ALLEXPORT] = 1;
pm = setsparam(v->name, val);
pm = setsparam(name, val);
opts[ALLEXPORT] = allexp;
} else
pm = setsparam(v->name, val);
pm = setsparam(name, val);
if (errflag)
return;
continue;
}
ptr = arr = (char **) zalloc(sizeof(char **) * (countlinknodes(vl) + 1));
if (vl) {
ptr = arr = (char **) zalloc(sizeof(char **) *
(countlinknodes(vl) + 1));
while (nonempty(vl))
*ptr++ = ztrdup((char *) ugetnode(vl));
while (nonempty(vl))
*ptr++ = ztrdup((char *) ugetnode(vl));
} else
ptr = arr = (char **) zalloc(sizeof(char **));
*ptr = NULL;
if (xtr) {
@ -1348,7 +1360,7 @@ addvars(LinkList l, int export)
fprintf(stderr, "%s ", *ptr);
fprintf(stderr, ") ");
}
setaparam(v->name, arr);
setaparam(name, arr);
if (errflag)
return;
}
@ -1364,15 +1376,19 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
struct multio *mfds[10];
char *text;
int save[10];
int fil, dfil, is_cursh, type, i;
int fil, dfil, is_cursh, type, flags, i;
int nullexec = 0, assign = 0, forked = 0;
int is_shfunc = 0, is_builtin = 0, is_exec = 0;
/* Various flags to the command. */
int cflags = 0, checked = 0;
LinkList vars, redir;
doneps4 = 0;
args = cmd->args;
args = listdup(cmd->args);
type = cmd->type;
flags = cmd->flags;
redir = dupheaplist(cmd->redir);
vars = cmd->vars;
for (i = 0; i < 10; i++) {
save[i] = -2;
@ -1381,7 +1397,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
/* If the command begins with `%', then assume it is a *
* reference to a job in the job table. */
if (type == SIMPLE && nonempty(args) &&
if (type == SIMPLE && args && nonempty(args) &&
*(char *)peekfirst(args) == '%') {
pushnode(args, dupstring((how & Z_DISOWN)
? "disown" : (how & Z_ASYNC) ? "bg" : "fg"));
@ -1393,7 +1409,8 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
* job currently in the job table. If it does, then we treat it *
* as a command to resume this job. */
if (isset(AUTORESUME) && type == SIMPLE && (how & Z_SYNC) &&
nonempty(args) && empty(cmd->redir) && !input &&
args && nonempty(args) &&
(!cmd->redir || empty(cmd->redir)) && !input &&
!nextnode(firstnode(args))) {
if (unset(NOTIFY))
scanjobs();
@ -1407,7 +1424,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
* only works in simple cases. has_token() is called to make sure *
* this really is a simple case. */
if (type == SIMPLE) {
while (nonempty(args)) {
while (args && nonempty(args)) {
char *cmdarg = (char *) peekfirst(args);
checked = !has_token(cmdarg);
if (!checked)
@ -1444,7 +1461,8 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
}
/* Do prefork substitutions */
prefork(args, (assign || isset(MAGICEQUALSUBST)) ? PF_TYPESET : 0);
if (args)
prefork(args, (assign || isset(MAGICEQUALSUBST)) ? PF_TYPESET : 0);
if (type == SIMPLE) {
int unglobbed = 0;
@ -1453,7 +1471,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
char *cmdarg;
if (!(cflags & BINF_NOGLOB))
while (!checked && !errflag && nonempty(args) &&
while (!checked && !errflag && args && nonempty(args) &&
has_token((char *) peekfirst(args)))
glob(args, firstnode(args));
else if (!unglobbed) {
@ -1465,12 +1483,12 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
/* Current shell should not fork unless the *
* exec occurs at the end of a pipeline. */
if ((cflags & BINF_EXEC) && last1 == 2)
cmd->flags |= CFLAG_EXEC;
flags |= CFLAG_EXEC;
/* Empty command */
if (empty(args)) {
if (nonempty(cmd->redir)) {
if (cmd->flags & CFLAG_EXEC) {
if (!args || empty(args)) {
if (redir && nonempty(redir)) {
if (flags & CFLAG_EXEC) {
/* Was this "exec < foobar"? */
nullexec = 1;
break;
@ -1480,17 +1498,23 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
errflag = lastval = 1;
return;
} else if (readnullcmd && *readnullcmd &&
((Redir) peekfirst(cmd->redir))->type == READ &&
!nextnode(firstnode(cmd->redir))) {
((Redir) peekfirst(redir))->type == READ &&
!nextnode(firstnode(redir))) {
if (!args)
args = newlinklist();
addlinknode(args, dupstring(readnullcmd));
} else
} else {
if (!args)
args = newlinklist();
addlinknode(args, dupstring(nullcmd));
}
} else if ((cflags & BINF_PREFIX) && (cflags & BINF_COMMAND)) {
lastval = 0;
return;
} else {
cmdoutval = 0;
addvars(cmd->vars, 0);
if (vars)
addvars(vars, 0);
if (errflag)
lastval = errflag;
else
@ -1502,7 +1526,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
return;
}
} else if (isset(RESTRICTED) && (cflags & BINF_EXEC) &&
(cmd->flags & CFLAG_EXEC)) {
(flags & CFLAG_EXEC)) {
zerrnam("exec", "%s: restricted", (char *) getdata(firstnode(args)), 0);
lastval = 1;
return;
@ -1548,22 +1572,32 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
}
/* Get the text associated with this command. */
if (jobbing || (how & Z_TIMED))
if (!sfcontext && (jobbing || (how & Z_TIMED)))
text = getjobtext((void *) cmd);
else
text = NULL;
/* Set up special parameter $_ */
zsfree(underscore);
if (nonempty(args)
&& (underscore = ztrdup((char *) getdata(lastnode(args)))))
untokenize(underscore);
else
underscore = ztrdup("");
if (args && nonempty(args)) {
char *u = (char *) getdata(lastnode(args));
if (u) {
int ul = strlen(u);
if (ul >= underscorelen) {
zfree(underscore, underscorelen);
underscore = (char *) zalloc(underscorelen = ul + 32);
}
strcpy(underscore, u);
} else
*underscore = '\0';
} else
*underscore = '\0';
/* Warn about "rm *" */
if (type == SIMPLE && interact && unset(RMSTARSILENT)
&& isset(SHINSTDIN) && nonempty(args) && nextnode(firstnode(args))
&& isset(SHINSTDIN) && args && nonempty(args)
&& nextnode(firstnode(args))
&& !strcmp(peekfirst(args), "rm")) {
LinkNode node, next;
@ -1596,11 +1630,11 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
if (type == SIMPLE && !nullexec) {
char *s;
char trycd = (isset(AUTOCD) && isset(SHINSTDIN)
&& empty(cmd->redir) && !empty(args)
&& (!redir || empty(redir)) && args && !empty(args)
&& !nextnode(firstnode(args))
&& *(char *)peekfirst(args));
DPUTS(empty(args), "BUG: empty(args) in exec.c");
DPUTS((!args || empty(args)), "BUG: empty(args) in exec.c");
if (!hn) {
/* Resolve external commands */
char *cmdarg = (char *) peekfirst(args);
@ -1652,7 +1686,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
* current shell. *
**************************************************************************/
if ((how & Z_ASYNC) || (!(cmd->flags & CFLAG_EXEC) &&
if ((how & Z_ASYNC) || (!(flags & CFLAG_EXEC) &&
(((is_builtin || is_shfunc) && output) ||
(!is_cursh && (last1 != 1 || sigtrapped[SIGZERR] ||
sigtrapped[SIGEXIT] || havefiles()))))) {
@ -1677,10 +1711,13 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
#endif
if (how & Z_ASYNC) {
lastpid = (zlong) pid;
} else if (!jobtab[thisjob].stty_in_env && nonempty(cmd->vars)) {
} else if (!jobtab[thisjob].stty_in_env &&
vars && nonempty(vars)) {
/* search for STTY=... */
while (nonempty(cmd->vars))
if (!strcmp(((Varasg) ugetnode(cmd->vars))->name, "STTY")) {
LinkNode n;
for (n = firstnode(vars); n; incnode(n))
if (!strcmp(((Varasg) getdata(n))->name, "STTY")) {
jobtab[thisjob].stty_in_env = 1;
break;
}
@ -1713,7 +1750,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
is_exec = 1;
}
if (!(cflags & BINF_NOGLOB))
if (args && !(cflags & BINF_NOGLOB))
globlist(args);
if (errflag) {
lastval = 1;
@ -1727,11 +1764,12 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
addfd(forked, save, mfds, 1, output, 1);
/* Do process substitutions */
spawnpipes(cmd->redir);
if (redir)
spawnpipes(redir);
/* Do io redirections */
while (nonempty(cmd->redir)) {
fn = (Redir) ugetnode(cmd->redir);
while (redir && nonempty(redir)) {
fn = (Redir) ugetnode(redir);
DPUTS(fn->type == HEREDOC || fn->type == HEREDOCDASH,
"BUG: unexpanded here document");
if (fn->type == INPIPE) {
@ -1749,7 +1787,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
}
addfd(forked, save, mfds, fn->fd1, fn->fd2, 1);
} else {
if (fn->type != HERESTR && xpandredir(fn, cmd->redir))
if (fn->type != HERESTR && xpandredir(fn, redir))
continue;
if (errflag) {
closemnodes(mfds);
@ -1870,15 +1908,15 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
if (is_exec)
entersubsh(how, type != SUBSH ? 2 : 1, 1);
if (type >= CURSH) {
static int (*func[]) _((Cmd)) = {
static int (*func[]) _((Cmd, LinkList, int)) = {
execcursh, exectime, execfuncdef, execfor, execwhile,
execrepeat, execif, execcase, execselect, execcond,
execarith, execautofn
};
if (last1 == 1)
cmd->flags |= CFLAG_EXEC;
lastval = (func[type - CURSH]) (cmd);
flags |= CFLAG_EXEC;
lastval = (func[type - CURSH]) (cmd, args, flags);
} else if (is_builtin || is_shfunc) {
LinkList restorelist = 0, removelist = 0;
/* builtin or shell function */
@ -1889,11 +1927,11 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
!(hn->flags & BINF_PSPECIAL))))
save_params(cmd, &restorelist, &removelist);
if (cmd->vars) {
if (vars) {
/* Export this if the command is a shell function,
* but not if it's a builtin.
*/
addvars(cmd->vars, is_shfunc);
addvars(vars, is_shfunc);
if (errflag) {
restore_params(restorelist, removelist);
lastval = 1;
@ -1904,6 +1942,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
if (is_shfunc) {
/* It's a shell function */
#ifdef PATH_DEV_FD
int i;
@ -1914,7 +1953,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
if (subsh_close >= 0)
zclose(subsh_close);
subsh_close = -1;
execshfunc(cmd, (Shfunc) hn);
execshfunc(cmd, (Shfunc) hn, args);
#ifdef PATH_DEV_FD
for (i = 10; i <= max_zsh_fd; i++)
if (fdtable[i] > 1)
@ -1943,7 +1982,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
clearerr(stdout);
}
if (cmd->flags & CFLAG_EXEC) {
if (flags & CFLAG_EXEC) {
if (subsh)
_exit(lastval);
@ -1957,7 +1996,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
restore_params(restorelist, removelist);
} else {
if (cmd->flags & CFLAG_EXEC) {
if (flags & CFLAG_EXEC) {
setiparam("SHLVL", --shlvl);
/* If we are exec'ing a command, and we are not *
* in a subshell, then save the history file. */
@ -1965,8 +2004,8 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
savehistfile(NULL, 1, HFILE_USE_OPTIONS);
}
if (type == SIMPLE) {
if (cmd->vars) {
addvars(cmd->vars, -1);
if (vars) {
addvars(vars, -1);
if (errflag)
_exit(1);
}
@ -1981,7 +2020,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
#endif
execute((Cmdnam) hn, cflags & BINF_DASH);
} else { /* ( ... ) */
DPUTS(cmd->vars && nonempty(cmd->vars),
DPUTS(vars && nonempty(vars),
"BUG: assigment before complex command");
list_pipe = 0;
if (subsh_close >= 0)
@ -2011,7 +2050,11 @@ save_params(Cmd cmd, LinkList *restore_p, LinkList *remove_p)
char *s;
MUSTUSEHEAP("save_params()");
if (!cmd->vars) {
*restore_p = *remove_p = NULL;
return;
}
*restore_p = newlinklist();
*remove_p = newlinklist();
@ -2283,8 +2326,9 @@ getoutput(char *cmd, int qt)
return NULL;
if (list != &dummy_list && !list->right && !list->left->flags &&
list->left->type == END && list->left->left->type == END &&
(c = list->left->left->left)->type == SIMPLE && empty(c->args) &&
empty(c->vars) && nonempty(c->redir) &&
(c = list->left->left->left)->type == SIMPLE &&
(!c->args || empty(c->args)) &&
(!c->vars || empty(c->vars)) && c->redir && nonempty(c->redir) &&
!nextnode(firstnode(c->redir)) &&
(r = (Redir) getdata(firstnode(c->redir)))->fd1 == 0 &&
r->type == READ) {
@ -2613,7 +2657,7 @@ extern int tracingcond;
/**/
static int
execcond(Cmd cmd)
execcond(Cmd cmd, LinkList args, int flags)
{
int stat;
if (isset(XTRACE)) {
@ -2633,18 +2677,19 @@ execcond(Cmd cmd)
/**/
static int
execarith(Cmd cmd)
execarith(Cmd cmd, LinkList args, int flags)
{
char *e;
zlong val = 0;
if (isset(XTRACE))
fprintf(stderr, "%s((", prompt4 ? prompt4 : "");
while ((e = (char *) ugetnode(cmd->args))) {
if (isset(XTRACE))
fprintf(stderr, " %s", e);
val = matheval(e);
}
if (args)
while ((e = (char *) ugetnode(args))) {
if (isset(XTRACE))
fprintf(stderr, " %s", e);
val = matheval(e);
}
if (isset(XTRACE)) {
fprintf(stderr, " ))\n");
fflush(stderr);
@ -2657,7 +2702,7 @@ execarith(Cmd cmd)
/**/
static int
exectime(Cmd cmd)
exectime(Cmd cmd, LinkList args, int flags)
{
int jb;
@ -2675,30 +2720,33 @@ exectime(Cmd cmd)
/**/
static int
execfuncdef(Cmd cmd)
execfuncdef(Cmd cmd, LinkList args, int flags)
{
Shfunc shf;
char *s;
int signum;
PERMALLOC {
while ((s = (char *) ugetnode(cmd->args))) {
shf = (Shfunc) zalloc(sizeof *shf);
shf->funcdef = (List) dupstruct(cmd->u.list);
shf->flags = 0;
if (args) {
PERMALLOC {
while ((s = (char *) ugetnode(args))) {
shf = (Shfunc) zalloc(sizeof *shf);
shf->funcdef = (List) dupstruct(cmd->u.list);
shf->flags = 0;
/* is this shell function a signal trap? */
if (!strncmp(s, "TRAP", 4) && (signum = getsignum(s + 4)) != -1) {
if (settrap(signum, shf->funcdef)) {
freestruct(shf->funcdef);
zfree(shf, sizeof *shf);
LASTALLOC_RETURN 1;
}
sigtrapped[signum] |= ZSIG_FUNC;
}
shfunctab->addnode(shfunctab, ztrdup(s), shf);
}
} LASTALLOC;
/* is this shell function a signal trap? */
if (!strncmp(s, "TRAP", 4) &&
(signum = getsignum(s + 4)) != -1) {
if (settrap(signum, shf->funcdef)) {
freestruct(shf->funcdef);
zfree(shf, sizeof *shf);
LASTALLOC_RETURN 1;
}
sigtrapped[signum] |= ZSIG_FUNC;
}
shfunctab->addnode(shfunctab, ztrdup(s), shf);
}
} LASTALLOC;
}
if(isset(HISTNOFUNCTIONS))
remhist();
return 0;
@ -2708,7 +2756,7 @@ execfuncdef(Cmd cmd)
/**/
static void
execshfunc(Cmd cmd, Shfunc shf)
execshfunc(Cmd cmd, Shfunc shf, LinkList args)
{
LinkList last_file_list = NULL;
@ -2726,16 +2774,17 @@ execshfunc(Cmd cmd, Shfunc shf)
if (isset(XTRACE)) {
LinkNode lptr;
fprintf(stderr, "%s", prompt4 ? prompt4 : prompt4);
for (lptr = firstnode(cmd->args); lptr; incnode(lptr)) {
if (lptr != firstnode(cmd->args))
fputc(' ', stderr);
fprintf(stderr, "%s", (char *)getdata(lptr));
}
if (args)
for (lptr = firstnode(args); lptr; incnode(lptr)) {
if (lptr != firstnode(args))
fputc(' ', stderr);
fprintf(stderr, "%s", (char *)getdata(lptr));
}
fputc('\n', stderr);
fflush(stderr);
}
doshfunc(shf->nam, shf->funcdef, cmd->args, shf->flags, 0);
doshfunc(shf->nam, shf->funcdef, args, shf->flags, 0);
if (!list_pipe)
deletefilelist(last_file_list);
@ -2749,10 +2798,16 @@ execshfunc(Cmd cmd, Shfunc shf)
/**/
static int
execautofn(Cmd cmd)
execautofn(Cmd cmd, LinkList args, int flags)
{
Shfunc shf = cmd->u.autofn->shf;
List l = getfpfunc(shf->nam);
int noalias = noaliases;
List l;
noaliases = (shf->flags & PM_UNALIASED);
l = getfpfunc(shf->nam);
noaliases = noalias;
if(l == &dummy_list) {
zerr("%s: function definition file not found", shf->nam, 0);
return 1;
@ -2773,9 +2828,7 @@ execautofn(Cmd cmd)
} LASTALLOC;
shf->flags &= ~PM_UNDEFINED;
}
HEAPALLOC {
execlist(dupstruct(shf->funcdef), 1, 0);
} LASTALLOC;
execlist(shf->funcdef, 1, 0);
return lastval;
}
@ -2822,7 +2875,8 @@ doshfunc(char *name, List list, LinkList doshargs, int flags, int noreturnval)
LinkNode node;
node = doshargs->first;
pparams = x = (char **) zcalloc(((sizeof *x) * (1 + countlinknodes(doshargs))));
pparams = x = (char **) zcalloc(((sizeof *x) *
(1 + countlinknodes(doshargs))));
if (isset(FUNCTIONARGZERO)) {
oargv0 = argzero;
argzero = ztrdup((char *) node->dat);
@ -2901,7 +2955,7 @@ void
runshfunc(List list, FuncWrap wrap, char *name)
{
int cont;
char *ou;
VARARR(char, ou, underscorelen);
while (wrap) {
wrap->module->wrapper++;
@ -2917,11 +2971,9 @@ runshfunc(List list, FuncWrap wrap, char *name)
wrap = wrap->next;
}
startparamscope();
ou = underscore;
underscore = ztrdup(underscore);
execlist(dupstruct(list), 1, 0);
zsfree(underscore);
underscore = ou;
strcpy(ou, underscore);
execlist(list, 1, 0);
strcpy(underscore, ou);
endparamscope();
}
@ -2949,20 +3001,18 @@ getfpfunc(char *s)
unmetafy(buf, NULL);
if (!access(buf, R_OK) && (fd = open(buf, O_RDONLY | O_NOCTTY)) != -1) {
if ((len = lseek(fd, 0, 2)) != -1) {
d = (char *) zalloc(len + 1);
lseek(fd, 0, 0);
d = (char *) zcalloc(len + 1);
if (read(fd, d, len) == len) {
close(fd);
d[len] = '\0';
d = metafy(d, len, META_REALLOC);
HEAPALLOC {
r = parse_string(d);
} LASTALLOC;
zfree(d, len + 1);
return r;
} else {
zfree(d, len + 1);
} else
close(fd);
}
} else {
close(fd);
}
@ -2995,9 +3045,10 @@ stripkshdef(List l, char *name)
if(p->right)
return l;
c = p->left;
if(c->type != FUNCDEF || c->flags ||
nonempty(c->redir) || nonempty(c->vars) ||
empty(c->args) || lastnode(c->args) != firstnode(c->args) ||
if (c->type != FUNCDEF || c->flags ||
(c->redir && nonempty(c->redir)) || (c->vars && nonempty(c->vars)) ||
!c->args || empty(c->args) ||
lastnode(c->args) != firstnode(c->args) ||
strcmp(name, peekfirst(c->args)))
return l;
return c->u.list;
@ -3076,8 +3127,7 @@ execsave(void)
es->trapreturn = trapreturn;
es->noerrs = noerrs;
es->subsh_close = subsh_close;
es->underscore = underscore;
underscore = ztrdup(underscore);
es->underscore = ztrdup(underscore);
es->next = exstack;
exstack = es;
noerrs = cmdoutpid = 0;
@ -3105,8 +3155,8 @@ execrestore(void)
trapreturn = exstack->trapreturn;
noerrs = exstack->noerrs;
subsh_close = exstack->subsh_close;
zsfree(underscore);
underscore = exstack->underscore;
strcpy(underscore, exstack->underscore);
zsfree(exstack->underscore);
en = exstack->next;
free(exstack);
exstack = en;

View file

@ -744,7 +744,7 @@ parsecomp(int gflag)
pptr++;
}
if (*pptr == Inpar && pptr[1] == Pound) {
if (*pptr == Inpar && pptr[1] == Pound && isset(EXTENDEDGLOB)) {
/* Found some globbing flags */
char *eptr = pptr;
if (kshfunc != KF_NONE)
@ -3432,17 +3432,17 @@ tokenize(char *s)
void
remnulargs(char *s)
{
int nl = *s;
char *t = s;
if (*s) {
char *t = s, *p = s, c;
while (*s)
if (INULL(*s))
chuck(s);
else
s++;
if (!*t && nl) {
t[0] = Nularg;
t[1] = '\0';
while ((c = *s++))
if (!INULL(c))
*p++ = c;
*p = '\0';
if (!*t) {
t[0] = Nularg;
t[1] = '\0';
}
}
}

View file

@ -880,7 +880,7 @@ printshfuncnode(HashNode hn, int printflags)
return;
}
t = getpermtext((void *) dupstruct((void *) f->funcdef));
t = getpermtext((void *) f->funcdef);
quotedzputs(f->nam, stdout);
printf(" () {\n\t");
zputs(t, stdout);
@ -1327,7 +1327,7 @@ addhistnode(HashTable ht, char *nam, void *nodeptr)
{
HashNode oldnode = addhashnode2(ht, nam, nodeptr);
Histent he = (Histent)nodeptr;
if (oldnode && oldnode != nodeptr) {
if (oldnode && oldnode != (HashNode)nodeptr) {
if (he->flags & HIST_MAKEUNIQUE
|| (he->flags & HIST_FOREIGN && (Histent)oldnode == he->up)) {
he->flags |= HIST_DUP;

View file

@ -30,6 +30,27 @@
#include "zsh.mdh"
#include "hist.pro"
/* Functions to call for getting/ungetting a character and for history
* word control. */
/**/
int (*hgetc) _((void));
/**/
void (*hungetc) _((int));
/**/
void (*hwaddc) _((int));
/**/
void (*hwbegin) _((int));
/**/
void (*hwend) _((void));
/**/
void (*addtoline) _((int));
/* != 0 means history substitution is turned off */
/**/
@ -159,12 +180,11 @@ int hlinesz;
/* default event (usually curhist-1, that is, "!!") */
static int defev;
/* add a character to the current history word */
/**/
void
hwaddc(int c)
static void
ihwaddc(int c)
{
/* Only if history line exists and lexing has not finished. */
if (chline && !(errflag || lexstop)) {
@ -182,7 +202,7 @@ hwaddc(int c)
if (hptr - chline >= hlinesz) {
int oldsiz = hlinesz;
chline = realloc(chline, hlinesz = oldsiz + 16);
chline = realloc(chline, hlinesz = oldsiz + 64);
hptr = chline + oldsiz;
}
}
@ -192,12 +212,12 @@ hwaddc(int c)
* zsh expands history (see doexpandhist() in zle_tricky.c). It also *
* calculates the new cursor position after the expansion. It is called *
* from hgetc() and from gettok() in lex.c for characters in comments. */
/**/
void
addtoline(int c)
iaddtoline(int c)
{
if (! expanding || lexstop)
if (!expanding || lexstop)
return;
if (qbang && c == bangchar && stophist < 2) {
exlast--;
@ -216,9 +236,8 @@ addtoline(int c)
line[cs++] = itok(c) ? ztokens[c - Pound] : c;
}
/**/
int
hgetc(void)
static int
ihgetc(void)
{
int c = ingetc();
@ -234,7 +253,7 @@ hgetc(void)
}
if ((inbufflags & INP_HIST) && !stophist) {
/* the current character c came from a history expansion *
* (inbufflags && INP_HIST) and history is not disabled *
* (inbufflags & INP_HIST) and history is not disabled *
* (e.g. we are not inside single quotes). In that case, \! *
* should be treated as ! (since this \! came from a previous *
* history line where \ was used to escape the bang). So if *
@ -606,9 +625,8 @@ histsubchar(int c)
/* unget a char and remove it from chline. It can only be used *
* to unget a character returned by hgetc. */
/**/
void
hungetc(int c)
static void
ihungetc(int c)
{
int doit = 1;
@ -641,10 +659,10 @@ hungetc(int c)
/**/
void
strinbeg(void)
strinbeg(int dohist)
{
strin++;
hbegin();
hbegin(dohist);
lexinit();
}
@ -661,17 +679,49 @@ strinend(void)
histdone = 0;
}
/* dummy functions to use instead of hwaddc(), hwbegin(), and hwend() when
* they aren't needed */
static void
nohw(int c)
{
}
static void
nohwe(void)
{
}
/* initialize the history mechanism */
/**/
void
hbegin(void)
hbegin(int dohist)
{
isfirstln = isfirstch = 1;
errflag = histdone = spaceflag = 0;
stophist = (!interact || unset(BANGHIST) || unset(SHINSTDIN)) << 1;
chline = hptr = zcalloc(hlinesz = 16);
chwords = zalloc((chwordlen = 16)*sizeof(short));
stophist = (dohist ? ((!interact || unset(SHINSTDIN)) << 1) : 2);
if (stophist == 2 || (inbufflags & INP_ALIAS)) {
chline = hptr = NULL;
hlinesz = 0;
chwords = NULL;
chwordlen = 0;
hgetc = ingetc;
hungetc = inungetc;
hwaddc = nohw;
hwbegin = nohw;
hwend = nohwe;
addtoline = nohw;
} else {
chline = hptr = zcalloc(hlinesz = 64);
chwords = zalloc((chwordlen = 64) * sizeof(short));
hgetc = ihgetc;
hungetc = ihungetc;
hwaddc = ihwaddc;
hwbegin = ihwbegin;
hwend = ihwend;
addtoline = iaddtoline;
}
chwordpos = 0;
if (histactive & HA_JUNKED)
@ -864,7 +914,8 @@ hend(void)
int flag, save = 1;
char *hf = getsparam("HISTFILE");
DPUTS(!chline, "BUG: chline is NULL in hend()");
DPUTS(stophist != 2 && !(inbufflags & INP_ALIAS) && !chline,
"BUG: chline is NULL in hend()");
if (histdone & HISTFLAG_SETTY)
settyinfo(&shttyinfo);
if (!(histactive & HA_NOINC)) {
@ -1005,8 +1056,10 @@ int hwgetword = -1;
/**/
void
hwbegin(int offset)
ihwbegin(int offset)
{
if (stophist == 2 || strin)
return;
if (chwordpos%2)
chwordpos--; /* make sure we're on a word start, not end */
/* If we're expanding an alias, we should overwrite the expansion
@ -1023,15 +1076,18 @@ hwbegin(int offset)
/**/
void
hwend(void)
ihwend(void)
{
if (stophist == 2 || strin)
return;
if (chwordpos%2 && chline) {
/* end of word reached and we've already begun a word */
if (hptr > chline + chwords[chwordpos-1]) {
chwords[chwordpos++] = hptr - chline;
if (chwordpos >= chwordlen) {
chwords = (short *) realloc(chwords,
(chwordlen += 16)*sizeof(short));
(chwordlen += 32) *
sizeof(short));
}
if (hwgetword > -1) {
/* We want to reuse the current word position */
@ -1606,7 +1662,7 @@ readhistfile(char *fn, int err, int readflags)
else if (!lockhistfile(fn, 1))
return;
if ((in = fopen(unmeta(fn), "r"))) {
nwordlist = 16;
nwordlist = 64;
wordlist = (short *)zalloc(nwordlist*sizeof(short));
bufsiz = 1024;
buf = zalloc(bufsiz);
@ -1717,7 +1773,7 @@ readhistfile(char *fn, int err, int readflags)
if (*pt) {
if (nwordpos >= nwordlist)
wordlist = (short *) realloc(wordlist,
(nwordlist += 16)*sizeof(short));
(nwordlist += 64)*sizeof(short));
wordlist[nwordpos++] = pt - start;
while (*pt && !inblank(*pt))
pt++;

View file

@ -37,6 +37,14 @@
/**/
int noexitct = 0;
/* buffer for $_ and its length */
/**/
char *underscore;
/**/
int underscorelen;
/* what level of sourcing we are at */
/**/
@ -94,7 +102,7 @@ loop(int toplevel, int justonce)
if (interact)
preprompt();
}
hbegin(); /* init history mech */
hbegin(1); /* init history mech */
intr(); /* interrupts on */
lexinit(); /* initialize lexical state */
if (!(list = parse_event())) { /* if we couldn't parse a list */
@ -128,6 +136,8 @@ loop(int toplevel, int justonce)
if (stopmsg) /* unset 'you have stopped jobs' flag */
stopmsg--;
execlist(list, 0, 0);
if (toplevel)
freestructs();
tok = toksav;
if (toplevel)
noexitct = 0;
@ -550,8 +560,20 @@ setupvals(void)
cdpath = mkarray(NULL);
manpath = mkarray(NULL);
fignore = mkarray(NULL);
#ifdef FUNCTION_DIR
fpath = mkarray(ztrdup(FUNCTION_DIR));
#ifdef FPATH_DIR
# ifdef FPATH_SUBDIRS
{
char *fpath_subdirs[] = FPATH_SUBDIRS;
int len = sizeof(fpath_subdirs)/sizeof(char *), j;
fpath = zalloc((len+1)*sizeof(char *));
for (j = 0; j < len; j++)
fpath[j] = tricat(FPATH_DIR, "/", fpath_subdirs[j]);
fpath[len] = NULL;
}
# else
fpath = mkarray(ztrdup(FPATH_DIR));
# endif
#else
fpath = mkarray(NULL);
#endif
@ -582,7 +604,8 @@ setupvals(void)
ifs = ztrdup(DEFAULT_IFS);
wordchars = ztrdup(DEFAULT_WORDCHARS);
postedit = ztrdup("");
underscore = ztrdup("");
underscore = (char *) zalloc(underscorelen = 32);
*underscore = '\0';
zoptarg = ztrdup("");
zoptind = 1;

View file

@ -65,10 +65,6 @@ struct tms shtms;
/**/
int ttyfrozen;
/* empty job structure for quick clearing of jobtab entries */
static struct job zero; /* static variables are initialized to zero */
static struct timeval dtimeval, now;
/* Diff two timevals for elapsed-time computations */
@ -244,8 +240,11 @@ update_job(Job jn)
adjustwinsize(0);
}
}
} else if (list_pipe && (val & 0200) && inforeground == 1) {
breaks = loops;
errflag = 1;
inerrflush();
}
if (somestopped && jn->stat & STAT_SUPERJOB)
return;
jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED :
@ -663,14 +662,16 @@ deletejob(Job jn)
nx = pn->next;
zfree(pn, sizeof(struct process));
}
zsfree(jn->pwd);
deletefilelist(jn->filelist);
if (jn->ty)
zfree(jn->ty, sizeof(struct ttyinfo));
*jn = zero;
jn->gleader = jn->other = 0;
jn->stat = jn->stty_in_env = 0;
jn->procs = NULL;
jn->filelist = NULL;
jn->ty = NULL;
}
/* add a process to the current job */
@ -831,7 +832,12 @@ waitjob(int job, int sig)
void
waitjobs(void)
{
waitjob(thisjob, 0);
Job jn = jobtab + thisjob;
if (jn->procs)
waitjob(thisjob, 0);
else
deletejob(jn);
thisjob = -1;
}
@ -843,12 +849,9 @@ clearjobtab(void)
{
int i;
for (i = 1; i < MAXJOB; i++) {
if (jobtab[i].pwd)
zsfree(jobtab[i].pwd);
for (i = 1; i < MAXJOB; i++)
if (jobtab[i].ty)
zfree(jobtab[i].ty, sizeof(struct ttyinfo));
}
memset(jobtab, 0, sizeof(jobtab)); /* zero out table */
}
@ -864,7 +867,11 @@ initjob(void)
for (i = 1; i < MAXJOB; i++)
if (!jobtab[i].stat) {
jobtab[i].stat = STAT_INUSE;
jobtab[i].pwd = ztrdup(pwd);
if (strlen(pwd) >= PATH_MAX) {
memcpy(jobtab[i].pwd, pwd, PATH_MAX);
jobtab[i].pwd[PATH_MAX] = '\0';
} else
strcpy(jobtab[i].pwd, pwd);
jobtab[i].gleader = 0;
return i;
}

View file

@ -179,6 +179,12 @@ struct lexstack {
int hwgetword;
int lexstop;
struct heredocs *hdocs;
int (*hgetc) _((void));
void (*hungetc) _((int));
void (*hwaddc) _((int));
void (*hwbegin) _((int));
void (*hwend) _((void));
void (*addtoline) _((int));
unsigned char *cstack;
int csp;
@ -226,6 +232,12 @@ lexsave(void)
ls->hwgetword = hwgetword;
ls->lexstop = lexstop;
ls->hdocs = hdocs;
ls->hgetc = hgetc;
ls->hungetc = hungetc;
ls->hwaddc = hwaddc;
ls->hwbegin = hwbegin;
ls->hwend = hwend;
ls->addtoline = addtoline;
cmdsp = 0;
inredir = 0;
hdocs = NULL;
@ -271,6 +283,12 @@ lexrestore(void)
hwgetword = lstack->hwgetword;
lexstop = lstack->lexstop;
hdocs = lstack->hdocs;
hgetc = lstack->hgetc;
hungetc = lstack->hungetc;
hwaddc = lstack->hwaddc;
hwbegin = lstack->hwbegin;
hwend = lstack->hwend;
addtoline = lstack->addtoline;
hlinesz = lstack->hlinesz;
errflag = 0;
@ -783,7 +801,7 @@ gettok(void)
static int
gettokstr(int c, int sub)
{
int bct = 0, pct = 0, brct = 0;
int bct = 0, pct = 0, brct = 0, fdpar = 0;
int intpos = 1, in_brace_param = 0;
int peek, inquote;
#ifdef DEBUG
@ -798,8 +816,12 @@ gettokstr(int c, int sub)
for (;;) {
int act;
int e;
int inbl = inblank(c);
if (fdpar && !inbl && c != ')')
fdpar = 0;
if (inblank(c) && !in_brace_param && !pct)
if (inbl && !in_brace_param && !pct)
act = LX2_BREAK;
else {
act = lexact2[STOUC(c)];
@ -822,6 +844,12 @@ gettokstr(int c, int sub)
add(Meta);
break;
case LX2_OUTPAR:
if (fdpar) {
/* this is a single word `( )', treat as INOUTPAR */
add(c);
*bptr = '\0';
return INOUTPAR;
}
if ((sub || in_brace_param) && isset(SHGLOB))
break;
if (!in_brace_param && !pct--) {
@ -898,11 +926,40 @@ gettokstr(int c, int sub)
e = hgetc();
hungetc(e);
lexstop = 0;
if (e == ')' ||
(incmdpos && !brct && peek != ENVSTRING))
/* For command words, parentheses are only
* special at the start. But now we're tokenising
* the remaining string. So I don't see what
* the old incmdpos test here is for.
* pws 1999/6/8
*
* Oh, no.
* func1( )
* is a valid function definition in [k]sh. The best
* thing we can do, without really nasty lookahead tricks,
* is break if we find a blank after a parenthesis. At
* least this can't happen inside braces or brackets. We
* only allow this with SHGLOB (set for both sh and ksh).
*
* Things like `print @( |foo)' should still
* work, because [k]sh don't allow multiple words
* in a function definition, so we only do this
* in command position.
* pws 1999/6/14
*/
if (e == ')' || (isset(SHGLOB) && inblank(e) && !bct &&
!brct && !intpos && incmdpos))
goto brk;
}
pct++;
/*
* This also handles the [k]sh `foo( )' function definition.
* Maintain a variable fdpar, set as long as a single set of
* parentheses contains only space. Then if we get to the
* closing parenthesis and it is still set, we can assume we
* have a function definition. Only do this at the start of
* the word, since the (...) must be a separate token.
*/
if (!pct++ && isset(SHGLOB) && intpos && !bct && !brct)
fdpar = 1;
}
c = Inpar;
break;
@ -1294,8 +1351,7 @@ parsestr(char *s)
lexsave();
untokenize(s);
inpush(dupstring(s), 0, NULL);
strinbeg();
stophist = 2;
strinbeg(0);
len = 0;
bptr = tokstr = s;
bsiz = l + 1;
@ -1331,8 +1387,7 @@ parse_subst_string(char *s)
lexsave();
untokenize(s);
inpush(dupstring(s), 0, NULL);
strinbeg();
stophist = 2;
strinbeg(0);
len = 0;
bptr = tokstr = s;
bsiz = l + 1;
@ -1377,8 +1432,7 @@ exalias(void)
if (!tokstr) {
yytext = tokstrings[tok];
if (yytext)
yytext = dupstring(yytext);
return 0;
}

View file

@ -38,7 +38,7 @@ newlinklist(void)
{
LinkList list;
list = (LinkList) alloc(sizeof *list);
list = (LinkList) ncalloc(sizeof *list);
list->first = NULL;
list->last = (LinkNode) list;
return list;
@ -53,7 +53,7 @@ insertlinknode(LinkList list, LinkNode node, void *dat)
LinkNode tmp, new;
tmp = node->next;
node->next = new = (LinkNode) alloc(sizeof *tmp);
node->next = new = (LinkNode) ncalloc(sizeof *tmp);
new->last = node;
new->dat = dat;
new->next = tmp;

View file

@ -44,21 +44,18 @@ int contflag;
/**/
int breaks;
/**/
int
execfor(Cmd cmd)
execfor(Cmd cmd, LinkList args, int flags)
{
List list;
Forcmd node;
char *str;
int val = 0;
LinkList args;
zlong val = 0;
node = cmd->u.forcmd;
args = cmd->args;
if (node->condition) {
str = node->name;
str = dupstring(node->name);
singsub(&str);
if (!errflag)
matheval(str);
@ -69,7 +66,7 @@ execfor(Cmd cmd)
args = newlinklist();
for (x = pparams; *x; x++)
addlinknode(args, ztrdup(*x));
addlinknode(args, dupstring(*x));
}
lastval = 0;
loops++;
@ -95,13 +92,12 @@ execfor(Cmd cmd)
if (!val)
break;
} else {
str = (char *) ugetnode(args);
if (!str)
if (!args || !(str = (char *) ugetnode(args)))
break;
setsparam(node->name, ztrdup(str));
}
list = (List) dupstruct(node->list);
execlist(list, 1, (cmd->flags & CFLAG_EXEC) && empty(args));
execlist(node->list, 1,
(flags & CFLAG_EXEC) && args && empty(args));
if (breaks) {
breaks--;
if (breaks || !contflag)
@ -129,27 +125,24 @@ execfor(Cmd cmd)
/**/
int
execselect(Cmd cmd)
execselect(Cmd cmd, LinkList args, int flags)
{
List list;
Forcmd node;
char *str, *s;
LinkList args;
LinkNode n;
int i;
FILE *inp;
size_t more;
node = cmd->u.forcmd;
args = cmd->args;
if (!node->inflag) {
char **x;
args = newlinklist();
for (x = pparams; *x; x++)
addlinknode(args, ztrdup(*x));
addlinknode(args, dupstring(*x));
}
if (empty(args))
if (!args || empty(args))
return 1;
loops++;
lastval = 0;
@ -196,8 +189,7 @@ execselect(Cmd cmd)
str = "";
}
setsparam(node->name, ztrdup(str));
list = (List) dupstruct(node->list);
execlist(list, 1, 0);
execlist(node->list, 1, 0);
freeheap();
if (breaks) {
breaks--;
@ -278,9 +270,8 @@ selectlist(LinkList l, size_t start)
/**/
int
execwhile(Cmd cmd)
execwhile(Cmd cmd, LinkList args, int flags)
{
List list;
struct whilecmd *node;
int olderrexit, oldval;
@ -290,9 +281,8 @@ execwhile(Cmd cmd)
pushheap();
loops++;
for (;;) {
list = (List) dupstruct(node->cont);
noerrexit = 1;
execlist(list, 1, 0);
execlist(node->cont, 1, 0);
noerrexit = olderrexit;
if (!((lastval == 0) ^ node->cond)) {
if (breaks)
@ -300,8 +290,7 @@ execwhile(Cmd cmd)
lastval = oldval;
break;
}
list = (List) dupstruct(node->loop);
execlist(list, 1, 0);
execlist(node->loop, 1, 0);
if (breaks) {
breaks--;
if (breaks || !contflag)
@ -322,22 +311,20 @@ execwhile(Cmd cmd)
/**/
int
execrepeat(Cmd cmd)
execrepeat(Cmd cmd, LinkList args, int flags)
{
List list;
int count;
lastval = 0;
if (empty(cmd->args) || nextnode(firstnode(cmd->args))) {
if (!args || empty(args) || nextnode(firstnode(args))) {
zerr("bad argument for repeat", NULL, 0);
return 1;
}
count = atoi(peekfirst(cmd->args));
count = atoi(peekfirst(args));
pushheap();
loops++;
while (count--) {
list = (List) dupstruct(cmd->u.list);
execlist(list, 1, 0);
execlist(cmd->u.list, 1, 0);
freeheap();
if (breaks) {
breaks--;
@ -357,7 +344,7 @@ execrepeat(Cmd cmd)
/**/
int
execif(Cmd cmd)
execif(Cmd cmd, LinkList args, int flags)
{
struct ifcmd *node;
int olderrexit;
@ -380,7 +367,7 @@ execif(Cmd cmd)
noerrexit = olderrexit;
if (*t)
execlist(*t, 1, cmd->flags & CFLAG_EXEC);
execlist(*t, 1, flags & CFLAG_EXEC);
else
lastval = 0;
@ -389,7 +376,7 @@ execif(Cmd cmd)
/**/
int
execcase(Cmd cmd)
execcase(Cmd cmd, LinkList args, int flags)
{
struct casecmd *node;
char *word;
@ -400,18 +387,18 @@ execcase(Cmd cmd)
l = node->lists;
p = node->pats;
word = *p++;
word = dupstring(*p++);
singsub(&word);
untokenize(word);
lastval = 0;
if (node) {
while (*p) {
char *pat = *p + 1;
char *pat = dupstring(*p + 1);
singsub(&pat);
if (matchpat(word, pat)) {
do {
execlist(*l++, 1, **p == ';' && (cmd->flags & CFLAG_EXEC));
execlist(*l++, 1, **p == ';' && (flags & CFLAG_EXEC));
} while(**p++ == '&' && *p);
break;
}
@ -421,4 +408,3 @@ execcase(Cmd cmd)
}
return lastval;
}

View file

@ -733,9 +733,9 @@ mathevall(char *s, int prek, char **ep)
char *xptr;
zlong xyyval;
LV xyylval;
char **xlvals = 0;
char **xlvals = 0, *nlvals[LVCOUNT];
int xsp;
struct mathvalue *xstack = 0;
struct mathvalue *xstack = 0, nstack[STACKSZ];
zlong ret;
xlastbase = xnoeval = xunary = xlvc = xyyval = xyylval = xsp = 0;
@ -753,9 +753,10 @@ mathevall(char *s, int prek, char **ep)
xsp = sp;
xstack = stack;
}
stack = (struct mathvalue *)zalloc(STACKSZ*sizeof(struct mathvalue));
stack = nstack;
lastbase = -1;
lvals = (char **)zcalloc(LVCOUNT*sizeof(char *));
memset(nlvals, 0, LVCOUNT*sizeof(char *));
lvals = nlvals;
lvc = 0;
ptr = s;
sp = -1;
@ -769,8 +770,6 @@ mathevall(char *s, int prek, char **ep)
ret = stack[0].val;
zfree(lvals, LVCOUNT*sizeof(char *));
zfree(stack, STACKSZ*sizeof(struct mathvalue));
if (--mlevel) {
lastbase = xlastbase;
noeval = xnoeval;
@ -827,7 +826,8 @@ mathevalarg(char *s, char **ss)
static void
mathparse(int pc)
{
int q, otok, onoeval;
zlong q;
int otok, onoeval;
if (errflag)
return;

View file

@ -97,7 +97,7 @@ static int h_m[1025], h_push, h_pop, h_free;
#endif
#define H_ISIZE sizeof(zlong)
#define HEAPSIZE (8192 - H_ISIZE)
#define HEAPSIZE (16384 - H_ISIZE)
#define HEAP_ARENA_SIZE (HEAPSIZE - sizeof(struct heap))
#define HEAPFREE (16384 - H_ISIZE)
@ -133,6 +133,10 @@ global_permalloc(void)
static Heap heaps;
/* first heap with free space, not always correct */
static Heap fheap;
/* Use new heaps from now on. This returns the old heap-list. */
/**/
@ -141,7 +145,7 @@ new_heaps(void)
{
Heap h = heaps;
heaps = NULL;
fheap = heaps = NULL;
return h;
}
@ -160,6 +164,7 @@ old_heaps(Heap old)
zfree(h, sizeof(*h));
}
heaps = old;
fheap = NULL;
}
/* Temporarily switch to other heaps (or back again). */
@ -171,6 +176,7 @@ switch_heaps(Heap new)
Heap h = heaps;
heaps = new;
fheap = NULL;
return h;
}
@ -208,6 +214,8 @@ freeheap(void)
#if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
h_free++;
#endif
fheap = NULL;
for (h = heaps; h; h = hn) {
hn = h->next;
if (h->sp) {
@ -215,6 +223,8 @@ freeheap(void)
memset(arena(h) + h->sp->used, 0xff, h->used - h->sp->used);
#endif
h->used = h->sp->used;
if (!fheap && h->used < HEAP_ARENA_SIZE)
fheap = h;
hl = h;
} else
zfree(h, HEAPSIZE);
@ -238,6 +248,7 @@ popheap(void)
h_pop++;
#endif
fheap = NULL;
for (h = heaps; h; h = hn) {
hn = h->next;
if ((hs = h->sp)) {
@ -246,6 +257,8 @@ popheap(void)
memset(arena(h) + hs->used, 0xff, h->used - hs->used);
#endif
h->used = hs->used;
if (!fheap && h->used < HEAP_ARENA_SIZE)
fheap = h;
zfree(hs, sizeof(*hs));
hl = h;
@ -275,13 +288,12 @@ zhalloc(size_t size)
/* find a heap with enough free space */
for (h = heaps; h; h = h->next) {
for (h = (fheap ? fheap : heaps); h; h = h->next) {
if (HEAP_ARENA_SIZE >= (n = size + h->used)) {
h->used = n;
return arena(h) + n - size;
}
}
{
Heap hp;
/* not found, allocate new heap */
@ -311,6 +323,7 @@ zhalloc(size_t size)
hp->next = h;
else
heaps = h;
fheap = NULL;
unqueue_signals();
return arena(h);
@ -361,6 +374,7 @@ hrealloc(char *p, size_t old, size_t new)
ph->next = h->next;
else
heaps = h->next;
fheap = NULL;
zfree(h, HEAPSIZE);
return NULL;
}
@ -593,6 +607,16 @@ struct m_hdr {
#define M_ISIZE (sizeof(zlong))
#define M_MIN (2 * M_ISIZE)
/* M_FREE is the number of bytes that have to be free before memory is
* given back to the system
* M_KEEP is the number of bytes that will be kept when memory is given
* back; note that this has to be less than M_FREE
* M_ALLOC is the number of extra bytes to request from the system */
#define M_FREE 65536
#define M_KEEP 32768
#define M_ALLOC M_KEEP
/* a pointer to the last free block, a pointer to the free list (the blocks
on this list are kept in order - lowest address first) */
@ -623,13 +647,13 @@ static char *m_high, *m_low;
#define M_SIDX(S) ((S) / M_ISIZE)
#define M_SNUM 50
#define M_SNUM 128
#define M_SLEN(M) ((M)->len / M_SNUM)
#define M_SBLEN(S) ((S) * M_SNUM + sizeof(struct m_shdr *) + \
sizeof(zlong) + sizeof(struct m_hdr *))
#define M_BSLEN(S) (((S) - sizeof(struct m_shdr *) - \
sizeof(zlong) - sizeof(struct m_hdr *)) / M_SNUM)
#define M_NSMALL 8
#define M_NSMALL 13
static struct m_hdr *m_small[M_NSMALL];
@ -691,9 +715,9 @@ malloc(MALLOC_ARG_T size)
m->used++;
/* if all small blocks in this block are allocated, the block is
put at the end of the list blocks wth small blocks of this
put at the end of the list blocks with small blocks of this
size (i.e., we try to keep blocks with free blocks at the
beginning of the list, to make the search faster */
beginning of the list, to make the search faster) */
if (m->used == M_SNUM && m->next) {
for (mt = m; mt->next; mt = mt->next);
@ -753,15 +777,24 @@ malloc(MALLOC_ARG_T size)
for (mp = NULL, m = m_free; m && m->len < size; mp = m, m = m->next);
}
if (!m) {
long nal;
/* no matching free block was found, we have to request new
memory from the system */
n = (size + M_HSIZE + m_pgsz - 1) & ~(m_pgsz - 1);
n = (size + M_HSIZE + M_ALLOC + m_pgsz - 1) & ~(m_pgsz - 1);
if (((char *)(m = (struct m_hdr *)sbrk(n))) == ((char *)-1)) {
DPUTS(1, "MEM: allocation error at sbrk.");
unqueue_signals();
return NULL;
}
if ((nal = ((long)(char *)m) & (M_ALIGN-1))) {
if ((char *)sbrk(M_ALIGN - nal) == (char *)-1) {
DPUTS(1, "MEM: allocation error at sbrk.");
unqueue_signals();
return NULL;
}
m = (struct m_hdr *) ((char *)m + (M_ALIGN - nal));
}
/* set m_low, for the check in free() */
if (!m_low)
m_low = (char *)m;
@ -1034,8 +1067,8 @@ zfree(void *p, int sz)
and now there is more than one page size of memory, we can give
it back to the system (and we do it ;-) */
if ((((char *)m_lfree) + M_ISIZE + m_lfree->len) == m_high &&
m_lfree->len >= m_pgsz + M_MIN) {
long n = (m_lfree->len - M_MIN) & ~(m_pgsz - 1);
m_lfree->len >= m_pgsz + M_MIN + M_FREE) {
long n = (m_lfree->len - M_MIN - M_KEEP) & ~(m_pgsz - 1);
m_lfree->len -= n;
if (brk(m_high -= n) == -1) {

View file

@ -52,7 +52,6 @@ char **pparams, /* $argv */
/**/
char *argzero, /* $0 */
*underscore, /* $_ */
*home, /* $HOME */
*hostnam, /* $HOST */
*ifs, /* $IFS */
@ -232,11 +231,6 @@ IPDEF9("manpath", &manpath, "MANPATH"),
IPDEF9("psvar", &psvar, "PSVAR"),
IPDEF9("watch", &watch, "WATCH"),
/*TEST BEGIN*/
#define IPDEF10(A) {NULL,A,PM_HASHED|PM_SPECIAL|PM_DONTIMPORT,BR((void *)0),SFN(hashsetfn),GFN(hashgetfn),stdunsetfn,0,NULL,NULL,NULL,0}
IPDEF10("testhash"),
/*TEST END*/
#ifdef DYNAMIC
IPDEF9F("module_path", &module_path, "MODULE_PATH", PM_RESTRICTED),
#endif
@ -723,16 +717,13 @@ isident(char *s)
#endif
}
static char **garr;
/**/
static zlong
getarg(char **str, int *inv, Value v, int a2, zlong *w)
{
int num = 1, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash;
int beg = 0, hasbeg = 0;
int hasbeg = 0, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash;
char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt;
zlong r = 0;
zlong num = 1, beg = 0, r = 0;
Comp c;
ishash = (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED);
@ -1147,7 +1138,6 @@ fetchvalue(char **pptr, int bracks, int flags)
int ppar = 0;
s = t = *pptr;
garr = NULL;
if (idigit(*s)) {
if (bracks >= 0)
@ -1638,7 +1628,7 @@ setaparam(char *s, char **val)
if (!(v = getvalue(&s, 1)))
createparam(t, PM_ARRAY);
*ss = '[';
if (PM_TYPE(v->pm->flags) == PM_HASHED) {
if (v && PM_TYPE(v->pm->flags) == PM_HASHED) {
zerr("attempt to set slice of associative array", NULL, 0);
freearray(val);
errflag = 1;
@ -2466,7 +2456,10 @@ wordcharssetfn(Param pm, char *x)
char *
underscoregetfn(Param pm)
{
return underscore;
char *u = dupstring(underscore);
untokenize(u);
return u;
}
/* Function to get value for special parameter `TERM' */

View file

@ -298,6 +298,8 @@ par_pline(void)
rdr->type = MERGEOUT;
rdr->fd1 = 2;
rdr->name = dupstring("1");
if (!c->redir)
c->redir = newlinklist();
addlinknode(c->redir, rdr);
cmdpush(CS_ERRPIPE);
@ -330,11 +332,14 @@ par_cmd(void)
c = (Cmd) make_cmd();
c->lineno = lineno;
c->args = newlinklist();
c->redir = newlinklist();
c->vars = newlinklist();
while (IS_REDIROP(tok))
par_redir(c->redir);
c->args = NULL;
c->vars = NULL;
if (IS_REDIROP(tok)) {
c->redir = newlinklist();
while (IS_REDIROP(tok))
par_redir(c->redir);
} else
c->redir = NULL;
switch (tok) {
case FOR:
cmdpush(CS_FOR);
@ -399,6 +404,8 @@ par_cmd(void)
break;
case DINPAR:
c->type = CARITH;
if (!c->args)
c->args = newlinklist();
addlinknode(c->args, tokstr);
yylex();
break;
@ -407,8 +414,12 @@ par_cmd(void)
return NULL;
break;
}
while (IS_REDIROP(tok))
par_redir(c->redir);
if (IS_REDIROP(tok)) {
if (!c->redir)
c->redir = newlinklist();
while (IS_REDIROP(tok))
par_redir(c->redir);
}
incmdpos = 1;
incasepat = 0;
incond = 0;
@ -460,6 +471,8 @@ par_for(Cmd c)
f->inflag = 1;
incmdpos = 0;
yylex();
if (!c->args)
c->args = newlinklist();
c->args = par_wordlist();
if (tok != SEPER)
YYERRORV;
@ -467,6 +480,8 @@ par_for(Cmd c)
f->inflag = 1;
incmdpos = 0;
yylex();
if (!c->args)
c->args = newlinklist();
c->args = par_nl_wordlist();
if (tok != OUTPAR)
YYERRORV;
@ -819,6 +834,8 @@ par_repeat(Cmd c)
yylex();
if (tok != STRING)
YYERRORV;
if (!c->args)
c->args = newlinklist();
addlinknode(c->args, tokstr);
incmdpos = 1;
yylex();
@ -966,6 +983,8 @@ par_simple(Cmd c)
v->str = p + 1;
} else
equalsplit(tokstr, &v->str);
if (!c->vars)
c->vars = newlinklist();
addlinknode(c->vars, v);
isnull = 0;
} else if (tok == ENVARRAY) {
@ -982,6 +1001,8 @@ par_simple(Cmd c)
if (tok != OUTPAR)
YYERROR;
incmdpos = oldcmdpos;
if (!c->vars)
c->vars = newlinklist();
addlinknode(c->vars, v);
isnull = 0;
} else
@ -993,9 +1014,13 @@ par_simple(Cmd c)
for (;;) {
if (tok == STRING) {
incmdpos = 0;
if (!c->args)
c->args = newlinklist();
addlinknode(c->args, tokstr);
yylex();
} else if (IS_REDIROP(tok)) {
if (!c->redir)
c->redir = newlinklist();
par_redir(c->redir);
} else if (tok == INOUTPAR) {
incmdpos = 1;
@ -1011,15 +1036,26 @@ par_simple(Cmd c)
YYERROR;
}
yylex();
} else
c->u.list = (List) expandstruct((struct node *) par_cmd(), N_LIST);
} else {
List l;
Sublist sl;
Pline pl;
l = (List) allocnode(N_LIST);
l->type = Z_SYNC;
l->left = sl = (Sublist) allocnode(N_SUBLIST);
sl->type = END;
sl->left = pl = (Pline) allocnode(N_PLINE);
pl->type = END;
pl->left = par_cmd();
}
cmdpop();
c->type = FUNCDEF;
} else
break;
isnull = 0;
}
if (isnull && empty(c->redir))
if (isnull && (!c->redir || empty(c->redir)))
return NULL;
incmdpos = 1;
return c;

View file

@ -719,7 +719,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
freelinklist(args, (FreeFunc) NULL);
zsfree(name);
} else HEAPALLOC {
execlist(dupstruct(sigfn), 1, 0);
execlist(sigfn, 1, 0);
} LASTALLOC;
if (trapreturn > 0)
trapret = trapreturn;

View file

@ -53,9 +53,9 @@ prefork(LinkList list, int flags)
MUSTUSEHEAP("prefork");
for (node = firstnode(list); node; incnode(node)) {
char *str, *str3;
char *str;
str = str3 = (char *)getdata(node);
str = (char *)getdata(node);
if ((*str == Inang || *str == Outang || *str == Equals) &&
str[1] == Inpar) {
if (*str == Inang || *str == Outang)

View file

@ -169,7 +169,6 @@ gettext2(struct node *n)
if (_List(n)->type & Z_DISOWN)
taddstr("|");
}
simplifyright(_List(n));
if (_List(n)->right) {
if (tnewlins)
taddnl();
@ -460,22 +459,23 @@ getsimptext(Cmd cmd)
{
LinkNode n;
for (n = firstnode(cmd->vars); n; incnode(n)) {
struct varasg *v = (struct varasg *)getdata(n);
if (cmd->vars)
for (n = firstnode(cmd->vars); n; incnode(n)) {
struct varasg *v = (struct varasg *)getdata(n);
taddstr(v->name);
taddchr('=');
if (PM_TYPE(v->type) == PM_ARRAY) {
taddchr('(');
taddlist(v->arr);
taddstr(") ");
} else if (PM_TYPE(v->type) == PM_HASHED) {
/* XXX */
} else {
taddstr(v->str);
taddchr(' ');
taddstr(v->name);
taddchr('=');
if (PM_TYPE(v->type) == PM_ARRAY) {
taddchr('(');
taddlist(v->arr);
taddstr(") ");
} else if (PM_TYPE(v->type) == PM_HASHED) {
/* XXX */
} else {
taddstr(v->str);
taddchr(' ');
}
}
}
taddlist(cmd->args);
}
@ -490,6 +490,8 @@ getredirs(Cmd cmd)
"<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">"
};
if (!cmd->redir)
return;
taddchr(' ');
for (n = firstnode(cmd->redir); n; incnode(n)) {
struct redir *f = (struct redir *)getdata(n);
@ -537,7 +539,7 @@ taddlist(LinkList l)
{
LinkNode n;
if (!(n = firstnode(l)))
if (!l || !(n = firstnode(l)))
return;
for (; n; incnode(n)) {
taddstr(getdata(n));

View file

@ -853,61 +853,131 @@ int resetneeded;
int winchanged;
#endif
/* check the size of the window and adjust if necessary. *
* The value of from: *
* 0: called from update_job or setupvals *
* 1: called from the SIGWINCH handler *
* 2: the user have just changed LINES manually *
* 3: the user have just changed COLUMNS manually */
/**/
void
adjustwinsize(int from)
static int
adjustlines(int signalled)
{
int oldcols = columns, oldrows = lines;
int oldlines = lines;
#ifdef TIOCGWINSZ
static int userlines, usercols;
if (SHTTY == -1)
return;
if (from == 2)
userlines = lines > 0;
if (from == 3)
usercols = columns > 0;
if (!ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize)) {
if (!userlines || from == 1)
lines = shttyinfo.winsize.ws_row;
if (!usercols || from == 1)
columns = shttyinfo.winsize.ws_col;
}
#endif /* TIOCGWINSZ */
if (lines <= 0)
if (signalled || lines <= 0)
lines = shttyinfo.winsize.ws_row;
else
shttyinfo.winsize.ws_row = lines;
#endif /* TIOCGWINSZ */
if (lines <= 0) {
DPUTS(signalled, "BUG: Impossible TIOCGWINSZ rows");
lines = tclines > 0 ? tclines : 24;
if (columns <= 0)
columns = tccolumns > 0 ? tccolumns : 80;
}
if (lines > 2)
termflags &= ~TERM_SHORT;
else
termflags |= TERM_SHORT;
return (lines != oldlines);
}
static int
adjustcolumns(int signalled)
{
int oldcolumns = columns;
#ifdef TIOCGWINSZ
if (signalled || columns <= 0)
columns = shttyinfo.winsize.ws_col;
else
shttyinfo.winsize.ws_col = columns;
#endif /* TIOCGWINSZ */
if (columns <= 0) {
DPUTS(signalled, "BUG: Impossible TIOCGWINSZ cols");
columns = tccolumns > 0 ? tccolumns : 80;
}
if (columns > 2)
termflags &= ~TERM_NARROW;
else
termflags |= TERM_NARROW;
return (columns != oldcolumns);
}
/* check the size of the window and adjust if necessary. *
* The value of from: *
* 0: called from update_job or setupvals *
* 1: called from the SIGWINCH handler *
* 2: called from the LINES parameter callback *
* 3: called from the COLUMNS parameter callback */
/**/
void
adjustwinsize(int from)
{
static int getwinsz = 1;
int ttyrows = shttyinfo.winsize.ws_row;
int ttycols = shttyinfo.winsize.ws_col;
int resetzle = 0;
if (getwinsz || from == 1) {
#ifdef TIOCGWINSZ
if (interact && from >= 2) {
shttyinfo.winsize.ws_row = lines;
shttyinfo.winsize.ws_col = columns;
if (SHTTY == -1)
return;
if (ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize) == 0) {
resetzle = (ttyrows != shttyinfo.winsize.ws_row ||
ttycols != shttyinfo.winsize.ws_col);
if (from == 0 && resetzle && ttyrows && ttycols)
from = 1; /* Signal missed while a job owned the tty? */
ttyrows = shttyinfo.winsize.ws_row;
ttycols = shttyinfo.winsize.ws_col;
} else {
/* Set to unknown on failure */
shttyinfo.winsize.ws_row = 0;
shttyinfo.winsize.ws_col = 0;
resetzle = 1;
}
#else
resetzle = from == 1;
#endif /* TIOCGWINSZ */
} /* else
return; */
switch (from) {
case 0:
case 1:
getwinsz = 0;
/* Calling setiparam() here calls this function recursively, but *
* because we've already called adjustlines() and adjustcolumns() *
* here, recursive calls are no-ops unless a signal intervenes. *
* The commented "else return;" above might be a safe shortcut, *
* but I'm concerned about what happens on race conditions; e.g., *
* suppose the user resizes his xterm during `eval $(resize)'? */
if (adjustlines(from) && zgetenv("LINES"))
setiparam("LINES", lines);
if (adjustcolumns(from) && zgetenv("COLUMNS"))
setiparam("COLUMNS", columns);
getwinsz = 1;
break;
case 2:
resetzle = adjustlines(0);
break;
case 3:
resetzle = adjustcolumns(0);
break;
}
#ifdef TIOCGWINSZ
if (interact && from >= 2 &&
(shttyinfo.winsize.ws_row != ttyrows ||
shttyinfo.winsize.ws_col != ttycols)) {
/* shttyinfo.winsize is already set up correctly */
ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize);
}
#endif
#endif /* TIOCGWINSZ */
if (zleactive && (from >= 2 || oldcols != columns || oldrows != lines)) {
resetneeded = winchanged = 1;
if (zleactive && resetzle) {
#ifdef TIOCGWINSZ
winchanged =
#endif /* TIOCGWINSZ */
resetneeded = 1;
zrefresh();
}
}
@ -1733,13 +1803,12 @@ char *
sepjoin(char **s, char *sep)
{
char *r, *p, **t;
int l, sl, elide = 0;
int l, sl;
char sepbuf[3];
if (!*s)
return "";
if (!sep) {
elide = 1;
sep = sepbuf;
sepbuf[0] = *ifs;
sepbuf[1] = *ifs == Meta ? ifs[1] ^ 32 : '\0';
@ -1853,329 +1922,21 @@ allocnode(int type)
{
struct node *n;
n = (struct node *) alloc(sizetab[type]);
n = (struct node *) ncalloc(sizetab[type]);
memset((void *) n, 0, sizetab[type]);
n->ntype = flagtab[type];
if (useheap)
n->ntype |= NT_HEAP;
return (void *) n;
}
/* duplicate a syntax tree */
/**/
void *
dupstruct(void *a)
{
struct node *n, *r;
n = (struct node *) a;
if (!a || ((List) a) == &dummy_list)
return (void *) a;
if ((n->ntype & NT_HEAP) && !useheap) {
HEAPALLOC {
n = (struct node *) dupstruct2((void *) n);
} LASTALLOC;
n = simplifystruct(n);
}
r = (struct node *)dupstruct2((void *) n);
if (!(n->ntype & NT_HEAP) && useheap)
r = expandstruct(r, N_LIST);
return (void *) r;
}
/**/
static struct node *
simplifystruct(struct node *n)
{
if (!n || ((List) n) == &dummy_list)
return n;
switch (NT_TYPE(n->ntype)) {
case N_LIST:
{
List l = (List) n;
l->left = (Sublist) simplifystruct((struct node *)l->left);
if ((l->type & Z_SYNC) && !l->right)
return (struct node *)l->left;
}
break;
case N_SUBLIST:
{
Sublist sl = (Sublist) n;
sl->left = (Pline) simplifystruct((struct node *)sl->left);
if (sl->type == END && !sl->flags && !sl->right)
return (struct node *)sl->left;
}
break;
case N_PLINE:
{
Pline pl = (Pline) n;
pl->left = (Cmd) simplifystruct((struct node *)pl->left);
if (pl->type == END && !pl->right)
return (struct node *)pl->left;
}
break;
case N_CMD:
{
Cmd c = (Cmd) n;
int i = 0;
if (empty(c->args))
c->args = NULL, i++;
if (empty(c->redir))
c->redir = NULL, i++;
if (empty(c->vars))
c->vars = NULL, i++;
c->u.list = (List) simplifystruct((struct node *)c->u.list);
if (i == 3 && !c->flags &&
(c->type == CWHILE || c->type == CIF ||
c->type == COND))
return (struct node *)c->u.list;
}
break;
case N_FOR:
{
Forcmd f = (Forcmd) n;
f->list = (List) simplifystruct((struct node *)f->list);
}
break;
case N_CASE:
{
struct casecmd *c = (struct casecmd *)n;
List *l;
for (l = c->lists; *l; l++)
*l = (List) simplifystruct((struct node *)*l);
}
break;
case N_IF:
{
struct ifcmd *i = (struct ifcmd *)n;
List *l;
for (l = i->ifls; *l; l++)
*l = (List) simplifystruct((struct node *)*l);
for (l = i->thenls; *l; l++)
*l = (List) simplifystruct((struct node *)*l);
}
break;
case N_WHILE:
{
struct whilecmd *w = (struct whilecmd *)n;
w->cont = (List) simplifystruct((struct node *)w->cont);
w->loop = (List) simplifystruct((struct node *)w->loop);
}
}
return n;
}
/**/
struct node *
expandstruct(struct node *n, int exp)
{
struct node *m;
if (!n || ((List) n) == &dummy_list)
return n;
if (exp != N_COUNT && exp != NT_TYPE(n->ntype)) {
switch (exp) {
case N_LIST:
{
List l;
m = (struct node *) allocnode(N_LIST);
l = (List) m;
l->type = Z_SYNC;
l->left = (Sublist) expandstruct(n, N_SUBLIST);
return (struct node *)l;
}
case N_SUBLIST:
{
Sublist sl;
m = (struct node *) allocnode(N_SUBLIST);
sl = (Sublist) m;
sl->type = END;
sl->left = (Pline) expandstruct(n, N_PLINE);
return (struct node *)sl;
}
case N_PLINE:
{
Pline pl;
m = (struct node *) allocnode(N_PLINE);
pl = (Pline) m;
pl->type = END;
pl->left = (Cmd) expandstruct(n, N_CMD);
return (struct node *)pl;
}
case N_CMD:
{
Cmd c;
m = (struct node *) allocnode(N_CMD);
c = (Cmd) m;
switch (NT_TYPE(n->ntype)) {
case N_WHILE:
c->type = CWHILE;
break;
case N_IF:
c->type = CIF;
break;
case N_COND:
c->type = COND;
}
c->u.list = (List) expandstruct(n, NT_TYPE(n->ntype));
c->args = newlinklist();
c->vars = newlinklist();
c->redir = newlinklist();
return (struct node *)c;
}
}
} else
switch (NT_TYPE(n->ntype)) {
case N_LIST:
{
List l = (List) n;
l->left = (Sublist) expandstruct((struct node *)l->left,
N_SUBLIST);
l->right = (List) expandstruct((struct node *)l->right,
N_LIST);
}
break;
case N_SUBLIST:
{
Sublist sl = (Sublist) n;
sl->left = (Pline) expandstruct((struct node *)sl->left,
N_PLINE);
sl->right = (Sublist) expandstruct((struct node *)sl->right,
N_SUBLIST);
}
break;
case N_PLINE:
{
Pline pl = (Pline) n;
pl->left = (Cmd) expandstruct((struct node *)pl->left,
N_CMD);
pl->right = (Pline) expandstruct((struct node *)pl->right,
N_PLINE);
}
break;
case N_CMD:
{
Cmd c = (Cmd) n;
if (!c->args)
c->args = newlinklist();
if (!c->vars)
c->vars = newlinklist();
if (!c->redir)
c->redir = newlinklist();
switch (c->type) {
case CFOR:
case CSELECT:
c->u.list = (List) expandstruct((struct node *)c->u.list,
N_FOR);
break;
case CWHILE:
c->u.list = (List) expandstruct((struct node *)c->u.list,
N_WHILE);
break;
case CIF:
c->u.list = (List) expandstruct((struct node *)c->u.list,
N_IF);
break;
case CCASE:
c->u.list = (List) expandstruct((struct node *)c->u.list,
N_CASE);
break;
case COND:
c->u.list = (List) expandstruct((struct node *)c->u.list,
N_COND);
break;
case ZCTIME:
c->u.list = (List) expandstruct((struct node *)c->u.list,
N_SUBLIST);
break;
case AUTOFN:
c->u.list = (List) expandstruct((struct node *)c->u.list,
N_AUTOFN);
break;
default:
c->u.list = (List) expandstruct((struct node *)c->u.list,
N_LIST);
}
}
break;
case N_FOR:
{
Forcmd f = (Forcmd) n;
f->list = (List) expandstruct((struct node *)f->list,
N_LIST);
}
break;
case N_CASE:
{
struct casecmd *c = (struct casecmd *)n;
List *l;
for (l = c->lists; *l; l++)
*l = (List) expandstruct((struct node *)*l, N_LIST);
}
break;
case N_IF:
{
struct ifcmd *i = (struct ifcmd *)n;
List *l;
for (l = i->ifls; *l; l++)
*l = (List) expandstruct((struct node *)*l, N_LIST);
for (l = i->thenls; *l; l++)
*l = (List) expandstruct((struct node *)*l, N_LIST);
}
break;
case N_WHILE:
{
struct whilecmd *w = (struct whilecmd *)n;
w->cont = (List) expandstruct((struct node *)w->cont,
N_LIST);
w->loop = (List) expandstruct((struct node *)w->loop,
N_LIST);
}
}
return n;
}
/* duplicate a syntax tree */
/**/
static void *
dupstruct2(void *a)
{
void **onodes, **nnodes, *ret, *n, *on;
int type, heap;
int type;
size_t nodeoffs;
if (!a || ((List) a) == &dummy_list)
@ -2183,53 +1944,33 @@ dupstruct2(void *a)
type = *(int *)a;
ret = alloc(sizetab[NT_TYPE(type)]);
memcpy(ret, a, nodeoffs = offstab[NT_TYPE(type)]);
*(int*)ret = (type & ~NT_HEAP) | (useheap ? NT_HEAP : 0);
onodes = (void **) ((char *)a + nodeoffs);
nnodes = (void **) ((char *)ret + nodeoffs);
heap = type & NT_HEAP;
for (type = (type & 0xffff00) >> 4; (type >>= 4); *nnodes++ = n) {
if (!(on = *onodes++))
n = NULL;
else {
switch (type & 0xf) {
case NT_NODE:
n = dupstruct2(on);
n = dupstruct(on);
break;
case NT_STR:
n = dupstring(on);
break;
case NT_LIST | NT_NODE:
if (heap) {
if (useheap)
n = duplist(on, (VFunc) dupstruct2);
else
n = list2arr(on, (VFunc) dupstruct2);
}
else if (useheap)
n = arr2list(on, (VFunc) dupstruct2);
else
n = duparray(on, (VFunc) dupstruct2);
n = duplist(on, (VFunc) dupstruct);
break;
case NT_LIST | NT_STR:
if (heap) {
if (useheap)
n = duplist(on, (VFunc) dupstring);
else
n = list2arr(on, (VFunc) ztrdup);
}
else if (useheap)
n = arr2list(on, (VFunc) dupstring);
else
n = duparray(on, (VFunc) ztrdup);
n = duplist(on, (VFunc) (useheap ? dupstring : ztrdup));
break;
case NT_NODE | NT_ARR:
n = duparray(on, (VFunc) dupstruct2);
n = duparray(on, (VFunc) dupstruct);
break;
case NT_STR | NT_ARR:
n = duparray(on, (VFunc) (useheap ? dupstring : ztrdup));
break;
default:
DPUTS(1, "BUG: bad node type in dupstruct2()");
DPUTS(1, "BUG: bad node type in dupstruct()");
abort();
}
}
@ -2237,19 +1978,46 @@ dupstruct2(void *a)
return ret;
}
/* free a syntax tree */
/* Free a syntax tree. Now, freestruct() only registers everything that
* has to be freed. Later, freestructs() will be called to do the real
* work. This is to avoid having functions that are currently executed
* free themselves by re-defining themselves. */
static LinkList freeslist = NULL;
/**/
void
freestruct(void *a)
{
void **nodes, *n;
int type, size;
if (!a || ((List) a) == &dummy_list)
return;
type = * (int *) a;
PERMALLOC {
if (!freeslist)
freeslist = newlinklist();
addlinknode(freeslist, a);
} LASTALLOC;
}
/**/
void
freestructs(void)
{
void *a;
if (freeslist)
while ((a = getlinknode(freeslist)))
ifreestruct(a);
}
/**/
static void
ifreestruct(void *a)
{
void **nodes, *n;
int type, size;
type = *(int *) a;
nodes = (void **) ((char *)a + offstab[NT_TYPE(type)]);
size = sizetab[NT_TYPE(type)];
for (type = (type & 0xffff00) >> 4; (type >>= 4);) {
@ -2262,6 +2030,8 @@ freestruct(void *a)
zsfree((char *) n);
break;
case NT_LIST | NT_NODE:
freelinklist((LinkList) n, (FreeFunc) freestruct);
break;
case NT_NODE | NT_ARR:
{
void **p = (void **) n;
@ -2272,6 +2042,8 @@ freestruct(void *a)
break;
}
case NT_LIST | NT_STR:
freelinklist((LinkList) n, (FreeFunc) zsfree);
break;
case NT_STR | NT_ARR:
freearray((char **) n);
break;
@ -2286,59 +2058,47 @@ freestruct(void *a)
zfree(a, size);
}
/**/
LinkList
dupheaplist(LinkList l)
{
if (!l)
return NULL;
return duplist(l, (VFunc) dupstruct);
}
/**/
static LinkList
duplist(LinkList l, VFunc func)
{
LinkList ret;
LinkNode node;
if (l && nonempty(l)) {
LinkList ret;
LinkNode node;
ret = newlinklist();
for (node = firstnode(l); node; incnode(node))
addlinknode(ret, func(getdata(node)));
return ret;
ret = newlinklist();
for (node = firstnode(l); node; incnode(node))
addlinknode(ret, func(getdata(node)));
return ret;
}
return NULL;
}
/**/
char **
duparray(char **arr, VFunc func)
{
char **ret, **rr;
if (arr && *arr) {
char **ret, **rr, *p;
ret = (char **) alloc((arrlen(arr) + 1) * sizeof(char *));
for (rr = ret; *arr;)
*rr++ = (char *)func(*arr++);
*rr = NULL;
ret = (char **) alloc((arrlen(arr) + 1) * sizeof(char *));
for (rr = ret; (p = *arr++);)
*rr++ = (char *)func(p);
*rr = NULL;
return ret;
}
/**/
static char **
list2arr(LinkList l, VFunc func)
{
char **arr, **r;
LinkNode n;
arr = r = (char **) alloc((countlinknodes(l) + 1) * sizeof(char *));
for (n = firstnode(l); n; incnode(n))
*r++ = (char *)func(getdata(n));
*r = NULL;
return arr;
}
/**/
static LinkList
arr2list(char **arr, VFunc func)
{
LinkList l = newlinklist();
while (*arr)
addlinknode(l, func(*arr++));
return l;
return ret;
}
return NULL;
}
/**/
@ -2384,28 +2144,6 @@ equalsplit(char *s, char **t)
return 0;
}
/* see if the right side of a list is trivial */
/**/
void
simplifyright(List l)
{
Cmd c;
if (l == &dummy_list || !l->right)
return;
if (l->right->right || l->right->left->right ||
l->right->left->flags || l->right->left->left->right ||
l->left->flags)
return;
c = l->left->left->left;
if (c->type != SIMPLE || nonempty(c->args) || nonempty(c->redir)
|| nonempty(c->vars))
return;
l->right = NULL;
return;
}
/* the ztypes table */
/**/
@ -2470,6 +2208,25 @@ arrdup(char **s)
return y;
}
/* Duplicate a list of strings. */
/**/
LinkList
listdup(LinkList l)
{
if (!l)
return NULL;
else {
LinkList r = newlinklist();
LinkNode n;
for (n = firstnode(l); n; incnode(n))
addlinknode(r, dupstring((char *) getdata(n)));
return r;
}
}
/**/
char **
listarr(LinkList l)

View file

@ -75,6 +75,7 @@ findcmd
firsthist
freearray
freeheap
freelinklist
freestruct
getaparam
gethashnode
@ -113,6 +114,7 @@ hist_skip_flags
holdintr
hptr
hrealloc
ifs
inbufct
incmdpos
incond
@ -179,7 +181,6 @@ path
pathchecked
popheap
postedit
pparams
ppid
prefork
prepromptfns

View file

@ -47,7 +47,11 @@
*/
#ifdef ZSH_64_BIT_TYPE
typedef ZSH_64_BIT_TYPE zlong;
typedef unsigned ZSH_64_BIT_TYPE zulong;
#ifdef ZSH_64_BIT_UTYPE
typedef ZSH_64_BIT_UTYPE zulong;
#else
typedef unsigned zlong zulong;
#endif
#else
typedef long zlong;
typedef unsigned long zulong;
@ -352,7 +356,6 @@ struct node {
#define NT_N(T, N) (((T) >> (8 + (N) * 4)) & 0xf)
#define NT_SET(T0, T1, T2, T3, T4) \
((T0) | ((T1) << 8) | ((T2) << 12) | ((T3) << 16) | ((T4) << 20))
#define NT_HEAP (1 << 30)
/* tree element for lists */
@ -605,7 +608,7 @@ struct job {
pid_t gleader; /* process group leader of this job */
pid_t other; /* subjob id or subshell pid */
int stat; /* see STATs below */
char *pwd; /* current working dir of shell when *
char pwd[PATH_MAX + 1]; /* current working dir of shell when *
* this job was spawned */
struct process *procs; /* list of processes */
LinkList filelist; /* list of files to delete when done */
@ -948,7 +951,12 @@ struct param {
#define PM_READONLY (1<<8) /* readonly */
#define PM_TAGGED (1<<9) /* tagged */
#define PM_EXPORTED (1<<10) /* exported */
/* The following are the same since they *
* both represent -U option to typeset */
#define PM_UNIQUE (1<<11) /* remove duplicates */
#define PM_UNALIASED (1<<11) /* do not expand aliases when autoloading */
#define PM_TIED (1<<12) /* array tied to colon-path or v.v. */
#define PM_SPECIAL (1<<13) /* special builtin parameter */
#define PM_DONTIMPORT (1<<14) /* do not import this variable */

View file

@ -31,7 +31,16 @@ version.h: $(sdir_top)/Config/version.mk
zshpaths.h: FORCE Makemod
@echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp
@if test x$(fndir) != xno; then \
echo '#define FUNCTION_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \
echo '#define FPATH_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \
if test x$(FUNCTIONS_SUBDIRS) != x -a \
x$(FUNCTIONS_SUBDIRS) != xno; then \
fpath_tmp="`for f in $$FUNCTIONS_INSTALL; do \
echo $$f | sed s%/.*%%; \
done | sort | uniq`"; \
fpath_tmp="`echo $$fpath_tmp | sed 's/ /\", \"/g'`"; \
echo "#define FPATH_SUBDIRS { \"$$fpath_tmp\" }" \
>>zshpaths.h.tmp; \
fi; \
fi
@if cmp -s zshpaths.h zshpaths.h.tmp; then \
rm -f zshpaths.h.tmp; \

View file

@ -504,3 +504,21 @@ Documentation
ocurring in the main text, "plugh" is a normal word that is being quoted
(it's the user that says `plugh', not the documentation), and "xyzzy"
is some text to be typed literally that is being quoted.
* For multiple-line pieces of text that should not be filled, there are
various models.
- If the text is pure example, i.e. with no metasyntactic variables etc.,
it should be included within `example(...)'. The text will be
indented, will not be filled and will be put into a fixed width font.
- If the text includes mixed fonts, it should be included within
`indent(...)'. As with `example()', the text is not filled, but now
explicit font-changing commands are required inside.
- If the text appears inside some other format, such as for example the
`item()' list structure, then the instruction `nofill(...)', which
simply turns off filling should be used; as with `indent(...)',
explicit font changing commands are required. This is also an
alternative to `indent()' when no identation is required, e.g. if the
accumulated indentation would otherwise be too long.
All the above should appear on their own, separated by newlines from the
surrounding text. No extra newlines after the opening or before the
closing parenthesis are required.

View file

@ -248,9 +248,12 @@
/* Define to 1 if long is 64 bits */
#undef LONG_IS_64_BIT
/* Define to a 64 bit type if there is one, but long is shorter */
/* Define to a 64 bit integer type if there is one, but long is shorter */
#undef ZSH_64_BIT_TYPE
/* Define to an unsigned variant of ZSH_64_BIT_TYPE if that is defined */
#undef ZSH_64_BIT_UTYPE
/* Define to 1 if off_t is 64 bit (for large file support) */
#undef OFF_T_IS_64_BIT

View file

@ -41,11 +41,13 @@ for ac_shellvar in $ac_shellvars; do
CPPFLAGS) ac_lfsvar=LFS_CFLAGS ;;
*) ac_lfsvar=LFS_$ac_shellvar ;;
esac
eval test '"${'$ac_shellvar'+set}"' = set && ac_set=$ac_shellvar
(getconf $ac_lfsvar) >/dev/null 2>&1 || { ac_result=no; break; }
ac_getconf=`getconf $ac_lfsvar`
ac_getconfs=$ac_getconfs$ac_getconf
eval ac_test_$ac_shellvar="\$ac_getconf"
if test -n "$ac_getconf"; then
eval test '"${'$ac_shellvar'+set}"' = set && ac_set=$ac_shellvar
ac_getconfs=$ac_getconfs$ac_getconf
eval ac_test_$ac_shellvar="\$ac_getconf"
fi
done
case "$ac_result$ac_getconfs" in
yes) ac_result=no ;;
@ -74,12 +76,12 @@ esac
dnl
dnl zsh_64_BIT_TYPE
dnl Check whether the first argument works as a 64-bit type.
dnl If there is a non-zero second argument, we just assume it works
dnl If there is a non-zero third argument, we just assume it works
dnl when we're cross compiling. This is to allow a type to be
dnl specified directly as --enable-lfs="long long".
dnl Sets zsh_cv_64_bit_type to the first argument if the test worked,
dnl `no' otherwise. Be careful testing this, as it may produce
dnl two words `long long' on an unquoted substitution.
dnl Sets the variable given in the second argument to the first argument
dnl if the test worked, `no' otherwise. Be careful testing this, as it
dnl may produce two words `long long' on an unquoted substitution.
dnl This macro does not produce messages as it may be run several times
dnl before finding the right type.
dnl
@ -95,11 +97,11 @@ main()
$1 foo = 0;
return sizeof($1) != 8;
}
], zsh_cv_64_bit_type="$1", zsh_cv_64_bit_type=no,
[if test x$2 != x ; then
zsh_cv_64_bit_type="$1"
], $2="$1", $2=no,
[if test x$3 != x ; then
$2="$1"
else
zsh_cv_64_bit_type=no
$2=no
fi])
])

View file

@ -97,8 +97,7 @@ AC_ARG_ENABLE(zsh-hash-debug,
AC_DEFINE(ZSH_HASH_DEBUG)
fi])
dnl Do you want large file support, if available (mostly Solaris)?
dnl Currently this is only partially implemented.
dnl Do you want large file support, if available?
undefine([lfs])dnl
AC_ARG_ENABLE(lfs,
[ --enable-lfs turn on support for large files])
@ -203,18 +202,35 @@ AC_DEFINE(RESTRICTED_R)
undefine([fndir])dnl
AC_ARG_ENABLE(fndir,
[ --enable-fndir=DIR where functions go (default DATADIR/zsh-fns)],
[fndir="$enableval"], [fndir=${datadir}/zsh/functions])
[ --enable-fndir=DIR where functions go (default DATADIR/zsh/functions)],
[if test $enableval = yes; then
fndir=${datadir}/zsh/functions
else
fndir="$enableval"
fi], [fndir=${datadir}/zsh/functions])
if test x${FUNCTIONS_INSTALL+set} != xset; then
undefine([function_subdirs])
AC_ARG_ENABLE(function-subdirs,
[ --enable-function-subdirs install functions in subdirectories])
if test "x${FUNCTIONS_INSTALL+set}" != xset; then
FUNCTIONS_INSTALL="Core/* Base/* Builtins/* User/* Commands/*"
if test $dynamic != no; then
FUNCTIONS_INSTALL="${FUNCTIONS_INSTALL} Zftp/*"
fi
fi
if test "x${enable_function_subdirs}" != x -a \
"x${enable_function_subdirs}" != xno -a \
"x$FUNCTIONS_INSTALL" != x; then
FUNCTIONS_SUBDIRS=yes
else
FUNCTIONS_SUBDIRS=no
fi
AC_SUBST(fndir)dnl
AC_SUBST(FUNCTIONS_INSTALL)dnl
AC_SUBST(FUNCTIONS_SUBDIRS)dnl
dnl ------------------
dnl CHECK THE COMPILER
@ -225,7 +241,7 @@ test -z "${LDFLAGS+set}" && LDFLAGS= auto_ldflags=1
AC_PROG_CC
dnl Check for large file support (Solaris).
dnl Check for large file support.
dnl This needs to be done early to get the stuff into the flags.
if test "x$enable_lfs" != x; then
zsh_LARGE_FILE_SUPPORT
@ -552,44 +568,69 @@ zsh_cv_long_is_64_bit=no)])
if test $zsh_cv_long_is_64_bit = yes; then
AC_DEFINE(LONG_IS_64_BIT)
elif test "x$enable_lfs" != x; then
AC_CACHE_CHECK(if compiler has a 64 bit type, zsh_cv_64_bit_type,
[if test "x$enable_lfs" != xyes; then
zsh_64_BIT_TYPE(${enable_lfs})
else
zsh_64_BIT_TYPE(long long)
if test "$zsh_cv_64_bit_type" = no; then
zsh_64_BIT_TYPE(quad_t)
fi
fi
])
if test "$zsh_cv_64_bit_type" != no; then
AC_DEFINE_UNQUOTED(ZSH_64_BIT_TYPE, $zsh_cv_64_bit_type)
AC_CACHE_CHECK(if off_t is 64 bit, zsh_cv_off_t_is_64_bit,
[AC_TRY_RUN([
else
AC_CACHE_CHECK(if off_t is 64 bit, zsh_cv_off_t_is_64_bit,
[AC_TRY_RUN([
#include <sys/types.h>
main() { return sizeof(off_t) < 8; }
],
zsh_cv_off_t_is_64_bit=yes,
zsh_cv_off_t_is_64_bit=no,
zsh_cv_off_t_is_64_bit=no)])
if test $zsh_cv_off_t_is_64_bit = yes; then
AC_DEFINE(OFF_T_IS_64_BIT)
fi
zsh_cv_off_t_is_64_bit=yes,
zsh_cv_off_t_is_64_bit=no,
zsh_cv_off_t_is_64_bit=no)])
if test $zsh_cv_off_t_is_64_bit = yes; then
AC_DEFINE(OFF_T_IS_64_BIT)
fi
AC_CACHE_CHECK(if ino_t is 64 bit, zsh_cv_ino_t_is_64_bit,
[AC_TRY_RUN([
AC_CACHE_CHECK(if ino_t is 64 bit, zsh_cv_ino_t_is_64_bit,
[AC_TRY_RUN([
#include <sys/types.h>
main() { return sizeof(ino_t) < 8; }
],
zsh_cv_ino_t_is_64_bit=yes,
zsh_cv_ino_t_is_64_bit=no,
zsh_cv_ino_t_is_64_bit=no)])
if test $zsh_cv_ino_t_is_64_bit = yes; then
AC_DEFINE(INO_T_IS_64_BIT)
zsh_cv_ino_t_is_64_bit=yes,
zsh_cv_ino_t_is_64_bit=no,
zsh_cv_ino_t_is_64_bit=no)])
if test $zsh_cv_ino_t_is_64_bit = yes; then
AC_DEFINE(INO_T_IS_64_BIT)
fi
if test "x$enable_lfs" != xno -o $zsh_cv_off_t_is_64_bit = yes \
-o $zsh_cv_ino_t_is_64_bit = yes; then
AC_CACHE_CHECK(if compiler has a 64 bit type, zsh_cv_64_bit_type,
[if test "x$enable_lfs" != xyes -a "x$enable_lfs" != xno; then
zsh_64_BIT_TYPE(${enable_lfs}, zsh_cv_64_bit_type, force)
else
zsh_64_BIT_TYPE(long long, zsh_cv_64_bit_type)
if test "$zsh_cv_64_bit_type" = no; then
zsh_64_BIT_TYPE(quad_t, zsh_cv_64_bit_type)
fi
if test "$zsh_cv_64_bit_type" = no; then
zsh_64_BIT_TYPE(__int64_t, zsh_cv_64_bit_type)
fi
dnl As a last resort, if we know off_t has 64 bits, use that as
dnl the 64-bit integer type. I don't dare try ino_t since there's
dnl probably nothing to stop that being unsigned.
if test "$zsh_cv_64_bit_type" = no -a \
"$zsh_cv_off_t_is_64_bit" = yes; then
zsh_64_BIT_TYPE(off_t, zsh_cv_64_bit_type)
fi
fi])
if test "$zsh_cv_64_bit_type" != no; then
AC_DEFINE_UNQUOTED(ZSH_64_BIT_TYPE, $zsh_cv_64_bit_type)
dnl Handle cases where unsigned type cannot be simply
dnl `unsigned ZSH_64_BIT_TYPE'. More tests may be required.
AC_CACHE_CHECK(for a corresponding unsigned 64 bit type,
zsh_cv_64_bit_utype,
[zsh_64_BIT_TYPE(unsigned $zsh_cv_64_bit_type, zsh_cv_64_bit_utype,
force)
if test "$zsh_cv_64_bit_utype" = no; then
zsh_64_BIT_TYPE(__uint64_t, zsh_cv_64_bit_utype)
fi])
if test "$zsh_cv_64_bit_utype" != no; then
AC_DEFINE_UNQUOTED(ZSH_64_BIT_UTYPE, $zsh_cv_64_bit_utype)
fi
fi
fi
fi
@ -1326,6 +1367,7 @@ eval "zshbin1=${bindir}"
eval "zshbin2=${zshbin1}"
eval "zshman=${mandir}"
eval "zshinfo=${infodir}"
eval "zshfndir=${fndir}"
echo "
zsh configuration
@ -1350,5 +1392,9 @@ echo "\
library flags : ${LIBS}
binary install path : ${zshbin2}
man page install path : ${zshman}
info install path : ${zshinfo}
info install path : ${zshinfo}"
if test "$zshfndir" != no; then
echo "functions install path : ${zshfndir}
installed functions : ${FUNCTIONS_INSTALL}
"
fi