about summary refs log tree commit diff
path: root/Etc
diff options
context:
space:
mode:
Diffstat (limited to 'Etc')
-rw-r--r--Etc/BUGS34
-rw-r--r--Etc/CVE-2021-45444-VCS_Info-workaround.patch98
-rw-r--r--Etc/FAQ.yo360
-rw-r--r--Etc/NEWS-4.32
-rw-r--r--Etc/completion-style-guide12
-rw-r--r--Etc/creating-a-release.txt37
-rw-r--r--Etc/zsh-development-guide33
7 files changed, 404 insertions, 172 deletions
diff --git a/Etc/BUGS b/Etc/BUGS
index f1f8e44f8..dee115ee0 100644
--- a/Etc/BUGS
+++ b/Etc/BUGS
@@ -23,22 +23,15 @@ the underlying VCS but not whether quilt is used.
 Workaround: test (( ${+funcstack[(r)VCS_INFO_quilt]} )).
 ------------------------------------------------------------------------
 41184: 'exec' optimization for last command in a subshell should be
-skipped when STTY=... is set for that command
+skipped when STTY=... is set for that command.  This is complicated
+because the decision to (not) fork is made in execcmd_exec() before
+the prefix parameter assignments are examined in execute().
 ------------------------------------------------------------------------
 41203 and others: Make it easier to maintain C modules out of tree.
 (May require defining a stable API for modules, see 41254)
 ------------------------------------------------------------------------
-42609: :|: =(hang)
-------------------------------------------------------------------------
-44007 - Martijn - exit in trap executes rest of function
-See test case in Test/C03traps.ztst.
-------------------------------------------------------------------------
-44133 debian #924736 (partial patch in 44134) three setopts following `    #`
-------------------------------------------------------------------------
 44850 terminal issues with continuation markers
 ------------------------------------------------------------------------
-45422 _arguments !-x !+x
-------------------------------------------------------------------------
 users/24765 -direct terminals. Not a bug as such but we may need to do
   something if -direct values in TERM are ever common
 ------------------------------------------------------------------------
@@ -51,17 +44,20 @@ interactive and the subshell is the foreground job.  The USEZLE option is
 always turned off in subshells, for reasons lost to history.  There is a
 related, probably obsolete, vared special case for $TERM set to "emacs".
 ------------------------------------------------------------------------
-users/26150: MULTIOS does not work with "exec":
-
-exec 3>/tmp/test1 3>/tmp/test2
-
-causes a script to hang.
-------------------------------------------------------------------------
 47561: [PATCH v4] vcs_info: choose backend by basedir
 ------------------------------------------------------------------------
-39319: () { exit } =(:) doesn't clean up the tempfile
+48091, 49276: Bug in compdescribe with matcher 'b:-=+'
+------------------------------------------------------------------------
+users/26071: Strange behavior about option completion of "git push --f"
 ------------------------------------------------------------------------
-48091: Bug in compdescribe with matcher 'b:-=+'
+50930: If a conditional expression appears in a current-shell construct
+(such as { sleep 20 && print $? }) which is then suspended with ^Z, the
+return value of the left side of the expression is always 148 (SIGTSTP)
+and thus the expression is likely to be incorrectly interpreted.
 ------------------------------------------------------------------------
