[Midnightbsd-cvs] src [6990] stable/0.5/contrib/mksh: update mksh to R50e as there are a number of regression bugs in the previous release that could cause users issues

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Mar 20 08:28:10 EDT 2015


Revision: 6990
          http://svnweb.midnightbsd.org/src/?rev=6990
Author:   laffer1
Date:     2015-03-20 08:28:09 -0400 (Fri, 20 Mar 2015)
Log Message:
-----------
update mksh to R50e as there are a number of regression bugs in the previous release that could cause users issues

Modified Paths:
--------------
    stable/0.5/UPDATING
    stable/0.5/bin/mksh/Makefile
    stable/0.5/contrib/mksh/Build.sh
    stable/0.5/contrib/mksh/check.t
    stable/0.5/contrib/mksh/dot.mkshrc
    stable/0.5/contrib/mksh/edit.c
    stable/0.5/contrib/mksh/eval.c
    stable/0.5/contrib/mksh/exec.c
    stable/0.5/contrib/mksh/expr.c
    stable/0.5/contrib/mksh/funcs.c
    stable/0.5/contrib/mksh/histrap.c
    stable/0.5/contrib/mksh/jobs.c
    stable/0.5/contrib/mksh/lalloc.c
    stable/0.5/contrib/mksh/lex.c
    stable/0.5/contrib/mksh/main.c
    stable/0.5/contrib/mksh/misc.c
    stable/0.5/contrib/mksh/mksh.1
    stable/0.5/contrib/mksh/sh.h
    stable/0.5/contrib/mksh/shf.c
    stable/0.5/contrib/mksh/syn.c
    stable/0.5/contrib/mksh/var.c

Property Changed:
----------------
    stable/0.5/contrib/mksh/

Modified: stable/0.5/UPDATING
===================================================================
--- stable/0.5/UPDATING	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/UPDATING	2015-03-20 12:28:09 UTC (rev 6990)
@@ -3,6 +3,8 @@
 20150320:
 	OpenSSL CVE-2015-0209 and CVE-2015-0288
 
+	mksh R50e
+
 20150319:
 	0.5.10 RELEASE
 

Modified: stable/0.5/bin/mksh/Makefile
===================================================================
--- stable/0.5/bin/mksh/Makefile	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/bin/mksh/Makefile	2015-03-20 12:28:09 UTC (rev 6990)
@@ -38,7 +38,7 @@
 		-DHAVE_SYS_ERRLIST_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=1 \
 		-DHAVE_SILENT_IDIVWRAPV=0 \
 		-DMKSH_BINSHREDUCED -DMKSH_MIDNIGHTBSD01ASH_COMPAT \
-		-DMKSH_DISABLE_DEPRECATED  -DMKSH_BUILD_R=504
+		-DMKSH_DISABLE_DEPRECATED  -DMKSH_BUILD_R=505
 
 WARNS?=	0
 MAN=	mksh.1 

Index: stable/0.5/contrib/mksh
===================================================================
--- stable/0.5/contrib/mksh	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh	2015-03-20 12:28:09 UTC (rev 6990)

Property changes on: stable/0.5/contrib/mksh
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,2 ##
 /branches/MIROS/contrib/mksh:5952-6384
-/vendor/MirOS/mksh/dist:6385-6851
\ No newline at end of property
+/vendor/MirOS/mksh/dist:6385-6989
\ No newline at end of property
Modified: stable/0.5/contrib/mksh/Build.sh
===================================================================
--- stable/0.5/contrib/mksh/Build.sh	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/Build.sh	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,5 +1,5 @@
 #!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669 2014/10/07 15:22:12 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669.2.2 2015/03/01 15:42:50 tg Exp $'
 #-
 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 #		2011, 2012, 2013, 2014
@@ -1700,22 +1700,22 @@
 ac_test can_inttypes '!' stdint_h 1 "for standard 32-bit integer types" <<-'EOF'
 	#include <sys/types.h>
 	#include <stddef.h>
-	int main(int ac, char **av) { return ((uint32_t)(ptrdiff_t)*av + (int32_t)ac); }
+	int main(int ac, char **av) { return ((uint32_t)(size_t)*av + (int32_t)ac); }
 EOF
 ac_test can_ucbints '!' can_inttypes 1 "for UCB 32-bit integer types" <<-'EOF'
 	#include <sys/types.h>
 	#include <stddef.h>
-	int main(int ac, char **av) { return ((u_int32_t)(ptrdiff_t)*av + (int32_t)ac); }
+	int main(int ac, char **av) { return ((u_int32_t)(size_t)*av + (int32_t)ac); }
 EOF
 ac_test can_int8type '!' stdint_h 1 "for standard 8-bit integer type" <<-'EOF'
 	#include <sys/types.h>
 	#include <stddef.h>
-	int main(int ac, char **av) { return ((uint8_t)(ptrdiff_t)av[ac]); }
+	int main(int ac, char **av) { return ((uint8_t)(size_t)av[ac]); }
 EOF
 ac_test can_ucbint8 '!' can_int8type 1 "for UCB 8-bit integer type" <<-'EOF'
 	#include <sys/types.h>
 	#include <stddef.h>
-	int main(int ac, char **av) { return ((u_int8_t)(ptrdiff_t)av[ac]); }
+	int main(int ac, char **av) { return ((u_int8_t)(size_t)av[ac]); }
 EOF
 
 ac_test rlim_t <<-'EOF'
@@ -1784,7 +1784,7 @@
 		#define EXTERN
 		#define MKSH_INCLUDES_ONLY
 		#include "sh.h"
-		__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.669 2014/10/07 15:22:12 tg Exp $");
+		__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.669.2.2 2015/03/01 15:42:50 tg Exp $");
 		int main(void) { printf("Hello, World!\n"); return (isatty(0)); }
 EOF
 	case $cm in
@@ -1969,13 +1969,13 @@
 ac_test setlocale_ctype '' 'setlocale(LC_CTYPE, "")' <<-'EOF'
 	#include <locale.h>
 	#include <stddef.h>
-	int main(void) { return ((int)(ptrdiff_t)(void *)setlocale(LC_CTYPE, "")); }
+	int main(void) { return ((int)(size_t)(void *)setlocale(LC_CTYPE, "")); }
 EOF
 
 ac_test langinfo_codeset setlocale_ctype 0 'nl_langinfo(CODESET)' <<-'EOF'
 	#include <langinfo.h>
 	#include <stddef.h>
-	int main(void) { return ((int)(ptrdiff_t)(void *)nl_langinfo(CODESET)); }
+	int main(void) { return ((int)(size_t)(void *)nl_langinfo(CODESET)); }
 EOF
 
 ac_test select <<-'EOF'
@@ -2150,9 +2150,9 @@
 cta(uari_wrap_32_bit,
     (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3) >
     (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 4));
-#define NUM 22
+#define NUM 21
 #else
-#define NUM 16
+#define NUM 15
 #endif
 /* these are always required */
 cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
@@ -2161,11 +2161,10 @@
 cta(ari_size_no_matter_of_signedness, sizeof(mksh_ari_t) == sizeof(mksh_uari_t));
 
 cta(sizet_size_no_matter_of_signedness, sizeof(ssize_t) == sizeof(size_t));
-cta(ptrdifft_sizet_same_size, sizeof(ptrdiff_t) == sizeof(size_t));
-cta(ptrdifft_voidptr_same_size, sizeof(ptrdiff_t) == sizeof(void *));
-cta(ptrdifft_funcptr_same_size, sizeof(ptrdiff_t) == sizeof(void (*)(void)));
+cta(sizet_voidptr_same_size, sizeof(size_t) == sizeof(void *));
+cta(sizet_funcptr_same_size, sizeof(size_t) == sizeof(void (*)(void)));
 /* our formatting routines assume this */
-cta(ptr_fits_in_long, sizeof(ptrdiff_t) <= sizeof(long));
+cta(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
 /* for struct alignment people */
 		char padding[64 - NUM];
 	};
@@ -2264,6 +2263,11 @@
 ;' >conftest.c
 	# GNU sed 2.03 segfaults when optimising this to sed -n
 	NSIG=`vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
+	    grep -v '^#' | \
+	    sed '/mksh_cfg.*= *$/{
+		N
+		s/\n/ /
+		}' | \
 	    grep '^ *mksh_cfg *=' | \
 	    sed 's/^ *mksh_cfg *=[	 ]*\([()0-9x+-][()0-9x+	 -]*\).*$/\1/'`
 	case $NSIG in
@@ -2295,6 +2299,11 @@
 		echo ';' >>conftest.c
 		# GNU sed 2.03 croaks on optimising this, too
 		vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
+		    grep -v '^#' | \
+		    sed '/mksh_cfg.*= *$/{
+			N
+			s/\n/ /
+			}' | \
 		    grep '^ *mksh_cfg *=' | \
 		    sed 's/^ *mksh_cfg *=[	 ]*\([0-9][0-9x]*\).*$/:\1 '$name/
 	done | sed -n '/^:[^ ]/s/^://p' | while read nr name; do
@@ -2316,7 +2325,7 @@
 addsrcs USE_PRINTF_BUILTIN printf.c
 test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
 test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
-add_cppflags -DMKSH_BUILD_R=504
+add_cppflags -DMKSH_BUILD_R=505
 
 $e $bi$me: Finished configuration testing, now producing output.$ao
 
@@ -2431,9 +2440,12 @@
 	;;
 esac
 echo ": # work around NeXTstep bug" >Rebuild.sh
