From d6d4a3abfc84f0940e663cd69537789a039a7056 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Mon, 19 Jul 1999 14:26:14 +0000 Subject: zsh-3.1.6-test-2 --- ChangeLog | 141 +++++++++++++++++++++++++++ Completion/.cvsignore | 1 + Completion/.distfiles | 2 +- Completion/Base/_brace_parameter | 2 +- Completion/Core/_path_files | 38 +++++--- Completion/User/.distfiles | 6 +- Completion/User/_gdb | 50 ++++++++++ Completion/User/_hosts | 2 +- Completion/User/_make | 2 +- Completion/User/_rlogin | 2 +- Completion/User/_sh | 8 ++ Completion/User/_su | 22 +++++ Completion/User/_x_options | 5 +- Config/version.mk | 4 +- Doc/.distfiles | 10 +- Doc/Zsh/compsys.yo | 26 +++-- Doc/Zsh/compwid.yo | 18 ++-- Doc/Zsh/expn.yo | 6 +- Doc/Zsh/mod_complist.yo | 13 ++- Doc/Zsh/options.yo | 29 +++++- Doc/Zsh/params.yo | 5 +- Doc/Zsh/zle.yo | 9 +- Etc/MACHINES | 13 ++- Etc/NEWS | 1 + Functions/.cvsignore | 1 + Functions/.distfiles | 2 +- Functions/Zftp/zfgoto | 5 +- Functions/Zftp/zfinit | 2 +- Functions/Zle/incremental-complete-word | 91 +++++++++++++----- INSTALL | 9 +- Misc/job-control-tests | 45 +++++++++ Src/Modules/zftp.c | 6 +- Src/Zle/comp.h | 26 ++--- Src/Zle/comp1.c | 1 + Src/Zle/comp1.export | 1 + Src/Zle/compctl.c | 1 + Src/Zle/complist.c | 42 +++++---- Src/Zle/zle.export | 1 + Src/Zle/zle_params.c | 25 +---- Src/Zle/zle_refresh.c | 8 +- Src/Zle/zle_tricky.c | 162 +++++++++++++++++++++++--------- Src/builtin.c | 114 ++++++++++++++-------- Src/exec.c | 17 +++- Src/glob.c | 10 +- Src/lex.c | 1 + Src/options.c | 1 + Src/parse.c | 26 +++-- Src/utils.c | 99 +++++++++---------- Src/zsh.h | 1 + configure.in | 6 +- 50 files changed, 822 insertions(+), 296 deletions(-) create mode 100644 Completion/.cvsignore create mode 100644 Completion/User/_gdb create mode 100644 Completion/User/_sh create mode 100644 Completion/User/_su create mode 100644 Functions/.cvsignore diff --git a/ChangeLog b/ChangeLog index 963e4ec89..feea8c23f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,146 @@ +1999-07-19 Peter Stephenson + + * pws: version 3.1.6-test-2 + + * pws: 7192: Src/glob.c: bug with null in pattern if at end of + test string (matched as if a real character). + +1999-07-18 Peter Stephenson + + * pws: 7185: Src/glob.c: don't use strcoll() for character + ranges [...] because it can have side effects. + + * pws: 7184: Src/lex.c: histactive didn't get get zeroed before + non-interactive history use, hence interactive lines with + remhist() were junked more than once. + + * Wayne: 7181: Doc/Zsh/options.y, Doc/Zsh/params.yo: history docs. + + * Wayne: 7180: Src/Zle/complist.c, Src/utils.c: warnings. + +1999-07-16 Peter Stephenson + + * pws: 7172: Doc/Zsh/options.yo, Src/builtin.c, Src/exec.c, + Src/options.c, Src/utils.c, Src/zsh.h: minor bugs with + 7164 fixed; CHASE_DOTS resolves ..'s to physical path; + CHASE_LINKS doesn't do logical path rationalization; + xsymlink() and xsymlinks() simplified and option-dependence + removed. + + * Sven: 7171: Src/builtin.c: alternate form of Digital/gcc + bug workaround. + +1999-07-15 Peter Stephenson + + * pws: 7164: Src/builtin.c, Src/exec.c: AUTOCD now allows + paths with symlinks (as real cd always did); simplify code + for testing for existing directory on foo/.. before removing + foo/..; as a side effect, relative cd's from directory which + has been deleted don't work. + + * Sven: 7161: Src/Zle/comp.h, Src/Zle/complist.c, + Src/Zle/zle_tricky.c, Completion/Base/_brace_parameter: + be more careful with quote-prefix/suffix and path-prefix/suffix + especially with accept-and-menu-complete. + + * pws: 7155: Functions/Zftp/zfgoto, Functions/Zftp/zfinit: + zfgoto can cd without needing to re-login; zfinit uses + zmodload -e to check for zftp. + + * Sven: 7154: Src/Zle/complist.c, Src/Zle/zle_refresh.c, + Src/Zle/zle_tricky.c, Doc/Zsh/mod_complist.yo: don't + list too many times on ambiguous completion; don't do + menu-selection if no alwayslastprompt behaviour. + +1999-07-14 Peter Stephenson + + * pws: 7148: INSTALL: User subdirectory + + * Thomas Köhler: 7146: Completion/User/_make: didn't work. + + * pws: 7145: Completion/User/_sh: use compset -q for completing + after -c option + + * Sven: 7143: Src/Zle/complist.c, Src/Zle/zle_tricky.c: + listing got confused with only hidden matches. + + * Sven: 7141: Completion/Core/_path_files: if there are + no completions in a valid directory when we have a path ending + in /, use the directory as a completion, to avoid + correction/approximation of the existing directory. + + * pws: 7139: Src/builtin.c: not particularly pleasant fix + to problem that `cd nonexistent/..' silently did nothing, while + making `cd ..' work even if current directory has gone. + + * Sven: 7138: Completion/User/_hosts, Completion/User/_x_options: + _hosts passes arguments as options to compadd. + + * Oliver: 7136: Completion/User/_rlogin, + Completion/User/_x_options: use _hosts. + + * Sven: 7135: Src/Zle/zle_tricky.c, Completion/Core/_path_files: + change quoting of files again. + + * Sven: 7133: Doc/Zsh/expn.yo, Doc/Zsh/mod_complist.yo: + ZLS_COLOURS not required for complist to work. + + * pws: 7127: configure.in: help now shows --disable-dynamic + and --disable-lfs. + + * Sven: 7126: Src/Zle/comp.h, Src/Zle/comp1.c, Src/Zle/compctl.c, + Src/Zle/zle_tricky.c, Doc/Zsh/compwid.yo, + Functions/Zle/incremental-complete-word: compstate key + normal_nmatches; more i-c-w prompt escapes + + * Sven: 7123: Src/Zle/zle_tricky.c: clear list on expansion + failure. + +1999-07-13 Peter Stephenson + + * pws: 7119: Src/Zle/zle_tricky.c: status from expansion + functions. + + * Sven: 7116: Doc/Zsh/compwid.yo, Doc/Zsh/expn.yo: minor + changes. + + * pws: 7114: Src/parse.c, Src/utils.c: line numbers again: + flushing line in a script made lineno appear one too large; + introduce zwarn() function. + + * Sven/pws: 7112: Src/Zle/zle_params.c, Doc/Zsh/zle.yo: change + array keys to scalar KEYS, works more like read -k; + documentation. + + * Sven: 7110: Src/Modules/zftp.c, Doc/Zsh/compsys.yo, + Etc/MACHINES: signed char warnings in zftp; document + _long_options options; Digital UNIX problem. + + * Sven: 2432: Src/builtin.c: workaround Digital UNIX 4.0 + + gcc 2.8.1 bug. + + * Sven: zsh-users/2430: Etc/NEWS: mention chmod-like mode glob + qualifier. + + * Sven: 7108: Misc/job-control-tests: more tests + + * Bart: 7107: configure.in: too many x's in lfs handling. + + * Sven: 7106: Functions/Zle/incremental-complete-word: prompting + changes. + + * pws: unposted: update .distfiles and .cvsignore: _sh, _su + zshcompsys.yo, zshcompwid.yo, zshzftp.yo, zshcompsys.1, + zshcompwid.1, zshzftp.1 were missing from the distribution. + + * Sven: 7105: Src/Zle/Zle_tricky.c: restore the command line + in more places. + 1999-07-12 Peter Stephenson + * Sven: 7103: Src/Zle/zle_tricky.c, Doc/Zsh/compwid.yo: update + CURRENT with compset -q; modify test for quoted delimiters. + * pws: version 3.1.6-test-1 * Sven: 7099: Completion/Core/_main_complete, Doc/Zsh/compsys.yo: diff --git a/Completion/.cvsignore b/Completion/.cvsignore new file mode 100644 index 000000000..f3c7a7c5d --- /dev/null +++ b/Completion/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/Completion/.distfiles b/Completion/.distfiles index e85e122ef..f1e1c87b3 100644 --- a/Completion/.distfiles +++ b/Completion/.distfiles @@ -1,3 +1,3 @@ DISTFILES_SRC=' - .distfiles README Makefile.in + .cvsignore .distfiles README Makefile.in ' diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter index 5993aecba..020dc81e9 100644 --- a/Completion/Base/_brace_parameter +++ b/Completion/Base/_brace_parameter @@ -18,4 +18,4 @@ q=${(M)lp%%\"#} [[ n -gt 0 ]] && suf='' -_parameters -s "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/' +_parameters -Qs "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/' diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files index e65f814e1..019e3abcf 100644 --- a/Completion/Core/_path_files +++ b/Completion/Core/_path_files @@ -244,7 +244,7 @@ for prepath in "$prepaths[@]"; do if [[ "$tmp2[1]" = */* ]]; then tmp2=( "${(@)tmp2#${prepath}${realpath}}" ) if [[ "$tmp2[1]" = */* ]]; then - exppaths=( "$exppaths[@]" ${^tmp2:h}/${tpre}${tsuf} ) + exppaths=( "$exppaths[@]" ${^tmp2:h:q}/${tpre}${tsuf} ) else exppaths=( "$exppaths[@]" ${tpre}${tsuf} ) fi @@ -252,6 +252,18 @@ for prepath in "$prepaths[@]"; do continue 2 fi elif (( ! $#tmp1 )); then + # A little extra hack: if we were completing `foo/' and `foo' + # contains no files, this will normally produce no matches and other + # completers might think that's it's their time now. But if the next + # completer is _correct or something like that, this will result in + # an attempt to correct a valid directory name. So we just add the + # original string in such a case so that the command line doesn't + # change but other completers still think there are matches. + + if [[ -z "$tpre$tsuf" && "$pre" = */ && -z "$suf" ]]; then + compadd -nQS '' - "$linepath$donepath$orig" + tmp4=- + fi continue 2 fi @@ -310,33 +322,33 @@ for prepath in "$prepaths[@]"; do if [[ -n $menu ]]; then [[ -n "$compconfig[path_cursor]" ]] && compstate[to_end]='' if [[ "$tmp3" = */* ]]; then - compadd -Uf -p "$linepath$testpath" -s "/${tmp3#*/}" \ + compadd -QUf -p "$linepath${testpath:q}" -s "/${tmp3#*/}" \ -W "$prepath$realpath$testpath" "$ignore[@]" \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - - "${(@)tmp1%%/*}" + - "${(@)${(@)tmp1%%/*}:q}" else - compadd -Uf -p "$linepath$testpath" \ + compadd -QUf -p "$linepath${testpath:q}" \ -W "$prepath$realpath$testpath" "$ignore[@]" \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - - "$tmp1[@]" + - "${(@)tmp1:q}" fi else if [[ "$tmp3" = */* ]]; then for i in "$tmp1[@]"; do - compadd -Uf -p "$linepath$testpath" -s "/${i#*/}" \ + compadd -QUf -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \ -W "$prepath$realpath$testpath" "$ignore[@]" \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - - "${i%%/*}" + - "${${i%%/*}:q}" done else - compadd -Uf -p "$linepath$testpath" \ + compadd -QUf -p "$linepath${testpath:q}" \ -W "$prepath$realpath$testpath" "$ignore[@]" \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - - "$tmp1[@]" + - "${(@)tmp1:q}" fi fi tmp4=- @@ -361,11 +373,11 @@ for prepath in "$prepaths[@]"; do done if [[ -z "$tmp4" ]]; then - compadd -Uf -p "$linepath$testpath" \ + compadd -QUf -p "$linepath${testpath:q}" \ -W "$prepath$realpath$testpath" "$ignore[@]" \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - - "$tmp1[@]" + - "${(@)tmp1:q}" fi done @@ -376,9 +388,9 @@ done exppaths=( "${(@)exppaths:#$orig}" ) if [[ -n "$compconfig[path_expand]" && - $#exppaths -eq 1 && nm -eq compstate[nmatches] ]]; then + $#exppaths -gt 0 && nm -eq compstate[nmatches] ]]; then compadd -QU -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ - -M 'r:|/=* r:|=*' -p "$linepath" - "${(@)exppaths}" + -M 'r:|/=* r:|=*' -p "$linepath" - "$exppaths[@]" fi [[ nm -ne compstate[nmatches] ]] diff --git a/Completion/User/.distfiles b/Completion/User/.distfiles index c96f2ba3e..9187fa520 100644 --- a/Completion/User/.distfiles +++ b/Completion/User/.distfiles @@ -1,6 +1,8 @@ DISTFILES_SRC=' .distfiles - _a2ps _chown _compress _configure _dd _dvi _find _groups _gunzip _gzip - _hosts _use_lo _make _man _mh _pdf _ps _rcs _rlogin _strip _stty + _a2ps _chown _compress _configure _dd _dvi _find + _gdb _groups _gunzip _gzip + _hosts _use_lo _make _man _mh _pdf _ps + _rcs _rlogin _sh _strip _stty _su _tar _tar_archive _tex _uncompress _x_options _xfig ' diff --git a/Completion/User/_gdb b/Completion/User/_gdb new file mode 100644 index 000000000..ff54e6a07 --- /dev/null +++ b/Completion/User/_gdb @@ -0,0 +1,50 @@ +#compdef gdb + +# This uses the configuration keys `ps_args' and `ps_listargs' +# described in the `_wait' function. + +local cur="$words[CURRENT]" prev w list ret=1 + +_long_options -t '*=(CORE|SYM)FILE' '_files' \ + '*=EXECFILE' '_files *(*)' \ + '*=TTY' 'compadd /dev/tty*' && return 0 + +if compset -P '-(cd|directory)='; then + _files -/ +elif compset -P '-tty='; then + compadd - /dev/tty* +elif compset -P '-(exec|se)='; then + _files -/g '*(*)' +elif compset -P '-(symbols|core|command)='; then + _files +elif compset -P -; then + compadd -QS '' - symbols\= exec\= se\= core\= command\= directory\= \ + cd\= tty\= + compadd - help h s e c x d nx n quiet q batch fullname f b +else + prev="$words[CURRENT-1]" + + case "$prev" in + (-d) _files -/ && return 0 ;; + (-e) _files -/g '*(*)' && return 0 ;; + (-[csx]) _files && return 0 ;; + (-b) compadd -V baud 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \ + 9600 19200 38400 57600 115200 230400 && return 0 ;; + esac + w=( "${(@)words[2,-1]}" ) + while [[ "$w[1]" = -* ]]; do + [[ "$w[1]" = -[decsxb] ]] && shift 1 w + shift 1 w + done + + if [[ $#w -gt 1 ]]; then + _files && ret=0 + list=("${(F)${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${w[1]:t}}} +") + compadd -y list - ${${${(M)${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}:#*${w[1]:t}*}## #}%% *} && ret=0 + + return ret + else + _files -/g '*(*)' + fi +fi diff --git a/Completion/User/_hosts b/Completion/User/_hosts index a0aca0a62..d498425bc 100644 --- a/Completion/User/_hosts +++ b/Completion/User/_hosts @@ -2,4 +2,4 @@ : ${(A)hosts:=${(s: :)${(ps:\t:)${${(f)"$()( -The maximum size of the history list. +The maximum number of events stored in the internal history list. +If you use the tt(HIST_EXPIRE_DUPS_FIRST) option, setting this value +larger than the tt(SAVEHIST) size will give you the difference as a +cushion for saving duplicated history events. ) vindex(HOME) item(tt(HOME) )( diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index ce1b27fec..60c003533 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -154,12 +154,9 @@ vindex(LASTWIDGET) item(tt(LASTWIDGET) (scalar))( The name of the last widget that was executed. ) -vindex(keys) -item(tt(keys) (array))( -The keys typed to invoke this widget, one element per -key. Control-keys are reported with a leading `tt(^)', as in `tt(^A)', -and meta-keys are reported with a leading `tt(M-)', as in `tt(M-a)' and -`tt(M-^A)'. +vindex(KEYS) +item(tt(KEYS) (scalar))( +The keys typed to invoke this widget, as a literal string. ) vindex(NUMERIC) item(tt(NUMERIC) (integer))( diff --git a/Etc/MACHINES b/Etc/MACHINES index fd386c7e0..038340e79 100644 --- a/Etc/MACHINES +++ b/Etc/MACHINES @@ -39,15 +39,21 @@ DEC: OSF/1 1.2, 1.3, 2.0, 3.*, DEC Unix 4.* (Alpha) remove the bogus strip and use /bin/strip instead. On Digital UNIX 4.0, compilation with gcc and with --enable-dynamic - apparently needs configuring with explicit flags: + apparently needs configuring with explicit flags when compiling + with debugging enabled: DLLD=gcc LDFLAGS='-g -rpath ' ./configure ... FreeBSD: FreeBSD 2.2.7 [3.1.4] Should build `out-of-the-box'. -HP: HP-UX 9, 10.20 +HP: HP-UX 9, 10.20, 11.0 Should build `out-of-the-box'. + Problems with dynamic loading have been reported under 11, but + this should compile using the standard dlopen() function set + (rather than the 10.20 shl_load() function set). More details of + any difficulties would be appreciated. + IBM: AIX Should build `out-of-the-box'. On AIX 3.x (at least), --enable-zsh-mem will not work. @@ -87,9 +93,6 @@ SGI: IRIX 5.1.1.1, 5.2, 5.3, 6.2, 6.3, 6.5 full optimization (cc -O3 -OPT:Olimit=0) causes problems. Sun: SunOS 4.1.* - Dynamic loading does not work under SunOS 4.1. Sometimes, - you may need to turn it off explicitly with --disable-dynamic. - Under 4.1.3 if yellow pages is used, username completion may cause segmentation violation. This is a bug in the shared library not in zsh. Some libc.so.1.9.* has this bug (it fails in yp_all). diff --git a/Etc/NEWS b/Etc/NEWS index 9d58c9cc6..aad7ccceb 100644 --- a/Etc/NEWS +++ b/Etc/NEWS @@ -34,6 +34,7 @@ Globbing changes: - Case-insensitive and approximate globbing. - Ordering and indexing of globbing matches, e.g. *(om[1]) picks most recently modified file. + - General file mode qualifier with chmod(1)-like syntax, e.g. *(f:u+wx:) New loadable modules: - zftp, plus associated function suite, for turning your zsh session diff --git a/Functions/.cvsignore b/Functions/.cvsignore new file mode 100644 index 000000000..f3c7a7c5d --- /dev/null +++ b/Functions/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/Functions/.distfiles b/Functions/.distfiles index fe60df9b7..03aebe308 100644 --- a/Functions/.distfiles +++ b/Functions/.distfiles @@ -1,3 +1,3 @@ DISTFILES_SRC=' - .distfiles Makefile.in README.zftp + .cvsignore .distfiles Makefile.in README.zftp ' diff --git a/Functions/Zftp/zfgoto b/Functions/Zftp/zfgoto index 8d6f00a3a..bd1cdbfe5 100644 --- a/Functions/Zftp/zfgoto +++ b/Functions/Zftp/zfgoto @@ -67,7 +67,10 @@ line=${line#*@} host=${line%%:*} dir=${line#*:} -if [[ $user = ftp || $user = anonymous ]]; then +if [[ $ZFTP_USER = $user && $ZFTP_HOST = $host ]]; then + # We're already there, just change directory + zfcd ${dir:-~} +elif [[ $user = ftp || $user = anonymous ]]; then # Anonymous ftp, so we don't need password etc. zfanon $host && [[ -n $dir ]] && zfcd $dir elif [[ $zflastsession = ${host}:* && $user = $zflastuser ]]; then diff --git a/Functions/Zftp/zfinit b/Functions/Zftp/zfinit index fbe6c5979..2a5fd9b47 100644 --- a/Functions/Zftp/zfinit +++ b/Functions/Zftp/zfinit @@ -1,6 +1,6 @@ emulate -L zsh -[[ $1 = -n ]] || zmodload -ia zftp +[[ $1 = -n ]] || zmodload -e zftp || zmodload -ia zftp alias zfcd='noglob zfcd' alias zfget='noglob zfget' diff --git a/Functions/Zle/incremental-complete-word b/Functions/Zle/incremental-complete-word index 2a9c1aff2..3831ecaa6 100644 --- a/Functions/Zle/incremental-complete-word +++ b/Functions/Zle/incremental-complete-word @@ -4,32 +4,55 @@ # to a key. # This allows incremental completion of a word. After starting this -# command, a list of completion choices is shown after every character you -# type, which you can delete with ^h or DEL. RET will accept the -# completion so far. You can hit TAB to do normal completion and ^g to -# abort back to the state when you started. +# command, a list of completion choices can be shown after every character +# you type, which you can delete with ^h or DEL. RET will accept the +# completion so far. You can hit TAB to do normal completion, ^g to +# abort back to the state when you started, and ^d to list the matches. # -# Completion keys: -# incremental_prompt Prompt to show in status line during icompletion; -# the sequence `%u' is replaced by the unambiguous -# part of all matches if there is any and it is -# different from the word on the line -# incremental_stop Pattern matching keys which will cause icompletion -# to stop and the key to be re-executed -# incremental_break Pattern matching keys which will cause icompletion -# to stop and the key to be discarded -# incremental_completer Set of completers, like the `completer' key -# incremental_list If set to a non-empty string, the matches will be -# listed on every key-press +# This works best with the new function based completion system. +# +# Configuration keys: +# +# incremental_prompt +# Prompt to show in status line during icompletion. The sequence `%u' +# is replaced by the unambiguous part of all matches if there is any +# and it is different from the word on the line. A `%s' is replaced +# with `-no match-', `-no prefix-', or an empty string if there is +# no completion matching the word on the line, if the matches have +# no common prefix different from the word on the line or if there is +# such a common prefix, respectively. The sequence `%c' is replaced +# by the name of the completer function that generated the matches +# (without the leading underscore). Finally, `%n' is replaced by the +# number of matches generated and `%a' is replaced by an empty string +# if the matches are in the normal set (i.e. the one without file names +# with one of the suffixes from `fignore') and with ` -alt-' if the +# matches are in the alternate set. +# +# incremental_stop +# Pattern matching keys which will cause icompletion to stop and the +# key to be re-executed. +# +# incremental_break +# Pattern matching keys which will cause icompletion to stop and the +# key to be discarded. +# +# incremental_completer +# Set of completers, like the `completer' key for normal completion. +# +# incremental_list +# If set to a non-empty string, the matches will be listed on every +# key-press. + emulate -L zsh unsetopt autolist menucomplete automenu # doesn't work well -local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word lastl lastr wid twid +local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word +local lastl lastr wid twid num alt [[ -n "$compconfig[incremental_completer]" ]] && -set ${(s.:.)compconfig[incremental_completer]} -pmpt="${compconfig[incremental_prompt]-incremental completion...}" + set ${(s.:.)compconfig[incremental_completer]} +pmpt="${compconfig[incremental_prompt]-incremental (%c): %u%s}" if [[ -n "$compconfig[incremental_list]" ]]; then wid=list-choices @@ -40,12 +63,22 @@ fi zle $wid "$@" LBUFFER="$lbuf" RBUFFER="$rbuf" -if [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then +if (( ! _lastcomp[nmatches] )); then + word='' + state='-no match-' +elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then word='' + state='-no prefix-' else word="${_lastcomp[unambiguous]}" + state='' +fi +num=$_lastcomp[normal_nmatches] +if (( ! num )); then + num="${_lastcomp[nmatches]}" + alt=' -alt-' fi -zle -R "${pmpt//\\%u/$word}" +zle -R "${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}" read -k key while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' && @@ -72,12 +105,24 @@ while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' && zle $twid "$@" LBUFFER="$lastl" RBUFFER="$lastr" - if [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then + if (( ! _lastcomp[nmatches] )); then word='' + state='-no match-' + elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then + word='' + state='-no prefix-' else word="${_lastcomp[unambiguous]}" + state='' + fi + num=$_lastcomp[normal_nmatches] + if (( ! num )); then + num="${_lastcomp[nmatches]}" + alt=' -alt-' + else + alt='' fi - zle -R "${pmpt//\\%u/$word}" + zle -R "${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}" read -k key done diff --git a/INSTALL b/INSTALL index b8eaa561c..5e61f0795 100644 --- a/INSTALL +++ b/INSTALL @@ -246,9 +246,12 @@ plus those provide functions for the line editor, i.e. FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* Zle/*' and if the --enable-dynamic option was given, the functions in Functions/Zftp, which require the zftp module to be available (see the -zshzftpsys manual page), will be included as well. There are also some -miscellaneous functions with documentation in comments; the complete set -of functions can be installed with +zshzftpsys manual page), will be included as well. Note, however, that +some of the functions in the User subdirectory are version- and +system-specific. + +There are also some miscellaneous functions with documentation in comments; +the complete set of functions can be installed with FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* \ Misc/* Zftp/* Zle/*' Note you should set this by hand to include `Zftp/*' if you have zftp diff --git a/Misc/job-control-tests b/Misc/job-control-tests index 7e35fba0b..ecb9a7694 100644 --- a/Misc/job-control-tests +++ b/Misc/job-control-tests @@ -29,3 +29,48 @@ while true; do sed -e 's/foo/bar/' Src/builtin.c >/dev/null; done # ignoring the error messages from sed. # ^Z is more of a problem since you have to catch the sed. while true; do sed -e 's/foo/bar/' non-existent-file >/dev/null; done + +# Try +# ^Z +# fg +# ^Z +# fg +fn() { + local a + while read a; do :; done + less "$@" +} +cat foo | fn bar + +# Try +# ^Z +# fg +fn() { + cat builtin.c +} +fn | while read a; do :; done + +# Try +# ^Z +# fg +# q +# ^Z +# fg +# q +fn() { + less builtin.c + echo done +} +x=2; while (( x-- )); do f; done + +# Try +# ^C +# This won't work because zcat doesn't tell us that it received a signal. +# But +# ^Z +# fg +# ^C (probably a second ^C is needed: if the continued zcat is still running) +# works. +# (See also the file Etc/BUGS) +while true; do zcat foo.gz > /dev/null; done + diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index 63bca854c..738d596fa 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -2261,7 +2261,7 @@ zftp_type(char *name, char **args, int flags) fflush(stdout); return 0; } else { - nt = toupper(*str); + nt = toupper(STOUC(*str)); /* * RFC959 specifies other types, but these are the only * ones we know what to do with. @@ -2294,7 +2294,7 @@ zftp_mode(char *name, char **args, int flags) fflush(stdout); return 0; } - nt = str[0] = toupper(*str); + nt = str[0] = toupper(STOUC(*str)); if (str[1] || (nt != 'S' && nt != 'B')) { zwarnnam(name, "transfer mode %s not recognised", str, 0); return 1; @@ -2651,7 +2651,7 @@ bin_zftp(char *name, char **args, char *ops, int func) if ((prefs = getsparam("ZFTP_PREFS"))) { zfprefs = 0; for (ptr = prefs; *ptr; ptr++) { - switch (toupper(*ptr)) { + switch (toupper(STOUC(*ptr))) { case 'S': /* sendport */ zfprefs |= ZFPF_SNDP; diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h index 8264890df..b0fbf3ac6 100644 --- a/Src/Zle/comp.h +++ b/Src/Zle/comp.h @@ -218,6 +218,8 @@ struct cmatch { int brsl; /* ...and the suffix */ char *rems; /* when to remove the suffix */ char *remf; /* shell function to call for suffix-removal */ + int qipl; /* length of quote-prefix */ + int qisl; /* length of quote-suffix */ int rnum; /* group relative number */ int gnum; /* global number */ }; @@ -349,25 +351,25 @@ struct chdata { #define CPN_NMATCHES 0 -#define CP_NMATCHES (1 << CPN_NMATCHES) +#define CP_NMATCHES (1 << CPN_NMATCHES) #define CPN_MATCHER 1 -#define CP_MATCHER (1 << CPN_MATCHER) +#define CP_MATCHER (1 << CPN_MATCHER) #define CPN_MATCHERSTR 2 -#define CP_MATCHERSTR (1 << CPN_MATCHERSTR) +#define CP_MATCHERSTR (1 << CPN_MATCHERSTR) #define CPN_MATCHERTOT 3 -#define CP_MATCHERTOT (1 << CPN_MATCHERTOT) +#define CP_MATCHERTOT (1 << CPN_MATCHERTOT) #define CPN_CONTEXT 4 -#define CP_CONTEXT (1 << CPN_CONTEXT) +#define CP_CONTEXT (1 << CPN_CONTEXT) #define CPN_PARAMETER 5 -#define CP_PARAMETER (1 << CPN_PARAMETER) +#define CP_PARAMETER (1 << CPN_PARAMETER) #define CPN_REDIRECT 6 -#define CP_REDIRECT (1 << CPN_REDIRECT) +#define CP_REDIRECT (1 << CPN_REDIRECT) #define CPN_QUOTE 7 -#define CP_QUOTE (1 << CPN_QUOTE) +#define CP_QUOTE (1 << CPN_QUOTE) #define CPN_QUOTING 8 -#define CP_QUOTING (1 << CPN_QUOTING) +#define CP_QUOTING (1 << CPN_QUOTING) #define CPN_RESTORE 9 -#define CP_RESTORE (1 << CPN_RESTORE) +#define CP_RESTORE (1 << CPN_RESTORE) #define CPN_LIST 10 #define CP_LIST (1 << CPN_LIST) #define CPN_FORCELIST 11 @@ -398,6 +400,8 @@ struct chdata { #define CP_OLDINS (1 << CPN_OLDINS) #define CPN_VARED 24 #define CP_VARED (1 << CPN_VARED) +#define CPN_NNMATCHES 25 +#define CP_NNMATCHES (1 << CPN_NNMATCHES) -#define CP_KEYPARAMS 25 +#define CP_KEYPARAMS 26 #define CP_ALLKEYS ((unsigned int) 0xffffff) diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c index ba8bcc868..c1e2bfb57 100644 --- a/Src/Zle/comp1.c +++ b/Src/Zle/comp1.c @@ -105,6 +105,7 @@ int incompfunc; /**/ zlong compcurrent, compnmatches, + compnnmatches, compmatcher, compmatchertot, complistmax; diff --git a/Src/Zle/comp1.export b/Src/Zle/comp1.export index 9b738cc78..4b6dd92fd 100644 --- a/Src/Zle/comp1.export +++ b/Src/Zle/comp1.export @@ -27,6 +27,7 @@ compmatcher compmatcherstr compmatchertot compnmatches +compnnmatches compoldlist compoldins compparameter diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 694af8429..e9ff83387 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -2210,6 +2210,7 @@ static struct compparam compkparams[] = { { "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL }, { "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL }, { "vared", PM_SCALAR, VAL(compvared), NULL, NULL }, + { "normal_nmatches", PM_INTEGER, VAL(compnnmatches), NULL, NULL }, { NULL, 0, NULL, NULL, NULL } }; diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 0e7152866..4bf3fec0e 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -308,8 +308,8 @@ complistmatches(Hookdef dummy, Chdata dat) Cmatch *p, m; Cexpl *e; int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0, opl = 0; - int of = isset(LISTTYPES); - int mc, ml = 0, cc, hasm = 0, cl; + int of = isset(LISTTYPES), cf; + int mc, ml = 0, cc, hasm = 0, cl = -1; struct listcols col; if (minfo.asked == 2) { @@ -318,15 +318,6 @@ complistmatches(Hookdef dummy, Chdata dat) } getcols(&col); - /* Set the cursor below the prompt. */ - if (inselect) - clearflag = 0; - trashzle(); - showinglist = listshown = 0; - - clearflag = (isset(USEZLE) && !termflags && - complastprompt && *complastprompt); - for (g = amatches; g; g = g->next) { char **pp = g->ylist; int nl = 0, l; @@ -403,6 +394,19 @@ complistmatches(Hookdef dummy, Chdata dat) nlines += 1 + ((1 + niceztrlen(m->str)) / columns); } } + cf = (isset(USEZLE) && !termflags && complastprompt && *complastprompt); + if (!nlines || (mselect >= 0 && (!cf || (nlines + nlnct - 1) >= lines))) { + showinglist = listshown = 0; + noselect = 1; + return 1; + } + /* Set the cursor below the prompt. */ + if (inselect) + clearflag = 0; + trashzle(); + showinglist = listshown = 0; + + clearflag = cf; /* Maybe we have to ask if the user wants to see the list. */ if ((!minfo.cur || !minfo.asked) && @@ -654,20 +658,20 @@ complistmatches(Hookdef dummy, Chdata dat) pnl = 1; g = g->next; } - if (clearflag) { /* Move the cursor up to the prompt, if always_last_prompt * * is set and all that... */ if ((nlines += nlnct - 1) < lines) { tcmultout(TCUP, TCMULTUP, nlines); showinglist = -1; - listshown = 1; } else clearflag = 0, putc('\n', shout); } else putc('\n', shout); + listshown = (clearflag ? 1 : -1); if (!hasm || nlines >= lines) noselect = 1; + return noselect; } @@ -676,7 +680,7 @@ typedef struct menustack *Menustack; struct menustack { Menustack prev; char *line; - int cs; + int cs, acc; struct menuinfo info; Cmgroup amatches, pmatches, lmatches; }; @@ -742,19 +746,19 @@ domenuselect(Hookdef dummy, Chdata dat) s->amatches = amatches; s->pmatches = pmatches; s->lmatches = lmatches; - menucmp = 0; + s->acc = menuacc; + menucmp = menuacc = 0; fixsuffix(); validlist = 0; pmatches = NULL; invalidatelist(); menucomplete(zlenoargs); if (dat->num < 2 || !minfo.cur || !*(minfo.cur)) { - noselect = 1; - clearlist = 1; + noselect = clearlist = listshown = 1; zrefresh(); break; } - clearlist = 1; + clearlist = listshown = 1; mselect = (*(minfo.cur))->gnum; continue; } else if (cmd == Th(z_acceptandhold) || @@ -767,6 +771,7 @@ domenuselect(Hookdef dummy, Chdata dat) s->cs = cs; memcpy(&(s->info), &minfo, sizeof(struct menuinfo)); s->amatches = s->pmatches = s->lmatches = NULL; + s->acc = menuacc; acceptlast(); do_menucmp(0); mselect = (*(minfo.cur))->gnum; @@ -782,6 +787,7 @@ domenuselect(Hookdef dummy, Chdata dat) spaceinline(l = strlen(u->line)); strncpy((char *) line, u->line, l); cs = u->cs; + menuacc = u->acc; memcpy(&minfo, &(u->info), sizeof(struct menuinfo)); p = &(minfo.cur); if (u->pmatches && pmatches != u->pmatches) { diff --git a/Src/Zle/zle.export b/Src/Zle/zle.export index 8bc049e16..f63f45eb8 100644 --- a/Src/Zle/zle.export +++ b/Src/Zle/zle.export @@ -24,6 +24,7 @@ lastambig linkkeymap listshown lmatches +menuacc menucmp menucomplete menucur diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index dc4e27685..5ed846cd6 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -67,7 +67,7 @@ static struct zleparam { zleunsetfn, NULL }, { "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget), zleunsetfn, NULL }, - { "keys", PM_ARRAY | PM_READONLY, NULL, FN(get_keys), + { "KEYS", PM_SCALAR | PM_READONLY, NULL, FN(get_keys), zleunsetfn, NULL }, { "NUMERIC", PM_INTEGER | PM_UNSET, FN(set_numeric), FN(get_numeric), unset_numeric, NULL }, @@ -247,29 +247,10 @@ get_lwidget(Param pm) } /**/ -static char ** +static char * get_keys(Param pm) { - char **r, **q, *p, *k, c; - - r = (char **) zhalloc((strlen(keybuf) + 1) * sizeof(char *)); - for (q = r, p = keybuf; (c = *p); q++, p++) { - k = *q = (char *) zhalloc(5); - if (c & 0x80) { - *k++ = 'M'; - *k++ = '-'; - c &= 0x7f; - } - if (c < 32 || c == 0x7f) { - *k++ = '^'; - c ^= 64; - } - *k++ = c; - *k = '\0'; - } - *q = NULL; - - return r; + return keybuf; } /**/ diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 48e1071b8..1dbffc21c 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -53,7 +53,8 @@ int nlnct; /**/ int showinglist; -/* Non-zero if a completion list was displayed. */ +/* > 0 if a completion list is displayed below the prompt, + * < 0 if a list is displayed above the prompt. */ /**/ int listshown; @@ -265,7 +266,7 @@ zrefresh(void) if (inlist) return; - if (clearlist && listshown) { + if (clearlist && listshown > 0) { if (tccan(TCCLEAREOD)) { int ovln = vln, ovcs = vcs; char *nb = nbuf[vln]; @@ -331,7 +332,8 @@ zrefresh(void) tcout(TCCLEAREOD); else cleareol = 1; /* request: clear to end of line */ - listshown = 0; + if (listshown > 0) + listshown = 0; } if (t0 > -1) olnct = t0; diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 5461079cb..b678a5cad 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -106,10 +106,11 @@ static int insmnum, insgnum, insgroup, insspace; static int movetoend; -/* != 0 if we are in the middle of a menu completion */ +/* != 0 if we are in the middle of a menu completion and number of matches +* accepted with accept-and-menu-complete */ /**/ -int menucmp; +int menucmp, menuacc; /* Information about menucompletion. */ @@ -192,6 +193,10 @@ static char *qipre, *qisuf, autoq; static int lpl, lsl, rpl, rsl, fpl, fsl, lppl, lpsl; static int noreal; +/* A parameter expansion prefix (like ${). */ + +static char *parpre; + /* This is either zero or equal to the special character the word we are * * trying to complete starts with (e.g. Tilde or Equals). */ @@ -209,9 +214,9 @@ static char *qword; static Cmgroup mgroup; -/* A match counter. */ +/* Match counters: all matches, normal matches (not alternate set). */ -static int mnum; +static int mnum, nmnum; /* The match counter when unambig_data() was called. */ @@ -540,6 +545,8 @@ reversemenucomplete(char **args) void acceptlast(void) { + menuacc++; + if (brbeg && *brbeg) { int l; @@ -553,10 +560,16 @@ acceptlast(void) brbeg[l] = ','; brbeg[l + 1] = '\0'; } else { + int l; + cs = minfo.pos + minfo.len + minfo.insc; iremovesuffix(' ', 1); - + l = cs; + cs = minfo.pos + minfo.len - (*(minfo.cur))->qisl; + foredel(l - cs); inststrlen(" ", 1, 1); + if (parpre) + inststr(parpre); minfo.insc = minfo.len = 0; minfo.pos = cs; minfo.we = 1; @@ -694,6 +707,9 @@ check_param(char *s, int set, int test) { char *p; + zsfree(parpre); + parpre = NULL; + if (!test) ispar = parq = eparq = 0; /* Try to find a `$'. */ @@ -755,6 +771,8 @@ check_param(char *s, int set, int test) /* Now make sure that the cursor is inside the name. */ if (offs <= e - s && offs >= b - s && n <= 0) { + char sav; + if (br) { p = e; while (*p == (test ? Dnull : '"')) @@ -782,6 +800,12 @@ check_param(char *s, int set, int test) else parq = eparq = 0; + /* Save the prefix. */ + sav = *b; + *b = '\0'; + untokenize(parpre = ztrdup(s)); + *b = sav; + /* And adjust wb, we, and offs again. */ offs -= b - s; wb = cs - offs; @@ -1017,7 +1041,7 @@ docomplete(int lst) int ocs = cs, ne = noerrs; noerrs = 1; - doexpansion(s, lst, olst, lincmd); + ret = doexpansion(s, lst, olst, lincmd); lastambig = 0; noerrs = ne; @@ -1043,8 +1067,8 @@ docomplete(int lst) } } ret = docompletion(s, lst, lincmd); - } else - ret = !strcmp(ol, (char *) line); + } else if (ret) + clearlist = 1; } else /* Just do completion. */ ret = docompletion(s, lst, lincmd); @@ -1064,7 +1088,7 @@ docomplete(int lst) dat.num = nmatches; dat.cur = NULL; if (runhookdef(MENUSTARTHOOK, (void *) &dat)) - menucmp = 0; + menucmp = menuacc = 0; } return ret; } @@ -1736,9 +1760,10 @@ get_comp_string(void) /* Expand the current word. */ /**/ -static void +static int doexpansion(char *s, int lst, int olst, int explincmd) { + int ret = 1; LinkList vl; char *ss; @@ -1775,7 +1800,7 @@ doexpansion(char *s, int lst, int olst, int explincmd) } if (lst == COMP_LIST_EXPAND) { /* Only the list of expansions was requested. */ - listlist(vl); + ret = listlist(vl); showinglist = 0; goto end; } @@ -1783,6 +1808,7 @@ doexpansion(char *s, int lst, int olst, int explincmd) cs = wb; foredel(we - wb); while ((ss = (char *)ugetnode(vl))) { + ret = 0; untokenize(ss); ss = quotename(ss, NULL); inststr(ss); @@ -1801,6 +1827,8 @@ doexpansion(char *s, int lst, int olst, int explincmd) end: popheap(); } LASTALLOC; + + return ret; } /* This is called from the lexer to give us word positions. */ @@ -3547,6 +3575,8 @@ add_match_data(int alt, char *str, Cline line, ai->line = join_clines(ai->line, line); mnum++; + if (!alt) + nmnum++; ai->count++; /* Allocate and fill the match structure. */ @@ -3569,6 +3599,8 @@ add_match_data(int alt, char *str, Cline line, cm->flags = flags; cm->brpl = bpl; cm->brsl = bsl; + cm->qipl = qipl; + cm->qisl = qisl; cm->autoq = (autoq ? autoq : (inbackt ? '`' : '\0')); cm->rems = cm->remf = NULL; addlinknode((alt ? fmatches : matches), cm); @@ -3896,6 +3928,7 @@ addmatches(Cadata dat, char **argv) } } compnmatches = mnum; + compnnmatches = nmnum; if (dat->exp) addexpl(); if (dat->apar) @@ -4380,10 +4413,14 @@ docompletion(char *s, int lst, int incmd) } if (comppatmatch && *comppatmatch && comppatmatch != opm) haspattern = 1; - if (!useline && uselist) + if (!useline && uselist) { /* All this and the guy only wants to see the list, sigh. */ + cs = 0; + foredel(ll); + inststr(origline); + cs = origcs; showinglist = -2; - else if (useline) { + } else if (useline) { /* We have matches. */ if (nmatches > 1) { /* There is more than one match. */ @@ -4399,9 +4436,13 @@ docompletion(char *s, int lst, int incmd) do_single(m->matches[0]); invalidatelist(); } - } else + } else { invalidatelist(); - + cs = 0; + foredel(ll); + inststr(origline); + cs = origcs; + } /* Print the explanation strings if needed. */ if (!showinglist && validlist && usemenu != 2 && nmatches != 1) { Cmgroup g = amatches; @@ -4582,22 +4623,22 @@ callcompfunc(char *s, char *fn) zsfree(compprefix); zsfree(compsuffix); if (unset(COMPLETEINWORD)) { - /* Maybe we'll have to do quoting here some time. */ - tmp = dupstring(s); + tmp = quotename(s, NULL); untokenize(tmp); compprefix = ztrdup(tmp); compsuffix = ztrdup(""); } else { char *ss, sav; - tmp = dupstring(s); - ss = tmp + offs; + ss = s + offs; sav = *ss; *ss = '\0'; + tmp = quotename(s, NULL); untokenize(tmp); compprefix = ztrdup(tmp); *ss = sav; + ss = quotename(ss, NULL); untokenize(ss); compsuffix = ztrdup(ss); } @@ -4611,6 +4652,7 @@ callcompfunc(char *s, char *fn) compqisuffix = ztrdup(qisuf ? qisuf : ""); compcurrent = (usea ? (clwpos + 1 - aadd) : 0); compnmatches = mnum; + compnnmatches = nmnum; zsfree(complist); switch (uselist) { @@ -4825,13 +4867,13 @@ makecomplist(char *s, int incmd, int lst) if (!validlist) lastambig = 0; amatches = NULL; - mnum = 0; + mnum = nmnum = 0; unambig_mnum = -1; isuf = NULL; insmnum = insgnum = 1; insgroup = oldlist = oldins = 0; begcmgroup("default", 0); - menucmp = 0; + menucmp = menuacc = 0; ccused = newlinklist(); ccstack = newlinklist(); @@ -4984,6 +5026,8 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) memcpy(tmp + sl + 1, s, noffs); tmp[(scs = cs = sl + 1 + noffs)] = 'x'; strcpy(tmp + sl + 2 + noffs, s + noffs); + if (incompfunc) + tmp = rembslash(tmp); inpush(dupstrspace(tmp), 0, NULL); line = (unsigned char *) tmp; ll = tl - 1; @@ -5013,6 +5057,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) p = NULL; if (!got && !zleparse) { DPUTS(!p, "no current word in substr"); + got = 1; cur = i; swb = wb - 1; swe = we - 1; @@ -5077,7 +5122,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) } sav = s[(i = swb - sl - 1)]; s[i] = '\0'; - qp = tricat(qipre, s, ""); + qp = tricat(qipre, (incompfunc ? rembslash(s) : s), ""); s[i] = sav; if (swe < swb) swe = swb; @@ -5085,7 +5130,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) sl = strlen(s); if (swe > sl) swe = sl, ns[swe - swb + 1] = '\0'; - qs = tricat(s + swe, qisuf, ""); + qs = tricat((incompfunc ? rembslash(s + swe) : s + swe), qisuf, ""); sl = strlen(ns); if (soffs > sl) soffs = sl; @@ -5172,7 +5217,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) compisuffix = ztrdup(""); zsfree(compqiprefix); zsfree(compqisuffix); - if (instring) { + if (ois) { compqiprefix = qp; compqisuffix = qs; } else { @@ -5188,6 +5233,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec) p = compwords[i] = (char *) getdata(n); untokenize(p); } + compcurrent = cur + 1; compwords[i] = NULL; } autoq = oaq; @@ -5242,6 +5288,7 @@ makecomplistcall(Compctl cc) inbackt = oib; autoq = oaq; compnmatches = mnum; + compnnmatches = nmnum; } LASTALLOC; } SWITCHBACKHEAPS; @@ -5317,6 +5364,7 @@ makecomplistctl(int flags) autoq = oaq; offs = ooffs; compnmatches = mnum; + compnnmatches = nmnum; zsfree(cmdstr); freearray(clwords); cmdstr = os; @@ -5979,7 +6027,10 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) char save = line[cs]; line[cs] = 0; - lppre = dupstring((char *) (line + wb)); + lppre = dupstring((char *) line + wb + + (qipre && *qipre ? + (strlen(qipre) - + (*qipre == '\'' || *qipre == '\"')) : 0)); line[cs] = save; if (brbeg && *brbeg) strcpy(lppre + qbrpl, lppre + qbrpl + strlen(brbeg)); @@ -5998,11 +6049,17 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) lppl = 0; } if (cs != we) { - char save = line[we]; + int end = we; + char save = line[end]; + + if (qisuf && *qisuf) { + int ql = strlen(qisuf); - line[we] = 0; + end -= ql - (qisuf[ql-1] == '\'' || qisuf[ql-1] == '"'); + } + line[end] = 0; lpsuf = dupstring((char *) (line + cs)); - line[we] = save; + line[end] = save; if (brend && *brend) { char *p = lpsuf + qbrsl - (cs - wb); @@ -6640,7 +6697,8 @@ invalidatelist(void) listmatches(); if (validlist) freematches(); - lastambig = menucmp = validlist = showinglist = fromcomp = 0; + lastambig = menucmp = menuacc = validlist = showinglist = + fromcomp = listshown = 0; minfo.cur = NULL; minfo.asked = 0; compwidget = NULL; @@ -6917,6 +6975,8 @@ dupmatch(Cmatch m) r->rems = ztrdup(m->rems); r->remf = ztrdup(m->remf); r->autoq = m->autoq; + r->qipl = m->qipl; + r->qisl = m->qisl; return r; } @@ -7346,7 +7406,9 @@ instmatch(Cmatch m, int *scs) /* Ignored prefix. */ if (m->ipre) { - inststrlen(m->ipre, 1, (l = strlen(m->ipre))); + char *p = m->ipre + (menuacc ? m->qipl : 0); + + inststrlen(p, 1, (l = strlen(p))); r += l; } /* -P prefix. */ @@ -7413,7 +7475,8 @@ static int do_ambiguous(void) { int ret = 0; - menucmp = 0; + + menucmp = menuacc = 0; /* If we have to insert the first match, call do_single(). This is * * how REC_EXACT takes effect. We effectively turn the ambiguous * @@ -7501,11 +7564,13 @@ do_ambiguous(void) * if it is needed. */ if (isset(LISTBEEP)) ret = 1; - if (uselist && (usemenu != 2 || (!showinglist && !oldlist)) && + + if (uselist && (usemenu != 2 || (!listshown && !oldlist)) && ((!showinglist && (!listshown || !oldlist)) || (usemenu == 3 && !oldlist)) && (smatches >= 2 || (compforcelist && *compforcelist))) showinglist = -2; + return ret; } @@ -7649,7 +7714,7 @@ do_single(Cmatch m) } } if (!minfo.insc) - cs = minfo.pos + minfo.len; + cs = minfo.pos + minfo.len - m->qisl; } /* If completing in a brace expansion... */ if (brbeg) { @@ -7688,8 +7753,11 @@ do_single(Cmatch m) if (minfo.we && m->ripre && isset(AUTOPARAMKEYS)) makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), minfo.insc - parq); - if ((menucmp && !minfo.we) || !movetoend) + if ((menucmp && !minfo.we) || !movetoend) { cs = minfo.end; + if (cs + m->qisl == lastend) + cs += minfo.insc; + } { Cmatch *om = minfo.cur; struct chdata dat; @@ -7732,6 +7800,7 @@ do_ambig_menu(void) if (usemenu != 3) { menucmp = 1; + menuacc = 0; minfo.cur = NULL; } else { if (oldlist) { @@ -7931,13 +8000,6 @@ ilistmatches(Hookdef dummy, Chdata dat) int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0; int of = isset(LISTTYPES), opl = 0; - /* Set the cursor below the prompt. */ - trashzle(); - showinglist = listshown = 0; - - clearflag = (isset(USEZLE) && !termflags && - complastprompt && *complastprompt); - for (g = amatches; g; g = g->next) { char **pp = g->ylist; int nl = 0, l; @@ -8013,6 +8075,16 @@ ilistmatches(Hookdef dummy, Chdata dat) nlines += 1 + ((1 + niceztrlen(m->str)) / columns); } } + if (!nlines) { + showinglist = listshown = 0; + return 1; + } + /* Set the cursor below the prompt. */ + trashzle(); + showinglist = listshown = 0; + + clearflag = (isset(USEZLE) && !termflags && + complastprompt && *complastprompt); /* Maybe we have to ask if the user wants to see the list. */ if ((!minfo.cur || !minfo.asked) && @@ -8152,25 +8224,25 @@ ilistmatches(Hookdef dummy, Chdata dat) pnl = 1; g = g->next; } - if (clearflag) { /* Move the cursor up to the prompt, if always_last_prompt * * is set and all that... */ if ((nlines += nlnct - 1) < lines) { tcmultout(TCUP, TCMULTUP, nlines); showinglist = -1; - listshown = 1; } else clearflag = 0, putc('\n', shout); } else putc('\n', shout); + listshown = (clearflag ? 1 : -1); + return 0; } /* This is used to print expansions. */ /**/ -void +int listlist(LinkList l) { struct cmgroup dg; @@ -8193,6 +8265,8 @@ listlist(LinkList l) validlist = vl; smatches = sm; complastprompt = oclp; + + return !dg.lcount; } /* Expand the history references. */ diff --git a/Src/builtin.c b/Src/builtin.c index 0e9baf9be..5c6b24601 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -658,6 +658,9 @@ set_pwd_env(void) } } +/* set if we are resolving links to their true paths */ +static int chasinglinks; + /* The main pwd changing function. The real work is done by other * * functions. cd_get_dest() does the initial argument processing; * * cd_do_chdir() actually changes directory, if possible; cd_new_pwd() * @@ -670,7 +673,6 @@ bin_cd(char *nam, char **argv, char *ops, int func) { LinkNode dir; struct stat st1, st2; - int chaselinks; if (isset(RESTRICTED)) { zwarnnam(nam, "restricted", NULL, 0); @@ -694,7 +696,7 @@ bin_cd(char *nam, char **argv, char *ops, int func) for (s = *argv; *++s; ops[STOUC(*s)] = 1); } brk: - chaselinks = ops['P'] || (isset(CHASELINKS) && !ops['L']); + chasinglinks = ops['P'] || (isset(CHASELINKS) && !ops['L']); PERMALLOC { pushnode(dirstack, ztrdup(pwd)); if (!(dir = cd_get_dest(nam, argv, ops, func))) { @@ -702,7 +704,7 @@ bin_cd(char *nam, char **argv, char *ops, int func) LASTALLOC_RETURN 1; } } LASTALLOC; - cd_new_pwd(func, dir, chaselinks); + cd_new_pwd(func, dir); if (stat(unmeta(pwd), &st1) < 0) { zsfree(pwd); @@ -710,7 +712,7 @@ bin_cd(char *nam, char **argv, char *ops, int func) } else if (stat(".", &st2) < 0) chdir(unmeta(pwd)); else if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) { - if (chaselinks) { + if (chasinglinks) { zsfree(pwd); pwd = metafy(zgetcwd(), -1, META_DUP); } else { @@ -915,40 +917,49 @@ static char * cd_try_chdir(char *pfix, char *dest, int hard) { char *buf; + int dlen, dochaselinks = 0; /* handle directory prefix */ if (pfix && *pfix) { if (*pfix == '/') buf = tricat(pfix, "/", dest); else { - int pwl = strlen(pwd); int pfl = strlen(pfix); + dlen = strlen(pwd); - buf = zalloc(pwl + pfl + strlen(dest) + 3); + buf = zalloc(dlen + pfl + strlen(dest) + 3); strcpy(buf, pwd); - buf[pwl] = '/'; - strcpy(buf + pwl + 1, pfix); - buf[pwl + 1 + pfl] = '/'; - strcpy(buf + pwl + pfl + 2, dest); + buf[dlen] = '/'; + strcpy(buf + dlen + 1, pfix); + buf[dlen + 1 + pfl] = '/'; + strcpy(buf + dlen + pfl + 2, dest); } } else if (*dest == '/') buf = ztrdup(dest); else { - int pwl = strlen(pwd); + dlen = strlen(pwd); - buf = zalloc(pwl + strlen(dest) + 2); + buf = zalloc(dlen + strlen(dest) + 2); strcpy(buf, pwd); - buf[pwl] = '/'; - strcpy(buf + pwl + 1, dest); + buf[dlen] = '/'; + strcpy(buf + dlen + 1, dest); } - /* Normalise path. See the definition of fixdir() for what this means. */ - fixdir(buf); + /* Normalise path. See the definition of fixdir() for what this means. + * We do not do this if we are chasing links. + */ + if (!chasinglinks) + dochaselinks = fixdir(buf); + else + unmetafy(buf, &dlen); if (lchdir(buf, NULL, hard)) { - zsfree(buf); + free(buf); return NULL; } + /* the chdir succeeded, so decide if we should force links to be chased */ + if (dochaselinks) + chasinglinks = 1; return metafy(buf, -1, META_NOALLOC); } @@ -956,7 +967,7 @@ cd_try_chdir(char *pfix, char *dest, int hard) /**/ static void -cd_new_pwd(int func, LinkNode dir, int chaselinks) +cd_new_pwd(int func, LinkNode dir) { List l; char *new_pwd, *s; @@ -972,7 +983,7 @@ cd_new_pwd(int func, LinkNode dir, int chaselinks) } else if (func == BIN_CD && unset(AUTOPUSHD)) zsfree(getlinknode(dirstack)); - if (chaselinks) { + if (chasinglinks) { s = new_pwd; new_pwd = findpwd(s); zsfree(s); @@ -1039,17 +1050,20 @@ printdirstack(void) } /* Normalise a path. Segments consisting of ., and foo/.. * - * combinations, are removed and the path is unmetafied. */ + * combinations, are removed and the path is unmetafied. + * Returns 1 if we found a ../ path which should force links to + * be chased, 0 otherwise. + */ /**/ -static void +int fixdir(char *src) { - char *dest = src; - char *d0 = dest; -#ifdef __CYGWIN__ + char *dest = src, *d0 = dest; +#ifdef __CYGWIN char *s0 = src; #endif + int ret = 0; /*** if have RFS superroot directory ***/ #ifdef HAVE_SUPERROOT @@ -1081,19 +1095,40 @@ fixdir(char *src) while (dest > d0 + 1 && dest[-1] == '/') dest--; *dest = '\0'; - return; + return ret; } if (src[0] == '.' && src[1] == '.' && - (src[2] == '\0' || src[2] == '/')) { - if (dest > d0 + 1) { - /* remove a foo/.. combination */ - for (dest--; dest > d0 + 1 && dest[-1] != '/'; dest--); - if (dest[-1] != '/') - dest--; - } - src++; - while (*++src == '/'); - } else if (src[0] == '.' && (src[1] == '/' || src[1] == '\0')) { + (src[2] == '\0' || src[2] == '/')) { + if (isset(CHASEDOTS)) { + ret = 1; + /* and treat as normal path segment */ + } else { + if (dest > d0 + 1) { + /* + * remove a foo/.. combination: + * first check foo exists, else return. + */ + struct stat st; + *dest = '\0'; + if (stat(d0, &st) < 0 || !S_ISDIR(st.st_mode)) { + char *ptrd, *ptrs; + if (dest == src) + *dest = '.'; + for (ptrs = src, ptrd = dest; *ptrs; ptrs++, ptrd++) + *ptrd = (*ptrs == Meta) ? (*++ptrs ^ 32) : *ptrs; + *ptrd = '\0'; + return 1; + } + for (dest--; dest > d0 + 1 && dest[-1] != '/'; dest--); + if (dest[-1] != '/') + dest--; + } + src++; + while (*++src == '/'); + continue; + } + } + if (src[0] == '.' && (src[1] == '/' || src[1] == '\0')) { /* skip a . section */ while (*++src == '/'); } else { @@ -3249,12 +3284,11 @@ bin_read(char *name, char **args, char *ops, int func) nchars = 1; args++; } - - firstarg = *args; - if (*args && **args == '?') - args++; - /* default result parameter */ + /* This `*args++ : *args' looks a bit weird, but it works around a bug + * in gcc-2.8.1 under DU 4.0. */ + firstarg = (*args && **args == '?' ? *args++ : *args); reply = *args ? *args++ : ops['A'] ? "reply" : "REPLY"; + if (ops['A'] && *args) { zwarnnam(name, "only one array argument allowed", NULL, 0); return 1; diff --git a/Src/exec.c b/Src/exec.c index 9c7a1ceb5..dc281675f 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -3144,9 +3144,24 @@ static int cancd2(char *s) { struct stat buf; - char *us = unmeta(s); + char *us, *us2 = NULL; + /* + * If CHASEDOTS and CHASELINKS are not set, we want to rationalize the + * path by removing foo/.. combinations in the logical rather than + * the physical path. If either is set, we test the physical path. + */ + if (!isset(CHASEDOTS) && !isset(CHASELINKS)) { + if (*s != '/') + us = tricat(pwd[1] ? pwd : "", "/", s); + else + us = ztrdup(s); + fixdir(us2 = us); + } else + us = unmeta(s); return !(access(us, X_OK) || stat(us, &buf) || !S_ISDIR(buf.st_mode)); + if (us2) + free(us2); } /**/ diff --git a/Src/glob.c b/Src/glob.c index ea4980b8b..cf22ef923 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -2724,6 +2724,9 @@ charmatch(Comp c, char *x, char *y) * Here we bypass tulower() and tuupper() for speed. */ int xi = (STOUC(UNMETA(x)) & 0xff), yi = (STOUC(UNMETA(y)) & 0xff); + /* A NULL is a real null, since a \000 would be metafied. */ + if (!*x || !*y) + return 0; return xi == yi || (((c->stat & C_IGNCASE) ? ((isupper(xi) ? tolower(xi) : xi) == @@ -2926,7 +2929,10 @@ rangematch(char **patptr, int ch, int rchar) * and optional ^ have already been skipped. */ char *pat = *patptr; -#ifdef HAVE_STRCOLL + /* We don't use strcoll() for ranges, since it can have side + * effects. It's less necessary now we have [:posix:] ranges. + */ +#if 0 char l_buf[2], r_buf[2], ch_buf[2]; ch_buf[0] = ch; @@ -2944,7 +2950,7 @@ rangematch(char **patptr, int ch, int rchar) break; } else if (*pat == '-' && pat[-1] != rchar && pat[1] != Outbrack) { -#ifdef HAVE_STRCOLL +#if 0 l_buf[0] = PPAT(-1); r_buf[0] = PAT(1); if (strcoll(l_buf, ch_buf) <= 0 && diff --git a/Src/lex.c b/Src/lex.c index 33b6598b9..069f9b39b 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -241,6 +241,7 @@ lexsave(void) cmdsp = 0; inredir = 0; hdocs = NULL; + histactive = 0; ls->next = lstack; lstack = ls; diff --git a/Src/options.c b/Src/options.c index 2eb73690e..0207cd232 100644 --- a/Src/options.c +++ b/Src/options.c @@ -91,6 +91,7 @@ static struct optname optns[] = { {NULL, "braceccl", 0, BRACECCL}, {NULL, "bsdecho", OPT_EMULATE|OPT_SH, BSDECHO}, {NULL, "cdablevars", 0, CDABLEVARS}, +{NULL, "chasedots", 0, CHASEDOTS}, {NULL, "chaselinks", 0, CHASELINKS}, {NULL, "clobber", OPT_ALL, CLOBBER}, {NULL, "completealiases", 0, COMPLETEALIASES}, diff --git a/Src/parse.c b/Src/parse.c index 626ffc982..658a66660 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -72,7 +72,13 @@ struct list dummy_list; #define YYERROR { tok = LEXERR; return NULL; } #define YYERRORV { tok = LEXERR; return; } -#define COND_ERROR(X,Y) do{herrflush();zerr(X,Y,0);YYERROR}while(0) +#define COND_ERROR(X,Y) do { \ + zwarn(X,Y,0); \ + herrflush(); \ + if (noerrs != 2) \ + errflag = 1; \ + YYERROR \ +} while(0) #define make_list() allocnode(N_LIST) #define make_sublist() allocnode(N_SUBLIST) @@ -140,11 +146,13 @@ par_event(void) } if (!l) { if (errflag) { - yyerror(); + yyerror(0); return NULL; } + yyerror(1); herrflush(); - yyerror(); + if (noerrs != 2) + errflag = 1; return NULL; } else { l->right = par_event(); @@ -163,7 +171,7 @@ parse_list(void) yylex(); ret = par_list(); if (tok == LEXERR) { - yyerror(); + yyerror(0); return NULL; } return ret; @@ -1480,7 +1488,7 @@ par_cond_multi(char *a, LinkList l) /**/ static void -yyerror(void) +yyerror(int noerr) { int t0; @@ -1488,9 +1496,11 @@ yyerror(void) if (!yytext || !yytext[t0] || yytext[t0] == '\n') break; if (t0 == 20) - zerr("parse error near `%l...'", yytext, 20); + zwarn("parse error near `%l...'", yytext, 20); else if (t0) - zerr("parse error near `%l'", yytext, t0); + zwarn("parse error near `%l'", yytext, t0); else - zerr("parse error", NULL, 0); + zwarn("parse error", NULL, 0); + if (!noerr && noerrs != 2) + errflag = 1; } diff --git a/Src/utils.c b/Src/utils.c index d82f62694..f86c18b16 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -30,23 +30,12 @@ #include "zsh.mdh" #include "utils.pro" -/* Print an error */ - -/**/ -void -zwarnnam(const char *cmd, const char *fmt, const char *str, int num) -{ - int waserr; - - waserr = errflag; - zerrnam(cmd, fmt, str, num); - errflag = waserr; -} - /* name of script being sourced */ /**/ char *scriptname; + +/* Print an error */ /**/ void @@ -57,7 +46,27 @@ zerr(const char *fmt, const char *str, int num) errflag = 1; return; } + zwarn(fmt, str, num); errflag = 1; +} + +/**/ +void +zerrnam(const char *cmd, const char *fmt, const char *str, int num) +{ + if (errflag || noerrs) + return; + + zwarnnam(cmd, fmt, str, num); + errflag = 1; +} + +/**/ +void +zwarn(const char *fmt, const char *str, int num) +{ + if (errflag || noerrs) + return; trashzle(); /* * scriptname is set when sourcing scripts, so that we get the @@ -68,25 +77,29 @@ zerr(const char *fmt, const char *str, int num) nicezputs((isset(SHINSTDIN) && !locallevel) ? "zsh" : scriptname ? scriptname : argzero, stderr); fputs(": ", stderr); - zerrnam(NULL, fmt, str, num); + zerrmsg(fmt, str, num); } /**/ void -zerrnam(const char *cmd, const char *fmt, const char *str, int num) +zwarnnam(const char *cmd, const char *fmt, const char *str, int num) { - if (cmd) { - if (errflag || noerrs) - return; - errflag = 1; - trashzle(); - if (unset(SHINSTDIN) || locallevel) { - nicezputs(scriptname ? scriptname : argzero, stderr); - fputs(": ", stderr); - } - nicezputs(cmd, stderr); + if (errflag || noerrs) + return; + trashzle(); + if (unset(SHINSTDIN) || locallevel) { + nicezputs(scriptname ? scriptname : argzero, stderr); fputs(": ", stderr); } + nicezputs(cmd, stderr); + fputs(": ", stderr); + zerrmsg(fmt, str, num); +} + +/**/ +void +zerrmsg(const char *fmt, const char *str, int num) +{ while (*fmt) if (*fmt == '%') { fmt++; @@ -302,7 +315,7 @@ slashsplit(char *s) /**/ static int -xsymlinks(char *s, int flag) +xsymlinks(char *s) { char **pp, **opp; char xbuf2[PATH_MAX*2], xbuf3[PATH_MAX*2]; @@ -325,15 +338,9 @@ xsymlinks(char *s, int flag) *p = '\0'; continue; } - if (unset(CHASELINKS)) { - strcat(xbuf, "/"); - strcat(xbuf, *pp); - zsfree(*pp); - continue; - } sprintf(xbuf2, "%s/%s", xbuf, *pp); t0 = readlink(unmeta(xbuf2), xbuf3, PATH_MAX); - if (t0 == -1 || !flag) { + if (t0 == -1) { strcat(xbuf, "/"); strcat(xbuf, *pp); zsfree(*pp); @@ -342,9 +349,9 @@ xsymlinks(char *s, int flag) metafy(xbuf3, t0, META_NOALLOC); if (*xbuf3 == '/') { strcpy(xbuf, ""); - xsymlinks(xbuf3 + 1, flag); + xsymlinks(xbuf3 + 1); } else - xsymlinks(xbuf3, flag); + xsymlinks(xbuf3); zsfree(*pp); } } @@ -352,19 +359,19 @@ xsymlinks(char *s, int flag) return ret; } -/* expand symlinks in s, and remove other weird things */ +/* + * expand symlinks in s, and remove other weird things: + * note that this always expands symlinks. + */ /**/ char * xsymlink(char *s) { - if (unset(CHASELINKS)) - return ztrdup(s); if (*s != '/') return NULL; *xbuf = '\0'; - if (!xsymlinks(s + 1, 1)) - return ztrdup(s); + xsymlinks(s + 1); if (!*xbuf) return ztrdup("/"); return ztrdup(xbuf); @@ -374,15 +381,10 @@ xsymlink(char *s) void print_if_link(char *s) { - int chase; - if (*s == '/') { - chase = opts[CHASELINKS]; - opts[CHASELINKS] = 1; *xbuf = '\0'; - if (xsymlinks(s + 1, 1)) + if (xsymlinks(s + 1)) printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout); - opts[CHASELINKS] = chase; } } @@ -573,7 +575,8 @@ getnameddir(char *name) /* Retrieve an entry from the password table/database for this user. */ struct passwd *pw; if ((pw = getpwnam(name))) { - char *dir = xsymlink(pw->pw_dir); + char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir) + : ztrdup(pw->pw_dir); adduserdir(name, dir, ND_USERNAME, 1); str = dupstring(dir); zsfree(dir); @@ -3202,7 +3205,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc) int meta = 0, control = 0; if (fromwhere == 6) - t = tmp; + t = buf = tmp; else if (fromwhere != 4) t = buf = zhalloc(strlen(s) + 1); else { diff --git a/Src/zsh.h b/Src/zsh.h index 2070e9b3f..d2b64b9bb 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1171,6 +1171,7 @@ enum { BRACECCL, BSDECHO, CDABLEVARS, + CHASEDOTS, CHASELINKS, CLOBBER, COMPLETEALIASES, diff --git a/configure.in b/configure.in index a5dbc6413..1452d8c2d 100644 --- a/configure.in +++ b/configure.in @@ -100,7 +100,7 @@ fi]) dnl Do you want large file support, if available? undefine([lfs])dnl AC_ARG_ENABLE(lfs, -[ --enable-lfs turn on support for large files], +[ --disable-lfs turn off support for large files], [lfs="$enableval"], [lfs=yes]) dnl Pathnames for global zsh scripts @@ -183,7 +183,7 @@ AC_SUBST(zlogout)dnl dnl Do you want dynamically loaded binary modules. undefine([dynamic])dnl AC_ARG_ENABLE(dynamic, -[ --enable-dynamic allow dynamically loaded binary modules], +[ --disable-dynamic turn off dynamically loaded binary modules], [dynamic="$enableval"], [dynamic=yes]) dnl Do you want to compile as K&R C. @@ -599,7 +599,7 @@ main() { return sizeof(ino_t) < 8; } if test $lfs != no -o $zsh_cv_off_t_is_64_bit = yes \ -o $zsh_cv_ino_t_is_64_bit = yes; then AC_CACHE_CHECK(if compiler has a 64 bit type, zsh_cv_64_bit_type, - [if test $lfs != xyes -a $lfs != xno; then + [if test $lfs != yes -a $lfs != no; then zsh_64_BIT_TYPE(${lfs}, zsh_cv_64_bit_type, force) else zsh_64_BIT_TYPE(long long, zsh_cv_64_bit_type) -- cgit 1.4.1