-users/26071: Strange behavior about option completion of `git push
+52521: Empty files and unreadable files cannot be removed using the
+mapfile module "unset 'mapfile[filename]'", and are not distinguished
+from files that do not exist.
 ------------------------------------------------------------------------
+52747,52755: HIST_IGNORE_DUPS et. al. ignore syntactically significant
+quoted whitespace and can incorrectly exclude commands as duplicates.
diff --git a/Etc/CVE-2021-45444-VCS_Info-workaround.patch b/Etc/CVE-2021-45444-VCS_Info-workaround.patch
new file mode 100644
index 000000000..13e54be77
--- /dev/null
+++ b/Etc/CVE-2021-45444-VCS_Info-workaround.patch
@@ -0,0 +1,98 @@
+From 972887bbe5eb6a00e5f0e73781d6d73bfdcafb93 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc=20Cornell=C3=A0?= <hello@mcornella.com>
+Date: Mon, 24 Jan 2022 09:43:28 +0100
+Subject: [PATCH] security/89: Partially work around CVE-2021-45444 in VCS_Info
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch is a partial, VCS_Info-specific work-around for CVE-2021-45444,
+which is mitigated in the shell itself in 5.8.1 and later versions. It is
+offered for users who are concerned about an exploit but are unable to update
+their binaries to receive the complete fix.
+
+The patch works around the vulnerability by pre-escaping values substituted
+into format strings in VCS_Info. Please note that this may break some user
+configurations that rely on those values being un-escaped (which is why it was
+not included directly in 5.8.1). It may be possible to limit this breakage by
+adjusting exactly which ones are pre-escaped, but of course this may leave
+them vulnerable again.
+
+If applying the patch to the file system is inconvenient or not possible, the
+following script can be used to idempotently patch the relevant function
+running in memory (and thus must be re-run when the shell is restarted):
+
+
+# Impacted versions go from v5.0.3 to v5.8 (v5.8.1 is the first patched version)
+autoload -Uz is-at-least
+if is-at-least 5.8.1 || ! is-at-least 5.0.3; then
+  return
+fi
+
+# Quote necessary $hook_com[<field>] items just before they are used
+# in the line "VCS_INFO_hook 'post-backend'" of the VCS_INFO_formats
+# function, where <field> is:
+#
+#   base:       the full path of the repository's root directory.
+#   base-name:  the name of the repository's root directory.
+#   branch:     the name of the currently checked out branch.
+#   revision:   an identifier of the currently checked out revision.
+#   subdir:     the path of the current directory relative to the
+#               repository's root directory.
+#   misc:       a string that may contain anything the vcs_info backend wants.
+#
+# This patch %-quotes these fields previous to their use in vcs_info hooks and
+# the zformat call and, eventually, when they get expanded in the prompt.
+# It's important to quote these here, and not later after hooks have modified the
+# fields, because then we could be quoting % characters from valid prompt sequences,
+# like %F{color}, %B, etc.
+#
+#  32   │ hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})"
+#  33   │ hook_com[subdir_orig]="${hook_com[subdir]}"
+#  34   │
+#  35 + │ for tmp in base base-name branch misc revision subdir; do
+#  36 + │     hook_com[$tmp]="${hook_com[$tmp]//\%/%%}"
+#  37 + │ done
+#  38 + │
+#  39   │ VCS_INFO_hook 'post-backend'
+#
+# This is especially important so that no command substitution is performed
+# due to malicious input as a consequence of CVE-2021-45444, which affects
+# zsh versions from 5.0.3 to 5.8.
+#
+autoload -Uz +X regexp-replace VCS_INFO_formats
+
+# We use $tmp here because it's already a local variable in VCS_INFO_formats
+typeset PATCH='for tmp (base base-name branch misc revision subdir) hook_com[$tmp]="${hook_com[$tmp]//\%/%%}"'
+# Unique string to avoid reapplying the patch if this code gets called twice
+typeset PATCH_ID=vcs_info-patch-9b9840f2-91e5-4471-af84-9e9a0dc68c1b
+# Only patch the VCS_INFO_formats function if not already patched
+if [[ "$functions[VCS_INFO_formats]" != *$PATCH_ID* ]]; then
+  regexp-replace 'functions[VCS_INFO_formats]' \
+    "VCS_INFO_hook 'post-backend'" \
+    ': ${PATCH_ID}; ${PATCH}; ${MATCH}'
+fi
+unset PATCH PATCH_ID
+
+
+---
+ Functions/VCS_Info/VCS_INFO_formats | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/Functions/VCS_Info/VCS_INFO_formats b/Functions/VCS_Info/VCS_INFO_formats
+index e0e1dc738..4d88e28b6 100644
+--- a/Functions/VCS_Info/VCS_INFO_formats
++++ b/Functions/VCS_Info/VCS_INFO_formats
+@@ -32,6 +32,10 @@ hook_com[base-name_orig]="${hook_com[base_name]}"
+ hook_com[subdir]="$(VCS_INFO_reposub ${hook_com[base]})"
+ hook_com[subdir_orig]="${hook_com[subdir]}"
+ 
++for tmp in base base-name branch misc revision subdir; do
++    hook_com[$tmp]="${hook_com[$tmp]//\%/%%}"
++done
++
+ VCS_INFO_hook 'post-backend'
+ 
+ ## description (for backend authors):
+-- 
+2.34.1
diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo
index 20f6449f1..2c83fe7fa 100644
--- a/Etc/FAQ.yo
+++ b/Etc/FAQ.yo
@@ -35,7 +35,7 @@ def(myeit)(0)(\
 def(myeitd)(0)(\
     whenlatex(eit())whenhtml(eit())whenman(eit())whenms(eit())whensgml(eit())\
     whentxt(.))\
-COMMENT(-- don't want headers for text, USENET headers must come first --)\
+COMMENT(-- don't want headers for text --)\
 def(myreport)(3)(\
 whentxt(report()()())\
 whenhtml(report(ARG1)(ARG2)(ARG3))\
@@ -55,17 +55,14 @@ def(emdash)(0)(\
     whenhtml(---)\
     whenman(--)whenms(--)whensgml(--)\
     whentxt(--))\
-def(LPAR)(0)(CHAR(40))\
-def(RPAR)(1)(CHAR(41))
+SUBST(_LPAR_)(CHAR(40))\
+SUBST(_RPAR_)(CHAR(41))
+COMMENT(-- preserve the indent of the 1st line of paragraph --)\
+IFDEF(txt)(\
+  DEFINESYMBOL(XXparagraph)()\
+  PUSHMACRO(PARAGRAPH)(0)(SYMBOLVALUE(XXparagraph))\
+)()
 myreport(Z-Shell Frequently-Asked Questions)(Peter Stephenson)(2010/02/15)
-COMMENT(-- the following are for Usenet and must appear first)\
-description(\
-mydit(Archive-Name:) unix-faq/shell/zsh
-mydit(Last-Modified:) 2020/08/08
-mydit(Submitted-By:) email(coordinator@zsh.org (Peter Stephenson))
-mydit(Posting-Frequency:) Monthly
-mydit(Copyright:) (C) P.W. Stephenson, 1995--2020 (see end of document)
-)
 
 This document contains a list of frequently-asked (or otherwise
 significant) questions concerning the Z-shell, a command interpreter
@@ -104,6 +101,10 @@ Chapter 2:  How does zsh differ from...?
 2.6. Shouldn't zsh be more/less like ksh/(t)csh?
 2.7. What is zsh's support for Unicode/UTF-8?
 2.8. Why does my bash script report an error when I run it under zsh?
+2.9. What is a `namespace' anyway?
+2.10. What about named references?
+2.11. What is zsh's support for non-forking command substitution?
+2.12. Comparisons of forking and non-forking command substitution
 
 Chapter 3:  How to get various things to work
 3.1. Why does `$var' where `var="foo bar"' not do what I expect?
@@ -136,6 +137,7 @@ Chapter 3:  How to get various things to work
 3.28. How do I edit the input buffer in $EDITOR?
 3.29. Why does `which' output for missing commands go to stdout?
 3.30. Why doesn't the expansion mytt(*.{tex,aux,pdf}) do what I expect?
+3.31. Why does mytt($RANDOM) return the same number more than once?
 
 Chapter 4:  The mysteries of completion
 4.1. What is completion?
@@ -163,7 +165,7 @@ Acknowledgments
 
 Copyright
 --- End of Contents ---
-)
+)\
 
 chapter(Introducing zsh and how to install it)
 
@@ -186,23 +188,6 @@ url(https://zsh.sourceforge.io/FAQ/)(https://zsh.sourceforge.io/FAQ/) .
   can be found at url(https://zsh.sourceforge.io/FAQ/zshfaq.txt)
 (https://zsh.sourceforge.io/FAQ/zshfaq.txt) .
 
-  Another useful source of information is the collection of FAQ articles
-  posted frequently to the Usenet news groups comp.unix.questions,
-  comp.unix.shells and comp.answers with answers to general questions
-  about UNIX.  The fifth of the seven articles deals with shells,
-  including zsh, with a brief description of differences.  There is
-  also a separate FAQ on shell differences and how to change your
-  shell.  Usenet FAQs are available via FTP from rtfm.mit.edu and
-  mirrors and also on the World Wide Web; see
-  description(
-    mydit(USA)         url(http://www.cis.ohio-state.edu/hypertext/faq/usenet/top.html)
-    (http://www.cis.ohio-state.edu/hypertext/faq/usenet/top.html)
-    mydit(UK)          url(http://www.lib.ox.ac.uk/internet/news/faq/comp.unix.shell.html)
-    (http://www.lib.ox.ac.uk/internet/news/faq/comp.unix.shell.html)
-    mydit(Netherlands) url(http://www.cs.uu.nl/wais/html/na-dir/unix-faq/shell/.html)
-    (http://www.cs.uu.nl/wais/html/na-dir/unix-faq/shell/.html)
-  )
-
   You can also get it via email by emailing \
 email(mail-server@rtfm.mit.edu)
   with, in the body of the message, mytt(send faqs/unix-faq/shell/zsh).
@@ -222,7 +207,6 @@ email(mail-server@rtfm.mit.edu)
   For any more eclectic information, you should contact the mailing
   list:  see question link(6.2)(62).
 
-
 sect(What is it?)
 
   Zsh is a UNIX command interpreter (shell) which of the standard
@@ -242,7 +226,6 @@ sect(What is it?)
   included with the source distribution are highly recommended.  A list
   of features is given in FEATURES, also with the source.
 
-
 sect(What is it good at?)
 
   Here are some things that zsh is particularly good at.  No claim of
@@ -284,7 +267,6 @@ sect(What is it good at?)
   it() Spelling correction.
   )
 
-
 sect(On what machines will it run?)
 
   From version 3.0, zsh uses GNU autoconf as the installation
@@ -313,10 +295,9 @@ sect(On what machines will it run?)
   signames.h file. This makes the signals code unusable. This often happens
   on Ultrix, HP-UX, IRIX (?). Install gawk if you experience such problems.
 
-
 sect(What's the latest version?)
 
-  Zsh 5.8 is the latest production version.  For details of all the
+  Zsh 5.9 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
@@ -333,8 +314,7 @@ sect(What's the latest version?)
   Changes of this kind are almost always forced by an awkward or
   unnecessary feature in the original design (as perceived by current
   users), or to enhance compatibility with other Bourne shell
-  derivatives, or (mostly in the 3.0 series) to provide POSIX compliancy.
-
+  derivatives, or (mostly in the 3.0 series) to provide POSIX compliance.
 
 sect(Where do I get it?)
 label(16)
@@ -435,13 +415,11 @@ sect(I don't have root access: how do I make zsh my login shell?)
   /etc/shells on all appropriate machines, including NIS clients, or you
   may have problems with FTP to that machine.
 
-
 chapter(How does zsh differ from...?)
 
 As has already been mentioned, zsh is most similar to ksh, while many
 of the additions are to please csh users.  Here are some more detailed
-notes.  See also the article `UNIX shell differences and how to change
-your shell' posted frequently to the USENET group comp.unix.shell.
+notes.
 
 sect(Differences from sh and ksh)
 label(21)
