about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Completion/.distfiles3
-rw-r--r--Completion/Base/.distfiles6
-rw-r--r--Completion/Base/_command_names10
-rw-r--r--Completion/Base/_condition8
-rw-r--r--Completion/Base/_default2
-rw-r--r--Completion/Base/_long_options309
-rw-r--r--Completion/Base/_match_pattern6
-rw-r--r--Completion/Base/_subscript9
-rw-r--r--Completion/Builtins/.distfiles7
-rw-r--r--Completion/Builtins/_bindkey11
-rw-r--r--Completion/Builtins/_cd13
-rw-r--r--Completion/Builtins/_disable12
-rw-r--r--Completion/Builtins/_enable12
-rw-r--r--Completion/Builtins/_kill8
-rw-r--r--Completion/Builtins/_setopt9
-rw-r--r--Completion/Builtins/_unhash12
-rw-r--r--Completion/Builtins/_unsetopt9
-rw-r--r--Completion/Builtins/_wait8
-rw-r--r--Completion/Builtins/_zftp3
-rw-r--r--Completion/Commands/.distfiles3
-rw-r--r--Completion/Core/.distfiles5
-rw-r--r--Completion/Core/_compalso6
-rw-r--r--Completion/Core/_files11
-rw-r--r--Completion/Core/_main_complete118
-rw-r--r--Completion/Core/_normal16
-rw-r--r--Completion/Core/_path_files141
-rw-r--r--Completion/Core/_sep_parts171
-rw-r--r--Completion/Core/compdump2
-rw-r--r--Completion/Core/compinit48
-rw-r--r--Completion/README14
-rw-r--r--Completion/User/.distfiles6
-rw-r--r--Completion/User/_a2ps53
-rw-r--r--Completion/User/_configure35
-rw-r--r--Completion/User/_dd2
-rw-r--r--Completion/User/_find8
-rw-r--r--Completion/User/_man2
-rw-r--r--Completion/User/_mh14
-rw-r--r--Completion/User/_rcs1
-rw-r--r--Completion/User/_strip1
-rw-r--r--Completion/User/_tar162
-rw-r--r--Completion/User/_tar_archive20
-rw-r--r--Config/version.mk4
-rw-r--r--Doc/Zsh/compctl.yo6
-rw-r--r--Doc/Zsh/compwid.yo6
-rw-r--r--Etc/FAQ.yo277
-rw-r--r--Src/Zle/comp.h11
-rw-r--r--Src/Zle/comp1.c4
-rw-r--r--Src/Zle/comp1.export1
-rw-r--r--Src/Zle/compctl.c14
-rw-r--r--Src/Zle/zle.h2
-rw-r--r--Src/Zle/zle_main.c15
-rw-r--r--Src/Zle/zle_misc.c7
-rw-r--r--Src/Zle/zle_tricky.c303
-rw-r--r--Src/glob.c25
-rw-r--r--Src/hist.c2
-rw-r--r--Src/init.c4
-rw-r--r--Src/input.c17
-rw-r--r--Src/options.c15
-rw-r--r--Src/signames2.awk2
-rw-r--r--Src/subst.c6
-rw-r--r--Src/zsh.h9
-rw-r--r--acconfig.h5
-rwxr-xr-xconfig.guess364
-rw-r--r--configure.in14
-rw-r--r--patchlist.txt103
65 files changed, 1931 insertions, 581 deletions
diff --git a/Completion/.distfiles b/Completion/.distfiles
new file mode 100644
index 000000000..c50107c61
--- /dev/null
+++ b/Completion/.distfiles
@@ -0,0 +1,3 @@
+DISTFILES_SRC='
+    .distfiles README
+'
diff --git a/Completion/Base/.distfiles b/Completion/Base/.distfiles
new file mode 100644
index 000000000..7e7635fa6
--- /dev/null
+++ b/Completion/Base/.distfiles
@@ -0,0 +1,6 @@
+DISTFILES_SRC='
+    .distfiles 
+    _brace_parameter _command_names _condition _default _equal
+    _long_options _match_pattern _match_pattern.orig _match_test _parameter
+    _precommand _redirect _subscript _tilde _vars 
+'
diff --git a/Completion/Base/_command_names b/Completion/Base/_command_names
index eab314dfa..f21af674c 100644
--- a/Completion/Base/_command_names
+++ b/Completion/Base/_command_names
@@ -1,7 +1,11 @@
 #defcomp -command-
 
-local nm=$compstate[nmatches]
+local nm=$compstate[nmatches] ret=1
 
-compgen -c
+compgen -c && ret=0
 
-[[ nm -eq compstate[nmatches] ]] && _path_files -/g "*(*)"
+if [[ nm -eq compstate[nmatches] ]]; then
+  _path_files -/g "*(*)"
+else
+  return ret
+fi
diff --git a/Completion/Base/_condition b/Completion/Base/_condition
index fb6b98b1b..db1adfd9a 100644
--- a/Completion/Base/_condition
+++ b/Completion/Base/_condition
@@ -7,6 +7,10 @@ if [[ "$prev" = -o ]]; then
 elif [[ "$prev" = -([no]t|ef) ]]; then
   _files
 else
-  _files
-  compgen -v
+  local ret=1
+
+  _files && ret=0
+  compgen -v && ret=0
+
+  return ret
 fi
diff --git a/Completion/Base/_default b/Completion/Base/_default
index 569bd6382..9ea1a09db 100644
--- a/Completion/Base/_default
+++ b/Completion/Base/_default
@@ -9,6 +9,6 @@
 # and insert the line `[[ compstate[nmatches] -eq 0 ]] || return' after
 # `compcall'.
 
-compcall || return
+compcall || return 0
 
 _files
diff --git a/Completion/Base/_long_options b/Completion/Base/_long_options
new file mode 100644
index 000000000..a5d92632c
--- /dev/null
+++ b/Completion/Base/_long_options
@@ -0,0 +1,309 @@
+#autoload
+
+# This function tries to automatically complete long option names. For 
+# this it invokes the command from the line with the `--help' option
+# and then parses the output to find possible option names. For
+# options that get an argument after a `=', the function also tries to 
+# automatically find out what should be complete as the argument.
+# The possible completions for option-arguments can be described with
+# the arguments to this function. This is done by giving pairs of
+# patterns and actions as consecutive arguments. The actions specify
+# what should be done to complete arguemts of those options that match 
+# the pattern. The action may be a list of words in brackets or in
+# parentheses, separated by spaces. A list in brackets denotes
+# possible values for an optional argument, a list in parentheses
+# gives words to complete for mandatory arguments. If the action does
+# not start with a bracket or parentheses, it should be the name of a
+# command (probably with arguments) that should be invoked to complete 
+# after the equal sign. E.g.:
+#
+#  _long_options '*\*'     '(yes no)' \
+#                '*=FILE*' '_files' \
+#                '*=DIR*'  '_files -/'
+#
+# This makes `yes' and `no' be completed as the argument of options
+# whose description ends in a star, file names for options that
+# contain the substring `=FILE' in the description, and paths for
+# options whose description contains `=DIR'. Note the last two
+# patterns are not needed since this function always completes files
+# for option descriptions containing `=FILE' and paths for option
+# descriptions that contain `=DIR' or `=PATH'. These builtin patterns
+# can be overridden by patterns given as arguments, though.
+#
+# This function also accepts the `-X', `-J', and `-V' options which
+# are given to `compadd'. Finally, it accepts the option `-t'. If this 
+# is given, completion is only done on words starting with two hyphens.
+
+local opt expl group test i name action ret=1 tmp suffix
+
+setopt extendedglob
+
+# Get the options.
+
+group=()
+expl=()
+if [[ $1 = -*~--* ]]; then
+  while getopts "J:V:X:t" opt; do
+    case "$opt" in
+      [JV]) group=("-$opt" "$OPTARG");;
+      X)    expl=(-X "$OPTARG");;
+      t)    test=yes;;
+    esac
+  done
+  shift OPTIND-1
+fi
+
+# Test if we are completing after `--' if we were asked to do so.
+
+[[ -n "$test" && "$PREFIX" != --* ]] && return 1
+
+# We cache the information about options and the command name, see if
+# we can use the cache.
+
+if [[ "$words[1]" = (.|..)/* ]]; then
+  tmp="$PWD/$words[1]"
+else
+  tmp="$words[1]"
+fi
+
+if [[ "$tmp" != $_lo_cache_cmd ]]; then
+
+  # No, store the new command name and clear the old parameters.
+
+  _lo_cache_cmd="$tmp"
+  (( $+_lo_cache_actions )) && unset "$_lo_cache_names[@]" _lo_cache_actions _lo_cache_names
+
+  local opts pattern anum=1 tmpo str
+
+  # Now get the long option names by calling the command with `--help'.
+  # The parameter expansion trickery first gets the lines as separate
+  # array elements. Then we select all lines whose first non-blank
+  # character is a hyphen. Since some commands document more than one
+  # option per line, separated by commas, we convert commas int
+  # newlines and then split the result again at newlines after joining 
+  # the old array elements with newlines between them. Then we select
+  # those elements that start with two hyphens, remove anything up to
+  # those hyphens and anything from the space or comma after the
+  # option up to the end. Finally all elements with option strings
+  # that contain uppercase letters are removed.
+
+  opts=("--${(@)^${(@)${(@)${(@M)${(@ps:\n:j:\n:)${(@)${(@M)${(@f)$("$words[1]" --help)}:#[ 	]#-*}//,/
+}}:#[ 	]#--*}#*--}%%[, ]*}:#(*-[A-Z]*|)}")
+
+  # The interpretation of the options is completely table driven. We
+  # use the positional parameters we were given and a few standard
+  # ones. Then we loop through this table.
+
+  set -- "$@" '*=FILE*' '_files' '*=(DIR|PATH)*' '_files -/' '*' ''
+
+  while [[ $# -gt 1 ]]; do
+
+    # First, we get the pattern and the action to use and take them
+    # from the positional parameters.
+
+    pattern="$1"
+    action="$2"
+    shift 2
+
+    # We get all options matching the pattern and take them from the
+    # list we have built. If no option matches the pattern, we
+    # continue with the next.
+
+    tmp=("${(@M)opts:##$~pattern}")
+    opts=("${(@)opts:##$~pattern}")
+
+    (( $#tmp )) || continue
+
+    # Now we collect the options for the pattern in an array. We also
+    # check if the options take an argument after a `=', and if this
+    # argument is optional. The name of the array built contains
+    # `_arg_' for mandatory arguments, `_optarg_' for optional
+    # arguments, and `_simple_' for options that don't get an
+    # argument. In `_lo_cache_names' we save the names of these
+    # arrays and in `_lo_cache_actions' the associated actions.
+
+    # If the action is a list of words in brackets, this denotes
+    # options that get an optional argument. If the action is a list
+    # of words in parentheses, the option has to get an argument.
+    # In both cases we just build the array name to use.
+
+    if [[ "$action[1]" = '[' ]]; then
+      name="_lo_cache_optarg_$anum"
+    elif [[ "$action[1]" = '(' ]]; then
+      name="_lo_cache_arg_$anum"
+    else
+
+      # If there are option strings with a `[=', we take make these
+      # get an optional argument...
+
+      tmpo=("${(@M)tmp:#*\[\=*}")
+      if (( $#tmpo )); then
+
+        # ...by removing them from the option list and storing them in 
+	# an array.
+
+        tmp=("${(@)tmp:#*\[\=*}")
+        tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
+        _lo_cache_names[anum]="_lo_cache_optarg_$anum"
+        _lo_cache_actions[anum]="$action"
+        eval "_lo_cache_optarg_${anum}=(\"\$tmpo[@]\")"
+	(( anum++ ))
+      fi
+
+      # Now we do the same for option strings containing `=', these
+      # are options getting an argument.
+
+      tmpo=("${(@M)tmp:#*\=*}")
+      if (( $#tmpo )); then
+        tmp=("${(@)tmp:#*\=*}")
+        tmpo=("${(@)${(@)tmpo%%\=*}//[^a-z0-9-]}")
+        _lo_cache_names[anum]="_lo_cache_arg_$anum"
+        _lo_cache_actions[anum]="$action"
+        eval "_lo_cache_arg_${anum}=(\"\$tmpo[@]\")"
+	(( anum++ ))
+      fi
+
+      # The name for the options without arguments, if any.
+
+      name="_lo_cache_simple_$anum"
+    fi
+    # Now filter out any option strings we don't like and stuff them
+    # in an array, if there are still some.
+
+    tmp=("${(@)${(@)tmp%%\=*}//[^a-z0-9-]}")
+    if (( $#tmp )); then
+      _lo_cache_names[anum]="$name"
+      _lo_cache_actions[anum]="$action"
+      eval "${name}=(\"\$tmp[@]\")"
+      (( anum++ ))
+    fi
+  done
+fi
+
+# We get the string from the line and and see if it already contains a 
+# equal sign.
+
+str="$PREFIX$SUFFIX"
+
+if [[ "$str" = *\=* ]]; then
+
+  # It contains a `=', now we ignore anything up to it, but first save 
+  # the old contents of the special parameters we change.
+
+  local oipre opre osuf pre parto parta pat patflags anum=1
+
+  oipre="$IPREFIX"
+  opre="$PREFIX"
+  osuf="$SUFFIX"
+
+  pre="${str%%\=*}"
+  IPREFIX="${IPREFIX}${pre}="
+  PREFIX="${str#*\=}"
+  SUFFIX=""
+
+  # We will check if the arrays contain an option matching what's on
+  # the line. To do this good, we build a pattern.
+
+  [[ -n "$_comp_correct" && $#pre -le _comp_correct ]] && return 1
+
+  pat="${pre}*"
+  patflags=''
+  _match_pattern _long_options pat patflags
+  [[ -n "$_comp_correct" ]] && patflags="$patflags(#a$_comp_correct)"
+
+  # Then we walk through the array names. For each array we test if it 
+  # contains the option string. If so, we `invoke' the action stored
+  # with the name. If the action is a list of words, we just add them, 
+  # otherwise we invoke the command or function named.
+
+  for name in "$_lo_cache_names[@]"; do
+    action="$_lo_cache_actions[anum]"
+    if (( ${(@)${(@P)name}[(I)$pre]} )); then
+      if [[ "$action[1]" = (\[|\() ]]; then
+        compadd - ${=action[2,-2]}
+      elif (( $#action )); then
+        $=action
+      fi
+
+      # We found the option string, return.
+
+      return
+    fi
+
+    # The array did not contain the full option string, see if it
+    # contains a string matching the string from the line.
+    # If there is one, we store the option string in `parto' and the
+    # element from `_lo_actions' in `parta'. If we find more than one
+    # such option or if we already had one, we set `parto' to `-'.
+
+    tmp=("${(@M)${(@P)name}:#${~pat}}")
+    if [[ $#tmp -eq 1 ]]; then
+      if [[ -z "$parto" ]]; then
+        parto="$tmp[1]"
+	parta="$action"
+      else
+        parto=-
+      fi
+    elif (( $#tmp )); then
+      parto=-
+    fi
+    (( anum++ ))
+  done
+
+  # If we found only one matching option, we accept it and immediatly
+  # try to complete the string after the `='.
+
+  if [[ -n "$parto" && "$parto" != - ]]; then
+    IPREFIX="${parto}="
+
+    if (( $#parta )); then
+      if [[ "$parta[1]" = (\[|\() ]]; then
+        compadd - ${=parta[2,-2]}
+      else
+        $=parta
+      fi
+    else
+      compadd -S '' - "$PREFIX"
+    fi
+    return
+  fi
+
+  # The option string was not found, restore the special parameters.
+
+  IPREFIX="$oipre"
+  PREFIX="$opre"
+  SUFFIX="$osuf"
+fi
+
+# The string on the line did not contain a `=', or we couldn't
+# complete the option string since there were more than one matching
+# what's on the line. So we just ad the option string as possible
+# matches, giving the string from the `=' on as a suffix.
+
+if [[ "$str" = *\=* ]]; then
+  str="=${str#*\=}"
+  PREFIX="${PREFIX%%\=*}"
+  suffix=()
+else
+  str=""
+  suffix=('-S=')
+fi
+
+anum=1
+for name in "$_lo_cache_names[@]"; do
+  action="$_lo_cache_actions[anum]"
+
+  if [[ "$name" = *_optarg_* ]]; then
+    compadd -M 'r:|-=* r:|=*' -Qq "$suffix[@]" -s "$str" - \
+            "${(@P)name}" && ret=0
+  elif [[ "$name" = *_arg_* ]]; then
+    compadd -M 'r:|-=* r:|=*' -Q "$suffix[@]" -s "$str" - \
+            "${(@P)name}" && ret=0
+  elif [[ -z "$str" ]]; then
+    compadd -M 'r:|-=* r:|=*' -Q - \
+            "${(@P)name}" && ret=0
+  fi
+  (( anum++ ))
+done
+
+return ret
diff --git a/Completion/Base/_match_pattern b/Completion/Base/_match_pattern
index 3df115d5b..91930a571 100644
--- a/Completion/Base/_match_pattern
+++ b/Completion/Base/_match_pattern
@@ -28,4 +28,10 @@
 # like the `r:|[.-]=* r:|=*'. To make this work, the function `_match_test'
 # would have to be changed to `(( compstate[matcher] <= 2 ))'
 #
+# When automatic correction is used (see the file `_main_complete'), you
+# probably don't want to set matching flags here as that may make the
+# results slightly unpredictable. For this, change the line above to:
+#
+#   [[ compstate[matcher] -lt 0 ]] && eval "${3}='(#l)'"
+#
 # The default implementation of this function is empty.
diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript
index d50fd8335..670739a9a 100644
--- a/Completion/Base/_subscript
+++ b/Completion/Base/_subscript
@@ -1,5 +1,10 @@
 #defcomp -subscript-
 
-_compalso -math-
+local ret=1
+
+_compalso -math- && ret=0
+
 [[ ${(Pt)${compstate[parameter]}} = assoc* ]] &&
-    compgen -k "( ${(kP)${compstate[parameter]}} )"
+  compgen -k "( ${(kP)${compstate[parameter]}} )" && ret=0
+
+return ret
diff --git a/Completion/Builtins/.distfiles b/Completion/Builtins/.distfiles
new file mode 100644
index 000000000..97906e91f
--- /dev/null
+++ b/Completion/Builtins/.distfiles
@@ -0,0 +1,7 @@
+DISTFILES_SRC='
+    .distfiles
+    _aliases _arrays _autoload _bg_jobs _bindkey _builtin _cd _command
+    _dirs _disable _echotc _enable _fc _functions _hash _jobs _kill
+    _limits _sched _set _setopt _source _trap _unhash _unsetopt _vars_eq
+    _wait _which _zftp _zle _zmodload 
+'
diff --git a/Completion/Builtins/_bindkey b/Completion/Builtins/_bindkey
index d3d019492..6fca200ba 100644
--- a/Completion/Builtins/_bindkey
+++ b/Completion/Builtins/_bindkey
@@ -1,7 +1,14 @@
 #defcomp bindkey
 
-if [[ "$words[2]" = -*[DAN]* || "$words[CURRENT-1] = -*M ]]; then
+# Normally, this completes names of zle widgets, whether the builtin ones
+# or ones defined by the user.  Note that a - allows a wildcard before it,
+# so h-b-s-b will complete to history-beginning-search-backward.  You
+# can alter this by removing the -M ... from the second compgen.
+#
+# Where appropriate, will complete keymaps instead of widgets.
+
+if [[ "$words[2]" = -*[DAN]* || "$words[CURRENT-1]" = -*M ]]; then
   compgen -s '$(bindkey -l)'
 else
-  compgen -b
+  compgen -b -M 'r:|-=* r:|=*'
 fi
diff --git a/Completion/Builtins/_cd b/Completion/Builtins/_cd
index 65ce7f293..9a58effe0 100644
--- a/Completion/Builtins/_cd
+++ b/Completion/Builtins/_cd
@@ -24,7 +24,7 @@ if [[ -position 3 ]]; then
   rep=(${~PWD/$words[2]/*}~$PWD(-/N))
   # Now remove all the common parts of $PWD and the completions from this
   rep=(${${rep#${PWD%%$words[2]*}}%${PWD#*$words[2]}})
-  (( $#rep )) && compadd $rep
+  (( ! $#rep )) || compadd $rep
 elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then
   # pushd: just complete the numbers, but show the full directory list with
   # numbers.
@@ -34,7 +34,8 @@ elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then
   # lazy to type pushd.
   IPREFIX=$PREFIX[1]
   PREFIX=$PREFIX[2,-1]
-  local list lines
+  local list lines ret=1
+
   # get the list of directories with their canonical number
   lines="$(dirs -v)"
   # turn the lines into an array, removing the current directory
@@ -52,9 +53,11 @@ elif [[ $words[1] = pu* && $PREFIX = [-+]* ]]; then
   lines="${(F)list}"
   # get the array of numbers only
   list=(${list%%[ 	]*})
-  compgen -y '$lines' -Q -k list
-  [[ -z $compstate[list] ]] && compstate[list]=list
-  [[ -n $compstate[insert] ]] && compstat[insert]=menu
+  compgen -y '$lines' -Q -k list && ret=0
+  [[ -z $compstate[list] ]] && compstate[list]=list && ret=0
+  [[ -n $compstate[insert] ]] && compstat[insert]=menu && ret=0
+
+  return ret
 elif [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then
   _path_files -W cdpath -/
 else
diff --git a/Completion/Builtins/_disable b/Completion/Builtins/_disable
index e3edafe2b..27db5c18f 100644
--- a/Completion/Builtins/_disable
+++ b/Completion/Builtins/_disable
@@ -1,8 +1,10 @@
 #defcomp disable
 
-local prev="$words[CURRENT-1]"
+local prev="$words[CURRENT-1]" ret=1
 
-[[ "$prev" = -*a* ]] && compgen -ea
-[[ "$prev" = -*f* ]] && compgen -eF
-[[ "$prev" = -*r* ]] && compgen -ew
-[[ "$prev" != -* ]] && compgen -eB
+[[ "$prev" = -*a* ]] && compgen -ea && ret=0
+[[ "$prev" = -*f* ]] && compgen -eF && ret=0
+[[ "$prev" = -*r* ]] && compgen -ew && ret=0
+[[ "$prev" != -* ]]  && compgen -eB && ret=0
+
+return ret
diff --git a/Completion/Builtins/_enable b/Completion/Builtins/_enable
index 111d1ae26..1baa09ed6 100644
--- a/Completion/Builtins/_enable
+++ b/Completion/Builtins/_enable
@@ -1,8 +1,10 @@
 #defcomp enable
 
-local prev="$words[CURRENT-1]"
+local prev="$words[CURRENT-1]" ret=1
 
-[[ "$prev" = -*a* ]] && compgen -da
-[[ "$prev" = -*f* ]] && compgen -dF
-[[ "$prev" = -*r* ]] && compgen -dw
-[[ "$prev" != -* ]] && compgen -dB
+[[ "$prev" = -*a* ]] && compgen -da && ret=0
+[[ "$prev" = -*f* ]] && compgen -dF && ret=0
+[[ "$prev" = -*r* ]] && compgen -dw && ret=0
+[[ "$prev" != -* ]]  && compgen -dB && ret=0
+
+return ret
diff --git a/Completion/Builtins/_kill b/Completion/Builtins/_kill
index c1afa78cb..36a23ccb2 100644
--- a/Completion/Builtins/_kill
+++ b/Completion/Builtins/_kill
@@ -5,7 +5,11 @@ local list
 if [[ -iprefix '-' ]]; then
   compgen -k "($signals[1,-3])"
 else
-  compgen -P '%' -j
+  local ret=1
+
+  compgen -P '%' -j && ret=0
   list=("$(ps 2>/dev/null)")
-  compgen -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`'
+  compgen -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' && ret=0
+
+  return ret
 fi
diff --git a/Completion/Builtins/_setopt b/Completion/Builtins/_setopt
index 98800152f..b458cb2b0 100644
--- a/Completion/Builtins/_setopt
+++ b/Completion/Builtins/_setopt
@@ -1,8 +1,11 @@
 #defcomp setopt
 
-local nm=$compstate[nmatches]
+local nm=$compstate[nmatches] ret=1
 
 compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-         -s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)'
+         -s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)' && ret=0
+
 [[ compstate[nmatches] -eq nm ]] &&
-    compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
+    compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o && ret=0
+
+return ret
diff --git a/Completion/Builtins/_unhash b/Completion/Builtins/_unhash
index 63d61c991..a9050cb49 100644
--- a/Completion/Builtins/_unhash
+++ b/Completion/Builtins/_unhash
@@ -1,8 +1,10 @@
 #defcomp unhash
 
-local fl="$words[2]"
+local fl="$words[2]" ret=1
 
-[[ "$fl" = -*d* ]] && compgen -n
-[[ "$fl" = -*a* ]] && compgen -a
-[[ "$fl" = -*f* ]] && compgen -F
-[[ "$fl" != -* ]] && compgen -m
+[[ "$fl" = -*d* ]] && compgen -n && ret=0
+[[ "$fl" = -*a* ]] && compgen -a && ret=0
+[[ "$fl" = -*f* ]] && compgen -F && ret=0
+[[ "$fl" != -* ]]  && compgen -m && ret=0
+
+return ret
diff --git a/Completion/Builtins/_unsetopt b/Completion/Builtins/_unsetopt
index a5c85b1ef..1194e28a7 100644
--- a/Completion/Builtins/_unsetopt
+++ b/Completion/Builtins/_unsetopt
@@ -1,8 +1,11 @@
 #defcomp unsetopt
 
-local nm=$compstate[nmatches]
+local nm=$compstate[nmatches] ret=1
 
 compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
-         -s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)'
+         -s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)' && ret=0
+
 [[ compstate[nmatches] -eq nm ]] &&
-    compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
+    compgen -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o && ret=0
+
+return ret
diff --git a/Completion/Builtins/_wait b/Completion/Builtins/_wait
index 6e3a4c3c9..9281a5cc2 100644
--- a/Completion/Builtins/_wait
+++ b/Completion/Builtins/_wait
@@ -1,7 +1,9 @@
 #defcomp wait
 
-local list
+local list ret=1
 
-compgen -P '%' -j
+compgen -P '%' -j && ret=0
 list=("$(ps 2>/dev/null)")
-compgen -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`'
+compgen -y '$list' -s '`ps 2>/dev/null | tail +2 | cut -c1-5`' && ret=0
+
+return ret
diff --git a/Completion/Builtins/_zftp b/Completion/Builtins/_zftp
index e93021acf..178d9d9e3 100644
--- a/Completion/Builtins/_zftp
+++ b/Completion/Builtins/_zftp
@@ -45,6 +45,7 @@ case $subcom in
 
   *)
   # dunno... try ordinary completion after all.
-  unset _compskip   
+  unset _compskip
+  return 1
   ;;
 esac
diff --git a/Completion/Commands/.distfiles b/Completion/Commands/.distfiles
new file mode 100644
index 000000000..f79d69704
--- /dev/null
+++ b/Completion/Commands/.distfiles
@@ -0,0 +1,3 @@
+DISTFILES_SRC='
+    .distfiles _correct_filename _most_recent_file 
+'
diff --git a/Completion/Core/.distfiles b/Completion/Core/.distfiles
new file mode 100644
index 000000000..ddf2a707e
--- /dev/null
+++ b/Completion/Core/.distfiles
@@ -0,0 +1,5 @@
+DISTFILES_SRC='
+    .distfiles
+    _compalso _files _main_complete _multi_parts _normal _path_files
+    _sep_parts compdump compinit
+'
diff --git a/Completion/Core/_compalso b/Completion/Core/_compalso
index 6ff6cf0bf..52fb08f05 100644
--- a/Completion/Core/_compalso
+++ b/Completion/Core/_compalso
@@ -7,7 +7,9 @@
 # `_compalso -math-' to get the completions that would be generated for a
 # mathematical context.
 
-local tmp
+local tmp ret=1
 
 tmp="$_comps[$1]"
-[[ -z "$tmp" ]] || "$tmp"
+[[ -z "$tmp" ]] || "$tmp" && ret=0
+
+return ret
diff --git a/Completion/Core/_files b/Completion/Core/_files
index 471824bfe..506ddbc8e 100644
--- a/Completion/Core/_files
+++ b/Completion/Core/_files
@@ -3,10 +3,9 @@
 # Utility function for completing files of a given type or any file.
 # In many cases you will want to call this one instead of _path_files().
 
-local nm=$compstate[nmatches] ret
+local nm=$compstate[nmatches] ret=1
 
-_path_files "$@"
-ret=$?
+_path_files "$@" && ret=0
 
 if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then
   local opt opts
@@ -23,7 +22,7 @@ if [[ $# -ne 0 && compstate[nmatches] -eq nm ]]; then
     [[ "$opt" = [PSWFJVX] ]] && opts=("$opts[@]" "-$opt" "$OPTARG")
   done
 
-  _path_files "$opts[@]"
-else
-  return $ret
+  _path_files "$opts[@]" && ret=0
 fi
+
+return ret
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index 34c5a3d3c..3571b712c 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -3,36 +3,47 @@
 # The main loop of the completion code. This is what is called when 
 # completion is attempted from the command line.
 #
-# This code will automatically try to correct the string on the
-# line based on the strings generated for the context if the
-# parameter `COMPCORRECT' is set and normal completion didn't yield
-# any matches. These corrected strings will be shown in a list and
-# one can cycle through them as in a menucompletion. To use this 
-# feature, `COMPCORRECT' should be set to a number, specifying the
+# This code will automatically try to correct the string on the line
+# based on the strings generated for the context if
+# `compconfig[correct]' is set and normal completion didn't yield any
+# matches. These corrected strings will be shown in a list and one can
+#cycle through them as in a menucompletion. To use this feature,
+#`compconfig[correct]' should be set to a number, specifying the 
 # maximum number of errors that should be accepted. If the string also
 # contains a `n' or `N', the code will use the numeric argument as the
 # maximum number of errors if a numeric argument was given. If no
 # numeric argument was given, the number from the value of
-# `COMPCORRECT' will be used. E.g. with `COMPCORRECT=2n' two errors
-# will be accepted, but if the user gives another number with the
-# numeric argument, this will be prefered. Also, with `COMPCORRECT=0n',
-# normally no automatic correction will be tried, but if a numeric
-# argument is given, automatic correction will be used. Once the
-# number of errors to accept is determined, the code will repeatedly
-# try to generate matches by allowing one error, two errors, and so
-# on.
-# If the parameter `CCORIG' is set (independent of the value), the
-# line will first be left unchanged and consecutive TABs cycle through 
-# the list.
-# When using automatic correction, one can also set the parameter
-# `CCPROMPT' to a string that will be shown when multiple
-# correction results are displayed and the code starts cycling
-# through them (this string is used with the `-X' option and thus may
-# contain the control sequences `%n', `%B',...).
-
-local comp name _comp_correct comax
-
-setopt localoptions nullglob rcexpandparam globdots
+# `compconfig[correct]' will be used. E.g. with `compconfig[correct]=2n'
+# two errors will be accepted, but if the user gives another number
+# with the numeric argument, this will be prefered. Also, with
+# `compconfig[correct]=0n',normally no automatic correction will be
+# tried, but if a numeric argument is given, automatic correction will
+# be used. Once the number of errors to accept is determined, the code
+# will repeatedly try to generate matches by allowing one error, two
+# errors, and so on. Independent of the number of errors the user
+# wants to accept, the code will allow only fewer errors than there
+# are characters in the string from the line.
+# The value of `compconfig[correct_orig]' is used to determine if the
+# original string should be included in the list (and thus be
+# presented to the user when cycling through the corrections). If it
+# is set to any non-empty value, the original string will be
+# offered. If it contains the sub-string `last', the original string
+# will apear as the last string when cycling through the corrections,
+# otherwise it will appear as the first one (so that the command line
+# does not change immediatly). Also, if the value of
+# `compconfig[correct_orig]' contains the sub-string `always', the
+# original string will always be included, whereas normally it is
+# included only if more than one possible correction was generated.
+# Finally, `compconfig[correct_prompt]' may be set to a string that
+# should be printed before the list of corrected strings when cycling
+# through them. This string may contain the control sequences `%n',
+# `%B', etc. known from the `-X' option of `compctl'. Also, the
+# sequence `%e' will be replaced by the number of errors accepted to
+# generate the corrected strings.
+
+local comp name _comp_correct _correct_prompt comax
+
+setopt localoptions nullglob rcexpandparam
 unsetopt markdirs globsubst shwordsplit nounset ksharrays
 
 # Special completion contexts after `~' and `='.
@@ -91,25 +102,30 @@ while true; do
 
   # Use automatic correction?
 
-  if (( $+COMPCORRECT )); then
+  if (( $+compconfig[correct] )); then
 
     # Do we have matches?
     if (( compstate[nmatches] )); then
 
       # Yes, were they added using correction? (More than one match?)
 
-      if [[ -n "$_comp_correct" && compstate[nmatches] -gt 1 ]]; then
+      if [[ -n "$_comp_correct" &&
+            ( "$compconfig[correct_orig]" = *always* ||
+	      compstate[nmatches] -gt 1 ) ]]; then
 
-        # If we got more than one string from correction, we add the 
-	# original string as a possible match, let it not be shown in
-	# the list, and probably display the `CCPROMPT'.
-
-        (( $+CCORIG )) && builtin compadd -nQ - "$PREFIX$SUFFIX"
+        if [[ "$compconfig[correct_orig]" = *last* ]]; then
+	  builtin compadd -V _correct_orig -nQ - "$PREFIX$SUFFIX"
+        elif [[ -n "$compconfig[correct_orig]" ]]; then
+	  builtin compadd -nQ - "$PREFIX$SUFFIX"
+	fi
 
 	# If you always want to see the list of possible corrections,
 	# set `compstate[list]=list' here.
+
+	compstate[force_list]=list
       fi
       # Since we have matches, we don't want to try again.
+
       break
     fi
 
@@ -117,25 +133,33 @@ while true; do
 
     if [[ -n "$_comp_correct" ]]; then
 
-      # Yes, give up if we reached the maximum number of tries,
-      # otherwise increment our counter.
+      # Yes, give up if we reached the maximum number of tries or the
+      # string from the line is too short, otherwise increment our 
+      # counter.
 
-      [[ _comp_correct -eq comax ]] && break
+      [[ _comp_correct -eq comax ||
+         "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct+1 ]] && break
       (( _comp_correct++ ))
 
+      _correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}"
+
     elif [[ compstate[matcher] -eq compstate[total_matchers] ]]; then
 
+      # We don't try correction if the string is too short.
+
+      [[ "${#${:-$PREFIX$SUFFIX}}" -le 1 ]] && return
+
       # No matches and no correction tried yet, but we just tried the
       # last global match specification, so let's see if we should use
       # correction now. First, get the maximum number of errors.
 
-      if [[ "$COMPCORRECT" = *[nN]* && NUMERIC -ne 1 ]]; then
+      if [[ "$compconfig[correct]" = *[nN]* && NUMERIC -ne 1 ]]; then
         # Prefer the numeric argument if that has a sensible value.
         comax="$NUMERIC"
       else
-        comax="${COMPCORRECT//[^0-9]}"
+        comax="${compconfig[correct]//[^0-9]}"
       fi
-      # If the number of errors to accept is to small, give up.
+      # If the number of errors to accept is too small, give up.
 
       [[ "$comax" -lt 1 ]] && break
 
@@ -145,25 +169,31 @@ while true; do
       # ignored prefix).
 
       compadd() {
+        [[ "$*" != *-([a-zA-Z/]#|)U* &&
+           "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct ]] && return
+
         if [[ "$PREFIX" = \~*/* ]]; then
 	  PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
 	else
           PREFIX="(#a${_comp_correct})$PREFIX"
 	fi