-for file in "$srcdir"/*.opt; do
+cd "$srcdir"
+optfiles=`echo *.opt`
+cd "$curdir"
+for file in $optfiles; do
 	echo "echo + Running genopt on '$file'..."
-	echo "(srcfile='$file'; BUILDSH_RUN_GENOPT=1; . '$srcdir/Build.sh')"
+	echo "(srcfile='$srcdir/$file'; BUILDSH_RUN_GENOPT=1; . '$srcdir/Build.sh')"
 done >>Rebuild.sh
 echo set -x >>Rebuild.sh
 for file in $SRCS; do
@@ -2467,11 +2479,11 @@
 	extras='emacsfn.h rlimits.opt sh.h sh_flags.opt var_spec.h'
 	test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc"
 	gens= genq=
-	for file in "$srcdir"/*.opt; do
+	for file in $optfiles; do
 		genf=`basename "$file" | sed 's/.opt$/.gen/'`
 		gens="$gens $genf"
-		genq="$genq$nl$genf: $srcdir/Build.sh $file
-			srcfile=$file; BUILDSH_RUN_GENOPT=1; . $srcdir/Build.sh"
+		genq="$genq$nl$genf: $srcdir/Build.sh $srcdir/$file
+			srcfile=$srcdir/$file; BUILDSH_RUN_GENOPT=1; . $srcdir/Build.sh"
 	done
 	cat >Makefrag.inc <<EOF
 # Makefile fragment for building mksh $dstversion
@@ -2515,9 +2527,9 @@
 	$e Generated Makefrag.inc successfully.
 	exit 0
 fi
-for file in "$srcdir"/*.opt; do
+for file in $optfiles; do
 	$e "+ Running genopt on '$file'..."
-	do_genopt "$file" || exit 1
+	do_genopt "$srcdir/$file" || exit 1
 done
 if test $cm = combine; then
 	objs="-o $mkshexe"

Modified: stable/0.5/contrib/mksh/check.t
===================================================================
--- stable/0.5/contrib/mksh/check.t	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/check.t	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,8 +1,8 @@
-# $MirOS: src/bin/mksh/check.t,v 1.661 2014/10/07 15:22:14 tg Exp $
-# OpenBSD src/regress/bin/ksh updated: 2013/12/02 20:39:44
+# $MirOS: src/bin/mksh/check.t,v 1.667.2.3 2015/03/01 15:42:51 tg Exp $
+# -*- mode: sh -*-
 #-
 # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-#	      2011, 2012, 2013, 2014
+#	      2011, 2012, 2013, 2014, 2015
 #	Thorsten Glaser <tg at mirbsd.org>
 #
 # Provided that these terms and disclaimer and all copyright notices
@@ -24,10 +24,13 @@
 # http://www.research.att.com/~gsf/public/ifs.sh
 #
 # More testsuites at:
-# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
+# http://svnweb.freebsd.org/base/head/bin/test/tests/legacy_test.sh?view=co&content-type=text%2Fplain
+#
+# Integrated testsuites from:
+# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
 
 expected-stdout:
-	@(#)MIRBSD KSH R50 2014/10/07
+	@(#)MIRBSD KSH R50 2015/03/01
 description:
 	Check version of shell.
 stdin:
@@ -36,7 +39,7 @@
 category: shell:legacy-no
 ---
 expected-stdout:
-	@(#)LEGACY KSH R50 2014/10/07
+	@(#)LEGACY KSH R50 2015/03/01
 description:
 	Check version of legacy shell.
 stdin:
@@ -2359,6 +2362,14 @@
 expected-stdout:
 	baz
 ---
+name: heredoc-9f
+description:
+	Check long here strings
+stdin:
+	cat <<< "$(  :                                                             )aa"
+expected-stdout:
+	aa
+---
 name: heredoc-10
 description:
 	Check direct here document assignment
@@ -2389,6 +2400,14 @@
 	vf=<<<$'=f $x \x40='
 	# now check
 	print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} ve={$ve} vf={$vf} |"
+	# check append
+	v=<<-EOF
+		vapp1
+	EOF
+	v+=<<-EOF
+		vapp2
+	EOF
+	print -r -- "| ${v//$'\n'/^} |"
 expected-stdout:
 	function foo {
 		vc=<<-EOF
@@ -2404,6 +2423,7 @@
 	} ve={=e $x \x40=
 	} vf={=f $x @=
 	} |
+	| vapp1^vapp2^ |
 ---
 name: heredoc-11
 description:
@@ -2433,6 +2453,14 @@
 	eval "$fnd"
 	foo
 	print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} |"
+	# check append
+	v=<<-
+		vapp1
+	<<
+	v+=<<-''
+		vapp2
+	
+	print -r -- "| ${v//$'\n'/^} |"
 expected-stdout:
 	function foo {
 		vc=<<-
@@ -2450,7 +2478,53 @@
 	} vc={=c u \x40=
 	} vd={=d $x \x40=
 	} |
+	| vapp1^vapp2^ |
 ---
+name: heredoc-12
+description:
+	Check here documents can use $* and $@; note shells vary:
+	• pdksh 5.2.14 acts the same
+	• dash has 1 and 2 the same but 3 lacks the space
+	• ksh93, bash4 differ in 2 by using space ipv colon
+stdin:
+	set -- a b
+	nl='
+	'
+	IFS=" 	$nl"; n=1
+	cat <<EOF
+	$n foo $* foo
+	$n bar "$*" bar
+	$n baz $@ baz
+	$n bla "$@" bla
+	EOF
+	IFS=":"; n=2
+	cat <<EOF
+	$n foo $* foo
+	$n bar "$*" bar
+	$n baz $@ baz
+	$n bla "$@" bla
+	EOF
+	IFS=; n=3
+	cat <<EOF
+	$n foo $* foo
+	$n bar "$*" bar
+	$n baz $@ baz
+	$n bla "$@" bla
+	EOF
+expected-stdout:
+	1 foo a b foo
+	1 bar "a b" bar
+	1 baz a b baz
+	1 bla "a b" bla
+	2 foo a:b foo
+	2 bar "a:b" bar
+	2 baz a:b baz
+	2 bla "a:b" bla
+	3 foo a b foo
+	3 bar "a b" bar
+	3 baz a b baz
+	3 bla "a b" bla
+---
 name: heredoc-comsub-1
 description:
 	Tests for here documents in COMSUB, taken from Austin ML
@@ -3585,7 +3659,7 @@
 description:
 	Simple test, default IFS
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	set -- A B C
 	showargs 1 $*
 	showargs 2 "$*"
@@ -3592,16 +3666,16 @@
 	showargs 3 $@
 	showargs 4 "$@"
 expected-stdout:
-	 <1> <A> <B> <C>
-	 <2> <A B C>
-	 <3> <A> <B> <C>
-	 <4> <A> <B> <C>
+	<1> <A> <B> <C> .
+	<2> <A B C> .
+	<3> <A> <B> <C> .
+	<4> <A> <B> <C> .
 ---
 name: IFS-colon-1
 description:
 	Simple test, IFS=:
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	IFS=:
 	set -- A B C
 	showargs 1 $*
@@ -3609,16 +3683,16 @@
 	showargs 3 $@
 	showargs 4 "$@"
 expected-stdout:
-	 <1> <A> <B> <C>
-	 <2> <A:B:C>
-	 <3> <A> <B> <C>
-	 <4> <A> <B> <C>
+	<1> <A> <B> <C> .
+	<2> <A:B:C> .
+	<3> <A> <B> <C> .
+	<4> <A> <B> <C> .
 ---
 name: IFS-null-1
 description:
 	Simple test, IFS=""
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	IFS=""
 	set -- A B C
 	showargs 1 $*
@@ -3626,16 +3700,16 @@
 	showargs 3 $@
 	showargs 4 "$@"
 expected-stdout:
-	 <1> <A> <B> <C>
-	 <2> <ABC>
-	 <3> <A> <B> <C>
-	 <4> <A> <B> <C>
+	<1> <A> <B> <C> .
+	<2> <ABC> .
+	<3> <A> <B> <C> .
+	<4> <A> <B> <C> .
 ---
 name: IFS-space-colon-1
 description:
 	Simple test, IFS=<white-space>:
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	IFS="$IFS:"
 	set --
 	showargs 1 $*
@@ -3644,11 +3718,11 @@
 	showargs 4 "$@"
 	showargs 5 : "$@"
 expected-stdout:
-	 <1>
-	 <2> <>
-	 <3>
-	 <4>
-	 <5> <:>
+	<1> .
+	<2> <> .
+	<3> .
+	<4> .
+	<5> <:> .
 ---
 name: IFS-space-colon-2
 description:
@@ -3655,23 +3729,23 @@
 	Simple test, IFS=<white-space>:
 	AT&T ksh fails this, POSIX says the test is correct.
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	IFS="$IFS:"
 	set --
 	showargs :"$@"
 expected-stdout:
-	 <:>
+	<:> .
 ---
 name: IFS-space-colon-4
 description:
 	Simple test, IFS=<white-space>:
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	IFS="$IFS:"
 	set --
 	showargs "$@$@"
 expected-stdout:
-	
+	.
 ---
 name: IFS-space-colon-5
 description:
@@ -3678,18 +3752,18 @@
 	Simple test, IFS=<white-space>:
 	Don't know what POSIX thinks of this.  AT&T ksh does not do this.
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	IFS="$IFS:"
 	set --
 	showargs "${@:-}"
 expected-stdout:
-	 <>
+	<> .
 ---
 name: IFS-subst-1
 description:
 	Simple test, IFS=<white-space>:
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	IFS="$IFS:"
 	x=":b: :"
 	echo -n '1:'; for i in $x ; do echo -n " [$i]" ; done ; echo
@@ -3711,34 +3785,34 @@
 expected-stdout:
 	1: [] [b] []
 	2: [:b::]
-	 <3> <> <b> <>
-	 <4> <:b::>
+	<3> <> <b> <> .
+	<4> <:b::> .
 	5: [a] [b]
-	 <6> <a> <b>
+	<6> <a> <b> .
 	7: [a] [] [c]
-	 <8> <a> <> <c>
+	<8> <a> <> <c> .
 	9: [h] [ith] [ere]
-	 <10> <h> <ith> <ere>
-	 <11> <h:ith:ere>
+	<10> <h> <ith> <ere> .
+	<11> <h:ith:ere> .
 	12: [A] [B] [] [D]
-	 <13> <A> <B> <> <D>
+	<13> <A> <B> <> <D> .
 ---
 name: IFS-subst-2
 description:
 	Check leading whitespace after trim does not make a field
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	x="X 1 2"
 	showargs 1 shift ${x#X}
 expected-stdout:
-	 <1> <shift> <1> <2>
+	<1> <shift> <1> <2> .
 ---
-name: IFS-subst-3
+name: IFS-subst-3-arr
 description:
 	Check leading IFS non-whitespace after trim does make a field
 	but leading IFS whitespace does not, nor empty replacements
 stdin:
-	showargs() { for i; do echo -n " <$i>"; done; echo; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	showargs 0 ${-+}
 	IFS=:
 	showargs 1 ${-+:foo:bar}
@@ -3745,19 +3819,46 @@
 	IFS=' '
 	showargs 2 ${-+ foo bar}
 expected-stdout:
-	 <0>
-	 <1> <> <foo> <bar>
-	 <2> <foo> <bar>
+	<0> .
+	<1> <> <foo> <bar> .
+	<2> <foo> <bar> .
 ---
+name: IFS-subst-3-ass
+description:
+	Check non-field semantics
+stdin:
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+	showargs 0 x=${-+}
+	IFS=:
+	showargs 1 x=${-+:foo:bar}
+	IFS=' '
+	showargs 2 x=${-+ foo bar}
+expected-stdout:
+	<0> <x=> .
+	<1> <x=> <foo> <bar> .
+	<2> <x=> <foo> <bar> .
+---
+name: IFS-subst-3-lcl
+description:
+	Check non-field semantics, smaller corner case (LP#1381965)
+stdin:
+	set -x
+	local regex=${2:-}
+	exit 1
+expected-exit: e != 0
+expected-stderr-pattern:
+	/regex=/
+---
 name: IFS-subst-4-1
 description:
 	reported by mikeserv
 stdin:
+	pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
 	a='space divded  argument
 	here'
 	IFS=\  ; set -- $a
 	IFS= ; q="$*" ; nq=$*
-	printf '<%s>\n' "$*" $* "$q" "$nq"
+	pfn "$*" $* "$q" "$nq"
 	[ "$q" = "$nq" ] && echo =true || echo =false
 expected-stdout:
 	<spacedivdedargument
@@ -3776,11 +3877,12 @@
 description:
 	extended testsuite based on problem by mikeserv
 stdin:
+	pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
 	a='space divded  argument
 	here'
 	IFS=\  ; set -- $a
 	IFS= ; q="$@" ; nq=$@
-	printf '<%s>\n' "$*" $* "$q" "$nq"
+	pfn "$*" $* "$q" "$nq"
 	[ "$q" = "$nq" ] && echo =true || echo =false
 expected-stdout:
 	<spacedivdedargument
@@ -3799,6 +3901,7 @@
 description:
 	extended testsuite based on problem by mikeserv
 stdin:
+	pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
 	a='space divded  argument
 	here'
 	IFS=\ ; set -- $a; IFS=
@@ -3806,14 +3909,14 @@
 	nqs=$*
 	qk="$@"
 	nqk=$@
-	printf '= qs '; printf '<%s>\n' "$qs"
-	printf '=nqs '; printf '<%s>\n' "$nqs"
-	printf '= qk '; printf '<%s>\n' "$qk"
-	printf '=nqk '; printf '<%s>\n' "$nqk"
-	printf '~ qs '; printf '<%s>\n' "$*"
-	printf '~nqs '; printf '<%s>\n' $*
-	printf '~ qk '; printf '<%s>\n' "$@"
-	printf '~nqk '; printf '<%s>\n' $@
+	print -nr -- '= qs '; pfn "$qs"
+	print -nr -- '=nqs '; pfn "$nqs"
+	print -nr -- '= qk '; pfn "$qk"
+	print -nr -- '=nqk '; pfn "$nqk"
+	print -nr -- '~ qs '; pfn "$*"
+	print -nr -- '~nqs '; pfn $*
+	print -nr -- '~ qk '; pfn "$@"
+	print -nr -- '~nqk '; pfn $@
 expected-stdout:
 	= qs <spacedivdedargument
 	here>
@@ -3842,21 +3945,22 @@
 description:
 	extended testsuite based on problem by mikeserv
 stdin:
+	pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
 	a='space divded  argument
 	here'
 	IFS=\ ; set -- $a; IFS=
 	qs="$*"
-	printf '= qs '; printf '<%s>\n' "$qs"
-	printf '~ qs '; printf '<%s>\n' "$*"
+	print -nr -- '= qs '; pfn "$qs"
+	print -nr -- '~ qs '; pfn "$*"
 	nqs=$*
-	printf '=nqs '; printf '<%s>\n' "$nqs"
-	printf '~nqs '; printf '<%s>\n' $*
+	print -nr -- '=nqs '; pfn "$nqs"
+	print -nr -- '~nqs '; pfn $*
 	qk="$@"
-	printf '= qk '; printf '<%s>\n' "$qk"
-	printf '~ qk '; printf '<%s>\n' "$@"
+	print -nr -- '= qk '; pfn "$qk"
+	print -nr -- '~ qk '; pfn "$@"
 	nqk=$@
-	printf '=nqk '; printf '<%s>\n' "$nqk"
-	printf '~nqk '; printf '<%s>\n' $@
+	print -nr -- '=nqk '; pfn "$nqk"
+	print -nr -- '~nqk '; pfn $@
 expected-stdout:
 	= qs <spacedivdedargument
 	here>
@@ -3885,22 +3989,23 @@
 description:
 	extended testsuite based on problem by mikeserv
 stdin:
+	pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
 	a='space divded  argument
 	here'
 	IFS=\ ; set -- $a; IFS=
 	unset v
 	qs=${v:-"$*"}
-	printf '= qs '; printf '<%s>\n' "$qs"
-	printf '~ qs '; printf '<%s>\n' ${v:-"$*"}
+	print -nr -- '= qs '; pfn "$qs"
+	print -nr -- '~ qs '; pfn ${v:-"$*"}
 	nqs=${v:-$*}
-	printf '=nqs '; printf '<%s>\n' "$nqs"
-	printf '~nqs '; printf '<%s>\n' ${v:-$*}
+	print -nr -- '=nqs '; pfn "$nqs"
+	print -nr -- '~nqs '; pfn ${v:-$*}
 	qk=${v:-"$@"}
-	printf '= qk '; printf '<%s>\n' "$qk"
-	printf '~ qk '; printf '<%s>\n' ${v:-"$@"}
+	print -nr -- '= qk '; pfn "$qk"
+	print -nr -- '~ qk '; pfn ${v:-"$@"}
 	nqk=${v:-$@}
-	printf '=nqk '; printf '<%s>\n' "$nqk"
-	printf '~nqk '; printf '<%s>\n' ${v:-$@}
+	print -nr -- '=nqk '; pfn "$nqk"
+	print -nr -- '~nqk '; pfn ${v:-$@}
 expected-stdout:
 	= qs <spacedivdedargument
 	here>
@@ -3929,21 +4034,22 @@
 description:
 	extended testsuite based on problem by mikeserv
 stdin:
+	pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
 	a='space divded  argument
 	here'
 	IFS=\ ; set -- $a; IFS=,
 	qs="$*"
-	printf '= qs '; printf '<%s>\n' "$qs"
-	printf '~ qs '; printf '<%s>\n' "$*"
+	print -nr -- '= qs '; pfn "$qs"
+	print -nr -- '~ qs '; pfn "$*"
 	nqs=$*
-	printf '=nqs '; printf '<%s>\n' "$nqs"
-	printf '~nqs '; printf '<%s>\n' $*
+	print -nr -- '=nqs '; pfn "$nqs"
+	print -nr -- '~nqs '; pfn $*
 	qk="$@"
-	printf '= qk '; printf '<%s>\n' "$qk"
-	printf '~ qk '; printf '<%s>\n' "$@"
+	print -nr -- '= qk '; pfn "$qk"
+	print -nr -- '~ qk '; pfn "$@"
 	nqk=$@
-	printf '=nqk '; printf '<%s>\n' "$nqk"
-	printf '~nqk '; printf '<%s>\n' $@
+	print -nr -- '=nqk '; pfn "$nqk"
+	print -nr -- '~nqk '; pfn $@
 expected-stdout:
 	= qs <space,divded,argument
 	here>
@@ -3972,22 +4078,23 @@
 description:
 	extended testsuite based on problem by mikeserv
 stdin:
+	pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
 	a='space divded  argument
 	here'
 	IFS=\ ; set -- $a; IFS=,
 	unset v
 	qs=${v:-"$*"}
-	printf '= qs '; printf '<%s>\n' "$qs"
-	printf '~ qs '; printf '<%s>\n' ${v:-"$*"}
+	print -nr -- '= qs '; pfn "$qs"
+	print -nr -- '~ qs '; pfn ${v:-"$*"}
 	nqs=${v:-$*}
-	printf '=nqs '; printf '<%s>\n' "$nqs"
-	printf '~nqs '; printf '<%s>\n' ${v:-$*}
+	print -nr -- '=nqs '; pfn "$nqs"
+	print -nr -- '~nqs '; pfn ${v:-$*}
 	qk=${v:-"$@"}
-	printf '= qk '; printf '<%s>\n' "$qk"
-	printf '~ qk '; printf '<%s>\n' ${v:-"$@"}
+	print -nr -- '= qk '; pfn "$qk"
+	print -nr -- '~ qk '; pfn ${v:-"$@"}
 	nqk=${v:-$@}
-	printf '=nqk '; printf '<%s>\n' "$nqk"
-	printf '~nqk '; printf '<%s>\n' ${v:-$@}
+	print -nr -- '=nqk '; pfn "$nqk"
+	print -nr -- '~nqk '; pfn ${v:-$@}
 expected-stdout:
 	= qs <space,divded,argument
 	here>
@@ -4026,38 +4133,55 @@
 	'emulate sh' zsh has extra fields in
 	- a5ins (IFS_NWS unquoted $*)
 	- b5ins, matching mksh’s
+	!!WARNING!! more to come: http://austingroupbugs.net/view.php?id=888
 stdin:
-	"$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=; set -- "" 2 ""; pfb $*; x=$*; pfn "$x"'
 	echo '=a1zns'
-	"$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=; set -- "" 2 ""; pfb "$*"; x="$*"; pfn "$x"'
 	echo '=a2zqs'
-	"$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=; set -- "" 2 ""; pfb $@; x=$@; pfn "$x"'
 	echo '=a3zna'
-	"$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=; set -- "" 2 ""; pfb "$@"; x="$@"; pfn "$x"'
 	echo '=a4zqa'
-	"$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=,; set -- "" 2 ""; pfb $*; x=$*; pfn "$x"'
 	echo '=a5ins'
-	"$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=,; set -- "" 2 ""; pfb "$*"; x="$*"; pfn "$x"'
 	echo '=a6iqs'
-	"$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=,; set -- "" 2 ""; pfb $@; x=$@; pfn "$x"'
 	echo '=a7ina'
-	"$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=,; set -- "" 2 ""; pfb "$@"; x="$@"; pfn "$x"'
 	echo '=a8iqa'
-	"$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=; set -- A B "" "" C; pfb $*; x=$*; pfn "$x"'
 	echo '=b1zns'
-	"$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=; set -- A B "" "" C; pfb "$*"; x="$*"; pfn "$x"'
 	echo '=b2zqs'
-	"$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=; set -- A B "" "" C; pfb $@; x=$@; pfn "$x"'
 	echo '=b3zna'
-	"$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=; set -- A B "" "" C; pfb "$@"; x="$@"; pfn "$x"'
 	echo '=b4zqa'
-	"$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=,; set -- A B "" "" C; pfb $*; x=$*; pfn "$x"'
 	echo '=b5ins'
-	"$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=,; set -- A B "" "" C; pfb "$*"; x="$*"; pfn "$x"'
 	echo '=b6iqs'
-	"$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=,; set -- A B "" "" C; pfb $@; x=$@; pfn "$x"'
 	echo '=b7ina'
-	"$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+	"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+		IFS=,; set -- A B "" "" C; pfb "$@"; x="$@"; pfn "$x"'
 	echo '=b8iqa'
 expected-stdout:
 	[2]
@@ -4133,6 +4257,62 @@
 	<A B   C>
 	=b8iqa
 ---
+name: IFS-subst-6
+description:
+	Regression wrt. vector expansion in trim
+stdin:
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+	IFS=
+	x=abc
+	set -- a b
+	showargs ${x#$*}
+expected-stdout:
+	<c> .
+---
+name: IFS-subst-7
+description:
+	ksh93 bug wrt. vector expansion in trim
+stdin:
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+	IFS="*"
+	a=abcd
+	set -- '' c
+	showargs "$*" ${a##"$*"}
+expected-stdout:
+	<*c> <abcd> .
+---
+name: IFS-subst-8
+description:
+	http://austingroupbugs.net/view.php?id=221
+stdin:
+	n() { echo "$#"; }; n "${foo-$@}"
+expected-stdout:
+	1
+---
+name: IFS-subst-9
+description:
+	Scalar context for $*/$@ in [[ and case
+stdin:
+	"$__progname" -c 'IFS=; set a b; [[ $* = "$1$2" ]]; echo 1 $?' sh a b
+	"$__progname" -c 'IFS=; [[ $* = ab ]]; echo 2 "$?"' sh a b
+	"$__progname" -c 'IFS=; [[ "$*" = ab ]]; echo 3 "$?"' sh a b
+	"$__progname" -c 'IFS=; [[ $* = a ]]; echo 4 "$?"' sh a b
+	"$__progname" -c 'IFS=; [[ "$*" = a ]]; echo 5 "$?"' sh a b
+	"$__progname" -c 'IFS=; [[ "$@" = a ]]; echo 6 "$?"' sh a b
+	"$__progname" -c 'IFS=; case "$@" in a) echo 7 a;; ab) echo 7 b;; a\ b) echo 7 ok;; esac' sh a b
+	"$__progname" -c 'IFS=; case $* in a) echo 8 a;; ab) echo 8 ok;; esac' sh a b
+	"$__progname" -c 'pfsp() { for s_arg in "$@"; do print -nr -- "<$s_arg> "; done; print .; }; IFS=; star=$* at="$@"; pfsp 9 "$star" "$at"' sh a b
+expected-stdout:
+	1 0
+	2 0
+	3 0
+	4 1
+	5 1
+	6 1
+	7 ok
+	8 ok
+	<9> <ab> <a b> .
+---
 name: IFS-arith-1
 description:
 	http://austingroupbugs.net/view.php?id=832
@@ -4139,7 +4319,7 @@
 stdin:
 	${ZSH_VERSION+false} || emulate sh
 	${BASH_VERSION+set -o posix}
-	showargs() { for x in "$@"; do echo -n "<$x> "; done; echo .; }
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
 	IFS=0
 	showargs $((1230456))
 expected-stdout:
@@ -7063,6 +7243,7 @@
 	XXX if the OS can already execute them, we lose
 	note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose
 	note: Ultrix perl5 t4 returns 65280 (exit-code 255) and no text
+	XXX fails when LD_PRELOAD is set with -e and Perl chokes it (ASan)
 need-pass: no
 category: !os:cygwin,!os:msys,!os:ultrix,!os:uwin-nt,!smksh
 env-setup: !FOO=BAR!
@@ -8013,6 +8194,66 @@
 	.fnr:f:
 	.f2r:f:
 ---
+name: unset-fnc-local-ksh
+description:
+	Check that “unset” removes a previous “local”
+	(ksh93 syntax compatible version); apparently,
+	there are shells which fail this?
+stdin:
+	function f {
+		echo f0: $x
+		typeset x
+		echo f1: $x
+		x=fa
+		echo f2: $x
+		unset x
+		echo f3: $x
+		x=fb
+		echo f4: $x
+	}
+	x=o
+	echo before: $x
+	f
+	echo after: $x
+expected-stdout:
+	before: o
+	f0: o
+	f1:
+	f2: fa
+	f3: o
+	f4: fb
+	after: fb
+---
+name: unset-fnc-local-sh
+description:
+	Check that “unset” removes a previous “local”
+	(Debian Policy §10.4 sh version); apparently,
+	there are shells which fail this?
+stdin:
+	f() {
+		echo f0: $x
+		local x
+		echo f1: $x
+		x=fa
+		echo f2: $x
+		unset x
+		echo f3: $x
+		x=fb
+		echo f4: $x
+	}
+	x=o
+	echo before: $x
+	f
+	echo after: $x
+expected-stdout:
+	before: o
+	f0: o
+	f1:
+	f2: fa
+	f3: o
+	f4: fb
+	after: fb
+---
 name: varexpand-substr-1
 description:
 	Check if bash-style substring expansion works
@@ -8172,13 +8413,21 @@
 description:
 	Ensure empty strings expand emptily
 stdin:
-	print x ${a} ${b} y
-	print z ${a#?} ${b%?} w
-	print v ${a=} ${b/c/d} u
+	print s ${a} . ${b} S
+	print t ${a#?} . ${b%?} T
+	print r ${a=} . ${b/c/d} R
+	print q
+	print s "${a}" . "${b}" S
+	print t "${a#?}" . "${b%?}" T
+	print r "${a=}" . "${b/c/d}" R
 expected-stdout:
-	x y
-	z w
-	v u
+	s . S
+	t . T
+	r . R
+	q
+	s  .  S
+	t  .  T
+	r  .  R
 ---
 name: varexpand-null-2
 description:
@@ -8194,13 +8443,41 @@
 name: varexpand-null-3
 description:
 	Ensure concatenating behaviour matches other shells
-	although the line 2<> is probably wrong? XNULLSUB case.
 stdin:
-	x=; printf "1<%s>\n" "$x$@"
-	set A; printf "2<%s>\n" "${@:+}"
+	showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+	x=; showargs 1 "$x"$@
+	set A; showargs 2 "${@:+}"
+	n() { echo "$#"; }
+	unset e
+	set -- a b
+	n """$@"
+	n "$@"
+	n "$@"""
+	n "$e""$@"
+	n "$@"
+	n "$@""$e"
+	set --
+	n """$@"
+	n "$@"
+	n "$@"""
+	n "$e""$@"
+	n "$@"
+	n "$@""$e"
 expected-stdout:
-	1<>
-	2<>
+	<1> <> .
+	<2> <> .
+	2
+	2
+	2
+	2
+	2
+	2
+	1
+	0
+	1
+	1
+	0
+	1
 ---
 name: print-funny-chars
 description:
@@ -10927,6 +11204,7 @@
 	(mypid=$$; try mypid)
 	echo =15
 	) 2>&1 | sed -e 's/^[^]]*]//' -e 's/^[^:]*: *//'
+	exit ${PIPESTATUS[0]}
 expected-stdout:
 	y
 	=1
@@ -11661,3 +11939,26 @@
 expected-stderr-pattern:
 	/.*/
 ---
+name: xtrace-2
+description:
+	Check that "set -x" is off during PS4 expansion
+stdin:
+	f() {
+		print -n "(f1:$-)"
+		set -x
+		print -n "(f2:$-)"
+	}
+	PS4='[(p:$-)$(f)] '
+	print "(o0:$-)"
+	set -x -o inherit-xtrace
+	print "(o1:$-)"
+	set +x
+	print "(o2:$-)"
+expected-stdout:
+	(o0:sh)
+	(o1:shx)
+	(o2:sh)
+expected-stderr:
+	[(p:sh)(f1:sh)(f2:sh)] print '(o1:shx)'
+	[(p:sh)(f1:sh)(f2:sh)] set +x
+---

Modified: stable/0.5/contrib/mksh/dot.mkshrc
===================================================================
--- stable/0.5/contrib/mksh/dot.mkshrc	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/dot.mkshrc	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,8 +1,8 @@
 # $Id$
-# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89 2014/07/28 21:45:44 tg Exp $
+# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89.2.1 2015/01/11 22:39:44 tg Exp $
 #-
 # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
-#		2011, 2012, 2013, 2014
+#		2011, 2012, 2013, 2014, 2015
 #	Thorsten Glaser <tg at mirbsd.org>
 #
 # Provided that these terms and disclaimer and all copyright notices
@@ -67,7 +67,7 @@
 		local dasc line i
 
 		cat "$@" | { set +U; if read -arN -1 line; then
-			typeset -i1 line
+			typeset -i1 'line[*]'
 			i=0
 			while (( i < ${#line[*]} )); do
 				hv=${line[i++]}
@@ -263,9 +263,8 @@
 
 # base64 encoder and decoder, RFC compliant, NUL safe
 function Lb64decode {
-	[[ -o utf8-mode ]]; local u=$?
+	[[ -o utf8-mode ]]; local u=$? c s="$*" t
 	set +U
-	local c s="$*" t=
 	[[ -n $s ]] || { s=$(cat; print x); s=${s%x}; }
 	local -i i=0 j=0 n=${#s} p=0 v x
 	local -i16 o
@@ -302,9 +301,8 @@
 set -A Lb64encode_code -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
     a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
 function Lb64encode {
-	[[ -o utf8-mode ]]; local u=$?
+	[[ -o utf8-mode ]]; local u=$? c s t
 	set +U
-	local c s t
 	if (( $# )); then
 		read -raN-1 s <<<"$*"
 		unset s[${#s[*]}-1]
@@ -342,9 +340,8 @@
 	Lbafh_v=0
 }
 function Lbafh_add {
-	[[ -o utf8-mode ]]; local u=$?
+	[[ -o utf8-mode ]]; local u=$? s
 	set +U
-	local s
 	if (( $# )); then
 		read -raN-1 s <<<"$*"
 		unset s[${#s[*]}-1]

Modified: stable/0.5/contrib/mksh/edit.c
===================================================================
--- stable/0.5/contrib/mksh/edit.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/edit.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,6 +1,6 @@
 /*	$OpenBSD: edit.c,v 1.39 2013/12/17 16:37:05 deraadt Exp $	*/
 /*	$OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $	*/
-/*	$OpenBSD: emacs.c,v 1.48 2013/12/17 16:37:05 deraadt Exp $	*/
+/*	$OpenBSD: emacs.c,v 1.49 2015/02/16 01:44:41 tedu Exp $	*/
 /*	$OpenBSD: vi.c,v 1.28 2013/12/18 16:45:46 deraadt Exp $	*/
 
 /*-
@@ -28,7 +28,7 @@
 
 #ifndef MKSH_NO_CMDLINE_EDITING
 
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276 2014/07/13 11:34:28 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276.2.3 2015/03/01 15:42:56 tg Exp $");
 
 /*
  * in later versions we might use libtermcap for this, but since external
@@ -327,7 +327,7 @@
 		/* ok, so split into "~foo"/"bar" or "~"/"baz" */
 		*cp++ = 0;
 		/* try to expand the tilde */
-		if (!(dp = tilde(s + 1))) {
+		if (!(dp = do_tilde(s + 1))) {
 			/* nope, revert damage */
 			*--cp = '/';
 		} else {
@@ -592,8 +592,6 @@
 	char **words = NULL;
 	bool is_command;
 
-	mkssert(buf != NULL);
-
 	len = x_locate_word(buf, buflen, pos, startp, &is_command);
 	if (!((*flagsp) & XCF_COMMAND))
 		is_command = false;
@@ -1009,7 +1007,6 @@
 static const struct x_ftab x_ftab[] = {
 #define EMACSFN_ITEMS
 #include "emacsfn.h"
-	{ 0, NULL, 0 }
 };
 
 static struct x_defbindings const x_defbindings[] = {
@@ -2240,7 +2237,6 @@
 {
 	char *cp;
 
-	mkssert(xcp != NULL);
 	strndupx(cp, xcp, nchars, AEDIT);
 	if (killstack[killsp])
 		afree(killstack[killsp], AEDIT);
@@ -2455,8 +2451,7 @@
 	/* List function names */
 	if (list) {
 		for (f = 0; f < NELEM(x_ftab); f++)
-			if (x_ftab[f].xf_name &&
-			    !(x_ftab[f].xf_flags & XF_NOBIND))
+			if (!(x_ftab[f].xf_flags & XF_NOBIND))
 				shprintf("%s\n", x_ftab[f].xf_name);
 		return (0);
 	}
@@ -2517,8 +2512,7 @@
 #endif
 	} else {
 		for (f = 0; f < NELEM(x_ftab); f++)
-			if (x_ftab[f].xf_name &&
-			    strcmp(x_ftab[f].xf_name, a2) == 0)
+			if (!strcmp(x_ftab[f].xf_name, a2))
 				break;
 		if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) {
 			bi_errorf("%s: %s %s", a2, "no such", Tfunction);

Modified: stable/0.5/contrib/mksh/eval.c
===================================================================
--- stable/0.5/contrib/mksh/eval.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/eval.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *		 2011, 2012, 2013, 2014
+ *		 2011, 2012, 2013, 2014, 2015
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.153 2014/10/07 15:22:16 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.4 2015/03/01 15:42:58 tg Exp $");
 
 /*
  * string expansion
@@ -59,10 +59,11 @@
 #define XSUBMID		6	/* middle of expanding ${} */
 
 /* States used for field splitting */
-#define IFS_WORD	0	/* word has chars (or quotes) */
+#define IFS_WORD	0	/* word has chars (or quotes except "$@") */
 #define IFS_WS		1	/* have seen IFS white-space */
 #define IFS_NWS		2	/* have seen IFS non-white-space */
 #define IFS_IWS		3	/* begin of word, ignore IFS WS */
+#define IFS_QUOTE	4	/* beg.w/quote, become IFS_WORD unless "$@" */
 
 static int varsub(Expand *, const char *, const char *, int *, int *);
 static int comsub(Expand *, const char *, int);
@@ -70,7 +71,7 @@
 static char *trimsub(char *, char *, int);
 static void glob(char *, XPtrV *, bool);
 static void globit(XString *, char **, char *, XPtrV *, int);
-static const char *maybe_expand_tilde(const char *, XString *, char **, int);
+static const char *maybe_expand_tilde(const char *, XString *, char **, bool);
 #ifndef MKSH_NOPWNAM
 static char *homedir(char *);
 #endif
@@ -237,7 +238,7 @@
 	/* record number of trailing newlines in COMSUB */
 	int newlines = 0;
 	bool saw_eq, make_magic;
-	int tilde_ok;
+	unsigned int tilde_ok;
 	size_t len;
 	char *cp;
 
@@ -246,7 +247,7 @@
 	/* for alias, readonly, set, typeset commands */
 	if ((f & DOVACHECK) && is_wdvarassign(ccp)) {
 		f &= ~(DOVACHECK | DOBLANK | DOGLOB | DOTILDE);
-		f |= DOASNTILDE | DOASNFIELD;
+		f |= DOASNTILDE | DOSCALAR;
 	}
 	if (Flag(FNOGLOB))
 		f &= ~DOGLOB;
@@ -290,7 +291,17 @@
 				c = *sp++;
 				break;
 			case OQUOTE:
-				word = IFS_WORD;
+				switch (word) {
+				case IFS_QUOTE:
+					/* """something */
+					word = IFS_WORD;
+					break;
+				case IFS_WORD:
+					break;
+				default:
+					word = IFS_QUOTE;
+					break;
+				}
 				tilde_ok = 0;
 				quote = 1;
 				continue;
@@ -383,6 +394,8 @@
 				if (f & DOBLANK)
 					doblank++;
 				tilde_ok = 0;
+				if (word == IFS_QUOTE && type != XNULLSUB)
+					word = IFS_WORD;
 				if (type == XBASE) {
 					/* expand? */
 					if (!st->next) {
@@ -516,7 +529,6 @@
 
 						/* check for special cases */
 						d = str_val(st->var);
-						mkssert(d != NULL);
 						switch (*pat) {
 						case '#':
 							/* anchor at begin */
@@ -622,7 +634,7 @@
 					case '%':
 						/* ! DOBLANK,DOBRACE,DOTILDE */
 						f = (f & DONTRUNCOMMAND) |
-						    DOPAT | DOTEMP;
+						    DOPAT | DOTEMP | DOSCALAR;
 						st->quotew = quote = 0;
 						/*
 						 * Prepend open pattern (so |
@@ -631,7 +643,7 @@
 						 */
 						if (!Flag(FSH)) {
 							*dp++ = MAGIC;
-							*dp++ = '@' | 0x80;
+							*dp++ = 0x80 | '@';
 						}
 						break;
 					case '=':
@@ -664,7 +676,11 @@
 						f |= DOTEMP;
 						/* FALLTHROUGH */
 					default:
-						word = quote ? IFS_WORD : IFS_IWS;
+						/* '-' '+' '?' */
+						if (quote)
+							word = IFS_WORD;
+						else if (dp == Xstring(ds, dp))
+							word = IFS_IWS;
 						/* Enable tilde expansion */
 						tilde_ok = 1;
 						f |= DOTILDE;
@@ -704,10 +720,16 @@
 					x.str = trimsub(str_val(st->var),
 						dp, st->stype);
 					if (x.str[0] != '\0') {
-						word = IFS_WS;
+						word = IFS_IWS;
 						type = XSUB;
-					} else
-						type = quote ? XSUB : XNULLSUB;
+					} else if (quote) {
+						word = IFS_WORD;
+						type = XSUB;
+					} else {
+						if (dp == Xstring(ds, dp))
+							word = IFS_IWS;
+						type = XNULLSUB;
+					}
 					if (f & DOBLANK)
 						doblank++;
 					st = st->prev;
@@ -743,7 +765,7 @@
 					if (f & DOBLANK)
 						doblank++;
 					st = st->prev;
-					word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS;
+					word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
 					continue;
 				case '?': {
 					char *s = Xrestpos(ds, dp, st->base);
@@ -759,11 +781,12 @@
 				case 0x100 | 'Q':
 					dp = Xrestpos(ds, dp, st->base);
 					type = XSUB;
-					word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS;
+					word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
 					if (f & DOBLANK)
 						doblank++;
 					st = st->prev;
 					continue;
+				/* default: '-' '+' */
 				}
 				st = st->prev;
 				type = XBASE;
@@ -799,8 +822,8 @@
 			type = XBASE;
 			if (f & DOBLANK) {
 				doblank--;
-				if (dp == Xstring(ds, dp))
-					word = IFS_WS;
+				if (dp == Xstring(ds, dp) && word != IFS_WORD)
+					word = IFS_IWS;
 			}
 			continue;
 
@@ -834,15 +857,20 @@
 					continue;
 				}
 				c = ifs0;
-				if ((f & DOASNFIELD)) {
-					/* assignment, do not field-split */
+				if ((f & DOHEREDOC)) {
+					/* pseudo-field-split reliably */
+					if (c == 0)
+						c = ' ';
+					break;
+				}
+				if ((f & DOSCALAR)) {
+					/* do not field-split */
 					if (x.split) {
 						c = ' ';
 						break;
 					}
-					if (c == 0) {
+					if (c == 0)
 						continue;
-					}
 				}
 				if (c == 0) {
 					if (quote && !x.split)
@@ -867,7 +895,7 @@
 				/* $(<...) failed */
 				subst_exstat = 1;
 				/* fake EOF */
-				c = EOF;
+				c = -1;
 			} else if (newlines) {
 				/* spit out saved NLs */
 				c = '\n';
@@ -877,13 +905,13 @@
 					if (c == '\n')
 						/* save newlines */
 						newlines++;
-				if (newlines && c != EOF) {
+				if (newlines && c != -1) {
 					shf_ungetc(c, x.u.shf);
 					c = '\n';
 					--newlines;
 				}
 			}
-			if (c == EOF) {
+			if (c == -1) {
 				newlines = 0;
 				if (x.u.shf)
 					shf_close(x.u.shf);
@@ -911,7 +939,7 @@
 			 *	IFS_IWS			-/WS	w/NWS	-
 			 * (w means generate a word)
 			 */
-			if ((word == IFS_WORD) || (c &&
+			if ((word == IFS_WORD) || (word == IFS_QUOTE) || (c &&
 			    (word == IFS_IWS || word == IFS_NWS) &&
 			    !ctype(c, C_IFSWS))) {
  emit_word:
@@ -1023,7 +1051,7 @@
 
 						tcp = maybe_expand_tilde(sp,
 						    &ds, &tdp,
-						    f & DOASNTILDE);
+						    tobool(f & DOASNTILDE));
 						if (tcp) {
 							if (dp != tdp)
 								word = IFS_WORD;
@@ -1659,7 +1687,7 @@
  * past the name, otherwise returns 0.
  */
 static const char *
-maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign)
+maybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign)
 {
 	XString ts;
 	char *dp = *dpp;
@@ -1676,7 +1704,7 @@
 	}
 	*tp = '\0';
 	r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ?
-	    tilde(Xstring(ts, tp)) : NULL;
+	    do_tilde(Xstring(ts, tp)) : NULL;
 	Xfree(ts, tp);
 	if (r) {
 		while (*r) {
@@ -1698,7 +1726,7 @@
  */
 
 char *
-tilde(char *cp)
+do_tilde(char *cp)
 {
 	char *dp = null;
 
@@ -1745,14 +1773,14 @@
 static void
 alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
 {
-	int count = 0;
+	unsigned int count = 0;
 	char *brace_start, *brace_end, *comma = NULL;
 	char *field_start;
-	char *p;
+	char *p = exp_start;
 
 	/* search for open brace */
-	for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != '{' /*}*/; p += 2)
-		;
+	while ((p = strchr(p, MAGIC)) && p[1] != '{' /*}*/)
+		p += 2;
 	brace_start = p;
 
 	/* find matching close brace, if any */
@@ -1759,14 +1787,16 @@
 	if (p) {
 		comma = NULL;
 		count = 1;
-		for (p += 2; *p && count; p++) {
-			if (ISMAGIC(*p)) {
-				if (*++p == '{' /*}*/)
-					count++;
+		p += 2;
+		while (*p && count) {
+			if (ISMAGIC(*p++)) {
+				if (*p == '{' /*}*/)
+					++count;
 				else if (*p == /*{*/ '}')
 					--count;
 				else if (*p == ',' && count == 1)
 					comma = p;
+				++p;
 			}
 		}
 	}
@@ -1795,7 +1825,7 @@
 	for (p = brace_start + 2; p != brace_end; p++) {
 		if (ISMAGIC(*p)) {
 			if (*++p == '{' /*}*/)
-				count++;
+				++count;
 			else if ((*p == /*{*/ '}' && --count == 0) ||
 			    (*p == ',' && count == 1)) {
 				char *news;

Modified: stable/0.5/contrib/mksh/exec.c
===================================================================
--- stable/0.5/contrib/mksh/exec.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/exec.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *		 2011, 2012, 2013, 2014
+ *		 2011, 2012, 2013, 2014, 2015
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.133 2014/10/03 17:32:11 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.2 2015/03/01 15:42:59 tg Exp $");
 
 #ifndef MKSH_DEFAULT_EXECSHELL
 #define MKSH_DEFAULT_EXECSHELL	"/bin/sh"
@@ -32,7 +32,7 @@
 static int comexec(struct op *, struct tbl * volatile, const char **,
     int volatile, volatile int *);
 static void scriptexec(struct op *, const char **) MKSH_A_NORETURN;
-static int call_builtin(struct tbl *, const char **, const char *);
+static int call_builtin(struct tbl *, const char **, const char *, bool);
 static int iosetup(struct ioword *, struct tbl *);
 static int herein(struct ioword *, char **);
 static const char *do_selectargs(const char **, bool);
@@ -81,6 +81,8 @@
 	/* we want to run an executable, do some variance checks */
 	if (t->type == TCOM) {
 		/* check if this is 'var=<<EOF' */
+		/*XXX this is broken, don’t use! */
+		/*XXX https://bugs.launchpad.net/mksh/+bug/1380389 */
 		if (
 		    /* we have zero arguments, i.e. no programme to run */
 		    t->args[0] == NULL &&
@@ -94,20 +96,23 @@
 		    /* the variable assignment begins with a valid varname */
 		    (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
 		    /* and has no right-hand side (i.e. "varname=") */
-		    ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS &&
+		    ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) ||
+		    /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR &&
+		    ccp[3] == '=' && ccp[4] == EOS)) &&
 		    /* plus we can have a here document content */
 		    herein(t->ioact[0], &cp) == 0 && cp && *cp) {
 			char *sp = cp, *dp;
-			size_t n = ccp - t->vars[0] + 2, z;
+			size_t n = ccp - t->vars[0] + (ccp[1] == '+' ? 4 : 2);
+			size_t z;
 
 			/* drop redirection (will be garbage collected) */
 			t->ioact = NULL;
 
 			/* set variable to its expanded value */
-			z = strlen(cp) + 1;
-			if (notoktomul(z, 2) || notoktoadd(z * 2, n))
+			z = strlen(cp);
+			if (notoktomul(z, 2) || notoktoadd(z * 2, n + 1))
 				internal_errorf(Toomem, (size_t)-1);
-			dp = alloc(z * 2 + n, ATEMP);
+			dp = alloc(z * 2 + n + 1, APERM);
 			memcpy(dp, t->vars[0], n);
 			t->vars[0] = dp;
 			dp += n;
@@ -398,7 +403,7 @@
 
 	case TCASE:
 		i = 0;
-		ccp = evalstr(t->str, DOTILDE);
+		ccp = evalstr(t->str, DOTILDE | DOSCALAR);
 		for (t = t->left; t != NULL && t->type == TPAT; t = t->right) {
 			for (ap = (const char **)t->vars; *ap; ap++) {
 				if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
@@ -441,7 +446,6 @@
 
 	case TEXEC:
 		/* an eval'd TCOM */
-		s = t->args[0];
 		up = makenv();
 		restoresigs();
 		cleanup_proc_env();
@@ -455,7 +459,7 @@
 		if (rv == ENOEXEC)
 			scriptexec(t, (const char **)up);
 		else
-			errorf("%s: %s", s, cstrerror(rv));
+			errorf("%s: %s", t->str, cstrerror(rv));
 	}
  Break:
 	exstat = rv & 0xFF;
@@ -500,18 +504,21 @@
 	/* Must be static (XXX but why?) */
 	static struct op texec;
 	int type_flags;
-	bool keepasn_ok;
+	bool resetspec;
 	int fcflags = FC_BI|FC_FUNC|FC_PATH;
-	bool bourne_function_call = false;
 	struct block *l_expand, *l_assign;
+	int optc;
+	const char *exec_argv0 = NULL;
+	bool exec_clrenv = false;
 
-	/*
-	 * snag the last argument for $_ XXX not the same as AT&T ksh,
-	 * which only seems to set $_ after a newline (but not in
-	 * functions/dot scripts, but in interactive and script) -
-	 * perhaps save last arg here and set it in shell()?.
-	 */
+	/* snag the last argument for $_ */
 	if (Flag(FTALKING) && *(lastp = ap)) {
+		/*
+		 * XXX not the same as AT&T ksh, which only seems to set $_
+		 * after a newline (but not in functions/dot scripts, but in
+		 * interactive and script) - perhaps save last arg here and
+		 * set it in shell()?.
+		 */
 		while (*++lastp)
 			;
 		/* setstr() can't fail here */
@@ -532,7 +539,7 @@
 	 *	FOO=bar command			FOO is neither kept nor exported
 	 *	PATH=... foobar			use new PATH in foobar search
 	 */
-	keepasn_ok = true;
+	resetspec = false;
 	while (tp && tp->type == CSHELL) {
 		/* undo effects of command */
 		fcflags = FC_BI|FC_FUNC|FC_PATH;
@@ -548,10 +555,25 @@
 		} else if (tp->val.f == c_exec) {
 			if (ap[1] == NULL)
 				break;
-			ap++;
+			ksh_getopt_reset(&builtin_opt, GF_ERROR);
+			while ((optc = ksh_getopt(ap, &builtin_opt, "a:c")) != -1)
+				switch (optc) {
+				case 'a':
+					exec_argv0 = builtin_opt.optarg;
+					break;
+				case 'c':
+					exec_clrenv = true;
+					/* ensure we can actually do this */
+					resetspec = true;
+					break;
+				default:
+					rv = 2;
+					goto Leave;
+				}
+			ap += builtin_opt.optind;
 			flags |= XEXEC;
 		} else if (tp->val.f == c_command) {
-			int optc, saw_p = 0;
+			bool saw_p = false;
 
 			/*
 			 * Ugly dealing with options in two places (here
@@ -559,8 +581,8 @@
 			 */
 			ksh_getopt_reset(&builtin_opt, 0);
 			while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p')
-				saw_p = 1;
-			if (optc != EOF)
+				saw_p = true;
+			if (optc != -1)
 				/* command -vV or something */
 				break;
 			/* don't look for functions */
@@ -579,7 +601,7 @@
 			 * POSIX says special builtins lose their status
 			 * if accessed using command.
 			 */
-			keepasn_ok = false;
+			resetspec = true;
 			if (!ap[0]) {
 				/* ensure command with no args exits with 0 */
 				subst_exstat = 0;
@@ -614,20 +636,21 @@
 	if (t->u.evalflags & DOTCOMEXEC)
 		flags |= XEXEC;
 	l_expand = e->loc;
-	if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
+	if (!resetspec && (!ap[0] || (tp && (tp->flag & KEEPASN))))
 		type_flags = 0;
 	else {
 		/* create new variable/function block */
 		newblock();
 		/* ksh functions don't keep assignments, POSIX functions do. */
-		if (keepasn_ok && tp && tp->type == CFUNC &&
-		    !(tp->flag & FKSH)) {
-			bourne_function_call = true;
+		if (!resetspec && tp && tp->type == CFUNC &&
+		    !(tp->flag & FKSH))
 			type_flags = EXPORT;
-		} else
+		else
 			type_flags = LOCAL|LOCAL_COPY|EXPORT;
 	}
 	l_assign = e->loc;
+	if (exec_clrenv)
+		l_assign->flags |= BF_STOPENV;
 	if (Flag(FEXPORT))
 		type_flags |= EXPORT;
 	if (Flag(FXTRACE))
@@ -635,7 +658,7 @@
 	for (i = 0; t->vars[i]; i++) {
 		/* do NOT lookup in the new var/fn block just created */
 		e->loc = l_expand;
-		cp = evalstr(t->vars[i], DOASNTILDE | DOASNFIELD);
+		cp = evalstr(t->vars[i], DOASNTILDE | DOSCALAR);
 		e->loc = l_assign;
 		if (Flag(FXTRACE)) {
 			const char *ccp;
@@ -651,8 +674,6 @@
 		}
 		/* but assign in there as usual */
 		typeset(cp, type_flags, 0, 0, 0);
-		if (bourne_function_call && !(type_flags & EXPORT))
-			typeset(cp, LOCAL | LOCAL_COPY | EXPORT, 0, 0, 0);
 	}
 
 	if (Flag(FXTRACE)) {
@@ -684,8 +705,8 @@
 
 	/* shell built-in */
 	case CSHELL:
-		rv = call_builtin(tp, (const char **)ap, null);
-		if (!keepasn_ok && tp->val.f == c_shift) {
+		rv = call_builtin(tp, (const char **)ap, null, resetspec);
+		if (resetspec && tp->val.f == c_shift) {
 			l_expand->argc = l_assign->argc;
 			l_expand->argv = l_assign->argv;
 		}
@@ -810,14 +831,24 @@
 			break;
 		}
 
-		/* set $_ to programme's full path */
+		/* set $_ to program's full path */
 		/* setstr() can't fail here */
 		setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0),
 		    tp->val.s, KSH_RETURN_ERROR);
 
-		if (flags&XEXEC) {
+		/* to fork, we set up a TEXEC node and call execute */
+		texec.type = TEXEC;
+		/* for vistree/dumptree */
+		texec.left = t;
+		texec.str = tp->val.s;
+		texec.args = ap;
+
+		/* in this case we do not fork, of course */
+		if (flags & XEXEC) {
+			if (exec_argv0)
+				texec.args[0] = exec_argv0;
 			j_exit();
-			if (!(flags&XBGND)
+			if (!(flags & XBGND)
 #ifndef MKSH_UNEMPLOYED
 			    || Flag(FMONITOR)
 #endif
@@ -827,12 +858,6 @@
 			}
 		}
 
-		/* to fork we set up a TEXEC node and call execute */
-		texec.type = TEXEC;
-		/* for tprint */
-		texec.left = t;
-		texec.str = tp->val.s;
-		texec.args = ap;
 		rv = exchild(&texec, flags, xerrok, -1);
 		break;
 	}
@@ -849,10 +874,8 @@
 {
 	const char *sh;
 #ifndef MKSH_SMALL
-	unsigned char *cp;
-	/* 64 == MAXINTERP in MirBSD <sys/param.h> */
-	char buf[64];
 	int fd;
+	unsigned char buf[68];
 #endif
 	union mksh_ccphack args, cap;
 
@@ -866,33 +889,35 @@
 
 #ifndef MKSH_SMALL
 	if ((fd = open(tp->str, O_RDONLY | O_BINARY)) >= 0) {
-		/* read first MAXINTERP octets from file */
-		if (read(fd, buf, sizeof(buf)) <= 0)
-			/* read error -> no good */
-			buf[0] = '\0';
+		unsigned char *cp;
+		unsigned short m;
+		ssize_t n;
+
+		/* read first couple of octets from file */
+		n = read(fd, buf, sizeof(buf) - 1);
 		close(fd);
+		/* read error or short read? */
+		if (n < 5)
+			goto nomagic;
+		/* terminate buffer */
+		buf[n] = '\0';
 
 		/* skip UTF-8 Byte Order Mark, if present */
-		cp = (unsigned char *)buf;
-		if ((cp[0] == 0xEF) && (cp[1] == 0xBB) && (cp[2] == 0xBF))
-			cp += 3;
-		/* save begin of shebang for later */
-		fd = (char *)cp - buf;		/* either 0 or (if BOM) 3 */
+		cp = buf + (n = ((buf[0] == 0xEF) && (buf[1] == 0xBB) &&
+		    (buf[2] == 0xBF)) ? 3 : 0);
 
-		/* scan for newline (or CR) or NUL _before_ end of buffer */
-		while ((size_t)((char *)cp - buf) < sizeof(buf))
-			if (*cp == '\0' || *cp == '\n' || *cp == '\r') {
-				*cp = '\0';
-				break;
-			} else
-				++cp;
+		/* scan for newline or NUL (end of buffer) */
+		while (*cp && *cp != '\n')
+			++cp;
 		/* if the shebang line is longer than MAXINTERP, bail out */
-		if ((size_t)((char *)cp - buf) >= sizeof(buf))
+		if (!*cp)
 			goto noshebang;
+		/* replace newline by NUL */
+		*cp = '\0';
 
 		/* restore begin of shebang position (buf+0 or buf+3) */
-		cp = (unsigned char *)(buf + fd);
-		/* bail out if read error (above) or no shebang */
+		cp = buf + n;
+		/* bail out if no shebang magic found */
 		if ((cp[0] != '#') || (cp[1] != '!'))
 			goto noshebang;
 
@@ -918,22 +943,24 @@
 			if (*cp)
 				*tp->args-- = (char *)cp;
 		}
+		goto nomagic;
  noshebang:
-		if (buf[0] == 0x7F && buf[1] == 'E' && buf[2] == 'L' &&
-		    buf[3] == 'F')
+		m = buf[0] << 8 | buf[1];
+		if (m == 0x7F45 && buf[2] == 'L' && buf[3] == 'F')
 			errorf("%s: not executable: %d-bit ELF file", tp->str,
-			    32 * ((uint8_t)buf[4]));
-		fd = buf[0] << 8 | buf[1];
-		if ((fd == /* OMAGIC */ 0407) ||
-		    (fd == /* NMAGIC */ 0410) ||
-		    (fd == /* ZMAGIC */ 0413) ||
-		    (fd == /* QMAGIC */ 0314) ||
-		    (fd == /* ECOFF_I386 */ 0x4C01) ||
-		    (fd == /* ECOFF_M68K */ 0x0150 || fd == 0x5001) ||
-		    (fd == /* ECOFF_SH */   0x0500 || fd == 0x0005) ||
-		    (fd == /* "MZ" */ 0x4D5A) ||
-		    (fd == /* gzip */ 0x1F8B))
-			errorf("%s: not executable: magic %04X", tp->str, fd);
+			    32 * buf[4]);
+		if ((m == /* OMAGIC */ 0407) ||
+		    (m == /* NMAGIC */ 0410) ||
+		    (m == /* ZMAGIC */ 0413) ||
+		    (m == /* QMAGIC */ 0314) ||
+		    (m == /* ECOFF_I386 */ 0x4C01) ||
+		    (m == /* ECOFF_M68K */ 0x0150 || m == 0x5001) ||
+		    (m == /* ECOFF_SH */   0x0500 || m == 0x0005) ||
+		    (m == /* "MZ" */ 0x4D5A) ||
+		    (m == /* gzip */ 0x1F8B) || (m == /* .Z */ 0x1F9D))
+			errorf("%s: not executable: magic %04X", tp->str, m);
+ nomagic:
+		;
 	}
 #endif
 	args.ro = tp->args;
@@ -952,7 +979,7 @@
 	struct tbl *tp;
 
 	tp = ktsearch(&builtins, *wp, hash(*wp));
-	return (call_builtin(tp, wp, "shcomexec"));
+	return (call_builtin(tp, wp, "shcomexec", false));
 }
 
 /*
@@ -1001,8 +1028,6 @@
 
 	while (/* CONSTCOND */ 1) {
 		tp = findfunc(name, nhash, true);
-		/* because findfunc:create=true */
-		mkssert(tp != NULL);
 
 		if (tp->flag & ISSET)
 			was_set = true;
@@ -1265,7 +1290,7 @@
 }
 
 static int
-call_builtin(struct tbl *tp, const char **wp, const char *where)
+call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec)
 {
 	int rv;
 
@@ -1272,7 +1297,7 @@
 	if (!tp)
 		internal_errorf("%s: %s", where, wp[0]);
 	builtin_argv0 = wp[0];
-	builtin_flag = tp->flag;
+	builtin_spec = tobool(!resetspec && (tp->flag & SPEC_BI));
 	shf_reopen(1, SHF_WR, shl_stdout);
 	shl_stdout_ok = true;
 	ksh_getopt_reset(&builtin_opt, GF_ERROR);
@@ -1279,8 +1304,8 @@
 	rv = (*tp->val.f)(wp);
 	shf_flush(shl_stdout);
 	shl_stdout_ok = false;
-	builtin_flag = 0;
 	builtin_argv0 = NULL;
+	builtin_spec = false;
 	return (rv);
 }
 
@@ -1467,7 +1492,7 @@
 		if (yylex(sub) != LWORD)
 			internal_errorf("%s: %s", "herein", "yylex");
 		source = osource;
-		ccp = evalstr(yylval.cp, 0);
+		ccp = evalstr(yylval.cp, DOSCALAR | DOHEREDOC);
 	}
 
 	if (resbuf == NULL)
@@ -1487,7 +1512,7 @@
 	struct temp *h;
 	int i;
 
-	/* ksh -c 'cat << EOF' can cause this... */
+	/* ksh -c 'cat <<EOF' can cause this... */
 	if (iop->heredoc == NULL) {
 		warningf(true, "%s missing", "here document");
 		/* special to iosetup(): don't print error */
@@ -1522,7 +1547,7 @@
 		return (-2);
 	}
 
-	if (shf_close(shf) == EOF) {
+	if (shf_close(shf) == -1) {
 		i = errno;
 		close(fd);
 		warningf(true, "can't %s temporary file %s: %s",
@@ -1559,7 +1584,8 @@
 		if (print_menu || !*str_val(global("REPLY")))
 			pr_menu(ap);
 		shellf("%s", str_val(global("PS3")));
-		if (call_builtin(findcom("read", FC_BI), read_args, Tselect))
+		if (call_builtin(findcom("read", FC_BI), read_args, Tselect,
+		    false))
 			return (NULL);
 		s = str_val(global("REPLY"));
 		if (*s && getn(s, &i))
@@ -1709,6 +1735,7 @@
 dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
 {
 	const char *s = *te->pos.wp;
+	int flags = DOTILDE | DOSCALAR;
 
 	if (!s)
 		return (NULL);
@@ -1719,11 +1746,9 @@
 		return (null);
 
 	if (op == TO_STEQL || op == TO_STNEQ)
-		s = evalstr(s, DOTILDE | DOPAT);
-	else
-		s = evalstr(s, DOTILDE);
+		flags |= DOPAT;
 
-	return (s);
+	return (evalstr(s, flags));
 }
 
 static void

Modified: stable/0.5/contrib/mksh/expr.c
===================================================================
--- stable/0.5/contrib/mksh/expr.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/expr.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,4 +1,4 @@
-/*	$OpenBSD: expr.c,v 1.23 2013/12/17 16:37:06 deraadt Exp $	*/
+/*	$OpenBSD: expr.c,v 1.24 2014/12/08 14:26:31 otto Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76 2014/06/24 19:53:19 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76.2.1 2015/01/25 15:44:05 tg Exp $");
 
 /* the order of these enums is constrained by the order of opinfo[] */
 enum token {

Modified: stable/0.5/contrib/mksh/funcs.c
===================================================================
--- stable/0.5/contrib/mksh/funcs.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/funcs.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -5,7 +5,7 @@
 
 /*-
  * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- *		 2010, 2011, 2012, 2013, 2014
+ *		 2010, 2011, 2012, 2013, 2014, 2015
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -38,7 +38,7 @@
 #endif
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.258 2014/09/03 19:55:51 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259.2.2 2015/01/25 15:35:44 tg Exp $");
 
 #if HAVE_KILLPG
 /*
@@ -550,7 +550,7 @@
 		if (vflag || (tp->type != CALIAS && tp->type != CEXEC &&
 		    tp->type != CTALIAS))
 			shf_puts(id, shl_stdout);
-		if (vflag)
+		if (vflag) {
 			switch (tp->type) {
 			case CKEYWD:
 			case CALIAS:
@@ -559,11 +559,20 @@
 				shf_puts(" is a", shl_stdout);
 				break;
 			}
+			switch (tp->type) {
+			case CKEYWD:
+			case CSHELL:
+			case CTALIAS:
+			case CEXEC:
+				shf_putc(' ', shl_stdout);
+				break;
+			}
+		}
 
 		switch (tp->type) {
 		case CKEYWD:
 			if (vflag)
-				shf_puts(" reserved word", shl_stdout);
+				shf_puts("reserved word", shl_stdout);
 			break;
 		case CALIAS:
 			if (vflag)
@@ -590,16 +599,17 @@
 			}
 			break;
 		case CSHELL:
-			if (vflag)
-				shprintf("%s %s %s",
-				    (tp->flag & SPEC_BI) ? " special" : null,
-				    "shell", Tbuiltin);
+			if (vflag) {
+				if (tp->flag & SPEC_BI)
+					shf_puts("special ", shl_stdout);
+				shprintf("%s %s", "shell", Tbuiltin);
+			}
 			break;
 		case CTALIAS:
 		case CEXEC:
 			if (tp->flag & ISSET) {
 				if (vflag) {
-					shf_puts(" is ", shl_stdout);
+					shf_puts("is ", shl_stdout);
 					if (tp->type == CTALIAS)
 						shprintf("a tracked %s%s for ",
 						    (tp->flag & EXPORT) ?
@@ -609,12 +619,12 @@
 				shf_puts(tp->val.s, shl_stdout);
 			} else {
 				if (vflag)
-					shprintf(" %s\n", "not found");
+					shf_puts("not found", shl_stdout);
 				rv = 1;
 			}
 			break;
 		default:
-			shprintf("%s is *GOK*", id);
+			shf_puts(" is *GOK*", shl_stdout);
 			break;
 		}
 		if (vflag || !rv)
@@ -1587,12 +1597,16 @@
 		return (1);
 	arg = wp[builtin_opt.optind];
 
-	if (arg) {
-		evaluate(arg, &val, KSH_UNWIND_ERROR, false);
-		n = val;
-	} else
+	if (!arg)
 		n = 1;
-	if (n < 0) {
+	else if (!evaluate(arg, &val, KSH_RETURN_ERROR, false)) {
+		/* error already printed */
+		bi_errorfz();
+		return (1);
+	} else if (!(n = val)) {
+		/* nothing to do */
+		return (0);
+	} else if (n < 0) {
 		bi_errorf("%s: %s", arg, "bad number");
 		return (1);
 	}
@@ -1813,7 +1827,7 @@
 	char *cp, *allocd = NULL, *xp;
 	const char *ccp;
 	XString xs;
-	ptrdiff_t xsave = 0;
+	size_t xsave = 0;
 	mksh_ttyst tios;
 	bool restore_tios = false;
 #if HAVE_SELECT
@@ -2417,9 +2431,8 @@
 		return (c_typeset(args));
 	}
 
-	argi = parse_args(wp, OF_SET, &setargs);
-	if (argi < 0)
-		return (1);
+	if ((argi = parse_args(wp, OF_SET, &setargs)) < 0)
+		return (2);
 	/* set $# and $* */
 	if (setargs) {
 		wp += argi - 1;
@@ -2794,8 +2807,6 @@
 
 	for (argc = 0; wp[argc]; argc++)
 		;
-	mkssert(argc > 0);
-	mkssert(wp[0] != NULL);
 
 	if (strcmp(wp[0], "[") == 0) {
 		if (strcmp(wp[--argc], "]") != 0) {

Modified: stable/0.5/contrib/mksh/histrap.c
===================================================================
--- stable/0.5/contrib/mksh/histrap.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/histrap.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,9 +1,9 @@
-/*	$OpenBSD: history.c,v 1.39 2010/05/19 17:36:08 jasper Exp $	*/
+/*	$OpenBSD: history.c,v 1.40 2014/11/20 15:22:39 tedu Exp $	*/
 /*	$OpenBSD: trap.c,v 1.23 2010/05/19 17:36:08 jasper Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *		 2011, 2012, 2014
+ *		 2011, 2012, 2014, 2015
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -27,7 +27,7 @@
 #include <sys/file.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134 2014/06/09 13:25:53 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134.2.3 2015/03/01 15:43:00 tg Exp $");
 
 Trap sigtraps[NSIG + 1];
 static struct sigaction Sigact_ign;
@@ -303,7 +303,7 @@
 	for (hp = rflag ? hlast : hfirst;
 	    hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1)
 		shf_fprintf(shf, "%s\n", *hp);
-	if (shf_close(shf) == EOF) {
+	if (shf_close(shf) == -1) {
 		bi_errorf("can't %s temporary file %s: %s",
 		    "write", tf->tffn, cstrerror(errno));
 		return (1);
@@ -423,7 +423,7 @@
 
 	if (getn(str, &n)) {
 		hp = histptr + (n < 0 ? n : (n - hist_source->line));
-		if ((ptrdiff_t)hp < (ptrdiff_t)history) {
+		if ((size_t)hp < (size_t)history) {
 			if (approx)
 				hp = hist_get_oldest();
 			else {
@@ -430,7 +430,7 @@
 				bi_errorf("%s: %s", str, Tnot_in_history);
 				hp = NULL;
 			}
-		} else if ((ptrdiff_t)hp > (ptrdiff_t)histptr) {
+		} else if ((size_t)hp > (size_t)histptr) {
 			if (approx)
 				hp = hist_get_newest(allow_cur);
 			else {
@@ -634,7 +634,6 @@
 	char **hp;
 	char *c, *cp;
 
-	mkssert(cmd != NULL);
 	strdupx(c, cmd, APERM);
 	if ((cp = strchr(c, '\n')) != NULL)
 		*cp = '\0';

Modified: stable/0.5/contrib/mksh/jobs.c
===================================================================
--- stable/0.5/contrib/mksh/jobs.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/jobs.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105 2014/10/03 12:32:48 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105.2.1 2015/01/25 15:44:06 tg Exp $");
 
 #if HAVE_KILLPG
 #define mksh_killpg		killpg
@@ -1047,7 +1047,7 @@
 static void
 j_set_async(Job *j)
 {
-	Job	*jl, *oldest;
+	Job *jl, *oldest;
 
 	if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE)
 		remove_job(async_job, "async");
@@ -1084,7 +1084,7 @@
 static void
 j_startjob(Job *j)
 {
-	Proc	*p;
+	Proc *p;
 
 	j->flags |= JF_STARTED;
 	for (p = j->proc_list; p->next; p = p->next)
@@ -1421,8 +1421,8 @@
 static void
 check_job(Job *j)
 {
-	int	jstate;
-	Proc	*p;
+	int jstate;
+	Proc *p;
 
 	/* XXX debugging (nasty - interrupt routine using shl_out) */
 	if (!(j->flags & JF_STARTED)) {
@@ -1524,14 +1524,14 @@
 static void
 j_print(Job *j, int how, struct shf *shf)
 {
-	Proc	*p;
-	int	state;
-	int	status;
-	int	coredumped;
-	char	jobchar = ' ';
-	char	buf[64];
+	Proc *p;
+	int state;
+	int status;
+	int coredumped;
+	char jobchar = ' ';
+	char buf[64];
 	const char *filler;
-	int	output = 0;
+	int output = 0;
 
 	if (how == JP_PGRP) {
 		/*
@@ -1737,8 +1737,8 @@
 static Job *
 new_job(void)
 {
-	int	i;
-	Job	*newj, *j;
+	int i;
+	Job *newj, *j;
 
 	if (free_jobs != NULL) {
 		newj = free_jobs;
@@ -1766,7 +1766,7 @@
 static Proc *
 new_proc(void)
 {
-	Proc	*p;
+	Proc *p;
 
 	if (free_procs != NULL) {
 		p = free_procs;
@@ -1786,10 +1786,9 @@
 static void
 remove_job(Job *j, const char *where)
 {
-	Proc	*p, *tmp;
-	Job	**prev, *curr;
+	Proc *p, *tmp;
+	Job **prev, *curr;
 
-	mkssert(j != NULL);
 	prev = &job_list;
 	curr = job_list;
 	while (curr && curr != j) {
@@ -1830,9 +1829,8 @@
 static void
 put_job(Job *j, int where)
 {
-	Job	**prev, *curr;
+	Job **prev, *curr;
 
-	mkssert(j != NULL);
 	/* Remove job from list (if there) */
 	prev = &job_list;
 	curr = job_list;
@@ -1869,8 +1867,8 @@
 static int
 kill_job(Job *j, int sig)
 {
-	Proc	*p;
-	int	rval = 0;
+	Proc *p;
+	int rval = 0;
 
 	for (p = j->proc_list; p != NULL; p = p->next)
 		if (p->pid != 0)

Modified: stable/0.5/contrib/mksh/lalloc.c
===================================================================
--- stable/0.5/contrib/mksh/lalloc.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/lalloc.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009, 2010, 2011, 2013
+ * Copyright (c) 2009, 2010, 2011, 2013, 2014
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -20,7 +20,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20 2013/06/03 22:28:33 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20.2.1 2015/01/25 15:35:47 tg Exp $");
 
 /* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
 #if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
@@ -29,7 +29,7 @@
 #define remalloc(p,n)	realloc_osi((p), (n))
 #endif
 
-#define ALLOC_ISUNALIGNED(p) (((ptrdiff_t)(p)) % ALLOC_SIZE)
+#define ALLOC_ISUNALIGNED(p) (((size_t)(p)) % ALLOC_SIZE)
 
 static ALLOC_ITEM *findptr(ALLOC_ITEM **, char *, Area *);
 

Modified: stable/0.5/contrib/mksh/lex.c
===================================================================
--- stable/0.5/contrib/mksh/lex.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/lex.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193 2014/06/29 11:28:28 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193.2.1 2015/01/11 22:39:50 tg Exp $");
 
 /*
  * states while lexing word
@@ -854,7 +854,7 @@
 			*dp = '\0';
 			/* store the quoted string */
 			*wp++ = OQUOTE;
-			XcheckN(ws, wp, (dp - sp));
+			XcheckN(ws, wp, (dp - sp) * 2);
 			dp = sp;
 			while ((c = *dp++)) {
 				if (c == '\\') {
@@ -1027,17 +1027,24 @@
 	/* copy word to unprefixed string ident */
 	sp = yylval.cp;
 	dp = ident;
-	if ((cf & HEREDELIM) && (sp[1] == '<'))
-		while ((dp - ident) < IDENT) {
-			if ((c = *sp++) == CHAR)
-				*dp++ = *sp++;
-			else if ((c != OQUOTE) && (c != CQUOTE))
-				break;
+	if ((cf & HEREDELIM) && (sp[1] == '<')) {
+ herestringloop:
+		switch ((c = *sp++)) {
+		case CHAR:
+			++sp;
+			/* FALLTHROUGH */
+		case OQUOTE:
+		case CQUOTE:
+			goto herestringloop;
+		default:
+			break;
 		}
-	else
+		/* dummy value */
+		*dp++ = 'x';
+	} else
 		while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
 			*dp++ = *sp++;
-	/* Make sure the ident array stays '\0' padded */
+	/* make sure the ident array stays NUL padded */
 	memset(dp, 0, (ident + IDENT) - dp + 1);
 	if (c != EOS)
 		/* word is not unquoted */

Modified: stable/0.5/contrib/mksh/main.c
===================================================================
--- stable/0.5/contrib/mksh/main.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/main.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,4 +1,4 @@
-/*	$OpenBSD: main.c,v 1.54 2013/11/28 10:33:37 sobrado Exp $	*/
+/*	$OpenBSD: main.c,v 1.55 2015/02/09 09:09:30 jsg Exp $	*/
 /*	$OpenBSD: tty.c,v 1.10 2014/08/10 02:44:26 guenther Exp $	*/
 /*	$OpenBSD: io.c,v 1.25 2014/08/11 20:28:47 guenther Exp $	*/
 /*	$OpenBSD: table.c,v 1.15 2012/02/19 07:52:30 otto Exp $	*/
@@ -34,7 +34,7 @@
 #include <locale.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.284 2014/10/03 17:19:27 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285.2.2 2015/03/01 15:43:01 tg Exp $");
 
 extern char **environ;
 
@@ -892,6 +892,13 @@
 			/* FALLTHROUGH */
 		default:
 			quitenv(NULL);
+			/*
+			 * quitenv() may have reclaimed the memory
+			 * used by source which will end badly when
+			 * we jump to a function that expects it to
+			 * be valid
+			 */
+			source = NULL;
 		}
 	}
 }
@@ -1014,8 +1021,6 @@
 	struct env *ep;
 	int fd;
 
-	mkssert(e != NULL);
-
 	/*
 	 * Don't clean up temporary files - parent will probably need them.
 	 * Also, can't easily reclaim memory since variables, etc. could be
@@ -1244,7 +1249,7 @@
 	 * non-interactive shells to exit.
 	 * XXX odd use of KEEPASN; also may not want LERROR here
 	 */
-	if (builtin_flag & SPEC_BI) {
+	if (builtin_spec) {
 		builtin_argv0 = NULL;
 		unwind(LERROR);
 	}

Modified: stable/0.5/contrib/mksh/misc.c
===================================================================
--- stable/0.5/contrib/mksh/misc.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/misc.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,9 +1,9 @@
-/*	$OpenBSD: misc.c,v 1.38 2013/11/28 10:33:37 sobrado Exp $	*/
+/*	$OpenBSD: misc.c,v 1.39 2015/01/16 06:39:32 deraadt Exp $	*/
 /*	$OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *		 2011, 2012, 2013, 2014
+ *		 2011, 2012, 2013, 2014, 2015
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -30,7 +30,7 @@
 #include <grp.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219 2014/01/05 21:57:27 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219.2.2 2015/03/01 15:43:02 tg Exp $");
 
 #define KSH_CHVT_FLAG
 #ifdef MKSH_SMALL
@@ -281,15 +281,15 @@
 #endif
 		DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid));
 #else /* !HAVE_SETRESUGID */
-		/* seteuid, setegid, setgid don't EAGAIN on Linux */
+		/* setgid, setegid, seteuid don't EAGAIN on Linux */
+		setgid(kshegid);
 #ifndef MKSH__NO_SETEUGID
-		seteuid(ksheuid);
+		setegid(kshegid);
 #endif
 		DO_SETUID(setuid, (ksheuid));
 #ifndef MKSH__NO_SETEUGID
-		setegid(kshegid);
+		seteuid(ksheuid);
 #endif
-		setgid(kshegid);
 #endif /* !HAVE_SETRESUGID */
 	} else if ((f == FPOSIX || f == FSH) && newval) {
 		/* Turning on -o posix or -o sh? */
@@ -304,6 +304,11 @@
 void
 change_xtrace(unsigned char newval, bool dosnapshot)
 {
+	static bool in_xtrace;
+
+	if (in_xtrace)
+		return;
+
 	if (!dosnapshot && newval == Flag(FXTRACE))
 		return;
 
@@ -328,8 +333,13 @@
 		shl_xtrace->fd = 2;
 
  changed_xtrace:
-	if ((Flag(FXTRACE) = newval) == 2)
+	if ((Flag(FXTRACE) = newval) == 2) {
+		in_xtrace = true;
+		Flag(FXTRACE) = 0;
 		shf_puts(substitute(str_val(global("PS4")), 0), shl_xtrace);
+		Flag(FXTRACE) = 2;
+		in_xtrace = false;
+	}
 }
 
 /*
@@ -485,7 +495,6 @@
 	if (arrayset) {
 		const char *ccp = NULL;
 
-		mkssert(array != NULL);
 		if (*array)
 			ccp = skip_varname(array, false);
 		if (!ccp || !(!ccp[0] || (ccp[0] == '+' && !ccp[1]))) {
@@ -1384,8 +1393,7 @@
 {
 	char *xp, *ip, *tp, *ipath, *ldest = NULL;
 	XString xs;
-	ptrdiff_t pos;
-	size_t len;
+	size_t pos, len;
 	int llen;
 	struct stat sb;
 #ifdef MKSH__NO_PATH_MAX

Modified: stable/0.5/contrib/mksh/mksh.1
===================================================================
--- stable/0.5/contrib/mksh/mksh.1	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/mksh.1	2015-03-20 12:28:09 UTC (rev 6990)
@@ -1,9 +1,9 @@
-.\" $MirOS: src/bin/mksh/mksh.1,v 1.344 2014/10/07 15:30:12 tg Exp $
-.\" $OpenBSD: ksh.1,v 1.153 2014/08/17 07:15:41 jmc Exp $
+.\" $MirOS: src/bin/mksh/mksh.1,v 1.344.2.3 2015/03/01 15:43:03 tg Exp $
+.\" $OpenBSD: ksh.1,v 1.156 2015/01/16 15:32:32 schwarze Exp $
 .\"-
 .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-.\"		2010, 2011, 2012, 2013, 2014
-.\"	Thorsten Glaser <tg at mirbsd.org>
+.\"		2010, 2011, 2012, 2013, 2014, 2015
+.\"	Thorsten “mirabilos” Glaser <tg at mirbsd.org>
 .\"
 .\" Provided that these terms and disclaimer and all copyright notices
 .\" are retained or reproduced in an accompanying document, permission
@@ -74,7 +74,7 @@
 .\" with -mandoc, it might implement .Mx itself, but we want to
 .\" use our own definition. And .Dd must come *first*, always.
 .\"
-.Dd $Mdocdate: October 7 2014 $
+.Dd $Mdocdate: March 1 2015 $
 .\"
 .\" Check which macro package we use, and do other -mdoc setup.
 .\"
@@ -673,11 +673,11 @@
 .It Xo case Ar word No in
 .Oo Op \&(
 .Ar pattern
-.Op \*(Ba Ar pat
+.Op \*(Ba Ar pattern
 .No ... Ns )
 .Ar list
-.Op ;; \*(Ba ;&\& \*(Ba ;\*(Ba\ \&
-.Oc ... esac
+.Ic terminator
+.Oc No ... esac
 .Xc
 The
 .Ic case
@@ -707,9 +707,11 @@
 and
 .Ic esac
 e.g.\&
-.Ic case $foo { *) echo bar;; } .
+.Ic case $foo { *) echo bar ;; } .
 .Pp
-The list terminators are:
+The list
+.Ic terminator Ns s
+are:
 .Bl -tag -width 4n
 .It Ql ;;
 Terminate after the list.
@@ -2923,6 +2925,10 @@
 .It
 The EXIT trap, if set in a function, will be executed after the function
 returns.
+.It
+Shell options
+.Pq Ic set Fl o
+have local scope, i.e. changes inside a function are reset upon its exit.
 .El
 .Ss Command execution
 After evaluation of command-line arguments, redirections, and parameter
@@ -3370,9 +3376,25 @@
 .Pp
 .It Xo
 .Ic exec
+.Op Fl a Ar argv0
+.Op Fl c
 .Op Ar command Op Ar arg ...
 .Xc
 The command is executed without forking, replacing the shell process.
+This is currently absolute, i.e.\&
+.Ic exec
+never returns, even if the
+.Ar command
+is not found.
+The
+.Fl a
+option permits setting a different
+.Li argv[0]
+value, and
+.Fl c
+clears the environment before executing the child process, except for the
+.Ev _
+variable and direct assignments.
 .Pp
 If no command is given except for I/O redirection, the I/O redirection is
 permanent and the shell is
@@ -6457,6 +6479,17 @@
 instead, but be aware that, in POSIX, it's legal for the OS to make
 .Li print $((2147483647 + 1))
 delete all files on your system, as it's Undefined Behaviour.
+.Pp
+.Nm mksh
+provides a consistent, clear interface normally.
+This may deviate from POSIX in optional or opinionated places, such
+as whether leading-digit-zero numbers should be interpreted as octal.
+.Ic set \-o posix
+will cause the shell (either
+.Nm mksh
+or
+.Nm lksh )
+to behave more like the standard expects.
 .Sh BUGS
 Suspending (using \*(haZ) pipelines like the one below will only suspend
 the currently running part of the pipeline; in this example,
@@ -6468,7 +6501,7 @@
 .Ed
 .Pp
 This document attempts to describe
-.Nm mksh\ R50
+.Nm mksh\ R50e
 and up,
 compiled without any options impacting functionality, such as
 .Dv MKSH_SMALL ,
@@ -6475,9 +6508,12 @@
 when not called as
 .Pa /bin/sh
 which, on some systems only, enables
+.Ic set \-o posix
+or
 .Ic set \-o sh
 automatically (whose behaviour differs across targets),
 for an operating environment supporting all of its advanced needs.
+.Pp
 Please report bugs in
 .Nm
 to the

Modified: stable/0.5/contrib/mksh/sh.h
===================================================================
--- stable/0.5/contrib/mksh/sh.h	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/sh.h	2015-03-20 12:28:09 UTC (rev 6990)
@@ -10,7 +10,7 @@
 
 /*-
  * Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *	       2011, 2012, 2013, 2014
+ *	       2011, 2012, 2013, 2014, 2015
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -169,9 +169,9 @@
 #endif
 
 #ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.697 2014/10/07 15:22:17 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.701.2.4 2015/03/01 15:43:05 tg Exp $");
 #endif
-#define MKSH_VERSION "R50 2014/10/07"
+#define MKSH_VERSION "R50 2015/03/01"
 
 /* arithmetic types: C implementation */
 #if !HAVE_CAN_INTTYPES
@@ -312,9 +312,13 @@
 #undef PATH_MAX
 #else
 #ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX	MAXPATHLEN
+#else
 #define PATH_MAX	1024
 #endif
 #endif
+#endif
 #ifndef SIZE_MAX
 #ifdef SIZE_T_MAX
 #define SIZE_MAX	SIZE_T_MAX
@@ -533,7 +537,7 @@
 #define mkssert(e)	do { } while (/* CONSTCOND */ 0)
 #endif
 
-#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 504)
+#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 505)
 #error Must run Build.sh to compile this.
 extern void thiswillneverbedefinedIhope(void);
 int
@@ -992,8 +996,8 @@
 
 /* name of called builtin function (used by error functions) */
 EXTERN const char *builtin_argv0;
-/* flags of called builtin (SPEC_BI, etc.) */
-EXTERN uint32_t builtin_flag;
+/* is called builtin SPEC_BI? */
+EXTERN bool builtin_spec;
 
 /* current working directory */
 EXTERN char	*current_wd;
@@ -1233,6 +1237,7 @@
 
 /* Values for struct block.flags */
 #define BF_DOGETOPTS	BIT(0)	/* save/restore getopts state */
+#define BF_STOPENV	BIT(1)	/* do not export further */
 
 /*
  * Used by ktwalk() and ktnext() routines.
@@ -1396,7 +1401,8 @@
 #define DOVACHECK BIT(9)	/* var assign check (for typeset, set, etc) */
 #define DOMARKDIRS BIT(10)	/* force markdirs behaviour */
 #define DOTCOMEXEC BIT(11)	/* not an eval flag, used by sh -c hack */
-#define DOASNFIELD BIT(12)	/* is assignment, change field handling */
+#define DOSCALAR BIT(12)	/* change field handling to non-list context */
+#define DOHEREDOC BIT(13)	/* change scalar handling to heredoc body */
 
 #define X_EXTRA	20	/* this many extra bytes in X string */
 
@@ -1645,7 +1651,7 @@
 char *debunk(char *, const char *, size_t);
 void expand(const char *, XPtrV *, int);
 int glob_str(char *, XPtrV *, bool);
-char *tilde(char *);
+char *do_tilde(char *);
 /* exec.c */
 int execute(struct op * volatile, volatile int, volatile int * volatile);
 int shcomexec(const char **);

Modified: stable/0.5/contrib/mksh/shf.c
===================================================================
--- stable/0.5/contrib/mksh/shf.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/shf.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
- *		 2012, 2013
+ *		 2012, 2013, 2015
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -25,7 +25,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62 2013/10/09 11:59:30 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62.2.2 2015/03/01 15:43:07 tg Exp $");
 
 /* flags to shf_emptybuf() */
 #define EB_READSW	0x01	/* about to switch to reading */
@@ -232,7 +232,7 @@
 	if (shf->fd >= 0) {
 		ret = shf_flush(shf);
 		if (close(shf->fd) < 0)
-			ret = EOF;
+			ret = -1;
 	}
 	if (shf->flags & SHF_ALLOCS)
 		afree(shf, shf->areap);
@@ -251,7 +251,7 @@
 	if (shf->fd >= 0) {
 		ret = shf_flush(shf);
 		if (close(shf->fd) < 0)
-			ret = EOF;
+			ret = -1;
 		shf->rnleft = 0;
 		shf->rp = shf->buf;
 		shf->wnleft = 0;
@@ -283,13 +283,13 @@
 
 /*
  * Un-read what has been read but not examined, or write what has been
- * buffered. Returns 0 for success, EOF for (write) error.
+ * buffered. Returns 0 for success, -1 for (write) error.
  */
 int
 shf_flush(struct shf *shf)
 {
 	if (shf->flags & SHF_STRING)
-		return ((shf->flags & SHF_WR) ? EOF : 0);
+		return ((shf->flags & SHF_WR) ? -1 : 0);
 
 	if (shf->fd < 0)
 		internal_errorf("%s: %s", "shf_flush", "no fd");
@@ -296,7 +296,7 @@
 
 	if (shf->flags & SHF_ERROR) {
 		errno = shf->errnosv;
-		return (EOF);
+		return (-1);
 	}
 
 	if (shf->flags & SHF_READING) {
@@ -315,7 +315,7 @@
 
 /*
  * Write out any buffered data. If currently reading, flushes the read
- * buffer. Returns 0 for success, EOF for (write) error.
+ * buffer. Returns 0 for success, -1 for (write) error.
  */
 static int
 shf_emptybuf(struct shf *shf, int flags)
@@ -327,7 +327,7 @@
 
 	if (shf->flags & SHF_ERROR) {
 		errno = shf->errnosv;
-		return (EOF);
+		return (-1);
 	}
 
 	if (shf->flags & SHF_READING) {
@@ -347,7 +347,7 @@
 		 */
 		if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) ||
 		    !(shf->flags & SHF_ALLOCB))
-			return (EOF);
+			return (-1);
 		/* allocate more space for buffer */
 		nbuf = aresize2(shf->buf, 2, shf->wbsize, shf->areap);
 		shf->rp = nbuf + (shf->rp - shf->buf);
@@ -379,7 +379,7 @@
 						    ntowrite);
 						shf->wp = shf->buf + ntowrite;
 					}
-					return (EOF);
+					return (-1);
 				}
 				buf += n;
 				ntowrite -= n;
@@ -399,7 +399,7 @@
 	return (ret);
 }
 
-/* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */
+/* Fill up a read buffer. Returns -1 for a read error, 0 otherwise. */
 static int
 shf_fillbuf(struct shf *shf)
 {
@@ -414,11 +414,11 @@
 	if (shf->flags & (SHF_EOF | SHF_ERROR)) {
 		if (shf->flags & SHF_ERROR)
 			errno = shf->errnosv;
-		return (EOF);
+		return (-1);
 	}
 
-	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
-		return (EOF);
+	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
+		return (-1);
 
 	shf->flags |= SHF_READING;
 
@@ -434,7 +434,7 @@
 		shf->errnosv = errno;
 		shf->rnleft = 0;
 		shf->rp = shf->buf;
-		return (EOF);
+		return (-1);
 	}
 	if ((shf->rnleft = n) == 0)
 		shf->flags |= SHF_EOF;
@@ -443,7 +443,7 @@
 
 /*
  * Read a buffer from shf. Returns the number of bytes read into buf, if
- * no bytes were read, returns 0 if end of file was seen, EOF if a read
+ * no bytes were read, returns 0 if end of file was seen, -1 if a read
  * error occurred.
  */
 ssize_t
@@ -459,7 +459,7 @@
 
 	while (bsize > 0) {
 		if (shf->rnleft == 0 &&
-		    (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
+		    (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
 			break;
 		ncopy = shf->rnleft;
 		if (ncopy > bsize)
@@ -471,12 +471,12 @@
 		shf->rnleft -= ncopy;
 	}
 	/* Note: fread(3S) returns 0 for errors - this doesn't */
-	return (orig_bsize == bsize ? (shf_error(shf) ? EOF : 0) :
+	return (orig_bsize == bsize ? (shf_error(shf) ? -1 : 0) :
 	    orig_bsize - bsize);
 }
 
 /*
- * Read up to a newline or EOF. The newline is put in buf; buf is always
+ * Read up to a newline or -1. The newline is put in buf; buf is always
  * NUL terminated. Returns NULL on read error or if nothing was read
  * before end of file, returns a pointer to the NUL byte in buf
  * otherwise.
@@ -498,7 +498,7 @@
 	--bsize;
 	do {
 		if (shf->rnleft == 0) {
-			if (shf_fillbuf(shf) == EOF)
+			if (shf_fillbuf(shf) == -1)
 				return (NULL);
 			if (shf->rnleft == 0) {
 				*buf = '\0';
@@ -520,7 +520,7 @@
 	return (buf);
 }
 
-/* Returns the char read. Returns EOF for error and end of file. */
+/* Returns the char read. Returns -1 for error and end of file. */
 int
 shf_getchar(struct shf *shf)
 {
@@ -527,8 +527,8 @@
 	if (!(shf->flags & SHF_RD))
 		internal_errorf("%s: flags 0x%X", "shf_getchar", shf->flags);
 
-	if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
-		return (EOF);
+	if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
+		return (-1);
 	--shf->rnleft;
 	return (*shf->rp++);
 }
@@ -535,7 +535,7 @@
 
 /*
  * Put a character back in the input stream. Returns the character if
- * successful, EOF if there is no room.
+ * successful, -1 if there is no room.
  */
 int
 shf_ungetc(int c, struct shf *shf)
@@ -543,12 +543,12 @@
 	if (!(shf->flags & SHF_RD))
 		internal_errorf("%s: flags 0x%X", "shf_ungetc", shf->flags);
 
-	if ((shf->flags & SHF_ERROR) || c == EOF ||
+	if ((shf->flags & SHF_ERROR) || c == -1 ||
 	    (shf->rp == shf->buf && shf->rnleft))
-		return (EOF);
+		return (-1);
 
-	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
-		return (EOF);
+	if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
+		return (-1);
 
 	if (shf->rp == shf->buf)
 		shf->rp = shf->buf + shf->rbsize;
@@ -558,7 +558,7 @@
 		 * we don't want to modify a string.
 		 */
 		if ((int)(shf->rp[-1]) != c)
-			return (EOF);
+			return (-1);
 		shf->flags &= ~SHF_EOF;
 		shf->rp--;
 		shf->rnleft++;
@@ -571,7 +571,7 @@
 }
 
 /*
- * Write a character. Returns the character if successful, EOF if the
+ * Write a character. Returns the character if successful, -1 if the
  * char could not be written.
  */
 int
@@ -580,8 +580,8 @@
 	if (!(shf->flags & SHF_WR))
 		internal_errorf("%s: flags 0x%X", "shf_putchar", shf->flags);
 
-	if (c == EOF)
-		return (EOF);
+	if (c == -1)
+		return (-1);
 
 	if (shf->flags & SHF_UNBUF) {
 		unsigned char cc = (unsigned char)c;
@@ -591,7 +591,7 @@
 			internal_errorf("%s: %s", "shf_putchar", "no fd");
 		if (shf->flags & SHF_ERROR) {
 			errno = shf->errnosv;
-			return (EOF);
+			return (-1);
 		}
 		while ((n = write(shf->fd, &cc, 1)) != 1)
 			if (n < 0) {
@@ -600,12 +600,12 @@
 					continue;
 				shf->flags |= SHF_ERROR;
 				shf->errnosv = errno;
-				return (EOF);
+				return (-1);
 			}
 	} else {
 		/* Flush deals with strings and sticky errors */
-		if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)
-			return (EOF);
+		if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == -1)
+			return (-1);
 		shf->wnleft--;
 		*shf->wp++ = c;
 	}
@@ -614,7 +614,7 @@
 }
 
 /*
- * Write a string. Returns the length of the string if successful, EOF
+ * Write a string. Returns the length of the string if successful, -1
  * if the string could not be written.
  */
 ssize_t
@@ -621,12 +621,12 @@
 shf_puts(const char *s, struct shf *shf)
 {
 	if (!s)
-		return (EOF);
+		return (-1);
 
 	return (shf_write(s, strlen(s), shf));
 }
 
-/* Write a buffer. Returns nbytes if successful, EOF if there is an error. */
+/* Write a buffer. Returns nbytes if successful, -1 if there is an error. */
 ssize_t
 shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
 {
@@ -653,13 +653,13 @@
 		if (shf->flags & SHF_STRING) {
 			/* resize buffer until there's enough space left */
 			while (nbytes > shf->wnleft)
-				if (shf_emptybuf(shf, EB_GROW) == EOF)
-					return (EOF);
+				if (shf_emptybuf(shf, EB_GROW) == -1)
+					return (-1);
 			/* then write everything into the buffer */
 		} else {
 			/* flush deals with sticky errors */
-			if (shf_emptybuf(shf, EB_GROW) == EOF)
-				return (EOF);
+			if (shf_emptybuf(shf, EB_GROW) == -1)
+				return (-1);
 			/* write chunks larger than window size directly */
 			if (nbytes > shf->wbsize) {
 				ncopy = nbytes;
@@ -679,7 +679,7 @@
 						 * Note: fwrite(3) returns 0
 						 * for errors - this doesn't
 						 */
-						return (EOF);
+						return (-1);
 					}
 					buf += n;
 					ncopy -= n;
@@ -767,12 +767,7 @@
 	ssize_t field, precision, len;
 	unsigned long lnum;
 	/* %#o produces the longest output */
-	char numbuf[(8 * sizeof(long) + 2) / 3 + 1
-#ifdef DEBUG
-		/* a NUL for LLVM/Clang scan-build */
-		+ 1
-#endif
-	    ];
+	char numbuf[(8 * sizeof(long) + 2) / 3 + 1];
 	/* this stuff for dealing with the buffer */
 	ssize_t nwritten = 0;
 
@@ -910,16 +905,6 @@
  integral:
 			flags |= FL_NUMBER;
 			cp = numbuf + sizeof(numbuf);
-#ifdef DEBUG
-			/*
-			 * this is necessary so Clang 3.2 realises
-			 * utf_skipcols/shf_putc in the output loop
-			 * terminate; these values are always ASCII
-			 * so an out-of-bounds access cannot happen
-			 * but Clang doesn't know that
-			 */
-			*--cp = '\0';
-#endif
 
 			switch (c) {
 			case 'd':
@@ -971,10 +956,6 @@
 			}
 			}
 			len = numbuf + sizeof(numbuf) - (s = cp);
-#ifdef DEBUG
-			/* see above comment for Clang 3.2 */
-			--len;
-#endif
 			if (flags & FL_DOT) {
 				if (precision > len) {
 					field = precision;
@@ -1068,7 +1049,7 @@
 		}
 	}
 
-	return (shf_error(shf) ? EOF : nwritten);
+	return (shf_error(shf) ? -1 : nwritten);
 }
 
 #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)

Modified: stable/0.5/contrib/mksh/syn.c
===================================================================
--- stable/0.5/contrib/mksh/syn.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/syn.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94 2014/01/05 21:57:29 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94.2.1 2015/01/25 15:35:54 tg Exp $");
 
 struct nesting_state {
 	int start_token;	/* token than began nesting (eg, FOR) */
@@ -196,10 +196,11 @@
 	musthave(LWORD, ishere ? HEREDELIM : 0);
 	if (ishere) {
 		iop->delim = yylval.cp;
-		if (*ident != 0)
+		if (*ident != 0) {
 			/* unquoted */
  gotnulldelim:
 			iop->flag |= IOEVAL;
+		}
 		if (herep > &heres[HERES - 1])
 			yyerror("too many %ss\n", "<<");
 		*herep++ = iop;

Modified: stable/0.5/contrib/mksh/var.c
===================================================================
--- stable/0.5/contrib/mksh/var.c	2015-03-20 12:23:17 UTC (rev 6989)
+++ stable/0.5/contrib/mksh/var.c	2015-03-20 12:28:09 UTC (rev 6990)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *		 2011, 2012, 2013, 2014
+ *		 2011, 2012, 2013, 2014, 2015
  *	Thorsten Glaser <tg at mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -28,7 +28,7 @@
 #include <sys/sysctl.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183 2014/10/04 11:47:19 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183.2.2 2015/03/01 15:43:07 tg Exp $");
 
 /*-
  * Variables
@@ -308,7 +308,6 @@
 	 * dereference namerefs; must come first
 	 */
 	n = array_index_calc(n, &array, &val);
-	mkssert(n != NULL);
 	h = hash(n);
 	if (!ksh_isalphx(*n)) {
 		vp = &vtemp;
@@ -679,8 +678,6 @@
 	char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
 	size_t namelen, vallen;
 
-	mkssert(val != NULL);
-
 	namelen = strlen(vp->name);
 	vallen = strlen(val) + 1;
 
@@ -1114,6 +1111,8 @@
 				}
 				XPput(denv, vp->val.s);
 			}
+		if (l->flags & BF_STOPENV)
+			break;
 	}
 	XPput(denv, NULL);
 	return ((char **)XPclose(denv));



More information about the Midnightbsd-cvs mailing list