1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-06-14 08:08:10 +02:00

zsh-3.1.5-pws-6

This commit is contained in:
Tanaka Akira 1999-04-15 18:12:56 +00:00
parent 20d67907c9
commit 7a40d6c258
30 changed files with 1793 additions and 844 deletions

View file

@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the
# `=' signs.
VERSION=3.1.5-pws-5
VERSION_DATE='January 19, 1998'
VERSION=3.1.5-pws-6
VERSION_DATE='January 28, 1998'

View file

@ -112,11 +112,11 @@ version.yo: $(sdir_top)/Config/version.mk
# ========== DEPENDENCIES FOR INSTALLING ==========
# install all the documentation
install: install.man install.info
# install just installs the manual pages
install: install.man
# uninstall all the documentation
uninstall: uninstall.man uninstall.info
# uninstall just unistalls the manual pages
uninstall: uninstall.man
# install man pages, creating install directory if necessary
install.man: $(MAN)
@ -141,6 +141,9 @@ install.info: zsh.info
else :; \
fi || exit 1; \
done
if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
install-info --dir-file=$(infodir)/dir $(infodir)/zsh.info; \
else true; fi
install.html: zsh_toc.html
$(sdir_top)/mkinstalldirs $(htmldir)

View file

@ -878,7 +878,10 @@ Equivalent to tt(whence -v).
findex(typeset)
cindex(parameters, setting)
cindex(parameters, declaring)
item(tt(typeset) [ {tt(PLUS())|tt(-)}tt(ALRUZafilrtuxm) [var(n)]] [ var(name)[tt(=)var(value)] ... ])(
xitem(tt(typeset) [ {tt(PLUS())|tt(-)}tt(ALRUZafilrtuxm) [var(n)]] [ \
var(name)[tt(=)var(value)] ... ])
item(tt(typeset) -T [ {tt(PLUS()|tt(-))}tt(LRUZrux) ] \
var(SCALAR)[tt(=)var(value)] var(array))(
Set or display attributes and values for shell parameters.
A parameter is created for each var(name) that does not already refer
@ -891,7 +894,7 @@ ifnzman(noderef(Local Parameters))\
which case the parameter is exported em(only) when var(name) does not
already appear in the environment.
For each nofill(var(name)tt(=)var(value)) assignment, the parameter
For each var(name)tt(=)var(value) assignment, the parameter
var(name) set to var(value). Note that arrays currently cannot be
assigned in tt(typeset) expressions; scalars and integers only.
@ -899,6 +902,19 @@ For each remaining var(name) that refers to a parameter that is set,
the name and value of the parameter are printed in the form of an
assignment. Nothing is printed for newly-created parameters.
If the tt(-T) option is given, exactly two (or zero) var(name)
arguments must be present. They represent a scalar and an array (in
that order) that will be tied together in the manner of tt($PATH) and
tt($path). In other words, an array present in the latter variable
appears as a scalar with the elements of the array joined by colons in
the former. Only the scalar may have an initial value. Both the
scalar and the array may otherwise be manipulated as normal. If one
is unset, the other will automatically be unset too. There is no way
of untying the variables without unsetting them, or converting the
type of one them with another tt(typeset) command; tt(+T) does not work,
assigning an array to var(SCALAR) is an error, and assigning a scalar
to var(array) sets it to be a single-element array.
If no var(name) is present, the names and values of all parameters are
printed. In this case the attribute flags restrict the the display to
only those parameters that have the specified attributes. Using

View file

@ -602,6 +602,46 @@ item(tt(f))(
Split the result of the expansion to lines. This is a shorthand
for `tt(ps:\n:)'.
)
item(tt(t))(
Don't work on the value of the parameter, but on a string describing
the type of the parameter. This string consists of keywords separated
by hyphens (`tt(-)'). The first keyword in the string describes the
main type, it can be one of `tt(scalar)', `tt(array)', `tt(integer)',
or `tt(association)'. The other keywords describe the type in more
detail:
startitem()
item(`tt(left)')(
for left justified parameters
)
item(`tt(right_blanks)')(
for right justified parameters with leading blanks
)
item(`tt(right_zeros)')(
for right justified parameters with leading zeros
)
item(`tt(lower)')(
for parameters whose value is converted to all lower case when it is
expanded
)
item(`tt(upper)')(
for parameters whose value is converted to all upper case when it is
expanded
)
item(`tt(readonly)')(
for readonly parameters
)
item(`tt(tag)')(
for tagged parameters
)
item(`tt(export)')(
for exported parameters
)
item(`tt(unique)')(
for arrays which keep only the first occurrence of duplicated values
)
enditem()
)
enditem()
The following flags are meaningful with the tt(${)...tt(#)...tt(}),
@ -1048,6 +1088,49 @@ setgid files (02000)
item(tt(t))(
files with the sticky bit (01000)
)
item(tt(o)var(spec))(
files with access rights matching var(spec). This var(spec) may be a
octal number optionally preceded by a `tt(=)', a `tt(PLUS())', or a
`tt(-)'. If none of these characters is given, the behavior is the
same as for `tt(=)'. The octal number decribes the mode bits to be
expected, if combined with a `tt(=)', the value given must match the
file-modes exactly, with a `tt(PLUS())', at least the bits in the
given number must be set in the file-modes, and with a `tt(-)', the
bits in the number must not be set. Giving a `tt(?)' instead of a
octal digit anywhere in the number ensures that the corresponding bits
inthe file-modes are not checked, this is only useful in combination
with `tt(=)'.
If the qualifier `tt(o)' is followed by any other character anything
up to the next matching character (`tt([)', `tt({)', and `tt(<)' match
`tt(])', `tt(})', and `tt(>)' respectively, any other character
matches itself) is taken as a list of comma-separated
var(sub-spec)s. Each var(sub-spec) may be either a octal number as
described above or a list of any of the characters `tt(u)', `tt(g)',
`tt(o)', and `tt(a)', followed by a `tt(=)', a `tt(PLUS())', or a
`tt(-)', followed by a list of any of the characters `tt(r)', `tt(w)',
`tt(x)', `tt(s)', and `tt(t)', or a octal digit. The first list of
characters specify which acess rights are to be checked. If a `tt(u)'
is given, those for the owner of the file are used, if a `tt(g)' is
given, those of the group are checked, a `tt(o)' means to test those
of other users, and the `tt(a)' says to test all three groups. The
`tt(=)', `tt(PLUS())', and `tt(-)' again says how the modes are to be
checked and have the same meaning as described for the first form
above. The second list of characters finally says which access rights
are to be expected: `tt(r)' for read access, `tt(w)' for write access,
`tt(x)' for the right to execute the file (or to search a directory),
`tt(s)' for the setuid and setgid bits, and `tt(t)' for the sticky
bit.
Thus, `tt(*(o70?))' gives the files for which the owner has read,
write, and execute permission, and for which other group members have
no rights, independent of the permissions for other user. The pattern
`tt(*(o-100))' gives all files for which the owner does not have
execute permission, and `tt(*(o:gu+w,o-rx))' gives the files for which
the owner and the other members of the group have at least write
permission, and fo which other users don't have read or execute
permission.
)
item(tt(d)var(dev))(
files on the device var(dev)
)
@ -1065,8 +1148,8 @@ item(tt(u)var(id))(
files owned by user ID var(id) if it is a number, if not, than the
character after the `tt(u)' will be used as a separator and the string
between it and the next matching separator
(`tt(LPAR())', `tt([)', `tt({)', and `tt(<)'
match `tt(RPAR())', `tt(])', `tt(})', and `tt(>)' respectively,
(`tt([)', `tt({)', and `tt(<)'
match `tt(])', `tt(})', and `tt(>)' respectively,
any other character matches
itself) will be taken as a user name, and the user ID of this user will
be taken (e.g. `tt(u:foo:)' or `tt(u[foo])' for user `tt(foo)')
@ -1122,6 +1205,27 @@ item(tt(D))(
sets the tt(GLOB_DOTS) option for the current pattern
pindex(GLOB_DOTS, setting in pattern)
)
item(tt(O)var(c))(
specifies how the names of the files should be sorted. If var(c) is
tt(n) they are sorted by name (the default), if var(c) is tt(L) they
are sorted depending on the size (length) of the files, tt(l) makes
them be sorted by the number of links, and tt(a), tt(m), and tt(c)
make them be sorted by the time of the last access, modification, and
inode change respectively. Note that tt(a), tt(m), and tt(c) compare
the age to the current time, so the first name in the list is the
one of the youngest file. Also note that the modifiers tt(^) and tt(-) are
used, so `tt(*(^-OL))' gives a list of all files sorted by file size in
descending order working not on symbolic links but on the files they
point to.
)
item(tt([)var(beg)[tt(,)var(end)]tt(]))(
specifies which of the matched filenames should be included in the
returned list. The syntax is the same as for array
subscripts. var(beg) and the optional var(end) may be mathematical
expressions. As in parameter subscripting they may be negative to make
them count from the last match backward. E.g.: `tt(*(^-OL[1,3]))'
gives a list of the names of three biggest files.
)
enditem()
More than one of these lists can be combined, separated by commas. The

View file

@ -57,6 +57,12 @@ def(texinfo)(2)(\
NOTRANS(@iftex)NL()\
NOTRANS(@set dsq '{}')NL()\
NOTRANS(@end iftex)NL()\
NOTRANS(@ifinfo)NL()\
NOTRANS(@dircategory Utilities)NL()\
NOTRANS(@direntry)NL()\
NOTRANS( * ZSH: (zsh). The Z Shell Guide.)NL()\
NOTRANS(@end direntry)NL()\
NOTRANS(@end ifinfo)NL()\
)
def(texiifinfo)(1)(\

37
Functions/zless Normal file
View file

@ -0,0 +1,37 @@
#!/usr/bin/zsh -f
#
# zsh function script to run less on various inputs, decompressing as required.
# Author: Phil Pennock. zsh-hacks@athenaeum.demon.co.uk
# Modified by Bart Schaefer.
# Thanks to zefram@fysh.org for a great deal of help in sorting this out,
# ie wrt syntax for unsetting members of arrays and eval "$(...)" when I
# asked for something better than . =(...)
#
# Use -zforce to pass through a display-formatting command
# zless -zforce 'bzip2 -dc' foo-no-dotbz2
# zless -zforce 'od -hc' foo-binfile
#
# If you can understand all of this without reference to zshexpn(1)
# and zshparam(1) then you either have a photographic memory or you
# need to get out more.
#
emulate -R zsh
setopt localoptions
[[ $# -ge 1 ]] || return
local lessopts
set -A lessopts
integer i=1 loi=1
while ((i <= $#))
do
case $argv[i] in
-zforce) argv[i,i+2]=("=($argv[i+1] \"$argv[i+2]\")"); ((++i));;
-*) lessopts[loi++]=\"$argv[i]\"; argv[i]=(); continue;;
*.(gz|Z)) argv[i]="=(zcat \"$argv[i]\")";;
*.bz2) argv[i]="=(bzip2 -dc \"$argv[i]\")";;
*.bz) argv[i]="=(bzip -dc \"$argv[i]\")";;
esac
((++i))
done
eval command less $lessopts $*

View file

@ -6,12 +6,13 @@ zmodload -i stat || return 1
emulate -R zsh
setopt localoptions
local f stat opts='' L=L mod=: dirs list
local f opts='' L=L mod=: dirs list
typeset -A stat
dirs=()
list=()
while getopts ailLFd f
while getopts ailLFdtuc f
do
opts=$opts$f
if [[ $f == '?' ]] then
@ -25,24 +26,40 @@ shift OPTIND-1
[[ $opts == *F* ]] && mod=T$mod
[[ $opts == *a* ]] && setopt globdots
local time=mtime tmod=m
[[ $opts == *u* ]] && time=atime tmod=a
[[ $opts == *c* ]] && time=ctime tmod=c
if ((! ARGC)) then
set *
if [[ $opts = *t* ]]; then
set *(O$tmod)
else
set *
fi
opts=d$opts
elif [[ $opts = *t* && $ARGC -gt 1 ]]; then
# another glaringly obvious zsh trick: reorder the argv list
# by time, without messing up metacharacters inside
local n='$1'
for (( f = 2; f <= $ARGC; f++ )); do
n="$n|\$$f"
done
eval "argv=(($n)(O$tmod))"
fi
for f in $*
do
stat -s$L -A stat -F "%b %e %H:%M" - $f || continue
if [[ $opts != *d* && $stat[3] == d* ]] then
stat -s$L -H stat -F "%b %e %H:%M" - $f || continue
if [[ $opts != *d* && $stat[mode] == d* ]] then
dirs=( $dirs $f )
elif [[ $opts == *l* ]] then
[[ $opts == *i* ]] && print -n "${(l:7:)stat[2]} "
[[ -n $stat[14] ]] && f=( $f '->' $stat[14] ) || f=( $f($mod) )
print -r -- "$stat[3] ${(l:3:)stat[4]} ${(r:8:)stat[5]} " \
"${(r:8:)stat[6]} ${(l:8:)stat[8]} $stat[10] $f"
[[ $opts == *i* ]] && print -n "${(l:7:)stat[inode]} "
[[ -n $stat[link] ]] && f=( $f '->' $stat[link] ) || f=( $f($mod) )
print -r -- "$stat[mode] ${(l:3:)stat[nlink]} ${(r:8:)stat[uid]} " \
"${(r:8:)stat[gid]} ${(l:8:)stat[size]} $stat[$time] $f"
else
f=( $f($mod) )
list=( "$list[@]" "${${(M)opts:%*i*}:+${(l:7:)stat[2]} }$f" )
list=( "$list[@]" "${${(M)opts:%*i*}:+${(l:7:)stat[inode]} }$f" )
fi
done
(($#list)) && print -cr -- "$list[@]"

15
INSTALL
View file

@ -114,15 +114,18 @@ To install the dynamically-loadable modules, do the command:
To install the zsh man page, do the command:
make install.man
To install the zsh info files, do the command:
make install.info
Or alternatively, you can install all the above with the command:
make install
"make install.info" will only move the info files into the info directory.
You will have to edit the topmost node of the info tree "dir" manually
in order to have the zsh info files available to your info reader.
To install the zsh info files (this must be done separately), do the
command:
make install.info
If the programme install-info is available, "make install.info" will
insert an entry in the file "dir" in the same directory as the info
files. Otherwise you will have to edit the topmost node of the info
tree "dir" manually in order to have the zsh info files available to
your info reader.
Building Zsh On Additional Architectures
----------------------------------------

View file

@ -55,9 +55,9 @@ META-FAQ: FORCE
install-strip:
$(MAKE) install STRIPFLAGS="-s"
# install/uninstall everything
install: install.bin install.modules install.man install.info
uninstall: uninstall.bin uninstall.modules uninstall.man uninstall.info
# install/uninstall everything (except info)
install: install.bin install.modules install.man
uninstall: uninstall.bin uninstall.modules uninstall.man
# install/uninstall just the binary
install.bin uninstall.bin:

View file

@ -19,21 +19,31 @@ typeset -A comps
# With only one argument the function/variable-name __$1 is used.
defcomp() {
local v
local v a=''
if [[ "$1" = -a ]] then
shift
a=yes
fi
if [[ $# -eq 1 ]] then
comps[$1]="__$1"
[[ -z "$a" ]] || autoload "__$1"
else
v="$1"
shift
for i; do
comps[$i]="$v"
done
[[ -z "$a" ]] || autoload "$v"
fi
}
defpatcomp() {
if [[ ${+patcomps} == 1 ]] then
if [[ "$1" = -a ]] then
shift
autoload "$1"
fi
if (( $+patcomps )) then
patcomps=("$patcomps[@]" "$2 $1" )
else
patcomps=( "$2 $1" )
@ -68,10 +78,10 @@ call-complete() {
local var
eval var\=\$\{\+$1\}
if [[ "$var" == 0 ]] then
"$@"
else
if (( var )); then
eval complist \$\{${1}\[\@\]\}
else
"$@"
fi
}
@ -80,11 +90,21 @@ call-complete() {
# arguments from the command line are gives as positional parameters.
main-complete() {
emulate -R zsh
# emulate -R zsh
local comp
setopt localoptions nullglob rcexpandparam globdots
unsetopt markdirs globsubst shwordsplit nounset
# We first try the `compctl's. This is without first (-T) and default (-D)
# completion. If you want them add `-T' and/or `-D' to this command.
# If this produces any matches, we don't try new style completion. If you
# want to have that tried anyway, remove the `[[ -nmatches ... ]] ...'
# below.
compcall
[[ -nmatches 0 ]] || return
# 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'
@ -164,21 +184,6 @@ do-complete() {
[[ -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.
@ -190,90 +195,123 @@ __precmd() {
# so you may want to modify this.
pfiles() {
local nm str pa pre epre a b c s rest
local nm ostr opa pre epre a b c s rest ppres
setopt localoptions nullglob rcexpandparam globdots extendedglob
unsetopt markdirs globsubst shwordsplit nounset
if [[ "$1" = -W ]] then
a="$2"
if [[ "$a[1]" = '(' ]] then
ppres=( $a[2,-2]/ )
else
eval ppres\=\( \$$a/ \)
[[ $#ppres -eq 0 ]] && ppres=( $a/ )
fi
[[ $#ppres -eq 0 ]] && ppres=( '' )
shift 2
else
ppres=( '' )
fi
str="$PREFIX*$SUFFIX"
if [[ -z "$a[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]] then
a=()
else
a=(-W "( $ppres )")
fi
nm=$NMATCHES
if [[ $# -eq 0 ]] then
complist -f
complist "$a[@]" -f
elif [[ "$1" = -g ]] then
complist -g "$argv[2,-1]"
complist "$a[@]" -g "$argv[2,-1]"
shift
else
complist $1
complist "$a[@]" $1
shift
fi
[[ -nmatches nm ]] || return
str="$PREFIX*$SUFFIX"
[[ -z "$1" ]] && 1='*'
if [[ $str[1] = \~ ]] then
if [[ "$str[1]" = \~ ]] then
pre="${str%%/*}/"
eval epre\=$pre
str="${str#*/}"
pa=''
opa=''
ppres=( '' )
else
pre=''
epre=''
if [[ $str[1] = / ]] then
if [[ "$str[1]" = / ]] then
str="$str[2,-1]"
pa='/'
opa='/'
ppres=( '' )
else
pa=''
[[ "$str" = (.|..)/* ]] && ppres=( '' )
opa=''
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"
[[ -e "$epre$opa${str%%/*}" ]] || break
opa="$opa${str%%/*}/"
str="${str#*/}"
done
ostr="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
for ppre in "$ppres[@]"; do
str="$ostr"
pa="$opa"
while [[ "$str" = */* ]] do
rest="${str#*/}"
a="${ppre}${epre}${pa}(#l)${str%%/*}(-/)"
a=( $~a )
if [[ $#a -eq 0 ]] then
continue 2
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
continue 2
elif [[ $#c -ne 1 ]] then
a="$ppre$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
continue 2
fi
a=( "$c[1]" )
fi
a="$a[1]"
pa="$pa${a##*/}/"
str="$rest"
done
a="$ppre$epre$pa"
s=( $str$@ )
s=( "${(@)s:gs.**.*.}" )
b=( $~a(#l)$~s )
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
compadd -p "$pre$pa" -W "$ppre$epre$pa" -f ${b#$a}
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
local nm=$NMATCHES
nm=$NMATCHES
pfiles "$@"
[[ $# -ne 0 && -nmatches nm ]] && pfiles
@ -289,23 +327,318 @@ __default() {
defcomp __command --command--
__command=( -c )
defcomp __math --math--
__math=( -v )
defcomp __vars --math--
__vars=( -v )
defcomp __subscr --subscr--
__subscr() {
local t
eval t\=\$\{\(t\)$COMMAND\}
compalso --math-- "$@"
# ...probably other stuff
[[ $t = assoc* ]] && eval complist -k \"\(\$\{\(k\)$COMMAND\}\)\"
}
# A simple pattern completion, just as an example.
# Do sub-completion for pre-command modifiers.
defpatcomp __x_options '*/X11/*'
__x_options() {
complist -J options -k '(-display -name -xrm)'
defcomp __precmd - nohup nice eval time rusage noglob nocorrect exec
__precmd() {
COMMAND="$1"
shift
(( CURRENT-- ))
if [[ CURRENT -eq 0 ]] then
CONTEXT=command
else
CONTEXT=argument
fi
compsub
}
# A better example: completion for `find'.
defcomp builtin
__builtin() {
if [[ -position 2 -1 ]] then
compsub
else
complist -eB
fi
}
defcomp command
__command() {
if [[ -position 2 -1 ]] then
compsub
else
complist -em
fi
}
# Various completions...
defcomp __jobs fg jobs
__jobs=(-j -P '%')
defcomp __bjobs bg
__bjobs=(-z -P '%')
defcomp __arrays shift
__arrays=(-A)
defcomp __which which whence where type
__which=( -caF )
defcomp unhash
__unhash() {
[[ -mword 1 -*d* ]] && complist -n
[[ -mword 1 -*a* ]] && complist -a
[[ -mword 1 -*f* ]] && complist -F
[[ ! -mword 1 -* ]] && complist -m
}
defcomp hash
__hash() {
if [[ -mword 1 -*d* ]] then
if [[ -string 1 '=' ]] then
pfiles -g '*(-/)'
else
complist -n -q -S '='
fi
elif [[ -string 1 '=' ]] then
files -g '*(*)' '*(-/)'
else
complist -m -q -S '='
fi
}
defcomp __funcs unfunction
__funcs=(-F)
defcomp echotc
__echotc=(-k '(al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up)')
defcomp __aliases unalias
__aliases=(-a)
defcomp __vars getopts read unset vared
defcomp __varseq declare export integer local readonly typeset
__varseq=(-v -S '=')
defcomp disable
__disable() {
[[ -mcurrent -1 -*a* ]] && complist -ea
[[ -mcurrent -1 -*f* ]] && complist -eF
[[ -mcurrent -1 -*r* ]] && complist -ew
[[ ! -mcurrent -1 -* ]] && complist -eB
}
defcomp enable
__enable() {
[[ -mcurrent -1 -*a* ]] && complist -da
[[ -mcurrent -1 -*f* ]] && complist -dF
[[ -mcurrent -1 -*r* ]] && complist -dw
[[ ! -mcurrent -1 -* ]] && complist -dB
}
defcomp __limits limit unlimit
__limits=(-k "(${(j: :)${(f)$(limit)}%% *})")
defcomp source
__source() {
if [[ -position 2 -1 ]] then
compsub
else
files
fi
}
defcomp setopt
__setopt() {
local nm=$NMATCHES
complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)'
[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
}
defcomp unsetopt
__unsetopt() {
local nm=$NMATCHES
complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)'
[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
}
defcomp autoload
__autoload=(-s '${^fpath}/*(N:t)')
defcomp bindkey
__bindkey() {
if [[ -mword 1 -*[DAN]* || -mcurrent -1 -*M ]] then
complist -s '$(bindkey -l)'
else
complist -b
fi
}
defcomp fc
__fc() {
if [[ -mcurrent -1 -*e ]] then
complist -c
elif [[ -mcurrent -1 -[ARWI]## ]] then
files
fi
}
defcomp sched
__sched() {
[[ -position 2 -1 ]] && compsub
}
defcomp set
__set() {
if [[ -mcurrent -1 [-+]o ]] then
complist -o
elif [[ -current -1 -A ]] then
complist -A
fi
}
defcomp zle
__zle() {
if [[ -word 1 -N && -position 3 ]] then
complist -F
else
complist -b
fi
}
defcomp zmodload
__zmodload() {
if [[ -mword 1 -*(a*u|u*a)* || -mword 1 -*a* && -position 3 -1 ]] then
complist -B
elif [[ -mword 1 -*u* ]] then
complist -s '$(zmodload)'
else
complist -s '${^module_path}/*(N:t:r)'
fi
}
defcomp trap
__trap() {
if [[ -position 1 ]] then
complist -c
else
complist -k signals
fi
}
killfunc() {
reply=( "$(ps -x 2>/dev/null)" )
}
defcomp kill
__kill() {
if [[ -iprefix '-' ]] then
complist -k "($signals[1,-3])"
else
complist -P '%' -j
complist -y killfunc -s '`ps -x 2>/dev/null | tail +2 | cut -c1-5`'
fi
}
defcomp wait
__wait() {
complist -P '%' -j
complist -y killfunc -s '`ps -x 2>/dev/null | tail +2 | cut -c1-5`'
}
defcomp cd
__cd() {
files -W cdpath -g '*(-/)'
}
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 __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 pmake
__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 __dvi xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
__dvi() {
files -g '*.(dvi|DVI)'
}
defcomp __dirs rmdir df du dircmp
__dirs() {
files -/ '*(-/)'
}
defcomp __uncompress uncompress zmore
__uncompress() {
files -g '*.Z'
}
defcomp compress
__compress() {
files -g '*~*.Z'
}
defcomp __tex tex latex slitex
__tex() {
files -g '*.(tex|TEX|texinfo|texi)'
}
defcomp __pdf acroread
__pdf() {
files -g '*.(pdf|PDF)'
}
defcomp tar
__tar() {
local nm=$NMATCHES tf="$2"
compsave
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
}
defcomp find
__find() {
@ -333,121 +666,9 @@ __find() {
fi
}
# Various completions...
# A simple pattern completion, just as an example.
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
defpatcomp __x_options '*/X11/*'
__x_options() {
complist -J options -k '(-display -name -xrm)'
}

View file

@ -267,3 +267,8 @@ struct cline {
#define CLF_MISS 4
#define CLF_DIFF 8
#define CLF_SUF 16
/* Flags for makecomplist*(). Things not to do. */
#define CFN_FIRST 1
#define CFN_DEFAULT 2

View file

@ -43,12 +43,6 @@ Cmlist cmatcher;
/* pointers to functions required by zle and defined by compctl */
/**/
void (*printcompctlptr) _((char *, Compctl, int, int));
/**/
Compctl (*compctl_widgetptr) _((char *, char **));
/**/
void (*makecompparamsptr) _((void));
@ -66,6 +60,8 @@ int (*getcpatptr) _((char *, int, char *, int));
/**/
void (*makecomplistcallptr) _((Compctl));
/**/
void (*makecomplistctlptr) _((int));
/* Hash table for completion info for commands */

View file

@ -11,7 +11,6 @@ clwsize
cmatcher
compcommand
compcontext
compctl_widgetptr
compctltab
compcurrent
compiprefix
@ -28,8 +27,8 @@ incompctlfunc
incompfunc
instring
makecomplistcallptr
makecomplistctlptr
makecompparamsptr
patcomps
printcompctlptr
quotename
rembslash

View file

@ -1638,38 +1638,6 @@ bin_compctl(char *name, char **argv, char *ops, int func)
return ret;
}
/* Externally callable version of get_compctl. Used for completion widgets */
/**/
static Compctl
compctl_widget(char *name, char **argv)
{
Compctl cc = (Compctl) zcalloc(sizeof(*cc));
cclist = 0;
showmask = 0;
if (get_compctl(name, &argv, cc, 1, 0, 0)) {
freecompctl(cc);
return NULL;
}
if (cclist & COMP_REMOVE) {
zwarnnam(name, "use -D to delete widget", NULL, 0);
return NULL;
} else if (cclist) {
zwarnnam(name, "special options illegal in widget", NULL, 0);
freecompctl(cc);
return NULL;
} else if (*argv) {
zwarnnam(name, "command names illegal in widget", NULL, 0);
freecompctl(cc);
return NULL;
}
cc->refc++;
return cc;
}
/**/
static int
bin_complist(char *name, char **argv, char *ops, int func)
@ -1677,7 +1645,7 @@ bin_complist(char *name, char **argv, char *ops, int func)
Compctl cc;
int ret = 0;
if (!incompfunc) {
if (incompfunc != 1) {
zerrnam(name, "can only be called from completion function", NULL, 0);
return 1;
}
@ -1706,7 +1674,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
char *pre = NULL, *suf = NULL, *group = NULL;
int f = 0, q = 0, m = 0, ns = 0, a = 0;
if (!incompfunc) {
if (incompfunc != 1) {
zerrnam(name, "can only be called from completion function", NULL, 0);
return 1;
}
@ -1792,15 +1760,27 @@ bin_compadd(char *name, char **argv, char *ops, int func)
}
}
ca_args:
if (!*argv) {
zerrnam(name, "missing completions", NULL, 0);
if (!*argv)
return 1;
}
addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
f, q, m, ns, a, argv);
return 0;
}
/**/
static int
bin_compcall(char *name, char **argv, char *ops, int func)
{
if (incompfunc != 1) {
zerrnam(name, "can only be called from completion function", NULL, 0);
return 1;
}
makecomplistctlptr((ops['T'] ? 0 : CFN_FIRST) |
(ops['D'] ? 0 : CFN_DEFAULT));
return 0;
}
#define VAR(X) ((void *) (&(X)))
static struct compparam {
char *name;
@ -1823,7 +1803,7 @@ void makecompparams(void)
struct compparam *cp;
for (cp = compparams; cp->name; cp++) {
Param pm = createparam(cp->name, cp->type | PM_SPECIAL);
Param pm = createparam(cp->name, cp->type | PM_SPECIAL|PM_REMOVABLE);
if (!pm)
pm = (Param) paramtab->getnode(paramtab, cp->name);
DPUTS(!pm, "param not set in makecompparams");
@ -1856,7 +1836,7 @@ compunsetfn(Param pm, int exp)
static int
comp_wrapper(List list, FuncWrap w, char *name)
{
if (!incompfunc)
if (incompfunc != 1)
return 1;
else {
char *octxt, *ocmd, *opre, *osuf, *oipre;
@ -1907,7 +1887,7 @@ ignore_prefix(int l)
static int
comp_check(void)
{
if (!incompfunc) {
if (incompfunc != 1) {
zerr("condition can only be used in completion function", NULL, 0);
return 0;
}
@ -2119,7 +2099,8 @@ cond_nmatches(char **a, int id)
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),
BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL),
BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL),
};
static struct conddef cotab[] = {
@ -2149,8 +2130,6 @@ int
setup_compctl(Module m)
{
compctltab->printnode = printcompctlp;
printcompctlptr = printcompctl;
compctl_widgetptr = compctl_widget;
makecompparamsptr = makecompparams;
return 0;
}
@ -2183,8 +2162,6 @@ int
finish_compctl(Module m)
{
compctltab->printnode = NULL;
printcompctlptr = NULL;
compctl_widgetptr = NULL;
makecompparamsptr = NULL;
return 0;
}

View file

@ -26,7 +26,7 @@
"capitalize-word", capitalizeword, 0
"clear-screen", clearscreen, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
"complete-word", completeword, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
"copy-prev-word", copyprevword, 0
"copy-prev-word", copyprevword, ZLE_KEEPSUFFIX
"copy-region-as-kill", copyregionaskill, ZLE_KEEPSUFFIX
"delete-char", deletechar, ZLE_KEEPSUFFIX
"delete-char-or-list", deletecharorlist, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP

View file

@ -46,7 +46,6 @@ struct widget {
union {
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 */
@ -56,20 +55,15 @@ struct widget {
};
#define WIDGET_INT (1<<0) /* widget is internally implemented */
#define WIDGET_COMP (1<<1) /* Special completion widget */
#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 */
#define WIDGET_NCOMP (1<<1) /* new style 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 ZLE_KEEPSUFFIX (1<<7) /* DON'T remove added suffix */
#define ZLE_NOTCOMMAND (1<<8) /* widget should not alter lastcmd */
#define ZLE_ISCOMP (1<<9) /* usable for new style completion */
/* thingies */
struct thingy {

View file

@ -45,10 +45,10 @@ int mark;
/**/
int c;
/* the binding for this key */
/* the bindings for the previous and for this key */
/**/
Thingy bindk;
Thingy lbindk, bindk;
/* insert mode/overwrite mode flag */
@ -554,6 +554,7 @@ zleread(char *lp, char *rp, int ha)
void
execzlefunc(Thingy func)
{
int r = 0;
Widget w;
if(func->flags & DISABLED) {
@ -565,14 +566,13 @@ execzlefunc(Thingy func)
showmsg(msg);
zsfree(msg);
feep();
} else if((w = func->widget)->flags &
(WIDGET_INT|WIDGET_COMP | WIDGET_NCOMP)) {
} else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
int wflags = w->flags;
if(!(wflags & ZLE_KEEPSUFFIX))
removesuffix();
if(!(wflags & ZLE_MENUCMP) ||
((wflags & (WIDGET_COMP|WIDGET_NCOMP)) && compwidget != w)) {
((wflags & 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.
@ -584,16 +584,14 @@ execzlefunc(Thingy func)
vilinerange = 1;
if(!(wflags & ZLE_LASTCOL))
lastcol = -1;
if (wflags & WIDGET_COMP) {
compwidget = w;
completespecial();
} else if (wflags & WIDGET_NCOMP) {
if (wflags & WIDGET_NCOMP) {
compwidget = w;
completecall();
} else
w->u.fn();
if (!(wflags & ZLE_NOTCOMMAND))
lastcmd = wflags;
r = 1;
} else {
List l = getshfunc(w->u.fnnam);
@ -610,14 +608,20 @@ execzlefunc(Thingy func)
int osc = sfcontext;
startparamscope();
makezleparams();
makezleparams(0);
sfcontext = SFC_WIDGET;
doshfunc(w->u.fnnam, l, NULL, 0, 1);
sfcontext = osc;
endparamscope();
lastcmd = 0;
r = 1;
}
}
if (r) {
unrefthingy(lbindk);
refthingy(func);
lbindk = func;
}
}
/* initialise command modifiers */
@ -877,9 +881,11 @@ setup_zle(Module m)
comp_strptr = comp_str;
getcpatptr = getcpat;
makecomplistcallptr = makecomplistcall;
makecomplistctlptr = makecomplistctl;
/* initialise the thingies */
init_thingies();
lbindk = NULL;
/* miscellaneous initialisations */
stackhist = stackcs = -1;
@ -920,6 +926,8 @@ finish_zle(Module m)
{
int i;
unrefthingy(lbindk);
cleanup_keymaps();
deletehashtable(thingytab);
@ -944,6 +952,7 @@ finish_zle(Module m)
comp_strptr = NULL;
getcpatptr = NULL;
makecomplistcallptr = NULL;
makecomplistctlptr = NULL;
return 0;
}

View file

@ -61,17 +61,22 @@ static struct zleparam {
zleunsetfn, NULL },
{ "RBUFFER", PM_SCALAR, FN(set_rbuffer), FN(get_rbuffer),
zleunsetfn, NULL },
{ "WIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_widget),
zleunsetfn, NULL },
{ "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget),
zleunsetfn, NULL },
{ NULL, 0, NULL, NULL, NULL, NULL }
};
/**/
void
makezleparams(void)
makezleparams(int ro)
{
struct zleparam *zp;
for(zp = zleparams; zp->name; zp++) {
Param pm = createparam(zp->name, zp->type | PM_SPECIAL);
Param pm = createparam(zp->name, (zp->type |PM_SPECIAL|PM_REMOVABLE|
(ro ? PM_READONLY : 0)));
if (!pm)
pm = (Param) paramtab->getnode(paramtab, zp->name);
DPUTS(!pm, "param not set in makezleparams");
@ -197,3 +202,17 @@ get_rbuffer(Param pm)
{
return metafy((char *)line + cs, ll - cs, META_HEAPDUP);
}
/**/
static char *
get_widget(Param pm)
{
return bindk->nam;
}
/**/
static char *
get_lwidget(Param pm)
{
return (lbindk ? lbindk->nam : "");
}

View file

@ -244,9 +244,7 @@ unbindwidget(Thingy t, int override)
static void
freewidget(Widget w)
{
if ((w->flags & WIDGET_COMP) && w->u.cc)
freecompctl(w->u.cc);
else if (w->flags & WIDGET_NCOMP) {
if (w->flags & WIDGET_NCOMP) {
zsfree(w->u.comp.wid);
zsfree(w->u.comp.func);
} else if(!(w->flags & WIDGET_INT))
@ -339,7 +337,7 @@ bin_zle(char *name, char **args, char *ops, int func)
{ 'D', bin_zle_del, 1, -1 },
{ 'A', bin_zle_link, 2, 2 },
{ 'N', bin_zle_new, 1, 2 },
{ 'C', bin_zle_compctl, 1, -1},
{ 'C', bin_zle_complete, 3, 3 },
{ 'c', bin_zle_complete, 3, 3 },
{ 0, bin_zle_call, 0, -1 },
};
@ -392,14 +390,11 @@ scanlistwidgets(HashNode hn, int list)
if(w->flags & WIDGET_INT)
return;
if(list) {
fputs((w->flags & WIDGET_COMP) ? "zle -C " : "zle -N ", stdout);
fputs("zle -N ", stdout);
if(t->nam[0] == '-')
fputs("-- ", stdout);
quotedzputs(t->nam, stdout);
if (w->flags & WIDGET_COMP) {
if (printcompctlptr && w->u.cc)
printcompctlptr(NULL, w->u.cc, PRINT_LIST, 0);
} else if (w->flags & WIDGET_NCOMP) {
if (w->flags & WIDGET_NCOMP) {
fputc(' ', stdout);
quotedzputs(w->u.comp.wid, stdout);
fputc(' ', stdout);
@ -410,11 +405,7 @@ scanlistwidgets(HashNode hn, int list)
}
} else {
nicezputs(t->nam, stdout);
if (w->flags & WIDGET_COMP) {
fputs(" -C", stdout);
if (printcompctlptr && w->u.cc)
printcompctlptr(NULL, w->u.cc, PRINT_TYPE, 0);
} else if (w->flags & WIDGET_NCOMP) {
if (w->flags & WIDGET_NCOMP) {
fputs(" -c ", stdout);
nicezputs(w->u.comp.wid, stdout);
fputc(' ', stdout);
@ -480,44 +471,6 @@ bin_zle_new(char *name, char **args, char *ops, char func)
return 1;
}
/**/
static int
bin_zle_compctl(char *name, char **args, char *ops, char func)
{
Compctl cc = NULL;
Widget w;
char *wname = args[0];
if (!compctl_widgetptr) {
zwarnnam(name, "compctl module is not loaded", NULL, 0);
return 1;
}
args++;
if (*args && !(cc = compctl_widgetptr(name, args)))
return 1;
w = zalloc(sizeof(*w));
w->flags = WIDGET_COMP|ZLE_MENUCMP|ZLE_KEEPSUFFIX;
w->first = NULL;
w->u.cc = cc;
if(bindwidget(w, rthingy(wname))) {
freewidget(w);
zerrnam(name, "widget name `%s' is protected", wname, 0);
return 1;
}
if (ops['m'])
w->flags |= ZLE_USEMENU;
else if (ops['M'])
w->flags |= ZLE_NOMENU;
if (ops['g'])
w->flags |= ZLE_USEGLOB;
else if (ops['G'])
w->flags |= ZLE_NOGLOB;
return 0;
}
/**/
static int
bin_zle_complete(char *name, char **args, char *ops, char func)

File diff suppressed because it is too large Load diff

View file

@ -50,7 +50,7 @@ static struct builtin builtins[] =
BUILTIN("cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL),
BUILTIN("chdir", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL),
BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL),
BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafilrtux", NULL),
BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafilrtux", NULL),
BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "v", NULL),
BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmr", NULL),
BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
@ -60,7 +60,7 @@ static struct builtin builtins[] =
BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmr", NULL),
BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRUZafilrtu", "x"),
BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRTUZafilrtu", "x"),
BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL),
BUILTIN("fc", BINF_FCOPTS, bin_fc, 0, -1, BIN_FC, "nlreIRWAdDfEim", NULL),
BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL),
@ -78,7 +78,7 @@ static struct builtin builtins[] =
BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL),
BUILTIN("kill", 0, bin_kill, 0, -1, 0, NULL, NULL),
BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL),
BUILTIN("local", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZailrtu", NULL),
BUILTIN("local", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZailrtu", NULL),
BUILTIN("log", 0, bin_log, 0, 0, 0, NULL, NULL),
BUILTIN("logout", 0, bin_break, 0, 1, BIN_LOGOUT, NULL, NULL),
@ -93,7 +93,7 @@ static struct builtin builtins[] =
BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
BUILTIN("r", BINF_R, bin_fc, 0, -1, BIN_FC, "nrl", NULL),
BUILTIN("read", 0, bin_read, 0, -1, 0, "rzu0123456789pkqecnAlE", NULL),
BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafiltux", "r"),
BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafiltux", "r"),
BUILTIN("rehash", 0, bin_hash, 0, 0, 0, "dfv", "r"),
BUILTIN("return", BINF_PSPECIAL, bin_break, 0, 1, BIN_RETURN, NULL, NULL),
BUILTIN("set", BINF_PSPECIAL, bin_set, 0, -1, 0, NULL, NULL),
@ -107,7 +107,7 @@ static struct builtin builtins[] =
BUILTIN("trap", BINF_PSPECIAL, bin_trap, 0, -1, 0, NULL, NULL),
BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsw", "v"),
BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafilrtuxm", NULL),
BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafilrtuxm", NULL),
BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "m", "a"),
BUILTIN("unfunction", 0, bin_unhash, 1, -1, 0, "m", "f"),
@ -1468,11 +1468,11 @@ getasg(char *s)
/* function to set a single parameter */
/**/
int
Param
typeset_single(char *cname, char *pname, Param pm, int func,
int on, int off, int roff, char *value)
int on, int off, int roff, char *value, Param altpm)
{
int usepm, tc;
int usepm, tc, keeplocal = 0;
/* use the existing pm? */
usepm = pm && !(pm->flags & PM_UNSET);
@ -1490,24 +1490,24 @@ typeset_single(char *cname, char *pname, Param pm, int func,
locallevel != pm->level && func != BIN_EXPORT)
usepm = 0;
/* attempting a type conversion? */
/* attempting a type conversion, or making a tied colonarray? */
if ((tc = usepm && (((off & pm->flags) | (on & ~pm->flags)) &
(PM_INTEGER|PM_HASHED|PM_ARRAY))))
(PM_INTEGER|PM_HASHED|PM_ARRAY|PM_TIED))))
usepm = 0;
if (tc && (pm->flags & PM_SPECIAL)) {
zerrnam(cname, "%s: can't change type of a special parameter",
pname, 0);
return 1;
return NULL;
}
if (usepm) {
if (!on && !roff && !value) {
paramtab->printnode((HashNode)pm, 0);
return 0;
return pm;
}
if ((pm->flags & PM_RESTRICTED && isset(RESTRICTED))) {
zerrnam(cname, "%s: restricted", pname, 0);
return 1;
return pm;
}
if (PM_TYPE(pm->flags) == PM_ARRAY && (on & PM_UNIQUE) &&
!(pm->flags & PM_READONLY & ~off))
@ -1530,9 +1530,9 @@ typeset_single(char *cname, char *pname, Param pm, int func,
setsparam(pname, ztrdup(value));
} else if (value) {
zwarnnam(cname, "can't assign new value for array %s", pname, 0);
return 1;
return NULL;
}
return 0;
return pm;
}
/*
@ -1542,10 +1542,15 @@ typeset_single(char *cname, char *pname, Param pm, int func,
* 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;
}
/* Maintain existing readonly/exported status... */
on |= ~off & (PM_READONLY|PM_EXPORTED) & pm->flags;
/* ...but turn off existing readonly so we can delete it */
pm->flags &= ~PM_READONLY;
/*
* If we're just changing the type, we should keep the
* variable at the current level of localness.
*/
keeplocal = pm->level;
/*
* Try to carry over a value, but not when changing from,
* to, or between non-scalar types.
@ -1563,17 +1568,33 @@ typeset_single(char *cname, char *pname, Param pm, int func,
pm = createparam(pname, on & ~PM_READONLY);
DPUTS(!pm, "BUG: parameter not created");
pm->ct = auxlen;
if (func != BIN_EXPORT)
if (altpm && PM_TYPE(pm->flags) == PM_SCALAR) {
/*
* It seems safer to set this here than in createparam(),
* to make sure we only ever use the colonarr functions
* when u.data is correctly set.
*/
pm->sets.cfn = colonarrsetfn;
pm->gets.cfn = colonarrgetfn;
pm->u.data = &altpm->u.arr;
}
if (keeplocal)
pm->level = keeplocal;
else 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;
/* the only safe thing to do here seems to be unset the param */
unsetparam_pm(pm, 0, 1);
return NULL;
}
return 0;
return pm;
}
/* declare, export, integer, local, readonly, typeset */
@ -1585,7 +1606,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
Param pm;
Asgment asg;
Comp com;
char *optstr = "aiALRZlurtxU";
char *optstr = "aiALRZlurtxUT";
int on = 0, off = 0, roff, bit = PM_ARRAY;
int i;
int returnval = 0, printflags = 0;
@ -1619,6 +1640,9 @@ bin_typeset(char *name, char **argv, char *ops, int func)
off |= PM_UPPER;
if (on & PM_HASHED)
off |= PM_ARRAY;
if (on & PM_TIED)
off |= PM_INTEGER | PM_ARRAY | PM_HASHED;
on &= ~off;
/* Given no arguments, list whatever the options specify. */
@ -1631,6 +1655,58 @@ bin_typeset(char *name, char **argv, char *ops, int func)
return 0;
}
if (on & PM_TIED) {
Param apm;
char *name1;
if (ops['m']) {
zwarnnam(name, "incompatible options for -T", NULL, 0);
return 1;
}
on &= ~off;
if (!argv[1] || argv[2]) {
zwarnnam(name, "-T requires names of scalar and array", NULL, 0);
return 1;
}
/*
* Create the tied array; this is normal except that
* it has the PM_TIED flag set. Do it first because
* we need the address.
*/
if (!(asg = getasg(argv[1])))
return 1;
name1 = ztrdup(asg->name);
if (!(apm=typeset_single(name, asg->name,
(Param)paramtab->getnode(paramtab,
asg->name),
func, on | PM_ARRAY, off, roff,
asg->value, NULL)))
return 1;
/*
* Create the tied colonarray. We make it as a normal scalar
* and fix up the oddities later.
*/
if (!(asg = getasg(argv[0])) ||
!(pm=typeset_single(name, asg->name,
(Param)paramtab->getnode(paramtab,
asg->name),
func, on, off, roff, asg->value, apm))) {
unsetparam_pm(apm, 1, 1);
return 1;
}
pm->ename = name1;
apm->ename = ztrdup(asg->name);
return 0;
}
if (off & PM_TIED) {
zerrnam(name, "use unset to remove tied variables", NULL, 0);
return 1;
}
/* With the -m option, treat arguments as glob patterns */
if (ops['m']) {
MUSTUSEHEAP("typeset -m");
@ -1664,8 +1740,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
}
for (pmnode = firstnode(pmlist); pmnode; incnode(pmnode)) {
pm = (Param) getdata(pmnode);
if (typeset_single(name, pm->nam, pm, func, on, off, roff,
asg->value))
if (!typeset_single(name, pm->nam, pm, func, on, off, roff,
asg->value, NULL))
returnval = 1;
}
}
@ -1680,9 +1756,9 @@ bin_typeset(char *name, char **argv, char *ops, int func)
returnval = 1;
continue;
}
if (typeset_single(name, asg->name,
(Param)paramtab->getnode(paramtab, asg->name),
func, on, off, roff, asg->value))
if (!typeset_single(name, asg->name,
(Param)paramtab->getnode(paramtab, asg->name),
func, on, off, roff, asg->value, NULL))
returnval = 1;
}
return returnval;

View file

@ -31,7 +31,42 @@
#include "glob.pro"
/* flag for CSHNULLGLOB */
typedef struct gmatch *Gmatch;
struct gmatch {
char *name;
long size;
long atime;
long mtime;
long ctime;
long links;
long _size;
long _atime;
long _mtime;
long _ctime;
long _links;
};
#define GS_NAME 1
#define GS_SIZE 2
#define GS_ATIME 4
#define GS_MTIME 8
#define GS_CTIME 16
#define GS_LINKS 32
#define GS_SHIFT 5
#define GS__SIZE (GS_SIZE << GS_SHIFT)
#define GS__ATIME (GS_ATIME << GS_SHIFT)
#define GS__MTIME (GS_MTIME << GS_SHIFT)
#define GS__CTIME (GS_CTIME << GS_SHIFT)
#define GS__LINKS (GS_LINKS << GS_SHIFT)
#define GS_DESC 2048
#define GS_NORMAL (GS_SIZE | GS_ATIME | GS_MTIME | GS_CTIME | GS_LINKS)
#define GS_LINKED (GS_NORMAL << GS_SHIFT)
/**/
int badcshglob;
@ -42,8 +77,8 @@ static int matchct; /* number of matches found */
static char *pathbuf; /* pathname buffer */
static int pathbufsz; /* size of pathbuf */
static int pathbufcwd; /* where did we chdir()'ed */
static char **matchbuf; /* array of matches */
static char **matchptr; /* &matchbuf[matchct] */
static Gmatch matchbuf; /* array of matches */
static Gmatch matchptr; /* &matchbuf[matchct] */
static char *colonmod; /* colon modifiers in qualifier list */
typedef struct stat *Statptr; /* This makes the Ultrix compiler happy. Go figure. */
@ -81,6 +116,7 @@ static struct qual *quals;
static int qualct, qualorct;
static int range, amc, units;
static int gf_nullglob, gf_markdirs, gf_noglobdots, gf_listtypes, gf_follow;
static int gf_sorts, gf_nsorts, gf_sortlist[11];
/* Prefix, suffix for doing zle trickery */
@ -213,6 +249,7 @@ insert(char *s, int checked)
if (!statted && statfullpath(s, &buf, 1))
return;
statted = 1;
qo = quals;
for (qn = qo; qn && qn->func;) {
range = qn->range;
@ -237,19 +274,44 @@ insert(char *s, int checked)
}
qn = qn->next;
}
} else if (!checked && statfullpath(s, NULL, 1))
return;
} else if (!checked) {
if (statfullpath(s, NULL, 1))
return;
statted = 1;
}
news = dyncat(pathbuf, news);
if (colonmod) {
/* Handle the remainder of the qualifer: e.g. (:r:s/foo/bar/). */
s = colonmod;
modify(&news, &s);
}
*matchptr++ = news;
if (!statted && (gf_sorts & GS_NORMAL)) {
statfullpath(s, &buf, 1);
statted = 1;
}
if (statted != 2 && (gf_sorts & GS_LINKED)) {
if (statted) {
if (!S_ISLNK(buf.st_mode) || statfullpath(s, &buf2, 0))
memcpy(&buf2, &buf, sizeof(buf));
} else if (statfullpath(s, &buf2, 0))
statfullpath(s, &buf2, 1);
}
matchptr->name = news;
matchptr->size = buf.st_size;
matchptr->atime = buf.st_atime;
matchptr->mtime = buf.st_mtime;
matchptr->ctime = buf.st_ctime;
matchptr->links = buf.st_nlink;
matchptr->_size = buf2.st_size;
matchptr->_atime = buf2.st_atime;
matchptr->_mtime = buf2.st_mtime;
matchptr->_ctime = buf2.st_ctime;
matchptr->_links = buf2.st_nlink;
matchptr++;
if (++matchct == matchsz) {
matchbuf = (char **)realloc((char *)matchbuf,
sizeof(char **) * (matchsz *= 2));
matchbuf = (Gmatch )realloc((char *)matchbuf,
sizeof(struct gmatch) * (matchsz *= 2));
matchptr = matchbuf + matchct;
}
@ -944,21 +1006,144 @@ qgetnum(char **s)
return v;
}
/* get octal number after qualifier */
/* get mode spec after qualifier */
/**/
static long
qgetoctnum(char **s)
qgetmodespec(char **s)
{
long v = 0;
long yes = 0, no = 0, val, mask, t;
char *p = *s, c, how, end;
if (!idigit(**s)) {
zerr("octal number expected", NULL, 0);
return 0;
if ((c = *p) == '=' || c == Equals || c == '+' || c == '-' ||
c == '?' || c == Quest || (c >= '0' && c <= '7')) {
end = 0;
c = 0;
} else {
end = (c == '<' ? '>' :
(c == '[' ? ']' :
(c == '{' ? '}' :
(c == Inang ? Outang :
(c == Inbrack ? Outbrack :
(c == Inbrace ? Outbrace : c))))));
p++;
}
while (**s >= '0' && **s <= '7')
v = v * 010 + *(*s)++ - '0';
return v;
do {
mask = 0;
while (((c = *p) == 'u' || c == 'g' || c == 'o' || c == 'a') && end) {
switch (c) {
case 'o': mask |= 01007; break;
case 'g': mask |= 02070; break;
case 'u': mask |= 04700; break;
case 'a': mask |= 07777; break;
}
p++;
}
how = ((c == '+' || c == '-') ? c : '=');
if (c == '+' || c == '-' || c == '=' || c == Equals)
p++;
val = 0;
if (mask) {
while ((c = *p++) != ',' && c != end) {
switch (c) {
case 'x': val |= 00111; break;
case 'w': val |= 00222; break;
case 'r': val |= 00444; break;
case 's': val |= 06000; break;
case 't': val |= 01000; break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
t = ((long) c - '0');
val |= t | (t << 3) | (t << 6);
break;
default:
zerr("invalid mode specification", NULL, 0);
return 0;
}
}
if (how == '=' || how == '+') {
yes |= val & mask;
val = ~val;
}
if (how == '=' || how == '-')
no |= val & mask;
} else {
t = 07777;
while ((c = *p) == '?' || c == Quest ||
(c >= '0' && c <= '7')) {
if (c == '?' || c == Quest) {
t = (t << 3) | 7;
val <<= 3;
} else {
t <<= 3;
val = (val << 3) | ((long) c - '0');
}
p++;
}
if (end && c != end && c != ',') {
zerr("invalid mode specification", NULL, 0);
return 0;
}
if (how == '=') {
yes = (yes & ~t) | val;
no = (no & ~t) | (~val & ~t);
} else if (how == '+')
yes |= val;
else
no |= val;
}
} while (end && c != end);
*s = p;
return ((yes & 07777) | ((no & 07777) << 12));
}
static int
gmatchcmp(Gmatch a, Gmatch b)
{
int i, *s;
long r;
for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
switch (*s & ~GS_DESC) {
case GS_NAME:
r = notstrcmp(&a->name, &b->name);
break;
case GS_SIZE:
r = b->size - a->size;
break;
case GS_ATIME:
r = a->atime - b->atime;
break;
case GS_MTIME:
r = a->mtime - b->mtime;
break;
case GS_CTIME:
r = a->ctime - b->ctime;
break;
case GS_LINKS:
r = b->links - a->links;
break;
case GS__SIZE:
r = b->_size - a->_size;
break;
case GS__ATIME:
r = a->_atime - b->_atime;
break;
case GS__MTIME:
r = a->_mtime - b->_mtime;
break;
case GS__CTIME:
r = a->_ctime - b->_ctime;
break;
case GS__LINKS:
r = b->_links - a->_links;
break;
}
if (r)
return (int) ((*s & GS_DESC) ? -r : r);
}
return 0;
}
/* Main entry point to the globbing code for filename globbing. *
@ -976,7 +1161,8 @@ glob(LinkList list, LinkNode np)
Complist q; /* pattern after parsing */
char *ostr = (char *)getdata(np); /* the pattern before the parser */
/* chops it up */
int first = 0, last = -1; /* index of first/last match to */
/* return */
MUSTUSEHEAP("glob");
if (unset(GLOBOPT) || !haswilds(ostr)) {
untokenize(ostr);
@ -994,6 +1180,7 @@ glob(LinkList list, LinkNode np)
gf_markdirs = isset(MARKDIRS);
gf_listtypes = gf_follow = 0;
gf_noglobdots = unset(GLOBDOTS);
gf_sorts = gf_nsorts = 0;
/* Check for qualifiers */
if (isset(BAREGLOBQUAL) && str[sl - 1] == Outpar) {
@ -1246,10 +1433,9 @@ glob(LinkList list, LinkNode np)
}
break;
case 'o':
/* Match octal mode of file exactly. *
* Currently undocumented. */
func = qualeqflags;
data = qgetoctnum(&s);
/* Match modes with chmod-spec. */
func = qualmodeflags;
data = qgetmodespec(&s);
break;
case 'M':
/* Mark directories with a / */
@ -1315,6 +1501,51 @@ glob(LinkList list, LinkNode np)
data = qgetnum(&s);
break;
case 'O':
{
int t;
switch (*s) {
case 'n': t = GS_NAME; break;
case 'L': t = GS_SIZE; break;
case 'l': t = GS_LINKS; break;
case 'a': t = GS_ATIME; break;
case 'm': t = GS_MTIME; break;
case 'c': t = GS_CTIME; break;
default:
zerr("unknown sort specifier", NULL, 0);
return;
}
if ((sense & 2) && t != GS_NAME)
t <<= GS_SHIFT;
if (gf_sorts & t) {
zerr("doubled sort specifier", NULL, 0);
return;
}
gf_sorts |= t;
gf_sortlist[gf_nsorts++] = t |
((sense & 1) ? GS_DESC : 0);
s++;
break;
}
case '[':
case Inbrack:
{
char *os = --s;
struct value v;
v.isarr = SCANPM_WANTVALS;
v.pm = NULL;
v.b = -1;
v.inv = 0;
if (getindex(&s, &v) || s == os) {
zerr("invalid subscript", NULL, 0);
return;
}
first = v.a;
last = v.b;
break;
}
default:
zerr("unknown file attribute", NULL, 0);
return;
@ -1353,10 +1584,14 @@ glob(LinkList list, LinkNode np)
zerr("bad pattern: %s", ostr, 0);
return;
}
if (!gf_nsorts) {
gf_sortlist[0] = gf_sorts = GS_NAME;
gf_nsorts = 1;
}
/* Initialise receptacle for matched files, *
* expanded by insert() where necessary. */
matchptr = matchbuf = (char **)zalloc((matchsz = 16) * sizeof(char *));
matchptr = matchbuf = (Gmatch)zalloc((matchsz = 16) *
sizeof(struct gmatch));
matchct = 0;
/* The actual processing takes place here: matches go into *
@ -1375,18 +1610,32 @@ glob(LinkList list, LinkNode np)
return;
} else {
/* treat as an ordinary string */
untokenize(*matchptr++ = dupstring(ostr));
untokenize(matchptr->name = dupstring(ostr));
matchptr++;
matchct = 1;
}
}
/* Sort arguments in to lexical (and possibly numeric) order. *
* This is reversed to facilitate insertion into the list. */
qsort((void *) & matchbuf[0], matchct, sizeof(char *),
(int (*) _((const void *, const void *)))notstrcmp);
qsort((void *) & matchbuf[0], matchct, sizeof(struct gmatch),
(int (*) _((const void *, const void *)))gmatchcmp);
matchptr = matchbuf;
while (matchct--) /* insert matches in the arg list */
insertlinknode(list, node, *matchptr++);
if (first < 0)
first += matchct;
if (last < 0)
last += matchct;
if (first < 0)
first = 0;
if (last >= matchct)
last = matchct - 1;
if (first <= last) {
matchptr = matchbuf + matchct - 1 - last;
last -= first;
while (last-- >= 0) { /* insert matches in the arg list */
insertlinknode(list, node, matchptr->name);
matchptr++;
}
}
free(matchbuf);
}
@ -2918,13 +3167,15 @@ qualflags(struct stat *buf, long mod)
return mode_to_octal(buf->st_mode) & mod;
}
/* mode matches number supplied exactly */
/* mode matches specification */
/**/
static int
qualeqflags(struct stat *buf, long mod)
qualmodeflags(struct stat *buf, long mod)
{
return mode_to_octal(buf->st_mode) == mod;
long v = mode_to_octal(buf->st_mode), y = mod & 07777, n = mod >> 12;
return ((v & y) == y && !(v & n));
}
/* regular executable file? */

View file

@ -300,18 +300,61 @@ init_io(void)
/* Make sure the tty is opened read/write. */
if (isatty(0)) {
#ifdef TIOCNXCL
/*
* See if the terminal claims to be busy. If so, and fd 0
* is a terminal, try and set non-exclusive use for that.
* This is something to do with Solaris over-cleverness.
*/
int tmpfd;
if ((tmpfd = open("/dev/tty", O_RDWR | O_NOCTTY)) < 0) {
if (errno == EBUSY)
ioctl(0, TIOCNXCL, 0);
} else
close(tmpfd);
#endif
zsfree(ttystrname);
if ((ttystrname = ztrdup(ttyname(0))))
SHTTY = movefd(open(ttystrname, O_RDWR | O_NOCTTY));
/*
* xterm, rxvt and probably all terminal emulators except
* dtterm on Solaris 2.6 & 7 have a bug. Applications are
* unable to open /dev/tty or /dev/pts/<terminal number here>
* because something in Sun's STREAMS modules doesn't like
* it. The open() call fails with EBUSY which is not even
* listed as a possibility in the open(2) man page. So we'll
* try to outsmart The Company. -- <dave@srce.hr>
*
* Presumably there's no harm trying this on any OS, given that
* isatty(0) worked but opening the tty didn't. Possibly we won't
* get the tty read/write, but it's the best we can do -- pws
*
* Try both stdin and stdout before trying /dev/tty. -- Bart
*/
#if defined(HAVE_FCNTL_H) && defined(F_GETFL)
#define rdwrtty(fd) ((fcntl(fd, F_GETFL) & O_RDWR) == O_RDWR)
#else
#define rdwrtty(fd) 1
#endif
if (SHTTY == -1 && rdwrtty(0)) {
SHTTY = movefd(dup(0));
}
}
if (SHTTY == -1 && isatty(1) && rdwrtty(1) &&
(SHTTY = movefd(dup(1))) != -1) {
zsfree(ttystrname);
ttystrname = ztrdup(ttyname(1));
}
if (SHTTY == -1 &&
(SHTTY = movefd(open("/dev/tty", O_RDWR | O_NOCTTY))) != -1) {
zsfree(ttystrname);
ttystrname = ztrdup("/dev/tty");
ttystrname = ztrdup(ttyname(SHTTY));
}
if (SHTTY == -1) {
zsfree(ttystrname);
ttystrname = ztrdup("");
} else if (!ttystrname) {
ttystrname = ztrdup("/dev/tty");
}
/* We will only use zle if shell is interactive, *

View file

@ -109,7 +109,8 @@ int parend;
/* text of puctuation tokens */
static char *tokstrings[WHILE + 1] = {
/**/
char *tokstrings[WHILE + 1] = {
NULL, /* NULLTOK 0 */
";", /* SEPER */
"\\n", /* NEWLIN */
@ -120,7 +121,7 @@ static char *tokstrings[WHILE + 1] = {
")", /* OUTPAR */
"||", /* DBAR */
"&&", /* DAMPER */
")", /* OUTANG 10 */
">", /* OUTANG 10 */
">|", /* OUTANGBANG */
">>", /* DOUTANG */
">>|", /* DOUTANGBANG */

View file

@ -679,7 +679,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
Comp c;
/* first parse any subscription flags */
if (*s == '(' || *s == Inpar) {
if (v->pm && (*s == '(' || *s == Inpar)) {
int escapes = 0;
int waste;
for (s++; *s != ')' && *s != Outpar && s != *str; s++) {
@ -765,7 +765,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
} else if (rev) {
v->isarr |= SCANPM_WANTVALS;
}
if (!down && PM_TYPE(v->pm->flags) == PM_HASHED)
if (!down && v->pm && PM_TYPE(v->pm->flags) == PM_HASHED)
v->isarr &= ~SCANPM_MATCHMANY;
*inv = ind;
}
@ -785,7 +785,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
singsub(&s);
if (!rev) {
if (PM_TYPE(v->pm->flags) == PM_HASHED) {
if (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED) {
HashTable ht = v->pm->gets.hfn(v->pm);
if (!ht) {
ht = newparamtable(17, v->pm->nam);
@ -1371,7 +1371,7 @@ setarrvalue(Value v, char **val)
freearray(val);
return;
}
if (PM_TYPE(v->pm->flags) & ~(PM_ARRAY|PM_HASHED)) {
if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED))) {
freearray(val);
zerr("attempt to assign array value to non-array", NULL, 0);
return;
@ -1501,7 +1501,7 @@ setsparam(char *s, char *val)
if (!(v = getvalue(&s, 1)))
createparam(t, PM_SCALAR);
else if (PM_TYPE(v->pm->flags) == PM_ARRAY &&
!(v->pm->flags & PM_SPECIAL) && unset(KSHARRAYS)) {
!(v->pm->flags & (PM_SPECIAL|PM_TIED)) && unset(KSHARRAYS)) {
unsetparam(t);
createparam(t, PM_SCALAR);
v = NULL;
@ -1545,7 +1545,7 @@ setaparam(char *s, char **val)
if (!(v = getvalue(&s, 1)))
createparam(t, PM_ARRAY);
else if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
!(v->pm->flags & PM_SPECIAL)) {
!(v->pm->flags & (PM_SPECIAL|PM_TIED))) {
int uniq = v->pm->flags & PM_UNIQUE;
unsetparam(t);
createparam(t, PM_ARRAY | uniq);
@ -1662,26 +1662,36 @@ unsetparam_pm(Param pm, int altflag, int exp)
unsetparam_pm(altpm, 1, exp);
}
/* If this was a local variable, we need to keep the old *
* struct so that it is resurrected at the right level. *
* This is partly because when an array/scalar value is set *
* and the parameter used to be the other sort, unsetparam() *
* is called. Beyond that, there is an ambiguity: should *
* foo() { local bar; unset bar; } make the global bar *
* available or not? The following makes the answer "no". */
if ((locallevel && locallevel >= pm->level) || (pm->flags & PM_SPECIAL))
/*
* If this was a local variable, we need to keep the old
* struct so that it is resurrected at the right level.
* This is partly because when an array/scalar value is set
* and the parameter used to be the other sort, unsetparam()
* is called. Beyond that, there is an ambiguity: should
* foo() { local bar; unset bar; } make the global bar
* available or not? The following makes the answer "no".
*
* Some specials, such as those used in zle, still need removing
* from the parameter table; they have the PM_REMOVABLE flag.
*/
if ((locallevel && locallevel >= pm->level) ||
(pm->flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL)
return;
paramtab->removenode(paramtab, pm->nam); /* remove parameter node from table */
/* remove parameter node from table */
paramtab->removenode(paramtab, pm->nam);
if (pm->old) {
oldpm = pm->old;
paramtab->addnode(paramtab, oldpm->nam, oldpm);
if ((PM_TYPE(oldpm->flags) == PM_SCALAR) && oldpm->sets.cfn == strsetfn)
if ((PM_TYPE(oldpm->flags) == PM_SCALAR) &&
oldpm->sets.cfn == strsetfn)
adduserdir(oldpm->nam, oldpm->u.str, 0, 0);
}
paramtab->freenode((HashNode) pm); /* free parameter node */
/* Even removable specials shouldn't be deleted. */
if (!(pm->flags & PM_SPECIAL))
paramtab->freenode((HashNode) pm); /* free parameter node */
}
/* Standard function to unset a parameter. This is mostly delegated to *
@ -1759,6 +1769,9 @@ arrsetfn(Param pm, char **x)
if (pm->flags & PM_UNIQUE)
uniqarray(x);
pm->u.arr = x;
/* Arrays tied to colon-arrays may need to fix the environment */
if (pm->ename && x)
arrfixenv(pm->ename, x);
}
/* Function to get value of an association parameter */
@ -1950,7 +1963,8 @@ arrvarsetfn(Param pm, char **x)
char *
colonarrgetfn(Param pm)
{
return zjoin(*(char ***)pm->u.data, ':');
char ***dptr = (char ***)pm->u.data;
return *dptr ? zjoin(*dptr, ':') : "";
}
/**/
@ -1959,8 +1973,15 @@ colonarrsetfn(Param pm, char *x)
{
char ***dptr = (char ***)pm->u.data;
freearray(*dptr);
*dptr = x ? colonsplit(x, pm->flags & PM_UNIQUE) : mkarray(NULL);
/*
* If this is tied to a parameter (rather than internal) array,
* the array itself may be NULL. Otherwise, we have to make
* sure it doesn't ever get null.
*/
if (*dptr)
freearray(*dptr);
*dptr = x ? colonsplit(x, pm->flags & PM_UNIQUE) :
(pm->flags & PM_TIED) ? NULL : mkarray(NULL);
if (pm->ename)
arrfixenv(pm->nam, *dptr);
zsfree(x);
@ -2399,7 +2420,7 @@ arrfixenv(char *s, char **t)
MUSTUSEHEAP("arrfixenv");
if (t == path)
cmdnamtab->emptytable(cmdnamtab);
u = zjoin(t, ':');
u = t ? zjoin(t, ':') : "";
len_s = strlen(s);
pm = (Param) paramtab->getnode(paramtab, s);
for (ep = environ; *ep; ep++)
@ -2602,6 +2623,9 @@ freeparamnode(HashNode hn)
if (delunset)
pm->unsetfn(pm, 1);
zsfree(pm->nam);
/* If this variable was tied by the user, ename was ztrdup'd */
if (pm->flags & PM_TIED)
zsfree(pm->ename);
zfree(pm, sizeof(struct param));
}

View file

@ -702,6 +702,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
int whichlen = 0;
int chkset = 0;
int vunset = 0;
int wantt = 0;
int spbreak = isset(SHWORDSPLIT) && !ssub && !qt;
char *val = NULL, **aval = NULL;
unsigned int fwidth = 0;
@ -902,6 +903,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
hvals = SCANPM_WANTVALS;
break;
case 't':
wantt = 1;
break;
default:
flagerr:
zerr("error in flags", NULL, 0);
@ -978,9 +983,47 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
*s = sav;
v = (Value) NULL;
} else {
if (!(v = fetchvalue(&s, (unset(KSHARRAYS) || inbrace) ? 1 : -1,
if (!(v = fetchvalue(&s, (wantt ? -1 :
((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
hkeys|hvals)))
vunset = 1;
if (wantt) {
if (v) {
int f = v->pm->flags;
switch (PM_TYPE(f)) {
case PM_SCALAR: val = "scalar"; break;
case PM_ARRAY: val = "array"; break;
case PM_INTEGER: val = "integer"; break;
case PM_HASHED: val = "association"; break;
}
val = dupstring(val);
if (f & PM_LEFT)
val = dyncat(val, "-left");
if (f & PM_RIGHT_B)
val = dyncat(val, "-right_blanks");
if (f & PM_RIGHT_Z)
val = dyncat(val, "-right_zeros");
if (f & PM_LOWER)
val = dyncat(val, "-lower");
if (f & PM_UPPER)
val = dyncat(val, "-upper");
if (f & PM_READONLY)
val = dyncat(val, "-readonly");
if (f & PM_TAGGED)
val = dyncat(val, "-tag");
if (f & PM_EXPORTED)
val = dyncat(val, "-export");
if (f & PM_UNIQUE)
val = dyncat(val, "-unique");
vunset = 0;
} else
val = dupstring("");
v = NULL;
isarr = 0;
}
}
while (v || ((inbrace || (unset(KSHARRAYS) && vunset)) && isbrack(*s))) {
if (!v) {

View file

@ -214,6 +214,7 @@ tgoto
tok
tokenize
tokstr
tokstrings
tputs
trashzleptr
tricat

View file

@ -780,6 +780,7 @@ struct shfunc {
#define SFC_HOOK 2 /* one of the special functions */
#define SFC_WIDGET 3 /* user defined widget */
#define SFC_COMPLETE 4 /* called from completion code */
#define SFC_CWIDGET 5 /* new style completion widget */
/* node in list of function call wrappers */
@ -916,10 +917,12 @@ struct param {
#define PM_TAGGED (1<<9) /* tagged */
#define PM_EXPORTED (1<<10) /* exported */
#define PM_UNIQUE (1<<11) /* remove duplicates */
#define PM_SPECIAL (1<<12) /* special builtin parameter */
#define PM_DONTIMPORT (1<<13) /* do not import this variable */
#define PM_RESTRICTED (1<<14) /* cannot be changed in restricted mode */
#define PM_UNSET (1<<15) /* has null value */
#define PM_TIED (1<<12) /* array tied to colon-path or v.v. */
#define PM_SPECIAL (1<<13) /* special builtin parameter */
#define PM_DONTIMPORT (1<<14) /* do not import this variable */
#define PM_RESTRICTED (1<<15) /* cannot be changed in restricted mode */
#define PM_UNSET (1<<16) /* has null value */
#define PM_REMOVABLE (1<<17) /* special can be removed from paramtab */
/* Flags for extracting elements of arrays and associative arrays */
#define SCANPM_WANTVALS (1<<0)

View file

@ -1008,9 +1008,24 @@ char *argv[];
aix*) DLLDFLAGS="${DLLDFLAGS=-G -bexpall -lc}" ;;
solaris*|sysv4*|esix*) DLLDFLAGS="${DLLDFLAGS=-G}" ;;
esac
case "$host_os" in
hpux*) EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-E}" ;;
linux*) EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-rdynamic}" ;;
case "$host" in
*-hpux*) EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-E}" ;;
*-linux*) EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-rdynamic}" ;;
mips-sni-sysv4)
#
# unfortunately, we have different compilers
# that need different flags
#
sni_cc_version=`$CC -V 2>&1 | head -1`
case "$sni_cc_version" in
CDS* )
EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-Blargedynsym}"
;;
* )
EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-LD-Blargedynsym}"
;;
esac
;;
esac
AC_CACHE_CHECK(if your dlsym() needs a leading underscore,
zsh_cv_func_dlsym_needs_underscore,

View file

@ -1,5 +1,5 @@
This version of zsh is based on 3.1.5 and includes the following
patches. (The version number built into the shell has not been changed.)
patches.
Old stuff:
@ -111,7 +111,7 @@ My special parameter unset fix, 4662
Third edition
I've taken the plunge and changed $ZSH_VERSION, the current one is now
3.1.5.pws-1 . It seemed rational to have something incremental at the
3.1.5.pws-3 . It seemed rational to have something incremental at the
end for testing, so I abandoned using the date.
4482 (cdmatch2)and 4641 (${assoc[0]}) now applied; 4641 was supposed
@ -261,8 +261,70 @@ 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.
4946, 4949, 4950, 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.
pws-6
Sven: fix for completion after redirection, 4957
Bart: add-on, 4965
Andrej: configure patch for Reliant UNIX et al., 5021 (as resubmitted)
Sven: compctl list with a single string, 4974
Sven: compctl -M matches with *'s, 4975, 5007
Sven: compadd and new-completion-examples, 4976
Sven: funky new glob modifiers: change sort order, select
item from list, 4979; make time order work like ls -t, 4987
Sven: fix completion whitespace for copy-previous-word, 4981
Sven: fix for new-style completion after redirection, 4986, 4988
New mirror site ftp://ftp.win.ne.jp/pub/shell/zsh/ in META-FAQ (not
posted)
Andrej: when installing info files, insert zsh.info into dir, 5016
Sven: ${(t)param} flag, 5022, 5045; no unset behaviour, 5078
Phil: zless, 5032, simplified by Bart, 5037, also added a `setopt
localoptions' after spending an hour wondering why nothing worked any
more.
Me: `make install' does not do `make install.info', 5047
Sven: compcall tries old-style completion from new-style function,
compctl -K ' func' handles newstyle completion, 5059; avoid recursion,
5065; my dynamic fix-up, 5085
Sven: inserting completion inside brace expansion, 5060
Sven: extra completion context, 5092
Me: typeset -T MYPATH mypath, 5094, plus fix for MYPATH=(foo),
mypath=foo (and also existing PATH=(foo) bug), 5120
Sven: doc fix for glob qualifiers, 5102
Drazen Kacar, modified by me: workaround for terminal bug on Solaris,
5103; modified by Bart, 5113
Sven: zle and widget information via variables in new completion
functions, 5104
Me: remove old zle -C, zle -C now does new completion, 5105
Sven: glob qualifier o for modes, 5107
Me: fix for unsetting special zle variables, 5111
Drazen Kacar, modified by me: unlock terminal device on Solaris, 5118
(5117 was wrong)