Android-x86
Fork
Faire un don

  • R/O
  • HTTP
  • SSH
  • HTTPS

external-mksh: Commit

external/mksh


Commit MetaInfo

Révision6e155df5a80c981187d6ae41698a84af1f375440 (tree)
l'heure2012-04-27 19:59:17
AuteurThorsten Glaser <tg@mirb...>
CommiterThorsten Glaser

Message de Log

Update mksh to 2012-04-22

The files in src/ are unmodified from MirBSD CVS and Not a Contribution.
src/00-NOTE.txt is excluded from that clause. Upstream ChangeLog:
https://www.mirbsd.org/mksh.htm#clog

Changes, other than upstream mksh code:
• update Copyright years
• sync with moving to a different AOSP project and other AOSP changes
• mkmf.sh: add test compilation mode
• be conservative in filedescriptor usage
• disable deprecated code (will be removed in next mksh release anyway):

– hack to change interactive input line starting with ‘!’
into one starting with ‘r ’ to access history
– parse numbers with leading zeros as octal

• don’t compile the $MirOS$ RCS IDs into the binary to save space
• update rest of mkmf.sh to work with updated AOSP and mksh
• use ro.product.device property as default hostname in mkshrc

(originally submitted by John Michelau <john.michelau@motorola.com>)

• do not export PS1 in mkshrc (cross-shell developers agreed on this)
• add “more” and “setenv” functions to mkshrc to get a simplistic pager
• mention Launchpad as upstream bugtracker as comment in mkshrc
• change TMPDIR to /data/data for now, as /sqlite_stmt_journals is gone

(although this is still no full replacement, it’s better than before)

• address the segfaults seen by DONG-DONG YANG

Change-Id: I2d4d175bc5163b3d6f5098024f98f316fe812e55

Change Summary

Modification

--- a/Android.mk
+++ b/Android.mk
@@ -1,4 +1,4 @@
1-# Copyright © 2010
1+# Copyright © 2010, 2012
22 # Thorsten Glaser <t.glaser@tarent.de>
33 # This file is provided under the same terms as mksh.
44
@@ -34,31 +34,38 @@ LOCAL_SYSTEM_SHARED_LIBRARIES:= libc
3434
3535 LOCAL_C_INCLUDES:= $(LOCAL_PATH)/src
3636 # additional flags first, then from Makefrag.inc: CFLAGS, CPPFLAGS
37-LOCAL_CFLAGS:= -DMKSH_DEFAULT_EXECSHELL=\"/system/bin/sh\" \
38- -DMKSH_DEFAULT_TMPDIR=\"/sqlite_stmt_journals\" \
39- -DMKSHRC_PATH=\"/system/etc/mkshrc\" \
37+LOCAL_CFLAGS:= -DMKSHRC_PATH=\"/system/etc/mkshrc\" \
38+ -DMKSH_DEFAULT_EXECSHELL=\"/system/bin/sh\" \
39+ -DMKSH_DEFAULT_TMPDIR=\"/data/data\" \
4040 -fwrapv \
41- -DMKSH_ASSUME_UTF8=0 -DMKSH_NOPWNAM \
42- -D_GNU_SOURCE \
41+ -DMKSH_ASSUME_UTF8=0 -DMKSH_CONSERVATIVE_FDS \
42+ -DMKSH_DISABLE_DEPRECATED -DMKSH_DONT_EMIT_IDSTRING \
43+ -DMKSH_NOPWNAM -DMKSH_BUILDSH \
44+ -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN \
4345 -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 \
4446 -DHAVE_ATTRIBUTE_NONNULL=1 -DHAVE_ATTRIBUTE_NORETURN=1 \
4547 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 \
46- -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_MKDEV_H=0 \
47- -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_SYSMACROS_H=1 \
48+ -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 \
49+ -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 \
50+ -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_SELECT_H=1 \
51+ -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 \
4852 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 \
49- -DHAVE_PATHS_H=1 -DHAVE_STDBOOL_H=1 -DHAVE_STDINT_H=1 \
53+ -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 \
5054 -DHAVE_STRINGS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 \
5155 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 \
5256 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 \
5357 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_SIGNAME=1 \
5458 -DHAVE_SYS_SIGLIST=1 -DHAVE_STRSIGNAL=0 \
59+ -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 \
5560 -DHAVE_GETRUSAGE=1 -DHAVE_KILLPG=1 -DHAVE_MKNOD=0 \
56- -DHAVE_MKSTEMP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 \
61+ -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 \
5762 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 \
58- -DHAVE_SETMODE=1 -DHAVE_SETRESUGID=1 \
59- -DHAVE_SETGROUPS=1 -DHAVE_STRCASESTR=1 \
63+ -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 \
6064 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 \
6165 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \
62- -DHAVE_PERSISTENT_HISTORY=0
66+ -DHAVE_PERSISTENT_HISTORY=0 -DHAVE_SILENT_IDIVWRAPV=0 \
67+ -DMKSH_BUILD_R=409
68+
69+# check categories: android convfds nodeprecated no-histfile
6370
6471 include $(BUILD_EXECUTABLE)
--- a/NOTICE
+++ b/NOTICE
@@ -1,7 +1,8 @@
11 mksh is covered by The MirOS Licence:
22
33 /*-
4- * Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4+ * Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5+ * 2011, 2012
56 * Thorsten Glaser <tg@mirbsd.org>
67 *
78 * Provided that these terms and disclaimer and all copyright notices
--- a/mkmf.sh
+++ b/mkmf.sh
@@ -1,4 +1,4 @@
1-# Copyright © 2010
1+# Copyright © 2010, 2012
22 # Thorsten Glaser <t.glaser@tarent.de>
33 # This file is provided under the same terms as mksh.
44 #-
@@ -8,11 +8,21 @@
88 # This script is supposed to be run from/inside AOSP by the
99 # porter of mksh to Android (and only manually).
1010
11+if test x"$1" = x"-t"; then
12+ # test compilation
13+ args=-r
14+ mkmfmode=1
15+else
16+ # prepare for AOSP
17+ args=-M
18+ mkmfmode=0
19+fi
20+
1121 cd "$(dirname "$0")"
1222 srcdir=$(pwd)
1323 rm -rf tmp
1424 mkdir tmp
15-cd ../../..
25+cd ../..
1626 aospdir=$(pwd)
1727 cd $srcdir/tmp
1828
@@ -42,64 +52,75 @@ LIBS=
4252 # Since we no longer use the NDK, the AOSP has to have been
4353 # built before using this script (targetting generic/emulator).
4454
45-CC=$aospdir/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-gcc
46-addvar CPPFLAGS -I$aospdir/system/core/include \
47- -I$aospdir/hardware/libhardware/include \
48- -I$aospdir/system/core/include \
49- -I$aospdir/hardware/libhardware/include \
50- -I$aospdir/hardware/libhardware_legacy/include \
51- -I$aospdir/hardware/ril/include \
52- -I$aospdir/dalvik/libnativehelper/include \
53- -I$aospdir/frameworks/base/include \
54- -I$aospdir/frameworks/base/opengl/include \
55- -I$aospdir/external/skia/include \
56- -I$aospdir/out/target/product/generic/obj/include \
57- -I$aospdir/bionic/libc/arch-arm/include \
58- -I$aospdir/bionic/libc/include \
59- -I$aospdir/bionic/libstdc++/include \
60- -I$aospdir/bionic/libc/kernel/common \
61- -I$aospdir/bionic/libc/kernel/arch-arm \
62- -I$aospdir/bionic/libm/include \
63- -I$aospdir/bionic/libm/include/arch/arm \
64- -I$aospdir/bionic/libthread_db/include \
65- -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ \
66- -I$aospdir/system/core/include/arch/linux-arm/ \
55+CC=$aospdir/prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-gcc
56+addvar CPPFLAGS \
57+ -I$aospdir/dalvik/libnativehelper/include/nativehelper \
58+ -isystem $aospdir/system/core/include \
59+ -isystem $aospdir/hardware/libhardware/include \
60+ -isystem $aospdir/hardware/libhardware_legacy/include \
61+ -isystem $aospdir/hardware/ril/include \
62+ -isystem $aospdir/dalvik/libnativehelper/include \
63+ -isystem $aospdir/frameworks/base/include \
64+ -isystem $aospdir/frameworks/base/opengl/include \
65+ -isystem $aospdir/frameworks/base/native/include \
66+ -isystem $aospdir/external/skia/include \
67+ -isystem $aospdir/out/target/product/generic/obj/include \
68+ -isystem $aospdir/bionic/libc/arch-arm/include \
69+ -isystem $aospdir/bionic/libc/include \
70+ -isystem $aospdir/bionic/libstdc++/include \
71+ -isystem $aospdir/bionic/libc/kernel/common \
72+ -isystem $aospdir/bionic/libc/kernel/arch-arm \
73+ -isystem $aospdir/bionic/libm/include \
74+ -isystem $aospdir/bionic/libm/include/arm \
75+ -isystem $aospdir/bionic/libthread_db/include \
6776 -include $aospdir/system/core/include/arch/linux-arm/AndroidConfig.h \
77+ -I$aospdir/system/core/include/arch/linux-arm/ \
6878 -DANDROID -DNDEBUG -UDEBUG
6979 addvar CFLAGS -fno-exceptions -Wno-multichar -msoft-float -fpic \
70- -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums \
71- -march=armv5te -mtune=xscale -mthumb-interwork -fmessage-length=0 \
72- -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type \
73- -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point \
74- -Wstrict-aliasing=2 -finline-functions -fno-inline-functions-called-once \
75- -fgcse-after-reload -frerun-cse-after-loop -frename-registers -mthumb \
76- -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
80+ -ffunction-sections -fdata-sections -funwind-tables -fstack-protector \
81+ -Wa,--noexecstack -Werror=format-security -fno-short-enums \
82+ -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -Wno-psabi \
83+ -mthumb-interwork -fmessage-length=0 -W -Wall -Wno-unused -Winit-self \
84+ -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor \
85+ -Werror=address -Werror=sequence-point -g -Wstrict-aliasing=2 \
86+ -fgcse-after-reload -frerun-cse-after-loop -frename-registers \
87+ -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing
7788 addvar LDFLAGS -nostdlib -Bdynamic -Wl,-T,$aospdir/build/core/armelf.x \
7889 -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections \
79- -Wl,-z,nocopyreloc -Wl,--no-undefined \
90+ -Wl,-z,nocopyreloc -Wl,-z,noexecstack -Wl,--icf=safe -Wl,--fix-cortex-a8 \
91+ -Wl,--no-undefined \
8092 $aospdir/out/target/product/generic/obj/lib/crtbegin_dynamic.o
8193 addvar LIBS -L$aospdir/out/target/product/generic/obj/lib \
8294 -Wl,-rpath-link=$aospdir/out/target/product/generic/obj/lib -lc \
83- $aospdir/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/interwork/libgcc.a \
95+ $aospdir/prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/armv7-a/libgcc.a \
8496 $aospdir/out/target/product/generic/obj/lib/crtend_android.o
8597
8698
99+### Flags used by test builds
100+if test $mkmfmode = 1; then
101+ addvar CPPFLAGS '-DMKSHRC_PATH=\"/system/etc/mkshrc\"'
102+ addvar CPPFLAGS '-DMKSH_DEFAULT_EXECSHELL=\"/system/bin/sh\"'
103+ addvar CPPFLAGS '-DMKSH_DEFAULT_TMPDIR=\"/data/data\"'
104+fi
105+
87106 ### Override flags
88107 # We don’t even *support* UTF-8 by default ☹
89108 addvar CPPFLAGS -DMKSH_ASSUME_UTF8=0
109+# Reduce filedescriptor usage
110+addvar CPPFLAGS -DMKSH_CONSERVATIVE_FDS
111+# Leave out things scheduled for later removal
112+addvar CPPFLAGS -DMKSH_DISABLE_DEPRECATED
113+# Leave out RCS ID strings from the binary
114+addvar CPPFLAGS -DMKSH_DONT_EMIT_IDSTRING
90115 # No getpwnam() calls (affects "cd ~username/" only)
91116 addvar CPPFLAGS -DMKSH_NOPWNAM
92-# Compile an extra small mksh (optional)
93-#addvar CPPFLAGS -DMKSH_SMALL
94117 # Leave out the ulimit builtin
95118 #addvar CPPFLAGS -DMKSH_NO_LIMITS
119+# Compile an extra small mksh (optional)
120+#addvar CPPFLAGS -DMKSH_SMALL
96121
97122 # Set target platform
98-TARGET_OS=Linux
99-# Building with -std=c99 or -std=gnu99 clashes with Bionic headers
100-HAVE_CAN_STDG99=0
101-HAVE_CAN_STDC99=0
102-export HAVE_CAN_STDG99 HAVE_CAN_STDC99
123+TARGET_OS=Android
103124
104125 # Android-x86 does not have helper functions for ProPolice SSP
105126 # and AOSP adds the flags by itself (same for warning flags)
@@ -108,16 +129,19 @@ HAVE_CAN_FSTACKPROTECTORALL=0
108129 HAVE_CAN_WALL=0
109130 export HAVE_CAN_FNOSTRICTALIASING HAVE_CAN_FSTACKPROTECTORALL HAVE_CAN_WALL
110131
111-# disable the mknod(8) built-in to get rid of needing setmode.c
112-HAVE_MKNOD=0; export HAVE_MKNOD
113-
114132 # even the idea of persistent history on a phone is funny
115133 HAVE_PERSISTENT_HISTORY=0; export HAVE_PERSISTENT_HISTORY
116134
135+# this is a run-time check and dependent on the target CPU
136+# architecture (at _least_!) and cannot be auto-detected,
137+# so always include the safety check even if unnecessary
138+HAVE_SILENT_IDIVWRAPV=0; export HAVE_SILENT_IDIVWRAPV
139+
117140 # ... and run it!
118141 export CC CPPFLAGS CFLAGS LDFLAGS LIBS TARGET_OS
119-sh ../src/Build.sh -M
142+sh ../src/Build.sh $args
120143 rv=$?
144+test x"$args" = x"-r" && exit $rv
121145 test x0 = x"$rv" && mv -f Makefrag.inc ../
122146 cd ..
123147 rm -rf tmp
--- a/mkshrc
+++ b/mkshrc
@@ -1,11 +1,13 @@
1-# Copyright (c) 2010
1+# Copyright (c) 2010, 2012
22 # Thorsten Glaser <t.glaser@tarent.de>
33 # This file is provided under the same terms as mksh.
44 #-
55 # Minimal /system/etc/mkshrc for Android
6+#
7+# Support: https://launchpad.net/mksh
68
7-: ${TERM:=vt100} ${HOME:=/data} ${MKSH:=/system/bin/sh} ${HOSTNAME:=android}
8-: ${SHELL:=$MKSH} ${USER:=$(typeset x=$(id); x=${x#*\(}; print -r -- ${x%%\)*})}
9+: ${TERM:=vt100} ${HOME:=/data} ${MKSH:=/system/bin/sh} ${HOSTNAME:=$(getprop ro.product.device)}
10+: ${SHELL:=$MKSH} ${USER:=$(typeset x=$(id); x=${x#*\(}; print -r -- ${x%%\)*})} ${HOSTNAME:=android}
911 if (( USER_ID )); then PS1='$'; else PS1='#'; fi
1012 function precmd {
1113 typeset e=$?
@@ -13,12 +15,33 @@ function precmd {
1315 (( e )) && print -n "$e|"
1416 }
1517 PS1='$(precmd)$USER@$HOSTNAME:${PWD:-?} '"$PS1 "
16-export HOME HOSTNAME MKSH PS1 SHELL TERM USER
18+export HOME HOSTNAME MKSH SHELL TERM USER
1719 alias l='ls'
1820 alias la='l -a'
1921 alias ll='l -l'
2022 alias lo='l -a -l'
2123
24+function more {
25+ local dummy line llen curlin=0
26+
27+ cat "$@" | while IFS= read -r line; do
28+ llen=${%line}
29+ (( llen == -1 )) && llen=${#line}
30+ (( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
31+ if (( (curlin += llen) >= LINES )); then
32+ print -n -- '\033[7m--more--\033[0m'
33+ read -u1 dummy
34+ [[ $dummy = [Qq]* ]] && return 0
35+ curlin=$llen
36+ fi
37+ print -r -- "$line"
38+ done
39+}
40+
41+function setenv {
42+ eval export $1'="$2"'
43+}
44+
2245 for p in ~/.bin; do
2346 [[ -d $p/. ]] || continue
2447 [[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
--- a/src/00-NOTE.txt
+++ b/src/00-NOTE.txt
@@ -1,4 +1,4 @@
1-This is mksh from AnonCVS on 2010-08-24 with the
1+This is mksh from CVS on 2012-04-22 with the
22 following files removed:
33 • Makefile
44 (not part of regular mksh releases anyway)
@@ -6,8 +6,6 @@ following files removed:
66 (not needed, we use our own for Android)
77 • mksh.1
88 (manpage; also available from the web)
9-• setmode.c
10- (not needed, we don’t use the mknod builtin)
119 • strlcpy.c
1210 (not needed, bionic provides this)
1311
@@ -17,6 +15,4 @@ online at https://www.mirbsd.org/man1/mksh (HTML).
1715
1816 The following changes are done to code in this subdirectory
1917 at the moment:
20-• check.t main.sh: remove the 'stop' alias to 'kill -STOP'
21- since Android has a built in stop command that the alias
22- overrides, causing problems with testing tools
\ No newline at end of file
18+• None
--- a/src/Build.sh
+++ b/src/Build.sh
@@ -1,7 +1,8 @@
11 #!/bin/sh
2-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.459 2010/08/24 15:46:06 tg Exp $'
2+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.551 2012/04/16 17:49:40 tg Exp $'
33 #-
4-# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4+# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5+# 2011, 2012
56 # Thorsten Glaser <tg@mirbsd.org>
67 #
78 # Provided that these terms and disclaimer and all copyright notices
@@ -22,18 +23,22 @@ srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.459 2010/08/24 15:46:06 tg Exp $'
2223 # People analysing the output must whitelist conftest.c for any kind
2324 # of compiler warning checks (mirtoconf is by design not quiet).
2425 #
25-# Environment used: CC CFLAGS CPPFLAGS LDFLAGS LIBS NOWARN NROFF
26-# TARGET_OS TARGET_OSREV
27-# Feature selectors: USE_PRINTF_BUILTIN
28-# CPPFLAGS recognised: MKSH_ASSUME_UTF8 MKSH_BINSHREDUCED MKSH_CLS_STRING
29-# MKSH_CONSERVATIVE_FDS MKSH_MIDNIGHTBSD01ASH_COMPAT
30-# MKSH_NOPWNAM MKSH_NO_LIMITS MKSH_SMALL MKSH_S_NOVI
31-# MKSH_UNEMPLOYED MKSH_DEFAULT_EXECSHELL MKSHRC_PATH
32-# MKSH_DEFAULT_TMPDIR MKSH_CLRTOEOL_STRING MKSH_A4PB
26+# Used environment documentation is at the end of this file.
3327
3428 LC_ALL=C
3529 export LC_ALL
3630
31+if test -n "${ZSH_VERSION+x}" && (emulate sh) >/dev/null 2>&1; then
32+ emulate sh
33+ NULLCMD=:
34+fi
35+
36+if test -d /usr/xpg4/bin/. >/dev/null 2>&1; then
37+ # Solaris: some of the tools have weird behaviour, use portable ones
38+ PATH=/usr/xpg4/bin:$PATH
39+ export PATH
40+fi
41+
3742 v() {
3843 $e "$*"
3944 eval "$@"
@@ -60,17 +65,6 @@ rmf() {
6065 done
6166 }
6267
63-if test -d /usr/xpg4/bin/. >/dev/null 2>&1; then
64- # Solaris: some of the tools have weird behaviour, use portable ones
65- PATH=/usr/xpg4/bin:$PATH
66- export PATH
67-fi
68-
69-if test -n "${ZSH_VERSION+x}" && (emulate sh) >/dev/null 2>&1; then
70- emulate sh
71- NULLCMD=:
72-fi
73-
7468 allu=QWERTYUIOPASDFGHJKLZXCVBNM
7569 alll=qwertyuiopasdfghjklzxcvbnm
7670 alln=0123456789
@@ -154,14 +148,14 @@ ac_testinit() {
154148 }
155149
156150 # pipe .c | ac_test[n] [!] label [!] checkif[!]0 [setlabelifcheckis[!]0] useroutput
157-ac_testn() {
151+ac_testnnd() {
158152 if test x"$1" = x"!"; then
159153 fr=1
160154 shift
161155 else
162156 fr=0
163157 fi
164- ac_testinit "$@" || return
158+ ac_testinit "$@" || return 1
165159 cat >conftest.c
166160 vv ']' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN conftest.c $LIBS $ccpr"
167161 test $tcfn = no && test -f a.out && tcfn=a.out
@@ -180,6 +174,10 @@ ac_testn() {
180174 test $ct = sunpro && vscan='-e ignored -e turned.off'
181175 fi
182176 test -n "$vscan" && grep $vscan vv.out >/dev/null 2>&1 && fv=$fr
177+ return 0
178+}
179+ac_testn() {
180+ ac_testnnd "$@" || return
183181 rmf conftest.c conftest.o ${tcfn}* vv.out
184182 ac_testdone
185183 }
@@ -204,11 +202,15 @@ EOF
204202 test x"$fv" = x"1"
205203 }
206204
205+add_cppflags() {
206+ CPPFLAGS="$CPPFLAGS $*"
207+}
208+
207209 ac_cppflags() {
208210 test x"$1" = x"" || fu=$1
209211 fv=$2
210212 test x"$2" = x"" && eval fv=\$HAVE_$fu
211- CPPFLAGS="$CPPFLAGS -DHAVE_$fu=$fv"
213+ add_cppflags -DHAVE_$fu=$fv
212214 }
213215
214216 ac_test() {
@@ -216,7 +218,7 @@ ac_test() {
216218 ac_cppflags
217219 }
218220
219-# ac_flags [-] add varname flags [text]
221+# ac_flags [-] add varname cflags [text] [ldflags]
220222 ac_flags() {
221223 if test x"$1" = x"-"; then
222224 shift
@@ -228,9 +230,14 @@ ac_flags() {
228230 vn=$2
229231 f=$3
230232 ft=$4
233+ fl=$5
231234 test x"$ft" = x"" && ft="if $f can be used"
232235 save_CFLAGS=$CFLAGS
233236 CFLAGS="$CFLAGS $f"
237+ if test -n "$fl"; then
238+ save_LDFLAGS=$LDFLAGS
239+ LDFLAGS="$LDFLAGS $fl"
240+ fi
234241 if test 1 = $hf; then
235242 ac_testn can_$vn '' "$ft"
236243 else
@@ -240,6 +247,9 @@ ac_flags() {
240247 EOF
241248 fi
242249 eval fv=\$HAVE_CAN_`upper $vn`
250+ if test -n "$fl"; then
251+ test 11 = $fa$fv || LDFLAGS=$save_LDFLAGS
252+ fi
243253 test 11 = $fa$fv || CFLAGS=$save_CFLAGS
244254 }
245255
@@ -253,6 +263,7 @@ ac_header() {
253263 fi
254264 hf=$1; shift
255265 hv=`echo "$hf" | tr -d '\012\015' | tr -c $alll$allu$alln $alls`
266+ echo "/* NeXTstep bug workaround */" >x
256267 for i
257268 do
258269 echo "#include <$i>" >>x
@@ -265,6 +276,12 @@ ac_header() {
265276 }
266277
267278 addsrcs() {
279+ addsrcs_s=0
280+ if test x"$1" = x"-s"; then
281+ # optstatic
282+ addsrcs_s=1
283+ shift
284+ fi
268285 if test x"$1" = x"!"; then
269286 fr=0
270287 shift
@@ -272,6 +289,13 @@ addsrcs() {
272289 fr=1
273290 fi
274291 eval i=\$$1
292+ if test $addsrcs_s = 1; then
293+ if test -f "$2" || test -f "$srcdir/$2"; then
294+ # always add $2, since it exists
295+ fr=1
296+ i=1
297+ fi
298+ fi
275299 test $fr = "$i" && case " $SRCS " in
276300 *\ $2\ *) ;;
277301 *) SRCS="$SRCS $2" ;;
@@ -283,12 +307,13 @@ if test -d mksh || test -d mksh.exe; then
283307 echo "$me: Error: ./mksh is a directory!" >&2
284308 exit 1
285309 fi
286-rmf a.exe* a.out* conftest.c *core lft mksh* no *.bc *.ll *.o \
310+rmf a.exe* a.out* conftest.c *core core.* lft mksh* no *.bc *.ll *.o \
287311 Rebuild.sh signames.inc test.sh x vv.out
288312
289-curdir=`pwd` srcdir=`dirname "$0"` check_categories=
290-test -n "$dirname" || dirname=.
313+curdir=`pwd` srcdir=`dirname "$0" 2>/dev/null` check_categories=
314+test -n "$srcdir" || srcdir=. # in case dirname does not exist
291315 dstversion=`sed -n '/define MKSH_VERSION/s/^.*"\(.*\)".*$/\1/p' $srcdir/sh.h`
316+add_cppflags -DMKSH_BUILDSH
292317
293318 e=echo
294319 r=0
@@ -301,7 +326,7 @@ last=
301326 for i
302327 do
303328 case $last:$i in
304- c:combine|c:dragonegg|c:llvm)
329+ c:combine|c:dragonegg|c:llvm|c:lto)
305330 cm=$i
306331 last=
307332 ;;
@@ -316,28 +341,14 @@ do
316341 :-c)
317342 last=c
318343 ;;
319- :-combine)
320- cm=combine
321- echo "$me: Warning: '$i' is deprecated, use '-c combine' instead!" >&2
322- ;;
323344 :-g)
324345 # checker, debug, valgrind build
325- CPPFLAGS="$CPPFLAGS -DDEBUG"
346+ add_cppflags -DDEBUG
326347 CFLAGS="$CFLAGS -g3 -fno-builtin"
327348 ;;
328349 :-j)
329350 pm=1
330351 ;;
331- :-llvm)
332- cm=llvm
333- optflags=-std-compile-opts
334- echo "$me: Warning: '$i' is deprecated, use '-c llvm -O' instead!" >&2
335- ;;
336- :-llvm=*)
337- cm=llvm
338- optflags=`echo "x$i" | sed 's/^x-llvm=//'`
339- echo "$me: Warning: '$i' is deprecated, use '-c llvm -o $llvm' instead!" >&2
340- ;;
341352 :-M)
342353 cm=makefile
343354 ;;
@@ -381,29 +392,105 @@ if test x"$srcdir" = x"."; then
381392 else
382393 CPPFLAGS="-I. -I'$srcdir' $CPPFLAGS"
383394 fi
395+test -n "$LDSTATIC" && if test -n "$LDFLAGS"; then
396+ LDFLAGS="$LDFLAGS $LDSTATIC"
397+else
398+ LDFLAGS=$LDSTATIC
399+fi
384400
385401 test x"$TARGET_OS" = x"" && TARGET_OS=`uname -s 2>/dev/null || uname`
402+if test x"$TARGET_OS" = x""; then
403+ echo "$me: Set TARGET_OS, your uname is broken!" >&2
404+ exit 1
405+fi
386406 oswarn=
387407 ccpc=-Wc,
388408 ccpl=-Wl,
389409 tsts=
390410 ccpr='|| for _f in ${tcfn}*; do test x"${_f}" = x"mksh.1" || rm -f "${_f}"; done'
391411
412+# Evil hack
413+if test x"$TARGET_OS" = x"Android"; then
414+ check_categories="$check_categories android"
415+ TARGET_OS=Linux
416+fi
417+
418+# Evil OS
419+if test x"$TARGET_OS" = x"Minix"; then
420+ echo >&2 "
421+WARNING: additional checks before running Build.sh required!
422+You can avoid these by calling Build.sh correctly, see below.
423+"
424+ cat >conftest.c <<'EOF'
425+#include <sys/types.h>
426+const char *
427+#ifdef _NETBSD_SOURCE
428+ct="Ninix3"
429+#else
430+ct="Minix3"
431+#endif
432+;
433+EOF
434+ ct=unknown
435+ vv ']' "${CC-cc} -E $CFLAGS $CPPFLAGS $NOWARN conftest.c | grep ct= | tr -d \\\\015 >x"
436+ sed 's/^/[ /' x
437+ eval `cat x`
438+ rmf x vv.out
439+ case $ct in
440+ Minix3|Ninix3)
441+ echo >&2 "
442+Warning: you set TARGET_OS to $TARGET_OS but that is ambiguous.
443+Please set it to either Minix3 or Ninix3, whereas the latter is
444+all versions of Minix with even partial NetBSD(R) userland. The
445+value determined from your compiler for the current compilation
446+(which may be wrong) is: $ct
447+"
448+ TARGET_OS=$ct
449+ ;;
450+ *)
451+ echo >&2 "
452+Warning: you set TARGET_OS to $TARGET_OS but that is ambiguous.
453+Please set it to either Minix3 or Ninix3, whereas the latter is
454+all versions of Minix with even partial NetBSD(R) userland. The
455+proper value couldn't be determined, continue at your own risk.
456+"
457+ ;;
458+ esac
459+fi
460+
392461 # Configuration depending on OS revision, on OSes that need them
393462 case $TARGET_OS in
394-QNX)
463+NEXTSTEP)
464+ test x"$TARGET_OSREV" = x"" && TARGET_OSREV=`hostinfo 2>&1 | grep 'NeXT Mach [0-9.]*:' | sed 's/^.*NeXT Mach \([0-9.]*\):.*$/\1/'`
465+ ;;
466+QNX|SCO_SV)
395467 test x"$TARGET_OSREV" = x"" && TARGET_OSREV=`uname -r`
396468 ;;
397469 esac
398470
399471 # Configuration depending on OS name
400472 case $TARGET_OS in
473+386BSD)
474+ : ${HAVE_CAN_OTWO=0}
475+ add_cppflags -DMKSH_NO_SIGSETJMP
476+ add_cppflags -DMKSH_TYPEDEF_SIG_ATOMIC_T=int
477+ ;;
401478 AIX)
402- CPPFLAGS="$CPPFLAGS -D_ALL_SOURCE"
479+ add_cppflags -D_ALL_SOURCE
403480 : ${HAVE_SETLOCALE_CTYPE=0}
404481 ;;
405482 BeOS)
406- oswarn=' and will currently not work'
483+ case $KSH_VERSION in
484+ *MIRBSD\ KSH*)
485+ oswarn="; it has minor issues"
486+ ;;
487+ *)
488+ oswarn="; you must recompile mksh with"
489+ oswarn="$oswarn${nl}itself in a second stage"
490+ ;;
491+ esac
492+ # BeOS has no real tty either
493+ add_cppflags -DMKSH_UNEMPLOYED
407494 ;;
408495 BSD/OS)
409496 : ${HAVE_SETLOCALE_CTYPE=0}
@@ -417,22 +504,34 @@ DragonFly)
417504 ;;
418505 FreeBSD)
419506 ;;
507+FreeMiNT)
508+ oswarn="; it has minor issues"
509+ add_cppflags -D_GNU_SOURCE
510+ : ${HAVE_SETLOCALE_CTYPE=0}
511+ ;;
420512 GNU)
513+ case $CC in
514+ *tendracc*) ;;
515+ *) add_cppflags -D_GNU_SOURCE ;;
516+ esac
421517 # define NO_PATH_MAX to use Hurd-only functions
422- CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -DNO_PATH_MAX"
518+ add_cppflags -DNO_PATH_MAX
423519 ;;
424520 GNU/kFreeBSD)
425- CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
521+ case $CC in
522+ *tendracc*) ;;
523+ *) add_cppflags -D_GNU_SOURCE ;;
524+ esac
426525 ;;
427526 Haiku)
428- CPPFLAGS="$CPPFLAGS -DMKSH_ASSUME_UTF8"
527+ add_cppflags -DMKSH_ASSUME_UTF8; HAVE_ISSET_MKSH_ASSUME_UTF8=1
429528 ;;
430529 HP-UX)
431530 ;;
432531 Interix)
433532 ccpc='-X '
434533 ccpl='-Y '
435- CPPFLAGS="$CPPFLAGS -D_ALL_SOURCE"
534+ add_cppflags -D_ALL_SOURCE
436535 : ${LIBS='-lcrypt'}
437536 : ${HAVE_SETLOCALE_CTYPE=0}
438537 ;;
@@ -440,35 +539,78 @@ IRIX*)
440539 : ${HAVE_SETLOCALE_CTYPE=0}
441540 ;;
442541 Linux)
443- CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
542+ case $CC in
543+ *tendracc*) ;;
544+ *) add_cppflags -D_GNU_SOURCE ;;
545+ esac
546+ add_cppflags -DSETUID_CAN_FAIL_WITH_EAGAIN
444547 : ${HAVE_REVOKE=0}
445548 ;;
549+LynxOS)
550+ oswarn="; it has minor issues"
551+ ;;
446552 MidnightBSD)
447553 ;;
448-Minix)
449- CPPFLAGS="$CPPFLAGS -DMKSH_UNEMPLOYED -DMKSH_CONSERVATIVE_FDS"
450- CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX"
554+Minix3)
555+ add_cppflags -DMKSH_UNEMPLOYED
556+ add_cppflags -DMKSH_CONSERVATIVE_FDS
557+ add_cppflags -DMKSH_NO_LIMITS
558+ add_cppflags -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX
451559 oldish_ed=no-stderr-ed # /usr/bin/ed(!) is broken
452560 : ${HAVE_SETLOCALE_CTYPE=0}
453561 ;;
454562 MirBSD)
455563 ;;
564+MSYS_*)
565+ add_cppflags -DMKSH_ASSUME_UTF8=0; HAVE_ISSET_MKSH_ASSUME_UTF8=1
566+ # almost same as CYGWIN* (from RT|Chatzilla)
567+ : ${HAVE_SETLOCALE_CTYPE=0}
568+ # broken on this OE (from ir0nh34d)
569+ : ${HAVE_STDINT_H=0}
570+ ;;
456571 NetBSD)
457572 ;;
573+NEXTSTEP)
574+ add_cppflags -D_NEXT_SOURCE
575+ add_cppflags -D_POSIX_SOURCE
576+ : ${AWK=gawk} ${CC=cc -posix}
577+ add_cppflags -DMKSH_NO_SIGSETJMP
578+ # NeXTstep cannot get a controlling tty
579+ add_cppflags -DMKSH_UNEMPLOYED
580+ case $TARGET_OSREV in
581+ 4.2*)
582+ # OpenStep 4.2 is broken by default
583+ oswarn="; it needs libposix.a"
584+ ;;
585+ esac
586+ ;;
587+Ninix3)
588+ # similar to Minix3
589+ add_cppflags -DMKSH_UNEMPLOYED
590+ add_cppflags -DMKSH_CONSERVATIVE_FDS
591+ add_cppflags -DMKSH_NO_LIMITS
592+ # but no idea what else could be needed
593+ oswarn="; it has unknown issues"
594+ ;;
458595 OpenBSD)
459596 : ${HAVE_SETLOCALE_CTYPE=0}
460597 ;;
461598 OSF1)
462599 HAVE_SIG_T=0 # incompatible
463- CPPFLAGS="$CPPFLAGS -D_OSF_SOURCE -D_POSIX_C_SOURCE=200112L"
464- CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED"
600+ add_cppflags -D_OSF_SOURCE
601+ add_cppflags -D_POSIX_C_SOURCE=200112L
602+ add_cppflags -D_XOPEN_SOURCE=600
603+ add_cppflags -D_XOPEN_SOURCE_EXTENDED
465604 : ${HAVE_SETLOCALE_CTYPE=0}
466605 ;;
467606 Plan9)
468- CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_LIMITS_EXTENSION"
469- CPPFLAGS="$CPPFLAGS -D_BSD_EXTENSION -D_SUSV2_SOURCE"
607+ add_cppflags -D_POSIX_SOURCE
608+ add_cppflags -D_LIMITS_EXTENSION
609+ add_cppflags -D_BSD_EXTENSION
610+ add_cppflags -D_SUSV2_SOURCE
611+ add_cppflags -DMKSH_ASSUME_UTF8; HAVE_ISSET_MKSH_ASSUME_UTF8=1
470612 oswarn=' and will currently not work'
471- CPPFLAGS="$CPPFLAGS -DMKSH_ASSUME_UTF8 -DMKSH_UNEMPLOYED"
613+ add_cppflags -DMKSH_UNEMPLOYED
472614 ;;
473615 PW32*)
474616 HAVE_SIG_T=0 # incompatible
@@ -476,7 +618,7 @@ PW32*)
476618 : ${HAVE_SETLOCALE_CTYPE=0}
477619 ;;
478620 QNX)
479- CPPFLAGS="$CPPFLAGS -D__NO_EXT_QNX"
621+ add_cppflags -D__NO_EXT_QNX
480622 case $TARGET_OSREV in
481623 [012345].*|6.[0123].*|6.4.[01])
482624 oldish_ed=no-stderr-ed # oldish /bin/ed is broken
@@ -484,18 +626,42 @@ QNX)
484626 esac
485627 : ${HAVE_SETLOCALE_CTYPE=0}
486628 ;;
629+SCO_SV)
630+ case $TARGET_OSREV in
631+ 3.2*)
632+ # SCO OpenServer 5
633+ add_cppflags -DMKSH_UNEMPLOYED
634+ ;;
635+ 5*)
636+ # SCO OpenServer 6
637+ ;;
638+ *)
639+ oswarn='; this is an unknown version of'
640+ oswarn="$oswarn$nl$TARGET_OS ${TARGET_OSREV}, please tell me what to do"
641+ ;;
642+ esac
643+ : ${HAVE_SYS_SIGLIST=0} ${HAVE__SYS_SIGLIST=0}
644+ ;;
645+skyos)
646+ oswarn="; it has minor issues"
647+ ;;
487648 SunOS)
488- CPPFLAGS="$CPPFLAGS -D_BSD_SOURCE -D__EXTENSIONS__"
649+ add_cppflags -D_BSD_SOURCE
650+ add_cppflags -D__EXTENSIONS__
489651 ;;
490652 syllable)
491- CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
653+ add_cppflags -D_GNU_SOURCE
492654 oswarn=' and will currently not work'
493655 ;;
494656 ULTRIX)
495657 : ${CC=cc -YPOSIX}
496- CPPFLAGS="$CPPFLAGS -Dssize_t=int"
658+ add_cppflags -DMKSH_TYPEDEF_SSIZE_T=int
497659 : ${HAVE_SETLOCALE_CTYPE=0}
498660 ;;
661+UnixWare|UNIX_SV)
662+ # SCO UnixWare
663+ : ${HAVE_SYS_SIGLIST=0} ${HAVE__SYS_SIGLIST=0}
664+ ;;
499665 UWIN*)
500666 ccpc='-Yc,'
501667 ccpl='-Yl,'
@@ -506,16 +672,23 @@ UWIN*)
506672 ;;
507673 *)
508674 oswarn='; it may or may not work'
675+ test x"$TARGET_OSREV" = x"" && TARGET_OSREV=`uname -r`
509676 ;;
510677 esac
511678
512-: ${CC=cc} ${NROFF=nroff}
679+: ${HAVE_MKNOD=0}
680+
681+: ${AWK=awk} ${CC=cc} ${NROFF=nroff}
513682 test 0 = $r && echo | $NROFF -v 2>&1 | grep GNU >/dev/null 2>&1 && \
514683 NROFF="$NROFF -c"
515684
516685 # this aids me in tracing FTBFSen without access to the buildd
517686 $e "Hi from$ao $bi$srcversion$ao on:"
518687 case $TARGET_OS in
688+AIX)
689+ vv '|' "oslevel >&2"
690+ vv '|' "uname -a >&2"
691+ ;;
519692 Darwin)
520693 vv '|' "hwprefs machine_type os_type os_class >&2"
521694 vv '|' "uname -a >&2"
@@ -528,6 +701,10 @@ OSF1)
528701 vv '|' "uname -a >&2"
529702 vv '|' "/usr/sbin/sizer -v >&2"
530703 ;;
704+SCO_SV|UnixWare|UNIX_SV)
705+ vv '|' "uname -a >&2"
706+ vv '|' "uname -X >&2"
707+ ;;
531708 *)
532709 vv '|' "uname -a >&2"
533710 ;;
@@ -538,7 +715,7 @@ operating system '$TARGET_OS'$oswarn. If you can provide
538715 a shell account to the developer, this may improve; please
539716 drop us a success or failure notice or even send in diffs.
540717 "
541-$e "$bi$me: Building the MirBSD Korn Shell$ao $ui$dstversion$ao"
718+$e "$bi$me: Building the MirBSD Korn Shell$ao $ui$dstversion$ao on $TARGET_OS ${TARGET_OSREV}..."
542719
543720 #
544721 # Begin of mirtoconf checks
@@ -556,62 +733,66 @@ $e $bi$me: Scanning for functions... please ignore any errors.$ao
556733 CPP="$CC -E"
557734 $e ... which compiler seems to be used
558735 cat >conftest.c <<'EOF'
736+const char *
559737 #if defined(__ICC) || defined(__INTEL_COMPILER)
560-ct=icc
738+ct="icc"
561739 #elif defined(__xlC__) || defined(__IBMC__)
562-ct=xlc
740+ct="xlc"
563741 #elif defined(__SUNPRO_C)
564-ct=sunpro
742+ct="sunpro"
565743 #elif defined(__ACK__)
566-ct=ack
744+ct="ack"
567745 #elif defined(__BORLANDC__)
568-ct=bcc
746+ct="bcc"
569747 #elif defined(__WATCOMC__)
570-ct=watcom
748+ct="watcom"
571749 #elif defined(__MWERKS__)
572-ct=metrowerks
750+ct="metrowerks"
573751 #elif defined(__HP_cc)
574-ct=hpcc
752+ct="hpcc"
575753 #elif defined(__DECC) || (defined(__osf__) && !defined(__GNUC__))
576-ct=dec
754+ct="dec"
577755 #elif defined(__PGI)
578-ct=pgi
756+ct="pgi"
579757 #elif defined(__DMC__)
580-ct=dmc
758+ct="dmc"
581759 #elif defined(_MSC_VER)
582-ct=msc
760+ct="msc"
583761 #elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
584-ct=adsp
762+ct="adsp"
585763 #elif defined(__IAR_SYSTEMS_ICC__)
586-ct=iar
764+ct="iar"
587765 #elif defined(SDCC)
588-ct=sdcc
766+ct="sdcc"
589767 #elif defined(__PCC__)
590-ct=pcc
768+ct="pcc"
591769 #elif defined(__TenDRA__)
592-ct=tendra
770+ct="tendra"
593771 #elif defined(__TINYC__)
594-ct=tcc
772+ct="tcc"
595773 #elif defined(__llvm__) && defined(__clang__)
596-ct=clang
774+ct="clang"
597775 #elif defined(__NWCC__)
598-ct=nwcc
776+ct="nwcc"
599777 #elif defined(__GNUC__)
600-ct=gcc
778+ct="gcc"
601779 #elif defined(_COMPILER_VERSION)
602-ct=mipspro
780+ct="mipspro"
603781 #elif defined(__sgi)
604-ct=mipspro
782+ct="mipspro"
605783 #elif defined(__hpux) || defined(__hpua)
606-ct=hpcc
784+ct="hpcc"
607785 #elif defined(__ultrix)
608-ct=ucode
786+ct="ucode"
787+#elif defined(__USLC__)
788+ct="uslc"
609789 #else
610-ct=unknown
790+ct="unknown"
611791 #endif
792+;
612793 EOF
613-ct=unknown
614-vv ']' "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c | grep ct= | tr -d \\\\015 >x"
794+ct=untested
795+vv ']' "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c | sed -n '/^ct *= */s//ct=/p' | tr -d \\\\015 >x"
615796 sed 's/^/[ /' x
616797 eval `cat x`
617798 rmf x vv.out
@@ -635,8 +816,9 @@ bcc)
635816 clang)
636817 # does not work with current "ccc" compiler driver
637818 vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN $LIBS -version"
638- # this works, for now
819+ # one of these two works, for now
639820 vv '|' "${CLANG-clang} -version"
821+ vv '|' "${CLANG-clang} --version"
640822 # ensure compiler and linker are in sync unless overridden
641823 case $CCC_CC:$CCC_LD in
642824 :*) ;;
@@ -729,17 +911,32 @@ ucode)
729911 vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN $LIBS -V"
730912 vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN -Wl,-V conftest.c $LIBS"
731913 ;;
914+uslc)
915+ case $TARGET_OS:$TARGET_OSREV in
916+ SCO_SV:3.2*)
917+ # SCO OpenServer 5
918+ CFLAGS="$CFLAGS -g"
919+ : ${HAVE_CAN_OTWO=0} ${HAVE_CAN_OPTIMISE=0}
920+ ;;
921+ esac
922+ vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN -V conftest.c $LIBS"
923+ ;;
732924 watcom)
733925 echo >&2 'Warning: Watcom C Compiler detected. This compiler has not yet
734926 been tested for compatibility with mksh. Continue at your
735927 own risk, please report success/failure to the developers.'
736928 ;;
737929 xlc)
930+ vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN $LIBS -qversion"
738931 vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN $LIBS -qversion=verbose"
739932 vv '|' "ld -V"
740933 ;;
741934 *)
935+ test x"$ct" = x"untested" && $e "!!! detecting preprocessor failed"
742936 ct=unknown
937+ vv "$CC --version"
938+ vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN -v conftest.c $LIBS"
939+ vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN -V conftest.c $LIBS"
743940 ;;
744941 esac
745942 case $cm in
@@ -786,6 +983,7 @@ if ac_ifcpp 'ifdef __TINYC__' couldbe_tcc '!' compiler_known 0 \
786983 'if this could be tcc'; then
787984 ct=tcc
788985 CPP='cpp -D__TINYC__'
986+ HAVE_COMPILER_KNOWN=1
789987 fi
790988
791989 if test $ct = sunpro; then
@@ -863,12 +1061,49 @@ i=0
8631061 if test $ct = gcc; then
8641062 # The following tests run with -Werror (gcc only) if possible
8651063 NOWARN=$DOWARN; phase=u
1064+ ac_flags 0 wnooverflow -Wno-overflow
8661065 ac_flags 1 fnostrictaliasing -fno-strict-aliasing
8671066 ac_flags 1 fstackprotectorall -fstack-protector-all
868- ac_flags 1 fwrapv -fwrapv
869- test $cm = combine && ac_flags 0 combine \
870- '-fwhole-program --combine' \
871- 'if gcc supports -fwhole-program --combine'
1067+ test $cm = dragonegg && case " $CC $CFLAGS $LDFLAGS " in
1068+ *\ -fplugin=*dragonegg*) ;;
1069+ *) ac_flags 1 fplugin_dragonegg -fplugin=dragonegg ;;
1070+ esac
1071+ if test $cm = lto; then
1072+ fv=0
1073+ checks='1 2 3 4 5 6 7 8'
1074+ elif test $cm = combine; then
1075+ fv=0
1076+ checks='7 8'
1077+ else
1078+ fv=1
1079+ fi
1080+ test $fv = 1 || for what in $checks; do
1081+ test $fv = 1 && break
1082+ case $what in
1083+ 1) t_cflags='-flto=jobserver'
1084+ t_ldflags='-fuse-linker-plugin'
1085+ t_use=1 t_name=fltojs_lp ;;
1086+ 2) t_cflags='-flto=jobserver' t_ldflags=''
1087+ t_use=1 t_name=fltojs_nn ;;
1088+ 3) t_cflags='-flto=jobserver'
1089+ t_ldflags='-fno-use-linker-plugin -fwhole-program'
1090+ t_use=1 t_name=fltojs_np ;;
1091+ 4) t_cflags='-flto'
1092+ t_ldflags='-fuse-linker-plugin'
1093+ t_use=1 t_name=fltons_lp ;;
1094+ 5) t_cflags='-flto' t_ldflags=''
1095+ t_use=1 t_name=fltons_nn ;;
1096+ 6) t_cflags='-flto'
1097+ t_ldflags='-fno-use-linker-plugin -fwhole-program'
1098+ t_use=1 t_name=fltons_np ;;
1099+ 7) t_cflags='-fwhole-program --combine' t_ldflags=''
1100+ t_use=0 t_name=combine cm=combine ;;
1101+ 8) fv=1 cm=normal ;;
1102+ esac
1103+ test $fv = 1 && break
1104+ ac_flags $t_use $t_name "$t_cflags" \
1105+ "if gcc supports $t_cflags $t_ldflags" "$t_ldflags"
1106+ done
8721107 i=1
8731108 elif test $ct = icc; then
8741109 ac_flags 1 fnobuiltinsetmode -fno-builtin-setmode
@@ -878,13 +1113,12 @@ elif test $ct = icc; then
8781113 elif test $ct = sunpro; then
8791114 phase=u
8801115 ac_flags 1 v -v
881- ac_flags 1 xc99 -xc99 'for support of ISO C99'
8821116 ac_flags 1 ipo -xipo 'for cross-module optimisation'
8831117 phase=x
8841118 elif test $ct = hpcc; then
8851119 phase=u
886- ac_flags 1 agcc -Agcc 'for support of GCC extensions'
887- ac_flags 1 ac99 -AC99 'for support of ISO C99'
1120+ # probably not needed
1121+ #ac_flags 1 agcc -Agcc 'for support of GCC extensions'
8881122 phase=x
8891123 elif test $ct = dec; then
8901124 ac_flags 0 verb -verbose
@@ -895,7 +1129,6 @@ elif test $ct = dmc; then
8951129 elif test $ct = bcc; then
8961130 ac_flags 1 strpool "${ccpc}-d" 'if string pooling can be enabled'
8971131 elif test $ct = mipspro; then
898- ac_flags 1 xc99 -c99 'for support of ISO C99'
8991132 ac_flags 1 fullwarn -fullwarn 'for remark output support'
9001133 elif test $ct = msc; then
9011134 ac_flags 1 strpool "${ccpc}/GF" 'if string pooling can be enabled'
@@ -907,8 +1140,6 @@ elif test $ct = msc; then
9071140 ac_flags 1 wall "${ccpc}/Wall" 'to enable all warnings'
9081141 ac_flags 1 wp64 "${ccpc}/Wp64" 'to enable 64-bit warnings'
9091142 elif test $ct = xlc; then
910- ac_flags 1 x99 -qlanglvl=extc99
911- test 1 = $HAVE_CAN_X99 || ac_flags 1 c99 -qlanglvl=stdc99
9121143 ac_flags 1 rodata "-qro -qroconst -qroptr"
9131144 ac_flags 1 rtcheck -qcheck=all
9141145 ac_flags 1 rtchkc -qextchk
@@ -919,22 +1150,20 @@ elif test $ct = tendra; then
9191150 test 1 = $HAVE_CAN_YSYSTEM && CPPFLAGS="-Ysystem $CPPFLAGS"
9201151 ac_flags 1 extansi -Xa
9211152 elif test $ct = tcc; then
922- ac_flags 1 boundschk -b
1153+ : #broken# ac_flags 1 boundschk -b
9231154 elif test $ct = clang; then
9241155 i=1
9251156 elif test $ct = nwcc; then
9261157 i=1
927- #broken# ac_flags 1 ssp -stackprotect
1158+ : #broken# ac_flags 1 ssp -stackprotect
9281159 fi
9291160 # flags common to a subset of compilers (run with -Werror on gcc)
9301161 if test 1 = $i; then
931- ac_flags 1 stdg99 -std=gnu99 'for support of ISO C99 + GCC extensions'
932- test 1 = $HAVE_CAN_STDG99 || \
933- ac_flags 1 stdc99 -std=c99 'for support of ISO C99'
9341162 ac_flags 1 wall -Wall
1163+ ac_flags 1 fwrapv -fwrapv
9351164 fi
936-phase=x
9371165
1166+phase=x
9381167 # The following tests run with -Werror or similar (all compilers) if possible
9391168 NOWARN=$DOWARN
9401169 test $ct = pcc && phase=u
@@ -942,76 +1171,77 @@ test $ct = pcc && phase=u
9421171 #
9431172 # Compiler: check for stuff that only generates warnings
9441173 #
945-ac_test attribute_bounded '' 'for __attribute__((bounded))' <<-'EOF'
946- #if defined(__GNUC__) && (__GNUC__ < 2)
947- /* force a failure: gcc 1.42 has a false positive here */
1174+ac_test attribute_bounded '' 'for __attribute__((__bounded__))' <<-'EOF'
1175+ #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1176+ /* force a failure: TenDRA and gcc 1.42 have false positive here */
9481177 int main(void) { return (thiswillneverbedefinedIhope()); }
9491178 #else
9501179 #include <string.h>
9511180 #undef __attribute__
9521181 int xcopy(const void *, void *, size_t)
953- __attribute__((bounded (buffer, 1, 3)))
954- __attribute__((bounded (buffer, 2, 3)));
1182+ __attribute__((__bounded__ (__buffer__, 1, 3)))
1183+ __attribute__((__bounded__ (__buffer__, 2, 3)));
9551184 int main(int ac, char *av[]) { return (xcopy(av[0], av[--ac], 1)); }
9561185 int xcopy(const void *s, void *d, size_t n) {
9571186 memmove(d, s, n); return ((int)n);
9581187 }
9591188 #endif
9601189 EOF
961-ac_test attribute_format '' 'for __attribute__((format))' <<-'EOF'
962- #if defined(__GNUC__) && (__GNUC__ < 2)
963- /* force a failure: gcc 1.42 has a false positive here */
1190+ac_test attribute_format '' 'for __attribute__((__format__))' <<-'EOF'
1191+ #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1192+ /* force a failure: TenDRA and gcc 1.42 have false positive here */
9641193 int main(void) { return (thiswillneverbedefinedIhope()); }
9651194 #else
1195+ #define fprintf printfoo
9661196 #include <stdio.h>
9671197 #undef __attribute__
968- #undef printf
969- extern int printf(const char *format, ...)
970- __attribute__((format (printf, 1, 2)));
971- int main(int ac, char **av) { return (printf("%s%d", *av, ac)); }
1198+ #undef fprintf
1199+ extern int fprintf(FILE *, const char *format, ...)
1200+ __attribute__((__format__ (__printf__, 2, 3)));
1201+ int main(int ac, char **av) { return (fprintf(stderr, "%s%d", *av, ac)); }
9721202 #endif
9731203 EOF
974-ac_test attribute_nonnull '' 'for __attribute__((nonnull))' <<-'EOF'
975- #if defined(__GNUC__) && (__GNUC__ < 2)
976- /* force a failure: gcc 1.42 has a false positive here */
1204+ac_test attribute_nonnull '' 'for __attribute__((__nonnull__))' <<-'EOF'
1205+ #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1206+ /* force a failure: TenDRA and gcc 1.42 have false positive here */
9771207 int main(void) { return (thiswillneverbedefinedIhope()); }
9781208 #else
979- int foo(char *s1, char *s2) __attribute__((nonnull));
980- int bar(char *s1, char *s2) __attribute__((nonnull (1, 2)));
981- int baz(char *s) __attribute__((nonnull (1)));
1209+ int foo(char *s1, char *s2) __attribute__((__nonnull__));
1210+ int bar(char *s1, char *s2) __attribute__((__nonnull__ (1, 2)));
1211+ int baz(char *s) __attribute__((__nonnull__ (1)));
9821212 int foo(char *s1, char *s2) { return (bar(s2, s1)); }
9831213 int bar(char *s1, char *s2) { return (baz(s1) - baz(s2)); }
9841214 int baz(char *s) { return (*s); }
9851215 int main(int ac, char **av) { return (ac == foo(av[0], av[ac-1])); }
9861216 #endif
9871217 EOF
988-ac_test attribute_noreturn '' 'for __attribute__((noreturn))' <<-'EOF'
989- #if defined(__GNUC__) && (__GNUC__ < 2)
990- /* force a failure: gcc 1.42 has a false positive here */
1218+ac_test attribute_noreturn '' 'for __attribute__((__noreturn__))' <<-'EOF'
1219+ #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1220+ /* force a failure: TenDRA and gcc 1.42 have false positive here */
9911221 int main(void) { return (thiswillneverbedefinedIhope()); }
9921222 #else
9931223 #include <stdlib.h>
9941224 #undef __attribute__
995- void fnord(void) __attribute__((noreturn));
1225+ void fnord(void) __attribute__((__noreturn__));
9961226 int main(void) { fnord(); }
9971227 void fnord(void) { exit(0); }
9981228 #endif
9991229 EOF
1000-ac_test attribute_unused '' 'for __attribute__((unused))' <<-'EOF'
1001- #if defined(__GNUC__) && (__GNUC__ < 2)
1002- /* force a failure: gcc 1.42 has a false positive here */
1230+ac_test attribute_unused '' 'for __attribute__((__unused__))' <<-'EOF'
1231+ #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1232+ /* force a failure: TenDRA and gcc 1.42 have false positive here */
10031233 int main(void) { return (thiswillneverbedefinedIhope()); }
10041234 #else
1005- int main(int ac __attribute__((unused)), char **av
1006- __attribute__((unused))) { return (0); }
1235+ int main(int ac __attribute__((__unused__)), char **av
1236+ __attribute__((__unused__))) { return (0); }
10071237 #endif
10081238 EOF
1009-ac_test attribute_used '' 'for __attribute__((used))' <<-'EOF'
1010- #if defined(__GNUC__) && (__GNUC__ < 2)
1011- /* force a failure: gcc 1.42 has a false positive here */
1239+ac_test attribute_used '' 'for __attribute__((__used__))' <<-'EOF'
1240+ #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1241+ /* force a failure: TenDRA and gcc 1.42 have false positive here */
10121242 int main(void) { return (thiswillneverbedefinedIhope()); }
10131243 #else
1014- static const char fnord[] __attribute__((used)) = "42";
1244+ static const char fnord[] __attribute__((__used__)) = "42";
10151245 int main(void) { return (0); }
10161246 #endif
10171247 EOF
@@ -1025,57 +1255,47 @@ phase=x
10251255 #
10261256 if ac_ifcpp 'ifdef MKSH_SMALL' isset_MKSH_SMALL '' \
10271257 "if a reduced-feature mksh is requested"; then
1028- #XXX this sucks; fix it for *all* compilers
1029- case $ct in
1030- clang|icc|nwcc)
1031- ac_flags 1 fnoinline -fno-inline
1032- ;;
1033- gcc)
1034- NOWARN=$DOWARN; phase=u
1035- ac_flags 1 fnoinline -fno-inline
1036- NOWARN=$save_NOWARN; phase=x
1037- ;;
1038- sunpro)
1039- ac_flags 1 fnoinline -xinline=
1040- ;;
1041- xlc)
1042- ac_flags 1 fnoinline -qnoinline
1043- ;;
1044- esac
1045-
1046- : ${HAVE_MKNOD=0}
10471258 : ${HAVE_NICE=0}
1048- : ${HAVE_REVOKE=0}
10491259 : ${HAVE_PERSISTENT_HISTORY=0}
1050- check_categories=$check_categories,smksh
1260+ check_categories="$check_categories smksh"
10511261 HAVE_ISSET_MKSH_CONSERVATIVE_FDS=1 # from sh.h
10521262 fi
10531263 ac_ifcpp 'ifdef MKSH_BINSHREDUCED' isset_MKSH_BINSHREDUCED '' \
10541264 "if a reduced-feature sh is requested" && \
1055- check_categories=$check_categories,binsh
1265+ check_categories="$check_categories binsh"
10561266 ac_ifcpp 'ifdef MKSH_UNEMPLOYED' isset_MKSH_UNEMPLOYED '' \
10571267 "if mksh will be built without job control" && \
1058- check_categories=$check_categories,arge
1268+ check_categories="$check_categories arge"
1269+ac_ifcpp 'ifdef MKSH_NOPROSPECTOFWORK' isset_MKSH_NOPROSPECTOFWORK '' \
1270+ "if mksh will be built without job signals" && \
1271+ check_categories="$check_categories arge nojsig"
10591272 ac_ifcpp 'ifdef MKSH_ASSUME_UTF8' isset_MKSH_ASSUME_UTF8 '' \
10601273 'if the default UTF-8 mode is specified' && : ${HAVE_SETLOCALE_CTYPE=0}
10611274 ac_ifcpp 'ifdef MKSH_CONSERVATIVE_FDS' isset_MKSH_CONSERVATIVE_FDS '' \
10621275 'if traditional/conservative fd use is requested' && \
1063- check_categories=$check_categories,convfds
1276+ check_categories="$check_categories convfds"
1277+#ac_ifcpp 'ifdef MKSH_DISABLE_DEPRECATED' isset_MKSH_DISABLE_DEPRECATED '' \
1278+# "if deprecated features are to be omitted" && \
1279+# check_categories="$check_categories nodeprecated"
10641280
10651281 #
10661282 # Environment: headers
10671283 #
1068-ac_header sys/param.h
1284+ac_header sys/bsdtypes.h
1285+ac_header sys/file.h sys/types.h
10691286 ac_header sys/mkdev.h sys/types.h
10701287 ac_header sys/mman.h sys/types.h
1288+ac_header sys/param.h
1289+ac_header sys/select.h sys/types.h
10711290 ac_header sys/sysmacros.h
1291+ac_header bstring.h
10721292 ac_header grp.h sys/types.h
10731293 ac_header libgen.h
10741294 ac_header libutil.h sys/types.h
10751295 ac_header paths.h
1076-ac_header stdbool.h
10771296 ac_header stdint.h stdarg.h
1078-ac_header strings.h sys/types.h
1297+# include strings.h only if compatible with string.h
1298+ac_header strings.h sys/types.h string.h
10791299 ac_header ulimit.h sys/types.h
10801300 ac_header values.h
10811301
@@ -1090,10 +1310,11 @@ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 &&
10901310 int main(void) { return (0); }' >lft.c
10911311 ac_testn can_lfs '' "for large file support" <lft.c
10921312 save_CPPFLAGS=$CPPFLAGS
1093-CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64"
1313+add_cppflags -D_FILE_OFFSET_BITS=64
10941314 ac_testn can_lfs_sus '!' can_lfs 0 "... with -D_FILE_OFFSET_BITS=64" <lft.c
10951315 if test 0 = $HAVE_CAN_LFS_SUS; then
1096- CPPFLAGS="$save_CPPFLAGS -D_LARGE_FILES=1"
1316+ CPPFLAGS=$save_CPPFLAGS
1317+ add_cppflags -D_LARGE_FILES=1
10971318 ac_testn can_lfs_aix '!' can_lfs 0 "... with -D_LARGE_FILES=1" <lft.c
10981319 test 1 = $HAVE_CAN_LFS_AIX || CPPFLAGS=$save_CPPFLAGS
10991320 fi
@@ -1136,17 +1357,17 @@ ac_testn sig_t <<-'EOF'
11361357 #include <sys/types.h>
11371358 #include <signal.h>
11381359 #include <stddef.h>
1139- int main(void) { return ((int)(ptrdiff_t)(sig_t)kill(0,0)); }
1360+ int main(void) { return ((int)(ptrdiff_t)(sig_t)(ptrdiff_t)kill(0,0)); }
11401361 EOF
11411362
11421363 ac_testn sighandler_t '!' sig_t 0 <<-'EOF'
11431364 #include <sys/types.h>
11441365 #include <signal.h>
11451366 #include <stddef.h>
1146- int main(void) { return ((int)(ptrdiff_t)(sighandler_t)kill(0,0)); }
1367+ int main(void) { return ((int)(ptrdiff_t)(sighandler_t)(ptrdiff_t)kill(0,0)); }
11471368 EOF
11481369 if test 1 = $HAVE_SIGHANDLER_T; then
1149- CPPFLAGS="$CPPFLAGS -Dsig_t=sighandler_t"
1370+ add_cppflags -Dsig_t=sighandler_t
11501371 HAVE_SIG_T=1
11511372 fi
11521373
@@ -1154,17 +1375,62 @@ ac_testn __sighandler_t '!' sig_t 0 <<-'EOF'
11541375 #include <sys/types.h>
11551376 #include <signal.h>
11561377 #include <stddef.h>
1157- int main(void) { return ((int)(ptrdiff_t)(__sighandler_t)kill(0,0)); }
1378+ int main(void) { return ((int)(ptrdiff_t)(__sighandler_t)(ptrdiff_t)kill(0,0)); }
11581379 EOF
11591380 if test 1 = $HAVE___SIGHANDLER_T; then
1160- CPPFLAGS="$CPPFLAGS -Dsig_t=__sighandler_t"
1381+ add_cppflags -Dsig_t=__sighandler_t
11611382 HAVE_SIG_T=1
11621383 fi
11631384
1164-test 1 = $HAVE_SIG_T || CPPFLAGS="$CPPFLAGS -Dsig_t=nosig_t"
1385+test 1 = $HAVE_SIG_T || add_cppflags -Dsig_t=nosig_t
11651386 ac_cppflags SIG_T
11661387
11671388 #
1389+# check whether whatever we use for the final link will succeed
1390+#
1391+if test $cm = makefile; then
1392+ : nothing to check
1393+else
1394+ HAVE_LINK_WORKS=x
1395+ ac_testinit link_works '' 'checking if the final link command may succeed'
1396+ fv=1
1397+ cat >conftest.c <<-'EOF'
1398+ #define EXTERN
1399+ #define MKSH_INCLUDES_ONLY
1400+ #include "sh.h"
1401+ __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.551 2012/04/16 17:49:40 tg Exp $");
1402+ int main(void) { printf("Hello, World!\n"); return (0); }
1403+EOF
1404+ case $cm in
1405+ llvm)
1406+ v "$CC $CFLAGS $CPPFLAGS $NOWARN -emit-llvm -c conftest.c" || fv=0
1407+ rmf mksh.s
1408+ test $fv = 0 || v "llvm-link -o - conftest.o | opt $optflags | llc -o mksh.s" || fv=0
1409+ test $fv = 0 || v "$CC $CFLAGS $LDFLAGS -o $tcfn mksh.s $LIBS $ccpr"
1410+ ;;
1411+ dragonegg)
1412+ v "$CC $CFLAGS $CPPFLAGS $NOWARN -S -flto conftest.c" || fv=0
1413+ test $fv = 0 || v "mv conftest.s conftest.ll"
1414+ test $fv = 0 || v "llvm-as conftest.ll" || fv=0
1415+ rmf mksh.s
1416+ test $fv = 0 || v "llvm-link -o - conftest.bc | opt $optflags | llc -o mksh.s" || fv=0
1417+ test $fv = 0 || v "$CC $CFLAGS $LDFLAGS -o $tcfn mksh.s $LIBS $ccpr"
1418+ ;;
1419+ combine)
1420+ v "$CC $CFLAGS $CPPFLAGS $LDFLAGS -fwhole-program --combine $NOWARN -o $tcfn conftest.c $LIBS $ccpr"
1421+ ;;
1422+ lto|normal)
1423+ cm=normal
1424+ v "$CC $CFLAGS $CPPFLAGS $NOWARN -c conftest.c" || fv=0
1425+ test $fv = 0 || v "$CC $CFLAGS $LDFLAGS -o $tcfn conftest.o $LIBS $ccpr"
1426+ ;;
1427+ esac
1428+ test -f $tcfn || fv=0
1429+ ac_testdone
1430+ test $fv = 1 || exit 1
1431+fi
1432+
1433+#
11681434 # Environment: signals
11691435 #
11701436 test x"NetBSD" = x"$TARGET_OS" && $e Ignore the compatibility warning.
@@ -1179,9 +1445,10 @@ for what in name list; do
11791445 extern const char *const _sys_sig${what}[];
11801446 int main(void) { return (_sys_sig${what}[0][0]); }
11811447 EOF
1182- if eval "test 1 = \$HAVE__SYS_SIG$uwhat"; then
1183- CPPFLAGS="$CPPFLAGS -Dsys_sig$what=_sys_sig$what"
1184- eval "HAVE_SYS_SIG$uwhat=1"
1448+ eval uwhat_v=\$HAVE__SYS_SIG$uwhat
1449+ if test 1 = "$uwhat_v"; then
1450+ add_cppflags -Dsys_sig$what=_sys_sig$what
1451+ eval HAVE_SYS_SIG$uwhat=1
11851452 fi
11861453 ac_cppflags SYS_SIG$uwhat
11871454 done
@@ -1195,15 +1462,20 @@ EOF
11951462 #
11961463 # Environment: library functions
11971464 #
1198-ac_testn flock_ex '' 'flock and mmap' <<-'EOF'
1199- #include <sys/types.h>
1200- #include <sys/file.h>
1201- #include <sys/mman.h>
1465+ac_test flock <<-'EOF'
12021466 #include <fcntl.h>
1203- #include <stdlib.h>
1204- int main(void) { return ((void *)mmap(NULL, (size_t)flock(0, LOCK_EX),
1205- PROT_READ, MAP_PRIVATE, 0, (off_t)0) == (void *)NULL ? 1 :
1206- munmap(NULL, 0)); }
1467+ #undef flock
1468+ int main(void) { return (flock(0, LOCK_EX | LOCK_UN)); }
1469+EOF
1470+
1471+ac_test lock_fcntl '!' flock 1 'whether we can lock files with fcntl' <<-'EOF'
1472+ #include <fcntl.h>
1473+ #undef flock
1474+ int main(void) {
1475+ struct flock lks;
1476+ lks.l_type = F_WRLCK | F_UNLCK;
1477+ return (fcntl(0, F_SETLKW, &lks));
1478+ }
12071479 EOF
12081480
12091481 ac_test getrusage <<-'EOF'
@@ -1232,10 +1504,19 @@ ac_test mknod '' 'if to use mknod(), makedev() and friends' <<-'EOF'
12321504 }
12331505 EOF
12341506
1235-ac_test mkstemp <<-'EOF'
1507+ac_test mmap lock_fcntl 0 'for mmap and munmap' <<-'EOF'
1508+ #include <sys/types.h>
1509+ #if HAVE_SYS_FILE_H
1510+ #include <sys/file.h>
1511+ #endif
1512+ #if HAVE_SYS_MMAN_H
1513+ #include <sys/mman.h>
1514+ #endif
1515+ #include <stddef.h>
12361516 #include <stdlib.h>
1237- #include <unistd.h>
1238- int main(void) { char tmpl[] = "X"; return (mkstemp(tmpl)); }
1517+ int main(void) { return ((void *)mmap(NULL, (size_t)0,
1518+ PROT_READ, MAP_PRIVATE, 0, (off_t)0) == (void *)NULL ? 1 :
1519+ munmap(NULL, 0)); }
12391520 EOF
12401521
12411522 ac_test nice <<-'EOF'
@@ -1264,18 +1545,30 @@ ac_test langinfo_codeset setlocale_ctype 0 'nl_langinfo(CODESET)' <<-'EOF'
12641545 int main(void) { return ((int)(ptrdiff_t)(void *)nl_langinfo(CODESET)); }
12651546 EOF
12661547
1267-ac_test setmode mknod 1 <<-'EOF'
1268- /* XXX imake style */
1269- /* XXX conditions correct? */
1270- #if defined(__MSVCRT__) || defined(__CYGWIN__)
1271- /* force a failure: Win32 setmode() is not what we want... */
1272- int main(void) { return (thiswillneverbedefinedIhope()); }
1273- #else
1548+ac_test select <<-'EOF'
12741549 #include <sys/types.h>
1275- #include <unistd.h>
1276- int main(int ac, char *av[]) { return (getmode(setmode(av[0]),
1277- (mode_t)ac)); }
1550+ #include <sys/time.h>
1551+ #if HAVE_SYS_BSDTYPES_H
1552+ #include <sys/bsdtypes.h>
1553+ #endif
1554+ #if HAVE_SYS_SELECT_H
1555+ #include <sys/select.h>
1556+ #endif
1557+ #if HAVE_BSTRING_H
1558+ #include <bstring.h>
1559+ #endif
1560+ #include <stddef.h>
1561+ #include <stdlib.h>
1562+ #include <string.h>
1563+ #if HAVE_STRINGS_H
1564+ #include <strings.h>
12781565 #endif
1566+ #include <unistd.h>
1567+ int main(void) {
1568+ struct timeval tv = { 1, 200000 };
1569+ fd_set fds; FD_ZERO(&fds); FD_SET(0, &fds);
1570+ return (select(FD_SETSIZE, &fds, NULL, NULL, &tv));
1571+ }
12791572 EOF
12801573
12811574 ac_test setresugid <<-'EOF'
@@ -1293,18 +1586,6 @@ ac_test setgroups setresugid 0 <<-'EOF'
12931586 int main(void) { gid_t gid = 0; return (setgroups(0, &gid)); }
12941587 EOF
12951588
1296-ac_test strcasestr <<-'EOF'
1297- #include <sys/types.h>
1298- #include <stddef.h>
1299- #include <string.h>
1300- #if HAVE_STRINGS_H
1301- #include <strings.h>
1302- #endif
1303- int main(int ac, char *av[]) {
1304- return ((int)(ptrdiff_t)(void *)strcasestr(*av, av[ac]));
1305- }
1306-EOF
1307-
13081589 ac_test strlcpy <<-'EOF'
13091590 #include <string.h>
13101591 int main(int ac, char *av[]) { return (strlcpy(*av, av[1],
@@ -1316,7 +1597,7 @@ EOF
13161597 #
13171598 save_CC=$CC; save_LDFLAGS=$LDFLAGS; save_LIBS=$LIBS
13181599 CC="$CC -c -o $tcfn"; LDFLAGS=; LIBS=
1319-ac_test '!' flock_decl flock_ex 1 'if flock() does not need to be declared' <<-'EOF'
1600+ac_test '!' flock_decl flock 1 'if flock() does not need to be declared' <<-'EOF'
13201601 #define MKSH_INCLUDES_ONLY
13211602 #include "sh.h"
13221603 long flock(void); /* this clashes if defined before */
@@ -1328,10 +1609,11 @@ ac_test '!' revoke_decl revoke 1 'if revoke() does not need to be declared' <<-'
13281609 long revoke(void); /* this clashes if defined before */
13291610 int main(void) { return ((int)revoke()); }
13301611 EOF
1331-ac_test sys_siglist_decl sys_siglist 1 'if sys_siglist[] does not need to be declared' <<-'EOF'
1612+ac_test '!' sys_siglist_decl sys_siglist 1 'if sys_siglist[] does not need to be declared' <<-'EOF'
13321613 #define MKSH_INCLUDES_ONLY
13331614 #include "sh.h"
1334- int main(void) { return (sys_siglist[0][0]); }
1615+ extern int sys_siglist[5][5][5][5][5]; /* this clashes happily */
1616+ int main(void) { return (sys_siglist[0][0][0][0][0]); }
13351617 EOF
13361618 CC=$save_CC; LDFLAGS=$save_LDFLAGS; LIBS=$save_LIBS
13371619
@@ -1339,11 +1621,120 @@ CC=$save_CC; LDFLAGS=$save_LDFLAGS; LIBS=$save_LIBS
13391621 # other checks
13401622 #
13411623 fd='if to use persistent history'
1342-ac_cache PERSISTENT_HISTORY || test 0 = $HAVE_FLOCK_EX || fv=1
1343-test 1 = $fv || check_categories=$check_categories,no-histfile
1624+ac_cache PERSISTENT_HISTORY || case $HAVE_MMAP$HAVE_FLOCK$HAVE_LOCK_FCNTL in
1625+11*|101) fv=1 ;;
1626+esac
1627+test 1 = $fv || check_categories="$check_categories no-histfile"
13441628 ac_testdone
13451629 ac_cppflags
13461630
1631+save_CFLAGS=$CFLAGS
1632+test x1 = x$HAVE_CAN_WNOOVERFLOW && CFLAGS="$CFLAGS -Wno-overflow"
1633+ac_testn compile_time_asserts_$$ '' 'whether compile-time assertions pass' <<-'EOF'
1634+ #define MKSH_INCLUDES_ONLY
1635+ #include "sh.h"
1636+ struct ctasserts {
1637+ #define cta(name, assertion) char name[(assertion) ? 1 : -1]
1638+/* this one should be defined by the standard */
1639+cta(char_is_1_char, (sizeof(char) == 1) && (sizeof(signed char) == 1) &&
1640+ (sizeof(unsigned char) == 1));
1641+/* the next assertion is probably not really needed */
1642+cta(short_is_2_char, sizeof(short) == 2);
1643+cta(short_size_no_matter_of_signedness, sizeof(short) == sizeof(unsigned short));
1644+/* the next assertion is probably not really needed */
1645+cta(int_is_4_char, sizeof(int) == 4);
1646+cta(int_size_no_matter_of_signedness, sizeof(int) == sizeof(unsigned int));
1647+
1648+cta(long_ge_int, sizeof(long) >= sizeof(int));
1649+
1650+/* the next assertion is probably not really needed */
1651+cta(ari_is_4_char, sizeof(mksh_ari_t) == 4);
1652+/* but the next three are; we REQUIRE signed integer wraparound */
1653+cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
1654+cta(ari_has_31_bit, 0 < (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 1));
1655+cta(ari_sign_32_bit_and_wrap,
1656+ (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 1) >
1657+ (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 2));
1658+/* the next assertion is probably not really needed */
1659+cta(uari_is_4_char, sizeof(mksh_uari_t) == 4);
1660+/* but the next four are; we REQUIRE unsigned integer wraparound */
1661+cta(uari_is_unsigned, (mksh_uari_t)-1 > (mksh_uari_t)0);
1662+cta(uari_has_31_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 2 + 1));
1663+cta(uari_has_32_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3));
1664+cta(uari_wrap_32_bit,
1665+ (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3) >
1666+ (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 4));
1667+
1668+cta(sizet_size_no_matter_of_signedness, sizeof(ssize_t) == sizeof(size_t));
1669+cta(ptrdifft_sizet_same_size, sizeof(ptrdiff_t) == sizeof(size_t));
1670+cta(ptrdifft_voidptr_same_size, sizeof(ptrdiff_t) == sizeof(void *));
1671+cta(ptrdifft_funcptr_same_size, sizeof(ptrdiff_t) == sizeof(void (*)(void)));
1672+/* our formatting routines assume this */
1673+cta(ptr_fits_in_long, sizeof(ptrdiff_t) <= sizeof(long));
1674+ };
1675+ int main(void) { return (sizeof(struct ctasserts)); }
1676+EOF
1677+CFLAGS=$save_CFLAGS
1678+eval test 1 = \$HAVE_COMPILE_TIME_ASSERTS_$$ || exit 1
1679+
1680+#
1681+# runtime checks
1682+# once this is more than one, check if we can do runtime
1683+# checks (not cross-compiling) first to save on warnings
1684+#
1685+$e "${bi}run-time checks follow$ao, please ignore any weird errors"
1686+
1687+if ac_testnnd silent_idivwrapv '' '(run-time) whether signed integer division overflows wrap silently' <<-'EOF'
1688+ #define MKSH_INCLUDES_ONLY
1689+ #include "sh.h"
1690+ #ifdef SIGFPE
1691+ static void fpe_catcher(int) MKSH_A_NORETURN;
1692+ #endif
1693+ int main(int ac, char **av) {
1694+ mksh_ari_t o1, o2, r1, r2;
1695+
1696+ #ifdef SIGFPE
1697+ signal(SIGFPE, fpe_catcher);
1698+ #endif
1699+ o1 = ((mksh_ari_t)1 << 31);
1700+ o2 = -ac;
1701+ r1 = o1 / o2;
1702+ r2 = o1 % o2;
1703+ if (r1 == o1 && r2 == 0) {
1704+ printf("si");
1705+ return (0);
1706+ }
1707+ printf("no %d %d %d %d %s", (int)o1, (int)o2, (int)r1,
1708+ (int)r2, av[0]);
1709+ return (1);
1710+ }
1711+ #ifdef SIGFPE
1712+ static const char fpe_msg[] = "no, got SIGFPE, what were they smoking?";
1713+ #define fpe_msglen (sizeof(fpe_msg) - 1)
1714+ static void fpe_catcher(int sig MKSH_A_UNUSED) {
1715+ _exit(write(1, fpe_msg, fpe_msglen) == fpe_msglen ? 2 : 3);
1716+ }
1717+ #endif
1718+EOF
1719+then
1720+ if test $fv = 0; then
1721+ echo "| hrm, compiling this failed, but we will just failback"
1722+ else
1723+ echo "| running test programme; this will fail if cross-compiling"
1724+ echo "| in which case we will gracefully degrade to the default"
1725+ ./$tcfn >vv.out 2>&1
1726+ rv=$?
1727+ echo "| result: `cat vv.out`"
1728+ fv=0
1729+ test $rv = 0 && test x"`cat vv.out`" = x"si" && fv=1
1730+ fi
1731+ rmf conftest.c conftest.o ${tcfn}* vv.out
1732+ ac_testdone
1733+fi
1734+ac_cppflags
1735+
1736+$e "${bi}end of run-time checks$ao"
1737+
13471738 #
13481739 # Compiler: Praeprocessor (only if needed)
13491740 #
@@ -1365,7 +1756,7 @@ $e ... done.
13651756 # the character count to standard output; cope for that
13661757 echo wq >x
13671758 ed x <x 2>/dev/null | grep 3 >/dev/null 2>&1 && \
1368- check_categories=$check_categories,$oldish_ed
1759+ check_categories="$check_categories $oldish_ed"
13691760 rmf x vv.out
13701761
13711762 if test 0 = $HAVE_SYS_SIGNAME; then
@@ -1374,7 +1765,8 @@ if test 0 = $HAVE_SYS_SIGNAME; then
13741765 else
13751766 $e No list of signal names available via cpp. Falling back...
13761767 fi
1377- sigseen=:
1768+ sigseenone=:
1769+ sigseentwo=:
13781770 echo '#include <signal.h>
13791771 #ifndef NSIG
13801772 #if defined(_NSIG)
@@ -1383,18 +1775,22 @@ if test 0 = $HAVE_SYS_SIGNAME; then
13831775 #define NSIG (SIGMAX+1)
13841776 #endif
13851777 #endif
1386-mksh_cfg: NSIG' >conftest.c
1778+int
1779+mksh_cfg= NSIG
1780+;' >conftest.c
1781+ # GNU sed 2.03 segfaults when optimising this to sed -n
13871782 NSIG=`vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
1388- grep mksh_cfg: | sed 's/^mksh_cfg:[ ]*\([0-9x ()+-]*\).*$/\1/'`
1783+ grep '^mksh_cfg *=[ ]*\([0-9x ()+-]*\).*$' | \
1784+ sed 's/^mksh_cfg *=[ ]*\([0-9x ()+-]*\).*$/\1/'`
13891785 case $NSIG in
1390- *[\ \(\)+-]*) NSIG=`awk "BEGIN { print $NSIG }"` ;;
1786+ *[\ \(\)+-]*) NSIG=`"$AWK" "BEGIN { print $NSIG }"` ;;
13911787 esac
13921788 printf=printf
13931789 (printf hallo) >/dev/null 2>&1 || printf=echo
13941790 test $printf = echo || NSIG=`printf %d "$NSIG" 2>/dev/null`
13951791 $printf "NSIG=$NSIG ... "
1396- sigs="ABRT ALRM BUS CHLD CLD CONT DIL EMT FPE HUP ILL INFO INT IO IOT"
1397- sigs="$sigs KILL LOST PIPE PROF PWR QUIT RESV SAK SEGV STOP SYS TERM"
1792+ sigs="INT SEGV ABRT KILL ALRM BUS CHLD CLD CONT DIL EMT FPE HUP ILL"
1793+ sigs="$sigs INFO IO IOT LOST PIPE PROF PWR QUIT RESV SAK STOP SYS TERM"
13981794 sigs="$sigs TRAP TSTP TTIN TTOU URG USR1 USR2 VTALRM WINCH XCPU XFSZ"
13991795 test 1 = $HAVE_CPP_DD && test $NSIG -gt 1 && sigs="$sigs "`vq \
14001796 "$CPP $CFLAGS $CPPFLAGS $NOWARN -dD conftest.c" | \
@@ -1402,18 +1798,25 @@ mksh_cfg: NSIG' >conftest.c
14021798 sed 's/^\(.*[ ]SIG\)\([A-Z0-9]*\)\([ ].*\)$/\2/' | sort`
14031799 test $NSIG -gt 1 || sigs=
14041800 for name in $sigs; do
1801+ case $sigseenone in
1802+ *:$name:*) continue ;;
1803+ esac
1804+ sigseenone=$sigseenone$name:
14051805 echo '#include <signal.h>' >conftest.c
1406- echo mksh_cfg: SIG$name >>conftest.c
1806+ echo int >>conftest.c
1807+ echo mksh_cfg= SIG$name >>conftest.c
1808+ echo ';' >>conftest.c
1809+ # GNU sed 2.03 croaks on optimising this, too
14071810 vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
1408- grep mksh_cfg: | \
1409- sed 's/^mksh_cfg:[ ]*\([0-9x]*\).*$/\1:'$name/
1410- done | grep -v '^:' | while IFS=: read nr name; do
1811+ grep '^mksh_cfg *=[ ]*\([0-9x]*\).*$' | \
1812+ sed 's/^mksh_cfg *=[ ]*\([0-9x]*\).*$/\1:'$name/
1813+ done | sed -e '/^:/d' -e 's/:/ /g' | while read nr name; do
14111814 test $printf = echo || nr=`printf %d "$nr" 2>/dev/null`
14121815 test $nr -gt 0 && test $nr -le $NSIG || continue
1413- case $sigseen in
1816+ case $sigseentwo in
14141817 *:$nr:*) ;;
14151818 *) echo " { \"$name\", $nr },"
1416- sigseen=$sigseen$nr:
1819+ sigseentwo=$sigseentwo$nr:
14171820 $printf "$name=$nr " >&2
14181821 ;;
14191822 esac
@@ -1422,26 +1825,67 @@ mksh_cfg: NSIG' >conftest.c
14221825 $e done.
14231826 fi
14241827
1425-addsrcs '!' HAVE_SETMODE setmode.c
1426-addsrcs '!' HAVE_STRLCPY strlcpy.c
1828+addsrcs -s '!' HAVE_STRLCPY strlcpy.c
14271829 addsrcs USE_PRINTF_BUILTIN printf.c
1428-test 1 = "$USE_PRINTF_BUILTIN" && CPPFLAGS="$CPPFLAGS -DMKSH_PRINTF_BUILTIN"
1429-test 0 = "$HAVE_SETMODE" && CPPFLAGS="$CPPFLAGS -DHAVE_CONFIG_H -DCONFIG_H_FILENAME=\\\"sh.h\\\""
1830+test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
14301831 test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
1832+test -n "$LDSTATIC" && add_cppflags -DMKSH_OPTSTATIC
1833+add_cppflags -DMKSH_BUILD_R=409
14311834
14321835 $e $bi$me: Finished configuration testing, now producing output.$ao
14331836
14341837 files=
14351838 objs=
14361839 sp=
1840+case $tcfn in
1841+a.exe) mkshexe=mksh.exe ;;
1842+*) mkshexe=mksh ;;
1843+esac
14371844 case $curdir in
1438-*\ *) echo "#!./mksh" >test.sh ;;
1439-*) echo "#!$curdir/mksh" >test.sh ;;
1845+*\ *) mkshshebang="#!./$mkshexe" ;;
1846+*) mkshshebang="#!$curdir/$mkshexe" ;;
14401847 esac
1441-cat >>test.sh <<-EOF
1848+cat >test.sh <<-EOF
1849+ $mkshshebang
14421850 LC_ALL=C PATH='$PATH'; export LC_ALL PATH
14431851 test -n "\$KSH_VERSION" || exit 1
1444- check_categories=$check_categories
1852+ set -A check_categories -- $check_categories
1853+ pflag='$curdir/$mkshexe'
1854+ sflag='$srcdir/check.t'
1855+ usee=0 Pflag=0 uset=0 vflag=0 xflag=0
1856+ while getopts "C:e:fPp:s:t:v" ch; do case \$ch {
1857+ (C) check_categories[\${#check_categories[*]}]=\$OPTARG ;;
1858+ (e) usee=1; eflag=\$OPTARG ;;
1859+ (f) check_categories[\${#check_categories[*]}]=fastbox ;;
1860+ (P) Pflag=1 ;;
1861+ (p) pflag=\$OPTARG ;;
1862+ (s) sflag=\$OPTARG ;;
1863+ (t) uset=1; tflag=\$OPTARG ;;
1864+ (v) vflag=1 ;;
1865+ (*) xflag=1 ;;
1866+ }
1867+ done
1868+ shift \$((OPTIND - 1))
1869+ set -A args -- '$srcdir/check.pl' -p "\$pflag" -s "\$sflag"
1870+ x=
1871+ for y in "\${check_categories[@]}"; do
1872+ x=\$x,\$y
1873+ done
1874+ if [[ -n \$x ]]; then
1875+ args[\${#args[*]}]=-C
1876+ args[\${#args[*]}]=\${x#,}
1877+ fi
1878+ if (( usee )); then
1879+ args[\${#args[*]}]=-e
1880+ args[\${#args[*]}]=\$eflag
1881+ fi
1882+ (( Pflag )) && args[\${#args[*]}]=-P
1883+ if (( uset )); then
1884+ args[\${#args[*]}]=-t
1885+ args[\${#args[*]}]=\$tflag
1886+ fi
1887+ (( vflag )) && args[\${#args[*]}]=-v
1888+ (( xflag )) && args[\${#args[*]}]=-x # force usage by synerr
14451889 print Testing mksh for conformance:
14461890 fgrep MirOS: '$srcdir/check.t'
14471891 fgrep MIRBSD '$srcdir/check.t'
@@ -1450,15 +1894,26 @@ cat >>test.sh <<-EOF
14501894 cstr='\$os = defined \$^O ? \$^O : "unknown";'
14511895 cstr="\$cstr"'print \$os . ", Perl version " . \$];'
14521896 for perli in \$PERL perl5 perl no; do
1453- [[ \$perli = no ]] && exit 1
1454- perlos=\$(\$perli -e "\$cstr") 2>&- || continue
1455- print "Perl interpreter '\$perli' running on '\$perlos'"
1456- [[ -n \$perlos ]] && break
1897+ if [[ \$perli = no ]]; then
1898+ print Cannot find a working Perl interpreter, aborting.
1899+ exit 1
1900+ fi
1901+ print "Trying Perl interpreter '\$perli'..."
1902+ perlos=\$(\$perli -e "\$cstr")
1903+ rv=\$?
1904+ print "Errorlevel \$rv, running on '\$perlos'"
1905+ if (( rv )); then
1906+ print "=> not using"
1907+ continue
1908+ fi
1909+ if [[ -n \$perlos ]]; then
1910+ print "=> using it"
1911+ break
1912+ fi
14571913 done
1458- exec \$perli '$srcdir/check.pl' -s '$srcdir/check.t' -p '$curdir/mksh' \${check_categories:+-C} \${check_categories#,} \$*$tsts
1914+ exec \$perli "\${args[@]}" "\$@"$tsts
14591915 EOF
14601916 chmod 755 test.sh
1461-test $HAVE_CAN_COMBINE$cm = 0combine && cm=normal
14621917 if test $cm = llvm; then
14631918 emitbc="-emit-llvm -c"
14641919 elif test $cm = dragonegg; then
@@ -1466,7 +1921,8 @@ elif test $cm = dragonegg; then
14661921 else
14671922 emitbc=-c
14681923 fi
1469-echo set -x >Rebuild.sh
1924+echo "# work around NeXTstep bug" >Rebuild.sh
1925+echo set -x >>Rebuild.sh
14701926 for file in $SRCS; do
14711927 op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'`
14721928 test -f $file || file=$srcdir/$file
@@ -1491,10 +1947,6 @@ dragonegg|llvm)
14911947 lobjs=$objs
14921948 ;;
14931949 esac
1494-case $tcfn in
1495-a.exe) mkshexe=mksh.exe ;;
1496-*) mkshexe=mksh ;;
1497-esac
14981950 echo tcfn=$mkshexe >>Rebuild.sh
14991951 echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh
15001952 echo 'test -f $tcfn || exit 1; size $tcfn' >>Rebuild.sh
@@ -1598,3 +2050,72 @@ $e
15982050 $e Run the regression test suite: ./test.sh
15992051 $e Please also read the sample file dot.mkshrc and the fine manual.
16002052 exit 0
2053+
2054+: <<'EOD'
2055+
2056+=== Environment used ===
2057+
2058+==== build environment ====
2059+AWK default: awk
2060+CC default: cc
2061+CFLAGS if empty, defaults to -xO2 or +O2
2062+ or -O3 -qstrict or -O2, per compiler
2063+CPPFLAGS default empty
2064+LDFLAGS default empty; added before sources
2065+LDSTATIC set this to '-static'; default unset
2066+LIBS default empty; added after sources
2067+ [Interix] default: -lcrypt (XXX still needed?)
2068+NOWARN -Wno-error or similar
2069+NROFF default: nroff
2070+TARGET_OS default: $(uname -s || uname)
2071+TARGET_OSREV [QNX] default: $(uname -r)
2072+
2073+==== feature selectors ====
2074+USE_PRINTF_BUILTIN 1 to include (unsupported) printf(1) as builtin
2075+===== general format =====
2076+HAVE_STRLEN ac_test
2077+HAVE_STRING_H ac_header
2078+HAVE_CAN_FSTACKPROTECTORALL ac_flags
2079+
2080+==== cpp definitions ====
2081+MKSHRC_PATH "~/.mkshrc" (do not change)
2082+MKSH_A4PB force use of arc4random_pushb
2083+MKSH_ASSUME_UTF8 (0=disabled, 1=enabled; default: unset)
2084+MKSH_BINSHREDUCED if */sh or */-sh, enable set -o sh
2085+MKSH_CLRTOEOL_STRING "\033[K"
2086+MKSH_CLS_STRING "\033[;H\033[J"
2087+MKSH_CONSERVATIVE_FDS fd 0-9 for scripts, shell only up to 31
2088+MKSH_DEFAULT_EXECSHELL "/bin/sh" (do not change)
2089+MKSH_DEFAULT_TMPDIR "/tmp" (do not change)
2090+MKSH_DISABLE_DEPRECATED disable code paths scheduled for later removal
2091+MKSH_DONT_EMIT_IDSTRING omit RCS IDs from binary
2092+MKSH_MIDNIGHTBSD01ASH_COMPAT set -o sh: additional compatibility quirk
2093+MKSH_NOPROSPECTOFWORK disable jobs, co-processes, etc. (do not use)
2094+MKSH_NOPWNAM skip PAM calls, for -static on eglibc, Solaris
2095+MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run
2096+MKSH_NO_EXTERNAL_CAT omit hack to skip cat builtin when flags passed
2097+MKSH_NO_LIMITS omit ulimit code
2098+MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available
2099+MKSH_SMALL omit some code, optimise hard for size (slower)
2100+MKSH_S_NOVI=1 disable Vi editing mode (default if MKSH_SMALL)
2101+MKSH_TYPEDEF_SIG_ATOMIC_T define to e.g. 'int' if sig_atomic_t is missing
2102+MKSH_TYPEDEF_SSIZE_T define to e.g. 'long' if your OS has no ssize_t
2103+MKSH_UNEMPLOYED disable job control (but not jobs/co-processes)
2104+
2105+=== generic installation instructions ===
2106+
2107+Set CC and possibly CFLAGS, CPPFLAGS, LDFLAGS, LIBS. If cross-compiling,
2108+also set TARGET_OS. To disable tests, set e.g. HAVE_STRLCPY=0; to enable
2109+them, set to a value other than 0 or 1. Ensure /bin/ed is installed. For
2110+MKSH_SMALL but with Vi mode, add -DMKSH_S_NOVI=0 to CPPFLAGS as well.
2111+
2112+Normally, the following command is what you want to run, then:
2113+$ (sh Build.sh -r -c lto && ./test.sh -v) 2>&1 | tee log
2114+
2115+Copy dot.mkshrc to /etc/skel/.mkshrc; install mksh into $prefix/bin; or
2116+/bin; install the manpage, if omitting the -r flag a catmanpage is made
2117+using $NROFF. Consider using a forward script as /etc/skel/.mkshrc like
2118+https://www.mirbsd.org/cvs.cgi/contrib/hosted/tg/deb/mksh/debian/.mkshrc?rev=HEAD
2119+and put dot.mkshrc as /etc/mkshrc so users need not keep up their HOME.
2120+
2121+EOD
--- a/src/check.pl
+++ b/src/check.pl
@@ -1,7 +1,7 @@
1-# $MirOS: src/bin/mksh/check.pl,v 1.23 2009/06/10 18:12:43 tg Rel $
1+# $MirOS: src/bin/mksh/check.pl,v 1.31 2012/04/06 12:22:14 tg Exp $
22 # $OpenBSD: th,v 1.13 2006/05/18 21:27:23 miod Exp $
33 #-
4-# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
4+# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012
55 # Thorsten Glaser <tg@mirbsd.org>
66 #
77 # Provided that these terms and disclaimer and all copyright notices
@@ -71,9 +71,11 @@
7171 # environment. Programs are run with
7272 # the following minimal environment:
7373 # HOME, LD_LIBRARY_PATH, LOCPATH,
74-# LOGNAME, PATH, SHELL, USER
74+# LOGNAME, PATH, SHELL, UNIXMODE,
75+# USER
7576 # (values taken from the environment of
7677 # the test harness).
78+# CYGWIN is set to nodosfilewarning.
7779 # ENV is set to /nonexistant.
7880 # __progname is set to the -p argument.
7981 # __perlname is set to $^X (perlexe).
@@ -135,6 +137,8 @@
135137 # One category os:XXX is predefined
136138 # (XXX is the operating system name,
137139 # eg, linux, dec_osf).
140+# need-ctty 'yes' if the test needs a ctty, run
141+# with -C regress:no-ctty to disable.
138142 # Flag meanings:
139143 # r tag is required (eg, a test must have a name tag).
140144 # m value can be multiple lines. Lines must be prefixed with
@@ -147,7 +151,24 @@
147151 # p tag takes parameters (used with m).
148152 # s tag can be used several times.
149153
150-use POSIX qw(EINTR);
154+# pull EINTR from POSIX.pm or Errno.pm if they exist
155+# otherwise just skip it
156+BEGIN {
157+ $EINTR = 0;
158+ eval {
159+ require POSIX;
160+ $EINTR = POSIX::EINTR();
161+ };
162+ if ($@) {
163+ eval {
164+ require Errno;
165+ $EINTR = Errno::EINTR();
166+ } or do {
167+ $EINTR = 0;
168+ };
169+ }
170+};
171+
151172 use Getopt::Std;
152173 use Config;
153174
@@ -156,19 +177,19 @@ $os = defined $^O ? $^O : 'unknown';
156177 ($prog = $0) =~ s#.*/##;
157178
158179 $Usage = <<EOF ;
159-Usage: $prog [-s test-set] [-C category] [-p prog] [-v] [-e e=v] name ...
160- -p p Use p as the program to test
180+Usage: $prog [-Pv] [-C cat] [-e e=v] [-p prog] [-s fn] [-t tmo] name ...
161181 -C c Specify the comma separated list of categories the program
162182 belongs to (see category field).
183+ -e e=v Set the environment variable e to v for all tests
184+ (if no =v is given, the current value is used)
185+ Only one -e option can be given at the moment, sadly.
186+ -P program (-p) string has multiple words, and the program is in
187+ the path (kludge option)
188+ -p p Use p as the program to test
163189 -s s Read tests from file s; if s is a directory, it is recursively
164190 scaned for test files (which end in .t).
165191 -t t Use t as default time limit for tests (default is unlimited)
166- -P program (-p) string has multiple words, and the program is in
167- the path (kludge option)
168192 -v Verbose mode: print reason test failed.
169- -e e=v Set the environment variable e to v for all tests
170- (if no =v is given, the current value is used)
171- Only one -e option can be given at the moment, sadly.
172193 name specifies the name of the test(s) to run; if none are
173194 specified, all tests are run.
174195 EOF
@@ -193,6 +214,8 @@ EOF
193214 'expected-stderr', 'm',
194215 'expected-stderr-pattern', 'm',
195216 'category', 'm',
217+ 'need-ctty', '',
218+ 'need-pass', '',
196219 );
197220 # Filled in by read_test()
198221 %internal_test_fields = (
@@ -213,13 +236,14 @@ $tempe = "/tmp/rte$$";
213236 $tempdir = "/tmp/rtd$$";
214237
215238 $nfailed = 0;
239+$nifailed = 0;
216240 $nxfailed = 0;
217241 $npassed = 0;
218242 $nxpassed = 0;
219243
220244 %known_tests = ();
221245
222-if (!getopts('C:p:Ps:t:ve:')) {
246+if (!getopts('C:e:Pp:s:t:v')) {
223247 print STDERR $Usage;
224248 exit 1;
225249 }
@@ -253,9 +277,10 @@ $all_tests = @ARGV == 0;
253277 # Set up a very minimal environment
254278 %new_env = ();
255279 foreach $env (('HOME', 'LD_LIBRARY_PATH', 'LOCPATH', 'LOGNAME',
256- 'PATH', 'SHELL', 'USER')) {
280+ 'PATH', 'SHELL', 'UNIXMODE', 'USER')) {
257281 $new_env{$env} = $ENV{$env} if defined $ENV{$env};
258282 }
283+$new_env{'CYGWIN'} = 'nodosfilewarning';
259284 $new_env{'ENV'} = '/nonexistant';
260285 if (($os eq 'VMS') || ($Config{perlpath} =~ m/$Config{_exe}$/i)) {
261286 $new_env{'__perlname'} = $Config{perlpath};
@@ -300,12 +325,13 @@ if (-d $test_set) {
300325 }
301326 &cleanup_exit() if !defined $ret;
302327
303-$tot_failed = $nfailed + $nxfailed;
328+$tot_failed = $nfailed + $nifailed + $nxfailed;
304329 $tot_passed = $npassed + $nxpassed;
305330 if ($tot_failed || $tot_passed) {
306331 print "Total failed: $tot_failed";
332+ print " ($nifailed ignored)" if $nifailed;
307333 print " ($nxfailed unexpected)" if $nxfailed;
308- print " (as expected)" if $nfailed && !$nxfailed;
334+ print " (as expected)" if $nfailed && !$nxfailed && !$nifailed;
309335 print "\nTotal passed: $tot_passed";
310336 print " ($nxpassed unexpected)" if $nxpassed;
311337 print "\n";
@@ -319,7 +345,11 @@ cleanup_exit
319345 local($sig, $exitcode) = ('', 1);
320346
321347 if ($_[0] eq 'ok') {
322- $exitcode = 0;
348+ unless ($nxfailed) {
349+ $exitcode = 0;
350+ } else {
351+ $exitcode = 1;
352+ }
323353 } elsif ($_[0] ne '') {
324354 $sig = $_[0];
325355 }
@@ -544,7 +574,9 @@ run_test
544574 $xpid = waitpid($pid, 0);
545575 $child_kill_ok = 0;
546576 if ($xpid < 0) {
547- next if $! == EINTR;
577+ if ($EINTR) {
578+ next if $! == $EINTR;
579+ }
548580 print STDERR "$prog: error waiting for child - $!\n";
549581 return undef;
550582 }
@@ -616,8 +648,13 @@ run_test
616648
617649 if ($failed) {
618650 if (!$test{'expected-fail'}) {
619- print "FAIL $name\n";
620- $nxfailed++;
651+ if ($test{'need-pass'}) {
652+ print "FAIL $name\n";
653+ $nxfailed++;
654+ } else {
655+ print "FAIL $name (ignored)\n";
656+ $nifailed++;
657+ }
621658 } else {
622659 print "fail $name (as expected)\n";
623660 $nfailed++;
@@ -642,6 +679,7 @@ category_check
642679 local(*test) = @_;
643680 local($c);
644681
682+ return 0 if ($test{'need-ctty'} && defined $categories{'regress:no-ctty'});
645683 return 1 if (!defined $test{'category'});
646684 local($ok) = 0;
647685 foreach $c (split(',', $test{'category'})) {
@@ -1064,6 +1102,26 @@ read_test
10641102 } else {
10651103 $test{'expected-fail'} = 0;
10661104 }
1105+ if (defined $test{'need-ctty'}) {
1106+ if ($test{'need-ctty'} !~ /^(yes|no)$/) {
1107+ print STDERR
1108+ "$prog:$test{':long-name'}: bad value for need-ctty field\n";
1109+ return undef;
1110+ }
1111+ $test{'need-ctty'} = $1 eq 'yes';
1112+ } else {
1113+ $test{'need-ctty'} = 0;
1114+ }
1115+ if (defined $test{'need-pass'}) {
1116+ if ($test{'need-pass'} !~ /^(yes|no)$/) {
1117+ print STDERR
1118+ "$prog:$test{':long-name'}: bad value for need-pass field\n";
1119+ return undef;
1120+ }
1121+ $test{'need-pass'} = $1 eq 'yes';
1122+ } else {
1123+ $test{'need-pass'} = 1;
1124+ }
10671125 if (defined $test{'arguments'}) {
10681126 local($firstc) = substr($test{'arguments'}, 0, 1);
10691127
--- a/src/check.t
+++ b/src/check.t
@@ -1,9 +1,10 @@
1-# $MirOS: src/bin/mksh/check.t,v 1.388 2010/08/24 15:47:44 tg Exp $
1+# $MirOS: src/bin/mksh/check.t,v 1.533 2012/04/22 21:50:29 tg Exp $
22 # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
33 # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
44 # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
55 #-
6-# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
6+# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
7+# 2011, 2012
78 # Thorsten Glaser <tg@mirbsd.org>
89 #
910 # Provided that these terms and disclaimer and all copyright notices
@@ -23,9 +24,12 @@
2324 #-
2425 # You may also want to test IFS with the script at
2526 # http://www.research.att.com/~gsf/public/ifs.sh
27+#
28+# More testsuites at:
29+# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
2630
2731 expected-stdout:
28- @(#)MIRBSD KSH R39 2010/08/24
32+ @(#)MIRBSD KSH R40 2012/04/22
2933 description:
3034 Check version of shell.
3135 stdin:
@@ -65,6 +69,16 @@ category: disabled
6569 stdin:
6670 set
6771 ---
72+name: selftest-direct-builtin-call
73+description:
74+ Check that direct builtin calls work
75+stdin:
76+ ln -s "$__progname" cat
77+ ln -s "$__progname" echo
78+ ./echo -c 'echo foo' | ./cat -u
79+expected-stdout:
80+ -c echo foo
81+---
6882 name: alias-1
6983 description:
7084 Check that recursion is detected/avoided in aliases.
@@ -269,6 +283,27 @@ stdin:
269283 expected-stdout:
270284 5
271285 ---
286+name: arith-div-byzero
287+description:
288+ Check division by zero errors out
289+stdin:
290+ x=$(echo $((1 / 0)))
291+ echo =$?:$x.
292+expected-stdout:
293+ =1:.
294+expected-stderr-pattern:
295+ /.*divisor/
296+---
297+name: arith-div-intmin-by-minusone
298+description:
299+ Check division overflow wraps around silently
300+stdin:
301+ echo signed:$((-2147483648 / -1))r$((-2147483648 % -1)).
302+ echo unsigned:$((# -2147483648 / -1))r$((# -2147483648 % -1)).
303+expected-stdout:
304+ signed:-2147483648r0.
305+ unsigned:0r2147483648.
306+---
272307 name: arith-assop-assoc-1
273308 description:
274309 Check associativity of assignment-operator operator
@@ -346,7 +381,7 @@ expected-stdout:
346381 ---
347382 name: bksl-nl-ign-1
348383 description:
349- Check that \newline is not collasped after #
384+ Check that \newline is not collapsed after #
350385 stdin:
351386 echo hi #there \
352387 echo folks
@@ -356,7 +391,7 @@ expected-stdout:
356391 ---
357392 name: bksl-nl-ign-2
358393 description:
359- Check that \newline is not collasped inside single quotes
394+ Check that \newline is not collapsed inside single quotes
360395 stdin:
361396 echo 'hi \
362397 there'
@@ -368,7 +403,7 @@ expected-stdout:
368403 ---
369404 name: bksl-nl-ign-3
370405 description:
371- Check that \newline is not collasped inside single quotes
406+ Check that \newline is not collapsed inside single quotes
372407 stdin:
373408 cat << \EOF
374409 hi \
@@ -418,7 +453,7 @@ expected-stdout:
418453 #
419454 name: bksl-nl-1
420455 description:
421- Check that \newline is collasped before, in the middle of, and
456+ Check that \newline is collapsed before, in the middle of, and
422457 after words
423458 stdin:
424459 \
@@ -430,7 +465,7 @@ expected-stdout:
430465 ---
431466 name: bksl-nl-2
432467 description:
433- Check that \newline is collasped in $ sequences
468+ Check that \newline is collapsed in $ sequences
434469 (ksh93 fails this)
435470 stdin:
436471 a=12
@@ -454,7 +489,7 @@ expected-stdout:
454489 ---
455490 name: bksl-nl-3
456491 description:
457- Check that \newline is collasped in $(..) and `...` sequences
492+ Check that \newline is collapsed in $(..) and `...` sequences
458493 (ksh93 fails this)
459494 stdin:
460495 echo $\
@@ -479,7 +514,7 @@ expected-stdout:
479514 ---
480515 name: bksl-nl-4
481516 description:
482- Check that \newline is collasped in $((..)) sequences
517+ Check that \newline is collapsed in $((..)) sequences
483518 (ksh93 fails this)
484519 stdin:
485520 echo $\
@@ -501,7 +536,7 @@ expected-stdout:
501536 ---
502537 name: bksl-nl-5
503538 description:
504- Check that \newline is collasped in double quoted strings
539+ Check that \newline is collapsed in double quoted strings
505540 stdin:
506541 echo "\
507542 hi"
@@ -516,7 +551,7 @@ expected-stdout:
516551 ---
517552 name: bksl-nl-6
518553 description:
519- Check that \newline is collasped in here document delimiters
554+ Check that \newline is collapsed in here document delimiters
520555 (ksh93 fails second part of this)
521556 stdin:
522557 a=12
@@ -539,7 +574,7 @@ expected-stdout:
539574 ---
540575 name: bksl-nl-7
541576 description:
542- Check that \newline is collasped in double-quoted here-document
577+ Check that \newline is collapsed in double-quoted here-document
543578 delimiter.
544579 stdin:
545580 a=12
@@ -558,7 +593,7 @@ expected-stdout:
558593 ---
559594 name: bksl-nl-8
560595 description:
561- Check that \newline is collasped in various 2+ character tokens
596+ Check that \newline is collapsed in various 2+ character tokens
562597 delimiter.
563598 (ksh93 fails this)
564599 stdin:
@@ -995,6 +1030,46 @@ expected-stdout:
9951030 1 /bin
9961031 0 /tmp
9971032 ---
1033+name: cd-pe
1034+description:
1035+ Check package for cd -Pe
1036+need-pass: no
1037+# the mv command fails on Cygwin
1038+# Hurd aborts the testsuite (permission denied)
1039+category: !os:cygwin,!os:gnu,!os:msys
1040+file-setup: file 644 "x"
1041+ mkdir noread noread/target noread/target/subdir
1042+ ln -s noread link
1043+ chmod 311 noread
1044+ cd -P$1 .
1045+ echo 0=$?
1046+ bwd=$PWD
1047+ cd -P$1 link/target
1048+ echo 1=$?,${PWD#$bwd/}
1049+ epwd=$($TSHELL -c pwd 2>/dev/null)
1050+ # This unexpectedly succeeds on GNU/Linux and MidnightBSD
1051+ #echo pwd=$?,$epwd
1052+ # expect: pwd=1,
1053+ mv ../../noread ../../renamed
1054+ cd -P$1 subdir
1055+ echo 2=$?,${PWD#$bwd/}
1056+ cd $bwd
1057+ chmod 755 renamed
1058+ rm -rf noread link renamed
1059+stdin:
1060+ export TSHELL="$__progname"
1061+ "$__progname" x
1062+ echo "now with -e:"
1063+ "$__progname" x e
1064+expected-stdout:
1065+ 0=0
1066+ 1=0,noread/target
1067+ 2=0,noread/target/subdir
1068+ now with -e:
1069+ 0=0
1070+ 1=0,noread/target
1071+ 2=1,noread/target/subdir
1072+---
9981073 name: env-prompt
9991074 description:
10001075 Check that prompt not printed when processing ENV
@@ -1003,6 +1078,7 @@ file-setup: file 644 "foo"
10031078 XXX=_
10041079 PS1=X
10051080 false && echo hmmm
1081+need-ctty: yes
10061082 arguments: !-i!
10071083 stdin:
10081084 echo hi${XXX}there
@@ -1015,11 +1091,14 @@ name: expand-ugly
10151091 description:
10161092 Check that weird ${foo+bar} constructs are parsed correctly
10171093 stdin:
1094+ print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn
1095+ print '#!'"$__progname"'\nfor x in "$@"; do print -nr -- "<$x> "; done' >pfs
1096+ chmod +x pfn pfs
10181097 (echo 1 ${IFS+'}'z}) 2>&- || echo failed in 1
10191098 (echo 2 "${IFS+'}'z}") 2>&- || echo failed in 2
10201099 (echo 3 "foo ${IFS+'bar} baz") 2>&- || echo failed in 3
1021- (echo -n '4 '; printf '%s\n' "foo ${IFS+"b c"} baz") 2>&- || echo failed in 4
1022- (echo -n '5 '; printf '%s\n' "foo ${IFS+b c} baz") 2>&- || echo failed in 5
1100+ (echo -n '4 '; ./pfn "foo ${IFS+"b c"} baz") 2>&- || echo failed in 4
1101+ (echo -n '5 '; ./pfn "foo ${IFS+b c} baz") 2>&- || echo failed in 5
10231102 (echo 6 ${IFS+"}"z}) 2>&- || echo failed in 6
10241103 (echo 7 "${IFS+"}"z}") 2>&- || echo failed in 7
10251104 (echo 8 "${IFS+\"}\"z}") 2>&- || echo failed in 8
@@ -1029,7 +1108,7 @@ stdin:
10291108 (echo 12 "$(echo ${IFS+'}'z})") 2>&- || echo failed in 12
10301109 (echo 13 ${IFS+\}z}) 2>&- || echo failed in 13
10311110 (echo 14 "${IFS+\}z}") 2>&- || echo failed in 14
1032- u=x; (echo -n '15 '; printf '<%s> ' "foo ${IFS+a"b$u{ {"{{\}b} c ${IFS+d{}} bar" ${IFS-e{}} baz; echo .) 2>&- || echo failed in 15
1111+ u=x; (echo -n '15 '; ./pfs "foo ${IFS+a"b$u{ {"{{\}b} c ${IFS+d{}} bar" ${IFS-e{}} baz; echo .) 2>&- || echo failed in 15
10331112 l=t; (echo 16 ${IFS+h`echo -n i ${IFS+$l}h`ere}) 2>&- || echo failed in 16
10341113 l=t; (echo 17 ${IFS+h$(echo -n i ${IFS+$l}h)ere}) 2>&- || echo failed in 17
10351114 l=t; (echo 18 "${IFS+h`echo -n i ${IFS+$l}h`ere}") 2>&- || echo failed in 18
@@ -1038,26 +1117,26 @@ stdin:
10381117 l=t; (echo 21 ${IFS+h$(echo -n i "${IFS+$l}"h)ere}) 2>&- || echo failed in 21
10391118 l=t; (echo 22 "${IFS+h`echo -n i "${IFS+$l}"h`ere}") 2>&- || echo failed in 22
10401119 l=t; (echo 23 "${IFS+h$(echo -n i "${IFS+$l}"h)ere}") 2>&- || echo failed in 23
1041- key=value; (echo -n '24 '; printf '%s\n' "${IFS+'$key'}") 2>&- || echo failed in 24
1042- key=value; (echo -n '25 '; printf '%s\n' "${IFS+"'$key'"}") 2>&- || echo failed in 25 # ksh93: “'$key'”
1043- key=value; (echo -n '26 '; printf '%s\n' ${IFS+'$key'}) 2>&- || echo failed in 26
1044- key=value; (echo -n '27 '; printf '%s\n' ${IFS+"'$key'"}) 2>&- || echo failed in 27
1045- (echo -n '28 '; printf '%s\n' "${IFS+"'"x ~ x'}'x"'}"x}" #') 2>&- || echo failed in 28
1046- u=x; (echo -n '29 '; printf '<%s> ' foo ${IFS+a"b$u{ {"{ {\}b} c ${IFS+d{}} bar ${IFS-e{}} baz; echo .) 2>&- || echo failed in 29
1047- (echo -n '30 '; printf '<%s> ' ${IFS+foo 'b\
1120+ key=value; (echo -n '24 '; ./pfn "${IFS+'$key'}") 2>&- || echo failed in 24
1121+ key=value; (echo -n '25 '; ./pfn "${IFS+"'$key'"}") 2>&- || echo failed in 25 # ksh93: “'$key'”
1122+ key=value; (echo -n '26 '; ./pfn ${IFS+'$key'}) 2>&- || echo failed in 26
1123+ key=value; (echo -n '27 '; ./pfn ${IFS+"'$key'"}) 2>&- || echo failed in 27
1124+ (echo -n '28 '; ./pfn "${IFS+"'"x ~ x'}'x"'}"x}" #') 2>&- || echo failed in 28
1125+ u=x; (echo -n '29 '; ./pfs foo ${IFS+a"b$u{ {"{ {\}b} c ${IFS+d{}} bar ${IFS-e{}} baz; echo .) 2>&- || echo failed in 29
1126+ (echo -n '30 '; ./pfs ${IFS+foo 'b\
10481127 ar' baz}; echo .) 2>&- || (echo failed in 30; echo failed in 31)
1049- (echo -n '32 '; printf '<%s> ' ${IFS+foo "b\
1128+ (echo -n '32 '; ./pfs ${IFS+foo "b\
10501129 ar" baz}; echo .) 2>&- || echo failed in 32
1051- (echo -n '33 '; printf '<%s> ' "${IFS+foo 'b\
1130+ (echo -n '33 '; ./pfs "${IFS+foo 'b\
10521131 ar' baz}"; echo .) 2>&- || echo failed in 33
1053- (echo -n '34 '; printf '<%s> ' "${IFS+foo "b\
1132+ (echo -n '34 '; ./pfs "${IFS+foo "b\
10541133 ar" baz}"; echo .) 2>&- || echo failed in 34
1055- (echo -n '35 '; printf '<%s> ' ${v=a\ b} x ${v=c\ d}; echo .) 2>&- || echo failed in 35
1056- (echo -n '36 '; printf '<%s> ' "${v=a\ b}" x "${v=c\ d}"; echo .) 2>&- || echo failed in 36
1057- (echo -n '37 '; printf '<%s> ' ${v-a\ b} x ${v-c\ d}; echo .) 2>&- || echo failed in 37
1134+ (echo -n '35 '; ./pfs ${v=a\ b} x ${v=c\ d}; echo .) 2>&- || echo failed in 35
1135+ (echo -n '36 '; ./pfs "${v=a\ b}" x "${v=c\ d}"; echo .) 2>&- || echo failed in 36
1136+ (echo -n '37 '; ./pfs ${v-a\ b} x ${v-c\ d}; echo .) 2>&- || echo failed in 37
10581137 (echo 38 ${IFS+x'a'y} / "${IFS+x'a'y}" .) 2>&- || echo failed in 38
10591138 foo="x'a'y"; (echo 39 ${foo%*'a'*} / "${foo%*'a'*}" .) 2>&- || echo failed in 39
1060- foo="a b c"; (echo -n '40 '; printf '<%s> ' "${foo#a}"; echo .) 2>&- || echo failed in 40
1139+ foo="a b c"; (echo -n '40 '; ./pfs "${foo#a}"; echo .) 2>&- || echo failed in 40
10611140 expected-stdout:
10621141 1 }z
10631142 2 ''z}
@@ -1360,6 +1439,56 @@ expected-stdout:
13601439 9 EQAL brac foo x c x} baz
13611440 9 QSTN brac foo x c x} baz
13621441 ---
1442+name: expand-threecolons-dblq
1443+description:
1444+ Check for a particular thing that used to segfault
1445+stdin:
1446+ TEST=1234
1447+ echo "${TEST:1:2:3}"
1448+ echo $? but still living
1449+expected-stderr-pattern:
1450+ /bad substitution/
1451+expected-exit: 1
1452+---
1453+name: expand-threecolons-unq
1454+description:
1455+ Check for a particular thing that used to not error out
1456+stdin:
1457+ TEST=1234
1458+ echo ${TEST:1:2:3}
1459+ echo $? but still living
1460+expected-stderr-pattern:
1461+ /bad substitution/
1462+expected-exit: 1
1463+---
1464+name: expand-weird-1
1465+description:
1466+ Check corner case of trim expansion vs. $# vs. ${#var}
1467+stdin:
1468+ set 1 2 3 4 5 6 7 8 9 10 11
1469+ echo ${#} # value of $#
1470+ echo ${##} # length of $#
1471+ echo ${##1} # $# trimmed 1
1472+ set 1 2 3 4 5 6 7 8 9 10 11 12
1473+ echo ${##1}
1474+expected-stdout:
1475+ 11
1476+ 2
1477+ 1
1478+ 2
1479+---
1480+name: expand-weird-2
1481+description:
1482+ Check corner case of ${var?} vs. ${#var}
1483+stdin:
1484+ (exit 0)
1485+ echo $? = ${#?} .
1486+ (exit 111)
1487+ echo $? = ${#?} .
1488+expected-stdout:
1489+ 0 = 1 .
1490+ 111 = 3 .
1491+---
13631492 name: eglob-bad-1
13641493 description:
13651494 Check that globbing isn't done when glob has syntax error
@@ -1495,6 +1624,27 @@ expected-stdout:
14951624 3: abcdef
14961625 4: cdef
14971626 ---
1627+name: eglob-trim-3
1628+description:
1629+ Check eglobbing works in trims, for Korn Shell
1630+ Ensure eglobbing does not work for reduced-feature /bin/sh
1631+stdin:
1632+ set +o sh
1633+ x=foobar
1634+ y=foobaz
1635+ z=fooba\?
1636+ echo "<${x%bar|baz},${y%bar|baz},${z%\?}>"
1637+ echo "<${x%ba(r|z)},${y%ba(r|z)}>"
1638+ set -o sh
1639+ echo "<${x%bar|baz},${y%bar|baz},${z%\?}>"
1640+ z='foo(bar'
1641+ echo "<${z%(*}>"
1642+expected-stdout:
1643+ <foo,foo,fooba>
1644+ <foo,foo>
1645+ <foobar,foobaz,fooba>
1646+ <foo>
1647+---
14981648 name: eglob-substrpl-1
14991649 description:
15001650 Check eglobbing works in substs... and they work at all
@@ -1742,6 +1892,10 @@ expected-stdout:
17421892 name: glob-bad-2
17431893 description:
17441894 Check that symbolic links aren't stat()'d
1895+# breaks on FreeMiNT (cannot unlink dangling symlinks)
1896+# breaks on MSYS (does not support symlinks)
1897+# breaks on Dell UNIX 4.0 R2.2 (SVR4) where unlink also fails
1898+category: !os:mint,!os:msys,!os:svr4.0
17451899 file-setup: dir 755 "dir"
17461900 file-setup: symlink 644 "dir/abc"
17471901 non-existent-file
@@ -1787,7 +1941,8 @@ name: glob-range-3
17871941 description:
17881942 Check that globbing matches the right things...
17891943 # breaks on Mac OSX (HFS+ non-standard Unicode canonical decomposition)
1790-category: !os:darwin
1944+# breaks on Cygwin 1.7 (files are now UTF-16 or something)
1945+category: !os:cygwin,!os:darwin,!os:msys
17911946 file-setup: file 644 "aÂc"
17921947 stdin:
17931948 echo a[Á-Ú]*
@@ -2007,6 +2162,230 @@ stdin:
20072162 expected-stdout:
20082163 one
20092164 ---
2165+name: heredoc-9e
2166+description:
2167+ Check here string related regression with multiple iops
2168+stdin:
2169+ echo $(tr r z <<<'bar' 2>&-)
2170+expected-stdout:
2171+ baz
2172+---
2173+name: heredoc-10
2174+description:
2175+ Check direct here document assignment
2176+stdin:
2177+ x=u
2178+ va=<<EOF
2179+ =a $x \x40=
2180+ EOF
2181+ vb=<<'EOF'
2182+ =b $x \x40=
2183+ EOF
2184+ function foo {
2185+ vc=<<-EOF
2186+ =c $x \x40=
2187+ EOF
2188+ }
2189+ typeset -f foo
2190+ foo
2191+ # rather nonsensical, but…
2192+ vd=<<<"=d $x \x40="
2193+ ve=<<<'=e $x \x40='
2194+ vf=<<<$'=f $x \x40='
2195+ # now check
2196+ print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} ve={$ve} vf={$vf} |"
2197+expected-stdout:
2198+ function foo {
2199+ vc= <<-EOF
2200+ =c $x \x40=
2201+ EOF
2202+
2203+ }
2204+ | va={=a u \x40=
2205+ } vb={=b $x \x40=
2206+ } vc={=c u \x40=
2207+ } vd={=d u \x40=
2208+ } ve={=e $x \x40=
2209+ } vf={=f $x @=
2210+ } |
2211+---
2212+name: heredoc-11
2213+description:
2214+ Check here documents with no or empty delimiter
2215+stdin:
2216+ x=u
2217+ va=<<
2218+ =a $x \x40=
2219+ <<
2220+ vb=<<''
2221+ =b $x \x40=
2222+
2223+ function foo {
2224+ vc=<<-
2225+ =c $x \x40=
2226+ <<
2227+ vd=<<-''
2228+ =d $x \x40=
2229+
2230+ }
2231+ typeset -f foo
2232+ foo
2233+ print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} |"
2234+expected-stdout:
2235+ function foo {
2236+ vc= <<-
2237+ =c $x \x40=
2238+ <<
2239+
2240+ vd= <<-""
2241+ =d $x \x40=
2242+
2243+
2244+ }
2245+ | va={=a u \x40=
2246+ } vb={=b $x \x40=
2247+ } vc={=c u \x40=
2248+ } vd={=d $x \x40=
2249+ } |
2250+---
2251+name: heredoc-comsub-1
2252+description:
2253+ Tests for here documents in COMSUB, taken from Austin ML
2254+stdin:
2255+ text=$(cat <<EOF
2256+ here is the text
2257+ EOF)
2258+ echo = $text =
2259+expected-stdout:
2260+ = here is the text =
2261+---
2262+name: heredoc-comsub-2
2263+description:
2264+ Tests for here documents in COMSUB, taken from Austin ML
2265+stdin:
2266+ unbalanced=$(cat <<EOF
2267+ this paren ) is a problem
2268+ EOF)
2269+ echo = $unbalanced =
2270+expected-stdout:
2271+ = this paren ) is a problem =
2272+---
2273+name: heredoc-comsub-3
2274+description:
2275+ Tests for here documents in COMSUB, taken from Austin ML
2276+stdin:
2277+ balanced=$(cat <<EOF
2278+ these parens ( ) are not a problem
2279+ EOF)
2280+ echo = $balanced =
2281+expected-stdout:
2282+ = these parens ( ) are not a problem =
2283+---
2284+name: heredoc-comsub-4
2285+description:
2286+ Tests for here documents in COMSUB, taken from Austin ML
2287+stdin:
2288+ balanced=$(cat <<EOF
2289+ these parens \( ) are a problem
2290+ EOF)
2291+ echo = $balanced =
2292+expected-stdout:
2293+ = these parens \( ) are a problem =
2294+---
2295+name: heredoc-subshell-1
2296+description:
2297+ Tests for here documents in subshells, taken from Austin ML
2298+stdin:
2299+ (cat <<EOF
2300+ some text
2301+ EOF)
2302+ echo end
2303+expected-stdout:
2304+ some text
2305+ end
2306+---
2307+name: heredoc-subshell-2
2308+description:
2309+ Tests for here documents in subshells, taken from Austin ML
2310+stdin:
2311+ (cat <<EOF
2312+ some text
2313+ EOF
2314+ )
2315+ echo end
2316+expected-stdout:
2317+ some text
2318+ end
2319+---
2320+name: heredoc-subshell-3
2321+description:
2322+ Tests for here documents in subshells, taken from Austin ML
2323+stdin:
2324+ (cat <<EOF; )
2325+ some text
2326+ EOF
2327+ echo end
2328+expected-stdout:
2329+ some text
2330+ end
2331+---
2332+name: heredoc-weird-1
2333+description:
2334+ Tests for here documents, taken from Austin ML
2335+ Documents current state in mksh, *NOT* necessarily correct!
2336+stdin:
2337+ cat <<END
2338+ hello
2339+ END\
2340+ END
2341+ END
2342+ echo end
2343+expected-stdout:
2344+ hello
2345+ ENDEND
2346+ end
2347+---
2348+name: heredoc-weird-2
2349+description:
2350+ Tests for here documents, taken from Austin ML
2351+stdin:
2352+ cat <<' END '
2353+ hello
2354+ END
2355+ echo end
2356+expected-stdout:
2357+ hello
2358+ end
2359+---
2360+name: heredoc-weird-4
2361+description:
2362+ Tests for here documents, taken from Austin ML
2363+ Documents current state in mksh, *NOT* necessarily correct!
2364+stdin:
2365+ cat <<END
2366+ hello\
2367+ END
2368+ END
2369+ echo end
2370+expected-stdout:
2371+ helloEND
2372+ end
2373+---
2374+name: heredoc-weird-5
2375+description:
2376+ Tests for here documents, taken from Austin ML
2377+ Documents current state in mksh, *NOT* necessarily correct!
2378+stdin:
2379+ cat <<END
2380+ hello
2381+ \END
2382+ END
2383+ echo end
2384+expected-stdout:
2385+ hello
2386+ \END
2387+ end
2388+---
20102389 name: heredoc-quoting-unsubst
20112390 description:
20122391 Check for correct handling of quoted characters in
@@ -2188,6 +2567,7 @@ description:
21882567 late. Heredoc in function, backgrounded call to function.
21892568 This check can fail on slow machines (<100 MHz), or Cygwin,
21902569 that's normal.
2570+need-pass: no
21912571 stdin:
21922572 TMPDIR=$PWD
21932573 # Background eval so main shell doesn't do parsing
@@ -2215,6 +2595,7 @@ expected-stdout:
22152595 name: history-basic
22162596 description:
22172597 See if we can test history at all
2598+need-ctty: yes
22182599 arguments: !-i!
22192600 env-setup: !ENV=./Env!HISTFILE=hist.file!
22202601 file-setup: file 644 "Env"
@@ -2231,6 +2612,7 @@ expected-stderr-pattern:
22312612 name: history-dups
22322613 description:
22332614 Verify duplicates and spaces are not entered
2615+need-ctty: yes
22342616 arguments: !-i!
22352617 env-setup: !ENV=./Env!HISTFILE=hist.file!
22362618 file-setup: file 644 "Env"
@@ -2251,6 +2633,7 @@ expected-stderr-pattern:
22512633 name: history-unlink
22522634 description:
22532635 Check if broken HISTFILEs do not cause trouble
2636+need-ctty: yes
22542637 arguments: !-i!
22552638 env-setup: !ENV=./Env!HISTFILE=foo/hist.file!
22562639 file-setup: file 644 "Env"
@@ -2268,11 +2651,12 @@ expected-stdout:
22682651 hi
22692652 1 echo hi
22702653 expected-stderr-pattern:
2271- /(.*cannot unlink HISTFILE.*\n)?X*$/
2654+ /(.*can't unlink HISTFILE.*\n)?X*$/
22722655 ---
22732656 name: history-e-minus-1
22742657 description:
22752658 Check if more recent command is executed
2659+need-ctty: yes
22762660 arguments: !-i!
22772661 env-setup: !ENV=./Env!HISTFILE=hist.file!
22782662 file-setup: file 644 "Env"
@@ -2292,6 +2676,7 @@ name: history-e-minus-2
22922676 description:
22932677 Check that repeated command is printed before command
22942678 is re-executed.
2679+need-ctty: yes
22952680 arguments: !-i!
22962681 env-setup: !ENV=./Env!HISTFILE=hist.file!
22972682 file-setup: file 644 "Env"
@@ -2311,6 +2696,7 @@ description:
23112696 fc -e - fails when there is no history
23122697 (ksh93 has a bug that causes this to fail)
23132698 (ksh88 loops on this)
2699+need-ctty: yes
23142700 arguments: !-i!
23152701 env-setup: !ENV=./Env!HISTFILE=hist.file!
23162702 file-setup: file 644 "Env"
@@ -2326,6 +2712,7 @@ expected-stderr-pattern:
23262712 name: history-e-minus-4
23272713 description:
23282714 Check if "fc -e -" command output goes to stdout.
2715+need-ctty: yes
23292716 arguments: !-i!
23302717 env-setup: !ENV=./Env!HISTFILE=hist.file!
23312718 file-setup: file 644 "Env"
@@ -2344,6 +2731,7 @@ expected-stderr-pattern:
23442731 name: history-e-minus-5
23452732 description:
23462733 fc is replaced in history by new command.
2734+need-ctty: yes
23472735 arguments: !-i!
23482736 env-setup: !ENV=./Env!HISTFILE=hist.file!
23492737 file-setup: file 644 "Env"
@@ -2369,6 +2757,7 @@ name: history-list-1
23692757 description:
23702758 List lists correct range
23712759 (ksh88 fails 'cause it lists the fc command)
2760+need-ctty: yes
23722761 arguments: !-i!
23732762 env-setup: !ENV=./Env!HISTFILE=hist.file!
23742763 file-setup: file 644 "Env"
@@ -2392,6 +2781,7 @@ description:
23922781 Lists oldest history if given pre-historic number
23932782 (ksh93 has a bug that causes this to fail)
23942783 (ksh88 fails 'cause it lists the fc command)
2784+need-ctty: yes
23952785 arguments: !-i!
23962786 env-setup: !ENV=./Env!HISTFILE=hist.file!
23972787 file-setup: file 644 "Env"
@@ -2414,6 +2804,7 @@ expected-stderr-pattern:
24142804 name: history-list-3
24152805 description:
24162806 Can give number 'options' to fc
2807+need-ctty: yes
24172808 arguments: !-i!
24182809 env-setup: !ENV=./Env!HISTFILE=hist.file!
24192810 file-setup: file 644 "Env"
@@ -2437,6 +2828,7 @@ expected-stderr-pattern:
24372828 name: history-list-4
24382829 description:
24392830 -1 refers to previous command
2831+need-ctty: yes
24402832 arguments: !-i!
24412833 env-setup: !ENV=./Env!HISTFILE=hist.file!
24422834 file-setup: file 644 "Env"
@@ -2459,6 +2851,7 @@ expected-stderr-pattern:
24592851 name: history-list-5
24602852 description:
24612853 List command stays in history
2854+need-ctty: yes
24622855 arguments: !-i!
24632856 env-setup: !ENV=./Env!HISTFILE=hist.file!
24642857 file-setup: file 644 "Env"
@@ -2485,6 +2878,7 @@ name: history-list-6
24852878 description:
24862879 HISTSIZE limits about of history kept.
24872880 (ksh88 fails 'cause it lists the fc command)
2881+need-ctty: yes
24882882 arguments: !-i!
24892883 env-setup: !ENV=./Env!HISTFILE=hist.file!HISTSIZE=3!
24902884 file-setup: file 644 "Env"
@@ -2510,6 +2904,7 @@ expected-stderr-pattern:
25102904 name: history-list-7
25112905 description:
25122906 fc allows too old/new errors in range specification
2907+need-ctty: yes
25132908 arguments: !-i!
25142909 env-setup: !ENV=./Env!HISTFILE=hist.file!HISTSIZE=3!
25152910 file-setup: file 644 "Env"
@@ -2536,6 +2931,7 @@ expected-stderr-pattern:
25362931 name: history-list-r-1
25372932 description:
25382933 test -r flag in history
2934+need-ctty: yes
25392935 arguments: !-i!
25402936 env-setup: !ENV=./Env!HISTFILE=hist.file!
25412937 file-setup: file 644 "Env"
@@ -2562,6 +2958,7 @@ expected-stderr-pattern:
25622958 name: history-list-r-2
25632959 description:
25642960 If first is newer than last, -r is implied.
2961+need-ctty: yes
25652962 arguments: !-i!
25662963 env-setup: !ENV=./Env!HISTFILE=hist.file!
25672964 file-setup: file 644 "Env"
@@ -2588,6 +2985,7 @@ expected-stderr-pattern:
25882985 name: history-list-r-3
25892986 description:
25902987 If first is newer than last, -r is cancelled.
2988+need-ctty: yes
25912989 arguments: !-i!
25922990 env-setup: !ENV=./Env!HISTFILE=hist.file!
25932991 file-setup: file 644 "Env"
@@ -2614,6 +3012,7 @@ expected-stderr-pattern:
26143012 name: history-subst-1
26153013 description:
26163014 Basic substitution
3015+need-ctty: yes
26173016 arguments: !-i!
26183017 env-setup: !ENV=./Env!HISTFILE=hist.file!
26193018 file-setup: file 644 "Env"
@@ -2632,6 +3031,7 @@ expected-stderr-pattern:
26323031 name: history-subst-2
26333032 description:
26343033 Does subst find previous command?
3034+need-ctty: yes
26353035 arguments: !-i!
26363036 env-setup: !ENV=./Env!HISTFILE=hist.file!
26373037 file-setup: file 644 "Env"
@@ -2650,6 +3050,7 @@ expected-stderr-pattern:
26503050 name: history-subst-3
26513051 description:
26523052 Does subst find previous command when no arguments given
3053+need-ctty: yes
26533054 arguments: !-i!
26543055 env-setup: !ENV=./Env!HISTFILE=hist.file!
26553056 file-setup: file 644 "Env"
@@ -2669,6 +3070,7 @@ name: history-subst-4
26693070 description:
26703071 Global substitutions work
26713072 (ksh88 and ksh93 do not have -g option)
3073+need-ctty: yes
26723074 arguments: !-i!
26733075 env-setup: !ENV=./Env!HISTFILE=hist.file!
26743076 file-setup: file 644 "Env"
@@ -2686,6 +3088,7 @@ name: history-subst-5
26863088 description:
26873089 Make sure searches don't find current (fc) command
26883090 (ksh88/ksh93 don't have the ? prefix thing so they fail this test)
3091+need-ctty: yes
26893092 arguments: !-i!
26903093 env-setup: !ENV=./Env!HISTFILE=hist.file!
26913094 file-setup: file 644 "Env"
@@ -2707,6 +3110,8 @@ description:
27073110 that prints no prompts). This is for oldish ed(1) which write
27083111 the character count to stdout.
27093112 category: stdout-ed
3113+need-ctty: yes
3114+need-pass: no
27103115 arguments: !-i!
27113116 env-setup: !ENV=./Env!HISTFILE=hist.file!
27123117 file-setup: file 644 "Env"
@@ -2729,6 +3134,8 @@ name: history-ed-2-old
27293134 description:
27303135 Correct command is edited when number given
27313136 category: stdout-ed
3137+need-ctty: yes
3138+need-pass: no
27323139 arguments: !-i!
27333140 env-setup: !ENV=./Env!HISTFILE=hist.file!
27343141 file-setup: file 644 "Env"
@@ -2760,6 +3167,8 @@ description:
27603167 (NOTE: adjusted for COMPLEX HISTORY compile time option)
27613168 (ksh88 fails 'cause it lists the fc command)
27623169 category: stdout-ed
3170+need-ctty: yes
3171+need-pass: no
27633172 arguments: !-i!
27643173 env-setup: !ENV=./Env!HISTFILE=hist.file!
27653174 file-setup: file 644 "Env"
@@ -2791,6 +3200,8 @@ description:
27913200 Basic (ed) editing works (assumes you have generic ed editor
27923201 that prints no prompts). This is for newish ed(1) and stderr.
27933202 category: !no-stderr-ed
3203+need-ctty: yes
3204+need-pass: no
27943205 arguments: !-i!
27953206 env-setup: !ENV=./Env!HISTFILE=hist.file!
27963207 file-setup: file 644 "Env"
@@ -2811,6 +3222,8 @@ name: history-ed-2
28113222 description:
28123223 Correct command is edited when number given
28133224 category: !no-stderr-ed
3225+need-ctty: yes
3226+need-pass: no
28143227 arguments: !-i!
28153228 env-setup: !ENV=./Env!HISTFILE=hist.file!
28163229 file-setup: file 644 "Env"
@@ -2838,6 +3251,8 @@ description:
28383251 Newly created multi line commands show up as single command
28393252 in history.
28403253 category: !no-stderr-ed
3254+need-ctty: yes
3255+need-pass: no
28413256 arguments: !-i!
28423257 env-setup: !ENV=./Env!HISTFILE=hist.file!
28433258 file-setup: file 644 "Env"
@@ -2943,23 +3358,6 @@ stdin:
29433358 expected-stdout:
29443359 <:>
29453360 ---
2946-name: IFS-space-colon-3
2947-description:
2948- Simple test, IFS=<white-space>:
2949- pdksh fails both of these tests
2950- not sure whether #2 is correct
2951-stdin:
2952- showargs() { for i; do echo -n " <$i>"; done; echo; }
2953- IFS="$IFS:"
2954- x=
2955- set --
2956- showargs "$x$@" 1
2957- showargs "$@$x" 2
2958-expected-fail: yes
2959-expected-stdout:
2960- <> <1>
2961- <> <2>
2962----
29633361 name: IFS-space-colon-4
29643362 description:
29653363 Simple test, IFS=<white-space>:
@@ -3051,6 +3449,7 @@ description:
30513449 Syntax errors in expressions and effects on bases
30523450 (interactive so errors don't cause exits)
30533451 (ksh88 fails this test - shell exits, even with -i)
3452+need-ctty: yes
30543453 arguments: !-i!
30553454 stdin:
30563455 PS1= # minimise prompt hassles
@@ -3227,6 +3626,127 @@ expected-stdout:
32273626 64
32283627 64
32293628 ---
3629+name: integer-base-check-flat
3630+description:
3631+ Check behaviour does not match POSuX, because a not type-safe
3632+ scripting language has *no* business interpreting "010" as octal
3633+stdin:
3634+ echo :$((10)).$((010)).$((0x10)).
3635+expected-stdout:
3636+ :10.10.16.
3637+---
3638+name: integer-base-check-numeric-from
3639+description:
3640+ Check behaviour for base one to 36, and that 37 errors out
3641+stdin:
3642+ echo 1:$((1#1))0.
3643+ i=1
3644+ while (( ++i <= 36 )); do
3645+ eval 'echo '$i':$(('$i'#10)).'
3646+ done
3647+ echo 37:$($__progname -c 'echo $((37#10))').$?:
3648+expected-stdout:
3649+ 1:490.
3650+ 2:2.
3651+ 3:3.
3652+ 4:4.
3653+ 5:5.
3654+ 6:6.
3655+ 7:7.
3656+ 8:8.
3657+ 9:9.
3658+ 10:10.
3659+ 11:11.
3660+ 12:12.
3661+ 13:13.
3662+ 14:14.
3663+ 15:15.
3664+ 16:16.
3665+ 17:17.
3666+ 18:18.
3667+ 19:19.
3668+ 20:20.
3669+ 21:21.
3670+ 22:22.
3671+ 23:23.
3672+ 24:24.
3673+ 25:25.
3674+ 26:26.
3675+ 27:27.
3676+ 28:28.
3677+ 29:29.
3678+ 30:30.
3679+ 31:31.
3680+ 32:32.
3681+ 33:33.
3682+ 34:34.
3683+ 35:35.
3684+ 36:36.
3685+ 37:.0:
3686+expected-stderr-pattern:
3687+ /.*bad number '37#10'/
3688+---
3689+name: integer-base-check-numeric-to
3690+description:
3691+ Check behaviour for base one to 36, and that 37 errors out
3692+stdin:
3693+ i=0
3694+ while (( ++i <= 37 )); do
3695+ typeset -Uui$i x=0x40
3696+ eval "typeset -i10 y=$x"
3697+ print $i:$x.$y.
3698+ done
3699+expected-stdout:
3700+ 1:1#@.64.
3701+ 2:2#1000000.64.
3702+ 3:3#2101.64.
3703+ 4:4#1000.64.
3704+ 5:5#224.64.
3705+ 6:6#144.64.
3706+ 7:7#121.64.
3707+ 8:8#100.64.
3708+ 9:9#71.64.
3709+ 10:64.64.
3710+ 11:11#59.64.
3711+ 12:12#54.64.
3712+ 13:13#4C.64.
3713+ 14:14#48.64.
3714+ 15:15#44.64.
3715+ 16:16#40.64.
3716+ 17:17#3D.64.
3717+ 18:18#3A.64.
3718+ 19:19#37.64.
3719+ 20:20#34.64.
3720+ 21:21#31.64.
3721+ 22:22#2K.64.
3722+ 23:23#2I.64.
3723+ 24:24#2G.64.
3724+ 25:25#2E.64.
3725+ 26:26#2C.64.
3726+ 27:27#2A.64.
3727+ 28:28#28.64.
3728+ 29:29#26.64.
3729+ 30:30#24.64.
3730+ 31:31#22.64.
3731+ 32:32#20.64.
3732+ 33:33#1V.64.
3733+ 34:34#1U.64.
3734+ 35:35#1T.64.
3735+ 36:36#1S.64.
3736+ 37:36#1S.64.
3737+expected-stderr-pattern:
3738+ /.*bad integer base: 37/
3739+---
3740+name: integer-arithmetic-span
3741+description:
3742+ Check wraparound and size that is defined in mksh
3743+stdin:
3744+ echo s:$((2147483647+1)).$(((2147483647*2)+1)).$(((2147483647*2)+2)).
3745+ echo u:$((#2147483647+1)).$((#(2147483647*2)+1)).$((#(2147483647*2)+2)).
3746+expected-stdout:
3747+ s:-2147483648.-1.0.
3748+ u:2147483648.4294967295.0.
3749+---
32303750 name: lineno-stdin
32313751 description:
32323752 See if $LINENO is updated and can be modified.
@@ -3346,6 +3866,26 @@ expected-stdout:
33463866 line <6>
33473867 expected-exit: 1
33483868 ---
3869+name: unknown-trap
3870+description:
3871+ Ensure unknown traps are not a syntax error
3872+stdin:
3873+ (
3874+ trap "echo trap 1 executed" UNKNOWNSIGNAL || echo "foo"
3875+ echo =1
3876+ trap "echo trap 2 executed" UNKNOWNSIGNAL EXIT 999999 FNORD
3877+ echo = $?
3878+ ) 2>&1 | sed "s^${__progname%.exe}\.*e*x*e*: <stdin>\[[0-9]*]PROG"
3879+expected-stdout:
3880+ PROG: trap: bad signal 'UNKNOWNSIGNAL'
3881+ foo
3882+ =1
3883+ PROG: trap: bad signal 'UNKNOWNSIGNAL'
3884+ PROG: trap: bad signal '999999'
3885+ PROG: trap: bad signal 'FNORD'
3886+ = 3
3887+ trap 2 executed
3888+---
33493889 name: read-IFS-1
33503890 description:
33513891 Simple test, default IFS
@@ -3372,6 +3912,74 @@ stdin:
33723912 expected-stdout:
33733913 [abc]
33743914 ---
3915+name: read-regress-1
3916+description:
3917+ Check a regression of read
3918+file-setup: file 644 "foo"
3919+ foo bar
3920+ baz
3921+ blah
3922+stdin:
3923+ while read a b c; do
3924+ read d
3925+ break
3926+ done <foo
3927+ echo "<$a|$b|$c><$d>"
3928+expected-stdout:
3929+ <foo|bar|><baz>
3930+---
3931+name: read-delim-1
3932+description:
3933+ Check read with delimiters
3934+stdin:
3935+ emit() {
3936+ print -n 'foo bar\tbaz\nblah \0blub\tblech\nmyok meck \0'
3937+ }
3938+ emit | while IFS= read -d "" foo; do print -r -- "<$foo>"; done
3939+ emit | while read -d "" foo; do print -r -- "<$foo>"; done
3940+ emit | while read -d "eh?" foo; do print -r -- "<$foo>"; done
3941+expected-stdout:
3942+ <foo bar baz
3943+ blah >
3944+ <blub blech
3945+ myok meck >
3946+ <foo bar baz
3947+ blah>
3948+ <blub blech
3949+ myok meck>
3950+ <foo bar baz
3951+ blah blub bl>
3952+ <ch
3953+ myok m>
3954+---
3955+name: read-ext-1
3956+description:
3957+ Check read with number of bytes specified, and -A
3958+stdin:
3959+ print 'foo\nbar' >x1
3960+ print -n x >x2
3961+ print 'foo\\ bar baz' >x3
3962+ x1a=u; read x1a <x1
3963+ x1b=u; read -N-1 x1b <x1
3964+ x2a=u; read x2a <x2; r2a=$?
3965+ x2b=u; read -N2 x2c <x2; r2b=$?
3966+ x2c=u; read -n2 x2c <x2; r2c=$?
3967+ x3a=u; read -A x3a <x3
3968+ print -r "x1a=<$x1a>"
3969+ print -r "x1b=<$x1b>"
3970+ print -r "x2a=$r2a<$x2a>"
3971+ print -r "x2b=$r2b<$x2b>"
3972+ print -r "x2c=$r2c<$x2c>"
3973+ print -r "x3a=<${x3a[0]}|${x3a[1]}|${x3a[2]}>"
3974+expected-stdout:
3975+ x1a=<foo>
3976+ x1b=<foo
3977+ bar>
3978+ x2a=1<x>
3979+ x2b=1<u>
3980+ x2c=0<x>
3981+ x3a=<foo bar|baz|>
3982+---
33753983 name: regression-1
33763984 description:
33773985 Lex array code had problems with this.
@@ -3782,6 +4390,9 @@ name: regression-33
37824390 description:
37834391 Does umask print a leading 0 when umask is 3 digits?
37844392 stdin:
4393+ # on MiNT, the first umask call seems to fail
4394+ umask 022
4395+ # now, the test proper
37854396 umask 222
37864397 umask
37874398 expected-stdout:
@@ -3887,12 +4498,15 @@ name: regression-42
38874498 description:
38884499 Can't use command line assignments to assign readonly parameters.
38894500 stdin:
4501+ print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
4502+ 'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
4503+ done >env; chmod +x env; PATH=.:$PATH
38904504 foo=bar
38914505 readonly foo
38924506 foo=stuff env | grep '^foo'
38934507 expected-exit: e != 0
38944508 expected-stderr-pattern:
3895- /.*read *only.*/
4509+ /read-only/
38964510 ---
38974511 name: regression-43
38984512 description:
@@ -4002,10 +4616,11 @@ name: regression-50
40024616 description:
40034617 Check that aliases do not use continuation prompt after trailing
40044618 semi-colon.
4005-file-setup: file 644 "env"
4619+file-setup: file 644 "envf"
40064620 PS1=Y
40074621 PS2=X
4008-env-setup: !ENV=./env!
4622+env-setup: !ENV=./envf!
4623+need-ctty: yes
40094624 arguments: !-i!
40104625 stdin:
40114626 alias foo='echo hi ; '
@@ -4031,11 +4646,12 @@ expected-stdout:
40314646 name: regression-52
40324647 description:
40334648 Check that globbing works in pipelined commands
4034-file-setup: file 644 "env"
4649+file-setup: file 644 "envf"
40354650 PS1=P
40364651 file-setup: file 644 "abc"
40374652 stuff
4038-env-setup: !ENV=./env!
4653+env-setup: !ENV=./envf!
4654+need-ctty: yes
40394655 arguments: !-i!
40404656 stdin:
40414657 sed 's/^/X /' < ab*
@@ -4369,6 +4985,101 @@ stdin:
43694985 time
43704986 }
43714987 ---
4988+name: regression-65
4989+description:
4990+ check for a regression with sleep builtin and signal mask
4991+category: !nojsig
4992+time-limit: 3
4993+stdin:
4994+ sleep 1
4995+ echo blub |&
4996+ while read -p line; do :; done
4997+ echo ok
4998+expected-stdout:
4999+ ok
5000+---
5001+name: regression-66
5002+description:
5003+ Check that quoting is sane
5004+stdin:
5005+ ac_space=' '
5006+ ac_newline='
5007+ '
5008+ set | grep ^ac_ |&
5009+ set -A lines
5010+ while IFS= read -pr line; do
5011+ if [[ $line = *space* ]]; then
5012+ lines[0]=$line
5013+ else
5014+ lines[1]=$line
5015+ fi
5016+ done
5017+ for line in "${lines[@]}"; do
5018+ print -r -- "$line"
5019+ done
5020+expected-stdout:
5021+ ac_space=' '
5022+ ac_newline=$'\n'
5023+---
5024+name: readonly-0
5025+description:
5026+ Ensure readonly is honoured for assignments and unset
5027+stdin:
5028+ "$__progname" -c 'u=x; echo $? $u .' || echo aborted, $?
5029+ echo =
5030+ "$__progname" -c 'readonly u; u=x; echo $? $u .' || echo aborted, $?
5031+ echo =
5032+ "$__progname" -c 'u=x; readonly u; unset u; echo $? $u .' || echo aborted, $?
5033+expected-stdout:
5034+ 0 x .
5035+ =
5036+ aborted, 2
5037+ =
5038+ 1 x .
5039+expected-stderr-pattern:
5040+ /read-only/
5041+---
5042+name: readonly-1
5043+description:
5044+ http://austingroupbugs.net/view.php?id=367 for export
5045+stdin:
5046+ "$__progname" -c 'readonly foo; export foo=a; echo $?' || echo aborted, $?
5047+expected-stdout:
5048+ aborted, 2
5049+expected-stderr-pattern:
5050+ /read-only/
5051+---
5052+name: readonly-2a
5053+description:
5054+ Check that getopts works as intended, for readonly-2b to be valid
5055+stdin:
5056+ "$__progname" -c 'set -- -a b; getopts a c; echo $? $c .; getopts a c; echo $? $c .' || echo aborted, $?
5057+expected-stdout:
5058+ 0 a .
5059+ 1 ? .
5060+---
5061+name: readonly-2b
5062+description:
5063+ http://austingroupbugs.net/view.php?id=367 for getopts
5064+stdin:
5065+ "$__progname" -c 'readonly c; set -- -a b; getopts a c; echo $? $c .' || echo aborted, $?
5066+expected-stdout:
5067+ 2 .
5068+expected-stderr-pattern:
5069+ /read-only/
5070+---
5071+name: readonly-3
5072+description:
5073+ http://austingroupbugs.net/view.php?id=367 for read
5074+stdin:
5075+ echo x | "$__progname" -c 'read s; echo $? $s .' || echo aborted, $?
5076+ echo y | "$__progname" -c 'readonly s; read s; echo $? $s .' || echo aborted, $?
5077+expected-stdout:
5078+ 0 x .
5079+ 2 .
5080+expected-stderr-pattern:
5081+ /read-only/
5082+---
43725083 name: syntax-1
43735084 description:
43745085 Check that lone ampersand is a syntax error
@@ -4472,6 +5183,9 @@ name: xxx-exec-environment-1
44725183 description:
44735184 Check to see if exec sets it's environment correctly
44745185 stdin:
5186+ print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
5187+ 'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
5188+ done >env; chmod +x env; PATH=.:$PATH
44755189 FOO=bar exec env
44765190 expected-stdout-pattern:
44775191 /(^|.*\n)FOO=bar\n/
@@ -4481,9 +5195,11 @@ description:
44815195 Check to make sure exec doesn't change environment if a program
44825196 isn't exec-ed
44835197 stdin:
4484- sortprog=$(whence -p sort) || sortprog=cat
4485- env | $sortprog | grep -v '^RANDOM=' >bar1
4486- FOO=bar exec; env | $sortprog | grep -v '^RANDOM=' >bar2
5198+ print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
5199+ 'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
5200+ done >env; chmod +x env; PATH=.:$PATH
5201+ env >bar1
5202+ FOO=bar exec; env >bar2
44875203 cmp -s bar1 bar2
44885204 ---
44895205 name: exec-function-environment-1
@@ -4567,6 +5283,7 @@ expected-stdout:
45675283 name: xxx-exec-1
45685284 description:
45695285 Check that exec exits for built-ins
5286+need-ctty: yes
45705287 arguments: !-i!
45715288 stdin:
45725289 exec echo hi
@@ -4614,6 +5331,7 @@ expected-stdout:
46145331 name: xxx-status-1
46155332 description:
46165333 Check that blank lines don't clear $?
5334+need-ctty: yes
46175335 arguments: !-i!
46185336 stdin:
46195337 (exit 1)
@@ -4701,29 +5419,38 @@ name: exit-err-1
47015419 description:
47025420 Check some "exit on error" conditions
47035421 stdin:
5422+ print '#!'"$__progname"'\nexec "$1"' >env
5423+ print '#!'"$__progname"'\nexit 1' >false
5424+ chmod +x env false
5425+ PATH=.:$PATH
47045426 set -ex
4705- /usr/bin/env false && echo something
5427+ env false && echo something
47065428 echo END
47075429 expected-stdout:
47085430 END
47095431 expected-stderr:
4710- + /usr/bin/env false
5432+ + env false
47115433 + echo END
47125434 ---
47135435 name: exit-err-2
47145436 description:
47155437 Check some "exit on error" edge conditions (POSIXly)
47165438 stdin:
5439+ print '#!'"$__progname"'\nexec "$1"' >env
5440+ print '#!'"$__progname"'\nexit 1' >false
5441+ print '#!'"$__progname"'\nexit 0' >true
5442+ chmod +x env false
5443+ PATH=.:$PATH
47175444 set -ex
4718- if /usr/bin/env true; then
4719- /usr/bin/env false && echo something
5445+ if env true; then
5446+ env false && echo something
47205447 fi
47215448 echo END
47225449 expected-stdout:
47235450 END
47245451 expected-stderr:
4725- + /usr/bin/env true
4726- + /usr/bin/env false
5452+ + env true
5453+ + env false
47275454 + echo END
47285455 ---
47295456 name: exit-err-3
@@ -4845,6 +5572,16 @@ expected-stdout:
48455572 E 0
48465573 F 0
48475574 ---
5575+name: exit-trap-1
5576+description:
5577+ Check that "exit" with no arguments behaves SUSv4 conformant.
5578+stdin:
5579+ trap 'echo hi; exit' EXIT
5580+ exit 9
5581+expected-stdout:
5582+ hi
5583+expected-exit: 9
5584+---
48485585 name: test-stlt-1
48495586 description:
48505587 Check that test also can handle string1 < string2 etc.
@@ -4981,6 +5718,7 @@ description:
49815718 Part 2: verify mkshrc can be read (interactive shells)
49825719 file-setup: file 644 ".mkshrc"
49835720 FNORD=42
5721+need-ctty: yes
49845722 arguments: !-i!
49855723 env-setup: !HOME=.!ENV=!PS1=!
49865724 stdin:
@@ -5104,6 +5842,7 @@ expected-stdout:
51045842 name: pipeline-2
51055843 description:
51065844 check that co-processes work with TCOMs, TPIPEs and TPARENs
5845+category: !nojsig
51075846 stdin:
51085847 "$__progname" -c 'i=100; echo hi |& while read -p line; do echo "$((i++)) $line"; done'
51095848 "$__progname" -c 'i=200; echo hi | cat |& while read -p line; do echo "$((i++)) $line"; done'
@@ -5113,10 +5852,33 @@ expected-stdout:
51135852 200 hi
51145853 300 hi
51155854 ---
5855+name: pipeline-3
5856+description:
5857+ Check that PIPESTATUS does what it's supposed to
5858+stdin:
5859+ echo 1 $PIPESTATUS .
5860+ echo 2 ${PIPESTATUS[0]} .
5861+ echo 3 ${PIPESTATUS[1]} .
5862+ (echo x; exit 12) | (cat; exit 23) | (cat; exit 42)
5863+ echo 5 $? , $PIPESTATUS , ${PIPESTATUS[0]} , ${PIPESTATUS[1]} , ${PIPESTATUS[2]} , ${PIPESTATUS[3]} .
5864+ echo 6 ${PIPESTATUS[0]} .
5865+ set | fgrep PIPESTATUS
5866+ echo 8 $(set | fgrep PIPESTATUS) .
5867+expected-stdout:
5868+ 1 0 .
5869+ 2 0 .
5870+ 3 .
5871+ x
5872+ 5 42 , 12 , 12 , 23 , 42 , .
5873+ 6 0 .
5874+ PIPESTATUS[0]=0
5875+ 8 PIPESTATUS[0]=0 PIPESTATUS[1]=0 .
5876+---
51165877 name: persist-history-1
51175878 description:
51185879 Check if persistent history saving works
51195880 category: !no-histfile
5881+need-ctty: yes
51205882 arguments: !-i!
51215883 env-setup: !ENV=./Env!HISTFILE=hist.file!
51225884 file-setup: file 644 "Env"
@@ -5128,17 +5890,51 @@ expected-stdout-pattern:
51285890 expected-stderr-pattern:
51295891 /^X*$/
51305892 ---
5131-name: typeset-padding-1
5893+name: typeset-1
51325894 description:
5133- Check if left/right justification works as per TFM
5895+ Check that global does what typeset is supposed to do
51345896 stdin:
5135- typeset -L10 ln=0hall0
5136- typeset -R10 rn=0hall0
5137- typeset -ZL10 lz=0hall0
5138- typeset -ZR10 rz=0hall0
5139- typeset -Z10 rx=" hallo "
5140- echo "<$ln> <$rn> <$lz> <$rz> <$rx>"
5141-expected-stdout:
5897+ set -A arrfoo 65
5898+ foo() {
5899+ global -Uui16 arrfoo[*]
5900+ }
5901+ echo before ${arrfoo[0]} .
5902+ foo
5903+ echo after ${arrfoo[0]} .
5904+ set -A arrbar 65
5905+ bar() {
5906+ echo inside before ${arrbar[0]} .
5907+ arrbar[0]=97
5908+ echo inside changed ${arrbar[0]} .
5909+ global -Uui16 arrbar[*]
5910+ echo inside typeset ${arrbar[0]} .
5911+ arrbar[0]=48
5912+ echo inside changed ${arrbar[0]} .
5913+ }
5914+ echo before ${arrbar[0]} .
5915+ bar
5916+ echo after ${arrbar[0]} .
5917+expected-stdout:
5918+ before 65 .
5919+ after 16#41 .
5920+ before 65 .
5921+ inside before 65 .
5922+ inside changed 97 .
5923+ inside typeset 16#61 .
5924+ inside changed 16#30 .
5925+ after 16#30 .
5926+---
5927+name: typeset-padding-1
5928+description:
5929+ Check if left/right justification works as per TFM
5930+stdin:
5931+ typeset -L10 ln=0hall0
5932+ typeset -R10 rn=0hall0
5933+ typeset -ZL10 lz=0hall0
5934+ typeset -ZR10 rz=0hall0
5935+ typeset -Z10 rx=" hallo "
5936+ echo "<$ln> <$rn> <$lz> <$rz> <$rx>"
5937+expected-stdout:
51425938 <0hall0 > < 0hall0> <hall0 > <00000hall0> <0000 hallo>
51435939 ---
51445940 name: typeset-padding-2
@@ -5208,7 +6004,7 @@ expected-stdout:
52086004 mit
52096005 ohne
52106006 =
5211- : mit
6007+ : ohne
52126008 ---
52136009 name: utf8bom-2
52146010 description:
@@ -5216,7 +6012,8 @@ description:
52166012 XXX if the OS can already execute them, we lose
52176013 note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose
52186014 note: Ultrix perl5 t4 returns 65280 (exit-code 255) and no text
5219-category: !os:cygwin,!os:uwin-nt,!os:ultrix,!smksh
6015+need-pass: no
6016+category: !os:cygwin,!os:msys,!os:ultrix,!os:uwin-nt,!smksh
52206017 env-setup: !FOO=BAR!
52216018 stdin:
52226019 print '#!'"$__progname"'\nprint "1 a=$ENV{FOO}";' >t1
@@ -5239,12 +6036,17 @@ expected-stderr-pattern:
52396036 name: utf8bom-3
52406037 description:
52416038 Reading the UTF-8 BOM should enable the utf8-mode flag
6039+ (temporarily for COMSUBs)
52426040 stdin:
52436041 "$__progname" -c ':; if [[ $- = *U* ]]; then echo 1 on; else echo 1 off; fi'
52446042 "$__progname" -c ':; if [[ $- = *U* ]]; then echo 2 on; else echo 2 off; fi'
6043+ "$__progname" -c 'if [[ $- = *U* ]]; then echo 3 on; else echo 3 off; fi; x=$(:; if [[ $- = *U* ]]; then echo 4 on; else echo 4 off; fi); echo $x; if [[ $- = *U* ]]; then echo 5 on; else echo 5 off; fi'
52456044 expected-stdout:
52466045 1 off
52476046 2 on
6047+ 3 off
6048+ 4 on
6049+ 5 off
52486050 ---
52496051 name: utf8opt-1a
52506052 description:
@@ -5281,7 +6083,9 @@ description:
52816083 -DMKSH_ASSUME_UTF8=1 => not expected, please investigate
52826084 -UMKSH_ASSUME_UTF8 => not expected, but if your OS is old,
52836085 try passing HAVE_SETLOCALE_CTYPE=0 to Build.sh
5284-category: !os:hpux
6086+need-pass: no
6087+category: !os:hpux,!os:msys
6088+need-ctty: yes
52856089 arguments: !-i!
52866090 env-setup: !PS1=!PS2=!LC_CTYPE=en_US.UTF-8!
52876091 stdin:
@@ -5300,6 +6104,7 @@ description:
53006104 Check that the utf8-mode flag is set at interactive startup
53016105 Expected failure if -DMKSH_ASSUME_UTF8=0
53026106 category: os:hpux
6107+need-ctty: yes
53036108 arguments: !-i!
53046109 env-setup: !PS1=!PS2=!LC_CTYPE=en_US.utf8!
53056110 stdin:
@@ -5313,29 +6118,40 @@ expected-stdout:
53136118 expected-stderr-pattern:
53146119 /(# )*/
53156120 ---
5316-name: utf8opt-3
6121+name: utf8opt-3a
53176122 description:
53186123 Ensure ±U on the command line is honoured
5319- (this test may pass falsely depending on CPPFLAGS)
6124+ (these two tests may pass falsely depending on CPPFLAGS)
53206125 stdin:
53216126 export i=0
53226127 code='if [[ $- = *U* ]]; then echo $i on; else echo $i off; fi'
53236128 let i++; "$__progname" -U -c "$code"
53246129 let i++; "$__progname" +U -c "$code"
6130+ echo $((++i)) done
6131+expected-stdout:
6132+ 1 on
6133+ 2 off
6134+ 3 done
6135+---
6136+name: utf8opt-3b
6137+description:
6138+ Ensure ±U on the command line is honoured, interactive shells
6139+need-ctty: yes
6140+stdin:
6141+ export i=0
6142+ code='if [[ $- = *U* ]]; then echo $i on; else echo $i off; fi'
53256143 let i++; "$__progname" -U -ic "$code"
53266144 let i++; "$__progname" +U -ic "$code"
53276145 echo $((++i)) done
53286146 expected-stdout:
53296147 1 on
53306148 2 off
5331- 3 on
5332- 4 off
5333- 5 done
6149+ 3 done
53346150 ---
53356151 name: aliases-1
53366152 description:
53376153 Check if built-in shell aliases are okay
5338-category: !arge
6154+category: !android,!arge
53396155 stdin:
53406156 alias
53416157 typeset -f
@@ -5351,13 +6167,14 @@ expected-stdout:
53516167 nohup='nohup '
53526168 r='fc -e -'
53536169 source='PATH=$PATH:. command .'
6170+ stop='kill -STOP'
53546171 suspend='kill -STOP $$'
53556172 type='whence -v'
53566173 ---
53576174 name: aliases-1-hartz4
53586175 description:
53596176 Check if built-in shell aliases are okay
5360-category: arge
6177+category: android,arge
53616178 stdin:
53626179 alias
53636180 typeset -f
@@ -5391,7 +6208,6 @@ name: aliases-3a
53916208 description:
53926209 Check if running as sh disables built-in aliases (except a few)
53936210 category: disabled
5394-arguments: !-o!sh!
53956211 stdin:
53966212 cp "$__progname" sh
53976213 ./sh -c 'alias; typeset -f'
@@ -5403,7 +6219,7 @@ expected-stdout:
54036219 name: aliases-2b
54046220 description:
54056221 Check if “set -o sh” does not influence built-in aliases
5406-category: !arge
6222+category: !android,!arge
54076223 arguments: !-o!sh!
54086224 stdin:
54096225 alias
@@ -5420,14 +6236,14 @@ expected-stdout:
54206236 nohup='nohup '
54216237 r='fc -e -'
54226238 source='PATH=$PATH:. command .'
6239+ stop='kill -STOP'
54236240 suspend='kill -STOP $$'
54246241 type='whence -v'
54256242 ---
54266243 name: aliases-3b
54276244 description:
54286245 Check if running as sh does not influence built-in aliases
5429-category: !arge
5430-arguments: !-o!sh!
6246+category: !android,!arge
54316247 stdin:
54326248 cp "$__progname" sh
54336249 ./sh -c 'alias; typeset -f'
@@ -5444,13 +6260,14 @@ expected-stdout:
54446260 nohup='nohup '
54456261 r='fc -e -'
54466262 source='PATH=$PATH:. command .'
6263+ stop='kill -STOP'
54476264 suspend='kill -STOP $$'
54486265 type='whence -v'
54496266 ---
54506267 name: aliases-2b-hartz4
54516268 description:
54526269 Check if “set -o sh” does not influence built-in aliases
5453-category: arge
6270+category: android,arge
54546271 arguments: !-o!sh!
54556272 stdin:
54566273 alias
@@ -5472,8 +6289,7 @@ expected-stdout:
54726289 name: aliases-3b-hartz4
54736290 description:
54746291 Check if running as sh does not influence built-in aliases
5475-category: arge
5476-arguments: !-o!sh!
6292+category: android,arge
54776293 stdin:
54786294 cp "$__progname" sh
54796295 ./sh -c 'alias; typeset -f'
@@ -5528,6 +6344,17 @@ stdin:
55286344 expected-stdout:
55296345 makro
55306346 ---
6347+name: aliases-funcdef-4
6348+description:
6349+ Functions should only take over if actually being defined
6350+stdin:
6351+ alias local
6352+ :|| local() { :; }
6353+ alias local
6354+expected-stdout:
6355+ local=typeset
6356+ local=typeset
6357+---
55316358 name: arrays-1
55326359 description:
55336360 Check if Korn Shell arrays work as expected
@@ -5538,10 +6365,9 @@ stdin:
55386365 expected-stdout:
55396366 5|a|$v|c d|$v|b|
55406367 ---
5541-name: arrays-2
6368+name: arrays-2a
55426369 description:
55436370 Check if bash-style arrays work as expected
5544-category: !smksh
55456371 stdin:
55466372 v="c d"
55476373 foo=(a \$v "$v" '$v' b)
@@ -5549,6 +6375,34 @@ stdin:
55496375 expected-stdout:
55506376 5|a|$v|c d|$v|b|
55516377 ---
6378+name: arrays-2b
6379+description:
6380+ Check if bash-style arrays work as expected, with newlines
6381+stdin:
6382+ print '#!'"$__progname"'\nfor x in "$@"; do print -nr -- "$x|"; done' >pfp
6383+ chmod +x pfp
6384+ test -n "$ZSH_VERSION" && setopt KSH_ARRAYS
6385+ v="e f"
6386+ foo=(a
6387+ bc
6388+ d \$v "$v" '$v' g
6389+ )
6390+ ./pfp "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo
6391+ foo=(a\
6392+ bc
6393+ d \$v "$v" '$v' g
6394+ )
6395+ ./pfp "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo
6396+ foo=(a\
6397+ bc\\
6398+ d \$v "$v" '$v'
6399+ g)
6400+ ./pfp "${#foo[*]}" "${foo[0]}" "${foo[1]}" "${foo[2]}" "${foo[3]}" "${foo[4]}" "${foo[5]}" "${foo[6]}"; echo
6401+expected-stdout:
6402+ 7|a|bc|d|$v|e f|$v|g|
6403+ 7|a|bc|d|$v|e f|$v|g|
6404+ 6|abc\|d|$v|e f|$v|g||
6405+---
55526406 name: arrays-3
55536407 description:
55546408 Check if array bounds are uint32_t
@@ -5566,7 +6420,6 @@ expected-stdout:
55666420 name: arrays-4
55676421 description:
55686422 Check if Korn Shell arrays with specified indices work as expected
5569-category: !smksh
55706423 stdin:
55716424 v="c d"
55726425 set -A foo -- [1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b
@@ -5577,7 +6430,6 @@ expected-stdout:
55776430 name: arrays-5
55786431 description:
55796432 Check if bash-style arrays with specified indices work as expected
5580-category: !smksh
55816433 stdin:
55826434 v="c d"
55836435 foo=([1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b)
@@ -5743,6 +6595,366 @@ expected-stdout:
57436595 2g 009 .
57446596 2h 00001 00002 .
57456597 ---
6598+name: arrays-9a
6599+description:
6600+ Check that we can concatenate arrays
6601+stdin:
6602+ unset foo; foo=(bar); foo+=(baz); echo 1 ${!foo[*]} : ${foo[*]} .
6603+ unset foo; foo=(foo bar); foo+=(baz); echo 2 ${!foo[*]} : ${foo[*]} .
6604+ unset foo; foo=([2]=foo [0]=bar); foo+=(baz [5]=quux); echo 3 ${!foo[*]} : ${foo[*]} .
6605+expected-stdout:
6606+ 1 0 1 : bar baz .
6607+ 2 0 1 2 : foo bar baz .
6608+ 3 0 2 3 5 : bar foo baz quux .
6609+---
6610+name: arrays-9b
6611+description:
6612+ Check that we can concatenate parameters too
6613+stdin:
6614+ unset foo; foo=bar; foo+=baz; echo 1 $foo .
6615+ unset foo; typeset -i16 foo=10; foo+=20; echo 2 $foo .
6616+expected-stdout:
6617+ 1 barbaz .
6618+ 2 16#a20 .
6619+---
6620+name: arrassign-basic
6621+description:
6622+ Check basic whitespace conserving properties of wdarrassign
6623+stdin:
6624+ a=($(echo a b))
6625+ b=($(echo "a b"))
6626+ c=("$(echo "a b")")
6627+ d=("$(echo a b)")
6628+ a+=($(echo c d))
6629+ b+=($(echo "c d"))
6630+ c+=("$(echo "c d")")
6631+ d+=("$(echo c d)")
6632+ echo ".a:${a[0]}.${a[1]}.${a[2]}.${a[3]}:"
6633+ echo ".b:${b[0]}.${b[1]}.${b[2]}.${b[3]}:"
6634+ echo ".c:${c[0]}.${c[1]}.${c[2]}.${c[3]}:"
6635+ echo ".d:${d[0]}.${d[1]}.${d[2]}.${d[3]}:"
6636+expected-stdout:
6637+ .a:a.b.c.d:
6638+ .b:a.b.c.d:
6639+ .c:a b.c d..:
6640+ .d:a b.c d..:
6641+---
6642+name: arrassign-fnc-none
6643+description:
6644+ Check locality of array access inside a function
6645+stdin:
6646+ function fn {
6647+ x+=(f)
6648+ echo ".fn:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6649+ }
6650+ function rfn {
6651+ if [[ -n $BASH_VERSION ]]; then
6652+ y=()
6653+ else
6654+ set -A y
6655+ fi
6656+ y+=(f)
6657+ echo ".rfn:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6658+ }
6659+ x=(m m)
6660+ y=(m m)
6661+ echo ".f0:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6662+ fn
6663+ echo ".f1:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6664+ fn
6665+ echo ".f2:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6666+ echo ".rf0:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6667+ rfn
6668+ echo ".rf1:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6669+ rfn
6670+ echo ".rf2:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6671+expected-stdout:
6672+ .f0:m.m..:
6673+ .fn:m.m.f.:
6674+ .f1:m.m.f.:
6675+ .fn:m.m.f.f:
6676+ .f2:m.m.f.f:
6677+ .rf0:m.m..:
6678+ .rfn:f...:
6679+ .rf1:f...:
6680+ .rfn:f...:
6681+ .rf2:f...:
6682+---
6683+name: arrassign-fnc-local
6684+description:
6685+ Check locality of array access inside a function
6686+ with the bash/mksh/ksh93 local/typeset keyword
6687+ (note: ksh93 has no local; typeset works only in FKSH)
6688+stdin:
6689+ function fn {
6690+ typeset x
6691+ x+=(f)
6692+ echo ".fn:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6693+ }
6694+ function rfn {
6695+ if [[ -n $BASH_VERSION ]]; then
6696+ y=()
6697+ else
6698+ set -A y
6699+ fi
6700+ typeset y
6701+ y+=(f)
6702+ echo ".rfn:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6703+ }
6704+ function fnr {
6705+ typeset z
6706+ if [[ -n $BASH_VERSION ]]; then
6707+ z=()
6708+ else
6709+ set -A z
6710+ fi
6711+ z+=(f)
6712+ echo ".fnr:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
6713+ }
6714+ x=(m m)
6715+ y=(m m)
6716+ z=(m m)
6717+ echo ".f0:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6718+ fn
6719+ echo ".f1:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6720+ fn
6721+ echo ".f2:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6722+ echo ".rf0:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6723+ rfn
6724+ echo ".rf1:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6725+ rfn
6726+ echo ".rf2:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6727+ echo ".f0r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
6728+ fnr
6729+ echo ".f1r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
6730+ fnr
6731+ echo ".f2r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
6732+expected-stdout:
6733+ .f0:m.m..:
6734+ .fn:f...:
6735+ .f1:m.m..:
6736+ .fn:f...:
6737+ .f2:m.m..:
6738+ .rf0:m.m..:
6739+ .rfn:f...:
6740+ .rf1:...:
6741+ .rfn:f...:
6742+ .rf2:...:
6743+ .f0r:m.m..:
6744+ .fnr:f...:
6745+ .f1r:m.m..:
6746+ .fnr:f...:
6747+ .f2r:m.m..:
6748+---
6749+name: arrassign-fnc-global
6750+description:
6751+ Check locality of array access inside a function
6752+ with the mksh-specific global keyword
6753+stdin:
6754+ function fn {
6755+ global x
6756+ x+=(f)
6757+ echo ".fn:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6758+ }
6759+ function rfn {
6760+ set -A y
6761+ global y
6762+ y+=(f)
6763+ echo ".rfn:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6764+ }
6765+ function fnr {
6766+ global z
6767+ set -A z
6768+ z+=(f)
6769+ echo ".fnr:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
6770+ }
6771+ x=(m m)
6772+ y=(m m)
6773+ z=(m m)
6774+ echo ".f0:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6775+ fn
6776+ echo ".f1:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6777+ fn
6778+ echo ".f2:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
6779+ echo ".rf0:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6780+ rfn
6781+ echo ".rf1:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6782+ rfn
6783+ echo ".rf2:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
6784+ echo ".f0r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
6785+ fnr
6786+ echo ".f1r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
6787+ fnr
6788+ echo ".f2r:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
6789+expected-stdout:
6790+ .f0:m.m..:
6791+ .fn:m.m.f.:
6792+ .f1:m.m.f.:
6793+ .fn:m.m.f.f:
6794+ .f2:m.m.f.f:
6795+ .rf0:m.m..:
6796+ .rfn:f...:
6797+ .rf1:f...:
6798+ .rfn:f...:
6799+ .rf2:f...:
6800+ .f0r:m.m..:
6801+ .fnr:f...:
6802+ .f1r:f...:
6803+ .fnr:f...:
6804+ .f2r:f...:
6805+---
6806+name: strassign-fnc-none
6807+description:
6808+ Check locality of string access inside a function
6809+stdin:
6810+ function fn {
6811+ x+=f
6812+ echo ".fn:$x:"
6813+ }
6814+ function rfn {
6815+ y=
6816+ y+=f
6817+ echo ".rfn:$y:"
6818+ }
6819+ x=m
6820+ y=m
6821+ echo ".f0:$x:"
6822+ fn
6823+ echo ".f1:$x:"
6824+ fn
6825+ echo ".f2:$x:"
6826+ echo ".rf0:$y:"
6827+ rfn
6828+ echo ".rf1:$y:"
6829+ rfn
6830+ echo ".rf2:$y:"
6831+expected-stdout:
6832+ .f0:m:
6833+ .fn:mf:
6834+ .f1:mf:
6835+ .fn:mff:
6836+ .f2:mff:
6837+ .rf0:m:
6838+ .rfn:f:
6839+ .rf1:f:
6840+ .rfn:f:
6841+ .rf2:f:
6842+---
6843+name: strassign-fnc-local
6844+description:
6845+ Check locality of string access inside a function
6846+ with the bash/mksh/ksh93 local/typeset keyword
6847+ (note: ksh93 has no local; typeset works only in FKSH)
6848+stdin:
6849+ function fn {
6850+ typeset x
6851+ x+=f
6852+ echo ".fn:$x:"
6853+ }
6854+ function rfn {
6855+ y=
6856+ typeset y
6857+ y+=f
6858+ echo ".rfn:$y:"
6859+ }
6860+ function fnr {
6861+ typeset z
6862+ z=
6863+ z+=f
6864+ echo ".fnr:$z:"
6865+ }
6866+ x=m
6867+ y=m
6868+ z=m
6869+ echo ".f0:$x:"
6870+ fn
6871+ echo ".f1:$x:"
6872+ fn
6873+ echo ".f2:$x:"
6874+ echo ".rf0:$y:"
6875+ rfn
6876+ echo ".rf1:$y:"
6877+ rfn
6878+ echo ".rf2:$y:"
6879+ echo ".f0r:$z:"
6880+ fnr
6881+ echo ".f1r:$z:"
6882+ fnr
6883+ echo ".f2r:$z:"
6884+expected-stdout:
6885+ .f0:m:
6886+ .fn:f:
6887+ .f1:m:
6888+ .fn:f:
6889+ .f2:m:
6890+ .rf0:m:
6891+ .rfn:f:
6892+ .rf1::
6893+ .rfn:f:
6894+ .rf2::
6895+ .f0r:m:
6896+ .fnr:f:
6897+ .f1r:m:
6898+ .fnr:f:
6899+ .f2r:m:
6900+---
6901+name: strassign-fnc-global
6902+description:
6903+ Check locality of string access inside a function
6904+ with the mksh-specific global keyword
6905+stdin:
6906+ function fn {
6907+ global x
6908+ x+=f
6909+ echo ".fn:$x:"
6910+ }
6911+ function rfn {
6912+ y=
6913+ global y
6914+ y+=f
6915+ echo ".rfn:$y:"
6916+ }
6917+ function fnr {
6918+ global z
6919+ z=
6920+ z+=f
6921+ echo ".fnr:$z:"
6922+ }
6923+ x=m
6924+ y=m
6925+ z=m
6926+ echo ".f0:$x:"
6927+ fn
6928+ echo ".f1:$x:"
6929+ fn
6930+ echo ".f2:$x:"
6931+ echo ".rf0:$y:"
6932+ rfn
6933+ echo ".rf1:$y:"
6934+ rfn
6935+ echo ".rf2:$y:"
6936+ echo ".f0r:$z:"
6937+ fnr
6938+ echo ".f1r:$z:"
6939+ fnr
6940+ echo ".f2r:$z:"
6941+expected-stdout:
6942+ .f0:m:
6943+ .fn:mf:
6944+ .f1:mf:
6945+ .fn:mff:
6946+ .f2:mff:
6947+ .rf0:m:
6948+ .rfn:f:
6949+ .rf1:f:
6950+ .rfn:f:
6951+ .rf2:f:
6952+ .f0r:m:
6953+ .fnr:f:
6954+ .f1r:f:
6955+ .fnr:f:
6956+ .f2r:f:
6957+---
57466958 name: varexpand-substr-1
57476959 description:
57486960 Check if bash-style substring expansion works
@@ -5865,6 +7077,22 @@ expected-stdout:
58657077 c we
58667078 d we
58677079 ---
7080+name: varexpand-special-hash
7081+description:
7082+ Check special ${var@x} expansion for x=hash
7083+stdin:
7084+ typeset -i8 foo=10
7085+ bar=baz
7086+ unset baz
7087+ bla=foo
7088+ print ${foo@#} ${bar@#} ${baz@#} .
7089+ print ${foo@#123} ${bar@#456} ${baz@#789} .
7090+ print ${foo@#bla} ${bar@#bar} ${baz@#OPTIND} .
7091+expected-stdout:
7092+ D50219A0 20E5DB5B 00000000 .
7093+ 554A1C76 004A212E CB209562 .
7094+ 6B21CF91 20E5DB5B 124EA49D .
7095+---
58687096 name: varexpand-null-1
58697097 description:
58707098 Ensure empty strings expand emptily
@@ -5881,7 +7109,9 @@ name: varexpand-null-2
58817109 description:
58827110 Ensure empty strings, when quoted, are expanded as empty strings
58837111 stdin:
5884- printf '<%s> ' 1 "${a}" 2 "${a#?}" + "${b%?}" 3 "${a=}" + "${b/c/d}"
7112+ print '#!'"$__progname"'\nfor x in "$@"; do print -nr -- "<$x> "; done' >pfs
7113+ chmod +x pfs
7114+ ./pfs 1 "${a}" 2 "${a#?}" + "${b%?}" 3 "${a=}" + "${b/c/d}"
58857115 echo .
58867116 expected-stdout:
58877117 <1> <> <2> <> <+> <> <3> <> <+> <> .
@@ -5904,16 +7134,13 @@ expected-stdout:
59047134 ---
59057135 name: print-nul-chars
59067136 description:
5907- Check handling of NUL characters for print and read
5908- note: second line should output “4 3” but we cannot
5909- handle NUL characters in strings yet
7137+ Check handling of NUL characters for print and COMSUB
59107138 stdin:
5911- print $(($(print '<\0>' | wc -c)))
59127139 x=$(print '<\0>')
5913- print $(($(print "$x" | wc -c))) ${#x}
5914-expected-stdout:
5915- 4
5916- 3 2
7140+ print $(($(print '<\0>' | wc -c))) $(($(print "$x" | wc -c))) \
7141+ ${#x} "$x" '<\0>'
7142+expected-stdout-pattern:
7143+ /^4 3 2 <> <\0>$/
59177144 ---
59187145 name: print-escapes
59197146 description:
@@ -5924,8 +7151,9 @@ stdin:
59247151 '\U\V\W\X\Y\Z\[\\\]\^\_\`\a\b \d\e\f\g\h\i\j\k\l\m\n\o\p' \
59257152 '\q\r\s\t\u\v\w\x\y\z\{\|\}\~' '\u20acd' '\U20acd' '\x123' \
59267153 '\0x' '\0123' '\01234' | {
7154+ # integer-base-one-3As
59277155 typeset -Uui16 -Z11 pos=0
5928- typeset -Uui16 -Z5 hv
7156+ typeset -Uui16 -Z5 hv=2147483647
59297157 typeset -i1 wc=0x0A
59307158 dasc=
59317159 nl=${wc#1#}
@@ -5948,13 +7176,11 @@ stdin:
59487176 line=${line:1}
59497177 done
59507178 done
5951- if (( (pos & 15) != 1 )); then
5952- while (( pos & 15 )); do
5953- print -n ' '
5954- (( (pos++ & 15) == 7 )) && print -n -- '- '
5955- done
5956- print "$dasc|"
5957- fi
7179+ while (( pos & 15 )); do
7180+ print -n ' '
7181+ (( (pos++ & 15) == 7 )) && print -n -- '- '
7182+ done
7183+ (( hv == 2147483647 )) || print "$dasc|"
59587184 }
59597185 expected-stdout:
59607186 00000000 5C 20 5C 21 5C 22 5C 23 - 5C 24 5C 25 5C 26 5C 27 |\ \!\"\#\$\%\&\'|
@@ -5971,19 +7197,38 @@ expected-stdout:
59717197 000000B0 E2 82 AC 64 20 EF BF BD - 20 12 33 20 78 20 53 20 |...d ... .3 x S |
59727198 000000C0 53 34 0A - |S4.|
59737199 ---
7200+name: dollar-doublequoted-strings
7201+description:
7202+ Check that a $ preceding "…" is ignored
7203+stdin:
7204+ echo $"Localise me!"
7205+ cat <<<$"Me too!"
7206+ V=X
7207+ aol=aol
7208+ cat <<-$"aol"
7209+ I do not take a $V for a V!
7210+ aol
7211+expected-stdout:
7212+ Localise me!
7213+ Me too!
7214+ I do not take a $V for a V!
7215+---
59747216 name: dollar-quoted-strings
59757217 description:
59767218 Check backslash expansion by $'…' strings
59777219 stdin:
5978- printf '%s\n' $'\ \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/ \1\2\3\4\5\6' \
7220+ print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn
7221+ chmod +x pfn
7222+ ./pfn $'\ \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/ \1\2\3\4\5\6' \
59797223 $'a\0b' $'a\01b' $'\7\8\9\:\;\<\=\>\?\@\A\B\C\D\E\F\G\H\I' \
59807224 $'\J\K\L\M\N\O\P\Q\R\S\T\U1\V\W\X\Y\Z\[\\\]\^\_\`\a\b\d\e' \
59817225 $'\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u1\v\w\x1\y\z\{\|\}\~ $x' \
59827226 $'\u20acd' $'\U20acd' $'\x123' $'fn\x0rd' $'\0234' $'\234' \
59837227 $'\2345' $'\ca' $'\c!' $'\c?' $'\c€' $'a\
59847228 b' | {
7229+ # integer-base-one-3As
59857230 typeset -Uui16 -Z11 pos=0
5986- typeset -Uui16 -Z5 hv
7231+ typeset -Uui16 -Z5 hv=2147483647
59877232 typeset -i1 wc=0x0A
59887233 dasc=
59897234 nl=${wc#1#}
@@ -6006,13 +7251,11 @@ stdin:
60067251 line=${line:1}
60077252 done
60087253 done
6009- if (( (pos & 15) != 1 )); then
6010- while (( pos & 15 )); do
6011- print -n ' '
6012- (( (pos++ & 15) == 7 )) && print -n -- '- '
6013- done
6014- print "$dasc|"
6015- fi
7254+ while (( pos & 15 )); do
7255+ print -n ' '
7256+ (( (pos++ & 15) == 7 )) && print -n -- '- '
7257+ done
7258+ (( hv == 2147483647 )) || print "$dasc|"
60167259 }
60177260 expected-stdout:
60187261 00000000 20 21 22 23 24 25 26 27 - 28 29 2A 2B 2C 2D 2E 2F | !"#$%&'()*+,-./|
@@ -6249,9 +7492,10 @@ expected-stderr-pattern:
62497492 /1#à€€: unexpected '€'/
62507493 expected-exit: e != 0
62517494 ---
6252-name: integer-base-one-3A
7495+name: integer-base-one-3As
62537496 description:
62547497 some sample code for hexdumping
7498+ not NUL safe; input lines must be NL terminated
62557499 stdin:
62567500 {
62577501 print 'Hello, World!\\\nこんにちは!'
@@ -6261,10 +7505,11 @@ stdin:
62617505 while (( i++ < 0x1FF )); do
62627506 print -n "\x${i#16#1}"
62637507 done
6264- print
7508+ print '\0z'
62657509 } | {
7510+ # integer-base-one-3As
62667511 typeset -Uui16 -Z11 pos=0
6267- typeset -Uui16 -Z5 hv
7512+ typeset -Uui16 -Z5 hv=2147483647
62687513 typeset -i1 wc=0x0A
62697514 dasc=
62707515 nl=${wc#1#}
@@ -6287,13 +7532,11 @@ stdin:
62877532 line=${line:1}
62887533 done
62897534 done
6290- if (( (pos & 15) != 1 )); then
6291- while (( pos & 15 )); do
6292- print -n ' '
6293- (( (pos++ & 15) == 7 )) && print -n -- '- '
6294- done
6295- print "$dasc|"
6296- fi
7535+ while (( pos & 15 )); do
7536+ print -n ' '
7537+ (( (pos++ & 15) == 7 )) && print -n -- '- '
7538+ done
7539+ (( hv == 2147483647 )) || print "$dasc|"
62977540 }
62987541 expected-stdout:
62997542 00000000 48 65 6C 6C 6F 2C 20 57 - 6F 72 6C 64 21 5C 0A E3 |Hello, World!\..|
@@ -6314,11 +7557,12 @@ expected-stdout:
63147557 000000F0 CF D0 D1 D2 D3 D4 D5 D6 - D7 D8 D9 DA DB DC DD DE |................|
63157558 00000100 DF E0 E1 E2 E3 E4 E5 E6 - E7 E8 E9 EA EB EC ED EE |................|
63167559 00000110 EF F0 F1 F2 F3 F4 F5 F6 - F7 F8 F9 FA FB FC FD FE |................|
6317- 00000120 FF 0A - |..|
7560+ 00000120 FF 7A 0A - |.z.|
63187561 ---
6319-name: integer-base-one-3W
7562+name: integer-base-one-3Ws
63207563 description:
63217564 some sample code for hexdumping Unicode
7565+ not NUL safe; input lines must be NL terminated
63227566 stdin:
63237567 set -U
63247568 {
@@ -6336,7 +7580,9 @@ stdin:
63367580 print \\xc0\\x80 # non-minimalistic
63377581 print \\xe0\\x80\\x80 # non-minimalistic
63387582 print '�￾￿' # end of range
7583+ print '\0z' # embedded NUL
63397584 } | {
7585+ # integer-base-one-3Ws
63407586 typeset -Uui16 -Z11 pos=0
63417587 typeset -Uui16 -Z7 hv
63427588 typeset -i1 wc=0x0A
@@ -6371,13 +7617,174 @@ stdin:
63717617 dasc=$dasc$dch
63727618 done
63737619 done
6374- if (( pos & 7 )); then
6375- while (( pos & 7 )); do
6376- print -n ' '
6377- (( (pos++ & 7) == 3 )) && print -n -- '- '
7620+ while (( pos & 7 )); do
7621+ print -n ' '
7622+ (( (pos++ & 7) == 3 )) && print -n -- '- '
7623+ done
7624+ (( hv == 2147483647 )) || print "$dasc|"
7625+ }
7626+expected-stdout:
7627+ 00000000 0048 0065 006C 006C - 006F 002C 0020 0057 |Hello, W|
7628+ 00000008 006F 0072 006C 0064 - 0021 005C 000A 3053 |orld!\.こ|
7629+ 00000010 3093 306B 3061 306F - FF01 000A 0001 0002 |んにちは!...|
7630+ 00000018 0003 0004 0005 0006 - 0007 0008 0009 000A |........|
7631+ 00000020 000B 000C 000D 000E - 000F 0010 0011 0012 |........|
7632+ 00000028 0013 0014 0015 0016 - 0017 0018 0019 001A |........|
7633+ 00000030 001B 001C 001D 001E - 001F 0020 0021 0022 |..... !"|
7634+ 00000038 0023 0024 0025 0026 - 0027 0028 0029 002A |#$%&'()*|
7635+ 00000040 002B 002C 002D 002E - 002F 0030 0031 0032 |+,-./012|
7636+ 00000048 0033 0034 0035 0036 - 0037 0038 0039 003A |3456789:|
7637+ 00000050 003B 003C 003D 003E - 003F 0040 0041 0042 |;<=>?@AB|
7638+ 00000058 0043 0044 0045 0046 - 0047 0048 0049 004A |CDEFGHIJ|
7639+ 00000060 004B 004C 004D 004E - 004F 0050 0051 0052 |KLMNOPQR|
7640+ 00000068 0053 0054 0055 0056 - 0057 0058 0059 005A |STUVWXYZ|
7641+ 00000070 005B 005C 005D 005E - 005F 0060 0061 0062 |[\]^_`ab|
7642+ 00000078 0063 0064 0065 0066 - 0067 0068 0069 006A |cdefghij|
7643+ 00000080 006B 006C 006D 006E - 006F 0070 0071 0072 |klmnopqr|
7644+ 00000088 0073 0074 0075 0076 - 0077 0078 0079 007A |stuvwxyz|
7645+ 00000090 007B 007C 007D 007E - 007F 0080 0081 0082 |{|}~....|
7646+ 00000098 0083 0084 0085 0086 - 0087 0088 0089 008A |........|
7647+ 000000A0 008B 008C 008D 008E - 008F 0090 0091 0092 |........|
7648+ 000000A8 0093 0094 0095 0096 - 0097 0098 0099 009A |........|
7649+ 000000B0 009B 009C 009D 009E - 009F 00A0 00A1 00A2 |..... ¡¢|
7650+ 000000B8 00A3 00A4 00A5 00A6 - 00A7 00A8 00A9 00AA |£¤¥¦§¨©ª|
7651+ 000000C0 00AB 00AC 00AD 00AE - 00AF 00B0 00B1 00B2 |«¬­®¯°±²|
7652+ 000000C8 00B3 00B4 00B5 00B6 - 00B7 00B8 00B9 00BA |³´µ¶·¸¹º|
7653+ 000000D0 00BB 00BC 00BD 00BE - 00BF 00C0 00C1 00C2 |»¼½¾¿ÀÁÂ|
7654+ 000000D8 00C3 00C4 00C5 00C6 - 00C7 00C8 00C9 00CA |ÃÄÅÆÇÈÉÊ|
7655+ 000000E0 00CB 00CC 00CD 00CE - 00CF 00D0 00D1 00D2 |ËÌÍÎÏÐÑÒ|
7656+ 000000E8 00D3 00D4 00D5 00D6 - 00D7 00D8 00D9 00DA |ÓÔÕÖ×ØÙÚ|
7657+ 000000F0 00DB 00DC 00DD 00DE - 00DF 00E0 00E1 00E2 |ÛÜÝÞßàáâ|
7658+ 000000F8 00E3 00E4 00E5 00E6 - 00E7 00E8 00E9 00EA |ãäåæçèéê|
7659+ 00000100 00EB 00EC 00ED 00EE - 00EF 00F0 00F1 00F2 |ëìíîïðñò|
7660+ 00000108 00F3 00F4 00F5 00F6 - 00F7 00F8 00F9 00FA |óôõö÷øùú|
7661+ 00000110 00FB 00FC 00FD 00FE - 00FF 000A EFFF 000A |ûüýþÿ.�.|
7662+ 00000118 EFC2 000A EFEF EFBF - EFC0 000A EFC0 EF80 |�.���.��|
7663+ 00000120 000A EFE0 EF80 EF80 - 000A FFFD EFEF EFBF |.���.���|
7664+ 00000128 EFBE EFEF EFBF EFBF - 000A 007A 000A |����.z.|
7665+---
7666+name: integer-base-one-3Ar
7667+description:
7668+ some sample code for hexdumping; NUL and binary safe
7669+stdin:
7670+ {
7671+ print 'Hello, World!\\\nこんにちは!'
7672+ typeset -Uui16 i=0x100
7673+ # change that to 0xFF once we can handle embedded
7674+ # NUL characters in strings / here documents
7675+ while (( i++ < 0x1FF )); do
7676+ print -n "\x${i#16#1}"
7677+ done
7678+ print '\0z'
7679+ } | {
7680+ # integer-base-one-3Ar
7681+ typeset -Uui16 -Z11 pos=0
7682+ typeset -Uui16 -Z5 hv=2147483647
7683+ dasc=
7684+ if read -arN -1 line; then
7685+ typeset -i1 line
7686+ i=0
7687+ while (( i < ${#line[*]} )); do
7688+ hv=${line[i++]}
7689+ if (( (pos & 15) == 0 )); then
7690+ (( pos )) && print "$dasc|"
7691+ print -n "${pos#16#} "
7692+ dasc=' |'
7693+ fi
7694+ print -n "${hv#16#} "
7695+ if (( (hv < 32) || (hv > 126) )); then
7696+ dasc=$dasc.
7697+ else
7698+ dasc=$dasc${line[i-1]#1#}
7699+ fi
7700+ (( (pos++ & 15) == 7 )) && print -n -- '- '
7701+ done
7702+ fi
7703+ while (( pos & 15 )); do
7704+ print -n ' '
7705+ (( (pos++ & 15) == 7 )) && print -n -- '- '
7706+ done
7707+ (( hv == 2147483647 )) || print "$dasc|"
7708+ }
7709+expected-stdout:
7710+ 00000000 48 65 6C 6C 6F 2C 20 57 - 6F 72 6C 64 21 5C 0A E3 |Hello, World!\..|
7711+ 00000010 81 93 E3 82 93 E3 81 AB - E3 81 A1 E3 81 AF EF BC |................|
7712+ 00000020 81 0A 01 02 03 04 05 06 - 07 08 09 0A 0B 0C 0D 0E |................|
7713+ 00000030 0F 10 11 12 13 14 15 16 - 17 18 19 1A 1B 1C 1D 1E |................|
7714+ 00000040 1F 20 21 22 23 24 25 26 - 27 28 29 2A 2B 2C 2D 2E |. !"#$%&'()*+,-.|
7715+ 00000050 2F 30 31 32 33 34 35 36 - 37 38 39 3A 3B 3C 3D 3E |/0123456789:;<=>|
7716+ 00000060 3F 40 41 42 43 44 45 46 - 47 48 49 4A 4B 4C 4D 4E |?@ABCDEFGHIJKLMN|
7717+ 00000070 4F 50 51 52 53 54 55 56 - 57 58 59 5A 5B 5C 5D 5E |OPQRSTUVWXYZ[\]^|
7718+ 00000080 5F 60 61 62 63 64 65 66 - 67 68 69 6A 6B 6C 6D 6E |_`abcdefghijklmn|
7719+ 00000090 6F 70 71 72 73 74 75 76 - 77 78 79 7A 7B 7C 7D 7E |opqrstuvwxyz{|}~|
7720+ 000000A0 7F 80 81 82 83 84 85 86 - 87 88 89 8A 8B 8C 8D 8E |................|
7721+ 000000B0 8F 90 91 92 93 94 95 96 - 97 98 99 9A 9B 9C 9D 9E |................|
7722+ 000000C0 9F A0 A1 A2 A3 A4 A5 A6 - A7 A8 A9 AA AB AC AD AE |................|
7723+ 000000D0 AF B0 B1 B2 B3 B4 B5 B6 - B7 B8 B9 BA BB BC BD BE |................|
7724+ 000000E0 BF C0 C1 C2 C3 C4 C5 C6 - C7 C8 C9 CA CB CC CD CE |................|
7725+ 000000F0 CF D0 D1 D2 D3 D4 D5 D6 - D7 D8 D9 DA DB DC DD DE |................|
7726+ 00000100 DF E0 E1 E2 E3 E4 E5 E6 - E7 E8 E9 EA EB EC ED EE |................|
7727+ 00000110 EF F0 F1 F2 F3 F4 F5 F6 - F7 F8 F9 FA FB FC FD FE |................|
7728+ 00000120 FF 00 7A 0A - |..z.|
7729+---
7730+name: integer-base-one-3Wr
7731+description:
7732+ some sample code for hexdumping Unicode; NUL and binary safe
7733+stdin:
7734+ set -U
7735+ {
7736+ print 'Hello, World!\\\nこんにちは!'
7737+ typeset -Uui16 i=0x100
7738+ # change that to 0xFF once we can handle embedded
7739+ # NUL characters in strings / here documents
7740+ while (( i++ < 0x1FF )); do
7741+ print -n "\u${i#16#1}"
7742+ done
7743+ print
7744+ print \\xff # invalid utf-8
7745+ print \\xc2 # invalid 2-byte
7746+ print \\xef\\xbf\\xc0 # invalid 3-byte
7747+ print \\xc0\\x80 # non-minimalistic
7748+ print \\xe0\\x80\\x80 # non-minimalistic
7749+ print '�￾￿' # end of range
7750+ print '\0z' # embedded NUL
7751+ } | {
7752+ # integer-base-one-3Wr
7753+ typeset -Uui16 -Z11 pos=0
7754+ typeset -Uui16 -Z7 hv=2147483647
7755+ dasc=
7756+ if read -arN -1 line; then
7757+ typeset -i1 line
7758+ i=0
7759+ while (( i < ${#line[*]} )); do
7760+ hv=${line[i++]}
7761+ if (( (hv < 32) || \
7762+ ((hv > 126) && (hv < 160)) )); then
7763+ dch=.
7764+ elif (( (hv & 0xFF80) == 0xEF80 )); then
7765+ dch=�
7766+ else
7767+ dch=${line[i-1]#1#}
7768+ fi
7769+ if (( (pos & 7) == 7 )); then
7770+ dasc=$dasc$dch
7771+ dch=
7772+ elif (( (pos & 7) == 0 )); then
7773+ (( pos )) && print "$dasc|"
7774+ print -n "${pos#16#} "
7775+ dasc=' |'
7776+ fi
7777+ print -n "${hv#16#} "
7778+ (( (pos++ & 7) == 3 )) && \
7779+ print -n -- '- '
7780+ dasc=$dasc$dch
63787781 done
6379- print "$dasc|"
63807782 fi
7783+ while (( pos & 7 )); do
7784+ print -n ' '
7785+ (( (pos++ & 7) == 3 )) && print -n -- '- '
7786+ done
7787+ (( hv == 2147483647 )) || print "$dasc|"
63817788 }
63827789 expected-stdout:
63837790 00000000 0048 0065 006C 006C - 006F 002C 0020 0057 |Hello, W|
@@ -6417,7 +7824,7 @@ expected-stdout:
64177824 00000110 00FB 00FC 00FD 00FE - 00FF 000A EFFF 000A |ûüýþÿ.�.|
64187825 00000118 EFC2 000A EFEF EFBF - EFC0 000A EFC0 EF80 |�.���.��|
64197826 00000120 000A EFE0 EF80 EF80 - 000A FFFD EFEF EFBF |.���.���|
6420- 00000128 EFBE EFEF EFBF EFBF - 000A |����.|
7827+ 00000128 EFBE EFEF EFBF EFBF - 000A 0000 007A 000A |����..z.|
64217828 ---
64227829 name: integer-base-one-4
64237830 description:
@@ -6440,9 +7847,36 @@ expected-stdout:
64407847 5 97
64417848 6 97
64427849 ---
7850+name: integer-base-one-5A
7851+description:
7852+ Check to see that we’re NUL and Unicode safe
7853+stdin:
7854+ set +U
7855+ print 'a\0b\xfdz' >x
7856+ read -a y <x
7857+ set -U
7858+ typeset -Uui16 y
7859+ print ${y[*]} .
7860+expected-stdout:
7861+ 16#61 16#0 16#62 16#FD 16#7A .
7862+---
7863+name: integer-base-one-5W
7864+description:
7865+ Check to see that we’re NUL and Unicode safe
7866+stdin:
7867+ set -U
7868+ print 'a\0b€c' >x
7869+ read -a y <x
7870+ set +U
7871+ typeset -Uui16 y
7872+ print ${y[*]} .
7873+expected-stdout:
7874+ 16#61 16#0 16#62 16#20AC 16#63 .
7875+---
64437876 name: ulimit-1
64447877 description:
64457878 Check if we can use a specific syntax idiom for ulimit
7879+category: !os:syllable
64467880 stdin:
64477881 if ! x=$(ulimit -d) || [[ $x = unknown ]]; then
64487882 #echo expected to fail on this OS
@@ -6555,7 +7989,7 @@ stdin:
65557989 expected-stdout:
65567990 ===
65577991 mir
6558-expected-stderr-pattern: /.*: cannot (create|overwrite) .*/
7992+expected-stderr-pattern: /.*: can't (create|overwrite) .*/
65597993 ---
65607994 name: bashiop-3b
65617995 description:
@@ -6661,6 +8095,9 @@ description:
66618095 global environment.
66628096 Inspired by PR 2450.
66638097 stdin:
8098+ print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
8099+ 'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
8100+ done >env; chmod +x env; PATH=.:$PATH
66648101 function k {
66658102 if [ x$FOO != xbar ]; then
66668103 echo 1
@@ -6720,21 +8157,22 @@ stdin:
67208157 name: fd-cloexec-1
67218158 description:
67228159 Verify that file descriptors > 2 are private for Korn shells
8160+ AT&T ksh93 does this still, which means we must keep it as well
67238161 file-setup: file 644 "test.sh"
6724- print -u3 Fowl
8162+ echo >&3 Fowl
67258163 stdin:
67268164 exec 3>&1
67278165 "$__progname" test.sh
67288166 expected-exit: e != 0
6729-expected-stderr:
6730- test.sh[1]: print: -u: 3: bad file descriptor
8167+expected-stderr-pattern:
8168+ /bad file descriptor/
67318169 ---
67328170 name: fd-cloexec-2
67338171 description:
67348172 Verify that file descriptors > 2 are not private for POSIX shells
67358173 See Debian Bug #154540, Closes: #499139
67368174 file-setup: file 644 "test.sh"
6737- print -u3 Fowl
8175+ echo >&3 Fowl
67388176 stdin:
67398177 test -n "$POSH_VERSION" || set -o sh
67408178 exec 3>&1
@@ -6742,28 +8180,54 @@ stdin:
67428180 expected-stdout:
67438181 Fowl
67448182 ---
6745-name: comsub-1
6746-description:
6747- COMSUB are currently parsed by hacking lex.c instead of
6748- recursively (see regression-6): matching parenthesēs bug
6749- Fails on: pdksh mksh bash2 bash3 zsh
6750- Passes on: bash4 ksh93
6751-expected-fail: yes
6752-stdin:
6753- echo $(case 1 in (1) echo yes;; (2) echo no;; esac)
6754- echo $(case 1 in 1) echo yes;; 2) echo no;; esac)
6755-expected-stdout:
6756- yes
6757- yes
8183+name: comsub-1a
8184+description:
8185+ COMSUB are now parsed recursively, so this works
8186+ see also regression-6: matching parenthesēs bug
8187+ Fails on: pdksh bash2 bash3 zsh
8188+ Passes on: bash4 ksh93 mksh(20110313+)
8189+stdin:
8190+ echo 1 $(case 1 in (1) echo yes;; (2) echo no;; esac) .
8191+ echo 2 $(case 1 in 1) echo yes;; 2) echo no;; esac) .
8192+ TEST=1234; echo 3 ${TEST: $(case 1 in (1) echo 1;; (*) echo 2;; esac)} .
8193+ TEST=5678; echo 4 ${TEST: $(case 1 in 1) echo 1;; *) echo 2;; esac)} .
8194+ a=($(case 1 in (1) echo 1;; (*) echo 2;; esac)); echo 5 ${a[0]} .
8195+ a=($(case 1 in 1) echo 1;; *) echo 2;; esac)); echo 6 ${a[0]} .
8196+expected-stdout:
8197+ 1 yes .
8198+ 2 yes .
8199+ 3 234 .
8200+ 4 678 .
8201+ 5 1 .
8202+ 6 1 .
8203+---
8204+name: comsub-1b
8205+description:
8206+ COMSUB are now parsed recursively, so this works
8207+ Fails on: pdksh bash2 bash3 bash4 zsh
8208+ Passes on: ksh93 mksh(20110313+)
8209+stdin:
8210+ echo 1 $(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10)) .
8211+ echo 2 $(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20)) .
8212+ (( a = $(case 1 in (1) echo 1;; (*) echo 2;; esac) )); echo 3 $a .
8213+ (( a = $(case 1 in 1) echo 1;; *) echo 2;; esac) )); echo 4 $a .
8214+ a=($(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10))); echo 5 ${a[0]} .
8215+ a=($(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20))); echo 6 ${a[0]} .
8216+expected-stdout:
8217+ 1 11 .
8218+ 2 21 .
8219+ 3 1 .
8220+ 4 1 .
8221+ 5 11 .
8222+ 6 21 .
67588223 ---
67598224 name: comsub-2
67608225 description:
67618226 RedHat BZ#496791 – another case of missing recursion
67628227 in parsing COMSUB expressions
6763- Fails on: pdksh mksh bash2 bash3¹ bash4¹ zsh
6764- Passes on: ksh93
8228+ Fails on: pdksh bash2 bash3¹ bash4¹ zsh
8229+ Passes on: ksh93 mksh(20110305+)
67658230 ① bash[34] seem to choke on comment ending with backslash-newline
6766-expected-fail: yes
67678231 stdin:
67688232 # a comment with " ' \
67698233 x=$(
@@ -6774,6 +8238,1081 @@ stdin:
67748238 expected-stdout:
67758239 yes
67768240 ---
8241+name: comsub-3
8242+description:
8243+ Extended test for COMSUB explaining why a recursive parser
8244+ is a must (a non-recursive parser cannot pass all three of
8245+ these test cases, especially the ‘#’ is difficult)
8246+stdin:
8247+ print '#!'"$__progname"'\necho 1234' >id; chmod +x id; PATH=.:$PATH
8248+ echo $(typeset -i10 x=16#20; echo $x)
8249+ echo $(typeset -Uui16 x=16#$(id -u)
8250+ ) .
8251+ echo $(c=1; d=1
8252+ typeset -Uui16 a=36#foo; c=2
8253+ typeset -Uui16 b=36 #foo; d=2
8254+ echo $a $b $c $d)
8255+expected-stdout:
8256+ 32
8257+ .
8258+ 16#4F68 16#24 2 1
8259+---
8260+name: comsub-4
8261+description:
8262+ Check the tree dump functions for !MKSH_SMALL functionality
8263+category: !smksh
8264+stdin:
8265+ x() { case $1 in u) echo x ;;& *) echo $1 ;; esac; }
8266+ typeset -f x
8267+expected-stdout:
8268+ x() {
8269+ case $1 in
8270+ (u)
8271+ echo x
8272+ ;|
8273+ (*)
8274+ echo $1
8275+ ;;
8276+ esac
8277+ }
8278+---
8279+name: comsub-5
8280+description:
8281+ Check COMSUB works with aliases (does not expand them twice)
8282+stdin:
8283+ print '#!'"$__progname"'\nfor x in "$@"; do print -r -- "$x"; done' >pfn
8284+ chmod +x pfn
8285+ alias echo='echo a'
8286+ foo() {
8287+ ./pfn "$(echo foo)"
8288+ }
8289+ ./pfn "$(echo b)"
8290+ typeset -f foo
8291+expected-stdout:
8292+ a b
8293+ foo() {
8294+ ./pfn "$(echo foo )"
8295+ }
8296+---
8297+name: comsub-torture
8298+description:
8299+ Check the tree dump functions work correctly
8300+stdin:
8301+ if [[ -z $__progname ]]; then echo >&2 call me with __progname; exit 1; fi
8302+ while IFS= read -r line; do
8303+ if [[ $line = '#1' ]]; then
8304+ lastf=0
8305+ continue
8306+ elif [[ $line = EOFN* ]]; then
8307+ fbody=$fbody$'\n'$line
8308+ continue
8309+ elif [[ $line != '#'* ]]; then
8310+ fbody=$fbody$'\n\t'$line
8311+ continue
8312+ fi
8313+ if (( lastf )); then
8314+ x="inline_${nextf}() {"$fbody$'\n}\n'
8315+ print -nr -- "$x"
8316+ print -r -- "${x}typeset -f inline_$nextf" | "$__progname"
8317+ x="function comsub_$nextf { x=\$("$fbody$'\n); }\n'
8318+ print -nr -- "$x"
8319+ print -r -- "${x}typeset -f comsub_$nextf" | "$__progname"
8320+ x="function reread_$nextf { x=\$(("$fbody$'\n)|tr u x); }\n'
8321+ print -nr -- "$x"
8322+ print -r -- "${x}typeset -f reread_$nextf" | "$__progname"
8323+ fi
8324+ lastf=1
8325+ fbody=
8326+ nextf=${line#?}
8327+ done <<'EOD'
8328+ #1
8329+ #TCOM
8330+ vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
8331+ #TPAREN_TPIPE_TLIST
8332+ (echo $foo | tr -dc 0-9; echo)
8333+ #TAND_TOR
8334+ cmd && echo ja || echo nein
8335+ #TSELECT
8336+ select file in *; do echo "<$file>" ; break ; done
8337+ #TFOR_TTIME
8338+ time for i in {1,2,3} ; do echo $i ; done
8339+ #TCASE
8340+ case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
8341+ #TIF_TBANG_TDBRACKET_TELIF
8342+ if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
8343+ #TWHILE
8344+ i=1; while (( i < 10 )); do echo $i; let ++i; done
8345+ #TUNTIL
8346+ i=10; until (( !--i )) ; do echo $i; done
8347+ #TCOPROC
8348+ cat * |& ls
8349+ #TFUNCT_TBRACE_TASYNC
8350+ function korn { echo eins; echo zwei ; }
8351+ bourne () { logger * & }
8352+ #IOREAD_IOCAT
8353+ tr x u 0<foo >>bar
8354+ #IOWRITE_IOCLOB_IOHERE_noIOSKIP
8355+ cat >|bar <<'EOFN'
8356+ foo
8357+ EOFN
8358+ #IOWRITE_noIOCLOB_IOHERE_IOSKIP
8359+ cat 1>bar <<-EOFI
8360+ foo
8361+ EOFI
8362+ #IORDWR_IODUP
8363+ sh 1<>/dev/console 0<&1 2>&1
8364+ #COMSUB_EXPRSUB
8365+ echo $(true) $((1+ 2))
8366+ #QCHAR_OQUOTE_CQUOTE
8367+ echo fo\ob\"a\`r\'b\$az
8368+ echo "fo\ob\"a\`r\'b\$az"
8369+ echo 'fo\ob\"a\`r'\''b\$az'
8370+ #OSUBST_CSUBST_OPAT_SPAT_CPAT
8371+ [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
8372+ #heredoc_closed
8373+ x=$(cat <<EOFN
8374+ note there must be no space between EOFN and )
8375+ EOFN); echo $x
8376+ #heredoc_space
8377+ x=$(cat <<EOFN\
8378+ note the space between EOFN and ) is actually part of the here document marker
8379+ EOFN ); echo $x
8380+ #patch_motd
8381+ x=$(sysctl -n kern.version | sed 1q)
8382+ [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd)" != $x ]] && \
8383+ ed -s /etc/motd 2>&1 <<-EOF
8384+ 1,/^\$/d
8385+ 0a
8386+ $x
8387+
8388+ .
8389+ wq
8390+ EOF)" = @(?) ]] && rm -f /etc/motd
8391+ if [[ ! -s /etc/motd ]]; then
8392+ install -c -o root -g wheel -m 664 /dev/null /etc/motd
8393+ print -- "$x\n" >/etc/motd
8394+ fi
8395+ #wdarrassign
8396+ case x in
8397+ x) a+=b; c+=(d e)
8398+ esac
8399+ #0
8400+ EOD
8401+expected-stdout:
8402+ inline_TCOM() {
8403+ vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
8404+ }
8405+ inline_TCOM() {
8406+ vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4"
8407+ }
8408+ function comsub_TCOM { x=$(
8409+ vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
8410+ ); }
8411+ function comsub_TCOM {
8412+ x=$(vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" )
8413+ }
8414+ function reread_TCOM { x=$((
8415+ vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4"
8416+ )|tr u x); }
8417+ function reread_TCOM {
8418+ x=$(( vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" ) | tr u x )
8419+ }
8420+ inline_TPAREN_TPIPE_TLIST() {
8421+ (echo $foo | tr -dc 0-9; echo)
8422+ }
8423+ inline_TPAREN_TPIPE_TLIST() {
8424+ ( echo $foo | tr -dc 0-9
8425+ echo )
8426+ }
8427+ function comsub_TPAREN_TPIPE_TLIST { x=$(
8428+ (echo $foo | tr -dc 0-9; echo)
8429+ ); }
8430+ function comsub_TPAREN_TPIPE_TLIST {
8431+ x=$(( echo $foo | tr -dc 0-9 ; echo ) )
8432+ }
8433+ function reread_TPAREN_TPIPE_TLIST { x=$((
8434+ (echo $foo | tr -dc 0-9; echo)
8435+ )|tr u x); }
8436+ function reread_TPAREN_TPIPE_TLIST {
8437+ x=$(( ( echo $foo | tr -dc 0-9 ; echo ) ) | tr u x )
8438+ }
8439+ inline_TAND_TOR() {
8440+ cmd && echo ja || echo nein
8441+ }
8442+ inline_TAND_TOR() {
8443+ cmd && echo ja || echo nein
8444+ }
8445+ function comsub_TAND_TOR { x=$(
8446+ cmd && echo ja || echo nein
8447+ ); }
8448+ function comsub_TAND_TOR {
8449+ x=$(cmd && echo ja || echo nein )
8450+ }
8451+ function reread_TAND_TOR { x=$((
8452+ cmd && echo ja || echo nein
8453+ )|tr u x); }
8454+ function reread_TAND_TOR {
8455+ x=$(( cmd && echo ja || echo nein ) | tr u x )
8456+ }
8457+ inline_TSELECT() {
8458+ select file in *; do echo "<$file>" ; break ; done
8459+ }
8460+ inline_TSELECT() {
8461+ select file in *
8462+ do
8463+ echo "<$file>"
8464+ break
8465+ done
8466+ }
8467+ function comsub_TSELECT { x=$(
8468+ select file in *; do echo "<$file>" ; break ; done
8469+ ); }
8470+ function comsub_TSELECT {
8471+ x=$(select file in * ; do echo "<$file>" ; break ; done )
8472+ }
8473+ function reread_TSELECT { x=$((
8474+ select file in *; do echo "<$file>" ; break ; done
8475+ )|tr u x); }
8476+ function reread_TSELECT {
8477+ x=$(( select file in * ; do echo "<$file>" ; break ; done ) | tr u x )
8478+ }
8479+ inline_TFOR_TTIME() {
8480+ time for i in {1,2,3} ; do echo $i ; done
8481+ }
8482+ inline_TFOR_TTIME() {
8483+ time for i in {1,2,3}
8484+ do
8485+ echo $i
8486+ done
8487+ }
8488+ function comsub_TFOR_TTIME { x=$(
8489+ time for i in {1,2,3} ; do echo $i ; done
8490+ ); }
8491+ function comsub_TFOR_TTIME {
8492+ x=$(time for i in {1,2,3} ; do echo $i ; done )
8493+ }
8494+ function reread_TFOR_TTIME { x=$((
8495+ time for i in {1,2,3} ; do echo $i ; done
8496+ )|tr u x); }
8497+ function reread_TFOR_TTIME {
8498+ x=$(( time for i in {1,2,3} ; do echo $i ; done ) | tr u x )
8499+ }
8500+ inline_TCASE() {
8501+ case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
8502+ }
8503+ inline_TCASE() {
8504+ case $foo in
8505+ (1)
8506+ echo eins
8507+ ;&
8508+ (2)
8509+ echo zwei
8510+ ;|
8511+ (*)
8512+ echo kann net bis drei zählen
8513+ ;;
8514+ esac
8515+ }
8516+ function comsub_TCASE { x=$(
8517+ case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
8518+ ); }
8519+ function comsub_TCASE {
8520+ x=$(case $foo in (1) echo eins ;& (2) echo zwei ;| (*) echo kann net bis drei zählen ;; esac )
8521+ }
8522+ function reread_TCASE { x=$((
8523+ case $foo in 1) echo eins;& 2) echo zwei ;| *) echo kann net bis drei zählen;; esac
8524+ )|tr u x); }
8525+ function reread_TCASE {
8526+ x=$(( case $foo in (1) echo eins ;& (2) echo zwei ;| (*) echo kann net bis drei zählen ;; esac ) | tr u x )
8527+ }
8528+ inline_TIF_TBANG_TDBRACKET_TELIF() {
8529+ if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
8530+ }
8531+ inline_TIF_TBANG_TDBRACKET_TELIF() {
8532+ if ! [[ 1 = 1 ]]
8533+ then
8534+ echo eins
8535+ elif [[ 1 = 2 ]]
8536+ then
8537+ echo zwei
8538+ else
8539+ echo drei
8540+ fi
8541+ }
8542+ function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$(
8543+ if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
8544+ ); }
8545+ function comsub_TIF_TBANG_TDBRACKET_TELIF {
8546+ x=$(if ! [[ 1 = 1 ]] ; then echo eins ; elif [[ 1 = 2 ]] ; then echo zwei ; else echo drei ; fi )
8547+ }
8548+ function reread_TIF_TBANG_TDBRACKET_TELIF { x=$((
8549+ if ! [[ 1 = 1 ]] ; then echo eins; elif [[ 1 = 2 ]]; then echo zwei ;else echo drei; fi
8550+ )|tr u x); }
8551+ function reread_TIF_TBANG_TDBRACKET_TELIF {
8552+ x=$(( if ! [[ 1 = 1 ]] ; then echo eins ; elif [[ 1 = 2 ]] ; then echo zwei ; else echo drei ; fi ) | tr u x )
8553+ }
8554+ inline_TWHILE() {
8555+ i=1; while (( i < 10 )); do echo $i; let ++i; done
8556+ }
8557+ inline_TWHILE() {
8558+ i=1
8559+ while let " i < 10 "
8560+ do
8561+ echo $i
8562+ let ++i
8563+ done
8564+ }
8565+ function comsub_TWHILE { x=$(
8566+ i=1; while (( i < 10 )); do echo $i; let ++i; done
8567+ ); }
8568+ function comsub_TWHILE {
8569+ x=$(i=1 ; while let " i < 10 " ; do echo $i ; let ++i ; done )
8570+ }
8571+ function reread_TWHILE { x=$((
8572+ i=1; while (( i < 10 )); do echo $i; let ++i; done
8573+ )|tr u x); }
8574+ function reread_TWHILE {
8575+ x=$(( i=1 ; while let " i < 10 " ; do echo $i ; let ++i ; done ) | tr u x )
8576+ }
8577+ inline_TUNTIL() {
8578+ i=10; until (( !--i )) ; do echo $i; done
8579+ }
8580+ inline_TUNTIL() {
8581+ i=10
8582+ until let " !--i "
8583+ do
8584+ echo $i
8585+ done
8586+ }
8587+ function comsub_TUNTIL { x=$(
8588+ i=10; until (( !--i )) ; do echo $i; done
8589+ ); }
8590+ function comsub_TUNTIL {
8591+ x=$(i=10 ; until let " !--i " ; do echo $i ; done )
8592+ }
8593+ function reread_TUNTIL { x=$((
8594+ i=10; until (( !--i )) ; do echo $i; done
8595+ )|tr u x); }
8596+ function reread_TUNTIL {
8597+ x=$(( i=10 ; until let " !--i " ; do echo $i ; done ) | tr u x )
8598+ }
8599+ inline_TCOPROC() {
8600+ cat * |& ls
8601+ }
8602+ inline_TCOPROC() {
8603+ cat * |&
8604+ ls
8605+ }
8606+ function comsub_TCOPROC { x=$(
8607+ cat * |& ls
8608+ ); }
8609+ function comsub_TCOPROC {
8610+ x=$(cat * |& ls )
8611+ }
8612+ function reread_TCOPROC { x=$((
8613+ cat * |& ls
8614+ )|tr u x); }
8615+ function reread_TCOPROC {
8616+ x=$(( cat * |& ls ) | tr u x )
8617+ }
8618+ inline_TFUNCT_TBRACE_TASYNC() {
8619+ function korn { echo eins; echo zwei ; }
8620+ bourne () { logger * & }
8621+ }
8622+ inline_TFUNCT_TBRACE_TASYNC() {
8623+ function korn {
8624+ echo eins
8625+ echo zwei
8626+ }
8627+ bourne() {
8628+ logger * &
8629+ }
8630+ }
8631+ function comsub_TFUNCT_TBRACE_TASYNC { x=$(
8632+ function korn { echo eins; echo zwei ; }
8633+ bourne () { logger * & }
8634+ ); }
8635+ function comsub_TFUNCT_TBRACE_TASYNC {
8636+ x=$(function korn { echo eins ; echo zwei ; } ; bourne() { logger * & } )
8637+ }
8638+ function reread_TFUNCT_TBRACE_TASYNC { x=$((
8639+ function korn { echo eins; echo zwei ; }
8640+ bourne () { logger * & }
8641+ )|tr u x); }
8642+ function reread_TFUNCT_TBRACE_TASYNC {
8643+ x=$(( function korn { echo eins ; echo zwei ; } ; bourne() { logger * & } ) | tr u x )
8644+ }
8645+ inline_IOREAD_IOCAT() {
8646+ tr x u 0<foo >>bar
8647+ }
8648+ inline_IOREAD_IOCAT() {
8649+ tr x u <foo >>bar
8650+ }
8651+ function comsub_IOREAD_IOCAT { x=$(
8652+ tr x u 0<foo >>bar
8653+ ); }
8654+ function comsub_IOREAD_IOCAT {
8655+ x=$(tr x u <foo >>bar )
8656+ }
8657+ function reread_IOREAD_IOCAT { x=$((
8658+ tr x u 0<foo >>bar
8659+ )|tr u x); }
8660+ function reread_IOREAD_IOCAT {
8661+ x=$(( tr x u <foo >>bar ) | tr u x )
8662+ }
8663+ inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() {
8664+ cat >|bar <<'EOFN'
8665+ foo
8666+ EOFN
8667+ }
8668+ inline_IOWRITE_IOCLOB_IOHERE_noIOSKIP() {
8669+ cat >|bar <<"EOFN"
8670+ foo
8671+ EOFN
8672+
8673+ }
8674+ function comsub_IOWRITE_IOCLOB_IOHERE_noIOSKIP { x=$(
8675+ cat >|bar <<'EOFN'
8676+ foo
8677+ EOFN
8678+ ); }
8679+ function comsub_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
8680+ x=$(cat >|bar <<"EOFN"
8681+ foo
8682+ EOFN
8683+ )
8684+ }
8685+ function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP { x=$((
8686+ cat >|bar <<'EOFN'
8687+ foo
8688+ EOFN
8689+ )|tr u x); }
8690+ function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
8691+ x=$(( cat >|bar <<"EOFN"
8692+ foo
8693+ EOFN
8694+ ) | tr u x )
8695+ }
8696+ inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
8697+ cat 1>bar <<-EOFI
8698+ foo
8699+ EOFI
8700+ }
8701+ inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
8702+ cat >bar <<-EOFI
8703+ foo
8704+ EOFI
8705+
8706+ }
8707+ function comsub_IOWRITE_noIOCLOB_IOHERE_IOSKIP { x=$(
8708+ cat 1>bar <<-EOFI
8709+ foo
8710+ EOFI
8711+ ); }
8712+ function comsub_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
8713+ x=$(cat >bar <<-EOFI
8714+ foo
8715+ EOFI
8716+ )
8717+ }
8718+ function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP { x=$((
8719+ cat 1>bar <<-EOFI
8720+ foo
8721+ EOFI
8722+ )|tr u x); }
8723+ function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
8724+ x=$(( cat >bar <<-EOFI
8725+ foo
8726+ EOFI
8727+ ) | tr u x )
8728+ }
8729+ inline_IORDWR_IODUP() {
8730+ sh 1<>/dev/console 0<&1 2>&1
8731+ }
8732+ inline_IORDWR_IODUP() {
8733+ sh 1<>/dev/console <&1 2>&1
8734+ }
8735+ function comsub_IORDWR_IODUP { x=$(
8736+ sh 1<>/dev/console 0<&1 2>&1
8737+ ); }
8738+ function comsub_IORDWR_IODUP {
8739+ x=$(sh 1<>/dev/console <&1 2>&1 )
8740+ }
8741+ function reread_IORDWR_IODUP { x=$((
8742+ sh 1<>/dev/console 0<&1 2>&1
8743+ )|tr u x); }
8744+ function reread_IORDWR_IODUP {
8745+ x=$(( sh 1<>/dev/console <&1 2>&1 ) | tr u x )
8746+ }
8747+ inline_COMSUB_EXPRSUB() {
8748+ echo $(true) $((1+ 2))
8749+ }
8750+ inline_COMSUB_EXPRSUB() {
8751+ echo $(true ) $((1+ 2))
8752+ }
8753+ function comsub_COMSUB_EXPRSUB { x=$(
8754+ echo $(true) $((1+ 2))
8755+ ); }
8756+ function comsub_COMSUB_EXPRSUB {
8757+ x=$(echo $(true ) $((1+ 2)) )
8758+ }
8759+ function reread_COMSUB_EXPRSUB { x=$((
8760+ echo $(true) $((1+ 2))
8761+ )|tr u x); }
8762+ function reread_COMSUB_EXPRSUB {
8763+ x=$(( echo $(true ) $((1+ 2)) ) | tr u x )
8764+ }
8765+ inline_QCHAR_OQUOTE_CQUOTE() {
8766+ echo fo\ob\"a\`r\'b\$az
8767+ echo "fo\ob\"a\`r\'b\$az"
8768+ echo 'fo\ob\"a\`r'\''b\$az'
8769+ }
8770+ inline_QCHAR_OQUOTE_CQUOTE() {
8771+ echo fo\ob\"a\`r\'b\$az
8772+ echo "fo\ob\"a\`r\'b\$az"
8773+ echo "fo\\ob\\\"a\\\`r"\'"b\\\$az"
8774+ }
8775+ function comsub_QCHAR_OQUOTE_CQUOTE { x=$(
8776+ echo fo\ob\"a\`r\'b\$az
8777+ echo "fo\ob\"a\`r\'b\$az"
8778+ echo 'fo\ob\"a\`r'\''b\$az'
8779+ ); }
8780+ function comsub_QCHAR_OQUOTE_CQUOTE {
8781+ x=$(echo fo\ob\"a\`r\'b\$az ; echo "fo\ob\"a\`r\'b\$az" ; echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" )
8782+ }
8783+ function reread_QCHAR_OQUOTE_CQUOTE { x=$((
8784+ echo fo\ob\"a\`r\'b\$az
8785+ echo "fo\ob\"a\`r\'b\$az"
8786+ echo 'fo\ob\"a\`r'\''b\$az'
8787+ )|tr u x); }
8788+ function reread_QCHAR_OQUOTE_CQUOTE {
8789+ x=$(( echo fo\ob\"a\`r\'b\$az ; echo "fo\ob\"a\`r\'b\$az" ; echo "fo\\ob\\\"a\\\`r"\'"b\\\$az" ) | tr u x )
8790+ }
8791+ inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() {
8792+ [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
8793+ }
8794+ inline_OSUBST_CSUBST_OPAT_SPAT_CPAT() {
8795+ [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
8796+ }
8797+ function comsub_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$(
8798+ [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
8799+ ); }
8800+ function comsub_OSUBST_CSUBST_OPAT_SPAT_CPAT {
8801+ x=$([[ ${foo#bl\(u\)b} = @(bar|baz) ]] )
8802+ }
8803+ function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT { x=$((
8804+ [[ ${foo#bl\(u\)b} = @(bar|baz) ]]
8805+ )|tr u x); }
8806+ function reread_OSUBST_CSUBST_OPAT_SPAT_CPAT {
8807+ x=$(( [[ ${foo#bl\(u\)b} = @(bar|baz) ]] ) | tr u x )
8808+ }
8809+ inline_heredoc_closed() {
8810+ x=$(cat <<EOFN
8811+ note there must be no space between EOFN and )
8812+ EOFN); echo $x
8813+ }
8814+ inline_heredoc_closed() {
8815+ x=$(cat <<EOFN
8816+ note there must be no space between EOFN and )
8817+ EOFN
8818+ )
8819+ echo $x
8820+ }
8821+ function comsub_heredoc_closed { x=$(
8822+ x=$(cat <<EOFN
8823+ note there must be no space between EOFN and )
8824+ EOFN); echo $x
8825+ ); }
8826+ function comsub_heredoc_closed {
8827+ x=$(x=$(cat <<EOFN
8828+ note there must be no space between EOFN and )
8829+ EOFN
8830+ ) ; echo $x )
8831+ }
8832+ function reread_heredoc_closed { x=$((
8833+ x=$(cat <<EOFN
8834+ note there must be no space between EOFN and )
8835+ EOFN); echo $x
8836+ )|tr u x); }
8837+ function reread_heredoc_closed {
8838+ x=$(( x=$(cat <<EOFN
8839+ note there must be no space between EOFN and )
8840+ EOFN
8841+ ) ; echo $x ) | tr u x )
8842+ }
8843+ inline_heredoc_space() {
8844+ x=$(cat <<EOFN\
8845+ note the space between EOFN and ) is actually part of the here document marker
8846+ EOFN ); echo $x
8847+ }
8848+ inline_heredoc_space() {
8849+ x=$(cat <<EOFN\
8850+ note the space between EOFN and ) is actually part of the here document marker
8851+ EOFN
8852+ )
8853+ echo $x
8854+ }
8855+ function comsub_heredoc_space { x=$(
8856+ x=$(cat <<EOFN\
8857+ note the space between EOFN and ) is actually part of the here document marker
8858+ EOFN ); echo $x
8859+ ); }
8860+ function comsub_heredoc_space {
8861+ x=$(x=$(cat <<EOFN\
8862+ note the space between EOFN and ) is actually part of the here document marker
8863+ EOFN
8864+ ) ; echo $x )
8865+ }
8866+ function reread_heredoc_space { x=$((
8867+ x=$(cat <<EOFN\
8868+ note the space between EOFN and ) is actually part of the here document marker
8869+ EOFN ); echo $x
8870+ )|tr u x); }
8871+ function reread_heredoc_space {
8872+ x=$(( x=$(cat <<EOFN\
8873+ note the space between EOFN and ) is actually part of the here document marker
8874+ EOFN
8875+ ) ; echo $x ) | tr u x )
8876+ }
8877+ inline_patch_motd() {
8878+ x=$(sysctl -n kern.version | sed 1q)
8879+ [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd)" != $x ]] && \
8880+ ed -s /etc/motd 2>&1 <<-EOF
8881+ 1,/^\$/d
8882+ 0a
8883+ $x
8884+
8885+ .
8886+ wq
8887+ EOF)" = @(?) ]] && rm -f /etc/motd
8888+ if [[ ! -s /etc/motd ]]; then
8889+ install -c -o root -g wheel -m 664 /dev/null /etc/motd
8890+ print -- "$x\n" >/etc/motd
8891+ fi
8892+ }
8893+ inline_patch_motd() {
8894+ x=$(sysctl -n kern.version | sed 1q )
8895+ [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF
8896+ 1,/^\$/d
8897+ 0a
8898+ $x
8899+
8900+ .
8901+ wq
8902+ EOF
8903+ )" = @(?) ]] && rm -f /etc/motd
8904+ if [[ ! -s /etc/motd ]]
8905+ then
8906+ install -c -o root -g wheel -m 664 /dev/null /etc/motd
8907+ print -- "$x\n" >/etc/motd
8908+ fi
8909+ }
8910+ function comsub_patch_motd { x=$(
8911+ x=$(sysctl -n kern.version | sed 1q)
8912+ [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd)" != $x ]] && \
8913+ ed -s /etc/motd 2>&1 <<-EOF
8914+ 1,/^\$/d
8915+ 0a
8916+ $x
8917+
8918+ .
8919+ wq
8920+ EOF)" = @(?) ]] && rm -f /etc/motd
8921+ if [[ ! -s /etc/motd ]]; then
8922+ install -c -o root -g wheel -m 664 /dev/null /etc/motd
8923+ print -- "$x\n" >/etc/motd
8924+ fi
8925+ ); }
8926+ function comsub_patch_motd {
8927+ x=$(x=$(sysctl -n kern.version | sed 1q ) ; [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF
8928+ 1,/^\$/d
8929+ 0a
8930+ $x
8931+
8932+ .
8933+ wq
8934+ EOF
8935+ )" = @(?) ]] && rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then install -c -o root -g wheel -m 664 /dev/null /etc/motd ; print -- "$x\n" >/etc/motd ; fi )
8936+ }
8937+ function reread_patch_motd { x=$((
8938+ x=$(sysctl -n kern.version | sed 1q)
8939+ [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd)" != $x ]] && \
8940+ ed -s /etc/motd 2>&1 <<-EOF
8941+ 1,/^\$/d
8942+ 0a
8943+ $x
8944+
8945+ .
8946+ wq
8947+ EOF)" = @(?) ]] && rm -f /etc/motd
8948+ if [[ ! -s /etc/motd ]]; then
8949+ install -c -o root -g wheel -m 664 /dev/null /etc/motd
8950+ print -- "$x\n" >/etc/motd
8951+ fi
8952+ )|tr u x); }
8953+ function reread_patch_motd {
8954+ x=$(( x=$(sysctl -n kern.version | sed 1q ) ; [[ -s /etc/motd && "$([[ "$(head -1 /etc/motd )" != $x ]] && ed -s /etc/motd 2>&1 <<-EOF
8955+ 1,/^\$/d
8956+ 0a
8957+ $x
8958+
8959+ .
8960+ wq
8961+ EOF
8962+ )" = @(?) ]] && rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then install -c -o root -g wheel -m 664 /dev/null /etc/motd ; print -- "$x\n" >/etc/motd ; fi ) | tr u x )
8963+ }
8964+ inline_wdarrassign() {
8965+ case x in
8966+ x) a+=b; c+=(d e)
8967+ esac
8968+ }
8969+ inline_wdarrassign() {
8970+ case x in
8971+ (x)
8972+ a+=b
8973+ set -A c+ -- d e
8974+ ;;
8975+ esac
8976+ }
8977+ function comsub_wdarrassign { x=$(
8978+ case x in
8979+ x) a+=b; c+=(d e)
8980+ esac
8981+ ); }
8982+ function comsub_wdarrassign {
8983+ x=$(case x in (x) a+=b ; set -A c+ -- d e ;; esac )
8984+ }
8985+ function reread_wdarrassign { x=$((
8986+ case x in
8987+ x) a+=b; c+=(d e)
8988+ esac
8989+ )|tr u x); }
8990+ function reread_wdarrassign {
8991+ x=$(( case x in (x) a+=b ; set -A c+ -- d e ;; esac ) | tr u x )
8992+ }
8993+---
8994+name: comsub-torture-io
8995+description:
8996+ Check the tree dump functions work correctly with I/O redirection
8997+stdin:
8998+ if [[ -z $__progname ]]; then echo >&2 call me with __progname; exit 1; fi
8999+ while IFS= read -r line; do
9000+ if [[ $line = '#1' ]]; then
9001+ lastf=0
9002+ continue
9003+ elif [[ $line = EOFN* ]]; then
9004+ fbody=$fbody$'\n'$line
9005+ continue
9006+ elif [[ $line != '#'* ]]; then
9007+ fbody=$fbody$'\n\t'$line
9008+ continue
9009+ fi
9010+ if (( lastf )); then
9011+ x="inline_${nextf}() {"$fbody$'\n}\n'
9012+ print -nr -- "$x"
9013+ print -r -- "${x}typeset -f inline_$nextf" | "$__progname"
9014+ x="function comsub_$nextf { x=\$("$fbody$'\n); }\n'
9015+ print -nr -- "$x"
9016+ print -r -- "${x}typeset -f comsub_$nextf" | "$__progname"
9017+ x="function reread_$nextf { x=\$(("$fbody$'\n)|tr u x); }\n'
9018+ print -nr -- "$x"
9019+ print -r -- "${x}typeset -f reread_$nextf" | "$__progname"
9020+ fi
9021+ lastf=1
9022+ fbody=
9023+ nextf=${line#?}
9024+ done <<'EOD'
9025+ #1
9026+ #TCOM
9027+ vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
9028+ #TPAREN_TPIPE_TLIST
9029+ (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
9030+ #TAND_TOR
9031+ cmd >&3 && >&3 echo ja || echo >&3 nein
9032+ #TSELECT
9033+ select file in *; do echo "<$file>" ; break >&3 ; done >&3
9034+ #TFOR_TTIME
9035+ for i in {1,2,3} ; do time >&3 echo $i ; done >&3
9036+ #TCASE
9037+ case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3
9038+ #TIF_TBANG_TDBRACKET_TELIF
9039+ if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3
9040+ #TWHILE
9041+ i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
9042+ #TUNTIL
9043+ i=10; until (( !--i )) >&3 ; do echo $i; done >&3
9044+ #TCOPROC
9045+ cat * >&3 |& >&3 ls
9046+ #TFUNCT_TBRACE_TASYNC
9047+ function korn { echo eins; echo >&3 zwei ; }
9048+ bourne () { logger * >&3 & }
9049+ #COMSUB_EXPRSUB
9050+ echo $(true >&3) $((1+ 2))
9051+ #0
9052+ EOD
9053+expected-stdout:
9054+ inline_TCOM() {
9055+ vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
9056+ }
9057+ inline_TCOM() {
9058+ vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3
9059+ }
9060+ function comsub_TCOM { x=$(
9061+ vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
9062+ ); }
9063+ function comsub_TCOM {
9064+ x=$(vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3 )
9065+ }
9066+ function reread_TCOM { x=$((
9067+ vara=1 varb='2 3' cmd arg1 $arg2 "$arg3 4" >&3
9068+ )|tr u x); }
9069+ function reread_TCOM {
9070+ x=$(( vara=1 varb="2 3" cmd arg1 $arg2 "$arg3 4" >&3 ) | tr u x )
9071+ }
9072+ inline_TPAREN_TPIPE_TLIST() {
9073+ (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
9074+ }
9075+ inline_TPAREN_TPIPE_TLIST() {
9076+ ( echo $foo | tr -dc 0-9 >&3
9077+ echo >&3 ) >&3
9078+ }
9079+ function comsub_TPAREN_TPIPE_TLIST { x=$(
9080+ (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
9081+ ); }
9082+ function comsub_TPAREN_TPIPE_TLIST {
9083+ x=$(( echo $foo | tr -dc 0-9 >&3 ; echo >&3 ) >&3 )
9084+ }
9085+ function reread_TPAREN_TPIPE_TLIST { x=$((
9086+ (echo $foo | tr -dc 0-9 >&3; echo >&3) >&3
9087+ )|tr u x); }
9088+ function reread_TPAREN_TPIPE_TLIST {
9089+ x=$(( ( echo $foo | tr -dc 0-9 >&3 ; echo >&3 ) >&3 ) | tr u x )
9090+ }
9091+ inline_TAND_TOR() {
9092+ cmd >&3 && >&3 echo ja || echo >&3 nein
9093+ }
9094+ inline_TAND_TOR() {
9095+ cmd >&3 && echo ja >&3 || echo nein >&3
9096+ }
9097+ function comsub_TAND_TOR { x=$(
9098+ cmd >&3 && >&3 echo ja || echo >&3 nein
9099+ ); }
9100+ function comsub_TAND_TOR {
9101+ x=$(cmd >&3 && echo ja >&3 || echo nein >&3 )
9102+ }
9103+ function reread_TAND_TOR { x=$((
9104+ cmd >&3 && >&3 echo ja || echo >&3 nein
9105+ )|tr u x); }
9106+ function reread_TAND_TOR {
9107+ x=$(( cmd >&3 && echo ja >&3 || echo nein >&3 ) | tr u x )
9108+ }
9109+ inline_TSELECT() {
9110+ select file in *; do echo "<$file>" ; break >&3 ; done >&3
9111+ }
9112+ inline_TSELECT() {
9113+ select file in *
9114+ do
9115+ echo "<$file>"
9116+ break >&3
9117+ done >&3
9118+ }
9119+ function comsub_TSELECT { x=$(
9120+ select file in *; do echo "<$file>" ; break >&3 ; done >&3
9121+ ); }
9122+ function comsub_TSELECT {
9123+ x=$(select file in * ; do echo "<$file>" ; break >&3 ; done >&3 )
9124+ }
9125+ function reread_TSELECT { x=$((
9126+ select file in *; do echo "<$file>" ; break >&3 ; done >&3
9127+ )|tr u x); }
9128+ function reread_TSELECT {
9129+ x=$(( select file in * ; do echo "<$file>" ; break >&3 ; done >&3 ) | tr u x )
9130+ }
9131+ inline_TFOR_TTIME() {
9132+ for i in {1,2,3} ; do time >&3 echo $i ; done >&3
9133+ }
9134+ inline_TFOR_TTIME() {
9135+ for i in {1,2,3}
9136+ do
9137+ time echo $i >&3
9138+ done >&3
9139+ }
9140+ function comsub_TFOR_TTIME { x=$(
9141+ for i in {1,2,3} ; do time >&3 echo $i ; done >&3
9142+ ); }
9143+ function comsub_TFOR_TTIME {
9144+ x=$(for i in {1,2,3} ; do time echo $i >&3 ; done >&3 )
9145+ }
9146+ function reread_TFOR_TTIME { x=$((
9147+ for i in {1,2,3} ; do time >&3 echo $i ; done >&3
9148+ )|tr u x); }
9149+ function reread_TFOR_TTIME {
9150+ x=$(( for i in {1,2,3} ; do time echo $i >&3 ; done >&3 ) | tr u x )
9151+ }
9152+ inline_TCASE() {
9153+ case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3
9154+ }
9155+ inline_TCASE() {
9156+ case $foo in
9157+ (1)
9158+ echo eins >&3
9159+ ;&
9160+ (2)
9161+ echo zwei >&3
9162+ ;|
9163+ (*)
9164+ echo kann net bis drei zählen >&3
9165+ ;;
9166+ esac >&3
9167+ }
9168+ function comsub_TCASE { x=$(
9169+ case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3
9170+ ); }
9171+ function comsub_TCASE {
9172+ x=$(case $foo in (1) echo eins >&3 ;& (2) echo zwei >&3 ;| (*) echo kann net bis drei zählen >&3 ;; esac >&3 )
9173+ }
9174+ function reread_TCASE { x=$((
9175+ case $foo in 1) echo eins >&3;& 2) echo zwei >&3 ;| *) echo kann net bis drei zählen >&3;; esac >&3
9176+ )|tr u x); }
9177+ function reread_TCASE {
9178+ x=$(( case $foo in (1) echo eins >&3 ;& (2) echo zwei >&3 ;| (*) echo kann net bis drei zählen >&3 ;; esac >&3 ) | tr u x )
9179+ }
9180+ inline_TIF_TBANG_TDBRACKET_TELIF() {
9181+ if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3
9182+ }
9183+ inline_TIF_TBANG_TDBRACKET_TELIF() {
9184+ if ! [[ 1 = 1 ]] >&3
9185+ then
9186+ echo eins
9187+ elif [[ 1 = 2 ]] >&3
9188+ then
9189+ echo zwei
9190+ else
9191+ echo drei
9192+ fi >&3
9193+ }
9194+ function comsub_TIF_TBANG_TDBRACKET_TELIF { x=$(
9195+ if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3
9196+ ); }
9197+ function comsub_TIF_TBANG_TDBRACKET_TELIF {
9198+ x=$(if ! [[ 1 = 1 ]] >&3 ; then echo eins ; elif [[ 1 = 2 ]] >&3 ; then echo zwei ; else echo drei ; fi >&3 )
9199+ }
9200+ function reread_TIF_TBANG_TDBRACKET_TELIF { x=$((
9201+ if ! [[ 1 = 1 ]] >&3 ; then echo eins; elif [[ 1 = 2 ]] >&3; then echo zwei ;else echo drei; fi >&3
9202+ )|tr u x); }
9203+ function reread_TIF_TBANG_TDBRACKET_TELIF {
9204+ x=$(( if ! [[ 1 = 1 ]] >&3 ; then echo eins ; elif [[ 1 = 2 ]] >&3 ; then echo zwei ; else echo drei ; fi >&3 ) | tr u x )
9205+ }
9206+ inline_TWHILE() {
9207+ i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
9208+ }
9209+ inline_TWHILE() {
9210+ i=1
9211+ while let " i < 10 " >&3
9212+ do
9213+ echo $i
9214+ let ++i
9215+ done >&3
9216+ }
9217+ function comsub_TWHILE { x=$(
9218+ i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
9219+ ); }
9220+ function comsub_TWHILE {
9221+ x=$(i=1 ; while let " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 )
9222+ }
9223+ function reread_TWHILE { x=$((
9224+ i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
9225+ )|tr u x); }
9226+ function reread_TWHILE {
9227+ x=$(( i=1 ; while let " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x )
9228+ }
9229+ inline_TUNTIL() {
9230+ i=10; until (( !--i )) >&3 ; do echo $i; done >&3
9231+ }
9232+ inline_TUNTIL() {
9233+ i=10
9234+ until let " !--i " >&3
9235+ do
9236+ echo $i
9237+ done >&3
9238+ }
9239+ function comsub_TUNTIL { x=$(
9240+ i=10; until (( !--i )) >&3 ; do echo $i; done >&3
9241+ ); }
9242+ function comsub_TUNTIL {
9243+ x=$(i=10 ; until let " !--i " >&3 ; do echo $i ; done >&3 )
9244+ }
9245+ function reread_TUNTIL { x=$((
9246+ i=10; until (( !--i )) >&3 ; do echo $i; done >&3
9247+ )|tr u x); }
9248+ function reread_TUNTIL {
9249+ x=$(( i=10 ; until let " !--i " >&3 ; do echo $i ; done >&3 ) | tr u x )
9250+ }
9251+ inline_TCOPROC() {
9252+ cat * >&3 |& >&3 ls
9253+ }
9254+ inline_TCOPROC() {
9255+ cat * >&3 |&
9256+ ls >&3
9257+ }
9258+ function comsub_TCOPROC { x=$(
9259+ cat * >&3 |& >&3 ls
9260+ ); }
9261+ function comsub_TCOPROC {
9262+ x=$(cat * >&3 |& ls >&3 )
9263+ }
9264+ function reread_TCOPROC { x=$((
9265+ cat * >&3 |& >&3 ls
9266+ )|tr u x); }
9267+ function reread_TCOPROC {
9268+ x=$(( cat * >&3 |& ls >&3 ) | tr u x )
9269+ }
9270+ inline_TFUNCT_TBRACE_TASYNC() {
9271+ function korn { echo eins; echo >&3 zwei ; }
9272+ bourne () { logger * >&3 & }
9273+ }
9274+ inline_TFUNCT_TBRACE_TASYNC() {
9275+ function korn {
9276+ echo eins
9277+ echo zwei >&3
9278+ }
9279+ bourne() {
9280+ logger * >&3 &
9281+ }
9282+ }
9283+ function comsub_TFUNCT_TBRACE_TASYNC { x=$(
9284+ function korn { echo eins; echo >&3 zwei ; }
9285+ bourne () { logger * >&3 & }
9286+ ); }
9287+ function comsub_TFUNCT_TBRACE_TASYNC {
9288+ x=$(function korn { echo eins ; echo zwei >&3 ; } ; bourne() { logger * >&3 & } )
9289+ }
9290+ function reread_TFUNCT_TBRACE_TASYNC { x=$((
9291+ function korn { echo eins; echo >&3 zwei ; }
9292+ bourne () { logger * >&3 & }
9293+ )|tr u x); }
9294+ function reread_TFUNCT_TBRACE_TASYNC {
9295+ x=$(( function korn { echo eins ; echo zwei >&3 ; } ; bourne() { logger * >&3 & } ) | tr u x )
9296+ }
9297+ inline_COMSUB_EXPRSUB() {
9298+ echo $(true >&3) $((1+ 2))
9299+ }
9300+ inline_COMSUB_EXPRSUB() {
9301+ echo $(true >&3 ) $((1+ 2))
9302+ }
9303+ function comsub_COMSUB_EXPRSUB { x=$(
9304+ echo $(true >&3) $((1+ 2))
9305+ ); }
9306+ function comsub_COMSUB_EXPRSUB {
9307+ x=$(echo $(true >&3 ) $((1+ 2)) )
9308+ }
9309+ function reread_COMSUB_EXPRSUB { x=$((
9310+ echo $(true >&3) $((1+ 2))
9311+ )|tr u x); }
9312+ function reread_COMSUB_EXPRSUB {
9313+ x=$(( echo $(true >&3 ) $((1+ 2)) ) | tr u x )
9314+ }
9315+---
67779316 name: test-stnze-1
67789317 description:
67799318 Check that the short form [ $x ] works
@@ -6864,9 +9403,9 @@ expected-stdout:
68649403 11 0
68659404 12 0
68669405 ---
6867-name: event-subst-1a
9406+name: event-subst-3
68689407 description:
6869- Check that '!' substitution in interactive mode works
9408+ Check that '!' substitution in noninteractive mode is ignored
68709409 category: !smksh
68719410 file-setup: file 755 "falsetto"
68729411 #! /bin/sh
@@ -6875,64 +9414,6 @@ file-setup: file 755 "falsetto"
68759414 file-setup: file 755 "!false"
68769415 #! /bin/sh
68779416 echo si
6878-arguments: !-i!
6879-stdin:
6880- export PATH=.:$PATH
6881- falsetto
6882- echo yeap
6883- !false
6884-expected-exit: 42
6885-expected-stdout:
6886- molto bene
6887- yeap
6888- molto bene
6889-expected-stderr-pattern:
6890- /.*/
6891----
6892-name: event-subst-1b
6893-description:
6894- Check that '!' substitution in interactive mode works
6895- even when a space separates it from the search command,
6896- which is not what GNU bash provides but required for the
6897- other regression tests below to check
6898-category: !smksh
6899-file-setup: file 755 "falsetto"
6900- #! /bin/sh
6901- echo molto bene
6902- exit 42
6903-file-setup: file 755 "!"
6904- #! /bin/sh
6905- echo si
6906-arguments: !-i!
6907-stdin:
6908- export PATH=.:$PATH
6909- falsetto
6910- echo yeap
6911- ! false
6912-expected-exit: 42
6913-expected-stdout:
6914- molto bene
6915- yeap
6916- molto bene
6917-expected-stderr-pattern:
6918- /.*/
6919----
6920-name: event-subst-2
6921-description:
6922- Check that '!' substitution in interactive mode
6923- does not break things
6924-category: !smksh
6925-file-setup: file 755 "falsetto"
6926- #! /bin/sh
6927- echo molto bene
6928- exit 42
6929-file-setup: file 755 "!"
6930- #! /bin/sh
6931- echo si
6932-arguments: !-i!
6933-env-setup: !ENV=./Env!
6934-file-setup: file 644 "Env"
6935- PS1=X
69369417 stdin:
69379418 export PATH=.:$PATH
69389419 falsetto
@@ -6946,18 +9427,16 @@ stdin:
69469427 expected-stdout:
69479428 molto bene
69489429 yeap
6949- molto bene
9430+ si
69509431 meow
6951- molto bene
6952- = 42
9432+ = 0
69539433 foo
6954-expected-stderr-pattern:
6955- /.*/
69569434 ---
6957-name: event-subst-3
9435+name: event-subst-0
69589436 description:
6959- Check that '!' substitution in noninteractive mode is ignored
6960-category: !smksh
9437+ Check that '!' substitution in interactive mode is ignored
9438+need-ctty: yes
9439+arguments: !-i!
69619440 file-setup: file 755 "falsetto"
69629441 #! /bin/sh
69639442 echo molto bene
@@ -6982,6 +9461,8 @@ expected-stdout:
69829461 meow
69839462 = 0
69849463 foo
9464+expected-stderr-pattern:
9465+ /.*/
69859466 ---
69869467 name: nounset-1
69879468 description:
@@ -7152,11 +9633,28 @@ expected-stdout:
71529633 2 a .
71539634 3 .
71549635 ---
9636+name: nameref-4
9637+description:
9638+ Ensure we don't run in an infinite loop
9639+time-limit: 3
9640+stdin:
9641+ baz() {
9642+ typeset -n foo=foo
9643+ foo[0]=bar
9644+ }
9645+ set -A foo bad
9646+ echo sind $foo .
9647+ baz
9648+ echo blah $foo .
9649+expected-stdout:
9650+ sind bad .
9651+ blah bar .
9652+---
71559653 name: better-parens-1a
71569654 description:
71579655 Check support for ((…)) and $((…)) vs (…) and $(…)
71589656 stdin:
7159- if ( (echo fubar) | tr u x); then
9657+ if ( (echo fubar)|tr u x); then
71609658 echo ja
71619659 else
71629660 echo nein
@@ -7169,7 +9667,15 @@ name: better-parens-1b
71699667 description:
71709668 Check support for ((…)) and $((…)) vs (…) and $(…)
71719669 stdin:
7172- echo $( (echo fubar) | tr u x) $?
9670+ echo $( (echo fubar)|tr u x) $?
9671+expected-stdout:
9672+ fxbar 0
9673+---
9674+name: better-parens-1c
9675+description:
9676+ Check support for ((…)) and $((…)) vs (…) and $(…)
9677+stdin:
9678+ x=$( (echo fubar)|tr u x); echo $x $?
71739679 expected-stdout:
71749680 fxbar 0
71759681 ---
@@ -7177,7 +9683,7 @@ name: better-parens-2a
71779683 description:
71789684 Check support for ((…)) and $((…)) vs (…) and $(…)
71799685 stdin:
7180- if ((echo fubar) | tr u x); then
9686+ if ((echo fubar)|tr u x); then
71819687 echo ja
71829688 else
71839689 echo nein
@@ -7190,7 +9696,15 @@ name: better-parens-2b
71909696 description:
71919697 Check support for ((…)) and $((…)) vs (…) and $(…)
71929698 stdin:
7193- echo $((echo fubar) | tr u x) $?
9699+ echo $((echo fubar)|tr u x) $?
9700+expected-stdout:
9701+ fxbar 0
9702+---
9703+name: better-parens-2c
9704+description:
9705+ Check support for ((…)) and $((…)) vs (…) and $(…)
9706+stdin:
9707+ x=$((echo fubar)|tr u x); echo $x $?
71949708 expected-stdout:
71959709 fxbar 0
71969710 ---
@@ -7198,7 +9712,7 @@ name: better-parens-3a
71989712 description:
71999713 Check support for ((…)) and $((…)) vs (…) and $(…)
72009714 stdin:
7201- if ( (echo fubar) | (tr u x)); then
9715+ if ( (echo fubar)|(tr u x)); then
72029716 echo ja
72039717 else
72049718 echo nein
@@ -7211,7 +9725,15 @@ name: better-parens-3b
72119725 description:
72129726 Check support for ((…)) and $((…)) vs (…) and $(…)
72139727 stdin:
7214- echo $( (echo fubar) | (tr u x)) $?
9728+ echo $( (echo fubar)|(tr u x)) $?
9729+expected-stdout:
9730+ fxbar 0
9731+---
9732+name: better-parens-3c
9733+description:
9734+ Check support for ((…)) and $((…)) vs (…) and $(…)
9735+stdin:
9736+ x=$( (echo fubar)|(tr u x)); echo $x $?
72159737 expected-stdout:
72169738 fxbar 0
72179739 ---
@@ -7219,7 +9741,7 @@ name: better-parens-4a
72199741 description:
72209742 Check support for ((…)) and $((…)) vs (…) and $(…)
72219743 stdin:
7222- if ((echo fubar) | (tr u x)); then
9744+ if ((echo fubar)|(tr u x)); then
72239745 echo ja
72249746 else
72259747 echo nein
@@ -7232,7 +9754,15 @@ name: better-parens-4b
72329754 description:
72339755 Check support for ((…)) and $((…)) vs (…) and $(…)
72349756 stdin:
7235- echo $((echo fubar) | (tr u x)) $?
9757+ echo $((echo fubar)|(tr u x)) $?
9758+expected-stdout:
9759+ fxbar 0
9760+---
9761+name: better-parens-4c
9762+description:
9763+ Check support for ((…)) and $((…)) vs (…) and $(…)
9764+stdin:
9765+ x=$((echo fubar)|(tr u x)); echo $x $?
72369766 expected-stdout:
72379767 fxbar 0
72389768 ---
@@ -7441,3 +9971,163 @@ expected-stdout:
74419971 24 ?lnnix/nix =lnnix/nix: No such file or directory !2
74429972 25 ?lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself =lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself/lnself: Too many levels of symbolic links !62
74439973 ---
9974+name: realpath-2
9975+description:
9976+ Ensure that exactly two leading slashes are not collapsed
9977+ POSIX guarantees this exception, e.g. for UNC paths on Cygwin
9978+category: os:mirbsd
9979+stdin:
9980+ ln -s /bin t1
9981+ ln -s //bin t2
9982+ ln -s ///bin t3
9983+ realpath /bin
9984+ realpath //bin
9985+ realpath ///bin
9986+ realpath /usr/bin
9987+ realpath /usr//bin
9988+ realpath /usr///bin
9989+ realpath t1
9990+ realpath t2
9991+ realpath t3
9992+ rm -f t1 t2 t3
9993+ cd //usr/bin
9994+ pwd
9995+ cd ../lib
9996+ pwd
9997+ realpath //usr/include/../bin
9998+expected-stdout:
9999+ /bin
10000+ //bin
10001+ /bin
10002+ /usr/bin
10003+ /usr/bin
10004+ /usr/bin
10005+ /bin
10006+ //bin
10007+ /bin
10008+ //usr/bin
10009+ //usr/lib
10010+ //usr/bin
10011+---
10012+name: crash-1
10013+description:
10014+ Crashed during March 2011, fixed on vernal equinōx ☺
10015+category: os:mirbsd,os:openbsd
10016+stdin:
10017+ export MALLOC_OPTIONS=FGJPRSX
10018+ "$__progname" -c 'x=$(tr z r <<<baz); echo $x'
10019+expected-stdout:
10020+ bar
10021+---
10022+name: debian-117-1
10023+description:
10024+ Check test - bug#465250
10025+stdin:
10026+ test \( ! -e \) ; echo $?
10027+expected-stdout:
10028+ 1
10029+---
10030+name: debian-117-2
10031+description:
10032+ Check test - bug#465250
10033+stdin:
10034+ test \( -e \) ; echo $?
10035+expected-stdout:
10036+ 0
10037+---
10038+name: debian-117-3
10039+description:
10040+ Check test - bug#465250
10041+stdin:
10042+ test ! -e ; echo $?
10043+expected-stdout:
10044+ 1
10045+---
10046+name: debian-117-4
10047+description:
10048+ Check test - bug#465250
10049+stdin:
10050+ test -e ; echo $?
10051+expected-stdout:
10052+ 0
10053+---
10054+name: case-zsh
10055+description:
10056+ Check that zsh case variants work
10057+stdin:
10058+ case 'b' in
10059+ a) echo a ;;
10060+ b) echo b ;;
10061+ c) echo c ;;
10062+ *) echo x ;;
10063+ esac
10064+ echo =
10065+ case 'b' in
10066+ a) echo a ;&
10067+ b) echo b ;&
10068+ c) echo c ;&
10069+ *) echo x ;&
10070+ esac
10071+ echo =
10072+ case 'b' in
10073+ a) echo a ;|
10074+ b) echo b ;|
10075+ c) echo c ;|
10076+ *) echo x ;|
10077+ esac
10078+expected-stdout:
10079+ b
10080+ =
10081+ b
10082+ c
10083+ x
10084+ =
10085+ b
10086+ x
10087+---
10088+name: stateptr-underflow
10089+description:
10090+ This check overflows an Xrestpos stored in a short in R40
10091+category: fastbox
10092+stdin:
10093+ function Lb64decode {
10094+ [[ -o utf8-mode ]]; local u=$?
10095+ set +U
10096+ local c s="$*" t=
10097+ [[ -n $s ]] || { s=$(cat;print x); s=${s%x}; }
10098+ local -i i=0 n=${#s} p=0 v x
10099+ local -i16 o
10100+
10101+ while (( i < n )); do
10102+ c=${s:(i++):1}
10103+ case $c {
10104+ (=) break ;;
10105+ ([A-Z]) (( v = 1#$c - 65 )) ;;
10106+ ([a-z]) (( v = 1#$c - 71 )) ;;
10107+ ([0-9]) (( v = 1#$c + 4 )) ;;
10108+ (+) v=62 ;;
10109+ (/) v=63 ;;
10110+ (*) continue ;;
10111+ }
10112+ (( x = (x << 6) | v ))
10113+ case $((p++)) {
10114+ (0) continue ;;
10115+ (1) (( o = (x >> 4) & 255 )) ;;
10116+ (2) (( o = (x >> 2) & 255 )) ;;
10117+ (3) (( o = x & 255 ))
10118+ p=0
10119+ ;;
10120+ }
10121+ t=$t\\x${o#16#}
10122+ done
10123+ print -n $t
10124+ (( u )) || set -U
10125+ }
10126+
10127+ i=-1
10128+ s=
10129+ while (( ++i < 12120 )); do
10130+ s+=a
10131+ done
10132+ Lb64decode $s >/dev/null
10133+---
--- a/src/edit.c
+++ b/src/edit.c
@@ -1,10 +1,11 @@
11 /* $OpenBSD: edit.c,v 1.34 2010/05/20 01:13:07 fgsch Exp $ */
2-/* $OpenBSD: edit.h,v 1.8 2005/03/28 21:28:22 deraadt Exp $ */
3-/* $OpenBSD: emacs.c,v 1.42 2009/06/02 06:47:47 halex Exp $ */
2+/* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */
3+/* $OpenBSD: emacs.c,v 1.44 2011/09/05 04:50:33 marco Exp $ */
44 /* $OpenBSD: vi.c,v 1.26 2009/06/29 22:50:19 martynas Exp $ */
55
66 /*-
7- * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
7+ * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
8+ * 2011, 2012
89 * Thorsten Glaser <tg@mirbsd.org>
910 *
1011 * Provided that these terms and disclaimer and all copyright notices
@@ -25,7 +26,7 @@
2526
2627 #include "sh.h"
2728
28-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.196 2010/07/25 11:35:40 tg Exp $");
29+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.234 2012/04/06 15:06:42 tg Exp $");
2930
3031 /*
3132 * in later versions we might use libtermcap for this, but since external
@@ -52,11 +53,14 @@ typedef struct {
5253
5354 static X_chars edchars;
5455
55-/* x_fc_glob() flags */
56+/* x_cf_glob() flags */
5657 #define XCF_COMMAND BIT(0) /* Do command completion */
5758 #define XCF_FILE BIT(1) /* Do file completion */
5859 #define XCF_FULLPATH BIT(2) /* command completion: store full path */
59-#define XCF_COMMAND_FILE (XCF_COMMAND|XCF_FILE)
60+#define XCF_COMMAND_FILE (XCF_COMMAND | XCF_FILE)
61+#define XCF_IS_COMMAND BIT(3) /* return flag: is command */
62+#define XCF_IS_SUBGLOB BIT(4) /* return flag: is $FOO or ~foo substitution */
63+#define XCF_IS_EXTGLOB BIT(5) /* return flag: is foo* expansion */
6064
6165 static char editmode;
6266 static int xx_cols; /* for Emacs mode */
@@ -65,12 +69,11 @@ static char holdbuf[LINE]; /* place to hold last edit buffer */
6569
6670 static int x_getc(void);
6771 static void x_putcf(int);
68-static bool x_mode(bool);
69-static int x_do_comment(char *, int, int *);
72+static void x_mode(bool);
73+static int x_do_comment(char *, ssize_t, ssize_t *);
7074 static void x_print_expansions(int, char *const *, bool);
71-static int x_cf_glob(int, const char *, int, int, int *, int *, char ***,
72- bool *);
73-static int x_longest_prefix(int, char *const *);
75+static int x_cf_glob(int *, const char *, int, int, int *, int *, char ***);
76+static size_t x_longest_prefix(int, char *const *);
7477 static int x_basename(const char *, const char *);
7578 static void x_free_words(int, char **);
7679 static int x_escape(const char *, size_t, int (*)(const char *, size_t));
@@ -89,17 +92,10 @@ static int x_vi(char *, size_t);
8992 #endif
9093
9194 static int path_order_cmp(const void *aa, const void *bb);
92-static char *add_glob(const char *, int)
93- MKSH_A_NONNULL((nonnull (1)))
94- MKSH_A_BOUNDED(string, 1, 2);
9595 static void glob_table(const char *, XPtrV *, struct table *);
9696 static void glob_path(int flags, const char *, XPtrV *, const char *);
97-static int x_file_glob(int, const char *, int, char ***)
98- MKSH_A_NONNULL((nonnull (2)))
99- MKSH_A_BOUNDED(string, 2, 3);
100-static int x_command_glob(int, const char *, int, char ***)
101- MKSH_A_NONNULL((nonnull (2)))
102- MKSH_A_BOUNDED(string, 2, 3);
97+static int x_file_glob(int, char *, char ***);
98+static int x_command_glob(int, char *, char ***);
10399 static int x_locate_word(const char *, int, int, int *, bool *);
104100
105101 static int x_e_getmbc(char *);
@@ -111,11 +107,14 @@ static int x_e_rebuildline(const char *);
111107 void
112108 x_init(void)
113109 {
114- /* set to -2 to force initial binding */
110+ /*
111+ * Set edchars to -2 to force initial binding, except
112+ * we need default values for some deficient systems…
113+ */
115114 edchars.erase = edchars.kill = edchars.intr = edchars.quit =
116115 edchars.eof = -2;
117- /* default value for deficient systems */
118- edchars.werase = 027; /* ^W */
116+ /* ^W */
117+ edchars.werase = 027;
119118 x_init_emacs();
120119 }
121120
@@ -136,7 +135,8 @@ x_read(char *buf, size_t len)
136135 i = x_vi(buf, len);
137136 #endif
138137 else
139- i = -1; /* internal error */
138+ /* internal error */
139+ i = -1;
140140 editmode = 0;
141141 x_mode(false);
142142 return (i);
@@ -148,7 +148,7 @@ static int
148148 x_getc(void)
149149 {
150150 char c;
151- int n;
151+ ssize_t n;
152152
153153 while ((n = blocking_read(STDIN_FILENO, &c, 1)) < 0 && errno == EINTR)
154154 if (trap) {
@@ -179,7 +179,8 @@ x_putcf(int c)
179179 * Misc common code for vi/emacs *
180180 *********************************/
181181
182-/* Handle the commenting/uncommenting of a line.
182+/*-
183+ * Handle the commenting/uncommenting of a line.
183184 * Returns:
184185 * 1 if a carriage return is indicated (comment added)
185186 * 0 if no return (comment removed)
@@ -188,12 +189,13 @@ x_putcf(int c)
188189 * moved to the start of the line after (un)commenting.
189190 */
190191 static int
191-x_do_comment(char *buf, int bsize, int *lenp)
192+x_do_comment(char *buf, ssize_t bsize, ssize_t *lenp)
192193 {
193- int i, j, len = *lenp;
194+ ssize_t i, j, len = *lenp;
194195
195196 if (len == 0)
196- return (1); /* somewhat arbitrary - it's what AT&T ksh does */
197+ /* somewhat arbitrary - it's what AT&T ksh does */
198+ return (1);
197199
198200 /* Already commented? */
199201 if (buf[0] == '#') {
@@ -238,7 +240,8 @@ x_print_expansions(int nwords, char * const *words, bool is_command)
238240 int prefix_len;
239241 XPtrV l = { NULL, NULL, NULL };
240242
241- /* Check if all matches are in the same directory (in this
243+ /*
244+ * Check if all matches are in the same directory (in this
242245 * case, we want to omit the directory name)
243246 */
244247 if (!is_command &&
@@ -272,7 +275,8 @@ x_print_expansions(int nwords, char * const *words, bool is_command)
272275 pr_list(use_copy ? (char **)XPptrv(l) : words);
273276
274277 if (use_copy)
275- XPfree(l); /* not x_free_words() */
278+ /* not x_free_words() */
279+ XPfree(l);
276280 }
277281
278282 /**
@@ -283,35 +287,40 @@ x_print_expansions(int nwords, char * const *words, bool is_command)
283287 * - returns number of matching strings
284288 */
285289 static int
286-x_file_glob(int flags MKSH_A_UNUSED, const char *str, int slen, char ***wordsp)
290+x_file_glob(int flags MKSH_A_UNUSED, char *toglob, char ***wordsp)
287291 {
288- char *toglob, **words;
289- int nwords, i, idx;
292+ char ch, **words;
293+ int nwords, i = 0, idx = 0;
290294 bool escaping;
291295 XPtrV w;
292296 struct source *s, *sold;
293297
294- if (slen < 0)
295- return (0);
296-
297- toglob = add_glob(str, slen);
298-
299298 /* remove all escaping backward slashes */
300299 escaping = false;
301- for (i = 0, idx = 0; toglob[i]; i++) {
302- if (toglob[i] == '\\' && !escaping) {
300+ while ((ch = toglob[i++])) {
301+ if (ch == '\\' && !escaping) {
303302 escaping = true;
304303 continue;
305304 }
306- /* specially escape escaped [ or $ or ` for globbing */
307- if (escaping && (toglob[i] == '[' ||
308- toglob[i] == '$' || toglob[i] == '`'))
309- toglob[idx++] = QCHAR;
310-
311- toglob[idx] = toglob[i];
312- idx++;
313- if (escaping)
305+ if (escaping) {
306+ /*
307+ * empirically made list of chars to escape
308+ * for globbing; ASCII 0x02 probably too as
309+ * that's what QCHAR is, but...
310+ */
311+ switch (ch) {
312+ case '$':
313+ case '*':
314+ case '?':
315+ case '[':
316+ case '\\':
317+ case '`':
318+ toglob[idx++] = QCHAR;
319+ break;
320+ }
314321 escaping = false;
322+ }
323+ toglob[idx++] = ch;
315324 }
316325 toglob[idx] = '\0';
317326
@@ -324,7 +333,7 @@ x_file_glob(int flags MKSH_A_UNUSED, const char *str, int slen, char ***wordsp)
324333 source = s;
325334 if (yylex(ONEWORD | LQCHAR) != LWORD) {
326335 source = sold;
327- internal_warningf("fileglob: substitute error");
336+ internal_warningf("%s: %s", "fileglob", "bad substitution");
328337 return (0);
329338 }
330339 source = sold;
@@ -338,8 +347,18 @@ x_file_glob(int flags MKSH_A_UNUSED, const char *str, int slen, char ***wordsp)
338347 if (nwords == 1) {
339348 struct stat statb;
340349
341- /* Check if globbing failed (returned glob pattern),
342- * but be careful (E.g. toglob == "ab*" when the file
350+ /* Drop all QCHAR from toglob for strcmp below */
351+ i = 0;
352+ idx = 0;
353+ while ((ch = toglob[i++])) {
354+ if (ch != QCHAR)
355+ toglob[idx++] = ch;
356+ }
357+ toglob[idx] = '\0';
358+
359+ /*
360+ * Check if globbing failed (returned glob pattern),
361+ * but be careful (e.g. toglob == "ab*" when the file
343362 * "ab*" exists is not an error).
344363 * Also, check for empty result - happens if we tried
345364 * to glob something which evaluated to an empty
@@ -353,7 +372,6 @@ x_file_glob(int flags MKSH_A_UNUSED, const char *str, int slen, char ***wordsp)
353372 nwords = 0;
354373 }
355374 }
356- afree(toglob, ATEMP);
357375
358376 if ((*wordsp = nwords ? words : NULL) == NULL && words != NULL)
359377 x_free_words(nwords, words);
@@ -381,21 +399,15 @@ path_order_cmp(const void *aa, const void *bb)
381399 }
382400
383401 static int
384-x_command_glob(int flags, const char *str, int slen, char ***wordsp)
402+x_command_glob(int flags, char *toglob, char ***wordsp)
385403 {
386- char *toglob, *pat, *fpath;
404+ char *pat, *fpath;
387405 int nwords;
388406 XPtrV w;
389407 struct block *l;
390408
391- if (slen < 0)
392- return (0);
393-
394- toglob = add_glob(str, slen);
395-
396409 /* Convert "foo*" (toglob) to a pattern for future use */
397410 pat = evalstr(toglob, DOPAT | DOTILDE);
398- afree(toglob, ATEMP);
399411
400412 XPinit(w, 32);
401413
@@ -424,7 +436,7 @@ x_command_glob(int flags, const char *str, int slen, char ***wordsp)
424436 int i, path_order = 0;
425437
426438 info = (struct path_order_info *)
427- alloc(nwords * sizeof(struct path_order_info), ATEMP);
439+ alloc2(nwords, sizeof(struct path_order_info), ATEMP);
428440 for (i = 0; i < nwords; i++) {
429441 info[i].word = words[i];
430442 info[i].base = x_basename(words[i], NULL);
@@ -481,7 +493,8 @@ x_locate_word(const char *buf, int buflen, int pos, int *startp,
481493 /* The case where pos == buflen happens to take care of itself... */
482494
483495 start = pos;
484- /* Keep going backwards to start of word (has effect of allowing
496+ /*
497+ * Keep going backwards to start of word (has effect of allowing
485498 * one blank after the end of a word)
486499 */
487500 for (; (start > 0 && IS_WORDC(buf[start - 1])) ||
@@ -502,7 +515,8 @@ x_locate_word(const char *buf, int buflen, int pos, int *startp,
502515 p--;
503516 iscmd = p < 0 || vstrchr(";|&()`", buf[p]);
504517 if (iscmd) {
505- /* If command has a /, path, etc. is not searched;
518+ /*
519+ * If command has a /, path, etc. is not searched;
506520 * only current directory is searched which is just
507521 * like file globbing.
508522 */
@@ -519,86 +533,105 @@ x_locate_word(const char *buf, int buflen, int pos, int *startp,
519533 }
520534
521535 static int
522-x_cf_glob(int flags, const char *buf, int buflen, int pos, int *startp,
523- int *endp, char ***wordsp, bool *is_commandp)
536+x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
537+ int *endp, char ***wordsp)
524538 {
525- int len, nwords;
539+ int len, nwords = 0;
526540 char **words = NULL;
527541 bool is_command;
528542
529543 len = x_locate_word(buf, buflen, pos, startp, &is_command);
530- if (!(flags & XCF_COMMAND))
544+ if (!((*flagsp) & XCF_COMMAND))
531545 is_command = false;
532- /* Don't do command globing on zero length strings - it takes too
546+ /*
547+ * Don't do command globing on zero length strings - it takes too
533548 * long and isn't very useful. File globs are more likely to be
534549 * useful, so allow these.
535550 */
536551 if (len == 0 && is_command)
537552 return (0);
538553
539- nwords = is_command ?
540- x_command_glob(flags, buf + *startp, len, &words) :
541- x_file_glob(flags, buf + *startp, len, &words);
554+ if (len >= 0) {
555+ char *toglob, *s;
556+ bool saw_dollar = false, saw_glob = false;
557+
558+ /*
559+ * Given a string, copy it and possibly add a '*' to the end.
560+ */
561+
562+ strndupx(toglob, buf + *startp, len + /* the '*' */ 1, ATEMP);
563+ toglob[len] = '\0';
564+
565+ /*
566+ * If the pathname contains a wildcard (an unquoted '*',
567+ * '?', or '[') or parameter expansion ('$'), or a ~username
568+ * with no trailing slash, then it is globbed based on that
569+ * value (i.e., without the appended '*').
570+ */
571+ for (s = toglob; *s; s++) {
572+ if (*s == '\\' && s[1])
573+ s++;
574+ else if (*s == '$') {
575+ /*
576+ * Do not append a space after the value
577+ * if expanding a parameter substitution
578+ * as in: “cat $HOME/.ss↹” (LP: #710539)
579+ */
580+ saw_dollar = true;
581+ } else if (*s == '?' || *s == '*' || *s == '[' ||
582+ /* ?() *() +() @() !() but two already checked */
583+ (s[1] == '(' /*)*/ &&
584+ (*s == '+' || *s == '@' || *s == '!'))) {
585+ /* just expand based on the extglob */
586+ saw_glob = true;
587+ }
588+ }
589+ if (saw_glob) {
590+ /*
591+ * do not append a glob, we already have a
592+ * glob or extglob; it works even if this is
593+ * a parameter expansion as we have a glob
594+ */
595+ *flagsp |= XCF_IS_EXTGLOB;
596+ } else if (saw_dollar ||
597+ (*toglob == '~' && !vstrchr(toglob, '/'))) {
598+ /* do not append a glob, nor later a space */
599+ *flagsp |= XCF_IS_SUBGLOB;
600+ } else {
601+ /* append a glob, this is not just a tilde */
602+ toglob[len] = '*';
603+ toglob[len + 1] = '\0';
604+ }
605+
606+ /*
607+ * Expand (glob) it now.
608+ */
609+
610+ nwords = is_command ?
611+ x_command_glob(*flagsp, toglob, &words) :
612+ x_file_glob(*flagsp, toglob, &words);
613+ afree(toglob, ATEMP);
614+ }
542615 if (nwords == 0) {
543616 *wordsp = NULL;
544617 return (0);
545618 }
546- if (is_commandp)
547- *is_commandp = is_command;
619+ if (is_command)
620+ *flagsp |= XCF_IS_COMMAND;
548621 *wordsp = words;
549622 *endp = *startp + len;
550623
551624 return (nwords);
552625 }
553626
554-/* Given a string, copy it and possibly add a '*' to the end.
555- * The new string is returned.
556- */
557-static char *
558-add_glob(const char *str, int slen)
559-{
560- char *toglob, *s;
561- bool saw_slash = false;
562-
563- if (slen < 0)
564- return (NULL);
565-
566- /* for clang's static analyser, the nonnull attribute isn't enough */
567- mkssert(str != NULL);
568-
569- strndupx(toglob, str, slen + 1, ATEMP); /* + 1 for "*" */
570- toglob[slen] = '\0';
571-
572- /*
573- * If the pathname contains a wildcard (an unquoted '*',
574- * '?', or '[') or parameter expansion ('$'), or a ~username
575- * with no trailing slash, then it is globbed based on that
576- * value (i.e., without the appended '*').
577- */
578- for (s = toglob; *s; s++) {
579- if (*s == '\\' && s[1])
580- s++;
581- else if (*s == '*' || *s == '[' || *s == '?' || *s == '$' ||
582- (s[1] == '(' /*)*/ && /* *s in '*','?' already checked */
583- (*s == '+' || *s == '@' || *s == '!')))
584- break;
585- else if (*s == '/')
586- saw_slash = true;
587- }
588- if (!*s && (*toglob != '~' || saw_slash)) {
589- toglob[slen] = '*';
590- toglob[slen + 1] = '\0';
591- }
592- return (toglob);
593-}
594-
595627 /*
596628 * Find longest common prefix
597629 */
598-static int
630+static size_t
599631 x_longest_prefix(int nwords, char * const * words)
600632 {
601- int i, j, prefix_len;
633+ int i;
634+ size_t j, prefix_len;
602635 char *p;
603636
604637 if (nwords <= 0)
@@ -611,6 +644,10 @@ x_longest_prefix(int nwords, char * const * words)
611644 prefix_len = j;
612645 break;
613646 }
647+ /* false for nwords==1 as 0 = words[0][prefix_len] then */
648+ if (UTFMODE && prefix_len && (words[0][prefix_len] & 0xC0) == 0x80)
649+ while (prefix_len && (words[0][prefix_len] & 0xC0) != 0xC0)
650+ --prefix_len;
614651 return (prefix_len);
615652 }
616653
@@ -622,7 +659,8 @@ x_free_words(int nwords, char **words)
622659 afree(words, ATEMP);
623660 }
624661
625-/* Return the offset of the basename of string s (which ends at se - need not
662+/*-
663+ * Return the offset of the basename of string s (which ends at se - need not
626664 * be null terminated). Trailing slashes are ignored. If s is just a slash,
627665 * then the offset is 0 (actually, length - 1).
628666 * s Return
@@ -678,13 +716,14 @@ glob_table(const char *pat, XPtrV *wp, struct table *tp)
678716 static void
679717 glob_path(int flags, const char *pat, XPtrV *wp, const char *lpath)
680718 {
681- const char *sp, *p;
719+ const char *sp = lpath, *p;
682720 char *xp, **words;
683- int staterr, pathlen, patlen, oldsize, newsize, i, j;
721+ size_t pathlen, patlen, oldsize, newsize, i, j;
684722 XString xs;
685723
686- patlen = strlen(pat) + 1;
687- sp = lpath;
724+ patlen = strlen(pat);
725+ checkoktoadd(patlen, 129 + X_EXTRA);
726+ ++patlen;
688727 Xinit(xs, xp, patlen + 128, ATEMP);
689728 while (sp) {
690729 xp = Xstring(xs, xp);
@@ -692,7 +731,8 @@ glob_path(int flags, const char *pat, XPtrV *wp, const char *lpath)
692731 p = sp + strlen(sp);
693732 pathlen = p - sp;
694733 if (pathlen) {
695- /* Copy sp into xp, stuffing any MAGIC characters
734+ /*
735+ * Copy sp into xp, stuffing any MAGIC characters
696736 * on the way
697737 */
698738 const char *s = sp;
@@ -711,15 +751,14 @@ glob_path(int flags, const char *pat, XPtrV *wp, const char *lpath)
711751 memcpy(xp, pat, patlen);
712752
713753 oldsize = XPsize(*wp);
714- glob_str(Xstring(xs, xp), wp, 1); /* mark dirs */
754+ /* mark dirs */
755+ glob_str(Xstring(xs, xp), wp, 1);
715756 newsize = XPsize(*wp);
716757
717758 /* Check that each match is executable... */
718759 words = (char **)XPptrv(*wp);
719760 for (i = j = oldsize; i < newsize; i++) {
720- staterr = 0;
721- if ((search_access(words[i], X_OK, &staterr) >= 0) ||
722- (staterr == EISDIR)) {
761+ if (ksh_access(words[i], X_OK) == 0) {
723762 words[j] = words[i];
724763 if (!(flags & XCF_FULLPATH))
725764 memmove(words[j], words[j] + pathlen,
@@ -807,7 +846,8 @@ struct x_defbindings {
807846 #define X_NTABS 3 /* normal, meta1, meta2 */
808847 #define X_TABSZ 256 /* size of keydef tables etc */
809848
810-/* Arguments for do_complete()
849+/*-
850+ * Arguments for do_complete()
811851 * 0 = enumerate M-= complete as much as possible and then list
812852 * 1 = complete M-Esc
813853 * 2 = list M-?
@@ -827,22 +867,23 @@ static char *xcp; /* current position */
827867 static char *xep; /* current end */
828868 static char *xbp; /* start of visible portion of input buffer */
829869 static char *xlp; /* last char visible on screen */
830-static int x_adj_ok;
870+static bool x_adj_ok;
831871 /*
832872 * we use x_adj_done so that functions can tell
833873 * whether x_adjust() has been called while they are active.
834874 */
835-static int x_adj_done;
875+static bool x_adj_done;
836876
837877 static int x_col;
838878 static int x_displen;
839879 static int x_arg; /* general purpose arg */
840-static int x_arg_defaulted; /* x_arg not explicitly set; defaulted to 1 */
880+static bool x_arg_defaulted; /* x_arg not explicitly set; defaulted to 1 */
841881
842882 static int xlp_valid;
843883
844884 static char **x_histp; /* history position */
845885 static int x_nextcmd; /* for newline-and-next */
886+static char **x_histncp; /* saved x_histp for " */
846887 static char *xmp; /* mark pointer */
847888 static unsigned char x_last_command;
848889 static unsigned char (*x_tab)[X_TABSZ]; /* key definition */
@@ -855,7 +896,7 @@ static char *killstack[KILLSIZE];
855896 static int killsp, killtp;
856897 static int x_curprefix;
857898 #ifndef MKSH_SMALL
858-static char *macroptr = NULL; /* bind key macro active? */
899+static char *macroptr; /* bind key macro active? */
859900 #endif
860901 #if !MKSH_S_NOVI
861902 static int cur_col; /* current column on line */
@@ -869,7 +910,7 @@ static char morec; /* more character at right of window */
869910 static int lastref; /* argument to last refresh() */
870911 static int holdlen; /* length of holdbuf */
871912 #endif
872-static int prompt_redraw; /* 0 if newline forced after prompt */
913+static bool prompt_redraw; /* false if newline forced after prompt */
873914
874915 static int x_ins(const char *);
875916 static void x_delete(int, int);
@@ -891,7 +932,7 @@ static int x_match(char *, char *);
891932 static void x_redraw(int);
892933 static void x_push(int);
893934 static char *x_mapin(const char *, Area *)
894- MKSH_A_NONNULL((nonnull (1)));
935+ MKSH_A_NONNULL((__nonnull__ (1)));
895936 static char *x_mapout(int);
896937 static void x_mapout2(int, char **);
897938 static void x_print(int, int);
@@ -998,7 +1039,8 @@ static struct x_defbindings const x_defbindings[] = {
9981039 { XFUNC_fold_capitalise, 1, 'C' },
9991040 { XFUNC_fold_capitalise, 1, 'c' },
10001041 #endif
1001- /* These for ansi arrow keys: arguablely shouldn't be here by
1042+ /*
1043+ * These for ANSI arrow keys: arguablely shouldn't be here by
10021044 * default, but its simpler/faster/smaller than using termcap
10031045 * entries.
10041046 */
@@ -1079,19 +1121,19 @@ static void
10791121 x_init_prompt(void)
10801122 {
10811123 x_col = promptlen(prompt);
1082- x_adj_ok = 1;
1083- prompt_redraw = 1;
1124+ x_adj_ok = true;
1125+ prompt_redraw = true;
10841126 if (x_col >= xx_cols)
10851127 x_col %= xx_cols;
10861128 x_displen = xx_cols - 2 - x_col;
1087- x_adj_done = 0;
1129+ x_adj_done = false;
10881130
10891131 pprompt(prompt, 0);
10901132 if (x_displen < 1) {
10911133 x_col = 0;
10921134 x_displen = xx_cols - 2;
10931135 x_e_putc2('\n');
1094- prompt_redraw = 0;
1136+ prompt_redraw = false;
10951137 }
10961138 }
10971139
@@ -1113,14 +1155,17 @@ x_emacs(char *buf, size_t len)
11131155 xx_cols = x_cols;
11141156 x_init_prompt();
11151157
1158+ x_histncp = NULL;
11161159 if (x_nextcmd >= 0) {
11171160 int off = source->line - x_nextcmd;
1118- if (histptr - history >= off)
1161+ if (histptr - history >= off) {
11191162 x_load_hist(histptr - off);
1163+ x_histncp = x_histp;
1164+ }
11201165 x_nextcmd = -1;
11211166 }
11221167 editmode = 1;
1123- while (1) {
1168+ while (/* CONSTCOND */ 1) {
11241169 x_flush();
11251170 if ((c = x_e_getc()) < 0)
11261171 return (0);
@@ -1142,7 +1187,7 @@ x_emacs(char *buf, size_t len)
11421187 if (!(x_ftab[f].xf_flags & XF_PREFIX) &&
11431188 x_last_command != XFUNC_set_arg) {
11441189 x_arg = 1;
1145- x_arg_defaulted = 1;
1190+ x_arg_defaulted = true;
11461191 }
11471192 i = c | (x_curprefix << 8);
11481193 x_curprefix = 0;
@@ -1154,7 +1199,8 @@ x_emacs(char *buf, size_t len)
11541199 case KEOL:
11551200 i = xep - xbuf;
11561201 return (i);
1157- case KINTR: /* special case for interrupt */
1202+ case KINTR:
1203+ /* special case for interrupt */
11581204 trapsig(SIGINT);
11591205 x_mode(false);
11601206 unwind(LSHELL);
@@ -1167,7 +1213,7 @@ x_emacs(char *buf, size_t len)
11671213 static int
11681214 x_insert(int c)
11691215 {
1170- static int left = 0, pos, save_arg;
1216+ static int left, pos, save_arg;
11711217 static char str[4];
11721218
11731219 /*
@@ -1253,7 +1299,7 @@ static int
12531299 x_ins(const char *s)
12541300 {
12551301 char *cp = xcp;
1256- int adj = x_adj_done;
1302+ bool adj = x_adj_done;
12571303
12581304 if (x_do_ins(s, strlen(s)) < 0)
12591305 return (-1);
@@ -1263,9 +1309,10 @@ x_ins(const char *s)
12631309 */
12641310 xlp_valid = false;
12651311 x_lastcp();
1266- x_adj_ok = (xcp >= xlp);
1312+ x_adj_ok = tobool(xcp >= xlp);
12671313 x_zots(cp);
1268- if (adj == x_adj_done) { /* has x_adjust() been called? */
1314+ /* has x_adjust() been called? */
1315+ if (adj == x_adj_done) {
12691316 /* no */
12701317 cp = xlp;
12711318 while (cp > xcp)
@@ -1273,7 +1320,7 @@ x_ins(const char *s)
12731320 }
12741321 if (xlp == xep - 1)
12751322 x_redraw(xx_cols);
1276- x_adj_ok = 1;
1323+ x_adj_ok = true;
12771324 return (0);
12781325 }
12791326
@@ -1354,13 +1401,15 @@ x_delete(int nc, int push)
13541401 x_push(nb);
13551402
13561403 xep -= nb;
1357- memmove(xcp, xcp + nb, xep - xcp + 1); /* Copies the NUL */
1358- x_adj_ok = 0; /* don't redraw */
1404+ /* Copies the NUL */
1405+ memmove(xcp, xcp + nb, xep - xcp + 1);
1406+ /* don't redraw */
1407+ x_adj_ok = false;
13591408 xlp_valid = false;
13601409 x_zots(xcp);
13611410 /*
13621411 * if we are already filling the line,
1363- * there is no need to ' ','\b'.
1412+ * there is no need to ' ', '\b'.
13641413 * But if we must, make sure we do the minimum.
13651414 */
13661415 if ((i = xx_cols - 2 - x_col) > 0 || xep - xlp == 0) {
@@ -1375,7 +1424,7 @@ x_delete(int nc, int push)
13751424 x_e_putc2('\b');
13761425 }
13771426 /*x_goto(xcp);*/
1378- x_adj_ok = 1;
1427+ x_adj_ok = true;
13791428 xlp_valid = false;
13801429 cp = x_lastcp();
13811430 while (cp > xcp)
@@ -1465,17 +1514,21 @@ x_fword(int move)
14651514 static void
14661515 x_goto(char *cp)
14671516 {
1468- if (UTFMODE)
1517+ if (cp >= xep)
1518+ cp = xep;
1519+ else if (UTFMODE)
14691520 while ((cp > xbuf) && ((*cp & 0xC0) == 0x80))
14701521 --cp;
14711522 if (cp < xbp || cp >= utf_skipcols(xbp, x_displen)) {
14721523 /* we are heading off screen */
14731524 xcp = cp;
14741525 x_adjust();
1475- } else if (cp < xcp) { /* move back */
1526+ } else if (cp < xcp) {
1527+ /* move back */
14761528 while (cp < xcp)
14771529 x_bs3(&xcp);
1478- } else if (cp > xcp) { /* move forward */
1530+ } else if (cp > xcp) {
1531+ /* move forward */
14791532 while (cp > xcp)
14801533 x_zotc3(&xcp);
14811534 }
@@ -1515,16 +1568,18 @@ x_size2(char *cp, char **dcp)
15151568 if (dcp)
15161569 *dcp = cp + 1;
15171570 if (c == '\t')
1518- return (4); /* Kludge, tabs are always four spaces. */
1571+ /* Kludge, tabs are always four spaces. */
1572+ return (4);
15191573 if (c < ' ' || c == 0x7f)
1520- return (2); /* control unsigned char */
1574+ /* control unsigned char */
1575+ return (2);
15211576 return (1);
15221577 }
15231578
15241579 static void
15251580 x_zots(char *str)
15261581 {
1527- int adj = x_adj_done;
1582+ bool adj = x_adj_done;
15281583
15291584 x_lastcp();
15301585 while (*str && str < xlp && adj == x_adj_done)
@@ -1700,7 +1755,8 @@ x_next_com(int c MKSH_A_UNUSED)
17001755 return (KSTD);
17011756 }
17021757
1703-/* Goto a particular history number obtained from argument.
1758+/*
1759+ * Goto a particular history number obtained from argument.
17041760 * If no argument is given history 1 is probably not what you
17051761 * want so we'll simply go to the oldest one.
17061762 */
@@ -1747,7 +1803,10 @@ x_load_hist(char **hp)
17471803 static int
17481804 x_nl_next_com(int c MKSH_A_UNUSED)
17491805 {
1750- x_nextcmd = source->line - (histptr - x_histp) + 1;
1806+ if (!x_histncp || (x_histp != x_histncp && x_histp != histptr + 1))
1807+ /* fresh start of ^O */
1808+ x_histncp = x_histp;
1809+ x_nextcmd = source->line - (histptr - x_histncp) + 1;
17511810 return (x_newline('\n'));
17521811 }
17531812
@@ -1765,12 +1824,12 @@ static int
17651824 x_search_hist(int c)
17661825 {
17671826 int offset = -1; /* offset of match in xbuf, else -1 */
1768- char pat[256 + 1]; /* pattern buffer */
1827+ char pat[80 + 1]; /* pattern buffer */
17691828 char *p = pat;
17701829 unsigned char f;
17711830
17721831 *p = '\0';
1773- while (1) {
1832+ while (/* CONSTCOND */ 1) {
17741833 if (offset < 0) {
17751834 x_e_puts("\nI-search: ");
17761835 x_e_puts(pat);
@@ -1833,7 +1892,8 @@ x_search_hist(int c)
18331892 if (offset >= 0)
18341893 x_load_hist(histptr + 1);
18351894 break;
1836- } else { /* other command */
1895+ } else {
1896+ /* other command */
18371897 x_e_ungetc(c);
18381898 break;
18391899 }
@@ -1965,7 +2025,8 @@ x_cls(int c MKSH_A_UNUSED)
19652025 return (x_e_rebuildline(MKSH_CLS_STRING));
19662026 }
19672027
1968-/* Redraw (part of) the line. If limit is < 0, the everything is redrawn
2028+/*
2029+ * Redraw (part of) the line. If limit is < 0, the everything is redrawn
19692030 * on a NEW line, otherwise limit is the screen column up to which needs
19702031 * redrawing.
19712032 */
@@ -1975,7 +2036,7 @@ x_redraw(int limit)
19752036 int i, j, x_trunc = 0;
19762037 char *cp;
19772038
1978- x_adj_ok = 0;
2039+ x_adj_ok = false;
19792040 if (limit == -1)
19802041 x_e_putc2('\n');
19812042 else
@@ -2002,7 +2063,8 @@ x_redraw(int limit)
20022063 limit = xx_cols;
20032064 if (limit >= 0) {
20042065 if (xep > xlp)
2005- i = 0; /* we fill the line */
2066+ /* we fill the line */
2067+ i = 0;
20062068 else {
20072069 char *cpl = xbp;
20082070
@@ -2019,7 +2081,8 @@ x_redraw(int limit)
20192081 j++;
20202082 }
20212083 i = ' ';
2022- if (xep > xlp) { /* more off screen */
2084+ if (xep > xlp) {
2085+ /* more off screen */
20232086 if (xbp > xbuf)
20242087 i = '*';
20252088 else
@@ -2034,7 +2097,7 @@ x_redraw(int limit)
20342097 cp = xlp;
20352098 while (cp > xcp)
20362099 x_bs3(&cp);
2037- x_adj_ok = 1;
2100+ x_adj_ok = true;
20382101 return;
20392102 }
20402103
@@ -2043,7 +2106,8 @@ x_transpose(int c MKSH_A_UNUSED)
20432106 {
20442107 unsigned int tmpa, tmpb;
20452108
2046- /* What transpose is meant to do seems to be up for debate. This
2109+ /*-
2110+ * What transpose is meant to do seems to be up for debate. This
20472111 * is a general summary of the options; the text is abcd with the
20482112 * upper case character or underscore indicating the cursor position:
20492113 * Who Before After Before After
@@ -2064,8 +2128,9 @@ x_transpose(int c MKSH_A_UNUSED)
20642128 x_e_putc2(7);
20652129 return (KSTD);
20662130 }
2067- /* Gosling/Unipress emacs style: Swap two characters before the
2068- * cursor, do not change cursor position
2131+ /*
2132+ * Gosling/Unipress emacs style: Swap two characters before
2133+ * the cursor, do not change cursor position
20692134 */
20702135 x_bs3(&xcp);
20712136 if (utf_mbtowc(&tmpa, xcp) == (size_t)-1) {
@@ -2082,7 +2147,8 @@ x_transpose(int c MKSH_A_UNUSED)
20822147 utf_wctomb(xcp, tmpb);
20832148 x_zotc3(&xcp);
20842149 } else {
2085- /* GNU emacs style: Swap the characters before and under the
2150+ /*
2151+ * GNU emacs style: Swap the characters before and under the
20862152 * cursor, move cursor position along one.
20872153 */
20882154 if (utf_mbtowc(&tmpa, xcp) == (size_t)-1) {
@@ -2177,7 +2243,7 @@ x_yank(int c MKSH_A_UNUSED)
21772243 static int
21782244 x_meta_yank(int c MKSH_A_UNUSED)
21792245 {
2180- int len;
2246+ size_t len;
21812247
21822248 if ((x_last_command != XFUNC_yank && x_last_command != XFUNC_meta_yank) ||
21832249 killstack[killtp] == 0) {
@@ -2230,7 +2296,7 @@ x_vt_hack(int c)
22302296 switch ((c = x_e_getc())) {
22312297 case '~':
22322298 x_arg = 1;
2233- x_arg_defaulted = 1;
2299+ x_arg_defaulted = true;
22342300 return (x_mv_begin(0));
22352301 case ';':
22362302 /* "interesting" sequence detected */
@@ -2245,7 +2311,7 @@ x_vt_hack(int c)
22452311
22462312 /*-
22472313 * At this point, we have read the following octets so far:
2248- * - ESC+[ or ESC+O or Ctrl-X (Præfix 2)
2314+ * - ESC+[ or ESC+O or Ctrl-X (Prefix 2)
22492315 * - 1 (vt_hack)
22502316 * - ;
22512317 * - 5 (Ctrl key combiner) or 3 (Alt key combiner)
@@ -2279,7 +2345,8 @@ x_mapin(const char *cp, Area *ap)
22792345 /* XXX -- should handle \^ escape? */
22802346 if (*cp == '^') {
22812347 cp++;
2282- if (*cp >= '?') /* includes '?'; ASCII */
2348+ if (*cp >= '?')
2349+ /* includes '?'; ASCII */
22832350 *op++ = CTRL(*cp);
22842351 else {
22852352 *op++ = '^';
@@ -2343,9 +2410,11 @@ x_print(int prefix, int key)
23432410 int
23442411 x_bind(const char *a1, const char *a2,
23452412 #ifndef MKSH_SMALL
2346- bool macro, /* bind -m */
2413+ /* bind -m */
2414+ bool macro,
23472415 #endif
2348- bool list) /* bind -l */
2416+ /* bind -l */
2417+ bool list)
23492418 {
23502419 unsigned char f;
23512420 int prefix, key;
@@ -2356,7 +2425,7 @@ x_bind(const char *a1, const char *a2,
23562425 #endif
23572426
23582427 if (x_tab == NULL) {
2359- bi_errorf("cannot bind, not a tty");
2428+ bi_errorf("can't bind, not a tty");
23602429 return (1);
23612430 }
23622431 /* List function names */
@@ -2398,16 +2467,16 @@ x_bind(const char *a1, const char *a2,
23982467 && ((*m1 != '~') || *(m1 + 1))
23992468 #endif
24002469 ) {
2401- char msg[256] = "key sequence '";
2470+ char msg[256];
24022471 const char *c = a1;
2403- m1 = msg + strlen(msg);
2472+ m1 = msg;
24042473 while (*c && m1 < (msg + sizeof(msg) - 3))
24052474 x_mapout2(*c++, &m1);
2406- bi_errorf("%s' too long", msg);
2475+ bi_errorf("%s: %s", "too long key sequence", msg);
24072476 return (1);
24082477 }
24092478 #ifndef MKSH_SMALL
2410- hastilde = *m1;
2479+ hastilde = tobool(*m1);
24112480 #endif
24122481 afree(m2, ATEMP);
24132482
@@ -2428,7 +2497,7 @@ x_bind(const char *a1, const char *a2,
24282497 strcmp(x_ftab[f].xf_name, a2) == 0)
24292498 break;
24302499 if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) {
2431- bi_errorf("%s: no such function", a2);
2500+ bi_errorf("%s: %s %s", a2, "no such", Tfunction);
24322501 return (1);
24332502 }
24342503 }
@@ -2466,7 +2535,7 @@ x_init_emacs(void)
24662535 ainit(AEDIT);
24672536 x_nextcmd = -1;
24682537
2469- x_tab = alloc(X_NTABS * sizeof(*x_tab), AEDIT);
2538+ x_tab = alloc2(X_NTABS, sizeof(*x_tab), AEDIT);
24702539 for (j = 0; j < X_TABSZ; j++)
24712540 x_tab[0][j] = XFUNC_insert;
24722541 for (i = 1; i < X_NTABS; i++)
@@ -2477,7 +2546,7 @@ x_init_emacs(void)
24772546 = x_defbindings[i].xdb_func;
24782547
24792548 #ifndef MKSH_SMALL
2480- x_atab = alloc(X_NTABS * sizeof(*x_atab), AEDIT);
2549+ x_atab = alloc2(X_NTABS, sizeof(*x_atab), AEDIT);
24812550 for (i = 1; i < X_NTABS; i++)
24822551 for (j = 0; j < X_TABSZ; j++)
24832552 x_atab[i][j] = NULL;
@@ -2603,10 +2672,10 @@ x_expand(int c MKSH_A_UNUSED)
26032672 {
26042673 char **words;
26052674 int start, end, nwords, i;
2606- bool is_command;
26072675
2608- nwords = x_cf_glob(XCF_FILE, xbuf, xep - xbuf, xcp - xbuf,
2609- &start, &end, &words, &is_command);
2676+ i = XCF_FILE;
2677+ nwords = x_cf_glob(&i, xbuf, xep - xbuf, xcp - xbuf,
2678+ &start, &end, &words);
26102679
26112680 if (nwords == 0) {
26122681 x_e_putc2(7);
@@ -2614,7 +2683,9 @@ x_expand(int c MKSH_A_UNUSED)
26142683 }
26152684 x_goto(xbuf + start);
26162685 x_delete(end - start, false);
2617- for (i = 0; i < nwords;) {
2686+
2687+ i = 0;
2688+ while (i < nwords) {
26182689 if (x_escape(words[i], strlen(words[i]), x_do_ins) < 0 ||
26192690 (++i < nwords && x_ins(" ") < 0)) {
26202691 x_e_putc2(7);
@@ -2626,45 +2697,53 @@ x_expand(int c MKSH_A_UNUSED)
26262697 return (KSTD);
26272698 }
26282699
2629-/* type == 0 for list, 1 for complete and 2 for complete-list */
26302700 static void
2631-do_complete(int flags, /* XCF_{COMMAND,FILE,COMMAND_FILE} */
2701+do_complete(
2702+ /* XCF_{COMMAND,FILE,COMMAND_FILE} */
2703+ int flags,
2704+ /* 0 for list, 1 for complete and 2 for complete-list */
26322705 Comp_type type)
26332706 {
26342707 char **words;
26352708 int start, end, nlen, olen, nwords;
2636- bool is_command, completed = false;
2709+ bool completed = false;
26372710
2638- nwords = x_cf_glob(flags, xbuf, xep - xbuf, xcp - xbuf,
2639- &start, &end, &words, &is_command);
2711+ nwords = x_cf_glob(&flags, xbuf, xep - xbuf, xcp - xbuf,
2712+ &start, &end, &words);
26402713 /* no match */
26412714 if (nwords == 0) {
26422715 x_e_putc2(7);
26432716 return;
26442717 }
26452718 if (type == CT_LIST) {
2646- x_print_expansions(nwords, words, is_command);
2719+ x_print_expansions(nwords, words,
2720+ tobool(flags & XCF_IS_COMMAND));
26472721 x_redraw(0);
26482722 x_free_words(nwords, words);
26492723 return;
26502724 }
26512725 olen = end - start;
26522726 nlen = x_longest_prefix(nwords, words);
2653- /* complete */
2654- if (nwords == 1 || nlen > olen) {
2655- x_goto(xbuf + start);
2656- x_delete(olen, false);
2657- x_escape(words[0], nlen, x_do_ins);
2658- x_adjust();
2727+ /* always complete */
2728+ x_goto(xbuf + start);
2729+ x_delete(olen, false);
2730+ x_escape(words[0], nlen, x_do_ins);
2731+ x_adjust();
2732+ /* check if we did add something */
2733+ if (xcp - (xbuf + start) > olen)
26592734 completed = true;
2660- }
2661- /* add space if single non-dir match */
2662- if (nwords == 1 && words[0][nlen - 1] != '/') {
2735+ /*
2736+ * append a space if this is a single non-directory match
2737+ * and not a parameter or homedir substitution
2738+ */
2739+ if (nwords == 1 && words[0][nlen - 1] != '/' &&
2740+ !(flags & XCF_IS_SUBGLOB)) {
26632741 x_ins(" ");
26642742 completed = true;
26652743 }
26662744 if (type == CT_COMPLIST && !completed) {
2667- x_print_expansions(nwords, words, is_command);
2745+ x_print_expansions(nwords, words,
2746+ tobool(flags & XCF_IS_COMMAND));
26682747 completed = true;
26692748 }
26702749 if (completed)
@@ -2673,7 +2752,8 @@ do_complete(int flags, /* XCF_{COMMAND,FILE,COMMAND_FILE} */
26732752 x_free_words(nwords, words);
26742753 }
26752754
2676-/* NAME:
2755+/*-
2756+ * NAME:
26772757 * x_adjust - redraw the line adjusting starting point etc.
26782758 *
26792759 * DESCRIPTION:
@@ -2689,7 +2769,8 @@ do_complete(int flags, /* XCF_{COMMAND,FILE,COMMAND_FILE} */
26892769 static void
26902770 x_adjust(void)
26912771 {
2692- x_adj_done++; /* flag the fact that we were called. */
2772+ /* flag the fact that we were called. */
2773+ x_adj_done = true;
26932774 /*
26942775 * we had a problem if the prompt length > xx_cols / 2
26952776 */
@@ -2811,13 +2892,14 @@ x_e_putc3(const char **cp)
28112892 static void
28122893 x_e_puts(const char *s)
28132894 {
2814- int adj = x_adj_done;
2895+ bool adj = x_adj_done;
28152896
28162897 while (*s && adj == x_adj_done)
28172898 x_e_putc3(&s);
28182899 }
28192900
2820-/* NAME:
2901+/*-
2902+ * NAME:
28212903 * x_set_arg - set an arg value for next function
28222904 *
28232905 * DESCRIPTION:
@@ -2829,19 +2911,28 @@ x_e_puts(const char *s)
28292911 static int
28302912 x_set_arg(int c)
28312913 {
2832- int n = 0, first = 1;
2914+ unsigned int n = 0;
2915+ bool first = true;
28332916
2834- c &= 255; /* strip command prefix */
2835- for (; c >= 0 && ksh_isdigit(c); c = x_e_getc(), first = 0)
2917+ /* strip command prefix */
2918+ c &= 255;
2919+ while (c >= 0 && ksh_isdigit(c)) {
28362920 n = n * 10 + (c - '0');
2921+ if (n > LINE)
2922+ /* upper bound for repeat */
2923+ goto x_set_arg_too_big;
2924+ c = x_e_getc();
2925+ first = false;
2926+ }
28372927 if (c < 0 || first) {
2928+ x_set_arg_too_big:
28382929 x_e_putc2(7);
28392930 x_arg = 1;
2840- x_arg_defaulted = 1;
2931+ x_arg_defaulted = true;
28412932 } else {
28422933 x_e_ungetc(c);
28432934 x_arg = n;
2844- x_arg_defaulted = 0;
2935+ x_arg_defaulted = false;
28452936 }
28462937 return (KSTD);
28472938 }
@@ -2851,7 +2942,7 @@ static int
28512942 x_comment(int c MKSH_A_UNUSED)
28522943 {
28532944 int oldsize = x_size_str(xbuf);
2854- int len = xep - xbuf;
2945+ ssize_t len = xep - xbuf;
28552946 int ret = x_do_comment(xbuf, xend - xbuf, &len);
28562947
28572948 if (ret < 0)
@@ -2873,7 +2964,8 @@ x_version(int c MKSH_A_UNUSED)
28732964 {
28742965 char *o_xbuf = xbuf, *o_xend = xend;
28752966 char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp;
2876- int vlen, lim = x_lastcp() - xbp;
2967+ int lim = x_lastcp() - xbp;
2968+ size_t vlen;
28772969 char *v;
28782970
28792971 strdupx(v, KSH_VERSION, ATEMP);
@@ -2889,7 +2981,7 @@ x_version(int c MKSH_A_UNUSED)
28892981 xbp = o_xbp;
28902982 xep = o_xep;
28912983 xcp = o_xcp;
2892- x_redraw(vlen);
2984+ x_redraw((int)vlen);
28932985
28942986 if (c < 0)
28952987 return (KSTD);
@@ -2927,7 +3019,8 @@ x_edit_line(int c MKSH_A_UNUSED)
29273019 }
29283020 #endif
29293021
2930-/* NAME:
3022+/*-
3023+ * NAME:
29313024 * x_prev_histword - recover word from prev command
29323025 *
29333026 * DESCRIPTION:
@@ -2948,11 +3041,17 @@ x_prev_histword(int c MKSH_A_UNUSED)
29483041 {
29493042 char *rcp, *cp;
29503043 char **xhp;
2951- int m;
2952-
2953- if (xmp && modified > 1)
2954- x_kill_region(0);
2955- m = modified ? modified : 1;
3044+ int m = 1;
3045+ /* -1 = defaulted; 0+ = argument */
3046+ static int last_arg = -1;
3047+
3048+ if (x_last_command == XFUNC_prev_histword) {
3049+ if (xmp && modified > 1)
3050+ x_kill_region(0);
3051+ if (modified)
3052+ m = modified;
3053+ } else
3054+ last_arg = x_arg_defaulted ? -1 : x_arg;
29563055 xhp = histptr - (m - 1);
29573056 if ((xhp < history) || !(cp = *xhp)) {
29583057 x_e_putc2(7);
@@ -2960,7 +3059,9 @@ x_prev_histword(int c MKSH_A_UNUSED)
29603059 return (KSTD);
29613060 }
29623061 x_set_mark(0);
2963- if (x_arg_defaulted) {
3062+ if ((x_arg = last_arg) == -1) {
3063+ /* x_arg_defaulted */
3064+
29643065 rcp = &cp[strlen(cp) - 1];
29653066 /*
29663067 * ignore white-space after the last word
@@ -2973,6 +3074,7 @@ x_prev_histword(int c MKSH_A_UNUSED)
29733074 rcp++;
29743075 x_ins(rcp);
29753076 } else {
3077+ /* not x_arg_defaulted */
29763078 char ch;
29773079
29783080 rcp = cp;
@@ -2981,7 +3083,7 @@ x_prev_histword(int c MKSH_A_UNUSED)
29813083 */
29823084 while (*rcp && is_cfs(*rcp))
29833085 rcp++;
2984- while (x_arg-- > 1) {
3086+ while (x_arg-- > 0) {
29853087 while (*rcp && !is_cfs(*rcp))
29863088 rcp++;
29873089 while (*rcp && is_cfs(*rcp))
@@ -3014,19 +3116,20 @@ x_fold_lower(int c MKSH_A_UNUSED)
30143116 return (x_fold_case('L'));
30153117 }
30163118
3017-/* Lowercase N(1) words */
3119+/* Titlecase N(1) words */
30183120 static int
30193121 x_fold_capitalise(int c MKSH_A_UNUSED)
30203122 {
30213123 return (x_fold_case('C'));
30223124 }
30233125
3024-/* NAME:
3126+/*-
3127+ * NAME:
30253128 * x_fold_case - convert word to UPPER/lower/Capital case
30263129 *
30273130 * DESCRIPTION:
3028- * This function is used to implement M-U,M-u,M-L,M-l,M-C and M-c
3029- * to UPPER case, lower case or Capitalise words.
3131+ * This function is used to implement M-U/M-u, M-L/M-l, M-C/M-c
3132+ * to UPPER CASE, lower case or Capitalise Words.
30303133 *
30313134 * RETURN VALUE:
30323135 * None
@@ -3051,9 +3154,11 @@ x_fold_case(int c)
30513154 * a different action than for the rest.
30523155 */
30533156 if (cp != xep) {
3054- if (c == 'L') /* lowercase */
3157+ if (c == 'L')
3158+ /* lowercase */
30553159 *cp = ksh_tolower(*cp);
3056- else /* uppercase, capitalise */
3160+ else
3161+ /* uppercase, capitalise */
30573162 *cp = ksh_toupper(*cp);
30583163 cp++;
30593164 }
@@ -3061,9 +3166,11 @@ x_fold_case(int c)
30613166 * now for the rest of the word
30623167 */
30633168 while (cp != xep && !is_mfs(*cp)) {
3064- if (c == 'U') /* uppercase */
3169+ if (c == 'U')
3170+ /* uppercase */
30653171 *cp = ksh_toupper(*cp);
3066- else /* lowercase, capitalise */
3172+ else
3173+ /* lowercase, capitalise */
30673174 *cp = ksh_tolower(*cp);
30683175 cp++;
30693176 }
@@ -3074,7 +3181,8 @@ x_fold_case(int c)
30743181 }
30753182 #endif
30763183
3077-/* NAME:
3184+/*-
3185+ * NAME:
30783186 * x_lastcp - last visible char
30793187 *
30803188 * SYNOPSIS:
@@ -3114,44 +3222,26 @@ x_lastcp(void)
31143222 return (xlp);
31153223 }
31163224
3117-static bool
3225+static void
31183226 x_mode(bool onoff)
31193227 {
31203228 static bool x_cur_mode;
3121- bool prev;
31223229
31233230 if (x_cur_mode == onoff)
3124- return (x_cur_mode);
3125- prev = x_cur_mode;
3231+ return;
31263232 x_cur_mode = onoff;
31273233
31283234 if (onoff) {
3129- struct termios cb;
3235+ x_mkraw(tty_fd, NULL, false);
31303236
3131- cb = tty_state;
3132-
3133- edchars.erase = cb.c_cc[VERASE];
3134- edchars.kill = cb.c_cc[VKILL];
3135- edchars.intr = cb.c_cc[VINTR];
3136- edchars.quit = cb.c_cc[VQUIT];
3137- edchars.eof = cb.c_cc[VEOF];
3237+ edchars.erase = tty_state.c_cc[VERASE];
3238+ edchars.kill = tty_state.c_cc[VKILL];
3239+ edchars.intr = tty_state.c_cc[VINTR];
3240+ edchars.quit = tty_state.c_cc[VQUIT];
3241+ edchars.eof = tty_state.c_cc[VEOF];
31383242 #ifdef VWERASE
3139- edchars.werase = cb.c_cc[VWERASE];
3140-#endif
3141- cb.c_iflag &= ~(INLCR | ICRNL);
3142- cb.c_lflag &= ~(ISIG | ICANON | ECHO);
3143-#if defined(VLNEXT) && defined(_POSIX_VDISABLE)
3144- /* osf/1 processes lnext when ~icanon */
3145- cb.c_cc[VLNEXT] = _POSIX_VDISABLE;
3146-#endif
3147- /* sunos 4.1.x & osf/1 processes discard(flush) when ~icanon */
3148-#if defined(VDISCARD) && defined(_POSIX_VDISABLE)
3149- cb.c_cc[VDISCARD] = _POSIX_VDISABLE;
3243+ edchars.werase = tty_state.c_cc[VWERASE];
31503244 #endif
3151- cb.c_cc[VTIME] = 0;
3152- cb.c_cc[VMIN] = 1;
3153-
3154- tcsetattr(tty_fd, TCSADRAIN, &cb);
31553245
31563246 #ifdef _POSIX_VDISABLE
31573247 /* Convert unset values to internal 'unset' value */
@@ -3183,8 +3273,6 @@ x_mode(bool onoff)
31833273 bind_if_not_bound(0, edchars.quit, XFUNC_noop);
31843274 } else
31853275 tcsetattr(tty_fd, TCSADRAIN, &tty_state);
3186-
3187- return (prev);
31883276 }
31893277
31903278 #if !MKSH_S_NOVI
@@ -3194,10 +3282,10 @@ x_mode(bool onoff)
31943282
31953283 struct edstate {
31963284 char *cbuf;
3197- int winleft;
3198- int cbufsize;
3199- int linelen;
3200- int cursor;
3285+ ssize_t winleft;
3286+ ssize_t cbufsize;
3287+ ssize_t linelen;
3288+ ssize_t cursor;
32013289 };
32023290
32033291 static int vi_hook(int);
@@ -3210,7 +3298,7 @@ static void yank_range(int, int);
32103298 static int bracktype(int);
32113299 static void save_cbuf(void);
32123300 static void restore_cbuf(void);
3213-static int putbuf(const char *, int, int);
3301+static int putbuf(const char *, ssize_t, int);
32143302 static void del_range(int, int);
32153303 static int findch(int, int, int, int);
32163304 static int forwword(int);
@@ -3220,8 +3308,8 @@ static int Forwword(int);
32203308 static int Backword(int);
32213309 static int Endword(int);
32223310 static int grabhist(int, int);
3223-static int grabsearch(int, int, int, char *);
3224-static void redraw_line(int);
3311+static int grabsearch(int, int, int, const char *);
3312+static void redraw_line(bool);
32253313 static void refresh(int);
32263314 static int outofwin(void);
32273315 static void rewindow(void);
@@ -3237,58 +3325,58 @@ static void vi_error(void);
32373325 static void vi_macro_reset(void);
32383326 static int x_vi_putbuf(const char *, size_t);
32393327
3240-#define C_ 0x1 /* a valid command that isn't a M_, E_, U_ */
3241-#define M_ 0x2 /* movement command (h, l, etc.) */
3242-#define E_ 0x4 /* extended command (c, d, y) */
3243-#define X_ 0x8 /* long command (@, f, F, t, T, etc.) */
3244-#define U_ 0x10 /* an UN-undoable command (that isn't a M_) */
3245-#define B_ 0x20 /* bad command (^@) */
3246-#define Z_ 0x40 /* repeat count defaults to 0 (not 1) */
3247-#define S_ 0x80 /* search (/, ?) */
3248-
3249-#define is_bad(c) (classify[(c)&0x7f]&B_)
3250-#define is_cmd(c) (classify[(c)&0x7f]&(M_|E_|C_|U_))
3251-#define is_move(c) (classify[(c)&0x7f]&M_)
3252-#define is_extend(c) (classify[(c)&0x7f]&E_)
3253-#define is_long(c) (classify[(c)&0x7f]&X_)
3254-#define is_undoable(c) (!(classify[(c)&0x7f]&U_))
3255-#define is_srch(c) (classify[(c)&0x7f]&S_)
3256-#define is_zerocount(c) (classify[(c)&0x7f]&Z_)
3328+#define vC 0x01 /* a valid command that isn't a vM, vE, vU */
3329+#define vM 0x02 /* movement command (h, l, etc.) */
3330+#define vE 0x04 /* extended command (c, d, y) */
3331+#define vX 0x08 /* long command (@, f, F, t, T, etc.) */
3332+#define vU 0x10 /* an UN-undoable command (that isn't a vM) */
3333+#define vB 0x20 /* bad command (^@) */
3334+#define vZ 0x40 /* repeat count defaults to 0 (not 1) */
3335+#define vS 0x80 /* search (/, ?) */
3336+
3337+#define is_bad(c) (classify[(c)&0x7f]&vB)
3338+#define is_cmd(c) (classify[(c)&0x7f]&(vM|vE|vC|vU))
3339+#define is_move(c) (classify[(c)&0x7f]&vM)
3340+#define is_extend(c) (classify[(c)&0x7f]&vE)
3341+#define is_long(c) (classify[(c)&0x7f]&vX)
3342+#define is_undoable(c) (!(classify[(c)&0x7f]&vU))
3343+#define is_srch(c) (classify[(c)&0x7f]&vS)
3344+#define is_zerocount(c) (classify[(c)&0x7f]&vZ)
32573345
32583346 static const unsigned char classify[128] = {
32593347 /* 0 1 2 3 4 5 6 7 */
32603348 /* 0 ^@ ^A ^B ^C ^D ^E ^F ^G */
3261- B_, 0, 0, 0, 0, C_|U_, C_|Z_, 0,
3349+ vB, 0, 0, 0, 0, vC|vU, vC|vZ, 0,
32623350 /* 1 ^H ^I ^J ^K ^L ^M ^N ^O */
3263- M_, C_|Z_, 0, 0, C_|U_, 0, C_, 0,
3351+ vM, vC|vZ, 0, 0, vC|vU, 0, vC, 0,
32643352 /* 2 ^P ^Q ^R ^S ^T ^U ^V ^W */
3265- C_, 0, C_|U_, 0, 0, 0, C_, 0,
3353+ vC, 0, vC|vU, 0, 0, 0, vC, 0,
32663354 /* 3 ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
3267- C_, 0, 0, C_|Z_, 0, 0, 0, 0,
3355+ vC, 0, 0, vC|vZ, 0, 0, 0, 0,
32683356 /* 4 <space> ! " # $ % & ' */
3269- M_, 0, 0, C_, M_, M_, 0, 0,
3357+ vM, 0, 0, vC, vM, vM, 0, 0,
32703358 /* 5 ( ) * + , - . / */
3271- 0, 0, C_, C_, M_, C_, 0, C_|S_,
3359+ 0, 0, vC, vC, vM, vC, 0, vC|vS,
32723360 /* 6 0 1 2 3 4 5 6 7 */
3273- M_, 0, 0, 0, 0, 0, 0, 0,
3361+ vM, 0, 0, 0, 0, 0, 0, 0,
32743362 /* 7 8 9 : ; < = > ? */
3275- 0, 0, 0, M_, 0, C_, 0, C_|S_,
3363+ 0, 0, 0, vM, 0, vC, 0, vC|vS,
32763364 /* 8 @ A B C D E F G */
3277- C_|X_, C_, M_, C_, C_, M_, M_|X_, C_|U_|Z_,
3365+ vC|vX, vC, vM, vC, vC, vM, vM|vX, vC|vU|vZ,
32783366 /* 9 H I J K L M N O */
3279- 0, C_, 0, 0, 0, 0, C_|U_, 0,
3367+ 0, vC, 0, 0, 0, 0, vC|vU, 0,
32803368 /* A P Q R S T U V W */
3281- C_, 0, C_, C_, M_|X_, C_, 0, M_,
3369+ vC, 0, vC, vC, vM|vX, vC, 0, vM,
32823370 /* B X Y Z [ \ ] ^ _ */
3283- C_, C_|U_, 0, 0, C_|Z_, 0, M_, C_|Z_,
3371+ vC, vC|vU, 0, 0, vC|vZ, 0, vM, vC|vZ,
32843372 /* C ` a b c d e f g */
3285- 0, C_, M_, E_, E_, M_, M_|X_, C_|Z_,
3373+ 0, vC, vM, vE, vE, vM, vM|vX, vC|vZ,
32863374 /* D h i j k l m n o */
3287- M_, C_, C_|U_, C_|U_, M_, 0, C_|U_, 0,
3375+ vM, vC, vC|vU, vC|vU, vM, 0, vC|vU, 0,
32883376 /* E p q r s t u v w */
3289- C_, 0, X_, C_, M_|X_, C_|U_, C_|U_|Z_, M_,
3377+ vC, 0, vX, vC, vM|vX, vC|vU, vC|vU|vZ, vM,
32903378 /* F x y z { | } ~ ^? */
3291- C_, E_|U_, 0, 0, M_|Z_, 0, C_, 0
3379+ vC, vE|vU, 0, 0, vM|vZ, 0, vC, 0
32923380 };
32933381
32943382 #define MAXVICMD 3
@@ -3340,7 +3428,8 @@ static int ohnum; /* history line copied (after mod) */
33403428 static int hlast; /* 1 past last position in history */
33413429 static int state;
33423430
3343-/* Information for keeping track of macros that are being expanded.
3431+/*
3432+ * Information for keeping track of macros that are being expanded.
33443433 * The format of buf is the alias contents followed by a NUL byte followed
33453434 * by the name (letter) of the alias. The end of the buffer is marked by
33463435 * a double NUL. The name of the alias is stored so recursive macros can
@@ -3349,14 +3438,14 @@ static int state;
33493438 struct macro_state {
33503439 unsigned char *p; /* current position in buf */
33513440 unsigned char *buf; /* pointer to macro(s) being expanded */
3352- int len; /* how much data in buffer */
3441+ size_t len; /* how much data in buffer */
33533442 };
33543443 static struct macro_state macro;
33553444
3356-enum expand_mode {
3357- NONE, EXPAND, COMPLETE, PRINT
3358-};
3359-static enum expand_mode expanded = NONE; /* last input was expanded */
3445+/* last input was expanded */
3446+static enum expand_mode {
3447+ NONE = 0, EXPAND, COMPLETE, PRINT
3448+} expanded;
33603449
33613450 static int
33623451 x_vi(char *buf, size_t len)
@@ -3386,10 +3475,11 @@ x_vi(char *buf, size_t len)
33863475
33873476 pprompt(prompt, 0);
33883477 if (cur_col > x_cols - 3 - MIN_EDIT_SPACE) {
3389- prompt_redraw = cur_col = 0;
3478+ prompt_redraw = false;
3479+ cur_col = 0;
33903480 x_putc('\n');
33913481 } else
3392- prompt_redraw = 1;
3482+ prompt_redraw = true;
33933483 pwidth = cur_col;
33943484
33953485 if (!wbuf_len || wbuf_len != x_cols - 3) {
@@ -3397,8 +3487,10 @@ x_vi(char *buf, size_t len)
33973487 wbuf[0] = aresize(wbuf[0], wbuf_len, APERM);
33983488 wbuf[1] = aresize(wbuf[1], wbuf_len, APERM);
33993489 }
3400- (void)memset(wbuf[0], ' ', wbuf_len);
3401- (void)memset(wbuf[1], ' ', wbuf_len);
3490+ if (wbuf_len) {
3491+ memset(wbuf[0], ' ', wbuf_len);
3492+ memset(wbuf[1], ' ', wbuf_len);
3493+ }
34023494 winwidth = x_cols - pwidth - 3;
34033495 win = 0;
34043496 morec = ' ';
@@ -3407,7 +3499,7 @@ x_vi(char *buf, size_t len)
34073499
34083500 editmode = 2;
34093501 x_flush();
3410- while (1) {
3502+ while (/* CONSTCOND */ 1) {
34113503 if (macro.p) {
34123504 c = *macro.p++;
34133505 /* end of current macro? */
@@ -3804,7 +3896,8 @@ vi_insert(int ch)
38043896 expanded = NONE;
38053897 return (0);
38063898 }
3807- /* If any chars are entered before escape, trash the saved insert
3899+ /*
3900+ * If any chars are entered before escape, trash the saved insert
38083901 * buffer (if user inserts & deletes char, ibuf gets trashed and
38093902 * we don't want to use it)
38103903 */
@@ -3905,14 +3998,14 @@ vi_cmd(int argcnt, const char *cmd)
39053998
39063999 case Ctrl('l'):
39074000 case Ctrl('r'):
3908- redraw_line(1);
4001+ redraw_line(true);
39094002 break;
39104003
39114004 case '@':
39124005 {
39134006 static char alias[] = "_\0";
39144007 struct tbl *ap;
3915- int olen, nlen;
4008+ size_t olen, nlen;
39164009 char *p, *nbuf;
39174010
39184011 /* lookup letter in alias list... */
@@ -3929,6 +4022,10 @@ vi_cmd(int argcnt, const char *cmd)
39294022 nlen = strlen(ap->val.s) + 1;
39304023 olen = !macro.p ? 2 :
39314024 macro.len - (macro.p - macro.buf);
4025+ /*
4026+ * at this point, it's fairly reasonable that
4027+ * nlen + olen + 2 doesn't overflow
4028+ */
39324029 nbuf = alloc(nlen + 1 + olen, APERM);
39334030 memcpy(nbuf, ap->val.s, nlen);
39344031 nbuf[nlen++] = cmd[1];
@@ -4323,29 +4420,37 @@ vi_cmd(int argcnt, const char *cmd)
43234420 return (ret);
43244421 }
43254422
4326- case '=': /* AT&T ksh */
4327- case Ctrl('e'): /* Nonstandard vi/ksh */
4423+ /* AT&T ksh */
4424+ case '=':
4425+ /* Nonstandard vi/ksh */
4426+ case Ctrl('e'):
43284427 print_expansions(es, 1);
43294428 break;
43304429
43314430
4332- case Ctrl('i'): /* Nonstandard vi/ksh */
4431+ /* Nonstandard vi/ksh */
4432+ case Ctrl('i'):
43334433 if (!Flag(FVITABCOMPLETE))
43344434 return (-1);
43354435 complete_word(1, argcnt);
43364436 break;
43374437
4338- case Ctrl('['): /* some annoying AT&T kshs */
4438+ /* some annoying AT&T kshs */
4439+ case Ctrl('['):
43394440 if (!Flag(FVIESCCOMPLETE))
43404441 return (-1);
4341- case '\\': /* AT&T ksh */
4342- case Ctrl('f'): /* Nonstandard vi/ksh */
4442+ /* AT&T ksh */
4443+ case '\\':
4444+ /* Nonstandard vi/ksh */
4445+ case Ctrl('f'):
43434446 complete_word(1, argcnt);
43444447 break;
43454448
43464449
4347- case '*': /* AT&T ksh */
4348- case Ctrl('x'): /* Nonstandard vi/ksh */
4450+ /* AT&T ksh */
4451+ case '*':
4452+ /* Nonstandard vi/ksh */
4453+ case Ctrl('x'):
43494454 expand_word(1);
43504455 break;
43514456 }
@@ -4613,7 +4718,7 @@ x_vi_putbuf(const char *s, size_t len)
46134718 }
46144719
46154720 static int
4616-putbuf(const char *buf, int len, int repl)
4721+putbuf(const char *buf, ssize_t len, int repl)
46174722 {
46184723 if (len == 0)
46194724 return (0);
@@ -4811,7 +4916,7 @@ grabhist(int save, int n)
48114916 }
48124917 (void)histnum(n);
48134918 if ((hptr = *histpos()) == NULL) {
4814- internal_warningf("grabhist: bad history array");
4919+ internal_warningf("%s: %s", "grabhist", "bad history array");
48154920 return (-1);
48164921 }
48174922 if (save)
@@ -4825,7 +4930,7 @@ grabhist(int save, int n)
48254930 }
48264931
48274932 static int
4828-grabsearch(int save, int start, int fwd, char *pat)
4933+grabsearch(int save, int start, int fwd, const char *pat)
48294934 {
48304935 char *hptr;
48314936 int hist;
@@ -4839,8 +4944,7 @@ grabsearch(int save, int start, int fwd, char *pat)
48394944 start--;
48404945 anchored = *pat == '^' ? (++pat, 1) : 0;
48414946 if ((hist = findhist(start, fwd, pat, anchored)) < 0) {
4842- /* if (start != 0 && fwd && match(holdbuf, pat) >= 0) { */
4843- /* XXX should strcmp be strncmp? */
4947+ /* (start != 0 && fwd && match(holdbuf, pat) >= 0) */
48444948 if (start != 0 && fwd && strcmp(holdbuf, pat) >= 0) {
48454949 restore_cbuf();
48464950 return (0);
@@ -4859,9 +4963,10 @@ grabsearch(int save, int start, int fwd, char *pat)
48594963 }
48604964
48614965 static void
4862-redraw_line(int newl)
4966+redraw_line(bool newl)
48634967 {
4864- (void)memset(wbuf[win], ' ', wbuf_len);
4968+ if (wbuf_len)
4969+ memset(wbuf[win], ' ', wbuf_len);
48654970 if (newl) {
48664971 x_putc('\r');
48674972 x_putc('\n');
@@ -4996,7 +5101,8 @@ display(char *wb1, char *wb2, int leftside)
49965101 col++;
49975102 }
49985103 if (es->winleft > 0 && moreright)
4999- /* POSIX says to use * for this but that is a globbing
5104+ /*
5105+ * POSIX says to use * for this but that is a globbing
50005106 * character and may confuse people; + is more innocuous
50015107 */
50025108 mc = '+';
@@ -5045,11 +5151,8 @@ static int
50455151 expand_word(int cmd)
50465152 {
50475153 static struct edstate *buf;
5048- int rval = 0;
5049- int nwords;
5050- int start, end;
5154+ int rval = 0, nwords, start, end, i;
50515155 char **words;
5052- int i;
50535156
50545157 /* Undo previous expansion */
50555158 if (cmd == 0 && expanded == EXPAND && buf) {
@@ -5063,9 +5166,9 @@ expand_word(int cmd)
50635166 buf = 0;
50645167 }
50655168
5066- nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH,
5067- es->cbuf, es->linelen, es->cursor,
5068- &start, &end, &words, NULL);
5169+ i = XCF_COMMAND_FILE | XCF_FULLPATH;
5170+ nwords = x_cf_glob(&i, es->cbuf, es->linelen, es->cursor,
5171+ &start, &end, &words);
50695172 if (nwords == 0) {
50705173 vi_error();
50715174 return (-1);
@@ -5075,7 +5178,8 @@ expand_word(int cmd)
50755178 expanded = EXPAND;
50765179 del_range(start, end);
50775180 es->cursor = start;
5078- for (i = 0; i < nwords; ) {
5181+ i = 0;
5182+ while (i < nwords) {
50795183 if (x_escape(words[i], strlen(words[i]), x_vi_putbuf) != 0) {
50805184 rval = -1;
50815185 break;
@@ -5100,10 +5204,11 @@ static int
51005204 complete_word(int cmd, int count)
51015205 {
51025206 static struct edstate *buf;
5103- int rval, nwords, start, end, match_len;
5207+ int rval, nwords, start, end, flags;
5208+ size_t match_len;
51045209 char **words;
51055210 char *match;
5106- bool is_command, is_unique;
5211+ bool is_unique;
51075212
51085213 /* Undo previous completion */
51095214 if (cmd == 0 && expanded == COMPLETE && buf) {
@@ -5122,12 +5227,15 @@ complete_word(int cmd, int count)
51225227 buf = 0;
51235228 }
51245229
5125- /* XCF_FULLPATH for count 'cause the menu printed by print_expansions()
5126- * was done this way.
5230+ /*
5231+ * XCF_FULLPATH for count 'cause the menu printed by
5232+ * print_expansions() was done this way.
51275233 */
5128- nwords = x_cf_glob(XCF_COMMAND_FILE | (count ? XCF_FULLPATH : 0),
5129- es->cbuf, es->linelen, es->cursor,
5130- &start, &end, &words, &is_command);
5234+ flags = XCF_COMMAND_FILE;
5235+ if (count)
5236+ flags |= XCF_FULLPATH;
5237+ nwords = x_cf_glob(&flags, es->cbuf, es->linelen, es->cursor,
5238+ &start, &end, &words);
51315239 if (nwords == 0) {
51325240 vi_error();
51335241 return (-1);
@@ -5138,15 +5246,16 @@ complete_word(int cmd, int count)
51385246 count--;
51395247 if (count >= nwords) {
51405248 vi_error();
5141- x_print_expansions(nwords, words, is_command);
5249+ x_print_expansions(nwords, words,
5250+ tobool(flags & XCF_IS_COMMAND));
51425251 x_free_words(nwords, words);
5143- redraw_line(0);
5252+ redraw_line(false);
51445253 return (-1);
51455254 }
51465255 /*
51475256 * Expand the count'th word to its basename
51485257 */
5149- if (is_command) {
5258+ if (flags & XCF_IS_COMMAND) {
51505259 match = words[count] +
51515260 x_basename(words[count], NULL);
51525261 /* If more than one possible match, use full path */
@@ -5165,7 +5274,8 @@ complete_word(int cmd, int count)
51655274 } else {
51665275 match = words[0];
51675276 match_len = x_longest_prefix(nwords, words);
5168- expanded = COMPLETE; /* next call will list completions */
5277+ /* next call will list completions */
5278+ expanded = COMPLETE;
51695279 is_unique = nwords == 1;
51705280 }
51715281
@@ -5173,18 +5283,25 @@ complete_word(int cmd, int count)
51735283 del_range(start, end);
51745284 es->cursor = start;
51755285
5176- /* escape all shell-sensitive characters and put the result into
5177- * command buffer */
5286+ /*
5287+ * escape all shell-sensitive characters and put the result into
5288+ * command buffer
5289+ */
51785290 rval = x_escape(match, match_len, x_vi_putbuf);
51795291
51805292 if (rval == 0 && is_unique) {
5181- /* If exact match, don't undo. Allows directory completions
5293+ /*
5294+ * If exact match, don't undo. Allows directory completions
51825295 * to be used (ie, complete the next portion of the path).
51835296 */
51845297 expanded = NONE;
51855298
5186- /* If not a directory, add a space to the end... */
5187- if (match_len > 0 && match[match_len - 1] != '/')
5299+ /*
5300+ * append a space if this is a non-directory match
5301+ * and not a parameter or homedir substitution
5302+ */
5303+ if (match_len > 0 && match[match_len - 1] != '/' &&
5304+ !(flags & XCF_IS_SUBGLOB))
51885305 rval = putbuf(" ", 1, 0);
51895306 }
51905307 x_free_words(nwords, words);
@@ -5192,7 +5309,8 @@ complete_word(int cmd, int count)
51925309 modified = 1;
51935310 hnum = hlast;
51945311 insert = INSERT;
5195- lastac = 0; /* prevent this from being redone... */
5312+ /* prevent this from being redone... */
5313+ lastac = 0;
51965314 refresh(0);
51975315
51985316 return (rval);
@@ -5201,20 +5319,19 @@ complete_word(int cmd, int count)
52015319 static int
52025320 print_expansions(struct edstate *est, int cmd MKSH_A_UNUSED)
52035321 {
5204- int start, end, nwords;
5322+ int start, end, nwords, i;
52055323 char **words;
5206- bool is_command;
52075324
5208- nwords = x_cf_glob(XCF_COMMAND_FILE | XCF_FULLPATH,
5209- est->cbuf, est->linelen, est->cursor,
5210- &start, &end, &words, &is_command);
5325+ i = XCF_COMMAND_FILE | XCF_FULLPATH;
5326+ nwords = x_cf_glob(&i, est->cbuf, est->linelen, est->cursor,
5327+ &start, &end, &words);
52115328 if (nwords == 0) {
52125329 vi_error();
52135330 return (-1);
52145331 }
5215- x_print_expansions(nwords, words, is_command);
5332+ x_print_expansions(nwords, words, tobool(i & XCF_IS_COMMAND));
52165333 x_free_words(nwords, words);
5217- redraw_line(0);
5334+ redraw_line(false);
52185335 return (0);
52195336 }
52205337
@@ -5247,3 +5364,34 @@ vi_macro_reset(void)
52475364 }
52485365 }
52495366 #endif /* !MKSH_S_NOVI */
5367+
5368+void
5369+x_mkraw(int fd, struct termios *ocb, bool forread)
5370+{
5371+ struct termios cb;
5372+
5373+ if (ocb)
5374+ tcgetattr(fd, ocb);
5375+ else
5376+ ocb = &tty_state;
5377+
5378+ cb = *ocb;
5379+ if (forread) {
5380+ cb.c_lflag &= ~(ICANON) | ECHO;
5381+ } else {
5382+ cb.c_iflag &= ~(INLCR | ICRNL);
5383+ cb.c_lflag &= ~(ISIG | ICANON | ECHO);
5384+ }
5385+#if defined(VLNEXT) && defined(_POSIX_VDISABLE)
5386+ /* OSF/1 processes lnext when ~icanon */
5387+ cb.c_cc[VLNEXT] = _POSIX_VDISABLE;
5388+#endif
5389+ /* SunOS 4.1.x & OSF/1 processes discard(flush) when ~icanon */
5390+#if defined(VDISCARD) && defined(_POSIX_VDISABLE)