mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-06-11 19:18:01 +02:00
zsh-3.1.5-pws-5
This commit is contained in:
parent
2a5a899a55
commit
20d67907c9
47 changed files with 2212 additions and 425 deletions
Config
Doc/Zsh
Etc
Misc
Src
Builtins
Modules
Zle
comp1.ccomp1.exportcompctl.ccompctl.mddiwidgets.listzle.hzle_keymap.czle_main.czle_refresh.czle_thingy.czle_tricky.c
builtin.ccond.cexec.cglob.chashtable.chist.cinput.cjobs.clex.cloop.cmem.cmkbltnmlst.shmkmakemod.shmodule.cparams.csubst.cwatch.czsh.exportzsh.hUtil
aczsh.m4configure.inpatchlist.txt
|
@ -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-4
|
||||
VERSION_DATE='December 17, 1998'
|
||||
VERSION=3.1.5-pws-5
|
||||
VERSION_DATE='January 19, 1998'
|
||||
|
|
|
@ -947,9 +947,10 @@ otherwise it is determined by the width of the value of the
|
|||
first assignment.
|
||||
)
|
||||
item(tt(-a))(
|
||||
The names refer to array parameters. For historical reasons, scalar
|
||||
parameters are created even when this flag is specified, but the
|
||||
output is restricted to arrays (including associative arrays).
|
||||
The names refer to array parameters. An array parameter may be
|
||||
created this way, but it may not be assigned to in the tt(typeset)
|
||||
statement. When displaying, both normal and associative arrays are
|
||||
shown.
|
||||
)
|
||||
item(tt(-f))(
|
||||
The names refer to functions rather than parameters. No assignments
|
||||
|
|
|
@ -85,7 +85,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
|
||||
|
||||
nofill(tt(compctl -Tx 'C[0,*/*]' -f - 's[~]' -k friends -S/))
|
||||
nofill(tt(compctl -Tx 'C[0,*/*]' -f - 's[~]' -k friends -S/ -tn))
|
||||
|
||||
to complete the strings in the array tt(friends) after a `tt(~)'.
|
||||
The first argument is necessary so that this form of ~-completion is
|
||||
|
@ -432,16 +432,18 @@ the sorted ones. I.e. it is possible to have a sorted and a unsorted group
|
|||
with the same name and the matches in those groups will not be mixed.
|
||||
)
|
||||
item(tt(-t) var(continue))(
|
||||
The var(continue)-string contains a set of characters that specify if
|
||||
and when completion should continue to produce matches where it normally
|
||||
would not do that. The character tt(c) means that completion continues
|
||||
with the next suitable compctl (i.e. if you don't specify this in a
|
||||
tt(compctl -T), compctls for commands are never used). The character
|
||||
tt(PLUS()) is used to continue with the matches for the next alternative
|
||||
completion (see below). The characters tt(-) and tt(x) may be used in
|
||||
sub-lists for extended completion (see below). They will make the completion
|
||||
code use the flag list after the next tt(-) (if the corresponding pattern
|
||||
matches) and the default flag list (those before the tt(-x)), respectively.
|
||||
The var(continue)-string contains a character that specifies which set
|
||||
of completion flags should be used next. Normally those of the next
|
||||
matching compctl are used, i.e. pattern compctls and normal compctls
|
||||
after tt(-T) and after a pattern compctl. If var(continue) is the
|
||||
character tt(PLUS()) the flags for the next alternative completion
|
||||
(see below) are used. The characters tt(-) and tt(x) can be used in
|
||||
sub-lists for extended completion (see below). They will make the
|
||||
completion code use the flag list after the next tt(-) (if the
|
||||
corresponding pattern matches) and the default flag list (those before
|
||||
the tt(-x)), respectively. if var(continue) is the character tt(n) no
|
||||
other flag lists are used, i.e. the generation of matches stops
|
||||
immediately.
|
||||
)
|
||||
item(tt(-M) var(match-spec))(
|
||||
This defines additional matching control specifications that should be used
|
||||
|
|
|
@ -92,6 +92,27 @@ nofill(tt(LPAR()zftp open; zftp get foo >bar; zftp close)tt(RPAR() &))
|
|||
--- here, the connection is restricted to a background subshell and
|
||||
you are free to open a simultaneous connection in the foreground.
|
||||
)
|
||||
item(tt(test))(
|
||||
Test the connection; if the server has reported
|
||||
that it has closed the connection (maybe due to a timeout), return
|
||||
status 2; if no connection was open anyway, return status 1; else
|
||||
return status 0. The tt(test) subcommand is
|
||||
silent, apart from messages printed by the tt($ZFTP_VERBOSE)
|
||||
mechanism, or error messages if the connection closes. There is no
|
||||
network overhead for this test.
|
||||
|
||||
The test is only supported on systems with either the tt(select(2)) or
|
||||
tt(poll(2)) system calls; otherwise the message tt(not
|
||||
supported on this system) is printed instead.
|
||||
|
||||
It is useful to put the code
|
||||
|
||||
nofill(tt([[ -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
|
||||
other subcommand when a connection is open.
|
||||
)
|
||||
item(tt(cd) var(directory))(
|
||||
Change the remote directory to var(directory). Also alters the shell
|
||||
variable tt(ZFTP_PWD).
|
||||
|
|
|
@ -45,7 +45,8 @@ HP: HP-UX 9, 10.20
|
|||
Should build `out-of-the-box'.
|
||||
|
||||
IBM: AIX
|
||||
Should build `out-of-the-box'.
|
||||
Should build `out-of-the-box'. On AIX 3.x (at least),
|
||||
--enable-zsh-mem will not work.
|
||||
|
||||
Linux: Linux (i386) [3.1.4]
|
||||
If you are using an early minor version of libc 5, then a bug
|
||||
|
@ -92,3 +93,6 @@ Sun: Solaris 2.*
|
|||
To avoid this, make sure you compile zsh without any reference
|
||||
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.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
DISTFILES_SRC='
|
||||
.distfiles
|
||||
c2z compctl-examples globtests globtests.ksh lete2ctl
|
||||
new-completion-examples zftp-functions
|
||||
'
|
||||
|
|
453
Misc/new-completion-examples
Normal file
453
Misc/new-completion-examples
Normal file
|
@ -0,0 +1,453 @@
|
|||
# Define a new widget behaving like `expand-or-complete' but calling the
|
||||
# function `main-complete' to generate matches.
|
||||
|
||||
zle -c my-comp expand-or-complete main-complete
|
||||
|
||||
bindkey '\C-i' my-comp
|
||||
|
||||
|
||||
# Below is a proposed main loop and the things it needs.
|
||||
|
||||
# One associative array for normal completions and one for patterns.
|
||||
|
||||
typeset -A comps
|
||||
|
||||
|
||||
# These may be used to define completion handlers. First argument is the
|
||||
# name of the function/variable containing the definition, the other
|
||||
# arguments are the command names for which this definition should be used.
|
||||
# With only one argument the function/variable-name __$1 is used.
|
||||
|
||||
defcomp() {
|
||||
local v
|
||||
|
||||
if [[ $# -eq 1 ]] then
|
||||
comps[$1]="__$1"
|
||||
else
|
||||
v="$1"
|
||||
shift
|
||||
for i; do
|
||||
comps[$i]="$v"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
defpatcomp() {
|
||||
if [[ ${+patcomps} == 1 ]] then
|
||||
patcomps=("$patcomps[@]" "$2 $1" )
|
||||
else
|
||||
patcomps=( "$2 $1" )
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# These can be used to easily save and restore the state of the special
|
||||
# variables used by the completion code.
|
||||
|
||||
alias compsave='local _opre _oipre _oargs _ocur;_opre="$PREFIX";_oipre="$IPREFIX";_oargs=( "$@" );_ocur="$CURRENT"'
|
||||
alias compreset='PREFIX="$_opre";IPREFIX="$_oipre";argv=( "$_oargs[@]" );CURRENT="$_ocur"'
|
||||
|
||||
# This is an easy way to get completion for sub-commands.
|
||||
|
||||
alias compsub='do-complete "$@" || return 1'
|
||||
|
||||
# This searches $1 in the array for normal completions and calls the result.
|
||||
|
||||
compalso() {
|
||||
1="$comps[$1]"
|
||||
[[ -z "$1" ]] || call-complete "$@"
|
||||
}
|
||||
|
||||
# This generates matches. The first argument is something we got from one
|
||||
# of the associative arrays above. This is expected to be either the name
|
||||
# of a variable in which case we use its value as arguments to complist,
|
||||
# or it is the name of a function in which case we call this function with
|
||||
# the arguments from the command line as its arguments.
|
||||
|
||||
call-complete() {
|
||||
local var
|
||||
|
||||
eval var\=\$\{\+$1\}
|
||||
if [[ "$var" == 0 ]] then
|
||||
"$@"
|
||||
else
|
||||
eval complist \$\{${1}\[\@\]\}
|
||||
fi
|
||||
}
|
||||
|
||||
# The main loop of the competion code. This is what is called when TAB is
|
||||
# pressed. The completion code gives us the special variables and the
|
||||
# arguments from the command line are gives as positional parameters.
|
||||
|
||||
main-complete() {
|
||||
emulate -R zsh
|
||||
local comp
|
||||
setopt localoptions nullglob rcexpandparam globdots
|
||||
unsetopt markdirs globsubst shwordsplit nounset
|
||||
|
||||
# An entry for `--first--' is the replacement for `compctl -T'
|
||||
# The `|| return 1' is used throughout: if a function producing matches
|
||||
# returns non-zero this is interpreted as `do not try to produce more matches'
|
||||
# (this is the replacement for `compctl -t').
|
||||
|
||||
comp="$comps[--first--]"
|
||||
[[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
|
||||
|
||||
# For arguments we use the `do-complete' function below called via the
|
||||
# convenience alias `compsub'.
|
||||
|
||||
if [[ $CONTEXT == argument || $CONTEXT == command ]] then
|
||||
compsub
|
||||
else
|
||||
# Let's see if we have a special completion definition for the other
|
||||
# possible contexts.
|
||||
|
||||
comp=''
|
||||
|
||||
case $CONTEXT in
|
||||
redirect) comp="$comps[--redir--]";;
|
||||
math) comp="$comps[--math--]";;
|
||||
subscript) comp="$comps[--subscr--]";;
|
||||
value) comp="$comps[--value--]";;
|
||||
condition) comp="$comps[--cond--]";;
|
||||
esac
|
||||
|
||||
# If not, we use default completion, if any.
|
||||
|
||||
[[ -z "$comp" ]] && comp="$comps[--default--]"
|
||||
[[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# This does completion for a command (in command position and for the
|
||||
# arguments).
|
||||
|
||||
do-complete() {
|
||||
local comp cmd1 cmd2 pat val
|
||||
|
||||
# Completing in command position? If not we set up `cmd1' and `cmd2' as
|
||||
# two strings we have search in the completion definition arrays (e.g.
|
||||
# a path and the last path name component).
|
||||
|
||||
if [[ $CONTEXT == command ]] then
|
||||
comp="$comps[--command--]"
|
||||
[[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
|
||||
return 0
|
||||
elif [[ "$COMMAND[1]" == '=' ]] then
|
||||
eval cmd1\=$COMMAND
|
||||
cmd2="$COMMAND[2,-1]"
|
||||
elif [[ "$COMMAND" == */* ]] then
|
||||
cmd1="$COMMAND"
|
||||
cmd2="${COMMAND:t}"
|
||||
else
|
||||
cmd1="$COMMAND"
|
||||
eval cmd2=$(whence -p $COMMAND)
|
||||
fi
|
||||
|
||||
# See if there are any matching pattern completions.
|
||||
|
||||
for i in "$patcomps[@]"; do
|
||||
pat="${i% *}"
|
||||
val="${i#* }"
|
||||
if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]] then
|
||||
call-complete "$val" "$@" || return 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Now look up the two names in the normal completion array.
|
||||
|
||||
comp="${comps[$cmd1]:-$comps[$cmd2]}"
|
||||
|
||||
# And generate the matches, probably using default completion.
|
||||
|
||||
[[ -z "$comp" ]] && comp="$comps[--default--]"
|
||||
[[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
|
||||
}
|
||||
|
||||
# Do sub-completion for pre-command modifiers.
|
||||
|
||||
defcomp __precmd - noglob nocorrect exec command builtin
|
||||
__precmd() {
|
||||
COMMAND="$1"
|
||||
shift
|
||||
(( CURRENT-- ))
|
||||
if [[ CURRENT -eq 0 ]] then
|
||||
CONTEXT=command
|
||||
else
|
||||
CONTEXT=argument
|
||||
fi
|
||||
compsub
|
||||
}
|
||||
|
||||
# Utility function for in-path completion.
|
||||
# First argument should be an complist-option (e.g. -f, -/, -g). The other
|
||||
# arguments should be glob patterns, one per argument.
|
||||
# E.g.: files -g '*.tex' '*.texi'
|
||||
# This is intended as a replacement for `complist -f', `complist -/', and
|
||||
# `complist -g ...' (but don't use it with other options).
|
||||
# This function behaves as if you have a matcher definition like:
|
||||
# compctl -M 'r:|[-.,_/]=* r:|=* m:{a-z}={A-Z} m:-=_ m:.=,'
|
||||
# so you may want to modify this.
|
||||
|
||||
pfiles() {
|
||||
local nm str pa pre epre a b c s rest
|
||||
|
||||
setopt localoptions nullglob rcexpandparam globdots extendedglob
|
||||
unsetopt markdirs globsubst shwordsplit nounset
|
||||
|
||||
nm=$NMATCHES
|
||||
if [[ $# -eq 0 ]] then
|
||||
complist -f
|
||||
elif [[ "$1" = -g ]] then
|
||||
complist -g "$argv[2,-1]"
|
||||
shift
|
||||
else
|
||||
complist $1
|
||||
shift
|
||||
fi
|
||||
[[ -nmatches nm ]] || return
|
||||
|
||||
str="$PREFIX*$SUFFIX"
|
||||
|
||||
[[ -z "$1" ]] && 1='*'
|
||||
if [[ $str[1] = \~ ]] then
|
||||
pre="${str%%/*}/"
|
||||
eval epre\=$pre
|
||||
str="${str#*/}"
|
||||
pa=''
|
||||
else
|
||||
pre=''
|
||||
epre=''
|
||||
if [[ $str[1] = / ]] then
|
||||
str="$str[2,-1]"
|
||||
pa='/'
|
||||
else
|
||||
pa=''
|
||||
fi
|
||||
fi
|
||||
str="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
|
||||
while [[ "$str" = */* ]] do
|
||||
rest="${str#*/}"
|
||||
a="${epre}${pa}(#l)${str%%/*}(-/)"
|
||||
a=( $~a )
|
||||
if [[ $#a -eq 0 ]] then
|
||||
return
|
||||
elif [[ $#a -gt 1 ]] then
|
||||
c=()
|
||||
s=( $rest$@ )
|
||||
s=( "${(@)s:gs.**.*.}" )
|
||||
for i in $a; do
|
||||
b=( $~i/(#l)$~s )
|
||||
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
|
||||
[[ $#b -ne 0 ]] && c=( $c $i )
|
||||
done
|
||||
if [[ $#c -eq 0 ]] then
|
||||
return
|
||||
elif [[ $#c -ne 1 ]] then
|
||||
a="$epre$pa"
|
||||
c=( $~c/(#l)$~s )
|
||||
eval c\=\( \$\{c:/\*\(${(j:|:)fignore}\)\} \)
|
||||
c=( ${c#$a} )
|
||||
for i in $c; do
|
||||
compadd -p "$pre$pa" -W "$a" -s "/${i#*/}" -f "${i%%/*}"
|
||||
done
|
||||
return
|
||||
fi
|
||||
a=( "$c[1]" )
|
||||
fi
|
||||
a="$a[1]"
|
||||
pa="$pa${a##*/}/"
|
||||
str="$rest"
|
||||
done
|
||||
a="$epre$pa"
|
||||
s=( $str$@ )
|
||||
s=( "${(@)s:gs.**.*.}" )
|
||||
b=( $~a(#l)$~s )
|
||||
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
|
||||
compadd -p "$pre$pa" -W "$epre$pa" -f ${b#$a}
|
||||
}
|
||||
|
||||
# Utility function for completing files of a given type or any file.
|
||||
# In many cases you will want to call this one instead of pfiles().
|
||||
|
||||
files() {
|
||||
local nm
|
||||
|
||||
nm=$NMATCHES
|
||||
pfiles "$@"
|
||||
|
||||
[[ $# -ne 0 && -nmatches nm ]] && pfiles
|
||||
}
|
||||
|
||||
# Simple default, command, and math completion defined with variables.
|
||||
|
||||
defcomp __default --default--
|
||||
__default() {
|
||||
files
|
||||
}
|
||||
|
||||
defcomp __command --command--
|
||||
__command=( -c )
|
||||
|
||||
defcomp __math --math--
|
||||
__math=( -v )
|
||||
|
||||
defcomp __subscr --subscr--
|
||||
__subscr() {
|
||||
compalso --math-- "$@"
|
||||
# ...probably other stuff
|
||||
}
|
||||
|
||||
# A simple pattern completion, just as an example.
|
||||
|
||||
defpatcomp __x_options '*/X11/*'
|
||||
__x_options() {
|
||||
complist -J options -k '(-display -name -xrm)'
|
||||
}
|
||||
|
||||
# A better example: completion for `find'.
|
||||
|
||||
defcomp find
|
||||
__find() {
|
||||
compsave
|
||||
|
||||
if [[ -mbetween -(ok|exec) \\\; ]] then
|
||||
compsub
|
||||
elif [[ -iprefix - ]] then
|
||||
complist -s 'daystart {max,min,}depth follow noleaf version xdev \
|
||||
{a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \
|
||||
{i,}{l,}name {no,}{user,group} path perm regex size true uid used \
|
||||
exec {f,}print{f,0,} ok prune ls'
|
||||
compreset
|
||||
elif [[ -position 1 ]] then
|
||||
complist -g '. ..'
|
||||
files -g '(-/)'
|
||||
elif [[ -mcurrent -1 -((a|c|)newer|fprint(|0|f)) ]] then
|
||||
files
|
||||
elif [[ -current -1 -fstype ]] then
|
||||
complist -k '(ufs 4.2 4.3 nfs tmp mfs S51K S52K)'
|
||||
elif [[ -current -1 -group ]] then
|
||||
complist -k groups
|
||||
elif [[ -current -1 -user ]] then
|
||||
complist -u
|
||||
fi
|
||||
}
|
||||
|
||||
# Various completions...
|
||||
|
||||
defcomp __gunzip gunzip zcat
|
||||
__gunzip() {
|
||||
files -g '*.[gG][z]'
|
||||
}
|
||||
|
||||
defcomp gzip
|
||||
__gzip() {
|
||||
files -g '*~*.[gG][zZ]'
|
||||
}
|
||||
|
||||
defcomp xfig
|
||||
__xfig() {
|
||||
files -g '*.fig'
|
||||
}
|
||||
|
||||
defcomp __make make gmake
|
||||
__make() {
|
||||
complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)"
|
||||
}
|
||||
|
||||
defcomp __ps gs ghostview gview psnup psselect pswrap pstops pstruct lpr
|
||||
__ps() {
|
||||
files -g '*([pP][sS]|eps)'
|
||||
}
|
||||
|
||||
defcomp __which which whence
|
||||
__which=( -caF )
|
||||
|
||||
defcomp __rlogin rlogin rsh ssh
|
||||
__rlogin() {
|
||||
if [[ -position 1 ]] then
|
||||
complist -k hosts
|
||||
elif [[ -position 2 ]] then
|
||||
complist -k '(-l)'
|
||||
elif [[ -position 3 && -word 1 artus ]] then
|
||||
complist -k '(puck root)'
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp __dvi xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
|
||||
__dvi() {
|
||||
files -g '*.(dvi|DVI)'
|
||||
}
|
||||
|
||||
defcomp __dirs rmdir df du dircmp cd
|
||||
__dirs() {
|
||||
files -/ '*(-/)'
|
||||
}
|
||||
|
||||
defcomp __jobs fg bg jobs
|
||||
__jobs=(-j -P '%?')
|
||||
|
||||
defcomp kill
|
||||
__kill() {
|
||||
if [[ -iprefix '-' ]] then
|
||||
complist -k signals
|
||||
else
|
||||
complist -P '%?' -j
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp __uncompress uncompress zmore
|
||||
__uncompress() {
|
||||
files -g '*.Z'
|
||||
}
|
||||
|
||||
defcomp compress
|
||||
__compress() {
|
||||
files -g '*~*.Z'
|
||||
}
|
||||
|
||||
defcomp __tex tex latex glatex slitex gslitex
|
||||
__tex() {
|
||||
files -g '*.(tex|TEX|texinfo|texi)'
|
||||
}
|
||||
|
||||
defcomp __options setopt unsetopt
|
||||
__options=(-M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o)
|
||||
|
||||
defcomp __funcs unfunction
|
||||
__funcs=(-F)
|
||||
|
||||
defcomp __aliases unalias
|
||||
__aliases=(-a)
|
||||
|
||||
defcomp __vars unset
|
||||
__vars=(-v)
|
||||
|
||||
defcomp __enabled disable
|
||||
__enabled=(-FBwa)
|
||||
|
||||
defcomp __disabled enable
|
||||
__disabled=(-dFBwa)
|
||||
|
||||
defcomp __pdf acroread
|
||||
__pdf() {
|
||||
files -g '*.(pdf|PDF)'
|
||||
}
|
||||
|
||||
defcomp tar
|
||||
__tar() {
|
||||
local nm tf
|
||||
compsave
|
||||
|
||||
tf="$2"
|
||||
nm=$NMATCHES
|
||||
if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]] then
|
||||
complist -k "( $(tar tf $tf) )"
|
||||
compreset
|
||||
elif [[ -mword 1 *c*f* && -position 3 100000 ]] then
|
||||
files
|
||||
compreset
|
||||
elif [[ -mcurrent -1 *f* && -position 2 ]] then
|
||||
files -g '*.(tar|TAR)'
|
||||
fi
|
||||
}
|
|
@ -264,7 +264,7 @@ bin_limit(char *nam, char **argv, char *ops, int func)
|
|||
* together more than one of these. It's easier to understand from *
|
||||
* the code: */
|
||||
val = zstrtorlimt(s, &s, 10);
|
||||
if (*s)
|
||||
if (*s) {
|
||||
if ((*s == 'h' || *s == 'H') && !s[1])
|
||||
val *= 3600L;
|
||||
else if ((*s == 'm' || *s == 'M') && !s[1])
|
||||
|
@ -275,6 +275,7 @@ bin_limit(char *nam, char **argv, char *ops, int func)
|
|||
zwarnnam("limit", "unknown scaling factor: %s", s, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
# ifdef RLIMIT_NPROC
|
||||
else if (lim == RLIMIT_NPROC)
|
||||
|
@ -339,12 +340,12 @@ bin_unlimit(char *nam, char **argv, char *ops, int func)
|
|||
/* Without arguments, remove all limits. */
|
||||
if (!*argv) {
|
||||
for (limnum = 0; limnum != RLIM_NLIMITS; limnum++) {
|
||||
if (hard)
|
||||
if (hard) {
|
||||
if (euid && current_limits[limnum].rlim_max != RLIM_INFINITY)
|
||||
ret++;
|
||||
else
|
||||
limits[limnum].rlim_max = RLIM_INFINITY;
|
||||
else
|
||||
} else
|
||||
limits[limnum].rlim_cur = limits[limnum].rlim_max;
|
||||
}
|
||||
if (ops['s'])
|
||||
|
@ -373,13 +374,13 @@ bin_unlimit(char *nam, char **argv, char *ops, int func)
|
|||
return 1;
|
||||
}
|
||||
/* remove specified limit */
|
||||
if (hard)
|
||||
if (hard) {
|
||||
if (euid && current_limits[lim].rlim_max != RLIM_INFINITY) {
|
||||
zwarnnam(nam, "can't remove hard limits", NULL, 0);
|
||||
ret++;
|
||||
} else
|
||||
limits[lim].rlim_max = RLIM_INFINITY;
|
||||
else
|
||||
} else
|
||||
limits[lim].rlim_cur = limits[lim].rlim_max;
|
||||
if (ops['s'] && zsetlimit(lim, nam))
|
||||
ret++;
|
||||
|
@ -478,11 +479,12 @@ bin_ulimit(char *name, char **argv, char *ops, int func)
|
|||
}
|
||||
}
|
||||
if (!*argv || **argv == '-') {
|
||||
if (res < 0)
|
||||
if (res < 0) {
|
||||
if (*argv || nres)
|
||||
continue;
|
||||
else
|
||||
res = RLIMIT_FSIZE;
|
||||
}
|
||||
resmask |= 1 << res;
|
||||
nres++;
|
||||
continue;
|
||||
|
|
|
@ -5,4 +5,5 @@ DISTFILES_SRC='
|
|||
example.mdd example.c
|
||||
files.mdd files.c
|
||||
stat.mdd stat.c
|
||||
zftp.mdd zftp.c
|
||||
'
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
autobins="example"
|
||||
|
||||
autoinfixconds="ex"
|
||||
autoprefixconds="len"
|
||||
|
||||
objects="example.o"
|
||||
|
|
|
@ -195,18 +195,18 @@ bin_ln(char *nam, char **args, char *ops, int func)
|
|||
|
||||
|
||||
if(func == BIN_MV) {
|
||||
move = rename;
|
||||
move = (MoveFunc) rename;
|
||||
flags = ops['f'] ? 0 : MV_ASKNW;
|
||||
flags |= MV_ATOMIC;
|
||||
} else {
|
||||
flags = ops['f'] ? MV_FORCE : 0;
|
||||
#ifdef HAVE_LSTAT
|
||||
if(ops['s'])
|
||||
move = symlink;
|
||||
move = (MoveFunc) symlink;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
move = link;
|
||||
move = (MoveFunc) link;
|
||||
if(!ops['d'])
|
||||
flags |= MV_NODIRS;
|
||||
}
|
||||
|
|
|
@ -346,7 +346,7 @@ bin_stat(char *name, char **args, char *ops, int func)
|
|||
} else {
|
||||
for (; *arg; arg++) {
|
||||
if (strchr("glLnNrstT", *arg))
|
||||
ops[*arg] = 1;
|
||||
ops[STOUC(*arg)] = 1;
|
||||
else if (*arg == 'A') {
|
||||
if (arg[1]) {
|
||||
arrnam = arg+1;
|
||||
|
@ -505,7 +505,7 @@ bin_stat(char *name, char **args, char *ops, int func)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (flags & STF_FILE)
|
||||
if (flags & STF_FILE) {
|
||||
if (arrnam)
|
||||
*arrptr++ = ztrdup(*args);
|
||||
else if (hashnam) {
|
||||
|
@ -513,6 +513,7 @@ bin_stat(char *name, char **args, char *ops, int func)
|
|||
*hashptr++ = ztrdup(*args);
|
||||
} else
|
||||
printf("%s%s", *args, (flags & STF_PICK) ? " " : ":\n");
|
||||
}
|
||||
if (iwhich > -1) {
|
||||
statprint(&statbuf, outbuf, *args, iwhich, flags);
|
||||
if (arrnam)
|
||||
|
@ -544,7 +545,7 @@ bin_stat(char *name, char **args, char *ops, int func)
|
|||
putchar('\n');
|
||||
}
|
||||
|
||||
if (arrnam)
|
||||
if (arrnam) {
|
||||
if (ret)
|
||||
freearray(array);
|
||||
else {
|
||||
|
@ -552,8 +553,9 @@ bin_stat(char *name, char **args, char *ops, int func)
|
|||
if (errflag)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hashnam)
|
||||
if (hashnam) {
|
||||
if (ret)
|
||||
freearray(hash);
|
||||
else {
|
||||
|
@ -561,6 +563,7 @@ bin_stat(char *name, char **args, char *ops, int func)
|
|||
if (errflag)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -62,9 +62,19 @@
|
|||
/* it's a TELNET based protocol, but don't think I like doing this */
|
||||
#include <arpa/telnet.h>
|
||||
|
||||
/*
|
||||
* We use poll() in preference to select because some subset of manuals says
|
||||
* that's the thing to do, plus it's a bit less fiddly. I don't actually
|
||||
* have access to a system with poll but not select, however, though
|
||||
* both bits of the code have been tested on a machine with both.
|
||||
*/
|
||||
#ifdef HAVE_POLL_H
|
||||
# include <poll.h>
|
||||
#endif
|
||||
|
||||
/* pinch the definition from <netinet/in.h> for deficient headers */
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
# define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -124,7 +134,8 @@ enum {
|
|||
ZFTP_HERE = 0x0100, /* here rather than over there */
|
||||
ZFTP_CDUP = 0x0200, /* CDUP rather than CWD */
|
||||
ZFTP_REST = 0x0400, /* restart: set point in remote file */
|
||||
ZFTP_RECV = 0x0800 /* receive rather than send */
|
||||
ZFTP_RECV = 0x0800, /* receive rather than send */
|
||||
ZFTP_TEST = 0x1000 /* test command, don't test */
|
||||
};
|
||||
|
||||
typedef struct zftpcmd *Zftpcmd;
|
||||
|
@ -134,6 +145,7 @@ static struct zftpcmd zftpcmdtab[] = {
|
|||
{ "params", zftp_params, 0, 4, 0 },
|
||||
{ "login", zftp_login, 0, 3, ZFTP_CONN },
|
||||
{ "user", zftp_login, 0, 3, ZFTP_CONN },
|
||||
{ "test", zftp_test, 0, 0, ZFTP_TEST },
|
||||
{ "cd", zftp_cd, 1, 1, ZFTP_CONN|ZFTP_LOGI },
|
||||
{ "cdup", zftp_cd, 0, 0, ZFTP_CONN|ZFTP_LOGI|ZFTP_CDUP },
|
||||
{ "dir", zftp_dir, 0, -1, ZFTP_CONN|ZFTP_LOGI },
|
||||
|
@ -674,8 +686,8 @@ zfgetmsg()
|
|||
|
||||
zfgetline(line, 256, tmout);
|
||||
ptr = line;
|
||||
if (zfdrrrring || !isdigit((int)*ptr) || !isdigit((int)ptr[1]) ||
|
||||
!isdigit((int)ptr[2])) {
|
||||
if (zfdrrrring || !isdigit(STOUC(*ptr)) || !isdigit(STOUC(ptr[1])) ||
|
||||
!isdigit(STOUC(ptr[2]))) {
|
||||
/* timeout, or not talking FTP. not really interested. */
|
||||
zcfinish = 2;
|
||||
if (!zfclosing)
|
||||
|
@ -820,7 +832,7 @@ zfopendata(char *name)
|
|||
zwarnnam(name, "Must set preference S or P to transfer data", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
zdfd = zfmovefd(socket(AF_INET, SOCK_STREAM, 0));
|
||||
zdfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (zdfd < 0) {
|
||||
zwarnnam(name, "can't get data socket: %e", NULL, errno);
|
||||
return 1;
|
||||
|
@ -851,7 +863,7 @@ zfopendata(char *name)
|
|||
* lastmsg already has the reply code expunged.
|
||||
*/
|
||||
for (ptr = lastmsg; *ptr; ptr++)
|
||||
if (isdigit(*ptr))
|
||||
if (isdigit(STOUC(*ptr)))
|
||||
break;
|
||||
if (sscanf(ptr, "%d,%d,%d,%d,%d,%d",
|
||||
nums, nums+1, nums+2, nums+3, nums+4, nums+5) != 6) {
|
||||
|
@ -986,11 +998,11 @@ zfgetdata(char *name, char *rest, char *cmd, int getsize)
|
|||
char *ptr = strstr(lastmsg, "bytes");
|
||||
zfstatus |= ZFST_NOSZ|ZFST_TRSZ;
|
||||
if (ptr) {
|
||||
while (ptr > lastmsg && !isdigit(*ptr))
|
||||
while (ptr > lastmsg && !isdigit(STOUC(*ptr)))
|
||||
ptr--;
|
||||
while (ptr > lastmsg && isdigit(ptr[-1]))
|
||||
while (ptr > lastmsg && isdigit(STOUC(ptr[-1])))
|
||||
ptr--;
|
||||
if (isdigit(*ptr)) {
|
||||
if (isdigit(STOUC(*ptr))) {
|
||||
zfstatus &= ~ZFST_NOSZ;
|
||||
if (getsize) {
|
||||
long sz = zstrtol(ptr, NULL, 10);
|
||||
|
@ -1017,6 +1029,13 @@ zfgetdata(char *name, char *rest, char *cmd, int getsize)
|
|||
return 1;
|
||||
}
|
||||
zdfd = newfd; /* this is now the actual data fd */
|
||||
} else {
|
||||
/*
|
||||
* We avoided dup'ing zdfd up to this point, to try to keep
|
||||
* things simple, so we now need to move it out of the way
|
||||
* of the user-visible fd's.
|
||||
*/
|
||||
zdfd = zfmovefd(zdfd);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1659,7 +1678,7 @@ zftp_open(char *name, char **args, int flags)
|
|||
}
|
||||
|
||||
zsock.sin_port = zservp->s_port;
|
||||
zcfd = zfmovefd(socket(zsock.sin_family, SOCK_STREAM, 0));
|
||||
zcfd = socket(zsock.sin_family, SOCK_STREAM, 0);
|
||||
if (zcfd < 0) {
|
||||
zwarnnam(name, "socket failed: %e", NULL, errno);
|
||||
zfunsetparam("ZFTP_HOST");
|
||||
|
@ -1667,12 +1686,6 @@ zftp_open(char *name, char **args, int flags)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#if defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
/* If the shell execs a program, we don't want this fd left open. */
|
||||
len = FD_CLOEXEC;
|
||||
fcntl(zcfd, F_SETFD, &len);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* now connect the socket. manual pages all say things like `this is all
|
||||
* explained oh-so-wonderfully in some other manual page'. not.
|
||||
|
@ -1708,6 +1721,19 @@ zftp_open(char *name, char **args, int flags)
|
|||
/* now we can talk to the control connection */
|
||||
zcfinish = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Move the fd out of the user-visible range. We need to do
|
||||
* this after the connect() on some systems.
|
||||
*/
|
||||
zcfd = zfmovefd(zcfd);
|
||||
|
||||
#if defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
/* If the shell execs a program, we don't want this fd left open. */
|
||||
len = FD_CLOEXEC;
|
||||
fcntl(zcfd, F_SETFD, &len);
|
||||
#endif
|
||||
|
||||
len = sizeof(zsock);
|
||||
if (getsockname(zcfd, (struct sockaddr *)&zsock, &len) < 0) {
|
||||
zwarnnam(name, "getsockname failed: %e", NULL, errno);
|
||||
|
@ -2022,6 +2048,69 @@ zftp_login(char *name, char **args, int flags)
|
|||
return zfgetcwd();
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the server wants to tell us something. On a timeout, we usually
|
||||
* have a `421 Timeout' or something such waiting for us, so we read
|
||||
* it here. As well as being called explicitly by the user
|
||||
* (precmd is a very good place for this, it's cheap since it has
|
||||
* no network overhead), we call it in the bin_zftp front end if we
|
||||
* have a connection and weren't going to call it anyway.
|
||||
*
|
||||
* Poll-free and select-free systems are few and far between these days,
|
||||
* but I'm willing to consider suggestions.
|
||||
*/
|
||||
|
||||
/**/
|
||||
static int
|
||||
zftp_test(char *name, char **args, int flags)
|
||||
{
|
||||
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
|
||||
int ret;
|
||||
# ifdef HAVE_POLL
|
||||
struct pollfd pfd;
|
||||
# else
|
||||
fd_set f;
|
||||
struct timeval tv;
|
||||
# endif /* HAVE_POLL */
|
||||
|
||||
if (zcfd == -1)
|
||||
return 1;
|
||||
|
||||
# ifdef HAVE_POLL
|
||||
# ifndef POLLIN
|
||||
/* safety first, though I think POLLIN is more common */
|
||||
# define POLLIN POLLNORM
|
||||
# endif /* HAVE_POLL */
|
||||
pfd.fd = zcfd;
|
||||
pfd.events = POLLIN;
|
||||
if ((ret = poll(&pfd, 1, 0)) < 0 && errno != EINTR && errno != EAGAIN)
|
||||
zfclose();
|
||||
else if (ret > 0 && pfd.revents) {
|
||||
/* handles 421 (maybe a bit noisily?) */
|
||||
zfgetmsg();
|
||||
}
|
||||
# else
|
||||
FD_ZERO(&f);
|
||||
FD_SET(zcfd, &f);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
if ((ret = select(zcfd +1, (SELECT_ARG_2_T) &f, NULL, NULL, &tv)) < 0
|
||||
&& errno != EINTR)
|
||||
zfclose();
|
||||
else if (ret > 0) {
|
||||
/* handles 421 */
|
||||
zfgetmsg();
|
||||
}
|
||||
# endif /* HAVE_POLL */
|
||||
/* if we now have zcfd == -1, then we've just been dumped out. */
|
||||
return (zcfd == -1) ? 2 : 0;
|
||||
#else
|
||||
zfwarnnam(name, "not supported on this system.", NULL, 0);
|
||||
return 3;
|
||||
#endif /* defined(HAVE_POLL) || defined(HAVE_SELECT) */
|
||||
}
|
||||
|
||||
|
||||
/* do ls or dir on the remote directory */
|
||||
|
||||
/**/
|
||||
|
@ -2476,7 +2565,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
|
|||
char fullname[11] = "zftp ";
|
||||
char *cnam = *args++, *prefs, *ptr;
|
||||
Zftpcmd zptr;
|
||||
int n, ret;
|
||||
int n, ret = 0;
|
||||
|
||||
for (zptr = zftpcmdtab; zptr->nam; zptr++)
|
||||
if (!strcmp(zptr->nam, cnam))
|
||||
|
@ -2521,8 +2610,25 @@ bin_zftp(char *name, char **args, char *ops, int func)
|
|||
"B" : "S"), ZFPM_READONLY);
|
||||
}
|
||||
}
|
||||
#if defined(HAVE_SELECT) || defined (HAVE_POLL)
|
||||
if (zcfd != -1 && !(zptr->flags & ZFTP_TEST)) {
|
||||
/*
|
||||
* Test the connection for a bad fd or incoming message, but
|
||||
* only if the connection was last heard of open, and
|
||||
* if we are not about to call the test command anyway.
|
||||
* Not worth it unless we have select() or poll().
|
||||
*/
|
||||
ret = zftp_test("zftp test", NULL, 0);
|
||||
}
|
||||
#endif
|
||||
if ((zptr->flags & ZFTP_CONN) && zcfd == -1) {
|
||||
zwarnnam(fullname, "not connected.", NULL, 0);
|
||||
if (ret != 2) {
|
||||
/*
|
||||
* with ret == 2, we just got dumped out in the test,
|
||||
* so enough messages already.
|
||||
*/
|
||||
zwarnnam(fullname, "not connected.", NULL, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ struct compctl cc_compos, cc_default, cc_first, cc_dummy;
|
|||
/**/
|
||||
Cmlist cmatcher;
|
||||
|
||||
/* pointers to functions required by zle */
|
||||
/* pointers to functions required by zle and defined by compctl */
|
||||
|
||||
/**/
|
||||
void (*printcompctlptr) _((char *, Compctl, int, int));
|
||||
|
@ -49,6 +49,24 @@ void (*printcompctlptr) _((char *, Compctl, int, int));
|
|||
/**/
|
||||
Compctl (*compctl_widgetptr) _((char *, char **));
|
||||
|
||||
/**/
|
||||
void (*makecompparamsptr) _((void));
|
||||
|
||||
/* pointers to functions required by compctl and defined by zle */
|
||||
|
||||
/**/
|
||||
void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, int, int, int, int, int, char **));
|
||||
|
||||
/**/
|
||||
char *(*comp_strptr) _((int*,int*));
|
||||
|
||||
/**/
|
||||
int (*getcpatptr) _((char *, int, char *, int));
|
||||
|
||||
/**/
|
||||
void (*makecomplistcallptr) _((Compctl));
|
||||
|
||||
|
||||
/* Hash table for completion info for commands */
|
||||
|
||||
/**/
|
||||
|
@ -72,6 +90,23 @@ char **clwords;
|
|||
/**/
|
||||
int incompctlfunc;
|
||||
|
||||
/* != 0 if we are in a new style completion function */
|
||||
|
||||
/**/
|
||||
int incompfunc;
|
||||
|
||||
/* global variables for shell parameters in new style completion */
|
||||
|
||||
/**/
|
||||
long compcurrent,
|
||||
compnmatches;
|
||||
|
||||
/**/
|
||||
char *compcontext,
|
||||
*compcommand,
|
||||
*compprefix,
|
||||
*compsuffix,
|
||||
*compiprefix;
|
||||
|
||||
/* This variable and the functions rembslash() and quotename() came from *
|
||||
* zle_tricky.c, but are now used in compctl.c, too. */
|
||||
|
@ -443,6 +478,8 @@ setup_comp1(Module m)
|
|||
cc_first.refc = 10000;
|
||||
cc_first.mask = 0;
|
||||
cc_first.mask2 = CC_CCCONT;
|
||||
compcontext = compcommand = compprefix = compsuffix =
|
||||
compiprefix = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -469,6 +506,11 @@ finish_comp1(Module m)
|
|||
deletehashtable(compctltab);
|
||||
zfree(clwords, clwsize * sizeof(char *));
|
||||
compctlreadptr = fallback_compctlread;
|
||||
zsfree(compcontext);
|
||||
zsfree(compcommand);
|
||||
zsfree(compprefix);
|
||||
zsfree(compiprefix);
|
||||
zsfree(compsuffix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!
|
||||
addmatchesptr
|
||||
cc_compos
|
||||
cc_default
|
||||
cc_dummy
|
||||
|
@ -8,14 +9,26 @@ clwords
|
|||
clwpos
|
||||
clwsize
|
||||
cmatcher
|
||||
compcommand
|
||||
compcontext
|
||||
compctl_widgetptr
|
||||
compctltab
|
||||
compcurrent
|
||||
compiprefix
|
||||
compnmatches
|
||||
compprefix
|
||||
comp_strptr
|
||||
compsuffix
|
||||
freecmatcher
|
||||
freecmlist
|
||||
freecompcond
|
||||
freecompctl
|
||||
getcpatptr
|
||||
incompctlfunc
|
||||
incompfunc
|
||||
instring
|
||||
makecomplistcallptr
|
||||
makecompparamsptr
|
||||
patcomps
|
||||
printcompctlptr
|
||||
quotename
|
||||
|
|
|
@ -373,7 +373,7 @@ parse_class(Cpattern p, unsigned char *s, unsigned char e)
|
|||
|
||||
/**/
|
||||
static int
|
||||
get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
||||
get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl)
|
||||
{
|
||||
/* Parse the basic flags for completion:
|
||||
* first is a flag that we are not in extended completion,
|
||||
|
@ -394,12 +394,17 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
if(argv[0] && argv[0][0] == '-')
|
||||
argv++;
|
||||
*av = argv;
|
||||
freecompctl(cc);
|
||||
cclist = COMP_REMOVE;
|
||||
return 0;
|
||||
if (cl)
|
||||
return 1;
|
||||
else {
|
||||
freecompctl(cc);
|
||||
cclist = COMP_REMOVE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memset((void *)&cct, 0, sizeof(cct));
|
||||
cct.mask2 = CC_CCCONT;
|
||||
|
||||
/* Loop through the flags until we have no more: *
|
||||
* those with arguments are not properly allocated yet, *
|
||||
|
@ -505,6 +510,10 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
{
|
||||
char *p;
|
||||
|
||||
if (cl) {
|
||||
zerrnam(name, "illegal option -%c", NULL, **argv);
|
||||
return 1;
|
||||
}
|
||||
if ((*argv)[1]) {
|
||||
p = (*argv) + 1;
|
||||
*argv = "" - 1;
|
||||
|
@ -516,26 +525,28 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
p = *++argv;
|
||||
*argv = "" - 1;
|
||||
}
|
||||
while (*p) {
|
||||
switch (*p) {
|
||||
case '+':
|
||||
cct.mask2 |= CC_XORCONT;
|
||||
break;
|
||||
case 'c':
|
||||
cct.mask2 |= CC_CCCONT;
|
||||
break;
|
||||
case '-':
|
||||
cct.mask2 |= CC_PATCONT;
|
||||
break;
|
||||
case 'x':
|
||||
cct.mask2 |= CC_DEFCONT;
|
||||
break;
|
||||
default:
|
||||
zwarnnam(name, "invalid retry specification character `%c'",
|
||||
NULL, *p);
|
||||
return 1;
|
||||
}
|
||||
p++;
|
||||
switch (*p) {
|
||||
case '+':
|
||||
cct.mask2 = CC_XORCONT;
|
||||
break;
|
||||
case 'n':
|
||||
cct.mask2 = 0;
|
||||
break;
|
||||
case '-':
|
||||
cct.mask2 = CC_PATCONT;
|
||||
break;
|
||||
case 'x':
|
||||
cct.mask2 = CC_DEFCONT;
|
||||
break;
|
||||
default:
|
||||
zwarnnam(name, "invalid retry specification character `%c'",
|
||||
NULL, *p);
|
||||
return 1;
|
||||
}
|
||||
if (p[1]) {
|
||||
zwarnnam(name, "too many retry specification characters: `%s'",
|
||||
p + 1, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -645,7 +656,10 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
}
|
||||
break;
|
||||
case 'l':
|
||||
if ((*argv)[1]) {
|
||||
if (cl) {
|
||||
zerrnam(name, "illegal option -%c", NULL, **argv);
|
||||
return 1;
|
||||
} else if ((*argv)[1]) {
|
||||
cct.subcmd = (*argv) + 1;
|
||||
*argv = "" - 1;
|
||||
} else if (!argv[1]) {
|
||||
|
@ -745,6 +759,10 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
*argv = "" - 1;
|
||||
break;
|
||||
case 'C':
|
||||
if (cl) {
|
||||
zerrnam(name, "illegal option -%c", NULL, **argv);
|
||||
return 1;
|
||||
}
|
||||
if (first && !hx) {
|
||||
cclist |= COMP_COMMAND;
|
||||
} else {
|
||||
|
@ -754,6 +772,10 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
}
|
||||
break;
|
||||
case 'D':
|
||||
if (cl) {
|
||||
zerrnam(name, "illegal option -%c", NULL, **argv);
|
||||
return 1;
|
||||
}
|
||||
if (first && !hx) {
|
||||
isdef = 1;
|
||||
cclist |= COMP_DEFAULT;
|
||||
|
@ -764,7 +786,11 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
}
|
||||
break;
|
||||
case 'T':
|
||||
if (first && !hx) {
|
||||
if (cl) {
|
||||
zerrnam(name, "illegal option -%c", NULL, **argv);
|
||||
return 1;
|
||||
}
|
||||
if (first && !hx) {
|
||||
cclist |= COMP_FIRST;
|
||||
} else {
|
||||
zwarnnam(name, "misplaced first completion (-T) flag",
|
||||
|
@ -773,6 +799,10 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
}
|
||||
break;
|
||||
case 'L':
|
||||
if (cl) {
|
||||
zerrnam(name, "illegal option -%c", NULL, **argv);
|
||||
return 1;
|
||||
}
|
||||
if (!first || hx) {
|
||||
zwarnnam(name, "illegal use of -L flag", NULL, 0);
|
||||
return 1;
|
||||
|
@ -780,6 +810,10 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
cclist |= COMP_LIST;
|
||||
break;
|
||||
case 'x':
|
||||
if (cl) {
|
||||
zerrnam(name, "extended completion not allowed", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (!argv[1]) {
|
||||
zwarnnam(name, "condition expected after -%c", NULL,
|
||||
**argv);
|
||||
|
@ -811,6 +845,10 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
|
||||
if (*++argv && (!ready || ready == 2) &&
|
||||
**argv == '+' && !argv[0][1]) {
|
||||
if (cl) {
|
||||
zerrnam(name, "xor'ed completion illegal", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
/* There's an alternative (+) completion: assign
|
||||
* what we have so far before moving on to that.
|
||||
*/
|
||||
|
@ -835,6 +873,7 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef)
|
|||
cc->xor = (Compctl) zcalloc(sizeof(*cc));
|
||||
cc = cc->xor;
|
||||
memset((void *)&cct, 0, sizeof(cct));
|
||||
cct.mask2 = CC_CCCONT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1084,7 +1123,7 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
|
|||
(*next)->cond = m;
|
||||
argv++;
|
||||
/* End of the condition; get the flags that go with it. */
|
||||
if (get_compctl(name, &argv, *next, 0, isdef))
|
||||
if (get_compctl(name, &argv, *next, 0, isdef, 0))
|
||||
return 1;
|
||||
if ((!argv || !*argv) && (cclist & COMP_SPECIAL))
|
||||
/* default, first, or command completion finished */
|
||||
|
@ -1362,17 +1401,16 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
|
|||
t >>= 1;
|
||||
}
|
||||
}
|
||||
if (flags2 & (CC_XORCONT | CC_CCCONT | CC_PATCONT | CC_DEFCONT)) {
|
||||
if (flags2 & (CC_XORCONT | CC_PATCONT | CC_DEFCONT)) {
|
||||
printf(" -t");
|
||||
if (flags2 & CC_XORCONT)
|
||||
putchar('+');
|
||||
if (flags2 & CC_CCCONT)
|
||||
putchar('c');
|
||||
if (flags2 & CC_PATCONT)
|
||||
putchar('-');
|
||||
if (flags2 & CC_DEFCONT)
|
||||
putchar('x');
|
||||
}
|
||||
} else if (!(flags2 & CC_CCCONT))
|
||||
printf(" -tn");
|
||||
/* now flags with arguments */
|
||||
printif(cc->mstr, 'M');
|
||||
if (flags2 & CC_NOSORT)
|
||||
|
@ -1518,7 +1556,7 @@ bin_compctl(char *name, char **argv, char *ops, int func)
|
|||
return ret - 1;
|
||||
|
||||
cc = (Compctl) zcalloc(sizeof(*cc));
|
||||
if (get_compctl(name, &argv, cc, 1, 0)) {
|
||||
if (get_compctl(name, &argv, cc, 1, 0, 0)) {
|
||||
freecompctl(cc);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1610,7 +1648,7 @@ compctl_widget(char *name, char **argv)
|
|||
cclist = 0;
|
||||
showmask = 0;
|
||||
|
||||
if (get_compctl(name, &argv, cc, 1, 0)) {
|
||||
if (get_compctl(name, &argv, cc, 1, 0, 0)) {
|
||||
freecompctl(cc);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1632,8 +1670,478 @@ compctl_widget(char *name, char **argv)
|
|||
return cc;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_complist(char *name, char **argv, char *ops, int func)
|
||||
{
|
||||
Compctl cc;
|
||||
int ret = 0;
|
||||
|
||||
if (!incompfunc) {
|
||||
zerrnam(name, "can only be called from completion function", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
cc = (Compctl) zcalloc(sizeof(*cc));
|
||||
cclist = 0;
|
||||
showmask = 0;
|
||||
|
||||
if (get_compctl(name, &argv, cc, 1, 0, 1))
|
||||
ret = 1;
|
||||
else if (*argv) {
|
||||
zerrnam(name, "command names illegal", NULL, 0);
|
||||
ret = 1;
|
||||
} else
|
||||
makecomplistcallptr(cc);
|
||||
|
||||
freecompctl(cc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_compadd(char *name, char **argv, char *ops, int func)
|
||||
{
|
||||
char *p, **sp, *e;
|
||||
char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
|
||||
char *pre = NULL, *suf = NULL, *group = NULL;
|
||||
int f = 0, q = 0, m = 0, ns = 0, a = 0;
|
||||
|
||||
if (!incompfunc) {
|
||||
zerrnam(name, "can only be called from completion function", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
for (; *argv && **argv == '-'; argv++) {
|
||||
for (p = *argv + 1; *p; p++) {
|
||||
sp = NULL;
|
||||
switch (*p) {
|
||||
case 'q':
|
||||
f |= CMF_REMOVE;
|
||||
break;
|
||||
case 'Q':
|
||||
q = 1;
|
||||
break;
|
||||
case 'f':
|
||||
f |= CMF_FILE;
|
||||
break;
|
||||
case 'n':
|
||||
f |= CMF_NOLIST;
|
||||
break;
|
||||
case 'U':
|
||||
m = 1;
|
||||
break;
|
||||
case 'P':
|
||||
sp = ⪯
|
||||
e = "string expected after -%c";
|
||||
break;
|
||||
case 'S':
|
||||
sp = &suf;
|
||||
e = "string expected after -%c";
|
||||
break;
|
||||
case 'J':
|
||||
sp = &group;
|
||||
e = "group name expected after -%c";
|
||||
break;
|
||||
case 'V':
|
||||
if (!group)
|
||||
ns = 1;
|
||||
sp = &group;
|
||||
e = "group name expected after -%c";
|
||||
break;
|
||||
case 'i':
|
||||
sp = &ipre;
|
||||
e = "string expected after -%c";
|
||||
break;
|
||||
case 'p':
|
||||
sp = &ppre;
|
||||
e = "string expected after -%c";
|
||||
break;
|
||||
case 's':
|
||||
sp = &psuf;
|
||||
e = "string expected after -%c";
|
||||
break;
|
||||
case 'W':
|
||||
sp = &prpre;
|
||||
e = "string expected after -%c";
|
||||
break;
|
||||
case 'a':
|
||||
a = 1;
|
||||
break;
|
||||
case '-':
|
||||
argv++;
|
||||
goto ca_args;
|
||||
default:
|
||||
zerrnam(name, "bad option: -%c", NULL, *p);
|
||||
return 1;
|
||||
}
|
||||
if (sp) {
|
||||
if (*sp) {
|
||||
zerrnam(name, "doubled option: -%c", NULL, *p);
|
||||
return 1;
|
||||
}
|
||||
if (p[1]) {
|
||||
*sp = p + 1;
|
||||
p = "" - 1;
|
||||
} else if (argv[1]) {
|
||||
*sp = *++argv;
|
||||
p = "" - 1;
|
||||
} else {
|
||||
zerrnam(name, e, NULL, *p);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ca_args:
|
||||
if (!*argv) {
|
||||
zerrnam(name, "missing completions", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
|
||||
f, q, m, ns, a, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define VAR(X) ((void *) (&(X)))
|
||||
static struct compparam {
|
||||
char *name;
|
||||
int type;
|
||||
void *var;
|
||||
} compparams[] = {
|
||||
{ "CURRENT", PM_INTEGER, VAR(compcurrent) },
|
||||
{ "CONTEXT", PM_SCALAR, VAR(compcontext) },
|
||||
{ "COMMAND", PM_SCALAR, VAR(compcommand) },
|
||||
{ "PREFIX", PM_SCALAR, VAR(compprefix) },
|
||||
{ "SUFFIX", PM_SCALAR, VAR(compsuffix) },
|
||||
{ "IPREFIX", PM_SCALAR, VAR(compiprefix) },
|
||||
{ "NMATCHES", PM_INTEGER, VAR(compnmatches) },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
/**/
|
||||
void makecompparams(void)
|
||||
{
|
||||
struct compparam *cp;
|
||||
|
||||
for (cp = compparams; cp->name; cp++) {
|
||||
Param pm = createparam(cp->name, cp->type | PM_SPECIAL);
|
||||
if (!pm)
|
||||
pm = (Param) paramtab->getnode(paramtab, cp->name);
|
||||
DPUTS(!pm, "param not set in makecompparams");
|
||||
|
||||
pm->level = locallevel;
|
||||
pm->u.data = cp->var;
|
||||
switch(PM_TYPE(cp->type)) {
|
||||
case PM_SCALAR:
|
||||
pm->sets.cfn = strvarsetfn;
|
||||
pm->gets.cfn = strvargetfn;
|
||||
break;
|
||||
case PM_INTEGER:
|
||||
pm->sets.ifn = intvarsetfn;
|
||||
pm->gets.ifn = intvargetfn;
|
||||
break;
|
||||
}
|
||||
pm->unsetfn = compunsetfn;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
compunsetfn(Param pm, int exp)
|
||||
{
|
||||
if (exp)
|
||||
stdunsetfn(pm, exp);
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
comp_wrapper(List list, FuncWrap w, char *name)
|
||||
{
|
||||
if (!incompfunc)
|
||||
return 1;
|
||||
else {
|
||||
char *octxt, *ocmd, *opre, *osuf, *oipre;
|
||||
long ocur;
|
||||
|
||||
ocur = compcurrent;
|
||||
octxt = dupstring(compcontext);
|
||||
ocmd = dupstring(compcommand);
|
||||
opre = dupstring(compprefix);
|
||||
osuf = dupstring(compsuffix);
|
||||
oipre = dupstring(compiprefix);
|
||||
|
||||
runshfunc(list, w, name);
|
||||
|
||||
compcurrent = ocur;
|
||||
zsfree(compcontext);
|
||||
compcontext = ztrdup(octxt);
|
||||
zsfree(compcommand);
|
||||
compcommand = ztrdup(ocmd);
|
||||
zsfree(compprefix);
|
||||
compprefix = ztrdup(opre);
|
||||
zsfree(compsuffix);
|
||||
compsuffix = ztrdup(osuf);
|
||||
zsfree(compiprefix);
|
||||
compiprefix = ztrdup(oipre);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
ignore_prefix(int l)
|
||||
{
|
||||
char *o, sav = compprefix[l];
|
||||
|
||||
compprefix[l] = '\0';
|
||||
o = compiprefix;
|
||||
compiprefix = tricat(o, compprefix, "");
|
||||
zsfree(o);
|
||||
compprefix[l] = sav;
|
||||
o = compprefix;
|
||||
compprefix = ztrdup(o + l);
|
||||
zsfree(o);
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
comp_check(void)
|
||||
{
|
||||
if (!incompfunc) {
|
||||
zerr("condition can only be used in completion function", NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
restrict_range(int b, int e)
|
||||
{
|
||||
int i = e - b;
|
||||
char **p = (char **) zcalloc((i + 1) * sizeof(char *)), **q, **pp;
|
||||
|
||||
for (q = p, pp = pparams + b + 1; i; i--, q++, pp++)
|
||||
*q = ztrdup(*pp);
|
||||
zsfree(compcommand);
|
||||
compcommand = ztrdup(pparams[b]);
|
||||
freearray(pparams);
|
||||
pparams = p;
|
||||
zsfree(compcontext);
|
||||
if ((compcurrent -= b + 1))
|
||||
compcontext = ztrdup("arg");
|
||||
else
|
||||
compcontext = ztrdup("cmd");
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_prefix(char **a, int id)
|
||||
{
|
||||
if (comp_check())
|
||||
return strpfx(cond_str(a, 0), compprefix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_iprefix(char **a, int id)
|
||||
{
|
||||
if (comp_check()) {
|
||||
char *s = cond_str(a, 0);
|
||||
|
||||
if (strpfx(s, compprefix)) {
|
||||
ignore_prefix(strlen(s));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_position(char **a, int id)
|
||||
{
|
||||
if (comp_check()) {
|
||||
int b = cond_val(a, 0), e = (a[1] ? cond_val(a, 1) : b);
|
||||
int l = arrlen(pparams), t, i = compcurrent - 1;
|
||||
|
||||
if (b > 0)
|
||||
b--;
|
||||
if (e > 0)
|
||||
e--;
|
||||
if (b < 0)
|
||||
b += l;
|
||||
if (e < 0)
|
||||
e += l;
|
||||
t = (b >= 0 && e >= 0 && i >= b && i <= e && b <= e);
|
||||
|
||||
if (t && a[1]) {
|
||||
if (b > l)
|
||||
b = l;
|
||||
if (e > l)
|
||||
e = l;
|
||||
restrict_range(b, e);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_word(char **a, int id)
|
||||
{
|
||||
if (comp_check()) {
|
||||
int o = ((id & 2) ? compcurrent : 0) + cond_val(a, 0);
|
||||
int l = arrlen(pparams);
|
||||
char *s;
|
||||
|
||||
if (o < 0)
|
||||
o += l;
|
||||
|
||||
o--;
|
||||
if (o < 0 || o >= l)
|
||||
return 0;
|
||||
|
||||
s = pparams[o];
|
||||
return ((id & 1) ? cond_match(a, 1, s) : !strcmp(s, cond_str(a, 1)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_strcl(char **a, int id)
|
||||
{
|
||||
if (comp_check()) {
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
if (a[1]) {
|
||||
s = cond_str(a, 1);
|
||||
i = cond_val(a, 0);
|
||||
} else {
|
||||
s = cond_str(a, 0);
|
||||
i = -1;
|
||||
}
|
||||
if (!getcpatptr) {
|
||||
zerr("zle not loaded, zle condition not available", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
i = getcpatptr(comp_strptr(NULL, NULL), i, s, id);
|
||||
if (i != -1) {
|
||||
ignore_prefix(i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_words(char **a, int id)
|
||||
{
|
||||
if (comp_check()) {
|
||||
int b = cond_val(a, 0), e = (a[1] ? cond_val(a, 1) : -1);
|
||||
int l = arrlen(pparams);
|
||||
|
||||
return (l >= b && l <= e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_range(char **a, int id)
|
||||
{
|
||||
if (comp_check()) {
|
||||
char *s, **p;
|
||||
int i, l = arrlen(pparams), t = 0, b = 0, e = l - 1;
|
||||
Comp c;
|
||||
|
||||
i = compcurrent - 1;
|
||||
if (i < 0 || i >= l)
|
||||
return 0;
|
||||
|
||||
if (id & 1) {
|
||||
s = a[0];
|
||||
singsub(&s);
|
||||
c = parsereg(s);
|
||||
} else
|
||||
s = cond_str(a, 0);
|
||||
|
||||
for (i--, p = pparams + i; i >= 0; p--, i--) {
|
||||
if (((id & 1) ? domatch(*p, c, 0) : !strcmp(*p, s))) {
|
||||
b = i + 1;
|
||||
t = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t && (id & 2)) {
|
||||
int tt = 0;
|
||||
|
||||
if (id & 1) {
|
||||
s = a[1];
|
||||
singsub(&s);
|
||||
c = parsereg(s);
|
||||
} else
|
||||
s = cond_str(a, 1);
|
||||
|
||||
for (i++, p = pparams + i; i < l; p++, i++) {
|
||||
if (((id & 1) ? domatch(*p, c, 0) : !strcmp(*p, s))) {
|
||||
e = i - 1;
|
||||
tt = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tt && i < compcurrent)
|
||||
t = 0;
|
||||
}
|
||||
if (e < b)
|
||||
t = 0;
|
||||
if (t)
|
||||
restrict_range(b, e);
|
||||
return t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_nmatches(char **a, int id)
|
||||
{
|
||||
if (comp_check())
|
||||
return compnmatches == cond_val(a, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct builtin bintab[] = {
|
||||
BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("complist", 0, bin_complist, 1, -1, 0, NULL, NULL),
|
||||
BUILTIN("compadd", 0, bin_compadd, 1, -1, 0, NULL, NULL),
|
||||
};
|
||||
|
||||
static struct conddef cotab[] = {
|
||||
CONDDEF("prefix", 0, cond_prefix, 1, 1, 0),
|
||||
CONDDEF("iprefix", 0, cond_iprefix, 1, 1, 0),
|
||||
CONDDEF("position", 0, cond_position, 1, 2, 0),
|
||||
CONDDEF("word", 0, cond_word, 2, 2, 0),
|
||||
CONDDEF("mword", 0, cond_word, 2, 2, 1),
|
||||
CONDDEF("current", 0, cond_word, 2, 2, 2),
|
||||
CONDDEF("mcurrent", 0, cond_word, 2, 2, 3),
|
||||
CONDDEF("string", 0, cond_strcl, 1, 2, 0),
|
||||
CONDDEF("class", 0, cond_strcl, 1, 2, 1),
|
||||
CONDDEF("words", 0, cond_words, 1, 2, 0),
|
||||
CONDDEF("between", 0, cond_range, 2, 2, 2),
|
||||
CONDDEF("mbetween", 0, cond_range, 2, 2, 3),
|
||||
CONDDEF("after", 0, cond_range, 1, 1, 0),
|
||||
CONDDEF("mafter", 0, cond_range, 1, 1, 1),
|
||||
CONDDEF("nmatches", 0, cond_nmatches, 1, 1, 0),
|
||||
};
|
||||
|
||||
static struct funcwrap wrapper[] = {
|
||||
WRAPDEF(comp_wrapper),
|
||||
};
|
||||
|
||||
/**/
|
||||
|
@ -1643,6 +2151,7 @@ setup_compctl(Module m)
|
|||
compctltab->printnode = printcompctlp;
|
||||
printcompctlptr = printcompctl;
|
||||
compctl_widgetptr = compctl_widget;
|
||||
makecompparamsptr = makecompparams;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1650,7 +2159,9 @@ setup_compctl(Module m)
|
|||
int
|
||||
boot_compctl(Module m)
|
||||
{
|
||||
if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)))
|
||||
if(!(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
|
||||
addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
|
||||
!addwrapper(m, wrapper)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1662,6 +2173,8 @@ int
|
|||
cleanup_compctl(Module m)
|
||||
{
|
||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
|
||||
deletewrapper(m, wrapper);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1672,6 +2185,7 @@ finish_compctl(Module m)
|
|||
compctltab->printnode = NULL;
|
||||
printcompctlptr = NULL;
|
||||
compctl_widgetptr = NULL;
|
||||
makecompparamsptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
moddeps="comp1"
|
||||
|
||||
autobins="compctl"
|
||||
autobins="compctl complist compadd"
|
||||
|
||||
autoprefixconds="prefix iprefix position word mword current mcurrent string class words between mbetween after mafter nmatches"
|
||||
|
||||
objects="compctl.o"
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
"beginning-of-line-hist", beginningoflinehist, 0
|
||||
"capitalize-word", capitalizeword, 0
|
||||
"clear-screen", clearscreen, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
|
||||
"complete-word", completeword, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
"complete-word", completeword, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
"copy-prev-word", copyprevword, 0
|
||||
"copy-region-as-kill", copyregionaskill, ZLE_KEEPSUFFIX
|
||||
"delete-char", deletechar, ZLE_KEEPSUFFIX
|
||||
"delete-char-or-list", deletecharorlist, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
"delete-char-or-list", deletecharorlist, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
"delete-word", deleteword, ZLE_KEEPSUFFIX
|
||||
"describe-key-briefly", describekeybriefly, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
|
||||
"digit-argument", digitargument, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
|
||||
|
@ -48,8 +48,8 @@
|
|||
"execute-named-cmd", NULL, 0
|
||||
"expand-cmd-path", expandcmdpath, 0
|
||||
"expand-history", expandhistory, 0
|
||||
"expand-or-complete", expandorcomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
"expand-or-complete-prefix", expandorcompleteprefix, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
"expand-or-complete", expandorcomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
"expand-or-complete-prefix", expandorcompleteprefix, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
"expand-word", expandword, 0
|
||||
"forward-char", forwardchar, 0
|
||||
"forward-word", forwardword, 0
|
||||
|
@ -68,11 +68,11 @@
|
|||
"kill-region", killregion, ZLE_KILL | ZLE_KEEPSUFFIX
|
||||
"kill-whole-line", killwholeline, ZLE_KILL | ZLE_KEEPSUFFIX
|
||||
"kill-word", killword, ZLE_KILL | ZLE_KEEPSUFFIX
|
||||
"list-choices", listchoices, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
|
||||
"list-choices", listchoices, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_ISCOMP
|
||||
"list-expand", listexpand, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
|
||||
"magic-space", magicspace, 0
|
||||
"menu-complete", menucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
"menu-expand-or-complete", menuexpandorcomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
"menu-complete", menucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
"menu-expand-or-complete", menuexpandorcomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
"neg-argument", negargument, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
|
||||
"overwrite-mode", overwritemode, 0
|
||||
"pound-insert", poundinsert, 0
|
||||
|
@ -84,7 +84,7 @@
|
|||
"quote-region", quoteregion, 0
|
||||
"redisplay", redisplay, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
|
||||
"redo", redo, 0
|
||||
"reverse-menu-complete", reversemenucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
"reverse-menu-complete", reversemenucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
"run-help", processcmd, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
|
||||
"self-insert", selfinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
"self-insert-unmeta", selfinsertunmeta, ZLE_MENUCMP | ZLE_KEEPSUFFIX
|
||||
|
|
|
@ -47,23 +47,29 @@ struct widget {
|
|||
ZleIntFunc fn; /* pointer to internally implemented widget */
|
||||
char *fnnam; /* name of the shell function for user-defined widget */
|
||||
Compctl cc; /* for use with a WIDGET_COMP widget */
|
||||
struct {
|
||||
ZleIntFunc fn; /* internal widget function to call */
|
||||
char *wid; /* name of widget to call */
|
||||
char *func; /* name of shell function to call */
|
||||
} comp;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define WIDGET_INT (1<<0) /* widget is internally implemented */
|
||||
#define WIDGET_COMP (1<<1) /* Special completion widget */
|
||||
#define ZLE_MENUCMP (1<<2) /* DON'T invalidate completion list */
|
||||
#define ZLE_YANK (1<<3)
|
||||
#define ZLE_LINEMOVE (1<<4) /* command is a line-oriented movement */
|
||||
#define ZLE_LASTCOL (1<<5) /* command maintains lastcol correctly */
|
||||
#define ZLE_KILL (1<<6)
|
||||
#define WIDGET_NCOMP (1<<2) /* new style completion widget */
|
||||
#define ZLE_MENUCMP (1<<3) /* DON'T invalidate completion list */
|
||||
#define ZLE_YANK (1<<4)
|
||||
#define ZLE_LINEMOVE (1<<5) /* command is a line-oriented movement */
|
||||
#define ZLE_LASTCOL (1<<6) /* command maintains lastcol correctly */
|
||||
#define ZLE_KILL (1<<7)
|
||||
#define ZLE_KEEPSUFFIX (1<<9) /* DON'T remove added suffix */
|
||||
#define ZLE_USEMENU (1<<10) /* Do ) use menu completion for */
|
||||
#define ZLE_NOMENU (1<<11) /* Don't ) widget, else use default */
|
||||
#define ZLE_USEGLOB (1<<12) /* Do ) use glob completion for */
|
||||
#define ZLE_NOGLOB (1<<13) /* Don't ) widget, else use default */
|
||||
#define ZLE_NOTCOMMAND (1<<14) /* widget should not alter lastcmd */
|
||||
|
||||
#define ZLE_ISCOMP (1<<15) /* usable for new style completion */
|
||||
/* thingies */
|
||||
|
||||
struct thingy {
|
||||
|
|
|
@ -598,10 +598,10 @@ bin_bindkey(char *name, char **argv, char *ops, int func)
|
|||
int n;
|
||||
|
||||
/* select operation and ensure no clashing arguments */
|
||||
for(op = opns; op->o && !ops[op->o]; op++) ;
|
||||
for(op = opns; op->o && !ops[STOUC(op->o)]; op++) ;
|
||||
if(op->o)
|
||||
for(opp = op; (++opp)->o; )
|
||||
if(ops[opp->o]) {
|
||||
if(ops[STOUC(opp->o)]) {
|
||||
zwarnnam(name, "incompatible operation selection options",
|
||||
NULL, 0);
|
||||
return 1;
|
||||
|
|
|
@ -443,9 +443,9 @@ zleread(char *lp, char *rp, int ha)
|
|||
insmode = unset(OVERSTRIKE);
|
||||
eofsent = 0;
|
||||
resetneeded = 0;
|
||||
lpptbuf = promptexpand(lp, 1, NULL, NULL);
|
||||
lpromptbuf = promptexpand(lp, 1, NULL, NULL);
|
||||
pmpt_attr = txtchange;
|
||||
rpptbuf = promptexpand(rp, 1, NULL, NULL);
|
||||
rpromptbuf = promptexpand(rp, 1, NULL, NULL);
|
||||
rpmpt_attr = txtchange;
|
||||
histallowed = ha;
|
||||
PERMALLOC {
|
||||
|
@ -529,8 +529,8 @@ zleread(char *lp, char *rp, int ha)
|
|||
statusline = NULL;
|
||||
invalidatelist();
|
||||
trashzle();
|
||||
free(lpptbuf);
|
||||
free(rpptbuf);
|
||||
free(lpromptbuf);
|
||||
free(rpromptbuf);
|
||||
zleactive = 0;
|
||||
alarm(0);
|
||||
} LASTALLOC;
|
||||
|
@ -565,13 +565,14 @@ execzlefunc(Thingy func)
|
|||
showmsg(msg);
|
||||
zsfree(msg);
|
||||
feep();
|
||||
} else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_COMP)) {
|
||||
} else if((w = func->widget)->flags &
|
||||
(WIDGET_INT|WIDGET_COMP | WIDGET_NCOMP)) {
|
||||
int wflags = w->flags;
|
||||
|
||||
if(!(wflags & ZLE_KEEPSUFFIX))
|
||||
removesuffix();
|
||||
if(!(wflags & ZLE_MENUCMP) ||
|
||||
((wflags & WIDGET_COMP) && compwidget != w)) {
|
||||
((wflags & (WIDGET_COMP|WIDGET_NCOMP)) && compwidget != w)) {
|
||||
/* If we are doing a special completion, and the widget
|
||||
* is not the one currently in use for special completion,
|
||||
* we are starting a new completion.
|
||||
|
@ -586,6 +587,9 @@ execzlefunc(Thingy func)
|
|||
if (wflags & WIDGET_COMP) {
|
||||
compwidget = w;
|
||||
completespecial();
|
||||
} else if (wflags & WIDGET_NCOMP) {
|
||||
compwidget = w;
|
||||
completecall();
|
||||
} else
|
||||
w->u.fn();
|
||||
if (!(wflags & ZLE_NOTCOMMAND))
|
||||
|
@ -855,7 +859,7 @@ trashzle(void)
|
|||
static struct builtin bintab[] = {
|
||||
BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLR", NULL),
|
||||
BUILTIN("vared", 0, bin_vared, 1, 7, 0, NULL, NULL),
|
||||
BUILTIN("zle", 0, bin_zle, 0, -1, 0, "lDANCLmMgG", NULL),
|
||||
BUILTIN("zle", 0, bin_zle, 0, -1, 0, "lDANCLmMgGc", NULL),
|
||||
};
|
||||
|
||||
/**/
|
||||
|
@ -869,6 +873,11 @@ setup_zle(Module m)
|
|||
spaceinlineptr = spaceinline;
|
||||
zlereadptr = zleread;
|
||||
|
||||
addmatchesptr = addmatches;
|
||||
comp_strptr = comp_str;
|
||||
getcpatptr = getcpat;
|
||||
makecomplistcallptr = makecomplistcall;
|
||||
|
||||
/* initialise the thingies */
|
||||
init_thingies();
|
||||
|
||||
|
@ -931,6 +940,11 @@ finish_zle(Module m)
|
|||
spaceinlineptr = noop_function_int;
|
||||
zlereadptr = fallback_zleread;
|
||||
|
||||
addmatchesptr = NULL;
|
||||
comp_strptr = NULL;
|
||||
getcpatptr = NULL;
|
||||
makecomplistcallptr = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
/* Expanded prompts */
|
||||
|
||||
/**/
|
||||
char *lpptbuf, *rpptbuf;
|
||||
char *lpromptbuf, *rpromptbuf;
|
||||
|
||||
/* Text attributes after displaying prompts */
|
||||
|
||||
|
@ -77,17 +77,17 @@ int cost;
|
|||
/* Oct/Nov 94: <mason> some code savagely redesigned to fix several bugs -
|
||||
refreshline() & tc_rightcurs() majorly rewritten; zrefresh() fixed -
|
||||
I've put my fingers into just about every routine in here -
|
||||
any queries about updates to mason@werple.net.au */
|
||||
any queries about updates to mason@primenet.com.au */
|
||||
|
||||
static char **nbuf = NULL, /* new video buffer line-by-line char array */
|
||||
**obuf = NULL; /* old video buffer line-by-line char array */
|
||||
static int more_start, /* more text before start of screen? */
|
||||
more_end, /* more stuff after end of screen? */
|
||||
lppth, /* lines taken up by the prompt */
|
||||
olnct, /* previous number of lines */
|
||||
ovln, /* previous video cursor position line */
|
||||
pptw, rpw, /* prompt widths on screen */
|
||||
rppth, /* right prompt height */
|
||||
lpromptw, rpromptw, /* prompt widths on screen */
|
||||
lprompth, /* lines taken up by the prompt */
|
||||
rprompth, /* right prompt height */
|
||||
vcs, vln, /* video cursor position column & line */
|
||||
vmaxln, /* video maximum number of lines */
|
||||
winw, winh, rwinh, /* window width & height */
|
||||
|
@ -100,7 +100,6 @@ resetvideo(void)
|
|||
int ln;
|
||||
static int lwinw = -1, lwinh = -1; /* last window width & height */
|
||||
|
||||
genprompts();
|
||||
winw = columns; /* terminal width */
|
||||
if (termflags & TERM_SHORT)
|
||||
winh = 1;
|
||||
|
@ -132,13 +131,16 @@ resetvideo(void)
|
|||
*obuf[ln] = '\0';
|
||||
}
|
||||
|
||||
if (pptw) {
|
||||
memset(nbuf[0], ' ', pptw);
|
||||
memset(obuf[0], ' ', pptw);
|
||||
nbuf[0][pptw] = obuf[0][pptw] = '\0';
|
||||
countprompt(lpromptbuf, &lpromptw, &lprompth);
|
||||
countprompt(rpromptbuf, &rpromptw, &rprompth);
|
||||
|
||||
if (lpromptw) {
|
||||
memset(nbuf[0], ' ', lpromptw);
|
||||
memset(obuf[0], ' ', lpromptw);
|
||||
nbuf[0][lpromptw] = obuf[0][lpromptw] = '\0';
|
||||
}
|
||||
|
||||
vcs = pptw;
|
||||
vcs = lpromptw;
|
||||
olnct = nlnct = 0;
|
||||
if (showinglist > 0)
|
||||
showinglist = -2;
|
||||
|
@ -280,21 +282,25 @@ zrefresh(void)
|
|||
tsetcap(TCSTANDOUTEND, 0);
|
||||
tsetcap(TCUNDERLINEEND, 0);
|
||||
|
||||
if (!clearflag)
|
||||
if (!clearflag) {
|
||||
if (tccan(TCCLEAREOD))
|
||||
tcout(TCCLEAREOD);
|
||||
else
|
||||
cleareol = 1; /* request: clear to end of line */
|
||||
}
|
||||
if (t0 > -1)
|
||||
olnct = t0;
|
||||
if (termflags & TERM_SHORT)
|
||||
vcs = 0;
|
||||
else if (!clearflag && lpptbuf[0])
|
||||
zputs(lpptbuf, shout);
|
||||
else if (!clearflag && lpromptbuf[0]) {
|
||||
zputs(lpromptbuf, shout);
|
||||
if (lpromptw == 0)
|
||||
zputs("\n", shout); /* works with both hasam and !hasam */
|
||||
}
|
||||
if (clearflag) {
|
||||
zputc('\r', shout);
|
||||
vcs = 0;
|
||||
moveto(0, pptw);
|
||||
moveto(0, lpromptw);
|
||||
}
|
||||
fflush(shout);
|
||||
clearf = clearflag;
|
||||
|
@ -326,7 +332,7 @@ zrefresh(void)
|
|||
if (!*nbuf)
|
||||
*nbuf = (char *)zalloc(winw + 2);
|
||||
|
||||
s = (unsigned char *)(nbuf[ln = 0] + pptw);
|
||||
s = (unsigned char *)(nbuf[ln = 0] + lpromptw);
|
||||
t = line;
|
||||
sen = (unsigned char *)(*nbuf + winw);
|
||||
for (; t < line+ll; t++) {
|
||||
|
@ -425,15 +431,16 @@ zrefresh(void)
|
|||
|
||||
/* determine whether the right-prompt exists and can fit on the screen */
|
||||
if (!more_start)
|
||||
put_rpmpt = rppth == 1 && rpptbuf[0] && !strchr(rpptbuf, '\t') &&
|
||||
(int)strlen(nbuf[0]) + rpw < winw - 1;
|
||||
put_rpmpt = rprompth == 1 && rpromptbuf[0] &&
|
||||
!strchr(rpromptbuf, '\t') &&
|
||||
(int)strlen(nbuf[0]) + rpromptw < winw - 1;
|
||||
else {
|
||||
/* insert >.... on first line if there is more text before start of screen */
|
||||
memset(nbuf[0], ' ', pptw);
|
||||
t0 = winw - pptw;
|
||||
memset(nbuf[0], ' ', lpromptw);
|
||||
t0 = winw - lpromptw;
|
||||
t0 = t0 > 5 ? 5 : t0;
|
||||
strncpy(nbuf[0] + pptw, ">....", t0);
|
||||
memset(nbuf[0] + pptw + t0, ' ', winw - t0 - pptw);
|
||||
strncpy(nbuf[0] + lpromptw, ">....", t0);
|
||||
memset(nbuf[0] + lpromptw + t0, ' ', winw - t0 - lpromptw);
|
||||
nbuf[0][winw] = nbuf[0][winw + 1] = '\0';
|
||||
}
|
||||
|
||||
|
@ -477,8 +484,8 @@ zrefresh(void)
|
|||
|
||||
/* output the right-prompt if appropriate */
|
||||
if (put_rpmpt && !ln && !oput_rpmpt) {
|
||||
moveto(0, winw - 1 - rpw);
|
||||
zputs(rpptbuf, shout);
|
||||
moveto(0, winw - 1 - rpromptw);
|
||||
zputs(rpromptbuf, shout);
|
||||
vcs = winw - 1;
|
||||
/* reset character attributes to that set by the main prompt */
|
||||
txtchange = pmpt_attr;
|
||||
|
@ -659,12 +666,12 @@ refreshline(int ln)
|
|||
/* 2c: if we're on the first line, start checking at the end of the prompt;
|
||||
we shouldn't be doing anything within the prompt */
|
||||
|
||||
if (ln == 0 && pptw) {
|
||||
i = pptw - ccs;
|
||||
if (ln == 0 && lpromptw) {
|
||||
i = lpromptw - ccs;
|
||||
j = strlen(ol);
|
||||
nl += i;
|
||||
ol += (i > j ? j : i); /* if ol is too short, point it to '\0' */
|
||||
ccs = pptw;
|
||||
ccs = lpromptw;
|
||||
}
|
||||
|
||||
/* 3: main display loop - write out the buffer using whatever tricks we can */
|
||||
|
@ -815,7 +822,7 @@ moveto(int ln, int cl)
|
|||
instead of TCDOWN */
|
||||
|
||||
while (ln > vln) {
|
||||
if (vln < vmaxln - 1)
|
||||
if (vln < vmaxln - 1) {
|
||||
if (ln > vmaxln - 1) {
|
||||
if (tc_downcurs(vmaxln - 1 - vln))
|
||||
vcs = 0;
|
||||
|
@ -826,6 +833,7 @@ moveto(int ln, int cl)
|
|||
vln = ln;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
zputc('\r', shout), vcs = 0; /* safety precaution */
|
||||
while (ln > vln) {
|
||||
zputc('\n', shout);
|
||||
|
@ -893,21 +901,23 @@ tc_rightcurs(int cl)
|
|||
|
||||
/* otherwise _carefully_ write the contents of the video buffer.
|
||||
if we're anywhere in the prompt, goto the left column and write the whole
|
||||
prompt out unless ztrlen(lpptbuf) == pptw : we can cheat then */
|
||||
if (vln == 0 && i < pptw) {
|
||||
if (strlen(lpptbuf) == pptw)
|
||||
fputs(lpptbuf + i, shout);
|
||||
else if (tccan(TCRIGHT) && (tclen[TCRIGHT] * ct <= ztrlen(lpptbuf)))
|
||||
prompt out unless ztrlen(lpromptbuf) == lpromptw : we can cheat then */
|
||||
if (vln == 0 && i < lpromptw) {
|
||||
if (strlen(lpromptbuf) == lpromptw)
|
||||
fputs(lpromptbuf + i, shout);
|
||||
else if (tccan(TCRIGHT) && (tclen[TCRIGHT] * ct <= ztrlen(lpromptbuf)))
|
||||
/* it is cheaper to send TCRIGHT than reprint the whole prompt */
|
||||
for (ct = pptw - i; ct--; )
|
||||
for (ct = lpromptw - i; ct--; )
|
||||
tcout(TCRIGHT);
|
||||
else {
|
||||
if (i != 0)
|
||||
zputc('\r', shout);
|
||||
tc_upcurs(lppth - 1);
|
||||
zputs(lpptbuf, shout);
|
||||
tc_upcurs(lprompth - 1);
|
||||
zputs(lpromptbuf, shout);
|
||||
if (lpromptw == 0)
|
||||
zputs("\n", shout); /* works with both hasam and !hasam */
|
||||
}
|
||||
i = pptw;
|
||||
i = lpromptw;
|
||||
ct = cl - i;
|
||||
}
|
||||
|
||||
|
@ -969,7 +979,7 @@ redisplay(void)
|
|||
{
|
||||
moveto(0, 0);
|
||||
zputc('\r', shout); /* extra care */
|
||||
tc_upcurs(lppth - 1);
|
||||
tc_upcurs(lprompth - 1);
|
||||
resetneeded = 1;
|
||||
clearflag = 0;
|
||||
}
|
||||
|
@ -987,7 +997,7 @@ singlerefresh(void)
|
|||
|
||||
nlnct = 1;
|
||||
/* generate the new line buffer completely */
|
||||
for (vsiz = 1 + pptw, t0 = 0; t0 != ll; t0++, vsiz++)
|
||||
for (vsiz = 1 + lpromptw, t0 = 0; t0 != ll; t0++, vsiz++)
|
||||
if (line[t0] == '\t')
|
||||
vsiz = (vsiz | 7) + 1;
|
||||
else if (icntrl(line[t0]))
|
||||
|
@ -1002,9 +1012,10 @@ singlerefresh(void)
|
|||
cs = 0;
|
||||
}
|
||||
|
||||
memcpy(vbuf, strchr(lpptbuf, 0) - pptw, pptw); /* only use last part of prompt */
|
||||
vbuf[pptw] = '\0';
|
||||
vp = vbuf + pptw;
|
||||
/* only use last part of prompt */
|
||||
memcpy(vbuf, strchr(lpromptbuf, 0) - lpromptw, lpromptw);
|
||||
vbuf[lpromptw] = '\0';
|
||||
vp = vbuf + lpromptw;
|
||||
|
||||
for (t0 = 0; t0 != ll; t0++) {
|
||||
if (line[t0] == '\t')
|
||||
|
@ -1104,13 +1115,3 @@ singmoveto(int pos)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* recheck size of prompts */
|
||||
|
||||
/**/
|
||||
static void
|
||||
genprompts(void)
|
||||
{
|
||||
countprompt(lpptbuf, &pptw, &lppth);
|
||||
countprompt(rpptbuf, &rpw, &rppth);
|
||||
}
|
||||
|
|
|
@ -246,7 +246,10 @@ freewidget(Widget w)
|
|||
{
|
||||
if ((w->flags & WIDGET_COMP) && w->u.cc)
|
||||
freecompctl(w->u.cc);
|
||||
else if(!(w->flags & WIDGET_INT))
|
||||
else if (w->flags & WIDGET_NCOMP) {
|
||||
zsfree(w->u.comp.wid);
|
||||
zsfree(w->u.comp.func);
|
||||
} else if(!(w->flags & WIDGET_INT))
|
||||
zsfree(w->u.fnnam);
|
||||
zfree(w, sizeof(*w));
|
||||
}
|
||||
|
@ -337,16 +340,17 @@ bin_zle(char *name, char **args, char *ops, int func)
|
|||
{ 'A', bin_zle_link, 2, 2 },
|
||||
{ 'N', bin_zle_new, 1, 2 },
|
||||
{ 'C', bin_zle_compctl, 1, -1},
|
||||
{ 'c', bin_zle_complete, 3, 3 },
|
||||
{ 0, bin_zle_call, 0, -1 },
|
||||
};
|
||||
struct opn const *op, *opp;
|
||||
int n;
|
||||
|
||||
/* select operation and ensure no clashing arguments */
|
||||
for(op = opns; op->o && !ops[op->o]; op++) ;
|
||||
for(op = opns; op->o && !ops[STOUC(op->o)]; op++) ;
|
||||
if(op->o)
|
||||
for(opp = op; (++opp)->o; )
|
||||
if(ops[opp->o]) {
|
||||
if(ops[STOUC(opp->o)]) {
|
||||
zerrnam(name, "incompatible operation selection options",
|
||||
NULL, 0);
|
||||
return 1;
|
||||
|
@ -395,6 +399,11 @@ scanlistwidgets(HashNode hn, int list)
|
|||
if (w->flags & WIDGET_COMP) {
|
||||
if (printcompctlptr && w->u.cc)
|
||||
printcompctlptr(NULL, w->u.cc, PRINT_LIST, 0);
|
||||
} else if (w->flags & WIDGET_NCOMP) {
|
||||
fputc(' ', stdout);
|
||||
quotedzputs(w->u.comp.wid, stdout);
|
||||
fputc(' ', stdout);
|
||||
quotedzputs(w->u.comp.func, stdout);
|
||||
} else if(strcmp(t->nam, w->u.fnnam)) {
|
||||
fputc(' ', stdout);
|
||||
quotedzputs(w->u.fnnam, stdout);
|
||||
|
@ -405,6 +414,11 @@ scanlistwidgets(HashNode hn, int list)
|
|||
fputs(" -C", stdout);
|
||||
if (printcompctlptr && w->u.cc)
|
||||
printcompctlptr(NULL, w->u.cc, PRINT_TYPE, 0);
|
||||
} else if (w->flags & WIDGET_NCOMP) {
|
||||
fputs(" -c ", stdout);
|
||||
nicezputs(w->u.comp.wid, stdout);
|
||||
fputc(' ', stdout);
|
||||
nicezputs(w->u.comp.func, stdout);
|
||||
} else if(strcmp(t->nam, w->u.fnnam)) {
|
||||
fputs(" (", stdout);
|
||||
nicezputs(w->u.fnnam, stdout);
|
||||
|
@ -504,13 +518,41 @@ bin_zle_compctl(char *name, char **args, char *ops, char func)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_zle_complete(char *name, char **args, char *ops, char func)
|
||||
{
|
||||
Thingy t;
|
||||
Widget w, cw;
|
||||
|
||||
t = rthingy(args[1]);
|
||||
cw = t->widget;
|
||||
unrefthingy(t);
|
||||
if (!(cw->flags & ZLE_ISCOMP)) {
|
||||
zerrnam(name, "invalid widget `%s'", args[1], 0);
|
||||
return 1;
|
||||
}
|
||||
w = zalloc(sizeof(*w));
|
||||
w->flags = WIDGET_NCOMP|ZLE_MENUCMP|ZLE_KEEPSUFFIX;
|
||||
w->first = NULL;
|
||||
w->u.comp.fn = cw->u.fn;
|
||||
w->u.comp.wid = ztrdup(args[1]);
|
||||
w->u.comp.func = ztrdup(args[2]);
|
||||
if (bindwidget(w, rthingy(args[0]))) {
|
||||
freewidget(w);
|
||||
zerrnam(name, "widget name `%s' is protected", args[0], 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_zle_call(char *name, char **args, char *ops, char func)
|
||||
{
|
||||
Thingy t;
|
||||
|
||||
if(!zleactive || incompctlfunc) {
|
||||
if(!zleactive || incompctlfunc || incompfunc) {
|
||||
zerrnam(name, "widgets can only be called when ZLE is active",
|
||||
NULL, 0);
|
||||
return 1;
|
||||
|
|
|
@ -237,6 +237,15 @@ struct aminfo {
|
|||
|
||||
static Aminfo ainfo, fainfo;
|
||||
|
||||
/* This contains the name of the function to call if this is for a new *
|
||||
* style completion. */
|
||||
|
||||
static char *compfunc = NULL;
|
||||
|
||||
/* The memory heap to use for new style completion generation. */
|
||||
|
||||
static Heap compheap;
|
||||
|
||||
/* Find out if we have to insert a tab (instead of trying to complete). */
|
||||
|
||||
/**/
|
||||
|
@ -272,6 +281,15 @@ completespecial(void)
|
|||
docomplete(compwidget->u.cc ? COMP_WIDGET : COMP_COMPLETE);
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
completecall(void)
|
||||
{
|
||||
compfunc = compwidget->u.comp.func;
|
||||
compwidget->u.comp.fn();
|
||||
compfunc = NULL;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
completeword(void)
|
||||
|
@ -408,11 +426,15 @@ reversemenucomplete(void)
|
|||
void
|
||||
acceptandmenucomplete(void)
|
||||
{
|
||||
int sl = suffixlen[' '];
|
||||
|
||||
if (!menucmp) {
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
cs = menuend + menuinsc;
|
||||
cs = menupos + menulen + menuinsc;
|
||||
if (sl)
|
||||
backdel(sl);
|
||||
inststrlen(" ", 1, 1);
|
||||
menuinsc = menulen = 0;
|
||||
menupos = cs;
|
||||
|
@ -439,6 +461,13 @@ static int lastambig;
|
|||
|
||||
static char *cmdstr;
|
||||
|
||||
/* This hold the name of the variable we are working on. */
|
||||
|
||||
static char *varname;
|
||||
|
||||
/* != 0 if we are in a subscript */
|
||||
|
||||
static int insubscr;
|
||||
|
||||
/* Check if the given string is the name of a parameter and if this *
|
||||
* parameter is one worth expanding. */
|
||||
|
@ -614,16 +643,13 @@ docomplete(int lst)
|
|||
lst = COMP_EXPAND;
|
||||
else {
|
||||
int t0, n = 0;
|
||||
char *fc;
|
||||
struct hashnode *hn;
|
||||
|
||||
for (t0 = cmdnamtab->hsize - 1; t0 >= 0; t0--)
|
||||
for (hn = cmdnamtab->nodes[t0]; hn;
|
||||
hn = hn->next) {
|
||||
if (strpfx(q, hn->nam) && (fc = findcmd(hn->nam))) {
|
||||
zsfree(fc);
|
||||
if (strpfx(q, hn->nam) && findcmd(hn->nam, 0))
|
||||
n++;
|
||||
}
|
||||
if (n == 2)
|
||||
break;
|
||||
}
|
||||
|
@ -889,7 +915,7 @@ unmetafy_line(void)
|
|||
static char *
|
||||
get_comp_string(void)
|
||||
{
|
||||
int t0, tt0, i, j, k, cp, rd, sl, ocs;
|
||||
int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins;
|
||||
char *s = NULL, *linptr, *tmp, *p, *tt = NULL;
|
||||
|
||||
zsfree(brbeg);
|
||||
|
@ -943,13 +969,16 @@ get_comp_string(void)
|
|||
linredir = inredir;
|
||||
zsfree(cmdstr);
|
||||
cmdstr = NULL;
|
||||
zsfree(varname);
|
||||
varname = NULL;
|
||||
insubscr = 0;
|
||||
zleparse = 1;
|
||||
clwpos = -1;
|
||||
lexsave();
|
||||
inpush(dupstrspace((char *) linptr), 0, NULL);
|
||||
strinbeg();
|
||||
stophist = 2;
|
||||
i = tt0 = cp = rd = 0;
|
||||
i = tt0 = cp = rd = ins = oins = 0;
|
||||
|
||||
/* This loop is possibly the wrong way to do this. It goes through *
|
||||
* the previously massaged command line using the lexer. It stores *
|
||||
|
@ -963,8 +992,10 @@ get_comp_string(void)
|
|||
* this would be to pass the command line through the parser too, *
|
||||
* and get the arguments that way. Maybe in 3.1... */
|
||||
do {
|
||||
lincmd = incmdpos;
|
||||
linredir = inredir;
|
||||
lincmd = ((incmdpos && !ins) || (oins == 2 && i == 2) ||
|
||||
(ins == 3 && i == 1));
|
||||
linredir = (inredir && !ins);
|
||||
oins = ins;
|
||||
/* Get the next token. */
|
||||
ctxtlex();
|
||||
if (tok == DINPAR)
|
||||
|
@ -973,7 +1004,9 @@ get_comp_string(void)
|
|||
/* We reached the end. */
|
||||
if (tok == ENDINPUT)
|
||||
break;
|
||||
if (tok == BAR || tok == AMPER ||
|
||||
if ((ins && (tok == DO || tok == SEPER)) ||
|
||||
(ins == 2 && i == 2) || (ins == 3 && i == 3) ||
|
||||
tok == BAR || tok == AMPER ||
|
||||
tok == BARAMP || tok == AMPERBANG ||
|
||||
((tok == DBAR || tok == DAMPER) && !incond)) {
|
||||
/* This is one of the things that separate commands. If we *
|
||||
|
@ -982,11 +1015,13 @@ get_comp_string(void)
|
|||
if (tt)
|
||||
break;
|
||||
/* Otherwise reset the variables we are collecting data in. */
|
||||
i = tt0 = cp = rd = 0;
|
||||
i = tt0 = cp = rd = ins = 0;
|
||||
}
|
||||
if (lincmd && tok == STRING) {
|
||||
if (lincmd && (tok == STRING || tok == FOR || tok == FOREACH ||
|
||||
tok == SELECT || tok == REPEAT || tok == CASE)) {
|
||||
/* The lexer says, this token is in command position, so *
|
||||
* store the token string (to find the right compctl). */
|
||||
ins = (tok == REPEAT ? 2 : (tok != STRING));
|
||||
zsfree(cmdstr);
|
||||
cmdstr = ztrdup(tokstr);
|
||||
i = 0;
|
||||
|
@ -1004,9 +1039,13 @@ get_comp_string(void)
|
|||
rd = linredir;
|
||||
if (inwhat == IN_NOTHING && incond)
|
||||
inwhat = IN_COND;
|
||||
}
|
||||
} else if (linredir)
|
||||
continue;
|
||||
if (!tokstr)
|
||||
continue;
|
||||
/* Hack to allow completion after `repeat n do'. */
|
||||
if (oins == 2 && !i && !strcmp(tokstr, "do"))
|
||||
ins = 3;
|
||||
/* We need to store the token strings of all words (for some of *
|
||||
* the more complicated compctl -x things). They are stored in *
|
||||
* the clwords array. Make this array big enough. */
|
||||
|
@ -1069,10 +1108,16 @@ get_comp_string(void)
|
|||
/* We found a simple string. */
|
||||
s = ztrdup(clwords[clwpos]);
|
||||
} else if (t0 == ENVSTRING) {
|
||||
char sav;
|
||||
/* The cursor was inside a parameter assignment. */
|
||||
for (s = tt; iident(*s); s++);
|
||||
sav = *s;
|
||||
*s = '\0';
|
||||
zsfree(varname);
|
||||
varname = ztrdup(tt);
|
||||
*s = sav;
|
||||
if (skipparens(Inbrack, Outbrack, &s) > 0 || s > tt + cs - wb)
|
||||
s = NULL, inwhat = IN_MATH;
|
||||
s = NULL, inwhat = IN_MATH, insubscr = 1;
|
||||
else if (*s == '=') {
|
||||
s++;
|
||||
wb += s - tt;
|
||||
|
@ -1110,14 +1155,32 @@ get_comp_string(void)
|
|||
* foo[_ wrong (note no $). If we are in a subscript, treat it *
|
||||
* as being in math. */
|
||||
if (inwhat != IN_MATH) {
|
||||
int i = 0;
|
||||
int i = 0, hn = 0;
|
||||
char *nb = (*s == String ? s + 1 : NULL), *ne = NULL;
|
||||
|
||||
for (tt = s; ++tt < s + cs - wb;)
|
||||
if (*tt == Inbrack)
|
||||
if (*tt == String) {
|
||||
hn = 0;
|
||||
nb = tt + 1;
|
||||
} else if (*tt == Inbrack) {
|
||||
i++;
|
||||
else if (i && *tt == Outbrack)
|
||||
if (nb && !hn) {
|
||||
hn = 1;
|
||||
ne = tt;
|
||||
}
|
||||
} else if (i && *tt == Outbrack)
|
||||
i--;
|
||||
if (i)
|
||||
if (i) {
|
||||
inwhat = IN_MATH;
|
||||
insubscr = 1;
|
||||
if (hn && nb && ne) {
|
||||
char sav = *ne;
|
||||
*ne = '\0';
|
||||
zsfree(varname);
|
||||
varname = ztrdup(nb);
|
||||
*ne = sav;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inwhat == IN_MATH) {
|
||||
/* In mathematical expression, we complete parameter names (even *
|
||||
|
@ -2336,6 +2399,119 @@ instmatch(Cmatch m)
|
|||
return r;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
|
||||
char *suf, char *group,
|
||||
int flags, int quote, int menu, int nosort, int alt, char **argv)
|
||||
{
|
||||
char *s, *t;
|
||||
int lpl, lsl, i;
|
||||
Aminfo ai = (alt ? fainfo : ainfo);
|
||||
Cmatch cm;
|
||||
|
||||
if (menu && isset(AUTOMENU))
|
||||
usemenu = 1;
|
||||
SWITCHHEAPS(compheap) {
|
||||
HEAPALLOC {
|
||||
if (ipre)
|
||||
ipre = dupstring(ipre);
|
||||
if (ppre) {
|
||||
ppre = dupstring(ppre);
|
||||
lpl = strlen(ppre);
|
||||
} else
|
||||
lpl = 0;
|
||||
if (psuf) {
|
||||
psuf = dupstring(psuf);
|
||||
lsl = strlen(psuf);
|
||||
} else
|
||||
lsl = 0;
|
||||
if (pre)
|
||||
pre = dupstring(pre);
|
||||
if (suf)
|
||||
suf = dupstring(suf);
|
||||
if (!prpre && (prpre = ppre)) {
|
||||
singsub(&prpre);
|
||||
untokenize(prpre);
|
||||
} else
|
||||
prpre = dupstring(prpre);
|
||||
if (group) {
|
||||
endcmgroup(NULL);
|
||||
begcmgroup(group, nosort);
|
||||
if (nosort)
|
||||
mgroup->flags |= CGF_NOSORT;
|
||||
}
|
||||
if (ai->pprefix) {
|
||||
if (pre)
|
||||
ai->pprefix[pfxlen(ai->pprefix, pre)] = '\0';
|
||||
else
|
||||
ai->pprefix[0] = '\0';
|
||||
} else
|
||||
ai->pprefix = dupstring(pre ? pre : "");
|
||||
|
||||
for (; (s = *argv); argv++) {
|
||||
if (ai->firstm) {
|
||||
if ((i = pfxlen(ai->firstm->str, s)) < ai->prerest)
|
||||
ai->prerest = i;
|
||||
if ((i = sfxlen(ai->firstm->str, s)) < ai->suflen)
|
||||
ai->suflen = i;
|
||||
}
|
||||
t = s;
|
||||
if (ppre)
|
||||
t = dyncat(ppre, t);
|
||||
if (ipre && *ipre) {
|
||||
ai->noipre = 0;
|
||||
if (ai->icpl > lpl)
|
||||
ai->icpl = lpl;
|
||||
if (ai->icsl > lsl)
|
||||
ai->icsl = lsl;
|
||||
if (ai->iaprefix)
|
||||
ai->iaprefix[pfxlen(ai->iaprefix, t)] = '\0';
|
||||
else
|
||||
ai->iaprefix = dupstring(t);
|
||||
if (ai->iprefix) {
|
||||
if (strcmp(ipre, ai->iprefix))
|
||||
ai->iprefix = "";
|
||||
} else
|
||||
ai->iprefix = dupstring(ipre);
|
||||
|
||||
t = dyncat(ipre, t);
|
||||
} else
|
||||
ai->iprefix = "";
|
||||
if (ai->cpl > lpl)
|
||||
ai->cpl = lpl;
|
||||
if (ai->csl > lsl)
|
||||
ai->csl = lsl;
|
||||
if (ai->aprefix)
|
||||
ai->aprefix[pfxlen(ai->aprefix, t)] = '\0';
|
||||
else
|
||||
ai->aprefix = dupstring(t);
|
||||
mnum++;
|
||||
ai->count++;
|
||||
|
||||
cm = (Cmatch) halloc(sizeof(struct cmatch));
|
||||
cm->ppre = ppre;
|
||||
cm->psuf = psuf;
|
||||
cm->prpre = prpre;
|
||||
if (!quote)
|
||||
s = quotename(s, NULL, NULL, NULL);
|
||||
cm->str = dupstring(s);
|
||||
cm->ipre = cm->ripre = ipre;
|
||||
cm->pre = pre;
|
||||
cm->suf = suf;
|
||||
cm->flags = flags;
|
||||
cm->brpl = brpl;
|
||||
cm->brsl = brsl;
|
||||
addlinknode((alt ? fmatches : matches), cm);
|
||||
|
||||
if (expl)
|
||||
expl->fcount++;
|
||||
if (!ai->firstm)
|
||||
ai->firstm = cm;
|
||||
}
|
||||
} LASTALLOC;
|
||||
} SWITCHBACKHEAPS;
|
||||
}
|
||||
|
||||
/* This adds a match to the list of matches. The string to add is given *
|
||||
* in s, the type of match is given in the global variable addwhat and *
|
||||
|
@ -2351,7 +2527,7 @@ addmatch(char *s, char *t)
|
|||
{
|
||||
int test = 0, sl = strlen(s), pl = rpl, cc = 0, isf = 0;
|
||||
int mpl = 0, msl = 0, bpl = brpl, bsl = brsl;
|
||||
char *e = NULL, *tt, *te, *fc, *ms = NULL;
|
||||
char *e = NULL, *tt, *te, *ms = NULL;
|
||||
Comp cp = patcomp;
|
||||
HashNode hn;
|
||||
Param pm;
|
||||
|
@ -2377,6 +2553,8 @@ addmatch(char *s, char *t)
|
|||
hn = (HashNode) t;
|
||||
pm = (Param) t;
|
||||
|
||||
if (incompfunc)
|
||||
s = dupstring(s);
|
||||
if (!addwhat) {
|
||||
test = 1;
|
||||
} else if (addwhat == -1 || addwhat == -5 || addwhat == -6 ||
|
||||
|
@ -2427,11 +2605,8 @@ addmatch(char *s, char *t)
|
|||
}
|
||||
}
|
||||
if (test) {
|
||||
fc = NULL;
|
||||
if (addwhat == -7 && !(fc = findcmd(s)))
|
||||
if (addwhat == -7 && !findcmd(s, 0))
|
||||
return;
|
||||
if (fc)
|
||||
zsfree(fc);
|
||||
isf = CMF_FILE;
|
||||
|
||||
if (addwhat == CC_FILES || addwhat == -6 ||
|
||||
|
@ -2515,7 +2690,6 @@ addmatch(char *s, char *t)
|
|||
}
|
||||
if (!test)
|
||||
return;
|
||||
|
||||
if (!ms && !ispattern && ai->firstm) {
|
||||
if ((test = sl - pfxlen(ai->firstm->str, s)) < ai->prerest)
|
||||
ai->prerest = test;
|
||||
|
@ -2602,8 +2776,13 @@ addmatch(char *s, char *t)
|
|||
cm->str = (ms ? ms : s);
|
||||
cm->ipre = (ipre && *ipre ? ipre : NULL);
|
||||
cm->ripre = (ripre && *ripre ? ripre : NULL);
|
||||
cm->pre = curcc->prefix;
|
||||
cm->suf = curcc->suffix;
|
||||
if (incompfunc) {
|
||||
cm->pre = dupstring(curcc->prefix);
|
||||
cm->suf = dupstring(curcc->suffix);
|
||||
} else {
|
||||
cm->pre = curcc->prefix;
|
||||
cm->suf = curcc->suffix;
|
||||
}
|
||||
cm->flags = mflags | isf;
|
||||
cm->brpl = bpl;
|
||||
cm->brsl = bsl;
|
||||
|
@ -2729,7 +2908,7 @@ maketildelist(void)
|
|||
/* This does the check for compctl -x `n' and `N' patterns. */
|
||||
|
||||
/**/
|
||||
static int
|
||||
int
|
||||
getcpat(char *str, int cpatindex, char *cpat, int class)
|
||||
{
|
||||
char *s, *t, *p;
|
||||
|
@ -2951,6 +3130,8 @@ docompletion(char *s, int lst, int incmd)
|
|||
|
||||
else if (nmatches == 1) {
|
||||
/* Only one match. */
|
||||
while (!amatches->mcount)
|
||||
amatches = amatches->next;
|
||||
do_single(amatches->matches[0]);
|
||||
invalidatelist();
|
||||
}
|
||||
|
@ -3051,7 +3232,98 @@ makecomplist(char *s, int incmd, int lst)
|
|||
ccused = newlinklist();
|
||||
ccstack = newlinklist();
|
||||
|
||||
makecomplistglobal(s, incmd, lst);
|
||||
if (compfunc) {
|
||||
List list;
|
||||
int lv = lastval;
|
||||
|
||||
if ((list = getshfunc(compfunc)) != &dummy_list) {
|
||||
LinkList args = newlinklist();
|
||||
char **p, *tmp;
|
||||
int aadd = 0, usea = 1;
|
||||
|
||||
addlinknode(args, compfunc);
|
||||
|
||||
zsfree(compcontext);
|
||||
zsfree(compcommand);
|
||||
compcommand = "";
|
||||
if (inwhat == IN_MATH) {
|
||||
if (insubscr) {
|
||||
compcontext = "subscript";
|
||||
compcommand = varname ? varname : "";
|
||||
} else
|
||||
compcontext = "math";
|
||||
usea = 0;
|
||||
} else if (lincmd)
|
||||
compcontext = (insubscr ? "subscript" : "command");
|
||||
else if (linredir)
|
||||
compcontext = "redirect";
|
||||
else
|
||||
switch (inwhat) {
|
||||
case IN_ENV:
|
||||
compcontext = "value";
|
||||
compcommand = varname;
|
||||
usea = 0;
|
||||
break;
|
||||
case IN_COND:
|
||||
compcontext = "condition";
|
||||
break;
|
||||
default:
|
||||
if (cmdstr) {
|
||||
compcontext = "argument";
|
||||
compcommand = cmdstr;
|
||||
} else {
|
||||
compcontext = "value";
|
||||
if (clwords[0])
|
||||
compcommand = clwords[0];
|
||||
}
|
||||
aadd = 1;
|
||||
}
|
||||
compcontext = ztrdup(compcontext);
|
||||
tmp = quotename(compcommand, NULL, NULL, NULL);
|
||||
untokenize(tmp);
|
||||
compcommand = ztrdup(tmp);
|
||||
if (usea && (!aadd || clwords[0]))
|
||||
for (p = clwords + aadd; *p; p++) {
|
||||
tmp = dupstring(*p);
|
||||
untokenize(tmp);
|
||||
addlinknode(args, tmp);
|
||||
}
|
||||
zsfree(compprefix);
|
||||
zsfree(compsuffix);
|
||||
if (unset(COMPLETEINWORD)) {
|
||||
tmp = quotename(s, NULL, NULL, NULL);
|
||||
untokenize(tmp);
|
||||
compprefix = ztrdup(tmp);
|
||||
compsuffix = ztrdup("");
|
||||
} else {
|
||||
char *ss = s + offs, sav;
|
||||
|
||||
tmp = quotename(s, &ss, NULL, NULL);
|
||||
sav = *ss;
|
||||
*ss = '\0';
|
||||
untokenize(tmp);
|
||||
compprefix = ztrdup(tmp);
|
||||
*ss = sav;
|
||||
untokenize(ss);
|
||||
compsuffix = ztrdup(ss);
|
||||
}
|
||||
zsfree(compiprefix);
|
||||
compiprefix = ztrdup("");
|
||||
compcurrent = (usea ? (clwpos + 1 - aadd) : 1);
|
||||
compnmatches = mnum;
|
||||
incompfunc = 1;
|
||||
startparamscope();
|
||||
makecompparamsptr();
|
||||
NEWHEAPS(compheap) {
|
||||
doshfunc(compfunc, list, args, 0, 1);
|
||||
} OLDHEAPS;
|
||||
endparamscope();
|
||||
lastcmd = 9;
|
||||
incompfunc = 0;
|
||||
}
|
||||
lastval = lv;
|
||||
} else
|
||||
makecomplistglobal(s, incmd, lst);
|
||||
|
||||
endcmgroup(NULL);
|
||||
|
||||
|
@ -3082,6 +3354,83 @@ makecomplist(char *s, int incmd, int lst)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* This should probably be moved into tokenize(). */
|
||||
|
||||
static char *
|
||||
ctokenize(char *p)
|
||||
{
|
||||
char *r = p;
|
||||
int bslash = 0;
|
||||
|
||||
tokenize(p);
|
||||
|
||||
for (p = r; *p; p++) {
|
||||
if (*p == '\\')
|
||||
bslash = 1;
|
||||
else {
|
||||
if (*p == '$') {
|
||||
if (bslash)
|
||||
p[-1] = Bnull;
|
||||
else
|
||||
*p = String;
|
||||
}
|
||||
bslash = 0;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**/
|
||||
char *
|
||||
comp_str(int *ipl, int *pl)
|
||||
{
|
||||
char *p = dupstring(compprefix);
|
||||
char *s = dupstring(compsuffix);
|
||||
char *ip = dupstring(compiprefix);
|
||||
char *str;
|
||||
int lp, ls, lip;
|
||||
|
||||
ctokenize(p);
|
||||
remnulargs(p);
|
||||
ctokenize(s);
|
||||
remnulargs(s);
|
||||
ctokenize(ip);
|
||||
remnulargs(ip);
|
||||
ls = strlen(s);
|
||||
lip = strlen(ip);
|
||||
lp = strlen(p);
|
||||
str = halloc(lip + lp + ls + 1);
|
||||
strcpy(str, ip);
|
||||
strcat(str, p);
|
||||
strcat(str, s);
|
||||
|
||||
if (ipl)
|
||||
*ipl = lip;
|
||||
if (pl)
|
||||
*pl = lp;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
makecomplistcall(Compctl cc)
|
||||
{
|
||||
SWITCHHEAPS(compheap) {
|
||||
HEAPALLOC {
|
||||
int ooffs = offs, lip, lp;
|
||||
char *str = comp_str(&lip, &lp);
|
||||
|
||||
offs = lip + lp;
|
||||
cc->refc++;
|
||||
ccont = 0;
|
||||
makecomplistor(cc, str, lincmd, lip, 0);
|
||||
offs = ooffs;
|
||||
compnmatches = mnum;
|
||||
} LASTALLOC;
|
||||
} SWITCHBACKHEAPS;
|
||||
}
|
||||
|
||||
/* This function gets the compctls for the given command line and *
|
||||
* adds all completions for them. */
|
||||
|
||||
|
@ -3159,7 +3508,7 @@ makecomplistcmd(char *os, int incmd)
|
|||
/* If the command string starts with `=', try the path name of the *
|
||||
* command. */
|
||||
if (cmdstr && cmdstr[0] == Equals) {
|
||||
char *c = findcmd(cmdstr + 1);
|
||||
char *c = findcmd(cmdstr + 1, 1);
|
||||
|
||||
if (c) {
|
||||
zsfree(cmdstr);
|
||||
|
@ -3191,7 +3540,7 @@ makecomplistpc(char *os, int incmd)
|
|||
{
|
||||
Patcomp pc;
|
||||
Comp pat;
|
||||
char *s = findcmd(cmdstr);
|
||||
char *s = findcmd(cmdstr, 1);
|
||||
|
||||
for (pc = patcomps; pc; pc = pc->next) {
|
||||
if ((pat = parsereg(pc->pat)) &&
|
||||
|
@ -3468,12 +3817,12 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
|
||||
ccont |= (cc->mask2 & (CC_CCCONT | CC_DEFCONT | CC_PATCONT));
|
||||
|
||||
if (findnode(ccstack, cc))
|
||||
if (!incompfunc && findnode(ccstack, cc))
|
||||
return;
|
||||
|
||||
addlinknode(ccstack, cc);
|
||||
|
||||
if (allccs) {
|
||||
if (!incompfunc && allccs) {
|
||||
if (findnode(allccs, cc)) {
|
||||
uremnode(ccstack, firstnode(ccstack));
|
||||
return;
|
||||
|
@ -4107,7 +4456,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
}
|
||||
|
||||
/* This flag allows us to use read -l and -c. */
|
||||
incompctlfunc = 1;
|
||||
if (!incompfunc)
|
||||
incompctlfunc = 1;
|
||||
sfcontext = SFC_COMPLETE;
|
||||
/* Call the function. */
|
||||
doshfunc(cc->func, list, args, 0, 1);
|
||||
|
@ -4126,7 +4476,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
char *j, *jj;
|
||||
|
||||
for (i = 0; i < MAXJOB; i++)
|
||||
if (jobtab[i].stat & STAT_INUSE) {
|
||||
if ((jobtab[i].stat & STAT_INUSE) &&
|
||||
jobtab[i].procs && jobtab[i].procs->text) {
|
||||
int stopped = jobtab[i].stat & STAT_STOPPED;
|
||||
|
||||
j = jj = dupstring(jobtab[i].procs->text);
|
||||
|
@ -4274,7 +4625,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
}
|
||||
|
||||
/* No harm in allowing read -l and -c here, too */
|
||||
incompctlfunc = 1;
|
||||
if (!incompfunc)
|
||||
incompctlfunc = 1;
|
||||
sfcontext = SFC_COMPLETE;
|
||||
doshfunc(cc->ylist, list, args, 0, 1);
|
||||
sfcontext = osc;
|
||||
|
@ -4528,10 +4880,12 @@ makearray(LinkList l, int s, int *np, int *nlp)
|
|||
for (bp = ap; bp[1] && matcheq(*ap, bp[1]); bp++, n--);
|
||||
ap = bp;
|
||||
/* Mark those, that would show the same string in the list. */
|
||||
for (; bp[1] && !strcmp((*ap)->str, (bp[1])->str); bp++) {
|
||||
(bp[1])->flags |= CMF_NOLIST; nl++;
|
||||
}
|
||||
for (; bp[1] && !strcmp((*ap)->str, (bp[1])->str); bp++)
|
||||
(bp[1])->flags |= CMF_NOLIST;
|
||||
}
|
||||
for (ap = rp; *ap; ap++)
|
||||
if ((*ap)->flags & CMF_NOLIST)
|
||||
nl++;
|
||||
*cp = NULL;
|
||||
}
|
||||
if (np)
|
||||
|
@ -4991,10 +5345,14 @@ do_single(Cmatch m)
|
|||
if (m->suf) {
|
||||
havesuff = 1;
|
||||
menuinsc = ztrlen(m->suf);
|
||||
if (menuwe && (m->flags & CMF_REMOVE)) {
|
||||
makesuffix(menuinsc);
|
||||
if (menuinsc == 1)
|
||||
suffixlen[m->suf[0]] = 1;
|
||||
menulen -= menuinsc;
|
||||
if (menuwe) {
|
||||
menuend += menuinsc;
|
||||
if (m->flags & CMF_REMOVE) {
|
||||
makesuffix(menuinsc);
|
||||
if (menuinsc == 1)
|
||||
suffixlen[STOUC(m->suf[0])] = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* There is no user-specified suffix, *
|
||||
|
@ -5463,7 +5821,8 @@ listmatches(void)
|
|||
}
|
||||
if (n) {
|
||||
putc('\n', shout);
|
||||
p = skipnolist(p + 1);
|
||||
if (n && nl)
|
||||
p = skipnolist(p + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5671,7 +6030,7 @@ expandcmdpath(void)
|
|||
feep();
|
||||
return;
|
||||
}
|
||||
str = findcmd(s);
|
||||
str = findcmd(s, 1);
|
||||
zsfree(s);
|
||||
if (!str) {
|
||||
feep();
|
||||
|
@ -5686,7 +6045,6 @@ expandcmdpath(void)
|
|||
cs += cmdwe - cmdwb + strlen(str);
|
||||
if (cs > ll)
|
||||
cs = ll;
|
||||
zsfree(str);
|
||||
}
|
||||
|
||||
/* Extra function added by AR Iano-Fletcher. */
|
||||
|
|
296
Src/builtin.c
296
Src/builtin.c
|
@ -680,7 +680,7 @@ bin_cd(char *nam, char **argv, char *ops, int func)
|
|||
goto brk;
|
||||
}
|
||||
} while (*++s);
|
||||
for (s = *argv; *++s; ops[*s] = 1);
|
||||
for (s = *argv; *++s; ops[STOUC(*s)] = 1);
|
||||
}
|
||||
brk:
|
||||
chaselinks = ops['P'] || (isset(CHASELINKS) && !ops['L']);
|
||||
|
@ -790,7 +790,7 @@ cd_get_dest(char *nam, char **argv, char *ops, int func)
|
|||
zsfree(remnode(dirstack, dir));
|
||||
return NULL;
|
||||
}
|
||||
if (dest != getdata(dir)) {
|
||||
if (dest != (char *)getdata(dir)) {
|
||||
zsfree(getdata(dir));
|
||||
setdata(dir, dest);
|
||||
}
|
||||
|
@ -1224,13 +1224,14 @@ bin_fc(char *nam, char **argv, char *ops, int func)
|
|||
if (!editor)
|
||||
editor = DEFAULT_FCEDIT;
|
||||
|
||||
if (fcedit(editor, fil))
|
||||
if (fcedit(editor, fil)) {
|
||||
if (stuff(fil))
|
||||
zwarnnam("fc", "%e: %s", s, errno);
|
||||
else {
|
||||
loop(0,1);
|
||||
retval = lastval;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unlink(fil);
|
||||
|
@ -1464,6 +1465,117 @@ getasg(char *s)
|
|||
return &asg;
|
||||
}
|
||||
|
||||
/* function to set a single parameter */
|
||||
|
||||
/**/
|
||||
int
|
||||
typeset_single(char *cname, char *pname, Param pm, int func,
|
||||
int on, int off, int roff, char *value)
|
||||
{
|
||||
int usepm, tc;
|
||||
|
||||
/* use the existing pm? */
|
||||
usepm = pm && !(pm->flags & PM_UNSET);
|
||||
|
||||
/* Always use an existing pm if special at current locallevel */
|
||||
if (pm && (pm->flags & PM_SPECIAL) && pm->level == locallevel)
|
||||
usepm = 1;
|
||||
|
||||
/*
|
||||
* Don't use a non-special existing param if
|
||||
* - the local level has changed, and
|
||||
* - the function is not `export'.
|
||||
*/
|
||||
if (usepm && !(pm->flags & PM_SPECIAL) &&
|
||||
locallevel != pm->level && func != BIN_EXPORT)
|
||||
usepm = 0;
|
||||
|
||||
/* attempting a type conversion? */
|
||||
if ((tc = usepm && (((off & pm->flags) | (on & ~pm->flags)) &
|
||||
(PM_INTEGER|PM_HASHED|PM_ARRAY))))
|
||||
usepm = 0;
|
||||
if (tc && (pm->flags & PM_SPECIAL)) {
|
||||
zerrnam(cname, "%s: can't change type of a special parameter",
|
||||
pname, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (usepm) {
|
||||
if (!on && !roff && !value) {
|
||||
paramtab->printnode((HashNode)pm, 0);
|
||||
return 0;
|
||||
}
|
||||
if ((pm->flags & PM_RESTRICTED && isset(RESTRICTED))) {
|
||||
zerrnam(cname, "%s: restricted", pname, 0);
|
||||
return 1;
|
||||
}
|
||||
if (PM_TYPE(pm->flags) == PM_ARRAY && (on & PM_UNIQUE) &&
|
||||
!(pm->flags & PM_READONLY & ~off))
|
||||
uniqarray((*pm->gets.afn) (pm));
|
||||
pm->flags = (pm->flags | on) & ~off;
|
||||
/* This auxlen/pm->ct stuff is a nasty hack. */
|
||||
if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER)) &&
|
||||
auxlen)
|
||||
pm->ct = auxlen;
|
||||
if (!(pm->flags & (PM_ARRAY|PM_HASHED))) {
|
||||
if (pm->flags & PM_EXPORTED) {
|
||||
if (!(pm->flags & PM_UNSET) && !pm->env && !value)
|
||||
pm->env = addenv(pname, getsparam(pname));
|
||||
} else if (pm->env) {
|
||||
delenv(pm->env);
|
||||
zsfree(pm->env);
|
||||
pm->env = NULL;
|
||||
}
|
||||
if (value)
|
||||
setsparam(pname, ztrdup(value));
|
||||
} else if (value) {
|
||||
zwarnnam(cname, "can't assign new value for array %s", pname, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We're here either because we're creating a new parameter,
|
||||
* or we're adding a parameter at a different local level,
|
||||
* or we're converting the type of a parameter. In the
|
||||
* last case only, we need to delete the old parameter.
|
||||
*/
|
||||
if (tc) {
|
||||
if (pm->flags & PM_READONLY) {
|
||||
on |= ~off & PM_READONLY;
|
||||
pm->flags &= ~PM_READONLY;
|
||||
}
|
||||
/*
|
||||
* Try to carry over a value, but not when changing from,
|
||||
* to, or between non-scalar types.
|
||||
*/
|
||||
if (!value && !((pm->flags|on) & (PM_ARRAY|PM_HASHED)))
|
||||
value = dupstring(getsparam(pname));
|
||||
/* pname may point to pm->nam which is about to disappear */
|
||||
pname = dupstring(pname);
|
||||
unsetparam_pm(pm, 0, 1);
|
||||
}
|
||||
/*
|
||||
* Create a new node for a parameter with the flags in `on' minus the
|
||||
* readonly flag
|
||||
*/
|
||||
pm = createparam(pname, on & ~PM_READONLY);
|
||||
DPUTS(!pm, "BUG: parameter not created");
|
||||
pm->ct = auxlen;
|
||||
if (func != BIN_EXPORT)
|
||||
pm->level = locallevel;
|
||||
if (value && !(pm->flags & (PM_ARRAY|PM_HASHED)))
|
||||
setsparam(pname, ztrdup(value));
|
||||
pm->flags |= (on & PM_READONLY);
|
||||
if (value && (pm->flags & (PM_ARRAY|PM_HASHED))) {
|
||||
zerrnam(cname, "%s: can't assign initial value for array", pname, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* declare, export, integer, local, readonly, typeset */
|
||||
|
||||
/**/
|
||||
|
@ -1475,7 +1587,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
Comp com;
|
||||
char *optstr = "aiALRZlurtxU";
|
||||
int on = 0, off = 0, roff, bit = PM_ARRAY;
|
||||
int initon, initoff, of, i;
|
||||
int i;
|
||||
int returnval = 0, printflags = 0;
|
||||
|
||||
/* hash -f is really the builtin `functions' */
|
||||
|
@ -1486,9 +1598,9 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
* Unfortunately, this depends on the order *
|
||||
* these flags are defined in zsh.h */
|
||||
for (; *optstr; optstr++, bit <<= 1)
|
||||
if (ops[*optstr] == 1)
|
||||
if (ops[STOUC(*optstr)] == 1)
|
||||
on |= bit;
|
||||
else if (ops[*optstr] == 2)
|
||||
else if (ops[STOUC(*optstr)] == 2)
|
||||
off |= bit;
|
||||
roff = off;
|
||||
|
||||
|
@ -1521,7 +1633,11 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
|
||||
/* With the -m option, treat arguments as glob patterns */
|
||||
if (ops['m']) {
|
||||
MUSTUSEHEAP("typeset -m");
|
||||
while ((asg = getasg(*argv++))) {
|
||||
LinkList pmlist = newlinklist();
|
||||
LinkNode pmnode;
|
||||
|
||||
tokenize(asg->name); /* expand argument */
|
||||
if (!(com = parsereg(asg->name))) {
|
||||
untokenize(asg->name);
|
||||
|
@ -1529,143 +1645,45 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
returnval = 1;
|
||||
continue;
|
||||
}
|
||||
/* If no options or values are given, display all *
|
||||
* parameters matching the glob pattern. */
|
||||
if (!(on || roff || asg->value)) {
|
||||
scanmatchtable(paramtab, com, 0, 0, paramtab->printnode, 0);
|
||||
continue;
|
||||
}
|
||||
/* Since either options or values are given, we search *
|
||||
* through the parameter table and change all parameters *
|
||||
* matching the glob pattern to have these flags and/or *
|
||||
* value. */
|
||||
/*
|
||||
* Search through the parameter table and change all parameters
|
||||
* matching the glob pattern to have these flags and/or value.
|
||||
* Bad news: if the parameter gets altered, e.g. by
|
||||
* a type conversion, then paramtab can be shifted around,
|
||||
* so we need to store the parameters to alter on a separate
|
||||
* list for later use.
|
||||
*/
|
||||
for (i = 0; i < paramtab->hsize; i++) {
|
||||
for (pm = (Param) paramtab->nodes[i]; pm; pm = (Param) pm->next) {
|
||||
for (pm = (Param) paramtab->nodes[i]; pm;
|
||||
pm = (Param) pm->next) {
|
||||
if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED))
|
||||
continue;
|
||||
if (domatch(pm->nam, com, 0)) {
|
||||
/* set up flags if we have any */
|
||||
if (on || roff) {
|
||||
if (PM_TYPE(pm->flags) == PM_ARRAY && (on & PM_UNIQUE) &&
|
||||
!(pm->flags & PM_READONLY & ~off))
|
||||
uniqarray((*pm->gets.afn) (pm));
|
||||
if ((on & ~pm->flags) & PM_HASHED) {
|
||||
char *nam = ztrdup(pm->nam);
|
||||
unsetparam(nam);
|
||||
pm = createparam(nam, on & ~PM_READONLY);
|
||||
DPUTS(!pm, "BUG: parameter not created");
|
||||
}
|
||||
pm->flags = (pm->flags | on) & ~off;
|
||||
if (PM_TYPE(pm->flags) != PM_ARRAY &&
|
||||
PM_TYPE(pm->flags) != PM_HASHED) {
|
||||
if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER)) && auxlen)
|
||||
pm->ct = auxlen;
|
||||
/* did we just export this? */
|
||||
if ((pm->flags & PM_EXPORTED) && !pm->env) {
|
||||
pm->env = addenv(pm->nam, (asg->value) ? asg->value : getsparam(pm->nam));
|
||||
} else if (!(pm->flags & PM_EXPORTED) && pm->env) {
|
||||
/* did we just unexport this? */
|
||||
delenv(pm->env);
|
||||
zsfree(pm->env);
|
||||
pm->env = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* set up a new value if given */
|
||||
if (asg->value) {
|
||||
setsparam(pm->nam, ztrdup(asg->value));
|
||||
}
|
||||
}
|
||||
if (domatch(pm->nam, com, 0))
|
||||
addlinknode(pmlist, pm);
|
||||
}
|
||||
}
|
||||
for (pmnode = firstnode(pmlist); pmnode; incnode(pmnode)) {
|
||||
pm = (Param) getdata(pmnode);
|
||||
if (typeset_single(name, pm->nam, pm, func, on, off, roff,
|
||||
asg->value))
|
||||
returnval = 1;
|
||||
}
|
||||
}
|
||||
return returnval;
|
||||
}
|
||||
|
||||
/* Save the values of on, off, and func */
|
||||
initon = on;
|
||||
initoff = off;
|
||||
of = func;
|
||||
|
||||
/* Take arguments literally. Don't glob */
|
||||
while ((asg = getasg(*argv++))) {
|
||||
/* restore the original values of on, off, and func */
|
||||
on = initon;
|
||||
off = initoff;
|
||||
func = of;
|
||||
on &= ~PM_ARRAY;
|
||||
|
||||
/* check if argument is a valid identifier */
|
||||
if (!isident(asg->name)) {
|
||||
zerr("not an identifier: %s", asg->name, 0);
|
||||
returnval = 1;
|
||||
continue;
|
||||
}
|
||||
bit = 0; /* flag for switching int<->not-int */
|
||||
if ((pm = (Param)paramtab->getnode(paramtab, asg->name)) &&
|
||||
(((pm->flags & PM_SPECIAL) && pm->level == locallevel) ||
|
||||
(!(pm->flags & PM_UNSET) &&
|
||||
((locallevel == pm->level) || func == BIN_EXPORT) &&
|
||||
!(bit = (((off & pm->flags) | (on & ~pm->flags)) &
|
||||
(PM_INTEGER|PM_HASHED)))))) {
|
||||
/* if no flags or values are given, just print this parameter */
|
||||
if (!on && !roff && !asg->value) {
|
||||
paramtab->printnode((HashNode) pm, 0);
|
||||
continue;
|
||||
}
|
||||
if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) {
|
||||
zerrnam(name, "%s: restricted", pm->nam, 0);
|
||||
returnval = 1;
|
||||
continue;
|
||||
}
|
||||
if((pm->flags & PM_SPECIAL) &&
|
||||
PM_TYPE((pm->flags | on) & ~off) != PM_TYPE(pm->flags)) {
|
||||
zerrnam(name, "%s: cannot change type of a special parameter",
|
||||
pm->nam, 0);
|
||||
returnval = 1;
|
||||
continue;
|
||||
}
|
||||
if (PM_TYPE(pm->flags) == PM_ARRAY && (on & PM_UNIQUE) &&
|
||||
!(pm->flags & PM_READONLY & ~off))
|
||||
uniqarray((*pm->gets.afn) (pm));
|
||||
pm->flags = (pm->flags | on) & ~off;
|
||||
if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER)) &&
|
||||
auxlen)
|
||||
pm->ct = auxlen;
|
||||
if (PM_TYPE(pm->flags) != PM_ARRAY &&
|
||||
PM_TYPE(pm->flags) != PM_HASHED) {
|
||||
if (pm->flags & PM_EXPORTED) {
|
||||
if (!(pm->flags & PM_UNSET) && !pm->env && !asg->value)
|
||||
pm->env = addenv(asg->name, getsparam(asg->name));
|
||||
} else if (pm->env) {
|
||||
delenv(pm->env);
|
||||
zsfree(pm->env);
|
||||
pm->env = NULL;
|
||||
}
|
||||
if (asg->value)
|
||||
setsparam(asg->name, ztrdup(asg->value));
|
||||
}
|
||||
} else {
|
||||
if (bit) {
|
||||
if (pm->flags & PM_READONLY) {
|
||||
on |= ~off & PM_READONLY;
|
||||
pm->flags &= ~PM_READONLY;
|
||||
}
|
||||
if (!asg->value)
|
||||
asg->value = dupstring(getsparam(asg->name));
|
||||
unsetparam(asg->name);
|
||||
}
|
||||
/* create a new node for a parameter with the *
|
||||
* flags in `on' minus the readonly flag */
|
||||
pm = createparam(ztrdup(asg->name), on & ~PM_READONLY);
|
||||
DPUTS(!pm, "BUG: parameter not created");
|
||||
pm->ct = auxlen;
|
||||
if (func != BIN_EXPORT)
|
||||
pm->level = locallevel;
|
||||
if (asg->value)
|
||||
setsparam(asg->name, ztrdup(asg->value));
|
||||
pm->flags |= (on & PM_READONLY);
|
||||
}
|
||||
if (typeset_single(name, asg->name,
|
||||
(Param)paramtab->getnode(paramtab, asg->name),
|
||||
func, on, off, roff, asg->value))
|
||||
returnval = 1;
|
||||
}
|
||||
return returnval;
|
||||
}
|
||||
|
@ -1989,7 +2007,7 @@ bin_whence(char *nam, char **argv, char *ops, int func)
|
|||
puts(wd ? ": none" : " not found");
|
||||
returnval = 1;
|
||||
}
|
||||
} else if ((cnam = findcmd(*argv))) {
|
||||
} else if ((cnam = findcmd(*argv, 1))) {
|
||||
/* Found external command. */
|
||||
if (wd) {
|
||||
printf("%s: command\n", *argv);
|
||||
|
@ -2001,7 +2019,6 @@ bin_whence(char *nam, char **argv, char *ops, int func)
|
|||
print_if_link(cnam);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
zsfree(cnam);
|
||||
} else {
|
||||
/* Not found at all. */
|
||||
if (v || csh || wd)
|
||||
|
@ -2328,9 +2345,17 @@ bin_print(char *name, char **args, char *ops, int func)
|
|||
args[n] = getkeystring(args[n], &len[n],
|
||||
func != BIN_ECHO && !ops['e'], &nnl);
|
||||
/* -P option -- interpret as a prompt sequence */
|
||||
if(ops['P'])
|
||||
args[n] = unmetafy(promptexpand(metafy(args[n], len[n],
|
||||
META_NOALLOC), 0, NULL, NULL), &len[n]);
|
||||
if(ops['P']) {
|
||||
/*
|
||||
* promptexpand uses permanent storage: to avoid
|
||||
* messy memory management, stick it on the heap
|
||||
* instead.
|
||||
*/
|
||||
char *str = unmetafy(promptexpand(metafy(args[n], len[n],
|
||||
META_NOALLOC), 0, NULL, NULL), &len[n]);
|
||||
args[n] = dupstring(str);
|
||||
free(str);
|
||||
}
|
||||
/* -D option -- interpret as a directory, and use ~ */
|
||||
if(ops['D']) {
|
||||
Nameddir d = finddir(args[n]);
|
||||
|
@ -2778,8 +2803,9 @@ zexit(int val, int from_signal)
|
|||
LASTALLOC_RETURN;
|
||||
}
|
||||
}
|
||||
if (in_exit++ && from_signal)
|
||||
if (in_exit++ && from_signal) {
|
||||
LASTALLOC_RETURN;
|
||||
}
|
||||
if (isset(MONITOR))
|
||||
/* send SIGHUP to any jobs left running */
|
||||
killrunjobs(from_signal);
|
||||
|
@ -3181,13 +3207,14 @@ bin_read(char *name, char **args, char *ops, int func)
|
|||
}
|
||||
if (c == EOF || (c == '\n' && !zbuf))
|
||||
break;
|
||||
if (!bslash && isep(c) && bptr == buf)
|
||||
if (!bslash && isep(c) && bptr == buf) {
|
||||
if (iwsep(c))
|
||||
continue;
|
||||
else if (!first) {
|
||||
first = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
bslash = c == '\\' && !bslash && !ops['r'];
|
||||
if (bslash)
|
||||
continue;
|
||||
|
@ -3240,7 +3267,7 @@ zread(void)
|
|||
char cc, retry = 0;
|
||||
|
||||
/* use zbuf if possible */
|
||||
if (zbuf)
|
||||
if (zbuf) {
|
||||
/* If zbuf points to anything, it points to the next character in the
|
||||
buffer. This may be a null byte to indicate EOF. If reading from the
|
||||
buffer, move on the buffer pointer. */
|
||||
|
@ -3248,6 +3275,7 @@ zread(void)
|
|||
return zbuf++, STOUC(*zbuf++ ^ 32);
|
||||
else
|
||||
return (*zbuf) ? STOUC(*zbuf++) : EOF;
|
||||
}
|
||||
for (;;) {
|
||||
/* read a character from readfd */
|
||||
switch (read(readfd, &cc, 1)) {
|
||||
|
|
|
@ -54,7 +54,7 @@ evalcond(Cond c)
|
|||
int l = arrlen((char **) c->right);
|
||||
|
||||
if (l < cd->min || (cd->max >= 0 && l > cd->max)) {
|
||||
zerr("unrecognized condition: `-%s'", (char *) c->left, 0);
|
||||
zerr("unrecognized condition: `%s'", (char *) c->left, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -68,13 +68,13 @@ evalcond(Cond c)
|
|||
int l = arrlen(a);
|
||||
|
||||
if (l < cd->min || (cd->max >= 0 && l > cd->max)) {
|
||||
zerr("unrecognized condition: `-%s'", (char *) c->left, 0);
|
||||
zerr("unrecognized condition: `%s'", (char *) c->left, 0);
|
||||
return 0;
|
||||
}
|
||||
a[0] = (char *) c->left;
|
||||
return cd->handler(a, cd->condid);
|
||||
} else
|
||||
zerr("unrecognized condition: `-%s'", (char *) c->left, 0);
|
||||
zerr("unrecognized condition: `%s'", (char *) c->left, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
18
Src/exec.c
18
Src/exec.c
|
@ -457,13 +457,17 @@ execute(Cmdnam not_used_yet, int dash)
|
|||
_exit(1);
|
||||
}
|
||||
|
||||
#define try(X) { if (iscom(X)) return ztrdup(X); }
|
||||
#define RET_IF_COM(X) { if (iscom(X)) return docopy ? dupstring(X) : arg0; }
|
||||
|
||||
/* get the full pathname of an external command */
|
||||
/*
|
||||
* Get the full pathname of an external command.
|
||||
* If the second argument is zero, return the first argument if found;
|
||||
* if non-zero, return the path using heap memory. (RET_IF_COM(X), above).
|
||||
*/
|
||||
|
||||
/**/
|
||||
char *
|
||||
findcmd(char *arg0)
|
||||
findcmd(char *arg0, int docopy)
|
||||
{
|
||||
char **pp;
|
||||
char *z, *s, buf[MAXCMDLEN];
|
||||
|
@ -476,7 +480,7 @@ findcmd(char *arg0)
|
|||
return NULL;
|
||||
for (s = arg0; *s; s++)
|
||||
if (*s == '/') {
|
||||
try(arg0);
|
||||
RET_IF_COM(arg0);
|
||||
if (arg0 == s || unset(PATHDIRS)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -496,13 +500,13 @@ findcmd(char *arg0)
|
|||
*z++ = '/';
|
||||
}
|
||||
strcpy(z, arg0);
|
||||
try(buf);
|
||||
RET_IF_COM(buf);
|
||||
}
|
||||
strcpy(nn, cn->u.name ? *(cn->u.name) : "");
|
||||
strcat(nn, "/");
|
||||
strcat(nn, cn->nam);
|
||||
}
|
||||
try(nn);
|
||||
RET_IF_COM(nn);
|
||||
}
|
||||
for (pp = path; *pp; pp++) {
|
||||
z = buf;
|
||||
|
@ -511,7 +515,7 @@ findcmd(char *arg0)
|
|||
*z++ = '/';
|
||||
}
|
||||
strcpy(z, arg0);
|
||||
try(buf);
|
||||
RET_IF_COM(buf);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -2318,7 +2318,7 @@ doesmatch(Comp c)
|
|||
for (; *pptr; pptr++) {
|
||||
if (*pptr == Meta)
|
||||
pptr++;
|
||||
else if (CHARMATCH(*pptr, looka))
|
||||
else if (CHARMATCH(STOUC(*pptr), STOUC(looka)))
|
||||
break;
|
||||
}
|
||||
if (!*(saves = pptr))
|
||||
|
@ -2688,7 +2688,7 @@ matchonce(Comp c)
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if (CHARMATCH(*pptr, *pat)) {
|
||||
if (CHARMATCH(STOUC(*pptr), STOUC(*pat))) {
|
||||
/* just plain old characters */
|
||||
pptr++;
|
||||
pat++;
|
||||
|
|
|
@ -172,7 +172,7 @@ addhashnode(HashTable ht, char *nam, void *nodeptr)
|
|||
ht->nodes[hashval] = hn;
|
||||
replacing:
|
||||
hn->next = hp->next;
|
||||
if(ht->scan)
|
||||
if(ht->scan) {
|
||||
if(ht->scan->sorted) {
|
||||
HashNode *tab = ht->scan->u.s.tab;
|
||||
int i;
|
||||
|
@ -181,6 +181,7 @@ addhashnode(HashTable ht, char *nam, void *nodeptr)
|
|||
tab[i] = hn;
|
||||
} else if(ht->scan->u.u == hp)
|
||||
ht->scan->u.u = hn;
|
||||
}
|
||||
ht->freenode(hp);
|
||||
return;
|
||||
}
|
||||
|
@ -270,7 +271,7 @@ removehashnode(HashTable ht, char *nam)
|
|||
ht->nodes[hashval] = hp->next;
|
||||
gotit:
|
||||
ht->ct--;
|
||||
if(ht->scan)
|
||||
if(ht->scan) {
|
||||
if(ht->scan->sorted) {
|
||||
HashNode *tab = ht->scan->u.s.tab;
|
||||
int i;
|
||||
|
@ -279,6 +280,7 @@ removehashnode(HashTable ht, char *nam)
|
|||
tab[i] = NULL;
|
||||
} else if(ht->scan->u.u == hp)
|
||||
ht->scan->u.u = hp->next;
|
||||
}
|
||||
return hp;
|
||||
}
|
||||
|
||||
|
|
|
@ -392,7 +392,7 @@ histsubchar(int c)
|
|||
c = ingetc();
|
||||
}
|
||||
*ptr = 0;
|
||||
if (!*buf)
|
||||
if (!*buf) {
|
||||
if (c != '%') {
|
||||
if (isset(CSHJUNKIEHISTORY))
|
||||
ev = curhist - 1;
|
||||
|
@ -408,6 +408,7 @@ histsubchar(int c)
|
|||
else
|
||||
ev = defev;
|
||||
evset = 0;
|
||||
}
|
||||
} else if ((t0 = atoi(buf))) {
|
||||
ev = (t0 < 0) ? curhist + t0 : t0;
|
||||
evset = 1;
|
||||
|
@ -749,11 +750,12 @@ hend(void)
|
|||
save = 0;
|
||||
else {
|
||||
*hptr = '\0';
|
||||
if (hptr[-1] == '\n')
|
||||
if (hptr[-1] == '\n') {
|
||||
if (chline[1]) {
|
||||
*--hptr = '\0';
|
||||
} else
|
||||
save = 0;
|
||||
}
|
||||
if (!*chline || !strcmp(chline, "\n") ||
|
||||
(isset(HISTIGNORESPACE) && spaceflag))
|
||||
save = 0;
|
||||
|
|
|
@ -219,7 +219,7 @@ inputline(void)
|
|||
char *ingetcline, *ingetcpmptl = NULL, *ingetcpmptr = NULL;
|
||||
|
||||
/* If reading code interactively, work out the prompts. */
|
||||
if (interact && isset(SHINSTDIN))
|
||||
if (interact && isset(SHINSTDIN)) {
|
||||
if (!isfirstln)
|
||||
ingetcpmptl = prompt2;
|
||||
else {
|
||||
|
@ -227,6 +227,7 @@ inputline(void)
|
|||
if (rprompt)
|
||||
ingetcpmptr = rprompt;
|
||||
}
|
||||
}
|
||||
if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
|
||||
/*
|
||||
* If not using zle, read the line straight from the input file.
|
||||
|
|
17
Src/jobs.c
17
Src/jobs.c
|
@ -462,7 +462,7 @@ printjob(Job jn, int lng, int synch)
|
|||
if (jn->stat & STAT_SUPERJOB &&
|
||||
jn->procs->status == SP_RUNNING && !pn->next)
|
||||
pn->status = SP_RUNNING;
|
||||
if (pn->status != SP_RUNNING)
|
||||
if (pn->status != SP_RUNNING) {
|
||||
if (WIFSIGNALED(pn->status)) {
|
||||
sig = WTERMSIG(pn->status);
|
||||
llen = strlen(sigmsg[sig]);
|
||||
|
@ -483,6 +483,7 @@ printjob(Job jn, int lng, int synch)
|
|||
} else if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
|
||||
WEXITSTATUS(pn->status))
|
||||
sflag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* print if necessary */
|
||||
|
@ -508,7 +509,7 @@ printjob(Job jn, int lng, int synch)
|
|||
break;
|
||||
len2 += strlen(qn->text) + 2;
|
||||
}
|
||||
if (job != thisjob)
|
||||
if (job != thisjob) {
|
||||
if (fline)
|
||||
fprintf(fout, "[%ld] %c ",
|
||||
(long)(jn - jobtab),
|
||||
|
@ -516,7 +517,7 @@ printjob(Job jn, int lng, int synch)
|
|||
: (job == prevjob) ? '-' : ' ');
|
||||
else
|
||||
fprintf(fout, (job > 9) ? " " : " ");
|
||||
else
|
||||
} else
|
||||
fprintf(fout, "zsh: ");
|
||||
if (lng & 1)
|
||||
fprintf(fout, "%ld ", (long) pn->pid);
|
||||
|
@ -531,18 +532,19 @@ printjob(Job jn, int lng, int synch)
|
|||
lng &= ~3;
|
||||
} else
|
||||
fprintf(fout, "%*s", skip, "");
|
||||
if (pn->status == SP_RUNNING)
|
||||
if (pn->status == SP_RUNNING) {
|
||||
if (!conted)
|
||||
fprintf(fout, "running%*s", len - 7 + 2, "");
|
||||
else
|
||||
fprintf(fout, "continued%*s", len - 9 + 2, "");
|
||||
else if (WIFEXITED(pn->status))
|
||||
}
|
||||
else if (WIFEXITED(pn->status)) {
|
||||
if (WEXITSTATUS(pn->status))
|
||||
fprintf(fout, "exit %-4d%*s", WEXITSTATUS(pn->status),
|
||||
len - 9 + 2, "");
|
||||
else
|
||||
fprintf(fout, "done%*s", len - 4 + 2, "");
|
||||
else if (WIFSTOPPED(pn->status))
|
||||
} else if (WIFSTOPPED(pn->status))
|
||||
fprintf(fout, "%-*s", len + 2, sigmsg[WSTOPSIG(pn->status)]);
|
||||
else if (WCOREDUMP(pn->status))
|
||||
fprintf(fout, "%s (core dumped)%*s",
|
||||
|
@ -1071,7 +1073,7 @@ bin_fg(char *name, char **argv, char *ops, int func)
|
|||
/* If you immediately type "exit" after "jobs", this *
|
||||
* will prevent zexit from complaining about stopped jobs */
|
||||
stopmsg = 2;
|
||||
if (!*argv)
|
||||
if (!*argv) {
|
||||
/* This block handles all of the default cases (no arguments). bg,
|
||||
fg and disown act on the current job, and jobs and wait act on all the
|
||||
jobs. */
|
||||
|
@ -1100,6 +1102,7 @@ bin_fg(char *name, char **argv, char *ops, int func)
|
|||
waitjob(job, SIGINT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Defaults have been handled. We now have an argument or two, or three...
|
||||
In the default case for bg, fg and disown, the argument will be provided by
|
||||
|
|
25
Src/lex.c
25
Src/lex.c
|
@ -457,11 +457,11 @@ add(int c)
|
|||
|
||||
#define SETPARBEGIN {if (zleparse && !(inbufflags & INP_ALIAS) && cs >= ll+1-inbufct) parbegin = inbufct;}
|
||||
#define SETPAREND {\
|
||||
if (zleparse && !(inbufflags & INP_ALIAS) && parbegin != -1 && parend == -1)\
|
||||
if (zleparse && !(inbufflags & INP_ALIAS) && parbegin != -1 && parend == -1) {\
|
||||
if (cs >= ll + 1 - inbufct)\
|
||||
parbegin = -1;\
|
||||
else\
|
||||
parend = inbufct;}
|
||||
parend = inbufct;} }
|
||||
|
||||
static int
|
||||
cmd_or_math(int cs_type)
|
||||
|
@ -823,20 +823,22 @@ gettokstr(int c, int sub)
|
|||
case LX2_OUTPAR:
|
||||
if ((sub || in_brace_param) && isset(SHGLOB))
|
||||
break;
|
||||
if (!in_brace_param && !pct--)
|
||||
if (!in_brace_param && !pct--) {
|
||||
if (sub) {
|
||||
pct = 0;
|
||||
break;
|
||||
} else
|
||||
goto brk;
|
||||
}
|
||||
c = Outpar;
|
||||
break;
|
||||
case LX2_BAR:
|
||||
if (!pct && !in_brace_param)
|
||||
if (!pct && !in_brace_param) {
|
||||
if (sub)
|
||||
break;
|
||||
else
|
||||
goto brk;
|
||||
}
|
||||
if (unset(SHGLOB) || (!sub && !in_brace_param))
|
||||
c = Bar;
|
||||
break;
|
||||
|
@ -912,8 +914,9 @@ gettokstr(int c, int sub)
|
|||
*bptr = '\0';
|
||||
return STRING;
|
||||
}
|
||||
if (in_brace_param)
|
||||
if (in_brace_param) {
|
||||
cmdpush(CS_BRACE);
|
||||
}
|
||||
bct++;
|
||||
}
|
||||
break;
|
||||
|
@ -922,8 +925,9 @@ gettokstr(int c, int sub)
|
|||
break;
|
||||
if (!bct)
|
||||
break;
|
||||
if (in_brace_param)
|
||||
if (in_brace_param) {
|
||||
cmdpop();
|
||||
}
|
||||
if (bct-- == in_brace_param)
|
||||
in_brace_param = 0;
|
||||
c = Outbrace;
|
||||
|
@ -933,11 +937,12 @@ gettokstr(int c, int sub)
|
|||
c = Comma;
|
||||
break;
|
||||
case LX2_OUTANG:
|
||||
if (!intpos)
|
||||
if (!intpos) {
|
||||
if (in_brace_param || sub)
|
||||
break;
|
||||
else
|
||||
goto brk;
|
||||
}
|
||||
e = hgetc();
|
||||
if (e != '(') {
|
||||
hungetc(e);
|
||||
|
@ -1101,11 +1106,12 @@ gettokstr(int c, int sub)
|
|||
break;
|
||||
}
|
||||
add(c);
|
||||
if (c == '\'')
|
||||
if (c == '\'') {
|
||||
if ((inquote = !inquote))
|
||||
STOPHIST
|
||||
else
|
||||
ALLOWHIST
|
||||
}
|
||||
}
|
||||
if (inquote)
|
||||
ALLOWHIST
|
||||
|
@ -1260,8 +1266,9 @@ dquote_parse(char endchar, int sub)
|
|||
}
|
||||
if (intick == 2)
|
||||
ALLOWHIST
|
||||
if (intick)
|
||||
if (intick) {
|
||||
cmdpop();
|
||||
}
|
||||
while (bct--)
|
||||
cmdpop();
|
||||
if (lexstop)
|
||||
|
|
|
@ -52,7 +52,7 @@ execfor(Cmd cmd)
|
|||
List list;
|
||||
Forcmd node;
|
||||
char *str;
|
||||
int val;
|
||||
int val = 0;
|
||||
LinkList args;
|
||||
|
||||
node = cmd->u.forcmd;
|
||||
|
|
58
Src/mem.c
58
Src/mem.c
|
@ -129,26 +129,52 @@ global_permalloc(void)
|
|||
return luh;
|
||||
}
|
||||
|
||||
/* heappush saves the current heap state using this structure */
|
||||
|
||||
struct heapstack {
|
||||
struct heapstack *next; /* next one in list for this heap */
|
||||
size_t used;
|
||||
};
|
||||
|
||||
/* A zsh heap. */
|
||||
|
||||
struct heap {
|
||||
struct heap *next; /* next one */
|
||||
size_t used; /* bytes used from the heap */
|
||||
struct heapstack *sp; /* used by pushheap() to save the value used */
|
||||
#define arena(X) ((char *) (X) + sizeof(struct heap))
|
||||
};
|
||||
|
||||
/* list of zsh heap */
|
||||
|
||||
static Heap heaps;
|
||||
|
||||
/* Use new heaps from now on. This returns the old heap-list. */
|
||||
|
||||
/**/
|
||||
Heap
|
||||
new_heaps(void)
|
||||
{
|
||||
Heap h = heaps;
|
||||
|
||||
heaps = NULL;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/* Re-install the old heaps again, freeing the new ones. */
|
||||
|
||||
/**/
|
||||
void
|
||||
old_heaps(Heap old)
|
||||
{
|
||||
Heap h, n;
|
||||
|
||||
for (h = heaps; h; h = n) {
|
||||
n = h->next;
|
||||
DPUTS(h->sp, "BUG: old_heaps() with pushed heaps");
|
||||
zfree(h, sizeof(*h));
|
||||
}
|
||||
heaps = old;
|
||||
}
|
||||
|
||||
/* Temporarily switch to other heaps (or back again). */
|
||||
|
||||
/**/
|
||||
Heap
|
||||
switch_heaps(Heap new)
|
||||
{
|
||||
Heap h = heaps;
|
||||
|
||||
heaps = new;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/* save states of zsh heaps */
|
||||
|
||||
/**/
|
||||
|
|
|
@ -24,11 +24,17 @@ for x_mod in $x_mods; do
|
|||
*" $x_mod "*) ;;
|
||||
*) echo "/* non-linked-in known module \`$x_mod' */"
|
||||
eval "loc=\$loc_$x_mod"
|
||||
unset moddeps autobins
|
||||
unset moddeps autobins autoinfixconds autoprefixconds
|
||||
. $srcdir/../$loc/${x_mod}.mdd
|
||||
for bin in $autobins; do
|
||||
echo " add_autobin(\"$bin\", \"$x_mod\");"
|
||||
done
|
||||
for cond in $autoinfixconds; do
|
||||
echo " add_autocond(\"$cond\", 1, \"$x_mod\");"
|
||||
done
|
||||
for cond in $autoprefixconds; do
|
||||
echo " add_autocond(\"$cond\", 0, \"$x_mod\");"
|
||||
done
|
||||
for dep in $moddeps; do
|
||||
case $bin_mods in
|
||||
*" $dep "*)
|
||||
|
|
|
@ -17,15 +17,18 @@
|
|||
# defines one module. The .mdd file is actually a shell script, which will
|
||||
# be sourced. It may define the following shell variables:
|
||||
#
|
||||
# moddeps modules on which this module depends (default none)
|
||||
# nozshdep non-empty indicates no dependence on the `zsh' pseudo-module
|
||||
# alwayslink if non-empty, always link the module into the executable
|
||||
# autobins builtins defined by the module, for autoloading
|
||||
# objects .o files making up this module (*must* be defined)
|
||||
# proto .pro files for this module (default generated from $objects)
|
||||
# headers extra headers for this module (default none)
|
||||
# hdrdeps extra headers on which the .mdh depends (default none)
|
||||
# otherincs extra headers that are included indirectly (default none)
|
||||
# moddeps modules on which this module depends (default none)
|
||||
# nozshdep non-empty indicates no dependence on the `zsh' pseudo-module
|
||||
# alwayslink if non-empty, always link the module into the executable
|
||||
# autobins builtins defined by the module, for autoloading
|
||||
# autoinfixconds infix condition codes defined by the module, for
|
||||
# autoloading (without the leading `-')
|
||||
# autoprefixconds like autoinfixconds, but for prefix condition codes
|
||||
# objects .o files making up this module (*must* be defined)
|
||||
# proto .pro files for this module (default generated from $objects)
|
||||
# headers extra headers for this module (default none)
|
||||
# hdrdeps extra headers on which the .mdh depends (default none)
|
||||
# otherincs extra headers that are included indirectly (default none)
|
||||
#
|
||||
# The .mdd file may also include a Makefile.in fragment between lines
|
||||
# `:<<\Make' and `Make' -- this will be copied into Makemod.in.
|
||||
|
@ -167,7 +170,7 @@ if $first_stage; then
|
|||
for module in $here_modules; do
|
||||
|
||||
unset moddeps nozshdep alwayslink hasexport
|
||||
unset autobins
|
||||
unset autobins autoinfixconds autoprefixconds
|
||||
unset objects proto headers hdrdeps otherincs
|
||||
. $top_srcdir/$the_subdir/${module}.mdd
|
||||
test -n "${moddeps+set}" || moddeps=
|
||||
|
|
|
@ -227,7 +227,6 @@ deletewrapper(Module m, FuncWrap w)
|
|||
|
||||
static char *dlerrstr[256];
|
||||
|
||||
/**/
|
||||
static void *
|
||||
load_and_bind(const char *fn)
|
||||
{
|
||||
|
@ -277,7 +276,6 @@ load_and_bind(const char *fn)
|
|||
# define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||
# define dlclose(handle) shl_unload((shl_t)(handle))
|
||||
|
||||
/**/
|
||||
static
|
||||
void *
|
||||
hpux_dlsym(void *handle, char *name)
|
||||
|
|
12
Src/params.c
12
Src/params.c
|
@ -765,7 +765,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
|||
} else if (rev) {
|
||||
v->isarr |= SCANPM_WANTVALS;
|
||||
}
|
||||
if (!down)
|
||||
if (!down && PM_TYPE(v->pm->flags) == PM_HASHED)
|
||||
v->isarr &= ~SCANPM_MATCHMANY;
|
||||
*inv = ind;
|
||||
}
|
||||
|
@ -1534,6 +1534,12 @@ setaparam(char *s, char **val)
|
|||
if (!(v = getvalue(&s, 1)))
|
||||
createparam(t, PM_ARRAY);
|
||||
*ss = '[';
|
||||
if (PM_TYPE(v->pm->flags) == PM_HASHED) {
|
||||
zerr("attempt to set slice of associative array", NULL, 0);
|
||||
freearray(val);
|
||||
errflag = 1;
|
||||
return NULL;
|
||||
}
|
||||
v = NULL;
|
||||
} else {
|
||||
if (!(v = getvalue(&s, 1)))
|
||||
|
@ -1571,13 +1577,13 @@ sethparam(char *s, char **val)
|
|||
}
|
||||
if (strchr(s, '[')) {
|
||||
freearray(val);
|
||||
zerr("attempt to set slice of associative array", NULL, 0);
|
||||
zerr("nested associative arrays not yet supported", NULL, 0);
|
||||
errflag = 1;
|
||||
return NULL;
|
||||
} else {
|
||||
if (!(v = getvalue(&s, 1)))
|
||||
createparam(t, PM_HASHED);
|
||||
else if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
|
||||
else if (!(PM_TYPE(v->pm->flags) & PM_HASHED) &&
|
||||
!(v->pm->flags & PM_SPECIAL)) {
|
||||
unsetparam(t);
|
||||
createparam(t, PM_HASHED);
|
||||
|
|
|
@ -387,11 +387,11 @@ filesubstr(char **namptr, int assign)
|
|||
for (pp = str + 1; !isend2(*pp); pp++);
|
||||
sav = *pp;
|
||||
*pp = 0;
|
||||
if (!(cnam = findcmd(str + 1))) {
|
||||
if (!(cnam = findcmd(str + 1, 1))) {
|
||||
Alias a = (Alias) aliastab->getnode(aliastab, str + 1);
|
||||
|
||||
if (a)
|
||||
cnam = ztrdup(a->text);
|
||||
cnam = a->text;
|
||||
else {
|
||||
if (isset(NOMATCH))
|
||||
zerr("%s not found", str + 1, 0);
|
||||
|
@ -399,7 +399,6 @@ filesubstr(char **namptr, int assign)
|
|||
}
|
||||
}
|
||||
*namptr = dupstring(cnam);
|
||||
zsfree(cnam);
|
||||
if (sav) {
|
||||
*pp = sav;
|
||||
*namptr = dyncat(*namptr, pp);
|
||||
|
|
|
@ -235,7 +235,7 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
|
|||
# endif /* WATCH_UTMP_UT_HOST */
|
||||
|
||||
while (*fmt)
|
||||
if (*fmt == '\\')
|
||||
if (*fmt == '\\') {
|
||||
if (*++fmt) {
|
||||
if (prnt)
|
||||
putchar(*fmt);
|
||||
|
@ -244,6 +244,7 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
|
|||
return fmt;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else if (*fmt == fini)
|
||||
return ++fmt;
|
||||
else if (*fmt != '%') {
|
||||
|
|
|
@ -23,6 +23,7 @@ closem
|
|||
cmdnamtab
|
||||
columns
|
||||
compctlreadptr
|
||||
cond_match
|
||||
cond_str
|
||||
cond_val
|
||||
coprocin
|
||||
|
@ -104,6 +105,8 @@ inredir
|
|||
insertlinknode
|
||||
install_handler
|
||||
intr
|
||||
intvargetfn
|
||||
intvarsetfn
|
||||
inwhat
|
||||
isfirstln
|
||||
jobtab
|
||||
|
@ -126,6 +129,7 @@ mypgrp
|
|||
mypid
|
||||
nameddirtab
|
||||
ncalloc
|
||||
new_heaps
|
||||
newhashtable
|
||||
newlinklist
|
||||
nicechar
|
||||
|
@ -137,6 +141,7 @@ noerrs
|
|||
noholdintr
|
||||
noop_function
|
||||
noop_function_int
|
||||
old_heaps
|
||||
optiontab
|
||||
opts
|
||||
paramtab
|
||||
|
@ -148,6 +153,7 @@ path
|
|||
pathchecked
|
||||
popheap
|
||||
postedit
|
||||
pparams
|
||||
ppid
|
||||
prefork
|
||||
prepromptfns
|
||||
|
@ -197,6 +203,9 @@ strpfx
|
|||
strsfx
|
||||
strucpy
|
||||
struncpy
|
||||
strvargetfn
|
||||
strvarsetfn
|
||||
switch_heaps
|
||||
tclen
|
||||
tcstr
|
||||
termflags
|
||||
|
|
34
Src/zsh.h
34
Src/zsh.h
|
@ -1305,6 +1305,22 @@ struct ttyinfo {
|
|||
* Memory management *
|
||||
*********************/
|
||||
|
||||
/* heappush saves the current heap state using this structure */
|
||||
|
||||
struct heapstack {
|
||||
struct heapstack *next; /* next one in list for this heap */
|
||||
size_t used;
|
||||
};
|
||||
|
||||
/* A zsh heap. */
|
||||
|
||||
struct heap {
|
||||
struct heap *next; /* next one */
|
||||
size_t used; /* bytes used from the heap */
|
||||
struct heapstack *sp; /* used by pushheap() to save the value used */
|
||||
#define arena(X) ((char *) (X) + sizeof(struct heap))
|
||||
};
|
||||
|
||||
#ifndef DEBUG
|
||||
# define HEAPALLOC do { int nonlocal_useheap = global_heapalloc(); do
|
||||
|
||||
|
@ -1318,6 +1334,13 @@ struct ttyinfo {
|
|||
# define LASTALLOC_RETURN \
|
||||
if ((nonlocal_useheap ? global_heapalloc() : \
|
||||
global_permalloc()), 0) {;} else return
|
||||
|
||||
# define NEWHEAPS(h) do { Heap oldheaps = h = new_heaps(); do
|
||||
# define OLDHEAPS while (0); old_heaps(oldheaps); } while (0);
|
||||
|
||||
# define SWITCHHEAPS(h) do { Heap oldheaps = switch_heaps(h); do
|
||||
# define SWITCHBACKHEAPS while (0); switch_heaps(oldheaps); } while (0);
|
||||
|
||||
#else
|
||||
# define HEAPALLOC do { int nonlocal_useheap = global_heapalloc(); \
|
||||
alloc_stackp++; do
|
||||
|
@ -1333,6 +1356,17 @@ struct ttyinfo {
|
|||
# define LASTALLOC_RETURN \
|
||||
if ((nonlocal_useheap ? global_heapalloc() : \
|
||||
global_permalloc()),alloc_stackp--,0){;}else return
|
||||
|
||||
# define NEWHEAPS(h) do { Heap oldheaps = h = new_heaps(); \
|
||||
alloc_stackp++; do
|
||||
# define OLDHEAPS while (0); alloc_stackp--; \
|
||||
old_heaps(oldheaps); } while (0);
|
||||
|
||||
# define SWITCHHEAPS(h) do { Heap oldheaps = switch_heaps(h); \
|
||||
alloc_stackp++; do
|
||||
# define SWITCHBACKHEAPS while (0); alloc_stackp--; \
|
||||
switch_heaps(oldheaps); } while (0);
|
||||
|
||||
#endif
|
||||
|
||||
/****************/
|
||||
|
|
|
@ -120,15 +120,18 @@ Modules are described by a file named `foo.mdd' for a module
|
|||
is build. To describe the module it can/should set the following shell
|
||||
variables:
|
||||
|
||||
- moddeps modules on which this module depends (default none)
|
||||
- nozshdep non-empty indicates no dependence on the `zsh' pseudo-module
|
||||
- alwayslink if non-empty, always link the module into the executable
|
||||
- autobins builtins defined by the module, for autoloading
|
||||
- objects .o files making up this module (*must* be defined)
|
||||
- proto .pro files for this module (default generated from $objects)
|
||||
- headers extra headers for this module (default none)
|
||||
- hdrdeps extra headers on which the .mdh depends (default none)
|
||||
- otherincs extra headers that are included indirectly (default none)
|
||||
- moddeps modules on which this module depends (default none)
|
||||
- nozshdep non-empty indicates no dependence on the `zsh' pseudo-module
|
||||
- alwayslink if non-empty, always link the module into the executable
|
||||
- autobins builtins defined by the module, for autoloading
|
||||
- autoinfixconds infix condition codes defined by the module, for
|
||||
autoloading (without the leading `-')
|
||||
- autoprefixconds like autoinfixconds, but for prefix condition codes
|
||||
- objects .o files making up this module (*must* be defined)
|
||||
- proto .pro files for this module (default generated from $objects)
|
||||
- headers extra headers for this module (default none)
|
||||
- hdrdeps extra headers on which the .mdh depends (default none)
|
||||
- otherincs extra headers that are included indirectly (default none)
|
||||
|
||||
Be sure to put the values in quotes. For further enlightenment have a
|
||||
look at the `mkmakemod.sh' script in the Src directory of the
|
||||
|
|
2
aczsh.m4
2
aczsh.m4
|
@ -45,7 +45,7 @@ else
|
|||
fi
|
||||
echo '
|
||||
extern char **environ;
|
||||
void *symlist1[] = {
|
||||
void *symlist1[[]] = {
|
||||
(void *)&environ,
|
||||
(void *)0
|
||||
};
|
||||
|
|
19
configure.in
19
configure.in
|
@ -340,7 +340,7 @@ AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \
|
|||
termios.h sys/param.h sys/filio.h string.h memory.h \
|
||||
limits.h fcntl.h libc.h sys/utsname.h sys/resource.h \
|
||||
locale.h errno.h stdlib.h unistd.h sys/capability.h \
|
||||
utmp.h utmpx.h sys/types.h pwd.h grp.h)
|
||||
utmp.h utmpx.h sys/types.h pwd.h grp.h poll.h)
|
||||
if test $dynamic = yes; then
|
||||
AC_CHECK_HEADERS(dlfcn.h)
|
||||
AC_CHECK_HEADERS(dl.h)
|
||||
|
@ -467,9 +467,22 @@ elif test $zsh_cv_decl_ospeed_must_define = yes; then
|
|||
fi
|
||||
|
||||
dnl Check if tgetent accepts NULL (and will allocate its own termcap buffer)
|
||||
dnl Some termcaps reportedly accept a zero buffer, but then dump core
|
||||
dnl in tgetstr().
|
||||
AC_CACHE_CHECK(if tgetent accepts NULL,
|
||||
zsh_cv_func_tgetent_accepts_null,
|
||||
[AC_TRY_RUN([main(){int i = tgetent((char*)0,"vt100");exit(!i || i == -1);}],
|
||||
[AC_TRY_RUN([
|
||||
main()
|
||||
{
|
||||
int i = tgetent((char*)0,"vt100");
|
||||
if (i > 0) {
|
||||
char tbuf[1024], *u;
|
||||
u = tbuf;
|
||||
tgetstr("cl", &u);
|
||||
}
|
||||
exit(!i || i == -1);
|
||||
}
|
||||
],
|
||||
zsh_cv_func_tgetent_accepts_null=yes,
|
||||
zsh_cv_func_tgetent_accepts_null=no,
|
||||
zsh_cv_func_tgetent_accepts_null=no)])
|
||||
|
@ -615,7 +628,7 @@ dnl need to integrate this function
|
|||
dnl AC_FUNC_STRFTIME
|
||||
|
||||
AC_CHECK_FUNCS(memcpy memmove \
|
||||
strftime waitpid select tcsetpgrp tcgetattr strstr lstat \
|
||||
strftime waitpid select poll tcsetpgrp tcgetattr strstr lstat \
|
||||
getlogin setpgid gettimeofday gethostname mkfifo wait3 difftime \
|
||||
sigblock sigsetmask sigrelse sighold killpg sigaction getrlimit \
|
||||
sigprocmask setuid seteuid setreuid setresuid setsid strerror \
|
||||
|
|
|
@ -213,3 +213,56 @@ Sven's ignored character fix, 4828
|
|||
More Sven condition patches, 4837, 4842
|
||||
|
||||
Final (???) isident() fix from Sven, 4845
|
||||
|
||||
pws-5
|
||||
|
||||
Name of top level directory is now zsh-3.1.5-pws-5
|
||||
|
||||
Missing part of Bart's sethparam() changes, 4851
|
||||
|
||||
zftp test subcommand, 4852
|
||||
|
||||
Geoff's refresh fix for a line the same length as the terminal width,
|
||||
4855
|
||||
|
||||
Bart's fix for array slices, 4874
|
||||
|
||||
Sven's accept-and-menu-complete-fix, 4878
|
||||
|
||||
Sven's group completion fix, 4879
|
||||
|
||||
Sven's module condition fixes, 4880
|
||||
|
||||
Oliver Kiddle's autoconf fix, 4887
|
||||
|
||||
My zftp fix (actually due to Andrej Borsenkow) for systems which only
|
||||
allow dup'ing sockets after they are connected, 4888.
|
||||
|
||||
Bart's fix to making setting associative array elements inside
|
||||
substitutions consistent, 4893
|
||||
|
||||
My typeset neatness and -a and -m fix, 4902
|
||||
|
||||
My brief Etc/MACHINES addition, 4912
|
||||
|
||||
My modification to findcmd() for memory leaks, 4923, plus comment
|
||||
alteration by Bart, 4924
|
||||
|
||||
Sven's patch for completion after various reserved words, 4930
|
||||
|
||||
My patch for compiler warnings, 4931
|
||||
|
||||
My configuration fix for when tgetent() accepts a null argument but
|
||||
then tgetstr() dumps core, 4939
|
||||
|
||||
Sven's alteration of `-t' behaviour, 4940. This is slightly
|
||||
incompatible with previous patched versions of 3.1.5 since now you don't
|
||||
need '-tc' with -T. However, you now do need '-tn' in cases where you
|
||||
don't want normal completion tried after a -T matches.
|
||||
|
||||
Sven's new completion functions, 4850, 4881, 4941, 4942, 4943, 4944,
|
||||
4946, 4949, plus my addition of function pointers, 4945. The example
|
||||
file is now in Misc/new-completion-examples.
|
||||
|
||||
(Effect of) fix from Helmut Jarausch in 4947 partly due to change
|
||||
missed in patch.
|
||||
|
|
Loading…
Reference in a new issue