-	if (( $+CCPROMPT )); then
-	  builtin compadd -X "$CCPROMPT" -J _correct "$@"
+	if [[ -n "$_correct_prompt" ]]; then
+	  builtin compadd -X "$_correct_prompt" -J _correct "$@"
 	else
 	  builtin compadd -J _correct "$@"
 	fi
       }
       compgen() {
+        [[ "$*" != *-([a-zA-Z/]#|)U* &&
+           "${#${:-$PREFIX$SUFFIX}}" -le _comp_correct ]] && return
+
         if [[ "$PREFIX" = \~*/* ]]; then
 	  PREFIX="${PREFIX%%/*}/(#a${_comp_correct})${PREFIX#*/}"
 	else
           PREFIX="(#a${_comp_correct})$PREFIX"
 	fi
-	if (( $+CCPROMPT )); then
-	  builtin compgen "$@" -X "$CCPROMPT" -J _correct
+	if [[ -n "$_correct_prompt" ]]; then
+	  builtin compgen "$@" -X "$_correct_prompt" -J _correct
 	else
 	  builtin compgen "$@" -J _correct
 	fi
@@ -179,6 +209,8 @@ while true; do
       _comp_correct=1
       compstate[matcher]=-1
 
+      _correct_prompt="${compconfig[correct_prompt]//\%e/$_comp_correct}"
+
       # We also need to set `extendedglob' and to make the completion
       # code behave as if globcomplete were set.
 
diff --git a/Completion/Core/_normal b/Completion/Core/_normal
index f56849194..98337eae5 100644
--- a/Completion/Core/_normal
+++ b/Completion/Core/_normal
@@ -1,6 +1,6 @@
 #autoload
 
-local comp command cmd1 cmd2 pat val name i ret
+local comp command cmd1 cmd2 pat val name i ret=1
 
 # Completing in command position? If not we set up `cmd1' and `cmd2' as
 # two strings we have search in the completion definition arrays (e.g.
@@ -9,8 +9,9 @@ local comp command cmd1 cmd2 pat val name i ret
 command="$words[1]"
 if [[ CURRENT -eq 1 ]]; then
   comp="$_comps[-command-]"
-  [[ -z "$comp" ]] || "$comp"
-  return
+  [[ -z "$comp" ]] || "$comp" && ret=0
+
+  return ret
 elif [[ "$command[1]" == '=' ]]; then
   eval cmd1\=$command
   cmd2="$command[2,-1]"
@@ -28,11 +29,10 @@ for i in "$_patcomps[@]"; do
   pat="${i% *}"
   val="${i#* }"
   if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]]; then
-    "$val"
-    ret=$?
+    "$val" && ret=0
     if (( $+_compskip )); then
       unset _compskip
-      return $ret
+      return ret
     fi
   fi
 done
@@ -53,4 +53,6 @@ if [[ -z "$comp" ]]; then
   name=-default-
   comp="$_comps[-default-]"
 fi
-[[ -z "$comp" ]] || "$comp"
+[[ -z "$comp" ]] || "$comp" && ret=0
+
+return ret
diff --git a/Completion/Core/_path_files b/Completion/Core/_path_files
index 3c03c0c61..535ba537c 100644
--- a/Completion/Core/_path_files
+++ b/Completion/Core/_path_files
@@ -2,13 +2,15 @@
 
 # Utility function for in-path completion.
 # Supported arguments are: `-f', `-/', `-g <patterns>', `-J <group>',
-# `-V <group>', `-W paths', `-X explanation', and `-F <ignore>'. All but 
-# the last have the same syntax and meaning as for `compgen'. The
-# `-F <ignore>' option may be used to give a list of suffixes either by
-# giving the name of an array or literally by giving them in a string
-# surrounded by parentheses. Files with one of the suffixes thus given
-# are treated like files with one of the suffixes in the `fignore' array
-# in normal completion.
+# `-V <group>', `-W paths', `-X explanation', `-P prefix', `-S suffix',
+# `-q', `-r remove-chars', `-R remove-func', and `-F <ignore>'. All but 
+# the last have the same syntax and meaning as for `compgen' or
+# `compadd', respectively. The `-F <ignore>' option may be used to give
+# a list of suffixes either by giving the name of an array or
+# literally by giving them in a string surrounded by
+# parentheses. Files with one of the suffixes thus given are treated
+# like files with one of the suffixes in the `fignore' array in normal
+# completion.
 #
 # This function uses the helper functions `_match_test' and `_match_pattern'.
 
@@ -20,9 +22,10 @@ _match_test _path_files || return 1
 
 local nm prepaths str linepath realpath donepath patstr prepath testpath rest
 local tmp1 collect tmp2 suffixes i ignore matchflags opt group sopt pats gopt
-local addpfx addsfx expl orig ostr nm=$compstate[nmatches]
+local addpfx addsfx expl orig ostr nm=$compstate[nmatches] menu remsfx patlast
+local origflags mflags
 
-setopt localoptions nullglob rcexpandparam globdots extendedglob
+setopt localoptions nullglob rcexpandparam extendedglob
 unsetopt markdirs globsubst shwordsplit nounset
 
 prepaths=('')
@@ -33,16 +36,21 @@ gopt=''
 pats=()
 addpfx=()
 addsfx=()
+remsfx=()
 expl=()
 
 # Get the options.
 
-while getopts "P:S:W:F:J:V:X:f/g:" opt; do
+while getopts "P:S:qr:R:W:F:J:V:X:f/g:" opt; do
   case "$opt" in
   P)     addpfx=(-P "$OPTARG")
          ;;
   S)     addsfx=(-S "$OPTARG")
          ;;
+  q)     tmp1=yes
+         ;;
+  [rR])  remsfx=("-$opt" "$OPTARG")
+         ;;
   W)     tmp1="$OPTARG"
          if [[ "$tmp1[1]" = '(' ]]; then
            prepaths=( ${^=tmp1[2,-2]}/ )
