about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-07-12 17:02:40 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-07-12 17:02:40 +0000
commit1f6786ef7ae24ff858f52c6d4ac2bc23d529c0c1 (patch)
tree608d6471d477e8d4d9eafa62f521be50c3248f6e
parent7c670f1e6a0e154f0b1a2d4b6eed0e71c9404b56 (diff)
downloadzsh-1f6786ef7ae24ff858f52c6d4ac2bc23d529c0c1.tar.gz
zsh-1f6786ef7ae24ff858f52c6d4ac2bc23d529c0c1.tar.xz
zsh-1f6786ef7ae24ff858f52c6d4ac2bc23d529c0c1.zip
zsh-3.1.6-test-1 zsh-3.1.6-test-1
-rw-r--r--ChangeLog244
-rw-r--r--Completion/Base/_command_names7
-rw-r--r--Completion/Base/_default9
-rw-r--r--Completion/Base/_parameter2
-rw-r--r--Completion/Builtins/_cd25
-rw-r--r--Completion/Commands/.distfiles3
-rw-r--r--Completion/Commands/_history_complete_word2
-rw-r--r--Completion/Commands/_read_comp158
-rw-r--r--Completion/Core/_main_complete30
-rw-r--r--Completion/Core/_match8
-rw-r--r--Completion/Core/_oldlist24
-rw-r--r--Completion/Core/_path_files7
-rw-r--r--Completion/Core/compinit12
-rw-r--r--Completion/Core/compinstall4
-rw-r--r--Completion/Makefile.in35
-rw-r--r--Completion/User/.distfiles2
-rw-r--r--Completion/User/_ps2
-rw-r--r--Completion/User/_tar1
-rw-r--r--Completion/User/_use_lo10
-rw-r--r--Config/.distfiles3
-rw-r--r--Config/funcinst.mk47
-rwxr-xr-xConfig/installfns.sh48
-rwxr-xr-xConfig/uninstallfns.sh31
-rw-r--r--Config/version.mk4
-rw-r--r--Doc/Zsh/arith.yo11
-rw-r--r--Doc/Zsh/builtins.yo43
-rw-r--r--Doc/Zsh/compsys.yo81
-rw-r--r--Doc/Zsh/compwid.yo2
-rw-r--r--Doc/Zsh/expn.yo11
-rw-r--r--Doc/Zsh/mod_complist.yo57
-rw-r--r--Doc/Zsh/mod_zle.yo19
-rw-r--r--Doc/Zsh/params.yo64
-rw-r--r--Doc/Zsh/prompt.yo33
-rw-r--r--Etc/BUGS21
-rw-r--r--Etc/CONTRIBUTORS38
-rw-r--r--Etc/MACHINES3
-rw-r--r--Etc/NEWS86
-rw-r--r--Functions/Makefile.in35
-rw-r--r--Functions/Zle/.distfiles3
-rw-r--r--Functions/Zle/incremental-complete-word89
-rw-r--r--Functions/Zle/insert-files42
-rw-r--r--INSTALL84
-rw-r--r--Misc/.distfiles3
-rw-r--r--Misc/job-control-tests31
-rw-r--r--Src/Zle/compctl.c4
-rw-r--r--Src/Zle/complist.c106
-rw-r--r--Src/Zle/zle.export10
-rw-r--r--Src/Zle/zle_bindings.c8
-rw-r--r--Src/Zle/zle_main.c8
-rw-r--r--Src/Zle/zle_misc.c2
-rw-r--r--Src/Zle/zle_params.c8
-rw-r--r--Src/Zle/zle_refresh.c4
-rw-r--r--Src/Zle/zle_thingy.c44
-rw-r--r--Src/Zle/zle_tricky.c57
-rw-r--r--Src/builtin.c170
-rw-r--r--Src/exec.c41
-rw-r--r--Src/hist.c2
-rw-r--r--Src/jobs.c160
-rw-r--r--Src/loop.c33
-rw-r--r--Src/math.c6
-rw-r--r--Src/params.c52
-rw-r--r--Src/prompt.c81
-rw-r--r--Src/utils.c26
-rw-r--r--Src/zsh.h49
-rw-r--r--configure.in22
65 files changed, 1860 insertions, 507 deletions
diff --git a/ChangeLog b/ChangeLog
index 91e131201..963e4ec89 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,12 +1,204 @@
-1999-07-03  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-07-12  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
+	* pws: version 3.1.6-test-1
+
+	* Sven: 7099: Completion/Core/_main_complete, Doc/Zsh/compsys.yo:
+	  config key last_prompt means don't turn off alwayslastprompt on
+	  prefix.
+
+	* Sven: 7097: Completion/Core/_oldlist: keeps old command line.
+
+1999-07-09  Peter Stephenson  <pws@ibmth.df.unipi.it>
+
+	* pws: 7091: configure.in, INSTALL: change defaults for
+	  dynamic and large file support to be enabled.
+
+	* Sven: 7083: Src/Zle/compctl.c, Src/Zle/zle_tricky.c,
+	  Doc/Zsh/compwid.yo: compset -q unconditionally splits
+	  the current word.
+
+	* Sven: 7082: Completion/Base/_parameter: use _parameters
+
+	* pws: 7076: Completion/Base/_command_names,
+	  Completion/Base/_first, Completion/User/_su: %resume should be
+	  in _command_names; _su should check $SHELL.
+
+	* pws: 7075, 7080, 7092: Completion/Core/compinit,
+	  Config/funcinst.mk, Config/installfns.sh,
+	  Config/uninstallfns.sh, INSTALL: Yet another attempt to install
+	  shell functions in a sensible way; compinit adds to the end of
+	  $fpath; fixed typo that it didn't check existing fpath properly.
+
+	* Oliver: 7067: Completion/Base/_first, Completion/User/_su,
+	  Completion/User/_sh: check for %resume on command line;
+	  new completions for _su and _sh.
+
+	* pws: 7066: configure.in: function install makefile in
+	  source, not build, hierarchy.
+
+	* Sven: 7062: Src/Zle/complist.c, Src/Zle/zle_tricky.c,
+	  Doc/Zsh/compsys.yo, Doc/Zsh/mod_complist.yo: undo works
+	  inside menu-selection for items completed by
+	  accept-and-infer-next-history; display is more reliable.
+
+	* Sven: 7058: Src/Zle/zle_params.c: turn off menu completion
+	  if the command line gets altered by a zle function.
+
+1999-07-08  Peter Stephenson  <pws@ibmth.df.unipi.it>
+	  
+	* pws: 7049: Src/builtin.c: eval didn't save/restore lexical
+	  state.
+	
+	* pws: 7046: Src/loop.c: xtrace for case and for statements.
+	
+	* Sven: 7043: Completion/Core/_oldlist:  Extra sophistication
+	  when using _oldlist with a particular completer.
+	
+	* pws: 7042: Etc/BUGS, Etc/CONTRIBUTORS, Etc/NEWS,
+	  Doc/Zsh/builtins.yo, Doc/Zsh/expn.yo, Doc/Zsh/mod_complist.yo,
+	  Doc/Zsh/params.yo:  Changes to admin files for 3.1.6; some minor
+	  documentation changes.
+	
+	* Sven: 7039: Completion/Commands/_read_comp: trapping SIGINT
+	  no longer necessary after 7038.
+	
+	* pws: 7038: Src/Zle/zle_main.c: restore breaks whenever errflag
+	  is restored as SIGINT handler sets both.
+	  
+	* Sven: 7036: Src/Zle/complist.c: make sure old list is thrown
+	  away when doing accept-and-infer-next-history in menu-completion.
+	
+	* Sven: 7028: Src/Zle/zle_tricky.c,
+	  Functions/Zle/incremental-complete-word: problems when BUFFER
+	  changes, %u in i-c-w prompt, config key for showing list.
+
+	* Sven: 7026: Completion/Core/_main_complete,
+	  Completion/Core/_match, Completion/Core/_oldlist,
+	  Completion/Core/compinit: More information stored in assoc array
+	  _lastcomp about the previous completion.
+
+	* Sven: 7025: Src/Zle/complist.c: remove list when accepting
+	  and retrying completion when unambiguous.
+
+1999-07-07  Peter Stephenson  <pws@ibmth.df.unipi.it>
+
+	* pws: 7021: Src/utils.c: error message in findsep() was
+	  erroneous.
+
+	* pws: 7020: Src/params.c: error message for whole assoc array
+	  assignment.
+
+	* Oliver: 7005: Src/builtin.c, Doc/Zsh/builtins.yo: alias
+	  takes +g and + flags.
+
+	* Sven: 7004: Src/Zle/zle_refresh.c: reset showinglist on
+	  clearlist.
+
+	* pws: 7002: Completion/Commands/_read_comp: does completion
+	  lists; handle errors better.
+
+	* pws: 7001: Src/hist.c: line numbers were wrong in some error
+	  messages (e.g. conditions) when reading from a string
+	  (e.g. autoloaded functions).
+
+	* pws: 6998: Src/Zle/zle_bindings.c: restore history-search
+	  bindings \M-n, \M-p.
+
+	* Sven: 6996: Src/Zle/complist.c, Src/Zle/zle_tricky.c,
+	  Doc/Zsh/mod_complist.yo: accept-and-infer-next-history
+	  in menu-select accepts a match, then restarts menu selection.
+
+	* Sven: 6995, 7000: Src/math.c, Src/utils.c, Doc/Zsh/arith.yo:
+	  allow bindkey strings in after #\ in math mode.  Also
+	  incremental-complete-word and insert-files, added by hand
+	  to directory Functions/Zle, with appropriate changes to
+	  configure.in and INSTALL.
+
+	* Sven: 6992: Src/Zle/zle_main.c, Src/Zle/zle_misc.c,
+	  Src/Zle/zle_thingy.c, Src/Zle/zle_tricky.c, Doc/Zsh/mod_zle.yo:
+	  zle -R can take list arguments; zle -cR clears the list;
+	  zle -U puts keys in the unget queue.
+
+	* Geoff: 6991: configure.in: NetBSD can use both ELF and a.out.
+
+1999-07-06  Peter Stephenson  <pws@ibmth.df.unipi.it>
+
+	* Andrej: 6990: Completion/Builtins/_cd,
+	  Completion/Core/_path_files: some local variable fixes.
+
+	* pws: 6987: Src/builtin.c: `typeset +f' and `functions +'
+	  should just print the function name.
+
+	* pws: 6986: Doc/Zsh/builtins.yo, Doc/Zsh/params.yo,
+	  Src/builtin.c, Src/params.c, Src/zsh.h: special parameters
+	  can become local, remaining special; be more careful that
+	  only the most global parameter can appear in the environment.
+
+	* pws: 6984: Doc/Zsh/compsys.yo: typo in 6973 docs
+
+1999-07-05  Peter Stephenson  <pws@ibmth.df.unipi.it>
+
+	* pws: 6982: Src/exec.c: variable assignment with redirection is
+	  interpreted as variable assignment with redirection, not
+	  nullcmd.
+
+	* pws: 6981: Completion/Commands/_read_comp: -n should be -z.
+
+	* Sven: 6979: Completion/Core/_path_files: compconfig[path_expand]
+	  fix.
+
+	* Sven: 6977: Completion/Core/_match: cosmetic `if' change.
+
+	* Sven: 6975: Src/Zle/zle_tricky.c: fix quoting of tildes at
+	  the start of file names.
+
+	* Sven: 6974: Src/exec.c: mark superjob as locked as soon
+	  as started.
+
+	* pws: 6973: Completion/Commands/_read_comp, Doc/Zsh/compsys.yo:
+	  _read_comp allows function arguments and ^U but won't add
+	  non-printables; document Completion/Commands widgets.
+
+	* Sven: 6971: Src/exec.c, Src/jobs.c: backgrounding jobs forked
+	  from current shell works again; job table not filled up by
+	  current shell subjobs; current/previous job not lost.
+
+1999-07-04  Peter Stephenson  <pws@ibmth.df.unipi.it>
+
+	* pws: 6970: Completion/Base/_default, Completion/Builtins/_cd,
+	  Completion/Commands/_read_comp: handle magicequalsubst and
+	  cdablevars optios; _read_comp can read and execute a completion
+	  function (_*) or compgen argument (-*) on the fly.
+
+	* pws: 6969: Doc/Zsh/builtins.yo, Src/builtin.c: print -b
+	  uses full bindkey string possibilities.
+
+	* Tanaka Akira: 6968: Completion/Core/compinit: compinit -D
+	  didn't actually work.
+
+	* pws: 6967: Completion/Core/_path_files: final return status
+	  inverted.
+
+	* pws: 6966: Completion/Makefile.in, Functions/Makefile.in,
+	  Config/funcinst.mk, configure.in, INSTALL:  prevent overwriting
+	  of changed shell functions on installation; move function
+	  installation code to funcinst.mk; clear up INSTALL a bit.
+
+1999-07-03  Peter Stephenson  <pws@ibmth.df.unipi.it>
+
+	* pws: 6962: Doc/Zsh/prompt.yo, Src/prompt.c:  %/ and %~ take
+	  numbers for trailing path segments like %c and %C, %N can too;
+	  function promptpath() to implement this.
+
+	* pws: 6957: 3.1.5-pws-25 made available
+	
 	* pws: 6955, 6956: Completion/Core/compinit,
 	  Completion/Core/compinstall, Doc/Zsh/compsys.yo: better handling
 	  of subdirectory structure for completion functions; -d is default
 	  for compinit, -D turns it off; documentation updated for installed
 	  files; bugfix for compinstall re-using compconf arguments.
 
-1999-07-02  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-07-02  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Tanaka Akira: 6953: Completion/Builtins/_cd: use pushd code for cd
 
@@ -22,7 +214,7 @@
 	  send-break to exit menu selection and return to normal menu
 	  completion.
 
-1999-07-01  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-07-01  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Sven: 6936: Src/jobs.c: time builtin was broken.
 
@@ -30,7 +222,7 @@
 	  control fixes:  running external command after loop in function;
 	  function on left hand side of pipeline with loop on right.
 
-1999-06-29  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-29  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Sven: 6908, 6926: Src/exec.c, Src/jobs.c, Src/zsh.h: more job
 	  control fixes:  functions with programs that send strange
@@ -50,7 +242,7 @@
 	  some (but not all) recent job handling patches to avoid more
 	  serious problems with recalcitrant programs.
 
-1999-06-28  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-28  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6899: Doc/Zsh/params.yo, Doc/Zsh/prompt.yo, Src/init.c:
 	  default PS4 is now "+%N:%i> ", except in [k]sh emulation.
@@ -67,7 +259,7 @@
 	* Geoff: 6884: Src/Zle/zle_refresh.c: bug when redisplaying line
 	  one shorter than terminal width
 
-1999-06-27  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-27  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
         * pws: 6881: Doc/Zsh/mod_zle.yo: explain keymap linking
 
@@ -83,11 +275,11 @@
 	* pws: 6866: Src/exec.c, Src/init.c: signed/unsigned character
 	  problems; one was causing SunOS 4.1.3_U1 with gcc 2.7.0 to hang.
 
-1999-06-26  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-26  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* 3.1.5-pws-24 made available
 
-1999-06-25  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-25  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6857: Completion/Core/compinit,
 	  Completion/Core/compinstall, Doc/Zsh/compsys.yo: compinit and
@@ -110,7 +302,7 @@
 
 	* Sven: 6841: Src/loop.c: %_ in else branches for PS4
 
-1999-06-24  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-24  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6834: Src/glob.c, Src/hashtable.c: dyncat() changed always
 	  to use heap memory (as it erroneously claimed); hashtable element
@@ -142,7 +334,7 @@
 	  don't automatically switch on select widget until there are
 	  $SELECTMIN choices.
 
-1999-06-23  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-23  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6816: Doc/Zsh/params.yo, Src/utils.c:  ZBEEP parameter
 	  gives string to output instead of beeping.
@@ -185,7 +377,7 @@
 	  Src/Zle/zle_main.c, Doc/Zsh/mod_complist.yo: Local keymaps can be
 	  defined, currently only used with menu-select.
 
-1999-06-22  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-22  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Sven: 6786: Src/Zle/zle_tricky.c, Doc/Zsh/compctl.yo: only use
 	  a range when you are after the first pattern in it.
@@ -212,7 +404,7 @@
 	* Oliver: 6772: Src/Zle/zle_tricky.c: use the whole
 	  command text for job completion.
 
-1999-06-21  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-21  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Sven: 6760: Src/Zle/zle_tricky.c: menucompletion displaying new
 	  list of matches sometimes got confused.
@@ -243,7 +435,7 @@
 
 	* Bart: 6731: Doc/Zsh/compctl.yo: spelling correction
 
-1999-06-20  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-20  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* zsh-3.1.5-pws-23 made available
 	
@@ -258,7 +450,7 @@
 	  to list to restore when outside a function, but do if the function
 	  simply unsets a trap which was set outside.
 
-1999-06-18  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-18  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6718: Completion/Core/compinit, Completion/Core/compdump,
 	  Doc/Zsh/compsys.yo: rebind existing completion widgets for new
@@ -281,7 +473,7 @@
 	  of stopping a command in such a structure where the command
 	  handles interruptions in such a way that zsh doesn't see them.
 
-1999-06-17  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-17  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6705: Doc/Zsh/builtins.yo, Src/builtin.c, Src/exec.c,
 	  Src/init.c, Src/input.c, Src/parse.c: some more LINENO
@@ -328,7 +520,7 @@
 	* Wayne: 6681: Src/builtin.c: start-of-loop check for history -r
 	  was wrong.
 
-1999-06-16  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-16  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6679: Src/Zle/zle_thingy.c, Doc/Zsh/compwid.yo:  always
 	  use .complete-word etc. as widget type in zle -C.
@@ -365,7 +557,7 @@
 	* Bart: 6646: Src/lex.c: extra braces to enhance beauty of code
 	  which appeared in 3.0.5.
 
-1999-06-15  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-15  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Tanaka Akira: 6642: Completion/Base/_tilde: complete directory
 	  stack elements after ~+ or ~-.
@@ -388,7 +580,7 @@
 	* Bart: 6628: Src/params.c: setting slices of unset array
 	  caused a crash.
 
-1999-06-14  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-14  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6626: Src/mem.c: in zsh's malloc, try to make sure when
 	  sbrk'ing that it's sufficiently well aligned.
@@ -419,7 +611,7 @@
 	  expn.yo, files.yo, mod_mapfile.yo, mod_zftp.yo, params.yo,
 	  zftpsys.yo, zle.yo: spelling corrections
 
-1999-06-12  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-12  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6601: Src/Makefile.in: don't remake Makemod just
 	  to clean up files
@@ -439,7 +631,7 @@
 	* Wayne: 6599: Src/Zle/zle_tricky.c: unitialised variable warnings
 	  from gcc
 
-1999-06-11  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-11  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6598: Doc/Zsh/zftpsys.yo, Functions/Zftp/zfinit,
 	  Functions/Zftp/zfgoto, Functions/Zftp/zfmark,
@@ -461,7 +653,7 @@
 	  struct cmd to insert cmd args and flags, always pass those
 	  separately
 
-1999-06-10  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-10  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Andrej: 6581: Doc/Makefile: dependencies for manuals
 
@@ -497,7 +689,7 @@
 
 	* Sven: 6557: Doc/zsh/compsys.yo: a few typos
 
-1999-06-09  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-09  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Andrej: 6556: aczsh.m4: don't disable setting variables
 	  for --enable-lfs just because some other variables were set
@@ -543,7 +735,7 @@
 	  on Solaris 2.7, despite previous reports; Sven says on Digital
 	  UNIX 4.0, you need special DLLD and LDFLAGS.
 
-1999-06-08  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-08  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: 6525: Src/lex.c (gettokstr): allow parentheses after
 	  first character in command word
@@ -560,7 +752,7 @@
 
 	* Wayne: 6510: Completion/Core/compinit: another nounset problem
 
-1999-06-07  Peter Stephenson  <pws@ibmth.difi.unipi.it>
+1999-06-07  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* pws: configure.in, Config/defs.mk.in, Functions/Makefile.in,
 	  Completion/Makefile.in, rearrangement of Functions
@@ -613,12 +805,12 @@
 	* 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>
+1999-06-06  Peter Stephenson  <pws@ibmth.df.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>
+1999-06-05  Peter Stephenson  <pws@ibmth.df.unipi.it>
 
 	* Merge ChangeLog entry from patchlist.txt in 3.1.5-pws-20
 	  These are briefer than normal ChangeLog entries, but upgrading
diff --git a/Completion/Base/_command_names b/Completion/Base/_command_names
index 8f75f1a77..61fea56dd 100644
--- a/Completion/Base/_command_names
+++ b/Completion/Base/_command_names
@@ -2,6 +2,13 @@
 
 local nm=$compstate[nmatches] ret=1
 
+
+# Complete jobs in implicit fg and bg
+if [[ "$PREFIX[1]" = "%" ]]; then
+  compgen -j -P '%'
+  [[ nm -ne compstate[nmatches] ]] && return
+fi
+
 compgen -c && ret=0
 
 if [[ nm -eq compstate[nmatches] ]]; then
diff --git a/Completion/Base/_default b/Completion/Base/_default
index b49ca7115..03bbfd49f 100644
--- a/Completion/Base/_default
+++ b/Completion/Base/_default
@@ -11,4 +11,11 @@
 
 compcall || return 0
 
-_files
+_files && return
+
+# magicequalsubst allows arguments like <any-old-stuff>=~/foo to do
+# file name expansion after the =.  In that case, it's natural to
+# allow completion to handle file names after any equals sign.
+if [[ -o magicequalsubst ]] && compset -P 1 '*='; then
+  _files
+fi
diff --git a/Completion/Base/_parameter b/Completion/Base/_parameter
index 7200ae440..b235a5fee 100644
--- a/Completion/Base/_parameter
+++ b/Completion/Base/_parameter
@@ -1,3 +1,3 @@
 #compdef -parameter-
 
-compgen -v
+_parameters -S ' ' -r '['
diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd
index 4a846c6aa..9ac29b8f8 100644
--- a/Completion/Builtins/_cd
+++ b/Completion/Builtins/_cd
@@ -11,11 +11,8 @@
 #    it's not a lot of use.  If you don't type the + or - it will
 #    complete directories as normal.
 
-local pushdminus
-[[ -o pushdminus ]] && pushdminus=1
-
-emulate -LR zsh
-setopt extendedglob
+emulate -L zsh
+setopt extendedglob nonomatch
 
 if [[ CURRENT -eq 3 ]]; then
   # cd old new: look for old in $PWD and see what can replace it
@@ -40,8 +37,8 @@ elif [[ $PREFIX = [-+]* ]]; then
   lines="$(dirs -v)"
   # turn the lines into an array, removing the current directory
   list=(${${(f)lines}##0*})
-  if [[ ( $IPREFIX = - && -z $pushdminus ) ||
-        ( $IPREFIX = + && -n $pushdminus ) ]]; then
+  if [[ ( $IPREFIX = - && ! -o pushdminus ) ||
+        ( $IPREFIX = + && -o pushdminus ) ]]; then
     # reverse the numbering: it counts the last one as -0, which
     # is a little strange.
     integer tot i
@@ -59,7 +56,19 @@ elif [[ $PREFIX = [-+]* ]]; then
 
   return ret
 elif [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then
-  _path_files -W "(. $cdpath)" -/
+  local tdir tdir2
+  # With cdablevars, we can convert foo/bar/... to ~foo/bar/... if
+  # there is no directory foo.  In that case we could also complete
+  # variable names, but it hardly seems worth it.
+  # Note we need a tilde because cdablevars also allows user home
+  # directories, hence we also need nonomatch to suppress error messages.
+  if [[ -o cdablevars && ! -d ${tdir::=${PREFIX%%/*}} &&
+    -d ${~tdir2::="~$tdir"} ]]; then
+      PREFIX="~$PREFIX"
+      _path_files -/
+  else
+    _path_files -W "(. $cdpath)" -/
+  fi
 else
   _path_files -/
 fi
diff --git a/Completion/Commands/.distfiles b/Completion/Commands/.distfiles
index 7b2a319fe..7fef35230 100644
--- a/Completion/Commands/.distfiles
+++ b/Completion/Commands/.distfiles
@@ -1,3 +1,4 @@
 DISTFILES_SRC='
-    .distfiles _correct_filename _correct_word _expand_word _most_recent_file 
+    .distfiles _correct_filename _correct_word _expand_word 
+    _history_complete_word _read_comp _most_recent_file 
 '
diff --git a/Completion/Commands/_history_complete_word b/Completion/Commands/_history_complete_word
new file mode 100644
index 000000000..fc67c0f14
--- /dev/null
+++ b/Completion/Commands/_history_complete_word
@@ -0,0 +1,2 @@
+#compdef -k complete-word \e/
+compgen -Q -H 0 ''
diff --git a/Completion/Commands/_read_comp b/Completion/Commands/_read_comp
new file mode 100644
index 000000000..a32879b56
--- /dev/null
+++ b/Completion/Commands/_read_comp
@@ -0,0 +1,158 @@
+#compdef -k complete-word \C-x\C-r
+
+# This allows an on-the-fly choice of completions.  On typing the key
+# sequence given above, you will be prompted for a string of arguments.  If
+# this string begins with `_', it will be taken as the name of a function to
+# evaluate to generate the completions; unambiguous strings in the function
+# name are automatically completed.
+#
+# Else it is taken to be a set of arguments for compgen to generate a list
+# of choices.  The possibilities are the same as the flags for generating
+# completions given in the zshcompctl manual page.  Note the arguments are
+# verbatim:  include minus signs, spaces, quotes, etc.
+#
+# On subsequent calls, the same completion will be re-performed.  To
+# force a new type of completion to be read, supply a numeric argument.
+#
+# For example,
+#  % bindkey | grep rever<C-xC-r>
+#  Completion: -b<RET>
+#  % bindkey | grep reverse-menu-complete _
+#
+# Global variables used:
+#  _read_comp         Last completion string read from user
+
+emulate -L zsh
+setopt extendedglob nobadpattern # xtrace promptsubst
+# local PS4='%N:%i:$((#key))> '
+
+# Took me ages to work this out.  If we're not on the first global
+# matcher specification, we mustn't do any I/O.
+if [[ compstate[matcher] -gt 1 && -z $_read_comp ]]; then
+  return 1
+fi
+
+if [[ compstate[matcher] -gt 1 ||
+  ( ${+NUMERIC} = 0 && -n $_read_comp ) ]]; then
+  if [[ $_read_comp = _* ]]; then
+    eval $_read_comp
+  else
+    eval "compgen $_read_comp"
+  fi
+  return
+fi
+
+_read_comp=
+
+local key search str str2 newch funcs funcs2 exact msg list
+integer pos
+
+msg="Completion: "
+
+zle -R $msg
+
+if ! read -k key; then
+  zle -cR ''
+  return 1
+fi
+
+while [[ '#key' -ne 10 && '#key' -ne 13 ]]; do
+  if [[ '#key' -eq 0 && '#key' -eq 3 || '#key' -eq 7 ]]; then
+    zle -cR ''
+    return 1
+  fi
+  if [[ ( '#key' -eq 8 || '#key' -eq 127 ) && -n $str ]]; then
+    # delete character
+    str="$str[1,-2]"
+    exact=
+    list=()
+  elif [[ '#key' -eq 21 ]]; then
+    # ^U: delete line
+    str=
+    exact=
+    list=()
+  elif [[ '#key' -eq 4 && $str = _[^\ ]# && $str != *' '* ]]; then
+    # ^D: list completions
+    list=(${$(whence -m "$str*" 2>/dev/null)%: function})
+  elif [[ ( -n $exact && $key != ' ' ) || '#key & 127' -lt 32 ]]; then
+    # If we've got an exact function, only allow a space after it.
+    # Don't try to insert non-printing characters.
+    if [[ -n $ZBEEP ]]; then
+      print -nb $ZBEEP
+    elif [[ -o beep ]]; then
+      print -n "\a"
+    fi
+    list=()
+  else
+    str="$str$key"
+    if [[ $str = _[^\ ]# ]]; then
+      # Rudimentary completion for function names.
+      # Allow arguments, i.e. don't do this after we've got a space.
+      funcs=(${$(whence -m "$str*" 2>/dev/null)%: function})
+      if [[ -o autolist && $#str -gt 1 ]]; then
+	list=($funcs)
+      else
+	list=()
+      fi
+      if (( $#funcs == 1 )); then
+	# Exact match; prompt the user for a newline to confirm
+	str=$funcs[1]
+	exact=" (Confirm)"
+      elif (( $#funcs == 0 )); then
+	# We can't call zle beep, because this isn't a zle widget.
+	if [[ -n $ZBEEP ]]; then
+	  print -nb $ZBEEP
+	elif [[ -o beep ]]; then
+	  print -n "\a"
+	fi
+	str="$str[1,-2]"
+	list=()
+      else
+	# Add characters to the string until a name doesn't
+	# match any more, then backtrack one character to get
+	# the longest unambiguous match.
+	str2=$str
+	pos=$#str2
+	while true; do
+	  (( pos++ ))
+	  newch=${funcs[1][pos]}
+	  [[ -z $newch ]] && break
+	  str2=$str2$newch
+	  funcs2=(${funcs##$str2*})
+	  (( $#funcs2 )) && break
+	  str=$str2
+	done
+      fi
+    else
+      exact=
+    fi
+  fi
+  if (( $#list )); then
+    zle -R "$msg$str$exact" $list
+  else
+    zle -cR "$msg$str$exact"
+  fi
+  if ! read -k key; then
+    zle -cR ''
+    return 1
+  fi
+done
+
+if [[ -z $str ]]; then
+  # string must be non-zero
+  return 1
+elif [[ $str = _* ]] && ! whence ${str%% *} >& /dev/null; then
+  # a function must be known to the shell
+  return 1
+else
+  # remember the string for re-use
+  _read_comp=$str
+fi
+
+zle -cR ''
+
+if [[ $str = _* ]]; then
+  eval $str
+else
+  eval "compgen $str"
+fi
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index 62e60a1cc..af659e1d4 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -15,9 +15,13 @@
 #    any matches, correction is tried and if that doesn't yield
 #    anything either, correcting completion is attempted.
 #
-# These completer functions are only used when this function is called
-# without arguments. If arguments are given, they should be names of
-# completer functions which will then be called.
+#    These completer functions are only used when this function is called
+#    without arguments. If arguments are given, they should be names of
+#    completer functions which will then be called.
+#
+#  last_prompt
+#    If this is set to `always' the cursor is moved up to the last prompt
+#    after printing a list even if a numeric argument was given.
 
 
 # If you want to complete only set or unset options for the unsetopt
@@ -33,7 +37,7 @@
 # state than the global one for which you are completing.
 
 
-local comp
+local comp ret=1
 
 setopt localoptions nullglob rcexpandparam
 unsetopt markdirs globsubst shwordsplit nounset ksharrays
@@ -54,5 +58,21 @@ fi
 # And now just call the completer functions defined.
 
 for comp; do
-  "$comp" && return
+  if "$comp"; then
+    ret=0
+    break;
+  fi
 done
+
+[[ "$compconfig[last_prompt]" = always ]] && compstate[last_prompt]=yes
+
+_lastcomp=( "${(@kv)compstate}" )
+_lastcomp[completer]="$comp"
+_lastcomp[prefix]="$PREFIX"
+_lastcomp[suffix]="$SUFFIX"
+_lastcomp[iprefix]="$IPREFIX"
+_lastcomp[isuffix]="$ISUFFIX"
+_lastcomp[qiprefix]="$QIPREFIX"
+_lastcomp[qisuffix]="$QISUFFIX"
+
+return ret
diff --git a/Completion/Core/_match b/Completion/Core/_match
index 251c65381..a4499dc08 100644
--- a/Completion/Core/_match
+++ b/Completion/Core/_match
@@ -60,10 +60,8 @@ _complete && ret=1
 compstate[pattern_match]="$opm"
 compstate[matcher]="$compstate[total_matchers]"
 
-if (( ! ret )); then
-  [[ "$compconfig[match_insert]" = unambig* &&
-     $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] && 
-      compstate[pattern_insert]=unambiguous
-fi
+[[ ret -eq 1 && "$compconfig[match_insert]" = unambig* &&
+   $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] && 
+    compstate[pattern_insert]=unambiguous
 
 return 1-ret
diff --git a/Completion/Core/_oldlist b/Completion/Core/_oldlist
index f42197695..bdf12f90c 100644
--- a/Completion/Core/_oldlist
+++ b/Completion/Core/_oldlist
@@ -4,12 +4,24 @@
 # and either the compconfig key oldlist_list is `always', or it is not `never'
 # and the list is not already shown, then use the existing list for listing
 # (even if it was generated by another widget).
-if [[ -n $compstate[old_list] && $compconfig[oldlist_list] != never &&
-  $WIDGET = *list* &&
-  ( $compconfig[oldlist_list] = always || $compstate[old_list] != shown ) ]]
-then
-  compstate[old_list]=keep
-  return 0
+# Do this also if there is an old list and it was generated by the
+# completer named by the oldlist_list key.
+if [[ -n $compstate[old_list] && $compconfig[oldlist_list] != never ]]; then
+  if [[ $WIDGET = *list* &&
+        ( $compconfig[oldlist_list] = always ||
+	  $compstate[old_list] != shown ) ]]; then
+    compstate[old_list]=keep
+    return 0
+  elif [[ $compconfig[oldlist_list] = *${_lastcomp[completer]}* ]]; then
+    [[ "$_lastcomp[insert]" = unambig* ]] && compstate[to_end]=single
+    compstate[old_list]=keep
+    if [[ -o automenu ]]; then
+      compstate[insert]=menu
+    else
+      compadd -Qs "$SUFFIX" - "$PREFIX"
+    fi
+    return 0
+  fi
 fi
 
 # If this is a completion widget, and we have a completion inserted already,
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index 58f343367..e65f814e1 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -33,12 +33,11 @@ typeset -U prepaths exppaths
 setopt localoptions nullglob rcexpandparam extendedglob
 unsetopt markdirs globsubst shwordsplit nounset
 
+local sopt='-' gopt='' opt
 exppaths=()
 prepaths=('')
 ignore=()
 group=()
-sopt='-'
-gopt=''
 pats=()
 addpfx=()
 addsfx=()
@@ -377,9 +376,9 @@ done
 exppaths=( "${(@)exppaths:#$orig}" )
 
 if [[ -n "$compconfig[path_expand]" &&
-      $#exppaths -eq 0 && nm -eq compstate[nmatches] ]]; then
+      $#exppaths -eq 1 && nm -eq compstate[nmatches] ]]; then
   compadd -QU -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
           -M 'r:|/=* r:|=*' -p "$linepath" - "${(@)exppaths}"
 fi
 
-[[ nm -eq compstate[nmatches] ]]
+[[ nm -ne compstate[nmatches] ]]
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index 9302d8243..63e4c0860 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -49,7 +49,7 @@ emulate -L zsh
 typeset _i_dumpfile _i_files _i_line _i_done _i_dir _i_autodump=1
 typeset _i_tag _i_file _i_addfiles
 
-while [[ $# -gt 0 && $1 = -[df] ]]; do
+while [[ $# -gt 0 && $1 = -[dDf] ]]; do
   if [[ "$1" = -d ]]; then
     _i_autodump=1
     shift
@@ -59,6 +59,7 @@ while [[ $# -gt 0 && $1 = -[df] ]]; do
     fi
   elif [[ "$1" = -D ]]; then
     _i_autodump=0
+    shift
   elif [[ "$1" = -f ]]; then
     # Not used any more; use _compdir
     shift
@@ -72,6 +73,11 @@ done
 typeset -gA _comps
 _patcomps=()
 
+# The associative array use to report information about the last
+# cmpletion to the outside.
+
+typeset -gA _lastcomp
+
 # This is the associative array used for configuration.
 
 typeset -gA compconfig
@@ -308,10 +314,10 @@ if [[ $#_i_files -lt 20 || $_compdir = */Core || -d $_compdir/Core ]]; then
     fi
     for _i_line in {1..$#i_addfiles}; do
       _i_file=${_i_addfiles[$_i_line]}
-      [[ -d $_i_file && -z ${fpath[(r)$_i_$file]} ]] ||
+      [[ -d $_i_file && -z ${fpath[(r)$_i_file]} ]] ||
         _i_addfiles[$_i_line]=
     done
-    fpath=($_i_addfiles $fpath)
+    fpath=($fpath $_i_addfiles)
     _i_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
   fi
 fi
diff --git a/Completion/Core/compinstall b/Completion/Core/compinstall
index 52b4bf707..bd58d643b 100644
--- a/Completion/Core/compinstall
+++ b/Completion/Core/compinstall
@@ -136,7 +136,7 @@ fi
 
 # Check if this is in fpath already, else put it there (with ~'s expanded).
 _ci_f=${~_ci_fdir}
-[[ -z ${fpath[(r)$_ci_f]} ]] && fpath=($_ci_f $fpath)
+[[ -z ${fpath[(r)$_ci_f]} ]] && fpath=($fpath $_ci_f)
 
 # Contract $HOME to ~ in the parameter to be used for writing.
 _ci_fdir=${_ci_fdir/#$HOME/\~}
@@ -183,7 +183,7 @@ ${_ci_dumpfile}.  Please edit a replacement."
 fi
 
 _ci_lines="${_ci_lines}_compdir=$_ci_fdir
-[[ -z \$fpath[(r)\$_compdir] ]] && fpath=(\$_compdir \$fpath)
+[[ -z \$fpath[(r)\$_compdir] ]] && fpath=(\$fpath \$_compdir)
 autoload -U compinit
 compinit"
 [[ $_ci_dtype != standard ]] && _ci_lines="${_ci_lines} $_ci_dumpfile"
diff --git a/Completion/Makefile.in b/Completion/Makefile.in
index 0ac4de304..27f88d01f 100644
--- a/Completion/Makefile.in
+++ b/Completion/Makefile.in
@@ -48,40 +48,7 @@ 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 \
-	      if test x$(FUNCTIONS_SUBDIRS) != x -a \
-	      x$(FUNCTIONS_SUBDIRS) != xno; then \
-	        subdir="`echo $$file | sed -e 's%/.*%%'`"; \
-	        $(sdir_top)/mkinstalldirs $(fndir)/$$subdir || exit 1; \
-	        $(INSTALL_DATA) $$file $(fndir)/$$subdir || exit 1; \
-	      else \
-	        $(INSTALL_DATA) $$file $(fndir) || exit 1; \
-	      fi; \
-	    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 \
-	      if test x$(FUNCTIONS_SUBDIRS) != x -a \
-              x$(FUNCTIONS_SUBDIRS) != xno; then \
-	        rm -f $(fndir)/$$file; \
-	      else \
-	        rm -f "$(fndir)/`echo $$file | sed -e 's%^.*/%%'`"; \
-	      fi; \
-	    fi; \
-	  done; \
-	fi; \
-	exit 0
+@FUNCINST_MK@
 
 # ========== DEPENDENCIES FOR CLEANUP ==========
 
diff --git a/Completion/User/.distfiles b/Completion/User/.distfiles
index 07fddc134..c96f2ba3e 100644
--- a/Completion/User/.distfiles
+++ b/Completion/User/.distfiles
@@ -1,6 +1,6 @@
 DISTFILES_SRC='
     .distfiles
     _a2ps _chown _compress _configure _dd _dvi _find _groups _gunzip _gzip
-    _hosts _make _man _mh _pdf _ps _rcs _rlogin _strip _stty
+    _hosts _use_lo _make _man _mh _pdf _ps _rcs _rlogin _strip _stty
     _tar _tar_archive _tex _uncompress _x_options _xfig 
 '
diff --git a/Completion/User/_ps b/Completion/User/_ps
index 6c0d91a23..39e357b69 100644
--- a/Completion/User/_ps
+++ b/Completion/User/_ps
@@ -1,3 +1,3 @@
-#compdef  gs ghostview gview psnup psselect pswrap pstops pstruct lpr
+#compdef  gs ghostview gv gview psnup psselect pswrap pstops pstruct lpr lp
 
 _files -g '*([pP][sS]|eps)'
diff --git a/Completion/User/_tar b/Completion/User/_tar
index f443fefb7..5fcce5c67 100644
--- a/Completion/User/_tar
+++ b/Completion/User/_tar
@@ -75,6 +75,7 @@ if [[ "$PREFIX" = --* ]]; then
   _long_options '--owner*'          "_tilde" \
                 '*=(PROG|COMMAND)*' "_command_names" \
 		'*=ARCHIVE*'        "_tar_archive" \
+		'*=NAME*'           "_files" \
 		'*=CONTROL*'        "[t numbered nil existing never simple]"
 
 elif [[ ( CURRENT -gt 2 && "$words[CURRENT-1]" = -*f* &&
diff --git a/Completion/User/_use_lo b/Completion/User/_use_lo
new file mode 100644
index 000000000..e469154ea
--- /dev/null
+++ b/Completion/User/_use_lo
@@ -0,0 +1,10 @@
+#compdef gls gdiff
+
+# This is for GNU-like commands which understand the --help option,
+# but which do not otherwise require special completion handling.
+
+if [[ $PREFIX = --* ]]; then
+  _long_options
+else
+  _default
+fi
diff --git a/Config/.distfiles b/Config/.distfiles
index cedbd27cf..0635f5405 100644
--- a/Config/.distfiles
+++ b/Config/.distfiles
@@ -1,4 +1,5 @@
 DISTFILES_SRC='
     .distfiles .cvsignore
-    clean.mk config.mk defs.mk.in version.mk
+    clean.mk config.mk defs.mk.in funcinst.mk version.mk
+    installfns.sh uninstallfns.sh
 '
diff --git a/Config/funcinst.mk b/Config/funcinst.mk
new file mode 100644
index 000000000..e473eb351
--- /dev/null
+++ b/Config/funcinst.mk
@@ -0,0 +1,47 @@
+#
+# Makefile definitions for installing shell functions
+#
+# Copyright (c) 1999 Peter Stephenson
+# 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.
+#
+
+# 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="$(sdir_top)" fndir="$(fndir)" sdir="$(sdir)" \
+	  FUNCTIONS_INSTALL="$(FUNCTIONS_INSTALL)" \
+	  FUNCTIONS_SUBDIRS="$(FUNCTIONS_SUBDIRS)" \
+	  INSTALL_DATA="$(INSTALL_DATA)" \
+	  $(SHELL) $(sdir_top)/Config/installfns.sh || exit 1; \
+	fi; \
+	exit 0
+
+uninstall.fns:
+	if test x$(fndir) != x && test x$(fndir) != xno; then \
+	  fndir="$(fndir)" sdir="$(sdir)" \
+	  FUNCTIONS_INSTALL="$(FUNCTIONS_INSTALL)" \
+	  FUNCTIONS_SUBDIRS="$(FUNCTIONS_SUBDIRS)" \
+	  $(SHELL) $(sdir_top)/Config/uninstallfns.sh || exit 1; \
+	fi; \
+	exit 0
diff --git a/Config/installfns.sh b/Config/installfns.sh
new file mode 100755
index 000000000..de7a52bce
--- /dev/null
+++ b/Config/installfns.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+if test -d $fndir.old; then
+  add_old=1
+fi
+
+$sdir_top/mkinstalldirs $fndir || exit 1;
+
+# If the source directory is somewhere else, we need to force
+# the shell to expand it in that directory, then strip it off.
+install=
+for file in $FUNCTIONS_INSTALL; do
+  if test -f "$sdir/$file"; then
+    install="$install $file"
+  else
+    install="$install `echo $sdir/$file | sed -e \"s%$sdir/%%g\"`"
+  fi
+done
+
+for file in $install; do
+  if test -f $sdir/$file; then
+    if test x$FUNCTIONS_SUBDIRS != x -a x$FUNCTIONS_SUBDIRS != xno; then
+      subfile="$file"
+      subdir="`echo $file | sed -e 's%/[^/]*$%%'`"
+      olddir="$fndir.old/$subdir"
+      instdir="$fndir/$subdir"
+    else
+      subfile="`echo $file | sed -e 's%^.*/%%'`"
+      olddir="$fndir.old"
+      instdir="$fndir"
+    fi
+    if test -f $fndir/$subfile; then
+      if cmp $fndir/$subfile $sdir/$file >/dev/null; then :; else
+	$sdir_top/mkinstalldirs $olddir
+        mv $fndir/$subfile $olddir
+        : ${add_old:=1}
+      fi
+    fi
+    $sdir_top/mkinstalldirs $instdir || exit 1
+    $INSTALL_DATA $sdir/$file $instdir || exit 1
+  fi
+done
+
+if test x$add_old != x1; then
+  rm -rf $fndir.old
+fi
+
+exit 0
diff --git a/Config/uninstallfns.sh b/Config/uninstallfns.sh
new file mode 100755
index 000000000..ae1b4fef5
--- /dev/null
+++ b/Config/uninstallfns.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# If the source directory is somewhere else, we need to force
+# the shell to expand it in that directory, then strip it off.
+install=
+for file in $FUNCTIONS_INSTALL; do
+  if test -f "$sdir/$file"; then
+    install="$install $file"
+  else
+    install="$install `echo $sdir/$file | sed -e \"s%$sdir/%%g\"`"
+  fi
+done
+
+for file in $install; do
+  if test -f $sdir/$file; then
+    if test x$FUNCTIONS_SUBDIRS != x -a x$FUNCTIONS_SUBDIRS != xno; then
+      rm -f $fndir/$file;
+      if test -f $fndir.old/$file; then
+	mv $fndir.old/$file $fndir/$file
+      fi
+    else
+      bfile="`echo $file | sed -e 's%^.*/%%'`"
+      rm -f "$fndir/$bfile"; \
+      if test -f $fndir.old/$bfile; then
+        mv $fndir.old/$bfile $fndir/$bfile
+      fi
+    fi
+  fi
+done
+
+exit 0
diff --git a/Config/version.mk b/Config/version.mk
index ab59f05ce..30858c298 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-25
-VERSION_DATE='July 3, 1999'
+VERSION=3.1.6-test-1
+VERSION_DATE='July 9, 1999'
diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo
index f22b35794..80c023301 100644
--- a/Doc/Zsh/arith.yo
+++ b/Doc/Zsh/arith.yo
@@ -74,11 +74,12 @@ is evaluated.  Note the precedence of the bitwise AND, OR,
 and XOR operators.
 
 An expression of the form `tt(#\)var(x)' where var(x) is any character
-gives the ascii value of this character and an expression of the form
-`tt(#)var(foo)' gives the ascii value of the first character of the value
-of the parameter var(foo).  Note that this is different from the expression
-`tt($#)var(foo)', a standard parameter substitution which gives the length
-of the parameter var(foo).
+sequence such as `tt(a)', `tt(^A)', or `tt(\M-\C-x)' gives the ascii
+value of this character and an expression of the form `tt(#)var(foo)'
+gives the ascii value of the first character of the value of the
+parameter var(foo).  Note that this is different from the expression
+`tt($#)var(foo)', a standard parameter substitution which gives the
+length of the parameter var(foo).
 
 Named parameters and subscripted arrays can be referenced by name within an
 arithmetic expression without using the parameter expansion syntax.  For
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 10202dbce..f6e24ab51 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -44,7 +44,7 @@ This command only expands parameters.  A zero exit code is returned.
 findex(alias)
 cindex(aliases, defining)
 cindex(aliases, listing)
-item(tt(alias) [ tt(-gmrL) ] [ var(name)[tt(=)var(value)] ... ])(
+item(tt(alias) [ {tt(PLUS()|tt(-))}tt(gmrL) ] [ var(name)[tt(=)var(value)] ... ])(
 For each var(name) with a corresponding var(value), define an alias
 with that value.  A trailing space in var(value) causes the next word
 to be checked for alias expansion.  If the tt(-g) flag is present,
@@ -58,7 +58,9 @@ are taken as patterns (they should be quoted to preserve them from being
 interpreted as glob patterns), and the aliases matching these patterns
 are printed.  When printing aliases and the tt(-g) or tt(-r) flags
 are present, then restrict the printing to global or regular
-aliases, respectively.
+aliases, respectively.  Using `tt(PLUS())' instead of `tt(-)', or ending
+the option list with a single `tt(PLUS())', prevents the values of the
+aliases from being printed.
 
 If the tt(-L) flag is present, then print each
 alias in a manner suitable for putting in a startup script.  The exit
@@ -550,7 +552,7 @@ If the tt(PUSHD_MINUS) option is set, the meanings of `tt(PLUS())' and
 `tt(-)' in this context are swapped.
 )
 findex(print)
-item(tt(print) [ tt(-nrslzpNDPoOicm) ] [ tt(-u)var(n) ] [ tt(-R) [ tt(-en) ]] [ var(arg) ... ])(
+item(tt(print) [ tt(-bnrslzpNDPoOicm) ] [ tt(-u)var(n) ] [ tt(-R) [ tt(-en) ]] [ var(arg) ... ])(
 With no flags or with flag `tt(-)', the arguments are printed on
 the standard output as described by tt(echo), with the following differences:
 the escape sequence `tt(\M-)var(x)' metafies the character
@@ -570,6 +572,13 @@ unless the tt(-e) flag is given.  The tt(-n) flag suppresses the trailing
 newline.  Only the tt(-e) and tt(-n) flags are recognized after
 tt(-R); all other arguments and options are printed.
 )
+item(tt(-b))(
+Recognize all the escape sequences defined for the tt(bindkey) command,
+see 
+ifzman(zmanref(zshmodules))\
+ifnzman(noderef(The zle Module))\
+.
+)
 item(tt(-m))(
 Take the first argument as a pattern (should be quoted), and remove
 it from the argument list together with subsequent arguments that
@@ -917,15 +926,18 @@ ifzman(`Local Parameters' in zmanref(zshparam))\
 ifnzman(noderef(Local Parameters))\
 .  Local parameters are not exported unless tt(ALL_EXPORT) is set, in
 which case the parameter is exported em(only) when var(name) does not
-already appear in the environment.
+already exist.  The same rules apply to special shell parameters, which
+retain their special attributes when made local.
 
 For each var(name)tt(=)var(value) assignment, the parameter
 var(name) set to var(value).  Note that arrays currently cannot be
 assigned in tt(typeset) expressions; scalars and integers only.
 
-For each remaining var(name) that refers to a parameter that is set,
-the name and value of the parameter are printed in the form of an
-assignment.  Nothing is printed for newly-created parameters.
+For each remaining var(name) that refers to a parameter that is set, the
+name and value of the parameter are printed in the form of an assignment.
+Nothing is printed for newly-created parameters, or if any attribute flags
+listed below are given.  Using `tt(PLUS())' instead of minus to introduce
+an attribute turns it off.
 
 If the tt(-T) option is given, exactly two (or zero) var(name)
 arguments must be present.  They represent a scalar and an array (in
@@ -951,13 +963,16 @@ has no effect when listing existing parameters, nor does the flag tt(+g)
 have any effect.
 
 If no var(name) is present, the names and values of all parameters are
-printed.  In this case the attribute flags restrict the display to
-only those parameters that have the specified attributes.  Using
-`tt(PLUS())' rather than `tt(-)' to introduce the flag causes the
-attribute to be turned off, and suppresses printing of the names and
-values.  If only the tt(-m) flag is given the arguments are taken as
-patterns (should be quoted) and all parameters (or functions with the
-tt(-f) flag) with matching names are printed.
+printed.  In this case the attribute flags restrict the display to only
+those parameters that have the specified attributes, and using `tt(PLUS())'
+rather than `tt(-)' to introduce the flag suppresses printing of the values
+of parameters when there is no parameter name.  Also, if the option list
+ends with `tt(PLUS())', values will not be printed.  If only the tt(-m)
+flag is given the arguments are taken as patterns (should be quoted) and
+all parameters (or functions with the tt(-f) flag) with matching names are
+printed.  If no attribute flags and no tt(-m) flag is present, the
+parameter names will be preceded by a list of any attributes (tt(array),
+tt(association), tt(exported), tt(integer), tt(readonly)).
 
 The following attribute flags may be specified:
 
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 2de4e4bd7..477fbdc77 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -17,6 +17,7 @@ menu(Initialization)
 menu(Control Functions)
 menu(Completion Functions)
 menu(Completion Directories)
+menu(Bindable Commands)
 endmenu()
 
 texinode(Initialization)(Control Functions)()(Completion System)
@@ -248,6 +249,11 @@ of the completer functions to decide if other completers should be
 called. If the return value is zero, no other completers are tried and the
 tt(_main_complete) function returns.
 
+The widget function tt(_main_complete) also uses the configuration key 
+tt(last_prompt). If this is set to tt(always), the cursor is moved up
+to the last prompt after printing a list of matches even if a numeric
+argument was given.
+
 The following completer functions are contained in the distribution (users
 may write their own):
 
@@ -578,7 +584,10 @@ it is set to tt(never), this will not be done (the behaviour without the
 tt(_oldlist) completer).  If it is unset, or any other value, then the
 existing list of completions will be displayed if it is not already;
 otherwise, the standard completion list will be generated:  this is the
-default behaviour of tt(_oldlist).
+default behaviour of tt(_oldlist). However, if there is an old list
+and this key contains the name of the completer function that
+generated the list, then the old list will be used even if it was
+generated by a widget which does not listing.
 
 For example, suppose you type tt(^Xc) to use the tt(_correct_word)
 widget, which generates a list of corrections for the word under the
@@ -586,6 +595,14 @@ cursor.  Usually, typing tt(^D) would generate a standard list of
 completions for the word on the command line, and show that.  With
 tt(_oldlist), it will instead show the list of corrections already
 generated.
+
+As another example consider the tt(_match) completer: with the
+tt(match_insert) key set to tt(unambig) it inserts only an
+unambiguous prefix string if there is any. But since this may remove
+parts of the original pattern, attempting completion again may result
+in more matches than on the first attempt. But by using the
+tt(_oldlist) completer and setting this key to tt(_match), the list of 
+matches generated on the first attempt will be used again.
 )
 item(tt(oldlist_menu))(
 Controls how menu completion behaves when a completion has already been
@@ -769,7 +786,7 @@ on words starting with two hyphens.
 )
 enditem()
 
-texinode(Completion Directories)()(Completion Functions)(Completion System)
+texinode(Completion Directories)(Bindable Commands)(Completion Functions)(Completion System)
 sect(Completion Directories)
 
 In the source distribution, the files are contained in various
@@ -802,3 +819,63 @@ Functions which implement special types of completion to be bound to
 keystrokes rather than called by context.
 )
 enditem()
+
+texinode(Bindable Commands)()(Completion Directories)(Completion System)
+sect(Bindable Commands)
+
+In addition to the context-dependent completions provided, which are
+expected to work in an intuitively obvious way, there are a few widgets
+implementing special behaviour which can be bound separately to keys.  The
+following is a list of these and their default bindings.
+
+startitem()
+item(tt(_correct_filename (^XC)))(
+Correct the filename path at the cursor position.  Allows up to six errors
+in the name.  Can also be correctly called with an argument to correct
+a filepath, independently of zle.
+)
+item(tt(_correct_word) (^Xc))(
+Performs correction of the current argument using the usual contextual
+completions as possible choices.
+)
+item(tt(_expand_word (^Xe)))(
+Performs expansion on the current word:  equivalent to the standard
+tt(expand-word) command, but using all the `tt(expand_*)' configuration
+keys described previously.  In addition, each such key can be overridden by
+a key starting with the string `tt(expandword_)'; for example, the
+tt(expandword_substitute) key if defined overrides the
+tt(expand_substitute) key.
+)
+item(tt(_history_complete_word) (\e/))(
+Complete words from the shell's command history.
+)
+item(tt(_most_recent_file (^Xm)))(
+Complete the name of the most recently modified file matching the pattern
+on the command line (which may be blank).  If given a numeric argument
+var(N), complete the var(N)th most recently modified file.  Note the
+completion, if any, is always unique.
+)
+item(tt(_read_comp (^X^R)))(
+Prompt the user for a string, and use that to perform completion on the
+current word.  There are two possibilities for the string.  First, it can
+be a set of words beginning `tt(_)', for example `tt(_files -/)', in which
+case the function with any arguments will be called to generate the
+completions.  Unambiguous parts of the function name will be completed
+automatically (normal completion is not available at this point) until a
+space is typed.
+
+Otherwise, any other string, for example `tt(-b)', will be passed as
+arguments to tt(compgen) and should hence be a set of flags specifying the
+type of completion.
+
+A very restricted set of editing commands is available when reading the
+string:  `tt(DEL)' and `tt(^H)' delete the last character; `tt(^U)' deletes
+the line, and `tt(^C)' and `tt(^G)' abort the function, while `tt(RET)'
+accepts the completion.  Note the string is used verbatim as a command
+line, so arguments must be quoted in accordance with standard shell rules.
+
+Once a string has been read, the next call to tt(_read_comp) will use the
+existing string instead of reading a new one.  To force a new string to be
+read, call tt(_read_comp) with a numeric argument.
+)
+enditem()
diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo
index 644578354..4d439ab30 100644
--- a/Doc/Zsh/compwid.yo
+++ b/Doc/Zsh/compwid.yo
@@ -620,7 +620,7 @@ 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
+The word
 currently 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 
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 5cc9fe4e3..89f94a507 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -248,6 +248,9 @@ reference on the command line, then they refer to the previous command.
 
 The character sequence `tt(^)var(foo)tt(^)var(bar)'
 repeats the last command, replacing the string var(foo) with var(bar).
+More precisely, the sequence `tt(^)var(foo)tt(^)var(bar)tt(^)' is
+synonymous with `tt(!!:s)tt(^)var(foo)tt(^)var(bar)tt(^)', hence other
+modifiers may follow the final `tt(^)'.
 
 If the shell encounters the character sequence `tt(!")'
 in the input, the history mechanism is temporarily disabled until
@@ -855,10 +858,10 @@ texinode(Command Substitution)(Arithmetic Expansion)(Parameter Expansion)(Expans
 sect(Command Substitution)
 cindex(command substitution)
 cindex(substitution, command)
-A command enclosed in parentheses
-preceded by a dollar sign, like `tt($LPAR())...tt(RPAR())', or quoted with grave
-accents, like `tt(`)...tt(`)', is replaced with its standard output, with any
-trailing newlines deleted.
+A command enclosed in parentheses preceded by a dollar sign, like
+`tt($LPAR())...tt(RPAR())', or quoted with grave 
+accents, like `tt(`)...tt(`)', is replaced with its standard output, with
+any trailing newlines deleted.
 If the substitution is not enclosed in double quotes, the
 output is broken into words using the tt(IFS) parameter.
 vindex(IFS, use of)
diff --git a/Doc/Zsh/mod_complist.yo b/Doc/Zsh/mod_complist.yo
index 101f4e69c..236896e43 100644
--- a/Doc/Zsh/mod_complist.yo
+++ b/Doc/Zsh/mod_complist.yo
@@ -5,6 +5,12 @@ The tt(complist) module offers two extensions to completion listings:
 the ability to highlight matches in such a list and a different
 style of menu-completion.
 
+Whenever one of the parameters tt(ZLS_COLORS) or tt(ZLS_COLOURS) is set 
+and the tt(complist) module is loaded or linked into the shell,
+completion lists will be colored.  Note, however, that tt(complist) will
+not automatically be loaded if it is not linked in:  on systems with
+dynamic loading, `tt(zmodload complist)' is required.
+
 subsect(Parameters)
 For both extensions one of the parameters tt(ZLS_COLORS) or tt(ZLS_COLOURS)
 must be set, even if the value is empty (which uses all the default values
@@ -12,12 +18,12 @@ given below). These describe how matches are highlighted. The format of the
 value of these parameters is the same as used by the GNU version of the
 tt(ls) command: a colon-separated list of specifications of the form
 `var(name)=var(value)'. The var(name) may be one of the following strings,
-most of which specify file-types for which the var(value) will be used. The
+most of which specify file types for which the var(value) will be used. The
 strings and their default values are:
 
 startitem()
 item(tt(no 0))(
-for normal text (not the string displayed for a match)
+for normal text (i.e. when displaying something other than a matched file)
 )
 item(tt(fi 0))(
 for regular files
@@ -44,7 +50,7 @@ item(tt(ex 35))(
 for executable files
 )
 item(tt(mi) var(none))(
-for names not naming a file (default is the value defined for tt(fi))
+for non-existent file (default is the value defined for tt(fi))
 )
 item(tt(lc \e[))(
 for the left code (see below)
@@ -71,46 +77,51 @@ The default values are ISO 6429 (ANSI) compliant and can be used on
 vt100 compatible terminals such as tt(xterm)s. On monochrome terminals
 the default values will have no visual effect.
 
-Whenever one of the parameters tt(ZLS_COLORS) or tt(ZLS_COLOURS) is set 
-and the tt(complist) module is loaded or linked into the shell,
-completion lists will be colored.
-
 subsect(Menu selection)
-The tt(complist) module also offers a different style of selecting
-matches from a list called menu-selection. It can be invoked directly by
+The tt(complist) module also offers an alternative style of selecting
+matches from a list, called menu-selection. It can be invoked directly by
 the widget tt(menu-select) defined by the module.  Alternatively,
-the parameter tt(SELECTMIN) can be set to an integer giving the minimum
-number of matches which must be present before menu selection is
+the parameter tt(SELECTMIN) can be set to an integer, which give the
+minimum number of matches that must be present before menu selection is
 automatically turned on.  This second method requires that menu completion
 be started, either directly from a widget such as tt(menu-complete), or due
 to one of the options tt(MENU_COMPLETE) or tt(AUTO_MENU) being set.  If
 tt(SELECTMIN) is set, but is 0, 1 or empty, menu selection will always be
-started during menu completion if the completion is ambiguous.
+started during an ambiguous menu completion.
 
 After menu-selection is started, the matches will be listed. The
 matches to insert into the command line can be selected from this
 list. In the list one match is highlighted using the value for tt(ma)
 from the tt(ZLS_COLORS) or tt(ZLS_COLOURS) parameter. The default
 value for this it `tt(7)' which forces the selected match to be
-highlighted using standout mode on a vt100 compatible terminal. If
+highlighted using standout mode on a vt100-compatible terminal. If
 neither tt(ZLS_COLORS) nor tt(ZLS_COLOURS) is set, the same terminal
-control sequence is used as for the `tt(%S)' escape in prompts.
+control sequence as for the `tt(%S)' escape in prompts is used.
 
 Selecting matches is done by moving the mark around using the zle movement
 functions. The zle functions tt(send-break) and tt(accept-line) can be used
 to leave menu-selection, leaving the match currently inserted into the line
-in place. In the case of tt(accept-line), the match currently inserted
-will be accepted and the immediatly trying completion again will
-complete after it. Using tt(send-break) leaves menu-selection and
-continues with normal menu-completion. The functions tt(accept-and-hold) and
+in place.  In the case of tt(accept-line), the match currently inserted
+will be accepted and a new completion may be attempted.
+Using tt(send-break) leaves menu-selection and continues with normal
+menu-completion.  The functions tt(accept-and-hold) and
 tt(accept-and-menu-complete) can be used to accept the match currently
-inserted and continue inserting matches after that. Matches inserted this
-way can be removed by invoking the tt(undo) function. Keys bound to one of
+inserted and continue inserting matches from the same list. The
+function tt(accept-and-infer-next-history) accepts the current match and
+then tries completion with menu-selection again.  In the case of
+files this allows one to select a directory and immediately attempt to
+complete files in it.  Matches inserted in one of these ways can be removed
+by invoking the tt(undo) function.  Keys bound to one of
 the completion functions will cycle to the next (or, in case of
 tt(reverse-menu-complete), the previous) match, and the tt(redisplay) and
 tt(clear-screen) functions work as usual without leaving
-menu-selection. Any other zle function leaves menu-selection and executes
-that function.
+menu-selection.
+
+Any other zle function leaves menu-selection and executes that function.
+It is possible to make widgets in the above list do the same by using the
+form of the widget with a `tt(.)' in front.  For example, the widget
+`tt(.accept-line)' has the effect of leaving menu selection and accepting
+the entire command line.
 
 During this selection the widget uses the keymap tt(menuselect). Any
 key that is not defined in this keymap or that is bound to
@@ -124,6 +135,6 @@ ifnzman(noderef(The zle Module))\
 ). For example, to make the return key leave menu-selection and
 continue with normal menu-completion one can call
 
-indent(tt(bindkey -M menuselect '^J' send-break))
+indent(tt(bindkey -M menuselect '^M' send-break))
 
 after loading the tt(complist) module.
diff --git a/Doc/Zsh/mod_zle.yo b/Doc/Zsh/mod_zle.yo
index cae4eadc2..7d438a5d4 100644
--- a/Doc/Zsh/mod_zle.yo
+++ b/Doc/Zsh/mod_zle.yo
@@ -177,7 +177,8 @@ xitem(tt(zle) tt(-D) var(widget) ...)
 xitem(tt(zle) tt(-A) var(old-widget) var(new-widget))
 xitem(tt(zle) tt(-N) var(widget) [ var(function) ])
 xitem(tt(zle) tt(-C) var(widget) var(completion-widget) var(function))
-xitem(tt(zle) tt(-R) [ var(display-string) ])
+xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])
+xitem(tt(zle) tt(-U) var(string))
 item(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)(
 The tt(zle) builtin performs a number of different actions concerning
 ZLE.  Which operation it performs depends on its options:
@@ -227,11 +228,21 @@ ifzman(zmanref(zshcompwid))\
 ifnzman(noderef(Completion Widgets))\
 .
 )
-item(tt(-R) [ var(display-string) ])(
+item(tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])(
 Redisplay the command line; this is to be called from within a user-defined
 widget to allow changes to become visible.  If a var(display-string) is
-given, this is shown in the status line (immediately below the line being
-edited).
+given and not empty, this is shown in the status line (immediately
+below the line being edited).
+
+If the optional var(string)s are given they are listed below the
+prompt in the same way as completion lists are printed. If no
+var(string)s are given but the tt(-c) option is used such a list is
+cleared.
+)
+item(tt(-U) var(string))(
+This puts the characters in the var(string) in the input queue of
+ZLE. After the widget currently executed finishes ZLE will behave as
+if the characters in the var(string) were typed by the user.
 )
 item(var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)(
 Invoke the specified widget.  This can only be done when ZLE is
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index ecf93864f..05bd24613 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -108,14 +108,15 @@ be a list of flags. The flags currently understood are:
 
 startitem()
 item(tt(e))(
-this option has no effect and retained for backward compatibility only.
+This option has no effect and retained for backward compatibility only.
 )
 item(tt(w))(
-if the parameter subscripted is a scalar than this flag makes
-subscription work on a per-word basis instead of characters.
+If the parameter subscripted is a scalar than this flag makes
+subscripting work on words instead of characters.  The default word
+separator is whitespace.
 )
 item(tt(s:)var(string)tt(:))(
-this gives the var(string) that separates words (for use with the
+This gives the var(string) that separates words (for use with the
 tt(w) flag).
 )
 item(tt(p))(
@@ -123,21 +124,22 @@ Recognize the same escape sequences as the tt(print) builtin in
 the string argument of a subsequent `tt(s)' flag.
 )
 item(tt(f))(
-if the parameter subscripted is a scalar than this flag makes
-subscription work on a per-line basis instead of characters.
-This is a shorthand for `tt(pws:\n:)'.
+If the parameter subscripted is a scalar than this flag makes
+subscripting work on lines instead of characters, i.e. with elements
+separated by newlines.  This is a shorthand for `tt(pws:\n:)'.
 )
 item(tt(r))(
-if this flag is given the var(exp) is taken as a pattern and the
-result is the first matching array element, substring or word (if the
-parameter is an array, if it is a scalar, or if it is a scalar and the
-`tt(w)' flag is given, respectively); note that this is like giving a
-number: `tt($foo[(r))var(??)tt(,3])' and `tt($foo[(r))var(??)tt(,(r)f*])' work.
-If the parameter is an associative array, only the value part of each pair
-is compared to the pattern.
+Reverse subscripting:  if this flag is given, the var(exp) is taken as a
+pattern and the  result is the first matching array element, substring or
+word (if the parameter is an array, if it is a scalar, or if it is a scalar
+and the `tt(w)' flag is given, respectively).  The subscript used is the
+number of the matching element, so that pairs of subscripts such as
+`tt($foo[(r))var(??)tt(,3])' and `tt($foo[(r))var(??)tt(,(r)f*])'
+are possible.  If the parameter is an associative array, only the value part
+of each pair is compared to the pattern.
 )
 item(tt(R))(
-like `tt(r)', but gives the last match.  For associative arrays, gives
+Like `tt(r)', but gives the last match.  For associative arrays, gives
 all possible matches.
 )
 item(tt(i))(
@@ -188,8 +190,7 @@ Shell function executions delimit scopes for shell parameters.
 (Parameters are dynamically scoped.)  The tt(typeset) builtin, and its
 alternative forms tt(declare), tt(integer), tt(local) and tt(readonly)
 (but not tt(export)), can be used to declare a parameter as being local
-to the innermost scope.  Note that em(special) parameters cannot be made
-local.
+to the innermost scope.
 
 When a parameter is read or assigned to, the
 innermost existing parameter of that name is used.  (That is, the
@@ -200,6 +201,23 @@ causes it to be created in the em(outer)most scope.
 Local parameters disappear when their scope ends.
 tt(unset) can be used to delete a parameter while it is still in scope;
 any outer parameter of the same name remains hidden.
+
+Special parameters may also be made local; they retain their special
+attributes.  This may have unexpected effects.  Firstly, there is no
+default value, so if there is no assigment at the point the variable is
+made local, it will be set to an empty value (or zero in the case of
+integers).  Secondly, special parameters which are made local will not be
+exported (as with other parameters), so that the global value of the
+parameter remains present in the environment if it is already there.  This
+should be particularly noted in the case of tt(PATH): the shell will use
+the local version of tt(PATH) for finding programmes, but programmes using
+the shell's environment will inherit the global version.  The following:
+
+example(typeset PATH=/new/directory:$PATH)
+
+is valid for temporarily allowing the shell to find the programs in
+tt(/new/directory) inside a function.
+
 texinode(Parameters Set By The Shell)(Parameters Used By The Shell)(Local Parameters)(Parameters)
 sect(Parameters Set By The Shell)
 The following parameters are automatically set by the shell:
@@ -715,12 +733,12 @@ set up the terminal before executing the command. The modes apply only to the
 command, and are reset when it finishes or is suspended. If the command is
 suspended and continued later with the tt(fg) or tt(wait) builtins it will
 see the modes specified by tt(STTY), as if it were not suspended.  This
-(intentionally) does not apply if the command is continued via `tt(kill -CONT)'.
-tt(STTY) is ignored if the command is run in the background, or if it is in the
-environment of the shell but not explicitly assigned to in the input line. This
-avoids running stty at every external command by accidentally exporting it.
-Also note that tt(STTY) should not be used for window size specifications; these
-will not be local to the command.
+(intentionally) does not apply if the command is continued via `tt(kill
+-CONT)'.  tt(STTY) is ignored if the command is run in the background, or
+if it is in the environment of the shell but not explicitly assigned to in
+the input line. This avoids running stty at every external command by
+accidentally exporting it. Also note that tt(STTY) should not be used for
+window size specifications; these will not be local to the command.
 )
 vindex(TERM)
 item(tt(TERM) <S>)(
diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo
index 29f1f2c22..a7a220633 100644
--- a/Doc/Zsh/prompt.yo
+++ b/Doc/Zsh/prompt.yo
@@ -42,21 +42,14 @@ A `tt(RPAR())'.
 )
 xitem(tt(%d))
 item(tt(%/))(
-Present working directory (tt($PWD)).
+Present working directory (tt($PWD)).  If an integer follows the `tt(%)',
+it specifies a number of trailing components of tt($PWD) to show; zero
+means the whole path.
 )
 item(tt(%~))(
-tt($PWD).
-If it has a named directory as its prefix, that part is replaced
-by a `tt(~)' followed by the name of the directory.
-If it starts with tt($HOME), that part is
-replaced by a `tt(~)'.
-)
-xitem(tt(%c))
-xitem(tt(%.))
-item(tt(%C))(
-Trailing component of tt($PWD).
-An integer may follow the `tt(%)' to get more than one component.
-Unless `tt(%C)' is used, tilde contraction is performed first.
+As tt(%d) and tt(%/), but if tt($PWD) has a named directory as its prefix,
+that part is replaced by a `tt(~)' followed by the name of the directory.
+If it starts with tt($HOME), that part is replaced by a `tt(~)'.
 )
 xitem(tt(%h))
 item(tt(%!))(
@@ -98,7 +91,9 @@ tt($USERNAME).
 item(tt(%N))(
 The name of the script, sourced file, or shell function that zsh is
 currently executing, whichever was started most recently.  If there is
-none, this is equivalent to the parameter tt($0).
+none, this is equivalent to the parameter tt($0).  An integer may follow
+the `tt(%)' to specify a number of trailing path components to show; zero
+means the full path.
 )
 item(tt(%i))(
 The line number currently being executed in the script, sourced file, or
@@ -235,4 +230,14 @@ current directory, followed by a `tt(%)' or `tt(#)', followed by a
 space.  Without the `tt(%<<)', those two characters would be included
 in the string to be truncated.
 )
+xitem(tt(%c))
+xitem(tt(%.))
+item(tt(%C))(
+Trailing component of tt($PWD).
+An integer may follow the `tt(%)' to get more than one component.
+Unless `tt(%C)' is used, tilde contraction is performed first.  These are
+deprecated as tt(%c) and tt(%C) are equivalent to tt(%1~) and tt(%1/),
+respectively, while explicit positive integers have the same effect as for
+the latter two sequences.
+)
 enditem()
diff --git a/Etc/BUGS b/Etc/BUGS
index 2a255444f..e89116f23 100644
--- a/Etc/BUGS
+++ b/Etc/BUGS
@@ -2,9 +2,20 @@
 KNOWN BUGS IN ZSH
 -----------------
 
+On some terminals, display of lines with exactly 80 characters is
+problematic.  zsh assumes that the terminal does not print an extra
+newline in this case, but some terminals (e.g. aixterm) do.
 ------------------------------------------------------------------------
-Completion has a habit of doing the wrong thing after a
-backslash/newline.
+When interrupting code like the following with ^C:
+  while true; do
+    sh -c '...'
+  done
+if the `sh' is executing, zsh does not know that the sh received a ^C and
+continues with the next iteration.  This happens for any program which
+handles the interrupt, then exits after tidying up; it does not happen for
+zsh, which exits directly from the signal handler.  The workaround is to
+use ^Z which forks the shell and makes the loop a separate job, then kill
+the suspended loop.
 ------------------------------------------------------------------------
 If you suspend "man", zle seems to get into cooked mode.  It works ok
 for plain "less".
@@ -26,12 +37,6 @@ Then if you suspend
 % foo less something
 from zsh/bash, zle/readline gets into cooked mode.
 ------------------------------------------------------------------------
-% zsh -c 'cat a_long_file | less ; :'
-can be interrupted with ^C. The prompt comes back and less is orphaned.
-If you go to the end of the file with less and cat terminates, ^C
-will not terminate less. The `; :' after less forces zsh to fork before
-executing less.
-------------------------------------------------------------------------
 The pattern %?* matches names beginning with %? instead of names with at
 least two characters beginning with %. This is a hack to allow %?foo job
 substitution without quoting. This behaviour is incompatible with sh
diff --git a/Etc/CONTRIBUTORS b/Etc/CONTRIBUTORS
index 52d664fad..7064ef742 100644
--- a/Etc/CONTRIBUTORS
+++ b/Etc/CONTRIBUTORS
@@ -4,8 +4,8 @@ ZSH CONTRIBUTORS
 
 Zsh was originally written by Paul Falstad <pf@zsh.org>.  Zsh is
 now maintained by the members of the zsh-workers mailing list
-<zsh-workers@math.gatech.edu>.  The development is currently coordinated
-by Andrew Main (Zefram) <zefram@zsh.org>.
+<zsh-workers@sunsite.auc.dk>.  The development is currently coordinated
+by Peter Stephenson <pws@zsh.org>.
 
 This file credits only the major contributors to the current release.
 See the ChangeLog files for a complete list of people who have submitted
@@ -15,6 +15,40 @@ to be currently accurate.  If you feel that you or someone else have
 been unfairly omitted from this list please mail the current maintainer
 at <coordinator@zsh.org>.
 
+Version 3.1.6
+-------------
+
+* Sven Wishnowsky <wischnow@informatik.hu-berlin.de>: completion code,
+  major rewrite and enhancements, including matching control, completion
+  widgets and function system, complist module; zle code additions; job
+  control code changes; parameters code changes; parameter module;
+  additional autoloading code; general code changes for extra efficiency;
+  subscripting and ordering of globbing lists.
+  
+* Peter Stephenson <pws@ibmth.df.unipi.it>: zftp and mapfile modules and
+  zf* functions; local parameters and typeset changes; changes in autoconf
+  system; case-independent and approximate pattern matching; various
+  options; a few completion modules; some zle changes; FAQ.
+
+* Bart Schaefer <schaefer@candle.brasslantern.com>: associative array
+  implementation; other parameter changes; keeping track of missing
+  patches; function autoloading changes.
+  
+* Wayne Davison <wayne@clari.net>:  History code novelties and improvements
+  with new options.
+  
+* Geoff Wing <mason@primenet.com.au>:  Zle display code fixes, mailing
+  list and patch archive.
+
+* Zoltán Hidvégi <hzoli@cs.elte.hu>: AIX dynamic loading code.
+
+* Matt Armstrong: cygwin configuration changes.
+
+Other improvements, bug fixes and design suggestions from all the above
+plus Andrej Borsenkow, Oliver Kiddle, Tanaka Akira, Naoki Wakamatsu, Tatuso
+Furukawa, Ville Herva, Will Day, Lehti Rahmi, Larry P. Schrof, Helmut
+Jarausch, Phil Pennock, Wilfredo Sanchez, Bruce Stephens.
+
 Version 3.0
 -----------
 
diff --git a/Etc/MACHINES b/Etc/MACHINES
index 89ec474c9..fd386c7e0 100644
--- a/Etc/MACHINES
+++ b/Etc/MACHINES
@@ -87,6 +87,9 @@ SGI: IRIX 5.1.1.1, 5.2, 5.3, 6.2, 6.3, 6.5
         full optimization (cc -O3 -OPT:Olimit=0) causes problems.
 
 Sun: SunOS 4.1.*
+	Dynamic loading does not work under SunOS 4.1.  Sometimes,
+	you may need to turn it off explicitly with --disable-dynamic.
+
 	Under 4.1.3 if yellow pages is used, username completion may cause
 	segmentation violation.  This is a bug in the shared library not
 	in zsh.  Some libc.so.1.9.* has this bug (it fails in yp_all).
diff --git a/Etc/NEWS b/Etc/NEWS
index e4bafc08d..9d58c9cc6 100644
--- a/Etc/NEWS
+++ b/Etc/NEWS
@@ -2,6 +2,92 @@
 CHANGES FROM PREVIOUS VERSIONS OF ZSH
 -------------------------------------
 
+New features in zsh version 3.1.6 (beta version)
+------------------------------------------------
+
+New completion system via shell functions; massive degree of
+programmability and configurability:
+ - ready-made function suite to use, see zshcompsys(1)
+ - approximate completion and spelling correction via completion
+ - control over matching for case-independence, partial word completion, etc.
+ - menu selection:  choose a completion by moving the cursor
+ - coloured completion lists
+
+Other editing changes:
+  - enhancements to function/editing interface:  new parameters, numeric
+    arguments, string argument passing, reading keys from widgets.
+  - the old history-search-{back,for}ward behaviour and bindings have
+    returned (up to minor details).
+  - BASH_AUTO_LIST option to show completion list only on second key press.
+  - the ZBEEP parameter gives a string to output instead of beeping,
+    allowing you to have a visual bell.
+
+History changes: new options HIST_NO_FUNCTIONS, HIST_EXPIRE_DUPS_FIRST,
+HIST_FIND_NO_DUPS, HIST_IGNORE_ALL_DUPS, INC_APPEND_HISTORY,
+HIST_SAVE_NO_DUPS, SHARE_HISTORY, allow better control of when history is
+read and written and how duplicates are handled.
+
+Associative arrays plus enhanced parameter substitutions to retrieve keys
+and values.
+
+Globbing changes:
+  - Case-insensitive and approximate globbing.
+  - Ordering and indexing of globbing matches, e.g. *(om[1]) picks
+    most recently modified file.
+
+New loadable modules:
+  - zftp, plus associated function suite, for turning your zsh session
+    into an FTP session too
+  - parameter, for examining and altering shell hash tables via an
+    associative array interface.
+  - mapfile, for reading and writing external files via an associative
+    array interface.
+
+Debugging and prompt enhancements:
+  - LINENO is now very much more useful in scripts and functions and has
+    corresponding prompt escape %i
+  - $PS4 can contain %i as well as %N for script or function names
+    (default PS4 changed), also %_ for current shell structure executing; 
+  - Prompt truncation %<...< is now more flexible: it applies to a
+    whole section of the prompt, not just one escape.  You need to put
+    %<< after the truncated escape to get the old behaviour.
+  - %20(l.yes.no) in prompts prints yes if at least 20 characters have
+    been output, else no (e.g. for outputting extra newlines).
+
+Parameter and expansion changes
+  - typeset -t MYPATH mypath creates tied path/PATH-like variables
+  - typeset -g allows operations on parameters without making them local
+  - New expansions
+    - ${(t)param} prints type information for $param
+    - ${(P)param} treats value of $param as the name of a param to
+      substitute
+    - ${foo:q} can quote replaced parameter text from expansion
+    - ${foo/old/new} substitution, like bash; also (S) flag for shortest
+      match
+    - $foo[(b.2.i)bar] starts searching $foo for bar starting at 2nd match
+    - more logical behaviour of nested parameters, now properly documented
+    - quote only nested expansion, e.g. ${(f)"$(<file)"} reads complete
+      `file', then splits lines into array.
+
+Builtin and function changes
+  - stat module: `stat -H hash foo' gives you e.g. $hash[mtime]
+  - autoload -U autoloads functions without alias expansion.
+
+Other new options:
+  - LOCAL_TRAPS allows signal traps to be local to functions (as in ksh).
+  - NO_RCS can now be turned on at any point in initialization files.
+  - NO_GLOBAL_RCS can force /etc/z* files after /etc/zshenv to be skipped.
+    (Please don't use this as an excuse to stuff more into /etc/zshenv!)
+  - existing MAGIC_EQUAL_SUBST option is more useful; any argument containing
+    ...=~...:~... will perform filename expansion on the ~.
+
+Configuration changes:
+  - Large file and 64-bit integers on 32-bit machines supported where
+    provided by OS.
+  - generation of signal names should be more reliable
+  - Customizable installation of shell functions from distribution.
+
+
 New features in zsh version 3.1 (beta version)
 ----------------------------------------------
 
diff --git a/Functions/Makefile.in b/Functions/Makefile.in
index 75ec418a0..a00936220 100644
--- a/Functions/Makefile.in
+++ b/Functions/Makefile.in
@@ -48,40 +48,7 @@ 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 \
-	      if test x$(FUNCTIONS_SUBDIRS) != x -a \
-	      x$(FUNCTIONS_SUBDIRS) != xno; then \
-	        subdir="`echo $$file | sed -e 's%/.*%%'`"; \
-	        $(sdir_top)/mkinstalldirs $(fndir)/$$subdir || exit 1; \
-	        $(INSTALL_DATA) $$file $(fndir)/$$subdir || exit 1; \
-	      else \
-	        $(INSTALL_DATA) $$file $(fndir) || exit 1; \
-	      fi; \
-	    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 \
-	      if test x$(FUNCTIONS_SUBDIRS) != x -a \
-	      x$(FUNCTIONS_SUBDIRS) != xno; then \
-	        rm -f $(fndir)/$$file; \
-	      else \
-	        rm -f "$(fndir)/`echo $$file | sed -e 's%^.*/%%'`"; \
-	      fi; \
-	    fi; \
-	  done; \
-	fi; \
-	exit 0
+@FUNCINST_MK@
 
 # ========== DEPENDENCIES FOR CLEANUP ==========
 
diff --git a/Functions/Zle/.distfiles b/Functions/Zle/.distfiles
new file mode 100644
index 000000000..429c133a0
--- /dev/null
+++ b/Functions/Zle/.distfiles
@@ -0,0 +1,3 @@
+DISTFILES_SRC='
+    .distfiles incremental-complete-word insert-files
+'
diff --git a/Functions/Zle/incremental-complete-word b/Functions/Zle/incremental-complete-word
new file mode 100644
index 000000000..2a9c1aff2
--- /dev/null
+++ b/Functions/Zle/incremental-complete-word
@@ -0,0 +1,89 @@
+# incremental-complete-word() {
+
+# Autoload this function, run `zle -N <func-name>' and bind <func-name>
+# to a key.
+
+# This allows incremental completion of a word.  After starting this
+# command, a list of completion choices is shown after every character you
+# type, which you can delete with ^h or DEL.  RET will accept the
+# completion so far.  You can hit TAB to do normal completion and ^g to
+# abort back to the state when you started.
+#
+# Completion keys:
+#   incremental_prompt   Prompt to show in status line during icompletion;
+#                        the sequence `%u' is replaced by the unambiguous
+#                        part of all matches if there is any and it is
+#                        different from the word on the line
+# incremental_stop       Pattern matching keys which will cause icompletion
+#                         to stop and the key to be re-executed
+# incremental_break      Pattern matching keys which will cause icompletion
+#                         to stop and the key to be discarded
+# incremental_completer  Set of completers, like the `completer' key
+#   incremental_list     If set to a non-empty string, the matches will be
+#                        listed on every key-press
+
+emulate -L zsh
+unsetopt autolist menucomplete automenu # doesn't work well
+
+local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word lastl lastr wid twid
+
+[[ -n "$compconfig[incremental_completer]" ]] &&
+set ${(s.:.)compconfig[incremental_completer]}
+pmpt="${compconfig[incremental_prompt]-incremental completion...}"
+
+if [[ -n "$compconfig[incremental_list]" ]]; then
+  wid=list-choices
+else
+  wid=complete-word
+fi
+
+zle $wid "$@"
+LBUFFER="$lbuf"
+RBUFFER="$rbuf"
+if [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then
+  word=''
+else
+  word="${_lastcomp[unambiguous]}"
+fi
+zle -R "${pmpt//\\%u/$word}"
+read -k key
+
+while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' &&
+         '#key' -ne '#\\C-g' ]]; do
+  twid=$wid
+  if [[ "$key" = ${~compconfig[incremental_stop]} ]]; then
+    zle -U "$key"
+    return
+  elif [[ "$key" = ${~compconfig[incremental_break]} ]]; then
+    return
+  elif [[ '#key' -eq '#\\C-h' || '#key' -eq '#\\C-?' ]]; then
+    [[ $#LBUFFER -gt $#l ]] && LBUFFER="$LBUFFER[1,-2]"
+  elif [[ '#key' -eq '#\\t' ]]; then
+    zle complete-word "$@"
+    lbuf="$LBUFFER"
+    rbuf="$RBUFFER"
+  elif [[ '#key' -eq '#\\C-d' ]]; then
+    twid=list-choices
+  else
+    LBUFFER="$LBUFFER$key"
+  fi
+  lastl="$LBUFFER"
+  lastr="$RBUFFER"
+  zle $twid "$@"
+  LBUFFER="$lastl"
+  RBUFFER="$lastr"
+  if [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then
+    word=''
+  else
+    word="${_lastcomp[unambiguous]}"
+  fi
+  zle -R "${pmpt//\\%u/$word}"
+  read -k key
+done
+
+if [[ '#key' -eq '#\\C-g' ]]; then
+  LBUFFER="$lbuf"
+  RBUFFER="$rbuf"
+fi
+zle -Rc
+# }
diff --git a/Functions/Zle/insert-files b/Functions/Zle/insert-files
new file mode 100644
index 000000000..10f90ed4a
--- /dev/null
+++ b/Functions/Zle/insert-files
@@ -0,0 +1,42 @@
+# insert-files() {
+
+# Autoload this function, run `zle -N <func-name>' and bind <func-name>
+# to a key.
+
+# This function allows you type a file pattern, and see the results of the
+# expansion at each step.  When you hit return, they will be inserted into
+# the command line.
+
+emulate -L zsh
+setopt nobadpattern
+
+local key str files
+
+files=( *(N) )
+if (( $#files )); then
+  zle -R "files: ${str}_" "$files[@]"
+else
+  zle -R "files: ${str}_ (failed)"
+fi
+read -k key
+while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' &&
+         '#key' -ne '#\\C-g' ]]; do
+  if [[ '#key' -eq '#\\C-h' || '#key' -eq '#\\C-?' ]]; then
+    [[ -n "$str" ]] && str="$str[1,-2]"
+  else
+    str="$str$key"
+  fi
+  eval "files=( \${~str}*(N) )"
+  if (( $#files )); then
+    zle -R "files: ${str}_" "$files[@]"
+  else
+    zle -R "files: ${str}_ (failed)"
+  fi
+  read -k key
+done
+zle -Rc
+if [[ '#key' -ne '#\\C-g' && $#files -gt 0 ]]; then
+  [[ "$LBUFFER[-1]" = ' ' ]] || files=('' "$files[@]")
+  LBUFFER="$LBUFFER$files "
+fi
+# }
diff --git a/INSTALL b/INSTALL
index 569246e92..b8eaa561c 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,6 +1,15 @@
---------------
-INSTALLING ZSH
---------------
+                        ++++++++++++++
+                        INSTALLING ZSH
+                        ++++++++++++++
+
+This file is divided into two parts:  making and installing the shell, and
+a description of various additional configuration options.  You should
+have a look at the items in the second part before following the
+instructions in the first.
+
+=====================
+MAKING AND INSTALLING
+=====================
 
 Check MACHINES File
 -------------------
@@ -27,15 +36,18 @@ top level Makefile.
 Dynamic loading
 ---------------
 
-Zsh-3.1 has support for dynamically loadable modules.  To enable this run
-configure with the --enable-dynamic option.  Note that dynamic loading
-does not work on all systems.  On these systems this option will have no
-effect, so it is always safe to use --enable-dynamic.  When dynamic
-loading is enabled, major parts of zsh (including the Zsh Line Editor) are
-compiled into modules and not included into the main zsh binary.  Zsh
-autoloads these modules when they are required.  This means that you have
-to execute make install.modules before you try the newly compiled zsh
-executable.
+Zsh-3.1 has support for dynamically loadable modules.  This is now enabled
+by default; to disable it, run configure with the --disable-dynamic option.
+Note that dynamic loading does not work on all systems.  On these systems
+this option will have no effect.  When dynamic loading is enabled, major
+parts of zsh (including the Zsh Line Editor) are compiled into modules and
+not included into the main zsh binary.  Zsh autoloads these modules when
+they are required.  This means that you have to execute make
+install.modules before you try the newly compiled zsh executable, and hence
+also the install paths must be correct.  The installation path for modules
+is EPREFIX/lib/zsh/<zsh-version-number>, where EPREFIX defaults to PREFIX
+unless given explicitly, and PREFIX defaults to /usr/local.  See the end of
+this file for options to configure to change these.
 
 Adding more modules
 -------------------
@@ -156,6 +168,11 @@ source code in the directory that "configure" is in.  For example,
     /usr/local/src/zsh-3.0/configure
     make
 
+
+=====================
+CONFIGURATION OPTIONS
+=====================
+
 Memory Routines
 ---------------
 
@@ -225,31 +242,44 @@ FUNCTIONS_INSTALL, either when running configure (e.g.
 `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/*'
+plus those provide functions for the line editor, i.e.
+  FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* Zle/*'
 and if the --enable-dynamic option was given, the functions in
 Functions/Zftp, which require the zftp module to be available (see the
 zshzftpsys manual page), will be included as well.  There are also some
 miscellaneous functions with documentation in comments; the complete set
 of functions can be installed with
-  FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* Misc/* Zftp/*'
-
-You can also set --enable-function-subdirs to allow shell
-functions to be installed into subdirectories of the function directory,
-i.e. `Core/*' files will be installed into `FNDIR/Core', and so on.
-This also initialises $fpath/$FPATH appropriately.
+  FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* \
+  Misc/* Zftp/* Zle/*'
+Note you should set this by hand to include `Zftp/*' if you have zftp
+compiled into a statically linked shell.
+
+You can also use the configure option --enable-function-subdirs to allow
+shell functions to be installed into subdirectories of the function
+directory, i.e. `Core/*' files will be installed into `FNDIR/Core', and so
+on. This also initialises $fpath/$FPATH appropriately.
+
+On installation, any completion function which already exists but is
+different from the new version will be moved to a corresponding place in
+FNDIR.old; for example, if a different version of User/_rcs exists when
+installing into /usr/local/share/zsh/functions/User, the old one will be
+moved into /usr/local/share/zsh/functions.old/User.  The installer is
+responsible for recovering or deleting old functions which have been moved
+in this way.  On uninstallation, any newly installed functions (including
+those which existed before but were unchanged) will be deleted and the
+files in the FNDIR.old hierarchy moved back into FNDIR.  To preserve the
+entire old hierarchy, you should move or copy it before installation.
 
 Support for large files and integers
 ------------------------------------
 
 Some 32-bit systems allow special compilation modes to get around the 2GB
-file size barrier; the zsh support for this is still experimental, and
-feedback is particularly appreciated.  The option --enable-lfs turns on the
-configure check for support for large files.  Not all systems recognize the
-test used by zsh (via the getconf command), so flags may need to be set by
-hand, but --enable-lfs should be used in any case to compile in the code
-for using 64 bit integers.  On HP-UX 10.20, zsh has been successfully
-compiled with large file support by configuring with
+file size barrier.  The option --enable-lfs turns on the configure check
+for support for large files.  This is now enabled by default; use
+--disable-lfs to turn it off.  Not all systems recognize the test used by
+zsh (via the getconf command), so flags may need to be set by hand.  On
+HP-UX 10.20, zsh has been successfully compiled with large file support by
+configuring with
   CC="cc -Ae" CPPFLAGS="-D_LARGEFILE_SOURCE -D_FILE64" configure \
   --enable-lfs ...
 You can also give a value to --enable-lfs, which will be interpreted as the
diff --git a/Misc/.distfiles b/Misc/.distfiles
index a02614511..a02c324d6 100644
--- a/Misc/.distfiles
+++ b/Misc/.distfiles
@@ -1,4 +1,5 @@
 DISTFILES_SRC='
     .distfiles
-    c2z compctl-examples globtests globtests.ksh lete2ctl
+    c2z compctl-examples globtests globtests.ksh
+    job-control-tests lete2ctl
 '
diff --git a/Misc/job-control-tests b/Misc/job-control-tests
new file mode 100644
index 000000000..7e35fba0b
--- /dev/null
+++ b/Misc/job-control-tests
@@ -0,0 +1,31 @@
+# These are some tests for the job control code.  The code chunks
+# have to be run interactively.  Some use files in the zsh distribution.
+
+# Try
+#   ^Z
+#   fg
+if true; then cat Src/builtin.c | less; fi
+
+# Try
+#   ^Z
+#   fg
+fn() {
+  if true; then cat Src/builtin.c | less; fi
+}
+fn
+
+# Try
+#   ^Z
+#   fg
+#   ^C
+# then
+#   ^Z
+#   bg
+#   kill
+while true; do sed -e 's/foo/bar/' Src/builtin.c >/dev/null; done
+
+# Try
+#   ^C
+# ignoring the error messages from sed.
+# ^Z is more of a problem since you have to catch the sed.
+while true; do sed -e 's/foo/bar/' non-existent-file >/dev/null; done
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index 2b426492e..694af8429 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -2096,9 +2096,7 @@ 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());
+    case 'q': return set_comp_sepptr();
     default:
 	zerrnam(name, "bad option -%c", NULL, argv[0][1]);
 	return 1;
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index aac8b410d..0e7152866 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -309,7 +309,7 @@ complistmatches(Hookdef dummy, Chdata dat)
     Cexpl *e;
     int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0, opl = 0;
     int of = isset(LISTTYPES);
-    int mc, ml = 0, cc, hasm = 0;
+    int mc, ml = 0, cc, hasm = 0, cl;
     struct listcols col;
 
     if (minfo.asked == 2) {
@@ -448,7 +448,12 @@ complistmatches(Hookdef dummy, Chdata dat)
 	mgtab = (Cmgroup *) zalloc(i * sizeof(Cmgroup));
 	memset(mgtab, 0, i * sizeof(Cmgroup));
 	mcols = ncols;
-	mlines = nlines;
+	mlines = cl = nlines;
+	if (cl < 2) {
+	    cl = -1;
+	    if (tccan(TCCLEAREOD))
+		tcout(TCCLEAREOD);
+	}
     }
     /* Now print the matches. */
     g = amatches;
@@ -456,14 +461,27 @@ complistmatches(Hookdef dummy, Chdata dat)
 	char **pp = g->ylist;
 
 	if ((e = g->expls)) {
+	    int l;
+
 	    while (*e) {
 		if ((*e)->count) {
 		    if (pnl) {
 			putc('\n', shout);
 			pnl = 0;
 			ml++;
+			if (cl >= 0 && --cl <= 1) {
+			    cl = -1;
+			    if (tccan(TCCLEAREOD))
+				tcout(TCCLEAREOD);
+			}
+		    }
+		    l = printfmt((*e)->str, (*e)->count, 1);
+		    ml += l;
+		    if (cl >= 0 && (cl -= l) <= 1) {
+			cl = -1;
+			if (tccan(TCCLEAREOD))
+			    tcout(TCCLEAREOD);
 		    }
-		    ml += printfmt((*e)->str, (*e)->count, 1);
 		    pnl = 1;
 		}
 		e++;
@@ -474,6 +492,11 @@ complistmatches(Hookdef dummy, Chdata dat)
 		putc('\n', shout);
 		pnl = 0;
 		ml++;
+		if (cl >= 0 && --cl <= 1) {
+		    cl = -1;
+		    if (tccan(TCCLEAREOD))
+			tcout(TCCLEAREOD);
+		}
 	    }
 	    if (g->flags & CGF_LINES) {
 		while (*pp) {
@@ -504,6 +527,11 @@ complistmatches(Hookdef dummy, Chdata dat)
 		    if (n) {
 			putc('\n', shout);
 			ml++;
+			if (cl >= 0 && --cl <= 1) {
+			    cl = -1;
+			    if (tccan(TCCLEAREOD))
+				tcout(TCCLEAREOD);
+			}
 		    }
 		    pp++;
 		}
@@ -517,6 +545,11 @@ complistmatches(Hookdef dummy, Chdata dat)
 		putc('\n', shout);
 		pnl = 0;
 		ml++;
+		if (cl >= 0 && --cl <= 1) {
+		    cl = -1;
+		    if (tccan(TCCLEAREOD))
+			tcout(TCCLEAREOD);
+		}
 	    }
 	    for (p = skipnolist(g->matches); n && nl--;) {
 		i = ncols;
@@ -607,6 +640,11 @@ complistmatches(Hookdef dummy, Chdata dat)
 		if (n) {
 		    putc('\n', shout);
 		    ml++;
+		    if (cl >= 0 && --cl <= 1) {
+			cl = -1;
+			if (tccan(TCCLEAREOD))
+			    tcout(TCCLEAREOD);
+		    }
 		    if (n && nl)
 			p = skipnolist(p + 1);
 		}
@@ -640,11 +678,13 @@ struct menustack {
     char *line;
     int cs;
     struct menuinfo info;
+    Cmgroup amatches, pmatches, lmatches;
 };
 
 static int
 domenuselect(Hookdef dummy, Chdata dat)
 {
+    static Chdata fdat = NULL;
     Cmatch **p;
     Cmgroup *pg;
     Thingy cmd;
@@ -652,10 +692,15 @@ domenuselect(Hookdef dummy, Chdata dat)
     int i = 0, acc = 0;
     char *s;
 
-    if (dummy && (!(s = getsparam("SELECTMIN")) ||
-		  (dat && dat->num < atoi(s))))
+    if (fdat || (dummy && (!(s = getsparam("SELECTMIN")) ||
+			   (dat && dat->num < atoi(s))))) {
+	if (fdat) {
+	    fdat->matches = dat->matches;
+	    fdat->num = dat->num;
+	}
 	return 0;
-
+    }
+    fdat = dat;
     selectlocalmap(mskeymap);
     noselect = 0;
     mselect = (*(minfo.cur))->gnum;
@@ -686,6 +731,32 @@ domenuselect(Hookdef dummy, Chdata dat)
 	else if (cmd == Th(z_acceptline)) {
 	    acc = 1;
 	    break;
+	} else if (cmd == Th(z_acceptandinfernexthistory)) {
+	    Menustack s = (Menustack) zhalloc(sizeof(*s));
+
+	    s->prev = u;
+	    u = s;
+	    s->line = dupstring((char *) line);
+	    s->cs = cs;
+	    memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
+	    s->amatches = amatches;
+	    s->pmatches = pmatches;
+	    s->lmatches = lmatches;
+	    menucmp = 0;
+	    fixsuffix();
+	    validlist = 0;
+	    pmatches = NULL;
+	    invalidatelist();
+	    menucomplete(zlenoargs);
+	    if (dat->num < 2 || !minfo.cur || !*(minfo.cur)) {
+		noselect = 1;
+		clearlist = 1;
+		zrefresh();
+		break;
+	    }
+	    clearlist = 1;
+	    mselect = (*(minfo.cur))->gnum;
+	    continue;
 	} else if (cmd == Th(z_acceptandhold) ||
 		 cmd == Th(z_acceptandmenucomplete)) {
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
@@ -695,6 +766,7 @@ domenuselect(Hookdef dummy, Chdata dat)
 	    s->line = dupstring((char *) line);
 	    s->cs = cs;
 	    memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
+	    s->amatches = s->pmatches = s->lmatches = NULL;
 	    acceptlast();
 	    do_menucmp(0);
 	    mselect = (*(minfo.cur))->gnum;
@@ -712,7 +784,15 @@ domenuselect(Hookdef dummy, Chdata dat)
 	    cs = u->cs;
 	    memcpy(&minfo, &(u->info), sizeof(struct menuinfo));
 	    p = &(minfo.cur);
+	    if (u->pmatches && pmatches != u->pmatches) {
+		freematches();
+		amatches = u->amatches;
+		pmatches = u->pmatches;
+		lmatches = u->lmatches;
+		hasperm = 1;
+	    }
 	    u = u->prev;
+	    clearlist = 1;
 	} else if (cmd == Th(z_redisplay)) {
 	    redisplay(zlenoargs);
 	    continue;
@@ -846,6 +926,19 @@ domenuselect(Hookdef dummy, Chdata dat)
 	do_single(**p);
 	mselect = (**p)->gnum;
     }
+    if (u) {
+	int hp = hasperm;
+	Cmgroup m = pmatches;
+
+	for (; u; u = u->prev) {
+	    if (u->pmatches != m) {
+		pmatches = u->pmatches;
+		freematches();
+	    }
+	}
+	pmatches = m;
+	hasperm = hp;
+    }
     selectlocalmap(NULL);
     mselect = -1;
     inselect = 0;
@@ -858,6 +951,7 @@ domenuselect(Hookdef dummy, Chdata dat)
 	showinglist = -2;
 	zrefresh();
     }
+    fdat = NULL;
     return (!noselect ^ acc);
 }
 
diff --git a/Src/Zle/zle.export b/Src/Zle/zle.export
index e6f469ad0..8bc049e16 100644
--- a/Src/Zle/zle.export
+++ b/Src/Zle/zle.export
@@ -1,23 +1,29 @@
 #!
 acceptlast
 addzlefunction
+amatches
 backdel
 backkill
 bindkey
 clearflag
+clearlist
 clearscreen
 deletezlefunction
 do_menucmp
 do_single
-feep
+fixsuffix
 foredel
 forekill
+freematches
 getkey
 getkeycmd
 getzlequery
+hasperm
+invalidatelist
 lastambig
 linkkeymap
 listshown
+lmatches
 menucmp
 menucomplete
 menucur
@@ -25,6 +31,7 @@ menugrp
 minfo
 newkeymap
 nlnct
+pmatches
 printfmt
 redisplay
 refthingy
@@ -39,6 +46,7 @@ thingies
 trashzle
 ungetkeycmd
 unlinkkeymap
+validlist
 zlenoargs
 zmod
 zrefresh
diff --git a/Src/Zle/zle_bindings.c b/Src/Zle/zle_bindings.c
index 40e555ad1..940d578d9 100644
--- a/Src/Zle/zle_bindings.c
+++ b/Src/Zle/zle_bindings.c
@@ -200,9 +200,9 @@ int metabind[128] = {
     /* M-K */ z_undefinedkey,
     /* M-L */ z_downcaseword,
     /* M-M */ z_undefinedkey,
-    /* M-N */ z_historybeginningsearchforward,
+    /* M-N */ z_historysearchforward,
     /* M-O */ z_undefinedkey,
-    /* M-P */ z_historybeginningsearchbackward,
+    /* M-P */ z_historysearchbackward,
     /* M-Q */ z_pushline,
     /* M-R */ z_undefinedkey,
     /* M-S */ z_spellword,
@@ -232,9 +232,9 @@ int metabind[128] = {
     /* M-k */ z_undefinedkey,
     /* M-l */ z_downcaseword,
     /* M-m */ z_undefinedkey,
-    /* M-n */ z_historybeginningsearchforward,
+    /* M-n */ z_historysearchforward,
     /* M-o */ z_undefinedkey,
-    /* M-p */ z_historybeginningsearchbackward,
+    /* M-p */ z_historysearchbackward,
     /* M-q */ z_pushline,
     /* M-r */ z_undefinedkey,
     /* M-s */ z_spellword,
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 8f6dfdf75..beef708fb 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -307,7 +307,7 @@ getkey(int keytmout)
     unsigned int ret;
     long exp100ths;
     int die = 0, r, icnt = 0;
-    int old_errno = errno;
+    int old_errno = errno, obreaks = breaks;
 
 #ifdef HAVE_SELECT
     fd_set foofd;
@@ -397,6 +397,7 @@ getkey(int keytmout)
 		if (!errflag && !retflag && !breaks)
 		    continue;
 		errflag = 0;
+		breaks = obreaks;
 		errno = old_errno;
 		return EOF;
 	    } else if (errno == EWOULDBLOCK) {
@@ -717,7 +718,7 @@ bin_vared(char *name, char **args, char *ops, int func)
     Value v;
     Param pm = 0;
     int create = 0;
-    int type = PM_SCALAR;
+    int type = PM_SCALAR, obreaks = breaks;
     char *p1 = NULL, *p2 = NULL;
 
     if (zleactive) {
@@ -809,6 +810,7 @@ bin_vared(char *name, char **args, char *ops, int func)
     if (!t || errflag) {
 	/* error in editing */
 	errflag = 0;
+	breaks = obreaks;
 	return 1;
     }
     /* strip off trailing newline, if any */
@@ -948,7 +950,7 @@ trashzle(void)
 static struct builtin bintab[] = {
     BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLR", NULL),
     BUILTIN("vared",   0, bin_vared,   1,  7, 0, NULL,             NULL),
-    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRa",  NULL),
+    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRaU", NULL),
 };
 
 /* The order of the entries in this table has to match the *HOOK
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index a51cdf92e..fedb9d5cf 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -736,6 +736,7 @@ executenamedcommand(char *prmt)
 		    statusll = l + len + 1;
 		    zmult = 1;
 		    listlist(cmdll);
+		    showinglist = 0;
 		    zmult = zmultsav;
 		} else if (!nextnode(firstnode(cmdll))) {
 		    strcpy(ptr = cmdbuf, peekfirst(cmdll));
@@ -754,6 +755,7 @@ executenamedcommand(char *prmt)
 			statusll = l + cmdambig + 1;
 			zmult = 1;
 			listlist(cmdll);
+			showinglist = 0;
 			zmult = zmultsav;
 		    }
 		    len = cmdambig;
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index bac399e7d..dc4e27685 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -137,6 +137,8 @@ set_buffer(Param pm, char *x)
 	    cs = ll;
     } else
 	cs = ll = 0;
+    fixsuffix();
+    menucmp = 0;
 }
 
 /**/
@@ -156,6 +158,8 @@ set_cursor(Param pm, zlong x)
 	cs = ll;
     else
 	cs = x;
+    fixsuffix();
+    menucmp = 0;
 }
 
 /**/
@@ -182,6 +186,8 @@ set_lbuffer(Param pm, char *x)
     ll = ll - cs + len;
     cs = len;
     zsfree(x);
+    fixsuffix();
+    menucmp = 0;
 }
 
 /**/
@@ -205,6 +211,8 @@ set_rbuffer(Param pm, char *x)
     sizeline(ll = cs + len);
     memcpy(line + cs, y, len);
     zsfree(x);
+    fixsuffix();
+    menucmp = 0;
 }
 
 /**/
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index dd4310078..48e1071b8 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -281,7 +281,9 @@ zrefresh(void)
 	    clearflag = 0;
 	    resetneeded = 1;
 	}
-	listshown = showinglist = 0;
+	listshown = 0;
+	if (showinglist != -2)
+	    showinglist = 0;
     }
     clearlist = 0;
 
diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index cf01f2fc1..f753b4769 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -340,7 +340,8 @@ bin_zle(char *name, char **args, char *ops, int func)
 	{ 'A', bin_zle_link, 2,  2 },
 	{ 'N', bin_zle_new,  1,  2 },
 	{ 'C', bin_zle_complete, 3, 3 },
-	{ 'R', bin_zle_refresh, 0, 1 },
+	{ 'R', bin_zle_refresh, 0, -1 },
+	{ 'U', bin_zle_unget, 1, 1 },
 	{ 0,   bin_zle_call, 0, -1 },
     };
     struct opn const *op, *opp;
@@ -396,23 +397,50 @@ static int
 bin_zle_refresh(char *name, char **args, char *ops, char func)
 {
     char *s = statusline;
-    int sl = statusll;
+    int sl = statusll, ocl = clearlist;
 
+    statusline = NULL;
+    statusll = 0;
     if (*args) {
-	statusline = *args;
-	statusll = strlen(statusline);
-    } else {
-	statusline = NULL;
-	statusll = 0;
-    }
+	if (**args) {
+	    statusline = *args;
+	    statusll = strlen(statusline);
+	}
+	if (*++args) {
+	    LinkList l = newlinklist();
+	    int zmultsav = zmult;
+
+	    for (; *args; args++)
+		addlinknode(l, *args);
+
+	    zmult = 1;
+	    listlist(l);
+	    showinglist = clearlist = 0;
+	    zmult = zmultsav;
+	} else if (ops['c'])
+	    clearlist = 1;
+    } else if (ops['c'])
+	clearlist = 1;
     zrefresh();
 
+    clearlist = ocl;
     statusline = s;
     statusll = sl;
     return 0;
 }
 
 /**/
+static int
+bin_zle_unget(char *name, char **args, char *ops, char func)
+{
+    char *p = *args;
+
+    while (*p)
+	ungetkey((int) *p++);
+    return 0;
+}
+
+/**/
 static void
 scanlistwidgets(HashNode hn, int list)
 {
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index f7b243d31..5461079cb 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -133,7 +133,8 @@ static LinkList matches, fmatches;
 /* This holds the list of matches-groups. lmatches is a pointer to the  *
  * last element in this list. */
 
-static Cmgroup pmatches, amatches, lmatches;
+/**/
+Cmgroup pmatches, amatches, lmatches;
 
 /* Non-zero if we have permanently allocated matches. */
 
@@ -150,7 +151,8 @@ static int nmatches, smatches;
 
 /* !=0 if we have a valid completion list. */
 
-static int validlist;
+/**/
+int validlist;
 
 /* This flag is non-zero if we are completing a pattern (with globcomplete) */
 
@@ -818,7 +820,8 @@ docomplete(int lst)
      * string inserted by the last completion. */
 
     if (fromcomp & FC_INWORD)
-	cs = lastend;
+	if ((cs = lastend) > ll)
+	    cs = ll;
 
     /* Check if we have to start a menu-completion (via automenu). */
 
@@ -1773,6 +1776,7 @@ doexpansion(char *s, int lst, int olst, int explincmd)
 	if (lst == COMP_LIST_EXPAND) {
 	    /* Only the list of expansions was requested. */
 	    listlist(vl);
+	    showinglist = 0;
 	    goto end;
 	}
 	/* Remove the current word and put the expansions there. */
@@ -2577,7 +2581,8 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp,
 	    return NULL;
     
 	r = (qu ? quotename(r, NULL) : dupstring(r));
-
+	if (qu == 2 && r[0] == '\\' && r[1] == '~')
+	    chuck(r);
 	/* We still break it into parts here, trying to build a sensible
 	 * cline list for these matches, too. */
 	wl = strlen(w);
@@ -2590,6 +2595,8 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp,
 	int mpl, rpl, wl;
 
 	w = (qu ? quotename(w, NULL) : dupstring(w));
+	if (qu == 2 && w[0] == '\\' && w[1] == '~')
+	    chuck(w);
 
 	wl = strlen(w);
 
@@ -3814,15 +3821,20 @@ addmatches(Cadata dat, char **argv)
 		    dat->rems = dupstring(dat->rems);
 
 		/* Probably quote the prefix and suffix for testing. */
-		if (!cp && (dat->aflags & CAF_MATCH) &&
-		    !(dat->aflags & CAF_QUOTE)) {
-		    lpre = quotename(lpre, NULL);
-		    lsuf = quotename(lsuf, NULL);
+		if (!(dat->aflags & CAF_QUOTE)) {
+		    if (!cp && (dat->aflags & CAF_MATCH)) {
+			lpre = quotename(lpre, NULL);
+			lsuf = quotename(lsuf, NULL);
+		    }
+		    if (dat->ppre) {
+			dat->ppre = quotename(dat->ppre, NULL);
+			if ((dat->flags & CMF_FILE) &&
+			    dat->ppre[0] == '\\' && dat->ppre[1] == '~')
+			    chuck(dat->ppre);
+		    }
+		    if (dat->psuf)
+			dat->psuf = quotename(dat->psuf, NULL);
 		}
-		if (dat->ppre)
-		    dat->ppre = quotename(dat->ppre, NULL);
-		if (dat->psuf)
-		    dat->psuf = quotename(dat->psuf, NULL);
 	    }
 	    /* Walk through the matches given. */
 	    for (; (s = *argv); argv++) {
@@ -3855,7 +3867,9 @@ addmatches(Cadata dat, char **argv)
 		    lc = bld_parts(ms, sl, -1, NULL);
 		    isexact = 0;
 		} else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc,
-					     !(dat->aflags & CAF_QUOTE),
+					     (!(dat->aflags & CAF_QUOTE) ?
+					      ((dat->ppre && dat->ppre) ||
+					       !(dat->flags & CMF_FILE) ? 1 : 2) : 0),
 					     &bpl, &bsl, &isexact))) {
 		    if (dparr && !*++dparr)
 			dparr = NULL;
@@ -3962,7 +3976,7 @@ addmatch(char *s, char *t)
 	}
 	ms = ((addwhat == CC_FILES || addwhat == -6 ||
 	       addwhat == -5 || addwhat == -8) ? 
-	      comp_match(qfpre, qfsuf, s, filecomp, &lc, 1,
+	      comp_match(qfpre, qfsuf, s, filecomp, &lc, (ppre && *ppre ? 1 : 2),
 			 &bpl, &bsl, &isexact) :
 	      comp_match(fpre, fsuf, s, filecomp, &lc, 0,
 			 &bpl, &bsl, &isexact));
@@ -4361,6 +4375,7 @@ docompletion(char *s, int lst, int incmd)
 	    cs = origcs;
 	    clearlist = 1;
 	    ret = 1;
+	    minfo.cur = NULL;
 	    goto compend;
 	}
 	if (comppatmatch && *comppatmatch && comppatmatch != opm)
@@ -5156,10 +5171,16 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
 	zsfree(compisuffix);
 	compisuffix = ztrdup("");
 	zsfree(compqiprefix);
-	compqiprefix = qp;
 	zsfree(compqisuffix);
-	compqisuffix = qs;
-
+	if (instring) {
+	    compqiprefix = qp;
+	    compqisuffix = qs;
+	} else {
+	    compqiprefix = ztrdup(quotename(qp, NULL));
+	    zsfree(qp);
+	    compqisuffix = ztrdup(quotename(qs, NULL));
+	    zsfree(qs);
+	}
 	freearray(compwords);
 	i = countlinknodes(foo);
 	compwords = (char **) zalloc((i + 1) * sizeof(char *));
@@ -7028,7 +7049,7 @@ freematch(Cmatch m)
 /* This frees the groups of matches. */
 
 /**/
-static void
+void
 freematches(void)
 {
     Cmgroup g = pmatches, n;
diff --git a/Src/builtin.c b/Src/builtin.c
index 8fe112cb5..0e9baf9be 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -42,7 +42,7 @@ static struct builtin builtins[] =
     BUILTIN("[", 0, bin_test, 0, -1, BIN_BRACKET, NULL, NULL),
     BUILTIN(".", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL),
     BUILTIN(":", BINF_PSPECIAL, bin_true, 0, -1, 0, NULL, NULL),
-    BUILTIN("alias", BINF_MAGICEQUALS, bin_alias, 0, -1, 0, "Lgmr", NULL),
+    BUILTIN("alias", BINF_MAGICEQUALS | BINF_PLUSOPTS, bin_alias, 0, -1, 0, "Lgmr", NULL),
     BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "tU", "u"),
     BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL),
     BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL),
@@ -87,7 +87,7 @@ static struct builtin builtins[] =
 #endif
 
     BUILTIN("popd", 0, bin_cd, 0, 2, BIN_POPD, NULL, NULL),
-    BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "RDPnrslzNu0123456789pioOcm-", NULL),
+    BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "RDPbnrslzNu0123456789pioOcm-", NULL),
     BUILTIN("pushd", 0, bin_cd, 0, 2, BIN_PUSHD, NULL, NULL),
     BUILTIN("pushln", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, NULL, "-nz"),
     BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
@@ -645,12 +645,14 @@ set_pwd_env(void)
     setsparam("OLDPWD", ztrdup(oldpwd));
 
     pm = (Param) paramtab->getnode(paramtab, "PWD");
-    if (!(pm->flags & PM_EXPORTED)) {
+    if (!(pm->flags & PM_EXPORTED) &&
+	(!pm->level || (isset(ALLEXPORT) && !pm->old))) {
 	pm->flags |= PM_EXPORTED;
 	pm->env = addenv("PWD", pwd);
     }
     pm = (Param) paramtab->getnode(paramtab, "OLDPWD");
-    if (!(pm->flags & PM_EXPORTED)) {
+    if (!(pm->flags & PM_EXPORTED) &&
+	(!pm->level || (isset(ALLEXPORT) && !pm->old))) {
 	pm->flags |= PM_EXPORTED;
 	pm->env = addenv("OLDPWD", oldpwd);
     }
@@ -1492,7 +1494,7 @@ Param
 typeset_single(char *cname, char *pname, Param pm, int func,
 	       int on, int off, int roff, char *value, Param altpm)
 {
-    int usepm, tc, keeplocal = 0;
+    int usepm, tc, keeplocal = 0, newspecial = 0;
 
     /*
      * Do we use the existing pm?  Note that this isn't the end of the
@@ -1503,22 +1505,31 @@ typeset_single(char *cname, char *pname, Param pm, int func,
      */
     usepm = pm && !(pm->flags & PM_UNSET);
 
-    /* Always use an existing pm if special at current locallevel */
-    if (pm && (pm->flags & PM_SPECIAL) && pm->level == locallevel)
+    /*
+     * We need to compare types with an existing pm if special,
+     * even if that's unset
+     */
+    if (pm && (pm->flags & PM_SPECIAL))
 	usepm = 1;
 
     /*
-     * Don't use a non-special existing param if
+     * Don't use an existing param if
      *   - the local level has changed, and
      *   - we are really locallizing the parameter
      */
-    if (usepm && !(pm->flags & PM_SPECIAL) &&
-	locallevel != pm->level && (on & PM_LOCAL))
+    if (usepm && locallevel != pm->level && (on & PM_LOCAL)) {
+	/*
+	 * If the original parameter was special and we're creating
+	 * a new one, we need to keep it special.
+	 */
+	newspecial = (pm->flags & PM_SPECIAL);
 	usepm = 0;
+    }
 
     /* attempting a type conversion, or making a tied colonarray? */
-    if ((tc = usepm && (((off & pm->flags) | (on & ~pm->flags)) &
-			(PM_INTEGER|PM_HASHED|PM_ARRAY|PM_TIED|PM_AUTOLOAD))))
+    if ((tc = (usepm || newspecial)
+	 && (((off & pm->flags) | (on & ~pm->flags)) &
+	     (PM_INTEGER|PM_HASHED|PM_ARRAY|PM_TIED|PM_AUTOLOAD))))
 	usepm = 0;
     if (tc && (pm->flags & PM_SPECIAL)) {
 	zerrnam(cname, "%s: can't change type of a special parameter",
@@ -1526,13 +1537,27 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	return NULL;
     }
 
+    /*
+     * According to the manual, local parameters don't get exported.
+     * A parameter will be local if
+     * 1. we are re-using an existing local parameter
+     *    or
+     * 2. we are not using an existing parameter, but
+     *   i. there is already a parameter, which will be hidden
+     *     or
+     *   ii. we are creating a new local parameter
+     */
+    if ((usepm && pm->level) ||
+	(!usepm && (pm || (locallevel && (on & PM_LOCAL)))))
+	on &= ~PM_EXPORTED;
+
     if (usepm) {
 	on &= ~PM_LOCAL;
 	if (!on && !roff && !value) {
 	    paramtab->printnode((HashNode)pm, 0);
 	    return pm;
 	}
-	if ((pm->flags & PM_RESTRICTED && isset(RESTRICTED))) {
+	if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) {
 	    zerrnam(cname, "%s: restricted", pname, 0);
 	    return pm;
 	}
@@ -1553,7 +1578,8 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	    if (pm->flags & PM_EXPORTED) {
 		if (!(pm->flags & PM_UNSET) && !pm->env && !value)
 		    pm->env = addenv(pname, getsparam(pname));
-	    } else if (pm->env) {
+	    } else if (pm->env &&
+		       (!pm->level || (isset(ALLEXPORT) && !pm->old))) {
 		delenv(pm->env);
 		zsfree(pm->env);
 		pm->env = NULL;
@@ -1593,13 +1619,68 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	pname = dupstring(pname);
 	unsetparam_pm(pm, 0, 1);
     }
-    /*
-     * Create a new node for a parameter with the flags in `on' minus the
-     * readonly flag
-     */
-    pm = createparam(pname, on & ~PM_READONLY);
-    DPUTS(!pm, "BUG: parameter not created");
-    pm->ct = auxlen;
+
+    if (newspecial) {
+	Param tpm, pm2;
+	if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) {
+	    zerrnam(cname, "%s: restricted", pname, 0);
+	    return pm;
+	}
+	/*
+	 * For specials, we keep the same struct but zero everything.
+	 * Maybe it would be easier to create a new struct but copy
+	 * the get/set methods.
+	 */
+	tpm = (Param) zalloc(sizeof *tpm);
+
+	tpm->nam = pm->nam;
+	if (pm->ename &&
+	    (pm2 = (Param) paramtab->getnode(paramtab, pm->ename)) &&
+	    pm2->level == locallevel) {
+	    /* This is getting silly, but anyway:  if one of a path/PATH
+	     * pair has already been made local at the current level, we
+	     * have to make sure that the other one does not have its value
+	     * saved:  since that comes from an internal variable it will
+	     * already reflect the local value, so restoring it on exit
+	     * would be wrong.
+	     *
+	     * This problem is also why we make sure we have a copy
+	     * of the environment entry in tpm->env, rather than relying
+	     * on the restored value to provide it.
+	     */
+	    tpm->flags = pm->flags | PM_NORESTORE;
+	} else {
+	    copyparam(tpm, pm, 1);
+	}
+	tpm->old = pm->old;
+	tpm->level = pm->level;
+	tpm->ct = pm->ct;
+	tpm->env = pm->env;
+
+	pm->old = tpm;
+	/*
+	 * The remaining on/off flags should be harmless to use,
+	 * because we've checked for unpleasant surprises above.
+	 */
+	pm->flags = (PM_TYPE(pm->flags) | on | PM_SPECIAL) & ~off;
+	/*
+	 * Final tweak: if we've turned on one of the flags with
+	 * numbers, we should use the appropriate integer.
+	 */
+	if (on & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z|PM_INTEGER))
+	    pm->ct = auxlen;
+	else
+	    pm->ct = 0;
+	pm->env = NULL;
+    } else {
+	/*
+	 * Create a new node for a parameter with the flags in `on' minus the
+	 * readonly flag
+	 */
+	pm = createparam(pname, on & ~PM_READONLY);
+	DPUTS(!pm, "BUG: parameter not created");
+	pm->ct = auxlen;
+    }
 
     if (altpm && PM_TYPE(pm->flags) == PM_SCALAR) {
 	/*
@@ -1618,6 +1699,28 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	pm->level = locallevel;
     if (value && !(pm->flags & (PM_ARRAY|PM_HASHED)))
 	setsparam(pname, ztrdup(value));
+    else if (newspecial && !(pm->old->flags & PM_NORESTORE)) {
+	/*
+	 * We need to use the special setting function to re-initialise
+	 * the special parameter to empty.
+	 */
+	HEAPALLOC {
+	    switch (PM_TYPE(pm->flags)) {
+	    case PM_SCALAR:
+		pm->sets.cfn(pm, ztrdup(""));
+		break;
+	    case PM_INTEGER:
+		pm->sets.ifn(pm, 0);
+		break;
+	    case PM_ARRAY:
+		pm->sets.afn(pm, mkarray(NULL));
+		break;
+	    case PM_HASHED:
+		pm->sets.hfn(pm, newparamtable(17, pm->nam));
+		break;
+	    }
+	} LASTALLOC;
+    }
     pm->flags |= (on & PM_READONLY);
     if (value && (pm->flags & (PM_ARRAY|PM_HASHED))) {
 	zerrnam(cname, "%s: can't assign initial value for array", pname, 0);
@@ -1839,7 +1942,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
     Comp com;
     Shfunc shf;
     int i, returnval = 0;
-    int on = 0, off = 0;
+    int on = 0, off = 0, pflags = 0;
 
     /* Do we have any flags defined? */
     if (ops['u'] == 1)
@@ -1860,13 +1963,17 @@ bin_functions(char *name, char **argv, char *ops, int func)
 	return 1;
     }
 
+    if (ops['f'] == 2 || ops['+'])
+	pflags |= PRINT_NAMEONLY;
+
     /* If no arguments given, we will print functions.  If flags *
      * are given, we will print only functions containing these  *
      * flags, else we'll print them all.                         */
     if (!*argv) {
 	if (ops['U'] && !ops['u'])
 	    on &= ~PM_UNDEFINED;
-	scanhashtable(shfunctab, 1, on|off, DISABLED, shfunctab->printnode, 0);
+	scanhashtable(shfunctab, 1, on|off, DISABLED, shfunctab->printnode,
+		      pflags);
 	return 0;
     }
 
@@ -1879,7 +1986,8 @@ bin_functions(char *name, char **argv, char *ops, int func)
 	    if ((com = parsereg(*argv))) {
 		/* with no options, just print all functions matching the glob pattern */
 		if (!(on|off)) {
-		    scanmatchtable(shfunctab, com, 0, DISABLED, shfunctab->printnode, 0);
+		    scanmatchtable(shfunctab, com, 0, DISABLED,
+				   shfunctab->printnode, pflags);
 		} else {
 		/* apply the options to all functions matching the glob pattern */
 		    for (i = 0; i < shfunctab->hsize; i++) {
@@ -1906,7 +2014,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
 		shf->flags = (shf->flags | (on & ~PM_UNDEFINED)) & ~off;
 	    else
 		/* no flags, so just print */
-		shfunctab->printnode((HashNode) shf, 0);
+		shfunctab->printnode((HashNode) shf, pflags);
 	} else if (on & PM_UNDEFINED) {
 	    /* Add a new undefined (autoloaded) function to the *
 	     * hash table with the corresponding flags set.     */
@@ -2407,6 +2515,8 @@ bin_alias(char *name, char **argv, char *ops, int func)
 
     if (ops['L'])
 	printflags |= PRINT_LIST;
+    else if (ops['r'] == 2 || ops['g'] == 2 || ops['m'] == 2 || ops['+'])
+	printflags |= PRINT_NAMEONLY;
 
     /* In the absence of arguments, list all aliases.  If a command *
      * line flag is specified, list only those of that type.        */
@@ -2512,8 +2622,8 @@ bin_print(char *name, char **args, char *ops, int func)
 	if (!ops['e'] && (ops['R'] || ops['r'] || ops['E']))
 	    unmetafy(args[n], &len[n]);
 	else
-	    args[n] = getkeystring(args[n], &len[n],
-				    func != BIN_ECHO && !ops['e'], &nnl);
+	    args[n] = getkeystring(args[n], &len[n], ops['b'] ? 2 :
+				    (func != BIN_ECHO && !ops['e']), &nnl);
 	/* -P option -- interpret as a prompt sequence */
 	if(ops['P']) {
 	    /*
@@ -3098,11 +3208,7 @@ bin_eval(char *nam, char **argv, char *ops, int func)
 {
     List list;
 
-    inpush(zjoin(argv, ' '), 0, NULL);
-    strinbeg(0);
-    list = parse_list();
-    strinend();
-    inpop();
+    list = parse_string(zjoin(argv, ' '), 0);
     if (!list) {
 	errflag = 0;
 	return 1;
diff --git a/Src/exec.c b/Src/exec.c
index bc5548f1e..9c7a1ceb5 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -916,7 +916,7 @@ execpline(Sublist l, int how, int last1)
 		    }
 
 		    jn->stat &= ~(STAT_DONE | STAT_NOPRINT);
-		    jn->stat |= STAT_STOPPED | STAT_CHANGED;
+		    jn->stat |= STAT_STOPPED | STAT_CHANGED | STAT_LOCKED;
 		    printjob(jn, !!isset(LONGLISTJOBS), 1);
 		}
 		else if (newjob != list_pipe_job)
@@ -1012,7 +1012,9 @@ execpline(Sublist l, int how, int last1)
 		jn = jobtab + pj;
 		killjb(jn, lastval & ~0200);
 	    }
-	    if (list_pipe_child || (list_pipe && (jn->stat & STAT_DONE)))
+	    if (list_pipe_child ||
+		((jn->stat & STAT_DONE) &&
+		 (list_pipe || (pline_level && !(jn->stat & STAT_SUBJOB)))))
 		deletejob(jn);
 	    thisjob = pj;
 
@@ -1530,6 +1532,9 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
 			/* Was this "exec < foobar"? */
 			nullexec = 1;
 			break;
+		    } else if (vars && nonempty(vars)) {
+			nullexec = 2;
+			break;
 		    } else if (!nullcmd || !*nullcmd ||
 			       (cflags & BINF_PREFIX)) {
 			zerr("redirection with no command", NULL, 0);
@@ -1869,7 +1874,8 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
 		addfd(forked, save, mfds, fn->fd1, fil, 0);
 		/* If this is 'exec < file', read from stdin, *
 		 * not terminal, unless `file' is a terminal. */
-		if (nullexec && fn->fd1 == 0 && isset(SHINSTDIN) && interact)
+		if (nullexec == 1 && fn->fd1 == 0 &&
+		    isset(SHINSTDIN) && interact)
 		    init_io();
 		break;
 	    case CLOSE:
@@ -1929,17 +1935,28 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
 	closemn(mfds, i);
 
     if (nullexec) {
-	for (i = 0; i < 10; i++)
-	    if (save[i] != -2)
-		zclose(save[i]);
+	if (nullexec == 1) {
+	    /*
+	     * If nullexec is 1 we specifically *don't* restore the original
+	     * fd's before returning.
+	     */
+	    for (i = 0; i < 10; i++)
+		if (save[i] != -2)
+		    zclose(save[i]);
+	    return;
+	}
 	/*
-	 * Here we specifically *don't* restore the original fd's
-	 * before returning.
+	 * If nullexec is 2, we have variables to add with the redirections
+	 * in place.
 	 */
-	return;
-    }
-
-    if (isset(EXECOPT) && !errflag) {
+	if (vars)
+	    addvars(vars, 0);
+	lastval = errflag ? errflag : cmdoutval;
+	if (isset(XTRACE)) {
+	    fputc('\n', stderr);
+	    fflush(stderr);
+	}
+    } else if (isset(EXECOPT) && !errflag) {
 	/*
 	 * We delay the entersubsh() to here when we are exec'ing
 	 * the current shell (including a fake exec to run a builtin then
diff --git a/Src/hist.c b/Src/hist.c
index edf74009e..167ffe171 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -291,7 +291,7 @@ safeinungetc(int c)
 void
 herrflush(void)
 {
-    while (!lexstop && inbufct)
+    while (!lexstop && inbufct && !strin)
 	hwaddc(ingetc());
 }
 
diff --git a/Src/jobs.c b/Src/jobs.c
index b2d7e9af1..fdf69a960 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -125,6 +125,86 @@ findproc(pid_t pid, Job *jptr, Process *pptr)
     return 0;
 }
 
+/* Find the super-job of a sub-job. */
+
+/**/
+static int
+super_job(int sub)
+{
+    int i;
+
+    for (i = 1; i < MAXJOB; i++)
+	if ((jobtab[i].stat & STAT_SUPERJOB) &&
+	    jobtab[i].other == sub &&
+	    jobtab[i].gleader)
+	    return i;
+    return 0;
+}
+
+/**/
+static int
+handle_sub(int job, int fg)
+{
+    Job jn = jobtab + job, sj = jobtab + jn->other;
+
+    if ((sj->stat & STAT_DONE) || !sj->procs) {
+	struct process *p;
+		    
+	for (p = sj->procs; p; p = p->next)
+	    if (WIFSIGNALED(p->status)) {
+		if (jn->gleader != mypgrp && jn->procs->next)
+		    killpg(jn->gleader, WTERMSIG(p->status));
+		else
+		    kill(jn->procs->pid, WTERMSIG(p->status));
+		kill(sj->other, SIGCONT);
+		kill(sj->other, WTERMSIG(p->status));
+		break;
+	    }
+	if (!p) {
+	    int cp;
+
+	    jn->stat &= ~STAT_SUPERJOB;
+	    jn->stat |= STAT_WASSUPER;
+
+	    if ((cp = ((WIFEXITED(jn->procs->status) ||
+			WIFSIGNALED(jn->procs->status)) &&
+		       killpg(jn->gleader, 0) == -1))) {
+		Process p;
+		for (p = jn->procs; p->next; p = p->next);
+		jn->gleader = p->pid;
+	    }
+	    /* This deleted the job too early if the parent
+	       shell waited for a command in a list that will
+	       be executed by the sub-shell (e.g.: if we have
+	       `ls|if true;then sleep 20;cat;fi' and ^Z the
+	       sleep, the rest will be executed by a sub-shell,
+	       but the parent shell gets notified for the
+	       sleep.
+	       deletejob(sj); */
+	    /* If this super-job contains only the sub-shell,
+	       we have to attach the tty to its process group
+	       now. */
+	    if ((fg || thisjob == job) &&
+		(!jn->procs->next || cp || jn->procs->pid != jn->gleader))
+		attachtty(jn->gleader);
+	    kill(sj->other, SIGCONT);
+	}
+	curjob = jn - jobtab;
+    } else if (sj->stat & STAT_STOPPED) {
+	struct process *p;
+
+	jn->stat |= STAT_STOPPED;
+	for (p = jn->procs; p; p = p->next)
+	    if (p->status == SP_RUNNING ||
+		(!WIFEXITED(p->status) && !WIFSIGNALED(p->status)))
+		p->status = sj->procs->status;
+	curjob = jn - jobtab;
+	printjob(jn, !!isset(LONGLISTJOBS), 1);
+	return 1;
+    }
+    return 0;
+}
+
 /* Update status of process that we have just WAIT'ed for */
 
 /**/
@@ -183,13 +263,8 @@ update_job(Job jn)
 		 * or to exit. So we have to send it a SIGTSTP. */
 		int i;
 
-		for (i = 1; i < MAXJOB; i++)
-		    if ((jobtab[i].stat & STAT_SUPERJOB) &&
-			jobtab[i].other == job &&
-			jobtab[i].gleader) {
-			killpg(jobtab[i].gleader, SIGTSTP);
-			break;
-		    }
+		if ((i = super_job(job)))
+		    killpg(jobtab[i].gleader, SIGTSTP);
 	    }
 	    return;
 	}
@@ -254,6 +329,13 @@ update_job(Job jn)
 	return;
     jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED :
 	STAT_CHANGED | STAT_DONE;
+    if (!inforeground &&
+	(jn->stat & (STAT_SUBJOB | STAT_DONE)) == (STAT_SUBJOB | STAT_DONE)) {
+	int su;
+
+	if ((su = super_job(jn - jobtab)))
+	    handle_sub(su, 0);
+    }
     if ((jn->stat & (STAT_DONE | STAT_STOPPED)) == STAT_STOPPED) {
 	prevjob = curjob;
 	curjob = job;
@@ -303,13 +385,14 @@ setprevjob(void)
 
     for (i = MAXJOB - 1; i; i--)
 	if ((jobtab[i].stat & STAT_INUSE) && (jobtab[i].stat & STAT_STOPPED) &&
-	    i != curjob && i != thisjob) {
+	    !(jobtab[i].stat & STAT_SUBJOB) && i != curjob && i != thisjob) {
 	    prevjob = i;
 	    return;
 	}
 
     for (i = MAXJOB - 1; i; i--)
-	if ((jobtab[i].stat & STAT_INUSE) && i != curjob && i != thisjob) {
+	if ((jobtab[i].stat & STAT_INUSE) && !(jobtab[i].stat & STAT_SUBJOB) &&
+	    i != curjob && i != thisjob) {
 	    prevjob = i;
 	    return;
 	}
@@ -791,64 +874,9 @@ waitjob(int job, int sig)
 		killjb(jn, SIGCONT);
 		jn->stat &= ~STAT_STOPPED;
 	    }
-	    if (jn->stat & STAT_SUPERJOB) {
-		Job sj = jobtab + jn->other;
-		if ((sj->stat & STAT_DONE) || !sj->procs) {
-		    struct process *p;
-		    
-		    for (p = sj->procs; p; p = p->next)
-			if (WIFSIGNALED(p->status)) {
-			    if (jn->gleader != mypgrp && jn->procs->next)
-				killpg(jn->gleader, WTERMSIG(p->status));
-			    else
-				kill(jn->procs->pid, WTERMSIG(p->status));
-			    kill(sj->other, SIGCONT);
-			    kill(sj->other, WTERMSIG(p->status));
-			    break;
-			}
-		    if (!p) {
-			int cp;
-
-			jn->stat &= ~STAT_SUPERJOB;
-			jn->stat |= STAT_WASSUPER;
-
-			if ((cp = ((WIFEXITED(jn->procs->status) ||
-				    WIFSIGNALED(jn->procs->status)) &&
-				   killpg(jn->gleader, 0) == -1))) {
-			    Process p;
-			    for (p = jn->procs; p->next; p = p->next);
-			    jn->gleader = p->pid;
-			}
-			/* This deleted the job too early if the parent
-			   shell waited for a command in a list that will
-			   be executed by the sub-shell (e.g.: if we have
-			   `ls|if true;then sleep 20;cat;fi' and ^Z the
-			   sleep, the rest will be executed by a sub-shell,
-			   but the parent shell gets notified for the
-			   sleep.
-			   deletejob(sj); */
-			/* If this super-job contains only the sub-shell,
-			   we have to attach the tty to our process group
-			   (which is shared by the sub-shell) now. */
-			if (!jn->procs->next || cp || jn->procs->pid != jn->gleader)
-			    attachtty(jn->gleader);
-			kill(sj->other, SIGCONT);
-		    }
-		    curjob = jn - jobtab;
-		}
-		else if (sj->stat & STAT_STOPPED) {
-		    struct process *p;
-
-		    jn->stat |= STAT_STOPPED;
-		    for (p = jn->procs; p; p = p->next)
-			if (p->status == SP_RUNNING ||
-			    (!WIFEXITED(p->status) && !WIFSIGNALED(p->status)))
-			    p->status = sj->procs->status;
-		    curjob = jn - jobtab;
-		    printjob(jn, !!isset(LONGLISTJOBS), 1);
+	    if (jn->stat & STAT_SUPERJOB)
+		if (handle_sub(jn - jobtab, 1))
 		    break;
-		}
-	    }
 	    child_block();
 	}
     } else
diff --git a/Src/loop.c b/Src/loop.c
index 16e4ff314..fd63edb5a 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -57,6 +57,13 @@ execfor(Cmd cmd, LinkList args, int flags)
     if (node->condition) {
 	str = dupstring(node->name);
 	singsub(&str);
+	if (isset(XTRACE)) {
+	    char *str2 = dupstring(str);
+	    untokenize(str2);
+	    printprompt4();
+	    fprintf(stderr, "%s\n", str2);
+	    fflush(stderr);
+	}
 	if (!errflag)
 	    matheval(str);
 	if (errflag)
@@ -79,9 +86,14 @@ execfor(Cmd cmd, LinkList args, int flags)
 	    if (!errflag) {
 		while (iblank(*str))
 		    str++;
-		if (*str)
+		if (*str) {
+		    if (isset(XTRACE)) {
+			printprompt4();
+			fprintf(stderr, "%s\n", str);
+			fflush(stderr);
+		    }
 		    val = matheval(str);
-		else
+		} else
 		    val = 1;
 	    }
 	    if (errflag) {
@@ -95,6 +107,11 @@ execfor(Cmd cmd, LinkList args, int flags)
 	} else {
 	    if (!args || !(str = (char *) ugetnode(args)))
 		break;
+	    if (isset(XTRACE)) {
+		printprompt4();
+		fprintf(stderr, "%s=%s\n", node->name, str);
+		fflush(stderr);
+	    }
 	    setsparam(node->name, ztrdup(str));
 	}
 	execlist(node->list, 1,
@@ -107,6 +124,11 @@ execfor(Cmd cmd, LinkList args, int flags)
 	}
 	if (node->condition && !errflag) {
 	    str = dupstring(node->advance);
+	    if (isset(XTRACE)) {
+		printprompt4();
+		fprintf(stderr, "%s\n", str);
+		fflush(stderr);
+	    }
 	    singsub(&str);
 	    if (!errflag)
 		matheval(str);
@@ -410,6 +432,13 @@ execcase(Cmd cmd, LinkList args, int flags)
 	while (*p) {
 	    char *pat = dupstring(*p + 1);
 	    singsub(&pat);
+	    if (isset(XTRACE)) {
+		char *pat2 = dupstring(pat);
+		untokenize(pat2);
+		printprompt4();
+		fprintf(stderr, "case %s (%s)\n", word, pat2);
+		fflush(stderr);
+	    }
 	    if (matchpat(word, pat)) {
 		do {
 		    execlist(*l++, 1, **p == ';' && (flags & CFLAG_EXEC));
diff --git a/Src/math.c b/Src/math.c
index 7e7e557ed..10821b284 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -357,9 +357,11 @@ zzlex(void)
 	    }
 	    if (*ptr == '#') {
 		if (*++ptr == '\\') {
+		    int v;
+
 		    ptr++;
-		    yyval = *ptr == Meta ? *++ptr ^ 32 : *ptr;
-		    ptr++;
+		    ptr = getkeystring(ptr, NULL, 6, &v);
+		    yyval = v;
 		    unary = 0;
 		    return NUM;
 		}
diff --git a/Src/params.c b/Src/params.c
index d71cfb46e..094d7a166 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1905,7 +1905,7 @@ arrhashsetfn(Param pm, char **val)
 
     if (alen % 2) {
 	freearray(val);
-	zerr("bad set of key/value pairs for associative array\n",
+	zerr("bad set of key/value pairs for associative array",
 	     NULL, 0);
 	return;
     }
@@ -2500,11 +2500,17 @@ arrfixenv(char *s, char **t)
     Param pm;
 
     MUSTUSEHEAP("arrfixenv");
+    pm = (Param) paramtab->getnode(paramtab, s);
+    /*
+     * Only one level of a parameter can be exported.  Unless
+     * ALLEXPORT is set, this must be global.
+     */
     if (t == path)
 	cmdnamtab->emptytable(cmdnamtab);
+    if (isset(ALLEXPORT) ? !!pm->old : pm->level)
+	return;
     u = t ? zjoin(t, ':') : "";
     len_s = strlen(s);
-    pm = (Param) paramtab->getnode(paramtab, s);
     for (ep = environ; *ep; ep++)
 	if (!strncmp(*ep, s, len_s) && (*ep)[len_s] == '=') {
 	    pm->env = replenv(*ep, u);
@@ -2685,8 +2691,46 @@ static void
 scanendscope(HashNode hn, int flags)
 {
     Param pm = (Param)hn;
-    if(pm->level > locallevel)
-	unsetparam_pm(pm, 0, 0);
+    if (pm->level > locallevel) {
+	if ((pm->flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL) {
+	    /*
+	     * Removable specials are normal in that they can be removed
+	     * to reveal an ordinary parameter beneath.  Here we handle
+	     * non-removable specials, which were made local by stealth
+	     * (see newspecial code in typeset_single()).  In fact the
+	     * visible pm is always the same struct; the pm->old is
+	     * just a place holder for old data and flags.
+	     */
+	    Param tpm = pm->old;
+
+	    DPUTS(!tpm || PM_TYPE(pm->flags) != PM_TYPE(tpm->flags) ||
+		  !(tpm->flags & PM_SPECIAL),
+		  "BUG: in restoring scope of special parameter");
+	    pm->old = tpm->old;
+	    pm->flags = (tpm->flags & ~PM_NORESTORE);
+	    pm->level = tpm->level;
+	    pm->ct = tpm->ct;
+	    pm->env = tpm->env;
+
+	    if (!(tpm->flags & PM_NORESTORE))
+		switch (PM_TYPE(pm->flags)) {
+		case PM_SCALAR:
+		    pm->sets.cfn(pm, tpm->u.str);
+		    break;
+		case PM_INTEGER:
+		    pm->sets.ifn(pm, tpm->u.val);
+		    break;
+		case PM_ARRAY:
+		    pm->sets.afn(pm, tpm->u.arr);
+		    break;
+		case PM_HASHED:
+		    pm->sets.hfn(pm, tpm->u.hash);
+		    break;
+		}
+	    zfree(tpm, sizeof(*tpm));
+	} else
+	    unsetparam_pm(pm, 0, 0);
+    }
 }
 
 
diff --git a/Src/prompt.c b/Src/prompt.c
index 89407694e..dcba16d56 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -97,6 +97,38 @@ static int dontcount;
 
 static char *rstring, *Rstring;
 
+/*
+ * Expand path p; maximum is npath segments where 0 means the whole path.
+ * If tilde is 1, try and find a named directory to use.
+ */
+
+static void
+promptpath(char *p, int npath, int tilde)
+{
+    char *modp = p;
+    Nameddir nd;
+
+    if (tilde && ((nd = finddir(p))))
+	modp = tricat("~", nd->nam, p + strlen(nd->dir));
+
+    if (npath) {
+	char *sptr;
+	for (sptr = modp + strlen(modp); sptr > modp; sptr--) {
+	    if (*sptr == '/' && !--npath) {
+		sptr++;
+		break;
+	    }
+	}
+	if (*sptr == '/' && sptr[1] && sptr != modp)
+	    sptr++;
+	stradd(sptr);
+    } else
+	stradd(modp);
+
+    if (p != modp)
+	zsfree(modp);
+}
+
 /* Perform prompt expansion on a string, putting the result in a *
  * permanently-allocated string.  If ns is non-zero, this string *
  * may have embedded Inpar and Outpar, which indicate a toggling *
@@ -293,49 +325,21 @@ putpromptchar(int doprint, int endchar)
 		}
 	    switch (*fm) {
 	    case '~':
-		if ((nd = finddir(pwd))) {
-		    char *t = tricat("~", nd->nam, pwd + strlen(nd->dir));
-		    stradd(t);
-		    zsfree(t);
-		    break;
-		}
+		promptpath(pwd, arg, 1);
+		break;
 	    case 'd':
 	    case '/':
-		stradd(pwd);
+		promptpath(pwd, arg, 0);
 		break;
 	    case 'c':
 	    case '.':
-	        {
-		    char *t;
-
-		    if ((nd = finddir(pwd)))
-			t = tricat("~", nd->nam, pwd + strlen(nd->dir));
-		    else
-			t = ztrdup(pwd);
-		    if (!arg)
-			arg++;
-		    for (ss = t + strlen(t); ss > t; ss--)
-			if (*ss == '/' && !--arg) {
-			    ss++;
-			    break;
-			}
-		    if(*ss == '/' && ss[1] && ss != t)
-			ss++;
-		    stradd(ss);
-		    zsfree(t);
-		    break;
-		}
+		promptpath(pwd, arg ? arg : 1, 1);
+		break;
 	    case 'C':
-		if (!arg)
-		    arg++;
-		for (ss = pwd + strlen(pwd); ss > pwd; ss--)
-		    if (*ss == '/' && !--arg) {
-			ss++;
-			break;
-		    }
-		if (*ss == '/' && ss[1] && (ss != pwd))
-		    ss++;
-		stradd(ss);
+		promptpath(pwd, arg ? arg : 1, 0);
+		break;
+	    case 'N':
+		promptpath(scriptname ? scriptname : argzero, arg, 0);
 		break;
 	    case 'h':
 	    case '!':
@@ -536,9 +540,6 @@ putpromptchar(int doprint, int endchar)
 		sprintf(bp, "%ld", (long)lineno);
 		bp += strlen(bp);
 		break;
-	    case 'N':
-		stradd(scriptname ? scriptname : argzero);
-		break;
 	    case '\0':
 		return 0;
 	    case Meta:
diff --git a/Src/utils.c b/Src/utils.c
index a409ab03c..d82f62694 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1735,10 +1735,11 @@ findsep(char **s, char *sep)
 	if (!*t)
 	    return i;
 	if (*(*s)++ == Meta) {
-	    (*s)++;
 #ifdef DEBUG
-	    if (! **s)
+	    if (! *(*s)++)
 		fprintf(stderr, "BUG: unexpected end of string in findsep()\n");
+#else
+	    (*s)++;
 #endif
 	}
     }
@@ -3187,24 +3188,28 @@ dquotedzputs(char const *s, FILE *stream)
  *   4:  Do $'...' quoting.  Overwrites the existing string instead of
  *       zhalloc'ing 
  *   5:  As 2, but \- is special.  Expects misc to be defined.
+ *   6:  As 2, but parses only one character and returns end-pointer
+ *       and parsed character in *misc
  */
 
 /**/
 char *
 getkeystring(char *s, int *len, int fromwhere, int *misc)
 {
-    char *buf;
+    char *buf, tmp[1];
     char *t, *u = NULL;
     char svchar = '\0';
     int meta = 0, control = 0;
 
-    if (fromwhere != 4)
-	buf = zhalloc(strlen(s) + 1);
+    if (fromwhere == 6)
+	t = tmp;
+    else if (fromwhere != 4)
+	t = buf = zhalloc(strlen(s) + 1);
     else {
-	buf = s;
+	t = buf = s;
 	s += 2;
     }
-    for (t = buf; *s; s++) {
+    for (; *s; s++) {
 	if (*s == '\\' && s[1]) {
 	    switch (*++s) {
 	    case 'a':
@@ -3303,7 +3308,8 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 	} else if (fromwhere == 4 && *s == Snull) {
 	    for (u = t; (*u++ = *s++););
 	    return t + 1;
-	} else if (*s == '^' && (fromwhere == 2 || fromwhere == 5)) {
+	} else if (*s == '^' &&
+		   (fromwhere == 2 || fromwhere == 5 || fromwhere == 6)) {
 	    control = 1;
 	    continue;
 	} else if (*s == Meta)
@@ -3330,6 +3336,10 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 	    t[-1] = Meta;
 	    t++;
 	}
+	if (fromwhere == 6 && t != tmp) {
+	    *misc = (int) tmp[0];
+	    return s + 1;
+	}
     }
     DPUTS(fromwhere == 4, "BUG: unterminated $' substitution");
     *t = '\0';
diff --git a/Src/zsh.h b/Src/zsh.h
index 88175eea6..2070e9b3f 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -951,40 +951,41 @@ struct param {
 /* flags for parameters */
 
 /* parameter types */
-#define PM_SCALAR	0	/* scalar                                     */
-#define PM_ARRAY	(1<<0)	/* array                                      */
-#define PM_INTEGER	(1<<1)	/* integer                                    */
-#define PM_HASHED	(1<<2)	/* association                                */
+#define PM_SCALAR	0	/* scalar                                   */
+#define PM_ARRAY	(1<<0)	/* array                                    */
+#define PM_INTEGER	(1<<1)	/* integer                                  */
+#define PM_HASHED	(1<<2)	/* association                              */
 
 #define PM_TYPE(X) (X & (PM_SCALAR|PM_INTEGER|PM_ARRAY|PM_HASHED))
 
-#define PM_LEFT		(1<<3)	/* left justify and remove leading blanks     */
-#define PM_RIGHT_B	(1<<4)	/* right justify and fill with leading blanks */
-#define PM_RIGHT_Z	(1<<5)	/* right justify and fill with leading zeros  */
-#define PM_LOWER	(1<<6)	/* all lower case                             */
+#define PM_LEFT		(1<<3)	/* left justify, remove leading blanks      */
+#define PM_RIGHT_B	(1<<4)	/* right justify, fill with leading blanks  */
+#define PM_RIGHT_Z	(1<<5)	/* right justify, fill with leading zeros   */
+#define PM_LOWER	(1<<6)	/* all lower case                           */
 
 /* The following are the same since they *
  * both represent -u option to typeset   */
-#define PM_UPPER	(1<<7)	/* all upper case                             */
-#define PM_UNDEFINED	(1<<7)	/* undefined (autoloaded) shell function      */
+#define PM_UPPER	(1<<7)	/* all upper case                           */
+#define PM_UNDEFINED	(1<<7)	/* undefined (autoloaded) shell function    */
 
-#define PM_READONLY	(1<<8)	/* readonly                                   */
-#define PM_TAGGED	(1<<9)	/* tagged                                     */
-#define PM_EXPORTED	(1<<10)	/* exported                                   */
+#define PM_READONLY	(1<<8)	/* readonly                                 */
+#define PM_TAGGED	(1<<9)	/* tagged                                   */
+#define PM_EXPORTED	(1<<10)	/* exported                                 */
 
 /* The following are the same since they *
  * both represent -U option to typeset   */
-#define PM_UNIQUE	(1<<11)	/* remove duplicates                          */
-#define PM_UNALIASED	(1<<11)	/* do not expand aliases when autoloading     */
-
-#define PM_TIED 	(1<<12)	/* array tied to colon-path or v.v. */
-#define PM_LOCAL	(1<<13) /* this parameter will be made local */
-#define PM_SPECIAL	(1<<14) /* special builtin parameter                  */
-#define PM_DONTIMPORT	(1<<15)	/* do not import this variable                */
-#define PM_RESTRICTED	(1<<16) /* cannot be changed in restricted mode       */
-#define PM_UNSET	(1<<17)	/* has null value                             */
-#define PM_REMOVABLE	(1<<18)	/* special can be removed from paramtab */
-#define PM_AUTOLOAD     (1<<19) /* autoloaded from module */
+#define PM_UNIQUE	(1<<11)	/* remove duplicates                        */
+#define PM_UNALIASED	(1<<11)	/* do not expand aliases when autoloading   */
+
+#define PM_TIED 	(1<<12)	/* array tied to colon-path or v.v.         */
+#define PM_LOCAL	(1<<13) /* this parameter will be made local        */
+#define PM_SPECIAL	(1<<14) /* special builtin parameter                */
+#define PM_DONTIMPORT	(1<<15)	/* do not import this variable              */
+#define PM_RESTRICTED	(1<<16) /* cannot be changed in restricted mode     */
+#define PM_UNSET	(1<<17)	/* has null value                           */
+#define PM_REMOVABLE	(1<<18)	/* special can be removed from paramtab     */
+#define PM_AUTOLOAD	(1<<19) /* autoloaded from module                   */
+#define PM_NORESTORE	(1<<20)	/* do not restore value of local special    */
 
 /* Flags for extracting elements of arrays and associative arrays */
 #define SCANPM_WANTVALS   (1<<0)
diff --git a/configure.in b/configure.in
index f134c97c1..a5dbc6413 100644
--- a/configure.in
+++ b/configure.in
@@ -100,7 +100,8 @@ fi])
 dnl Do you want large file support, if available?
 undefine([lfs])dnl
 AC_ARG_ENABLE(lfs,
-[  --enable-lfs               turn on support for large files])
+[  --enable-lfs               turn on support for large files],
+[lfs="$enableval"], [lfs=yes])
 
 dnl Pathnames for global zsh scripts
 undefine([etcdir])dnl
@@ -183,7 +184,7 @@ dnl Do you want dynamically loaded binary modules.
 undefine([dynamic])dnl
 AC_ARG_ENABLE(dynamic,
 [  --enable-dynamic           allow dynamically loaded binary modules],
-[dynamic="$enableval"], [dynamic=no])
+[dynamic="$enableval"], [dynamic=yes])
 
 dnl Do you want to compile as K&R C.
 AC_ARG_ENABLE(ansi2knr,
@@ -214,7 +215,7 @@ AC_ARG_ENABLE(function-subdirs,
 [  --enable-function-subdirs  install functions in subdirectories])
 
 if test "x${FUNCTIONS_INSTALL+set}" != xset; then
-  FUNCTIONS_INSTALL="Core/* Base/* Builtins/* User/* Commands/*"
+  FUNCTIONS_INSTALL="Core/* Base/* Builtins/* User/* Commands/* Zle/*"
   if test $dynamic != no; then
     FUNCTIONS_INSTALL="${FUNCTIONS_INSTALL} Zftp/*"
   fi
@@ -243,7 +244,7 @@ AC_PROG_CC
 
 dnl Check for large file support.
 dnl This needs to be done early to get the stuff into the flags.
-if test "x$enable_lfs" != x; then
+if test $lfs != no; then
 zsh_LARGE_FILE_SUPPORT
 fi
 
@@ -595,12 +596,11 @@ main() { return sizeof(ino_t) < 8; }
     AC_DEFINE(INO_T_IS_64_BIT)
   fi
 
-  if test "x$enable_lfs" != xno -o $zsh_cv_off_t_is_64_bit = yes \
+  if test $lfs != no -o $zsh_cv_off_t_is_64_bit = yes \
   -o $zsh_cv_ino_t_is_64_bit = yes; then
     AC_CACHE_CHECK(if compiler has a 64 bit type, zsh_cv_64_bit_type,
-    [if test "x$enable_lfs" != x -a "x$enable_lfs" != xyes \
-     -a "x$enable_lfs" != xno; then
-      zsh_64_BIT_TYPE(${enable_lfs}, zsh_cv_64_bit_type, force)
+    [if test $lfs != xyes -a $lfs != xno; then
+      zsh_64_BIT_TYPE(${lfs}, zsh_cv_64_bit_type, force)
      else
        zsh_64_BIT_TYPE(long long, zsh_cv_64_bit_type)
        if test "$zsh_cv_64_bit_type" = no; then
@@ -1171,8 +1171,10 @@ char *argv[];
   DL_EXT="${DL_EXT=so}"
   if test $zsh_cv_sys_elf = yes; then
     DLLD="${DLLD=$CC}"
+    DLLDARG="${LDARG}"
   else
     DLLD="${DLLD=ld}"
+    DLLDARG=""
   fi
   if test -n "$GCC"; then
     DLCFLAGS="${DLCFLAGS=-fpic}"
@@ -1188,7 +1190,7 @@ char *argv[];
     linux*|irix*|osf*) DLLDFLAGS="${DLLDFLAGS=-shared}" ;;
     sunos*)       DLLDFLAGS="${DLLDFLAGS=-assert nodefinitions}" ;;
     sysv4*|esix*) DLLDFLAGS="${DLLDFLAGS=-G $ldflags}" ;;
-    netbsd*)      DLLDFLAGS="${DLLDFLAGS=-x -shared --whole-archive}" ;;
+    netbsd*)      DLLDFLAGS="${DLLDFLAGS=${DLLDARG}-x -shared --whole-archive}" ;;
     aix*)         DLLDFLAGS="${DLLDFLAGS=-G -bexpall -lc}" ;;
     solaris*|sysv4*|esix*) DLLDFLAGS="${DLLDFLAGS=-G}" ;;
   esac
@@ -1340,11 +1342,13 @@ CLEAN_MK="${srcdir}/Config/clean.mk"
 CONFIG_MK="${srcdir}/Config/config.mk"
 dnl defs.mk is in the build tree, not the source tree
 DEFS_MK="Config/defs.mk"
+FUNCINST_MK="${srcdir}/Config/funcinst.mk"
 VERSION_MK="${srcdir}/Config/version.mk"
 
 AC_SUBST_FILE(CLEAN_MK)dnl
 AC_SUBST_FILE(CONFIG_MK)dnl
 AC_SUBST_FILE(DEFS_MK)dnl
+AC_SUBST_FILE(FUNCINST_MK)dnl
 AC_SUBST_FILE(VERSION_MK)dnl
 
 real_no_create=$no_create