summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog370
-rw-r--r--Completion/Base/Utility/_call_program17
-rw-r--r--Completion/Base/Utility/_describe2
-rw-r--r--Completion/Base/Widget/_complete_debug2
-rw-r--r--Completion/Linux/Command/_btrfs3
-rw-r--r--Completion/Linux/Command/_cryptsetup175
-rw-r--r--Completion/Unix/Command/_augeas58
-rw-r--r--Completion/Unix/Command/_dvi2
-rw-r--r--Completion/Unix/Command/_git70
-rw-r--r--Completion/Unix/Command/_graphicsmagick2
-rw-r--r--Completion/Unix/Command/_imagemagick2
-rw-r--r--Completion/Unix/Command/_notmuch3
-rw-r--r--Completion/Unix/Command/_perforce15
-rw-r--r--Completion/Unix/Command/_quilt425
-rw-r--r--Completion/Unix/Command/_stgit11
-rw-r--r--Completion/Unix/Command/_sysctl9
-rwxr-xr-xCompletion/Unix/Type/_mime_types4
-rw-r--r--Completion/Unix/Type/_net_interfaces27
-rw-r--r--Completion/Unix/Type/_path_files22
-rw-r--r--Completion/X/Command/_mplayer2
-rw-r--r--Completion/Zsh/Command/_setopt22
-rw-r--r--Completion/Zsh/Command/_typeset15
-rw-r--r--Completion/Zsh/Command/_unsetopt10
-rw-r--r--Config/defs.mk.in1
-rw-r--r--Config/version.mk4
-rw-r--r--Doc/Makefile.in6
-rw-r--r--Doc/Zsh/builtins.yo36
-rw-r--r--Doc/Zsh/contrib.yo22
-rw-r--r--Doc/Zsh/expn.yo29
-rw-r--r--Doc/Zsh/grammar.yo9
-rw-r--r--Doc/Zsh/mod_computil.yo12
-rw-r--r--Doc/Zsh/mod_parameter.yo8
-rw-r--r--Doc/Zsh/mod_zutil.yo2
-rw-r--r--Doc/Zsh/options.yo4
-rw-r--r--Doc/Zsh/params.yo2
-rw-r--r--Doc/Zsh/prompt.yo7
-rw-r--r--Doc/Zsh/zle.yo2
-rw-r--r--Etc/FAQ.yo2
-rw-r--r--Etc/zsh-development-guide16
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_git131
-rw-r--r--Functions/VCS_Info/VCS_INFO_quilt8
-rw-r--r--Functions/VCS_Info/VCS_INFO_reposub7
-rw-r--r--Misc/vcs_info-examples2
-rw-r--r--NEWS33
-rw-r--r--README12
-rw-r--r--Src/Modules/parameter.c55
-rw-r--r--Src/Modules/pcre.c2
-rw-r--r--Src/Zle/compcore.c2
-rw-r--r--Src/Zle/compctl.c2
-rw-r--r--Src/Zle/zle_refresh.c3
-rw-r--r--Src/builtin.c4
-rw-r--r--Src/exec.c187
-rw-r--r--Src/glob.c24
-rw-r--r--Src/hashtable.c15
-rw-r--r--Src/hist.c21
-rw-r--r--Src/init.c37
-rw-r--r--Src/jobs.c4
-rw-r--r--Src/lex.c110
-rw-r--r--Src/params.c39
-rw-r--r--Src/parse.c290
-rw-r--r--Src/pattern.c10
-rw-r--r--Src/prompt.c38
-rw-r--r--Src/signals.c15
-rw-r--r--Src/subst.c15
-rw-r--r--Src/utils.c44
-rw-r--r--Src/zsh.h4
-rw-r--r--Src/zsh.mdd3
-rw-r--r--Src/ztype.h9
-rw-r--r--Test/A04redirect.ztst78
-rw-r--r--Test/A05execution.ztst36
-rw-r--r--Test/C01arith.ztst4
-rw-r--r--Test/C04funcdef.ztst10
-rw-r--r--Test/D02glob.ztst7
-rw-r--r--Test/V07pcre.ztst9
-rw-r--r--configure.ac36
75 files changed, 1967 insertions, 769 deletions
diff --git a/ChangeLog b/ChangeLog
index 5ccfd42b0..969273b5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,373 @@
+2014-10-07 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: Config/version.mk: 5.0.7
+
+2014-10-06 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33365: Src/exec.c: avoid buffer overflow for very long fds in >&
+ fd syntax.
+
+2014-10-06 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted (discussed offline): README: update description of
+ integer import problem.
+
+2014-10-04 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33354: Src/jobs.c, Test/A05execution.ztst: when backgrounding
+ a pipeline, close all pipe descriptors in the parent; add test
+ for both this and 33345+33346
+
+2014-10-03 Bart Schaefer <schaefer@zsh.org>
+
+ * 33346: Src/parse.c: another bit of the 33345 repair
+
+2014-10-03 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33345: Src/parse.c, Test/C04funcdef.ztst: fix longstanding
+ anonoymous function corruption of "complex" state that allowed
+ complex wordcode to be passed to execsimple(), causing crash.
+
+ * unposted: src/parse.c: comments were the wrong way round.
+
+ * 33343: Src/parse.c, Test/C04funcdef.ztst: variant anonymous
+ function syntax with arguments.
+
+2014-10-02 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: 5.0.6-dev-1.
+
+2014-10-02 Oliver Kiddle <opk@zsh.org>
+
+ * 33323: Completion/Zsh/Command/_typeset, Doc/Zsh/builtins.yo,
+ Src/builtin.c: fix bug in removing math functions and complete
+ -M option to functions
+
+ * 33315: Completion/Unix/Command/_sysctl: fix pattern to
+ match freebsd10 and later
+
+2014-10-02 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted: remove "major".
+
+ * 33330: README, Etc/FAQ.yo: information for forthcoming 5.0.7
+ release.
+
+ * 33332: Test/C01arith.ztst: test numeric import fix in 33276.
+
+2014-10-02 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33320 (cf. PWS 33311): Completion/Base/Completer/_expand_alias,
+ Src/Zle/compcore.c, Src/utils.c, Src/ztype.h: revert 33069; add
+ typtab_flags bits (replaces specialcomma boolean) to record any
+ unusual handling of typtab entries; signal safety; make bangchar
+ non-special during completion lexing of the command line.
+
+2014-10-02 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33325: Src/exec.c, Test/A05execution.ztst: fix ksh autoloads
+ with redirections on function definitions.
+
+2014-10-01 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33319: Doc/Zsh/grammar.yo: fix parens in example from 33312
+
+2014-10-02 Axel Beckert <abe@deuxchevaux.org>
+
+ * 33284: Mathieu Malaterre: Completion/Unix/Command/_{graphics,
+ image}magick: Add missing JPEG 2000 file extensions.
+
+2014-10-01 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33312: Doc/Zsh/builtins.yo, Doc/Zsh/grammar.yo: document
+ redirections applied to function definitions.
+
+2014-09-30 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33298: Src/lex.c: make lexrestore() more signal-safe
+
+2014-09-30 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33294: Src/Modules/parameter.c, Test/A04redirect.ztst:
+ functions[func] value for functions with redirections and
+ extra tests.
+
+ * 33293: Src/Zle/compctl.c, Src/Zle/zle_refresh.c: fix warnings
+ from swish new compilers with a contemporary outlook.
+
+2014-09-29 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33286: Src/exec.c, Test/A04redirect.ztst: handle redirections
+ for multiple named functions.
+
+ * 33285: NEWS, Src/exec.c, Src/hashtable.c, Src/parse.c,
+ Src/signals.c, Src/zsh.h, Test/A04redirect.ztst: redirections in
+ function definitions are applied at execution not definition.
+
+2014-09-29 Frank Terbeck <ft@bewatermyfriend.org>
+
+ * 33277: Functions/VCS_Info/VCS_INFO_reposub: Fix
+ VCS_INFO_reposub's command expansion
+
+2014-09-29 Peter Stephenson <p.stephenson@samsung.com>
+
+ * users/19183: Src/hist.c: handle unlikely error case with
+ fdopen() better.
+
+ * 33276: Src/params.c, Src/zsh.h: safer import of numerical
+ variables from environment.
+
+2014-09-28 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33268: Src/exec.c, Src/init.c, Src/signals.c: interactive shells
+ treat SIGPIPE like SIGHUP if and only if SHTTY is disconnected
+
+2014-09-27 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33256: Src/prompt.c: fix prompttrunc() counting of %{ %} spans
+
+2014-09-26 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33242: Src/parse.c: don't treat tokens immediately following
+ end of shell constructs for, while, repeat, if as being in
+ command position.
+
+ * Wieland Hoffmann: 33252: Completion/Unix/Command/_notmuch:
+ complete more subcommands.
+
+2014-09-25 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * users/19143: Src/glob.c: **/*(odonT) didn't work because
+ the trailing slash wasn't properly ignored.
+
+2014-09-25 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted: NEWS: tweak last change.
+
+2014-09-24 Oliver Kiddle <opk@zsh.org>
+
+ * 33238: Completion/Unix/Command/_quilt: correct return values
+
+2014-09-24 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Eric Cook: 33224: Completion/Linux/Command/_btrfs: complete
+ directory as second argument.
+
+2014-09-23 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33223: Completion/Base/Utility/_call_program: discard stderr
+ except when _complete_debug is in progress.
+
+2014-09-23 Øystein Walle <oystwa@gmail.com>
+
+ * 33179: Completion/Unix/Command/_git: _git: updates for Git 2.0.0
+
+ * 33176: Completion/Unix/Command/_git: _git: Add missing --list to
+ git-tag
+
+ * 33178: Completion/Unix/Command/_git: _git: updates for Git 2.1.0
+
+ * 33177: Completion/Unix/Command/_git: _git: fix typo in git-apply
+
+ * 33180: Completion/Unix/Command/_git: _git: add missing --3way
+ option
+
+2014-09-23 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: NEWS: more minor tweaks.
+
+ * unposted: NEWS: mention numeric output with underscore separators.
+
+ * unposted: NEWS: mention new
+ /usr/local/share/zsh/site-functions default.
+
+2014-09-23 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33221 (including 33173 from Anthony Heading):
+ Completion/Unix/Command/_perforce: complete directories
+ when handling unmaintained files and rationalise code that does
+ this.
+
+ * unposted: Completion/Unix/Command/_dvi: add dvipdf to list of
+ commands.
+
+ * Richard Hartmann: 33218: Completion/X/Command/_mplayer:
+ complete m4a files.
+
+2014-09-22 Oliver Kiddle <opk@zsh.org>
+
+ * 33198: Completion/Unix/Command/_augeas: new augtool completion
+
+ * users/19113: Completion/Linux/_cryptsetup: reorganised function
+
+2014-09-22 Daniel Hahler <dhahler@gmail.com>
+
+ * 33217: Functions/VCS_Info/Backends/VCS_INFO_get_data_git:
+ vcs_info: use `--ignore-submodules=dirty` with diff/diff-index
+
+2014-09-22 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33208: Tanu Kaskinen: improve printing of paths at end of
+ configuration.
+
+2014-09-20 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33214 (modified yet further): configure.ac: test prefixes better.
+
+ * 33213: configure.ac, Config/defs.mk.in: try again.
+
+ * 33212: Src/zsh.mdd: Src/init.c, Src/zsh.mdd, configure.ac: add
+ /usr/local/share/zsh/site-functions to head of fpath if not
+ present from result of running configure. There's no
+ configuration for this as it serves as a fallback.
+
+ * Tanu Kaskinen: 33209: Doc/Makefile.in: don't fail
+ catastrophically when builing zsh.texi if yodl isn't available.
+
+2014-09-19 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33206: Doc/Zsh/mod_computil.yo: fix compdescribe doc
+
+ * 33205: Completion/Base/Utility/_describe: if passed both an
+ array of completions and an array of display strings, keep them
+ in sync when filtering for matches.
+
+2014-09-18 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * users/19097: Doc/Zsh/mod_parameter.yo,
+ Src/Modules/parameter.c: remove functypetrace and instead add
+ cross-reference to zsh_eval_context.
+
+2014-09-16 Marc Finet <m.dreadlock@gmail.com>
+
+ * 33188: Functions/VCS_Info/Backends/VCS_INFO_get_data_git:
+ vcs_info git: set rrn before using it
+
+ * 33184: Doc/Zsh/contrib.yo,
+ Functions/VCS_Info/Backends/VCS_INFO_get_data_git: vcs_info git:
+ consider patches for rebase
+
+2014-09-16 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33136: Doc/Zsh/expn.yo, Src/glob.c: P glob qualifier appends
+ words when negated.
+
+ * 33137: Completion/Unix/Type/_path_files: complete # to introduce
+ a glob flag
+
+2014-09-14 Marc Finet <m.dreadlock@gmail.com>
+
+ * 33149: Misc/vcs_info-examples: vcs_info examples: fix typo
+
+ * 33151: Completion/Unix/Command/_git: completion git: support
+ aliases when \n exist
+
+ * 33147: Functions/VCS_Info/Backends/VCS_INFO_get_data_git:
+ vcs_info git: detect revert or cherry-pick with multiple commits
+
+ * 33148: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt:
+ refactor standalone detection
+
+ * 33145: Functions/VCS_Info/Backends/VCS_INFO_get_data_git:
+ vcs_info git: fix applied-string name
+
+ * 33150: Completion/Unix/Command/_git: completion git: fix
+ send-email --confirm values
+
+2014-09-12 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33143: Src/init.c: POSIX_ARGZERO more closely matches bash et al.
+
+2014-09-12 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * users/19075: Doc/Zsh/mod_parameter.yo,
+ Src/Modules/parameter.c: $functypestack gives "function",
+ "source" or "eval" for parallel element of $funcstack.
+
+2014-09-09 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Eric Cook: 33132: Completion/Unix/Type/_net_interfaces: use ip
+ on Linux to get interface names.
+
+2014-09-08 Peter Stephenson <p.stephenson@samsung.com>
+
+ * users/19059 based on users/19058 (Paulo César Pereira de
+ Andrade): Src/pattern.c, Test/D02glob.ztst: remove inefficiency
+ with multiple "*"s in pattern matching and add test.
+
+2014-09-07 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33122: Src/Modules/pcre.c, Test/V07pcre.ztst: typo from 32891
+ caused incorrect matches for pcre_match -n
+
+2014-09-06 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33118: Src/subst.c: record original param unset state when
+ ${name:#word} et al. need to treat empty the same as unset, to
+ avoid incorrect NO_UNSET error
+
+ * 33116: Src/hist.c: followup to 32580 to prevent double-locking
+ with shared or incremental history
+
+ * unposted: Doc/Zsh/expn.yo: clarify ${(~j.|.)array} example
+
+2014-08-21 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33061: Completion/Zsh/Command/_setopt,
+ Completion/Zsh/Command/_unsetopt: More useful setopt / unsetopt
+ completion.
+
+2014-09-04 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33110: Doc/Zsh/expn.yo: document use of $IFS[1] for variable
+ padding.
+
+2014-09-04 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Alexandre Rames: 33108: Completion/Unix/Command/_stgit:
+ --patch completion.
+
+ * 33091: Doc/Zsh/builtins.yo: improve documentation for ttyctl.
+
+2014-09-03 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33100: Src/exec.c: check $fd more rigorously in "exec {fd}<&-"
+
+ * 33088: Completion/Base/Widget/_complete_debug: indentation in $PS4
+
+2014-09-01 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * Mark Oteiza: 33081: Completion/Unix/Type/_mime_types: suppress
+ error message if unnecessary file not found.
+
+2014-08-31 Barton E. Schaefer <schaefer@zsh.org>
+
+ * unposted: Test/A05execution.ztst: further tweaking of the
+ descriptor leak regression test that sometimes hangs
+
+ * 33077: Src/exec.c: SHTTY = -1 when closing it in closem()
+
+2014-08-30 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33070: Doc/Zsh/prompt.yo, Src/prompt.c: add %(e..) based on %e
+
+ * 33069: Completion/Base/Completer/_expand_alias: remove internal
+ quoting before looking up aliases when expanding aliases in an
+ unquoted word
+
+2014-08-29 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33057: Doc/Zsh/prompt.yo, Src/prompt.c: %e in prompts shows
+ evaluation / execution depth.
+
2014-08-28 Peter Stephenson <p.w.stephenson@ntlworld.com>
+ * 33062: Etc/zsh-development-guide: update note on use of
+ .distfiles based on 33047.
+
+ * unposted: Config/version.mk: update to 5.0.6-dev-0 for new
+ commits post release.
+
* unposted: Config/version.mk: 5.0.6.
2014-08-24 Peter Stephenson <p.w.stephenson@ntlworld.com>
@@ -161,7 +529,7 @@
Completion/openSUSE/Command/_SuSEconfig ->
Completion/openSUSE/Command/_SUSEconfig: rename file.
-2014-08-04 Barton E. Schaefer <schaefer@brasslantern.com>
+2014-08-04 Barton E. Schaefer <schaefer@zsh.org>
* Miles Ohlrich: 32958: Src/Zle/compctl.c: bitwise logic fix
diff --git a/Completion/Base/Utility/_call_program b/Completion/Base/Utility/_call_program
index b038a80bc..b65764827 100644
--- a/Completion/Base/Utility/_call_program
+++ b/Completion/Base/Utility/_call_program
@@ -1,6 +1,13 @@
#autoload +X
-local tmp
+local tmp err_fd=-1
+
+if (( ${debug_fd:--1} > 2 ))
+then exec {err_fd}>&2 # debug_fd is saved stderr, 2 is log file
+else exec {err_fd}>/dev/null
+fi
+
+{ # Begin "always" block
if zstyle -s ":completion:${curcontext}:${1}" command tmp; then
if [[ "$tmp" = -* ]]; then
@@ -10,4 +17,10 @@ if zstyle -s ":completion:${curcontext}:${1}" command tmp; then
fi
else
eval "$argv[2,-1]"
-fi
+fi 2>&$err_fd
+
+} always {
+
+exec {err_fd}>&-
+
+}
diff --git a/Completion/Base/Utility/_describe b/Completion/Base/Utility/_describe
index f899b0ad0..1a9f52f5d 100644
--- a/Completion/Base/Utility/_describe
+++ b/Completion/Base/Utility/_describe
@@ -96,7 +96,7 @@ while _tags; do
fi
if [[ -n $_mats ]]; then
- compadd "$_opts[@]" "${(@)_expl:/-J/-2V}" -D $_strs - \
+ compadd "$_opts[@]" "${(@)_expl:/-J/-2V}" -D $_strs -O $_mats - \
"${(@)${(@M)${(@P)_mats}##([^:\\]|\\?)##}//\\(#b)(?)/$match[1]}"
else
compadd "$_opts[@]" "${(@)_expl:/-J/-2V}" -D $_strs - \
diff --git a/Completion/Base/Widget/_complete_debug b/Completion/Base/Widget/_complete_debug
index eff0f8e28..604486376 100644
--- a/Completion/Base/Widget/_complete_debug
+++ b/Completion/Base/Widget/_complete_debug
@@ -12,6 +12,8 @@ integer debug_fd=-1
exec {debug_fd}>&2 2>| $tmp
fi
+ local -a debug_indent; debug_indent=( '%'{3..20}'(e. .)' )
+ local PROMPT4 PS4="${(j::)debug_indent}+%N:%i> "
setopt xtrace
: $ZSH_NAME $ZSH_VERSION
${1:-_main_complete}
diff --git a/Completion/Linux/Command/_btrfs b/Completion/Linux/Command/_btrfs
index c8f87ef70..77deeefcb 100644
--- a/Completion/Linux/Command/_btrfs
+++ b/Completion/Linux/Command/_btrfs
@@ -125,7 +125,8 @@ while (( $#state )); do
args+=(
'-r[readonly snapshot]'
'*-i[assign to qgroup]:qgroup: _message "qgroup"'
- '1:snapshot:_files -/'
+ '1:source directory:_files -/'
+ '2:snapshot name or destination:_files -/'
)
;;
subvolume:list)
diff --git a/Completion/Linux/Command/_cryptsetup b/Completion/Linux/Command/_cryptsetup
index 3519336e8..0e7a5d37e 100644
--- a/Completion/Linux/Command/_cryptsetup
+++ b/Completion/Linux/Command/_cryptsetup
@@ -1,103 +1,82 @@
#compdef cryptsetup
-## completion for cryptsetup 1.3.0, based on cryptsetup(1)
-function _cryptsetup_action {
- typeset -a actions
- actions=(
- 'create:create a mapping'
- 'remove:remove an existing mapping'
- 'status:report mapping status'
- 'resize:resize an active mapping'
- 'luksFormat:Initialize a LUKS partition'
- 'luksOpen:Open LUKS partition'
- 'luksClose:remove an existing mapping'
- 'luksSuspend:suspend active device'
- 'luksResume:resume suspended device'
- 'luksAddKey:add a new key'
- 'luksRemoveKey:remove a key'
- 'luksChangeKey:change a key'
- 'luksKillSlot:wipe key from slot'
- 'luksUUID:print/change device UUID'
- 'isLuks:check if device is a LUKS partition'
- 'luksDump:dump header information'
- 'luksHeaderBackup:store binary backup of headers'
- 'luksHeaderRestore:restore header backup'
- )
- _describe action actions
-}
+local curcontext="$curcontext" ret=1
+local -a actions state line expl
-function _cryptsetup_device {
- typeset expl
- _wanted file expl device \
- _files
-}
+_arguments \
+ '(-v --verbose)'{-v,--verbose}'[enable verbose mode]' \
+ '--debug[enable debug mode]' \
+ '(-h --hash)'{-h,--hash}'[hash algorithm]:hash algorithm' \
+ '(-c --cipher)'{-c,--cipher}'[set cipher]:cipher specification' \
+ '(-y --verify-passphrase)'{-y,--verify-passphrase}'[query for password twice]' \
+ '(-d --key-file)'{-d,--key-file}'[set keyfile]:key file:_files' \
+ '(-l --keyfile-size)'{-l,--keyfile-size}'[set keyfile size]:size (bytes)' \
+ '--new-keyfile-size[set new keyfile size (luksAddKey)]:size (bytes)' \
+ '--master-key-file[set master key]:key file:_files' \
+ '--dump-master-key[dump luks master key]' \
+ '(--use-urandom)--use-random[use /dev/random to generate volume key]' \
+ '(--use-random)--use-urandom[use /dev/urandom to generate volume key]' \
+ '(-S --key-slot)'{-S,--key-slot}'[select key slot]:key slot' \
+ '(-s --key-size)'{-s,--key-size}'[set key size]:size (bits)' \
+ '(-b --size)'{-b,--size}'[force device size]:sectors' \
+ '(-o --offset)'{-o,--offset}'[set start offset]:sectors' \
+ '(-p --skip)'{-p,--skip}'[data to skip at beginning]:sectors' \
+ '--readonly[set up read-only mapping]' \
+ '(-i --iter-time)'{-i,--iter-time}'[set password processing duration]:duration (milliseconds)' \
+ '(-q --batch-mode)'{-q,--batch-mode}'[do not ask for confirmation]' \
+ '(-t --timeout)'{-t,--timeout}'[set password prompt timeout]:timeout (seconds)' \
+ '(-T --tries)'{-T,--tries}'[set maximum number of retries]:number of retries' \
+ '--align-payload[set payload alignment]:sectors' \
+ '--uuid[set device UUID]:uuid' \
+ '(- : *)--version[show version information]' \
+ ':action:->actions' \
+ '*::arguments:->action-arguments' && ret=0
-function _cryptsetup_mapping {
- typeset expl
- _wanted file expl 'mapping name' \
- _path_files -W /dev/mapper
-}
+case $state in
+ actions)
+ actions=(
+ 'create:create a mapping'
+ 'remove:remove an existing mapping'
+ 'status:report mapping status'
+ 'resize:resize an active mapping'
+ 'luksFormat:initialize a LUKS partition'
+ 'luksOpen:open LUKS partition'
+ 'luksClose:remove an existing mapping'
+ 'luksSuspend:suspend active device'
+ 'luksResume:resume suspended device'
+ 'luksAddKey:add a new key'
+ 'luksRemoveKey:remove a key'
+ 'luksChangeKey:change a key'
+ 'luksKillSlot:wipe key from slot'
+ 'luksUUID:print/change device UUID'
+ 'isLuks:check if device is a LUKS partition'
+ 'luksDump:dump header information'
+ 'luksHeaderBackup:store binary backup of headers'
+ 'luksHeaderRestore:restore header backup'
+ )
+ _describe action actions && ret=0
+ ;;
+ action-arguments)
+ local -a args
+ local mapping=':mapping:_path_files -W /dev/mapper'
+ local device=':device:_files'
+ case ${words[1]} in
+ create) args=( $mapping $device );;
+ luksKillSlot) args=( $device ':key slot number' );;
+ luksOpen) args=( $device $mapping );;
+ remove|status|resize|luksClose|luksSuspend|luksResume) args=( $mapping );;
+ luks(AddKey|RemoveKey|DelKey|UUID|Dump)|isLuks) args=( $device );;
+ luks(Format|AddKey|RemoveKey|ChangeKey))
+ args=( $device ':key file:_files' )
+ ;;
+ luksHeader*) args=( $device '--header-backup-file:file:_files' );;
+ *)
+ _default
+ return
+ ;;
+ esac
+ _arguments $args && ret=0
+ ;;
+esac
-function _cryptsetup_arguments {
-
- case ${words[1]} in
-
- create)
- _arguments ':mapping:_cryptsetup_mapping' ':device:_cryptsetup_device'
- ;;
-
- remove|status|resize|luksClose|luksSuspend|luksResume)
- _arguments ': :_cryptsetup_mapping'
- ;;
-
- luks(AddKey|RemoveKey|DelKey|UUID|Dump)|isLuks)
- _arguments ': :_cryptsetup_device'
- ;;
-
- luks(Format|AddKey|RemoveKey|ChangeKey))
- _arguments ': :_cryptsetup_device' ':key file:_files'
- ;;
-
- luksKillSlot)
- _arguments ': :_cryptsetup_device' ':key slot number'
- ;;
-
- luksOpen)
- _arguments ': :_cryptsetup_device' ': :_cryptsetup_mapping'
- ;;
-
- esac
-}
-
-function _cryptsetup {
- _arguments \
- '(-v --verbose)'{-v,--verbose}'[enable verbose mode]' \
- '--debug[enable debug mode]' \
- '(-h --hash)'{-h,--hash}'[hash algorithm]:hash algorithm' \
- '(-c --cipher)'{-c,--cipher}'[set cipher]:cipher specification' \
- '(-y --verify-passphrase)'{-y,--verify-passphrase}'[query for password twice]' \
- '(-d --key-file)'{-d,--key-file}'[set keyfile]:key file:_files' \
- '(-l --keyfile-size)'{-l,--keyfile-size}'[set keyfile size]:bytes' \
- '--new-keyfile-size[set new keyfile size (luksAddKey)]:bytes' \
- '--master-key-file[set master key]:key file:_files' \
- '--dump-master-key[dump luks master key]' \
- '(--use-urandom)--use-random[use /dev/random to generate volume key]' \
- '(--use-random)--use-urandom[use /dev/urandom to generate volume key]' \
- '(-S --key-slot)'{-S,--key-slot}'[select key slot]:key slot' \
- '(-s --key-size)'{-s,--key-size}'[set key size]:bits' \
- '(-b --size)'{-b,--size}'[force device size]:sectors' \
- '(-o --offset)'{-o,--offset}'[set start offset]:sectors' \
- '(-p --skip)'{-p,--skip}'[data to skip at beginning]:sectors' \
- '--readonly[set up read-only mapping]' \
- '(-i --iter-time)'{-i,--iter-time}'[set password processing duration]:milliseconds' \
- '(-q --batch-mode)'{-q,--batch-mode}'[do not ask for confirmation]' \
- '(-t --timeout)'{-t,--timeout}'[set password prompt timeout]:seconds' \
- '(-T --tries)'{-T,--tries}'[set maximum number of retries]:maximum retries' \
- '--align-payload[set payload alignment]:sectors' \
- '--uuid[set device UUID]:uuid' \
- '--version[show version information]' \
- ':action:_cryptsetup_action' \
- '*::arguments:_cryptsetup_arguments'
-}
-
-_cryptsetup "$@"
+return ret
diff --git a/Completion/Unix/Command/_augeas b/Completion/Unix/Command/_augeas
new file mode 100644
index 000000000..622fa3467
--- /dev/null
+++ b/Completion/Unix/Command/_augeas
@@ -0,0 +1,58 @@
+#compdef augtool
+
+local curcontext="$curcontext" state line expl ret=1
+local -A opt_args
+
+_arguments -C -s \
+ '(-c --typecheck)'{-c,--typecheck}'[perform type checking on lenses]' \
+ '(-b --backup)'{-b,--backup}'[preserve original files with .augsave extension]' \
+ '(-n --new)'{-n,--new}'[leave files untouched but save changes with a .augnew extension]' \
+ '(-r --root)'{-r,--root=}'[specify filesystem root]:root directory:_files -/' \
+ \*{-I+,--include=}'[add directory containing lenses to search path]:directory:_files -/' \
+ '(-f --file *)'{-f+,--file=}'[read commands from specified file]:file:_files' \
+ '(-i --interactive)'{-i,--interactive}'[read commands from the terminal]' \
+ '(-e --echo)'{-e,--echo}'[echo commands read from a file or stdin]' \
+ '(-s --autosave)'{-s,--autosave}'[automatically save at the end of instructions]' \
+ '(-S --nostdinc)'{-S,--nostdinc}'[do not search the builtin default directories for modules]' \
+ '(-L --noload)'{-L,--noload}'[do not load any files into the tree on startup]' \
+ '(-A --noautoload)'{-A,--noautoload}'[do not autoload modules from the search path]' \
+ '--span[load span positions for nodes related to a file]' \
+ '(- *)--version[print version information]' \
+ '(-)'{-h,--help}'[print help information]' \
+ '*:: :->subcommands' && ret=0
+
+[[ -z $state ]] && return ret
+
+if [[ CURRENT -eq 1 || $words[1] == help ]]; then
+ local -a subcmds
+ subcmds=( ${${${(f)"$(_call_program subcommands augtool help 2>/dev/null)"}[2,-2]## #}// #- /:} )
+ _describe -t subcommands "augtool command" subcmds && ret=0
+ return ret
+fi
+
+_tags paths
+while _tags; do
+ if _requested paths; then
+ local subcmd="$words[1]"
+ curcontext="${curcontext%:*}-${subcmd}:"
+ if compset -P '/files/'; then
+ _all_labels paths expl path _path_files -W / && ret=0
+ elif compset -P '/augeas/'; then
+ compset -P '*/'
+ local files
+ files=( ${${(f)"$(_call_program path augtool ls ${words[CURRENT]%/*} 2>/dev/null)"}% = *} )
+ while _next_label paths expl path; do
+ compadd "$expl[@]" -- ${files:#*/} && ret=0
+ compadd "$expl[@]" -S '' -- ${(M)files:#*/} && ret=0
+ done
+ else
+ local -a suf
+ suf=(-S '')
+ compset -S '/*' || suf=( -S / )
+ _all_labels paths expl path compadd -P/ "$suf[@]" files augeas && ret=0
+ fi
+ fi
+ (( ret )) || break
+done
+
+return ret
diff --git a/Completion/Unix/Command/_dvi b/Completion/Unix/Command/_dvi
index c01792978..6576a84d9 100644
--- a/Completion/Unix/Command/_dvi
+++ b/Completion/Unix/Command/_dvi
@@ -1,4 +1,4 @@
-#compdef dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
+#compdef dvips dvibook dviconcat dvicopy dvidvi dvipdf dviselect dvitodvi dvitype
local expl args
diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git
index b1f411a5e..c4e386b15 100644
--- a/Completion/Unix/Command/_git
+++ b/Completion/Unix/Command/_git
@@ -104,6 +104,8 @@ _git-am () {
# undocumented (and not implemented here).
_arguments -S \
'(-s --signoff)'{-s,--signoff}'[add Signed-off-by: line to the commit message]' \
+ '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
+ '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
'(-k --keep)'{-k,--keep}'[pass -k to git mailinfo]' \
'--keep-non-patch[pass -b to git mailinfo]' \
'( --no-keep-cr)--keep-cr[pass --keep-cr to git mailsplit]' \
@@ -508,6 +510,8 @@ _git-cherry-pick () {
'(-m --mainline)'{-m,--mainline}'[specify mainline when cherry-picking a merge commit]:parent number' \
'(-n --no-commit --ff)'{-n,--no-commit}'[do not make the actually commit]' \
'(-s --signoff --ff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \
+ '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
+ '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
'*'{-s,--strategy=}'[use given merge strategy]:merge strategy:__git_merge_strategies' \
'*'{-X,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]' \
'(-e --edit -x -n --no-commit -s --signoff)--ff[fast forward, if possible]' \
@@ -663,6 +667,7 @@ _git-commit () {
'--cleanup=[specify how the commit message should be cleaned up]:mode:((verbatim\:"do not change the commit message at all"
whitespace\:"remove leading and trailing whitespace lines"
strip\:"remove both whitespace and commentary lines"
+ scissors\:"same as whitespace but cut from scissor line"
default\:"act as '\''strip'\'' if the message is to be edited and as '\''whitespace'\'' otherwise"))' \
'(-e --edit --no-edit)'{-e,--edit}'[edit the commit message before committing]' \
'(-e --edit --no-edit)--no-edit[do not edit the commit message before committing]' \
@@ -677,7 +682,8 @@ _git-commit () {
'--dry-run[only show list of paths that are to be commited or not, and any untracked]' \
'( --no-status)--status[include the output of git status in the commit message template]' \
'(--status )--no-status[do not include the output of git status in the commit message template]' \
- '(-S --gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
+ '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
+ '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
'(-a --all --interactive -o --only -i --include *)--interactive[interactively update paths in the index file]' \
'*: :__git_ignore_line_inside_arguments __git_changed_files' \
- '(message)' \
@@ -870,8 +876,9 @@ _git-format-patch () {
'*--add-header=[add an arbitrary header to email headers]:header' \
'--cover-letter[generate a cover letter template]' \
'--notes=[append notes for the commit after the three-dash line]:: :__git_notes_refs' \
- '( --no-signature)--signature=[add a signature]:signature' \
- '(--signature )--no-signature[do not add a signature]' \
+ '( --no-signature --signature-file)--signature=[add a signature]:signature' \
+ '(--signature --signature-file)--no-signature[do not add a signature]' \
+ '(--signature --no-signature )--signature-file=[use contents of file as signature]' \
'--suffix=[use the given suffix for filenames]:filename suffix' \
'--quiet[suppress the output of the names of generated files]' \
'--no-binary[do not output contents of changes in binary files, only note that they differ]' \
@@ -1317,6 +1324,8 @@ _git-rebase () {
'--keep-empty[keep empty commits in the result]' \
'(- :)--skip[skip the current patch]' \
'(-m --merge)'{-m,--merge}'[use merging strategies to rebase]' \
+ '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
+ '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
'*'{-s,--strategy=}'[use given merge strategy]:merge strategy:__git_merge_strategies' \
'*'{-X,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]' \
'(-q --quiet -v --verbose --stat -n --no-stat)'{-q,--quiet}'[suppress all output]' \
@@ -1349,6 +1358,7 @@ _git-reset () {
_arguments -w -C -s \
'( --mixed --hard --merge --keep -p --patch -- *)--soft[do not touch the index file nor the working tree]' \
'(--soft --hard --merge --keep -p --patch -- *)--mixed[reset the index but not the working tree (default)]' \
+ '(--soft --hard --merge --keep -p --patch -- *)-N[keep --intent-to-add entries in the index]' \
'(--soft --mixed --merge --keep -p --patch -- *)--hard[match the working tree and index to the given tree]' \
'(--soft --mixed --hard --keep -p --patch -- *)--merge[reset out of a conflicted merge]' \
'(--soft --mixed --hard --merge -p --patch -- *)--keep[like --hard, but keep local working tree changes]' \
@@ -1382,6 +1392,8 @@ _git-revert () {
'(-m --mainline)'{-m+,--mainline=}'[pick which parent is mainline]:parent number' \
'(-n --no-commit)'{-n,--no-commit}'[do not commit the reversion]' \
'(-s --signoff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \
+ '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
+ '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
': :__git_commits'
}
@@ -1752,11 +1764,13 @@ _git-tag () {
'*:: :__git_ignore_line_inside_arguments __git_tags' \
- listing \
'-n+[limit line output of annotation]: :__git_guard_number "limit"' \
- '-l[list tags matching pattern]' \
+ '(-l --list)'{-l,--list}'[list tags matching pattern]' \
'(--no-column)--column=-[display tag listing in columns]::column.tag option:((always\:"always show in columns" never\:"never show in columns" auto\:"show in columns if the output is to the terminal" column\:"fill columns before rows (default)" row\:"fill rows before columns" plain\:"show in one column" dense\:"make unequal size columns to utilize more space" nodense\:"make equal size columns"))' \
'(--column)--no-column[do not display in columns]' \
'--contains=[only list tags which contain the specified commit]: :__git_commits' \
'--points-at=[only list tags of the given object]: :__git_commits' \
+ '--sort=[specify how the tags should be sorted]:mode:((refname\:"lexicographic order"
+ version\\\:refname\:"tag names are treated as version numbers"))' \
'::pattern' \
- verification \
'-v[verifies gpg signutare of tags]' \
@@ -1890,7 +1904,7 @@ _git-config () {
core.packedGitWindowSize:'size of mappings of pack files:pack window size:->bytes'
core.packedGitLimit:'maximum number of bytes to map from pack files:maximum pack file map size:->bytes'
core.precomposeunicode:'revert the unicode decomposition of filenames done by Mac OS::->bool:false'
- core.deltaBaseCacheLimit:'maximum size of cache for base objects:maximum base objects cache size:->bytes:16m'
+ core.deltaBaseCacheLimit:'maximum size of cache for base objects:maximum base objects cache size:->bytes:96m'
core.bigFileThreshold:'maximum size of files to compress:maximum compress size:->bytes:512m'
core.excludesfile:'additional file to use for exclusion:excludes file:_files'
core.askpass:'program to use for asking for passwords:password command:_path_commands'
@@ -1898,7 +1912,7 @@ _git-config () {
core.pager:'pager to use for paginating output:pager:_path_commands'
core.whitespace:'list of common whitespace problems to notice::->core.whitespace'
core.fsyncobjectfiles:'fsync() when writing object files::->bool:false'
- core.preloadindex:'use parallel index preload for operations like git diff::->bool:false'
+ core.preloadindex:'use parallel index preload for operations like git diff::->bool:true'
core.createObject:'take steps to prevent overwriting existing objects::->core.createObject:link'
core.checkstat:'determine which stat fields to match between the index and work tree::->core.checkstat:default'
core.notesRef:'show notes in given refs:refs:->string:refs/notes/commits'
@@ -1969,6 +1983,7 @@ _git-config () {
color.status.nobranch:'color of no-branch warning::->color'
color.ui:'color output of capable git commands::->color-bool:auto'
commit.cleanup:'default --cleanup option::->commit.cleanup:default'
+ commit.gpgsign:'always GPG-sign commits::->bool:false'
commit.status:'include status information in commit message template::->bool:true'
commit.template:'template file for commit messages:template:_files'
'diff.*.binary:make the diff driver treat files as binary::->bool:false'
@@ -2017,6 +2032,7 @@ _git-config () {
format.signoff:'enable --signoff by default::->bool:false'
'gc.*.reflogexpire:grace period for git reflog expire::->days:90'
'gc.*.reflogexpireunreachable:grace period for git reflog expire for unreachable entries::->days:30'
+ gc.aggressiveDepth:'maximum delta depth:maximum delta depth::->int:250'
gc.aggressiveWindow:'window size used in delta compression algorithm::->int:250'
gc.auto:'minimum limit for packing loose objects with --auto::->int:6700'
gc.autopacklimit:'minimum limit for packing packs with --auto::->int:50'
@@ -2077,6 +2093,7 @@ _git-config () {
guitool.title:'title of prompt dialog:prompt title:->string'
guitool.prompt:'prompt to display:prompt:->string'
grep.extendedRegexp:'enable --extended-regexp option by default (ignored when grep.patternType is set)::->bool:false'
+ grep.fullname:'enable --full-name option by default::->bool:false'
grep.lineNumber:'enable -n option by default::->bool:false'
grep.patternType:'default matching pattern type::->grep.patternType:default'
help.browser:'browser used to display help in web format::__git_browsers'
@@ -2161,7 +2178,7 @@ _git-config () {
'man.*.path:path to use for the man viewer:absolute man tool path:_files -g "*(*)"'
merge.branchdesc:'populate the log message with the branch description text as well::->bool:false'
merge.conflictstyle:'style used for conflicted hunks::->merge.conflictstyle:merge'
- merge.defaultToUpstream:'merge the upstream branches configured for the current branch by default::->bool:false'
+ merge.defaultToUpstream:'merge the upstream branches configured for the current branch by default::->bool:true'
merge.ff:'allow fast-forward merges::->merge.ff:true'
merge.log:'include summaries of merged commits in new merge commit messages::->bool:false'
merge.renameLimit:'number of files to consider when detecting copy/renames during merge:limit:->int'
@@ -2192,10 +2209,11 @@ _git-config () {
pack.threads:'number of threads to use for searching for best delta matches:number of threads:->int'
pack.indexVersion:'default pack index version:index version:->string'
pack.packSizeLimit:'maximum size of packs:maximum size of packs:->bytes'
+ pull.ff:'accept fast-forwards only::->bool:false'
pull.octopus:'default merge strategy to use when pulling multiple branches::__git_merge_strategies'
pull.rebase:'rebase branches on top of the fetched branch, instead of merging::->pull.rebase:false'
pull.twohead:'default merge strategy to use when pulling a single branch::__git_merge_strategies'
- push.default:'action git push should take if no refspec is given::->push.default:matching'
+ push.default:'action git push should take if no refspec is given::->push.default:simple'
rebase.stat:'show a diffstat of what changed upstream since last rebase::->bool:false'
rebase.autosquash:'autosquash by default::->bool:false'
rebase.autostash:'autostash by default::->bool:false'
@@ -2311,6 +2329,7 @@ _git-config () {
'svn-remote.*.pushurl:URL to push to::_urls'
'svn-remote.*.branches:branch mappings:branch mapping:->string'
'svn-remote.*.tags:tag mappings:tag mapping:->string'
+ tag.sort:'Default sorting method:->string'
'tar.*.command:specify a shell command through which the tar output generated by git archive should be piped::_path_commands'
'tar.*.remote:enable <format> for use by remote clients via git-upload-archive::->bool'
tar.umask:'umask to apply::->umask'
@@ -2319,6 +2338,7 @@ _git-config () {
transfer.hiderefs:'string(s) to decide which refs to omit from initial advertisements:hidden refs:->string'
uploadpack.hiderefs:'string(s) upload-pack uses to decide which refs to omit from its initial advertisement:hidden refs:->string'
uploadpack.allowtipsha1inwant:'allow upload-pack to accept a fetch request that asks for an object at the tip of a hidden ref::->bool:false'
+ uploadarchive.allowUnreachable:'allow git-upload-archive to accept an archive requests that ask for unreachable objects::->bool:false'
'url.*.insteadOf:string to start URLs with:prefix:->string'
'url.*.pushInsteadOf:string to start URLs to push to with:prefix:->string'
user.email:'email address used for commits::_email_addresses'
@@ -2516,6 +2536,7 @@ _git-config () {
tar:'git tar-tree options'
transfer:'options controlling transfers'
uploadpack:'git upload-pack options'
+ uploadarchive:'git upload-archive options'
url:'URL prefixes'
user:'options controlling user identity'
web:'web options'
@@ -3219,6 +3240,8 @@ _git-repack () {
(( $+functions[_git-replace] )) ||
_git-replace () {
_arguments -w -S -s \
+ '--edit[edit existing object as base a starting point]' \
+ '--graft[rewrite the parents of a commit]' \
'(- *)-f[overwrite existing replace ref]' \
'(- 2)-d[delete existing replace refs]' \
'(- : *)-l[list replace refs]:pattern' \
@@ -3530,6 +3553,13 @@ _git-show-branch () {
return ret
}
+(( $+functions[_git-verify-commit] )) ||
+_git-verify-commit () {
+ _arguments -w -S -s \
+ '(-v --verbose)'{-v,--verbose}'[print the contents of the commit object before validating it]' \
+ '*: :__git_commits'
+}
+
(( $+functions[_git-verify-tag] )) ||
_git-verify-tag () {
_arguments -w -S -s \
@@ -3654,6 +3684,8 @@ _git-send-email () {
'--annotate[review and edit each patch before sending it]' \
'--bcc=[Bcc: value for each email]: :_email_addresses' \
'--cc=[starting Cc: value for each email]: :_email_addresses' \
+ '--to-cover[Copy the To: list from the first file to the rest]' \
+ '--cc-cover[Copy the Cc: list from the first file to the rest]' \
'--compose[edit introductory message for patch series]' \
'--from=[specify sender]:email address:_email_addresses' \
'--in-reply-to=[specify contents of first In-Reply-To header]:message-id' \
@@ -3683,7 +3715,7 @@ _git-send-email () {
'(--suppress-from )--no-suppress-from[add the From: address to the Cc: list]' \
'( --no-thread)--thread[set In-Reply-To: and References: headers]' \
'(--thread )--no-thread[do not set In-Reply-To: and References: headers]' \
- '--confirm[specify type of confirmation required before sending]: :__git_sendemail_confirm' \
+ '--confirm[specify type of confirmation required before sending]: :__git_sendemail_confirm_values' \
'--dry-run[do everything except actually sending the emails]' \
'( --no-format-patch)--format-patch[interpret ambiguous arguments as format-patch arguments]' \
'(--format-patch )--no-format-patch[interpret ambiguous arguments file-name arguments]' \
@@ -3954,13 +3986,14 @@ _git-apply () {
_arguments -w -S -s \
$apply_options \
+ '(--index --cached --reject)'{-3,--3way}'[fall back on 3-way merge if patch fails]' \
'--stat[output diffstat for input (turns off "apply")]' \
'--numstat[same as --stat but in decimal notation and complete pathnames (turns off "apply")]' \
'--summary[output summary of git-diff extended headers (turns off "apply")]' \
'--check[check if patches are applicable (turns off "apply")]' \
'( --cached)--index[make sure that patch is applicable to index]' \
'(--index )--cached[apply patches without touching working tree]' \
- '--build-face-ancestor[build temporary index for blobs with ambiguous origin]:index:_files' \
+ '--build-fake-ancestor[build temporary index for blobs with ambiguous origin]:index:_files' \
'(-R --reverse)'{-R,--reverse}'[apply patches in reverse]' \
'-z[use NUL termination on output]' \
'--unidiff-zero[disable unified-diff-context check]' \
@@ -5049,6 +5082,7 @@ _git_commands () {
rerere:'reuse recorded resolution of conflicted merges'
rev-parse:'pick out and massage parameters for other git commands'
show-branch:'show branches and their commits'
+ verify-commit:'check GPG signature of commits'
verify-tag:'check GPG signature of tags'
whatchanged:'show commit-logs and differences they introduce')
@@ -6135,7 +6169,8 @@ __git_setup_revision_options () {
'--parents[display parents of commit]'
'--children[display children of commit]'
'--left-right[mark which side of symmetric diff commit is reachable from]'
- '--graph[display graphical representation of commit history]'
+ '(--show-linear-break )--graph[display graphical representation of commit history]'
+ '( --graph)--show-linear-break=[show a barrier between commits from different branches]:barrier'
'--count[display how many commits would have been listed]'
'(-n --max-count)'{-n+,--max-count=}'[maximum number of commits to display]: :__git_guard_number'
'--skip=[skip given number of commits before output]: :__git_guard_number'
@@ -6222,6 +6257,8 @@ __git_setup_merge_options () {
'( --no-squash)--squash[merge, but do not commit]'
'(--squash )--no-squash[merge and commit]'
'--ff-only[refuse to merge unless HEAD is up to date or merge can be resolved as a fast-forward]'
+ '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
+ '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
'*'{-s,--strategy=}'[use given merge strategy]:merge strategy:__git_merge_strategies'
'*'{-X,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]'
'(--verify-signatures)--verify-signatures[verify the commits being merged or abort]'
@@ -6429,6 +6466,7 @@ __git_diff-or-merge-tools () {
vimdiff
gvimdiff
vimdiff2
+ vimdiff3
gvimdiff2
emerge
ecmerge
@@ -6560,9 +6598,13 @@ _git() {
if (( CURRENT > 2 )); then
local -a aliases
local -A git_aliases
- # TODO: Should use -z here, but I couldn't get it to work.
- aliases=(${(f)${${${(f)"$(_call_program aliases git config --get-regexp '\^alias\.')"}#alias.}/ /$'\n'}/(#e)/$'\n'})
- (( $#aliases % 2 == 0 )) && git_aliases=($aliases)
+ local k v
+ aliases=(${(0)"$(_call_program aliases git config -z --get-regexp '\^alias\.')"})
+ for a in ${aliases}; do
+ k="${${a/$'\n'*}/alias.}"
+ v="${a#*$'\n'}"
+ git_aliases[$k]="$v"
+ done
if (( $+git_aliases[$words[2]] && !$+commands[git-$words[2]] && !$+functions[_git-$words[2]] )); then
local -a tmpwords expalias
diff --git a/Completion/Unix/Command/_graphicsmagick b/Completion/Unix/Command/_graphicsmagick
index d18ffbc7f..9306acd9c 100644
--- a/Completion/Unix/Command/_graphicsmagick
+++ b/Completion/Unix/Command/_graphicsmagick
@@ -3,7 +3,7 @@
local state line expl formats curcontext="$curcontext"
typeset -A opt_args
-formats=jpg:jpeg:tiff:miff:ras:bmp:cgm:dcx:ps:eps:fig:fits:fpx:gif:mpeg:pbm:pgm:ppm:pcd:pcl:pdf:pcx:png:rad:rgb:rgba:rle:sgi:html:shtml:tga:ttf:uil:xcf:xwd:xbm:xpm:yuv
+formats=jpg:jpeg:jp2:j2k:jpc:jpx:jpf:tiff:miff:ras:bmp:cgm:dcx:ps:eps:fig:fits:fpx:gif:mpeg:pbm:pgm:ppm:pcd:pcl:pdf:pcx:png:rad:rgb:rgba:rle:sgi:html:shtml:tga:ttf:uil:xcf:xwd:xbm:xpm:yuv
if (( $# )); then
_files "$@" -g "*.(#i)(${~formats//:/|})(-.)"
diff --git a/Completion/Unix/Command/_imagemagick b/Completion/Unix/Command/_imagemagick
index 5876adc47..115cb01e4 100644
--- a/Completion/Unix/Command/_imagemagick
+++ b/Completion/Unix/Command/_imagemagick
@@ -11,7 +11,7 @@ typeset -A opt_args
#
# and certainly many other things...
-formats=jpg:jpeg:tiff:miff:ras:bmp:cgm:dcx:ps:eps:fig:fits:fpx:gif:mpeg:pbm:pgm:ppm:pcd:pcl:pdf:pcx:png:rad:rgb:rgba:rle:sgi:html:shtml:tga:ttf:uil:xcf:xwd:xbm:xpm:yuv
+formats=jpg:jpeg:jp2:j2k:jpc:jpx:jpf:tiff:miff:ras:bmp:cgm:dcx:ps:eps:fig:fits:fpx:gif:mpeg:pbm:pgm:ppm:pcd:pcl:pdf:pcx:png:rad:rgb:rgba:rle:sgi:html:shtml:tga:ttf:uil:xcf:xwd:xbm:xpm:yuv
if (( $# )); then
_files "$@" -g "*.(#i)(${~formats//:/|})(-.)"
diff --git a/Completion/Unix/Command/_notmuch b/Completion/Unix/Command/_notmuch
index 0c23aa5f6..b576d2b29 100644
--- a/Completion/Unix/Command/_notmuch
+++ b/Completion/Unix/Command/_notmuch
@@ -13,6 +13,9 @@ _notmuch_commands()
'dump:creates a plain-text dump of the tags of each message'
'restore:restores the tags from the given file'
'help:show details on a command'
+ 'compact:compact the notmuch database'
+ 'config:access the notmuch configuration file'
+ 'count:count messages matching the given search terms'
)
_describe -t command 'command' notmuch_commands
diff --git a/Completion/Unix/Command/_perforce b/Completion/Unix/Command/_perforce
index 839870211..db91e11af 100644
--- a/Completion/Unix/Command/_perforce
+++ b/Completion/Unix/Command/_perforce
@@ -1231,10 +1231,15 @@ _perforce_files() {
# "subdirs:subdirectory search:_perforce_subdirs"
)
_alternative $altfiles
- elif [[ -n $unmaintained && -z $dodirs ]]; then
- # a la _cvs_nonentried_files: directories are never maintained,
- # so skip 'em. Unmaintained files can't be integrated, opened
- # or resolved, so treat as exclusive (just as well, since
+ elif [[ -n $unmaintained ]]; then
+ # As directories are always umaintained, but may contain files
+ # we want to add, we'll always complete directories here. That's
+ # neater than the alternative of excluding them here and requesting
+ # them separately in the caller. The only client for this
+ # branch is currently 'p4 add'.
+ #
+ # Unmaintained files can't be integrated, opened
+ # or resolved, so treat as exclusive to other options (just as well, since
# this bit's messy).
local MATCH MBEGIN MEND
local -a omitpats
@@ -1253,7 +1258,7 @@ _perforce_files() {
[[ $#omitpats -eq 1 && $omitpats[1] = '' ]] && omitpats=()
if (( ${#omitpats} )); then
- _path_files -g "*~(*/|)(${(j:|:)~omitpats})(D.)"
+ _path_files -g "*~(*/|)(${(j:|:)~omitpats})(D)"
else
_path_files
fi
diff --git a/Completion/Unix/Command/_quilt b/Completion/Unix/Command/_quilt
index 2ceb2ffaa..76dda222f 100644
--- a/Completion/Unix/Command/_quilt
+++ b/Completion/Unix/Command/_quilt
@@ -1,249 +1,206 @@
#compdef quilt
-local -a tmp
-local rc
+local curcontext="$curcontext" state line
+local help="(- : *)-h[show help information]"
+local verbose='(-h)-v[verbose, more user friendly output]'
+local color='(-h)--color=[use syntax coloring]:color:(always auto never)'
+local pstyle='(-h)-p+[select patch style]:patch style:((0\:exclude\ top-level\ directory 1\:use\ .orig\ on\ top-level\ directory ab\:use\ a\ or\ b\ as\ top-level\ directory))'
+local -a pform rcfile
+pform=(
+ '(-U -c -C -h)-u[create a unified diff]'
+ '(-u -c -C -h)-U+[create a unified diff with num lines of context]:lines'
+ '(-u -U -C -h)-c[create a context diff]'
+ '(-u -U -c -h)-C+[create a context diff with num lines of context]:lines'
+)
+typeset -A opt_args
-_quilt_applied () {
- tmp=( ${(f)"$(quilt applied 2>&1)"} )
- rc=$?
- if (( rc == 0 )); then
- _wanted -V 'applied patches' expl 'patch' compadd "${tmp[@]}"
- else
- _message "No applied patches"
- fi
+_quilt_applied() {
+ local expl
+ _wanted -V patches expl patch compadd \
+ ${(f)"$(_call_program patches quilt $rcfile applied)"}
}
-_quilt_series () {
- _wanted -V 'patches' expl 'patch' compadd ${(f)"$(quilt series)"}
+_quilt_series() {
+ local expl
+ _wanted -V patches expl 'patch' compadd \
+ ${(f)"$(_call_program patches quilt $rcfile series)"}
}
-_quilt_unapplied () {
- tmp=( ${(f)"$(quilt unapplied 2>&1)"} )
- rc=$?
- if (( rc == 0 )); then
- _wanted -V 'unapplied patches' expl 'patch' compadd "${tmp[@]}"
- else
- _message "No unapplied patches"
- fi
+_quilt_unapplied() {
+ local expl
+ _wanted -V patches expl 'unapplied patch' compadd \
+ ${(f)"$(_call_program patches quilt $rcfile unapplied)"}
}
-_arguments \
- '--trace[Runs the command in bash trace mode]' \
- '--quiltrc[Use the specified configuration file]:files:_files' \
- '--version[Print the version number and exit]' \
+_arguments $help \
+ '--trace[run the command in bash trace mode]' \
+ '--quiltrc=[use the specified configuration file]:files:_files' \
+ '--version[print the version number and exit]' \
':quilt command:(add annotate applied delete diff edit files fold fork graph
grep header import mail new next patches pop previous push refresh remove
rename revert series setup snapshot top unapplied upgrade)' \
- '*::subcmd:->subcmd' && return 0
+ '*:: :->subcmd' && return
-case "$state" in (subcmd)
- case "$words[1]" in
- (add)
- _arguments '-h' \
- '-P[Patch to add files to]:quilt series:_quilt_series' \
- '*:files:_files'
- ;;
- (annotate)
- _arguments '-h' \
- '-P[Stop checking for changes at the specified rather than the topmost patch]:quilt series:_quilt_series' \
- ':files:_files'
- ;;
- (applied)
- _arguments '-h' \
- ':quilt series:_quilt_series'
- ;;
- (delete)
- _arguments '-h' \
- '-n[Delete the next patch after topmost]' \
- '-r[Remove the deleted patch file from the patches directory as well]' \
- '--backup[Rename the patch file to patch~ rather than deleting it]' \
- ':quilt series:_quilt_series'
- ;;
- (diff)
- _arguments '-h' \
- '-p[Select a patch style]:quilt patch style:(0 1 ab)' \
- '-u[Create a unified diff]' \
- '-U[Create a unified diff with num lines of context]:quilt unified diff: ' \
- '-c[Create a context diff]' \
- '-C[Create a context diff with num lines of context]:quilt context diff: ' \
- '--no-timestamps[Do not include file timestamps in patch headers]' \
- '--no-index[Do not output Index: lines]' \
- '-z[Write to standard output the changes that have been made relative to the topmost or specified patch]' \
- '-R[Create a reverse diff]' \
- '-P[Create a diff for the specified patch]:quilt series:_quilt_series' \
- '--combine[Create a combined diff for all patches between this patch and the patch specified with -P]:quilt series:_quilt_series' \
- '--snapshot[Diff against snapshot]' \
- '--diff=[Use the specified utility for generating the diff]:quilt select diff utility:_command_names -e' \
- '--color=[Use syntax coloring]:quilt select color:(always auto never)' \
- '--sort[Sort files by their name]' \
- '*:files:_files'
- ;;
- (edit)
- _arguments '-h' \
- '*:files:_files'
- ;;
- (files)
- _arguments '-h' \
- '-a[List all files in all applied patches]' \
- '-l[Add patch name to output]' \
- '-v[Verbose, more user friendly output]' \
- '--combine[Create a listing for all patches between this patch and the topmost or specified patch]:quilt series:_quilt_series' \
- ':quilt series:_quilt_series'
- ;;
- (fold)
- _arguments '-h' \
- '-R[Apply patch in reverse]' \
- '-q[Quiet operation]' \
- '-f[Force apply]' \
- '-p[The number of pathname components to strip]:quilt select strip-level: '
- ;;
- (fork)
- _arguments '-h'
- ;;
- (graph)
- _arguments '-h' \
- '--all[Generate a graph including all applied patches and their dependencies]' \
- '--reduce[Eliminate transitive edges from the graph]' \
- '--lines[Compute dependencies by looking at the lines the patches modify]:quilt select lines: ' \
- '--edge-labels=files[Label graph edges with the file names that the adjacent patches modify]' \
- '-T ps[Directly produce a PostScript output file]' \
- ':quilt series:_quilt_series'
- ;;
- (grep)
- _arguments '-h'
- ;;
- (header)
- _arguments '-h' \
- '-a[Append the exiting patch header]' \
- '-r[Replace the exiting patch header]' \
- '-e[Edit the header in $EDITOR]' \
- '--strip-diffstat[Strip diffstat output from the header]' \
- '--strip-trailing-whitespace[Strip trailing whitespace at the end of lines of the header]' \
- '--backup[Create a backup copy of the old version of a patch as patch~]' \
- ':quilt series:_quilt_series'
- ;;
- (import)
- _arguments '-h' \
- '-p[Number of directory levels to strip when applying]:quilt select strip-level: ' \
- '-R[Apply patch in reverse]' \
- '-P[Patch filename to use inside quilt]:quilt select patch filename: ' \
- '-f[Overwrite/update existing patches]' \
- '-d[When overwriting in existing patch, keep the old (o), all (a), or new (n) patch header]:quilt select patch:(a n o)' \
- '*:files:_files'
- ;;
- (mail)
- _arguments '-h' \
- '-m[Text to use as the text in the introduction]:quilt select text: ' \
- '-M[Like the -m option, but read the introduction from file]:files:_files' \
- '--prefix[Use an alternate prefix in the bracketed part of the subjects generated]:quilt select prefix: ' \
- '--mbox[Store all messages in the specified file in mbox format]:files:_files' \
- '--send[Send the messages directly]' \
- '--sender[The envelope sender address to use]:quilt select sender: ' \
- '--from[From header]:quilt select from: ' \
- '--subject[Subject header]:quilt select subject: ' \
- '--to[Append a recipient to the To header]:quilt select to: ' \
- '--cc[Append a recipient to the Cc header]:quilt select cc: ' \
- '--bcc[Append a recipient to the Bcc header]:quilt select bcc: ' \
- '--signature[Append the specified signature to messages]:files:_files' \
- '--reply-to[Add the appropriate headers to reply to the specified message]:quilt select reply-to: ' \
- '*:quilt series:_quilt_series'
- ;;
- (new)
- _arguments '-h' \
- '-p[Select a patch style]:quilt patch style:(0 1 ab)'
- ;;
- (next)
- _arguments '-h' \
- ':quilt series:_quilt_series'
- ;;
- (patches)
- _arguments '-h' \
- '-v[Verbose, more user friendly output]' \
- ':files:_files'
- ;;
- (pop)
- _arguments '-h' \
- '-a[Remove all applied patches]' \
- '-f[Force remove]' \
- '-R[Always verify if the patch removes cleanly]' \
- '-q[Quiet operation]' \
- '-v[Verbose operation]' \
- ':quilt applied:_quilt_applied'
- ;;
- (previous)
- _arguments '-h' \
- ':quilt series:_quilt_series'
- ;;
- (push)
- _arguments '-h' \
- '-a[Apply all patches in the series file]' \
- '-q[Quiet operation]' \
- '-f[Force apply, even if the patch has rejects]' \
- '-v[Verbose operation]' \
- '--fuzz[Set the maximum fuzz factor]' \
- '--merge=[Merge the patch file into the original files]:quilt select merge:(merge diff3)' \
- '--leave-rejects[Leave around the reject files patch produced]' \
- '--color=[Use syntax coloring]:quilt select color:(always auto never)' \
- ':quilt unapplied:_quilt_unapplied'
- ;;
- (refresh)
- _arguments '-h' \
- '-p[Select a patch style]:quilt patch style:(0 1 ab)' \
- '-u[Create a unified diff]' \
- '-U[Create a unified diff with num lines of context]:quilt unified diff: ' \
- '-c[Create a context diff]' \
- '-C[Create a context diff with num lines of context]:quilt context diff: ' \
- '-z[Create a new patch containing the changes instead of refreshing the topmost patch]:quilt select new patch name: ' \
- '--no-timestamps[Do not include file timestamps in patch headers]' \
- '--no-index[Do not output Index: lines]' \
- '--diffstat[Add a diffstat section to the patch header, or replace the existing diffstat section]' \
- '-f[Enforce refreshing of a patch that is not on top]' \
- '--backup[Create a backup copy of the old version of a patch as patch~]' \
- '--sort[Sort files by their name instead of preserving the original order]' \
- '--strip-trailing-whitespace[Strip trailing whitespace at the end of lines]' \
- ':quilt series:_quilt_series'
- ;;
- (remove)
- _arguments '-h' \
- '-P[Patch to remove]:quilt series:_quilt_series'
- ;;
- (rename)
- _arguments '-h' \
- '-P[Patch to rename]:quilt series:_quilt_series'
- ;;
- (revert)
- _arguments '-h' \
- '-P[Revert changes in the named patch]:quilt series:_quilt_series' \
- '*:files:_files'
- ;;
- (series)
- _arguments '-h' \
- '-v[Verbose, more user friendly output]'
- ;;
- (setup)
- _arguments '-h' \
- '-d[Optional path prefix for the resulting source tree]:quilt select path-prefix: ' \
- '--sourcedir[Directory that contains the package sources]:quilt select package sources directory: ' \
- '-v[Verbose debug output]' \
- '--fuzz[Set the maximum fuzz factor]' \
- ':files:_files'
- ;;
- (snapshot)
- _arguments '-h' \
- '-d[Remove current snapshot]'
- ;;
- (top)
- _arguments '-h'
- ;;
- (unapplied)
- _arguments '-h' \
- ':quilt series:_quilt_series'
- ;;
- (upgrade)
- _arguments '-h'
- ;;
- (*)
- ;;
- esac
+[[ -z $state ]] && return 1
+rcfile=( ${opt_args[--quiltrc]:+--quiltrc=${opt_args[--quiltrc]}} )
+case $words[1] in
+ add)
+ _arguments -S $help \
+ '-P+[specify patch to add files to]:patch:_quilt_applied' \
+ '*:files:_files' && return
+ ;;
+ annotate)
+ _arguments $help \
+ '-P[stop checking for changes at the specified rather than the topmost patch]:patch:_quilt_series' \
+ ':files:_files' && return
+ ;;
+ applied) _arguments $help ':quilt series:_quilt_series' && return ;;
+ delete)
+ _arguments -s $help \
+ '(:)-n[delete the next patch after topmost]' \
+ '-r[remove the deleted patch file from the patches directory as well]' \
+ '--backup[rename the patch file to patch~ rather than deleting it]' \
+ '(-n):patch:_quilt_series' && return
+ ;;
+ diff)
+ _arguments -s $help $pstyle $pform $color \
+ "--no-timestamps[don't include file timestamps in patch headers]" \
+ "--no-index[don't output Index: lines]" \
+ '(-P --snapshot)-z[show changes relative to the topmost or specified patch]' \
+ '-R[create a reverse diff]' \
+ '(-z --snapshot)-P[create a diff for the specified patch]:patch:_quilt_series' \
+ '--combine[create a combined diff for all patches between this patch and the patch specified with -P]:patch:_quilt_series' \
+ '(-P -z)--snapshot[diff against snapshot]' \
+ '--diff=[use the specified utility for generating the diff]:diff utility:_command_names -e' \
+ '--sort[sort files by name]' \
+ '*:files:_files' && return
+ ;;
+ edit) _arguments $help '*:files:_files' && return ;;
+ files)
+ _arguments -s $help $verbose \
+ '-a[list all files in all applied patches]' \
+ '-l[add patch name to output]' \
+ '--combine[create a listing for all patches between this patch and the topmost or specified patch]::patch:_quilt_series' \
+ ':patch:_quilt_series' && return
+ ;;
+ fold)
+ _arguments -s $help \
+ '-R[apply patch in reverse]' \
+ '-q[quiet operation]' \
+ '-f[force apply]' \
+ '-p+[specify number of pathname components to strip]:components to strip' && return
+ ;;
+ fork) _arguments $help ':patch name' && return ;;
+ graph)
+ _arguments $help \
+ '--all[include all applied patches and their dependencies]' \
+ '--reduce[eliminate transitive edges from the graph]' \
+ '--lines=-[compute dependencies by looking at lines patches modify]::number of lines' \
+ '--edge-labels=files[label graph edges with file names that adjacent patches modify]' \
+ '-T ps[produce a PostScript output file]' \
+ ':patch:_quilt_series' && return
+ ;;
+ grep) _grep && return ;;
+ header)
+ _arguments $help \
+ '(-r -e -h)-a[append to existing patch header]' \
+ '(-a -e -h)-r[replace existing patch header]' \
+ '(-a -r -h)-e[edit the header in $EDITOR]' \
+ '--strip-diffstat[strip diffstat output from the header]' \
+ '--strip-trailing-whitespace[strip trailing whitespace at the end of lines of the header]' \
+ '--backup[create backup copy of patch with tilde suffix]' \
+ ':patch:_quilt_series' && return
+ ;;
+ import)
+ _arguments $help \
+ '-p+[number of directory levels to strip when applying]:quilt select strip-level: ' \
+ '-R[apply patch in reverse]' \
+ '-P+[patch filename to use inside quilt]:quilt select patch filename: ' \
+ '-f[overwrite/update existing patches]' \
+ '-d+[header resolution when overwriting in existing patch]:resolution:((a\:all\ headers n\:new\ headers o\:old\ headers))' \
+ '*:files:_files' && return
+ ;;
+ mail)
+ _arguments $help \
+ '(-h -M)-m[introduction text to use]:introduction text' \
+ '(-h -m)-M[read introduction text from file]:file:_files' \
+ '--prefix=[use an alternate prefix in the bracketed part of the subjects generated]:quilt select prefix: ' \
+ '--mbox=[store all messages in the specified file in mbox format]:files:_files' \
+ '--send[send the messages directly]' \
+ '--sender=[specify envelope sender address to use]:sender:_email_addresses -c' \
+ '--from=[from header]:address:_email_addresses' \
+ '--subject=[subject header]:subject' \
+ '*--to=[append a recipient to the To header]:recipient:_email_addresses' \
+ '*--cc=[append a recipient to the Cc header]:recipient:_email_addresses' \
+ '*--bcc=[append a recipient to the Bcc header]:recipient:_email_addresses' \
+ '--signature=[append specified signature file to messages]:files:_files' \
+ '--reply-to=[add reply address to message]:address:_email_addresses' \
+ '*:patch:_quilt_series' && return
+ ;;
+ new) _arguments $help $pstyle ':patch name' && return ;;
+ next) _arguments $help ':patch:_quilt_series' && return ;;
+ patches) _arguments -S $help $verbose $color '*:files:_files' && return ;;
+ pop)
+ _arguments -s $help $verbose \
+ '-a[remove all applied patches]' \
+ '-f[force remove]' \
+ '-R[always verify if the patch removes cleanly]' \
+ '-q[quiet operation]' \
+ ':patch:_quilt_applied' && return
+ ;;
+ previous) _arguments $help ':patch:_quilt_series' && return ;;
+ push)
+ _arguments $help $verbose $color \
+ '-a[apply all patches in the series file]' \
+ '-q[quiet operation]' \
+ '-f[force apply, even if the patch has rejects]' \
+ '--fuzz=[set the maximum fuzz factor]:factor [2]' \
+ '--merge=[merge the patch file into the original files]::merge scheme:(merge diff3)' \
+ '--leave-rejects[leave around the reject files patch produced]' \
+ ':quilt unapplied:_quilt_unapplied' && return
+ ;;
+ refresh)
+ _arguments -s $help $pstyle $pform \
+ '-z-[create a new patch containing the changes instead of refreshing the topmost patch]::new patch name' \
+ '--no-timestamps[do not include file timestamps in patch headers]' \
+ '--no-index[do not output Index: lines]' \
+ '--diffstat[add a diffstat section to the patch header, or replace the existing diffstat section]' \
+ '-f[enforce refreshing of a patch that is not on top]' \
+ '--backup[create a backup copy of the old version of a patch as patch~]' \
+ '--sort[sort files by their name instead of preserving the original order]' \
+ '--strip-trailing-whitespace[strip trailing whitespace at the end of lines]' \
+ ':patch:_quilt_series' && return
+ ;;
+ remove)
+ _arguments $help \
+ '-P[patch to remove]:patch:_quilt_series' \
+ '*:file:_files' && return
+ ;;
+ rename)
+ _arguments $help \
+ '(-h)-P[patch to rename]:patch:_quilt_series' \
+ ':new name' && return
+ ;;
+ revert)
+ _arguments $help \
+ '-P[revert changes in the named patch]:patch:_quilt_series' \
+ '*:files:_files' && return
+ ;;
+ series) _arguments $help $verbose $color && return ;;
+ setup)
+ _arguments $help $verbose \
+ '-d[specify path prefix for resulting source tree]:prefix:_files -W / -P /' \
+ '--sourcedir[specify location of package sources]:directory:_directories' \
+ '--fuzz=[set the maximum fuzz factor]:factor' \
+ ':files:_files' && return
+ ;;
+ snapshot) _arguments $help '-d[only remove current snapshot]' && return ;;
+ unapplied) _arguments $help ':patch:_quilt_series' && return ;;
+ top|upgrade) _arguments $help && return ;;
+ *)
+ _default
+ return
;;
esac
+
+return 1
diff --git a/Completion/Unix/Command/_stgit b/Completion/Unix/Command/_stgit
index b2f2aeafa..6248267eb 100644
--- a/Completion/Unix/Command/_stgit
+++ b/Completion/Unix/Command/_stgit
@@ -32,6 +32,17 @@ else
compadd $(stg series --noprefix 2> /dev/null) \
&& ret=0
;;
+ (ref*)
+ last_word="$words[$CURRENT-1]"
+ refresh_patch_options=( -p --patch )
+ if [[ -n ${refresh_patch_options[(r)$last_word]} ]]; then
+ _wanted -V "applied patches" expl "patch" \
+ compadd ${${(M)${(f)"$(stg series 2> /dev/null)"}##[+>] *}#[+>] } \
+ && ret=0
+ else
+ _files
+ fi
+ ;;
(*)
_files
;;
diff --git a/Completion/Unix/Command/_sysctl b/Completion/Unix/Command/_sysctl
index 36b579bc7..ff3312fac 100644
--- a/Completion/Unix/Command/_sysctl
+++ b/Completion/Unix/Command/_sysctl
@@ -1,9 +1,9 @@
#compdef sysctl
case $OSTYPE in
- *freebsd[5-9].*|freebsd4.[4-9]*)
+ *freebsd<5->.*|freebsd4.[4-9]*)
local -a sysctlvars
- sysctlvars=( $(sysctl -aN) )
+ sysctlvars=( $(_call_program sysctl-variables sysctl -aN) )
_arguments -s -A "-*" \
'(*)-a[list all]' \
'-b[binary output]' \
@@ -41,5 +41,8 @@ case $OSTYPE in
'(-w)-n[show only values]' \
'(-a -A -n)-w[write variable]' \
'(-a -A)*:sysctl variable:_multi_parts ${words[(r)-w]:+-S=} -i . _cache_sysctlvars'
- ;;
+ ;;
+ *)
+ _default
+ ;;
esac
diff --git a/Completion/Unix/Type/_mime_types b/Completion/Unix/Type/_mime_types
index b8ed889b8..18a332e09 100755
--- a/Completion/Unix/Type/_mime_types
+++ b/Completion/Unix/Type/_mime_types
@@ -33,10 +33,10 @@ if [[ $PREFIX = (#b)([^/]##)/* ]]; then
compset -p $(( ${#maintype} + 1 ))
_wanted mime-subtypes expl 'MIME subtype' \
compadd -- $(sed -ne "s%^\(type=\|\)${maintype}/\([^ ]*\).*$%\2%p" \
- $type_files)
+ $type_files 2>/dev/null)
else
# Search for main type.
_wanted mime-types expl 'MIME type' \
compadd -S/ -- $(sed -ne "s/^type=//" \
- -e "s%^\(${PREFIX:-[a-z]}[^=\"]*\)/.*$%\1%p" $type_files)
+ -e "s%^\(${PREFIX:-[a-z]}[^=\"]*\)/.*$%\1%p" $type_files 2>/dev/null)
fi
diff --git a/Completion/Unix/Type/_net_interfaces b/Completion/Unix/Type/_net_interfaces
index 666287259..2cac3e3bb 100644
--- a/Completion/Unix/Type/_net_interfaces
+++ b/Completion/Unix/Type/_net_interfaces
@@ -3,6 +3,10 @@
local expl list intf sep
local -a disp
+# Make sure needed tools are in the path.
+local PATH=$PATH
+PATH=/sbin:$PATH
+
case $OSTYPE in
aix*)
intf=( ${(f)"$(lsdev -C -c if -F 'name:description')"} )
@@ -14,17 +18,22 @@ case $OSTYPE in
;;
darwin*|freebsd*|dragonfly*) intf=( $(ifconfig -l) ) ;;
irix*) intf=( ${${${(f)"$(/usr/etc/netstat -i)"}%% *}[2,-1]} ) ;;
+ *linux*)
+ if (( $+commands[ip] )); then
+ intf=( ${${(m)${(f)"$(ip -o link)"}#*: }%%: *} )
+ fi
+ ;&
*)
- # Make sure ifconfig is in the path.
- local PATH=$PATH
- PATH=/sbin:$PATH
- intf=( $(ifconfig -a 2>/dev/null | sed -n 's/^\([^ :]*\).*/\1/p') )
- if [[ ${#intf} -eq 0 && -d /proc/sys/net/ipv4/conf ]]; then
- # On linux we used to use the following as the default.
- # However, we now use ifconfig since it finds additional devices such
- # as tunnels. So only do this if that didn't work.
- intf=( /proc/sys/net/ipv4/conf/*~*(all|default)(N:t) )
+ if [[ ${#intf} -eq 0 ]]; then
+ # linux's deprecated ifconfig may truncate long interface names
+ intf=( $(ifconfig -a 2>/dev/null | sed -n 's/^\([^ :]*\).*/\1/p') )
+ if [[ -d /proc/sys/net/ipv4/conf ]]; then
+ # On linux we used to use the following as the default.
+ # However, we now use ip or ifconfig since it finds additional devices such
+ # as tunnels. So only do this if that didn't work.
+ intf=( /proc/sys/net/ipv4/conf/*~*(all|default)(N:t) )
+ fi
fi
;;
esac
diff --git a/Completion/Unix/Type/_path_files b/Completion/Unix/Type/_path_files
index 85feae54c..ed3f54de3 100644
--- a/Completion/Unix/Type/_path_files
+++ b/Completion/Unix/Type/_path_files
@@ -15,13 +15,21 @@ local -a match mbegin mend
# a bare glob qualifier.
# The later test looks for an outstanding quote.
if _have_glob_qual $PREFIX; then
- compset -p ${#match[1]}
- if [[ $_comp_caller_options[extendedglob] == on ]] && compset -P '\#'; then
- _globflags
- else
- _globquals
- fi
- return
+ local ret=1
+ compset -p ${#match[1]}
+ if [[ $_comp_caller_options[extendedglob] == on ]] && compset -P '\#'; then
+ _globflags && ret=0
+ else
+ if [[ $_comp_caller_options[extendedglob] == on ]]; then
+ local -a flags
+ flags=(
+ '#:introduce glob flag'
+ )
+ _describe -t globflags "glob flag" flags -Q -S '' && ret=0
+ fi
+ _globquals && ret=0
+ fi
+ return ret
fi
# Utility function for in-path completion. This allows `/u/l/b<TAB>'
diff --git a/Completion/X/Command/_mplayer b/Completion/X/Command/_mplayer
index eaf6e84bc..f2f4c3d45 100644
--- a/Completion/X/Command/_mplayer
+++ b/Completion/X/Command/_mplayer
@@ -115,7 +115,7 @@ case "$state" in
_tags files urls
while _tags; do
_requested files expl 'media file' _files -g \
- "*.(#i)(asf|asx|avi|flac|flv|m1v|m2p|m2v|m4v|mjpg|mka|mkv|mov|mp3|mp4|mpe|mpeg|mpg|ogg|ogm|ogv|qt|rm|ts|vob|wav|webm|wma|wmv)(-.)" && ret=0
+ "*.(#i)(asf|asx|avi|flac|flv|m1v|m2p|m2v|m4a|m4v|mjpg|mka|mkv|mov|mp3|mp4|mpe|mpeg|mpg|ogg|ogm|ogv|qt|rm|ts|vob|wav|webm|wma|wmv)(-.)" && ret=0
if _requested urls; then
while _next_label urls expl URL; do
_urls "$expl[@]" && ret=0
diff --git a/Completion/Zsh/Command/_setopt b/Completion/Zsh/Command/_setopt
index f72c20dda..fb38d1da6 100644
--- a/Completion/Zsh/Command/_setopt
+++ b/Completion/Zsh/Command/_setopt
@@ -1,10 +1,16 @@
-#compdef setopt
+#compdef setopt unsetopt
-# If you first want to complete only unset options, un-comment the lines
-# setting the _options_unset array and then use:
-#
-# _options_unset || _options
-#
-# here.
+local expl ret=1
+local -a onopts offopts
+onopts=( ${(k)_comp_caller_options[(R)on]} )
+offopts=( ${(k)_comp_caller_options[(R)off]} )
+case $service in
+ setopt) onopts=(no$onopts) ;;
+ unsetopt) offopts=(no$offopts) ;;
+esac
+_wanted zsh-options expl 'zsh options (set)' \
+ compadd -J 'enabled options' -M 'M:_= M:{A-Z}={a-z}' -k - onopts && ret=0
+_wanted zsh-options expl 'zsh options (unset)' \
+ compadd -J 'disabled options' -M 'M:_= M:{A-Z}={a-z}' -k - offopts && ret=0
-_options
+return ret
diff --git a/Completion/Zsh/Command/_typeset b/Completion/Zsh/Command/_typeset
index f876e1beb..367dbfc23 100644
--- a/Completion/Zsh/Command/_typeset
+++ b/Completion/Zsh/Command/_typeset
@@ -1,7 +1,7 @@
#compdef autoload declare export functions integer float local readonly typeset
local expl state line func i use curcontext="$curcontext"
-local fopts="-f -k -z"
+local fopts="-f -k -z +k +z"
local popts="-A -E -F -L -R -T -Z -a -g -h -H -i -l -r -x"
local -A allargs opt_args
local -a args
@@ -51,8 +51,9 @@ case ${service} in
;;
float) use="EFHghlprtux";;
functions)
- use="UkmTtuz"
+ use="UkmTtuzM"
func=f
+ allargs[M]='(-k -t -T -u -U -z -M +M +k +t +z)-+M[define mathematical function]'
;;
integer)
use="Hghilprtux"
@@ -73,14 +74,20 @@ onopts=${(j..)${${words[1,CURRENT-1]:#^-*}##-}}
offopts=${(j..)${${words[1,CURRENT-1]:#^+*}##+}}
for ((i=1;i<=$#use;++i)); do
- args+=( ${allargs[${use[$i]}${${(s::)use[$i]}[(r)[Uut]]:+$func}]} )
+ args+=( ${allargs[${use[$i]}${${(s::)use[$i]}[(r)[UutT]]:+$func}]} )
done
_arguments -C -s -A "-*" -S "${args[@]}" '*::vars:= ->vars_eq'
if [[ "$state" = vars_eq ]]; then
if [[ $func = f ]]; then
- if (( $+opt_args[-w] ));then
+ if (( $+opt_args[+M] || ( $+opt_args[-M] && $+opt_args[-m] ) )); then
+ _wanted functions expl 'math function' compadd -F line - \
+ ${${${(f)"$(functions -M)"}##*-M }%% *}
+ elif (( $+opt_args[-M] )); then
+ _arguments ':new math function:_functions' ':minimum arguments' \
+ ':maximum arguments' ':shell function:_functions'
+ elif (( $+opt_args[-w] )); then
_wanted files expl 'zwc file' _files -g '*.zwc(-.)'
elif [[ $service = autoload || -n $opt_args[(i)-[uU]] ]]; then
args=(${^fpath}/*(-.:t))
diff --git a/Completion/Zsh/Command/_unsetopt b/Completion/Zsh/Command/_unsetopt
deleted file mode 100644
index 75a33e9dd..000000000
--- a/Completion/Zsh/Command/_unsetopt
+++ /dev/null
@@ -1,10 +0,0 @@
-#compdef unsetopt
-
-# If you first want to complete only unset options, uncomment the lines
-# setting the _options_set array and then use:
-#
-# _options_set || _options
-#
-# here.
-
-_options
diff --git a/Config/defs.mk.in b/Config/defs.mk.in
index f6ea5c1cd..3c84610e8 100644
--- a/Config/defs.mk.in
+++ b/Config/defs.mk.in
@@ -47,6 +47,7 @@ mandir = @mandir@
datarootdir = @datarootdir@
datadir = @datadir@
fndir = @fndir@
+fixed_sitefndir = @fixed_sitefndir@
sitefndir = @sitefndir@
scriptdir = @scriptdir@
sitescriptdir = @sitescriptdir@
diff --git a/Config/version.mk b/Config/version.mk
index 949f58af4..03289c155 100644
--- a/Config/version.mk
+++ b/Config/version.mk
@@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the
# `=' signs.
-VERSION=5.0.6
-VERSION_DATE='August 28, 2014'
+VERSION=5.0.7
+VERSION_DATE='October 7, 2014'
diff --git a/Doc/Makefile.in b/Doc/Makefile.in
index f4ee0d760..41af4a33e 100644
--- a/Doc/Makefile.in
+++ b/Doc/Makefile.in
@@ -119,8 +119,10 @@ texi: $(sdir)/zsh.texi
.PHONY: texi
$(sdir)/zsh.texi: version.yo
- $(YODL) -o $@ -I$(sdir) -w ztexi.yo version.yo zsh.yo; \
- test -f $@
+ case '$(YODL)' in :*) touch $@ ;; *) \
+ $(YODL) -o $@ -I$(sdir) -w ztexi.yo version.yo zsh.yo; \
+ test -f $@ \
+ ;; esac
info: zsh.info
.PHONY: info
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index f709f5020..46f40cc3a 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -603,7 +603,7 @@ tt(enable -p) reenables patterns disabled with tt(disable -p). Note
that it does not override globbing options; for example, `tt(enable -p
"~")' does not cause the pattern character tt(~) to be active unless
the tt(EXTENDED_GLOB) option is also set. To enable all possible
-patterns (so that they may be invidually disabled with tt(disable -p)),
+patterns (so that they may be individually disabled with tt(disable -p)),
use `tt(setopt EXTENDED_GLOB KSH_GLOB NO_SH_GLOB)'.
)
findex(eval)
@@ -773,7 +773,7 @@ findex(functions)
xitem(tt(functions) [ {tt(PLUS())|tt(-)}tt(UXkmtTuz) ] [ var(name) ... ])
xitem(tt(functions -M) var(mathfn) [ var(min) [ var(max) [ var(shellfn) ] ] ])
xitem(tt(functions -M) [ tt(-m) var(pattern) ... ])
-item(tt(functions +M) [ tt(-m) ] var(mathfn))(
+item(tt(functions +M) [ tt(-m) ] var(mathfn) ... )(
Equivalent to tt(typeset -f), with the exception of the tt(-M) option.
Use of the tt(-M) option may not be combined with any of the options
handled by tt(typeset -f).
@@ -1639,14 +1639,26 @@ Do nothing and return an exit status of 0.
findex(ttyctl)
cindex(tty, freezing)
item(tt(ttyctl) tt(-fu))(
-The tt(-f) option freezes the tty, and tt(-u) unfreezes it.
+The tt(-f) option freezes the tty (i.e. terminal or terminal emulator), and
+tt(-u) unfreezes it.
When the tty is frozen, no changes made to the tty settings by
external programs will be honored by the shell, except for changes in the
size of the screen; the shell will
simply reset the settings to their previous values as soon as each
command exits or is suspended. Thus, tt(stty) and similar programs have
-no effect when the tty is frozen. Without options it reports whether the
-terminal is frozen or not.
+no effect when the tty is frozen. Freezing the tty does not cause
+the current state to be remembered: instead, it causes future changes
+to the state to be blocked.
+
+Without options it reports whether the terminal is frozen or not.
+
+Note that, regardless of whether the tty is frozen or not, the
+shell needs to change the settings when the line editor starts, so
+unfreezing the tty does not guarantee settings made on the
+command line are preserved. Strings of commands run between
+editing the command line will see a consistent tty state.
+See also the shell variable tt(STTY) for a means of initialising
+the tty before running external commands.
)
findex(type)
item(tt(type) [ tt(-wfpams) ] var(name) ...)(
@@ -2162,6 +2174,20 @@ match one of these patterns will be written. If no var(name) is given,
the definitions of all functions currently defined or marked as
autoloaded will be written.
+Note the second form cannot be used for compiling functions that
+include redirections as part of the definition rather than within
+the body of the function; for example
+
+example(fn1() { { ... } >~/logfile })
+
+can be compiled but
+
+example(fn1() { ... } >~/logfile)
+
+cannot. It is possible to use the first form of tt(zcompile) to compile
+autoloadable functions that include the full function definition instead
+of just the body of the function.
+
The third form, with the tt(-t) option, examines an existing
compiled file. Without further arguments, the names of the original
files compiled into it are listed. The first line of output shows
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 1c1a66a3b..8c5e66b17 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -1156,8 +1156,8 @@ item(tt(vcs_info_hookdel))(
Remove hook-functions from a given hook. The hook needs to be given as the
first non-option argument; what follows is a list of hook-function
names to un-register from the hook. If `tt(-a)' is used as the first
-argument, tt(all) occurances of the functions are unregistered. Otherwise
-only the last occurance is removed (if a function was registered to a hook
+argument, tt(all) occurrences of the functions are unregistered. Otherwise
+only the last occurrence is removed (if a function was registered to a hook
more than once) . The `tt(+vi-)' prefix needs to be left out here. See
bf(Hooks in vcs_info) below for details.
)
@@ -1292,14 +1292,14 @@ tt(vcs_info) collected from `hg'.
When setting tt(ret) to non-zero, the string in
tt(${hook_com[hg-bookmark-string]}) will be used in the tt(%m) escape in
-tt(formats) and tt(actionformats) and will be availabe in the global
+tt(formats) and tt(actionformats) and will be available in the global
tt(backend_misc) array as tt(${backend_misc[bookmarks]}).
)
item(tt(gen-applied-string))(
-Called in the tt(git) (with tt(stgit)), and tt(hg) (with tt(mq)) backends
-and in tt(quilt) support when the tt(applied-string) is generated; the
-tt(use-quilt) zstyle must be true for tt(quilt) (the tt(mq) and tt(stgit)
-backends are active by default).
+Called in the tt(git) (with tt(stgit) or during rebase), and tt(hg)
+(with tt(mq)) backends and in tt(quilt) support when the tt(applied-string)
+is generated; the tt(use-quilt) zstyle must be true for tt(quilt) (the tt(mq)
+and tt(stgit) backends are active by default).
This hook gets the names of all applied patches which tt(vcs_info) collected
so far in the opposite order, which means that the first argument is the
@@ -1312,9 +1312,9 @@ tt(backend_misc) array as tt($backend_misc[patches]}); and it will be
available as tt(%p) in the tt(patch-format) and tt(nopatch-format) styles.
)
item(tt(gen-unapplied-string))(
-Called in the tt(git) (with tt(stgit)), and tt(hg) (with tt(mq)) backend
-and in tt(quilt) support when the tt(unapplied-string) is generated; the
-tt(get-unapplied) style must be true.
+Called in the tt(git) (with tt(stgit) or during rebase), and tt(hg) (with
+tt(mq)) backend and in tt(quilt) support when the tt(unapplied-string) is
+generated; the tt(get-unapplied) style must be true.
This hook gets the names of all unapplied patches which tt(vcs_info)
collected so far in the opposite order, which mean that the first argument is
@@ -2965,7 +2965,7 @@ types even if they are executable. As this example shows, the complete
file name is matched against the pattern, regardless of how the file
was passed to the handler. The file is resolved to a full path using
the tt(:A) modifier described in
-ifzman(the subsection Modifers in zmanref(zshexpn))\
+ifzman(the subsection Modifiers in zmanref(zshexpn))\
ifnzman(noderef(Modifiers));
this means that symbolic links are resolved where possible, so that
links into other file systems behave in the correct fashion.
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index d01d804d2..5aab25954 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -316,7 +316,7 @@ the rightmost `tt(?)' in a context scan can similarly be omitted. Note
the same record of the last var(l) and var(r) is maintained across all
forms of expansion.
-Note that if a `tt(&)' is used within glob qualifers an extra backslash
+Note that if a `tt(&)' is used within glob qualifiers an extra backslash
is needed as a tt(&) is a special character in this case.
If the option tt(HIST_SUBST_PATTERN) is set, var(l) is treated as
@@ -475,7 +475,7 @@ spawned from the parent shell which will wait for their completion.
Another problem arises any time a job with a substitution that requires
a temporary file is disowned by the shell, including the case where
`tt(&!)' or `tt(&|)' appears at the end of a command containing a
-subsitution. In that case the temporary file will not be cleaned up as
+substitution. In that case the temporary file will not be cleaned up as
the shell no longer has any memory of the job. A workaround is to use
a subshell, for example,
@@ -632,7 +632,7 @@ quoted, the elements of var(arrayname) are instead tested against the
entire expression.
)
item(tt(${)var(name)tt(:*)var(arrayname)tt(}))(
-Similar to the preceding subsitution, but in the opposite sense,
+Similar to the preceding substitution, but in the opposite sense,
so that entries present in both the original substitution and as
elements of var(arrayname) are retained and others removed.
)
@@ -701,7 +701,7 @@ print ${foo:$(( 1 + 2))}
print ${foo:$(echo 1 + 2)})
all have the same effect, extracting the string starting at the fourth
-character of tt($foo) if the substution would otherwise return a scalar,
+character of tt($foo) if the substitution would otherwise return a scalar,
or the array starting at the fourth element if tt($foo) would return an
array. Note that with the option tt(KSH_ARRAYS) tt($foo) always returns
a scalar (regardless of the use of the offset syntax) and a form
@@ -924,7 +924,7 @@ that result from field splitting.
item(tt(D))(
Assume the string or array elements contain directories and attempt
to substitute the leading part of these by names. The remainder of
-the path (the whole of it if the leading part was not subsituted)
+the path (the whole of it if the leading part was not substituted)
is then quoted so that the whole string can be used as a shell
argument. This is the reverse of `tt(~)' substitution: see
ifnzman(noderef(Filename Expansion))\
@@ -1126,13 +1126,14 @@ in string arguments to any of the flags described below that
follow this argument.
)
item(tt(~))(
-Force string arguments to any of the flags below that follow within
-the parentheses to be treated as patterns. Compare with a tt(~)
+Strings inserted into the expansion by any of the flags below are to
+be treated as patterns. This applies to the string arguments of flags
+that follow tt(~) within the same set of parentheses. Compare with tt(~)
outside parentheses, which forces the entire substituted string to
be treated as a pattern. Hence, for example,
example([[ "?" = ${(~j.|.)array} ]])
-with the tt(EXTENDED_GLOB) option set succeeds if and only if tt($array)
-contains the string `tt(?)' as an element. The argument may be
+treats `tt(|)' as a pattern and succeeds if and only if tt($array)
+contains the string `tt(?)' as an element. The tt(~) may be
repeated to toggle the behaviour; its effect only lasts to the
end of the parenthesised group.
)
@@ -1155,6 +1156,10 @@ var(string1) and var(string2) are given, tt(string2) is inserted once
directly to the left of each word, truncated if necessary, before
var(string1) is used to produce any remaining padding.
+If either of var(string1) or tt(string2) is present but empty,
+i.e. there are two delimiters together at that point, the first
+character of tt($IFS) is used instead.
+
If the tt(MULTIBYTE) option is in effect, the flag tt(m) may also
be given, in which case widths will be used for the calculation of
padding; otherwise individual multibyte characters are treated as occupying
@@ -2658,6 +2663,12 @@ list of glob qualifiers.
A typical use for this is to prepend an option before all occurrences
of a file name; for example, the pattern `tt(*(P:-f:))' produces the
command line arguments `tt(-f) var(file1) tt(-f) var(file2) ...'
+
+If the modifier tt(^) is active, then var(string) will be appended
+instead of prepended. Prepending and appending is done independently
+so both can be used on the same glob expression; for example by writing
+`tt(*(P:foo:^P:bar:^P:baz:))' which produces the command line arguments
+`tt(foo) tt(baz) var(file1) tt(bar) ...'
)
enditem()
diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo
index 77f0098e3..4d04c2470 100644
--- a/Doc/Zsh/grammar.yo
+++ b/Doc/Zsh/grammar.yo
@@ -352,6 +352,15 @@ If the option tt(SH_GLOB) is set for compatibility with other shells, then
whitespace may appear between between the left and right parentheses when
there is a single var(word); otherwise, the parentheses will be treated as
forming a globbing pattern in that case.
+
+In any of the forms above, a redirection may appear outside the
+function body, for example
+
+example(func+LPAR()RPAR() { ... } 2>&1)
+
+The redirection is stored with the function and applied whenever the
+function is executed. Any variables in the redirection are expanded
+at the point the function is executed, but outside the function scope.
)
cindex(timing)
findex(time)
diff --git a/Doc/Zsh/mod_computil.yo b/Doc/Zsh/mod_computil.yo
index 593f85ad3..af537c9c0 100644
--- a/Doc/Zsh/mod_computil.yo
+++ b/Doc/Zsh/mod_computil.yo
@@ -33,12 +33,12 @@ arguments are like the definition arguments to tt(_describe) itself.
Once tt(compdescribe) has been called with either the tt(-i) or the
tt(-I) option, it can be repeatedly called with the tt(-g) option and
-the names of five arrays as its arguments. This will step through the
-different sets of matches and store the options in the first array,
-the strings with descriptions in the second, the matches for these in
-the third, the strings without descriptions in the fourth, and the
-matches for them in the fifth array. These are then directly given to
-tt(compadd) to register the matches with the completion code.
+the names of four parameters as its arguments. This will step through
+the different sets of matches and store the value of tt(compstate[list])
+in the first scalar, the options for tt(compadd) in the second array,
+the matches in the third array, and the strings to be displayed in the
+completion listing in the fourth array. The arrays may then be directly
+given to tt(compadd) to register the matches with the completion code.
)
findex(compfiles)
item(tt(compfiles))(
diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo
index 32d4796f7..09ceba258 100644
--- a/Doc/Zsh/mod_parameter.yo
+++ b/Doc/Zsh/mod_parameter.yo
@@ -212,6 +212,14 @@ This array contains the names of the functions, sourced files,
and (if tt(EVAL_LINENO) is set) tt(eval) commands. currently being
executed. The first element is the name of the function using the
parameter.
+
+The standard shell array tt(zsh_eval_context) can be used to
+determine the type of shell construct being executed at each depth:
+note, however, that is in the opposite order, with the most recent
+item last, and it is more detailed, for example including an
+entry for tt(toplevel), the main shell code being executed
+either interactively or from a script, which is not present
+in tt($funcstack).
)
vindex(functrace)
item(tt(functrace))(
diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo
index ee9ec3adf..7e8911113 100644
--- a/Doc/Zsh/mod_zutil.yo
+++ b/Doc/Zsh/mod_zutil.yo
@@ -265,7 +265,7 @@ string var(array) is interpreted as the name of another var(spec),
which is used to choose where to store the values. If no other var(spec)
is found, the values are stored as usual. This changes only the way the
values are stored, not the way tt($*) is parsed, so results may be
-unpredicable if the `var(name)tt(+)' specifier is used inconsistently.
+unpredictable if the `var(name)tt(+)' specifier is used inconsistently.
)
item(tt(-E))(
This changes the parsing rules to em(not) stop at the first string
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index ec1f1645a..068a253ac 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -1780,7 +1780,7 @@ cindex(tracing, of commands)
cindex(commands, tracing)
item(tt(XTRACE) (tt(-x), ksh: tt(-x)))(
Print commands and their arguments as they are executed. The
-output is proceded by the value of tt($PS4), formatted as described
+output is preceded by the value of tt($PS4), formatted as described
in
ifzman(the section EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\
ifnzman(noderef(Prompt Expansion)).
@@ -2079,7 +2079,7 @@ variables, or in arguments to external programs.
When this option is set, the tt($')var(...)tt(') expression is truncated at
the null character. Note that remaining parts of the same string
-beyond the termination of the quotes are not trunctated.
+beyond the termination of the quotes are not truncated.
For example, the command line argument tt(a$'b\0c'd) is treated with
the option off as the characters tt(a), tt(b), null, tt(c), tt(d),
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index dbac51182..3698829f3 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -1042,7 +1042,7 @@ backquotes only. Should the chosen character be one of singlequote,
doublequote or backquote, there must also be an odd number of them
on the command line for the last one to be removed.
-For backward compabitility, if the tt(SUNKEYBOARDHACK) option is
+For backward compatibility, if the tt(SUNKEYBOARDHACK) option is
explicitly set, the value of tt(KEYBOARD_HACK) reverts to backquote.
If the option is explicitly unset, this variable is set to empty.
)
diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo
index 0ed52b580..17af5b0fb 100644
--- a/Doc/Zsh/prompt.yo
+++ b/Doc/Zsh/prompt.yo
@@ -108,6 +108,12 @@ the full path;
ifzman(see em(Dynamic) and em(Static named directories) in zmanref(zshexpn))\
ifnzman(noderef(Filename Expansion)).
)
+item(tt(%e))(
+Evaluation depth of the current sourced file, shell function, or tt(eval).
+This is incremented or decremented every time the value of tt(%N) is
+set or reverted to a previous value, respectively. This is most useful
+for debugging as part of tt($PS4).
+)
xitem(tt(%h))
item(tt(%!))(
Current history event number.
@@ -299,6 +305,7 @@ least var(n) elements relative to the root directory, hence tt(/) is
counted as 0 elements.)
sitem(tt(D))(True if the month is equal to var(n) (January = 0).)
sitem(tt(d))(True if the day of the month is equal to var(n).)
+sitem(tt(e))(True if the evaluation depth is at least var(n).)
sitem(tt(g))(True if the effective gid of the current process is var(n).)
sitem(tt(j))(True if the number of jobs is at least var(n).)
sitem(tt(L))(True if the tt(SHLVL) parameter is at least var(n).)
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 2a907c52c..98f38025a 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -2315,7 +2315,7 @@ These characters are described below.
)
cindex(completion removable suffix, highlighting)
cindex(suffix, highlighting removable, in completion)
-cindex(removable suffix, highlighting in completino)
+cindex(removable suffix, highlighting in completion)
item(tt(suffix))(
This context is used in completion for characters that are
marked as suffixes that will be removed if the completion ends
diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo
index ed703c68b..08ea979ee 100644
--- a/Etc/FAQ.yo
+++ b/Etc/FAQ.yo
@@ -302,7 +302,7 @@ sect(On what machines will it run?)
sect(What's the latest version?)
- Zsh 5.0.6 is the latest production version. For details of all the
+ Zsh 5.0.7 is the latest production version. For details of all the
changes, see the NEWS file in the source distribution.
A beta of the next version is sometimes available. Development of zsh is
diff --git a/Etc/zsh-development-guide b/Etc/zsh-development-guide
index 37364e118..2ed75423b 100644
--- a/Etc/zsh-development-guide
+++ b/Etc/zsh-development-guide
@@ -931,18 +931,22 @@ freely available tools.
To indicate which files should be distributed, each directory in the git
tree includes a file .distfiles that sets any number of a set of Bourne
shell (scalar) parameters. The value of the parameter is expanded as a
-set of standard command line arguments. Basic globbing is allowed in the
-values.
+set of standard command line arguments. Apart from DISTFILES_NOT, which
+must be an explicit list of files separated by whitespace, basic
+globbing is allowed in the values.
+
+Because of the way DISTFILES_SRC is constructed it is only possible
+to make a release from a git checkout.
The following parameters are currently used:
- DISTFILES_SRC is a list of files from the directory for the "src"
- distribution.
+ distribution. However, if the file .distfiles is present in
+ a directory, all files known to git will be added to DISTFILES_SRC
+ except for files listed explicitly in DISTFILES_NOT.
- DISTFILES_DOC is a list of files from the directory for the "doc"
distribution.
- DISTFILES_NOT is a list of files that will not be included in a
- distribution, but that need to be present in the git tree. This
- variable is not used by the zsh build process and is present for
- the convenience of external checks.
+ distribution even though they are present in the git tree.
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
index 76ab92f33..ee50be6ca 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
@@ -3,9 +3,9 @@
## Distributed under the same BSD-ish license as zsh itself.
setopt localoptions extendedglob NO_shwordsplit
-local gitdir gitbase gitbranch gitaction gitunstaged gitstaged gitsha1
-local stgitpatch stgitunapplied
+local gitdir gitbase gitbranch gitaction gitunstaged gitstaged gitsha1 gitmisc
local -i querystaged queryunstaged
+local -a git_patches_applied git_patches_unapplied
local -A hook_com
VCS_INFO_git_getaction () {
@@ -62,6 +62,11 @@ VCS_INFO_git_getaction () {
return 0
fi
+ if [[ -d "${gitdir}/sequencer" ]] ; then
+ gitaction="cherry-or-revert"
+ return 0
+ fi
+
return 1
}
@@ -108,8 +113,48 @@ VCS_INFO_git_getbranch () {
return 0
}
+VCS_INFO_git_handle_patches () {
+ local git_applied_s git_unapplied_s gitmsg git_all
+ git_patches_applied=(${(Oa)git_patches_applied})
+ git_patches_unapplied=(${(Oa)git_patches_unapplied})
+ (( git_all = ${#git_patches_applied} + ${#git_patches_unapplied} ))
+
+ if VCS_INFO_hook 'gen-applied-string' "${git_patches_applied[@]}"; then
+ if (( ${#git_patches_applied} )); then
+ git_applied_s=${git_patches_applied[1]}
+ else
+ git_applied_s=""
+ fi
+ else
+ git_applied_s=${hook_com[applied-string]}
+ fi
+ hook_com=()
+ if VCS_INFO_hook 'gen-unapplied-string' "${git_patches_unapplied[@]}"; then
+ git_patches_unapplied=${#git_patches_unapplied}
+ else
+ git_patches_unapplied=${hook_com[unapplied-string]}
+ fi
+
+ if (( ${#git_patches_applied} )); then
+ zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" patch-format gitmsg || gitmsg="%p (%n applied)"
+ else
+ zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" nopatch-format gitmsg || gitmsg="no patch applied"
+ fi
+ hook_com=( applied "${git_applied_s}" unapplied "${git_patches_unapplied}"
+ applied-n ${#git_patches_applied} unapplied-n ${#git_patches_unapplied} all-n ${git_all} )
+ if VCS_INFO_hook 'set-patch-format' "${gitmsg}"; then
+ zformat -f gitmisc "${gitmsg}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
+ "n:${#git_patches_applied}" "c:${#git_patches_unapplied}" "a:${git_all}"
+ else
+ gitmisc=${hook_com[patch-replace]}
+ fi
+ hook_com=()
+}
+
gitdir=${vcs_comm[gitdir]}
VCS_INFO_git_getbranch ${gitdir}
+gitbase=$( ${vcs_comm[cmd]} rev-parse --show-toplevel )
+rrn=${gitbase:t}
if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then
gitsha1=$(${vcs_comm[cmd]} rev-parse --quiet --verify HEAD)
else
@@ -131,17 +176,17 @@ if (( querystaged || queryunstaged )) && \
[[ "$(${vcs_comm[cmd]} rev-parse --is-inside-work-tree 2> /dev/null)" == 'true' ]] ; then
# Default: off - these are potentially expensive on big repositories
if (( queryunstaged )) ; then
- ${vcs_comm[cmd]} diff --no-ext-diff --ignore-submodules --quiet --exit-code ||
+ ${vcs_comm[cmd]} diff --no-ext-diff --ignore-submodules=dirty --quiet --exit-code ||
gitunstaged=1
fi
if (( querystaged )) ; then
if ${vcs_comm[cmd]} rev-parse --quiet --verify HEAD &> /dev/null ; then
- ${vcs_comm[cmd]} diff-index --cached --quiet --ignore-submodules HEAD 2> /dev/null
+ ${vcs_comm[cmd]} diff-index --cached --quiet --ignore-submodules=dirty HEAD 2> /dev/null
(( $? && $? != 128 )) && gitstaged=1
else
# empty repository (no commits yet)
# 4b825dc642cb6eb9a060e54bf8d69288fbee4904 is the git empty tree.
- ${vcs_comm[cmd]} diff-index --cached --quiet --ignore-submodules 4b825dc642cb6eb9a060e54bf8d69288fbee4904 2>/dev/null
+ ${vcs_comm[cmd]} diff-index --cached --quiet --ignore-submodules=dirty 4b825dc642cb6eb9a060e54bf8d69288fbee4904 2>/dev/null
(( $? && $? != 128 )) && gitstaged=1
fi
fi
@@ -149,55 +194,47 @@ fi
VCS_INFO_adjust
VCS_INFO_git_getaction ${gitdir}
-gitbase=$( ${vcs_comm[cmd]} rev-parse --show-toplevel )
-rrn=${gitbase:t}
+
+
+VCS_INFO_get_get_rebase()
+{
+ if [[ -f "$1" ]]; then
+ echo "$(< "$1")"
+ fi
+}
local patchdir=${gitdir}/patches/${gitbranch}
if [[ -d $patchdir ]] && [[ -f $patchdir/applied ]] \
&& [[ -f $patchdir/unapplied ]]
then
- local -a stgit_applied stgit_unapplied stgit_all
-
- stgit_applied=(${(f)"$(< "${patchdir}/applied")"})
- stgit_applied=( ${(Oa)stgit_applied} )
- stgit_unapplied=(${(f)"$(< "${patchdir}/unapplied")"})
- stgit_unapplied=( ${(oa)stgit_unapplied} )
- stgit_all=( ${(Oa)stgit_applied} ${stgit_unapplied} )
-
- if VCS_INFO_hook 'gen-applied-string' "${stgit_applied[@]}"; then
- if (( ${#stgit_applied} )); then
- stgitpatch=${stgit_applied[1]}
- else
- stgitpatch=""
- fi
- else
- stgitpatch=${hook_com[patch-string]}
- fi
- hook_com=()
- if VCS_INFO_hook 'gen-unapplied-string' "${stgit_unapplied[@]}"; then
- stgitunapplied=${#stgit_unapplied}
- else
- stgitunapplied=${hook_com[unapplied-string]}
- fi
+ git_patches_applied=(${(f)"$(< "${patchdir}/applied")"})
+ git_patches_unapplied=(${(f)"$(< "${patchdir}/unapplied")"})
+ VCS_INFO_git_handle_patches
+elif [[ -d "${gitdir}/rebase-merge" ]]; then
+ patchdir="${gitdir}/rebase-merge"
+ local p
+ for p in ${(f)"$(< "${patchdir}/done")"}; do
+ # remove action
+ git_patches_applied+=("${${(s: :)p}[2,-1]}")
+ done
+ git_patches_unapplied=(${(f)"$(grep -v '^$' "${patchdir}/git-rebase-todo" | grep -v '^#')"})
+ VCS_INFO_git_handle_patches
+elif [[ -d "${gitdir}/rebase-apply" ]]; then
+ # Fake patch names for all but current patch
+ patchdir="${gitdir}/rebase-apply"
+ local cur=$(< "${patchdir}/next")
+ local p
+ for p in $(seq $(($cur - 1))); do
+ git_patches_applied+=("$(printf "%04d" $p) ?")
+ done
+ git_patches_applied+=("$(< "${patchdir}/original-commit") ${${(f)$(< "${patchdir}/msg-clean")}[1]}")
+ git_patches_unapplied=($(seq $cur $(< "${patchdir}/last")))
- if (( ${#stgit_applied} )); then
- zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" patch-format stgitmsg || stgitmsg="%p (%n applied)"
- else
- zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" nopatch-format stgitmsg || stgitmsg="no patch applied"
- fi
- hook_com=( applied "${stgitpatch}" unapplied "${stgitunapplied}"
- applied-n ${#stgit_applied} unapplied-n ${#stgit_unapplied} all-n ${#stgit_all} )
- if VCS_INFO_hook 'set-patch-format' "${stgitmsg}"; then
- zformat -f stgitmsg "${stgitmsg}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
- "n:${#stgit_applied}" "c:${#stgit_unapplied}" "a:${#stgit_all}"
- else
- stgitmsg=${hook_com[patch-replace]}
- fi
- hook_com=()
+ VCS_INFO_git_handle_patches
else
- stgitmsg=''
+ gitmisc=''
fi
-backend_misc[patches]="${stgitmsg}"
-VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}" "${gitstaged}" "${gitunstaged}" "${gitsha1}" "${stgitmsg}"
+backend_misc[patches]="${gitmisc}"
+VCS_INFO_formats "${gitaction}" "${gitbranch}" "${gitbase}" "${gitstaged}" "${gitunstaged}" "${gitsha1}" "${gitmisc}"
return 0
diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt
index 7001eca07..db15dda74 100644
--- a/Functions/VCS_Info/VCS_INFO_quilt
+++ b/Functions/VCS_Info/VCS_INFO_quilt
@@ -70,13 +70,11 @@ function VCS_INFO_quilt-dirfind() {
olddir=${vcs_comm[basedir]}
vcs_comm[basedir]=''
- if [[ -n "${file}" ]]; then
- oldfile=${vcs_comm[detect_need_file]}
- vcs_comm[detect_need_file]=${file}
- fi
+ oldfile=${vcs_comm[detect_need_file]}
+ vcs_comm[detect_need_file]=${file}
VCS_INFO_bydir_detect ${dir}
ret=$?
- [[ -n "${file}" ]] && vcs_comm[detect_need_file]=${oldfile}
+ vcs_comm[detect_need_file]=${oldfile}
printf '%s' ${vcs_comm[basedir]}
vcs_comm[basedir]="${olddir}"
return ${ret}
diff --git a/Functions/VCS_Info/VCS_INFO_reposub b/Functions/VCS_Info/VCS_INFO_reposub
index 1c16f0e7b..8ebc90b6e 100644
--- a/Functions/VCS_Info/VCS_INFO_reposub
+++ b/Functions/VCS_Info/VCS_INFO_reposub
@@ -3,11 +3,12 @@
## Distributed under the same BSD-ish license as zsh itself.
setopt localoptions extendedglob NO_shwordsplit
-local base=${1%%/##}
+local base=${1%%/##} tmp
-[[ $(pwd -P) == ${base}/* ]] || {
+tmp="$(pwd -P)"
+[[ $tmp == ${base}/* ]] || {
printf '.'
return 1
}
-printf '%s' ${$(pwd -P)#$base/}
+printf '%s' ${tmp#$base/}
return 0
diff --git a/Misc/vcs_info-examples b/Misc/vcs_info-examples
index 5d8ff187e..766eb82a4 100644
--- a/Misc/vcs_info-examples
+++ b/Misc/vcs_info-examples
@@ -301,7 +301,7 @@ zstyle ':vcs_info:*+pre-get-data:*' hooks pre-get-data
# If we got to this point, running vcs_info was not forced, so now we
# default to not running it and selectively choose when we want to run
- # it (ret=1 means run it, ret=0 means don't).
+ # it (ret=0 means run it, ret=1 means don't).
ret=1
# If a git/hg command was run then run vcs_info as the status might
# need to be updated.
diff --git a/NEWS b/NEWS
index 1f2a9daad..bf8969b26 100644
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,11 @@ Changes since 5.0.0
- Numeric constants encountered in mathematical expressions (but not other
contexts) can contain underscores as separators that will be ignored on
evaluation, as allowed in other scripting languages. For example,
- 0xFFFF_FFFF, or 3.141_592_654.
+ 0xFFFF_FFFF, or 3.141_592_654. From 5.0.6 this is also available
+ in output, e.g.
+ setopt cbases
+ zmodload zsh/mathfunc
+ print $(( [#16_4] 2**32 - 1 )) $(( [#_3] 4 * atan(1.0) ))
- "functions -T" turns on tracing for the specified function(s) only,
similar to "functions -t" except that tracing is turned off for any
@@ -21,6 +25,14 @@ Changes since 5.0.0
to be treated as floating point. This is most useful locally within
functions or scripts performing floating point calculations.
+- The default $fpath/$FPATH is now designed always to include
+ /usr/local/share/zsh/site-functions. This directory does not need to
+ exist. Sites that set an explicit site directory can put that in
+ /etc/zshenv as before. The intention of the new path element is to
+ increase the likelihood that locally added functions can be found with
+ the shell running "out of the box", no matter how the shell was
+ configured.
+
- Individual pattern characters can be disabled. For example, to allow '^'
to be an ordinary character even if the option EXTENDED_GLOB is set, use
"disable -p '^'".
@@ -39,7 +51,7 @@ Changes since 5.0.0
- In file completion, the recursive-files style can be set to an array of
patterns to match against "$PWD/". In any matched location, it is
- possibly to complete files in arbitrarily deep subdirectories without
+ possible to complete files in arbitrarily deep subdirectories without
needing to type the directory prefix. See example in the zshcompsys
manual.
@@ -71,13 +83,17 @@ Changes since 5.0.0
values of N still count the space used since the start of the prompt).
In PS1 and PROMPT, this counts to the right margin, whereas in RPS1 and
RPROMPT, it counts to the left margin (not to the opposite prompt).
-
+
+- Also in prompt strings, %e or the equivalent test %(e..) are used to
+ output or test the execution / evaluation depth of a shell
+ construct within functions etc. This is useful in $PS4.
+
- Another new prompt feature is the %. escape within time strings, for
- example %D{%H:%M:%S.%.}. It provides zero-padded decimal fractions of
+ example %D{%H:%M:%S.%.}. It provides zero-padded decimal fractions of a
second; by default milliseconds are shown, but the number of digits may
be indicated from 1 to 6, e.g. "%6.". (Note this is part of the
extensions to strftime() formats rather than basic prompt escapes.)
-
+
- The operators :^ and :^^ in parameter substitution allow for array
zipping in the form ${name:^array}. With the :^ operator, all entries
in $name and $array will be output in alternating order. With :^ the
@@ -91,6 +107,13 @@ Changes since 5.0.0
Also, the value of $pipestatus is now updated when a job stops, not just
when it exits.
+- Redirections applied to function definitions take effect when the
+ function is executed, not when it is defined. Other shells already
+ work this way. For example,
+ fn() { echo hello } >~/logfile
+ Running fn writes "hello" to logfile. In older versions of the shell
+ it would create an empty file at the point of definition.
+
Changes between 4.2 and 5.0.0
-----------------------------
diff --git a/README b/README
index 198e4c8ff..e3ccc70b1 100644
--- a/README
+++ b/README
@@ -5,8 +5,16 @@ THE Z SHELL (ZSH)
Version
-------
-This is version 5.0.6 of the shell. This is a stable release.
-There are minor new features as well as bug fixes since 5.0.5.
+This is version 5.0.7 of the shell. This is a stable release.
+There are minor new features as well as bug fixes since 5.0.6.
+
+Note in particular there is a security fix to disallow evaluation of the
+initial values of integer variables imported from the environment (they
+are instead treated as literal numbers). That could allow local
+privilege escalation, under some specific and atypical conditions where
+zsh is being invoked in privilege elevation contexts when the
+environment has not been properly sanitized, such as when zsh is invoked
+by sudo on systems where "env_reset" has been disabled.
Installing Zsh
--------------
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 0385a709e..55157a90c 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -392,20 +392,36 @@ getfunction(UNUSED(HashTable ht), const char *name, int dis)
((shf->node.flags & PM_TAGGED) ? "t" : "")));
} else {
char *t = getpermtext(shf->funcdef, NULL, 1), *n, *h;
+ char *start;
+
+ if (shf->redir)
+ start = "{\n\t";
+ else
+ start = "\t";
if (shf->funcdef->flags & EF_RUN) {
n = nicedupstring(name);
- h = (char *) zhalloc(strlen(t) + strlen(n) + 9);
- h[0] = '\t';
- strcpy(h + 1, t);
+ h = (char *) zhalloc(strlen(start) + strlen(t) + strlen(n) + 8);
+ strcpy(h, start);
+ strcat(h, t);
strcat(h, "\n\t");
strcat(h, n);
strcat(h, " \"$@\"");
} else
- h = dyncat("\t", t);
+ h = dyncat(start, t);
zsfree(t);
+ /*
+ * TBD: Is this unmetafy correct? Surely as this
+ * is a parameter value it stays metafied?
+ */
unmetafy(h, NULL);
+ if (shf->redir) {
+ t = getpermtext(shf->redir, NULL, 1);
+ h = zhtricat(h, "\n}", t);
+ zsfree(t);
+ }
+
pm->u.str = h;
}
} else {
@@ -456,21 +472,38 @@ scanfunctions(UNUSED(HashTable ht), ScanFunc func, int flags, int dis)
((shf->node.flags & PM_TAGGED) ? "Ut" : "U") :
((shf->node.flags & PM_TAGGED) ? "t" : "")));
} else {
- char *t = getpermtext(((Shfunc) hn)->funcdef, NULL, 1);
- char *n;
+ Shfunc shf = (Shfunc)hn;
+ char *t = getpermtext(shf->funcdef, NULL, 1);
+ char *n, *start;
- if (((Shfunc) hn)->funcdef->flags & EF_RUN) {
+ if (shf->redir)
+ start = "{\n\t";
+ else
+ start = "\t";
+
+ if (shf->funcdef->flags & EF_RUN) {
n = nicedupstring(hn->nam);
- pm.u.str = (char *) zhalloc(strlen(t) + strlen(n) + 9);
- pm.u.str[0] = '\t';
- strcpy(pm.u.str + 1, t);
+ pm.u.str = (char *) zhalloc(
+ strlen(start) + strlen(t) + strlen(n) + 8);
+ strcpy(pm.u.str, start);
+ strcat(pm.u.str, t);
strcat(pm.u.str, "\n\t");
strcat(pm.u.str, n);
strcat(pm.u.str, " \"$@\"");
} else
- pm.u.str = dyncat("\t", t);
+ pm.u.str = dyncat(start, t);
+ /*
+ * TBD: Is this unmetafy correct? Surely as this
+ * is a parameter value it stays metafied?
+ */
unmetafy(pm.u.str, NULL);
zsfree(t);
+
+ if (shf->redir) {
+ t = getpermtext(shf->redir, NULL, 1);
+ pm.u.str = zhtricat(pm.u.str, "\n}", t);
+ zsfree(t);
+ }
}
}
func(&pm.node, flags);
diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c
index 040a33f8e..2393cd1e7 100644
--- a/Src/Modules/pcre.c
+++ b/Src/Modules/pcre.c
@@ -289,7 +289,7 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
matched_portion = OPT_ARG(ops,c);
}
if(OPT_HASARG(ops,c='n')) { /* The offset position to start the search, in bytes. */
- if ((offset_start = getposint(OPT_ARG(ops,c), nam) < 0))
+ if ((offset_start = getposint(OPT_ARG(ops,c), nam)) < 0)
return 1;
}
/* For the entire match, 'Return' the offset byte positions instead of the matched string */
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index ac7785ab7..35d410cc6 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -702,6 +702,7 @@ callcompfunc(char *s, char *fn)
}
zsfree(compprefix);
zsfree(compsuffix);
+ makebangspecial(0);
if (unset(COMPLETEINWORD)) {
tmp = (linwhat == IN_MATH ? dupstring(s) : multiquote(s, 0));
untokenize(tmp);
@@ -722,6 +723,7 @@ callcompfunc(char *s, char *fn)
untokenize(ss);
compsuffix = ztrdup(ss);
}
+ makebangspecial(1);
zsfree(complastprefix);
zsfree(complastsuffix);
complastprefix = ztrdup(compprefix);
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index 52b9e9c82..0b7a32445 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -3416,7 +3416,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
*npp++ = tp;
pp++;
}
- *npp = '\0';
+ *npp = NULL;
}
}
if (!dirs) {
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 80be27f03..684ac13a2 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -258,7 +258,6 @@ static const REFRESH_ELEMENT zr_cr = { ZWC('\r'), 0 };
static const REFRESH_ELEMENT zr_dt = { ZWC('.'), 0 };
static const REFRESH_ELEMENT zr_nl = { ZWC('\n'), 0 };
static const REFRESH_ELEMENT zr_sp = { ZWC(' '), 0 };
-static const REFRESH_ELEMENT zr_ht = { ZWC('\t'), 0 };
static const REFRESH_ELEMENT zr_zr = { ZWC('\0'), 0 };
/*
@@ -429,7 +428,7 @@ get_region_highlight(UNUSED(Param pm))
digbuf1, digbuf2);
(void)output_highlight(rhp->atr, *arrp + strlen(*arrp));
}
- *arrp = '\0';
+ *arrp = NULL;
return retarr;
}
diff --git a/Src/builtin.c b/Src/builtin.c
index a2a3ad748..4a10c7dd1 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2759,7 +2759,7 @@ bin_functions(char *name, char **argv, Options ops, int func)
tokenize(*argv);
if ((pprog = patcompile(*argv, PAT_STATIC, 0))) {
queue_signals();
- for (p = mathfuncs, q = NULL; p; q = p, p = p->next) {
+ for (p = mathfuncs, q = NULL; p; q = p) {
MathFunc next;
do {
next = NULL;
@@ -2774,6 +2774,8 @@ bin_functions(char *name, char **argv, Options ops, int func)
}
/* if we deleted one, retry with the new p */
} while (next);
+ if (p)
+ p = p->next;
}
unqueue_signals();
} else {
diff --git a/Src/exec.c b/Src/exec.c
index 5ad957f98..d0fadd69a 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -198,7 +198,8 @@ static char *blank_env[] = { NULL };
/* Execution functions. */
static int (*execfuncs[WC_COUNT-WC_CURSH]) _((Estate, int)) = {
- execcursh, exectime, execfuncdef, execfor, execselect,
+ execcursh, exectime, NULL /* execfuncdef handled specially */,
+ execfor, execselect,
execwhile, execrepeat, execcase, execif, execcond,
execarith, execautofn, exectry
};
@@ -1005,6 +1006,8 @@ entersubsh(int flags)
signal_default(SIGTERM);
if (!(sigtrapped[SIGINT] & ZSIG_IGNORED))
signal_default(SIGINT);
+ if (!(sigtrapped[SIGPIPE]))
+ signal_default(SIGPIPE);
}
if (!(sigtrapped[SIGQUIT] & ZSIG_IGNORED))
signal_default(SIGQUIT);
@@ -1116,8 +1119,11 @@ execsimple(Estate state)
fflush(xtrerr);
}
lv = (errflag ? errflag : cmdoutval);
- } else
+ } else if (code == WC_FUNCDEF) {
+ lv = execfuncdef(state, NULL);
+ } else {
lv = (execfuncs[code - WC_CURSH])(state, 0);
+ }
thisjob = otj;
@@ -2783,6 +2789,58 @@ execcmd(Estate state, int input, int output, int how, int last1)
errflag = 1;
}
+ if (type == WC_FUNCDEF) {
+ /*
+ * The first word of a function definition is a list of
+ * names. If this is empty, we're doing an anonymous function:
+ * in that case redirections are handled normally.
+ * If not, it's a function definition: then we don't do
+ * redirections here but pass in the list of redirections to
+ * be stored for recall with the function.
+ */
+ if (*state->pc != 0) {
+ /* Nonymous, don't do redirections here */
+ redir = NULL;
+ }
+ } else if (is_shfunc || type == WC_AUTOFN) {
+ Shfunc shf;
+ if (is_shfunc)
+ shf = (Shfunc)hn;
+ else {
+ shf = loadautofn(state->prog->shf, 1, 0);
+ if (shf)
+ state->prog->shf = shf;
+ else {
+ /*
+ * This doesn't set errflag, so just return now.
+ */
+ lastval = 1;
+ if (oautocont >= 0)
+ opts[AUTOCONTINUE] = oautocont;
+ return;
+ }
+ }
+ /*
+ * A function definition may have a list of additional
+ * redirections to apply, so retrieve it.
+ */
+ if (shf->redir) {
+ struct estate s;
+ LinkList redir2;
+
+ s.prog = shf->redir;
+ s.pc = shf->redir->prog;
+ s.strs = shf->redir->strs;
+ redir2 = ecgetredirs(&s);
+ if (!redir)
+ redir = redir2;
+ else {
+ while (nonempty(redir2))
+ addlinknode(redir, ugetnode(redir2));
+ }
+ }
+ }
+
if (errflag) {
lastval = 1;
if (oautocont >= 0)
@@ -3050,7 +3108,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
break;
case REDIR_CLOSE:
if (fn->varid) {
- char *s = fn->varid;
+ char *s = fn->varid, *t;
struct value vbuf;
Value v;
int bad = 0;
@@ -3060,13 +3118,25 @@ execcmd(Estate state, int input, int output, int how, int last1)
} else if (v->pm->node.flags & PM_READONLY) {
bad = 2;
} else {
- fn->fd1 = (int)getintvalue(v);
+ s = getstrvalue(v);
if (errflag)
bad = 1;
- else if (fn->fd1 <= max_zsh_fd) {
- if (fn->fd1 >= 10 &&
- fdtable[fn->fd1] == FDT_INTERNAL)
- bad = 3;
+ else {
+ fn->fd1 = zstrtol(s, &t, 0);
+ if (s == t)
+ bad = 1;
+ else if (*t) {
+ /* Check for base#number format */
+ if (*t == '#' && *s != '0')
+ fn->fd1 = zstrtol(s = t+1, &t, fn->fd1);
+ if (s == t || *t)
+ bad = 1;
+ }
+ if (!bad && fn->fd1 <= max_zsh_fd) {
+ if (fn->fd1 >= 10 &&
+ fdtable[fn->fd1] == FDT_INTERNAL)
+ bad = 3;
+ }
}
}
if (bad) {
@@ -3131,7 +3201,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
fil = movefd(dup(fd));
}
if (fil == -1) {
- char fdstr[4];
+ char fdstr[DIGBUFSIZE];
closemnodes(mfds);
fixfds(save);
@@ -3226,10 +3296,44 @@ execcmd(Estate state, int input, int output, int how, int last1)
flags |= ESUB_REVERTPGRP;
entersubsh(flags);
}
- if (type >= WC_CURSH) {
+ if (type == WC_FUNCDEF) {
+ Eprog redir_prog;
+ if (!redir && wc_code(*beg) == WC_REDIR) {
+ /*
+ * We're not using a redirection from the currently
+ * parsed environment, which is what we'd do for an
+ * anonymous function, but there are redirections we
+ * should store with the new function.
+ */
+ struct estate s;
+
+ s.prog = state->prog;
+ s.pc = beg;
+ s.strs = state->prog->strs;
+
+ /*
+ * The copy uses the wordcode parsing area, so save and
+ * restore state.
+ */
+ lexsave();
+ redir_prog = eccopyredirs(&s);
+ lexrestore();
+ } else
+ redir_prog = NULL;
+
+ lastval = execfuncdef(state, redir_prog);
+ }
+ else if (type >= WC_CURSH) {
if (last1 == 1)
do_exec = 1;
- lastval = (execfuncs[type - WC_CURSH])(state, do_exec);
+ if (type == WC_AUTOFN) {
+ /*
+ * We pre-loaded this to get any redirs.
+ * So we execuate a simplified function here.
+ */
+ lastval = execautofn_basic(state, do_exec);
+ } else
+ lastval = (execfuncs[type - WC_CURSH])(state, do_exec);
} else if (is_builtin || is_shfunc) {
LinkList restorelist = 0, removelist = 0;
/* builtin or shell function */
@@ -3569,8 +3673,11 @@ closem(int how)
for (i = 10; i <= max_zsh_fd; i++)
if (fdtable[i] != FDT_UNUSED &&
- (how == FDT_UNUSED || fdtable[i] == how))
+ (how == FDT_UNUSED || fdtable[i] == how)) {
+ if (i == SHTTY)
+ SHTTY = -1;
zclose(i);
+ }
}
/* convert here document into a here string */
@@ -4220,11 +4327,12 @@ exectime(Estate state, UNUSED(int do_exec))
/**/
static int
-execfuncdef(Estate state, UNUSED(int do_exec))
+execfuncdef(Estate state, Eprog redir_prog)
{
Shfunc shf;
char *s = NULL;
int signum, nprg, sbeg, nstrs, npats, len, plen, i, htok = 0, ret = 0;
+ int nfunc = 0;
Wordcode beg = state->pc, end;
Eprog prog;
Patprog *pp;
@@ -4249,6 +4357,8 @@ execfuncdef(Estate state, UNUSED(int do_exec))
}
}
+ DPUTS(!names && redir_prog,
+ "Passing redirection to anon function definition.");
while (!names || (s = (char *) ugetnode(names))) {
if (!names) {
prog = (Eprog) zhalloc(sizeof(*prog));
@@ -4290,6 +4400,15 @@ execfuncdef(Estate state, UNUSED(int do_exec))
shf->node.flags = 0;
shf->filename = ztrdup(scriptfilename);
shf->lineno = lineno;
+ /*
+ * redir_prog is permanently allocated --- but if
+ * this function has multiple names we need an additional
+ * one.
+ */
+ if (nfunc++ && redir_prog)
+ shf->redir = dupeprog(redir_prog, 0);
+ else
+ shf->redir = redir_prog;
shfunc_set_sticky(shf);
if (!names) {
@@ -4320,6 +4439,8 @@ execfuncdef(Estate state, UNUSED(int do_exec))
ret = lastval;
freeeprog(shf->funcdef);
+ if (shf->redir) /* shouldn't be */
+ freeeprog(shf->redir);
zsfree(shf->filename);
zfree(shf, sizeof(*shf));
break;
@@ -4343,6 +4464,10 @@ execfuncdef(Estate state, UNUSED(int do_exec))
shfunctab->addnode(shfunctab, ztrdup(s), shf);
}
}
+ if (!nfunc && redir_prog) {
+ /* For completeness, shouldn't happen */
+ freeeprog(redir_prog);
+ }
state->pc = end;
return ret;
}
@@ -4439,21 +4564,28 @@ execshfunc(Shfunc shf, LinkList args)
deletefilelist(last_file_list, 0);
}
-/* Function to execute the special type of command that represents an *
- * autoloaded shell function. The command structure tells us which *
- * function it is. This function is actually called as part of the *
- * execution of the autoloaded function itself, so when the function *
- * has been autoloaded, its list is just run with no frills. */
+/*
+ * Function to execute the special type of command that represents an
+ * autoloaded shell function. The command structure tells us which
+ * function it is. This function is actually called as part of the
+ * execution of the autoloaded function itself, so when the function
+ * has been autoloaded, its list is just run with no frills.
+ *
+ * There are two cases because if we are doing all-singing, all-dancing
+ * non-simple code we load the shell function early in execcmd() (the
+ * action also present in the non-basic version) to check if
+ * there are redirections that need to be handled at that point.
+ * Then we call execautofn_basic() to do the rest.
+ */
/**/
static int
-execautofn(Estate state, UNUSED(int do_exec))
+execautofn_basic(Estate state, UNUSED(int do_exec))
{
Shfunc shf;
char *oldscriptname, *oldscriptfilename;
- if (!(shf = loadautofn(state->prog->shf, 1, 0)))
- return 1;
+ shf = state->prog->shf;
/*
* Probably we didn't know the filename where this function was
@@ -4473,6 +4605,19 @@ execautofn(Estate state, UNUSED(int do_exec))
}
/**/
+static int
+execautofn(Estate state, UNUSED(int do_exec))
+{
+ Shfunc shf;
+
+ if (!(shf = loadautofn(state->prog->shf, 1, 0)))
+ return 1;
+
+ state->prog->shf = shf;
+ return execautofn_basic(state, 0);
+}
+
+/**/
Shfunc
loadautofn(Shfunc shf, int fksh, int autol)
{
diff --git a/Src/glob.c b/Src/glob.c
index cb853870a..ca7bc4410 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -178,7 +178,7 @@ struct globdata {
int gd_gf_numsort;
int gd_gf_follow, gd_gf_sorts, gd_gf_nsorts;
struct globsort gd_gf_sortlist[MAX_SORTS];
- LinkList gd_gf_pre_words;
+ LinkList gd_gf_pre_words, gd_gf_post_words;
char *gd_glob_pre, *gd_glob_suf;
};
@@ -210,6 +210,7 @@ static struct globdata curglobdata;
#define gf_nsorts (curglobdata.gd_gf_nsorts)
#define gf_sortlist (curglobdata.gd_gf_sortlist)
#define gf_pre_words (curglobdata.gd_gf_pre_words)
+#define gf_post_words (curglobdata.gd_gf_post_words)
/* and macros for save/restore */
@@ -899,6 +900,9 @@ gmatchcmp(Gmatch a, Gmatch b)
/* Count slashes. Trailing slashes don't count. */
while (*aptr && *aptr == *bptr)
aptr++, bptr++;
+ /* Like I just said... */
+ if ((!*aptr || !*bptr) && aptr > a->name && aptr[-1] == '/')
+ aptr--, bptr--;
if (*aptr)
for (; aptr[1]; aptr++)
if (*aptr == '/') {
@@ -1074,7 +1078,14 @@ insert_glob_match(LinkList list, LinkNode next, char *data)
}
}
- insertlinknode(list, next, data);
+ next = insertlinknode(list, next, data);
+
+ if (gf_post_words) {
+ LinkNode added;
+ for (added = firstnode(gf_post_words); added; incnode(added)) {
+ next = insertlinknode(list, next, dupstring(getdata(added)));
+ }
+ }
}
/*
@@ -1190,7 +1201,7 @@ zglob(LinkList list, LinkNode np, int nountok)
gf_noglobdots = unset(GLOBDOTS);
gf_numsort = isset(NUMERICGLOBSORT);
gf_sorts = gf_nsorts = 0;
- gf_pre_words = NULL;
+ gf_pre_words = gf_post_words = NULL;
/* Check for qualifiers */
while (!nobareglob ||
@@ -1679,9 +1690,10 @@ zglob(LinkList list, LinkNode np, int nountok)
if (tt != NULL)
{
- if (!gf_pre_words)
- gf_pre_words = newlinklist();
- addlinknode(gf_pre_words, tt);
+ LinkList *words = sense & 1 ? &gf_post_words : &gf_pre_words;
+ if (!*words)
+ *words = newlinklist();
+ addlinknode(*words, tt);
}
break;
}
diff --git a/Src/hashtable.c b/Src/hashtable.c
index ef187927b..7a430629d 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -887,6 +887,8 @@ freeshfuncnode(HashNode hn)
zsfree(shf->node.nam);
if (shf->funcdef)
freeeprog(shf->funcdef);
+ if (shf->redir)
+ freeeprog(shf->redir);
zsfree(shf->filename);
if (shf->sticky) {
if (shf->sticky->n_on_opts)
@@ -954,10 +956,19 @@ printshfuncnode(HashNode hn, int printflags)
printf(" \"$@\"");
}
}
- printf("\n}\n");
+ printf("\n}");
} else {
- printf(" () { }\n");
+ printf(" () { }");
}
+ if (f->redir) {
+ t = getpermtext(f->redir, NULL, 1);
+ if (t) {
+ zputs(t, stdout);
+ zsfree(t);
+ }
+ }
+
+ putchar('\n');
}
/**************************************/
diff --git a/Src/hist.c b/Src/hist.c
index 770d559b1..4660fd073 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -2490,6 +2490,9 @@ flockhistfile(char *fn, int keep_trying)
struct flock lck;
int ctr = keep_trying ? 9 : 0;
+ if (flock_fd >= 0)
+ return 0; /* already locked */
+
if ((flock_fd = open(unmeta(fn), O_RDWR | O_NOCTTY)) < 0)
return errno == ENOENT ? 0 : 2; /* "successfully" locked missing file */
@@ -2590,7 +2593,12 @@ savehistfile(char *fn, int err, int writeflags)
out = NULL;
} else {
int fd = open(tmpfile, O_CREAT | O_WRONLY | O_EXCL, 0600);
- out = fd >= 0 ? fdopen(fd, "w") : NULL;
+ if (fd >=0) {
+ out = fdopen(fd, "w");
+ if (!out)
+ close(fd);
+ } else
+ out = NULL;
}
#ifdef HAVE_FCHMOD
@@ -2768,12 +2776,6 @@ lockhistfile(char *fn, int keep_trying)
if (!fn && !(fn = getsparam("HISTFILE")))
return 1;
-#ifdef HAVE_FCNTL_H
- if (isset(HISTFCNTLLOCK) && flock_fd < 0) {
- return flockhistfile(fn, keep_trying);
- }
-#endif
-
if (!lockhistct++) {
struct stat sb;
int fd;
@@ -2786,6 +2788,11 @@ lockhistfile(char *fn, int keep_trying)
# endif
#endif
+#ifdef HAVE_FCNTL_H
+ if (isset(HISTFCNTLLOCK))
+ return flockhistfile(fn, keep_trying);
+#endif
+
lockfile = bicat(unmeta(fn), ".LOCK");
/* NOTE: only use symlink locking on a link()-having host in order to
* avoid a change from open()-based locking to symlink()-based. */
diff --git a/Src/init.c b/Src/init.c
index 5e92f59df..6d005dce7 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -252,8 +252,9 @@ parseargs(char **argv, char **runscript)
paramlist = znewlinklist();
if (*argv) {
if (unset(SHINSTDIN)) {
+ posixzero = *argv;
if (cmd)
- argzero = posixzero = *argv;
+ argzero = *argv;
else
*runscript = *argv;
opts[INTERACTIVE] &= 1;
@@ -769,7 +770,8 @@ setupvals(void)
struct timezone dummy_tz;
char *ptr;
int i, j;
-#if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined (ADDITIONAL_FPATH)
+#if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined (ADDITIONAL_FPATH) || defined(FIXED_FPATH_DIR)
+#define FPATH_NEEDS_INIT 1
char **fpathptr;
# if defined(FPATH_DIR) && defined(FPATH_SUBDIRS)
char *fpath_subdirs[] = FPATH_SUBDIRS;
@@ -778,11 +780,17 @@ setupvals(void)
char *more_fndirs[] = ADDITIONAL_FPATH;
int more_fndirs_len;
# endif
+# ifdef FIXED_FPATH_DIR
+# define FIXED_FPATH_LEN 1
+# else
+# define FIXED_FPATH_LEN 0
+# endif
# ifdef SITEFPATH_DIR
- int fpathlen = 1;
+# define SITE_FPATH_LEN 1
# else
- int fpathlen = 0;
+# define SITE_FPATH_LEN 0
# endif
+ int fpathlen = FIXED_FPATH_LEN + SITE_FPATH_LEN;
#endif
int close_fds[10], tmppipe[2];
@@ -861,23 +869,27 @@ setupvals(void)
manpath = mkarray(NULL);
fignore = mkarray(NULL);
-#if defined(SITEFPATH_DIR) || defined(FPATH_DIR) || defined(ADDITIONAL_FPATH)
+#ifdef FPATH_NEEDS_INIT
# ifdef FPATH_DIR
# ifdef FPATH_SUBDIRS
fpathlen += sizeof(fpath_subdirs)/sizeof(char *);
-# else
+# else /* FPATH_SUBDIRS */
fpathlen++;
-# endif
-# endif
+# endif /* FPATH_SUBDIRS */
+# endif /* FPATH_DIR */
# if defined(ADDITIONAL_FPATH)
more_fndirs_len = sizeof(more_fndirs)/sizeof(char *);
fpathlen += more_fndirs_len;
-# endif
+# endif /* ADDITONAL_FPATH */
fpath = fpathptr = (char **)zalloc((fpathlen+1)*sizeof(char *));
+# ifdef FIXED_FPATH_DIR
+ *fpathptr++ = ztrdup(FIXED_FPATH_DIR);
+ fpathlen--;
+# endif
# ifdef SITEFPATH_DIR
*fpathptr++ = ztrdup(SITEFPATH_DIR);
fpathlen--;
-# endif
+# endif /* SITEFPATH_DIR */
# if defined(ADDITIONAL_FPATH)
for (j = 0; j < more_fndirs_len; j++)
*fpathptr++ = ztrdup(more_fndirs[j]);
@@ -896,9 +908,9 @@ setupvals(void)
# endif
# endif
*fpathptr = NULL;
-#else
+#else /* FPATH_NEEDS_INIT */
fpath = mkarray(NULL);
-#endif
+#endif /* FPATH_NEEDS_INIT */
mailpath = mkarray(NULL);
watch = mkarray(NULL);
@@ -1122,6 +1134,7 @@ init_signals(void)
winch_block(); /* See utils.c:preprompt() */
#endif
if (interact) {
+ install_handler(SIGPIPE);
install_handler(SIGALRM);
signal_ignore(SIGTERM);
}
diff --git a/Src/jobs.c b/Src/jobs.c
index 83a4d96a4..bd95afb7a 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -1627,8 +1627,10 @@ spawnjob(void)
}
if (!hasprocs(thisjob))
deletejob(jobtab + thisjob, 0);
- else
+ else {
jobtab[thisjob].stat |= STAT_LOCKED;
+ pipecleanfilelist(jobtab[thisjob].filelist);
+ }
thisjob = -1;
}
diff --git a/Src/lex.c b/Src/lex.c
index 8e9a49f3b..1a854f52b 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -325,66 +325,70 @@ lexsave(void)
mod_export void
lexrestore(void)
{
- struct lexstack *ln;
+ struct lexstack *ln = lstack;
DPUTS(!lstack, "BUG: lexrestore() without lexsave()");
- incmdpos = lstack->incmdpos;
- incond = lstack->incond;
- incasepat = lstack->incasepat;
- dbparens = lstack->dbparens;
- isfirstln = lstack->isfirstln;
- isfirstch = lstack->isfirstch;
- histactive = lstack->histactive;
- histdone = lstack->histdone;
- lexflags = lstack->lexflags;
- stophist = lstack->stophist;
- chline = lstack->hline;
- hptr = lstack->hptr;
+
+ queue_signals();
+ lstack = lstack->next;
+
+ if (!lstack) {
+ /* Back to top level: don't need special ZLE value */
+ DPUTS(ln->hline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
+ zle_chline = NULL;
+ }
+
+ incmdpos = ln->incmdpos;
+ incond = ln->incond;
+ incasepat = ln->incasepat;
+ dbparens = ln->dbparens;
+ isfirstln = ln->isfirstln;
+ isfirstch = ln->isfirstch;
+ histactive = ln->histactive;
+ histdone = ln->histdone;
+ lexflags = ln->lexflags;
+ stophist = ln->stophist;
+ chline = ln->hline;
+ hptr = ln->hptr;
if (cmdstack)
- free(cmdstack);
- cmdstack = lstack->cstack;
- cmdsp = lstack->csp;
- tok = lstack->tok;
- isnewlin = lstack->isnewlin;
- tokstr = lstack->tokstr;
- zshlextext = lstack->zshlextext;
- bptr = lstack->bptr;
- bsiz = lstack->bsiz;
- len = lstack->len;
- chwords = lstack->chwords;
- chwordlen = lstack->chwordlen;
- chwordpos = lstack->chwordpos;
- hwgetword = lstack->hwgetword;
- lexstop = lstack->lexstop;
- hdocs = lstack->hdocs;
- hgetc = lstack->hgetc;
- hungetc = lstack->hungetc;
- hwaddc = lstack->hwaddc;
- hwbegin = lstack->hwbegin;
- hwend = lstack->hwend;
- addtoline = lstack->addtoline;
+ zfree(cmdstack, CMDSTACKSZ);
+ cmdstack = ln->cstack;
+ cmdsp = ln->csp;
+ tok = ln->tok;
+ isnewlin = ln->isnewlin;
+ tokstr = ln->tokstr;
+ zshlextext = ln->zshlextext;
+ bptr = ln->bptr;
+ bsiz = ln->bsiz;
+ len = ln->len;
+ chwords = ln->chwords;
+ chwordlen = ln->chwordlen;
+ chwordpos = ln->chwordpos;
+ hwgetword = ln->hwgetword;
+ lexstop = ln->lexstop;
+ hdocs = ln->hdocs;
+ hgetc = ln->hgetc;
+ hungetc = ln->hungetc;
+ hwaddc = ln->hwaddc;
+ hwbegin = ln->hwbegin;
+ hwend = ln->hwend;
+ addtoline = ln->addtoline;
if (ecbuf)
zfree(ecbuf, eclen);
- eclen = lstack->eclen;
- ecused = lstack->ecused;
- ecnpats = lstack->ecnpats;
- ecbuf = lstack->ecbuf;
- ecstrs = lstack->ecstrs;
- ecsoffs = lstack->ecsoffs;
- ecssub = lstack->ecssub;
- ecnfunc = lstack->ecnfunc;
- hlinesz = lstack->hlinesz;
- toklineno = lstack->toklineno;
+ eclen = ln->eclen;
+ ecused = ln->ecused;
+ ecnpats = ln->ecnpats;
+ ecbuf = ln->ecbuf;
+ ecstrs = ln->ecstrs;
+ ecsoffs = ln->ecsoffs;
+ ecssub = ln->ecssub;
+ ecnfunc = ln->ecnfunc;
+ hlinesz = ln->hlinesz;
+ toklineno = ln->toklineno;
errflag = 0;
+ free(ln);
- ln = lstack->next;
- if (!ln) {
- /* Back to top level: don't need special ZLE value */
- DPUTS(chline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
- zle_chline = NULL;
- }
- free(lstack);
- lstack = ln;
+ unqueue_signals();
}
/**/
diff --git a/Src/params.c b/Src/params.c
index 0699ead85..61edc5d08 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -46,7 +46,7 @@
/**/
mod_export int locallevel;
-
+
/* Variables holding values of special parameters */
/**/
@@ -325,9 +325,12 @@ IPDEF4("ZSH_SUBSHELL", &zsh_subshell),
IPDEF5("COLUMNS", &zterm_columns, zlevar_gsu),
IPDEF5("LINES", &zterm_lines, zlevar_gsu),
IPDEF5U("ZLE_RPROMPT_INDENT", &rprompt_indent, zlevar_gsu),
-IPDEF5("OPTIND", &zoptind, varinteger_gsu),
IPDEF5("SHLVL", &shlvl, varinteger_gsu),
-IPDEF5("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu),
+
+/* Don't import internal integer status variables. */
+#define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0}
+IPDEF6("OPTIND", &zoptind, varinteger_gsu),
+IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu),
#define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
#define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
@@ -742,7 +745,8 @@ createparamtable(void)
if (!idigit(*iname) && isident(iname) && !strchr(iname, '[')) {
if ((!(pm = (Param) paramtab->getnode(paramtab, iname)) ||
!(pm->node.flags & PM_DONTIMPORT || pm->node.flags & PM_EXPORTED)) &&
- (pm = setsparam(iname, metafy(ivalue, -1, META_DUP)))) {
+ (pm = assignsparam(iname, metafy(ivalue, -1, META_DUP),
+ ASSPM_ENV_IMPORT))) {
pm->node.flags |= PM_EXPORTED;
if (pm->node.flags & PM_SPECIAL)
pm->env = mkenvstr (pm->node.nam,
@@ -2271,6 +2275,13 @@ export_param(Param pm)
mod_export void
setstrvalue(Value v, char *val)
{
+ assignstrvalue(v, val, 0);
+}
+
+/**/
+mod_export void
+assignstrvalue(Value v, char *val, int flags)
+{
if (unset(EXECOPT))
return;
if (v->pm->node.flags & PM_READONLY) {
@@ -2347,7 +2358,13 @@ setstrvalue(Value v, char *val)
break;
case PM_INTEGER:
if (val) {
- v->pm->gsu.i->setfn(v->pm, mathevali(val));
+ zlong ival;
+ if (flags & ASSPM_ENV_IMPORT) {
+ char *ptr;
+ ival = zstrtol_underscore(val, &ptr, 0, 1);
+ } else
+ ival = mathevali(val);
+ v->pm->gsu.i->setfn(v->pm, ival);
if ((v->pm->node.flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) &&
!v->pm->width)
v->pm->width = strlen(val);
@@ -2359,7 +2376,13 @@ setstrvalue(Value v, char *val)
case PM_EFLOAT:
case PM_FFLOAT:
if (val) {
- mnumber mn = matheval(val);
+ mnumber mn;
+ if (flags & ASSPM_ENV_IMPORT) {
+ char *ptr;
+ mn.type = MN_FLOAT;
+ mn.u.d = strtod(val, &ptr);
+ } else
+ mn = matheval(val);
v->pm->gsu.f->setfn(v->pm, (mn.type & MN_FLOAT) ? mn.u.d :
(double)mn.u.l);
if ((v->pm->node.flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) &&
@@ -2742,8 +2765,8 @@ assignsparam(char *s, char *val, int flags)
}
}
}
-
- setstrvalue(v, val);
+
+ assignstrvalue(v, val, flags);
unqueue_signals();
return v->pm;
}
diff --git a/Src/parse.c b/Src/parse.c
index 5f1303f1c..433efb94e 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -202,7 +202,7 @@ struct heredocs *hdocs;
* sublists is that they can be executed faster, see exec.c. In the
* parser, the test if a list can be simplified is done quite simply
* by passing a int* around which gets set to non-zero if the thing
- * just parsed is `complex', i.e. may need to be run by forking or
+ * just parsed is `cmplx', i.e. may need to be run by forking or
* some such.
*
* In each of the above, strings are encoded as one word code. For empty
@@ -375,6 +375,8 @@ init_parse(void)
/* Build eprog. */
+/* careful: copy_ecstr is from arg1 to arg2, unlike memcpy */
+
static void
copy_ecstr(Eccstr s, char *p)
{
@@ -386,24 +388,25 @@ copy_ecstr(Eccstr s, char *p)
}
static Eprog
-bld_eprog(void)
+bld_eprog(int heap)
{
Eprog ret;
int l;
ecadd(WCB_END());
- ret = (Eprog) zhalloc(sizeof(*ret));
+ ret = heap ? (Eprog) zhalloc(sizeof(*ret)) : (Eprog) zalloc(sizeof(*ret));
ret->len = ((ecnpats * sizeof(Patprog)) +
(ecused * sizeof(wordcode)) +
ecsoffs);
ret->npats = ecnpats;
- ret->nref = -1; /* Eprog is on the heap */
- ret->pats = (Patprog *) zhalloc(ret->len);
+ ret->nref = heap ? -1 : 1;
+ ret->pats = heap ? (Patprog *) zhalloc(ret->len) :
+ (Patprog *) zshcalloc(ret->len);
ret->prog = (Wordcode) (ret->pats + ecnpats);
ret->strs = (char *) (ret->prog + ecused);
ret->shf = NULL;
- ret->flags = EF_HEAP;
+ ret->flags = heap ? EF_HEAP : EF_REAL;
ret->dump = NULL;
for (l = 0; l < ecnpats; l++)
ret->pats[l] = dummy_patprog1;
@@ -455,7 +458,7 @@ parse_event(void)
clear_hdocs();
return NULL;
}
- return bld_eprog();
+ return bld_eprog(1);
}
/**/
@@ -534,7 +537,7 @@ parse_list(void)
yyerror(0);
return NULL;
}
- return bld_eprog();
+ return bld_eprog(1);
}
/*
@@ -553,7 +556,7 @@ parse_cond(void)
clear_hdocs();
return NULL;
}
- return bld_eprog();
+ return bld_eprog(1);
}
/* This adds a list wordcode. The important bit about this is that it also
@@ -561,9 +564,9 @@ parse_cond(void)
/**/
static void
-set_list_code(int p, int type, int complex)
+set_list_code(int p, int type, int cmplx)
{
- if (!complex && (type == Z_SYNC || type == (Z_SYNC | Z_END)) &&
+ if (!cmplx && (type == Z_SYNC || type == (Z_SYNC | Z_END)) &&
WC_SUBLIST_TYPE(ecbuf[p + 1]) == WC_SUBLIST_END) {
int ispipe = !(WC_SUBLIST_FLAGS(ecbuf[p + 1]) & WC_SUBLIST_SIMPLE);
ecbuf[p] = WCB_LIST((type | Z_SIMPLE), ecused - 2 - p);
@@ -578,9 +581,9 @@ set_list_code(int p, int type, int complex)
/**/
static void
-set_sublist_code(int p, int type, int flags, int skip, int complex)
+set_sublist_code(int p, int type, int flags, int skip, int cmplx)
{
- if (complex)
+ if (cmplx)
ecbuf[p] = WCB_SUBLIST(type, flags, skip);
else {
ecbuf[p] = WCB_SUBLIST(type, (flags | WC_SUBLIST_SIMPLE), skip);
@@ -594,7 +597,7 @@ set_sublist_code(int p, int type, int flags, int skip, int complex)
/**/
static int
-par_list(int *complex)
+par_list(int *cmplx)
{
int p, lp = -1, c;
@@ -607,10 +610,10 @@ par_list(int *complex)
c = 0;
if (par_sublist(&c)) {
- *complex |= c;
+ *cmplx |= c;
if (tok == SEPER || tok == AMPER || tok == AMPERBANG) {
if (tok != SEPER)
- *complex = 1;
+ *cmplx = 1;
set_list_code(p, ((tok == SEPER) ? Z_SYNC :
(tok == AMPER) ? Z_ASYNC :
(Z_ASYNC | Z_DISOWN)), c);
@@ -635,13 +638,13 @@ par_list(int *complex)
/**/
static int
-par_list1(int *complex)
+par_list1(int *cmplx)
{
int p = ecadd(0), c = 0;
if (par_sublist(&c)) {
set_list_code(p, (Z_SYNC | Z_END), c);
- *complex |= c;
+ *cmplx |= c;
return 1;
} else {
ecused--;
@@ -655,7 +658,7 @@ par_list1(int *complex)
/**/
static int
-par_sublist(int *complex)
+par_sublist(int *cmplx)
{
int f, p, c = 0;
@@ -664,7 +667,7 @@ par_sublist(int *complex)
if ((f = par_sublist2(&c)) != -1) {
int e = ecused;
- *complex |= c;
+ *cmplx |= c;
if (tok == DBAR || tok == DAMPER) {
enum lextok qtok = tok;
int sl;
@@ -673,7 +676,7 @@ par_sublist(int *complex)
zshlex();
while (tok == SEPER)
zshlex();
- sl = par_sublist(complex);
+ sl = par_sublist(cmplx);
set_sublist_code(p, (sl ? (qtok == DBAR ?
WC_SUBLIST_OR : WC_SUBLIST_AND) :
WC_SUBLIST_END),
@@ -694,20 +697,20 @@ par_sublist(int *complex)
/**/
static int
-par_sublist2(int *complex)
+par_sublist2(int *cmplx)
{
int f = 0;
if (tok == COPROC) {
- *complex = 1;
+ *cmplx = 1;
f |= WC_SUBLIST_COPROC;
zshlex();
} else if (tok == BANG) {
- *complex = 1;
+ *cmplx = 1;
f |= WC_SUBLIST_NOT;
zshlex();
}
- if (!par_pline(complex) && !f)
+ if (!par_pline(cmplx) && !f)
return -1;
return f;
@@ -719,19 +722,19 @@ par_sublist2(int *complex)
/**/
static int
-par_pline(int *complex)
+par_pline(int *cmplx)
{
int p;
zlong line = toklineno;
p = ecadd(0);
- if (!par_cmd(complex)) {
+ if (!par_cmd(cmplx, 0)) {
ecused--;
return 0;
}
if (tok == BAR) {
- *complex = 1;
+ *cmplx = 1;
cmdpush(CS_PIPE);
zshlex();
while (tok == SEPER)
@@ -739,7 +742,7 @@ par_pline(int *complex)
ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0));
ecispace(p + 1, 1);
ecbuf[p + 1] = ecused - 1 - p;
- if (!par_pline(complex)) {
+ if (!par_pline(cmplx)) {
tok = LEXERR;
}
cmdpop();
@@ -755,7 +758,7 @@ par_pline(int *complex)
ecbuf[r + 1] = 2;
ecbuf[r + 2] = ecstrcode("1");
- *complex = 1;
+ *cmplx = 1;
cmdpush(CS_ERRPIPE);
zshlex();
while (tok == SEPER)
@@ -763,7 +766,7 @@ par_pline(int *complex)
ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0));
ecispace(p + 1, 1);
ecbuf[p + 1] = ecused - 1 - p;
- if (!par_pline(complex)) {
+ if (!par_pline(cmplx)) {
tok = LEXERR;
}
cmdpop();
@@ -777,18 +780,20 @@ par_pline(int *complex)
/*
* cmd : { redir } ( for | case | if | while | repeat |
* subsh | funcdef | time | dinbrack | dinpar | simple ) { redir }
+ *
+ * zsh_construct is passed through to par_subsh(), q.v.
*/
/**/
static int
-par_cmd(int *complex)
+par_cmd(int *cmplx, int zsh_construct)
{
int r, nr = 0;
r = ecused;
if (IS_REDIROP(tok)) {
- *complex = 1;
+ *cmplx = 1;
while (IS_REDIROP(tok)) {
nr += par_redir(&r, NULL);
}
@@ -796,57 +801,57 @@ par_cmd(int *complex)
switch (tok) {
case FOR:
cmdpush(CS_FOR);
- par_for(complex);
+ par_for(cmplx);
cmdpop();
break;
case FOREACH:
cmdpush(CS_FOREACH);
- par_for(complex);
+ par_for(cmplx);
cmdpop();
break;
case SELECT:
- *complex = 1;
+ *cmplx = 1;
cmdpush(CS_SELECT);
- par_for(complex);
+ par_for(cmplx);
cmdpop();
break;
case CASE:
cmdpush(CS_CASE);
- par_case(complex);
+ par_case(cmplx);
cmdpop();
break;
case IF:
- par_if(complex);
+ par_if(cmplx);
break;
case WHILE:
cmdpush(CS_WHILE);
- par_while(complex);
+ par_while(cmplx);
cmdpop();
break;
case UNTIL:
cmdpush(CS_UNTIL);
- par_while(complex);
+ par_while(cmplx);
cmdpop();
break;
case REPEAT:
cmdpush(CS_REPEAT);
- par_repeat(complex);
+ par_repeat(cmplx);
cmdpop();
break;
case INPAR:
- *complex = 1;
+ *cmplx = 1;
cmdpush(CS_SUBSH);
- par_subsh(complex);
+ par_subsh(cmplx, zsh_construct);
cmdpop();
break;
case INBRACE:
cmdpush(CS_CURSH);
- par_subsh(complex);
+ par_subsh(cmplx, zsh_construct);
cmdpop();
break;
case FUNC:
cmdpush(CS_FUNCDEF);
- par_funcdef(complex);
+ par_funcdef(cmplx);
cmdpop();
break;
case DINBRACK:
@@ -864,7 +869,7 @@ par_cmd(int *complex)
static int inpartime = 0;
if (!inpartime) {
- *complex = 1;
+ *cmplx = 1;
inpartime = 1;
par_time();
inpartime = 0;
@@ -877,13 +882,13 @@ par_cmd(int *complex)
{
int sr;
- if (!(sr = par_simple(complex, nr))) {
+ if (!(sr = par_simple(cmplx, nr))) {
if (!nr)
return 0;
} else {
/* Take account of redirections */
if (sr > 1) {
- *complex = 1;
+ *cmplx = 1;
r += sr - 1;
}
}
@@ -891,7 +896,7 @@ par_cmd(int *complex)
break;
}
if (IS_REDIROP(tok)) {
- *complex = 1;
+ *cmplx = 1;
while (IS_REDIROP(tok))
(void)par_redir(&r, NULL);
}
@@ -909,7 +914,7 @@ par_cmd(int *complex)
/**/
static void
-par_for(int *complex)
+par_for(int *cmplx)
{
int oecused = ecused, csh = (tok == FOREACH), p, sel = (tok == SELECT);
int type;
@@ -994,25 +999,28 @@ par_for(int *complex)
zshlex();
if (tok == DOLOOP) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != DONE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (tok == INBRACE) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (csh || isset(CSHJUNKIELOOPS)) {
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != ZEND)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (unset(SHORTLOOPS)) {
YYERRORV(oecused);
} else
- par_save_list1(complex);
+ par_save_list1(cmplx);
ecbuf[p] = (sel ?
WCB_SELECT(type, ecused - 1 - p) :
@@ -1028,7 +1036,7 @@ par_for(int *complex)
/**/
static void
-par_case(int *complex)
+par_case(int *cmplx)
{
int oecused = ecused, brflag, p, pp, n = 1, type;
int ona, onc;
@@ -1145,7 +1153,7 @@ par_case(int *complex)
pp = ecadd(0);
ecstr(str);
ecadd(ecnpats++);
- par_save_list(complex);
+ par_save_list(cmplx);
n++;
if (tok == SEMIAMP)
type = WC_CASE_AND;
@@ -1175,7 +1183,7 @@ par_case(int *complex)
/**/
static void
-par_if(int *complex)
+par_if(int *cmplx)
{
int oecused = ecused, p, pp, type, usebrace = 0;
enum lextok xtok;
@@ -1186,9 +1194,12 @@ par_if(int *complex)
for (;;) {
xtok = tok;
cmdpush(xtok == IF ? CS_IF : CS_ELIF);
- zshlex();
- if (xtok == FI)
+ if (xtok == FI) {
+ incmdpos = 0;
+ zshlex();
break;
+ }
+ zshlex();
if (xtok == ELSE)
break;
while (tok == SEPER)
@@ -1199,7 +1210,7 @@ par_if(int *complex)
}
pp = ecadd(0);
type = (xtok == IF ? WC_IF_IF : WC_IF_ELIF);
- par_save_list(complex);
+ par_save_list(cmplx);
incmdpos = 1;
if (tok == ENDINPUT) {
cmdpop();
@@ -1214,7 +1225,7 @@ par_if(int *complex)
cmdpop();
cmdpush(nc);
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
incmdpos = 1;
cmdpop();
@@ -1223,12 +1234,13 @@ par_if(int *complex)
cmdpop();
cmdpush(nc);
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE) {
cmdpop();
YYERRORV(oecused);
}
ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
+ /* command word (else) allowed to follow immediately */
zshlex();
incmdpos = 1;
if (tok == SEPER)
@@ -1240,7 +1252,7 @@ par_if(int *complex)
} else {
cmdpop();
cmdpush(nc);
- par_save_list1(complex);
+ par_save_list1(cmplx);
ecbuf[pp] = WCB_IF(type, ecused - 1 - pp);
incmdpos = 1;
break;
@@ -1254,18 +1266,19 @@ par_if(int *complex)
zshlex();
if (tok == INBRACE && usebrace) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE) {
cmdpop();
YYERRORV(oecused);
}
} else {
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != FI) {
cmdpop();
YYERRORV(oecused);
}
}
+ incmdpos = 0;
ecbuf[pp] = WCB_IF(WC_IF_ELSE, ecused - 1 - pp);
zshlex();
cmdpop();
@@ -1280,31 +1293,33 @@ par_if(int *complex)
/**/
static void
-par_while(int *complex)
+par_while(int *cmplx)
{
int oecused = ecused, p;
int type = (tok == UNTIL ? WC_WHILE_UNTIL : WC_WHILE_WHILE);
p = ecadd(0);
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
incmdpos = 1;
while (tok == SEPER)
zshlex();
if (tok == DOLOOP) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != DONE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (tok == INBRACE) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (isset(CSHJUNKIELOOPS)) {
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != ZEND)
YYERRORV(oecused);
zshlex();
@@ -1320,7 +1335,7 @@ par_while(int *complex)
/**/
static void
-par_repeat(int *complex)
+par_repeat(int *cmplx)
{
int oecused = ecused, p;
@@ -1337,25 +1352,27 @@ par_repeat(int *complex)
zshlex();
if (tok == DOLOOP) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != DONE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (tok == INBRACE) {
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != OUTBRACE)
YYERRORV(oecused);
+ incmdpos = 0;
zshlex();
} else if (isset(CSHJUNKIELOOPS)) {
- par_save_list(complex);
+ par_save_list(cmplx);
if (tok != ZEND)
YYERRORV(oecused);
zshlex();
} else if (unset(SHORTLOOPS)) {
YYERRORV(oecused);
} else
- par_save_list1(complex);
+ par_save_list1(cmplx);
ecbuf[p] = WCB_REPEAT(ecused - 1 - p);
}
@@ -1363,11 +1380,15 @@ par_repeat(int *complex)
/*
* subsh : INPAR list OUTPAR |
* INBRACE list OUTBRACE [ "always" INBRACE list OUTBRACE ]
+ *
+ * With zsh_construct non-zero, we're doing a zsh special in which
+ * the following token is not considered in command position. This
+ * is used for arguments of anonymous functions.
*/
/**/
static void
-par_subsh(int *complex)
+par_subsh(int *cmplx, int zsh_construct)
{
enum lextok otok = tok;
int oecused = ecused, p, pp;
@@ -1376,11 +1397,11 @@ par_subsh(int *complex)
/* Extra word only needed for always block */
pp = ecadd(0);
zshlex();
- par_list(complex);
+ par_list(cmplx);
ecadd(WCB_END());
if (tok != ((otok == INPAR) ? OUTPAR : OUTBRACE))
YYERRORV(oecused);
- incmdpos = 1;
+ incmdpos = !zsh_construct;
zshlex();
/* Optional always block. No intervening SEPERs allowed. */
@@ -1397,7 +1418,7 @@ par_subsh(int *complex)
cmdpush(CS_ALWAYS);
zshlex();
- par_save_list(complex);
+ par_save_list(cmplx);
while (tok == SEPER)
zshlex();
@@ -1420,7 +1441,7 @@ par_subsh(int *complex)
/**/
static void
-par_funcdef(int *complex)
+par_funcdef(int *cmplx)
{
int oecused = ecused, num = 0, onp, p, c = 0;
int so, oecssub = ecssub;
@@ -1502,7 +1523,8 @@ par_funcdef(int *complex)
num++;
zshlex();
}
- *complex = (num > 0);
+ if (num > 0)
+ *cmplx = 1;
ecbuf[parg] = ecused - parg; /*?*/
ecbuf[parg+1] = num;
}
@@ -1564,15 +1586,15 @@ par_dinbrack(void)
/**/
static int
-par_simple(int *complex, int nr)
+par_simple(int *cmplx, int nr)
{
int oecused = ecused, isnull = 1, r, argc = 0, p, isfunc = 0, sr = 0;
- int c = *complex, nrediradd, assignments = 0;
+ int c = *cmplx, nrediradd, assignments = 0;
r = ecused;
for (;;) {
if (tok == NOCORRECT) {
- *complex = c = 1;
+ *cmplx = c = 1;
nocorrect = 1;
} else if (tok == ENVSTRING) {
char *p, *name, *str;
@@ -1600,7 +1622,7 @@ par_simple(int *complex, int nr)
*/
if (p[1] == Inpar &&
(*p == Equals || *p == Inang || *p == OutangProc)) {
- *complex = 1;
+ *cmplx = 1;
break;
}
}
@@ -1612,10 +1634,10 @@ par_simple(int *complex, int nr)
int oldcmdpos = incmdpos, n, type2;
/*
- * We consider array setting complex because it can
+ * We consider array setting cmplx because it can
* contain process substitutions, which need a valid job.
*/
- *complex = c = 1;
+ *cmplx = c = 1;
p = ecadd(0);
incmdpos = 0;
if ((type2 = strlen(tokstr) - 1) && tokstr[type2] == '+') {
@@ -1647,7 +1669,7 @@ par_simple(int *complex, int nr)
if (tok == STRING) {
int redir_var = 0;
- *complex = 1;
+ *cmplx = 1;
incmdpos = 0;
if (!isset(IGNOREBRACES) && *tokstr == Inbrace)
@@ -1666,7 +1688,7 @@ par_simple(int *complex, int nr)
if (IS_REDIROP(tok) && tokfd == -1)
{
- *complex = c = 1;
+ *cmplx = c = 1;
nrediradd = par_redir(&r, idstring);
p += nrediradd;
sr += nrediradd;
@@ -1687,7 +1709,7 @@ par_simple(int *complex, int nr)
zshlex();
}
} else if (IS_REDIROP(tok)) {
- *complex = c = 1;
+ *cmplx = c = 1;
nrediradd = par_redir(&r, NULL);
p += nrediradd;
sr += nrediradd;
@@ -1702,7 +1724,7 @@ par_simple(int *complex, int nr)
if (assignments)
YYERROR(oecused);
- *complex = c;
+ *cmplx = c;
lineno = 0;
incmdpos = 1;
cmdpush(CS_FUNCDEF);
@@ -1745,10 +1767,21 @@ par_simple(int *complex, int nr)
sl = ecadd(0);
(void)ecadd(WCB_PIPE(WC_PIPE_END, 0));
- if (!par_cmd(&c)) {
+ if (!par_cmd(&c, argc == 0)) {
cmdpop();
YYERROR(oecused);
}
+ if (argc == 0) {
+ /*
+ * Anonymous function, possibly with arguments.
+ * N.B. for cmplx structures in particular
+ * ( ... ) we rely on lower level code doing this
+ * to get the immediately following word (the
+ * first token after the ")" has already been
+ * read).
+ */
+ incmdpos = 0;
+ }
set_sublist_code(sl, WC_SUBLIST_END, 0, ecused - 1 - sl, c);
set_list_code(ll, (Z_SYNC | Z_END), c);
@@ -1775,7 +1808,8 @@ par_simple(int *complex, int nr)
argc++;
zshlex();
}
- *complex = (argc > 0);
+ if (argc > 0)
+ *cmplx = 1;
ecbuf[parg] = ecused - parg; /*?*/
ecbuf[parg+1] = argc;
}
@@ -2542,6 +2576,73 @@ ecgetredirs(Estate s)
return ret;
}
+/*
+ * Copy the consecutive set of redirections in the state at s.
+ * Return NULL if none, else an Eprog consisting only of the
+ * redirections from permanently allocated memory.
+ *
+ * s is left in the state ready for whatever follows the redirections.
+ */
+
+/**/
+Eprog
+eccopyredirs(Estate s)
+{
+ Wordcode pc = s->pc;
+ wordcode code = *pc;
+ int ncode, ncodes = 0, r, type;
+
+ if (wc_code(code) != WC_REDIR)
+ return NULL;
+
+ init_parse();
+
+ while (wc_code(code) == WC_REDIR) {
+ type = WC_REDIR_TYPE(code);
+
+ DPUTS(type == REDIR_HEREDOC || type == REDIR_HEREDOCDASH,
+ "unexpanded here document");
+
+ if (WC_REDIR_FROM_HEREDOC(code))
+ ncode = 5;
+ else
+ ncode = 3;
+ if (WC_REDIR_VARID(code))
+ ncode++;
+ pc += ncode;
+ ncodes += ncode;
+ code = *pc;
+ }
+ r = ecused;
+ ecispace(r, ncodes);
+
+ code = *s->pc;
+ while (wc_code(code) == WC_REDIR) {
+ s->pc++;
+
+ ecbuf[r++] = code;
+ /* fd1 */
+ ecbuf[r++] = *s->pc++;
+ /* name or HERE string */
+ /* No DUP needed as we'll copy into Eprog immediately below */
+ ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
+ if (WC_REDIR_FROM_HEREDOC(code))
+ {
+ /* terminator, raw */
+ ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
+ /* terminator, munged */
+ ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
+ }
+ if (WC_REDIR_VARID(code))
+ ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL));
+
+ code = *s->pc;
+ }
+
+ /* bld_eprog() appends a useful WC_END marker */
+ return bld_eprog(0);
+}
+
/**/
mod_export struct eprog dummy_eprog;
@@ -3534,4 +3635,3 @@ dump_autoload(char *nam, char *file, int on, Options ops, int func)
}
return ret;
}
-
diff --git a/Src/pattern.c b/Src/pattern.c
index 94a299ebb..df5e602ca 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -3012,6 +3012,16 @@ patmatch(Upat prog)
break;
case P_STAR:
/* Handle specially for speed, although really P_ONEHASH+P_ANY */
+ while (P_OP(next) == P_STAR) {
+ /*
+ * If there's another * following we can optimise it
+ * out. Chains of *'s can give pathologically bad
+ * performance.
+ */
+ scan = next;
+ next = PATNEXT(scan);
+ }
+ /*FALLTHROUGH*/
case P_ONEHASH:
case P_TWOHASH:
/*
diff --git a/Src/prompt.c b/Src/prompt.c
index 328ae3c66..0cc9ef917 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -372,6 +372,17 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
if (t0 >= arg)
test = 1;
break;
+ case 'e':
+ {
+ Funcstack fsptr = funcstack;
+ test = arg;
+ while (fsptr && test > 0) {
+ test--;
+ fsptr = fsptr->prev;
+ }
+ test = !test;
+ }
+ break;
case 'L':
if (shlvl >= arg)
test = 1;
@@ -786,6 +797,19 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
if(bv->Rstring)
stradd(bv->Rstring);
break;
+ case 'e':
+ {
+ int depth = 0;
+ Funcstack fsptr = funcstack;
+ while (fsptr) {
+ depth++;
+ fsptr = fsptr->prev;
+ }
+ addbufspc(DIGBUFSIZE);
+ sprintf(bv->bp, "%d", depth);
+ bv->bp += strlen(bv->bp);
+ break;
+ }
case 'I':
if (funcstack && funcstack->tp != FS_SOURCE &&
!IN_EVAL_TRAP()) {
@@ -1292,12 +1316,11 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar,
*/
for (;;) {
*ptr++ = *fulltextptr;
- if (*fulltextptr == Outpar ||
- *fulltextptr == '\0')
+ if (*fulltextptr == '\0' ||
+ *fulltextptr++ == Outpar)
break;
- if (*fulltextptr == Nularg)
+ if (fulltextptr[-1] == Nularg)
remw--;
- fulltextptr++;
}
} else {
#ifdef MULTIBYTE_SUPPORT
@@ -1373,12 +1396,11 @@ prompttrunc(int arg, int truncchar, int doprint, int endchar,
if (*skiptext == Inpar) {
/* see comment on left truncation above */
for (;;) {
- if (*skiptext == Outpar ||
- *skiptext == '\0')
+ if (*skiptext == '\0' ||
+ *skiptext++ == Outpar)
break;
- if (*skiptext == Nularg)
+ if (skiptext[-1] == Nularg)
maxwidth--;
- skiptext++;
}
} else {
#ifdef MULTIBYTE_SUPPORT
diff --git a/Src/signals.c b/Src/signals.c
index cb2b58161..2df69f96e 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -594,6 +594,17 @@ zhandler(int sig)
wait_for_processes();
break;
+ case SIGPIPE:
+ if (!handletrap(SIGPIPE)) {
+ if (!interact)
+ _exit(SIGPIPE);
+ else if (!isatty(SHTTY)) {
+ stopmsg = 1;
+ zexit(SIGPIPE, 1);
+ }
+ }
+ break;
+
case SIGHUP:
if (!handletrap(SIGHUP)) {
stopmsg = 1;
@@ -752,7 +763,7 @@ dosavetrap(int sig, int level)
Shfunc shf, newshf = NULL;
if ((shf = (Shfunc)gettrapnode(sig, 1))) {
/* Copy the node for saving */
- newshf = (Shfunc) zalloc(sizeof(*newshf));
+ newshf = (Shfunc) zshcalloc(sizeof(*newshf));
newshf->node.nam = ztrdup(shf->node.nam);
newshf->node.flags = shf->node.flags;
newshf->funcdef = dupeprog(shf->funcdef, 0);
@@ -897,6 +908,8 @@ removetrap(int sig)
noholdintr();
} else if (sig == SIGHUP)
install_handler(sig);
+ else if (sig == SIGPIPE && interact && !forklevel)
+ install_handler(sig);
else if (sig && sig <= SIGCOUNT &&
#ifdef SIGWINCH
sig != SIGWINCH &&
diff --git a/Src/subst.c b/Src/subst.c
index 4a5fe3a3c..1aa9b982e 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1522,6 +1522,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
* unset. I don't quite understand why (v == NULL) isn't
* good enough, but there are places where we seem to need
* to second guess whether a value is a real value or not.
+ * See in particular the (colf && !vunset) test below.
*/
int vunset = 0;
/*
@@ -2638,8 +2639,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
* - (array) contains no elements
* - (scalar) contains an empty string
*/
- if (colf && !vunset)
+ if (colf && !vunset) {
vunset = (isarr) ? !*aval : !*val || (*val == Nularg && !val[1]);
+ vunset *= -1; /* Record that vunset was originally false */
+ }
switch (s[-1]) {
case '+':
@@ -2862,7 +2865,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
getmatcharr(&aval, s, flags, flnum, replstr);
} else {
if (vunset) {
- if (unset(UNSET)) {
+ if (vunset > 0 && unset(UNSET)) {
*idend = '\0';
zerr("%s: parameter not set", idbeg);
return NULL;
@@ -2892,7 +2895,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
return NULL;
}
if (vunset) {
- if (unset(UNSET)) {
+ if (vunset > 0 && unset(UNSET)) {
*idend = '\0';
zerr("%s: parameter not set", idbeg);
return NULL;
@@ -2974,7 +2977,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
*ap = NULL;
} else {
if (vunset) {
- if (unset(UNSET)) {
+ if (vunset > 0 && unset(UNSET)) {
*idend = '\0';
zerr("%s: parameter not set", idbeg);
deletehashtable(ht);
@@ -3003,7 +3006,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
}
}
if (vunset) {
- if (unset(UNSET)) {
+ if (vunset > 0 && unset(UNSET)) {
*idend = '\0';
zerr("%s: parameter not set", idbeg);
return NULL;
@@ -3020,7 +3023,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
val = dupstring(vunset ? "0" : "1");
isarr = 0;
} else if (vunset) {
- if (unset(UNSET)) {
+ if (vunset > 0 && unset(UNSET)) {
*idend = '\0';
zerr("%s: parameter not set", idbeg);
return NULL;
diff --git a/Src/utils.c b/Src/utils.c
index 9109f66a7..e6eb8e6a7 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3424,12 +3424,12 @@ equalsplit(char *s, char **t)
return 0;
}
-static int specialcomma;
/* the ztypes table */
/**/
mod_export short int typtab[256];
+static int typtab_flags = 0;
/* initialize the ztypes table */
@@ -3440,8 +3440,15 @@ inittyptab(void)
int t0;
char *s;
- for (t0 = 0; t0 != 256; t0++)
- typtab[t0] = 0;
+ if (!(typtab_flags & ZTF_INIT)) {
+ typtab_flags = ZTF_INIT;
+ if (interact && isset(SHINSTDIN))
+ typtab_flags |= ZTF_INTERACT;
+ }
+
+ queue_signals();
+
+ memset(typtab, 0, sizeof(typtab));
for (t0 = 0; t0 != 32; t0++)
typtab[t0] = typtab[t0 + 128] = ICNTRL;
typtab[127] = ICNTRL;
@@ -3514,20 +3521,43 @@ inittyptab(void)
#endif
for (s = SPECCHARS; *s; s++)
typtab[STOUC(*s)] |= ISPECIAL;
- if (specialcomma)
+ if (typtab_flags & ZTF_SP_COMMA)
typtab[STOUC(',')] |= ISPECIAL;
- if (isset(BANGHIST) && bangchar && interact && isset(SHINSTDIN))
+ if (isset(BANGHIST) && bangchar && (typtab_flags & ZTF_INTERACT)) {
+ typtab_flags |= ZTF_BANGCHAR;
typtab[bangchar] |= ISPECIAL;
+ } else
+ typtab_flags &= ~ZTF_BANGCHAR;
+
+ unqueue_signals();
}
/**/
mod_export void
makecommaspecial(int yesno)
{
- if ((specialcomma = yesno) != 0)
+ if (yesno != 0) {
+ typtab_flags |= ZTF_SP_COMMA;
typtab[STOUC(',')] |= ISPECIAL;
- else
+ } else {
+ typtab_flags &= ~ZTF_SP_COMMA;
typtab[STOUC(',')] &= ~ISPECIAL;
+ }
+}
+
+/**/
+mod_export void
+makebangspecial(int yesno)
+{
+ /* Name and call signature for congruence with makecommaspecial(),
+ * but in this case when yesno is nonzero we defer to the state
+ * saved by inittyptab().
+ */
+ if (yesno == 0) {
+ typtab[bangchar] &= ~ISPECIAL;
+ } else if (typtab_flags & ZTF_BANGCHAR) {
+ typtab[bangchar] |= ISPECIAL;
+ }
}
diff --git a/Src/zsh.h b/Src/zsh.h
index fa7396112..d284c7aa7 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1139,6 +1139,7 @@ struct shfunc {
char *filename; /* Name of file located in */
zlong lineno; /* line number in above file */
Eprog funcdef; /* function definition */
+ Eprog redir; /* redirections to apply */
Emulation_options sticky; /* sticky emulation definitions, if any */
};
@@ -1820,7 +1821,8 @@ struct paramdef {
*/
enum {
ASSPM_AUGMENT = 1 << 0,
- ASSPM_WARN_CREATE = 1 << 1
+ ASSPM_WARN_CREATE = 1 << 1,
+ ASSPM_ENV_IMPORT = 1 << 2
};
/* node for named directory hash table (nameddirtab) */
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index cec3edab7..9a8c923f9 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -73,6 +73,9 @@ zshpaths.h: Makemod $(CONFIG_INCS)
@if test x$(sitefndir) != xno; then \
echo '#define SITEFPATH_DIR "'$(sitefndir)'"' >> zshpaths.h.tmp; \
fi
+ @if test x$(fixed_sitefndir) != x; then \
+ echo '#define FIXED_FPATH_DIR "'$(fixed_sitefndir)'"' >> zshpaths.h.tmp; \
+ fi
@if test x$(fndir) != xno; then \
echo '#define FPATH_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \
if test x$(FUNCTIONS_SUBDIRS) != x && \
diff --git a/Src/ztype.h b/Src/ztype.h
index 14f66101c..eef0f23db 100644
--- a/Src/ztype.h
+++ b/Src/ztype.h
@@ -59,6 +59,15 @@
#define iwsep(X) zistype(X,IWSEP)
#define inull(X) zistype(X,INULL)
+/*
+ * Bit flags for typtab_flags --- preserved after
+ * shell initialisation.
+ */
+#define ZTF_INIT (0x0001) /* One-off initialisation done */
+#define ZTF_INTERACT (0x0002) /* Shell interative and reading from stdin */
+#define ZTF_SP_COMMA (0x0004) /* Treat comma as a special characters */
+#define ZTF_BANGCHAR (0x0008) /* Treat bangchar as a special character */
+
#ifdef MULTIBYTE_SUPPORT
#define WC_ZISTYPE(X,Y) wcsitype((X),(Y))
#define WC_ISPRINT(X) iswprint(X)
diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst
index 7ad02db3b..a39ce46c8 100644
--- a/Test/A04redirect.ztst
+++ b/Test/A04redirect.ztst
@@ -54,7 +54,7 @@
0:Here-documents stripping tabs
>barbar
- cat <<-$'$HERE '`$(THERE) `'$((AND)) '"\EVERYWHERE"
+ cat <<-$'$HERE '`$(THERE) `'$((AND)) '"\EVERYWHERE" #
# tabs again. sorry about the max miller.
Here's a funny thing. Here is a funny thing.
I went home last night. There's a funny thing.
@@ -455,3 +455,79 @@
[</dev/null ]
1:check behaviour with square brackets
+
+ print any old rubbish >input1
+ () {
+ local var
+ read var
+ print I just read $var
+ } <input1 >output1
+ print Nothing output yet
+ cat output1
+0:anonymous function redirections are applied immediately
+>Nothing output yet
+>I just read any old rubbish
+
+ redirfn() {
+ local var
+ read var
+ print I want to tell you about $var
+ print Also, this might be an error >&2
+ } <input2 >output2 2>&1
+ print something I heard on the radio >input2
+ redirfn
+ print No output until after this
+ cat output2
+0:redirections with normal function definition
+>No output until after this
+>I want to tell you about something I heard on the radio
+>Also, this might be an error
+
+ which redirfn
+0:text output of function with redirections
+>redirfn () {
+> local var
+> read var
+> print I want to tell you about $var
+> print Also, this might be an error >&2
+>} < input2 > output2 2>&1
+
+ 1func 2func 3func() { print Ich heisse $0 } >output3
+ for i in 1 2 3; do
+ f=${i}func
+ print Running $f
+ $f
+ cat output3
+ unfunction $f
+ done
+0:multiply named functions with redirection
+>Running 1func
+>Ich heisse 1func
+>Running 2func
+>Ich heisse 2func
+>Running 3func
+>Ich heisse 3func
+
+ redirfn2() { print The latest output; } >&3
+ redirfn2 3>output4
+ print No output yet
+ cat output4
+0:Redirections in both function definition and command line
+>No output yet
+>The latest output
+
+# This relies on the fact that the test harness always loads
+# the zsh/parameter module.
+ print $functions[redirfn]
+0:Output from $functions[] for definition with redirection
+>{
+> local var
+> read var
+> print I want to tell you about $var
+> print Also, this might be an error >&2
+>} < input2 > output2 2>&1
+
+ noredirfn() { print This rather boring function has no redirection.; }
+ print $functions[noredirfn]
+0:Output from $functions[] for definition with no redirection
+> print This rather boring function has no redirection.
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
index 9615f091b..ca97f4f41 100644
--- a/Test/A05execution.ztst
+++ b/Test/A05execution.ztst
@@ -204,15 +204,43 @@ F:the bug is still there or it reappeared. See workers-29973 for details.
F:This similar test was triggering a reproducible failure with pipestatus.
{ unsetopt MONITOR } 2>/dev/null
- coproc { read -Et 5 || kill -INT $$ }
+ coproc { read -et 5 || { print -u $ZTST_fd KILLED; kill -HUP -$$ } }
print -u $ZTST_fd 'This test takes 5 seconds to fail...'
- { printf "%d\n" {1..20000} } | ( read -E )
- hang(){ printf "%d\n" {2..20000} | cat }; hang | ( read -E )
+ { printf "%d\n" {1..20000} } | ( read -e )
+ hang(){ printf "%d\n" {2..20000} | cat }; hang | ( read -e )
print -p done
- read -Et 6 -p
+ read -et 6 -p
0:Bug regression: piping a shell construct to an external process may hang
>1
>2
>done
F:This test checks for a file descriptor leak that could cause the left
F:side of a pipe to block on write after the right side has exited
+
+ { setopt MONITOR } 2>/dev/null
+ if [[ -o MONITOR ]]
+ then
+ ( while :; do print "This is a line"; done ) | () : &
+ sleep 1
+ jobs -l
+ else
+ print -u $ZTST_fd "Skipping pipe leak test, requires MONITOR option"
+ print "[0] 0 0"
+ fi
+0:Bug regression: piping to anonymous function; piping to backround function
+*>\[<->\] <-> <->
+F:This test checks for two different bugs, a parser segfault piping to an
+F:anonymous function, and a descriptor leak when backgrounding a pipeline
+
+ print "autoload_redir() { print Autoloaded ksh style; } >autoload.log" >autoload_redir
+ autoload -Uk autoload_redir
+ autoload_redir
+ print No output yet
+ cat autoload.log
+ functions autoload_redir
+0:
+>No output yet
+>Autoloaded ksh style
+>autoload_redir () {
+> print Autoloaded ksh style
+>} > autoload.log
diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst
index 25cd8b83a..4c55b961e 100644
--- a/Test/C01arith.ztst
+++ b/Test/C01arith.ztst
@@ -282,3 +282,7 @@
print $(( [#_] (5. ** 10) / 16. ))
0:Grouping output with underscores: floating point
>610_351.562_5
+
+ env SHLVL=1+RANDOM $ZTST_testdir/../Src/zsh -f -c 'print $SHLVL'
+0:Imported integer functions are not evaluated
+>2
diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst
index a2660315f..10491a229 100644
--- a/Test/C04funcdef.ztst
+++ b/Test/C04funcdef.ztst
@@ -272,6 +272,16 @@
>ignorebraces is off
>ignorebraces is still on here
+# lsfoo should not be expanded as an anonymous function argument
+ alias lsfoo='This is not ls.'
+ () (echo anon func; echo "$@") lsfoo
+0:Anonmous function with arguments in a form nobody sane would ever use but unfortunately we have to support anyway
+>anon func
+>lsfoo
+
+ print foo | () cat
+0:Simple anonymous function should not simplify enclosing pipeline
+>foo
%clean
diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst
index 4697ca414..217ce7c06 100644
--- a/Test/D02glob.ztst
+++ b/Test/D02glob.ztst
@@ -565,3 +565,10 @@
print $match[1]
0:(#q) is ignored completely in conditional pattern matching
>fichier
+
+# The following should not cause excessive slowdown.
+ print glob.tmp/*.*
+ print glob.tmp/**************************.*************************
+0:Optimisation to squeeze multiple *'s used as ordinary glob wildcards.
+>glob.tmp/ra=1.0_et=3.5
+>glob.tmp/ra=1.0_et=3.5
diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst
index f5b05deaa..3a65331b3 100644
--- a/Test/V07pcre.ztst
+++ b/Test/V07pcre.ztst
@@ -108,3 +108,12 @@
>1
>0 xo→t →t
>0 Xo→t →t
+
+ string="The following zip codes: 78884 90210 99513"
+ pcre_compile -m "\d{5}"
+ pcre_match -b -- $string && print "$MATCH; ZPCRE_OP: $ZPCRE_OP"
+ pcre_match -b -n $ZPCRE_OP[(w)2] -- $string || print failed
+ print "$MATCH; ZPCRE_OP: $ZPCRE_OP"
+0:pcre_match -b and pcre_match -n
+>78884; ZPCRE_OP: 25 30
+>90210; ZPCRE_OP: 31 36
diff --git a/configure.ac b/configure.ac
index 37f35858f..306a0057d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -315,6 +315,24 @@ else
sitefndir="$enableval"
fi], [sitefndir=${datadir}/${tzsh_name}/site-functions])
+dnl Add /usr/local/share/zsh/site-functions if not yet present
+dnl owing to $sitefndir, whether or not explicitly given.
+dnl If not explicitly given, it hasn't been expanded yet.
+if test X$sitefndir = X/usr/local/share/zsh/site-functions
+then fixed_sitefndir=''
+elif test X$prefix != X/usr/local; then
+ if test X$prefix = XNONE && test X$ac_default_prefix = X/usr/local; then
+ if test X$tzsh_name != Xzsh
+ then fixed_sitefndir=/usr/local/share/zsh/site-functions
+ else fixed_sitefndir=''
+ fi
+ else fixed_sitefndir=/usr/local/share/zsh/site-functions
+ fi
+elif test X$tzsh_name != Xzsh
+then fixed_sitefndir=/usr/local/share/zsh/site-functions
+else fixed_sitefndir=''
+fi
+
ifdef([function_subdirs],[undefine([function_subdirs])])
AC_ARG_ENABLE(function-subdirs,
AC_HELP_STRING([--enable-function-subdirs], [install functions in subdirectories]))
@@ -340,6 +358,7 @@ AC_SUBST(runhelp)dnl
AC_SUBST(additionalfpath)dnl
AC_SUBST(fndir)dnl
AC_SUBST(sitefndir)dnl
+AC_SUBST(fixed_sitefndir)dnl
AC_SUBST(FUNCTIONS_SUBDIRS)dnl
dnl Directories for scripts such as newuser.
@@ -3181,9 +3200,12 @@ AC_OUTPUT
eval "zshbin1=${bindir}"
eval "zshbin2=${zshbin1}"
-eval "zshman=${mandir}"
-eval "zshinfo=${infodir}"
-eval "zshfndir=${fndir}"
+eval "zshman1=${mandir}"
+eval "zshman2=${zshman1}"
+eval "zshinfo1=${infodir}"
+eval "zshinfo2=${zshinfo1}"
+eval "zshfndir1=${fndir}"
+eval "zshfndir2=${zshfndir1}"
echo "
zsh configuration
@@ -3208,10 +3230,10 @@ echo "\
library flags : ${LIBS}
installation basename : ${tzsh_name}
binary install path : ${zshbin2}
-man page install path : ${zshman}
-info install path : ${zshinfo}"
-if test "$zshfndir" != no; then
- echo "functions install path : ${zshfndir}"
+man page install path : ${zshman2}
+info install path : ${zshinfo2}"
+if test "$zshfndir2" != no; then
+ echo "functions install path : ${zshfndir2}"
fi
if test "x$additionalfpath" != x; then
echo "additional fpath entries : ${additionalfpath}"