@@ -76,6 +84,8 @@ while getopts "P:S:W:F:J:V:X:f/g:" opt; do
   esac
 done
 
+[[ -n "$tmp1" && $#addsfx -ne 0 ]] && addsfx[1]=-qS
+
 # If we were given no file selection option, we behave as if we were given
 # a `-f'.
 
@@ -89,19 +99,25 @@ if [[ "$sopt" = - ]]; then
 fi
 
 # str holds the whole string from the command line with a `*' between
-# the prefix and the suffix.
+# the prefix and the suffix. Then we see if we will do menucompletion.
 
-if [[ -o globcomplete ]]; then
+if [[ $#compstate[pattern_match] -ne 0 ]]; then
   str="${PREFIX}*${SUFFIX}"
 else
   str="${PREFIX:q}*${SUFFIX:q}"
+  [[ "$str" = \\\~* ]] && str="$str[2,-1]"
 fi
 orig="${PREFIX}${SUFFIX}"
 
+[[ $compstate[insert] = *menu || -n "$_comp_correct" ||
+   ( $#compstate[pattern_match] -ne 0 &&
+     "$orig" != "${orig:q}" ) ]] && menu=yes
+
+
 # We will first try normal completion called with `compgen', but only if we
-# weren't given a `-F' option.
+# weren't given a `-F', `-r', or `-R' option.
 
-if (( ! $#ignore )); then
+if [[ $#ignore -eq 0 && $#remsfx -eq 0 && -z "$_comp_correct" ]]; then
   # First build an array containing the `-W' option, if there is any and we
   # want to use it. We don't want to use it if the string from the command line
   # is a absolute path or relative to the current directory.
@@ -124,11 +140,11 @@ if (( ! $#ignore )); then
   # If this generated any matches, we don't want to do in-path completion.
 
   [[ compstate[nmatches] -eq nm ]] || return 0
+fi
 
-  # No `-F' option, so we want to use `fignore'.
+# No `-F' option, so we want to use `fignore'.
 
-  ignore=(-F fignore)
-fi
+(( $#ignore )) || ignore=(-F fignore)
 
 # Now let's have a closer look at the string to complete.
 
@@ -176,6 +192,7 @@ fi
 patstr="$str"
 matchflags=""
 _match_pattern _path_files patstr matchflags
+origflags="$matchflags"
 [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
 
 # We almost expect the pattern to have changed `..' into `*.*.', `/.' into
@@ -185,13 +202,40 @@ _match_pattern _path_files patstr matchflags
 
 patstr="$patstr:gs-/-*/-:gs/*.*./../:gs-/*.-/.-:gs/**/*/:gs-.*/-./-"
 
+# We take the last pathname component from the pattern and store it in
+# `patlast', replacing `*'s in it with patterns that match any character
+# but not slashes. Later we will generate matches using `patstr' with the
+# patterns we were given (like `*.c') appended to it, producing all matching
+# files. These filenames are then compared to `patlast' and all names not
+# matching that will be removed. All this is needed to be able to correctly
+# support `completeinword' as otherwise we would have something like `a*x'
+# from the line (the `*' was inserted above) and appending the `-g' pattern
+# `*.tex' would yield `a*x*.tex' which is not what we want.
+
+if [[ "$patstr" = */* ]]; then
+  if [[ -n "$_comp_correct" && "${#orig##*/}" -le _comp_correct ]]; then
+    patlast="*/${origflags}${${patstr##*/}//\*/[^/]#}"
+  else
+    patlast="*/${matchflags}${${patstr##*/}//\*/[^/]#}"
+  fi
+  patstr="${patstr%/*}/"
+else
+  if [[ -n "$_comp_correct" && "$#orig" -le _comp_correct ]]; then
+    patlast="${origflags}${patstr//\*/[^/]#}"
+  else
+    patlast="${matchflags}${patstr//\*/[^/]#}"
+  fi
+  patstr=""
+fi
+
 # First we skip over all pathname components in `str' which really exist in
 # the file-system, so that `/usr/lib/l<TAB>' doesn't offer you `lib' and
 # `lib5'. Pathname components skipped this way are taken from `orig' and added
 # to `donepath'.
 
 while [[ "$orig" = */* ]] do
-  tmp1=( ${~matchflags}$realpath$donepath${orig%%/*}/${~patstr#*/}$^pats )
+  tmp1=( $realpath$donepath${orig%%/*}/${~matchflags}${~patstr#*/}$^pats )
+  tmp1=("${(@M)tmp1:#$~patlast}")
   [[ $#tmp1 -gt 0 && -e "$realpath$donepath${orig%%/*}" ]] || break
   donepath="$donepath${orig%%/*}/"
   orig="${orig#*/}"
@@ -217,8 +261,13 @@ for prepath in "$prepaths[@]"; do
     # we get the globbing matches for the pathname component currently
     # handled.
 
+    if [[ -n "$_comp_correct" && "${#ostr%%/*}" -le _comp_correct ]]; then
+      mflags="$origflags"
+    else
+      mflags="$matchflags"
+    fi
     rest="${str#*/}"
-    tmp1="${prepath}${realpath}${testpath}${~matchflags}${str%%/*}(-/)"
+    tmp1="${prepath}${realpath}${testpath}${~mflags}${str%%/*}(-/)"
     tmp1=( $~tmp1 )
 
     if [[ $#tmp1 -eq 0 ]]; then
@@ -240,12 +289,19 @@ for prepath in "$prepaths[@]"; do
       suffixes=( $rest$^pats )
       suffixes=( "${(@)suffixes:gs.**.*.}" )
 
+      if [[ -n "$_comp_correct" && "${#ostr#*/}" -le _comp_correct ]]; then
+        mflags="$origflags"
+      else
+        mflags="$matchflags"
+      fi
+
       # In the loop the prefixes from the `tmp1' array produced above and
       # the suffixes we just built are used to produce possible matches
       # via globbing.
 
       for i in "$tmp1[@]" ; do
-        tmp2=( ${~i}/${~matchflags}${~suffixes} )
+        tmp2=( ${~i}/${~mflags}${~suffixes} )
+        tmp2=("${(@M)tmp2:#$~patlast}")
         [[ $#tmp2 -ne 0 ]] && collect=( $collect $i )
       done
 
@@ -255,9 +311,6 @@ for prepath in "$prepaths[@]"; do
       # next `-W' path.
 
       if [[ $#collect -eq 0 ]]; then
-        compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
-                -i "$IPREFIX" -p "${linepath:q}${testpath:q}" -S "/${ostr#*/}" \
-		-W "$tmp1" -f "$ignore[@]" - "${(@)tmp1:q}"
         continue 2
       elif [[ $#collect -ne 1 ]]; then
         # If we have more than one possible match, this means that the
@@ -270,6 +323,7 @@ for prepath in "$prepaths[@]"; do
 	# Now produce all matching pathnames in `collect'.
 
         collect=( ${~collect}/${~matchflags}${~suffixes} )
+	collect=("${(@M)collect:#$~patlast}")
 
 	# And then remove the common path prefix from all these matches.
 
@@ -282,15 +336,16 @@ for prepath in "$prepaths[@]"; do
 	# these are file names and that `fignore' should be used as usual
 	# (the `-f' and `-F' options).
 
-	if [[ $compstate[insert] = *menu ]]; then
+	if [[ -n "$menu" ]]; then
           compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
-                  -i "$IPREFIX" -p "${linepath:q}${testpath:q}" -S "/${ostr#*/}" \
+                  -i "$IPREFIX" -p "$linepath${testpath:q}" \
+		  -s "/${ostr#*/}" \
 		  -W "$tmp1" -f "$ignore[@]" - "${(@)${(@)collect%%/*}:q}"
 	else
           for i in $collect; do
-            compadd -U "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
-	            -i "$IPREFIX" -p "$linepath$testpath" -s "/${i#*/}" \
-		    -M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${i%%/*}"
+            compadd -QU "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
+	            -i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
+		    -M 'r:|/=*' -W "$tmp1" -f "$ignore[@]" - "${${i%%/*}:q}"
           done
 	fi
 
@@ -299,12 +354,27 @@ for prepath in "$prepaths[@]"; do
 
 	continue 2
       fi
+
       # We reach this point if only one of the path prefixes in `tmp1'
       # has a existing path-suffix matching the string from the line.
       # In this case we accept this match and continue with the next
       # path-name component.
 
       tmp1=( "$collect[1]" )
+    elif [[ -n "$_comp_correct" && "$mflags" = "$matchflags" ]]; then
+
+      # If we got only one match with auto-correction and if we get none
+      # without correction, stop now.
+
+      tmp2="${prepath}${realpath}${testpath}${~origflags}${str%%/*}(-/)"
+      tmp2=( $~tmp2 )
+
+      if [[ $#tmp1 -ne $#tmp2 ]]; then
+        compadd -QU "$addpfx[@]" -S '' "$group[@]" "$expl[@]" \
+                -i "$IPREFIX" -p "$linepath${testpath:q}" -s "/${ostr#*/}" \
+		- "${${tmp1#${prepath}${realpath}${testpath}}:q}"
+        continue 2
+      fi
     fi
     # This is also reached if the first globbing produced only one match
     # in this case we just continue with the next pathname component, too.
@@ -320,10 +390,17 @@ for prepath in "$prepaths[@]"; do
   # no path suffix, the `-W' we are currently handling, all the matches we
   # can produce in this directory, if any.
 
+  if [[ -n "$_comp_correct" && "${#ostr#*/}" -le _comp_correct ]]; then
+    mflags="$origflags"
+  else
+    mflags="$matchflags"
+  fi
   tmp1="$prepath$realpath$testpath"
   suffixes=( $str$^pats )
   suffixes=( "${(@)suffixes:gs.**.*.}" )
   tmp2=( ${~tmp1}${~matchflags}${~suffixes} )
+  tmp2=("${(@M)tmp2:#$~patlast}")
+
   if [[ $#tmp2 -eq 0 ]]; then
     # No match, insert the expanded path and add the original tail.
 
@@ -334,11 +411,11 @@ for prepath in "$prepaths[@]"; do
     [[ "$linepath$testpath$ostr" = "$PREFIX$SUFFIX" ]] && return 1
 
     compadd -QU -S '' "$group[@]" "$expl[@]" \
-            -i "$IPREFIX" -f - "${linepath:q}${testpath:q}$ostr"
+            -i "$IPREFIX" -f - "$linepath${testpath:q}$ostr"
   else
-    compadd -U "$addpfx[@]" "$addsfx[@]" "$group[@]" "$expl[@]" \
-            -i "$IPREFIX" -p "$linepath$testpath" -f "$ignore[@]" \
-	    -W "$prepath$realpath$testpath" - "${(@)tmp2#$tmp1}"
+    compadd -QU "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" "$group[@]" "$expl[@]" \
+            -i "$IPREFIX" -p "$linepath${testpath:q}" -f "$ignore[@]" \
+	    -W "$prepath$realpath$testpath" - "${(@)${(@)tmp2#$tmp1}:q}"
   fi
 done
 
diff --git a/Completion/Core/_sep_parts b/Completion/Core/_sep_parts
new file mode 100644
index 000000000..c1cda2b9a
--- /dev/null
+++ b/Completion/Core/_sep_parts
@@ -0,0 +1,171 @@
+#autoload
+
+# This function can be used to separately complete parts of strings
+# where each part may be one of a set of matches and different parts
+# have different sets.
+# Arguments are alternatingly arrays and separator strings. Arrays may
+# be given by name or literally as words separated by white space in
+# parentheses, e.g.:
+#
+#  _sep_parts '(foo bar)' @ hosts
+#
+# This will make this function complete the strings in the array
+# `friends'. If the string on the line contains a `@', the substring
+# after it will be completed from the array `hosts'. Of course more
+# arrays may be given, each preceded by another separator string.
+#
+# This function understands the `-J group', `-V group', and
+# `-X explanation' options.
+#
+# This function does part of the matching itself and calls the functions
+# `_match_test' and `_match_pattern' for this.
+
+local str arr sep test testarr tmparr prefix suffixes matchers autosuffix
+local matchflags opt group expl nm=$compstate[nmatches]
+
+# Test if we should use this function for the global matcher in use.
+
+_match_test _sep_parts || return 1
+
+# Get the options.
+
+group=()
+expl=()
+while getopts "J:V:X:" opt; do
+  case "$opt" in
+  [JV]) group=("-$opt" "$OPTARG");;
+  X)    expl=(-X "$OPTARG");;
+  esac
+done
+shift OPTIND-1
+
+# Get the string from the line.
+
+str="$PREFIX$SUFFIX"
+[[ $#compstate[pattern_match] -ne 0 ]] || str="$str:q"
+prefix=""
+
+# Walk through the arguments to find the longest unambiguous prefix.
+
+while [[ $# -gt 1 ]]; do
+  # Get the next array and separator.
+  arr="$1"
+  sep="$2"
+
+  if [[ "$arr[1]" == '(' ]]; then
+    tmparr=( ${=arr[2,-2]} )
+    arr=tmparr
+  fi
+  # Is the separator on the line?
+  [[ "$str" != *${sep}* ]] && break
+
+  # Build a pattern matching the possible matches and get all these
+  # matches in an array.
+
+  test="${str%%${sep}*}"
+  [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
+
+  matchflags=""
+  _match_pattern _sep_parts test matchflags
+  [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+
+  test="${matchflags}${test}"
+  testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
+  testarr=( "${(@)testarr:#}" )
+
+  # If there are no matches we give up. If there is more than one
+  # match, this is the part we will complete.
+  (( $#testarr )) || return 1
+  [[ $#testarr -gt 1 ]] && break
+
+  # Only one match, add it to the prefix and skip over it in `str',
+  # continuing with the next array and separator.
+  prefix="${prefix}${testarr[1]}${sep}"
+  str="${str#*${sep}}"
+  shift 2
+done
+
+# Get the array to work upon.
+arr="$1"
+if [[ "$arr[1]" == '(' ]]; then
+  tmparr=( ${=arr[2,-2]} )
+  arr=tmparr
+fi
+if [[ $# -le 1 || "$str" != *${2}* ]]; then
+  # No more separators, build the matches.
+
+  test="$str"
+  [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
+
+  matchflags=""
+  _match_pattern _sep_parts test matchflags
+  [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+
+  test="${matchflags}${test}"
+  testarr=( "${(@M)${(@P)arr}:#${~test}*}" )
+  testarr=( "${(@)testarr:#}" )
+fi
+
+[[ $#testarr -eq 0 || ${#testarr[1]} -eq 0 ]] && return 1
+
+# Now we build the suffixes to give to the completion code.
+shift
+matchers=()
+suffixes=("")
+autosuffix=()
+
+while [[ $# -gt 0 && "$str" == *${1}* ]]; do
+  # Remove anything up to the the suffix.
+  str="${str#*${1}}"
+
+  # Again, we get the string from the line up to the next separator
+  # and build a pattern from it.
+  if [[ $# -gt 2 ]]; then
+    test="${str%%${3}*}"
+  else
+    test="$str"
+  fi
+
+  [[ -n "$_comp_correct" && $#test -le _comp_correct ]] && return 1
+
+  matchflags=""
+  _match_pattern _sep_parts test matchflags
+  [[ -n "$_comp_correct" ]] && matchflags="$matchflags(#a$_comp_correct)"
+  test="${matchflags}${test}"
+
+  # We incrementally add suffixes by appending to them the seperators
+  # and the strings from the next array that match the pattern we built.
+
+  arr="$2"
+  if [[ "$arr[1]" == '(' ]]; then
+    tmparr=( ${=arr[2,-2]} )
+    arr=tmparr
+  fi
+  tmparr=( "${(@M)${(@P)arr}:#${~test}*}" )
+  tmparr=( "${(@)tmparr:#}" )
+  suffixes=("${(@)^suffixes[@]}${1}${(@)^tmparr}")
+
+  # We want the completion code to generate the most specific suffix
+  # for us, so we collect matching specifications that allow partial
+  # word matching before the separators on the fly.
+  matchers=("$matchers[@]" "r:|${1:q}=*")
+  shift 2
+done
+
+# If we were given at least one more separator we make the completion
+# code offer it by appending it as a autoremovable suffix.
+(( $# )) && autosuffix=(-qS "$1")
+
+# If we have collected matching specifications, we build an array
+# from it that can be used as arguments to `compadd'.
+[[ $#matchers -gt 0 ]] && matchers=(-M "$matchers")
+
+# Add the matches for each of the suffixes.
+for i in "$suffixes[@]"; do
+  compadd -U "$group[@]" "$expl[@]" "$matchers[@]" "$autosuffix[@]" \
+          -i "$IPREFIX" -p "$prefix" -s "$i" - "$testarr[@]"
+done
+
+# This sets the return value to indicate that we added matches (or not).
+
+[[ nm -ne compstate[nmatches] ]]
diff --git a/Completion/Core/compdump b/Completion/Core/compdump
index 8be096f50..5fdee8c7a 100644
--- a/Completion/Core/compdump
+++ b/Completion/Core/compdump
@@ -15,7 +15,7 @@
 # Print the number of files used for completion. This is used in compinit
 # to see if auto-dump should re-dump the dump-file.
 
-_d_file=${COMPDUMP-${0:h}/compinit.dump}
+_d_file=${compconfig[dump_file]-${0:h}/compinit.dump}
 
 typeset -U _d_files
 _d_files=( ${^~fpath}/_*~*~(N:t) )
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index ec5867838..31d011565 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -37,18 +37,24 @@
 # Note that no white space is allowed between the `#' and the rest of
 # the string.
 #
-# See the file `compdump' for how to speed up initialiation.
+# Functions that are used to generate matches should return zero if they
+# were able to add matches and non-zero otherwise.
+#
+# See the file `compdump' for how to speed up initialisation.
 #
 # If you are using global matching specifications with `compctl -M ...'
 # have a look at the files `_match_test' and `_match_pattern'. To make
 # all the example functions use matching as specified with `-M' these
 # need some editing.
-#
+
 # If we got the `-d'-flag, we will automatically dump the new state (at
 # the end).
+# If we were given an argument, this will be taken as the name of the
+# file in which to store the dump.
 
 if [[ "$1" = -d ]]; then
   _i_autodump=1
+  shift
 else
   _i_autodump=0
 fi
@@ -59,6 +65,18 @@ fi
 typeset -A _comps
 _patcomps=()
 
+# This is the associative array used for configuration.
+
+typeset -A compconfig
+
+# Standard initialisation for `compconfig'.
+
+(( $# )) && compconfig[dump_file]="$1"
+[[ -z "$compconfig[dump_file]" ]] && compconfig[dump_file]="$0.dump"
+
+compconfig[correct_prompt]='correct to:'
+
+
 # This function is used to register or delete completion functions. For
 # registering completion functions, it is invoked with the name of the
 # function as it's first argument (after the options). The other
@@ -197,11 +215,25 @@ compdef() {
   fi
 }
 
-# Now we automatically make the definition files autoloaded.
+# Functional interface to configuration. This takes its arguments
+# and sets the according values in `compconfig'.
+# Arguments may be `foo=bar' to set key `foo' to `bar' or `baz' to
+# set key `baz' to the empty string.
 
-# First we get the name of a dump file if this will be used.
+compconf() {
+  local i name
 
-: ${COMPDUMP:=$0.dump}
+  for i; do
+    if [[ "$i" = *\=* ]]; then
+      name="${i%%\=*}"
+      compconfig[$name]="${i#*\=}"
+    else
+      compconfig[$i]=''
+    fi
+  done
+}
+
+# Now we automatically make the definition files autoloaded.
 
 if [[ ! -o extendedglob ]]; then
   _i_noextglob=yes
@@ -215,10 +247,10 @@ _i_done=''
 
 # If we have a dump file, load it.
 
-if [[ -f "$COMPDUMP" ]]; then
-  read -rA _i_line < "$COMPDUMP"
+if [[ -f "$compconfig[dump_file]" ]]; then
+  read -rA _i_line < "$compconfig[dump_file]"
   if [[ _i_autodump -eq 1 && $_i_line[2] -eq $#_i_files ]]; then
-    builtin . "$COMPDUMP"
+    builtin . "$compconfig[dump_file]"
     _i_done=yes
   fi
   unset _i_line
diff --git a/Completion/README b/Completion/README
index 43ffcbcc2..f95e67699 100644
--- a/Completion/README
+++ b/Completion/README
@@ -9,9 +9,12 @@ Core/compinit.  It is recommnded that you use the -d option, which outputs
 a file containing the necessary variables, bindkeys etc., making later
 loading much faster.  For example,
   [[ -f ~/completion/compinit ]] && . ~/completion/compinit -d
+The name of the file to use may be given as an extra argument.
+
 This will rebind any keys which do completion to use the new system.
 For more detailed instructions, including how to add new completions, see
-the top of Core/compinit.
+the top of Core/compinit. For information about how to configure the code,
+see the comment at the top of Core/_main_complete.
 
 The subdirectories contain:
 
@@ -27,7 +30,7 @@ Core:
     This dumps the completions status for faster initialisation.  The
     easiest way of doing this is to use the -d option to compinit rather
     than calling compdump directly.
-  _comp_parts
+  _sep_parts
     Utility used for completing words with multiple separate parts, such as
     `<user>@<host>'
   _multi_parts
@@ -67,10 +70,15 @@ Base:
     This handles completion of command arguments when no special function
     exists.  Usually this means completing files, but you can modify this
     as you wish.
+  _long_options
+    This handles options beginning with `--', as in many GNU commands.
+    The command must accept the --help option to list the possible options.
+    __long_options can also take arguments to help it decide what to
+    complete as the value of the option.
   _match_pattern
   _match_test
     These are used by Base/_path_files (and hence also Base/_files)
-    and Base/_comp_parts for file completion with control over
+    and Base/_sep_parts for file completion with control over
     matching (whether to complete case-insensitively, or to allow
     insertion before `.', etc.)  See _match_test for instructions.
     Note _path_files expects these files to be present.
diff --git a/Completion/User/.distfiles b/Completion/User/.distfiles
new file mode 100644
index 000000000..ee0017035
--- /dev/null
+++ b/Completion/User/.distfiles
@@ -0,0 +1,6 @@
+DISTFILES_SRC='
+    .distfiles
+    _a2ps _compress _configure _dd _dvi _find _gunzip _gzip _hosts
+    _make _man _mh _pdf _ps _rcs _rlogin _strip _stty _tar _tar_archive
+    _tex _uncompress _x_options _xfig 
+'
diff --git a/Completion/User/_a2ps b/Completion/User/_a2ps
index 600b58872..9923ae20d 100644
--- a/Completion/User/_a2ps
+++ b/Completion/User/_a2ps
@@ -1,22 +1,39 @@
 #defcomp a2ps
 
-if [[ "$PREFIX[1,2]" = -- ]]; then
-  _comp_parts '(--borders --compact --truncate-lines --interpret
-                --print-anyway --delegate)' '=' '(yes no)'
-  _comp_parts '(--major)' '=' '(rows columns)'
-  _comp_parts '(--end-of-line)' '=' '(r n nr rn any)'
+# This is for the GNU version of a2ps.
 
-  compgen -S= -k '(--medium --columns --rows --line-numbers
-                    --font-size --lines-per-page --chars-per-line
- 		    --tabsize --non-printable-format --encoding
-		    --title --stdin --prologue --highlight-level
-		    --strip-level --output --version-control --suffix
-		    --printer --copies --sides --page-prefeed
-		    --no-page-prefeed)'
-  compgen -qS= -k '(--margin --header --underlay --left-title
-                     --right-title --left-footer --footer --right-footer
-		     --pages --pretty-print)'
-  compgen -k '(--landscape --portrait --catman --no-header)'
-else
-  _files -F fignore -g "*~*.ps"
+if [[ "$words[1]" != "$_a2ps_cache_cmd" ]]; then
+  local descr
+
+  _a2ps_cache_cmd="$words[1]"
+
+  descr=( "${(@)${(f@)$($words[1] --list=features)//
+ /	}:#}" )
+
+  _a2ps_cache_values=(
+      "${descr[(r)Known style sheets*]#*	}"
+      "${descr[(r)Known encodings*]#*	}"
+      "${descr[(r)Known media*]#*	}"
+      "${descr[(r)Known prologues*]#*	}"
+      "${descr[(r)Known PostScript Printer Descriptions*]#*	}"
+      "${descr[(r)Known output destination*]#*	}"
+      "${descr[(r)Known user options*]#*	}"
+      "${descr[(r)Known Variables*]#*	}"
+  )
 fi
+
+_long_options -t '*\*'                '(yes no)' \
+                 '*=DIRECTION'        '(rows columns)' \
+                 '*=TYPE'             '(r n nr rn any)' \
+		 '--highlight-level*' '(none normal heavy)' \
+		 '--version-control*' '(none off t numbered nil 
+		                        existing never simple)' \
+	         '--pretty-print*'    "[${_a2ps_cache_values[1]}]" \
+	         '--encoding*'        "(${_a2ps_cache_values[2]})" \
+	         '--medium*'          "[${_a2ps_cache_values[3]}]" \
+	         '--prologue*'        "[${_a2ps_cache_values[4]}]" \
+	         '--ppd*'             "[${_a2ps_cache_values[5]}]" \
+	         '--printer*'         "[${_a2ps_cache_values[6]}]" \
+	         '--user-option*'     "[${_a2ps_cache_values[7]}]" \
+	         '--variable*'        "[${_a2ps_cache_values[8]}]" ||
+    _files -F fignore -g '*~*.(ps|PS|eps|EPS)'
diff --git a/Completion/User/_configure b/Completion/User/_configure
index 050701fac..7559852e8 100644
--- a/Completion/User/_configure
+++ b/Completion/User/_configure
@@ -1,35 +1,4 @@
 #defcomp configure
 
-setopt localoptions extendedglob
-
-if [[ $PREFIX = *=* ]]; then
-  # Complete filenames after e.g. --prefix=
-  IPREFIX=${PREFIX%%=*}=
-  PREFIX=${PREFIX#*=}
-  compgen -f
-else
-  # Generate a list of options from configure --help
-  local -a pars
-  local i
-  pars=($($words[1] --help | awk '$1 ~ /--[a-z]*.*/ {print $1}'))
-  for i in $pars
-  do
-    case $i in
-      (--(((en|dis)able-FEATURE)|(with(out|)-PACKAGE))*)
-        : Skip standard help output
-      ;;
-      --enable)
-        : Skip standard help output
-      ;;
-      --*\[=* )
-        compadd -M 'r:|-=* r:|=*' -q -S = -- ${i%%\[=*}
-      ;;
-      --*=* )
-        compadd -M 'r:|-=* r:|=*' -S = -- ${i%%=*}
-      ;;
-      * )
-        compadd -M 'r:|-=* r:|=*' -- $i
-      ;;
-    esac
-  done
-fi
+_long_options '*=(E|)PREFIX*' '_files -/' \
+              '*=PROGRAM*'    '_command_names'
diff --git a/Completion/User/_dd b/Completion/User/_dd
index 86a47b1ab..63ae40f50 100644
--- a/Completion/User/_dd
+++ b/Completion/User/_dd
@@ -5,7 +5,7 @@ if [[ -iprefix conv= ]]; then
   # test alone will have that effect.
   [[ -string , ]]
   compgen -S, -q \
-  -k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)'
+      -k '(ascii ebcdic ibm block unblock lcase ucase swab noerror sync)'
 elif [[ -iprefix 'if=' || -iprefix 'of=' ]]; then
   _files
 else
diff --git a/Completion/User/_find b/Completion/User/_find
index 8fcdafb83..cb637fc26 100644
--- a/Completion/User/_find
+++ b/Completion/User/_find
@@ -10,8 +10,12 @@ elif [[ -iprefix - ]]; then
     {i,}{l,}name {no,}{user,group} path perm regex size true uid used \
     exec {f,}print{f,0,} ok prune ls'
 elif [[ -position 2 ]]; then
-  compgen -g '. ..'
-  _files -g '(-/)'
+  local ret=1
+
+  compgen -g '. ..' && ret=0
+  _files -g '(-/)' && ret=0
+
+  return ret
 elif [[ "$prev" = -((a|c|)newer|fprint(|0|f)) ]]; then
   _files
 elif [[ "$prev" = -fstype ]]; then
diff --git a/Completion/User/_man b/Completion/User/_man
index 67d59f24a..cd1badc4d 100644
--- a/Completion/User/_man
+++ b/Completion/User/_man
@@ -1,7 +1,9 @@
 #defcomp man
+
 setopt localoptions rcexpandparam
 
 local rep
+
 if [[ $words[2] = (<->*|ln) ]]; then
   rep=( $manpath/(man|cat)${words[2]}/$PREFIX*$SUFFIX.<->*(N:t:r) )
 else
diff --git a/Completion/User/_mh b/Completion/User/_mh
index 7e8575123..c6c018220 100644
--- a/Completion/User/_mh
+++ b/Completion/User/_mh
@@ -4,6 +4,7 @@
 # Alter the following two to your own mh directory and the directory
 # where standard mh library files live.  (It works anyway, but this
 # will save a little time.)
+
 local mymhdir=~/Mail
 local mhlib=/usr/lib/mh
 
@@ -25,6 +26,7 @@ if [[ -iprefix - ]]; then
 elif [[ -iprefix '+' || -iprefix '@' || "$prev" = -draftfolder ]]; then
   # Complete folder names.
   local mhpath
+
   if [[ $IPREFIX != '@' ]]; then
     [[ $IPREFIX = '+' ]] || IPREFIX=+
     mhpath=$mymhdir
@@ -53,7 +55,8 @@ elif [[ "$prev" = -[rw]cache ]]; then
   compadd public private never ask
 else
   # Generate sequences.
-  local foldnam folddir f
+  local foldnam folddir f ret
+
   for f in $argv; do
     [[ $f = [@+]* ]] && foldnam=$f
   done
@@ -66,7 +69,10 @@ else
     # leaving foldnam empty works here
   fi
 
-  compgen -s '$(mark $foldnam 2>/dev/null | awk -F: '\''{ print $1 }'\'')'
-  compadd reply next cur prev first last all unseen
-  compgen -W folddir -g '<->'
+  compgen -s '$(mark $foldnam 2>/dev/null | awk -F: '\''{ print $1 }'\'')' &&
+      ret=0
+  compadd reply next cur prev first last all unseen && ret=0
+  compgen -W folddir -g '<->' && ret=0
+
+  return ret
 fi
diff --git a/Completion/User/_rcs b/Completion/User/_rcs
index 5a751605c..5e53cb4da 100644
--- a/Completion/User/_rcs
+++ b/Completion/User/_rcs
@@ -6,6 +6,7 @@ local nm=$compstate[nmatches]
 
 if [[ $compstate[nmatches] -eq nm && -d RCS && $words[1] != ci ]]; then
   local rep
+
   rep=(RCS/$PREFIX*$SUFFIX,v(:t:s/\,v//))
   (( $#rep )) && compadd - $rep
 fi
diff --git a/Completion/User/_strip b/Completion/User/_strip
index 6962ac455..541c901ad 100644
--- a/Completion/User/_strip
+++ b/Completion/User/_strip
@@ -1,2 +1,3 @@
 #defcomp strip
+
 _files -g '*(*)'
diff --git a/Completion/User/_tar b/Completion/User/_tar
index 84c490f1e..d11ee76c8 100644
--- a/Completion/User/_tar
+++ b/Completion/User/_tar
@@ -1,69 +1,125 @@
 #defcomp tar
 
 # Tar completion.  Features:
-#  - Assumes tar commands are in second position, tar archive is in third
-#    e.g. tar xvzf zsh-3.0.5.tar.gz ...
-#    Could search better.  Send me the patch.
+#  - Tries to collect tar commands from second position, single letter
+#    option, and long options.
 #  - `tar' can be called anything, will use the correct name
-#  - Preferentially completes *.tar and *.TAR files in third position
-#  - unless z or Z appears in the commands, in which case prefer *.tar.gz
-#    and similar (GNU tar).
-#  - From fourth position on, if command is x or t, completes files inside
-#    archive.  This is supposed to look pretty much as if the files are
-#    in an ordinary directory hierarchy.  Handles extraction from compressed
-#    archives (GNU tar).
+#  - Uses the function `_tar_archive' to complete archive files.
+#  - Tries to find out if compressed archives should be used.
+#  - Completes files inside archive.  This is supposed to look pretty
+#    much as if the files are in an ordinary directory hierarchy.
+#    Handles extraction from compressed archives (GNU tar).
 #  - Anywhere -- appears, gets a list of long options to complete from
-#    tar itself (GNU tar); this needs perl.  If you have GNU tar but not
-#    perl:  your system manager is weird.
+#    tar itself (GNU tar)
 #  - Things like --directory=... are also completed correctly.
 
 emulate -LR zsh
 setopt extendedglob
 
-local nm=$NMATCHES tcmd="$words[2]" tf="$words[3]"
+local _tar_cmd tf tmp del
 
-if [[ $PREFIX = *=* ]]; then
-  # For GNU tar arguments like --directory=
-  IPREFIX=${PREFIX%%\=*}=
-  PREFIX=${PREFIX#*=}
-  if [[ $IPREFIX = --directory* ]]; then
-    _path_files -/
-  else
-    _files
+# First we collect in `_tar_cmd' single letter options describing what
+# should be done with the archive and if it is compressed. This
+# collected from options arguments that start with only one hyphen,
+# from some of the possible long options, and from the second word if
+# that does not start with a hyphen.
+
+tmp=("${(@M)words:#-[^-]*}")
+_tar_cmd="${(j::)tmp#-}"
+
+(( $words[(I)--(un|)gzip] ))     && _tar_cmd="z$_tar_cmd"
+(( $words[(I)--(un|)compress] )) && _tar_cmd="Z$_tar_cmd"
+(( $words[(I)--list] ))          && _tar_cmd="t$_tar_cmd"
+(( $words[(I)--(extract|get)] )) && _tar_cmd="x$_tar_cmd"
+(( $words[(I)--create] ))        && _tar_cmd="c$_tar_cmd"
+
+# Other ways of finding out what we're doing:  first
+# look in the first argument if it's not an option
+if [[ "$words[2]" = *[txcdruA]*~-* ]]; then
+  _tar_cmd="$words[2]$_tar_cmd"
+elif [[ $_tar_cmd != *[txcdruA]* && CURRENT -gt 2 ]]; then
+  # look for more obscure long options: these aren't all handled.
+  (( $words[(I)--(diff|compare)] )) && _tar_cmd="d$_tar_cmd"
+  (( $words[(I)--append] )) && _tar_cmd="r$_tar_cmd"
+  (( $words[(I)--update] )) && _tar_cmd="u$_tar_cmd"
+  (( $words[(I)--(con|)catenate] )) && _tar_cmd="A$_tar_cmd"
+  (( $words[(I)--delete] )) && del=1
+fi
+
+# Next, we try to find the archive name and store it in `tf'. The name 
+# is searched after a `--file=' long option, in the third word if the
+# second one didn't start with a hyphen but contained a `f', and after 
+# an option argument starting with only one hyphen and containing a `f'.
+
+tmp="$words[(I)--file=*]"
+if (( tmp )); then
+  tf="${words[tmp][8,-1]}"
+  _tar_cmd="f$_tar_cmd"
+elif [[ "$words[2]" != -* && "$words[2]" = *f* ]]; then
+  tf="$words[3]"
+  _tar_cmd="f$_tar_cmd"
+else
+  tmp="${words[(I)-*f*~--*]}"
+  if (( tmp )); then
+    tf="$words[tmp+1]"
+    _tar_cmd="f$_tar_cmd"
   fi
-elif [[ $PREFIX = --* ]]; then
-  # gnu tar, generate completions from --help
-  # ones followed by = get that as a suffix
-  local -a ownlist eqlist
-  local comp
-  $words[1] --help |
-  perl -ne 'while (/--[^[\s,='\'']+=?/g) { print "$&\n"; }' |
-  while read comp; do
-    if [[ $comp = *= ]]; then
-      eqlist[$#eqlist+1]=${comp%=}
-    else
-      ownlist[$#ownlist+1]=$comp
-    fi
-  done
-  compgen -S '=' -k eqlist
-  compgen -k ownlist
-elif [[ "$tcmd" = *[tx]*f* && $CURRENT -ge 4 ]] then
-  # Listing or extracting a particular file.  We run `tar t...'
-  # on the file, keeping the list of filenames cached, plus the
-  # name of the tarfile so we know if it changes.
+fi
+
+# Now we complete...
+
+if [[ "$PREFIX" = --* ]]; then
+
+  # ...long options after `--'.
+
+  _long_options '--owner*'          "_tilde" \
+                '*=(PROG|COMMAND)*' "_command_names" \
+		'*=ARCHIVE*'        "_tar_archive" \
+		'*=CONTROL*'        "[t numbered nil existing never simple]"
+
+elif [[ ( CURRENT -gt 2 && "$words[CURRENT-1]" = -*f* &&
+          "$words[CURRENT-1]" != --* ) ||
+        ( CURRENT -eq 3 && "$words[2]" = *f* && "$words[2]" != -* ) ]]; then
+
+  # ...archive files if we think they are wanted here.
+
+  _tar_archive
+
+elif [[ ( "$_tar_cmd" = *[xt]* || -n $del ) && -n "$tf" ]]; then
+
+  # ...and files from the archive if we found an archive name and tar
+  # commands. We run `tar t...' on the file, keeping the list of
+  # filenames cached, plus the name of the tarfile so we know if it
+  # changes.
+
   local largs=-tf
 
-  [[ $words[2] = *z* ]] && largs=-tzf
-  [[ $words[2] = *Z* ]] && largs=-tZf
-  if [[ $tf != $tar_cache_name ]]; then
-    tar_cache_list=("${(@f)$($words[1] $largs $tf)}")
-    tar_cache_name=$tf
+  if [[ $_tar_cmd = *z* ]]; then
+    largs=-tzf
+  elif [[ $_tar_cmd = *Z* ]]; then
+    largs=-tZf
+  else
+    # Some random compression program e.g. bzip2
+    tmp="${words[(r)--use-comp*]}"
+    [[ -n $tmp ]] && largs=($tmp -tf)
+  fi
+
+  if [[ $tf != $_tar_cache_name ]]; then
+    _tar_cache_list=("${(@f)$($words[1] $largs $tf)}")
+    _tar_cache_name=$tf
+  fi
+
+  _multi_parts / _tar_cache_list
+else
+  
+  # See if we should use a path prefix.  We have to use eval as the dir can
+  # be any unevaluated thing which appears on the command line, including a
+  # parameter.
+  tmp=${words[(r)--dir[a-z]#=*]}
+  if [[ -n $tmp ]]; then
+    eval "tmp=(${tmp#*=})"
+    _path_files -W tmp
+  else
+    _files
   fi
-  _multi_parts / tar_cache_list
-elif [[ "$tcmd" = *c*f* && $CURRENT -ge 4 ]] then
-  _files
-elif [[ "$tcmd" = *[zZ]*f* && $CURRENT -eq 3 ]] then
-  _files -g '*.((tar|TAR).(gz|Z)|.tgz)'
-elif [[ "$tcmd" = *f* && $CURRENT -eq 3 ]] then
-  _files -g '*.(tar|TAR)'
 fi
diff --git a/Completion/User/_tar_archive b/Completion/User/_tar_archive
new file mode 100644
index 000000000..58e436c4d
--- /dev/null
+++ b/Completion/User/_tar_archive
@@ -0,0 +1,20 @@
+#autoload
+
+# This is used to generate filenames usable as a tar archive. This may
+# get one argument, a collection of tar option characters that may be
+# used to find out what kind of filename is needed. If no argument is
+# given but the parameter `_tar_cmd' is set, that is used.
+# If your version of `tar' supports this you may want to complete
+# things like `host:file' or `user@host:file' here.
+
+[[ $# -eq 0 && $+_tar_cmd -ne 0 ]] && set "$_tar_cmd"
+
+if [[ "$1" = *[tx]* ]]; then
+  if [[ "$1" = *[zZ]* ]]; then
+    _files -g '*.((tar|TAR).(gz|GZ|Z)|.tgz)'
+  else
+    _files -g '*.(tar|TAR)'
+  fi
+else
+  _files
+fi
diff --git a/Config/version.mk b/Config/version.mk
index be39570f4..e5fa2cbd6 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-11
-VERSION_DATE='March 3, 1999'
+VERSION=3.1.5-pws-12
+VERSION_DATE='March 11, 1999'
diff --git a/Doc/Zsh/compctl.yo b/Doc/Zsh/compctl.yo
index 4e1a98dab..f494ec5f9 100644
--- a/Doc/Zsh/compctl.yo
+++ b/Doc/Zsh/compctl.yo
@@ -703,7 +703,8 @@ The pattern var(tpat) may also be a single star, `tt(*)'. This means
 that the pattern on the command line can match any number of characters
 in the trial completion. In this case the pattern must be anchored (on
 either side); the var(anchor) then determines how much of the trial
-completion is to be included.
+completion is to be included --- only the characters up to the next
+appearance of the anchor will be matched.
 
 Examples:
 
@@ -758,7 +759,8 @@ nofill(tt(compctl -M 'r:|.=* r:|=*' \
   -k '(comp.sources.unix comp.sources.misc ...)' ngroups))
 )
 The first specification says that tt(lpat) is the empty string, while
-tt(anchor) is a dot; tt(tpat) is tt(*), so this can match anything in
+tt(anchor) is a dot; tt(tpat) is tt(*), so this can match anything
+except for the `tt(.)' from the anchor in
 the trial completion word.  So in tt(c.s.u), the matcher sees tt(c),
 followed by the empty string, followed by the anchor `tt(.)', and
 likewise for the second dot, and replaces the empty strings before the
diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo
index 44ae72002..46393167c 100644
--- a/Doc/Zsh/compwid.yo
+++ b/Doc/Zsh/compwid.yo
@@ -176,6 +176,12 @@ tt(LIST_AMBIGUOUS) is set, respectively. Inside the completion widget
 it may be set to any of these values to make the completion code as if 
 the appropriate options had been set.
 )
+item(tt(force_list))(
+If the value for the tt(list) key is tt(ambiguous), the list will
+normally be shown only if there are at least two matches in the
+list. Setting tt(force_list) to an non-empty string makes the list be
+shown even if there is only one match.
+)
 item(tt(insert))(
 This will be unset by the completon code if the contents of the
 command line will not be changed. It is set to tt(unambiguous),
diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo
index 4e7491088..fc3da7820 100644
--- a/Etc/FAQ.yo
+++ b/Etc/FAQ.yo
@@ -43,22 +43,25 @@ whenlatex(report(ARG1)(ARG2)(ARG3))\
 whenman(report(ARG1)(ARG2)(ARG3))\
 whenms(report(ARG1)(ARG2)(ARG3))\
 whensgml(report(ARG1)(ARG2)(ARG3)))
-myreport(Z-Shell Frequently-Asked Questions)(Peter Stephenson)(1998/10/26)
+myreport(Z-Shell Frequently-Asked Questions)(Peter Stephenson)(1999/02/25)
 COMMENT(-- the following are for Usenet and must appear first)\
 description(
 mydit(Archive-Name:) unix-faq/shell/zsh
-mydit(Last-Modified:) 1998/10/26
-mydit(Submitted-By:) email(pws@amtp.liv.ac.uk (Peter Stephenson))
-mydit(Version:) $Id: FAQ.yo,v 1.1.1.1 1999/04/15 18:05:37 akr Exp $
-mydit(Frequency:) Monthly
-mydit(Copyright:) (C) P.W. Stephenson, 1995, 1996, 1997, 1998 \
-(see end of document)
+mydit(Last-Modified:) 1999/02/05
+mydit(Submitted-By:) email(pws@ibmth.df.unipi.it (Peter Stephenson))
+mydit(Version:) $Id: FAQ.yo,v 1.1.1.2 1999/04/15 18:20:31 akr Exp $
+mydit(Posting-Frequency:) Monthly
+mydit(Copyright:) (C) P.W. Stephenson, 1995--1999 (see end of document)
 )
 
-bf(Changes since issue posted September 1998:)
+bf(Changes since issue posted January 1999:)
 description(
-mydit(2.1)  Another mytt(typeset) difference turned up.
-mydit(5.4)  Slight addition to Y2K item (prompt formatting)
+mydit(1.1)  deleted the bit saying startup files are not mentioned.
+mydit(3.2)  New: about startup files.
+mydit(3.7)  we just found the PRINT_EIGHT_BIT option again...
+mydit(3.22) New: about ${(e)...} and ${${...}}.
+mydit(5.2)  (In wishlist): patch exists for 3.1 to handle tying
+     texinputs/TEXINPUTS etc.
 )
 
 This document contains a list of frequently-asked (or otherwise
@@ -99,25 +102,27 @@ Chapter 2:  How does zsh differ from...?
 
 Chapter 3:  How to get various things to work
 3.1. Why does `$var' where `var="foo bar"' not do what I expect?
-3.2. What is the difference between `export' and the ALL_EXPORT option?
-3.3. How do I turn off spelling correction/globbing for a single command?
-3.4. How do I get the meta key to work on my xterm?
-3.5. How do I automatically display the directory in my xterm title bar?
-3.6. How do I make the completion list use eight bit characters?
-3.7. Why do the cursor (arrow) keys not work?
-3.8. Why does my terminal act funny in some way?
-3.9. Why does zsh not work in an Emacs shell mode any more?
-3.10. Why do my autoloaded functions not autoload [the first time]?
-3.11. How does base arithmetic work?
-3.12. How do I get a newline in my prompt?
-3.13. Why does `bindkey ^a command-name' or 'stty intr ^-' do something funny?
-3.14. Why can't I bind \C-s and \C-q any more?
-3.15. How do I execute command `foo' within function `foo'?
-3.16. Why do history substitutions with single bangs do something funny?
-3.17. Why does zsh kill off all my background jobs when I logout?
-3.18. How do I list all my history entries?
-3.19. How does the alternative loop syntax, e.g. mytt(while {...} {...}) work?
-3.20. Why is my history not being saved?
+3.2. In which startup file do I put...?
+3.3. What is the difference between `export' and the ALL_EXPORT option?
+3.4. How do I turn off spelling correction/globbing for a single command?
+3.5. How do I get the meta key to work on my xterm?
+3.6. How do I automatically display the directory in my xterm title bar?
+3.7. How do I make the completion list use eight bit characters?
+3.8. Why do the cursor (arrow) keys not work?
+3.9. Why does my terminal act funny in some way?
+3.10. Why does zsh not work in an Emacs shell mode any more?
+3.11. Why do my autoloaded functions not autoload [the first time]?
+3.12. How does base arithmetic work?
+3.13. How do I get a newline in my prompt?
+3.14. Why does `bindkey ^a command-name' or 'stty intr ^-' do something funny?
+3.15. Why can't I bind \C-s and \C-q any more?
+3.16. How do I execute command `foo' within function `foo'?
+3.17. Why do history substitutions with single bangs do something funny?
+3.18. Why does zsh kill off all my background jobs when I logout?
+3.19. How do I list all my history entries?
+3.20. How does the alternative loop syntax, e.g. mytt(while {...} {...}) work?
+3.21. Why is my history not being saved?
+3.22. How do I get a variable's value to be evaluated as another variable?
 
 Chapter 4:  The mysteries of completion
 4.1. What is completion?
@@ -164,20 +169,23 @@ url(http://sunsite.auc.dk/zsh/FAQ/)(http://sunsite.auc.dk/zsh/FAQ/) .
   posted frequently to the Usenet news groups comp.unix.questions,
   comp.unix.shells and comp.answers with answers to general questions
   about UNIX.  The fifth of the seven articles deals with shells,
-  including zsh, with a brief description of differences.  (This article
-  also talks about shell startup files which would otherwise rate a
-  mention here.)  There is also a separate FAQ on shell differences
-  and how to change your shell.  Usenet FAQs are available via FTP
-  from rtfm.mit.edu and mirrors and also on the World Wide Web; see
+  including zsh, with a brief description of differences.  There is
+  also a separate FAQ on shell differences and how to change your
+  shell.  Usenet FAQs are available via FTP from rtfm.mit.edu and
+  mirrors and also on the World Wide Web; see
   description(
     mydit(USA)         url(http://www.cis.ohio-state.edu/hypertext/faq/usenet/top.html)
     (http://www.cis.ohio-state.edu/hypertext/faq/usenet/top.html)
     mydit(UK)          url(http://www.lib.ox.ac.uk/internet/news/faq/comp.unix.shell.html)
     (http://www.lib.ox.ac.uk/internet/news/faq/comp.unix.shell.html)
-    mydit(Netherlands) url(http://www.cs.ruu.nl/wais/html/na-dir/unix-faq/shell/.html)
-    (http://www.cs.ruu.nl/wais/html/na-dir/unix-faq/shell/.html)
+    mydit(Netherlands) url(http://www.cs.uu.nl/wais/html/na-dir/unix-faq/shell/.html)
+    (http://www.cs.uu.nl/wais/html/na-dir/unix-faq/shell/.html)
   )
 
+  You can also get it via email by emailing \
+email(mail-server@rtfm.mit.edu)
+  with, in the body of the message, mytt(send faqs/unix-faq/shell/zsh).
+
   The latest version of this FAQ is also available directly from any
   of the zsh archive sites listed in question link(1.6)(16).
 
@@ -296,7 +304,7 @@ sect(What's the latest version?)
   the list of incompatibilities at the end of link(5.1)(51).  This is
   longer than usual due to enhanced sh, ksh and POSIX compatibility.
 
-  The beta version 3.1.4 is also available.  Development of zsh is
+  The beta version 3.1.5 is also available.  Development of zsh is
   usually patch by patch, with each intermediate version publicly
   available.  Note that this `open' development system does mean bugs
   are sometimes introduced into the most recent archived version.
@@ -352,6 +360,8 @@ url(http://www.math.technion.ac.il/mirror/ftp.zsh.org/pub/zsh/)
 (ftp://ftp.tohoku.ac.jp/mirror/zsh/)
     mydit()          url(ftp://ftp.nis.co.jp/pub/shells/zsh/)
 (ftp://ftp.nis.co.jp/pub/shells/zsh/)
+    mydit()          url(ftp://ftp.win.ne.jp/pub/shell/zsh/)
+(ftp://ftp.win.ne.jp/pub/shell/zsh/)
     mydit(Norway)    url(ftp://ftp.uit.no/pub/unix/shells/zsh/)
 (ftp://ftp.uit.no/pub/unix/shells/zsh/)
     mydit(Romania)   url(ftp://ftp.roedu.net/pub/mirrors/ftp.zsh.org/pub/zsh/)
@@ -623,6 +633,7 @@ link(2.3)(23).
     it()* Options are not local to functions (use LOCAL_OPTIONS; note this
         may always be unset locally to propagate options settings from a
         function to the calling level).
+    it()  Function definitions themselves are not local to functions.
   )
     it() Traps and signals:
   itemize(
@@ -720,12 +731,12 @@ label(23)
   )
   can be replaced by the zsh function,
   verb(
-    cd() { builtin cd $*; echo $PWD; }
+    cd() { builtin cd "$@"; echo $PWD; }
   )
   (the `builtin' tells zsh to use its own `cd', avoiding an infinite loop)
   or, perhaps better,
   verb(
-    cd() { builtin cd $*; print -D $PWD; }
+    cd() { builtin cd "$@"; print -D $PWD; }
   )
   (which converts your home directory to a tt(~)).  In fact, this problem is
   better solved by defining the special function chpwd() (see the manual).
@@ -746,7 +757,7 @@ label(23)
 
   myeit() If the csh alias references its own name (tt(alias rm "rm -i")),
      then in a zsh function you need the "command" keyword
-     (function tt(rm() { command rm -i $* })), but in a zsh alias
+     (function tt(rm() { command rm -i "$@" })), but in a zsh alias
      you don't (tt(alias rm="rm -i")).
 
   myeit() If you have aliases that refer to each other (tt(alias ls "ls -C";
@@ -799,7 +810,7 @@ label(23)
   There is one other serious problem with aliases: consider
   verb(
     alias l='/bin/ls -F'
-    l() { /bin/ls -la $* | more }
+    l() { /bin/ls -la "$@" | more }
   )
   mytt(l) in the function definition is in command position and is expanded
   as an alias, defining mytt(/bin/ls) and mytt(-F) as functions which call
@@ -959,13 +970,68 @@ label(31)
 
   Note also the tt("$@") method of word splitting is always available in zsh
   functions and scripts (though strictly this does array splitting, not
-  word splitting).
+  word splitting).  This is more portable than the tt($*), since it
+  will work regardless of the SHWORDSPLIT setting; the other
+  difference is that tt($*) removes empty arguments from the array.
+  You can fix the first half of that objection by using tt(${==*}),
+  which turns off SHWORDSPLIT for the duration of the expansion.
 
   SHWORDSPLIT is set when zsh is invoked with the names `ksh' or `sh',
   or (entirely equivalent) when mytt(emulate ksh) or mytt(emulate sh) is in
   effect.
 
 
+sect(In which startup file do I put...?)
+
+  When zsh starts up, there are four files you can change which it will
+  run under various circumstances: tt(.zshenv), tt(.zprofile), tt(.zshrc)
+  and tt(.zlogin).  They are usually in your home directory, but the
+  variable tt($ZDOTDIR) may be set to alter that.  Here are a few simple
+  hints about how to use them.  There are also files which the system
+  administrator can set for all shells; you can avoid running all except
+  tt(/etc/zshenv) by starting zsh with the tt(-f) option --- for this
+  reason it is important for administrators to make sure tt(/etc/zshenv)
+  is as brief as possible.
+
+  The order in which the four files are searched (none of them myem(need)
+  to exist) is the one just given.  However, tt(.zprofile) and tt(.zlogin)
+  are only run when the shell is a login shell --- when you first login,
+  of course, and whenever you start zsh with the tt(-l) option.  All
+  login shells are interactive.  The order is the only difference
+  between those; you should decide whether you need things set before or
+  after tt(.zshrc).  These files are a good place to set environment
+  variables (i.e. mytt(export) commands), since they are passed on to
+  all shells without you having to set them again, and also to check
+  that your terminal is set up properly (except that if you want to
+  change settings for terminal emulator windows like tt(xterm) you will
+  need to put those in tt(.zshrc), since usually you do not get a login
+  shell here).  
+
+  The only file you can alter which is started with every zsh (unless
+  you use the tt(-f) option) is tt(.zshenv), so this is a good place to \
+  put
+  things you want even if the shell is non-interactive: options for
+  changing the the syntax, like EXTENDED_GLOB, any changes to set with
+  mytt(limit), any more variables you want to make sure are set as for
+  example tt($fpath) to find functions.  You almost certainly do not
+  want tt(.zshenv) to produce any output.  Some people prefer not to
+  use tt(.zshenv) for setting options, as this affects scripts; but
+  making zsh scripts portable usually requires special handling anyway.
+
+  Finally, tt(.zshrc) is run for every interactive shell; that includes
+  login shells, but also any other time you start up a shell, such as
+  simply by typing mytt(zsh) or opening a new terminal emulator window.
+  This file is the place to change the editing behaviour via options or
+  mytt(bindkey), control how your history is saved, set aliases unless
+  you want to use them in scripts too, and for any other clutter which
+  can't be exported but you only use when interacting directly with the
+  shell.  You probably don't want tt(.zshrc) to produce output, either,
+  since there are occasions when this can be a problem, such as when
+  using mytt(rsh) from another host.  See link(3.21)(321) for what to \
+  put in tt(.zshrc)
+  to save your history.
+
+
 sect(What is the difference between `export' and the ALL_EXPORT option?)
 
   Normally, you would put a variable into the environment by using
@@ -1019,7 +1085,7 @@ sect(How do I turn off spelling correction/globbing for a single command?)
 
 
 sect(How do I get the meta key to work on my xterm?)
-label(34)
+label(35)
 
   As stated in the manual, zsh needs to be told about the meta key by
   using mytt(bindkey -me) or mytt(bindkey -mv) in your .zshrc or on the
@@ -1071,36 +1137,12 @@ sect(How do I automatically display the directory in my xterm title bar?)
 
 sect(How do I make the completion list use eight bit characters?)
 
-  A traditional UNIX environment (character terminal and ASCII
-  character sets) is not sufficient to be able to handle non-ASCII
-  characters, and there are so many possible enhancements that in
-  general this is hard.  However, if you have something like an xterm
-  using a standard character set like ISO-8859-1 (which is often the
-  default for xterm), read on.  You should also note question
-  link(3.4)(34) on the subject of eight bit characters.
-
-  You are probably creating files with names including non-ASCII
-  accented characters, and find they show up in the completion list as
-  verb(\M-i) or something such.  This is because the library routines
-  (not zsh itself) which test whether a character is printable have
-  replied that it is not; zsh has simply found a way to show them
-  anyway.
-
-  The answer, under a modern POSIXy operating system, is to find a
-  locale where these are treated as printable characters.  Zsh has
-  handling for locales built in and will recognise when you set a
-  relevant variable. You need to look in /usr/lib/locale to find one
-  which suits you; the subdirectories correspond to the locale names.
-  The simplest possibility is likely to be en_US, so that the simplest
-  answer to your problem is to set
-
-  verb(
-    LC_CTYPE=en_US
-  )
-
-  when your terminal is capable of showing eight bit characters.  If
-  you only have a default domain (called C), you may need to have some
-  additional files installed on your system.
+  If you are sure your terminal handles this, the easiest way is to
+  set the option PRINT_EIGHT_BIT.  In principle, this will work
+  automatically if your computer uses the `locale' system and your
+  locale variables are set properly, as zsh understands this.
+  However, it is quite complicated, so if it isn't already set up,
+  trying the option is a lot easier.
 
 
 sect(Why do the cursor (arrow) keys not work?)
@@ -1433,6 +1475,7 @@ work?)
 
 
 sect(Why is my history not being saved?)
+label(321)
 
   In zsh, you need to set three variables to make sure your history is
   written out when the shell exits.  For example,
@@ -1449,6 +1492,43 @@ sect(Why is my history not being saved?)
   manual.
 
 
+sect(How do I get a variable's value to be evaluated as another variable?)
+
+  The problem is that you have a variable tt($E) containing the string
+  mytt(EDITOR), and a variable tt($EDITOR) containing the string mytt(emacs),
+  or something such.  How do you get from tt($E) to emacs in one easy
+  stage?
+
+  There is no standard single-stage way of doing this.  However, there
+  is a zsh idiom (available in all versions of zsh since 3.0) for this:
+  verb(
+    print ${(e)E:+\$$E}
+  )
+  Ignore the mytt((e)) for now.  The mytt(:+) means: if the variable
+  tt($E) is set, substitute the following, i.e. mytt(\$$E).  This is
+  expanded to mytt($EDITOR) by the normal rules.  Finally, the mytt((e)) \
+  means:
+  evaluate the expression you just made.  This gives mytt(emacs).
+
+  For a standard shell way of doing this, you are stuck with mytt(eval):
+  verb(
+    eval echo \$$E
+  )
+  produces the same result.
+
+  Future versions of zsh will probably allow you to do this directly,
+  with a new flag; mytt(${(P)E}).
+
+  As a slight aside, sometimes people note that the syntax mytt(${${E}})
+  is valid and expect it to have this effect.  It probably ought to, but
+  in the early days of zsh it was found convenient to have this way of
+  producing different substitutions on the same parameter; for example,
+  mytt(${${file##**/}%.*}) removes everything up to the last slash in
+  mytt($file), then everything from the last dot on, inclusive (try
+  it, this works).  So in mytt(${${E}}), the internal mytt(${...})
+  actually does nothing.
+
+
 chapter(The mysteries of completion)
 
 Programmable completion using the `compctl' command is one of the most
@@ -1879,13 +1959,18 @@ label(52)
   The shell is being maintained by various (entirely self-appointed)
   subscribers to the mailing list,
   verb(
-    zsh-workers@math.gatech.edu
+    zsh-workers@sunsite.auc.dk
   )
   so mail on any issues (bug reports, suggestions, complaints...)
   related to the development of the shell should be sent there.  If
   you want someone to mail you directly, say so.  Most patches to zsh
   appear there first.
 
+  Note that this location has just changed (January 1999), and the
+  instructions to go with it are slightly different --- in particular,
+  if you are already subscribed, the instructions about how to
+  unsubscribe are different.
+
   Please note when reporting bugs that many exist only on certain
   architectures, which the developers may not have access to.  In
   this case debugging information, as detailed as possible, is
@@ -1894,12 +1979,12 @@ label(52)
   Two progressively lower volume lists exist, one with messages
   concerning the use of zsh,
   verb(
-    zsh-users@math.gatech.edu
+    zsh-users@sunsite.auc.dk
   )
   and one just containing announcements:  about releases, about major
   changes in the shell, or this FAQ, for example,
   verb(
-    zsh-announce@math.gatech.edu
+    zsh-announce@sunsite.auc.dk
   )
   (posting to the last one is currently restricted).
 
@@ -1913,20 +1998,16 @@ label(52)
 
   To join zsh-workers, send email to
   verb(
-    zsh-workers-request@math.gatech.edu
+    zsh-workers-subscribe@sunsite.auc.dk
   )
-  with the mybf(subject) line (this is a change from the old list)
-  verb(
-    subscribe <your-email-address>
-  )
-  e.g.
-  verb(
-    Subject:  subscribe P.Stephenson@swansea.ac.uk
-  )
-  and you can unsubscribe in the same way.
-  The list maintainer, Richard Coleman, can be reached at
-  email(coleman@math.gatech.edu).
-
+  (the actual content is unimportant).  Replace tt(subscribe) with
+  tt(unsubscribe) to unsubscribe.  The mailing software (tt(ezlm)) has
+  various bells and whistles: you can retrieve archived messages.
+  Mail email(zsh-workers-help@sunsite.auc.dk) for detailed information.
+  Adminstrative matters are best sent to
+  email(zsh-workers-owner@sunsite.auc.dk).  The list maintainer's
+  real name is email(Karsten Thygesen <karthy@kom.auc.dk>).
+  
   The list from May 1992 to May 1995 is archived in
     url(ftp://ftp.sterling.com/zsh/zsh-list/YY-MM)
 (ftp://ftp.sterling.com/zsh/zsh-list/YY-MM)
@@ -1951,14 +2032,15 @@ sect(What's on the wish-list?)
   of multiple functions to keystrokes, is being developed.
 
   itemize(
-  it() Loadable module support (will be in 3.1 but much work still needs doing).
+  it() Loadable module support (will be in 3.1 but much work still needs
+     doing).
   it() Ksh compatibility could be improved.
   it() Option for glob qualifiers to follow perl syntax (a traditional item).
   it() Binding of shell functions to key strokes, accessing editing
      buffer from functions, executing zle functions as a command:  now
      under development for 3.1. 
   it() Users should be able to create their own foopath/FOOPATH array/path
-     combinations.
+     combinations (now exists as a patch for 3.1).
   )
 
 
@@ -1996,17 +2078,18 @@ nsect(Acknowledgments:)
 Thanks to zsh-list, in particular Bart Schaefer, for suggestions
 regarding this document.  Zsh has been in the hands of archivists Jim
 Mattson, Bas de Bakker, Richard Coleman, Zoltan Hidvegi and Andrew
-Main, and the mailing list has been run by Peter Gray, Rick Ohnemus
-and Richard Coleman, all of whom deserve thanks.  The world is
-eternally in the debt of Paul Falstad for inventing zsh in the first
-place (though the wizzo extended completion is by Sven Wischnowsky).
+Main, and the mailing list has been run by Peter Gray, Rick Ohnemus,
+Richard Coleman and Karsten Thygesen, all of whom deserve thanks.  The
+world is eternally in the debt of Paul Falstad for inventing zsh in
+the first place (though the wizzo extended completion is by Sven
+Wischnowsky).
 
 
 nsect(Copyright Information:)
 
 This document is copyright (C) P.W. Stephenson, 1995, 1996, 1997,
-1998. This text originates in the U.K. and the author asserts his
-moral rights under the Copyrights, Designs and Patents Act, 1988.
+1998, 1999. This text originates in the U.K. and the author asserts
+his moral rights under the Copyrights, Designs and Patents Act, 1988.
 
 Permission is hereby granted, without written agreement and without
 license or royalty fees, to use, copy, modify, and distribute this
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h
index d7f3610f1..1444197a3 100644
--- a/Src/Zle/comp.h
+++ b/Src/Zle/comp.h
@@ -311,11 +311,12 @@ struct cline {
 #define CP_QUOTING    (1 << 14)
 #define CP_RESTORE    (1 << 15)
 #define CP_LIST       (1 << 16)
-#define CP_INSERT     (1 << 17)
-#define CP_EXACT      (1 << 18)
-#define CP_EXACTSTR   (1 << 19)
-#define CP_PATMATCH   (1 << 20)
+#define CP_FORCELIST  (1 << 17)
+#define CP_INSERT     (1 << 18)
+#define CP_EXACT      (1 << 19)
+#define CP_EXACTSTR   (1 << 20)
+#define CP_PATMATCH   (1 << 21)
 
-#define CP_NUM              21
+#define CP_NUM              22
 
 #define CP_ALLMASK    ((1 << CP_NUM) - 1)
diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c
index ccccf5a34..29836fbac 100644
--- a/Src/Zle/comp1.c
+++ b/Src/Zle/comp1.c
@@ -115,6 +115,7 @@ char **compwords,
      *compquoting,
      *comprestore,
      *complist,
+     *compforcelist,
      *compinsert,
      *compexact,
      *compexactstr,
@@ -432,7 +433,7 @@ setup_comp1(Module m)
     compprefix = compsuffix = compiprefix = compmatcherstr = 
 	compcontext = compparameter = compredirect = compquote =
 	compquoting = comprestore = complist = compinsert =
-	compexact = compexactstr = comppatmatch = NULL;
+	compexact = compexactstr = comppatmatch = compforcelist = NULL;
     makecompparamsptr = NULL;
     comp_setunsetptr = NULL;
     return 0;
@@ -473,6 +474,7 @@ finish_comp1(Module m)
     zsfree(compquoting);
     zsfree(comprestore);
     zsfree(complist);
+    zsfree(compforcelist);
     zsfree(compinsert);
     zsfree(compexact);
     zsfree(compexactstr);
diff --git a/Src/Zle/comp1.export b/Src/Zle/comp1.export
index 35b63e7d3..23d2d8dd2 100644
--- a/Src/Zle/comp1.export
+++ b/Src/Zle/comp1.export
@@ -15,6 +15,7 @@ compctltab
 compcurrent
 compexact
 compexactstr
+compforcelist
 compinsert
 compiprefix
 complist
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index b5c8e4b3f..df38dcc96 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -183,7 +183,7 @@ print_gmatcher(int ac)
 static Cmatcher
 parse_cmatcher(char *name, char *s)
 {
-    Cmatcher ret = NULL, r, n;
+    Cmatcher ret = NULL, r = NULL, n;
     Cpattern line, word, left, right;
     int fl, ll, wl, lal, ral, err;
 
@@ -276,8 +276,10 @@ parse_cmatcher(char *name, char *s)
 	n->right = right;
 	n->ralen = ral;
 
-	if (ret) r->next = n;
-	else ret = n;
+	if (ret)
+	    r->next = n;
+	else
+	    ret = n;
 
 	r = n;
     }
@@ -290,7 +292,7 @@ parse_cmatcher(char *name, char *s)
 static Cpattern
 parse_pattern(char *name, char **sp, int *lp, char e, int *err)
 {
-    Cpattern ret = NULL, r, n;
+    Cpattern ret = NULL, r = NULL, n;
     unsigned char *s = (unsigned char *) *sp;
     int l = 0;
 
@@ -1707,6 +1709,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
 	}
 	for (p = *argv + 1; *p; p++) {
 	    sp = NULL;
+	    e = NULL;
 	    dm = 0;
 	    switch (*p) {
 	    case 'q':
@@ -1864,6 +1867,7 @@ static struct compparam {
     { "quoting", PM_SCALAR, VAR(compquoting) },
     { "restore", PM_SCALAR, VAR(comprestore) },
     { "list", PM_SCALAR, VAR(complist) },
+    { "force_list", PM_SCALAR, VAR(compforcelist) },
     { "insert", PM_SCALAR, VAR(compinsert) },
     { "exact", PM_SCALAR, VAR(compexact) },
     { "exact_string", PM_SCALAR, VAR(compexactstr) },
@@ -2228,7 +2232,7 @@ cond_range(char **a, int id)
     if (comp_check()) {
 	char *s, **p;
 	int i, l = arrlen(compwords), t = 0, b = 0, e = l - 1;
-	Comp c;
+	Comp c = NULL;
 
 	i = compcurrent - 1;
 	if (i < 0 || i >= l)
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index 144bb1996..d5e0ee89c 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -125,7 +125,7 @@ typedef void (*KeyScanFunc) _((char *, Thingy, char *, void *));
 
 /* Standard type of suffix removal. */
 
-#define removesuffix() iremovesuffix(256)
+#define removesuffix() iremovesuffix(256, 0)
 
 /* Cut/kill buffer type.  The buffer itself is purely binary data, *
  * not NUL-terminated.  len is a length count.  flags uses the     *
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 97d012f7b..7ac4a7126 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -394,11 +394,13 @@ getkey(int keytmout)
     return ret;
 }
 
+static int no_restore_tty;
+
 /* Read a line.  It is returned metafied. */
 
 /**/
 unsigned char *
-zleread(char *lp, char *rp, int ha)
+zleread(char *lp, char *rp, int flags)
 {
     unsigned char *s;
     int old_errno = errno;
@@ -451,7 +453,7 @@ zleread(char *lp, char *rp, int ha)
     pmpt_attr = txtchange;
     rpromptbuf = promptexpand(rp, 1, NULL, NULL);
     rpmpt_attr = txtchange;
-    histallowed = ha;
+    histallowed = (flags & ZLRF_HISTORY);
     PERMALLOC {
 	histline = curhist;
 #ifdef HAVE_SELECT
@@ -486,6 +488,8 @@ zleread(char *lp, char *rp, int ha)
 	if (tmout)
 	    alarm(tmout);
 	zleactive = 1;
+	if (flags & ZLRF_NOSETTY)
+	  no_restore_tty = 1;
 	resetneeded = 1;
 	errflag = retflag = 0;
 	lastcol = -1;
@@ -535,7 +539,7 @@ zleread(char *lp, char *rp, int ha)
 	trashzle();
 	free(lpromptbuf);
 	free(rpromptbuf);
-	zleactive = 0;
+	zleactive = no_restore_tty = 0;
 	alarm(0);
     } LASTALLOC;
     zsfree(curhistline);
@@ -754,7 +758,7 @@ bin_vared(char *name, char **args, char *ops, int func)
     PERMALLOC {
 	pushnode(bufstack, ztrdup(s));
     } LASTALLOC;
-    t = (char *) zleread(p1, p2, ops['h']);
+    t = (char *) zleread(p1, p2, ops['h'] ? ZLRF_HISTORY : 0);
     if (!t || errflag) {
 	/* error in editing */
 	errflag = 0;
@@ -885,7 +889,8 @@ trashzle(void)
 	    fprintf(shout, "%s", postedit);
 	fflush(shout);
 	resetneeded = 1;
-	settyinfo(&shttyinfo);
+	if (!no_restore_tty)
+	  settyinfo(&shttyinfo);
     }
     if (errflag)
 	kungetct = 0;
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 1c25cd7eb..cf9aac435 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -42,7 +42,7 @@ doinsert(char *str)
     int neg = zmult < 0;             /* insert *after* the cursor? */
     int m = neg ? -zmult : zmult;    /* number of copies to insert */
 
-    iremovesuffix(c1);
+    iremovesuffix(c1, 0);
     invalidatelist();
 
     if(insmode)
@@ -849,7 +849,7 @@ makesuffixstr(char *f, char *s, int n)
 
 /**/
 void
-iremovesuffix(int c)
+iremovesuffix(int c, int keep)
 {
     if (suffixfunc) {
 	List l = getshfunc(suffixfunc);
@@ -876,7 +876,8 @@ iremovesuffix(int c)
 	int sl = suffixlen[c];
 	if(sl) {
 	    backdel(sl);
-	    invalidatelist();
+	    if (!keep)
+		invalidatelist();
 	}
     }
     fixsuffix();
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index f01ffbf1c..62c39fdc9 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -442,8 +442,7 @@ reversemenucomplete(void)
 		    menugrp = lmatches;
 	    } while (!menugrp->mcount);
 	    menucur = menugrp->matches + menugrp->mcount - 1;
-	}
-	else
+	} else
 	    menucur--;
 	metafy_line();
 	do_single(*menucur);
@@ -464,7 +463,11 @@ acceptandmenucomplete(void)
 	return;
     }
     if (brbeg && *brbeg) {
-	int l = (brscs >= 0 ? brscs : cs) - brpcs;
+	int l;
+
+	iremovesuffix(',', 1);
+
+	l = (brscs >= 0 ? brscs : cs) - brpcs;
 
 	zsfree(brbeg);
 	brbeg = (char *) zalloc(l + 2);
@@ -472,11 +475,8 @@ acceptandmenucomplete(void)
 	brbeg[l] = ',';
 	brbeg[l + 1] = '\0';
     } else {
-	int sl = suffixlen[' '];
-
 	cs = menupos + menulen + menuinsc;
-	if (sl)
-	    backdel(sl);
+	iremovesuffix(' ', 1);
 
 	inststrlen(" ", 1, 1);
 	menuinsc = menulen = 0;
@@ -894,21 +894,23 @@ docomplete(int lst)
 	     * change the command line, do completion.                  */
 	    if (olst == COMP_EXPAND_COMPLETE &&
 		!strcmp(ol, (char *)line)) {
-		char *p;
-
 		cs = ocs;
 		errflag = 0;
 
-		p = s;
-		if (*p == Tilde || *p == Equals)
-		    p++;
-		for (; *p; p++)
-		    if (itok(*p)) {
-			if (*p != String && *p != Qstring)
-			    *p = ztokens[*p - Pound];
-			else if (p[1] == Inbrace)
-			    p++, skipparens(Inbrace, Outbrace, &p);
-		    }
+		if (!compfunc) {
+		    char *p;
+
+		    p = s;
+		    if (*p == Tilde || *p == Equals)
+			p++;
+		    for (; *p; p++)
+			if (itok(*p)) {
+			    if (*p != String && *p != Qstring)
+				*p = ztokens[*p - Pound];
+			    else if (p[1] == Inbrace)
+				p++, skipparens(Inbrace, Outbrace, &p);
+			}
+		}
 		docompletion(s, lst, lincmd);
 	    }
 	} else
@@ -1244,16 +1246,20 @@ get_comp_string(void)
 	inpop();
 	errflag = zleparse = 0;
 	if (parbegin != -1) {
-	    /* We are in command or process substitution */
+	    /* We are in command or process substitution if we are not in
+	     * a $((...)). */
 	    if (parend >= 0 && !tmp)
 		line = (unsigned char *) dupstring(tmp = (char *)line);
 	    linptr = (char *) line + ll + addedx - parbegin + 1;
-	    if (parend >= 0) {
-		ll -= parend;
-		line[ll + addedx] = '\0';
+	    if ((linptr - (char *) line) < 2 ||
+		linptr[-1] != '(' || linptr[-2] != '$') {
+		if (parend >= 0) {
+		    ll -= parend;
+		    line[ll + addedx] = '\0';
+		}
+		lexrestore();
+		goto start;
 	    }
-	    lexrestore();
-	    goto start;
 	}
 
 	if (inwhat == IN_MATH)
@@ -1278,7 +1284,7 @@ get_comp_string(void)
 	    *s = sav;
 	    if (skipparens(Inbrack, Outbrack, &s) > 0 || s > tt + cs - wb)
 		s = NULL, inwhat = IN_MATH, insubscr = 1;
-	    else if (*s == '=') {
+	    else if (*s == '=' && cs > wb + (s - tt)) {
 		s++;
 		wb += s - tt;
 		t0 = STRING;
@@ -1315,25 +1321,23 @@ get_comp_string(void)
 	 * foo[_ wrong (note no $).  If we are in a subscript, treat it   *
 	 * as being in math.                                              */
 	if (inwhat != IN_MATH) {
-	    int i = 0, hn = 0;
-	    char *nb = (*s == String ? s + 1 : NULL), *ne = NULL;
+	    int i = 0;
+	    char *nb = (iident(*s) ? s : s + 1), *ne = NULL;
 
 	    for (tt = s; ++tt < s + cs - wb;)
-		if (*tt == String) {
-		    hn = 0;
-		    nb = tt + 1;
-		} else if (*tt == Inbrack) {
+		if (*tt == Inbrack) {
 		    i++;
-		    if (nb && !hn) {
-			hn = 1;
-			ne = tt;
-		    }
+		    ne = tt;
 		} else if (i && *tt == Outbrack)
 		    i--;
+		else if (!iident(*tt)) {
+		    nb = tt + 1;
+		    ne = NULL;
+		}
 	    if (i) {
 		inwhat = IN_MATH;
 		insubscr = 1;
-		if (hn && nb && ne) {
+		if (nb < ne) {
 		    char sav = *ne;
 		    *ne = '\0';
 		    zsfree(varname);
@@ -1353,6 +1357,19 @@ get_comp_string(void)
 	    s = zalloc(we - wb + 1);
 	    strncpy(s, (char *) line + wb, we - wb);
 	    s[we - wb] = '\0';
+	    if (wb > 2 && line[wb - 1] == '[' && iident(line[wb - 2])) {
+		int i = wb - 3;
+		unsigned char sav = line[wb - 1];
+
+		while (i >= 0 && iident(line[i]))
+		    i--;
+
+		line[wb - 1] = '\0';
+		zsfree(varname);
+		varname = ztrdup((char *) line + i + 1);
+		line[wb - 1] = sav;
+		insubscr = 1;
+	    }
 	}
 	/* This variable will hold the current word in quoted form. */
 	qword = ztrdup(s);
@@ -1599,8 +1616,7 @@ addtoword(char **rwp, int *rwlenp, char *nw,
 	    memcpy(np, rw, rwlen);
 	    nw += np - rw;
 	    zfree(rw, rwlen);
-	}
-	else
+	} else
 	    nw = np;
 	*rwp = rw = np;
 	rwlen = nl;
@@ -1609,8 +1625,7 @@ addtoword(char **rwp, int *rwlenp, char *nw,
     if (prep) {
 	memmove(rw + al, rw, rwlen - al);
 	memcpy(rw, as, al);
-    }
-    else
+    } else
 	memcpy(nw, as, al);
 
     return nw + al;
@@ -2348,7 +2363,7 @@ join_new_pfx(Cline line, int len, char *word, int *missp)
 	    /* The cline doesn't have a string built by reverse matching,
 	     * so we have to work on the original substring in the cline
 	     * and the new string. */
-	    if (line->wlen == len && strncmp(line->word, word, len)) {
+	    if (line->wlen == len && !strncmp(line->word, word, len)) {
 		/* They are equal, accept and return. If there was
 		 * another element in the list, shorten the list. */
 		if (next)
@@ -2793,7 +2808,7 @@ join_new_sfx(Cline line, int len, char *word, int *missp)
 		    ret = line;
 	    }
 	} else {
-	    if (line->wlen == len && strncmp(line->word, word - len, len)) {
+	    if (line->wlen == len && !strncmp(line->word, word - len, len)) {
 		if (next)
 		    miss = 1;
 		line->next = NULL;
@@ -2870,7 +2885,7 @@ bld_sfx(Cline o, Cline n)
 	o->suffix = join_new_sfx(o->suffix, n->wlen, n->word, &miss);
 	if (miss)
 	    o->flags |= CLF_MISS;
-    } else {
+    } else if (o->wlen && n->wlen) {
 	char so = o->word[o->wlen], sn = n->word[n->wlen];
 	char *new = o->word;
 	int newl = o->wlen, mol, mnl;
@@ -2896,7 +2911,8 @@ bld_sfx(Cline o, Cline n)
 
 	if (!o->suffix && n->wlen != o->wlen)
 	    o->flags |= CLF_MISS;
-    }
+    } else
+	o->wlen = 0;
 }
 
 /* Joins two Cline lists, building the most specific line string *
@@ -2909,7 +2925,7 @@ join_clines(Cline o, Cline n)
     Cline oo = o;
 
     if (!o)
-	/* This is the first time this was called, so just return the
+	/* This is the first time we are being called, so just return
 	 * the second list. In future calls we will get this list as
 	 * the first argument. */
 	return n;
@@ -3026,13 +3042,11 @@ join_clines(Cline o, Cline n)
 			o->word = NULL;
 			o->flags |= CLF_DIFF;
 		    }
-		}
-		else {
+		} else {
 		    o->word = NULL;
 		    o->flags |= CLF_DIFF;
 		}
-	    }
-	    else if (n->word)
+	    } else if (n->word)
 		o->flags |= CLF_DIFF;
 
 	    q = n->next;
@@ -3152,8 +3166,7 @@ merge_cline(Cline lc, char *p, int pl, char *s, int sl, int psl)
 	    pll -= sl - psl;
 	}
 	sll = strlen(s) - sl;
-    }
-    else
+    } else
 	sll = 0;
 
     pll -= pl;
@@ -3459,11 +3472,20 @@ match_pfx(char *l, char *w, Cline *nlp, int *lp, Cline *rlp, int *bplp)
 				 * characters are matched by the `*' pattern.
 				 * We do this by looping over the string
 				 * and calling this function recursively. */
-				int i = 0, j = iw, k = lw;
+				int i = 0, j = iw, k = lw, m = 0;
 				int jj = il + mp->llen, kk = ll - mp->llen;
 				char *p = l + mp->llen, *q = w;
 
 				for (; k; i++, j++, k--, q++) {
+				    if ((mp->flags & CMF_RIGHT) &&
+					(mp->right && k >= mp->ralen &&
+					 pattern_match(mp->right, q, 
+						       NULL, NULL))) {
+					if (m++) {
+					    k = 0;
+					    break;
+					}
+				    }
 				    if (match_pfx(p, q, NULL, NULL, NULL, NULL))
 					break;
 				}
@@ -3503,11 +3525,9 @@ match_pfx(char *l, char *w, Cline *nlp, int *lp, Cline *rlp, int *bplp)
 				    }
 				    lm = mp;
 				    break;
-				}
-				else
+				} else
 				    t = 0;
-			    }
-			    else
+			    } else
 				t = 0;
 			}
 		    } else {
@@ -3687,13 +3707,23 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp)
 				     !pattern_match(mp->left, w - mp->lalen,
 						    NULL, NULL));
 			    if (t) {
-				int i = 0, j = iw, k = lw;
+				int i = 0, j = iw, k = lw, m = 0;
 				int jj = il + mp->llen, kk = ll - mp->llen;
 				char *p = l - mp->llen - 1, *q = w - 1;
 
-				for (; k; i++, j++, k--, q--)
+				for (; k; i++, j++, k--, q--) {
+				    if ((mp->flags & CMF_LEFT) &&
+					(mp->left && k >= mp->lalen &&
+					 pattern_match(mp->left, q - mp->lalen, 
+						       NULL, NULL))) {
+					if (m++) {
+					    k = 0;
+					    break;
+					}
+				    }
 				    if (match_pfx(p, q, NULL, NULL, NULL, NULL))
 					break;
+				}
 				if (k && i) {
 				    if (nlp) {
 					nw = addtoword(&rw, &rwlen, nw, mp,
@@ -3718,8 +3748,7 @@ match_sfx(char *l, char *w, Cline *nlp, int *lp, int *bslp)
 				    }
 				    lm = mp;
 				    break;
-				}
-				else
+				} else
 				    t = 0;
 			    }
 			}
@@ -3865,8 +3894,7 @@ comp_match(char *pfx, char *sfx, char *w, Cline *clp, int qu, int *bpl, int *bsl
 
 		return NULL;
 	    }
-	}
-	else
+	} else
 	    return NULL;
     } else if (!(r = match_pfx(pfx, w, &pli, &pl, NULL, bpl)))
 	/* We had only the prefix to match and that didn't match. */
@@ -4205,12 +4233,14 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 		t = s;
 		if (ppre)
 		    t = dyncat(ppre, t);
-		lc = NULL;
 		if (!cp && !ms && (mstack || psuf)) {
 		    int bl = ((aflags & CAF_MATCH) ? llpl : 0);
 		    Cline *clp = &lc, tlc;
 		    char *ss = dupstring(s), *ee = me + (ss - s);
 
+		    DPUTS(me < s || me > s + sl,
+			  "BUG: invalid end-pointer (me)");
+
 		    if (ppre && *ppre) {
 			*clp = tlc = getcline(NULL, 0, ppre, lpl, CLF_VAR);
 			clp = &(tlc->next);
@@ -4245,9 +4275,13 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 			lc = tlc;
 		    }
 		    if (psuf && *psuf) {
-			for (tlc = lc; tlc->next; tlc = tlc->next);
-			tlc->next = getcline(NULL, 0, psuf, lsl,
-					     CLF_END | CLF_VAR);
+			if (lc) {
+			    for (tlc = lc; tlc->next; tlc = tlc->next);
+			    tlc->next = getcline(NULL, 0, psuf, lsl,
+						 CLF_END | CLF_VAR);
+			} else
+			    lc = getcline(NULL, 0, psuf, lsl,
+					  CLF_END | CLF_VAR);
 		    }
 		}
 		if (ipre && *ipre) {
@@ -4402,7 +4436,7 @@ addmatch(char *s, char *t)
 	    return;
 
 	if ((addwhat == CC_FILES ||
-	     addwhat == -5) && !*psuf && !*fsuf) {
+	     addwhat == -5) && !*psuf) {
 	    /* If this is a filename, do the fignore check. */
 	    char **pt = fignore;
 	    int filell;
@@ -4559,6 +4593,8 @@ addmatch(char *s, char *t)
 	Cline *clp = &lc, tlc;
 	char *ss = dupstring(s), *ee = e + (ss - s);
 
+	DPUTS(e < s || e > s + sl, "BUG: invalid end-pointer (e)");
+
 	if (lppre && *lppre) {
 	    *clp = str_cline(lppre, strlen(lppre), &tlc);
 	    clp = &(tlc->next);
@@ -4628,19 +4664,16 @@ addmatch(char *s, char *t)
 	if (lpsuf && *lpsuf && strsfx(lpsuf, s)) {
 	    s[sl - lpsl] = '\0';
 	    cm->psuf = lpsuf;
-	}
-	else
+	} else
 	    cm->psuf = NULL;
 
 	if (lppre && *lppre && strpfx(lppre, s)) {
 	    s += lppl;
 	    cm->ppre = lppre;
 	    cm->prpre = (isf && prpre && *prpre ? prpre : NULL);
-	}
-	else
+	} else
 	    cm->ppre = cm->prpre = NULL;
-    }
-    else {
+    } else {
 	cm->ppre = (lppre && *lppre ? lppre : NULL);
 	cm->psuf = (lpsuf && *lpsuf ? lpsuf : NULL);
 	cm->prpre = (isf && prpre && *prpre ? prpre : NULL);
@@ -5013,6 +5046,8 @@ docompletion(char *s, int lst, int incmd)
 		    (isset(LISTAMBIGUOUS) ? 3 : 2) : 0) : 1);
 	zsfree(comppatmatch);
 	comppatmatch = ztrdup(useglob ? "yes" : "");
+	zsfree(compforcelist);
+	compforcelist = ztrdup("");
 	haspattern = 0;
 
 	/* Make sure we have the completion list and compctl. */
@@ -5022,6 +5057,8 @@ docompletion(char *s, int lst, int incmd)
 	    clearlist = 1;
 	    goto compend;
 	}
+	if (comppatmatch && *comppatmatch)
+	    haspattern = 1;
 	if (!useline && uselist)
 	    /* All this and the guy only wants to see the list, sigh. */
 	    showinglist = -2;
@@ -5106,7 +5143,7 @@ callcompfunc(char *s, char *fn)
 	comppms = (Param *) zalloc(CP_NUM * sizeof(Param));
 
 	set = -1 & ~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING |
-		     CP_EXACTSTR | (useglob ? 0 : CP_PATMATCH));
+		     CP_EXACTSTR | CP_FORCELIST | (useglob ? 0 : CP_PATMATCH));
 	zsfree(compcontext);
 	zsfree(compparameter);
 	zsfree(compredirect);
@@ -5200,19 +5237,23 @@ callcompfunc(char *s, char *fn)
 	    compquote = ztrdup("");
 	    compquoting = ztrdup("");
 	}
-	untokenize(s = dupstring(s));
 	zsfree(compprefix);
 	zsfree(compsuffix);
 	if (unset(COMPLETEINWORD)) {
-	    compprefix = ztrdup(s);
+	    tmp = quotename(s, NULL, NULL, NULL);
+	    untokenize(tmp);
+	    compprefix = ztrdup(tmp);
 	    compsuffix = ztrdup("");
 	} else {
 	    char *ss = s + offs, sav;
-
+	    
+	    tmp = quotename(s, &ss, NULL, NULL);
 	    sav = *ss;
 	    *ss = '\0';
-	    compprefix = ztrdup(s);
+	    untokenize(tmp);
+	    compprefix = ztrdup(tmp);
 	    *ss = sav;
+	    untokenize(ss);
 	    compsuffix = ztrdup(ss);
 	}
 	zsfree(compiprefix);
@@ -5315,7 +5356,7 @@ makecomplist(char *s, int incmd, int lst)
     char *p, *os = s;
 
     /* Inside $... ? */
-    if ((p = check_param(s, 0)))
+    if (compfunc && (p = check_param(s, 0)))
 	os = s = p;
 
     /* We build a copy of the list of matchers to use to make sure that this
@@ -5416,6 +5457,32 @@ makecomplist(char *s, int incmd, int lst)
 /* This should probably be moved into tokenize(). */
 
 /**/
+static char *
+ctokenize(char *p)
+{
+    char *r = p;
+    int bslash = 0;
+
+    tokenize(p);
+
+    for (p = r; *p; p++) {
+	if (*p == '\\')
+	    bslash = 1;
+	else {
+	    if (*p == '$' || *p == '{' || *p == '}') {
+		if (bslash)
+		    p[-1] = Bnull;
+		else
+		    *p = (*p == '$' ? String :
+			  (*p == '{' ? Inbrace : Outbrace));
+	    }
+	    bslash = 0;
+	}
+    }
+    return r;
+}
+
+/**/
 char *
 comp_str(int *ipl, int *pl, int untok)
 {
@@ -5426,11 +5493,11 @@ comp_str(int *ipl, int *pl, int untok)
     int lp, ls, lip;
 
     if (!untok) {
-	tokenize(p);
+	ctokenize(p);
 	remnulargs(p);
-	tokenize(s);
+	ctokenize(s);
 	remnulargs(s);
-	tokenize(ip);
+	ctokenize(ip);
 	remnulargs(ip);
     }
     ls = strlen(s);
@@ -5964,8 +6031,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
     if (cc->explain) {
 	expl = (Cexpl) zhalloc(sizeof(struct cexpl));
 	expl->count = expl->fcount = 0;
-    }
-    else
+    } else
 	expl = NULL;
     /* compadd is the number of characters we have to ignore at the  *
      * beginning of the word.                                        */
@@ -5980,8 +6046,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	    uremnode(ccstack, firstnode(ccstack));
 	    return;
 	}
-    }
-    else
+    } else
 	ipre = NULL;
 
     if (cc->matcher) {
@@ -6159,12 +6224,14 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	    if ((p = strrchr(lppre, '/'))) {
 		p[1] = '\0';
 		lppl = strlen(lppre);
-	    } else {
+	    } else if (!sf1) {
 		lppre = NULL;
 		lppl = 0;
+	    } else {
+		lppre = ppre;
+		lppl = strlen(lppre);
 	    }
-	}
-	else {
+	} else {
 	    lppre = NULL;
 	    lppl = 0;
 	}
@@ -6179,10 +6246,10 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 
 		strcpy(p, p + strlen(brend));
 	    }
-	    lpsuf = strchr(lpsuf, '/');
+	    if (!(lpsuf = strchr(lpsuf, '/')) && sf2)
+		lpsuf = psuf;
 	    lpsl = (lpsuf ? strlen(lpsuf) : 0);
-	}
-	else {
+	} else {
 	    lpsuf = NULL;
 	    lpsl = 0;
 	}
@@ -6244,7 +6311,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 		opts[NULLGLOB] = 1;
 
 		addwhat = 0;
-		p = (char *)ncalloc(lpl + lsl + 3);
+		p = (char *)zhalloc(lpl + lsl + 3);
 		strcpy(p, lpre);
 		if (*lsuf != '*' && *lpre && lpre[lpl - 1] != '*')
 		    strcat(p, "*");
@@ -6696,8 +6763,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 
 		    sprintf(p, "%s%s%s", m->ppre, m->str, m->psuf);
 		    addlinknode(args, dupstring(p));
-		}
-		else
+		} else
 		    addlinknode(args, dupstring(m->str));
 	    }
 
@@ -6725,8 +6791,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	else
 	    endcmgroup(NULL);
 	begcmgroup("default", 0);
-    }
-    else if ((tt = cc->explain)) {
+    } else if ((tt = cc->explain)) {
 	tt = dupstring(tt);
 	if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
 	    singsub(&tt);
@@ -6949,8 +7014,7 @@ makearray(LinkList l, int s, int *np, int *nlp)
 	    ap = bp;
 	}
 	*cp = NULL;
-    }
-    else if (s) {
+    } else if (s) {
 	/* Now sort the array (it contains matches). */
 	qsort((void *) rp, n, sizeof(Cmatch),
 	      (int (*) _((const void *, const void *)))matchcmp);
@@ -7153,8 +7217,7 @@ permmatches(void)
 		e->str = ztrdup(o->str);
 	    }
 	    *ep = NULL;
-	}
-	else
+	} else
 	    n->expls = NULL;
 
 	if ((n->ccount = g->ccount)) {
@@ -7163,8 +7226,7 @@ permmatches(void)
 	    for (cq = g->ccs; *cq; cq++, cp++)
 		*cp = *cq;
 	    *cp = NULL;
-	}
-	else
+	} else
 	    n->ccs = NULL;
 	g = g->next;
     }
@@ -7306,8 +7368,11 @@ do_ambiguous(void)
 	    ls = ainfo->csl;
 	}
 	if (lc) {
+	    if (!ps)
+		ps = "";
 	    if (lp) {
 		if (ls) {
+		    DPUTS(!ainfo->firstm, "BUG: merge without firtsm");
 		    if (ainfo->firstm->psuf)
 			merge_cline(lc, ps, lp,
 				    dyncat(ainfo->firstm->str,
@@ -7329,11 +7394,13 @@ do_ambiguous(void)
 		ocs += l;
 		cs = ocs;
 	    }
-	    if(ainfo->suflen && !atend)
+	    if(ainfo->suflen && !atend) {
+		DPUTS(!ainfo->firstm, "BUG: suffix without firstm");
 		inststrlen(ainfo->firstm->str +
 			   strlen(ainfo->firstm->str) - ainfo->suflen, 1,
 			   ainfo->suflen);
-	    if (ainfo->firstm->psuf)
+	    }
+	    if (ainfo->firstm && ainfo->firstm->psuf)
 		inststrlen(ainfo->firstm->psuf, 0, -1);
 	    if (brend && *brend) {
 		cs -= brsl;
@@ -7374,7 +7441,8 @@ do_ambiguous(void)
      * if it is needed.                                                     */
     if (isset(LISTBEEP))
 	feep();
-    if (uselist && usemenu != 2 && !showinglist && smatches >= 2)
+    if (uselist && usemenu != 2 && !showinglist &&
+	(smatches >= 2 || (compforcelist && *compforcelist)))
 	showinglist = -2;
 }
 
@@ -7484,13 +7552,11 @@ do_single(Cmatch m)
 		    sprintf(p, "%s%s%s", m->ripre, str, psuf);
 		    if (pl && p[pl-1] == Inbrace)
 			strcpy(p+pl-1, p+pl);
-		}
-		else if (ic) {
+		} else if (ic) {
 		    p = (char *) ncalloc(strlen(ppre) + strlen(str) +
 					 strlen(psuf) + 2);
 		    sprintf(p, "%c%s%s%s", ic, ppre, str, psuf);
-		}
-		else {
+		} else {
 		    p = (char *) ncalloc(strlen(ppre) + strlen(str) +
 					 strlen(psuf) + 1);
 		    sprintf(p, "%s%s%s", ppre, str, psuf);
@@ -7744,8 +7810,7 @@ listmatches(void)
 		    pp++;
 		}
 		nlines--;
-	    }
-	    else {
+	    } else {
 		while (*pp) {
 		    if ((l = strlen(*pp)) > longest)
 			longest = l;
@@ -7753,8 +7818,7 @@ listmatches(void)
 		    pp++;
 		}
 	    }
-	}
-	else {
+	} else {
 	    for (p = g->matches; (m = *p); p++) {
 		if (!(m->flags & CMF_NOLIST)) {
 		    if ((l = niceztrlen(m->str)) > longest)
@@ -7851,8 +7915,7 @@ listmatches(void)
 		    if (*++pp)
 			putc('\n', shout);
 		}
-	    }
-	    else {
+	    } else {
 		int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, a;
 		char **pq;
 
@@ -7876,8 +7939,7 @@ listmatches(void)
 		    pp++;
 		}
 	    }
-	}
-	else if (g->lcount) {
+	} else if (g->lcount) {
 	    int n = g->lcount, nl = (n + ncols - 1) / ncols, nc = nl, i, j, a = 0;
 	    Cmatch *q;
 
@@ -7938,8 +8000,7 @@ listmatches(void)
 	    showinglist = -1;
 	} else
 	    clearflag = 0, putc('\n', shout);
-    }
-    else
+    } else
 	putc('\n', shout);
 }
 
diff --git a/Src/glob.c b/Src/glob.c
index 738753377..56e0ac133 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -2304,26 +2304,25 @@ getmatch(char **sp, char *pat, int fl, int n, char *replstr)
     case SUB_LONG:
 	/*
 	 * Largest/smallest possible match at head of string.
-	 * First get the longest match.
+	 * First get the longest match...
 	 */
 	if (dolongestmatch(s, c, 0)) {
 	    char *mpos = pptr;
-	    while (!(fl & SUB_LONG) && pptr > s) {
-		/*
-		 * If we want the shortest, keep backing up to the
-		 * previous character and find the longest up to there.
-		 * That way we can usually reach the shortest in only
-		 * a few attempts.
-		 */
-		t = (pptr > s + 1 && pptr[-2] == Meta) ? pptr - 2 : pptr -1;
+	    if (!(fl & SUB_LONG)) {
+	      /*
+	       * ... now we know whether it's worth looking for the
+	       * shortest, which we do by brute force.
+	       */
+	      for (t = s; t < mpos; METAINC(t)) {
 		sav = *t;
 		*t = '\0';
-		if (!dolongestmatch(s, c, 0)) {
-		    *t = sav;
-		    break;
+		if (dolongestmatch(s, c, 0)) {
+		  mpos = pptr;
+		  *t = sav;
+		  break;
 		}
-		mpos = pptr;
 		*t = sav;
+	      }
 	    }
 	    *sp = get_match_ret(*sp, 0, mpos-s, fl, replstr);
 	    return 1;
diff --git a/Src/hist.c b/Src/hist.c
index d77b2febd..e104e1f3e 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -735,6 +735,8 @@ hend(void)
     int flag, save = 1;
 
     DPUTS(!chline, "BUG: chline is NULL in hend()");
+    if (histdone & HISTFLAG_SETTY)
+	settyinfo(&shttyinfo);
     if (histactive & (HA_NOSTORE|HA_NOINC)) {
 	zfree(chline, hlinesz);
 	zfree(chwords, chwordlen*sizeof(short));
diff --git a/Src/init.c b/Src/init.c
index d66d157c9..ab955b26a 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -792,7 +792,11 @@ run_init_scripts(void)
 void
 init_misc(void)
 {
+#ifndef RESTRICTED_R
+    if ( restricted )
+#else
     if (*zsh_name == 'r' || restricted)
+#endif
 	dosetopt(RESTRICTED, 1, 0);
     if (cmd) {
 	if (SHIN >= 10)
diff --git a/Src/input.c b/Src/input.c
index 66a21000c..6e62ce2c7 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -249,8 +249,21 @@ inputline(void)
 	    free(pptbuf);
 	}
 	ingetcline = shingetline();
-    } else
-	ingetcline = (char *)zleread(ingetcpmptl, ingetcpmptr, 1);
+    } else {
+	/*
+	 * Since we may have to read multiple lines before getting
+	 * a complete piece of input, we tell zle not to restore the
+	 * original tty settings after reading each chunk.  Instead,
+	 * this is done when the history mechanism for the current input
+	 * terminates, which is not until we have the whole input.
+	 * This is supposed to minimise problems on systems that clobber
+	 * typeahead when the terminal settings are altered.
+	 *                     pws 1998/03/12
+	 */
+	ingetcline = (char *)zleread(ingetcpmptl, ingetcpmptr,
+				     ZLRF_HISTORY|ZLRF_NOSETTY);
+	histdone |= HISTFLAG_SETTY;
+    }
     if (!ingetcline) {
 	return lexstop = 1;
     }
diff --git a/Src/options.c b/Src/options.c
index 693132494..bfe146e1e 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -522,11 +522,20 @@ bin_setopt(char *nam, char **args, char *ops, int isun)
 	/* Globbing option (-m) set. */
 	while (*args) {
 	    Comp com;
+	    char *s, *t;
+
+	    t = s = dupstring(*args);
+	    while (*t)
+		if (*t == '_')
+		    chuck(t);
+		else {
+		    *t = tulower(*t);
+		    t++;
+		}
 
 	    /* Expand the current arg. */
-	    tokenize(*args);
-	    if (!(com = parsereg(*args))) {
-		untokenize(*args);
+	    tokenize(s);
+	    if (!(com = parsereg(s))) {
 		zwarnnam(nam, "bad pattern: %s", *args, 0);
 		continue;
 	    }
diff --git a/Src/signames2.awk b/Src/signames2.awk
index 3aea76ee3..51cda0f10 100644
--- a/Src/signames2.awk
+++ b/Src/signames2.awk
@@ -6,7 +6,7 @@
 # NB: On SunOS 4.1.3 - user-functions don't work properly, also \" problems
 # Without 0 + hacks some nawks compare numbers as strings
 #
-/^XXNAMES XXSIG[A-Z][A-Z0-9]* [1-9][0-9]*/ {
+/^XXNAMES XXSIG[A-Z][A-Z0-9]*[\t ][\t ]*[1-9][0-9]*/ {
     sigindex = index($0, "SIG")
     sigtail = substr($0, sigindex, 80)
     split(sigtail, tmp)
diff --git a/Src/subst.c b/Src/subst.c
index 6445776d1..42e8e36d4 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -263,7 +263,7 @@ multsub(char **s, char ***a, int *isarr, char *sep)
 	    *isarr = 0;
 	return 0;
     }
-    if ((l = countlinknodes(foo)) > 1) {
+    if ((l = countlinknodes(foo)) > 1 || a) {
 	p = r = ncalloc((l + 1) * sizeof(char*));
 	while (nonempty(foo))
 	    *p++ = (char *)ugetnode(foo);
@@ -976,7 +976,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
 	sav = *s;
 	*s = 0;
-	if (multsub(&val, (aspar ? NULL : &aval), &isarr, NULL) && quoted) {
+	if (multsub(&val, (((quoted || aspar) && !nojoin) ? NULL : &aval),
+		    &isarr, NULL) &&
+	    quoted) {
 	    isarr = -1;
 	    aval = alloc(sizeof(char *));
 	    aspar = 0;
diff --git a/Src/zsh.h b/Src/zsh.h
index fa5b5632c..d0b566e3f 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1013,7 +1013,7 @@ struct histent {
 #define HISTFLAG_DONE   1
 #define HISTFLAG_NOEXEC 2
 #define HISTFLAG_RECALL 4
-
+#define HISTFLAG_SETTY  8
 
 /******************************************/
 /* Definitions for programable completion */
@@ -1403,6 +1403,13 @@ struct heap {
 #define ZSIG_IGNORED	(1<<1)
 #define ZSIG_FUNC	(1<<2)
 
+/**********************************/
+/* Flags to third argument of zle */
+/**********************************/
+
+#define ZLRF_HISTORY	0x01
+#define ZLRF_NOSETTY	0x02
+
 /****************/
 /* Entry points */
 /****************/
diff --git a/acconfig.h b/acconfig.h
index bcd111c8c..1e0473557 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -158,6 +158,11 @@
  * hash tables.  This turns on the `hashinfo' builtin.              */
 #undef ZSH_HASH_DEBUG
 
+/* Undefine this if you don't want to get a restricted shell *
+ * when zsh is exec'd with basename that starts with r.      *
+ * By default this is defined.                               */
+#undef RESTRICTED_R
+
 /* Define to 1 if your termcap library has the ospeed variable */
 #undef HAVE_OSPEED
 /* Define to 1 if you have ospeed, but it is not defined in termcap.h */
diff --git a/config.guess b/config.guess
index 0d66b2e56..2960d6e0d 100755
--- a/config.guess
+++ b/config.guess
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+#   Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
 #
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -52,11 +52,53 @@ trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
 	# A Vn.n version is a released version.
 	# A Tn.n version is a released field test version.
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
-	echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
+	cat <<EOF >dummy.s
+	.globl main
+	.ent main
+main:
+	.frame \$30,0,\$26,0
+	.prologue 0
+	.long 0x47e03d80 # implver $0
+	lda \$2,259
+	.long 0x47e20c21 # amask $2,$1
+	srl \$1,8,\$2
+	sll \$2,2,\$2
+	sll \$0,3,\$0
+	addl \$1,\$0,\$0
+	addl \$2,\$0,\$0
+	ret \$31,(\$26),1
+	.end main
+EOF
+	${CC-cc} dummy.s -o dummy 2>/dev/null
+	if test "$?" = 0 ; then
+		./dummy
+		case "$?" in
+			7)
+				UNAME_MACHINE="alpha"
+				;;
+			15)
+				UNAME_MACHINE="alphaev5"
+				;;
+			14)
+				UNAME_MACHINE="alphaev56"
+				;;
+			10)
+				UNAME_MACHINE="alphapca56"
+				;;
+			16)
+				UNAME_MACHINE="alphaev6"
+				;;
+		esac
+	fi
+	rm -f dummy.s dummy
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
 	exit 0 ;;
     21064:Windows_NT:50:3)
 	echo alpha-dec-winnt3.5
@@ -68,15 +110,39 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
       echo m68k-cbm-netbsd${UNAME_RELEASE}
       exit 0 ;;
     amiga:OpenBSD:*:*)
-      echo m68k-cbm-openbsd${UNAME_RELEASE}
-      exit 0 ;;
-    sa110:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-	echo arm-unknown-linux
-	exit 0;;
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    arc64:OpenBSD:*:*)
+	echo mips64el-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hkmips:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mips-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
 	exit 0;;
-    Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+    arm32:NetBSD:*:*)
+	echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+	exit 0 ;;
+    SR2?01:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*)
 	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
 	if test "`(/bin/universe) 2>/dev/null`" = att ; then
 		echo pyramid-pyramid-sysv3
@@ -87,6 +153,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     NILE:*:*:dcosx)
 	echo pyramid-pyramid-svr4
 	exit 0 ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
 	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit 0 ;;
@@ -111,6 +180,18 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     sun3*:SunOS:*:*)
 	echo m68k-sun-sunos${UNAME_RELEASE}
 	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
     aushp:SunOS:*:*)
 	echo sparc-auspex-sunos${UNAME_RELEASE}
 	exit 0 ;;
@@ -118,23 +199,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	echo m68k-atari-netbsd${UNAME_RELEASE}
 	exit 0 ;;
     atari*:OpenBSD:*:*)
-	echo m68k-atari-openbsd${UNAME_RELEASE}
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
     sun3*:NetBSD:*:*)
 	echo m68k-sun-netbsd${UNAME_RELEASE}
 	exit 0 ;;
     sun3*:OpenBSD:*:*)
-	echo m68k-sun-openbsd${UNAME_RELEASE}
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
     mac68k:NetBSD:*:*)
 	echo m68k-apple-netbsd${UNAME_RELEASE}
 	exit 0 ;;
     mac68k:OpenBSD:*:*)
-	echo m68k-apple-openbsd${UNAME_RELEASE}
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
 	exit 0 ;;
     powerpc:machten:*:*)
 	echo powerpc-apple-machten${UNAME_RELEASE}
 	exit 0 ;;
+    macppc:NetBSD:*:*)
+        echo powerpc-apple-netbsd${UNAME_RELEASE}
+        exit 0 ;;
     RISC*:Mach:*:*)
 	echo mips-dec-mach_bsd4.3
 	exit 0 ;;
@@ -144,6 +234,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     VAX*:ULTRIX*:*:*)
 	echo vax-dec-ultrix${UNAME_RELEASE}
 	exit 0 ;;
+    2020:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
     mips:*:*:UMIPS | mips:*:*:RISCos)
 	sed 's/^	//' << EOF >dummy.c
 	int main (argc, argv) int argc; char **argv; {
@@ -237,7 +330,8 @@ EOF
 	fi
 	exit 0 ;;
     *:AIX:*:4)
-	if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
 		IBM_ARCH=rs6000
 	else
 		IBM_ARCH=powerpc
@@ -270,12 +364,44 @@ EOF
     hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
 	echo m68k-hp-bsd4.4
 	exit 0 ;;
-    9000/[3478]??:HP-UX:*:*)
+    9000/[34678]??:HP-UX:*:*)
 	case "${UNAME_MACHINE}" in
 	    9000/31? )            HP_ARCH=m68000 ;;
 	    9000/[34]?? )         HP_ARCH=m68k ;;
-	    9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
-	    9000/8?? )            HP_ARCH=hppa1.0 ;;
+	    9000/6?? | 9000/7?? | 9000/80[24] | 9000/8?[13679] | 9000/892 )
+              sed 's/^              //' << EOF >dummy.c
+              #include <stdlib.h>
+              #include <unistd.h>
+              
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif 
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+              
+                  switch (cpu) 
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0: 
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits) 
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif 
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+	(${CC-cc} dummy.c -o dummy 2>/dev/null ) && HP_ARCH=`./dummy`
+	rm -f dummy.c dummy
 	esac
 	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
 	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
@@ -378,8 +504,11 @@ EOF
     hp3[0-9][05]:NetBSD:*:*)
 	echo m68k-hp-netbsd${UNAME_RELEASE}
 	exit 0 ;;
-    hp3[0-9][05]:OpenBSD:*:*)
-	echo m68k-hp-openbsd${UNAME_RELEASE}
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
 	exit 0 ;;
     i?86:BSD/386:*:* | *:BSD/OS:*:*)
 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -394,54 +523,146 @@ EOF
 	echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
 	exit 0 ;;
     i*:CYGWIN*:*)
-	echo i386-pc-cygwin32
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
 	exit 0 ;;
     p*:CYGWIN*:*)
-	echo powerpcle-unknown-cygwin32
+	echo powerpcle-unknown-cygwin
 	exit 0 ;;
     prep*:SunOS:5.*:*)
 	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit 0 ;;
     *:GNU:*:*)
-	echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
 	exit 0 ;;
     *:Linux:*:*)
+	# uname on the ARM produces all sorts of strangeness, and we need to
+	# filter it out.
+	case "$UNAME_MACHINE" in
+	  arm* | sa110*)	      UNAME_MACHINE="arm" ;;
+	esac
+
 	# The BFD linker knows what the default object file format is, so
 	# first see if it will tell us.
 	ld_help_string=`ld --help 2>&1`
-	if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then
-	  echo "${UNAME_MACHINE}-pc-linux" ; exit 0
-	elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32arm"; then
-	  echo "arm-unknown-linux" ; exit 0
-	elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then
-	  echo "${UNAME_MACHINE}-pc-linuxaout" ; exit 0
-	elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then
-	  echo "${UNAME_MACHINE}-pc-linuxcoff" ; exit 0
-	elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
-	  echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
-	elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
-	  echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
-	elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then
-	  echo "powerpc-unknown-linux" ; exit 0
-	elif test "${UNAME_MACHINE}" = "alpha" ; then
-	  echo alpha-unknown-linux ; exit 0
-	elif test "${UNAME_MACHINE}" = "sparc" ; then
-	  echo sparc-unknown-linux ; exit 0
+	ld_supported_emulations=`echo $ld_help_string \
+			 | sed -ne '/supported emulations:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported emulations: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_emulations" in
+	  i?86linux)  echo "${UNAME_MACHINE}-pc-linux-gnuaout"      ; exit 0 ;;
+	  i?86coff)   echo "${UNAME_MACHINE}-pc-linux-gnucoff"      ; exit 0 ;;
+	  sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+	  armlinux)   echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+	  m68klinux)  echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+	  elf32ppc)   echo "powerpc-unknown-linux-gnu"              ; exit 0 ;;
+	esac
+
+	if test "${UNAME_MACHINE}" = "alpha" ; then
+		sed 's/^	//'  <<EOF >dummy.s
+		.globl main
+		.ent main
+	main:
+		.frame \$30,0,\$26,0
+		.prologue 0
+		.long 0x47e03d80 # implver $0
+		lda \$2,259
+		.long 0x47e20c21 # amask $2,$1
+		srl \$1,8,\$2
+		sll \$2,2,\$2
+		sll \$0,3,\$0
+		addl \$1,\$0,\$0
+		addl \$2,\$0,\$0
+		ret \$31,(\$26),1
+		.end main
+EOF
+		LIBC=""
+		${CC-cc} dummy.s -o dummy 2>/dev/null
+		if test "$?" = 0 ; then
+			./dummy
+			case "$?" in
+			7)
+				UNAME_MACHINE="alpha"
+				;;
+			15)
+				UNAME_MACHINE="alphaev5"
+				;;
+			14)
+				UNAME_MACHINE="alphaev56"
+				;;
+			10)
+				UNAME_MACHINE="alphapca56"
+				;;
+			16)
+				UNAME_MACHINE="alphaev6"
+				;;
+			esac	
+
+			objdump --private-headers dummy | \
+			  grep ld.so.1 > /dev/null
+			if test "$?" = 0 ; then
+				LIBC="libc1"
+			fi
+		fi	
+		rm -f dummy.s dummy
+		echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
+	elif test "${UNAME_MACHINE}" = "mips" ; then
+	  cat >dummy.c <<EOF
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+#ifdef __MIPSEB__
+  printf ("%s-unknown-linux-gnu\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+  printf ("%sel-unknown-linux-gnu\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+	  ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+	  rm -f dummy.c dummy
 	else
-	  # Either a pre-BFD a.out linker (linuxoldld) or one that does not give us
-	  # useful --help.  Gcc wants to distinguish between linuxoldld and linuxaout.
-	  test ! -d /usr/lib/ldscripts/. \
-	    && echo "${UNAME_MACHINE}-pc-linuxoldld" && exit 0
+	  # Either a pre-BFD a.out linker (linux-gnuoldld)
+	  # or one that does not give us useful --help.
+	  # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
+	  # If ld does not provide *any* "supported emulations:"
+	  # that means it is gnuoldld.
+	  echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
+	  test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+
+	  case "${UNAME_MACHINE}" in
+	  i?86)
+	    VENDOR=pc;
+	    ;;
+	  *)
+	    VENDOR=unknown;
+	    ;;
+	  esac
 	  # Determine whether the default compiler is a.out or elf
 	  cat >dummy.c <<EOF
+#include <features.h>
 main(argc, argv)
-int argc;
-char *argv[];
+     int argc;
+     char *argv[];
 {
 #ifdef __ELF__
-  printf ("%s-pc-linux\n", argv[1]);
+# ifdef __GLIBC__
+#  if __GLIBC__ >= 2
+    printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
+#  else
+    printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+#  endif
+# else
+   printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
 #else
-  printf ("%s-pc-linuxaout\n", argv[1]);
+  printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
 #endif
   return 0;
 }
@@ -454,6 +675,14 @@ EOF
     i?86:DYNIX/ptx:4*:*)
 	echo i386-sequent-sysv4
 	exit 0 ;;
+    i?86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
     i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
 	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
 		echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
@@ -475,6 +704,18 @@ EOF
 		echo ${UNAME_MACHINE}-pc-sysv32
 	fi
 	exit 0 ;;
+    i?86:UnixWare:*:*)
+	if /bin/uname -X 2>/dev/null >/dev/null ; then
+	  (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+	    && UNAME_MACHINE=i586
+	fi
+	echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION}
+	exit 0 ;;
+    pc:*:*:*)
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
     Intel:Mach:3*:*)
 	echo i386-pc-mach3
 	exit 0 ;;
@@ -526,9 +767,6 @@ EOF
     RM*:SINIX-*:*:*)
 	echo mips-sni-sysv4
 	exit 0 ;;
-    RM*:ReliantUNIX-*:*:*)
-	echo mips-sni-sysv4
-	exit 0 ;;
     *:SINIX-*:*:*)
 	if uname -p 2>/dev/null >/dev/null ; then
 		UNAME_MACHINE=`(uname -p) 2>/dev/null`
@@ -537,6 +775,10 @@ EOF
 		echo ns32k-sni-sysv
 	fi
 	exit 0 ;;
+    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                           # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
     *:UNIX_System_V:4*:FTX*)
 	# From Gerald Hewes <hewes@openmarket.com>.
 	# How about differentiating between stratus architectures? -djm
@@ -549,23 +791,25 @@ EOF
     mc68*:A/UX:*:*)
 	echo m68k-apple-aux${UNAME_RELEASE}
 	exit 0 ;;
-    R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+    news*:NEWS-OS:*:6*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*)
 	if [ -d /usr/nec ]; then
 	        echo mips-nec-sysv${UNAME_RELEASE}
 	else
 	        echo mips-unknown-sysv${UNAME_RELEASE}
 	fi
         exit 0 ;;
-    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                           # says <Richard.M.Bartel@ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit 0 ;;
-    Power*:Rhapsody:*:*)
-        echo powerpc-apple-rhapsody${UNAME_RELEASE}
-        exit 0 ;;
-    *:Rhapsody:*:*)
-        echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
-        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
diff --git a/configure.in b/configure.in
index 5cfaec326..11aab932d 100644
--- a/configure.in
+++ b/configure.in
@@ -185,6 +185,16 @@ AC_ARG_ENABLE(ansi2knr,
 [  --enable-ansi2knr          translate source to K&R C before compiling],
 [ansi2knr="$enableval"], [ansi2knr=default])
 
+dnl Do you want to disable restricted on r* commands
+undefine([resticted-r])dnl
+AC_ARG_ENABLE(resticted-r,
+[  --disable-resticted-r      turn off restricted shell if the invoked command is r*],
+[if test x$enableval = xyes; then
+  AC_DEFINE(RESTRICTED_R)
+fi],
+AC_DEFINE(RESTRICTED_R)
+)
+
 dnl ------------------
 dnl CHECK THE COMPILER
 dnl ------------------
@@ -766,7 +776,7 @@ if test $zsh_cv_rlim_t_is_longer = yes; then
 #include <sys/resource.h>
 main() { 
   struct rlimit r;
-  char buf[[20]];
+  char buf[20];
   r.rlim_cur = 0;
   sprintf(buf, "%qd", r.rlim_cur);
   exit(strcmp(buf, "0"));
@@ -774,7 +784,7 @@ main() {
   zsh_cv_rlim_t_is_quad_t=yes,
   zsh_cv_rlim_t_is_quad_t=no,
   zsh_cv_rlim_t_is_quad_t=no)])
-  if test $zsh_cv_tlim_t_is_quad_t = yes; then
+  if test $zsh_cv_rlim_t_is_quad_t = yes; then
     AC_DEFINE(RLIM_T_IS_QUAD_T)
     DEFAULT_RLIM_T=quad_t
   else
diff --git a/patchlist.txt b/patchlist.txt
index 3d76dd023..7766e1e2e 100644
--- a/patchlist.txt
+++ b/patchlist.txt
@@ -556,6 +556,8 @@ Sven: 5544: another completion cleanup
 
 pws: 5545: silly set -x mistake
 
+Sven: 5547: group handling -J/-V in compadd
+
 Sven: 5548: _path_files, _comp_parts
 
 Matt: 5553: under _WIN32, .exe suffix is optional for commands
@@ -571,6 +573,8 @@ for four days.
 
 Larry P. Schrof: 5550: last -> previous in history documentation
 
+pws: 5559: cd /.. doesn't show .. (except if RFS was detected).
+
 Sven: 5560: subscripting fixes in params.c: flags for scalars and
 converting integer AA element to string
 
@@ -644,10 +648,14 @@ Sven: 5629: approximate correction patches
 
 Sven: 5631: compilation warnings
 
+Sven: 5634: return values for compgen and compadd
+
 Sven: 5637: mustuseheap check in complistflags
 
 Sven: 5640: _multi_parts, _path_files, _tar
 
+Sven: 5647: _multi_parts doesn't replace so many *'s
+
 Andrej: 5650: more tricks with _configure
 
 Sven: 5651: widespread completion fixes
@@ -663,3 +671,98 @@ Sven: 5665: return values from completion functions
 Sven: 5666: calling inststrlen() with a null string
 
 pws: from autoconf 2.13: new config.sub
+
+  pws-12
+
+Sven: 5670: parameter completion fix
+
+Sven: 5671: another small parameter fix for multiple braces
+
+Sven: 5675: tidying up for zle_tricky.c
+
+pws: from autoconf 2.13: new config.guess, too.
+
+Sven: 5676: all Completion example functions return a status
+
+Sven: 5677, 5679: Completion/User/_long_options and consequent upgrades for
+Completion/User files which use long GNU-style options.
+
+Sven: 5682: bindkey fix
+
+Sven: 5692: remove compstate[matcher] test from _long_options
+
+Sven: 5696, 5697: "${${path}[1]}" indexes on characters again
+
+Sven: 5698: array indexing in _long_options and _multi_parts
+
+Sven: 5699: matching prefixes of various sorts
+
+Sven: 5701: _main_complete, _multi_parts, _path_files, a few cosmetic
+changes.
+
+Sven: 5704: _long_options
+
+Sven: 5707: tokenization changes
+
+Sven: 5708: completion manual, -M anchors must be matched explicitly
+
+Sven: 5710: zle_tricky.c, completion inside words
+
+Sven: 5712: _path_files, noglobcomplete fix
+
+Sven: 5713: zle_tricky.c, interesting code specimen made extinct
+
+Sven: 5714: _path_files: failed completions get left alone more often
+
+Sven: 5716: zle.h, zle_misc.c, zle_tricky.c: iremovesuffix() can be told
+whether to keep a list of matches
+
+Andrej: 5719: _bindkey can use - as anchor for wildcard matching
+
+Will Day: 5724 (+postprocessing, 5741): signames2.awk: match extra spaces
+if produced by CPP.
+
+Sven: 5726: zle_tricky.c: ctokenize() fix and parameter completion
+
+pws: 5729: _bindkey doc
+
+Sven: 5732: _a2ps, _long_options
+
+Sven: 5736: completion before = in assignment
+
+pws: 5737: ${foo#* } is more efficient in ordinary cases
+
+Sven: zsh-users/2211 (+ p -> s): setopt -m handles underscores and case
+sensitivity
+
+Lehti Rami: 5754: --disable-restricted-r stops the shell becoming
+restricted when its name starts with r
+
+Sven: 5756: compstate[force_list]
+
+Sven: 5757: compconfig
+
+Sven: 5758: _path_files accepts -q, -r and -R options
+
+pws: www archive: updated Etc/FAQ finally, keep forgetting
+
+Sven: 5759: math environment fixes
+
+Sven: 5761: remove unnecessary compiler warnings in compctl.c
+
+Sven: 5766: _path_files closer to compctl/compgen behaviour
+
+Sven: 5770: _path_files again
+
+Sven: 5775: correcting completion will not ignore everything the user has
+typed; prefix quote fix
+
+pws: 5776: untested patch for typeahead problems when reading multiple
+lines of input
+
+pws: unposted archive changes: .distfiles in Completion hierarchy, dunno
+what these do but it looks better; _comp_parts is now _sep_parts; moved
+_long_options into Base and mentioned it in Completion/README.
+
+Geoff: 5779: correct mistakes some bozo (guess who) made testing rlim_t for
+long long.