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:
parent
805381040d
commit
a2159285e8
77 changed files with 1651 additions and 1236 deletions
ChangeLog
Completion
Config
Doc
Makefile.in
Zsh
arith.yobuiltins.yocompctl.yocompsys.yocompwid.yoexpn.yofiles.yofunc.yogrammar.yoguide.yojobs.yometafaq.yomod_compctl.yomod_mapfile.yomod_zftp.yoparams.yoredirect.yozftpsys.yozle.yo
zman.yozsh.yoztexi.yoEtc
Functions
INSTALLSrc
Builtins
Makefile.inModules
Zle
builtin.ccond.cexec.cglob.chashtable.chist.cinit.cjobs.clex.clinklist.cloop.cmath.cmem.cparams.cparse.csignals.csubst.ctext.cutils.czsh.exportzsh.hzsh.mddUtil
acconfig.haczsh.m4configure.in
179
ChangeLog
179
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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 '-:?#%+=[/'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#compdef fg jobs
|
||||
#compdef disown fg jobs
|
||||
|
||||
compgen -j -P '%'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#compdef limit unlimit
|
||||
|
||||
compgen -k "(${(j: :)${(f)$(limit)}%% *})"
|
||||
compgen -s '${${(f)"$(limit)"}%% *}'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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 = \
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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(")'.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) ])(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
10
Doc/zman.yo
10
Doc/zman.yo
|
@ -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 ---)
|
||||
|
|
|
@ -17,7 +17,7 @@ def(ifzshall)(1)()\
|
|||
)\
|
||||
ifztexi(\
|
||||
texinfo(zsh.info)(zsh)
|
||||
NOTRANS(@setchapternewpage odd
|
||||
NOTRANS(@setchapternewpage off
|
||||
@iftex
|
||||
@finalout
|
||||
@afourpaper
|
||||
|
|
12
Doc/ztexi.yo
12
Doc/ztexi.yo
|
@ -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 ---)
|
||||
|
|
10
Etc/MACHINES
10
Etc/MACHINES
|
@ -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.
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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
0
Functions/Zftp/zfgoto
Normal 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
0
Functions/Zftp/zfmark
Normal 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
24
INSTALL
|
@ -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
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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@
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
|
|
91
Src/cond.c
91
Src/cond.c
|
@ -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;
|
||||
}
|
||||
|
|
394
Src/exec.c
394
Src/exec.c
|
@ -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;
|
||||
|
|
22
Src/glob.c
22
Src/glob.c
|
@ -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';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
110
Src/hist.c
110
Src/hist.c
|
@ -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++;
|
||||
|
|
31
Src/init.c
31
Src/init.c
|
@ -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;
|
||||
|
|
35
Src/jobs.c
35
Src/jobs.c
|
@ -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;
|
||||
}
|
||||
|
|
76
Src/lex.c
76
Src/lex.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
64
Src/loop.c
64
Src/loop.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
14
Src/math.c
14
Src/math.c
|
@ -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;
|
||||
|
|
55
Src/mem.c
55
Src/mem.c
|
@ -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) {
|
||||
|
|
21
Src/params.c
21
Src/params.c
|
@ -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' */
|
||||
|
|
56
Src/parse.c
56
Src/parse.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
34
Src/text.c
34
Src/text.c
|
@ -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));
|
||||
|
|
645
Src/utils.c
645
Src/utils.c
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
14
Src/zsh.h
14
Src/zsh.h
|
@ -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 */
|
||||
|
|
11
Src/zsh.mdd
11
Src/zsh.mdd
|
@ -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; \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
24
aczsh.m4
24
aczsh.m4
|
@ -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])
|
||||
])
|
||||
|
||||
|
|
118
configure.in
118
configure.in
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue