about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-06-08 09:25:39 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-06-08 09:25:39 +0000
commit805381040dd69dd02b78423d2d71913b33f3cc33 (patch)
tree1fa89ee643e8e577a2f79e76e3d6cafc93256ca2
parentf42e3fa8e6152e145251e8f16f4c61c23dec1f59 (diff)
downloadzsh-805381040dd69dd02b78423d2d71913b33f3cc33.tar.gz
zsh-805381040dd69dd02b78423d2d71913b33f3cc33.tar.xz
zsh-805381040dd69dd02b78423d2d71913b33f3cc33.zip
zsh-3.1.5-pws-21 zsh-3.1.5-pws-21
-rw-r--r--ChangeLog1238
-rw-r--r--Completion/.distfiles2
-rw-r--r--Completion/Base/.distfiles2
-rw-r--r--Completion/Base/_brace_parameter14
-rw-r--r--Completion/Base/_first63
-rw-r--r--Completion/Base/_long_options10
-rw-r--r--Completion/Core/.distfiles7
-rw-r--r--Completion/Core/_approximate12
-rw-r--r--Completion/Core/_complete10
-rw-r--r--Completion/Core/_correct4
-rw-r--r--Completion/Core/_expand2
-rw-r--r--Completion/Core/_files8
-rw-r--r--Completion/Core/_list4
-rw-r--r--Completion/Core/_normal2
-rw-r--r--Completion/Core/_parameters7
-rw-r--r--Completion/Core/_sep_parts2
-rw-r--r--Completion/Core/compinit34
-rw-r--r--Completion/Makefile.in86
-rw-r--r--Completion/User/_make3
-rw-r--r--Completion/User/_mh2
-rw-r--r--Config/.distfiles2
-rw-r--r--Config/config.mk2
-rw-r--r--Config/defs.mk.in7
-rw-r--r--Config/version.mk4
-rw-r--r--Doc/Makefile.in4
-rw-r--r--Doc/Zsh/.distfiles12
-rw-r--r--Doc/Zsh/builtins.yo6
-rw-r--r--Doc/Zsh/compat.yo20
-rw-r--r--Doc/Zsh/compctl.yo17
-rw-r--r--Doc/Zsh/compsys.yo20
-rw-r--r--Doc/Zsh/compwid.yo20
-rw-r--r--Doc/Zsh/expn.yo119
-rw-r--r--Doc/Zsh/files.yo16
-rw-r--r--Doc/Zsh/metafaq.yo23
-rw-r--r--Doc/Zsh/options.yo70
-rw-r--r--Doc/Zsh/zftpsys.yo58
-rw-r--r--Doc/ztexi.yo2
-rw-r--r--Functions/.distfiles4
-rw-r--r--Functions/Makefile.in86
-rw-r--r--Functions/Misc/.distfiles6
-rwxr-xr-xFunctions/Misc/acx6
-rw-r--r--Functions/Misc/allopt29
-rw-r--r--Functions/Misc/cat16
-rwxr-xr-xFunctions/Misc/cdmatch23
-rw-r--r--Functions/Misc/cdmatch215
-rw-r--r--Functions/Misc/checkmail26
-rwxr-xr-xFunctions/Misc/cx6
-rw-r--r--Functions/Misc/harden6
-rw-r--r--Functions/Misc/mere3
-rwxr-xr-xFunctions/Misc/multicomp72
-rwxr-xr-xFunctions/Misc/proto8
-rw-r--r--Functions/Misc/pushd13
-rwxr-xr-xFunctions/Misc/randline3
-rw-r--r--Functions/Misc/run-help72
-rwxr-xr-xFunctions/Misc/yp2
-rwxr-xr-xFunctions/Misc/yu2
-rw-r--r--Functions/Misc/zed65
-rw-r--r--Functions/Misc/zless37
-rw-r--r--Functions/Misc/zls72
-rw-r--r--Functions/README.zftp4
-rw-r--r--Functions/Zftp/.distfiles7
-rw-r--r--INSTALL32
-rw-r--r--Makefile.in9
-rw-r--r--Misc/.distfiles1
-rw-r--r--Src/.distfiles7
-rw-r--r--Src/Modules/.distfiles1
-rw-r--r--Src/Modules/mapfile.c1
-rw-r--r--Src/Zle/.distfiles4
-rw-r--r--Src/Zle/comp.h118
-rw-r--r--Src/Zle/comp1.c18
-rw-r--r--Src/Zle/comp1.export5
-rw-r--r--Src/Zle/compctl.c131
-rw-r--r--Src/Zle/zle_hist.c19
-rw-r--r--Src/Zle/zle_main.c5
-rw-r--r--Src/Zle/zle_misc.c5
-rw-r--r--Src/Zle/zle_move.c2
-rw-r--r--Src/Zle/zle_refresh.c3
-rw-r--r--Src/Zle/zle_tricky.c649
-rw-r--r--Src/glob.c3
-rw-r--r--Src/hist.c6
-rw-r--r--Src/init.c42
-rw-r--r--Src/loop.c13
-rw-r--r--Src/main.c24
-rw-r--r--Src/options.c11
-rw-r--r--Src/subst.c15
-rw-r--r--Src/zsh.export2
-rw-r--r--Src/zsh.mdd3
-rw-r--r--Util/zsh-development-guide13
-rw-r--r--configure.in20
89 files changed, 3178 insertions, 481 deletions
diff --git a/ChangeLog b/ChangeLog
index a1a22e495..48818fe3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,1241 @@
+1999-06-08  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+
+	* 3.1.5-pws-21 made available
+
+	* Sven: 6515: Src/Zle/zle_tricky.c: fix memory problems with 6492
+
+	* Wayne: 6510: Completion/Core/compinit: another nounset problem
+
+1999-06-07  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+
+	* pws: configure.in, Config/defs.mk.in, Functions/Makefile.in,
+	  Completion/Makefile.in, rearrangement of Functions
+	  subdirectories:  --enable-fndir allows function installation,
+	  defaults to ${datadir}/zsh/functions; is compiled into $fpath;
+	  FUNCTIONS_INSTALL can specify functions to install e.g.
+	  'Core/* Base/* Builtins/* Zftp/*'.
+
+	* pws: 6509: Src/Zle/zle_tricky.c: comp_setunset -> comp_setunsetptr
+
+	* pws: 6506: Completion/Core/compinit, Doc/Zsh/compsys.yo: if
+	  completion dumpfile is not writeable, use
+	  ${ZDOTDIR:-$HOME}/.zcompdump
+
+	* Sven: 6502: Doc/Zsh/options.yo: document 6496
+
+	* Sven: 6496: Src/Zle/zle_misc.c (makesuffix): more characters
+	  that can't be part of a filename
+
+	* Sven: 6493: Completion/Core/_approximate,
+	  Completion/Core/_expand: %e wasn't being replaced properly in
+	  correction prompts
+
+	* Sven: 6492: Src/Zle/comp.h, Src/Zle/comp1.c, Src/Zle/compctl.c,
+	  Src/Zle/zle_main.c, Src/Zle/zle_tricky.c, Doc/Zsh/compctl.yo,
+	  Doc/Zsh/compsys.yo, Doc/Zsh/compwid.yo,
+	  Completion/Base/_brace_parameter:  Completion inside quotes
+	  now acts as if the file name is the entire quoted string;
+	  `compctl -h' takes a command line from inside a quoted string;
+	  the compctl tests q[s], q[d], q[b] are true if we are in single,
+	  double, back quotes; compset -q tests quotes and splits the word,
+	  affecting $PREFIX, $SUFFX and setting $IQPREFIX, $IQSUFFIX for
+	  the bits which will now be ignored.
+
+	* pws: 6490: Completion/Core/compinit: nounset workaround
+
+	* Bart: 6485: Src/loop.c: only show one screenful at a time
+	  in select, as LINES doc implies it should do
+
+	* Sven: 6484: Src/Zle/zle_main.c, Src/Zle/zle_tricky.c: close
+	  fd 0 during zle widgets and completion and redup back afterwards
+	  (removed unnecessary zclose()'s)
+	
+	* Wayne: 6481: Doc/Zsh/builtins.yo, Doc/Zsh/options.yo,
+	  Src/hist.c:  improved new history documentation and comments
+
+	* Wayne: 6480: Src/hist.c: Ignore some lines in remhist() to
+	  workaround crashes attempting to add already removed lines
+
+	* Tanaka Akira: 6478: Completion/User/_make: complete files
+	  as fallback (but use _files instead of compgen -f)
+
+1999-06-06  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+
+	* Naoki Wakamatsu <naoki-w@ht-net21.ne.jp>: 6477: configure.in:
+	  undefine etcdir, not zshenv
+
+1999-06-05  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+
+	* Merge ChangeLog entry from patchlist.txt in 3.1.5-pws-20
+	  These are briefer than normal ChangeLog entries, but upgrading
+	  all of them is too much work.
+
+	* pws: 6473: Src/Modules/mapfile.c: munmap() after writing file
+
+	* Bart: 6472: doc for 6458
+
+	* pws: 6470: options.yo doc for globalrcs
+
+	* Sven: 6468: -first- context example; allow $compcontext for
+	  direct context in _complete; other stuff
+
+	* pws: 6464: fix problem with 6433; disallow nested parameter
+	  substitution without braces
+
+	* Sven: 6458: allow seconds in globbing qualifier time comparisons
+
+	* Zefram: off-list: metafaq updates
+
+	* pws: 6437: rearrange quotes in expn.yo, zftpsys.yo, minor
+	  corrections
+
+	* pws: 6433: allow quotes around names of parameters in braces
+
+	* pws: 6431: su saga again: new documentation
+
+	* Bart: 4127: su saga: 6299 and 6313 backed off; this alters
+	  ZSH_NAME using zgetenv("SHELL").  It can be turned into an
+	  --enable if anyone complains.
+
+	* Wayne: 6430: history tweaks: more careful ignoring history with
+	  foreign lines, changed name incappendhistory
+
+	* pws: 6424: reduce excess quoting in info files
+
+	* pws: 6421: _mh should use $words instead of $argv
+
+	* pws: 6416: document ${(f)"$(foo)"} change and nesting of quotes
+	  in braces
+
+	* Sven: 6414: completing parameters with extra quotes, don't
+	  complete local parameters
+
+	* Sven: 6411: fix display bug on terminals which can do
+	  TCMULTRIGHT (gap left when clearing list).
+
+	* pws: 6410: RCS option can now take affect at any point during
+	  initialisation, new GLOBAL_RCS applies to /etc/z* files.
+
+	* Bart: 6404: singleton arrays treated as scalars locally (as
+	  before), but correct array/scalar status is passed to enclosing
+	  substitutions.
+
+	* Bart: 6395: uninstall info files over 9, too
+
+	* Sven: 6212 (previously missed): an extra clear list
+
+	* Andrej: 6392: install info files higher than 9
+
+	* 3.1.5-pws-20
+
+	* Sven: 6388: completion in braces removes later arguments
+
+	* Sven: 6374: autoremove behaviour on -r and -R, documentation
+
+	* Bart: 6369: fix use of relative paths in compinstall
+
+	* Bart: 6368: don't use cp -f, use rm -f in configure.in
+
+	* Sven: 6355: ALL_EXPORT crashed the shell if set on command line
+
+	* Sven: 6352, 6354: more quoting in completion
+
+	* pws: 6346: msync() missing from mapfile.c, somehow
+
+	* pws: 6345: Config/defs.mk is now in build tree, not source tree
+
+	* Sven: 6343: test length of anchor in partial word matching
+
+	* pws: 6340: INSTALL didn't work if it was install-sh after 6330
+
+	* pws: 6335: now you can do ${(f)"$(...)"} to get arrays
+
+	* pws: 6332: mapfile module
+
+	* pws: 6331: protect against null hash tables in parameter module
+
+	* pws: 6330: rewrite configuration system to use AC_SUBST_FILE
+	  instead of including files by ed trickery (ed is now no longer
+	  required).
+
+	* Sven: 6326: compadd -r and -R work on automatically added
+	  suffixes, too
+
+	* Sven: 6322: reverse indexing of nested arrays
+
+	* Sven: 6318: memory fixes for parameter module (and compctl).
+
+	* 3.1.5-pws-19 made available
+
+	* pws: unposted: updated some .distfiles
+
+	* pws: 6314: in something like `{ false; } || true', errexit
+	  shouldn't be used at all on the left of the ||
+
+	* pws: 6313: fix 6299 to use $SHELL to decide emulation
+
+	* pws: 6307, 6312: wider support for 64-bit integers on 32-bit
+	  architectures
+
+	* Tanaka Akira: 6303: _path_files: find files after symbolic link
+
+	* Sven: 6302: more list_pipe intricacies
+
+	* Sven: 6301: expanded ignored prefix ignored for testing
+
+	* pws: 6299: if called as su* or -su*, zsh doesn't do sh emulation
+
+	* Sven: 6298: (mult_isarr) ${*:-word} didn't use the default word
+
+	* pws: 6294: typeset -U MANPATH performs uniqueness test straight
+	  away
+
+	* pws: 6291: zftp only checks for system type after login.
+
+	* pws: 6290: parameter module uses global scope, $parameters gets
+	  unreadonlied, gcc warning
+
+	* Sven: 6285: tty/job handling when executing some command in
+	  current shell code within RHS of pipeline
+
+	* Sven: 6283: compadd -U didn't quote characters properly
+
+	* Sven: 6278: fix ${$(foo)...} to produce an array
+
+	* Tatsuo Furukawa: 6274: updated form of zle_refresh patch
+
+	* Tatsuo Furukawa: 6273: don't need to defined _POSIX* flags
+	  specially on HPUX
+
+	* pws: 6272: correct even more mistakes some bozo (guess who) made
+	  with rlim_t: put back RLIM_T_IS_UNSIGNED code.
+
+	* pws: 6271: make sure -D_LARGEFILE_SOURCE is defined any time
+	  there are other -D's for large file support
+
+	* pws: 6284, should have been in 6269: changes to large file
+	  support
+
+	* Sven: 6268: parameter module for access to internal tables
+
+	* pws: 6263: incrementalappendhistory -> incappendhistory
+
+	* 3.1.5-pws-18 made available
+
+	* pws: 6259: second version of compinstall
+
+	* pws: 6258: yet another attempt at the same problem
+
+	* pws: 6257: rewrite 6240 for any old builtin structure after the
+	  pipeline
+
+	* Wayne: 6255: more history: zle toggle between local/global
+	  history;  `zle widget' can now take a direct numeric argument;
+	  small tweaks
+
+	* Sven: 6249: fix for 6046 (problem showed up with $(...))
+
+	* pws: 6246: doc changes for 6046, plus subscripts done properly
+
+	* Sven: 6046: nested parameter expansions can return either arrays
+	  or scalars.
+
+	* Wayne: 6241: history editing can use foreign history commands;
+	  history appended in hend() instead of hbegin()
+
+	* pws: 6240: a pipeline ending in a builtin didn't attach to the
+	  tty pgrp.
+
+	* pws: 6239: need space after incrementalappendhistory for
+	  kshoptionprint
+
+	* pws: 6238: Wayne's share_history option set in ksh emulation
+
+	* pws: 6237: window size code upgraded from 3.0.6-pre2, plus
+	  Bart's patch 4447.
+
+	* Wayne: 6236: history changes to improve management of duplicate
+	  lines, incremental history read/write, and sharing history
+
+	* pws: 6235: unset -m shouldn't restore unset parameters;
+	  unsetting a global should remove it from paramtab even inside a
+	  function.
+
+	* pws: 6227: configuration for large file support (from bash
+	  aclocal.m4).
+
+	* pws: 6224: alter 6205 to read chars only when necessary, but
+	  ensure terminal is set appropriately.
+
+	* Wayne: 6220: various compilation warnings
+
+	* Tanaka Akira: 6219: initialize a variable in zle_tricky.c
+
+	* Bart: 6213: race condition in $(...), use waitforpid() instead
+	  of unblocking child (which shouldn't happen until later).
+
+	* pws: 6205: use FIONREAD wherever defined, read chars immediately
+	  into buffer
+
+	* pws: 6202: trivial _correct_filename change, ^Xc -> ^XC
+
+	* Sven: 6197: off by one error parsing assignment in completion
+
+	* Sven: 6195: _expand_word and _correct_word change.
+
+	* Sven: 6194: complete assoc array arguments by default where
+	  necessary
+
+	* pws: 6193: [un]setopt shouldn't complain when setting an
+	  unsettable option to the value it already has
+
+	* Bart: 6188: compinit speedup
+
+	* 3.1.5-pws-17 made available
+
+	* pws: 6180: Completion/Core/compinstall
+
+	* Bart: 6171 as rewritten in 6174: old RedHat Linux doesn't have
+	  normal definitions for poll.
+
+	* Sven: 6167: show unloaded parameters as undefined
+
+	* pws: 6165: globsubst'd foo='~/bin' depended on extendedglob
+	  being set
+
+	* Bart: 6162: autoloadable parameter code links without dynamic
+	  loading
+
+	* Sven: 6153: realparamtab to smooth access to autoloaded parameters
+
+	* Sven: 6152: compstate[vared]
+
+	* Sven: 6150: alwayslastprompt sometimes failed in M-x
+
+	* Sven: 6133: autoloaded parameters
+
+	* Sven: 6132: compctl.mdd
+
+	* Ville Herva: 6131, see 6126: reset tv.tv_sec before select for
+	  Linux
+
+	* Sven: 6129: comments for struct cadata
+
+	* Sven: 6128: completion after an expansion; list after a
+	  non-completion list
+
+	* Sven: 6124: menu completion wasn't consistent between tabs
+
+	* Sven: 6121: try harder with braces after a parameter expansion
+
+	* Sven: 6119: don't insert word separator before ignored suffix
+
+	* pws: 6118: _closequote and _oldlist completers
+
+	* Sven: 6117: position of ignored suffix in inserted match
+
+	* Sven: 6113: compadd -D, nuke element in an array for each failed
+	  match
+
+	* Sven: 6109: completion in parameter assignment should set
+	  context `value'
+
+	* Bart: 6106: short documentation fixes in expn.yo, options.yo,
+	  redirect.yo
+
+	* Sven: 6105: _make patch whitespace
+
+	* Geoff: 6104: multi-line prompt fix (6101 backed off)
+
+	* 3.1.5-pws-16 made available
+
+	* pws: 6101: multi-line prompt ending in '\n' got another newline
+
+	* Tanaka Akira: 6092: _find, bad glob pattern
+
+	* Tanaka Akira: 6085: _make can hang when no [mM]akefile
+
+	* pws: zsh-announce/94: FAQ and FAQ.yo updated
+
+	* Sven: 6079: compwid.yo typo
+
+	* Tanaka Akira: 6078: _find syntax error
+
+	* Sven: 6077: do_single() fix for old completion
+
+	* pws: 6074: zftp function suite moved to Functions/Zftp and
+	  provided with documentation.
+
+	* pws: 6070: ~ in character class in parentheses with extendedglob
+	  failed
+
+	* Sven: 6066: create list of modules built into the base executable
+
+	* Sven: 6062: test whether using the same widget when doing
+	  menucompletion
+
+	* Sven: 6060: don't invalidatelist() in zle_main.c before calling
+	  completion functions
+
+	* Sven: 6058: small changes in _path_files, compinit and
+	  documentation
+
+	* Sven: 6056: compwid.yo
+
+	* pws: 6053: compwid.yo
+
+	* 3.1.5-pws-15 made available
+
+	* Sven: 6031: defcomp -> compdef
+
+	* pws: 6030: compsys.yo
+
+	* Sven: 6026: _path_files slight rewrite for speed
+
+	* Sven: 6021: _path_files expanding path fix
+
+	* pws: 6018: (#l) and friends with a trailing / on the glob
+	  pattern always failed
+
+	* pws: 6016: compinit and _zftp
+
+	* Andrej: 6017 (ex 6014): -i and -s options for _long_options
+
+	* Sven: 6013: pass ignored prefix and suffix in _path_files
+
+	* Sven: 6011: compadd uses first (not last) occurrence of an option
+
+	* Sven: 6010: _match_pattern and _match_test replaced by options
+	  to compadd (and deleted from distribution)
+
+	* Sven: extracted from 6009: chunk for getmatcharr()
+
+	* Sven: 6008: %{ works in completion listings
+
+	* Sven: 6005: Misc/compctl-examples altered for latest (more
+	  consistent) nested parameter expansion rules
+
+	* Bart: 6002, 6003: in ${foo/#bar/thing}, the `#' can appear from
+	  substitution and can be quoted
+
+	* Sven: 5999: ~foo<TAB> completes with /
+
+	* Sven: 5996: compsys.yo, special contexts
+
+	* Sven: 5995: should fix 5969
+
+	* Sven: 5986: compstate[insert]
+
+	* Sven: 5983: documentation for Completion/ system (compsys.1).
+
+	* Sven: 5982: menu behaviour
+
+	* Sven: 5981: bit masks in comp.h
+
+	* Sven: 5972: compconf without arguments lists; _compalso takes
+	  extra arguments
+
+	* Sven: 5971: shell code control over re-using existing completion
+	  lists
+
+	* Sven: 5970: completion fix compilation; #defcomp is now #compdef
+
+	* Sven: 5969: clear to end of display optimization (may need
+	  modifying for some terminals)
+
+	* Sven: 5968: fix brace re-insertion problem in completion
+
+	* pws: 5965: _correct_word
+
+	* Sven: 5960: $PREBUFFER: lines before current $BUFFER
+
+	* Sven: 5959: quoting characters in completion
+
+	* Bruce: 5958: _make
+
+	* Sven: 5955: more compstate choices: list_max, last_prompt, to_end
+
+	* 3.1.5-pws-14 made avaliable
+
+	* pws: unposted: updated .distfiles under Completion
+
+	* Sven: 5947: completion functions fix
+
+	* Sven: 5942: spaces in file names with old completion
+
+	* Sven: 5940: move cursor
+
+	* Sven: 5938, 5937: compset to replace modifying conditions
+
+	* Sven: 5936: replace modifying completion tests with compset
+
+	* pws: 5934: option GLOBAL_RCS_FIRST runs /etc/z* files before
+	  user's files.
+
+	* Sven: 5933: don't complete local parameters; _setopt/_unsetopt
+	  complete all options (code to use currently unset/set options
+	  remains in comments)
+
+	* pws: 5931: more parameter substitution rules
+
+	* Sven: 5928: copy context in zle_tricky
+
+	* Sven: 5926: $HISTNO
+
+	* Sven: 5925: path_expand
+
+	* Sven: 5918: _list completer
+
+	* Sven: 5916: _expand completer
+
+	* pws: 5915: minor type fixes
+
+	* Sven: 5914: _main_complete takes optional completer arguments
+
+	* Sven: 5913: zle -C test
+
+	* Sven: 5912: compiler warnings
+
+	* pws: 5905: _main_complete should at least try to get
+	  _unset_options correct.
+
+	* Sven: 5904: print local for parameters
+
+	* Sven: 5895, 5898, 5906: fix completion prefixes
+
+	* Sven: 5890: _match completer
+
+	* Sven: 5879, 5899: completion documentation
+
+	* Sven: 5872, 5881, 5889: corresponding Completion function rewrite
+
+	* Sven: 5871, 5875: big zle_tricky.c cleanup, with compstate
+	  changes and IFSUFFIX
+
+	* Bart: 5868: expn.yo fixes
+
+	* 3.1.5-pws-13 made available
+
+	* pws: 5863: substitution rules
+
+	* Sven: 5862: _path_files (turning on menu) and _cd (include . in
+	  path)
+
+	* pws: 5854: man page dependencies in Doc/Makefile.in
+
+	* Sven: 5852: warnings about _long_options
+
+	* pws: 5844: don't set errflag if noerrs = 2.
+
+	* Sven: 5831: in subscripts and math environments, the whole
+	  string is always passed down to the function handler.
+
+	* Sven: 5830: in ${#:-stuff}, stuff is treated as a single word
+	  (unless split for some other reason).
+
+	* Sven: 5829: clear the completion list in more zle functions
+
+	* Sven: 5818: parameter name in subscript which looks math-like;
+	  _subscript.
+
+	* Sven: 5811: put back _multi_parts which got left out when it was
+	  moved into Core.
+
+	* Sven: 5804: _pdf
+
+	* Sven: 5800: _path_files; path altered when no possible match
+
+	* pws: 5797: set CLOBBERS_TYPEAHEAD for Irix; old config.guess
+	  change for Reliant UNIX and Apple Rhapsody re-imported from old
+	  config.guess.
+
+	* Sven: 5796: globcomplete shouldn't always turn on menucompletion
+
+	* Sven: 5795: parsing change for assignment and arrays in nested
+	  substitution.
+
+	* Sven (reposted by Bart): 5783: zerr() sets errflag even if
+	  noerrs is set
+
+	* pws: 5780: Completion/Base/_brace_parameter change
+
+	* 3.1.5-pws-12 made available
+
+	* Geoff: 5779: correct mistakes some bozo (guess who) made testing
+	  rlim_t for long long.
+
+	* pws: unposted archive changes: .distfiles in Completion
+	  hierarchy, dunno what these do but it looks better; _comp_parts
+	  is now _sep_parts; moved _long_options into Base and mentioned
+	  it in Completion/README.
+
+	* pws: 5776: untested patch for typeahead problems when reading
+	  multiple lines of input
+
+	* Sven: 5775: correcting completion will not ignore everything the
+	  user has typed; prefix quote fix
+
+	* Sven: 5770: _path_files again
+
+	* Sven: 5766: _path_files closer to compctl/compgen behaviour
+
+	* Sven: 5761: remove unnecessary compiler warnings in compctl.c
+
+	* Sven: 5759: math environment fixes
+
+	* pws: www archive: updated Etc/FAQ finally, keep forgetting
+
+	* Sven: 5758: _path_files accepts -q, -r and -R options
+
+	* Sven: 5757: compconfig
+
+	* Sven: 5756: compstate[force_list]
+
+	* Lehti Rami: 5754: --disable-restricted-r stops the shell
+	  becoming restricted when its name starts with r
+
+	* Sven: zsh-users/2211 (+ p -> s): setopt -m handles underscores
+	  and case sensitivity
+
+	* pws: 5737: ${foo#* } is more efficient in ordinary cases
+
+	* Sven: 5736: completion before = in assignment
+
+	* Sven: 5732: _a2ps, _long_options
+
+	* pws: 5729: _bindkey doc
+
+	* Sven: 5726: zle_tricky.c: ctokenize() fix and parameter completion
+
+	* Will Day: 5724 (+postprocessing, 5741): signames2.awk: match
+	  extra spaces if produced by CPP.
+
+	* Andrej: 5719: _bindkey can use - as anchor for wildcard matching
+
+	* Sven: 5716: zle.h, zle_misc.c, zle_tricky.c: iremovesuffix() can
+	  be told whether to keep a list of matches
+
+	* Sven: 5714: _path_files: failed completions get left alone more
+	  often
+
+	* Sven: 5713: zle_tricky.c, interesting code specimen made extinct
+
+	* Sven: 5712: _path_files, noglobcomplete fix
+
+	* Sven: 5710: zle_tricky.c, completion inside words
+
+	* Sven: 5708: completion manual, -M anchors must be matched
+	  explicitly
+
+	* Sven: 5707: tokenization changes
+
+	* Sven: 5704: _long_options
+
+	* Sven: 5701: _main_complete, _multi_parts, _path_files, a few
+	  cosmetic changes.
+
+	* Sven: 5699: matching prefixes of various sorts
+
+	* Sven: 5698: array indexing in _long_options and _multi_parts
+
+	* Sven: 5696, 5697: "${${path}[1]}" indexes on characters again
+
+	* Sven: 5692: remove compstate[matcher] test from _long_options
+
+	* Sven: 5682: bindkey fix
+
+	* Sven: 5677, 5679: Completion/User/_long_options and consequent
+	  upgrades for Completion/User files which use long GNU-style
+	  options.
+
+	* Sven: 5676: all Completion example functions return a status
+
+	* pws: from autoconf 2.13: new config.guess, too.
+
+	* Sven: 5675: tidying up for zle_tricky.c
+
+	* Sven: 5671: another small parameter fix for multiple braces
+
+	* Sven: 5670: parameter completion fix
+
+	* 3.1.5-pws-11 made available
+
+	* pws: from autoconf 2.13: new config.sub
+
+	* Sven: 5666: calling inststrlen() with a null string
+
+	* Sven: 5665: return values from completion functions
+
+	* Sven: 5663: compctl -i _completion_function
+
+	* Sven: 5662: / following brace parameter
+
+	* Sven: 5659: globcomplete changes
+
+	* Sven: 5651: widespread completion fixes
+
+	* Andrej: 5650: more tricks with _configure
+
+	* Sven: 5647: _multi_parts doesn't replace so many *'s
+
+	* Sven: 5640: _multi_parts, _path_files, _tar
+
+	* Sven: 5637: mustuseheap check in complistflags
+
+	* Sven: 5634: return values for compgen and compadd
+
+	* Sven: 5631: compilation warnings
+
+	* Sven: 5629: approximate correction patches
+
+	* pws: 5628: _builtin, _cd, _most_recent_file
+
+	* Sven: 5624: CCORIG required to be offered original string when
+	  correcting using COMPCORRECT
+
+	* Sven: 5623: -X strings with compadd were mishandled
+
+	* Sven: 5622: zshcompwid manual: clarifications
+
+	* Sven: 5621: manual for nmatches and matcher
+
+	* Sven: 5620: fix for completion inside expansible braces
+
+	* Bart: 5614: Completion/Base/_match_test works out of the box
+
+	* Sven: 5613: copy scalar variable used for compgen -y
+
+	* Sven: 5605: explanation listing fix
+
+	* Sven: 5604: approximate completion.
+
+	* Sven: 5603: compstat[pattern_match]
+
+	* pws: 5602: _tar
+
+	* Sven: 5601: compstate[exact_string] and compstate[total_matchers]
+
+	* Sven: 5599: _comp_parts, _path_files tweaks
+
+	* Sven: 5598: a neater way of handling compadd -p/-P
+
+	* pws; 5597: Use separate file mymods.conf for your own builtin
+	  modules rather than the automatically generated modules-bltin.
+
+	* Matt: 5596: Makefile dependencies for module compilation
+
+	* Sven: 5593: _path_files -w
+
+	* Sven: 5590: compadd -p, -s and -P fixes
+
+	* Sven: 5588: fix _most_recent_file idiocy
+
+	* Sven: 5586: addmatch fix (old completion wasn't working)
+
+	* pws: 5583: post-patch restructuring of _mh, _zftp,
+	  _most_recent_file.
+
+	* Sven: 5582: _path_files will expand /u/ -> /usr/ even if /u
+	  exists if nothing later on would match otherwise (got that?)
+
+	* Sven: 5574, 5578: Completion/README notes
+
+	* Sven: 5571: Functions/Builtins/_cd tests if $cdpath is set
+
+	* Sven: 5566: $foo[(b.<index>.i)<match>] starts searching $foo for
+	  for <match> at <index>
+
+	* Sven: 5565, 5576: $NUMERIC gives the numeric argument in a zle
+	  widget
+
+	* Sven: 5564, 5577, 5579: massive new completion reworking with
+	  $words, $compstate, etc., etc.
+
+	* pws: 5561: attempted (untested) fix for QNX4 compilation;
+	  halloc() is now zhalloc().  (By private email from
+	  probin@qnx.co.uk, it seems the QNX problems are more
+	  considerable with 3.1.5.)
+
+	* Sven: 5560: subscripting fixes in params.c: flags for scalars
+	  and converting integer AA element to string
+
+	* pws: 5559: cd /.. doesn't show .. (except if RFS was detected).
+
+	* Larry P. Schrof: 5550: last -> previous in history documentation
+
+	* pws: 5557: configure.in for making sure signals really are
+	  defined in the file found.  This was in pws-10, but the patch
+	  didn't appear on the list for four days.
+
+	* 3.1.5-pws-10 made available
+
+	* pws: unposted: Functions/Completion moved to Completion;
+	  subdirectories Core, Base, Builtins, User, Commands created;
+	  Completion/README created.
+
+	* Matt: 5553: under _WIN32, .exe suffix is optional for commands
+
+	* Sven: 5548: _path_files, _comp_parts
+
+	* Sven: 5547: group handling -J/-V in compadd
+
+	* pws: 5545: silly set -x mistake
+
+	* Sven: 5544: another completion cleanup
+
+	* Sven: 5543: compadd -X, zshcompwid manual
+
+	* pws: 5538: approximate pattern matching, (#a1)readme etc.
+
+	* pws: 5531: small init fix
+
+	* Sven: 5529: cleanup for Functions/Completion
+
+	* Sven: 5521: improved option handling for _path_files
+
+	* Sven: 5512, 5525: globcomplete fix for new completion
+
+	* Sven: 5511: make sure compctl is available for new completion
+
+	* pws: 5508: init and dump, globbing and printing.
+
+	* pws: unposted, see 5503: remove dynamic=no from configure.in when
+	  underscore is needed.
+
+	* Sven: 5490: unset test for AA elements when substituting
+
+	* Sven: 5489: control for matching in _path_files and _comp_parts
+
+	* Sven: 5483: completeinword fixes
+
+	* Sven: 5476: quoting of tildes in Functions/Completion/_path_files
+	  
+	* Sven: 5471: range code knows not to handle associative arrays
+
+	* Sven: 5470: new completion conditions didn't handle untokenization
+	  consistently.
+
+	* Sven: 5469: init fix and Functions/Completion/_comp_parts
+
+	* Sven: 5467: expn manual typo
+
+	* Sven: 5466: compwid manual for -after and -between
+
+	* Sven: 5455: keep track of which matcher specification to use
+
+	* Matt: 5330: I've put this back the way it original was.  I hate
+	  sed almost as much as awk.
+
+	* Martin Buchholz: 5448: libc.h can't be included on Debian Linux,
+	  so only include it on NeXT where it's necessary.
+
+	* 3.1.5-pws-9 made available
+
+	* pws: unposted (but see 5440): zftp changes: more return 6's,
+	  functions now do auto-open and avoid subshells.
+
+	* pws: 5436: set -x for function calls and ((...)).
+
+	* Sven: 5430: rewrite Functions/Completions with simplified syntax
+	  (no #array type completions).
+
+	* Sven: 5429: $CONTEXT strings
+
+	* pws: 5425: fix pattern matching for new completion
+
+	* Sven: 5424: addmatches fix when not doing matching
+
+	* Sven: 5423: compadd accepts either - or -- to end options
+
+	* Sven: 5422: braces in completions were not tokenized; array
+	  parameters wereused uncopied
+
+	* pws: 5421: setting same element of assoc array in full array
+	  assignment crashed
+
+	* Sven: 5418: small addmatches fixes
+
+	* Sven: 5417: multiple subscripts with undefined array
+
+	* Sven: 5415: anchors in matchers shouldn't match variable part of
+	  completion
+
+	* Sven: 5412: better matcher control
+
+	* Helmut Jarausch/pws: 5410: IRIX 6.5 problems in Etc/MACHINES
+
+	* pws: 5408: set -x output for [[ ... ]]
+
+	* pws: 5403: magicequalsubst now affects all ...=~...:~
+
+	* Sven: 5401: files -> __files
+
+	* Sven: 5400, 5402: print needs - in dump; auto-dump and use
+	  $COMPDUMP file
+
+	* Sven: 5399, 5407: do_ambiguous overhaul
+
+	* pws: 5398: fixlet for __path_files
+
+	* pws: 5393: dump new completion status for faster init
+
+	* Sven: 5384, 5397: manual for new completion so far
+
+	* Andrej: 5377: Reliant UNIX configuration
+
+	* Oliver: 5374: compctl -T doc for ~dirs
+
+	* Oliver: 5372: change of mailing list host
+
+	* Bart: 5367: CVS ignores version.h
+
+	* 3.1.5-pws-8 made available
+
+	* pws: 5365: make dependencies for main.o, Makemod, zshpaths.h
+
+	* pws: 5364: 5281 now works
+
+	* pws: Misc/Completion now Functions/Completion, some new
+	  new-style completions
+
+	* pws: 5362: #key-* completions allow >= 0 key bindings
+
+	* Sven: 5355: compadd -R function for suffix removal
+
+	* Sven: 5354: redisplaying completion lists, don't show if
+	  completion failed
+
+	* Sven: 5352: new fignore handling
+
+	* pws/Bart: 5349, 5361: "$foo[@]" didn't get removed if $foo
+	  wasn't set
+
+	* pws/Sven: 5341, 5351: completion init and __normal
+
+	* Sven: 5342, 5343: ignoring ignored prefix in new conditions
+
+	* Sven: 5341: modularise new completion shell code
+
+	* Sven: 5335: printing zle condition codes
+
+	* pws: 5332: emulate -L
+
+	* Sweth/Bart/pws: zsh-users/2121: Functions/allopt with the odd
+	  emulate and local added
+
+	* pws/Matt: 5326, 5329, 5330: signames.c generation
+
+	* pws: 5321: compctl -LM
+
+	* Sven: 5320: keys available in zle widgets
+
+	* Sven: 5316: compctl matcher users reference counts
+
+	* Matt: 5311: CHAR(+) -> CHAR(43) in zmacros
+
+	* Bart: 5305: trashzle() crashed shell with loading dynamic but
+	  zle builtin
+
+	* Bart: 5299: PWD, OLDPWD export confusion
+
+	* Bart: 5297: local variables and $argv doc
+
+	* Geoff: 5295: no ld -g on NetBSD
+
+	* 3.1.5-pws-7 made available
+
+	* pws; 5281: interrupts in getquery() weren't handled gracefully
+
+	* Sven: 5266: get matcher number in new completion functions
+
+	* Sven: 5265, 5284: rewrite of $foo:q and doc
+
+	* Sven: 5262: compctl -M, REC_EXACT fixes
+
+	* Sven: 5261, 5268: GLOB_COMPLETE docs
+
+	* Bart: 5260: new mailing lists in Meta-FAQ
+
+	* Bart: 5258: parameter scoping docs
+
+	* pws: 5247: typeset -T fix
+
+	* pws: Etc/MACHINES: Linux Alpha with egcs
+
+	* pws: 5233: .zlogout doc
+
+	* pws/Sven: 5229, 5234, 5235, 5269: bashautolist option
+
+	* Sven: 5120: use ${foo:q} for quoting completion prefix/suffix
+
+	* Sven: 5208: preliminary version of ${foo:q}
+
+	* Sven: 5207: completion in conditions
+
+	* Sven: 5206: completion in arrays
+
+	* Sven: 5203: o -> f, O -> o, O = ^o
+
+	* Sven: 5201: zle commands erase listing when minibuffer used
+
+	* pws: 5185, 5198: compctl documentation tidy-up
+
+	* Sven: 5183, 5199, 5200: ${(P)...} flag
+
+	* Sven: 5178: fix for command completion and pattern completions
+
+	* Bart: 5174: unset assoc array elements
+
+	* Sven: 5145, 5204: compadd -m, -F, -r
+
+	* Sven: 5144: partial word completion fix
+
+	* Matt: 5133: cygwin needs native getcwd()
+
+	* Matt Armstrong: 5132, 5151: makepro.awk can spit out
+	  preprocessor lines, move init.pro inclusion
+
+	* Bart: 5129: vared assoc array and elements thereof
+
+	* Bart: 4965, missing hunk: unset assoc array when assigned as
+	  scalar
+
+	* pws: 5054: zls
+
+	* 3.1.5-pws-6 made available
+
+	* Drazen Kacar/pws: 5118: unlock terminal device on Solaris
+
+	* pws: 5111: unsetting special zle variables
+
+	* Sven: 5107: glob qualifier o for modes
+
+	* pws: 5105: remove old zle -C, zle -C does new completion
+	
+	* Sven: 5104: zle and widget information via variables
+
+	* Drazen Kacar/pws/Bart: 5103, 5113: terminal bug on Solaris with
+	  Openwindows
+
+	* Sven: 5102: glob qualifiers doc
+
+	* pws: 5094, 5120: typeset -T MYPATH mypath; MYPATH=(foo),
+	  mypath=foo fix; PATH=(foo) bug
+
+	* Sven: 5092: extra completion context
+
+	* Sven: 5060: completion in brace expansion
+
+	* Sven: 5059, 5065, 5085: compcall, compctl -K ' func', avoid
+	  recursion, fix dynamic loading
+
+	* pws: 5047: make install doesn't make install.info
+
+	* Phil/Bart: 5032, 5037: zless with localoptions added
+
+	* Sven: 5022, 5045, 5078: ${(t)param} and nounset behaviour
+
+	* Andrej: 5016: insert zsh.info into dir when installing
+
+	* pws: new mirror site ftp://ftp.win.ne.jp/pub/shell/zsh/
+
+	* Sven: 4986, 4988: new-style completion after redirection
+
+	* Sven: 4981: fix completion whitespace for copy-previous-word
+
+	* Sven: 4979, 4987: new glob modifiers for sort order and
+	  selecting items from list
+
+	* Sven: 4976: compadd and new-completion-examples
+
+	* Sven: 4975, 5007: comptl -M matches with *'s
+
+	* Sven: 4974: compctl list with single string
+
+	* Andrej: 5021: configuration on Reliant UNIX
+
+	* Bart: 4965: add-on
+
+	* Sven: 4957: completion after redirection
+
+	* Made available as 3.1.5-pws-5; top level directory now
+	  zsh-3.1.5-pws-5
+
+	* Helmut Jarausch: 4947: part of patch missed
+
+	* Sven: 4850, 4881, 4941, 4942, 4943, 4944, 4946, 4949, 4950,
+	  4945: New completion system
+
+	* Sven: 4940: compctl -t (minor incompatibility)
+
+	* pws: 4939: configure checks for tgetent() accepts null but then
+	  tgetstr() dumps core
+
+	* pws: 4931: compiler warnings
+
+	* Sven: 4930: completion after reserved words
+
+	* pws/Bart: 4923, 4924: findcmd() memory leak and comment
+
+	* pws: 4912: Etc/MACHINES
+
+	* pws: 4902: typeset neatness, -a, -m
+
+	* Bart: 4893: setting assoc array elements inside a substitution
+
+	* Andrej Borsenkow + pws: 4888: zftp shouldn't dup sockets until
+	  connected
+
+	* Oliver Kiddle: 4887: configure
+
+	* Sven: 4880: conditions from module again
+
+	* Sven: 4879: group completion
+
+	* Sven: 4878: accept-and-menu-complete
+
+	* Bart: 4874: array slices
+
+	* Geoff: 4855: refresh line the same length as terminal width
+
+	* pws: 4852: zftp test subcommand
+
+	* Bart: 4851: sethparam(), part got missed
+
+	* 3.1.5-pws-4 made available
+
+	* Sven: 4845: isident()
+
+	* Sven: 4837, 4842: more for loadable conditions
+
+	* Sven: 4828: ignored character
+
+	* Bart/Sven: 4826, 4831, 4836: assoc array fixes
+
+	* Gene Cohler + pws: 4824, 4833, 4843: dynamical loading under
+	  HPUX
+
+	* Sven: 4821: network byte order in zftp
+
+	* Bart: 4817: parameter documentation
+
+	* Sven: 4806, 4815, 4820, 4822, 4830: be careful when unloading
+	  modules which may have side effects
+
+	* pws: 4805: define INADDR_NONE in zftp if not defined
+
+	* pws: 4801: compilation without HAVE_GETPWUID
+
+	* Bart: 4792: Handle --program-{suf,pre}fix in configure
+
+	* Bart: 4791: don't hash PWD after all
+
+	* Bart: 4789, 4794, 4795: sethparam(), setsparam; allow assoc
+	  array assignment ${(AA)=assoc::=key1 val1 ...}
+
+	* Bart: 4788: some missing patches put back
+
+	* Phil: 4784: unused variable j in glob.c
+
+	* Phil: 4783: wtmp is in /var/log on Linux
+
+	* pws: 4779: compiling statically linked
+
+	* pws: version 3.1.5-pws-3 made available
+
+	* Sven: 4767: completion listing fix
+
+	* Bart: 4763, 4766, 4764: associative arrays using subscripting
+	  flags and typeset output
+
+	* Bart: 4762: use of conddef without dynamic loading
+
+	* pws: 4761: zftp module
+
+	* Phil: 4737: typeset -a docs
+
+	* pws: 4736, 4754: ${foo/orig/new} subst as in bash; optimize
+	  pattern matching in strings
+	
+	* Phil Pennock: 4727: associative arrays in stat builtin
+
+	* Sven: 4716, 4732, 4734, 4742, 4769:  allow modules for
+	  conditions and wrappers around functions
+
+	* Sven: 4700: heap memory fixes suggested by Phil Pennock
+
+	* Sven: 4698, 4707: ignore completions if cursor not in
+	  completable part of word
+
+	* Sven: 4697: zle_tricky.c
+
+	* pws: 4693: case-indendent globbing fix
+
+	* Bart: 4678: viforwardword
+
+	* pws: don't use vifirstnonblank()in vioperswapcase()
+
+	* Bart: 4674: scanmatchtable()
+
+	* Bart: 4482: cdmatch2
+
+	* Bart: 4644: delimiters in parameter substitution flags
+
+	* Bart: 4624: don't be too clever with optimizing when doing ***
+
+	* pws: 4612: 8 bit character input problem if char was signed
+
+	* Bart: 4606: error messages from parameters
+
+	* pws: 4601: rewrite prompt truncation in more predictable,
+	  delimitable way
+
+	* Bart: 4599, 4602, 4608, 4641, 4653, 4654: associative arrays
+
+	* pws: 4596: allow PWD to be hashed on explicit user request
+
+	* pws: 4595: globbing fix for problem which showed up in `case'
+
+	* Wilfredo Sanchez: 4594: fix configure problems
+
+	* pws: 4591: test line length in prompt e.g. %(40l.yes.no)
+
+	* Bart: 4589: PWD and OLDPWD fix
+
+	* Bart: 4472: doc fixes
+
+	* Bart: 4471: fixes for shell functions
+
+	* Bart: line missed in zle_tricky.c when patching
+
+	* Bart: 4589: chpwd
+
+	* pws: lete2ctl update
+
+	* pws: fixsuffix() missed in delcharorlist() when patching
+
+	* Bart: 4574: doc fix
+
+	* Bart: 4570: flags to allow zle command not to interrupt
+	  cumulative effects, deltochar
+
+	* pws: 4564: fix completion suffix for yank
+
+	* pws: 4533: ~PWD should not be displayed as such
+
+	* pws: 4513, 4552: case-insensitive globbing (#i)
+
+	* Sven: 4509, 4510, 4526, 4527, 4534, 4557: alternative matches in
+	  completion (compctl -t), mapping between characters on line and
+	  in matches (compctl -M)
+
+	* pws: 4477: change function names to avoid dynamic loading
+	  clashes
+
+	* Bart: 4473, 4475, 4476: collected minor fixes since 3.1.5
+
+	* Zoli: 3933: AIX dynamic patch
+
 Thu Oct 29 21:51:10 1998  Andrew Main  <zefram@zsh.org>
 
 	* Config/version.mk: Version 3.1.5.
diff --git a/Completion/.distfiles b/Completion/.distfiles
index c50107c61..e85e122ef 100644
--- a/Completion/.distfiles
+++ b/Completion/.distfiles
@@ -1,3 +1,3 @@
 DISTFILES_SRC='
-    .distfiles README
+    .distfiles README Makefile.in
 '
diff --git a/Completion/Base/.distfiles b/Completion/Base/.distfiles
index 6c537c26b..ef1e9df73 100644
--- a/Completion/Base/.distfiles
+++ b/Completion/Base/.distfiles
@@ -1,6 +1,6 @@
 DISTFILES_SRC='
     .distfiles 
-    _brace_parameter _command_names _condition _default _equal
+    _brace_parameter _command_names _condition _default _equal _first
     _long_options _math _parameter _precommand _redirect _subscript
     _tilde _vars 
 '
diff --git a/Completion/Base/_brace_parameter b/Completion/Base/_brace_parameter
index d45e317be..f688e175a 100644
--- a/Completion/Base/_brace_parameter
+++ b/Completion/Base/_brace_parameter
@@ -1,9 +1,19 @@
 #compdef -brace-parameter-
 
+setopt localoptions extendedglob
+
+local lp ls n q suf=''
+
 if [[ "$SUFFIX" = *\}* ]]; then
   ISUFFIX="${SUFFIX#*\}}$ISUFFIX"
   SUFFIX="${SUFFIX%%\}*}"
-  _parameters -S '} ' -r '-:?#%+=[/'
 else
-  _parameters -S '} ' -r '-:?#%+=[/'
+  suf='} '
 fi
+
+lp="$LBUFFER[1,-${#PREFIX}-1]"
+ls="$RBUFFER[${#SUFFIX}+1,-1]"
+n=${(M)#ls##\"#}
+q=${(M)lp%%\"#}
+
+_parameters -s "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/'
diff --git a/Completion/Base/_first b/Completion/Base/_first
new file mode 100644
index 000000000..d9e7ee82c
--- /dev/null
+++ b/Completion/Base/_first
@@ -0,0 +1,63 @@
+#compdef -first-
+
+# This function is called at the very beginning before any other
+# function for a specific context.
+#
+# This just gives some examples of things you might want to do here.
+#
+#
+# If you use the vared builtin and want completion in there to act the 
+# way completion on the right hand side of assignments is done, add
+# (or un-comment) this code:
+#
+#     if [[ -n $compstate[vared] ]]; then
+#       if [[ $compstate[vared] = *\[* ]]; then
+#         # vared on an array-element
+#         compstate[parameter]=${compstate[vared]%%\[*}
+#         compstate[context]=value
+#       else
+#         # vared on a parameter, let's see if it is an array
+#         compstate[parameter]=$compstate[vared]
+#         if [[ ${(tP)compstate[vared]} = *(array|assoc)* ]]; then
+#           compstate[context]=array_value
+#         else
+#           compstate[context]=value
+#         fi
+#       fi
+#       return
+#     fi
+#
+#
+#
+# Other things you can do here is to complete different things if the
+# word on the line matches a certain pattern. This example allows
+# completion of words from the history by adding two commas at the end 
+# and hitting TAB.
+#
+#     if [[ "$PREFIX" = *,, ]]; then
+#       local max i=1
+#     
+#       PREFIX="$PREFIX[1,-2]"
+#       # If a numeric prefix is given, we use it as the number of
+#       # lines (multiplied by ten below) in the history to search.
+#       if [[ NUMERIC -gt 1 ]]; then
+#         max=$NUMERIC
+#         NUMERIC=1
+#       else
+#         # The default is to search the last 100 lines.
+#         max=10
+#       fi
+#       # We first search in the last ten lines, then in the last
+#       # twenty lines, and so on...
+#       while [[ i -le max ]]; do
+#         if compgen -X "%Bhistory ($n):%b" -Q -H $(( i*10 )) ''; then
+#           # We have found at least one matching word, so we switch
+#           # on menu-completion and make sure that no other
+#           # completion function is called by setting _comp_skip.
+#           compstate[insert]=menu
+#           _comp_skip=1
+#           return
+#         fi
+#         (( i++ ))
+#       done
+#     fi
diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options
index 6288fc3a0..a50edee1c 100644
--- a/Completion/Base/_long_options
+++ b/Completion/Base/_long_options
@@ -7,11 +7,11 @@
 # a command that does not support this option.
 #
 # For options that get an argument after a `=', the function also tries
-# to automatically find out what should be complete as the argument.
+# to automatically find out what should be completed as the argument.
 # The possible completions for option-arguments can be described with
 # the arguments to this function. This is done by giving pairs of
 # patterns and actions as consecutive arguments. The actions specify
-# what should be done to complete arguemts of those options that match 
+# what should be done to complete arguments of those options that match 
 # the pattern. The action may be a list of words in brackets or in
 # parentheses, separated by spaces. A list in brackets denotes
 # possible values for an optional argument, a list in parentheses
@@ -27,18 +27,18 @@
 # This makes `yes' and `no' be completed as the argument of options
 # whose description ends in a star, file names for options that
 # contain the substring `=FILE' in the description, and paths for
-# options whose description contains `=DIR'. Note the last two
+# options whose description contains `=DIR'. Note that the last two
 # patterns are not needed since this function always completes files
 # for option descriptions containing `=FILE' and paths for option
 # descriptions that contain `=DIR' or `=PATH'. These builtin patterns
 # can be overridden by patterns given as arguments, though.
 # 
-# This function accepts following options:
+# This function accepts the following options:
 #
 # -t   do completion only on words starting with two hyphens
 #
 # -i   list of patterns. Options, matching these patterns, are ignored.
-#      The list may be given as array name or as literal list in braces.
+#      The list may be given as a array name or as a literal list in braces.
 #      E.g. _long_options -i '(--(enable|disable)-FEATURE*)' will ignore
 #      --enable-FEATURE, that is listed in configure help output
 #
diff --git a/Completion/Core/.distfiles b/Completion/Core/.distfiles
index 9a9e87d7c..c9362dccb 100644
--- a/Completion/Core/.distfiles
+++ b/Completion/Core/.distfiles
@@ -1,7 +1,8 @@
 DISTFILES_SRC='
     .distfiles
-    _approximate _closequotes _compalso _complete _correct _expand _files
-    _list _main_complete _match _menu _multi_parts _normal _oldlist _options
-    _parameters _path_files _sep_parts _set_options _unset_options
+    _approximate _compalso _complete _correct _expand
+    _files _list _main_complete _match _menu _multi_parts
+    _normal _oldlist _options _parameters _path_files
+    _sep_parts _set_options _unset_options
     compdump compinit compinstall
 '
diff --git a/Completion/Core/_approximate b/Completion/Core/_approximate
index 1b40f7cbf..c63416901 100644
--- a/Completion/Core/_approximate
+++ b/Completion/Core/_approximate
@@ -1,9 +1,9 @@
 #autoload
 
 # This code will try to correct the string on the line based on the
-# strings generated for the context if `compconfig[correct]' is set.
-# These corrected strings will be shown in a list and one can
-# cycle through them as in a menucompletion or get the corrected prefix.
+# strings generated for the context. These corrected strings will be
+# shown in a list and one can cycle through them as in a menucompletion
+# or get the corrected prefix.
 #
 # Supported configuration keys:
 #
@@ -64,7 +64,7 @@
 local _comp_correct _correct_prompt comax
 local cfgacc cfgorig cfgps cfgins
 
-# Only if all global matchers hav been tried.
+# Only if all global matchers have been tried.
 
 [[ compstate[matcher] -ne compstate[total_matchers] ]] && return 1
 
@@ -153,7 +153,7 @@ compgen() {
 _comp_correct=1
 compstate[matcher]=-1
 
-_correct_prompt="${cfgps//\%e/1}"
+_correct_prompt="${cfgps//\\%e/1}"
 
 # We also need to set `extendedglob' and make the completion
 # code behave as if globcomplete were set.
@@ -188,7 +188,7 @@ while [[ _comp_correct -le comax ]]; do
   [[ "${#:-$PREFIX$SUFFIX}" -le _comp_correct+1 ]] && break
   (( _comp_correct++ ))
 
-  _correct_prompt="${cfgps//\%e/$_comp_correct}"
+  _correct_prompt="${cfgps//\\%e/$_comp_correct}"
 done
 
 compstate[matcher]="$compstate[total_matchers]"
diff --git a/Completion/Core/_complete b/Completion/Core/_complete
index 0f4d5ff4b..86ccc8c67 100644
--- a/Completion/Core/_complete
+++ b/Completion/Core/_complete
@@ -6,6 +6,15 @@
 
 local comp name
 
+# If we have a user-supplied context name, use only that.
+
+if [[ -n "$compcontext" ]]; then
+  comp="$_comps[$compcontext]"
+  [[ -z "$comp" ]] || "$comp"
+
+  return
+fi
+
 # An entry for `-first-' is the replacement for `compctl -T'
 # Completion functions may set `_compskip' to any value to make the 
 # main loops stop calling other completion functions.
@@ -20,6 +29,7 @@ if [[ ! -z "$comp" ]]; then
   fi
 fi
 
+
 # For arguments and command names we use the `_normal' function.
 
 if [[ "$compstate[context]" = command ]]; then
diff --git a/Completion/Core/_correct b/Completion/Core/_correct
index 35ab01cf1..c9c3d999c 100644
--- a/Completion/Core/_correct
+++ b/Completion/Core/_correct
@@ -1,8 +1,8 @@
 #autoload
 
-# This is mainly a wrapper around the more general `_approximate.
+# This is mainly a wrapper around the more general `_approximate'.
 # By setting `compstate[pattern_match]' to something unequal to `*' and
-# then calling `_approximate, we get only corrections, not all strings
+# then calling `_approximate', we get only corrections, not all strings
 # with the corrected prefix and something after it.
 #
 # Supported configuration keys are the same as for `_approximate', only
diff --git a/Completion/Core/_expand b/Completion/Core/_expand
index 9172b6cbf..aca3839d4 100644
--- a/Completion/Core/_expand
+++ b/Completion/Core/_expand
@@ -132,7 +132,7 @@ else
   if [[ -z "$compconfig[expand_prompt]" ]]; then
     compadd -UQ $group _expand - "$exp[@]"
   else
-    compadd -UQ -X "${compconfig[expand_prompt]//\%o/$word}" \
+    compadd -UQ -X "${compconfig[expand_prompt]//\\%o/$word}" \
             $group _expand - "$exp[@]"
   fi
   [[ "$compconfig[expand_menu]" != *last* &&
diff --git a/Completion/Core/_files b/Completion/Core/_files
index 506ddbc8e..b6349a8c5 100644
--- a/Completion/Core/_files
+++ b/Completion/Core/_files
@@ -1,7 +1,7 @@
 #autoload
 
 # Utility function for completing files of a given type or any file.
-# In many cases you will want to call this one instead of _path_files().
+# In many cases you will want to call this one instead of `_path_files'.
 
 local nm=$compstate[nmatches] ret=1
 
@@ -12,9 +12,9 @@ if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then
 
   # We didn't get any matches for those types of files described by
   # the `-g' or `-/' option. Now we try it again accepting all files.
-  # First we get those options that we have to use even if then. If
-  # we find out that the `-f' option was given, we already accepted
-  # all files and give up immediatly.
+  # First we get those options that we have to use even then. If we
+  # find out that the `-f' option was given, we already accepted all
+  # files and give up immediatly.
 
   opts=()
   while getopts "P:S:W:F:J:V:X:f/g:" opt; do
diff --git a/Completion/Core/_list b/Completion/Core/_list
index 099c6bc7b..0d5651c23 100644
--- a/Completion/Core/_list
+++ b/Completion/Core/_list
@@ -1,8 +1,8 @@
 #autoload
 
 # This completer function makes the other completer functions used
-# insert possible completions only after once the list has been
-# shown.
+# insert possible completions only after the list has been shown at
+# least once.
 #
 # Configuration keys:
 #
diff --git a/Completion/Core/_normal b/Completion/Core/_normal
index 98337eae5..ed7243bb1 100644
--- a/Completion/Core/_normal
+++ b/Completion/Core/_normal
@@ -3,7 +3,7 @@
 local comp command cmd1 cmd2 pat val name i ret=1
 
 # Completing in command position? If not we set up `cmd1' and `cmd2' as
-# two strings we have search in the completion definition arrays (e.g.
+# two strings we have to search in the completion definition arrays (e.g.
 # a path and the last path name component).
 
 command="$words[1]"
diff --git a/Completion/Core/_parameters b/Completion/Core/_parameters
index 0e8c548f7..d9d8a38b2 100644
--- a/Completion/Core/_parameters
+++ b/Completion/Core/_parameters
@@ -1,8 +1,7 @@
 #autoload
 
 # This should be used to complete parameter names if you need some of the
-# extra options of compadd. It first tries to complete only non-local
-# parameters. All arguments are given to compadd.
+# extra options of compadd. It completes only non-local parameters. All
+# arguments are given to compadd.
 
-compadd "$@" - "${(@)${(@)${(@)${(@f)$(typeset)}:#*local *\=*}%%\=*}##* }" ||
-    compadd "$@" - "${(@)${(@)${(@f)$(typeset)}%%\=*}##* }"
+compadd "$@" - "${(@)${(@)${(@)${(@f)$(typeset)}:#*local *\=*}%%\=*}##* }"
diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts
index b906a3042..6f2595120 100644
--- a/Completion/Core/_sep_parts
+++ b/Completion/Core/_sep_parts
@@ -9,7 +9,7 @@
 #
 #  _sep_parts '(foo bar)' @ hosts
 #
-# This will make this function complete the strings `foo' and `bar'
+# This will make this function complete the strings `foo' and `bar'.
 # If the string on the line contains a `@', the substring after it
 # will be completed from the array `hosts'. Of course more arrays
 # may be given, each preceded by another separator string.
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index 77f918502..af2467bec 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -2,7 +2,7 @@
 # functions and aliases. Everything else is split into different files that
 # will automatically be made autoloaded (see the end of this file).
 # The names of the files that will be considered for autoloading have to
-# start with an underscores (like `_setopt).
+# start with an underscores (like `_setopt').
 # The first line of these files will be read and has to say what should be
 # done with its contents:
 #
@@ -50,11 +50,11 @@
 _i_fdir=''
 _i_dumpfile=''
 _i_autodump=0
-while [[ $1 = -[df] ]]; do
+while [[ $# -gt 0 && $1 = -[df] ]]; do
   if [[ "$1" = -d ]]; then
     _i_autodump=1
     shift
-    if [[ -n "$1" && "$1" != -[df] ]]; then
+    if [[ $# -gt 0 && "$1" != -[df] ]]; then
       _i_dumpfile="$1"
       shift
     fi
@@ -91,13 +91,31 @@ elif [[ -n $_i_fdir ]]; then
   # We were told what directory to use.
   compconfig[dumpfile]="$_i_fdir/compinit.dump"
 else
-  # Now we're stuck, but we'd better do something.
-  compconfig[dumpfile]="$HOME/.compinit.dump"
+  compconfig[dumpfile]=''
 fi
 
-compconfig[correct_accept]=2n
-compconfig[correct_prompt]='correct to:'
-compconfig[completer]=_complete
+if [[ -n $compconfig[dumpfile] ]]; then
+  # Check the file is writeable.  If it doesn't exist, the
+  # only safe way is to try and create it.
+  if [[ -f $compconfig[dumpfile] ]]; then
+    [[ -w $compconfig[dumpfile] ]] || compconfig[dumpfile]=''
+  elif touch $compconfig[dumpfile] >& /dev/null; then
+    rm -f $compconfig[dumpfile]
+  else
+    compconfig[dumpfile]=''
+  fi
+fi
+
+if [[ -z $compconfig[dumpfile] ]]; then
+  # If no dumpfile given, or it was not writeable, then use
+  # user's ZDOTDIR.
+  compconfig[dumpfile]="${ZDOTDIR:-$HOME}/.zcompdump"
+fi
+
+(( ${+compconfig[correct_accept]} )) || compconfig[correct_accept]=2n
+(( ${+compconfig[correct_prompt]} )) ||
+  compconfig[correct_prompt]='correct to:'
+(( ${+compconfig[completer]} )) || compconfig[completer]=_complete
 
 # This function is used to register or delete completion functions. For
 # registering completion functions, it is invoked with the name of the
diff --git a/Completion/Makefile.in b/Completion/Makefile.in
new file mode 100644
index 000000000..8b7776a7f
--- /dev/null
+++ b/Completion/Makefile.in
@@ -0,0 +1,86 @@
+#
+# Makefile for Completion subdirectory
+#
+# Copyright (c) 1999 Peter Stephensons
+# All rights reserved.
+#
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and to distribute modified versions of this software for any
+# purpose, provided that the above copyright notice and the following
+# two paragraphs appear in all copies of this software.
+#
+# In no event shall Peter Stephenson or the Zsh Development Group be liable
+# to any party for direct, indirect, special, incidental, or consequential
+# damages arising out of the use of this software and its documentation,
+# even if Peter Stephenson and the Zsh Development Group have been advised of
+# the possibility of such damage.
+#
+# Peter Stephenson and the Zsh Development Group specifically disclaim any
+# warranties, including, but not limited to, the implied warranties of
+# merchantability and fitness for a particular purpose.  The software
+# provided hereunder is on an "as is" basis, and Peter Stephenson and the
+# Zsh Development Group have no obligation to provide maintenance,
+# support, updates, enhancements, or modifications.
+#
+
+subdir = Completion
+dir_top = ..
+SUBDIRS =
+
+@VERSION_MK@
+
+# source/build directories
+VPATH           = @srcdir@
+sdir            = @srcdir@
+sdir_top        = @top_srcdir@
+INSTALL         = @INSTALL@
+
+@DEFS_MK@
+
+# ========== DEPENDENCIES FOR BUILDING ==========
+
+all:
+
+# ========== DEPENDENCIES FOR INSTALLING ==========
+
+install: install.fns
+
+uninstall: uninstall.fns
+
+# install functions, including those in subdirectories, creating
+# install directory if necessary
+install.fns:
+	if test x$(fndir) != x && test x$(fndir) != xno; then \
+	  $(sdir_top)/mkinstalldirs $(fndir) || exit 1; \
+	  for file in $(FUNCTIONS_INSTALL); do \
+	    if test -f $$file; then \
+	      $(INSTALL_DATA) $$file $(fndir) || exit 1; \
+	    fi; \
+	  done; \
+	fi; \
+	exit 0
+
+uninstall.fns:
+	if test x$(fndir) != x && test x$(fndir) != xno; then \
+	  for file in $(FUNCTIONS_INSTALL); do \
+	    if test -f $$file; then \
+	      rm -f "$(fndir)/`echo $$file | sed -e 's%^.*/%%'`"; \
+	    fi; \
+	  done; \
+	fi; \
+	exit 0
+
+# ========== DEPENDENCIES FOR CLEANUP ==========
+
+@CLEAN_MK@
+
+mostlyclean-here:
+
+distclean-here:
+
+realclean-here:
+
+# ========== DEPENDENCIES FOR MAINTENANCE ==========
+
+@CONFIG_MK@
diff --git a/Completion/User/_make b/Completion/User/_make
index a30ca4b7a..4770c0d7a 100644
--- a/Completion/User/_make
+++ b/Completion/User/_make
@@ -1,3 +1,4 @@
 #compdef make gmake pmake
 
-compgen -s "\$(awk '/^[a-zA-Z0-9][^\/ 	]+:/ {print \$1}' FS=: [mM]akefile /dev/null)"
+compgen -s "\$(awk '/^[a-zA-Z0-9][^\/ 	]+:/ {print \$1}' FS=: [mM]akefile /dev/null)" ||
+_files
diff --git a/Completion/User/_mh b/Completion/User/_mh
index c2801b896..e228d31b0 100644
--- a/Completion/User/_mh
+++ b/Completion/User/_mh
@@ -57,7 +57,7 @@ else
   # Generate sequences.
   local foldnam folddir f ret
 
-  for f in $argv; do
+  for f in $words; do
     [[ $f = [@+]* ]] && foldnam=$f
   done
   if [[ $foldnam = '+'* ]]; then
diff --git a/Config/.distfiles b/Config/.distfiles
index eb59d5ee3..cedbd27cf 100644
--- a/Config/.distfiles
+++ b/Config/.distfiles
@@ -1,4 +1,4 @@
 DISTFILES_SRC='
-    .distfiles
+    .distfiles .cvsignore
     clean.mk config.mk defs.mk.in version.mk
 '
diff --git a/Config/config.mk b/Config/config.mk
index dd91476d0..f997bf478 100644
--- a/Config/config.mk
+++ b/Config/config.mk
@@ -25,7 +25,7 @@
 #
 
 config: Makefile
-	@subdir='$(SUBDIRS)'; for subdir in $$subdirs; do \
+	@subdirs='$(SUBDIRS)'; for subdir in $$subdirs; do \
 	  (cd $$subdir && $(MAKE) $(MAKEDEFS) $@) || exit 1; \
 	done
 
diff --git a/Config/defs.mk.in b/Config/defs.mk.in
index 3394123d5..27c9aea99 100644
--- a/Config/defs.mk.in
+++ b/Config/defs.mk.in
@@ -36,6 +36,7 @@ libdir          = @libdir@
 MODDIR          = $(libdir)/zsh/$(VERSION)
 infodir         = @infodir@
 mandir          = @mandir@
+fndir           = @fndir@
 
 # compilation
 CC              = @CC@
@@ -65,6 +66,9 @@ YODL2HTML       = $(YODL)2html
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_DATA    = @INSTALL_DATA@
 
+# variables used in determining what to install
+FUNCTIONS_INSTALL = @FUNCTIONS_INSTALL@
+
 # flags passed to recursive makes in subdirectories
 MAKEDEFS = \
 prefix='$(prefix)' exec_prefix='$(exec_prefix)' bindir='$(bindir)' \
@@ -74,7 +78,8 @@ LDFLAGS='$(LDFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' \
 DLCFLAGS='$(DLCFLAGS)' DLLDFLAGS='$(DLLDFLAGS)' \
 LIBLDFLAGS='$(LIBLDFLAGS)' EXELDFLAGS='$(EXELDFLAGS)' \
 LIBS='$(LIBS)' DL_EXT='$(DL_EXT)' DLLD='$(DLLD)' \
-AWK='$(AWK)' YODL='$(YODL)' YODL2TXT='$(YODL2TXT)' YODL2HTML='$(YODL2HTML)'
+AWK='$(AWK)' YODL='$(YODL)' YODL2TXT='$(YODL2TXT)' YODL2HTML='$(YODL2HTML)' \
+FUNCTIONS_INSTALL='$(FUNCTIONS_INSTALL)'
 
 # override built-in suffix list
 .SUFFIXES:
diff --git a/Config/version.mk b/Config/version.mk
index cd9e33110..3e6726141 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=3.1.5-pws-20
-VERSION_DATE='May 25, 1999'
+VERSION=3.1.5-pws-21
+VERSION_DATE='June 6, 1999'
diff --git a/Doc/Makefile.in b/Doc/Makefile.in
index f7dbf3866..c0ae8d80d 100644
--- a/Doc/Makefile.in
+++ b/Doc/Makefile.in
@@ -174,7 +174,7 @@ install.man: $(MAN)
 # install info pages, creating install directory if necessary
 install.info: zsh.info
 	$(sdir_top)/mkinstalldirs $(infodir)
-	for file in zsh.info zsh.info-[1-9]; do \
+	for file in zsh.info zsh.info-[1-9]*; do \
 	  if test -f $$file; then \
 	    $(INSTALL_DATA) $$file $(infodir); \
 	  elif test -f $(sdir)/$$file; then \
@@ -198,7 +198,7 @@ uninstall.man:
 
 # uninstall info pages
 uninstall.info:
-	rm -f $(infodir)/zsh.info $(infodir)/zsh.info-[1-9]
+	rm -f $(infodir)/zsh.info $(infodir)/zsh.info-[1-9]*
 
 # ========== DEPENDENCIES FOR CLEANUP ==========
 
diff --git a/Doc/Zsh/.distfiles b/Doc/Zsh/.distfiles
index f3e7352a5..3fbde5ef1 100644
--- a/Doc/Zsh/.distfiles
+++ b/Doc/Zsh/.distfiles
@@ -1,10 +1,12 @@
 DISTFILES_SRC='
     .distfiles
-    arith.yo builtins.yo compat.yo compctl.yo compwid.yo cond.yo exec.yo
-    expn.yo filelist.yo files.yo func.yo grammar.yo guide.yo index.yo intro.yo
-    invoke.yo jobs.yo metafaq.yo mod_cap.yo mod_clone.yo mod_comp1.yo
+    arith.yo builtins.yo compat.yo compctl.yo compsys.yo compwid.yo
+    cond.yo exec.yo expn.yo filelist.yo files.yo func.yo grammar.yo
+    guide.yo index.yo intro.yo invoke.yo jobs.yo metafaq.yo
+    mod_cap.yo mod_clone.yo mod_comp1.yo
     mod_compctl.yo mod_deltochar.yo mod_example.yo mod_files.yo
-    mod_mapfile.yo mod_sched.yo mod_stat.yo mod_zftp.yo mod_zle.yo
+    mod_mapfile.yo mod_parameter.yo mod_sched.yo mod_stat.yo
+    mod_zftp.yo mod_zle.yo
     modules.yo options.yo params.yo 
-    prompt.yo redirect.yo restricted.yo seealso.yo zle.yo
+    prompt.yo redirect.yo restricted.yo seealso.yo zftpsys.yo zle.yo
 '
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 7cbdb1114..157b3420d 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -315,9 +315,9 @@ With the tt(-D) flag, tt(fc) prints elapsed times.
 
 cindex(history, file)
 cindex(file, history)
-tt(fc -R) reads the history from the given file,
-tt(fc -W) writes the history out to the given file,
-and tt(fc -A) appends the history out to the given file.
+`tt(fc -R)' reads the history from the given file,
+`tt(fc -W)' writes the history out to the given file,
+and `tt(fc -A)' appends the history out to the given file.
 If no filename is specified, the tt($HISTFILE) is assumed.
 If the tt(-I) option is added to tt(-R), only those events that are
 not already contained within the internal history list are added.
diff --git a/Doc/Zsh/compat.yo b/Doc/Zsh/compat.yo
index 26f8fe896..43fa40390 100644
--- a/Doc/Zsh/compat.yo
+++ b/Doc/Zsh/compat.yo
@@ -7,19 +7,15 @@ cindex(compatibility)
 cindex(sh, compatibility)
 cindex(ksh, compatibility)
 Zsh tries to emulate bf(sh) or bf(ksh) when it is invoked as
-tt(sh) or tt(ksh) respectively.  More precisely, it looks at the first
-letter of the name passed to it, which may not necessarily be the
-name of the executable file, ignoring any initial `tt(-)' as well as
-`tt(r)' (for restricted); an `tt(s)' or `tt(b)' will force
-bf(sh) compatibility, while `tt(k)' will force bf(ksh) compatibility.  An
-exception is if the name excluding any `tt(-)' is tt(su), in which case
-the environment variable tt(SHELL) will be used to test the emulation;
-this is to workaround a problem under some operating systems where the
-tt(su) command does not change the name when executing a user shell.  Note
-that, from within zsh itself, this mechanism can be invoked by `tt(ARGV0=sh
-zsh ...)'.
+tt(sh) or tt(ksh) respectively; more precisely, it looks at the first
+letter of the name by which it was invoked, excluding any initial `tt(r)'
+(assumed to stand for `restricted'), and if that is `tt(s)' or `tt(k)' it
+will emulate bf(sh) or bf(ksh).  Furthermore, if invoked as tt(su) (which
+happens on certain systems when the shell is executed by the tt(su)
+command), the shell will try to find an alternative name from the tt(SHELL)
+environment variable and perform emulation based on that.
 
-In this emulation mode, the following
+In bf(sh) and bf(ksh) compatibility modes the following
 parameters are not special and not initialized by the shell:
 tt(ARGC),
 tt(argv),
diff --git a/Doc/Zsh/compctl.yo b/Doc/Zsh/compctl.yo
index 7b672dd68..4fecce92f 100644
--- a/Doc/Zsh/compctl.yo
+++ b/Doc/Zsh/compctl.yo
@@ -128,7 +128,7 @@ list([ tt(-K) var(function) ] [ tt(-i) var(function) ])
 list([ tt(-Q) ] [ tt(-P) var(prefix) ] [ tt(-S) var(suffix) ])
 list([ tt(-W) var(file-prefix) ] [ tt(-H) var(num pattern) ])
 list([ tt(-q) ] [ tt(-X) var(explanation) ] [ tt(-Y) var(explanation) ])
-list([ tt(-y) var(func-or-var) ] [ tt(-l) var(cmd) ] [ tt(-U) ])
+list([ tt(-y) var(func-or-var) ] [ tt(-l) var(cmd) ] [ tt(-h) var(cmd) ] [ tt(-U) ])
 list([ tt(-t) var(continue) ] [ tt(-J) var(name) ] [ tt(-V) var(name) ])
 list([ tt(-M) var(match-spec) ])
 endlist()
@@ -401,6 +401,15 @@ completes arguments between `tt(-exec)' and the following `tt(;)' (or the end
 of the command line if there is no such string) as if they were
 a separate command line.
 )
+item(tt(-h) var(cmd))(
+Normally zsh completes quoted strings as a whole. With this option,
+completion can be done separately on different parts of such
+strings. It works like the tt(-l) option but makes the completion code 
+work on the parts of the current word that are separated by
+spaces. These parts are completed as if they were arguments to the
+given var(cmd). If var(cmd) is the empty string, the first part is
+completed as a command name, as with tt(-l).
+)
 item(tt(-U))(
 Use the whole list of possible completions, whether or not they
 actually match the word on the command line.  The word typed so far
@@ -631,6 +640,12 @@ omitted, it matches if the cursor is after a word with prefix var(str1).
 item(tt(R[)var(str1)tt(,)var(str2)tt(])...)(
 Like tt(r) but using pattern matching instead.
 )
+item(tt(q[)var(str)tt(])...)(
+Matches the word currently being completed is in single quotes and the 
+var(str) begins with the letter `s', or if completion is done in
+double quotes and var(str) starts with the letter `d', or if
+completion is done in backticks and var(str) starts with a `b'.
+)
 enditem()
 
 texinode(Matching Control)(Example)(Extended Completion)(Programmable Completion)
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 90f6b2910..94533415e 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -89,9 +89,11 @@ To speed up the running of tt(compinit), it can be made to produce a dumped
 configuration which will be read in on future invocations.  The easiest way
 to do this is by adding the option tt(-d) whenever tt(compinit) is sourced.
 In this case the dumped file will have the same name as the sourced file,
-but with tt(.dump) appended to the end; alternatively, an explicit file
-name can be given following the tt(-d).  On the next call to tt(compinit
--d), the dumped file will be read instead.
+but with tt(.dump) appended to the end, or, if that is not writeable by the
+user, the file tt(.zcompdump) in the same directory as the startup files
+(i.e. tt($ZDOTDIR) or tt($HOME)); alternatively, an explicit file name can
+be given following the tt(-d).  On the next call to tt(compinit -d), the
+dumped file will be read instead.
 
 The other option accepted by tt(compinit) is tt(-f var(dir)), which gives
 the directory in which tt(compinit) resides.  If you source tt(compinit) by
@@ -331,6 +333,11 @@ Default implementations are supplied for each of these
 contexts, in most cases named after the context itself
 (e.g. completion for the `tt(-tilde-)' context is done by the function 
 named `tt(_tilde)').
+
+Before trying to find a function for a specific context, tt(_complete) 
+checks if the parameter `tt(compcontext)' is set to a non-empty
+value. If it is, the value is taken as the name of the context to use
+and the function defined for that context will be called.
 )
 item(tt(_approximate))(
 This completer function uses the tt(_complete) completer to generate
@@ -615,13 +622,6 @@ list of completions.
 )
 enditem()
 )
-item(tt(_closequotes))(
-When a completion starts in quotes, this completer will recognise the fact
-and insert a matching closing quote if there is not already one later on
-the line.  It should come earlier in the list of completers than any of the
-completers which generate matches.  It can be confused by some of the more
-sophisticated forms of completion.
-)
 enditem()
 
 texinode(Completion Functions)()(Control Functions)(Completion System)
diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo
index d74054a9c..d30adc0f1 100644
--- a/Doc/Zsh/compwid.yo
+++ b/Doc/Zsh/compwid.yo
@@ -81,6 +81,13 @@ nofill(PREFIX=${PREFIX#*=})
 causes the part of the prefix up to and including the first equal sign not
 to be treated as part of a matched string.
 )
+item(tt(QIPREFIX))(
+This parameter is read-only and contains the quoted string up to the
+word being completed. E.g. when completing `tt("foo)', this parameter
+contains the double quote. If the tt(-q) option of tt(compset) is used 
+(see below), and the original string was `tt("foo bar)' with the
+cursor on the `tt(bar)', this parameter contains `tt("foo )'.
+)
 item(tt(SUFFIX))(
 Initially this will be set to the part of the current word from the
 cursor position to the end; it may be altered to give a common suffix for
@@ -93,6 +100,9 @@ As tt(IPREFIX), but for a suffix that should not be considered part
 of the matches; note that the tt(ISUFFIX) string follows the tt(SUFFIX)
 string.
 )
+item(tt(QISUFFIX))(
+Like tt(QIPREFIX), but containing the suffix.
+)
 item(tt(compstate))(
 This is an associative array with various keys and values that the
 completion code uses to exchange information with the completion widget.
@@ -544,7 +554,8 @@ xitem(tt(compset -P) [ var(number) ] var(pattern))
 xitem(tt(compset -s) var(number))
 xitem(tt(compset -S) [ var(number) ] var(pattern))
 xitem(tt(compset -n) var(begin) [ var(end) ])
-item(tt(compset -N) var(beg-pat) [ var(end-pat) ])(
+xitem(tt(compset -N) var(beg-pat) [ var(end-pat) ])
+item(tt(compset -q))(
 This command simplifies modification of the special parameters,
 while its return value allows tests on them to be carried out.
 
@@ -607,6 +618,13 @@ matching tt(end-pat) are also removed from the tt(words)
 array. If tt(words) contains no word matching var(end-pat), the
 testing and modification is performed as if it were not given.
 )
+item(tt(-q))(
+If the cursor is currently inside single or double quotes, the word
+currenly being completed is split in separate words at the spaces. The 
+resulting words are stored in the tt(words) array, and tt(PREFIX),
+tt(SUFFIX), tt(QIPREFIX), and tt(QISUFFIX) are modified to reflect the 
+word part that is completed.
+)
 enditem()
 
 In all the above cases the return value is zero if the test succeded
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 5853d792f..7fdf973b4 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -332,9 +332,9 @@ a letter, digit, or underscore that is not to be interpreted
 as part of var(name).  In addition, more complicated forms of substitution
 usually require the braces to be present; exceptions, which only apply if
 the option tt(KSH_ARRAYS) is not set, are a single subscript or any colon
-modifiers appearing after the name, or any of the characters tt(^), tt(=),
-tt(~), tt(#) or tt(+) appearing before the name, all of which work with or
-without braces.
+modifiers appearing after the name, or any of the characters `tt(^)',
+`tt(=)', `tt(~)', `tt(#)' or `tt(+)' appearing before the name, all of
+which work with or without braces.
 
 If var(name) is an array parameter, then the value of each
 element of var(name) is substituted, one element per word.
@@ -375,8 +375,8 @@ containing a colon, then the shell only checks whether
 var(name) is set, not whether its value is null.
 
 In the following expressions, when var(name) is an array and
-the substitution is not quoted, or if the tt((@)) flag or the
-`var(name)tt([@])' syntax is used, matching and replacement is
+the substitution is not quoted, or if the `tt((@))' flag or the
+var(name)tt([@]) syntax is used, matching and replacement is
 performed on each array element separately.
 
 startitem()
@@ -404,7 +404,7 @@ item(tt(${)var(name)tt(:#)var(pattern)tt(}))(
 If the var(pattern) matches the value of var(name), then substitute
 the empty string; otherwise, just substitute the value of var(name).
 If var(name) is an array
-the matching array elements are removed (use the tt((M)) flag to
+the matching array elements are removed (use the `tt((M))' flag to
 remove the non-matched elements).
 )
 xitem(tt(${)var(name)tt(/)var(pattern)tt(/)var(repl)tt(}))
@@ -412,15 +412,15 @@ item(tt(${)var(name)tt(//)var(pattern)tt(/)var(repl)tt(}))(
 Replace by string var(repl), the longest possible match of
 var(pattern) in the expansion of parameter var(name).  The first form
 replaces just the first occurrence, the second form all occurrences.
-The var(pattern) may begin with a var(#), in which case the
-var(pattern) must match at the start of the string, or var(%), in
+The var(pattern) may begin with a `tt(#)', in which case the
+var(pattern) must match at the start of the string, or `tt(%)', in
 which case it must match at the end of the string.  The var(repl) may
-be an empty string, in which case the final tt(/) may also be omitted.
-To quote the final tt(/) in other cases it should be preceded by two
+be an empty string, in which case the final `tt(/)' may also be omitted.
+To quote the final `tt(/)' in other cases it should be preceded by two
 backslashes (i.e., a quoted backslash); this is not necessary if the
-tt(/) occurs inside a substituted parameter.
+`tt(/)' occurs inside a substituted parameter.
 
-The first tt(/) may be preceded by a tt(:), in which case the match
+The first `tt(/)' may be preceded by a `tt(:)', in which case the match
 will only succeed if it matches the entire word.  Note also the
 effect of the tt(I) and tt(S) parameter expansion flags below; however,
 the flags tt(M), tt(R), tt(B), tt(E) and tt(N) are not useful.
@@ -431,7 +431,7 @@ nofill(tt(foo="twinkle twinkle little star" sub="t*e" rep="spy")
 tt(print ${foo//${~sub}/$rep})
 tt(print ${(S)foo//${~sub}/$rep}))
 
-Here, the tt(~) ensures that the text of tt($sub) is treated as a
+Here, the `tt(~)' ensures that the text of tt($sub) is treated as a
 pattern rather than a plain string.  In the first case, the longest
 match for tt(t*e) is substituted and the result is `tt(spy star)',
 while in the second case, the shortest matches are taken and the
@@ -442,8 +442,8 @@ If var(spec) is one of the above substitutions, substitute
 the length in characters of the result instead of
 the result itself.  If var(spec) is an array expression,
 substitute the number of elements of the result.
-Note that tt(^), tt(=), and tt(~), below, must appear
-to the left of tt(#) when these forms are combined.
+Note that `tt(^)', `tt(=)', and `tt(~)', below, must appear
+to the left of `tt(#)' when these forms are combined.
 )
 item(tt(${^)var(spec)tt(}))(
 pindex(RC_EXPAND_PARAM, use of)
@@ -452,7 +452,7 @@ cindex(rc, array expansion style)
 Turn on the tt(RC_EXPAND_PARAM) option for the
 evaluation of var(spec); if the `tt(^)' is doubled, turn it off.
 When this option is set, array expansions of the form
-`var(foo)tt(${)var(xx)tt(})var(bar)',
+var(foo)tt(${)var(xx)tt(})var(bar),
 where the parameter var(xx)
 is set to tt(LPAR())var(a b c)tt(RPAR()), are substituted with
 `var(fooabar foobbar foocbar)' instead of the default
@@ -498,10 +498,19 @@ tt($LPAR())...tt(RPAR()) type command substitution is used in place of
 var(name) above, it is expanded first and the result is used as if
 it were the value of var(name).  Thus it is
 possible to perform nested operations:  tt(${${foo#head}%tail})
-substitutes the value of tt($foo) with both tt(head) and tt(tail)
+substitutes the value of tt($foo) with both `tt(head)' and `tt(tail)'
 deleted.  The form with tt($LPAR())...tt(RPAR()) is often useful in
 combination with the flags described next; see the examples below.
 
+Note that double quotes may appear around nested substitutions, in which
+case only the part inside is treated as quoted; for example,
+tt(${(f)"$(foo)"}) quotes the result of tt($(foo)), but the flag `tt((f))'
+(see below) is applied using the rules for unquoted substitutions.  Note
+further that quotes are themselves nested in this context; for example, in
+tt("${(@f)"$(foo)"}"), there are two sets of quotes, one surrounding the
+whole expression, the other (redundant) surrounding the tt($(foo)) as
+before.
+
 subsect(Parameter Expansion Flags)
 cindex(parameter expansion flags)
 cindex(flags, parameter expansion)
@@ -526,8 +535,8 @@ when creating an associative array.
 )
 item(tt(@))(
 In double quotes, array elements are put into separate words.
-E.g., `tt("${(@)foo}")' is equivalent to `tt("${foo[@]}")' and
-`tt("${(@)foo[1,2]}")' is the same as `tt("$foo[1]" "$foo[2]")'.
+E.g., tt("${(@)foo}") is equivalent to tt("${foo[@]}") and
+tt("${(@)foo[1,2]}") is the same as tt("$foo[1]" "$foo[2]").
 )
 item(tt(e))(
 Perform em(parameter expansion), em(command substitution) and
@@ -541,7 +550,7 @@ type parameter expression or a tt($LPAR())...tt(RPAR()) type command
 substitution in place of the parameter name this flag makes the result
 of the expansion be taken as a parameter name which is then
 used. E.g. if you have `tt(foo=bar)' and `tt(bar=baz)', the strings
-`tt(${(P)foo})' and `tt(${(P)${foo}})' will be expanded to `tt(baz)'.
+tt(${(P)foo}) and tt(${(P)${foo}}) will be expanded to `tt(baz)'.
 )
 item(tt(o))(
 Sort the resulting words in ascending order.
@@ -722,7 +731,7 @@ outermost.  The flags are not propagated up to enclosing
 substitutions; the nested subsitution will return either a scalar or an
 array as determined by the flags, possibly adjusted for quoting.  All the
 following steps take place where applicable at all levels of substitution.
-Note that, unless the tt((P)) flag is present, the flags and any subscripts
+Note that, unless the `tt((P))' flag is present, the flags and any subscripts
 apply directly to the value of the nested substitution; for example, the
 expansion tt(${${foo}}) behaves exactly the same as tt(${foo}).
 )
@@ -749,57 +758,57 @@ arrays are not modified).  If the tt((j)) flag is present, that is used for
 joining instead of tt($IFS).
 )
 item(tt(5.) em(Nested Subscripting))(
-Any remaining subscript (i.e. of a nested substitution) is evaluated at
-this point, based on whether the value is an array or a scalar; if it was
-an array, a second subscript for the character in the word may also appear.
-Note that tt(${foo[2,4][2]}) is thus equivalent to tt(${${foo[2,4]}[2]})
-and also to tt("${${(@)foo[2,4]}[2]}") (the nested substitution returns an
-array in both cases), but not to tt("${${foo[2,4]}[2]}") (the nested
-substitution returns a scalar because of the quotes).
+Any remaining subscripts (i.e. of a nested substitution) are evaluated at
+this point, based on whether the value is an array or a scalar.  As with
+tt(2.), multiple subscripts can appear.  Note that tt(${foo[2,4][2]}) is
+thus equivalent to tt(${${foo[2,4]}[2]}) and also to
+tt("${${(@)foo[2,4]}[2]}") (the nested substitution returns an array in
+both cases), but not to tt("${${foo[2,4]}[2]}") (the nested substitution
+returns a scalar because of the quotes).
 )
 item(tt(6.) em(Modifiers))(
-Any modifiers, as specified by a trailing tt(#), tt(%), tt(/)
+Any modifiers, as specified by a trailing `tt(#)', `tt(%)', `tt(/)'
 (possibly doubled) or by a set of modifiers of the form tt(:...) (see
 noderef(Modifiers) in noderef(History Expansion)), are applied to the words
 of the value at this level.
 )
 item(tt(7.) em(Forced Joining))(
-If the tt((j)) flag is present, or no tt((j)) flag is present but
+If the `tt((j))' flag is present, or no `tt((j))' flag is present but
 the string is to be split as given by rules tt(8.) or tt(9.), and joining
 did not take place at step tt(4.), any words in the value are joined
 together using the given string or the first character of tt($IFS) if none.
-Note that the tt((F)) flag implicitly supplies a string for joining in this
+Note that the `tt((F))' flag implicitly supplies a string for joining in this
 manner.
 )
 item(tt(8.) em(Forced Splitting))(
-If one of the tt((s)) or tt((f)) flags are present, or the tt(=)
+If one of the `tt((s))' or `tt((f))' flags are present, or the `tt(=)'
 specifier was present (e.g. tt(${=)var(var)tt(})), the word is split on
 occurrences of the specified string, or (for tt(=) with neither of the two
 flags present) any of the characters in tt($IFS).
 )
 item(tt(9.) em(Shell Word Splitting))(
-If no tt((s)), tt((f)) or tt(=) was given, but the word is not
+If no `tt((s))', `tt((f))' or `tt(=)' was given, but the word is not
 quoted and the option tt(SH_WORD_SPLIT) is set, the word is split on
 occurrences of any of the characters in tt($IFS).  Note this step, too,
 take place at all levels of a nested substitution.
 )
 item(tt(10.) em(Re-Evaluation))(
-Any tt((e)) flag is applied to the value, forcing it to be re-examined for
-new parameter substitutions, but also for command and arithmetic
+Any `tt((e))' flag is applied to the value, forcing it to be re-examined
+for new parameter substitutions, but also for command and arithmetic
 substitutions.
 )
 item(tt(11.) em(Padding))(
-Any padding of the value by the tt(LPAR()l.)var(fill)tt(.RPAR()) or
-tt(LPAR()r.)var(fill)tt(.RPAR()) flags is applied.
+Any padding of the value by the `tt(LPAR()l.)var(fill)tt(.RPAR())' or
+`tt(LPAR()r.)var(fill)tt(.RPAR())' flags is applied.
 )
 enditem()
 
 subsect(Examples)
 The flag tt(f) is useful to split a double-quoted substitution line by
-line.  For example, `tt("${(f)$LPAR()<)var(file)tt(RPAR()}")'
+line.  For example, tt("${(f)$LPAR()<)var(file)tt(RPAR()}")
 substitutes the contents of var(file) divided so that each line is
 an element of the resulting array.  Compare this with the effect of
-`tt($)tt(LPAR()<)var(file)tt(RPAR())' alone, which divides the file
+tt($)tt(LPAR()<)var(file)tt(RPAR()) alone, which divides the file
 up by words, or the same inside double quotes, which makes the entire
 content of the file a single string.
 
@@ -811,19 +820,19 @@ item(tt("${(@)${foo}[1]}"))(
 This produces the result tt(b).  First, the inner substitution
 tt("${foo}"), which has no array (tt(@)) flag, produces a single word
 result tt("bar baz").  The outer substitution tt("${(@)...[1]}") detects
-that this is a scalar, so that (despite the tt((@)) flag) the subscript
+that this is a scalar, so that (despite the `tt((@))' flag) the subscript
 picks the first character. 
 )
 item(tt("${${(@)foo}[1]}"))(
-The produces the result tt(bar).  In this case, the inner substitution
-tt("${(@)foo}") produces the array tt(LPAR()bar baz)tt(RPAR()).  The outer
+The produces the result `tt(bar)'.  In this case, the inner substitution
+tt("${(@)foo}") produces the array `tt(LPAR()bar baz)tt(RPAR())'.  The outer
 substitution tt("${...[1]}") detects that this is an array and picks the
 first word.  This is similar to the simple case tt("${foo[1]}").
 )
 enditem()
 
 As an example of the rules for word splitting and joining, suppose tt($foo)
-contains the array tt(LPAR()ax1 bx1)tt(RPAR()).  Then
+contains the array `tt(LPAR()ax1 bx1)tt(RPAR())'.  Then
 
 startitem()
 item(tt(${(s/x/)foo}))(
@@ -1371,21 +1380,21 @@ be taken (e.g. `tt(u:foo:)' or `tt(u[foo])' for user `tt(foo)')
 item(tt(g)var(id))(
 like tt(u)var(id) but with group IDs or names
 )
-item(tt(a)[tt(Mwhm)][tt(-)|tt(PLUS())]var(n))(
-files accessed exactly var(n) days ago.  Files accessed within the
-last var(n) days are selected using a negative value for var(n)
-(tt(-)var(n)).  Files accessed more than var(n) days ago are selected by a
-positive var(n) value (tt(PLUS())var(n)).  Optional unit specifiers `tt(M)',
-`tt(w)', `tt(h)' or `tt(m)' (e.g. `tt(ah5)') cause the check to be
-performed with months (of 30 days), weeks, hours, or minutes instead of
-days, respectively.  For instance, `tt(echo *(ah-5))' would echo files
-accessed within the last five hours.
-)
-item(tt(m)[tt(Mwhm)][tt(-)|tt(PLUS())]var(n))(
+item(tt(a)[tt(Mwhms)][tt(-)|tt(PLUS())]var(n))(
+files accessed exactly var(n) days ago.  Files accessed within the last
+var(n) days are selected using a negative value for var(n) (tt(-)var(n)).
+Files accessed more than var(n) days ago are selected by a positive var(n)
+value (tt(PLUS())var(n)).  Optional unit specifiers `tt(M)', `tt(w)',
+`tt(h)', `tt(m)' or `tt(s)' (e.g. `tt(ah5)') cause the check to be
+performed with months (of 30 days), weeks, hours, minutes or seconds
+instead of days, respectively.  For instance, `tt(echo *(ah-5))' would
+echo files accessed within the last five hours.
+)
+item(tt(m)[tt(Mwhms)][tt(-)|tt(PLUS())]var(n))(
 like the file access qualifier, except that it uses the file modification
 time.
 )
-item(tt(c)[tt(Mwhm)][tt(-)|tt(PLUS())]var(n))(
+item(tt(c)[tt(Mwhms)][tt(-)|tt(PLUS())]var(n))(
 like the file access qualifier, except that it uses the file inode change
 time.
 )
diff --git a/Doc/Zsh/files.yo b/Doc/Zsh/files.yo
index 9ff59fe19..17b29677b 100644
--- a/Doc/Zsh/files.yo
+++ b/Doc/Zsh/files.yo
@@ -8,13 +8,12 @@ cindex(shutdown files)
 pindex(NO_RCS, use of)
 pindex(NO_GLOBAL_RCS, use of)
 Commands are first read from tt(/etc/zshenv); this cannot be overridden.
-If the tt(RCS) option is unset, no further files are read; changing this
-option after this point has no effect on initialization files, but may
-affect behaviour on logout.  Subsequent behaviour is also modified by the
-option tt(GLOBAL_RCS).  If it is unset at any point during initialisation,
-later files in the tt(/etc) directory will not be read.  It is also
-possible for a file in tt($ZDOTDIR) to re-enable tt(GLOBAL_RCS). Both
-tt(RCS) and tt(GLOBAL_RCS) are set by default.
+Subsequent behaviour is modified by the tt(RCS) and
+tt(GLOBAL_RCS) options; the former affects all startup files, while the
+second only affects those in the tt(/etc) directory.  If one of the options
+is unset at any point, the corresponding startup file(s) will not be read.
+It is also possible for a file in tt($ZDOTDIR) to re-enable
+tt(GLOBAL_RCS). Both tt(RCS) and tt(GLOBAL_RCS) are set by default.
 
 Commands are then read from tt($ZDOTDIR/.zshenv).
 pindex(LOGIN, use of)
@@ -31,6 +30,9 @@ via the tt(exit) or tt(logout) commands, or an implict exit by reading
 end-of-file from the terminal.  However, if the shell terminates due
 to tt(exec)'ing another process, the logout files are not read.
 These are also affected by the tt(RCS) and tt(GLOBAL_RCS) options.
+Note also that the tt(RCS) option affects the saving of history files,
+i.e. if tt(RCS) is unset when the shell exits, no history file will be
+saved.
 
 If tt(ZDOTDIR) is unset, tt(HOME) is used instead.
 Those files listed above as being in tt(/etc) may be in another
diff --git a/Doc/Zsh/metafaq.yo b/Doc/Zsh/metafaq.yo
index 1d1636942..569d91716 100644
--- a/Doc/Zsh/metafaq.yo
+++ b/Doc/Zsh/metafaq.yo
@@ -31,26 +31,26 @@ tt(http://www.zsh.org/pub/zsh/))
 item(Australia)(
 nofill(tt(ftp://ftp.zsh.org/pub/zsh/)
 tt(http://www.zsh.org/pub/zsh/)
-tt(ftp://ftp.ips.oz.au/pub/packages/zsh/)  em((G))  em((H)))
+tt(ftp://ftp.ips.gov.au/pub/packages/zsh/)  em((G))  em((H)))
 )
 item(Denmark)(
 nofill(tt(ftp://sunsite.auc.dk/pub/unix/shells/zsh/))
 )
 item(Finland)(
-nofill(tt(ftp://ftp.funet.fi/pub/unix/shells/zsh/)  em((H)))
+nofill(tt(ftp://ftp.funet.fi/pub/unix/shells/zsh/))
 )
 item(France)(
 nofill(tt(ftp://ftp.cenatls.cena.dgac.fr/pub/shells/zsh/))
 )
 item(Germany)(
 nofill(tt(ftp://ftp.fu-berlin.de/pub/unix/shells/zsh/)  em((H))
-tt(ftp://ftp.gmd.de/packages/zsh/)  em((H))
-tt(ftp://ftp.uni-trier.de/pub/unix/shell/zsh/)  em((H)))
+tt(ftp://ftp.gmd.de/packages/zsh/)
+tt(ftp://ftp.uni-trier.de/pub/unix/shell/zsh/))
 )
 item(Hungary)(
 nofill(tt(ftp://ftp.cs.elte.hu/pub/zsh/)
 tt(http://www.cs.elte.hu/pub/zsh/)
-tt(ftp://ftp.kfki.hu/pub/packages/zsh/)  em((H)))
+tt(ftp://ftp.kfki.hu/pub/packages/zsh/))
 )
 item(Israel)(
 nofill(tt(ftp://ftp.math.technion.ac.il/mirror/ftp.zsh.org/pub/zsh/)
@@ -58,10 +58,11 @@ tt(http://www.math.technion.ac.il/mirror/ftp.zsh.org/pub/zsh/))
 )
 item(Japan)(
 nofill(tt(ftp://ftp.tohoku.ac.jp/mirror/zsh/)  em((H))
-tt(ftp://ftp.nis.co.jp/pub/shells/zsh/)  em((H)))
+tt(ftp://ftp.nisiq.net/pub/shells/zsh/)  em((H))
+tt(ftp://ftp.win.ne.jp/pub/shell/zsh/))
 )
 item(Norway)(
-nofill(tt(ftp://ftp.uit.no/pub/unix/shells/zsh/)  em((H)))
+nofill(tt(ftp://ftp.uit.no/pub/unix/shells/zsh/))
 )
 item(Romania)(
 nofill(tt(ftp://ftp.roedu.net/pub/mirrors/ftp.zsh.org/pub/zsh/))
@@ -70,17 +71,17 @@ item(Slovenia)(
 nofill(tt(ftp://ftp.siol.net/pub/unix/shells/zsh/)  em((H)))
 )
 item(Sweden)(
-nofill(tt(ftp://ftp.lysator.liu.se/pub/unix/zsh/)  em((H)))
+nofill(tt(ftp://ftp.lysator.liu.se/pub/unix/zsh/))
 )
 item(UK)(
-nofill(tt(ftp://ftp.net.lut.ac.uk/zsh/)  em((H))
-tt(ftp://sunsite.doc.ic.ac.uk/packages/unix/shells/zsh/)  em((G)))
+nofill(tt(ftp://ftp.net.lut.ac.uk/zsh/)
+tt(ftp://sunsite.org.uk/packages/zsh/))
 )
 item(USA)(
 nofill(tt(ftp://ftp.math.gatech.edu/pub/zsh/)
 tt(ftp://uiarchive.uiuc.edu/pub/packages/shells/zsh/)
 tt(ftp://ftp.sterling.com/zsh/)  em((G))  em((H))
-tt(ftp://ftp.rge.com/pub/shells/zsh/)  em((G))  em((H))
+tt(ftp://ftp.rge.com/pub/shells/zsh/)
 tt(ftp://foad.org/pub/zsh/)
 tt(http://foad.org/zsh/))
 )
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index c34736107..472364d3e 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -119,7 +119,8 @@ pindex(AUTO_REMOVE_SLASH)
 cindex(slash, removing trailing)
 item(tt(AUTO_REMOVE_SLASH))(
 When the last character resulting from a completion is a slash and the next
-character typed is a word delimiter or a slash, remove the slash.
+character typed is a word delimiter, a slash, or a character that ends 
+a command (such as a semicolon or an ampersand), remove the slash.
 )
 pindex(AUTO_RESUME)
 cindex(jobs, resuming automatically)
@@ -304,7 +305,8 @@ cindex(history, timestamping)
 item(tt(EXTENDED_HISTORY))(
 Save each command's beginning timestamp (in seconds since the epoch)
 and the duration (in seconds) to the history file.  The format of
-this prefixed data is
+this prefixed data is:
+
 `tt(:)var(<beginning time>)tt(:)var(<elapsed seconds>)tt(:)var(<command>)'.
 )
 pindex(FLOW_CONTROL)
@@ -327,15 +329,14 @@ item(tt(GLOB) (tt(PLUS()F), ksh: tt(PLUS()f)))(
 Perform filename generation (globbing).
 (See noderef(Filename Generation).)
 )
-pindex(GLOBAL_RCS_FIRST)
-cindex(startup files, changing order)
-cindex(files, startup, changing order)
-item(tt(GLOBAL_RCS_FIRST) (tt(-d)))(
-If this option is set, and the tt(RCS) option is also set (as it is by
-default), then the order in which startup files are sourced after
-tt(/etc/zshenv) changes to tt(/etc/zprofile), tt(/etc/zshrc),
-tt(/etc/zlogin), tt(.zshenv), tt(.zprofile), tt(.zshrc), tt(.zlogin).
-The order of tt(.zlogout) and tt(/etc/zlogout) is not affected.
+pindex(GLOBAL_RCS)
+cindex(startup files, global, inhibiting)
+cindex(files, global startup, inhibiting)
+item(tt(GLOBAL_RCS) (tt(-d)))(
+If this option is unset, the startup files tt(/etc/zprofile),
+tt(/etc/zshrc), tt(/etc/zlogin) and tt(/etc/zlogout) will not be run.  It
+can be disabled and re-enabled at any time, including inside local startup
+files (tt(.zshrc), etc.).
 )
 pindex(GLOB_ASSIGN)
 item(tt(GLOB_ASSIGN))(
@@ -409,13 +410,13 @@ isn't there.
 pindex(HIST_EXPIRE_DUPS_FIRST)
 cindex(history, expiring duplicates)
 item(tt(HIST_EXPIRE_DUPS_FIRST))(
-If the history needs to be trimmed to add a new line, setting this
-option will cause the oldest duplicate history line to be lost before
-losing a unique line from the internal history list.
+If the internal history needs to be trimmed to add a new line,
+setting this option will cause the oldest duplicate history line to
+be lost before losing a unique line from the list.
 )
 pindex(HIST_IGNORE_ALL_DUPS)
 cindex(history, ignoring all duplicates)
-item(tt(HIST_IGNORE_ALL_DUPS) (tt(-h)))(
+item(tt(HIST_IGNORE_ALL_DUPS))(
 If a new command line being added to the history list duplicates an
 older one, the older command is removed from the list (even if it is
 not the previous event).
@@ -482,11 +483,11 @@ to avoid the shell hanging if its tty goes away.
 pindex(INC_APPEND_HISTORY)
 cindex(history, incremental appending to a file)
 item(tt(INC_APPEND_HISTORY))(
-This options works like APPEND_HISTORY except that new history lines
-are added to the tt($HISTFILE) when they finish running, rather than
-waiting until the shell is killed. The file is periodically trimmed
-to the number of lines specified by tt($SAVEHIST), but can exceed this
-value between trimmings.
+This options works like tt(APPEND_HISTORY) except that new history lines
+are added to the tt($HISTFILE) incrementally (as soon as they are
+entered), rather than waiting until the shell is killed.
+The file is periodically trimmed to the number of lines specified by
+tt($SAVEHIST), but can exceed this value between trimmings.
 )
 pindex(INTERACTIVE)
 item(tt(INTERACTIVE) (tt(-i), ksh: tt(-i)))(
@@ -568,7 +569,8 @@ tt(XTRACE) and tt(PRINT_EXIT_VALUE) options are restored.  Hence
 if this is explicitly unset by a shell function the other options in
 force at the point of return will remain so.
 A shell function can also guarantee itself a known shell configuration
-with a formulation like `tt(emulate zsh; setopt localoptions)'.
+with a formulation like `tt(emulate -L zsh)'; the tt(-L) activates
+tt(LOCAL_OPTIONS).
 )
 pindex(LOGIN)
 item(tt(LOGIN) (tt(-l), ksh: tt(-l)))(
@@ -795,7 +797,10 @@ After tt(/etc/zshenv) is sourced on startup, source the
 tt(.zshenv), tt(/etc/zprofile), tt(.zprofile),
 tt(/etc/zshrc), tt(.zshrc), tt(/etc/zlogin), tt(.zlogin), and tt(.zlogout)
 files, as described in noderef(Files).
-If this option is unset, only the tt(/etc/zshenv) file is sourced.
+If this option is unset, the tt(/etc/zshenv) file is still sourced, but any
+of the others will not be; it can be set at any time to prevent the
+remaining startup files after the currently executing one from
+being sourced.
 )
 pindex(REC_EXACT)
 cindex(completion, exact matches)
@@ -833,21 +838,22 @@ cindex(history, sharing)
 item(tt(SHARE_HISTORY))(
 
 This option both imports new commands from the history file, and also
-causes your typed commands to be appended to the history file (like
-specifiying tt(INCREMENTAL_APPEND_HISTORY)).  The history lines are also
-output with timestamps ala tt(EXTENDED_HISTORY) (which makes it easier to
-find the spot where we left off reading the file after it gets re-written).
+causes your typed commands to be appended to the history file (the
+latter is like specifying tt(INC_APPEND_HISTORY)).
+The history lines are also output with timestamps ala
+tt(EXTENDED_HISTORY) (which makes it easier to find the spot where
+we left off reading the file after it gets re-written).
 
-By default, history movement commands visit the imported lines as well as
-the local lines, but you can toggle this on and off with the
+By default, history movement commands visit the imported lines as
+well as the local lines, but you can toggle this on and off with the
 set-local-history zle binding.  It is also possible to create a zle
-widget that will make some commands ignore imported commands, and some
-include them.
+widget that will make some commands ignore imported commands, and
+some include them.
 
 If you find that you want more control over when commands
 get imported, you may wish to turn tt(SHARE_HISTORY) off,
-tt(INCREMENTAL_APPEND_HISTORY) on, and then manually import
-commands whenever you need them using `fc -RI'.
+tt(INC_APPEND_HISTORY) on, and then manually import
+commands whenever you need them using `tt(fc -RI)'.
 )
 pindex(SH_FILE_EXPANSION)
 cindex(sh, expansion style)
diff --git a/Doc/Zsh/zftpsys.yo b/Doc/Zsh/zftpsys.yo
index f20a0a6c3..6983dedb9 100644
--- a/Doc/Zsh/zftpsys.yo
+++ b/Doc/Zsh/zftpsys.yo
@@ -7,10 +7,10 @@ This describes the set of shell functions supplied with the source
 distribution as an interface to the tt(zftp) builtin command, allowing you
 to perform FTP operations from the shell command line or within functions
 or scripts.  The interface is similar to a traditional FTP client (e.g. the
-manref(ftp)(1) command itself), but as it is entirely done within the shell
-all the familar completion, editing and globbing features, and so on, are
-present, and macros are particularly simple to write as they are just
-ordinary shell functions.
+tt(ftp) command itself, see manref(ftp)(1)), but as it is entirely done
+within the shell all the familar completion, editing and globbing features,
+and so on, are present, and macros are particularly simple to write as they
+are just ordinary shell functions.
 
 The prerequisite is that the tt(zftp) command, as described in
 ifzman(\
@@ -20,11 +20,11 @@ ifnzman(\
 noderef(The zftp Module)
 ), must be available in the
 version of tt(zsh) installed at your site.  If the shell is configured to
-load new commands at run time, it probably is: typing tt(zmodload zftp)
+load new commands at run time, it probably is: typing `tt(zmodload zftp)'
 will make sure (if that runs silently, it has worked).  If this is not the
 case, it is possible tt(zftp) was linked into the shell anyway: to test
-this, type tt(which zftp) and if tt(zftp) is available you will get the
-message tt(zftp: shell built-in command).
+this, type `tt(which zftp)' and if tt(zftp) is available you will get the
+message `tt(zftp: shell built-in command)'.
 
 Commands given directly with tt(zftp) builtin may be interspersed between
 the functions in this suite; in a few cases, using tt(zftp) directly may
@@ -43,7 +43,7 @@ sect(Installation)
 
 You should make sure all the functions from the tt(Functions/Zftp)
 directory of the source distribution are available; they all begin with the
-two letters tt(zf).  They may already have been installed on your system;
+two letters `tt(zf)'.  They may already have been installed on your system;
 otherwise, you will need to find them and copy them.  The directory should
 appear as one of the elements of the tt($fpath) array, and the functions
 should be autoloaded.  Finally, to initialise the use of the system you
@@ -93,13 +93,13 @@ described below.
 
 Normally, the var(host), var(user) and var(password) are internally
 recorded for later re-opening, either by a tt(zfopen) with no arguments, or
-automatically (see below).  With the option tt(-1), no information is
+automatically (see below).  With the option `tt(-1)', no information is
 stored.
 )
 item(tt(zfanon [ -1 ] var(host)))(
 Open a connection var(host) for anonymous FTP.  The username used is
 tt(anonymous).  The password (which will be reported the first time) is
-generated from var(user)tt(@)tt(host); this is then stored in the shell
+generated as var(user)tt(@)var(host); this is then stored in the shell
 parameter tt($EMAIL_ADDR) which can alternatively be set manually to a
 suitable string.
 )
@@ -114,9 +114,9 @@ Change the current directory on the remote server:  this is implemented to
 have many of the features of the shell builtin tt(cd).
 
 In the first form with var(dir) present, change to the directory var(dir).
-The command tt(zfcd ..) is treated specially, so is guaranteed to work on
+The command `tt(zfcd ..)' is treated specially, so is guaranteed to work on
 non-UNIX servers (note this is handled internall by tt(zftp)).  If var(dir)
-is omitted, has the effect of tt(zfcd ~).
+is omitted, has the effect of `tt(zfcd ~)'.
 
 The second form changes to the directory previously current.
 
@@ -125,22 +125,22 @@ first occurrence of the string var(old) with the string var(new) in the
 current directory.
 
 Note that in this command, and indeed anywhere a remote filename is
-expected, the string which on the local host corresponds to tt(~) is
-converted back to a tt(~) before being passed to the remote machine.
+expected, the string which on the local host corresponds to `tt(~)' is
+converted back to a `tt(~)' before being passed to the remote machine.
 This is convenient because of the way expansion is performed on the command
 line before tt(zfcd) receives a string.  For example, suppose the command
-is tt(zfcd ~/foo).  The shell will expand this to a full path as in tt(zfcd
-/home/user2/pws/foo).  At this stage, tt(zfcd) recognises the initial path
-as tt(~), and the directory sent to the remote host is tt(~/foo), so that
-the tt(~) will be expanded by the server to the correct remote host
-directory.  Other named directories of the form tt(~name) are not treated
-in this fashion.
+is `tt(zfcd ~/foo)'.  The shell will expand this to a full path as in
+`tt(zfcd /home/user2/pws/foo)'.  At this stage, tt(zfcd) recognises the
+initial path as `tt(~)', and the directory sent to the remote host is
+tt(~/foo), so that the `tt(~)' will be expanded by the server to the
+correct remote host directory.  Other named directories of the form
+`tt(~name)' are not treated in this fashion.
 )
 item(tt(zfhere))(
 Change directory on the remote server to the one corresponding to the
-current local directory, with special handling of tt(~) as in tt(zfcd).
+current local directory, with special handling of `tt(~)' as in tt(zfcd).
 For example, if the current local directory is tt(~/foo/bar), then
-tt(zfhere) performs the effect of tt(zfcd ~/foo/bar).
+tt(zfhere) performs the effect of `tt(zfcd ~/foo/bar)'.
 )
 item(tt(zfdir [ -rfd ] [ - ] [ var(dir-options) ] [ var(dir) ]))(
 Produce a long directory listing.  The arguments var(dir-options) and
@@ -163,7 +163,7 @@ listing.
 item(tt(zfls) [ var(ls-options) ] [ var(dir) ])(
 List files on the remote server.  With no arguments, this will produce a
 simple list of file names for the current remote directory.  Any arguments
-are passed directory to the server.  No pager and no caching is used.
+are passed directly to the server.  No pager and no caching is used.
 )
 enditem()
 
@@ -171,9 +171,9 @@ subsect(Status commands)
 startitem()
 item(tt(zftype) [ var(type) ])(
 With no arguments, show the type of data to be transferred, usually ASCII
-or binary.  With an argument, change the type: the types tt(A) or
-tt(ASCII) for ASCII data and tt(B) or tt(BINARY), tt(I) or tt(IMAGE) for
-binary data are understood case-insensitively.
+or binary.  With an argument, change the type: the types `tt(A)' or
+`tt(ASCII)' for ASCII data and `tt(B)' or `tt(BINARY)', `tt(I)' or
+`tt(IMAGE)' for binary data are understood case-insensitively.
 )
 item(tt(zfstat) [ -v ])(
 Show the status of the current or last connection, as well as the status of
@@ -266,9 +266,9 @@ A problem arises if you attempt to use tt(zfpcp) var(lfile1) var(rdir),
 i.e. the second form of copying but with two arguments, as the command has
 no simple way of knowing if var(rdir) corresponds to a directory or a
 filename.  It attempts to resolve this in various ways.  First, if the
-var(rdir) argument is tt(.) or tt(..) or ends in a slash, it is assumed to
-be a directory.  Secondly, if the operation of copying to a remote file in
-the first form failed, and the remote server sends back the expected
+var(rdir) argument is `tt(.)' or `tt(..)' or ends in a slash, it is assumed
+to be a directory.  Secondly, if the operation of copying to a remote file
+in the first form failed, and the remote server sends back the expected
 failure code 553 and a reply including the string `tt(Is a directory)',
 then tt(zfpcp) will retry using the second form.
 )
diff --git a/Doc/ztexi.yo b/Doc/ztexi.yo
index 7388c61aa..231a70b84 100644
--- a/Doc/ztexi.yo
+++ b/Doc/ztexi.yo
@@ -33,7 +33,7 @@ COMMENT(--- emphasised text ---)
 
 def(em)(1)(NOTRANS(@emph{)ARG1NOTRANS(}))
 def(bf)(1)(NOTRANS(@cite{)ARG1NOTRANS(}))
-def(tt)(1)(NOTRANS(@code{)ARG1NOTRANS(}))
+def(tt)(1)(NOTRANS(@t{)ARG1NOTRANS(}))
 def(var)(1)(NOTRANS(@var{)ARG1NOTRANS(}))
 
 COMMENT(--- man page headers ---)
diff --git a/Functions/.distfiles b/Functions/.distfiles
index 1aa4fbc89..fe60df9b7 100644
--- a/Functions/.distfiles
+++ b/Functions/.distfiles
@@ -1,5 +1,3 @@
 DISTFILES_SRC='
-    .distfiles
-    acx cat cdmatch cdmatch2 checkmail cx harden mere multicomp proto
-    pushd randline run-help yp yu zed zls
+    .distfiles Makefile.in README.zftp
 '
diff --git a/Functions/Makefile.in b/Functions/Makefile.in
new file mode 100644
index 000000000..d6344dd62
--- /dev/null
+++ b/Functions/Makefile.in
@@ -0,0 +1,86 @@
+#
+# Makefile for Functions subdirectory
+#
+# Copyright (c) 1999 Peter Stephensons
+# All rights reserved.
+#
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and to distribute modified versions of this software for any
+# purpose, provided that the above copyright notice and the following
+# two paragraphs appear in all copies of this software.
+#
+# In no event shall Peter Stephenson or the Zsh Development Group be liable
+# to any party for direct, indirect, special, incidental, or consequential
+# damages arising out of the use of this software and its documentation,
+# even if Peter Stephenson and the Zsh Development Group have been advised of
+# the possibility of such damage.
+#
+# Peter Stephenson and the Zsh Development Group specifically disclaim any
+# warranties, including, but not limited to, the implied warranties of
+# merchantability and fitness for a particular purpose.  The software
+# provided hereunder is on an "as is" basis, and Peter Stephenson and the
+# Zsh Development Group have no obligation to provide maintenance,
+# support, updates, enhancements, or modifications.
+#
+
+subdir = Functions
+dir_top = ..
+SUBDIRS =
+
+@VERSION_MK@
+
+# source/build directories
+VPATH           = @srcdir@
+sdir            = @srcdir@
+sdir_top        = @top_srcdir@
+INSTALL         = @INSTALL@
+
+@DEFS_MK@
+
+# ========== DEPENDENCIES FOR BUILDING ==========
+
+all:
+
+# ========== DEPENDENCIES FOR INSTALLING ==========
+
+install: install.fns
+
+uninstall: uninstall.fns
+
+# install functions, including those in subdirectories, creating
+# install directory if necessary
+install.fns:
+	if test x$(fndir) != x && test x$(fndir) != xno; then \
+	  $(sdir_top)/mkinstalldirs $(fndir) || exit 1; \
+	  for file in $(FUNCTIONS_INSTALL); do \
+	    if test -f $$file; then \
+	      $(INSTALL_DATA) $$file $(fndir) || exit 1; \
+	    fi; \
+	  done; \
+	fi; \
+	exit 0
+
+uninstall.fns:
+	if test x$(fndir) != x && test x$(fndir) != xno; then \
+	  for file in $(FUNCTIONS_INSTALL); do \
+	    if test -f $$file; then \
+	      rm -f "$(fndir)/`echo $$file | sed -e 's%^.*/%%'`"; \
+	    fi; \
+	  done; \
+	fi; \
+	exit 0
+
+# ========== DEPENDENCIES FOR CLEANUP ==========
+
+@CLEAN_MK@
+
+mostlyclean-here:
+
+distclean-here:
+
+realclean-here:
+
+# ========== DEPENDENCIES FOR MAINTENANCE ==========
+
+@CONFIG_MK@
diff --git a/Functions/Misc/.distfiles b/Functions/Misc/.distfiles
new file mode 100644
index 000000000..eab3626b6
--- /dev/null
+++ b/Functions/Misc/.distfiles
@@ -0,0 +1,6 @@
+DISTFILES_SRC='
+    .distfiles
+    acx allopt cat cdmatch cdmatch2 checkmail cx harden mere multicomp
+    proto pushd randline run-help yp yu zed zless zls
+'
+
diff --git a/Functions/Misc/acx b/Functions/Misc/acx
new file mode 100755
index 000000000..f7c680bb0
--- /dev/null
+++ b/Functions/Misc/acx
@@ -0,0 +1,6 @@
+#! /bin/sh
+#
+# zsh shell function to make its arguments 755
+# also works as an sh script
+#
+chmod 755 $*
diff --git a/Functions/Misc/allopt b/Functions/Misc/allopt
new file mode 100644
index 000000000..604e76198
--- /dev/null
+++ b/Functions/Misc/allopt
@@ -0,0 +1,29 @@
+# This function lists options with the no's in front removed for
+# improved comprehension, i.e. `norcs off' becomes `rcs on'.
+# The format is otherwise like that with `kshoptionprint' set,
+# i.e. you can see all options whether on or off.
+# It can take a list of option names or parts thereof to search for
+# via egrep.
+#
+# Written by Sweth Chandramouli with hacks by Bart Schaefer.
+
+listalloptions () {
+   emulate -R zsh
+   builtin setopt localoptions kshoptionprint
+   local OPT_NAME OPT_PAIR OPT_VALUE
+   for OPT_PAIR in "${(f)$(builtin setopt)}" ; do
+      OPT_VALUE=${OPT_PAIR##* }
+      OPT_NAME=${OPT_PAIR%% *}
+      if [[ ${OPT_NAME#no} != ${OPT_NAME} ]] ; then
+         OPT_VALUE=${(L)${${OPT_VALUE:s/on/OFF}:s/off/on}} &&
+            OPT_NAME=${OPT_NAME#no};
+      fi;
+      echo ${(r:21:)OPT_NAME} ${OPT_VALUE}
+   done
+}
+
+if [[ -n $@ ]]; then
+    listalloptions | egrep "${(j.|.)@}"
+else
+    listalloptions
+fi
diff --git a/Functions/Misc/cat b/Functions/Misc/cat
new file mode 100644
index 000000000..612deac03
--- /dev/null
+++ b/Functions/Misc/cat
@@ -0,0 +1,16 @@
+#! /usr/local/bin/zsh -f
+
+local file
+
+if ((! ARGC)) then
+	set -- -
+fi
+
+for file
+do
+	if [[ "$file" == - ]] then
+		while read -u0ek 4096; do ; done
+	else
+		while read -u0ek 4096; do ; done < "$file"
+	fi
+done
diff --git a/Functions/Misc/cdmatch b/Functions/Misc/cdmatch
new file mode 100755
index 000000000..7c4bb9ae7
--- /dev/null
+++ b/Functions/Misc/cdmatch
@@ -0,0 +1,23 @@
+# Start of cdmatch.
+# Save in your functions directory and autoload, then do
+# compctl -x 'S[/][~][./][../]' -g '*(-/)' - \
+#         'n[-1,/], s[]' -K cdmatch -S '/' -- cd pushd
+#
+# Completes directories for cd, pushd, ... anything which knows about cdpath.
+# You do not have to include `.' in your cdpath.
+#
+# It works properly only if $ZSH_VERSION > 3.0-pre4.  Remove `emulate -R zsh'
+# for all other values of $ZSH_VERSION > 2.6-beta2. For earlier versions
+# it still works if RC_EXPAND_PARAM is not set or when cdpath is empty.
+emulate -R zsh
+setopt localoptions
+local narg pref cdp
+
+read -nc narg
+read -Ac pref
+
+cdp=(. $cdpath)
+reply=( ${^cdp}/${pref[$narg]%$2}*$2(-/DN^M:t) )
+
+return
+# End of cdmatch.
diff --git a/Functions/Misc/cdmatch2 b/Functions/Misc/cdmatch2
new file mode 100644
index 000000000..8a3e9591f
--- /dev/null
+++ b/Functions/Misc/cdmatch2
@@ -0,0 +1,15 @@
+# This function should be called from compctl to complete the
+# second argument of cd and pushd.
+
+emulate -R zsh				# Requires zsh 3.0-pre4 or later
+setopt localoptions extendedglob
+local from
+
+read -Ac from
+from="${from[2]}"
+
+eval "reply=( \${PWD:s@$from@$1*$2@}~$PWD(ND-/:) )"
+reply=( "${${reply[@]#${PWD%%$from*}}%${PWD#*$from}}" )
+[[ ${#reply[(r),-1]} != 0 ]] && reply[(r)]="''"
+
+return
diff --git a/Functions/Misc/checkmail b/Functions/Misc/checkmail
new file mode 100644
index 000000000..9cc743db4
--- /dev/null
+++ b/Functions/Misc/checkmail
@@ -0,0 +1,26 @@
+#! /usr/local/bin/zsh
+#
+# This autoloadable function checks the folders specified as arguments
+# for new mails.  The arguments are interpeted in exactly the same way
+# as the mailpath special zsh parameter (see zshparam(1)).
+#
+# If no arguments are given mailpath is used.  If mailpath is empty, $MAIL
+# is used and if that is also empty, /var/spool/mail/$LOGNAME is used.
+# This function requires zsh-3.0.1 or newer.
+#
+
+local file message
+
+for file in "${@:-${mailpath[@]:-${MAIL:-/var/spool/mail/$LOGNAME}}}"
+do
+	message="${${(M)file%%\?*}#\?}"
+	file="${file%%\?*}"
+	if [[ -d "$file" ]] then
+		file=( "$file"/**/*(.ND) )
+		if (($#file)) then
+			checkmail "${^file}\?$message"
+		fi
+	elif test -s "$file" -a -N "$file"; then  # this also sets $_ to $file
+		print -r -- "${(e)message:-You have new mail.}"
+	fi
+done
diff --git a/Functions/Misc/cx b/Functions/Misc/cx
new file mode 100755
index 000000000..a0b34a4f0
--- /dev/null
+++ b/Functions/Misc/cx
@@ -0,0 +1,6 @@
+#! /bin/sh
+#
+# zsh shell function to make its arguments executable
+# also works as a sh script
+#
+chmod +x $*
diff --git a/Functions/Misc/harden b/Functions/Misc/harden
new file mode 100644
index 000000000..c02689362
--- /dev/null
+++ b/Functions/Misc/harden
@@ -0,0 +1,6 @@
+#! /bin/sh
+# harden a link (convert it to a singly linked file)
+cp $1 $1.foo
+rm $1
+mv $1.foo $1
+
diff --git a/Functions/Misc/mere b/Functions/Misc/mere
new file mode 100644
index 000000000..cf8d8ad14
--- /dev/null
+++ b/Functions/Misc/mere
@@ -0,0 +1,3 @@
+#! /bin/sh
+# read a man page in the current directory
+nroff -man -Tman $1 | less -s
diff --git a/Functions/Misc/multicomp b/Functions/Misc/multicomp
new file mode 100755
index 000000000..c28558d95
--- /dev/null
+++ b/Functions/Misc/multicomp
@@ -0,0 +1,72 @@
+# multicomp() {
+# Completes all manner of files given prefixes for each path segment.
+# e.g. s/z/s -> src/zsh-2.4/src
+#
+# Usage: e.g.
+# compctl -D -f + -U -Q -S '' -K multicomp
+#
+# Will expand glob patterns already in the word, but use complete-word,
+# not TAB (expand-or-complete), or you will get ordinary glob expansion.
+# Requires the -U option to compctl.
+# Menucompletion is highly recommended for ambiguous matches.
+# Liable to screw up escaped metacharacters royally.
+# $fignore is not used: feel free to add your own bit.
+
+emulate -R zsh				# Requires zsh 3.0-pre4 or later
+local pref head sofar origtop newtop globdir="(-/)" wild
+setopt localoptions nullglob rcexpandparam globdots
+unsetopt markdirs globsubst shwordsplit nounset
+
+pref="${1}$2"
+# Hack to allow programmable completion to select multicomp after a :
+# (e.g.
+# compctl -D -f -x 's[:]' -U -Q -S '' -K multicomp
+# )
+pref="${pref#:}"
+
+sofar=('')
+reply=('')
+
+if [[ "$pref" = \~* ]]; then
+  # If the string started with ~, save the head and what it will become.
+  origtop="${pref%%/*}"
+  eval "newtop=$origtop"
+  # Save the expansion as the bit matched already
+  sofar=($newtop)
+  pref="${pref#$origtop}"
+fi
+
+while [[ -n "$pref" ]]; do
+  [[ "$pref" = /* ]] && sofar=(${sofar}/) && pref="${pref#/}"
+  head="${pref%%/*}"
+  pref="${pref#$head}"
+  [[ -z "$pref" ]] && globdir=
+  # if path segment contains wildcards, don't add another.
+  if [[ "$head" = *[\[\(\*\?\$\~]* ]]; then
+    wild=$head
+  else
+    # Simulate case-insensitive globbing for ASCII characters
+    wild="[${(j(][))${(s())head:l}}]*"	# :gs/a/[a]/ etc.
+    # The following could all be one expansion, but for readability:
+    wild=$wild:gs/a/aA/:gs/b/bB/:gs/c/cC/:gs/d/dD/:gs/e/eE/:gs/f/fF/
+    wild=$wild:gs/g/gG/:gs/h/hH/:gs/i/iI/:gs/j/jJ/:gs/k/kK/:gs/l/lL/
+    wild=$wild:gs/m/mM/:gs/n/nN/:gs/o/oO/:gs/p/pP/:gs/q/qQ/:gs/r/rR/
+    wild=$wild:gs/s/sS/:gs/t/tT/:gs/u/uU/:gs/v/vV/:gs/w/wW/:gs/x/xX/
+    wild=$wild:gs/y/yY/:gs/z/zZ/:gs/-/_/:gs/_/-_/:gs/[]//
+
+    # Expand on both sides of '.' (except when leading) as for '/'
+    wild="${${wild:gs/[.]/*.*/}#\*}"
+  fi
+
+  reply=(${sofar}"${wild}${globdir}")
+  reply=(${~reply})
+
+  [[ -z $reply[1] ]] && reply=() && break
+  [[ -n $pref ]] && sofar=($reply)
+done
+
+# Restore ~'s in front if there were any.
+# There had better not be anything funny in $newtop.
+[[ -n "$origtop" ]] && reply=("$origtop"${reply#$newtop})
+
+# }
diff --git a/Functions/Misc/proto b/Functions/Misc/proto
new file mode 100755
index 000000000..df1826506
--- /dev/null
+++ b/Functions/Misc/proto
@@ -0,0 +1,8 @@
+#! /bin/sh
+# generate prototypes, if your style is the same as mine
+for i
+do
+	rm $i:r.pro 2>/dev/null
+	grep -v '[{};:#]' $i | grep '^[A-Za-z]' |
+		grep -v static | sed 's/$/;/' >! $i:r.pro
+done
diff --git a/Functions/Misc/pushd b/Functions/Misc/pushd
new file mode 100644
index 000000000..965c774bf
--- /dev/null
+++ b/Functions/Misc/pushd
@@ -0,0 +1,13 @@
+# pushd function to emulate the old zsh behaviour.  With this function
+# pushd +/-n just lifts the selected element to the top of the stack
+# instead of just cycling the stack.
+
+emulate -R zsh
+setopt localoptions
+
+if [[ ARGC -eq 1 && "$1" == [+-]<-> ]] then
+	setopt pushdignoredups
+	builtin pushd ~$1
+else
+	builtin pushd "$@"
+fi
diff --git a/Functions/Misc/randline b/Functions/Misc/randline
new file mode 100755
index 000000000..7b06b7982
--- /dev/null
+++ b/Functions/Misc/randline
@@ -0,0 +1,3 @@
+# get a random line from a file
+integer z="$(wc -l <$1)"
+sed -n $[RANDOM%z+1]p $1
diff --git a/Functions/Misc/run-help b/Functions/Misc/run-help
new file mode 100644
index 000000000..a8109e3ea
--- /dev/null
+++ b/Functions/Misc/run-help
@@ -0,0 +1,72 @@
+#!/usr/local/bin/zsh
+#
+# Figure out where to get the best help, and get it.
+#
+# Install this function by placing it in your FPATH and then
+# adding to your .zshrc the lines:
+#	unalias run-help
+#	autoload run-help
+#
+
+emulate -R zsh
+setopt localoptions
+
+# Check whether Util/helpfiles has been used to generate zsh help
+if [[ $1 == "-l" ]]
+then
+    if [[ -n "${HELPDIR:-}" ]]
+    then
+	echo 'Here is a list of topics for which help is available:'
+	echo ""
+	print -rc $HELPDIR/*(:t)
+    else
+	echo 'There is no list of help topics available at this time'
+    fi
+    return 0
+elif [[ -n "${HELPDIR:-}" && -r $HELPDIR/$1 && $1 != compctl ]]
+then
+    ${=PAGER:-more} $HELPDIR/$1
+    return $?
+fi
+
+# No zsh help, use "whence" to figure out where else we might look
+local what places newline='
+'
+integer i=0 didman=0
+
+places=( "${(@f)$(builtin whence -va $1)}" )
+
+while ((i++ < $#places))
+do
+    what=$places[$i]
+    builtin print -r $what
+    case $what in
+    (*( is an alias)*)
+	[[ ${what[(w)6]:t} != ${what[(w)1]} ]] && run-help ${what[(w)6]:t}
+	;;
+    (*( is a * function))
+	builtin functions ${what[(w)1]} | ${=PAGER:-more}
+	;;
+    (*( is a * builtin))
+	case ${what[(w)1]} in
+	(compctl) man zshcompctl;;
+	(bindkey) man zshzle;;
+	(*setopt) man zshoptions;;
+	(*) man zshbuiltins;;
+	esac
+	;;
+    (*( is hashed to *))
+	man ${what[(w)-1]:t}
+	;;
+    (*)
+	((! didman++)) && man $1
+	;;
+    esac
+    if ((i < $#places && ! didman))
+    then
+	builtin print -nP "%SPress any key for more help or q to quit%s"
+	builtin read -k what
+	[[ $what != $newline ]] && echo
+	[[ $what == [qQ] ]] && break
+    fi
+done
diff --git a/Functions/Misc/yp b/Functions/Misc/yp
new file mode 100755
index 000000000..7e09613ef
--- /dev/null
+++ b/Functions/Misc/yp
@@ -0,0 +1,2 @@
+#! /bin/sh
+ypmatch $1 passwd
diff --git a/Functions/Misc/yu b/Functions/Misc/yu
new file mode 100755
index 000000000..3c5f170cf
--- /dev/null
+++ b/Functions/Misc/yu
@@ -0,0 +1,2 @@
+#! /bin/sh
+ypmatch $1 passwd.byuid
diff --git a/Functions/Misc/zed b/Functions/Misc/zed
new file mode 100644
index 000000000..e8e7212ef
--- /dev/null
+++ b/Functions/Misc/zed
@@ -0,0 +1,65 @@
+#
+# zed
+#
+# No other shell could do this.
+# Edit small files with the command line editor.
+# Use ^X^W to save, ^C to abort.
+# Option -f: edit shell functions.  (Also if called as fned.)
+#
+# Completion: use
+# compctl -f -x 'w[1,-f]' -F -- zed
+#
+
+local var fun cleanup
+# We do not want timeout while we are editing a file
+integer TMOUT=0
+
+[[ $1 = -f || $0 = fned ]] && fun=1
+[[ $1 = -(|-|f) ]] && shift
+
+[[ -z "$1" ]] && echo 'Usage: "zed filename" or "zed -f function"' && return 1
+
+# catch interrupts
+cleanup="$(bindkey -L "^M"; bindkey -L -M emacs "^X^W"; bindkey -aL "ZZ"
+    echo "trap - INT EXIT"; trap)"
+trap "return 130" INT
+trap "$cleanup" EXIT
+
+# don't mangle !'s
+setopt localoptions nobanghist
+
+bindkey "^M" self-insert-unmeta
+# Depending on your stty's, you may be able to use ^J as accept-line, else:
+bindkey -M emacs "^X^W" accept-line
+bindkey -a "ZZ" accept-line
+
+if ((fun)) then
+  var="$(functions $1)"
+  # If function is undefined but autoloadable, load it
+  if [[ $var = undefined* ]] then
+    local dir
+    for dir in $fpath; do
+      if [[ -f $dir/$1 ]] then
+	var="$1() {
+$(<$dir/$1)
+}"
+	break
+      fi
+    done
+  elif [[ -z $var ]] then
+    var="$1() {
+}"
+  fi
+  vared var && eval function "$var"
+else
+  [[ -f $1 ]] && var="$(<$1)"
+  while vared var
+  do
+    (print -r -- "$var" >| $1) && break
+    echo -n -e '\a'
+  done
+fi
+
+return 0
+
+# End of zed
diff --git a/Functions/Misc/zless b/Functions/Misc/zless
new file mode 100644
index 000000000..809ce35c7
--- /dev/null
+++ b/Functions/Misc/zless
@@ -0,0 +1,37 @@
+#!/usr/bin/zsh -f
+#
+# zsh function script to run less on various inputs, decompressing as required.
+# Author: Phil Pennock.  zsh-hacks@athenaeum.demon.co.uk
+# Modified by Bart Schaefer.
+# Thanks to zefram@fysh.org for a great deal of help in sorting this out,
+# ie wrt syntax for unsetting members of arrays and eval "$(...)" when I
+# asked for something better than . =(...)
+#
+# Use -zforce to pass through a display-formatting command
+#  zless -zforce 'bzip2 -dc' foo-no-dotbz2
+#  zless -zforce 'od -hc' foo-binfile
+#
+# If you can understand all of this without reference to zshexpn(1)
+# and zshparam(1) then you either have a photographic memory or you
+# need to get out more.
+#
+
+emulate -R zsh
+setopt localoptions
+
+[[ $# -ge 1 ]] || return
+local lessopts
+set -A lessopts
+integer i=1 loi=1
+while ((i <= $#))
+do
+  case $argv[i] in
+  -zforce) argv[i,i+2]=("=($argv[i+1] \"$argv[i+2]\")"); ((++i));;
+  -*) lessopts[loi++]=\"$argv[i]\"; argv[i]=(); continue;;
+  *.(gz|Z)) argv[i]="=(zcat \"$argv[i]\")";;
+  *.bz2) argv[i]="=(bzip2 -dc \"$argv[i]\")";;
+  *.bz) argv[i]="=(bzip -dc \"$argv[i]\")";;
+  esac
+  ((++i))
+done
+eval command less $lessopts $*
diff --git a/Functions/Misc/zls b/Functions/Misc/zls
new file mode 100644
index 000000000..22138cd6c
--- /dev/null
+++ b/Functions/Misc/zls
@@ -0,0 +1,72 @@
+# zls () {
+# simple internal ls using the stat module
+
+zmodload -i stat || return 1
+
+emulate -R zsh
+setopt localoptions
+
+local f opts='' L=L mod=: dirs list
+typeset -A stat
+
+dirs=()
+list=()
+
+while getopts ailLFdtuc f
+do
+    opts=$opts$f
+    if [[ $f == '?' ]] then
+	echo Usage: $0 [ -ailLFd ] [ filename ... ]
+	return 1
+    fi
+done
+shift OPTIND-1
+
+[[ $opts == *L* ]] && L=''
+[[ $opts == *F* ]] && mod=T$mod
+[[ $opts == *a* ]] && setopt globdots
+
+local time=mtime tmod=m
+[[ $opts == *u* ]] && time=atime tmod=a
+[[ $opts == *c* ]] && time=ctime tmod=c
+
+if ((! ARGC)) then
+    if [[ $opts = *t* ]]; then
+        set *(o$tmod)
+    else
+        set *
+    fi
+    opts=d$opts
+elif [[ $opts = *t* && $ARGC -gt 1 ]]; then
+    # another glaringly obvious zsh trick:  reorder the argv list
+    # by time, without messing up metacharacters inside
+    local n='$1'
+    for (( f = 2; f <= $ARGC; f++ )); do
+	n="$n|\$$f"
+    done
+    eval "argv=(($n)(o$tmod))"
+fi
+
+for f in $*
+do
+    stat -s$L -H stat -F "%b %e %H:%M" - $f || continue
+    if [[ $opts != *d* && $stat[mode] == d* ]] then
+	dirs=( $dirs $f )
+    elif [[ $opts == *l* ]] then
+	[[ $opts == *i* ]] && print -n "${(l:7:)stat[inode]} "
+	[[ -n $stat[link] ]] && f=( $f '->' $stat[link] ) || f=( $f($mod) )
+	print -r -- "$stat[mode] ${(l:3:)stat[nlink]} ${(r:8:)stat[uid]} " \
+		    "${(r:8:)stat[gid]} ${(l:8:)stat[size]} $stat[$time] $f"
+    else
+	f=( $f($mod) )
+	list=( "$list[@]" "${${(M)opts:%*i*}:+${(l:7:)stat[inode]} }$f" )
+    fi
+done
+(($#list)) && print -cr -- "$list[@]"
+while (($#dirs)) do
+    ((ARGC > $#dirs)) && echo
+    ((ARGC > 1)) && echo $dirs[1]:
+    (cd $dirs[1] && $0 -d$opts)
+    shift dirs
+done
+# }
diff --git a/Functions/README.zftp b/Functions/README.zftp
new file mode 100644
index 000000000..3b56f81d0
--- /dev/null
+++ b/Functions/README.zftp
@@ -0,0 +1,4 @@
+The Zftp directory contains a set of functions acting as a front end to the
+zftp command, provided as an add-on module.  They allow you to perform FTP
+tasks from within the shell using as many of the shell's own facilities
+as possible.  For more information, see the zshzftpsys manual page.
diff --git a/Functions/Zftp/.distfiles b/Functions/Zftp/.distfiles
new file mode 100644
index 000000000..c45e8d1c8
--- /dev/null
+++ b/Functions/Zftp/.distfiles
@@ -0,0 +1,7 @@
+DISTFILES_SRC='
+    .distfiles
+    zfanon zfautocheck zfcd zfcd_match zfcget zfclose zfcput zfdir
+    zfgcp zfget zfget_match zfhere zfinit zfls zfopen zfparams
+    zfpcp zfput zfrglob zfrtime zfstat zftp_chpwd zftp_progress
+    zftype zfuget zfuput
+'
diff --git a/INSTALL b/INSTALL
index e25ba08b2..c793ff827 100644
--- a/INSTALL
+++ b/INSTALL
@@ -115,6 +115,10 @@ To install the dynamically-loadable modules, do the command:
 To install the zsh man page, do the command:
     make install.man
 
+To install all the shell functions which come with the distribution, do the
+command:
+    make install.fns
+
 Or alternatively, you can install all the above with the command:
     make install
 
@@ -202,6 +206,33 @@ Any startup/shutdown script can be disabled by giving the
 --disable-scriptname option to "configure".  The --disable-etcdir option
 disables all startup/shutdown files which are not explicitely enabled.
 
+Shell functions
+---------------
+
+By default, the shell functions which are installed with `make install' or
+`make install.fns' go into the directory ${datadir}/zsh/functions, which
+unless you have specified --datadir is the same as
+${prefix}/share/zsh/functions ($prefix itself defaults to /usr/local, as
+described below).  This directory will also be compiled into the shell as
+the default directory for the variable $fpath/$FPATH. You can override it
+with --enable-fndir=directory; --disable-fndir or --enable-fndir=no will
+turn off both installation of functions and the setting of a default value
+for $fpath/$FPATH.
+
+You can control the functions which get installed by setting
+FUNCTIONS_INSTALL, either when running configure or when running `make
+install' or `make install.fns'.  It includes a list of files relative to
+either the Completion or Functions subdirectories.  By default, all the
+functions for the Completion system will be installed (see the zshcompsys
+manual page), i.e.
+  FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/*'
+and if the --enable-dynamic option was given, the functions in
+Functions/Zftp, which require the zftp module to be available (see the
+zshzftpsys manual page), will be included as well.  There are also some
+miscellaneous functions with documentation in comments; the complete set
+of functions can be installed with
+  FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* Misc/* Zftp/*'
+
 Support for large files and integers
 ------------------------------------
 
@@ -269,5 +300,6 @@ Features:
      zlogin=pathname     # the full pathname of the global zlogin script
      zprofile=pathname   # the full pathname of the global zprofile script
      zlogout=pathname    # the full pathname of the global zlogout script
+     fns=directory       # the directory where shell functions will go
      dynamic             # allow dynamically loaded binary modules
      lfs                 # allow configure check for large files
diff --git a/Makefile.in b/Makefile.in
index cd5420dbf..def71d50f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -63,8 +63,8 @@ install-strip:
 	$(MAKE) install STRIPFLAGS="-s"
 
 # install/uninstall everything (except info)
-install: install.bin install.modules install.man
-uninstall: uninstall.bin uninstall.modules uninstall.man
+install: install.bin install.modules install.man install.fns
+uninstall: uninstall.bin uninstall.modules uninstall.man uninstall.fns
 
 # install/uninstall just the binary
 install.bin uninstall.bin:
@@ -78,6 +78,11 @@ install.modules uninstall.modules:
 install.man uninstall.man:
 	@cd Doc && $(MAKE) $(MAKEDEFS) $@
 
+# install/uninstall just the shell functions
+install.fns uninstall.fns:
+	@cd Completion && $(MAKE) $(MAKEDEFS) $@
+	@cd Functions && $(MAKE) $(MAKEDEFS) $@
+
 # install/uninstall just the info pages
 install.info uninstall.info:
 	@cd Doc && $(MAKE) $(MAKEDEFS) $@
diff --git a/Misc/.distfiles b/Misc/.distfiles
index fab78c0d1..a02614511 100644
--- a/Misc/.distfiles
+++ b/Misc/.distfiles
@@ -1,5 +1,4 @@
 DISTFILES_SRC='
     .distfiles
     c2z compctl-examples globtests globtests.ksh lete2ctl
-    new-completion-examples zftp-functions
 '
diff --git a/Src/.distfiles b/Src/.distfiles
index 727c855cc..ce135a00e 100644
--- a/Src/.distfiles
+++ b/Src/.distfiles
@@ -1,11 +1,12 @@
 DISTFILES_SRC='
     .cvsignore .distfiles .exrc .indent.pro
     Makefile.in Makemod.in.in
-    ansi2knr.c
+    signames1.awk signames2.awk
+    ansi2knr.c modentry.c
     builtin.c compat.c cond.c exec.c glob.c hashtable.c hashtable.h
     hist.c init.c input.c jobs.c lex.c linklist.c loop.c main.c makepro.awk
     math.c mem.c mkbltnmlst.sh mkmakemod.sh mkmodindex.sh
     module.c options.c params.c parse.c prompt.c prototypes.h
-    signals.c signals.h signames.awk subst.c system.h text.c utils.c
-    watch.c xmods.conf zsh.h zsh.mdd ztype.h
+    signals.c signals.h subst.c system.h text.c utils.c
+    watch.c xmods.conf zsh.h zsh.mdd ztype.h zsh.export
 '
diff --git a/Src/Modules/.distfiles b/Src/Modules/.distfiles
index dbc152fa8..dc851bf9b 100644
--- a/Src/Modules/.distfiles
+++ b/Src/Modules/.distfiles
@@ -4,6 +4,7 @@ DISTFILES_SRC='
     clone.mdd clone.c
     example.mdd example.c
     files.mdd files.c
+    mapfile.mdd mapfile.c
     parameter.mdd parameter.c
     stat.mdd stat.c
     zftp.mdd zftp.c
diff --git a/Src/Modules/mapfile.c b/Src/Modules/mapfile.c
index e98da7889..41cae80b8 100644
--- a/Src/Modules/mapfile.c
+++ b/Src/Modules/mapfile.c
@@ -149,6 +149,7 @@ setpmmapfile(Param pm, char *value)
 	 * pages.  Honestly, I tried it without, and you need both.
 	 */
 	ftruncate(fd, len);
+	munmap(mmptr, len);
     }
 #else /* don't USE_MMAP */
     /* can't be bothered to do anything too clever here */
diff --git a/Src/Zle/.distfiles b/Src/Zle/.distfiles
index 42c62efe9..9dbf27758 100644
--- a/Src/Zle/.distfiles
+++ b/Src/Zle/.distfiles
@@ -1,10 +1,10 @@
 DISTFILES_SRC='
     .cvsignore .distfiles .exrc
-    comp1.mdd comp.h comp1.c
+    comp1.mdd comp.h comp1.c comp1.export
     compctl.mdd compctl.c
     deltochar.mdd deltochar.c
     zle.mdd iwidgets.list zle.h zle_bindings.c zle_hist.c
     zle_keymap.c zle_main.c zle_misc.c zle_move.c zle_params.c
     zle_refresh.c zle_things.sed zle_thingy.c zle_tricky.c
-    zle_utils.c zle_vi.c zle_widget.sed zle_word.c
+    zle_utils.c zle_vi.c zle_widget.sed zle_word.c zle.export
 '
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h
index caeb4d6c3..bf3ea816f 100644
--- a/Src/Zle/comp.h
+++ b/Src/Zle/comp.h
@@ -91,6 +91,7 @@ struct compcond {
 #define CCT_NUMWORDS  10
 #define CCT_RANGESTR  11
 #define CCT_RANGEPAT  12
+#define CCT_QUOTE     13
 
 /* Contains the real description for compctls */
 
@@ -107,6 +108,7 @@ struct compctl {
     char *ylist;		/* for -y (user-defined desc. for listing) */
     char *prefix, *suffix;	/* for -P and -S (prefix, suffix)          */
     char *subcmd;		/* for -l (command name to use)            */
+    char *substr;		/* for -1 (command name to use)            */
     char *withd;		/* for -w (with directory                  */
     char *hpat;			/* for -H (history pattern)                */
     int hnum;			/* for -H (number of events to search)     */
@@ -209,6 +211,7 @@ struct cmatch {
     char *prpre;		/* path prefix for opendir */
     char *pre;			/* prefix string from -P */
     char *suf;			/* suffix string from -S */
+    char autoq;			/* closing quote to add automatically */
     int flags;			/* see CMF_* below */
     int brpl;			/* the place where to put the brace prefix */
     int brsl;			/* ...and the suffix */
@@ -297,42 +300,79 @@ struct cadata {
 
 /* Flags for special parameters. */
 
-#define CP_WORDS      (1 <<  0)
-#define CP_CURRENT    (1 <<  1)
-#define CP_PREFIX     (1 <<  2)
-#define CP_SUFFIX     (1 <<  3)
-#define CP_IPREFIX    (1 <<  4)
-#define CP_ISUFFIX    (1 <<  5)
-#define CP_COMPSTATE  (1 <<  6)
-
-#define CP_REALPARAMS        7
-
-#define CP_NMATCHES   (1 <<  7)
-#define CP_MATCHER    (1 <<  8)
-#define CP_MATCHERSTR (1 <<  9)
-#define CP_MATCHERTOT (1 << 10)
-#define CP_CONTEXT    (1 << 11)
-#define CP_PARAMETER  (1 << 12)
-#define CP_REDIRECT   (1 << 13)
-#define CP_QUOTE      (1 << 14)
-#define CP_QUOTING    (1 << 15)
-#define CP_RESTORE    (1 << 16)
-#define CP_LIST       (1 << 17)
-#define CP_FORCELIST  (1 << 18)
-#define CP_INSERT     (1 << 19)
-#define CP_EXACT      (1 << 20)
-#define CP_EXACTSTR   (1 << 21)
-#define CP_PATMATCH   (1 << 22)
-#define CP_PATINSERT  (1 << 23)
-#define CP_UNAMBIG    (1 << 24)
-#define CP_UNAMBIGC   (1 << 25)
-#define CP_LISTMAX    (1 << 26)
-#define CP_LASTPROMPT (1 << 27)
-#define CP_TOEND      (1 << 28)
-#define CP_OLDLIST    (1 << 29)
-#define CP_OLDINS     (1 << 30)
-#define CP_VARED      (1 << 31)
-
-#define CP_NUM              32
-
-#define CP_ALLMASK    ((unsigned int) 0xffffffff)
+#define CPN_WORDS      0
+#define CP_WORDS       (1 <<  CPN_WORDS)
+#define CPN_CURRENT    1
+#define CP_CURRENT     (1 <<  CPN_CURRENT)
+#define CPN_PREFIX     2
+#define CP_PREFIX      (1 <<  CPN_PREFIX)
+#define CPN_SUFFIX     3
+#define CP_SUFFIX      (1 <<  CPN_SUFFIX)
+#define CPN_IPREFIX    4
+#define CP_IPREFIX     (1 <<  CPN_IPREFIX)
+#define CPN_ISUFFIX    5
+#define CP_ISUFFIX     (1 <<  CPN_ISUFFIX)
+#define CPN_QIPREFIX   6
+#define CP_QIPREFIX    (1 <<  CPN_QIPREFIX)
+#define CPN_QISUFFIX   7
+#define CP_QISUFFIX    (1 <<  CPN_QISUFFIX)
+#define CPN_COMPSTATE  8
+#define CP_COMPSTATE   (1 <<  CPN_COMPSTATE)
+
+#define CP_REALPARAMS  9
+#define CP_ALLREALS    ((unsigned int) 0x1ff)
+
+
+#define CPN_NMATCHES   0
+#define CP_NMATCHES    (1 <<  CPN_NMATCHES)
+#define CPN_MATCHER    1
+#define CP_MATCHER     (1 <<  CPN_MATCHER)
+#define CPN_MATCHERSTR 2
+#define CP_MATCHERSTR  (1 <<  CPN_MATCHERSTR)
+#define CPN_MATCHERTOT 3
+#define CP_MATCHERTOT  (1 <<  CPN_MATCHERTOT)
+#define CPN_CONTEXT    4
+#define CP_CONTEXT     (1 <<  CPN_CONTEXT)
+#define CPN_PARAMETER  5
+#define CP_PARAMETER   (1 <<  CPN_PARAMETER)
+#define CPN_REDIRECT   6
+#define CP_REDIRECT    (1 <<  CPN_REDIRECT)
+#define CPN_QUOTE      7
+#define CP_QUOTE       (1 <<  CPN_QUOTE)
+#define CPN_QUOTING    8
+#define CP_QUOTING     (1 <<  CPN_QUOTING)
+#define CPN_RESTORE    9
+#define CP_RESTORE     (1 <<  CPN_RESTORE)
+#define CPN_LIST       10
+#define CP_LIST        (1 << CPN_LIST)
+#define CPN_FORCELIST  11
+#define CP_FORCELIST   (1 << CPN_FORCELIST)
+#define CPN_INSERT     12
+#define CP_INSERT      (1 << CPN_INSERT)
+#define CPN_EXACT      13
+#define CP_EXACT       (1 << CPN_EXACT)
+#define CPN_EXACTSTR   14
+#define CP_EXACTSTR    (1 << CPN_EXACTSTR)
+#define CPN_PATMATCH   15
+#define CP_PATMATCH    (1 << CPN_PATMATCH)
+#define CPN_PATINSERT  16
+#define CP_PATINSERT   (1 << CPN_PATINSERT)
+#define CPN_UNAMBIG    17
+#define CP_UNAMBIG     (1 << CPN_UNAMBIG)
+#define CPN_UNAMBIGC   18
+#define CP_UNAMBIGC    (1 << CPN_UNAMBIGC)
+#define CPN_LISTMAX    19
+#define CP_LISTMAX     (1 << CPN_LISTMAX)
+#define CPN_LASTPROMPT 20
+#define CP_LASTPROMPT  (1 << CPN_LASTPROMPT)
+#define CPN_TOEND      21
+#define CP_TOEND       (1 << CPN_TOEND)
+#define CPN_OLDLIST    22
+#define CP_OLDLIST     (1 << CPN_OLDLIST)
+#define CPN_OLDINS     23
+#define CP_OLDINS      (1 << CPN_OLDINS)
+#define CPN_VARED      24
+#define CP_VARED       (1 << CPN_VARED)
+
+#define CP_KEYPARAMS   25
+#define CP_ALLKEYS     ((unsigned int) 0xffffff)
diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c
index 071a8e64a..ba8bcc868 100644
--- a/Src/Zle/comp1.c
+++ b/Src/Zle/comp1.c
@@ -47,7 +47,7 @@ Cmlist cmatcher;
 void (*makecompparamsptr) _((void));
 
 /**/
-void (*comp_setunsetptr) _((unsigned int, unsigned int));
+void (*comp_setunsetptr) _((int, int, int, int));
 
 /* pointers to functions required by compctl and defined by zle */
 
@@ -69,6 +69,9 @@ int (*makecomplistctlptr) _((int));
 /**/
 char *(*unambig_dataptr) _((int *));
 
+/**/
+int (*set_comp_sepptr) _((void));
+
 /* Hash table for completion info for commands */
  
 /**/
@@ -112,6 +115,8 @@ char **compwords,
      *compsuffix,
      *compiprefix,
      *compisuffix,
+     *compqiprefix,
+     *compqisuffix,
      *compmatcherstr,
      *compcontext,
      *compparameter,
@@ -133,7 +138,7 @@ char **compwords,
      *compvared;
 
 /**/
-Param *comppms;
+Param *comprpms, *compkpms;
 
 /* The function rembslash() came from zle_tricky.c, but is now used *
  * in compctl.c, too.                                               */
@@ -193,6 +198,7 @@ freecompctl(Compctl cc)
     zsfree(cc->hpat);
     zsfree(cc->gname);
     zsfree(cc->subcmd);
+    zsfree(cc->substr);
     if (cc->cond)
 	freecompcond(cc->cond);
     if (cc->ext) {
@@ -440,9 +446,10 @@ setup_comp1(Module m)
     cc_first.refc = 10000;
     cc_first.mask = 0;
     cc_first.mask2 = CC_CCCONT;
-    comppms = NULL;
+    comprpms = compkpms = NULL;
     compwords = NULL;
-    compprefix = compsuffix = compiprefix = compisuffix = compmatcherstr = 
+    compprefix = compsuffix = compiprefix = compisuffix = 
+	compqiprefix = compqisuffix = compmatcherstr = 
 	compcontext = compparameter = compredirect = compquote =
 	compquoting = comprestore = complist = compinsert =
 	compexact = compexactstr = comppatmatch = comppatinsert =
@@ -450,6 +457,7 @@ setup_comp1(Module m)
 	compoldlist = compoldins = compvared = NULL;
     makecompparamsptr = NULL;
     comp_setunsetptr = NULL;
+    set_comp_sepptr = NULL;
     return 0;
 }
 
@@ -481,6 +489,8 @@ finish_comp1(Module m)
     zsfree(compsuffix);
     zsfree(compiprefix);
     zsfree(compisuffix);
+    zsfree(compqiprefix);
+    zsfree(compqisuffix);
     zsfree(compmatcherstr);
     zsfree(compcontext);
     zsfree(compparameter);
diff --git a/Src/Zle/comp1.export b/Src/Zle/comp1.export
index 2dc285d3a..9b738cc78 100644
--- a/Src/Zle/comp1.export
+++ b/Src/Zle/comp1.export
@@ -19,6 +19,7 @@ compforcelist
 compinsert
 compiprefix
 compisuffix
+compkpms
 complastprompt
 complist
 complistmax
@@ -34,9 +35,12 @@ comppatmatch
 comppms
 compprefix
 compredirect
+compqiprefix
+compqisuffix
 compquote
 compquoting
 comprestore
+comprpms
 comp_setunsetptr
 comp_strptr
 compsuffix
@@ -56,4 +60,5 @@ makecomplistctlptr
 makecompparamsptr
 patcomps
 rembslash
+set_comp_sepptr
 unambig_dataptr
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index f644dfc38..c5b24714e 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -688,6 +688,22 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl)
 		    *argv = "" - 1;
 		}
 		break;
+	    case 'h':
+		if (cl) {
+		    zerrnam(name, "illegal option -%c", NULL, **argv);
+		    return 1;
+		} else if ((*argv)[1]) {
+		    cct.substr = (*argv) + 1;
+		    *argv = "" - 1;
+		} else if (!argv[1]) {
+		    zwarnnam(name, "command name expected after -%c", NULL,
+			    **argv);
+		    return 1;
+		} else {
+		    cct.substr = *++argv;
+		    *argv = "" - 1;
+		}
+		break;
 	    case 'W':
 		if ((*argv)[1]) {
 		    cct.withd = (*argv) + 1;
@@ -933,6 +949,9 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 		t++;
 	    /* First get the condition code */
 	    switch (*t) {
+	    case 'q':
+		c->type = CCT_QUOTE;
+		break;
 	    case 's':
 		c->type = CCT_CURSUF;
 		break;
@@ -1017,7 +1036,8 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 		c->u.r.a = (int *)zcalloc(n * sizeof(int));
 		c->u.r.b = (int *)zcalloc(n * sizeof(int));
 	    } else if (c->type == CCT_CURSUF ||
-		       c->type == CCT_CURPRE)
+		       c->type == CCT_CURPRE ||
+		       c->type == CCT_QUOTE)
 		c->u.s.s = (char **)zcalloc(n * sizeof(char *));
 
 	    else if (c->type == CCT_RANGESTR ||
@@ -1059,7 +1079,8 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 			c->u.r.b[l] = atoi(tt);
 		    }
 		} else if (c->type == CCT_CURSUF ||
-			   c->type == CCT_CURPRE) {
+			   c->type == CCT_CURPRE ||
+			   c->type == CCT_QUOTE) {
 		    /* -s[..] or -S[..]:  single string expected */
 		    for (; *t && *t != '\200'; t++)
 			if (*t == '\201')
@@ -1218,6 +1239,7 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass)
     zsfree(cc->prefix);
     zsfree(cc->suffix);
     zsfree(cc->subcmd);
+    zsfree(cc->substr);
     zsfree(cc->withd);
     zsfree(cc->hpat);
     zsfree(cc->gname);
@@ -1239,6 +1261,7 @@ cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass)
     cc->prefix = ztrdup(cct->prefix);
     cc->suffix = ztrdup(cct->suffix);
     cc->subcmd = ztrdup(cct->subcmd);
+    cc->substr = ztrdup(cct->substr);
     cc->withd = ztrdup(cct->withd);
     cc->gname = ztrdup(cct->gname);
     cc->hpat = ztrdup(cct->hpat);
@@ -1366,7 +1389,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
 {
     Compctl cc2;
     char *css = "fcqovbAIFpEjrzBRGudeNOZUnQmw/";
-    char *mss = " pcCwWsSnNmrR";
+    char *mss = " pcCwWsSnNmrRq";
     unsigned long t = 0x7fffffff;
     unsigned long flags = cc->mask, flags2 = cc->mask2;
     unsigned long oldshowmask;
@@ -1448,6 +1471,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
     printif(cc->glob, 'g');
     printif(cc->str, 's');
     printif(cc->subcmd, 'l');
+    printif(cc->substr, 'h');
     printif(cc->withd, 'W');
     if (cc->hpat) {
 	printf(" -H %d ", cc->hnum);
@@ -1484,6 +1508,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
 			    break;
 			case CCT_CURSUF:
 			case CCT_CURPRE:
+			case CCT_QUOTE:
 			    printqt(c->u.s.s[i]);
 			    break;
 			case CCT_RANGESTR:
@@ -2067,6 +2092,9 @@ bin_compset(char *name, char **argv, char *ops, int func)
     case 'P': test = CVT_PREPAT; break;
     case 's': test = CVT_SUFNUM; break;
     case 'S': test = CVT_SUFPAT; break;
+    case 'q': return !(compquote && *compquote &&
+		       (*compquote == '\'' || *compquote == '"') &&
+		       !set_comp_sepptr());
     default:
 	zerrnam(name, "bad option -%c", NULL, argv[0][1]);
 	return 1;
@@ -2135,19 +2163,25 @@ bin_compcall(char *name, char **argv, char *ops, int func)
  * order of the CP_* bits in comp.h */
 
 #define VAL(X) ((void *) (&(X)))
-static struct compparam {
+struct compparam {
     char *name;
     int type;
     void *var, *set, *get;
-} compparams[] = {
+};
+
+static struct compparam comprparams[] = {
     { "words", PM_ARRAY, VAL(compwords), NULL, NULL },
     { "CURRENT", PM_INTEGER, VAL(compcurrent), NULL, NULL },
     { "PREFIX", PM_SCALAR, VAL(compprefix), NULL, NULL },
     { "SUFFIX", PM_SCALAR, VAL(compsuffix), NULL, NULL },
     { "IPREFIX", PM_SCALAR, VAL(compiprefix), NULL, NULL },
     { "ISUFFIX", PM_SCALAR, VAL(compisuffix), NULL, NULL },
-    { NULL, 0, NULL, NULL, NULL },
+    { "QIPREFIX", PM_SCALAR | PM_READONLY, VAL(compqiprefix), NULL, NULL },
+    { "QISUFFIX", PM_SCALAR | PM_READONLY, VAL(compqisuffix), NULL, NULL },
+    { NULL, 0, NULL, NULL, NULL }
+};
 
+static struct compparam compkparams[] = {
     { "nmatches", PM_INTEGER, VAL(compnmatches), NULL, NULL },
     { "matcher", PM_INTEGER, VAL(compmatcher), NULL, NULL },
     { "matcher_string", PM_SCALAR, VAL(compmatcherstr), NULL, NULL },
@@ -2155,8 +2189,8 @@ static struct compparam {
     { "context", PM_SCALAR, VAL(compcontext), NULL, NULL },
     { "parameter", PM_SCALAR, VAL(compparameter), NULL, NULL },
     { "redirect", PM_SCALAR, VAL(compredirect), NULL, NULL },
-    { "quote", PM_SCALAR, VAL(compquote), NULL, NULL },
-    { "quoting", PM_SCALAR, VAL(compquoting), NULL, NULL },
+    { "quote", PM_SCALAR | PM_READONLY, VAL(compquote), NULL, NULL },
+    { "quoting", PM_SCALAR | PM_READONLY, VAL(compquoting), NULL, NULL },
     { "restore", PM_SCALAR, VAL(comprestore), NULL, NULL },
     { "list", PM_SCALAR, VAL(complist), NULL, NULL },
     { "force_list", PM_SCALAR, VAL(compforcelist), NULL, NULL },
@@ -2179,11 +2213,9 @@ static struct compparam {
 
 #define COMPSTATENAME "compstate"
 
-static struct compparam *
-addcompparams(struct compparam *cp)
+static void
+addcompparams(struct compparam *cp, Param *pp)
 {
-    Param *pp = comppms + (cp - compparams);
-
     for (; cp->name; cp++, pp++) {
 	Param pm = createparam(cp->name, cp->type | PM_SPECIAL | PM_REMOVABLE);
 	if (!pm)
@@ -2214,31 +2246,29 @@ addcompparams(struct compparam *cp)
 	}
 	pm->unsetfn = compunsetfn;
     }
-    return cp;
 }
 
 /**/
 void
 makecompparams(void)
 {
-    struct compparam *cp;
     Param cpm;
     HashTable tht;
 
-    cp = addcompparams(compparams);
+    addcompparams(comprparams, comprpms);
 
     if (!(cpm = createparam(COMPSTATENAME, PM_SPECIAL|PM_REMOVABLE|PM_HASHED)))
 	cpm = (Param) paramtab->getnode(paramtab, COMPSTATENAME);
     DPUTS(!cpm, "param not set in makecompparams");
 
-    comppms[cp - compparams] = cpm;
+    comprpms[CPN_COMPSTATE] = cpm;
     tht = paramtab;
     cpm->level = locallevel;
     cpm->gets.hfn = get_compstate;
     cpm->sets.hfn = set_compstate;
     cpm->unsetfn = compunsetfn;
-    cpm->u.hash = paramtab = newparamtable(17, COMPSTATENAME);
-    addcompparams(cp + 1);
+    cpm->u.hash = paramtab = newparamtable(31, COMPSTATENAME);
+    addcompparams(compkparams, compkpms);
     paramtab = tht;
 }
 
@@ -2262,8 +2292,8 @@ set_compstate(Param pm, HashTable ht)
 
     for (i = 0; i < ht->hsize; i++)
 	for (hn = ht->nodes[i]; hn; hn = hn->next)
-	    for (cp = compparams + CP_REALPARAMS,
-		 pp = comppms + CP_REALPARAMS; cp->name; cp++, pp++)
+	    for (cp = compkparams,
+		 pp = compkpms; cp->name; cp++, pp++)
 		if (!strcmp(hn->nam, cp->name)) {
 		    v.isarr = v.inv = v.a = 0;
 		    v.b = -1;
@@ -2318,20 +2348,25 @@ compunsetfn(Param pm, int exp)
 
 /**/
 void
-comp_setunset(unsigned int set, unsigned int unset)
+comp_setunset(int rset, int runset, int kset, int kunset)
 {
     Param *p;
 
-    if (!comppms)
-	return;
-
-    set &= CP_ALLMASK;
-    unset &= CP_ALLMASK;
-    for (p = comppms; set || unset; set >>= 1, unset >>= 1, p++) {
-	if (set & 1)
-	    (*p)->flags &= ~PM_UNSET;
-	if (unset & 1)
-	    (*p)->flags |= PM_UNSET;
+    if (comprpms && (rset >= 0 || runset >= 0)) {
+	for (p = comprpms; rset || runset; rset >>= 1, runset >>= 1, p++) {
+	    if (rset & 1)
+		(*p)->flags &= ~PM_UNSET;
+	    if (runset & 1)
+		(*p)->flags |= PM_UNSET;
+	}
+    }
+    if (comprpms && (kset >= 0 || kunset >= 0)) {
+	for (p = compkpms; kset || kunset; kset >>= 1, kunset >>= 1, p++) {
+	    if (kset & 1)
+		(*p)->flags &= ~PM_UNSET;
+	    if (kunset & 1)
+		(*p)->flags |= PM_UNSET;
+	}
     }
 }
 
@@ -2343,16 +2378,19 @@ comp_wrapper(List list, FuncWrap w, char *name)
 	return 1;
     else {
 	char *orest, *opre, *osuf, *oipre, *oisuf, **owords;
+	char *oqipre, *oqisuf, *oq, *oqi;
 	zlong ocur;
-	unsigned int unset = 0, m, sm;
+	unsigned int runset = 0, kunset = 0, m, sm;
 	Param *pp;
 
 	m = CP_WORDS | CP_CURRENT | CP_PREFIX | CP_SUFFIX | 
-	    CP_IPREFIX | CP_ISUFFIX | CP_RESTORE;
-	for (pp = comppms, sm = 1; m; pp++, m >>= 1, sm <<= 1) {
+	    CP_IPREFIX | CP_ISUFFIX | CP_QIPREFIX | CP_QISUFFIX;
+	for (pp = comprpms, sm = 1; m; pp++, m >>= 1, sm <<= 1) {
 	    if ((m & 1) && ((*pp)->flags & PM_UNSET))
-		unset |= sm;
+		runset |= sm;
 	}
+	if (compkpms[CPN_RESTORE]->flags & PM_UNSET)
+	    kunset = CP_RESTORE;
 	orest = comprestore;
 	comprestore = ztrdup("auto");
 	ocur = compcurrent;
@@ -2360,6 +2398,10 @@ comp_wrapper(List list, FuncWrap w, char *name)
 	osuf = dupstring(compsuffix);
 	oipre = dupstring(compiprefix);
 	oisuf = dupstring(compisuffix);
+	oqipre = dupstring(compqiprefix);
+	oqisuf = dupstring(compqisuffix);
+	oq = dupstring(compquote);
+	oqi = dupstring(compquoting);
 
 	HEAPALLOC {
 	    owords = arrdup(compwords);
@@ -2377,18 +2419,27 @@ comp_wrapper(List list, FuncWrap w, char *name)
 	    compiprefix = ztrdup(oipre);
 	    zsfree(compisuffix);
 	    compisuffix = ztrdup(oisuf);
+	    zsfree(compqiprefix);
+	    compqiprefix = ztrdup(oqipre);
+	    zsfree(compqisuffix);
+	    compqisuffix = ztrdup(oqisuf);
+	    zsfree(compquote);
+	    compquote = ztrdup(oq);
+	    zsfree(compquoting);
+	    compquoting = ztrdup(oqi);
 	    freearray(compwords);
 	    PERMALLOC {
 		compwords = arrdup(owords);
 	    } LASTALLOC;
 	    comp_setunset(CP_COMPSTATE |
-			  (~unset & (CP_WORDS | CP_CURRENT | CP_PREFIX |
+			  (~runset & (CP_WORDS | CP_CURRENT | CP_PREFIX |
 				     CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX |
-				     CP_RESTORE)),
-			  unset);
+				     CP_QIPREFIX | CP_QISUFFIX)),
+			  (runset & CP_ALLREALS),
+			  (~kunset & CP_RESTORE), (kunset & CP_ALLKEYS));
 	} else
-	    comp_setunset(CP_COMPSTATE | (~unset & CP_RESTORE),
-			  (unset & CP_RESTORE));
+	    comp_setunset(CP_COMPSTATE, 0, (~kunset & CP_RESTORE),
+			  (kunset & CP_RESTORE));
 	zsfree(comprestore);
 	comprestore = orest;
 
diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c
index d2b9a3233..2fc55e98c 100644
--- a/Src/Zle/zle_hist.c
+++ b/Src/Zle/zle_hist.c
@@ -76,7 +76,8 @@ forget_edits(void)
 void
 uphistory(void)
 {
-    if (!zle_goto_hist(histline, -zmult) && isset(HISTBEEP))
+    int nodups = isset(HISTIGNOREDUPS);
+    if (!zle_goto_hist(histline, -zmult, nodups) && isset(HISTBEEP))
 	feep();
 }
 
@@ -267,7 +268,8 @@ acceptlineanddownhistory(void)
 void
 downhistory(void)
 {
-    if (!zle_goto_hist(histline, zmult) && isset(HISTBEEP))
+    int nodups = isset(HISTIGNOREDUPS);
+    if (!zle_goto_hist(histline, zmult, nodups) && isset(HISTBEEP))
 	feep();
 }
 
@@ -370,7 +372,7 @@ beginningofbufferorhistory(void)
 void
 beginningofhistory(void)
 {
-    if (!zle_goto_hist(firsthist(), 0) && isset(HISTBEEP))
+    if (!zle_goto_hist(firsthist(), 0, 0) && isset(HISTBEEP))
 	feep();
 }
 
@@ -388,7 +390,7 @@ endofbufferorhistory(void)
 void
 endofhistory(void)
 {
-    zle_goto_hist(curhist, 0);
+    zle_goto_hist(curhist, 0, 0);
 }
 
 /**/
@@ -472,9 +474,14 @@ setlocalhistory(void)
 
 /**/
 int
-zle_goto_hist(int ev, int n)
+zle_goto_hist(int ev, int n, int skipdups)
 {
     Histent he = movehistent(quietgethist(ev), n, hist_skip_flags);
+    if (skipdups && n) {
+	n = n < 0? -1 : 1;
+	while (he && !metadiffer(ZLETEXT(he), (char *) line, ll))
+	    he = movehistent(he, n, hist_skip_flags);
+    }
     if (!he)
 	return 0;
     zle_setline(he);
@@ -906,7 +913,7 @@ vifetchhistory(void)
 	    return;
 	}
     }
-    if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist, 0) &&
+    if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist, 0, 0) &&
 	isset(HISTBEEP))
 	feep();
 }
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index dfb437308..13f3cc402 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -640,7 +640,7 @@ execzlefunc(Thingy func)
 	    zsfree(msg);
 	    feep();
 	} else {
-	    int osc = sfcontext;
+	    int osc = sfcontext, osi = movefd(0);
 
 	    startparamscope();
 	    makezleparams(0);
@@ -650,6 +650,7 @@ execzlefunc(Thingy func)
 	    endparamscope();
 	    lastcmd = 0;
 	    r = 1;
+	    redup(osi, 0);
 	}
     }
     if (r) {
@@ -952,6 +953,7 @@ setup_zle(Module m)
     makecomplistcallptr = makecomplistcall;
     makecomplistctlptr = makecomplistctl;
     unambig_dataptr = unambig_data;
+    set_comp_sepptr = set_comp_sep;
 
     /* initialise the thingies */
     init_thingies();
@@ -1027,6 +1029,7 @@ finish_zle(Module m)
     makecomplistcallptr = NULL;
     makecomplistctlptr = NULL;
     unambig_dataptr = NULL;
+    set_comp_sepptr = NULL;
 
     return 0;
 }
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 30c31c358..c12c5894b 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -127,6 +127,7 @@ killwholeline(void)
 	for (i = cs; i != ll && line[i] != '\n'; i++);
 	forekill(i - cs + (i != ll), fg);
     }
+    clearlist = 1;
 }
 
 /**/
@@ -787,7 +788,9 @@ static char *suffixfunc;
 void
 makesuffix(int n)
 {
-    suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] = n;
+    suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] =
+	suffixlen[';'] = suffixlen['|'] = suffixlen['&'] = 
+	suffixlen['<'] = suffixlen['>'] = n;
 }
 
 /* Set up suffix for parameter names: the last n characters are a suffix *
diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c
index 7169f5700..aec1c1767 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -476,7 +476,7 @@ vigotomark(void)
 	feep();
 	return;
     }
-    if (curhist != vimarkline[ch] && !zle_goto_hist(vimarkline[ch], 0)) {
+    if (curhist != vimarkline[ch] && !zle_goto_hist(vimarkline[ch], 0, 0)) {
 	vimarkline[ch] = 0;
 	feep();
 	return;
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 9742ba501..ac18f52f0 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -268,10 +268,13 @@ zrefresh(void)
     if (clearlist && listshown) {
 	if (tccan(TCCLEAREOD)) {
 	    int ovln = vln, ovcs = vcs;
+	    char *nb = nbuf[vln];
 
+	    nbuf[vln] = obuf[vln];
 	    moveto(nlnct, 0);
 	    tcout(TCCLEAREOD);
 	    moveto(ovln, ovcs);
+	    nbuf[vln] = nb;
 	} else {
 	    invalidatelist();
 	    moveto(0, 0);
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index 41ea12e77..281fe211d 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -63,6 +63,11 @@ dopestring;
 
 #define inststr(X) inststrlen((X),1,-1)
 
+/* The line before completion was tried. */
+
+static char *origline;
+static int origcs;
+
 /* wb and we hold the beginning/end position of the word we are completing. */
 
 static int wb, we;
@@ -177,6 +182,8 @@ static Comp patcomp, filecomp;
  * prpre       -- ppre in expanded form usable for opendir                 *
  * ipre,ripre  -- the ignored prefix (quoted and unquoted)                 *
  * isuf        -- the ignored suffix                                       *
+ * qipre, qisuf-- ingnored quoted string                                   *
+ * autoq       -- quotes to automatically insert                           *
  *                                                                         *
  * The integer variables hold the lengths of lpre, lsuf, rpre, rsuf,       *
  * fpre, fsuf, lppre, and lpsuf.  noreal is non-zero if we have rpre/rsuf. */
@@ -188,6 +195,7 @@ static char *fpre, *fsuf;
 static char *ipre, *ripre;
 static char *isuf;
 static char *qfpre, *qfsuf, *qrpre, *qrsuf, *qlpre, *qlsuf;
+static char *qipre, *qisuf, autoq;
 static int lpl, lsl, rpl, rsl, fpl, fsl, lppl, lpsl;
 static int noreal;
 
@@ -559,7 +567,7 @@ acceptandmenucomplete(void)
 /* These are flags saying if we are completing in the command *
  * position, in a redirection, or in a parameter expansion.   */
 
-static int lincmd, linredir, ispar, linwhat, linarr;
+static int lincmd, linredir, ispar, parq, eparq, linwhat, linarr;
 
 /* The string for the redirection operator. */
 
@@ -673,21 +681,24 @@ cmphaswilds(char *str)
 /* Check if we have to complete a parameter name. */
 
 static char *
-check_param(char *s, int set)
+check_param(char *s, int set, char **ep)
 {
     char *p;
+    int bq = 0, eq = 0, i;
 
-    ispar = 0;
+    if (!ep)
+	ispar = parq = eparq = 0;
     /* Try to find a `$'. */
-    for (p = s + offs; p > s && *p != String; p--);
-    if (*p == String) {
+    for (p = s + offs; p > s && *p != String && *p != Qstring; p--);
+    if (*p == String || *p == Qstring) {
 	/* Handle $$'s */
-	while (p > s && p[-1] == String)
+	while (p > s && (p[-1] == String || p[-1] == Qstring))
 	    p--;
-	while (p[1] == String && p[2] == String)
+	while ((p[1] == String || p[1] == Qstring) &&
+	       (p[2] == String || p[2] == Qstring))
 	    p += 2;
     }
-    if (*p == String &&	p[1] != Inpar && p[1] != Inbrack) {
+    if ((*p == String || *p == Qstring) && p[1] != Inpar && p[1] != Inbrack) {
 	/* This is really a parameter expression (not $(...) or $[...]). */
 	char *b = p + 1, *e = b;
 	int n = 0, br = 1;
@@ -714,6 +725,12 @@ check_param(char *s, int set)
 	    b++;
 
 	e = b;
+	if (br) {
+	    while (*e == (ep ? Dnull : '"'))
+		e++, parq++, bq++;
+	    if (!ep)
+		b = e;
+	}
 	/* Find the end of the name. */
 	if (*e == Quest || *e == Star || *e == String || *e == Qstring ||
 	    *e == '?'   || *e == '*'  || *e == '$'    ||
@@ -730,22 +747,44 @@ check_param(char *s, int set)
 
 	/* Now make sure that the cursor is inside the name. */
 	if (offs <= e - s && offs >= b - s && n <= 0) {
+	    if (br) {
+		p = e;
+		while (*p == (ep ? Dnull : '"'))
+		    p++, parq--, eparq++, eq++;
+	    }
 	    /* It is. */
+	    if (ep) {
+		*ep = e;
+		return b;
+	    }
 	    /* If we were called from makecomplistflags(), we have to set the
 	     * global variables. */
+
 	    if (set) {
 		if (br >= 2)
 		    mflags |= CMF_PARBR;
 
 		/* Get the prefix (anything up to the character before the name). */
-		lpsuf = dupstring(quotename(e, NULL));
+		for (i = eq, p = e; i; i--, p++)
+		    *p = '.';
+		isuf = quotename(e, NULL);
+		for (i = eq, p = isuf; i; i--, p++)
+		    *p = '"';
 		*e = '\0';
-		lpsl = strlen(lpsuf);
 		ripre = dupstring(s);
 		ripre[b - s] = '\0';
-		ipre = dupstring(quotename(ripre, NULL));
+		for (i = bq, p = ripre + (b - s) - 1; i; i--, p--)
+		    *p = '.';
+		ipre = quotename(ripre, NULL);
+		for (i = bq, p = ripre + strlen(ripre) - 1; i; i--, p--)
+		    *p = '"';
+		for (i = bq, p = ipre + strlen(ipre) - 1; i; i--, p--)
+		    *p = '"';
 		untokenize(ipre);
 	    }
+	    else
+		parq = eparq = 0;
+
 	    /* And adjust wb, we, and offs again. */
 	    offs -= b - s;
 	    wb = cs - offs;
@@ -817,8 +856,15 @@ docomplete(int lst)
 	ol = NULL;
     inwhat = IN_NOTHING;
     qword = NULL;
+    zsfree(qipre);
+    qipre = ztrdup("");
+    zsfree(qisuf);
+    qisuf = ztrdup("");
+    autoq = '\0';
     /* Get the word to complete. */
     noerrs = 1;
+    origline = dupstring((char *) line);
+    origcs = cs;
     s = get_comp_string();
     DPUTS(wb < 0 || cs < wb || cs > we,
 	  "BUG: 0 <= wb <= cs <= we is not true!");
@@ -1152,7 +1198,8 @@ get_comp_string(void)
     noaliases = isset(COMPLETEALIASES);
 
     /* Find out if we are somewhere in a `string', i.e. inside '...', *
-     * "...", `...`, or ((...)).                                      */
+     * "...", `...`, or ((...)). Nowadays this is only used to find   *
+     * out if we are inside `...`.                                    */
 
     for (i = j = k = 0, p = (char *)line; p < (char *)line + cs; p++)
 	if (*p == '`' && !(k & 1))
@@ -1163,28 +1210,9 @@ get_comp_string(void)
 	    k++;
 	else if (*p == '\\' && p[1] && !(k & 1))
 	    p++;
-    instring = (j & 1) ? 2 : (k & 1);
     inbackt = (i & 1);
+    instring = 0;
     addx(&tmp);
-    if (instring) {
-	/* Yes, we are in a string. */
-	if (!tmp) {
-	    tmp = (char *)line;
-	    line = (unsigned char *) dupstring((char *) line);
-	}
-	/* Now remove the quotes.                                   *
-	 * What??  Why that??  Well, we want to be able to complete *
-	 * inside strings.  The lexer code gives us no help here,   *
-	 * so we have to cheat.  We remove the quotes, the lexer    *
-	 * will then treat the words in the strings normally and we *
-	 * can complete them.                                       *
-	 * This is completely the wrong thing to do, but it's       *
-	 * occasionally useful, and we can't handle quotes properly *
-	 * yet anyway.                                              */
-	for (p = (char *)line; *p; p++)
-	    if (*p == '"' || *p == '\'')
-		*p = ' ';
-    }
     linptr = (char *)line;
     pushheap();
     HEAPALLOC {
@@ -1227,6 +1255,16 @@ get_comp_string(void)
 	    if (linarr)
 		incmdpos = 0;
 	    ctxtlex();
+
+	    if (tok == LEXERR) {
+		if (!tokstr)
+		    break;
+		for (j = 0, p = tokstr; *p; p++)
+		    if (*p == Snull || *p == Dnull)
+			j++;
+		if (j & 1)
+		    tok = STRING;
+	    }
 	    if (tok == ENVARRAY) {
 		linarr = 1;
 		zsfree(varname);
@@ -1496,8 +1534,28 @@ get_comp_string(void)
 	}
 	/* This variable will hold the current word in quoted form. */
 	qword = ztrdup(s);
-	/* While building the quoted form, we also clean up the command line. */
 	offs = cs - wb;
+	if ((p = check_param(s, 0, &tt))) {
+	    for (; *p == Dnull; p++)
+		*p = '"';
+	    for (; *tt == Dnull; tt++)
+		*tt = '"';
+	}
+	if (*s == Snull || *s == Dnull) {
+	    char *q = (*s == Snull ? "'" : "\""), *n = tricat(qipre, q, "");
+	    int sl = strlen(s);
+
+	    instring = (*s == Snull ? 1 : 2);
+	    zsfree(qipre);
+	    qipre = n;
+	    if (sl > 1 && s[sl - 1] == *s) {
+		n = tricat(q, qisuf, "");
+		zsfree(qisuf);
+		qisuf = n;
+	    }
+	    autoq = *q;
+	}
+	/* While building the quoted form, we also clean up the command line. */
 	for (p = s, tt = qword, i = wb; *p; p++, tt++, i++)
 	    if (INULL(*p)) {
 		if (i < cs)
@@ -3367,7 +3425,9 @@ add_match_data(int alt, char *str, Cline line,
 {
     Cmatch cm;
     Aminfo ai = (alt ? fainfo : ainfo);
-    int palen = 0, salen = 0, ipl = 0, pl = 0, ppl = 0, isl = 0, psl = 0;
+    int palen, salen, qipl, ipl, pl, ppl, qisl, isl, psl;
+
+    palen = salen = qipl = ipl = pl = ppl = isl = psl = 0;
 
     DPUTS(!line, "BUG: add_match_data() without cline");
 
@@ -3377,41 +3437,60 @@ add_match_data(int alt, char *str, Cline line,
 	salen = (psl = strlen(psuf));
     if (isuf)
 	salen += (isl = strlen(isuf));
+    if (qisuf)
+	salen += (qisl = strlen(qisuf));
 
     if (salen) {
 	char *asuf = (char *) zhalloc(salen);
-	Cline pp, p, s;
+	Cline pp, p, s, sl = NULL;
 
 	if (psl)
 	    memcpy(asuf, psuf, psl);
 	if (isl)
 	    memcpy(asuf + psl, isuf, isl);
-
-	s = bld_parts(asuf, salen, salen, NULL);
+	if (qisl)
+	    memcpy(asuf + psl + isl, qisuf, qisl);
 
 	for (pp = NULL, p = line; p->next; pp = p, p = p->next);
 
-	if (!(p->flags & (CLF_SUF | CLF_MID)) &&
-	    !p->llen && !p->wlen && !p->olen) {
-	    if (p->prefix) {
-		Cline q;
+	if (salen > qisl) {
+	    s = bld_parts(asuf, salen - qisl, salen - qisl, &sl);
 
-		for (q = p->prefix; q->next; q = q->next);
-		q->next = s->prefix;
-		s->prefix = p->prefix;
-		p->prefix = NULL;
-	    }
-	    free_cline(p);
-	    if (pp)
-		pp->next = s;
+	    if (!(p->flags & (CLF_SUF | CLF_MID)) &&
+		!p->llen && !p->wlen && !p->olen) {
+		if (p->prefix) {
+		    Cline q;
+
+		    for (q = p->prefix; q->next; q = q->next);
+		    q->next = s->prefix;
+		    s->prefix = p->prefix;
+		    p->prefix = NULL;
+		}
+		free_cline(p);
+		if (pp)
+		    pp->next = s;
+		else
+		    line = s;
+	    } else
+		p->next = s;
+	}
+	if (qisl) {
+	    Cline qsl = bld_parts(asuf + psl + isl, qisl, qisl, NULL);
+
+	    qsl->flags |= CLF_SUF;
+	    qsl->suffix = qsl->prefix;
+	    qsl->prefix = NULL;
+	    if (sl)
+		sl->next = qsl;
 	    else
-		line = s;
-	} else
-	    p->next = s;
+		p->next = qsl;
+	}
     }
     /* And the same for the prefix. */
+    if (qipre)
+	palen = (qipl = strlen(qipre));
     if (ipre)
-	palen = (ipl = strlen(ipre));
+	palen += (ipl = strlen(ipre));
     if (pre)
 	palen += (pl = strlen(pre));
     if (ppre)
@@ -3421,12 +3500,14 @@ add_match_data(int alt, char *str, Cline line,
 	char *apre = (char *) zhalloc(palen);
 	Cline p, lp;
 
+	if (qipl)
+	    memcpy(apre, qipre, qipl);
 	if (ipl)
-	    memcpy(apre, ipre, ipl);
+	    memcpy(apre + qipl, ipre, ipl);
 	if (pl)
-	    memcpy(apre + ipl, pre, pl);
+	    memcpy(apre + qipl + ipl, pre, pl);
 	if (ppl)
-	    memcpy(apre + ipl + pl, ppre, ppl);
+	    memcpy(apre + qipl + ipl + pl, ppre, ppl);
 
 	p = bld_parts(apre, palen, palen, &lp);
 	if (lp->prefix && !(line->flags & (CLF_SUF | CLF_MID))) {
@@ -3461,14 +3542,21 @@ add_match_data(int alt, char *str, Cline line,
     cm->ppre = (ppre && *ppre ? ppre : NULL);
     cm->psuf = (psuf && *psuf ? psuf : NULL);
     cm->prpre = ((flags & CMF_FILE) && prpre && *prpre ? prpre : NULL);
-    cm->ipre = (ipre && *ipre ? ipre : NULL);
+    if (qipre && *qipre)
+	cm->ipre = (ipre && *ipre ? dyncat(qipre, ipre) : dupstring(qipre));
+    else
+	cm->ipre = (ipre && *ipre ? ipre : NULL);
     cm->ripre = (ripre && *ripre ? ripre : NULL);
-    cm->isuf = (isuf && *isuf ? isuf : NULL);
+    if (qisuf && *qisuf)
+	cm->isuf = (isuf && *isuf ? dyncat(isuf, qisuf) : dupstring(qisuf));
+    else
+	cm->isuf = (isuf && *isuf ? isuf : NULL);
     cm->pre = pre;
     cm->suf = suf;
     cm->flags = flags;
     cm->brpl = bpl;
     cm->brsl = bsl;
+    cm->autoq = (autoq ? autoq : (inbackt ? '`' : '\0'));
     cm->rems = cm->remf = NULL;
     addlinknode((alt ? fmatches : matches), cm);
 
@@ -3505,14 +3593,14 @@ add_match_data(int alt, char *str, Cline line,
 		e += sl;
 		if (cm->psuf)
 		    strcpy(e, cm->psuf);
-		comp_setunsetptr(CP_EXACTSTR, 0);
+		comp_setunsetptr(0, 0, CP_EXACTSTR, 0);
 	    }
 	    ai->exactm = cm;
 	} else {
 	    ai->exact = 2;
 	    ai->exactm = NULL;
 	    if (incompfunc)
-		comp_setunsetptr(0, CP_EXACTSTR);
+		comp_setunsetptr(0, 0, 0, CP_EXACTSTR);
 	}
     }
     return cm;
@@ -3543,9 +3631,10 @@ int
 addmatches(Cadata dat, char **argv)
 {
     char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL;
-    char **aign = NULL, **dparr = NULL;
+    char **aign = NULL, **dparr = NULL, oaq = autoq;
+    char *oqp = qipre, *oqs = qisuf, qc;
     int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum;
-    int oisalt = 0, isalt, isexact, doadd;
+    int oisalt = 0, isalt, isexact, doadd, ois = instring, oib = inbackt;
     Cline lc = NULL;
     Cmatch cm;
     struct cmlist mst;
@@ -3553,6 +3642,23 @@ addmatches(Cadata dat, char **argv)
     Comp cp = NULL;
     LinkList aparl = NULL, oparl = NULL, dparl = NULL;
 
+    if (compquote && (qc = *compquote)) {
+	if (qc == '`') {
+	    instring = 0;
+	    inbackt = 0;
+	    autoq = '\0';
+	} else {
+	    instring = (qc == '\'' ? 1 : 2);
+	    inbackt = 0;
+	    autoq = qc;
+	}
+    } else {
+	instring = inbackt = 0;
+	autoq = '\0';
+    }
+    qipre = ztrdup(compqiprefix ? compqiprefix : "");
+    qisuf = ztrdup(compqisuffix ? compqisuffix : "");
+
     /* Switch back to the heap that was used when the completion widget
      * was invoked. */
     SWITCHHEAPS(compheap) {
@@ -3778,6 +3884,14 @@ addmatches(Cadata dat, char **argv)
      * matchers. */
     mstack = oms;
 
+    instring = ois;
+    inbackt = oib;
+    autoq = oaq;
+    zsfree(qipre);
+    zsfree(qisuf);
+    qipre = oqp;
+    qisuf = oqs;
+
     return (mnum == nm);
 }
 
@@ -4222,6 +4336,10 @@ docompletion(char *s, int lst, int incmd)
 	/* Make sure we have the completion list and compctl. */
 	if (makecomplist(s, incmd, lst)) {
 	    /* Error condition: feeeeeeeeeeeeep(). */
+	    cs = 0;
+	    foredel(ll);
+	    inststr(origline);
+	    cs = origcs;
 	    feep();
 	    clearlist = 1;
 	    goto compend;
@@ -4308,23 +4426,25 @@ callcompfunc(char *s, char *fn)
     if ((list = getshfunc(fn)) != &dummy_list) {
 	char **p, *tmp;
 	int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext;
-	unsigned int set;
-	Param *ocpms = comppms;
+	unsigned int rset, kset;
+	Param *ocrpms = comprpms, *ockpms = compkpms;
 
-	comppms = (Param *) zalloc(CP_NUM * sizeof(Param));
+	comprpms = (Param *) zalloc(CP_REALPARAMS * sizeof(Param));
+	compkpms = (Param *) zalloc(CP_KEYPARAMS * sizeof(Param));
 
-	set = CP_ALLMASK &
+	rset = CP_ALLREALS;
+	kset = CP_ALLKEYS &
 	    ~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING |
 	      CP_EXACTSTR | CP_FORCELIST | CP_OLDLIST | CP_OLDINS |
 	      (useglob ? 0 : CP_PATMATCH));
 	zsfree(compvared);
 	if (varedarg) {
 	    compvared = ztrdup(varedarg);
-	    set |= CP_VARED;
+	    kset |= CP_VARED;
 	} else
 	    compvared = ztrdup("");
 	if (!*complastprompt)
-	    set &= ~CP_LASTPROMPT;
+	    kset &= ~CP_LASTPROMPT;
 	zsfree(compcontext);
 	zsfree(compparameter);
 	zsfree(compredirect);
@@ -4336,7 +4456,7 @@ callcompfunc(char *s, char *fn)
 		compcontext = "subscript";
 		if (varname) {
 		    compparameter = varname;
-		    set |= CP_PARAMETER;
+		    kset |= CP_PARAMETER;
 		}
 	    } else
 		compcontext = "math";
@@ -4344,20 +4464,20 @@ callcompfunc(char *s, char *fn)
 	} else if (lincmd) {
 	    if (insubscr) {
 		compcontext = "subscript";
-		set |= CP_PARAMETER;
+		kset |= CP_PARAMETER;
 	    } else
 		compcontext = "command";
 	} else if (linredir) {
 	    compcontext = "redirect";
 	    if (rdstr)
 		compredirect = rdstr;
-	    set |= CP_REDIRECT;
+	    kset |= CP_REDIRECT;
 	} else
 	    switch (linwhat) {
 	    case IN_ENV:
 		compcontext = (linarr ? "array_value" : "value");
 		compparameter = varname;
-		set |= CP_PARAMETER;
+		kset |= CP_PARAMETER;
 		if (!clwpos) {
 		    clwpos = 1;
 		    zsfree(clwords[1]);
@@ -4373,7 +4493,7 @@ callcompfunc(char *s, char *fn)
 		    compcontext = "command";
 		else {
 		    compcontext = "value";
-		    set |= CP_PARAMETER;
+		    kset |= CP_PARAMETER;
 		    if (clwords[0])
 			compparameter = clwords[0];
 		    aadd = 1;
@@ -4410,10 +4530,11 @@ callcompfunc(char *s, char *fn)
 		compquote = ztrdup("\"");
 		compquoting = ztrdup("double");
 	    }
-	    set |= CP_QUOTE | CP_QUOTING;
+	    kset |= CP_QUOTE | CP_QUOTING;
 	} else if (inbackt) {
 	    compquote = ztrdup("`");
 	    compquoting = ztrdup("backtick");
+	    kset |= CP_QUOTE | CP_QUOTING;
 	} else {
 	    compquote = ztrdup("");
 	    compquoting = ztrdup("");
@@ -4444,12 +4565,16 @@ callcompfunc(char *s, char *fn)
 	compiprefix = ztrdup("");
 	zsfree(compisuffix);
 	compisuffix = ztrdup("");
+	zsfree(compqiprefix);
+	compqiprefix = ztrdup(qipre ? qipre : "");
+	zsfree(compqisuffix);
+	compqisuffix = ztrdup(qisuf ? qisuf : "");
 	compcurrent = (usea ? (clwpos + 1 - aadd) : 0);
 	compnmatches = mnum;
 
 	zsfree(complist);
 	switch (uselist) {
-	case 0: complist = ""; set &= ~CP_LIST; break;
+	case 0: complist = ""; kset &= ~CP_LIST; break;
 	case 1: complist = "list"; break;
 	case 2: complist = "autolist"; break;
 	case 3: complist = "ambiguous"; break;
@@ -4464,14 +4589,14 @@ callcompfunc(char *s, char *fn)
 	    }
 	} else {
 	    compinsert = "";
-	    set &= ~CP_INSERT;
+	    kset &= ~CP_INSERT;
 	}
 	compinsert = ztrdup(compinsert);
 	if (useexact)
 	    compexact = ztrdup("accept");
 	else {
 	    compexact = ztrdup("");
-	    set &= ~CP_EXACT;
+	    kset &= ~CP_EXACT;
 	}
 	zsfree(comptoend);
 	if (movetoend == 1)
@@ -4485,11 +4610,11 @@ callcompfunc(char *s, char *fn)
 		compoldlist = "shown";
 	    else
 		compoldlist = "yes";
-	    set |= CP_OLDLIST;
+	    kset |= CP_OLDLIST;
 	    if (menucur) {
 		sprintf(buf, "%d", (*menucur)->gnum);
 		compoldins = buf;
-		set |= CP_OLDINS;
+		kset |= CP_OLDINS;
 	    } else
 		compoldins = "";
 	} else
@@ -4500,7 +4625,8 @@ callcompfunc(char *s, char *fn)
 	incompfunc = 1;
 	startparamscope();
 	makecompparamsptr();
-	comp_setunsetptr(set, ~set);
+	comp_setunsetptr(rset, (~rset & CP_ALLREALS),
+			 kset, (~kset & CP_ALLKEYS));
 	makezleparams(1);
 	sfcontext = SFC_CWIDGET;
 	NEWHEAPS(compheap) {
@@ -4557,8 +4683,10 @@ callcompfunc(char *s, char *fn)
 	oldins = (hasperm && menucur &&
 		  compoldins && !strcmp(compoldins, "keep"));
 
-	zfree(comppms, CP_NUM * sizeof(Param));
-	comppms = ocpms;
+	zfree(comprpms, CP_REALPARAMS * sizeof(Param));
+	zfree(compkpms, CP_KEYPARAMS * sizeof(Param));
+	comprpms = ocrpms;
+	compkpms = ockpms;
     }
     lastval = lv;
 }
@@ -4586,10 +4714,10 @@ makecomplist(char *s, int incmd, int lst)
     struct cmlist ms;
     Cmlist m;
     char *p, *os = s;
-    int onm = nmatches;
+    int onm = nmatches, osi = movefd(0);
 
     /* Inside $... ? */
-    if (compfunc && (p = check_param(s, 0)))
+    if (compfunc && (p = check_param(s, 0, NULL)))
 	os = s = p;
 
     /* We build a copy of the list of matchers to use to make sure that this
@@ -4676,6 +4804,8 @@ makecomplist(char *s, int incmd, int lst)
 	    validlist = 1;
 	    amatches = pmatches;
 
+	    redup(osi, 0);
+
 	    return 0;
 	}
 	PERMALLOC {
@@ -4685,6 +4815,8 @@ makecomplist(char *s, int incmd, int lst)
 	if (nmatches && !errflag) {
 	    validlist = 1;
 
+	    redup(osi, 0);
+
 	    return 0;
 	}
 	if (!m || !(m = m->next))
@@ -4693,6 +4825,7 @@ makecomplist(char *s, int incmd, int lst)
 	errflag = 0;
 	compmatcher++;
     }
+    redup(osi, 0);
     return 1;
 }
 
@@ -4760,25 +4893,279 @@ comp_str(int *ipl, int *pl, int untok)
 
 /**/
 int
+set_comp_sep(void)
+{
+    int lip, lp;
+    char *s = comp_str(&lip, &lp, 0);
+
+    if (compisuffix)
+	s = dyncat(s, compisuffix);
+
+    return sep_comp_string("", s, lip + lp, 0);
+}
+
+/**/
+static int
+sep_comp_string(char *ss, char *s, int noffs, int rec)
+{
+    LinkList foo = newlinklist();
+    LinkNode n;
+    int owe = we, owb = wb, ocs = cs, swb, swe, scs, soffs, ne = noerrs;
+    int sl = strlen(ss), tl, got = 0, i = 0, cur = -1, oll = ll;
+    int ois = instring, oib = inbackt;
+    char *tmp, *p, *ns, *ol = (char *) line, sav, oaq = autoq, *qp, *qs;
+
+    /* Put the string in the lexer buffer and call the lexer to *
+     * get the words we have to expand.                        */
+    zleparse = 1;
+    addedx = 1;
+    noerrs = 1;
+    lexsave();
+    tmp = (char *) zhalloc(tl = sl + 3 + strlen(s));
+    strcpy(tmp, ss);
+    tmp[sl] = ' ';
+    memcpy(tmp + sl + 1, s, noffs);
+    tmp[(scs = cs = sl + 1 + noffs)] = 'x';
+    strcpy(tmp + sl + 2 + noffs, s + noffs);
+    inpush(dupstrspace(tmp), 0, NULL);
+    line = (unsigned char *) tmp;
+    ll = tl - 1;
+    strinbeg();
+    stophist = 2;
+    noaliases = 1;
+    do {
+	ctxtlex();
+	if (tok == LEXERR) {
+	    int j;
+
+	    if (!tokstr)
+		break;
+	    for (j = 0, p = tokstr; *p; p++)
+		if (*p == Snull || *p == Dnull)
+		    j++;
+	    if (j & 1) {
+		tok = STRING;
+		if (p > tokstr && p[-1] == ' ')
+		    p[-1] = '\0';
+	    }
+	}
+	if (tok == ENDINPUT || tok == LEXERR)
+	    break;
+	if (tokstr && *tokstr)
+	    addlinknode(foo, (p = ztrdup(tokstr)));
+	else
+	    p = NULL;
+	if (!got && !zleparse) {
+	    DPUTS(!p, "no current word in substr");
+	    cur = i;
+	    swb = wb - 1;
+	    swe = we - 1;
+	    soffs = cs - swb;
+	    chuck(p + soffs);
+	    ns = dupstring(p);
+	}
+	i++;
+    } while (tok != ENDINPUT && tok != LEXERR);
+    noaliases = 0;
+    strinend();
+    inpop();
+    errflag = zleparse = 0;
+    noerrs = ne;
+    lexrestore();
+    wb = owb;
+    we = owe;
+    cs = ocs;
+    line = (unsigned char *) ol;
+    ll = oll;
+    if (cur < 0 || i < 1)
+	return 1;
+    if (*ns == Snull || *ns == Dnull) {
+	instring = (*ns == Snull ? 1 : 2);
+	inbackt = 0;
+	swb++;
+	if (ns[strlen(ns) - 1] == *ns)
+	    swe--;
+	autoq = (*ns == Snull ? '\'' : '"');
+    } else {
+	instring = 0;
+	autoq = '\0';
+    }
+    for (p = ns, i = swb; *p; p++, i++) {
+	if (INULL(*p)) {
+	    if (i < scs)
+		soffs--;
+	    if (p[1] || *p != Bnull) {
+		if (*p == Bnull) {
+		    if (scs == i + 1)
+			scs++, soffs++;
+		} else {
+		    if (scs > i--)
+			scs--;
+		}
+	    } else {
+		if (scs == swe)
+		    scs--;
+	    }
+	    chuck(p--);
+	}
+    }
+    sav = s[(i = swb - sl - 1)];
+    s[i] = '\0';
+    qp = tricat(qipre, s, "");
+    s[i] = sav;
+    if (swe < swb)
+	swe = swb;
+    swe -= sl + 1;
+    sl = strlen(s);
+    if (swe > sl)
+	swe = sl, ns[swe - swb + 1] = '\0';
+    qs = tricat(s + swe, qisuf, "");
+    sl = strlen(ns);
+    if (soffs > sl)
+	soffs = sl;
+
+    if (rec) {
+	char **ow = clwords, *os = cmdstr, *oqp = qipre, *oqs = qisuf;
+	int olws = clwsize, olwn = clwnum, olwp = clwpos;
+	int obr = brange, oer = erange, oof = offs;
+	
+	clwsize = clwnum = countlinknodes(foo);
+	clwords = (char **) zalloc((clwnum + 1) * sizeof(char *));
+	for (n = firstnode(foo), i = 0; n; incnode(n), i++) {
+	    p = clwords[i] = (char *) getdata(n);
+	    untokenize(p);
+	}
+	clwords[i] = NULL;
+	clwpos = cur;
+	cmdstr = ztrdup(clwords[0]);
+	brange = 0;
+	erange = clwnum - 1;
+	qipre = qp;
+	qisuf = qs;
+	offs = soffs;
+	makecomplistcmd(ns, !clwpos, CFN_FIRST);
+	offs = oof;
+	zsfree(cmdstr);
+	cmdstr = os;
+	freearray(clwords);
+	clwords = ow;
+	clwsize = olws;
+	clwnum = olwn;
+	clwpos = olwp;
+	brange = obr;
+	erange = oer;
+	zsfree(qipre);
+	qipre = oqp;
+	zsfree(qisuf);
+	qisuf = oqs;
+    } else {
+	int set = CP_QUOTE | CP_QUOTING, unset = 0;
+
+	zsfree(compquote);
+	zsfree(compquoting);
+	if (instring == 2) {
+	    compquote = "\"";
+	    compquoting = "double";
+	} else if (instring == 1) {
+	    compquote = "'";
+	    compquoting = "single";
+	} else {
+	    compquote = compquoting = "";
+	    unset = set;
+	    set = 0;
+	}
+	compquote = ztrdup(compquote);
+	compquoting = ztrdup(compquoting);
+	comp_setunsetptr(0, 0, set, unset);
+
+	if (unset(COMPLETEINWORD)) {
+	    untokenize(ns);
+	    zsfree(compprefix);
+	    compprefix = ztrdup(ns);
+	    zsfree(compsuffix);
+	    compsuffix = ztrdup("");
+	} else {
+	    char *ss, sav;
+	    
+	    ss = ns + soffs;
+
+	    sav = *ss;
+	    *ss = '\0';
+	    untokenize(ns);
+	    compprefix = ztrdup(ns);
+	    *ss = sav;
+	    untokenize(ss);
+	    compsuffix = ztrdup(ss);
+	}
+	zsfree(compiprefix);
+	compiprefix = ztrdup("");
+	zsfree(compisuffix);
+	compisuffix = ztrdup("");
+	zsfree(compqiprefix);
+	compqiprefix = qp;
+	zsfree(compqisuffix);
+	compqisuffix = qs;
+
+	freearray(compwords);
+	i = countlinknodes(foo);
+	compwords = (char **) zalloc((i + 1) * sizeof(char *));
+	for (n = firstnode(foo), i = 0; n; incnode(n), i++) {
+	    p = compwords[i] = (char *) getdata(n);
+	    untokenize(p);
+	}
+	compwords[i] = NULL;
+    }
+    autoq = oaq;
+    instring = ois;
+    inbackt = oib;
+
+    return 0;
+}
+
+/**/
+int
 makecomplistcall(Compctl cc)
 {
     int nm = mnum;
 
     SWITCHHEAPS(compheap) {
 	HEAPALLOC {
-	    int ooffs = offs, lip, lp;
-	    char *str = comp_str(&lip, &lp, 0);
-	    char *oisuf = isuf;
-
+	    int ooffs = offs, lip, lp, ois = instring, oib = inbackt;
+	    char *str = comp_str(&lip, &lp, 0), qc;
+	    char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, oaq = autoq;
+
+	    if (compquote && (qc = *compquote)) {
+		if (qc == '`') {
+		    instring = 0;
+		    inbackt = 0;
+		    autoq = '\0';
+		} else {
+		    instring = (qc == '\'' ? 1 : 2);
+		    inbackt = 0;
+		    autoq = qc;
+		}
+	    } else {
+		instring = inbackt = 0;
+		autoq = '\0';
+	    }
 	    isuf = dupstring(compisuffix);
 	    ctokenize(isuf);
 	    remnulargs(isuf);
+	    qipre = ztrdup(compqiprefix ? compqiprefix : "");
+	    qisuf = ztrdup(compqisuffix ? compqisuffix : "");
 	    offs = lip + lp;
 	    cc->refc++;
 	    ccont = 0;
 	    makecomplistor(cc, str, lincmd, lip, 0);
 	    offs = ooffs;
 	    isuf = oisuf;
+	    zsfree(qipre);
+	    zsfree(qisuf);
+	    qipre = oqp;
+	    qisuf = oqs;
+	    instring = ois;
+	    inbackt = oib;
+	    autoq = oaq;
 	    compnmatches = mnum;
 	} LASTALLOC;
     } SWITCHBACKHEAPS;
@@ -4807,10 +5194,26 @@ makecomplistctl(int flags)
 	HEAPALLOC {
 	    int ooffs = offs, lip, lp;
 	    char *str = comp_str(&lip, &lp, 0), *t;
-	    char *os = cmdstr, **ow = clwords, **p, **q;
-	    int on = clwnum, op = clwpos;
-	    char *oisuf = isuf;
-
+	    char *os = cmdstr, **ow = clwords, **p, **q, qc;
+	    int on = clwnum, op = clwpos, ois =  instring, oib = inbackt;
+	    char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, oaq = autoq;
+
+	    if (compquote && (qc = *compquote)) {
+		if (qc == '`') {
+		    instring = 0;
+		    inbackt = 0;
+		    autoq = '\0';
+		} else {
+		    instring = (qc == '\'' ? 1 : 2);
+		    inbackt = 0;
+		    autoq = qc;
+		}
+	    } else {
+		instring = inbackt = 0;
+		autoq = '\0';
+	    }
+	    qipre = ztrdup(compqiprefix ? compqiprefix : "");
+	    qisuf = ztrdup(compqisuffix ? compqisuffix : "");
 	    isuf = dupstring(compisuffix);
 	    ctokenize(isuf);
 	    remnulargs(isuf);
@@ -4830,6 +5233,13 @@ makecomplistctl(int flags)
 	    ret = makecomplistglobal(str, !clwpos, COMP_COMPLETE, flags);
 	    incompfunc = 1;
 	    isuf = oisuf;
+	    zsfree(qipre);
+	    zsfree(qisuf);
+	    qipre = oqp;
+	    qisuf = oqs;
+	    instring = ois;
+	    inbackt = oib;
+	    autoq = oaq;
 	    offs = ooffs;
 	    compnmatches = mnum;
 	    zsfree(cmdstr);
@@ -5078,9 +5488,11 @@ makecomplistext(Compctl occ, char *os, int incmd)
     Compctl compc;
     Compcond or, cc;
     Comp comp;
-    int compadd, m = 0, d = 0, t, tt, i, j, a, b;
+    int compadd, m = 0, d = 0, t, tt, i, j, a, b, ins;
     char *sc = NULL, *s, *ss;
 
+    ins = (instring ? instring : (inbackt ? 3 : 0));
+
     /* This loops over the patterns separated by `-'s. */
     for (compc = occ->ext; compc; compc = compc->next) {
 	compadd = t = brange = 0;
@@ -5096,6 +5508,11 @@ makecomplistext(Compctl occ, char *os, int incmd)
 		    brange = 0;
 		    erange = clwnum - 1;
 		    switch (cc->type) {
+		    case CCT_QUOTE:
+			t = ((cc->u.s.s[i][0] == 's' && ins == 1) ||
+			     (cc->u.s.s[i][0] == 'd' && ins == 2) ||
+			     (cc->u.s.s[i][0] == 'b' && ins == 3));
+			break;
 		    case CCT_POS:
 			tt = clwpos;
 			goto cct_num;
@@ -5366,7 +5783,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	ic = 0;
 
     /* Check if we have to complete a parameter name... */
-    if (!incompfunc && (p = check_param(s, 1))) {
+    if (!incompfunc && (p = check_param(s, 1, NULL))) {
 	s = p;
 	/* And now make sure that we complete parameter names. */
 	cc = &cc_dummy;
@@ -5917,7 +6334,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 
 	opts[NULLGLOB] = 1;
 
-	/* Put the strin in the lexer buffer and call the lexer to *
+	/* Put the string in the lexer buffer and call the lexer to *
 	 * get the words we have to expand.                        */
 	zleparse = 1;
 	lexsave();
@@ -6127,6 +6544,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	    clwords[brange - 1] = ops;
 	ccont = occ;
     }
+    if (cc->substr)
+	sep_comp_string(cc->substr, s, offs, 1);
     uremnode(ccstack, firstnode(ccstack));
     if (cc->matcher)
 	mstack = mstack->next;
@@ -6417,6 +6836,7 @@ dupmatch(Cmatch m)
     r->brsl = m->brsl;
     r->rems = ztrdup(m->rems);
     r->remf = ztrdup(m->remf);
+    r->autoq = m->autoq;
 
     return r;
 }
@@ -6938,7 +7358,7 @@ do_ambiguous(void)
 	 * completion options.                                             */
 	do_ambig_menu();
     } else if (ainfo) {
-	int atend = (cs == we), oll = ll, la;
+	int atend = (cs == we), oll = ll, la, eq, tcs;
 	VARARR(char, oline, ll);
 
 	menucur = NULL;
@@ -6954,7 +7374,13 @@ do_ambiguous(void)
 
 	/* Now get the unambiguous string and insert it into the line. */
 	cline_str(ainfo->line, 1, NULL);
-
+	if (eparq) {
+	    tcs = cs;
+	    cs = lastend;
+	    for (eq = eparq; eq; eq--)
+		inststrlen("\"", 0, 1);
+	    cs = tcs;
+	}
 	/* la is non-zero if listambiguous may be used. Copying and
 	 * comparing the line looks like BFI but it is the easiest
 	 * solution. Really. */
@@ -7078,12 +7504,18 @@ do_single(Cmatch m)
 	 * so generate one automagically.     */
 	cs = scs;
 	if (m->ripre && (m->flags & CMF_PARBR)) {
+	    int pq;
+
 	    /*{{*/
 	    /* Completing a parameter in braces.  Add a removable `}' suffix. */
+	    cs += eparq;
+	    for (pq = parq; pq; pq--)
+		inststrlen("\"", 1, 1);
+	    menuinsc += parq;
 	    inststrlen("}", 1, 1);
 	    menuinsc++;
 	    if (menuwe)
-		menuend++;
+		menuend += menuinsc;
 	}
 	if ((m->flags & CMF_FILE) || (m->ripre && isset(AUTOPARAMSLASH))) {
 	    /* If we have a filename or we completed a parameter name      *
@@ -7105,6 +7537,7 @@ do_single(Cmatch m)
 		    noerrs = 1;
 		    parsestr(p);
 		    singsub(&p);
+		    errflag = 0;
 		    noerrs = ne;
 		} else {
 		    p = (char *) zhalloc(strlen(prpre) + strlen(str) +
@@ -7153,24 +7586,30 @@ do_single(Cmatch m)
 	    if ((!menucmp || menuwe) && isset(AUTOPARAMKEYS))
 		suffixlen[','] = suffixlen['}'] = 1;
 	}
-    } else if (!menucmp && !havesuff && (!(m->flags & CMF_FILE) || !sr)) {
+    } else if (!havesuff && (!(m->flags & CMF_FILE) || !sr)) {
 	/* If we didn't add a suffix, add a space, unless we are *
 	 * doing menu completion or we are completing files and  *
 	 * the string doesn't name an existing file.             */
-	inststrlen(" ", 1, 1);
-	menuinsc++;
-	if (menuwe)
-	    makesuffix(1);
+	if (m->autoq && (!m->isuf || m->isuf[0] != m->autoq)) {
+	    inststrlen(&(m->autoq), 1, 1);
+	    menuinsc++;
+	}
+	if (!menucmp) {
+	    inststrlen(" ", 1, 1);
+	    menuinsc++;
+	    if (menuwe)
+		makesuffix(1);
+	}
     }
     if (menuwe && m->ripre && isset(AUTOPARAMKEYS))
-	makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), menuinsc);
+	makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), menuinsc - parq);
 
     if ((menucmp && !menuwe) || !movetoend)
 	cs = menuend;
 }
 
 /* This maps the value in v into the range [0,m-1], decrementing v
- * if it is non-negative and making negative values cound backwards. */
+ * if it is non-negative and making negative values count backwards. */
 
 static int
 comp_mod(int v, int m)
diff --git a/Src/glob.c b/Src/glob.c
index 596a05ebf..35aa447de 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -97,6 +97,7 @@ typedef struct stat *Statptr;	 /* This makes the Ultrix compiler happy.  Go figu
 #define TT_MINS 2
 #define TT_WEEKS 3
 #define TT_MONTHS 4
+#define TT_SECONDS 5
 
 #define TT_BYTES 0
 #define TT_POSIX_BLOCKS 1
@@ -1615,6 +1616,8 @@ glob(LinkList list, LinkNode np)
 				units = TT_WEEKS, ++s;
 			    else if (*s == 'M')
 				units = TT_MONTHS, ++s;
+			    else if (*s == 's')
+				units = TT_SECONDS, ++s;
 			}
 			/* See if it's greater than, equal to, or less than */
 			if ((range = *s == '+' ? 1 : *s == '-' ? -1 : 0))
diff --git a/Src/hist.c b/Src/hist.c
index 6b2c2a653..4d672deab 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -58,8 +58,8 @@ int excs, exlast;
  * the line does not get added to the list until hend(), if at all.
  * However, curhist is incremented to reflect the current line anyway
  * and a temporary history entry is inserted while the user is editing.
- * If the resulting line was not added to the list, curhist is
- * decremented in hend().
+ * If the resulting line was not added to the list, a flag is set so
+ * that curhist will be decremented in hbegin().
  */
  
 /**/
@@ -984,6 +984,8 @@ hend(void)
 void
 remhist(void)
 {
+    if (hist_ring == &curline)
+	return;
     if (!(histactive & HA_ACTIVE)) {
 	if (!(histactive & HA_JUNKED)) {
 	    freehistnode((HashNode)hist_ring);
diff --git a/Src/init.c b/Src/init.c
index 7f1b2153a..f9e6574dd 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -550,7 +550,11 @@ setupvals(void)
     cdpath   = mkarray(NULL);
     manpath  = mkarray(NULL);
     fignore  = mkarray(NULL);
+#ifdef FUNCTION_DIR
+    fpath    = mkarray(ztrdup(FUNCTION_DIR));
+#else
     fpath    = mkarray(NULL);
+#endif
     mailpath = mkarray(NULL);
     watch    = mkarray(NULL);
     psvar    = mkarray(NULL);
@@ -758,33 +762,31 @@ run_init_scripts(void)
 #ifdef GLOBAL_ZSHENV
 	source(GLOBAL_ZSHENV);
 #endif
-	if (isset(RCS)) {
-	    if (unset(PRIVILEGED))
-		sourcehome(".zshenv");
-	    if (islogin) {
+	if (isset(RCS) && unset(PRIVILEGED))
+	    sourcehome(".zshenv");
+	if (islogin) {
 #ifdef GLOBAL_ZPROFILE
-		if (isset(GLOBALRCS))
+	    if (isset(RCS) && isset(GLOBALRCS))
 		    source(GLOBAL_ZPROFILE);
 #endif
-		if (unset(PRIVILEGED))
-		    sourcehome(".zprofile");
-	    }
-	    if (interact) {
+	    if (isset(RCS) && unset(PRIVILEGED))
+		sourcehome(".zprofile");
+	}
+	if (interact) {
 #ifdef GLOBAL_ZSHRC
-		if (isset(GLOBALRCS))
-		    source(GLOBAL_ZSHRC);
+	    if (isset(RCS) && isset(GLOBALRCS))
+		source(GLOBAL_ZSHRC);
 #endif
-		if (unset(PRIVILEGED))
-		    sourcehome(".zshrc");
-	    }
-	    if (islogin) {
+	    if (isset(RCS) && unset(PRIVILEGED))
+		sourcehome(".zshrc");
+	}
+	if (islogin) {
 #ifdef GLOBAL_ZLOGIN
-		if (isset(GLOBALRCS))
-		    source(GLOBAL_ZLOGIN);
+	    if (isset(RCS) && isset(GLOBALRCS))
+		source(GLOBAL_ZLOGIN);
 #endif
-		if (unset(PRIVILEGED))
-		    sourcehome(".zlogin");
-	    }
+	    if (isset(RCS) && unset(PRIVILEGED))
+		sourcehome(".zlogin");
 	}
     }
     noerrexit = 0;
diff --git a/Src/loop.c b/Src/loop.c
index 95ec4832a..070173fa2 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -138,6 +138,7 @@ execselect(Cmd cmd)
     LinkNode n;
     int i;
     FILE *inp;
+    size_t more;
 
     node = cmd->u.forcmd;
     args = cmd->args;
@@ -154,7 +155,7 @@ execselect(Cmd cmd)
     lastval = 0;
     pushheap();
     inp = fdopen(dup((SHTTY == -1) ? 0 : SHTTY), "r");
-    selectlist(args);
+    more = selectlist(args, 0);
     for (;;) {
 	for (;;) {
 	    if (empty(bufstack)) {
@@ -181,7 +182,7 @@ execselect(Cmd cmd)
 		*s = '\0';
 	    if (*str)
 	      break;
-	    selectlist(args);
+	    more = selectlist(args, more);
 	}
 	setsparam("REPLY", ztrdup(str));
 	i = atoi(str);
@@ -217,8 +218,8 @@ execselect(Cmd cmd)
 /* And this is used to print select lists. */
 
 /**/
-static void
-selectlist(LinkList l)
+size_t
+selectlist(LinkList l, size_t start)
 {
     size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct;
     LinkNode n;
@@ -245,7 +246,7 @@ selectlist(LinkList l)
     else
 	fw = (columns - 1) / fct;
     colsz = (ct + fct - 1) / fct;
-    for (t1 = 0; t1 != colsz; t1++) {
+    for (t1 = start; t1 != colsz && t1 - start < lines - 2; t1++) {
 	ap = arr + t1;
 	do {
 	    int t2 = strlen(*ap) + 2, t3;
@@ -271,6 +272,8 @@ selectlist(LinkList l)
        }
        while (*ap);*/
     fflush(stderr);
+
+    return t1 < colsz ? t1 : 0;
 }
 
 /**/
diff --git a/Src/main.c b/Src/main.c
index 7ec8f07bd..762e06b90 100644
--- a/Src/main.c
+++ b/Src/main.c
@@ -45,12 +45,24 @@ main(int argc, char **argv)
 
     for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++);
 
-    if (!(zsh_name = strrchr(argv[0], '/')))
-	zsh_name = argv[0];
-    else
-	zsh_name++;
-    if (*zsh_name == '-')
-	zsh_name++;
+    zsh_name = argv[0];
+    do {
+      char *arg0 = zsh_name;
+      if (!(zsh_name = strrchr(arg0, '/')))
+	  zsh_name = arg0;
+      else
+	  zsh_name++;
+      if (*zsh_name == '-')
+	  zsh_name++;
+      if (strcmp(zsh_name, "su") == 0) {
+	  char *sh = zgetenv("SHELL");
+	  if (sh && *sh && arg0 != sh)
+	      zsh_name = sh;
+	  else
+	      break;
+      } else
+	  break;
+    } while (zsh_name);
 
     fdtable_size = OPEN_MAX;
     fdtable = zcalloc(fdtable_size);
diff --git a/Src/options.c b/Src/options.c
index 5725d27c0..504ccdf7e 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -438,17 +438,6 @@ emulate(const char *zsh_name, int fully)
 {
     char ch = *zsh_name;
 
-    if (!strcmp("su", zsh_name)) {
-	/* We haven't set up the paramtable yet, so just use zgetenv */
-	char *ptr = zgetenv("SHELL");
-	if (ptr && *ptr) {
-	    zsh_name = ptr;
-	    if ((ptr = strrchr(zsh_name, '/')))
-		zsh_name = ptr+1;
-	    ch = *zsh_name;
-	} else
-	    ch = 'z';
-    }
     if (ch == 'r')
 	ch = zsh_name[1];
 
diff --git a/Src/subst.c b/Src/subst.c
index 47b59e793..0017b205e 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -976,7 +976,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		zerr("bad substitution", NULL, 0);
 		return NULL;
 	    }
-	} else if (INULL(*s))
+	} else if (inbrace && INULL(*s))
 	    s++;
 	else
 	    break;
@@ -984,7 +984,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
     globsubst = globsubst && !qt;
 
     idbeg = s;
-    if ((subexp = (s[-1] && isstring(*s) &&
+    if ((subexp = (inbrace && s[-1] && isstring(*s) &&
 		   (s[1] == Inbrace || s[1] == Inpar)))) {
 	int sav;
 	int quoted = *s == Qstring;
@@ -1168,6 +1168,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
     }
 
     idend = s;
+    if (inbrace)
+	while (INULL(*s))
+	    s++;
     if ((colf = *s == ':'))
 	s++;
 
@@ -1484,6 +1487,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	val = dupstring("");
 	isarr = 0;
     } else if (isarr && aval && aval[0] && !aval[1]) {
+	/* treat a one-element array as a scalar for purposes of   *
+	 * concatenation with surrounding text (some${param}thing) *
+	 * and rc_expand_param handling.  Note: mult_isarr (above) *
+	 * propagates the true array type from nested expansions.  */
 	val = aval[0];
 	isarr = 0;
     }
@@ -1500,8 +1507,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		val = aval[0];
 	    else
 		isarr = 2;
-	    mult_isarr = isarr;
 	}
+	mult_isarr = isarr;
     }
     if (casmod) {
 	if (isarr) {
@@ -1665,7 +1672,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    return NULL;
 	xlen = strlen(x);
 	*str = strcatsub(&y, ostr, aptr, x, xlen, fstr, globsubst);
-	if (qt && !*y && isarr != 2)
+	if (qt && !*y)
 	    y = dupstring(nulstring);
 	setdata(n, (void *) y);
     }
diff --git a/Src/zsh.export b/Src/zsh.export
index 7595f1d2e..ef9fca8c6 100644
--- a/Src/zsh.export
+++ b/Src/zsh.export
@@ -145,6 +145,7 @@ metadiffer
 metafy
 metalen
 mode_to_octal
+movefd
 movehistent
 mypgrp
 mypid
@@ -194,6 +195,7 @@ quietgethist
 quotedzputs
 readoutput
 realparamtab
+redup
 refreshptr
 remlpaths
 remnulargs
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index 214f26681..bd9aabc2e 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -30,6 +30,9 @@ version.h: $(sdir_top)/Config/version.mk
 
 zshpaths.h: FORCE Makemod
 	@echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp
+	@if test x$(fndir) != xno; then \
+	  echo '#define FUNCTION_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \
+	fi
 	@if cmp -s zshpaths.h zshpaths.h.tmp; then \
 	    rm -f zshpaths.h.tmp; \
 	    echo "\`zshpaths.h' is up to date." ; \
diff --git a/Util/zsh-development-guide b/Util/zsh-development-guide
index 3775f43b7..a37abfe32 100644
--- a/Util/zsh-development-guide
+++ b/Util/zsh-development-guide
@@ -17,12 +17,13 @@ Patches
 
 * Send all patches to the mailing list rather than directly to me.
 
-* Send only context diffs "diff -c oldfile newfile".  They are much
-  easier to read and understand while also allowing the patch program
-  to patch more intelligently.  Please make sure the filenames in
-  the diff header are relative to the top-level directory of the zsh
-  distribution; for example, it should say "Src/init.c" rather than
-  "init.c" or "zsh/Src/init.c".
+* Send only context diffs "diff -c oldfile newfile" or unified diffs
+  "diff -u oldfile newfile".  They are much easier to read and
+  understand while also allowing the patch program to patch more
+  intelligently.  Please make sure the filenames in the diff header
+  are relative to the top-level directory of the zsh distribution; for
+  example, it should say "Src/init.c" rather than "init.c" or
+  "zsh/Src/init.c".
 
 * Please put only one bug fix or feature enhancement in a single patch and
   only one patch per mail message.  This helps me to multiplex the many
diff --git a/configure.in b/configure.in
index 68413fad7..02abcc67b 100644
--- a/configure.in
+++ b/configure.in
@@ -104,7 +104,7 @@ AC_ARG_ENABLE(lfs,
 [  --enable-lfs               turn on support for large files])
 
 dnl Pathnames for global zsh scripts
-undefine([zshenv])dnl
+undefine([etcdir])dnl
 AC_ARG_ENABLE(etcdir,
 [  --enable-etcdir=directory  default directory for global zsh scripts],
 [etcdir="$enableval"], [etcdir=/etc])
@@ -201,6 +201,21 @@ fi],
 AC_DEFINE(RESTRICTED_R)
 )
 
+undefine([fndir])dnl
+AC_ARG_ENABLE(fndir,
+[  --enable-fndir=DIR        where functions go (default DATADIR/zsh-fns)],
+[fndir="$enableval"], [fndir=${datadir}/zsh/functions])
+
+if test x${FUNCTIONS_INSTALL+set} != xset; then
+  FUNCTIONS_INSTALL="Core/* Base/* Builtins/* User/* Commands/*"
+  if test $dynamic != no; then
+    FUNCTIONS_INSTALL="${FUNCTIONS_INSTALL} Zftp/*"
+  fi
+fi
+
+AC_SUBST(fndir)dnl
+AC_SUBST(FUNCTIONS_INSTALL)dnl
+
 dnl ------------------
 dnl CHECK THE COMPILER
 dnl ------------------
@@ -1293,7 +1308,8 @@ AC_SUBST_FILE(VERSION_MK)dnl
 real_no_create=$no_create
 no_create=yes
 
-AC_OUTPUT(Config/defs.mk Makefile Doc/Makefile Etc/Makefile Src/Makefile, \
+AC_OUTPUT(Config/defs.mk Makefile Doc/Makefile Etc/Makefile Src/Makefile \
+Completion/Makefile Functions/Makefile, \
 [test -z "$CONFIG_HEADERS" || echo > stamp-h])
 
 dnl The standard config.status is missing some essential features.