@@ -472,7 +450,14 @@ label(21)
      invoked with the appropriate name.  Including the command
      `emulate sh; setopt localoptions' in a shell function will
      turn on sh emulation for that function only.  In version 4 (and in
-     3.0.6 through 8), this can be abbreviated as `emulate -L sh'.
+     3.0.6 through 8), this can be abbreviated as `emulate -L sh';
+  myeit() in versions after 5.9, the myem(namespace) syntax and
+     myem(named references) (ksh mytt(nameref)) are available, but
+     differ in some details from the ksh93+ semantics;
+  myeit() also after 5.9, myem(non-forking command substitutions) are
+     available.  These are described by ksh as myem(a brace group preceded
+     by a dollar sign) (mytt(${ list;})), but zsh has both some added
+     features adopted from mksh, and some limitations, see link(2.11)(211)
    )
 
   The classic difference is word splitting, discussed in question \
@@ -523,9 +508,9 @@ tt(RM_STAR_SILENT),
 	those are a completely different type of object.)
     it()  Coprocesses are established by mytt(coproc); mytt(|&) behaves like
         csh.  Handling of coprocess file descriptors is also different.
-    it()  In mytt(cmd1 && cmd2 &), only mytt(cmd2) instead of the whole
-        expression is run in the background in zsh.  The manual implies
-        this is a bug.  Use mytt({ cmd1 && cmd2 } &) as a workaround.
+    it()  In mytt(cmd1 && cmd2 &), instead of backgrounding the whole
+        expression, only mytt(cmd2) is run in the background in zsh.
+        Use mytt(( cmd1 && cmd2 ) &) as a workaround.
   )
   it() Command line substitutions, globbing etc.:
   itemization(
@@ -639,7 +624,6 @@ link(2.3)(23).
   )
   )
 
-
 sect(Similarities with csh)
 
   Although certain features aim to ease the withdrawal symptoms of csh
@@ -673,7 +657,6 @@ sect(Similarities with csh)
   it()  Arrays have csh-like features (see under link(2.1)(21)).
   )
 
-
 sect(Why do my csh aliases not work?  (Plus other alias pitfalls.))
 label(23)
 
@@ -706,7 +689,7 @@ label(23)
     cd() { builtin cd "$@"; print -D $PWD; }
   )
   (which converts your home directory to a tt(~)).  In fact, this problem is
-  better solved by defining the special function chpwd+LPAR()RPAR() (see
+  better solved by defining the special function chpwd+_LPAR__RPAR_ (see
   the manual). Note also that the mytt(;) at the end of the function is
   optional in zsh, but not in ksh or sh (for sh's where it exists).
 
@@ -790,7 +773,7 @@ label(23)
     function l { /bin/ls -la "$@" | more }
   )
   The mytt(l) after mytt(function) is not expanded.  Note you don't need
-  the mytt(LPAR()RPAR()) in this case, although it's harmless.
+  the mytt(_LPAR__RPAR_) in this case, although it's harmless.
 
   You need to be careful if you are defining a function with multiple
   names; most people don't need to do this, so it's an unusual problem,
@@ -803,7 +786,7 @@ label(23)
   This oddity was fixed in version 5.1.
 
   The rest of this item assumes you use the (more common,
-  but equivalent) mytt(LPAR()RPAR()) definitions.
+  but equivalent) mytt(_LPAR__RPAR_) definitions.
 
   Bart Schaefer's rule is:  Define first those aliases you expect to
   use in the body of a function, but define the function first if the
@@ -863,7 +846,6 @@ mytt(compctl)
   )
   and can now bind tt(run-fg-editor) just like any other editor function.
 
-
 sect(Similarities with bash)
 label(25)
 
@@ -871,7 +853,7 @@ label(25)
   the most obvious difference from zsh is that it does not attempt to
   emulate the Korn shell.  Since both shells are under active
   development it is probably not sensible to be too specific here.
-  Broadly, bash has paid more attention to standards compliancy
+  Broadly, bash has paid more attention to standards compliance
   (i.e. POSIX) for longer, and has so far avoided the more abstruse
   interactive features (programmable completion, etc.) that zsh has.
 
@@ -889,7 +871,6 @@ label(25)
   and `tt((#e))' to match the end.  These require the option
   tt(EXTENDED_GLOB) to be set.
 
-
 sect(Shouldn't zsh be more/less like ksh/(t)csh?)
 
   People often ask why zsh has all these `unnecessary' csh-like features,
@@ -903,10 +884,7 @@ sect(Shouldn't zsh be more/less like ksh/(t)csh?)
   tt(CSH_JUNKIE) options.  This argument still holds.  On the other hand,
   the arguments for having what is close to a plug-in replacement for ksh
   are, if anything, even more powerful:  the deficiencies of csh as a
-  programming language are well known (look in any Usenet FAQ archive, e.g.
-    url(http://www.cis.ohio-state.edu/hypertext/faq/usenet/unix-faq/\ 
-        shell/csh-whynot/faq.html)
-(http://www.cis.ohio-state.edu/hypertext/faq/usenet/unix-faq/shell/csh-whynot/faq.html)
+  programming language are well known (search for tt(csh-whynot)
   if you are in any doubt) and zsh is able to run many standard
   scripts such as /etc/rc.
 
@@ -916,7 +894,6 @@ sect(Shouldn't zsh be more/less like ksh/(t)csh?)
   want.  The introduction of loadable in modules in version 3.1 should
   help.
 
-
 sect(What is zsh's support for Unicode/UTF-8?)
 
   `Unicode', or UCS for Universal Character Set, is the modern way
@@ -935,7 +912,6 @@ sect(What is zsh's support for Unicode/UTF-8?)
   this becomes a production release.)  This is discussed more
   fully below, see `Multibyte input and output'.
 
-
 sect(Why does my bash script report an error when I run it under zsh?)
 label(28)
 
@@ -996,6 +972,163 @@ label(28)
   languages and adjusting it accordingly, just like you would
   when translating a book from American English to British English.
 
+sect(What is a mytt(namespace) anyway?)
+label(29)
+
+  As of this writing, namespaces in zsh are little more than syntactic
+  sugar for grouping related parameters.  For example, as of the update
+  to PCRE2, the parameters ${.pcre.match} and ${.pcre.subject} are used
+  for regular expression substring capture.  The mytt(.pcre.) part is
+  the namespace, and when you refer to a parameter that has one, you
+  mybf(must) use the mytt(${...}) braces around the name.  Assignments
+  are not special, they have the form mytt(.nspace.var=value) as usual.
+
+  Parameters using a namespace have the additional property that, like
+  file names beginning with a dot for globbing, they're hidden from
+  mytt(typeset) output unless explicitly asked for.
+
+  Namespaces appear in releases after but not including zsh 5.9.
+
+sect(What about named references?)
+label(210)
+
+  Named references are a bit like aliases, but for parameters.  A named
+  reference would typically be usable in the same cases as ${(P)name}
+  (see link(3.22)(322)).  The value of a named reference is the name
+  of another parameter, and when you expand or assign to the named
+  reference, that other parameter is expanded or assigned instead.
+  Thus a trivial example is
+  verb(
+    % target=RING
+    % typeset -n ref=target
+    % print $ref
+    RING
+    % ref=BULLSEYE
+    % print $target
+    BULLSEYE
+  )
+
+  One exception to this behavior is when a named reference is used as
+  the loop variable in a mytt(for) loop.  In that case the reference is
+  unset and reset on each iteration of the loop.
+  verb(
+    % target=RING bullseye=SPOT other=MISS
+    % typeset -n ref=other
+    % for ref in target bullseye; do
+    > print $ref
+    > ref=HIT:$ref
+    > done
+    RING
+    SPOT
+    % print $other
+    MISS
+    % print $ref
+    HIT:SPOT
+  )
+
+  Dynamic scoping applies to named references, so for example a named
+  reference declared in global scope may be used in function scopes.
+  In ksh, local parameters have static scope, so named references in
+  zsh may have side-effects that do not occur in ksh.  To limit those
+  effects, mytt(zmodload zsh/param/private) and declare all named
+  references mytt(private).
+
+  Named references may be used in zsh versions later than 5.9.
+
+sect(What is zsh's support for non-forking command substitution?)
+label(211)
+
+  This is for cases where you'd write mytt($(command)) but you don't want
+  the overhead or other issues associated with forking a subshell.
+  There are 3 variations:
+  itemization(
+  eit() Borrowed from mksh
+   verb(
+     ${| code }
+   )
+   Runs code in the current shell context and then substitutes mytt(${REPLY}).
+   The result is not split into words unless the tt(SH_WORD_SPLIT) option
+   is set, for example by mytt(${=${| code }}).  mytt($REPLY) is a local
+   parameter within the substitution so its value in the surrounding scope
+   is not changed.
+
+  eit() An extension to #1
+   verb(
+     ${{var} code }
+   )
+   Runs code in the current shell and then substitutes mytt(${var}).  If
+   mytt(${var}) names an array, the result is an array of those elements,
+   but no further splitting is done without tt(SH_WORD_SPLIT). mytt(${var})
+   is myem(not) local to the substitution.
+
+  eit() The traditional ksh form, except that the closing mytt(;)
+   may usually be omitted:
+   verb(
+     ${ code }
+   )
+   Runs code in the current shell and substitutes its standard output.
+   (this is done with a temporary file ala mytt($(<=( code ))) but
+   without the fork implied by mytt(=(...))).  The result is not split
+   into words without tt(SH_WORD_SPLIT).
+  )
+
+  In all three forms mytt(code) behaves myem(similarly) to an anonymous
+  function invoked like:
+  verb(
+    () { code } "$@"
+  )
+  Thus, all parameters declared inside the substitution are local by
+  default, and positional parameters mytt($1), mytt($2), etc. are those
+  of the calling context.
+
+  The most significant limitation is that braces (mytt({) and mytt(}))
+  within the substitutions must either be in balanced pairs, or must be
+  quoted, that is, included in a quoted string or prefixed by backslash.
+  These substitutions first become usable after zsh 5.9.
+
+sect(Comparisons of forking and non-forking command substitution)
+
+  mytt(${ command }) and variants may change the caller's options by using
+  mytt(setopt) and may modify the caller's local parameters, including the
+  positional parameters mytt($1), mytt($2), etc., via both assignments and
+  mytt(set -- pos1 pos2 etc).  Nothing that happens within mytt($(command))
+  affects the caller.
+
+  When not enclosed in double quotes, the expansion of mytt($(command)) is
+  split on tt(IFS) into an array of words.  In contrast, and unlike both
+  bash and ksh, unquoted non-forking substitutions behave like parameter
+  expansions with respect to the tt(SH_WORD_SPLIT) option.
+
+  Both mytt(${|...}) and mytt(${{var} ...}) retain any trailing newlines,
+  except as handled by the tt(SH_WORD_SPLIT) option, consistent with
+  mytt(${|...}) from mksh. mytt(${ command }) removes a single final
+  newline, but mytt("${ command }") retains it.  This differs from
+  bash and ksh, so in emulation modes, newlines are stripped even from
+  quoted command output.  In all cases, mytt($(command)) removes all
+  trailing newlines from the output of mytt(command).
+
+  When mytt(command) is myem(not) a builtin, mytt(${ command }) does
+  fork, and typically forks the same number of times as
+  mytt($(command)), because in the latter case zsh usually optimizes
+  the final fork into an exec.
+
+  Redirecting input from files has subtle differences:
+  itemization(
+    it() mytt($(<file)) is optimized to read from mytt(file) without forking,
+    	 but per above it removes trailing newlines.
+    it() mytt(${<file}) is a substitution error.
+    it() mytt(${ <file }) copies mytt(file) using the mytt(NULLCMD) programs,
+    	 then reads and substitutes the contents of the copy.  Also, this
+	 fails if the tt(CSH_NULLCMD) or tt(SH_NULLCMD) options are in effect,
+	 so it does not work in emulation modes.
+    it() mytt(${|<file}) copies mytt(file) to the standard output using
+    	 tt(NULLCMD) but substitutes nothing because there is no assignment
+	 to tt(REPLY).  It also fails in emulation modes.
+    )
+  mytt(${|IFS= read -rd '' <file}) is therefore the best solution for files
+  that do not contain nul bytes, because it copies the file directly into
+  the local mytt(REPLY) and then substitutes that.  For very large files,
+  refer to mytt(Functions/Misc/zslurp).
 
 chapter(How to get various things to work)
 
@@ -1055,8 +1188,9 @@ label(31)
 
   Other ways of causing word splitting include a judicious use of
   `eval':
+  COMMENT(CHAR(39) is a workaround for a bug in some versions of yodl)\
   verb(
-    sentence="Longtemps, je me suis couch\\'e de bonne heure."
+    sentence="Longtemps, je me suis couch\\CHAR(39)e de bonne heure."
     eval "words=($sentence)"
   )
   after which $words is an array with the words of $sentence (note
@@ -1165,7 +1299,6 @@ sect(In which startup file do I put...?)
   put in tt(.zshrc)
   to save your history.
 
-
 sect(What is the difference between `export' and the tt(ALL_EXPORT) option?)
 
   Normally, you would put a variable into the environment by using
@@ -1191,7 +1324,6 @@ sect(What is the difference between `export' and the tt(ALL_EXPORT) option?)
   it immediately afterwards.  Only those variables will be automatically
   exported.
 
-
 sect(How do I turn off spelling correction/globbing for a single command?)
 
   In the first case, you presumably have mytt(setopt correctall) in an
@@ -1216,7 +1348,6 @@ sect(How do I turn off spelling correction/globbing for a single command?)
   Note also that a shell function won't work: the no... directives must
   be expanded before the rest of the command line is parsed.
 
-
 sect(How do I get the Meta key to work on my xterm?)
 label(35)
 
@@ -1254,7 +1385,6 @@ label(35)
   each byte is used to indicate a part of a multibyte character.  See
   link(chapter 5)(c5).
 
-
 sect(How do I automatically display the directory in my xterm title bar?)
 
   You should use the special function mytt(chpwd), which is called when
@@ -1282,7 +1412,6 @@ sect(How do I automatically display the directory in my xterm title bar?)
   directly: just put mytt(chpwd) in tt(.zshrc) after it is defined or \
   autoloaded.
 
-
 sect(How do I make the completion list use eight bit characters?)
 
   If you are sure your terminal handles this, the easiest way from versions
@@ -1296,7 +1425,6 @@ sect(How do I make the completion list use eight bit characters?)
   possibility may be to set tt(LC_ALL=en_US).  For older versions of the
   shell, there is no easy way out.
 
-
 sect(Why do the cursor (arrow) keys not work?  (And other terminal oddities.))
 
   The cursor keys send different codes depending on the terminal; zsh
@@ -1364,7 +1492,6 @@ sect(Why do the cursor (arrow) keys not work?  (And other terminal oddities.))
   what we used to get the cursor keys above), replace mytt(echoti smkx)
   with mytt(echotc ks) and replace mytt(echoti rmkx) with mytt(echotc ke).
 
-
 sect(Why does my terminal act funny in some way?)
 
   If you are using an OpenWindows cmdtool as your terminal, any
@@ -1407,7 +1534,6 @@ sect(Why does my terminal act funny in some way?)
   afterwards: just the modes it uses itself and a number of special
   processing characters (see the tt(stty(1)) manual page).
 
-
 sect(Why does zsh not work in an Emacs shell mode any more?)
 
   (This information comes from Bart Schaefer and other zsh-workers.)
@@ -1437,7 +1563,6 @@ sect(Why does zsh not work in an Emacs shell mode any more?)
   )
   to ~/.emacs.
 
-
 sect(Why do my autoloaded functions not autoload [the first time]?)
 
   The problem is that there are two possible ways of autoloading a
@@ -1483,7 +1608,6 @@ sect(Why do my autoloaded functions not autoload [the first time]?)
   parentheses removes the directory part of the filenames, leaving
   just the function names.)
 
-
 sect(How does base arithmetic work?)
 
   The ksh syntax is now understood, i.e.
@@ -1527,7 +1651,6 @@ sect(How does base arithmetic work?)
     print $(( [#16] 255 ))
   )
 
-
 sect(How do I get a newline in my prompt?)
 label(313)
 
@@ -1550,7 +1673,6 @@ label(313)
   is a neat way of doing what you want.  Note that it is the quotes, not
   the prompt expansion, which turns the `tt(\n)' into a newline.
 
-
 sect(Why does mytt(bindkey ^a command-name) or mytt(stty intr ^-) do something funny?)
 
   You probably have the extendedglob option set in which case tt(^) and tt(#)
@@ -1560,7 +1682,6 @@ sect(Why does mytt(bindkey ^a command-name) or mytt(stty intr ^-) do something f
   See link(3.27)(327) if you want to know more about the pattern
   character mytt(^).
 
-
 sect(Why can't I bind tt(\C-s) and tt(\C-q) any more?)
 
   The control-s and control-q keys now do flow control by default,
@@ -1574,7 +1695,6 @@ sect(Why can't I bind tt(\C-s) and tt(\C-q) any more?)
   control and hence restoring the use of the keys: put mytt(setopt
   noflowcontrol) in your tt(.zshrc) file.
 
-
 sect(How do I execute command mytt(foo) within function mytt(foo)?)
 
   The command mytt(command foo) does just that.  You don't need this with
@@ -1586,7 +1706,6 @@ sect(How do I execute command mytt(foo) within function mytt(foo)?)
   using `command'.  If mytt(foo) is a builtin rather than an external
   command, use mytt(builtin foo) instead.
 
-
 sect(Why do history substitutions with single bangs do something funny?)
 
   If you have a command like "tt(echo !-2:$ !$)", the first history
@@ -1595,7 +1714,6 @@ sect(Why do history substitutions with single bangs do something funny?)
   tt(!-2:$).  The option tt(CSH_JUNKIE_HISTORY) makes all single bangs refer
   to the last command.
 
-
 sect(Why does zsh kill off all my background jobs when I logout?)
 
   Simple answer: you haven't asked it not to.  Zsh (unlike [t]csh) gives
@@ -1613,13 +1731,11 @@ sect(Why does zsh kill off all my background jobs when I logout?)
   Likewise, you can start a background job with mytt(&!) instead of just
   mytt(&) at the end, which will automatically disown the job.
 
-
 sect(How do I list all my history entries?)
 
   Tell zsh to start from entry 1: mytt(history 1).  Those entries at the
   start which are no longer in memory will be silently omitted.
 
-
 sect(How does the alternative loop syntax, e.g. mytt(while {...} {...}) \
 work?)
 
@@ -1677,7 +1793,6 @@ work?)
   manual), which you are in any case encouraged even more strongly not
   to use in programs as it can be very confusing.
 
-
 sect(Why is my history not being saved?)
 label(321)
 
@@ -1695,8 +1810,8 @@ label(321)
   above.  There are also various options affecting history; see the
   manual.
 
-
 sect(How do I get a variable's value to be evaluated as another variable?)
+label(322)
 
   The problem is that you have a variable tt($E) containing the string
   mytt(EDITOR), and a variable tt($EDITOR) containing the string mytt(emacs),
@@ -1732,7 +1847,6 @@ sect(How do I get a variable's value to be evaluated as another variable?)
   it, this works).  So in mytt(${${E}}), the internal mytt(${...})
   actually does nothing.
 
-
 sect(How do I prevent the prompt overwriting output when there is no newline?)
 
   The problem is normally limited to zsh versions prior to 4.3.0 due to the
@@ -1775,7 +1889,6 @@ sect(How do I prevent the prompt overwriting output when there is no newline?)
   One final alternative is to put a newline in your prompt -- see question
   link(3.13)(313) for that.
 
-
 sect(What's wrong with cut and paste on my xterm?)
 
   On the majority of modern UNIX systems, cutting text from one window and
@@ -1814,7 +1927,6 @@ sect(What's wrong with cut and paste on my xterm?)
      in the tt(zshparam) manual page for details.
   )
 
-
 sect(How do I get coloured prompts on my colour xterm?)
 
   (Or `color xterm', if you're reading this in black and white.)
@@ -1858,7 +1970,6 @@ sect(How do I get coloured prompts on my colour xterm?)
   `mytt(<ESC>[0m)' puts printing back to normal so that the rest of the line
   is unchanged.
 
-
 sect(Why is my output duplicated with `tt(foo 2>&1 >foo.out | bar)'?)
 
   This is a slightly unexpected effect of the option tt(MULTIOS), which is
@@ -1893,7 +2004,7 @@ sect(Why is my output duplicated with `tt(foo 2>&1 >foo.out | bar)'?)
   to both files when the redirector appears twice.  What's going on in the
   first example is exactly the same, however the second redirector is
   disguised as a pipe.  So if you want to turn this effect off, you need
-  to unset the option mytt(MULTIOS), or alternatively write the following:
+  to unset the option tt(MULTIOS), or alternatively write the following:
   verb(
     % { print output; print error >&2 } 2>&1 >&- >foo.out | sed 's/error/erratic/'
     erratic
@@ -1902,7 +2013,6 @@ sect(Why is my output duplicated with `tt(foo 2>&1 >foo.out | bar)'?)
   (to the pipe) and start anew with tt(>foo.out) instead of adding it as a
   redirection target to stdout.
 
-
 sect(What are these `^' and `~' pattern characters, anyway?)
 label(327)
 
@@ -1986,7 +2096,7 @@ label(327)
   mytt(something) mustn't contain tt(/) if the pattern is being used for
   globbing.
 
-  Likewise, mytt(abc+LPAR()<->~<10-100>RPAR().txt) matches a file consisting of
+  Likewise, mytt(abc+_LPAR_<->~<10-100>_RPAR_.txt) matches a file consisting of
   tt(abc), then some digits, then tt(.txt), unless the digits happen to
   match a number from 10 to 100 inclusive (remember the handy mytt(<->)
   pattern for matching integers with optional limits to the range).  So
@@ -2029,7 +2139,6 @@ label(327)
      in the current directory or any parent.)
   )
 
-
 sect(How do I edit the input buffer in $EDITOR?)
 label(328)
 
@@ -2045,7 +2154,6 @@ label(328)
   command-line for editing.  The command will not be automatically executed;
   quitting the editor will only return to zsh's command-line editing mode.
 
-
 sect(Why does `which' output for missing commands go to stdout?)
 
   The issue is that if you run:
@@ -2075,7 +2183,6 @@ sect(Why does `which' output for missing commands go to stdout?)
   other Bourne-style shells it is in fact self-consistent.  Note that
   the exit status does reflect the fact the command can't be found.
 
-
 sect(Why doesn't the expansion mytt(*.{tex,aux,pdf}) do what I expect?)
 
   Based on the behaviour of some other shells, you might guess that the
@@ -2109,13 +2216,42 @@ sect(Why doesn't the expansion mytt(*.{tex,aux,pdf}) do what I expect?)
 
   This use of parentheses is special to zsh.  Modern Bourne-like shells
   have a syntax like this, too, but with an mytt(@) in front of the
-  parentheses: again, see link(2.1)(21), and search for mytt(@+LPAR()).
+  parentheses: again, see link(2.1)(21), and search for mytt(@_LPAR_).
   This is harder for the user to remember but easier for the shell to
   parse!
 
+sect(Why does mytt($RANDOM) return the same number more than once?)
 
-chapter(The mysteries of completion)
+  As tt(zshparam(1)) says:
+  verb(
+      The values of RANDOM form an intentionally-repeatable
+      pseudo-random sequence; subshells that reference RANDOM
+      will result in identical pseudo-random values unless the
+      value of RANDOM is referenced or seeded in the parent shell
+      in between subshell invocations.
+  )
+
+  You can use a function, including an anonymous function, to always
+  evaluate mytt($RANDOM) in the parent shell.  This example illustrates
+  the difference:
+  verb(
+    for i in {1..10}; do
+      echo subshell: $(echo $RANDOM) $RANDOM
+      () { echo parent: $(echo $1) $2 } $RANDOM $RANDOM;
+    done
+  )
+
+  Remember that for a pipe like mytt(A | B), zsh runs A in a subshell
+  and B in the current shell.  This means that, for example:
+  verb(
+    for i in {1..10}; do
+      echo $RANDOM | tee
+    done
+  )
+  also repeats the same value, because mytt($RANDOM) is evaluated in
+  the subshell and the parent sequence is left unchanged.
 
+chapter(The mysteries of completion)
 
 sect(What is completion?)
 
@@ -2146,7 +2282,6 @@ sect(What is completion?)
   compinit; compinit)' in your tt(.zshrc) should be enough if the system is
   installed properly.
 
-
 sect(What sorts of things can be completed?)
 label(42)
 
@@ -2170,7 +2305,6 @@ label(42)
   `anything where an automated guess is possible'.  Just hit TAB
   and see if the shell manages to guess correctly.
 
-
 sect(How does zsh deal with ambiguous completions?)
 
   Often there will be more than one possible completion: two files
@@ -2208,7 +2342,6 @@ sect(How does zsh deal with ambiguous completions?)
   from version 3.1 tt(LIST_AMBIGUOUS) is set by default; if you use
   autolist, you may well want to `unsetopt listambiguous'.
 
-
 sect(How do I complete in the middle of words / just what's before the cursor?)
 
   Sometimes you have a word on the command-line which is incomplete in the
@@ -2237,7 +2370,6 @@ sect(How do I complete in the middle of words / just what's before the cursor?)
   can expand to tt(/usr/local/bin) or anything else that matches.  This
   saves you having to expand the middle part of the path separately.
 
-
 sect(How do I get started with programmable completion?)
 label(45)
 
@@ -2250,7 +2382,6 @@ label(45)
   tells you how to configure the completion system and chapter 15 how
   to write your own completion functions.
 
-
 sect(Suppose I want to complete all files during a special completion?)
 
   If you're using the completion system the shell will decide what
@@ -2282,7 +2413,6 @@ sect(Suppose I want to complete all files during a special completion?)
   completion.  Your actual completer style may include other actions,
   such as expansion or approximate completion.
 
-
 chapter(Multibyte input and output)
 label(c5)
 
@@ -2333,7 +2463,6 @@ sect(What is multibyte input?)
   way, for example on Windows, but the shell can't deal directly with text
   in those formats.)
 
-
 sect(How does zsh handle multibyte input and output?)
 
   Until version 4.3, zsh didn't handle multibyte input properly at all.
@@ -2378,7 +2507,6 @@ sect(How does zsh handle multibyte input and output?)
   in inverse video.  Highlighting of such special characters can
   be modified using the new array parameter tt(zle_highlight).
 
-
 sect(How do I ensure multibyte input and output work on my system?)
 
   Once you have a version of zsh with multibyte support, you need to
@@ -2450,7 +2578,6 @@ sect(How do I ensure multibyte input and output work on my system?)
   to compile with the tt(MULTIBYTE) option enabled, but the system
   didn't provide full support for it.
 
-
 sect(How can I input characters that aren't on my keyboard?)
 
   Two functions are provided with zsh that help you input characters.
@@ -2494,7 +2621,6 @@ url(http://www.unicode.org/charts/)(http://www.unicode.org/charts/).
   See also url(http://www.cl.cam.ac.uk/~mgk25/unicode.html#input)(http://www.cl.cam.ac.uk/~mgk25/unicode.html#input)
   for general information on entering Unicode characters from a keyboard.
 
-
 chapter(The future of zsh)
 
 sect(What bugs are currently known and unfixed? (Plus recent \
@@ -2511,7 +2637,6 @@ label(61)
   most important changes, and in particular draws attention to
   incompatibilities you might notice.
 
-
 sect(Where do I report bugs, get more info / who's working on zsh?)
 label(62)
 
@@ -2565,7 +2690,7 @@ label(62)
   Mail email(sympa@zsh.org?subject=help) for detailed information.
   Administrative matters are best sent to
   email(zsh-workers-owner@zsh.org).
-  
+
   Note that this location changed in August 2020, and the
   instructions to go with it are slightly different.
 
@@ -2573,10 +2698,6 @@ label(62)
     url(http://www.zsh.org/mla/)(http://www.zsh.org/mla/)
   at the main zsh archive site.
 
-  Of course, you can also post zsh queries to the Usenet group
-  comp.unix.shell; if all else fails, you could even e-mail me.
-
-
 sect(What's on the wish-list?)
 
   The code bears the marks of the ages and many things could be done much
@@ -2590,17 +2711,13 @@ sect(What's on the wish-list?)
      characters.  Initial support for this appeared in version 4.3;
      it is reasonably complete in the line editor but patchy elsewhere
      (note this may require the configuration option --enable-multibyte).
-  it() The parameter code could do with tidying up, maybe with more of the
-     features made available in ksh93.
+  it() The parameter code could do with tidying up.
   it() Configuration files to enable zsh startup files to be created
      with the Dotfile Generator.
   it() Further improvements in integrating the line editor with shell
      functions.
-  it() POSIX compatibility could be improved.
-  it() Option for glob qualifiers to follow perl syntax (a traditional item).
   )
 
-
 sect(Did zsh have problems in the year 2000?)
 
   Not that I heard of; it's up to you to be careful with two-digit dates,
@@ -2608,7 +2725,6 @@ sect(Did zsh have problems in the year 2000?)
   and also by the command `tt(print -P)'.  Earlier versions of zsh may
   show problems here.
 
-
 sect(When reporting a bug, how do I reduce my mytt(.zshrc) into a minimal reproduction recipe?)
 
   When reporting a bug, the gold standard is to include with the bug
@@ -2622,9 +2738,8 @@ sect(When reporting a bug, how do I reduce my mytt(.zshrc) into a minimal reprod
   and then, within that instance of the shell, run a minimal short
   sequence of commands that reproduces the bug.  A good way to devise
   such recipes is the following:
-
 COMMENT(For reference, here's Vim's write-up of a similar process:
-https://github.com/chrisbra/vim_faq/blob/de424bd8e08bcf0e6b1e0563ee49514dfed926ae/vim_faq.txt#L1153-L1228)
+https://github.com/chrisbra/vim_faq/blob/de424bd8e08bcf0e6b1e0563ee49514dfed926ae/vim_faq.txt#L1153-L1228)\
 
   enumeration(
   myeit() First, ensure the bug is reproducible.  To do this, start
@@ -2700,31 +2815,30 @@ https://github.com/chrisbra/vim_faq/blob/de424bd8e08bcf0e6b1e0563ee49514dfed926a
   Bug reports should be emailed to the mytt(zsh-workers@zsh.org) public
   mailing list; see link(6.2)(62) for details.
 
-
 nsect(Acknowledgments:)
 
-Thanks to zsh-list, in particular Bart Schaefer, for suggestions
+Thanks to zsh-workers, in particular Bart Schaefer, for suggestions
 regarding this document.  Zsh has been in the hands of archivists Jim
 Mattson, Bas de Bakker, Richard Coleman, Zoltan Hidvegi and Andrew
-Main, and the mailing list has been run by Peter Gray, Rick Ohnemus,
-Richard Coleman, Karsten Thygesen and Geoff Wing, all of whom deserve
+Main, and the mailing lists have been managed or hosted by Peter Gray,
+Rick Ohnemus, Richard Coleman, Karsten Thygesen, Geoff Wing, Phil
+Pennock, Daniel Shahaf, and Oliver Kiddle, all of whom deserve
 thanks.  The world is eternally in the debt of Paul Falstad for inventing
 zsh in the first place (though the wizzo extended completion is by Sven
 Wischnowsky).
 
-
 nsect(Copyright Information:)
 
 This document is copyright (C) P.W. Stephenson, 1995, 1996, 1997,
-1998, 1999, 2000, 2012, 2020. This text originates in the U.K. and the author
-asserts his moral rights under the Copyrights, Designs and Patents Act,
-1988.
+1998, 1999, 2000, 2012, 2020, 2023. This text originates in the U.K.
+and the author asserts his moral rights under the Copyrights, Designs
+and Patents Act, 1988.
 
 Permission is hereby granted, without written agreement and without
 license or royalty fees, to use, copy, modify, and distribute this
 documentation for any purpose, provided that the above copyright
 notice appears in all copies of this documentation.  Remember,
-however, that this document changes monthly and it may be more useful
+however, this document changes occasionally and it may be more useful
 to provide a pointer to it rather than the entire text.  A suitable
 pointer is "information on the Z-shell can be obtained on the World
 Wide Web at URL https://zsh.sourceforge.io/".
diff --git a/Etc/NEWS-4.3 b/Etc/NEWS-4.3
index 19b3daada..8d93af134 100644
--- a/Etc/NEWS-4.3
+++ b/Etc/NEWS-4.3
@@ -139,7 +139,7 @@ The new shell option POSIX_CD, active in emulations of POSIX-based shells,
 makes the cd builtin POSIX-compatible.
 
 The POSIX_JOBS option already referred to has various other
-compatibility enchancements.
+compatibility enhancements.
 
 The new shell option POSIX_STRINGS makes a null character in $'...'
 expansion terminate the string, as is already the case in bash.  This is
diff --git a/Etc/completion-style-guide b/Etc/completion-style-guide
index 62e6a2787..f7dcae230 100644
--- a/Etc/completion-style-guide
+++ b/Etc/completion-style-guide
@@ -75,6 +75,8 @@ but use:
 To indicate a default value, use square brackets:
   '--timeout[specify connection timeout]:timeout (ms) [5000]'
 These two conventions can be used together or individually as appropriate.
+Alternatively the `_numbers' function may be used:
+  '--timeout[specify connection timeout]: :_numbers -u ms -d 5000 timeout'
 
 Group descriptions should be singular because only one thing is being
 completed even though many may be listed. This applies even where you
@@ -570,3 +572,13 @@ Misc. remarks
       data derived from another command's output to the helper. Consider
       using some variation of the `q` expansion flag to deal with this:
       `_call_program vals $words[1] ${(q-)myfile}'
+10) If you are going to create a new completion function '_cmd' for a
+    command 'cmd', and if the 'cmd' supports the --help option, then you
+    may try
+      compdef _gnu_generic cmd
+      cmd -<TAB>
+    _gnu_generic may not work sufficiently well for 'cmd', but the specs
+    for _arguments generated from the help text are cached in a variable
+    '_args_cache_cmd', and you can save them in a file '_cmd' by
+      print -r -- ${(F)${(@qqq)_args_cache_cmd}} > _cmd
+    and use the file as a draft of the new completion function.
diff --git a/Etc/creating-a-release.txt b/Etc/creating-a-release.txt
index 16784a054..80fe2b301 100644
--- a/Etc/creating-a-release.txt
+++ b/Etc/creating-a-release.txt
@@ -7,9 +7,9 @@ To create a zsh release:
 
 	Config/version.mk to today's date
 	Config/version.mk version number
-	Etc/FAQ.yo
-	README
-	NEWS
+	Etc/FAQ.yo ('latest version' section)
+	README (first two paragraphs, 'incompatibilities since' sections)
+	NEWS ('changes since' sections)
 
   The version-number sequence is as follows:
 
@@ -31,7 +31,9 @@ To create a zsh release:
 
   README should document compatibility-breaking changes. Generally, NEWS should
   document new features and major bug fixes (but not routine fixes or changes to
-  completion/contrib functions).
+  completion/contrib functions). Historically, these documents have often been
+  missed at the time the changes were actually committed, so it may be a good
+  idea to scan back through the history and fill in any blanks before release.
 
   For -test releases, you may update the FAQ, README, etc., to refer to the
   upcoming stable version number.
@@ -77,7 +79,7 @@ To create a zsh release:
 
 - Create the keyring:
 
-        cat web.git/Keys/*.asc > zsh-keyring.asc
+	cat web.git/Keys/*.asc > zsh-keyring.asc
 
 - Upload to sf.net:
 
@@ -90,13 +92,13 @@ To create a zsh release:
 
   You should upload five files:
 
-        zsh-5.8.tar.xz
-        zsh-5.8.tar.xz.asc
-        zsh-doc-5.8.tar.xz
-        zsh-doc-5.8.tar.xz.asc
-        zsh-keyring.asc
+	zsh-5.8.tar.xz
+	zsh-5.8.tar.xz.asc
+	zsh-doc-5.8.tar.xz
+	zsh-doc-5.8.tar.xz.asc
+	zsh-keyring.asc
 
-        (TODO: what about MD5SUM, FAQ, META-FAQ, all in www.zsh.org/pub/?)
+	(TODO: what about MD5SUM, FAQ, META-FAQ, all in www.zsh.org/pub/?)
 
   Note that zsh-keyring.asc is fine to just overwrite, since it's only ever
   appended to, and in any case the underlying Keys/*.asc files are in version
@@ -142,10 +144,17 @@ To create a zsh release:
 	# several minutes to appear afterwards
 	rsync ...
 
-- For stable releases, upload the build artefacts to zsh.org/pub; you may need
-  assistance from another dev if you don't have access to do this.
+- For stable releases, upload the build artefacts to zsh.org/pub, making sure to
+  move the previous ones to old/. For example (assuming the new artefacts are in
+  the CWD):
 
-- Post to -workers@
+	mv /usr/local/www/ftp/pub/zsh-*.*(.) /usr/local/www/ftp/pub/old/
+	mv zsh-*.*(.) /usr/local/www/ftp/pub/
+
+  You may need assistance from another dev if you don't have access to do this.
+
+- Post to -workers@. You may also wish to (ask someone to) update the #zsh
+  channel topic on IRC.
 
 - After a day or so post to:
 
diff --git a/Etc/zsh-development-guide b/Etc/zsh-development-guide
index e8c292cfd..bdabe17d8 100644
--- a/Etc/zsh-development-guide
+++ b/Etc/zsh-development-guide
@@ -223,9 +223,6 @@ C coding style
 * Do not use space between the function name and the opening parenthesis.
   Use space after if/for/while.  Use space after type casts.
 
-* Do not use (unsigned char) casts since some compilers do not handle
-  them properly.  Use the provided STOUC(X) macro instead.
-
 * If you use emacs 19.30 or newer you can put the following line to your
   ~/.emacs file to make these formatting rules the default:
 
@@ -243,7 +240,7 @@ C coding style
   There must be an empty line, a line with "/**/", a line with the
   type of the function, and finally the name of the function with typed
   arguments.  These lines must not be indented.  The script generating
-  function prototypes and the ansi2knr program depend on this format.
+  function prototypes depends on this format.
 
 * Variable declarations must similarly be preceded by a
   line containing only "/**/", for the prototype generation script.
@@ -374,8 +371,8 @@ particular they can be called before or after `boot_'.
 The function named `boot_' should register function wrappers, hooks and
 anything that will be visible to the user that is not handled by features_
 and enables_ (so features should not be turned on here).  It will be called
-after the `setup_'-function, and also after the initial set of features
-have been set by calls to `features_' and `enables_'.
+after the initial set of features have been set by calls to `features_'
+and `enables_'.
 
 The function named `cleanup_', is called when the user tries to unload
 a module and should de-register all features and hooks.  A call
@@ -615,7 +612,7 @@ For defining parameters, a module can call `createparam()' directly or
 use a table to describe them, e.g.:
 
   static struct paramdef patab[] = {
-    PARAMDEF("foo", PM_INTEGER, NULL, get_foo, set_foo, unset_foo),
+    PARAMDEF("foo", PM_INTEGER, NULL, foo_gsu),
     INTPARAMDEF("exint", &intparam),
     STRPARAMDEF("exstr", &strparam),
     ARRPARAMDEF("exarr", &arrparam),
@@ -627,17 +624,23 @@ There are four macros used:
     - the name of the parameter
     - the parameter flags to set for it (from the PM_* flags defined
       in zsh.h)
-    - optionally a pointer to a variable holding the value of the
-      parameter
-    - three functions that will be used to get the value of the
-      parameter, store a value in the parameter, and unset the
-      parameter
+    - optionally a pointer to the value of the parameter
+    - a GSU pointer to the three functions that will be used to get
+      the value of the parameter, store a value in the parameter,
+      and unset the parameter
   - the other macros provide simple ways to define the most common
     types of parameters; they get the name of the parameter and a
     pointer to a variable holding the value as arguments; they are
-    used to define integer-, scalar-, and array-parameters, so the
-    variables whose addresses are given should be of type `long',
-    `char *', and `char **', respectively
+    used to define integer-, scalar-, and array-parameters, so for
+    those macros the pointer to the parameter value should be the
+    address of a variable of type `long', `char *',or `char **',
+    respectively, pointing in turn to the desired value.
+  - Parameters used in a module that don't have special behaviour
+    shouldn't be declared in this way, instead they should just be
+    created in `boot_'  with the standard parameter functions.
+
+GSU (get, set, unset) structures are defined in Src/zsh.h for each of
+the parameter types scalar, integer, float, array, and hash.
 
 For a description of how to write functions for getting or setting the 
 value of parameters, or how to write a function to unset a parameter,