OSDN Git Service

Upgrade to mksh 51.
authorElliott Hughes <enh@google.com>
Fri, 17 Jul 2015 18:39:41 +0000 (11:39 -0700)
committerElliott Hughes <enh@google.com>
Fri, 17 Jul 2015 18:44:21 +0000 (11:44 -0700)
Bug: http://b/22413333
Change-Id: Id86d5bf463af540b84d03a7b8fe092d23702f414

30 files changed:
Android.mk
Makefrag.inc
src/Build.sh
src/check.pl
src/check.t
src/dot.mkshrc
src/edit.c
src/emacsfn.h
src/eval.c
src/exec.c
src/expr.c
src/funcs.c
src/histrap.c
src/jobs.c
src/lalloc.c
src/lex.c
src/lksh.1
src/main.c
src/mirhash.h
src/misc.c
src/mksh.1
src/rlimits.gen
src/rlimits.opt
src/sh.h
src/sh_flags.gen
src/sh_flags.opt
src/shf.c
src/syn.c
src/tree.c
src/var.c

index a78409f..9b1d914 100644 (file)
@@ -61,7 +61,7 @@ LOCAL_CFLAGS += \
     -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 \
     -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 \
     -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 \
-    -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 \
+    -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_IO_H=0 -DHAVE_LIBGEN_H=1 \
     -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 \
     -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 \
     -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 \
@@ -79,6 +79,6 @@ LOCAL_CFLAGS += \
     -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 \
     -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
     -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 \
-    -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=506
+    -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=511
 
 include $(BUILD_EXECUTABLE)
index 9c3632b..0f29116 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile fragment for building mksh R50 2015/04/19
+# Makefile fragment for building mksh R51 2015/07/10
 
 PROG=          mksh
 MAN=           mksh.1
@@ -10,7 +10,7 @@ NONSRCS_INST= dot.mkshrc $(MAN)
 NONSRCS_NOINST=        Build.sh Makefile Rebuild.sh check.pl check.t test.sh
 CC=            /huge-ssd/aosp-arm64/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/*-gcc
 CFLAGS=                 -fno-exceptions -Wno-multichar -fpic -fPIE -ffunction-sections -fdata-sections -funwind-tables -fstack-protector -Wa,--noexecstack -Werror=format-security -fno-short-enums -Wno-unused-but-set-variable -fno-builtin-sin -fno-strict-volatile-bitfields -Wno-psabi -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -g -Wstrict-aliasing=2 -fgcse-after-reload -frerun-cse-after-loop -frename-registers -Os -fomit-frame-pointer -fno-strict-aliasing -Wno-deprecated-declarations -fno-asynchronous-unwind-tables -fstack-protector-strong -fwrapv
-CPPFLAGS=      -I. -I'../src'  -isystem /huge-ssd/aosp-arm64/bionic/libc/arch-arm64/include -isystem /huge-ssd/aosp-arm64/bionic/libc/include -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi/asm-arm64 -isystem /huge-ssd/aosp-arm64/bionic/libm/include -isystem /huge-ssd/aosp-arm64/bionic/libm/include/arm64 -D_FORTIFY_SOURCE=2 -include /huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/AndroidConfig.h -I/huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/ -DANDROID -DNDEBUG -UDEBUG -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 -DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_ISSETUGID=0 -DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=506
+CPPFLAGS=      -I. -I'../src'  -isystem /huge-ssd/aosp-arm64/bionic/libc/arch-arm64/include -isystem /huge-ssd/aosp-arm64/bionic/libc/include -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi/asm-arm64 -isystem /huge-ssd/aosp-arm64/bionic/libm/include -isystem /huge-ssd/aosp-arm64/bionic/libm/include/arm64 -D_FORTIFY_SOURCE=2 -include /huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/AndroidConfig.h -I/huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/ -DANDROID -DNDEBUG -UDEBUG -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_IO_H=0 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 -DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_ISSETUGID=0 -DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=511
 LDFLAGS=        -nostdlib -Bdynamic -fPIE -pie -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined /huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib/crtbegin_dynamic.o
 LIBS=           -L/huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib -Wl,-rpath-link=/huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib -Wl,--no-whole-archive /huge-ssd/aosp-arm64/out/target/product/flounder/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a -lc /huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib/crtend_android.o
 
index 70c1d24..d5884be 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669.2.4 2015/04/19 19:18:08 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.689 2015/07/10 17:16:23 tg Exp $'
 #-
 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 #              2011, 2012, 2013, 2014, 2015
@@ -314,6 +314,7 @@ ac_testnnd() {
        vv ']' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN conftest.c $LIBS $ccpr"
        test $tcfn = no && test -f a.out && tcfn=a.out
        test $tcfn = no && test -f a.exe && tcfn=a.exe
+       test $tcfn = no && test -f conftest.exe && tcfn=conftest.exe
        test $tcfn = no && test -f conftest && tcfn=conftest
        if test -f $tcfn; then
                test 1 = $fr || fv=1
@@ -577,8 +578,8 @@ if test -d $tfn || test -d $tfn.exe; then
        echo "$me: Error: ./$tfn is a directory!" >&2
        exit 1
 fi
-rmf a.exe* a.out* conftest.c *core core.* lft ${tfn}* no *.bc *.ll *.o *.gen \
-    Rebuild.sh signames.inc test.sh x vv.out
+rmf a.exe* a.out* conftest.c conftest.exe* *core core.* ${tfn}* *.bc *.dbg \
+    *.ll *.o *.gen Rebuild.sh lft no signames.inc test.sh x vv.out
 
 SRCS="lalloc.c eval.c exec.c expr.c funcs.c histrap.c jobs.c"
 SRCS="$SRCS lex.c main.c misc.c shf.c syn.c tree.c var.c"
@@ -682,14 +683,14 @@ esac
 # Configuration depending on OS name
 case $TARGET_OS in
 386BSD)
-       : ${HAVE_CAN_OTWO=0}
+       : "${HAVE_CAN_OTWO=0}"
        add_cppflags -DMKSH_NO_SIGSETJMP
        add_cppflags -DMKSH_TYPEDEF_SIG_ATOMIC_T=int
        add_cppflags -DMKSH_CONSERVATIVE_FDS
        ;;
 AIX)
        add_cppflags -D_ALL_SOURCE
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 BeOS)
        case $KSH_VERSION in
@@ -708,7 +709,7 @@ BeOS)
        add_cppflags -DMKSH__NO_SETEUGID
        ;;
 BSD/OS)
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 Coherent)
        oswarn="; it has major issues"
@@ -719,7 +720,7 @@ Coherent)
        add_cppflags -DMKSH_DISABLE_TTY_WARNING
        ;;
 CYGWIN*)
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 Darwin)
        add_cppflags -D_DARWIN_C_SOURCE
@@ -732,7 +733,7 @@ FreeMiNT)
        oswarn="; it has minor issues"
        add_cppflags -D_GNU_SOURCE
        add_cppflags -DMKSH_CONSERVATIVE_FDS
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 GNU)
        case $CC in
@@ -757,11 +758,11 @@ Interix)
        ccpc='-X '
        ccpl='-Y '
        add_cppflags -D_ALL_SOURCE
-       : ${LIBS='-lcrypt'}
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${LIBS=-lcrypt}"
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 IRIX*)
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 Linux)
        case $CC in
@@ -769,7 +770,7 @@ Linux)
        *) add_cppflags -D_GNU_SOURCE ;;
        esac
        add_cppflags -DSETUID_CAN_FAIL_WITH_EAGAIN
-       : ${HAVE_REVOKE=0}
+       : "${HAVE_REVOKE=0}"
        ;;
 LynxOS)
        oswarn="; it has minor issues"
@@ -782,7 +783,7 @@ Minix-vmd)
        add_cppflags -DMKSH_CONSERVATIVE_FDS
        add_cppflags -D_MINIX_SOURCE
        oldish_ed=no-stderr-ed          # no /bin/ed, maybe see below
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 Minix3)
        add_cppflags -DMKSH_UNEMPLOYED
@@ -790,23 +791,24 @@ Minix3)
        add_cppflags -DMKSH_NO_LIMITS
        add_cppflags -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX
        oldish_ed=no-stderr-ed          # /usr/bin/ed(!) is broken
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 MirBSD)
        ;;
 MSYS_*)
        add_cppflags -DMKSH_ASSUME_UTF8=0; HAVE_ISSET_MKSH_ASSUME_UTF8=1
        # almost same as CYGWIN* (from RT|Chatzilla)
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        # broken on this OE (from ir0nh34d)
-       : ${HAVE_STDINT_H=0}
+       : "${HAVE_STDINT_H=0}"
        ;;
 NetBSD)
        ;;
 NEXTSTEP)
        add_cppflags -D_NEXT_SOURCE
        add_cppflags -D_POSIX_SOURCE
-       : ${AWK=gawk} ${CC=cc -posix}
+       : "${AWK=gawk}"
+       : "${CC=cc -posix}"
        add_cppflags -DMKSH_NO_SIGSETJMP
        # NeXTstep cannot get a controlling tty
        add_cppflags -DMKSH_UNEMPLOYED
@@ -827,7 +829,17 @@ Ninix3)
        oswarn="; it has unknown issues"
        ;;
 OpenBSD)
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
+       ;;
+OS/2)
+       HAVE_TERMIOS_H=0
+       HAVE_MKNOD=0    # setmode() incompatible
+       oswarn="; it is currently being ported"
+       check_categories="$check_categories nosymlink"
+       : "${CC=gcc}"
+       : "${SIZE=: size}"
+       add_cppflags -DMKSH_UNEMPLOYED
+       add_cppflags -DMKSH_NOPROSPECTOFWORK
        ;;
 OSF1)
        HAVE_SIG_T=0    # incompatible
@@ -835,7 +847,7 @@ OSF1)
        add_cppflags -D_POSIX_C_SOURCE=200112L
        add_cppflags -D_XOPEN_SOURCE=600
        add_cppflags -D_XOPEN_SOURCE_EXTENDED
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 Plan9)
        add_cppflags -D_POSIX_SOURCE
@@ -853,7 +865,7 @@ Plan9)
 PW32*)
        HAVE_SIG_T=0    # incompatible
        oswarn=' and will currently not work'
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 QNX)
        add_cppflags -D__NO_EXT_QNX
@@ -863,7 +875,7 @@ QNX)
                oldish_ed=no-stderr-ed          # oldish /bin/ed is broken
                ;;
        esac
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 SCO_SV)
        case $TARGET_OSREV in
@@ -880,7 +892,7 @@ SCO_SV)
                ;;
        esac
        add_cppflags -DMKSH_CONSERVATIVE_FDS
-       : ${HAVE_SYS_SIGLIST=0} ${HAVE__SYS_SIGLIST=0}
+       : "${HAVE_SYS_SIGLIST=0}${HAVE__SYS_SIGLIST=0}"
        ;;
 skyos)
        oswarn="; it has minor issues"
@@ -895,15 +907,15 @@ syllable)
        oswarn=' and will currently not work'
        ;;
 ULTRIX)
-       : ${CC=cc -YPOSIX}
+       : "${CC=cc -YPOSIX}"
        add_cppflags -DMKSH_TYPEDEF_SSIZE_T=int
        add_cppflags -DMKSH_CONSERVATIVE_FDS
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 UnixWare|UNIX_SV)
        # SCO UnixWare
        add_cppflags -DMKSH_CONSERVATIVE_FDS
-       : ${HAVE_SYS_SIGLIST=0} ${HAVE__SYS_SIGLIST=0}
+       : "${HAVE_SYS_SIGLIST=0}${HAVE__SYS_SIGLIST=0}"
        ;;
 UWIN*)
        ccpc='-Yc,'
@@ -911,7 +923,7 @@ UWIN*)
        tsts=" 3<>/dev/tty"
        oswarn="; it will compile, but the target"
        oswarn="$oswarn${nl}platform itself is very flakey/unreliable"
-       : ${HAVE_SETLOCALE_CTYPE=0}
+       : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
 _svr4)
        # generic target for SVR4 Unix with uname -s = uname -n
@@ -925,11 +937,11 @@ _svr4)
        ;;
 esac
 
-: ${HAVE_MKNOD=0}
+: "${HAVE_MKNOD=0}"
 
-: ${AWK=awk} ${CC=cc} ${NROFF=nroff} ${SIZE=size}
+: "${AWK=awk}${CC=cc}${NROFF=nroff}${SIZE=size}"
 test 0 = $r && echo | $NROFF -v 2>&1 | grep GNU >/dev/null 2>&1 && \
-    NROFF="$NROFF -c"
+    echo | $NROFF -c >/dev/null 2>&1 && NROFF="$NROFF -c"
 
 # this aids me in tracing FTBFSen without access to the buildd
 $e "Hi from$ao $bi$srcversion$ao on:"
@@ -1050,7 +1062,7 @@ ct="unknown"
 #endif
 ;
 const char *
-#if defined(__KLIBC__)
+#if defined(__KLIBC__) && !defined(__OS2__)
 et="klibc"
 #else
 et="unknown"
@@ -1194,7 +1206,7 @@ uslc)
        SCO_SV:3.2*)
                # SCO OpenServer 5
                CFLAGS="$CFLAGS -g"
-               : ${HAVE_CAN_OTWO=0} ${HAVE_CAN_OPTIMISE=0}
+               : "${HAVE_CAN_OTWO=0}${HAVE_CAN_OPTIMISE=0}"
                ;;
        esac
        vv '|' "$CC $CFLAGS $CPPFLAGS $LDFLAGS $NOWARN -V conftest.c $LIBS"
@@ -1233,7 +1245,7 @@ unknown)
        ;;
 esac
 $e "$bi==> which compiler seems to be used...$ao $ui$ct${et+ on $et}$ao"
-rmf conftest.c conftest.o conftest a.out* a.exe* vv.out
+rmf conftest.c conftest.o conftest a.out* a.exe* conftest.exe* vv.out
 
 #
 # Compiler: works as-is, with -Wno-error and -Werror
@@ -1248,7 +1260,7 @@ test $ct = unknown || HAVE_COMPILER_KNOWN=1
 if ac_ifcpp 'if 0' compiler_fails '' \
     'if the compiler does not fail correctly'; then
        save_CFLAGS=$CFLAGS
-       : ${HAVE_CAN_DELEXE=x}
+       : "${HAVE_CAN_DELEXE=x}"
        case $ct in
        dec)
                CFLAGS="$CFLAGS ${ccpl}-non_shared"
@@ -1610,8 +1622,8 @@ phase=x
 #
 if ac_ifcpp 'ifdef MKSH_SMALL' isset_MKSH_SMALL '' \
     "if a reduced-feature mksh is requested"; then
-       : ${HAVE_NICE=0}
-       : ${HAVE_PERSISTENT_HISTORY=0}
+       : "${HAVE_NICE=0}"
+       : "${HAVE_PERSISTENT_HISTORY=0}"
        check_categories="$check_categories smksh"
        HAVE_ISSET_MKSH_CONSERVATIVE_FDS=1      # from sh.h
 fi
@@ -1625,7 +1637,7 @@ ac_ifcpp 'ifdef MKSH_NOPROSPECTOFWORK' isset_MKSH_NOPROSPECTOFWORK '' \
     "if mksh will be built without job signals" && \
     check_categories="$check_categories arge nojsig"
 ac_ifcpp 'ifdef MKSH_ASSUME_UTF8' isset_MKSH_ASSUME_UTF8 '' \
-    'if the default UTF-8 mode is specified' && : ${HAVE_SETLOCALE_CTYPE=0}
+    'if the default UTF-8 mode is specified' && : "${HAVE_SETLOCALE_CTYPE=0}"
 ac_ifcpp 'ifdef MKSH_CONSERVATIVE_FDS' isset_MKSH_CONSERVATIVE_FDS '' \
     'if traditional/conservative fd use is requested' && \
     check_categories="$check_categories convfds"
@@ -1662,6 +1674,7 @@ ac_header sys/select.h sys/types.h
 ac_header sys/sysmacros.h
 ac_header bstring.h
 ac_header grp.h sys/types.h
+ac_header io.h
 ac_header libgen.h
 ac_header libutil.h sys/types.h
 ac_header paths.h
@@ -2248,20 +2261,22 @@ if test 0 = $HAVE_SYS_SIGNAME; then
        sigseenone=:
        sigseentwo=:
        echo '#include <signal.h>
-#ifndef NSIG
-#if defined(_NSIG)
-#define NSIG _NSIG
+#if defined(NSIG_MAX)
+#define cfg_NSIG NSIG_MAX
+#elif defined(NSIG)
+#define cfg_NSIG NSIG
+#elif defined(_NSIG)
+#define cfg_NSIG _NSIG
 #elif defined(SIGMAX)
-#define NSIG (SIGMAX+1)
+#define cfg_NSIG (SIGMAX + 1)
 #elif defined(_SIGMAX)
-#define NSIG (_SIGMAX+1)
+#define cfg_NSIG (_SIGMAX + 1)
 #else
-/* XXX better error out, see sh.h */
-#define NSIG 64
-#endif
+/*XXX better error out, see sh.h */
+#define cfg_NSIG 64
 #endif
 int
-mksh_cfg= NSIG
+mksh_cfg= cfg_NSIG
 ;' >conftest.c
        # GNU sed 2.03 segfaults when optimising this to sed -n
        NSIG=`vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
@@ -2283,8 +2298,8 @@ mksh_cfg= NSIG
        $printf "NSIG=$NSIG ... "
        sigs="ABRT FPE ILL INT SEGV TERM ALRM BUS CHLD CONT HUP KILL PIPE QUIT"
        sigs="$sigs STOP TSTP TTIN TTOU USR1 USR2 POLL PROF SYS TRAP URG VTALRM"
-       sigs="$sigs XCPU XFSZ INFO WINCH EMT IO DIL LOST PWR SAK CLD IOT RESV"
-       sigs="$sigs STKFLT UNUSED"
+       sigs="$sigs XCPU XFSZ INFO WINCH EMT IO DIL LOST PWR SAK CLD IOT STKFLT"
+       sigs="$sigs ABND DCE DUMP IOERR TRACE DANGER THCONT THSTOP RESV UNUSED"
        test 1 = $HAVE_CPP_DD && test $NSIG -gt 1 && sigs="$sigs "`vq \
            "$CPP $CFLAGS $CPPFLAGS $NOWARN -dD conftest.c" | \
            grep '[      ]SIG[A-Z0-9][A-Z0-9]*[  ]' | \
@@ -2310,7 +2325,7 @@ mksh_cfg= NSIG
                    sed 's/^ *mksh_cfg *=[       ]*\([0-9][0-9x]*\).*$/:\1 '$name/
        done | sed -n '/^:[^ ]/s/^://p' | while read nr name; do
                test $printf = echo || nr=`printf %d "$nr" 2>/dev/null`
-               test $nr -gt 0 && test $nr -le $NSIG || continue
+               test $nr -gt 0 && test $nr -lt $NSIG || continue
                case $sigseentwo in
                *:$nr:*) ;;
                *)      echo "          { \"$name\", $nr },"
@@ -2327,7 +2342,7 @@ addsrcs '!' HAVE_STRLCPY strlcpy.c
 addsrcs USE_PRINTF_BUILTIN printf.c
 test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
 test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
-add_cppflags -DMKSH_BUILD_R=506
+add_cppflags -DMKSH_BUILD_R=511
 
 $e $bi$me: Finished configuration testing, now producing output.$ao
 
@@ -2335,8 +2350,13 @@ files=
 objs=
 sp=
 case $tcfn in
-a.exe) mkshexe=$tfn.exe ;;
-*)     mkshexe=$tfn ;;
+a.exe|conftest.exe)
+       mkshexe=$tfn.exe
+       add_cppflags -DMKSH_EXE_EXT
+       ;;
+*)
+       mkshexe=$tfn
+       ;;
 esac
 case $curdir in
 *\ *)  mkshshebang="#!./$mkshexe" ;;
@@ -2643,7 +2663,6 @@ MKSH_NOPROSPECTOFWORK             disable jobs, co-processes, etc. (do not use)
 MKSH_NOPWNAM                   skip PAM calls, for -static on glibc or Solaris
 MKSH_NO_CMDLINE_EDITING                disable command line editing code entirely
 MKSH_NO_DEPRECATED_WARNING     omit warning when deprecated stuff is run
-MKSH_NO_EXTERNAL_CAT           omit hack to skip cat builtin when flags passed
 MKSH_NO_LIMITS                 omit ulimit code
 MKSH_NO_SIGSETJMP              define if sigsetjmp is broken or not available
 MKSH_NO_SIGSUSPEND             use sigprocmask+pause instead of sigsuspend
@@ -2670,4 +2689,7 @@ using $NROFF. Consider using a forward script as /etc/skel/.mkshrc like
 http://anonscm.debian.org/cgit/collab-maint/mksh.git/plain/debian/.mkshrc
 and put dot.mkshrc as /etc/mkshrc so users need not keep up their HOME.
 
+You may also want to install the lksh binary (also as /bin/sh) built by:
+$ CPPFLAGS="$CPPFLAGS -DMKSH_BINSHPOSIX" sh Build.sh -L -r -c lto
+
 EOD
index ce45773..4417f82 100644 (file)
@@ -1,4 +1,4 @@
-# $MirOS: src/bin/mksh/check.pl,v 1.37.2.1 2015/04/12 22:32:16 tg Exp $
+# $MirOS: src/bin/mksh/check.pl,v 1.40 2015/07/10 19:36:31 tg Exp $
 # $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $
 #-
 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
 #                                      the following minimal environment:
 #                                          HOME, LD_LIBRARY_PATH, LOCPATH,
 #                                          LOGNAME, PATH, SHELL, UNIXMODE,
-#                                          USER
+#                                          UNIXROOT, USER
 #                                      (values taken from the environment of
 #                                      the test harness).
 #                                      CYGWIN is set to nodosfilewarning.
 #                                      ENV is set to /nonexistant.
+#                                      PATHSEP is set to either : or ;.
 #                                      __progname is set to the -p argument.
 #                                      __perlname is set to $^X (perlexe).
 #      file-setup              mps     Used to create files, directories
@@ -275,11 +276,12 @@ $all_tests = @ARGV == 0;
 # Set up a very minimal environment
 %new_env = ();
 foreach $env (('HOME', 'LD_LIBRARY_PATH', 'LOCPATH', 'LOGNAME',
-  'PATH', 'SHELL', 'UNIXMODE', 'USER')) {
+  'PATH', 'SHELL', 'UNIXMODE', 'UNIXROOT', 'USER')) {
     $new_env{$env} = $ENV{$env} if defined $ENV{$env};
 }
 $new_env{'CYGWIN'} = 'nodosfilewarning';
 $new_env{'ENV'} = '/nonexistant';
+$new_env{'PATHSEP'} = $os eq 'os2' ? ';' : ':';
 if (($os eq 'VMS') || ($Config{perlpath} =~ m/$Config{_exe}$/i)) {
        $new_env{'__perlname'} = $Config{perlpath};
 } else {
@@ -312,9 +314,10 @@ die "$prog: couldn't get temporary directory\n" if $temp_dir eq '';
 die "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd);
 
 if (!$program_kludge) {
-    $test_prog = "$pwd/$test_prog" if substr($test_prog, 0, 1) ne '/';
+    $test_prog = "$pwd/$test_prog" if (substr($test_prog, 0, 1) ne '/') &&
+      ($os ne 'os2' || substr($test_prog, 1, 1) ne ':');
     die "$prog: $test_prog is not executable - bye\n"
-       if (! -x $test_prog && $os ne 'os2');
+      if (! -x $test_prog && $os ne 'os2');
 }
 
 @trap_sigs = ('TERM', 'QUIT', 'INT', 'PIPE', 'HUP');
@@ -1165,7 +1168,7 @@ read_test
                print STDERR "$prog:$test{':long-name'}: expected-exit value $val not in 0..255\n";
                return undef;
            }
-       } elsif ($val !~ /^([\s<>+-=*%\/&|!()]|\b[wse]\b|\bSIG[A-Z][A-Z0-9]*\b)+$/) {
+       } elsif ($val !~ /^([\s\d<>+=*%\/&|!()-]|\b[wse]\b|\bSIG[A-Z][A-Z0-9]*\b)+$/) {
            print STDERR "$prog:$test{':long-name'}: bad expected-exit expression: $val\n";
            return undef;
        }
index 1d59d38..989722b 100644 (file)
@@ -1,4 +1,4 @@
-# $MirOS: src/bin/mksh/check.t,v 1.667.2.7 2015/04/19 19:18:10 tg Exp $
+# $MirOS: src/bin/mksh/check.t,v 1.703 2015/07/10 19:36:31 tg Exp $
 # -*- mode: sh -*-
 #-
 # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@@ -30,7 +30,7 @@
 # (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
 
 expected-stdout:
-       @(#)MIRBSD KSH R50 2015/04/19
+       @(#)MIRBSD KSH R51 2015/07/10
 description:
        Check version of shell.
 stdin:
@@ -39,7 +39,7 @@ name: KSH_VERSION
 category: shell:legacy-no
 ---
 expected-stdout:
-       @(#)LEGACY KSH R50 2015/04/19
+       @(#)LEGACY KSH R51 2015/07/10
 description:
        Check version of legacy shell.
 stdin:
@@ -232,7 +232,7 @@ time-limit: 3
 stdin:
        print '#!'"$__progname"'\necho tf' >lq
        chmod +x lq
-       PATH=$PWD:$PATH
+       PATH=$PWD$PATHSEP$PATH
        alias lq=lq
        lq
        echo = now
@@ -1198,7 +1198,7 @@ need-pass: no
 # the mv command fails on Cygwin
 # Hurd aborts the testsuite (permission denied)
 # QNX does not find subdir to cd into
-category: !os:cygwin,!os:gnu,!os:msys,!os:nto,!nosymlink
+category: !os:cygwin,!os:gnu,!os:msys,!os:nto,!os:os390,!nosymlink
 file-setup: file 644 "x"
        mkdir noread noread/target noread/target/subdir
        ln -s noread link
@@ -2075,9 +2075,9 @@ expected-stdout:
 name: glob-bad-2
 description:
        Check that symbolic links aren't stat()'d
-# breaks on FreeMiNT (cannot unlink dangling symlinks)
-# breaks on MSYS (does not support symlinks)
 # breaks on Dell UNIX 4.0 R2.2 (SVR4) where unlink also fails
+# breaks on FreeMiNT (cannot unlink dangling symlinks)
+# breaks on MSYS, OS/2 (do not support symlinks)
 category: !os:mint,!os:msys,!os:svr4.0,!nosymlink
 file-setup: dir 755 "dir"
 file-setup: symlink 644 "dir/abc"
@@ -2132,7 +2132,7 @@ description:
 # breaks on Mac OSX (HFS+ non-standard Unicode canonical decomposition)
 # breaks on Cygwin 1.7 (files are now UTF-16 or something)
 # breaks on QNX 6.4.1 (says RT)
-category: !os:cygwin,!os:darwin,!os:msys,!os:nto
+category: !os:cygwin,!os:darwin,!os:msys,!os:nto,!os:os2
 need-pass: no
 file-setup: file 644 "aÂc"
 stdin:
@@ -3555,7 +3555,6 @@ name: history-ed-3-old
 description:
        Newly created multi line commands show up as single command
        in history.
-       (NOTE: adjusted for COMPLEX HISTORY compile time option)
        (ksh88 fails 'cause it lists the fc command)
 category: stdout-ed
 need-ctty: yes
@@ -3582,7 +3581,7 @@ expected-stdout:
        a new line
        1       echo abc def
        2       echo FOOBAR def
-       3       echo a new line
+               echo a new line
 expected-stderr-pattern:
        /^X*echo FOOBAR def\necho a new line\nX*$/
 ---
@@ -3664,7 +3663,7 @@ expected-stdout:
        a new line
        1       echo abc def
        2       echo FOOBAR def
-       3       echo a new line
+               echo a new line
 expected-stderr-pattern:
        /^X*13\n32\necho FOOBAR def\necho a new line\nX*$/
 ---
@@ -4545,6 +4544,20 @@ expected-stdout:
        64
        64
 ---
+name: integer-base-8
+description:
+       Check that base-36 works (full span)
+stdin:
+       echo 1:$((36#109AZ)).
+       typeset -i36 x=1691675
+       echo 2:$x.
+       typeset -Uui36 x
+       echo 3:$x.
+expected-stdout:
+       1:1691675.
+       2:36#109az.
+       3:36#109AZ.
+---
 name: integer-base-check-flat
 description:
        Check behaviour does not match POSuX (except if set -o posix),
@@ -4561,11 +4574,11 @@ expected-stdout:
 ---
 name: integer-base-check-numeric-from
 description:
-       Check behaviour for base one to 36, and that 37 errors out
+       Check behaviour for base one to 36, and that 37 degrades to 10
 stdin:
        echo 1:$((1#1))0.
        i=1
-       while (( ++i <= 36 )); do
+       while (( ++i <= 37 )); do
                eval 'echo '$i':$(('$i'#10)).'
        done
        echo 37:$($__progname -c 'echo $((37#10))').$?:
@@ -4606,13 +4619,12 @@ expected-stdout:
        34:34.
        35:35.
        36:36.
-       37:.0:
-expected-stderr-pattern:
-       /.*bad number '37#10'/
+       37:10.
+       37:10.0:
 ---
 name: integer-base-check-numeric-to
 description:
-       Check behaviour for base one to 36, and that 37 errors out
+       Check behaviour for base one to 36, and that 37 degrades to 10
 stdin:
        i=0
        while (( ++i <= 37 )); do
@@ -4657,9 +4669,7 @@ expected-stdout:
        34:34#1U.64.
        35:35#1T.64.
        36:36#1S.64.
-       37:36#1S.64.
-expected-stderr-pattern:
-       /.*bad integer base: 37/
+       37:64.64.
 ---
 name: integer-arithmetic-span
 description:
@@ -4826,7 +4836,7 @@ expected-stdout:
        PROG: trap: bad signal 'UNKNOWNSIGNAL'
        PROG: trap: bad signal '999999'
        PROG: trap: bad signal 'FNORD'
-       = 3
+       = 1
        trap 2 executed
 ---
 name: read-IFS-1
@@ -5008,8 +5018,8 @@ description:
        need to be moved out of the switch to before findcom() is
        called - I don't know what this will break.
 stdin:
-       : ${PWD:-`pwd 2> /dev/null`}
-       : ${PWD:?"PWD not set - can't do test"}
+       : "${PWD:-`pwd 2> /dev/null`}"
+       : "${PWD:?"PWD not set - can't do test"}"
        mkdir Y
        cat > Y/xxxscript << EOF
        #!/bin/sh
@@ -5547,7 +5557,7 @@ description:
 stdin:
        print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
            'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
-           done >env; chmod +x env; PATH=.:$PATH
+           done >env; chmod +x env; PATH=.$PATHSEP$PATH
        foo=bar
        readonly foo
        foo=stuff env | grep '^foo'
@@ -6253,7 +6263,7 @@ description:
 stdin:
        print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
            'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
-           done >env; chmod +x env; PATH=.:$PATH
+           done >env; chmod +x env; PATH=.$PATHSEP$PATH
        FOO=bar exec env
 expected-stdout-pattern:
        /(^|.*\n)FOO=bar\n/
@@ -6265,7 +6275,7 @@ description:
 stdin:
        print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
            'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
-           done >env; chmod +x env; PATH=.:$PATH
+           done >env; chmod +x env; PATH=.$PATHSEP$PATH
        env >bar1
        FOO=bar exec; env >bar2
        cmp -s bar1 bar2
@@ -6509,7 +6519,7 @@ stdin:
        print '#!'"$__progname"'\nexec "$1"' >env
        print '#!'"$__progname"'\nexit 1' >false
        chmod +x env false
-       PATH=.:$PATH
+       PATH=.$PATHSEP$PATH
        set -ex
        env false && echo something
        echo END
@@ -6527,7 +6537,7 @@ stdin:
        print '#!'"$__progname"'\nexit 1' >false
        print '#!'"$__progname"'\nexit 0' >true
        chmod +x env false
-       PATH=.:$PATH
+       PATH=.$PATHSEP$PATH
        set -ex
        if env true; then
                env false && echo something
@@ -7271,7 +7281,7 @@ stdin:
        set -A anzahl -- foo/*
        echo got ${#anzahl[*]} files
        chmod +x foo/*
-       export PATH=$(pwd)/foo:$PATH
+       export PATH=$(pwd)/foo$PATHSEP$PATH
        "$__progname" -c 'fnord'
        echo =
        "$__progname" -c 'fnord; fnord; fnord; fnord'
@@ -7441,24 +7451,24 @@ expected-stdout:
 name: aliases-1
 description:
        Check if built-in shell aliases are okay
-category: !android,!arge
+category: !android,!arge,!os:os2
 stdin:
        alias
        typeset -f
 expected-stdout:
-       autoload='typeset -fu'
-       functions='typeset -f'
-       hash='alias -t'
-       history='fc -l'
-       integer='typeset -i'
-       local=typeset
-       login='exec login'
-       nameref='typeset -n'
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
        nohup='nohup '
-       r='fc -e -'
-       source='PATH=$PATH:. command .'
-       stop='kill -STOP'
-       type='whence -v'
+       r='\builtin fc -e -'
+       source='PATH=$PATH:. \command .'
+       stop='\kill -STOP'
+       type='\builtin whence -v'
 ---
 name: aliases-1-hartz4
 description:
@@ -7468,132 +7478,173 @@ stdin:
        alias
        typeset -f
 expected-stdout:
-       autoload='typeset -fu'
-       functions='typeset -f'
-       hash='alias -t'
-       history='fc -l'
-       integer='typeset -i'
-       local=typeset
-       login='exec login'
-       nameref='typeset -n'
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
        nohup='nohup '
-       r='fc -e -'
-       source='PATH=$PATH:. command .'
-       type='whence -v'
+       r='\builtin fc -e -'
+       source='PATH=$PATH:. \command .'
+       type='\builtin whence -v'
 ---
-name: aliases-2a
+name: aliases-1-os2
 description:
-       Check if “set -o sh” disables built-in aliases (except a few)
-category: disabled
+       Check if built-in shell aliases are okay
+category: os:os2
+stdin:
+       alias
+       typeset -f
+expected-stdout:
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
+       nohup='nohup '
+       r='\builtin fc -e -'
+       source='PATH=$PATH;. \command .'
+       type='\builtin whence -v'
+---
+name: aliases-2b
+description:
+       Check if “set -o sh” does not influence built-in aliases
+category: !android,!arge,!os:os2
 arguments: !-o!sh!
 stdin:
        alias
        typeset -f
 expected-stdout:
-       integer='typeset -i'
-       local=typeset
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
+       nohup='nohup '
+       r='\builtin fc -e -'
+       source='PATH=$PATH:. \command .'
+       stop='\kill -STOP'
+       type='\builtin whence -v'
 ---
-name: aliases-3a
+name: aliases-3b
 description:
-       Check if running as sh disables built-in aliases (except a few)
-category: disabled
+       Check if running as sh does not influence built-in aliases
+category: !android,!arge,!os:os2
 stdin:
        cp "$__progname" sh
        ./sh -c 'alias; typeset -f'
        rm -f sh
 expected-stdout:
-       integer='typeset -i'
-       local=typeset
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
+       nohup='nohup '
+       r='\builtin fc -e -'
+       source='PATH=$PATH:. \command .'
+       stop='\kill -STOP'
+       type='\builtin whence -v'
 ---
-name: aliases-2b
+name: aliases-2b-hartz4
 description:
        Check if “set -o sh” does not influence built-in aliases
-category: !android,!arge
+category: android,arge
 arguments: !-o!sh!
 stdin:
        alias
        typeset -f
 expected-stdout:
-       autoload='typeset -fu'
-       functions='typeset -f'
-       hash='alias -t'
-       history='fc -l'
-       integer='typeset -i'
-       local=typeset
-       login='exec login'
-       nameref='typeset -n'
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
        nohup='nohup '
-       r='fc -e -'
-       source='PATH=$PATH:. command .'
-       stop='kill -STOP'
-       type='whence -v'
+       r='\builtin fc -e -'
+       source='PATH=$PATH:. \command .'
+       type='\builtin whence -v'
 ---
-name: aliases-3b
+name: aliases-3b-hartz4
 description:
        Check if running as sh does not influence built-in aliases
-category: !android,!arge
+category: android,arge
 stdin:
        cp "$__progname" sh
        ./sh -c 'alias; typeset -f'
        rm -f sh
 expected-stdout:
-       autoload='typeset -fu'
-       functions='typeset -f'
-       hash='alias -t'
-       history='fc -l'
-       integer='typeset -i'
-       local=typeset
-       login='exec login'
-       nameref='typeset -n'
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
        nohup='nohup '
-       r='fc -e -'
-       source='PATH=$PATH:. command .'
-       stop='kill -STOP'
-       type='whence -v'
+       r='\builtin fc -e -'
+       source='PATH=$PATH:. \command .'
+       type='\builtin whence -v'
 ---
-name: aliases-2b-hartz4
+name: aliases-2b-os2
 description:
        Check if “set -o sh” does not influence built-in aliases
-category: android,arge
+category: os:os2
 arguments: !-o!sh!
 stdin:
        alias
        typeset -f
 expected-stdout:
-       autoload='typeset -fu'
-       functions='typeset -f'
-       hash='alias -t'
-       history='fc -l'
-       integer='typeset -i'
-       local=typeset
-       login='exec login'
-       nameref='typeset -n'
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
        nohup='nohup '
-       r='fc -e -'
-       source='PATH=$PATH:. command .'
-       type='whence -v'
+       r='\builtin fc -e -'
+       source='PATH=$PATH;. \command .'
+       type='\builtin whence -v'
 ---
-name: aliases-3b-hartz4
+name: aliases-3b-os2
 description:
        Check if running as sh does not influence built-in aliases
-category: android,arge
+category: os:os2
 stdin:
        cp "$__progname" sh
        ./sh -c 'alias; typeset -f'
        rm -f sh
 expected-stdout:
-       autoload='typeset -fu'
-       functions='typeset -f'
-       hash='alias -t'
-       history='fc -l'
-       integer='typeset -i'
-       local=typeset
-       login='exec login'
-       nameref='typeset -n'
+       autoload='\typeset -fu'
+       functions='\typeset -f'
+       hash='\builtin alias -t'
+       history='\builtin fc -l'
+       integer='\typeset -i'
+       local='\typeset'
+       login='\exec login'
+       nameref='\typeset -n'
        nohup='nohup '
-       r='fc -e -'
-       source='PATH=$PATH:. command .'
-       type='whence -v'
+       r='\builtin fc -e -'
+       source='PATH=$PATH;. \command .'
+       type='\builtin whence -v'
 ---
 name: aliases-cmdline
 description:
@@ -7609,6 +7660,20 @@ expected-stdout:
 name: aliases-funcdef-1
 description:
        Check if POSIX functions take precedences over aliases
+category: shell:legacy-no
+stdin:
+       alias foo='echo makro'
+       foo() {
+               echo funktion
+       }
+       foo
+expected-stdout:
+       makro
+---
+name: aliases-funcdef-1-legacy
+description:
+       Check if POSIX functions take precedences over aliases
+category: shell:legacy-yes
 stdin:
        alias foo='echo makro'
        foo() {
@@ -7621,6 +7686,20 @@ expected-stdout:
 name: aliases-funcdef-2
 description:
        Check if POSIX functions take precedences over aliases
+category: shell:legacy-no
+stdin:
+       alias foo='echo makro'
+       foo () {
+               echo funktion
+       }
+       foo
+expected-stdout:
+       makro
+---
+name: aliases-funcdef-2-legacy
+description:
+       Check if POSIX functions take precedences over aliases
+category: shell:legacy-yes
 stdin:
        alias foo='echo makro'
        foo () {
@@ -7650,8 +7729,8 @@ stdin:
        :|| local() { :; }
        alias local
 expected-stdout:
-       local=typeset
-       local=typeset
+       local='\typeset'
+       local='\typeset'
 ---
 name: arrays-1
 description:
@@ -8518,6 +8597,7 @@ description:
        Ensure concatenating behaviour matches other shells
 stdin:
        showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+       showargs 0 ""$@
        x=; showargs 1 "$x"$@
        set A; showargs 2 "${@:+}"
        n() { echo "$#"; }
@@ -8537,6 +8617,7 @@ stdin:
        n "$@"
        n "$@""$e"
 expected-stdout:
+       <0> <> .
        <1> <> .
        <2> <> .
        2
@@ -8597,6 +8678,7 @@ stdin:
        cat >foo <<-'EOF'
                x='bar\r
                ' #\r
+               echo .${#x} #\r
                if test x"$KSH_VERSION" = x""; then #\r
                        printf '<%s>' "$x" #\r
                else #\r
@@ -8608,8 +8690,10 @@ stdin:
                print -r -- "{$line}"
        done
 expected-stdout:
-       [<bar\r
+       [.5
+       <bar\r
        >]
+       {.5}
        {<bar\r}
 ---
 name: print-lf
@@ -8619,6 +8703,7 @@ stdin:
        cat >foo <<-'EOF'
                x='bar
                ' #
+               echo .${#x} #
                if test x"$KSH_VERSION" = x""; then #
                        printf '<%s>' "$x" #
                else #
@@ -8630,8 +8715,10 @@ stdin:
                print -r -- "{$line}"
        done
 expected-stdout:
-       [<bar
+       [.4
+       <bar
        >]
+       {.4}
        {<bar}
 ---
 name: print-nul-chars
@@ -8835,6 +8922,7 @@ description:
        make aliases not conflict with functions, legacy version:
        undefine these aliases upon definition of the function
        note: for ksh functions, the order of preference differs in GNU bash
+category: shell:legacy-yes
 stdin:
        # POSIX function overrides and removes alias
        alias foo='echo bar'
@@ -8871,6 +8959,46 @@ expected-stdout:
        bal
        bfn
 ---
+name: alias-function-no-conflict
+description:
+       make aliases not conflict with function definitions
+category: shell:legacy-no
+stdin:
+       # POSIX function can be defined, but alias overrides it
+       alias foo='echo bar'
+       foo
+       foo() {
+               echo baz
+       }
+       foo
+       unset -f foo
+       foo 2>/dev/null || echo rab
+       # alias overrides ksh function
+       alias korn='echo bar'
+       korn
+       function korn {
+               echo baz
+       }
+       korn
+       # alias temporarily overrides POSIX function
+       bla() {
+               echo bfn
+       }
+       bla
+       alias bla='echo bal'
+       bla
+       unalias bla
+       bla
+expected-stdout:
+       bar
+       bar
+       bar
+       bar
+       bar
+       bfn
+       bal
+       bfn
+---
 name: bash-function-parens
 description:
        ensure the keyword function is ignored when preceding
@@ -8886,8 +9014,8 @@ stdin:
        mk 'function foo' >f-korn
        mk 'foo ()' >f-dash
        mk 'function foo ()' >f-bash
-       # pre-R51 can do without a backslash in front of the second stop
-       mk 'function stop ()' 'stop' >f-stop
+       # lksh can do without the backslash, too (cf. aliases-funcdef-2-legacy)
+       mk 'function stop ()' '\stop' >f-stop
        print '#!'"$__progname"'\nprint -r -- "${0%/f-argh}"' >f-argh
        chmod +x f-*
        u=$(./f-argh)
@@ -9844,7 +9972,7 @@ description:
 stdin:
        print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
            'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
-           done >env; chmod +x env; PATH=.:$PATH
+           done >env; chmod +x env; PATH=.$PATHSEP$PATH
        function k {
                if [ x$FOO != xbar ]; then
                        echo 1
@@ -10016,7 +10144,7 @@ description:
        is a must (a non-recursive parser cannot pass all three of
        these test cases, especially the ‘#’ is difficult)
 stdin:
-       print '#!'"$__progname"'\necho 1234' >id; chmod +x id; PATH=.:$PATH
+       print '#!'"$__progname"'\necho 1234' >id; chmod +x id; PATH=.$PATHSEP$PATH
        echo $(typeset -i10 x=16#20; echo $x)
        echo $(typeset -Uui16 x=16#$(id -u)
        ) .
@@ -10328,7 +10456,7 @@ expected-stdout:
        }
        inline_TWHILE() {
                i=1 
-               while let] " i < 10 " 
+               while \let] " i < 10 " 
                do
                        echo $i 
                        let ++i 
@@ -10338,20 +10466,20 @@ expected-stdout:
                i=1; while (( i < 10 )); do echo $i; let ++i; done
        ); }
        function comsub_TWHILE {
-               x=$(i=1 ; while let] " i < 10 " ; do echo $i ; let ++i ; done ) 
+               x=$(i=1 ; while \let] " i < 10 " ; do echo $i ; let ++i ; done ) 
        } 
        function reread_TWHILE { x=$((
                i=1; while (( i < 10 )); do echo $i; let ++i; done
        )|tr u x); }
        function reread_TWHILE {
-               x=$(( i=1 ; while let] " i < 10 " ; do echo $i ; let ++i ; done ) | tr u x ) 
+               x=$(( i=1 ; while \let] " i < 10 " ; do echo $i ; let ++i ; done ) | tr u x ) 
        } 
        inline_TUNTIL() {
                i=10; until  (( !--i )) ; do echo $i; done
        }
        inline_TUNTIL() {
                i=10 
-               until let] " !--i " 
+               until \let] " !--i " 
                do
                        echo $i 
                done 
@@ -10360,13 +10488,13 @@ expected-stdout:
                i=10; until  (( !--i )) ; do echo $i; done
        ); }
        function comsub_TUNTIL {
-               x=$(i=10 ; until let] " !--i " ; do echo $i ; done ) 
+               x=$(i=10 ; until \let] " !--i " ; do echo $i ; done ) 
        } 
        function reread_TUNTIL { x=$((
                i=10; until  (( !--i )) ; do echo $i; done
        )|tr u x); }
        function reread_TUNTIL {
-               x=$(( i=10 ; until let] " !--i " ; do echo $i ; done ) | tr u x ) 
+               x=$(( i=10 ; until \let] " !--i " ; do echo $i ; done ) | tr u x ) 
        } 
        inline_TCOPROC() {
                cat  *  |&  ls
@@ -10742,7 +10870,7 @@ expected-stdout:
                case x in
                (x)
                        a+=b 
-                       set -A c+ -- d e 
+                       \set -A c+ -- d e 
                        ;;
                esac 
        } 
@@ -10752,7 +10880,7 @@ expected-stdout:
                esac
        ); }
        function comsub_wdarrassign {
-               x=$(case x in (x) a+=b ; set -A c+ -- d e  ;; esac ) 
+               x=$(case x in (x) a+=b ; \set -A c+ -- d e  ;; esac ) 
        } 
        function reread_wdarrassign { x=$((
                case x in
@@ -10760,7 +10888,7 @@ expected-stdout:
                esac
        )|tr u x); }
        function reread_wdarrassign {
-               x=$(( case x in (x) a+=b ; set -A c+ -- d e  ;; esac ) | tr u x ) 
+               x=$(( case x in (x) a+=b ; \set -A c+ -- d e  ;; esac ) | tr u x ) 
        } 
 ---
 name: comsub-torture-io
@@ -10980,7 +11108,7 @@ expected-stdout:
        }
        inline_TWHILE() {
                i=1 
-               while let] " i < 10 " >&3 
+               while \let] " i < 10 " >&3 
                do
                        echo $i 
                        let ++i 
@@ -10990,20 +11118,20 @@ expected-stdout:
                i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
        ); }
        function comsub_TWHILE {
-               x=$(i=1 ; while let] " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) 
+               x=$(i=1 ; while \let] " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) 
        } 
        function reread_TWHILE { x=$((
                i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
        )|tr u x); }
        function reread_TWHILE {
-               x=$(( i=1 ; while let] " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x ) 
+               x=$(( i=1 ; while \let] " i < 10 " >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x ) 
        } 
        inline_TUNTIL() {
                i=10; until  (( !--i )) >&3 ; do echo $i; done >&3
        }
        inline_TUNTIL() {
                i=10 
-               until let] " !--i " >&3 
+               until \let] " !--i " >&3 
                do
                        echo $i 
                done >&3 
@@ -11012,13 +11140,13 @@ expected-stdout:
                i=10; until  (( !--i )) >&3 ; do echo $i; done >&3
        ); }
        function comsub_TUNTIL {
-               x=$(i=10 ; until let] " !--i " >&3 ; do echo $i ; done >&3 ) 
+               x=$(i=10 ; until \let] " !--i " >&3 ; do echo $i ; done >&3 ) 
        } 
        function reread_TUNTIL { x=$((
                i=10; until  (( !--i )) >&3 ; do echo $i; done >&3
        )|tr u x); }
        function reread_TUNTIL {
-               x=$(( i=10 ; until let] " !--i " >&3 ; do echo $i ; done >&3 ) | tr u x ) 
+               x=$(( i=10 ; until \let] " !--i " >&3 ; do echo $i ; done >&3 ) | tr u x ) 
        } 
        inline_TCOPROC() {
                cat  *  >&3 |&  >&3 ls
@@ -11251,7 +11379,7 @@ file-setup: file 755 "!false"
        #! /bin/sh
        echo si
 stdin:
-       export PATH=.:$PATH
+       export PATH=.$PATHSEP$PATH
        falsetto
        echo yeap
        !false
@@ -11281,7 +11409,7 @@ file-setup: file 755 "!false"
        #! /bin/sh
        echo si
 stdin:
-       export PATH=.:$PATH
+       export PATH=.$PATHSEP$PATH
        falsetto
        echo yeap
        !false
@@ -12104,9 +12232,30 @@ expected-stderr:
        [(p:sh)(f1:sh)(f2:sh)] print '(o1:shx)'
        [(p:sh)(f1:sh)(f2:sh)] set +x
 ---
+name: fksh-flags
+description:
+       Check that FKSH functions have their own shell flags
+category: shell:legacy-no
+stdin:
+       [[ $KSH_VERSION = Version* ]] && set +B
+       function foo {
+               set +f
+               set -e
+               echo 2 "${-/s}" .
+       }
+       set -fh
+       echo 1 "${-/s}" .
+       foo
+       echo 3 "${-/s}" .
+expected-stdout:
+       1 fh .
+       2 eh .
+       3 fh .
+---
 name: fksh-flags-legacy
 description:
        Check that even FKSH functions share the shell flags
+category: shell:legacy-yes
 stdin:
        [[ $KSH_VERSION = Version* ]] && set +B
        foo() {
index f65eaa7..4c64395 100644 (file)
@@ -1,5 +1,5 @@
 # $Id$
-# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89.2.3 2015/04/12 22:32:22 tg Exp $
+# $MirOS: src/bin/mksh/dot.mkshrc,v 1.100 2015/07/10 19:36:33 tg Exp $
 #-
 # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
 #              2011, 2012, 2013, 2014, 2015
@@ -28,127 +28,129 @@ case ${KSH_VERSION:-} in
 *) return 0 ;;
 esac
 
-PS1='#'; (( USER_ID )) && PS1='$'; : "${TERM:=vt100}${HOSTNAME:=$(ulimit -c \
-    0; hostname 2>/dev/null)}${EDITOR:=/bin/ed}${USER:=$(ulimit -c 0; id -un \
-    2>/dev/null || echo \?)}${MKSH:=$(whence -p mksh)}"
+PS1='#'; (( USER_ID )) && PS1='$'; \: "${TERM:=vt100}${HOSTNAME:=$(\ulimit -c \
+    0; hostname 2>/dev/null)}${EDITOR:=/bin/ed}${USER:=$(\ulimit -c 0; id -un \
+    2>/dev/null || \echo \?)}${MKSH:=$(\builtin whence -p mksh)}"
 HOSTNAME=${HOSTNAME%%*([        ]).*}; HOSTNAME=${HOSTNAME##*([         ])}
 [[ $HOSTNAME = ?(ip6-)localhost?(6) ]] && HOSTNAME=
-: "${HOSTNAME:=nil}${MKSH:=/bin/mksh}"; export EDITOR HOSTNAME MKSH TERM USER
+\: "${HOSTNAME:=nil}${MKSH:=/bin/mksh}"; \export EDITOR HOSTNAME MKSH TERM USER
 PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${|
-       local e=$?
+       \typeset e=$?
 
        (( e )) && REPLY+="$e|"
        REPLY+=${USER}@${HOSTNAME%%.*}:
 
-       local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~}
-       local m=${%d} n p=...; (( m > 0 )) || m=${#d}
+       \typeset d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~}
+       \typeset m=${%d} n p=...; (( m > 0 )) || m=${#d}
        (( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p=
        REPLY+=$p$d
 
-       return $e
+       \return $e
 } '"$PS1 "
-alias ls=ls
-unalias ls
-alias l='ls -F'
-alias la='l -a'
-alias ll='l -l'
-alias lo='l -alo'
-alias doch='sudo mksh -c "$(fc -ln -1)"'
-command -v rot13 >/dev/null || alias rot13='tr \
+\alias ls=ls
+\unalias ls
+\alias l='ls -F'
+\alias la='l -a'
+\alias ll='l -l'
+\alias lo='l -alo'
+\alias doch='sudo mksh -c "$(\builtin fc -ln -1)"'
+\command -v rot13 >/dev/null || \alias rot13='tr \
     abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \
     nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
-if command -v hd >/dev/null; then :; elif command -v hexdump >/dev/null; then
+if \command -v hd >/dev/null; then \:; elif \command -v hexdump >/dev/null; then
        function hd {
                hexdump -e '"%08.8_ax  " 8/1 "%02X " " - " 8/1 "%02X "' \
                    -e '"  |" "%_p"' -e '"|\n"' "$@"
        }
 else
        function hd {
-               local -Uui16 -Z11 pos=0
-               local -Uui16 -Z5 hv=2147483647
-               local dasc line i
+               \typeset -Uui16 -Z11 pos=0
+               \typeset -Uui16 -Z5 hv=2147483647
+               \typeset dasc line i
+               \set +U
 
-               cat "$@" | { set +U; if read -arN -1 line; then
-                       typeset -i1 'line[*]'
+               \cat "$@" | if \read -arN -1 line; then
+                       \typeset -i1 'line[*]'
                        i=0
                        while (( i < ${#line[*]} )); do
                                hv=${line[i++]}
                                if (( (pos & 15) == 0 )); then
                                        (( pos )) && \
-                                           print -r -- "$dasc|"
-                                       print -n "${pos#16#}  "
+                                           \builtin print -r -- "$dasc|"
+                                       \builtin print -n "${pos#16#}  "
                                        dasc=' |'
                                fi
-                               print -n "${hv#16#} "
+                               \builtin print -n "${hv#16#} "
+                               #XXX EBCDIC, but we need [[:print:]] to fix this
                                if (( (hv < 32) || (hv > 126) )); then
                                        dasc+=.
                                else
                                        dasc+=${line[i-1]#1#}
                                fi
                                (( (pos++ & 15) == 7 )) && \
-                                   print -n -- '- '
+                                   \builtin print -n -- '- '
                        done
                        while (( pos & 15 )); do
-                               print -n '   '
+                               \builtin print -n '   '
                                (( (pos++ & 15) == 7 )) && \
-                                   print -n -- '- '
+                                   \builtin print -n -- '- '
                        done
-                       (( hv == 2147483647 )) || print -r -- "$dasc|"
-               fi; }
+                       (( hv == 2147483647 )) || \builtin print -r -- "$dasc|"
+               fi
        }
 fi
 
 # Berkeley C shell compatible dirs, popd, and pushd functions
 # Z shell compatible chpwd() hook, used to update DIRSTACK[0]
-DIRSTACKBASE=$(realpath ~/. 2>/dev/null || \
-    print -nr -- "${HOME:-/}")
+DIRSTACKBASE=$(\builtin realpath ~/. 2>/dev/null || \
+    \builtin print -nr -- "${HOME:-/}")
 set -A DIRSTACK
 function chpwd {
-       DIRSTACK[0]=$(realpath . 2>/dev/null || \
-           print -r -- "$PWD")
+       DIRSTACK[0]=$(\builtin realpath . 2>/dev/null || \
+           \builtin print -r -- "$PWD")
        [[ $DIRSTACKBASE = ?(*/) ]] || \
            DIRSTACK[0]=${DIRSTACK[0]/#$DIRSTACKBASE/~}
-       :
+       \:
 }
-chpwd .
-function cd {
-       builtin cd "$@" || return $?
-       chpwd "$@"
+\chpwd .
+cd() {
+       \builtin cd "$@" || \return $?
+       \chpwd "$@"
 }
 function cd_csh {
-       local d t=${1/#~/$DIRSTACKBASE}
+       \typeset d t=${1/#~/$DIRSTACKBASE}
 
-       if ! d=$(builtin cd "$t" 2>&1); then
-               print -u2 "${1}: ${d##*cd: $t: }."
-               return 1
+       if ! d=$(\builtin cd "$t" 2>&1); then
+               \builtin print -u2 "${1}: ${d##*cd: $t: }."
+               \return 1
        fi
-       cd "$t"
+       \cd "$t"
 }
 function dirs {
-       local d dwidth
-       local -i fl=0 fv=0 fn=0 cpos=0
+       \typeset d dwidth
+       \typeset -i fl=0 fv=0 fn=0 cpos=0
 
-       while getopts ":lvn" d; do
+       while \getopts ":lvn" d; do
                case $d {
                (l)     fl=1 ;;
                (v)     fv=1 ;;
                (n)     fn=1 ;;
-               (*)     print -u2 'Usage: dirs [-lvn].'
-                       return 1 ;;
+               (*)     \builtin print -u2 'Usage: dirs [-lvn].'
+                       \return 1 ;;
                }
        done
-       shift $((OPTIND - 1))
+       \shift $((OPTIND - 1))
        if (( $# > 0 )); then
-               print -u2 'Usage: dirs [-lvn].'
-               return 1
+               \builtin print -u2 'Usage: dirs [-lvn].'
+               \return 1
        fi
        if (( fv )); then
                fv=0
                while (( fv < ${#DIRSTACK[*]} )); do
                        d=${DIRSTACK[fv]}
                        (( fl )) && d=${d/#~/$DIRSTACKBASE}
-                       print -r -- "$fv        $d"
-                       let fv++
+                       \builtin print -r -- "$fv       $d"
+                       \builtin let fv++
                done
        else
                fv=0
@@ -158,138 +160,138 @@ function dirs {
                        (( dwidth = (${%d} > 0 ? ${%d} : ${#d}) ))
                        if (( fn && (cpos += dwidth + 1) >= 79 && \
                            dwidth < 80 )); then
-                               print
+                               \builtin print
                                (( cpos = dwidth + 1 ))
                        fi
-                       print -nr -- "$d "
-                       let fv++
+                       \builtin print -nr -- "$d "
+                       \builtin let fv++
                done
-               print
+               \builtin print
        fi
-       return 0
+       \return 0
 }
 function popd {
-       local d fa
-       local -i n=1
+       \typeset d fa
+       \typeset -i n=1
 
-       while getopts ":0123456789lvn" d; do
+       while \getopts ":0123456789lvn" d; do
                case $d {
                (l|v|n) fa+=" -$d" ;;
                (+*)    n=2
-                       break ;;
-               (*)     print -u2 'Usage: popd [-lvn] [+<n>].'
-                       return 1 ;;
+                       \break ;;
+               (*)     \builtin print -u2 'Usage: popd [-lvn] [+<n>].'
+                       \return 1 ;;
                }
        done
-       shift $((OPTIND - n))
+       \shift $((OPTIND - n))
        n=0
        if (( $# > 1 )); then
-               print -u2 popd: Too many arguments.
-               return 1
+               \builtin print -u2 popd: Too many arguments.
+               \return 1
        elif [[ $1 = ++([0-9]) && $1 != +0 ]]; then
                if (( (n = ${1#+}) >= ${#DIRSTACK[*]} )); then
-                       print -u2 popd: Directory stack not that deep.
-                       return 1
+                       \builtin print -u2 popd: Directory stack not that deep.
+                       \return 1
                fi
        elif [[ -n $1 ]]; then
-               print -u2 popd: Bad directory.
-               return 1
+               \builtin print -u2 popd: Bad directory.
+               \return 1
        fi
        if (( ${#DIRSTACK[*]} < 2 )); then
-               print -u2 popd: Directory stack empty.
-               return 1
+               \builtin print -u2 popd: Directory stack empty.
+               \return 1
        fi
-       unset DIRSTACK[n]
-       set -A DIRSTACK -- "${DIRSTACK[@]}"
-       cd_csh "${DIRSTACK[0]}" || return 1
-       dirs $fa
+       \unset DIRSTACK[n]
+       \set -A DIRSTACK -- "${DIRSTACK[@]}"
+       \cd_csh "${DIRSTACK[0]}" || \return 1
+       \dirs $fa
 }
 function pushd {
-       local d fa
-       local -i n=1
+       \typeset d fa
+       \typeset -i n=1
 
-       while getopts ":0123456789lvn" d; do
+       while \getopts ":0123456789lvn" d; do
                case $d {
                (l|v|n) fa+=" -$d" ;;
                (+*)    n=2
-                       break ;;
-               (*)     print -u2 'Usage: pushd [-lvn] [<dir>|+<n>].'
-                       return 1 ;;
+                       \break ;;
+               (*)     \builtin print -u2 'Usage: pushd [-lvn] [<dir>|+<n>].'
+                       \return 1 ;;
                }
        done
-       shift $((OPTIND - n))
+       \shift $((OPTIND - n))
        if (( $# == 0 )); then
                if (( ${#DIRSTACK[*]} < 2 )); then
-                       print -u2 pushd: No other directory.
-                       return 1
+                       \builtin print -u2 pushd: No other directory.
+                       \return 1
                fi
                d=${DIRSTACK[1]}
                DIRSTACK[1]=${DIRSTACK[0]}
-               cd_csh "$d" || return 1
+               \cd_csh "$d" || \return 1
        elif (( $# > 1 )); then
-               print -u2 pushd: Too many arguments.
-               return 1
+               \builtin print -u2 pushd: Too many arguments.
+               \return 1
        elif [[ $1 = ++([0-9]) && $1 != +0 ]]; then
                if (( (n = ${1#+}) >= ${#DIRSTACK[*]} )); then
-                       print -u2 pushd: Directory stack not that deep.
-                       return 1
+                       \builtin print -u2 pushd: Directory stack not that deep.
+                       \return 1
                fi
                while (( n-- )); do
                        d=${DIRSTACK[0]}
-                       unset DIRSTACK[0]
-                       set -A DIRSTACK -- "${DIRSTACK[@]}" "$d"
+                       \unset DIRSTACK[0]
+                       \set -A DIRSTACK -- "${DIRSTACK[@]}" "$d"
                done
-               cd_csh "${DIRSTACK[0]}" || return 1
+               \cd_csh "${DIRSTACK[0]}" || \return 1
        else
-               set -A DIRSTACK -- placeholder "${DIRSTACK[@]}"
-               cd_csh "$1" || return 1
+               \set -A DIRSTACK -- placeholder "${DIRSTACK[@]}"
+               \cd_csh "$1" || \return 1
        fi
-       dirs $fa
+       \dirs $fa
 }
 
 # pager (not control character safe)
 function smores {
        (
-               set +m
-               cat "$@" |&
-               trap "rv=\$?; kill $! >/dev/null 2>&1; exit \$rv" EXIT
-               while IFS= read -pr line; do
+               \set +m
+               \cat "$@" |&
+               \trap "rv=\$?; 'kill' $! >/dev/null 2>&1; 'exit' \$rv" EXIT
+               while IFS= \read -pr line; do
                        llen=${%line}
                        (( llen == -1 )) && llen=${#line}
                        (( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
                        if (( (curlin += llen) >= LINES )); then
-                               print -n -- '\033[7m--more--\033[0m'
-                               read -u1 || exit $?
-                               [[ $REPLY = [Qq]* ]] && exit 0
+                               \builtin print -n -- '\e[7m--more--\e[0m'
+                               \read -u1 || \exit $?
+                               [[ $REPLY = [Qq]* ]] && \exit 0
                                curlin=$llen
                        fi
-                       print -r -- "$line"
+                       \builtin print -r -- "$line"
                done
        )
 }
 
-# base64 encoder and decoder, RFC compliant, NUL safe
+# base64 encoder and decoder, RFC compliant, NUL safe, not EBCDIC safe
 function Lb64decode {
-       [[ -o utf8-mode ]]; local u=$? c s="$*" t
-       set +U
-       [[ -n $s ]] || { s=$(cat; print x); s=${s%x}; }
-       local -i i=0 j=0 n=${#s} p=0 v x
-       local -i16 o
+       \set +U
+       \typeset c s="$*" t
+       [[ -n $s ]] || { s=$(\cat; \builtin print x); s=${s%x}; }
+       \typeset -i i=0 j=0 n=${#s} p=0 v x
+       \typeset -i16 o
 
        while (( i < n )); do
                c=${s:(i++):1}
                case $c {
-               (=)     break ;;
+               (=)     \break ;;
                ([A-Z]) (( v = 1#$c - 65 )) ;;
                ([a-z]) (( v = 1#$c - 71 )) ;;
                ([0-9]) (( v = 1#$c + 4 )) ;;
                (+)     v=62 ;;
                (/)     v=63 ;;
-               (*)     continue ;;
+               (*)     \continue ;;
                }
                (( x = (x << 6) | v ))
                case $((p++)) {
-               (0)     continue ;;
+               (0)     \continue ;;
                (1)     (( o = (x >> 4) & 255 )) ;;
                (2)     (( o = (x >> 2) & 255 )) ;;
                (3)     (( o = x & 255 ))
@@ -297,26 +299,25 @@ function Lb64decode {
                        ;;
                }
                t+=\\x${o#16#}
-               (( ++j & 4095 )) && continue
-               print -n $t
+               (( ++j & 4095 )) && \continue
+               \builtin print -n $t
                t=
        done
-       print -n $t
-       (( u )) || set -U
+       \builtin print -n $t
 }
 
-set -A Lb64encode_code -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
+\set -A Lb64encode_tbl -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
     a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
 function Lb64encode {
-       [[ -o utf8-mode ]]; local u=$? c s t
-       set +U
+       \set +U
+       \typeset c s t
        if (( $# )); then
-               read -raN-1 s <<<"$*"
-               unset s[${#s[*]}-1]
+               \read -raN-1 s <<<"$*"
+               \unset s[${#s[*]}-1]
        else
-               read -raN-1 s
+               \read -raN-1 s
        fi
-       local -i i=0 n=${#s[*]} j v
+       \typeset -i i=0 n=${#s[*]} j v
 
        while (( i < n )); do
                (( v = s[i++] << 16 ))
@@ -324,86 +325,277 @@ function Lb64encode {
                (( v |= j << 8 ))
                (( j = i < n ? s[i++] : 0 ))
                (( v |= j ))
-               t+=${Lb64encode_code[v >> 18]}${Lb64encode_code[v >> 12 & 63]}
-               c=${Lb64encode_code[v >> 6 & 63]}
+               t+=${Lb64encode_tbl[v >> 18]}${Lb64encode_tbl[v >> 12 & 63]}
+               c=${Lb64encode_tbl[v >> 6 & 63]}
                if (( i <= n )); then
-                       t+=$c${Lb64encode_code[v & 63]}
+                       t+=$c${Lb64encode_tbl[v & 63]}
                elif (( i == n + 1 )); then
                        t+=$c=
                else
                        t+===
                fi
                if (( ${#t} == 76 || i >= n )); then
-                       print $t
+                       \builtin print $t
                        t=
                fi
        done
-       (( u )) || set -U
 }
 
 # Better Avalanche for the Jenkins Hash
-typeset -Z11 -Uui16 Lbafh_v
+\typeset -Z11 -Uui16 Lbafh_v
 function Lbafh_init {
        Lbafh_v=0
 }
 function Lbafh_add {
-       [[ -o utf8-mode ]]; local u=$? s
-       set +U
+       \set +U
+       \typeset s
        if (( $# )); then
-               read -raN-1 s <<<"$*"
-               unset s[${#s[*]}-1]
+               \read -raN-1 s <<<"$*"
+               \unset s[${#s[*]}-1]
        else
-               read -raN-1 s
+               \read -raN-1 s
        fi
-       local -i i=0 n=${#s[*]}
+       \typeset -i i=0 n=${#s[*]}
 
        while (( i < n )); do
                ((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
                ((# Lbafh_v ^= Lbafh_v >> 6 ))
        done
-
-       (( u )) || set -U
 }
 function Lbafh_finish {
-       local -Ui t
+       \typeset -Ui t
 
        ((# t = (((Lbafh_v >> 7) & 0x01010101) * 0x1B) ^ \
            ((Lbafh_v << 1) & 0xFEFEFEFE) ))
        ((# Lbafh_v = t ^ (t >>> 8) ^ (Lbafh_v >>> 8) ^ \
            (Lbafh_v >>> 16) ^ (Lbafh_v >>> 24) ))
-       :
+       \:
 }
 
 # strip comments (and leading/trailing whitespace if IFS is set) from
 # any file(s) given as argument, or stdin if none, and spew to stdout
 function Lstripcom {
-       cat "$@" | { set -o noglob; while read _line; do
+       \set -o noglob
+       \cat "$@" | while \read _line; do
                _line=${_line%%#*}
-               [[ -n $_line ]] && print -r -- $_line
-       done; }
+               [[ -n $_line ]] && \builtin print -r -- $_line
+       done
 }
 
 # give MidnightBSD's laffer1 a bit of csh feeling
 function setenv {
-       eval export "\"$1\""'="$2"'
+       \eval "'export' \"$1\""'="$2"'
+}
+
+# toggle built-in aliases and utilities, and aliases and functions from mkshrc
+function enable {
+       \typeset doprnt=0 mode=1 x y z rv=0
+       \typeset b_alias i_alias i_func nalias=0 nfunc=0 i_all
+       \set -A b_alias
+       \set -A i_alias
+       \set -A i_func
+
+       # accumulate mksh built-in aliases, in ASCIIbetical order
+       i_alias[nalias]=autoload; b_alias[nalias++]='\typeset -fu'
+       i_alias[nalias]=functions; b_alias[nalias++]='\typeset -f'
+       i_alias[nalias]=hash; b_alias[nalias++]='\builtin alias -t'
+       i_alias[nalias]=history; b_alias[nalias++]='\builtin fc -l'
+       i_alias[nalias]=integer; b_alias[nalias++]='\typeset -i'
+       i_alias[nalias]=local; b_alias[nalias++]='\typeset'
+       i_alias[nalias]=login; b_alias[nalias++]='\exec login'
+       i_alias[nalias]=nameref; b_alias[nalias++]='\typeset -n'
+       i_alias[nalias]=nohup; b_alias[nalias++]='nohup '
+       i_alias[nalias]=r; b_alias[nalias++]='\builtin fc -e -'
+       #XXX OS/2
+       i_alias[nalias]=source; b_alias[nalias++]='PATH=$PATH:. \command .'
+       i_alias[nalias]=stop; b_alias[nalias++]='\kill -STOP'
+       i_alias[nalias]=type; b_alias[nalias++]='\builtin whence -v'
+
+       # accumulate mksh built-in utilities, in definition order, even ifndef
+       i_func[nfunc++]=.
+       i_func[nfunc++]=:
+       i_func[nfunc++]='['
+       i_func[nfunc++]=alias
+       i_func[nfunc++]=break
+       i_func[nfunc++]=builtin
+       i_func[nfunc++]=cat
+       i_func[nfunc++]=cd
+       i_func[nfunc++]=chdir
+       i_func[nfunc++]=command
+       i_func[nfunc++]=continue
+       i_func[nfunc++]=echo
+       i_func[nfunc++]=eval
+       i_func[nfunc++]=exec
+       i_func[nfunc++]=exit
+       i_func[nfunc++]=export
+       i_func[nfunc++]=false
+       i_func[nfunc++]=fc
+       i_func[nfunc++]=getopts
+       i_func[nfunc++]=global
+       i_func[nfunc++]=jobs
+       i_func[nfunc++]=kill
+       i_func[nfunc++]=let
+       i_func[nfunc++]='let]'
+       i_func[nfunc++]=print
+       i_func[nfunc++]=pwd
+       i_func[nfunc++]=read
+       i_func[nfunc++]=readonly
+       i_func[nfunc++]=realpath
+       i_func[nfunc++]=rename
+       i_func[nfunc++]=return
+       i_func[nfunc++]=set
+       i_func[nfunc++]=shift
+       i_func[nfunc++]=suspend
+       i_func[nfunc++]=test
+       i_func[nfunc++]=times
+       i_func[nfunc++]=trap
+       i_func[nfunc++]=true
+       i_func[nfunc++]=typeset
+       i_func[nfunc++]=ulimit
+       i_func[nfunc++]=umask
+       i_func[nfunc++]=unalias
+       i_func[nfunc++]=unset
+       i_func[nfunc++]=wait
+       i_func[nfunc++]=whence
+       i_func[nfunc++]=bg
+       i_func[nfunc++]=fg
+       i_func[nfunc++]=bind
+       i_func[nfunc++]=mknod
+       i_func[nfunc++]=printf
+       i_func[nfunc++]=sleep
+       i_func[nfunc++]=domainname
+
+       # accumulate aliases from dot.mkshrc, in definition order
+       i_alias[nalias]=l; b_alias[nalias++]='ls -F'
+       i_alias[nalias]=la; b_alias[nalias++]='l -a'
+       i_alias[nalias]=ll; b_alias[nalias++]='l -l'
+       i_alias[nalias]=lo; b_alias[nalias++]='l -alo'
+       i_alias[nalias]=doch; b_alias[nalias++]='sudo mksh -c "$(\builtin fc -ln -1)"'
+       i_alias[nalias]=rot13; b_alias[nalias++]='tr abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
+       i_alias[nalias]=cls; b_alias[nalias++]='\builtin print -n \\ec'
+
+       # accumulate functions from dot.mkshrc, in definition order
+       i_func[nfunc++]=hd
+       i_func[nfunc++]=chpwd
+       i_func[nfunc++]=cd_csh
+       i_func[nfunc++]=dirs
+       i_func[nfunc++]=popd
+       i_func[nfunc++]=pushd
+       i_func[nfunc++]=smores
+       i_func[nfunc++]=Lb64decode
+       i_func[nfunc++]=Lb64encode
+       i_func[nfunc++]=Lbafh_init
+       i_func[nfunc++]=Lbafh_add
+       i_func[nfunc++]=Lbafh_finish
+       i_func[nfunc++]=Lstripcom
+       i_func[nfunc++]=setenv
+       i_func[nfunc++]=enable
+
+       # collect all identifiers, sorted ASCIIbetically
+       \set -sA i_all -- "${i_alias[@]}" "${i_func[@]}"
+
+       # handle options, we don't do dynamic loading
+       while \getopts "adf:nps" x; do
+               case $x {
+               (a)
+                       mode=-1
+                       ;;
+               (d)
+                       # deliberately causing an error, like bash-static
+                       ;|
+               (f)
+                       \builtin print -u2 enable: dynamic loading not available
+                       \return 2
+                       ;;
+               (n)
+                       mode=0
+                       ;;
+               (p)
+                       doprnt=1
+                       ;;
+               (s)
+                       \set -sA i_all -- . : break continue eval exec exit \
+                           export readonly return set shift times trap unset
+                       ;;
+               (*)
+                       \builtin print -u2 enable: usage: \
+                           "enable [-adnps] [-f filename] [name ...]"
+                       return 2
+                       ;;
+               }
+       done
+       \shift $((OPTIND - 1))
+
+       # display builtins enabled/disabled/all/special?
+       if (( doprnt || ($# == 0) )); then
+               for x in "${i_all[@]}"; do
+                       y=$(\alias "$x") || y=
+                       [[ $y = "$x='\\builtin whence -p $x >/dev/null || (\\builtin print mksh: $x: not found; exit 127) && \$(\\builtin whence -p $x)'" ]]; z=$?
+                       case $mode:$z {
+                       (-1:0|0:0)
+                               \print -r -- "enable -n $x"
+                               ;;
+                       (-1:1|1:1)
+                               \print -r -- "enable $x"
+                               ;;
+                       }
+               done
+               \return 0
+       fi
+
+       for x in "$@"; do
+               z=0
+               for y in "${i_alias[@]}" "${i_func[@]}"; do
+                       [[ $x = "$y" ]] || \continue
+                       z=1
+                       \break
+               done
+               if (( !z )); then
+                       \builtin print -ru2 enable: "$x": not a shell builtin
+                       rv=1
+                       \continue
+               fi
+               if (( !mode )); then
+                       # disable this
+                       \alias "$x=\\builtin whence -p $x >/dev/null || (\\builtin print mksh: $x: not found; exit 127) && \$(\\builtin whence -p $x)"
+               else
+                       # find out if this is an alias or not, first
+                       z=0
+                       y=-1
+                       while (( ++y < nalias )); do
+                               [[ $x = "${i_alias[y]}" ]] || \continue
+                               z=1
+                               \break
+                       done
+                       if (( z )); then
+                               # re-enable the original alias body
+                               \alias "$x=${b_alias[y]}"
+                       else
+                               # re-enable the original utility/function
+                               \unalias "$x"
+                       fi
+               fi
+       done
+       \return $rv
 }
 
-: place customisations below this line
+\: place customisations below this line
 
 for p in ~/.etc/bin ~/bin; do
-       [[ -d $p/. ]] || continue
+       [[ -d $p/. ]] || \continue
+       #XXX OS/2
        [[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
 done
 
-export SHELL=$MKSH MANWIDTH=80 LESSHISTFILE=-
-alias cls='print -n \\033c'
+\export SHELL=$MKSH MANWIDTH=80 LESSHISTFILE=-
+\alias cls='\builtin print -n \\ec'
 
-#unset LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_IDENTIFICATION LC_MONETARY \
+#\unset LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_IDENTIFICATION LC_MONETARY \
 #    LC_NAME LC_NUMERIC LC_TELEPHONE LC_TIME
 #p=en_GB.UTF-8
-#set -U
-#export LANG=C LC_CTYPE=$p LC_MEASUREMENT=$p LC_MESSAGES=$p LC_PAPER=$p
+#\set -U
+#\export LANG=C LC_CTYPE=$p LC_MEASUREMENT=$p LC_MESSAGES=$p LC_PAPER=$p
 
-unset p
+\unset p
 
-: place customisations above this line
+\: place customisations above this line
index 4f9298c..4578647 100644 (file)
@@ -28,7 +28,7 @@
 
 #ifndef MKSH_NO_CMDLINE_EDITING
 
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276.2.5 2015/04/12 22:32:22 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.290 2015/07/10 19:36:34 tg Exp $");
 
 /*
  * in later versions we might use libtermcap for this, but since external
@@ -771,7 +771,7 @@ glob_path(int flags, const char *pat, XPtrV *wp, const char *lpath)
        Xinit(xs, xp, patlen + 128, ATEMP);
        while (sp) {
                xp = Xstring(xs, xp);
-               if (!(p = cstrchr(sp, ':')))
+               if (!(p = cstrchr(sp, MKSH_PATHSEPC)))
                        p = sp + strlen(sp);
                pathlen = p - sp;
                if (pathlen) {
@@ -887,7 +887,7 @@ struct x_defbindings {
 /* Separator for motion */
 #define        is_mfs(c)       (!(ksh_isalnux(c) || (c) == '$' || ((c) & 0x80)))
 
-#define X_NTABS                3                       /* normal, meta1, meta2 */
+#define X_NTABS                4                       /* normal, meta1, meta2, pc */
 #define X_TABSZ                256                     /* size of keydef tables etc */
 
 /*-
@@ -1099,8 +1099,28 @@ static struct x_defbindings const x_defbindings[] = {
        { XFUNC_mv_end | 0x80,          2,      '8'     },
        { XFUNC_mv_end,                 2,      'F'     },
        { XFUNC_del_char | 0x80,        2,      '3'     },
+       { XFUNC_del_char,               2,      'P'     },
        { XFUNC_search_hist_up | 0x80,  2,      '5'     },
        { XFUNC_search_hist_dn | 0x80,  2,      '6'     },
+#endif
+       /* PC scancodes */
+#if !defined(MKSH_SMALL) || defined(__OS2__)
+       { XFUNC_meta3,                  0,      0       },
+       { XFUNC_mv_begin,               3,      71      },
+       { XFUNC_prev_com,               3,      72      },
+#ifndef MKSH_SMALL
+       { XFUNC_search_hist_up,         3,      73      },
+#endif
+       { XFUNC_mv_back,                3,      75      },
+       { XFUNC_mv_forw,                3,      77      },
+       { XFUNC_mv_end,                 3,      79      },
+       { XFUNC_next_com,               3,      80      },
+#ifndef MKSH_SMALL
+       { XFUNC_search_hist_dn,         3,      81      },
+#endif
+       { XFUNC_del_char,               3,      83      },
+#endif
+#ifndef MKSH_SMALL
        /* more non-standard ones */
        { XFUNC_edit_line,              2,      'e'     }
 #endif
@@ -2215,6 +2235,13 @@ x_meta2(int c MKSH_A_UNUSED)
 }
 
 static int
+x_meta3(int c MKSH_A_UNUSED)
+{
+       x_curprefix = 3;
+       return (KSTD);
+}
+
+static int
 x_kill(int c MKSH_A_UNUSED)
 {
        size_t col = xcp - xbuf;
@@ -2412,8 +2439,8 @@ x_print(int prefix, int key)
 
        if (prefix)
                /* prefix == 1 || prefix == 2 */
-               shf_puts(x_mapout(prefix == 1 ?
-                   CTRL('[') : CTRL('X')), shl_stdout);
+               shf_puts(x_mapout(prefix == 1 ? CTRL('[') :
+                   prefix == 2 ? CTRL('X') : 0), shl_stdout);
 #ifdef MKSH_SMALL
        shprintf("%s = ", x_mapout(key));
 #else
@@ -2478,6 +2505,8 @@ x_bind(const char *a1, const char *a2,
                        prefix = 1;
                else if (f == XFUNC_meta2)
                        prefix = 2;
+               else if (f == XFUNC_meta3)
+                       prefix = 3;
                else
                        break;
        }
@@ -2966,7 +2995,7 @@ x_set_arg(int c)
        /* strip command prefix */
        c &= 255;
        while (c >= 0 && ksh_isdigit(c)) {
-               n = n * 10 + (c - '0');
+               n = n * 10 + ksh_numdig(c);
                if (n > LINE)
                        /* upper bound for repeat */
                        goto x_set_arg_too_big;
@@ -3053,7 +3082,7 @@ x_edit_line(int c MKSH_A_UNUSED)
                }
                if (modified) {
                        *xep = '\0';
-                       histsave(&source->line, xbuf, true, true);
+                       histsave(&source->line, xbuf, HIST_STORE, true);
                        x_arg = 0;
                } else
                        x_arg = source->line - (histptr - x_histp);
@@ -3290,8 +3319,23 @@ x_mode(bool onoff)
                edchars.eof = tty_state.c_cc[VEOF];
 #ifdef VWERASE
                edchars.werase = tty_state.c_cc[VWERASE];
+#else
+               edchars.werase = 0;
 #endif
 
+               if (!edchars.erase)
+                       edchars.erase = CTRL('H');
+               if (!edchars.kill)
+                       edchars.kill = CTRL('U');
+               if (!edchars.intr)
+                       edchars.intr = CTRL('C');
+               if (!edchars.quit)
+                       edchars.quit = CTRL('\\');
+               if (!edchars.eof)
+                       edchars.eof = CTRL('D');
+               if (!edchars.werase)
+                       edchars.werase = CTRL('W');
+
 #ifdef _POSIX_VDISABLE
                /* Convert unset values to internal 'unset' value */
                if (edchars.erase == _POSIX_VDISABLE)
@@ -3602,6 +3646,18 @@ vi_hook(int ch)
        switch (state) {
 
        case VNORMAL:
+               /* PC scancodes */
+               if (!ch) switch (cmdlen = 0, (ch = x_getc())) {
+               case 71: ch = '0'; goto pseudo_vi_command;
+               case 72: ch = 'k'; goto pseudo_vi_command;
+               case 73: ch = 'A'; goto vi_xfunc_search_up;
+               case 75: ch = 'h'; goto pseudo_vi_command;
+               case 77: ch = 'l'; goto pseudo_vi_command;
+               case 79: ch = '$'; goto pseudo_vi_command;
+               case 80: ch = 'j'; goto pseudo_vi_command;
+               case 83: ch = 'x'; goto pseudo_vi_command;
+               default: ch = 0; goto vi_insert_failed;
+               }
                if (insert != 0) {
                        if (ch == CTRL('v')) {
                                state = VLIT;
@@ -3609,6 +3665,7 @@ vi_hook(int ch)
                        }
                        switch (vi_insert(ch)) {
                        case -1:
+ vi_insert_failed:
                                vi_error();
                                state = VNORMAL;
                                break;
@@ -3627,10 +3684,11 @@ vi_hook(int ch)
                                return (1);
                        cmdlen = 0;
                        argc1 = 0;
-                       if (ch >= '1' && ch <= '9') {
-                               argc1 = ch - '0';
+                       if (ch >= ord('1') && ch <= ord('9')) {
+                               argc1 = ksh_numdig(ch);
                                state = VARG1;
                        } else {
+ pseudo_vi_command:
                                curcmd[cmdlen++] = ch;
                                state = nextstate(ch);
                                if (state == VSEARCH) {
@@ -3672,7 +3730,7 @@ vi_hook(int ch)
 
        case VARG1:
                if (ksh_isdigit(ch))
-                       argc1 = argc1 * 10 + ch - '0';
+                       argc1 = argc1 * 10 + ksh_numdig(ch);
                else {
                        curcmd[cmdlen++] = ch;
                        state = nextstate(ch);
@@ -3681,8 +3739,8 @@ vi_hook(int ch)
 
        case VEXTCMD:
                argc2 = 0;
-               if (ch >= '1' && ch <= '9') {
-                       argc2 = ch - '0';
+               if (ch >= ord('1') && ch <= ord('9')) {
+                       argc2 = ksh_numdig(ch);
                        state = VARG2;
                        return (0);
                } else {
@@ -3698,7 +3756,7 @@ vi_hook(int ch)
 
        case VARG2:
                if (ksh_isdigit(ch))
-                       argc2 = argc2 * 10 + ch - '0';
+                       argc2 = argc2 * 10 + ksh_numdig(ch);
                else {
                        if (argc1 == 0)
                                argc1 = argc2;
@@ -3799,6 +3857,7 @@ vi_hook(int ch)
                break;
 
        case VPREFIX2:
+ vi_xfunc_search_up:
                state = VFAIL;
                switch (ch) {
                case 'A':
@@ -4310,8 +4369,8 @@ vi_cmd(int argcnt, const char *cmd)
                                        return (-1);
                                if (modified) {
                                        es->cbuf[es->linelen] = '\0';
-                                       histsave(&source->line, es->cbuf, true,
-                                           true);
+                                       histsave(&source->line, es->cbuf,
+                                           HIST_STORE, true);
                                } else
                                        argcnt = source->line + 1 -
                                            (hlast - hnum);
index 1333399..6e64cfb 100644 (file)
@@ -1,5 +1,5 @@
 #if defined(EMACSFN_DEFNS)
-__RCSID("$MirOS: src/bin/mksh/emacsfn.h,v 1.5 2010/07/17 22:09:33 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/emacsfn.h,v 1.6 2015/07/10 18:41:07 tg Exp $");
 #define FN(cname,sname,flags)  static int x_##cname(int);
 #elif defined(EMACSFN_ENUMS)
 #define FN(cname,sname,flags)  XFUNC_##cname,
@@ -52,6 +52,7 @@ FN(list_file, "list-file", 0)
 FN(literal, "quote", 0)
 FN(meta1, "prefix-1", XF_PREFIX)
 FN(meta2, "prefix-2", XF_PREFIX)
+FN(meta3, "prefix-3", XF_PREFIX)
 FN(meta_yank, "yank-pop", 0)
 FN(mv_back, "backward-char", XF_ARG)
 FN(mv_begin, "beginning-of-line", 0)
index 81240c5..0b585bc 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.5 2015/04/12 22:32:24 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.170 2015/07/06 17:45:33 tg Exp $");
 
 /*
  * string expansion
@@ -291,21 +291,14 @@ expand(
                                c = *sp++;
                                break;
                        case OQUOTE:
-                               switch (word) {
-                               case IFS_QUOTE:
-                                       /* """something */
-                                       word = IFS_WORD;
-                                       break;
-                               case IFS_WORD:
-                                       break;
-                               default:
+                               if (word != IFS_WORD)
                                        word = IFS_QUOTE;
-                                       break;
-                               }
                                tilde_ok = 0;
                                quote = 1;
                                continue;
                        case CQUOTE:
+                               if (word == IFS_QUOTE)
+                                       word = IFS_WORD;
                                quote = st->quotew;
                                continue;
                        case COMSUB:
@@ -528,43 +521,27 @@ expand(
                                                afree(tpat0, ATEMP);
 
                                                /* check for special cases */
-                                               d = str_val(st->var);
                                                switch (*pat) {
                                                case '#':
-                                                       /* anchor at begin */
-                                                       tpat0 = pat + 1;
-                                                       tpat1 = rrep;
-                                                       tpat2 = d;
-                                                       break;
                                                case '%':
-                                                       /* anchor at end */
                                                        tpat0 = pat + 1;
-                                                       tpat1 = d;
-                                                       tpat2 = rrep;
                                                        break;
                                                case '\0':
-                                                       /* empty pattern */
+                                                       /* empty pattern, reject */
                                                        goto no_repl;
                                                default:
                                                        tpat0 = pat;
-                                                       /* silence gcc */
-                                                       tpat1 = tpat2 = NULL;
                                                }
                                                if (gmatchx(null, tpat0, false)) {
                                                        /*
-                                                        * pattern matches
-                                                        * the empty string
+                                                        * pattern matches empty
+                                                        * string => don't loop
                                                         */
-                                                       if (tpat0 == pat)
-                                                               goto no_repl;
-                                                       /* but is anchored */
-                                                       s = shf_smprintf("%s%s",
-                                                           tpat1, tpat2);
-                                                       goto do_repl;
+                                                       stype &= ~0x80;
                                                }
 
                                                /* prepare string on which to work */
-                                               strdupx(s, d, ATEMP);
+                                               strdupx(s, str_val(st->var), ATEMP);
                                                sbeg = s;
 
                                                /* first see if we have any match at all */
@@ -622,7 +599,6 @@ expand(
                                                        goto again_repl;
  end_repl:
                                                afree(tpat1, ATEMP);
- do_repl:
                                                x.str = s;
  no_repl:
                                                afree(pat, ATEMP);
@@ -1734,7 +1710,7 @@ do_tilde(char *cp)
                dp = str_val(global("HOME"));
        else if (cp[0] == '+' && cp[1] == '\0')
                dp = str_val(global("PWD"));
-       else if (cp[0] == '-' && cp[1] == '\0')
+       else if (ksh_isdash(cp))
                dp = str_val(global("OLDPWD"));
 #ifndef MKSH_NOPWNAM
        else
index f9eeb4c..6a743a2 100644 (file)
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.4 2015/04/19 19:18:15 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.160 2015/07/10 19:36:35 tg Exp $");
 
 #ifndef MKSH_DEFAULT_EXECSHELL
-#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
+#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
 #endif
 
 static int comexec(struct op *, struct tbl * volatile, const char **,
@@ -41,8 +41,8 @@ static const char *dbteste_getopnd(Test_env *, Test_op, bool);
 static void dbteste_error(Test_env *, int, const char *);
 static int search_access(const char *, int);
 /* XXX: horrible kludge to fit within the framework */
-static char *plain_fmt_entry(char *, size_t, unsigned int, const void *);
-static char *select_fmt_entry(char *, size_t, unsigned int, const void *);
+static void plain_fmt_entry(char *, size_t, unsigned int, const void *);
+static void select_fmt_entry(char *, size_t, unsigned int, const void *);
 
 /*
  * execute command tree
@@ -551,6 +551,12 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
                        }
                        if ((tp = findcom(cp, FC_BI)) == NULL)
                                errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin");
+                       if (tp->type == CSHELL && (tp->val.f == c_cat
+#ifdef MKSH_PRINTF_BUILTIN
+                           || tp->val.f == c_printf
+#endif
+                           ))
+                               break;
                        continue;
                } else if (tp->val.f == c_exec) {
                        if (ap[1] == NULL)
@@ -607,24 +613,28 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
                                subst_exstat = 0;
                                break;
                        }
-#ifndef MKSH_NO_EXTERNAL_CAT
                } else if (tp->val.f == c_cat) {
-                       /*
-                        * if we have any flags, do not use the builtin
-                        * in theory, we could allow -u, but that would
-                        * mean to use ksh_getopt here and possibly ad-
-                        * ded complexity and more code and isn't worth
-                        * additional hassle (and the builtin must call
-                        * ksh_getopt already but can't come back here)
-                        */
+                       /* if we have any flags, do not use the builtin */
                        if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' &&
                            /* argument, begins with -, is not - or -- */
-                           (ap[1][1] != '-' || ap[1][2] != '\0'))
-                               /* don't look for builtins or functions */
-                               fcflags = FC_PATH;
-                       else
-                               /* go on, use the builtin */
-                               break;
+                           (ap[1][1] != '-' || ap[1][2] != '\0')) {
+                               struct tbl *ext_cat;
+
+                               ext_cat = findcom(Tcat, FC_PATH | FC_FUNC);
+                               if (ext_cat && (ext_cat->type != CTALIAS ||
+                                   (ext_cat->flag & ISSET)))
+                                       tp = ext_cat;
+                       }
+                       break;
+#ifdef MKSH_PRINTF_BUILTIN
+               } else if (tp->val.f == c_printf) {
+                       struct tbl *ext_printf;
+
+                       ext_printf = findcom(Tprintf, FC_PATH | FC_FUNC);
+                       if (ext_printf && (ext_printf->type != CTALIAS ||
+                           (ext_printf->flag & ISSET)))
+                               tp = ext_printf;
+                       break;
 #endif
                } else if (tp->val.f == c_trap) {
                        t->u.evalflags &= ~DOTCOMEXEC;
@@ -705,6 +715,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
 
        /* shell built-in */
        case CSHELL:
+ do_call_builtin:
                rv = call_builtin(tp, (const char **)ap, null, resetspec);
                if (resetspec && tp->val.f == c_shift) {
                        l_expand->argc = l_assign->argc;
@@ -714,9 +725,9 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
 
        /* function call */
        case CFUNC: {
-               volatile unsigned char old_xflag;
                volatile uint32_t old_inuse;
                const char * volatile old_kshname;
+               volatile uint8_t old_flags[FNFLAGS];
 
                if (!(tp->flag & ISSET)) {
                        struct tbl *ftp;
@@ -729,6 +740,18 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
                                break;
                        }
                        if (include(tp->u.fpath, 0, NULL, false) < 0) {
+                               if (!strcmp(cp, Tcat)) {
+ no_cat_in_FPATH:
+                                       tp = findcom(Tcat, FC_BI);
+                                       goto do_call_builtin;
+                               }
+#ifdef MKSH_PRINTF_BUILTIN
+                               if (!strcmp(cp, Tprintf)) {
+ no_printf_in_FPATH:
+                                       tp = findcom(Tprintf, FC_BI);
+                                       goto do_call_builtin;
+                               }
+#endif
                                warningf(true, "%s: %s %s %s: %s", cp,
                                    "can't open", "function definition file",
                                    tp->u.fpath, cstrerror(errno));
@@ -737,6 +760,12 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
                        }
                        if (!(ftp = findfunc(cp, hash(cp), false)) ||
                            !(ftp->flag & ISSET)) {
+                               if (!strcmp(cp, Tcat))
+                                       goto no_cat_in_FPATH;
+#ifdef MKSH_PRINTF_BUILTIN
+                               if (!strcmp(cp, Tprintf))
+                                       goto no_printf_in_FPATH;
+#endif
                                warningf(true, "%s: %s %s", cp,
                                    "function not defined by", tp->u.fpath);
                                rv = 127;
@@ -768,8 +797,9 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
                        getopts_reset(1);
                }
 
-               old_xflag = Flag(FXTRACE) ? 1 : 0;
-               change_xtrace((Flag(FXTRACEREC) ? old_xflag : 0) |
+               for (type_flags = 0; type_flags < FNFLAGS; ++type_flags)
+                       old_flags[type_flags] = shell_flags[type_flags];
+               change_xtrace((Flag(FXTRACEREC) ? Flag(FXTRACE) : 0) |
                    ((tp->flag & TRACE) ? 1 : 0), false);
                old_inuse = tp->flag & FINUSE;
                tp->flag |= FINUSE;
@@ -781,7 +811,15 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
                }
 
                kshname = old_kshname;
-               change_xtrace(old_xflag, false);
+               change_xtrace(old_flags[(int)FXTRACE], false);
+#ifndef MKSH_LEGACY_MODE
+               if (tp->flag & FKSH) {
+                       /* Korn style functions restore Flags on return */
+                       old_flags[(int)FXTRACE] = Flag(FXTRACE);
+                       for (type_flags = 0; type_flags < FNFLAGS; ++type_flags)
+                               shell_flags[type_flags] = old_flags[type_flags];
+               }
+#endif
                tp->flag = (tp->flag & ~FINUSE) | old_inuse;
 
                /*
@@ -887,7 +925,7 @@ scriptexec(struct op *tp, const char **ap)
        *tp->args-- = tp->str;
 
 #ifndef MKSH_SMALL
-       if ((fd = open(tp->str, O_RDONLY | O_BINARY)) >= 0) {
+       if ((fd = binopen2(tp->str, O_RDONLY)) >= 0) {
                unsigned char *cp;
                unsigned short m;
                ssize_t n;
@@ -917,10 +955,15 @@ scriptexec(struct op *tp, const char **ap)
                /* restore begin of shebang position (buf+0 or buf+3) */
                cp = buf + n;
                /* bail out if no shebang magic found */
-               if ((cp[0] != '#') || (cp[1] != '!'))
+               if (cp[0] == '#' && cp[1] == '!')
+                       cp += 2;
+#ifdef __OS2__
+               else if (!strncmp(cp, Textproc, 7) &&
+                   (cp[7] == ' ' || cp[7] == '\t'))
+                       cp += 8;
+#endif
+               else
                        goto noshebang;
-
-               cp += 2;
                /* skip whitespace before shell name */
                while (*cp == ' ' || *cp == '\t')
                        ++cp;
@@ -955,7 +998,10 @@ scriptexec(struct op *tp, const char **ap)
                    (m == /* ECOFF_I386 */ 0x4C01) ||
                    (m == /* ECOFF_M68K */ 0x0150 || m == 0x5001) ||
                    (m == /* ECOFF_SH */   0x0500 || m == 0x0005) ||
-                   (m == /* "MZ" */ 0x4D5A) ||
+                   (m == /* bzip */ 0x425A) || (m == /* "MZ" */ 0x4D5A) ||
+                   (m == /* "NE" */ 0x4E45) || (m == /* "LX" */ 0x4C58) ||
+                   (m == /* xz */ 0xFD37 && buf[2] == 'z' && buf[3] == 'X' &&
+                   buf[4] == 'Z') || (m == /* 7zip */ 0x377A) ||
                    (m == /* gzip */ 0x1F8B) || (m == /* .Z */ 0x1F9D))
                        errorf("%s: not executable: magic %04X", tp->str, m);
  nomagic:
@@ -1019,11 +1065,13 @@ define(const char *name, struct op *t)
 
        nhash = hash(name);
 
+#ifdef MKSH_LEGACY_MODE
        if (t != NULL && !tobool(t->u.ksh_func)) {
                /* drop same-name aliases for POSIX functions */
                if ((tp = ktsearch(&aliases, name, nhash)))
                        ktdelete(tp);
        }
+#endif
 
        while (/* CONSTCOND */ 1) {
                tp = findfunc(name, nhash, true);
@@ -1199,7 +1247,7 @@ flushcom(bool all)
        struct tstate ts;
 
        for (ktwalk(&ts, &taliases); (tp = ktnext(&ts)) != NULL; )
-               if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) {
+               if ((tp->flag&ISSET) && (all || !mksh_abspath(tp->val.s))) {
                        if (tp->flag&ALLOC) {
                                tp->flag &= ~(ALLOC|ISSET);
                                afree(tp->val.s, APERM);
@@ -1260,7 +1308,7 @@ search_path(const char *name, const char *lpath,
        sp = lpath;
        while (sp != NULL) {
                xp = Xstring(xs, xp);
-               if (!(p = cstrchr(sp, ':')))
+               if (!(p = cstrchr(sp, MKSH_PATHSEPC)))
                        p = sp + strlen(sp);
                if (p != sp) {
                        XcheckN(xs, xp, p - sp);
@@ -1371,7 +1419,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
                const char *emsg;
 
                do_open = false;
-               if (*cp == '-' && !cp[1]) {
+               if (ksh_isdash(cp)) {
                        /* prevent error return below */
                        u = 1009;
                        do_close = true;
@@ -1397,7 +1445,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
                        warningf(true, "%s: %s", cp, "restricted");
                        return (-1);
                }
-               u = open(cp, flags | O_BINARY, 0666);
+               u = binopen3(cp, flags, 0666);
        }
        if (u < 0) {
                /* herein() may already have printed message */
@@ -1530,7 +1578,7 @@ herein(struct ioword *iop, char **resbuf)
         * so temp doesn't get removed too soon).
         */
        h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
-       if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY | O_BINARY, 0)) < 0) {
+       if (!(shf = h->shf) || (fd = binopen3(h->tffn, O_RDONLY, 0)) < 0) {
                i = errno;
                warningf(true, "can't %s temporary file %s: %s",
                    !shf ? "create" : "open", h->tffn, cstrerror(i));
@@ -1599,7 +1647,7 @@ struct select_menu_info {
 };
 
 /* format a single select menu item */
-static char *
+static void
 select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
 {
        const struct select_menu_info *smi =
@@ -1607,7 +1655,6 @@ select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
 
        shf_snprintf(buf, buflen, "%*u) %s",
            smi->num_width, i + 1, smi->args[i]);
-       return (buf);
 }
 
 /*
@@ -1653,11 +1700,10 @@ pr_menu(const char * const *ap)
            true);
 }
 
-static char *
+static void
 plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
 {
        strlcpy(buf, ((const char * const *)arg)[i], buflen);
-       return (buf);
 }
 
 void
index 6b328ad..ef544df 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76.2.1 2015/01/25 15:44:05 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.77 2014/12/15 23:26:36 tg Exp $");
 
 /* the order of these enums is constrained by the order of opinfo[] */
 enum token {
index 95187e6..0d2aec3 100644 (file)
@@ -38,7 +38,7 @@
 #endif
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259.2.5 2015/04/19 19:18:16 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.280 2015/07/09 20:52:39 tg Exp $");
 
 #if HAVE_KILLPG
 /*
@@ -99,7 +99,7 @@ const struct builtin mkshbuiltins[] = {
        {Talias, c_alias},
        {"*=break", c_brkcont},
        {Tgbuiltin, c_builtin},
-       {"cat", c_cat},
+       {Tcat, c_cat},
        {"cd", c_cd},
        /* dash compatibility hack */
        {"chdir", c_cd},
@@ -138,7 +138,7 @@ const struct builtin mkshbuiltins[] = {
        {"ulimit", c_ulimit},
        {"umask", c_umask},
        {Tunalias, c_unalias},
-       {Tsgunset, c_unset},
+       {"*=unset", c_unset},
        {"=wait", c_wait},
        {"whence", c_whence},
 #ifndef MKSH_UNEMPLOYED
@@ -152,7 +152,7 @@ const struct builtin mkshbuiltins[] = {
        {"mknod", c_mknod},
 #endif
 #ifdef MKSH_PRINTF_BUILTIN
-       {"printf", c_printf},
+       {Tprintf, c_printf},
 #endif
 #if HAVE_SELECT
        {"sleep", c_sleep},
@@ -161,6 +161,9 @@ const struct builtin mkshbuiltins[] = {
        /* alias to "true" for historical reasons */
        {"domainname", c_true},
 #endif
+#ifdef __OS2__
+       {Textproc, c_true},
+#endif
        {NULL, (int (*)(const char **))NULL}
 };
 
@@ -224,7 +227,7 @@ static int test_primary(Test_env *, bool);
 static Test_op ptest_isa(Test_env *, Test_meta);
 static const char *ptest_getopnd(Test_env *, Test_op, bool);
 static void ptest_error(Test_env *, int, const char *);
-static char *kill_fmt_entry(char *, size_t, unsigned int, const void *);
+static void kill_fmt_entry(char *, size_t, unsigned int, const void *);
 static void p_time(struct shf *, bool, long, int, int,
     const char *, const char *);
 
@@ -442,7 +445,7 @@ c_print(const char **wp)
 
        if (flags & PO_HIST) {
                Xput(xs, xp, '\0');
-               histsave(&source->line, Xstring(xs, xp), true, false);
+               histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
                Xfree(xs, xp);
        } else {
                int len = Xlength(xs, xp);
@@ -538,7 +541,7 @@ c_whence(const char **wp)
                uint32_t h = 0;
 
                tp = NULL;
-               if ((iam_whence || vflag) && !pflag)
+               if (!pflag)
                        tp = ktsearch(&keywords, id, h = hash(id));
                if (!tp && !pflag) {
                        tp = ktsearch(&aliases, id, h ? h : hash(id));
@@ -778,9 +781,13 @@ c_typeset(const char **wp)
 
        if (fieldstr && !bi_getn(fieldstr, &field))
                return (1);
-       if (basestr && (!getn(basestr, &base) || base < 1 || base > 36)) {
-               bi_errorf("%s: %s", "bad integer base", basestr);
-               return (1);
+       if (basestr) {
+               if (!getn(basestr, &base)) {
+                       bi_errorf("%s: %s", "bad integer base", basestr);
+                       return (1);
+               }
+               if (base < 1 || base > 36)
+                       base = 10;
        }
 
        if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind] &&
@@ -1303,7 +1310,7 @@ c_fgbg(const char **wp)
 #endif
 
 /* format a single kill item */
-static char *
+static void
 kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
 {
        const struct kill_info *ki = (const struct kill_info *)arg;
@@ -1313,7 +1320,6 @@ kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
            ki->num_width, i,
            ki->name_width, sigtraps[i].name,
            sigtraps[i].mess);
-       return (buf);
 }
 
 int
@@ -1327,7 +1333,7 @@ c_kill(const char **wp)
        /* assume old style options if -digits or -UPPERCASE */
        if ((p = wp[1]) && *p == '-' && (ksh_isdigit(p[1]) ||
            ksh_isupper(p[1]))) {
-               if (!(t = gettrap(p + 1, false))) {
+               if (!(t = gettrap(p + 1, false, false))) {
                        bi_errorf("bad signal '%s'", p + 1);
                        return (1);
                }
@@ -1341,7 +1347,8 @@ c_kill(const char **wp)
                                lflag = true;
                                break;
                        case 's':
-                               if (!(t = gettrap(builtin_opt.optarg, true))) {
+                               if (!(t = gettrap(builtin_opt.optarg,
+                                   true, false))) {
                                        bi_errorf("bad signal '%s'",
                                            builtin_opt.optarg);
                                        return (1);
@@ -1367,24 +1374,25 @@ c_kill(const char **wp)
                        for (; wp[i]; i++) {
                                if (!bi_getn(wp[i], &n))
                                        return (1);
-#if (NSIG < 128)
-                               if (n > 128 && n < 128 + NSIG)
+#if (ksh_NSIG < 128)
+                               if (n > 128 && n < 128 + ksh_NSIG)
                                        n -= 128;
 #endif
-                               if (n > 0 && n < NSIG)
+                               if (n > 0 && n < ksh_NSIG)
                                        shprintf("%s\n", sigtraps[n].name);
                                else
                                        shprintf("%d\n", n);
                        }
                } else {
-                       ssize_t w, mess_cols, mess_octs;
-                       int j;
-                       struct kill_info ki;
+                       ssize_t w, mess_cols = 0, mess_octs = 0;
+                       int j = ksh_NSIG;
+                       struct kill_info ki = { 0, 0 };
 
-                       for (j = NSIG, ki.num_width = 1; j >= 10; j /= 10)
+                       do {
                                ki.num_width++;
-                       ki.name_width = mess_cols = mess_octs = 0;
-                       for (j = 0; j < NSIG; j++) {
+                       } while ((j /= 10));
+
+                       for (j = 1; j < ksh_NSIG; j++) {
                                w = strlen(sigtraps[j].name);
                                if (w > ki.name_width)
                                        ki.name_width = w;
@@ -1396,7 +1404,7 @@ c_kill(const char **wp)
                                        mess_cols = w;
                        }
 
-                       print_columns(shl_stdout, (unsigned int)(NSIG - 1),
+                       print_columns(shl_stdout, (unsigned int)(ksh_NSIG - 1),
                            kill_fmt_entry, (void *)&ki,
                            ki.num_width + 1 + ki.name_width + 1 + mess_octs,
                            ki.num_width + 1 + ki.name_width + 1 + mess_cols,
@@ -1662,8 +1670,11 @@ c_umask(const char **wp)
                mode_t new_umask;
 
                if (ksh_isdigit(*cp)) {
-                       for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++)
-                               new_umask = new_umask * 8 + (*cp - '0');
+                       new_umask = 0;
+                       while (*cp >= ord('0') && *cp <= ord('7')) {
+                               new_umask = new_umask * 8 + ksh_numdig(*cp);
+                               ++cp;
+                       }
                        if (*cp) {
                                bi_errorf("bad number");
                                return (1);
@@ -1955,8 +1966,9 @@ c_read(const char **wp)
                        break;
                case 0:
                        /* timeout expired for this call */
-                       rv = 1;
-                       goto c_read_out;
+                       bytesread = 0;
+                       /* fake EOF read; all cases return 1 */
+                       goto c_read_didread;
                default:
                        bi_errorf("%s: %s", Tselect, cstrerror(errno));
                        rv = 2;
@@ -1981,6 +1993,7 @@ c_read(const char **wp)
                goto c_read_readloop;
        }
 
+ c_read_didread:
        switch (readmode) {
        case READALL:
                if (bytesread == 0) {
@@ -2003,7 +2016,7 @@ c_read(const char **wp)
                if (bytesread == 0) {
                        /* end of file reached */
                        rv = 1;
-                       xp = Xstring(xs, xp);
+                       /* may be partial read: $? = 1, but content */
                        goto c_read_readdone;
                }
                xp += bytesread;
@@ -2066,7 +2079,7 @@ c_read(const char **wp)
        }
 
        if (savehist)
-               histsave(&source->line, Xstring(xs, xp), true, false);
+               histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
 
        ccp = cp = Xclose(xs, xp);
        expanding = false;
@@ -2279,41 +2292,44 @@ c_eval(const char **wp)
 int
 c_trap(const char **wp)
 {
-       int i;
+       Trap *p = sigtraps;
+       int i = ksh_NSIG + 1;
        const char *s;
-       Trap *p;
 
        if (ksh_getopt(wp, &builtin_opt, null) == '?')
                return (1);
        wp += builtin_opt.optind;
 
        if (*wp == NULL) {
-               for (p = sigtraps, i = NSIG + 1; --i >= 0; p++)
-                       if (p->trap != NULL) {
+               do {
+                       if (p->trap) {
                                shf_puts("trap -- ", shl_stdout);
                                print_value_quoted(shl_stdout, p->trap);
                                shprintf(" %s\n", p->name);
                        }
+                       ++p;
+               } while (--i);
                return (0);
        }
 
-       /*
-        * Use case sensitive lookup for first arg so the
-        * command 'exit' isn't confused with the pseudo-signal
-        * 'EXIT'.
-        */
-       /* get command */
-       s = (gettrap(*wp, false) == NULL) ? *wp++ : NULL;
-       if (s != NULL && s[0] == '-' && s[1] == '\0')
+       if (getn(*wp, &i)) {
+               /* first argument is a signal number, reset them all */
                s = NULL;
+       } else {
+               /* first argument must be a command, then */
+               s = *wp++;
+               /* reset traps? */
+               if (ksh_isdash(s))
+                       s = NULL;
+       }
 
-       /* set/clear traps */
+       /* set/clear the traps */
        i = 0;
-       while (*wp != NULL)
-               if ((p = gettrap(*wp++, true)) == NULL) {
+       while (*wp)
+               if (!(p = gettrap(*wp++, true, true))) {
                        warningf(true, "%s: %s '%s'", builtin_argv0,
                            "bad signal", wp[-1]);
-                       ++i;
+                       i = 1;
                } else
                        settrap(p, s);
        return (i);
@@ -3412,7 +3428,27 @@ ptest_error(Test_env *te, int ofs, const char *msg)
 # error nonsensical v ulimit
 #endif
 
+struct limits {
+       /* limit resource */
+       int resource;
+       /* multiply by to get rlim_{cur,max} values */
+       unsigned int factor;
+       /* getopts char */
+       char optchar;
+       /* limit name */
+       char name[1];
+};
+
 #define RLIMITS_DEFNS
+#define FN(lname,lid,lfac,lopt)                                \
+       static const struct {                           \
+               int resource;                           \
+               unsigned int factor;                    \
+               char optchar;                           \
+               char name[sizeof(lname)];               \
+       } rlimits_ ## lid = {                           \
+               lid, lfac, lopt, lname                  \
+       };
 #include "rlimits.gen"
 
 static void print_ulimit(const struct limits *, int);
@@ -3630,9 +3666,9 @@ c_cat(const char **wp)
        do {
                if (*wp) {
                        fn = *wp++;
-                       if (fn[0] == '-' && fn[1] == '\0')
+                       if (ksh_isdash(fn))
                                fd = STDIN_FILENO;
-                       else if ((fd = open(fn, O_RDONLY | O_BINARY)) < 0) {
+                       else if ((fd = binopen2(fn, O_RDONLY)) < 0) {
                                eno = errno;
                                bi_errorf("%s: %s", fn, cstrerror(eno));
                                rv = 1;
index 0dfe1c2..7a96aa8 100644 (file)
@@ -27,9 +27,9 @@
 #include <sys/file.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134.2.5 2015/04/19 19:18:18 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.149 2015/07/09 20:52:40 tg Exp $");
 
-Trap sigtraps[NSIG + 1];
+Trap sigtraps[ksh_NSIG + 1];
 static struct sigaction Sigact_ign;
 
 #if HAVE_PERSISTENT_HISTORY
@@ -38,7 +38,7 @@ static int writehistline(int, int, const char *);
 static void writehistfile(int, const char *);
 #endif
 
-static int hist_execute(char *);
+static int hist_execute(char *, Area *);
 static char **hist_get(const char *, bool, bool);
 static char **hist_get_oldest(void);
 
@@ -84,6 +84,9 @@ static const char TFCEDIT_dollaru[] = "${FCEDIT:-/bin/ed} $_";
 /* maximum considered size of persistent history file */
 #define MKSH_MAXHISTFSIZE      ((off_t)1048576 * 96)
 
+/* hidden option */
+#define HIST_DISCARD           5
+
 int
 c_fc(const char **wp)
 {
@@ -223,7 +226,7 @@ c_fc(const char **wp)
                        xp += len;
                        line = Xclose(xs, xp);
                }
-               return (hist_execute(line));
+               return (hist_execute(line, ATEMP));
        }
 
        if (editor && (lflag || nflag)) {
@@ -360,18 +363,17 @@ c_fc(const char **wp)
                shf_close(shf);
                *xp = '\0';
                strip_nuls(Xstring(xs, xp), Xlength(xs, xp));
-               return (hist_execute(Xstring(xs, xp)));
+               return (hist_execute(Xstring(xs, xp), hist_source->areap));
        }
 }
 
-/* Save cmd in history, execute cmd (cmd gets trashed) */
+/* save cmd in history, execute cmd (cmd gets afree’d) */
 static int
-hist_execute(char *cmd)
+hist_execute(char *cmd, Area *areap)
 {
        static int last_line = -1;
        Source *sold;
        int ret;
-       char *p, *q;
 
        /* Back up over last histsave */
        if (histptr >= history && last_line != hist_source->line) {
@@ -381,22 +383,12 @@ hist_execute(char *cmd)
                last_line = hist_source->line;
        }
 
-       for (p = cmd; p; p = q) {
-               if ((q = strchr(p, '\n'))) {
-                       /* kill the newline */
-                       *q++ = '\0';
-                       if (!*q)
-                               /* ignore trailing newline */
-                               q = NULL;
-               }
-               histsave(&hist_source->line, p, true, true);
-
-               /* POSIX doesn't say this is done... */
-               shellf("%s\n", p);
-               if (q)
-                       /* restore \n (trailing \n not restored) */
-                       q[-1] = '\n';
-       }
+       histsave(&hist_source->line, cmd, HIST_STORE, true);
+       /* now *histptr == cmd without all trailing newlines */
+       afree(cmd, areap);
+       cmd = *histptr;
+       /* pdksh says POSIX doesn’t say this is done, testsuite needs it */
+       shellf("%s\n", cmd);
 
        /*-
         * Commands are executed here instead of pushing them onto the
@@ -578,6 +570,7 @@ sethistfile(const char *name)
                afree(hname, APERM);
                hname = NULL;
                /* let's reset the history */
+               histsave(NULL, NULL, HIST_DISCARD, true);
                histptr = history - 1;
                hist_source->line = 0;
        }
@@ -612,6 +605,8 @@ histsync(void)
 {
        bool changed = false;
 
+       /* called by histsave(), may not HIST_DISCARD, caller should flush */
+
        if (histfd != -1) {
                int lno = hist_source->line;
 
@@ -631,30 +626,74 @@ histsync(void)
  * save command in history
  */
 void
-histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
+histsave(int *lnp, const char *cmd, int svmode, bool ignoredups)
 {
-       char **hp;
-       char *c, *cp;
+       static char *enqueued = NULL;
+       char **hp, *c;
+       const char *ccp;
 
-       strdupx(c, cmd, APERM);
-       if ((cp = strchr(c, '\n')) != NULL)
-               *cp = '\0';
+       if (svmode == HIST_DISCARD) {
+               afree(enqueued, APERM);
+               enqueued = NULL;
+               return;
+       }
 
-       if (ignoredups && !strcmp(c, *histptr)
-#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
-           && !histsync()
-#endif
-           ) {
+       if (svmode == HIST_APPEND) {
+               if (!enqueued)
+                       svmode = HIST_STORE;
+       } else if (enqueued) {
+               c = enqueued;
+               enqueued = NULL;
+               --*lnp;
+               histsave(lnp, c, HIST_STORE, true);
                afree(c, APERM);
+       }
+
+       if (svmode == HIST_FLUSH)
                return;
+
+       ccp = cmd + strlen(cmd);
+       while (ccp > cmd && ccp[-1] == '\n')
+               --ccp;
+       strndupx(c, cmd, ccp - cmd, APERM);
+
+       if (svmode != HIST_APPEND) {
+               if (ignoredups && !strcmp(c, *histptr)
+#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
+                   && !histsync()
+#endif
+                   ) {
+                       afree(c, APERM);
+                       return;
+               }
+               ++*lnp;
        }
-       ++*lnp;
 
 #if HAVE_PERSISTENT_HISTORY
-       if (dowrite && histfd != -1)
+       if (svmode == HIST_STORE && histfd != -1)
                writehistfile(*lnp, c);
 #endif
 
+       if (svmode == HIST_QUEUE || svmode == HIST_APPEND) {
+               size_t nenq, ncmd;
+
+               if (!enqueued) {
+                       if (*c)
+                               enqueued = c;
+                       else
+                               afree(c, APERM);
+                       return;
+               }
+
+               nenq = strlen(enqueued);
+               ncmd = strlen(c);
+               enqueued = aresize(enqueued, nenq + 1 + ncmd + 1, APERM);
+               enqueued[nenq] = '\n';
+               memcpy(enqueued + nenq + 1, c, ncmd + 1);
+               afree(c, APERM);
+               return;
+       }
+
        hp = histptr;
 
        if (++hp >= history + histsize) {
@@ -707,6 +746,8 @@ hist_init(Source *s)
        enum { hist_init_first, hist_init_retry, hist_init_restore } hs;
 #endif
 
+       histsave(NULL, NULL, HIST_DISCARD, true);
+
        if (Flag(FTALKING) == 0)
                return;
 
@@ -723,8 +764,7 @@ hist_init(Source *s)
 
  retry:
        /* we have a file and are interactive */
-       if ((fd = open(hname, O_RDWR | O_CREAT | O_APPEND | O_BINARY,
-           0600)) < 0)
+       if ((fd = binopen3(hname, O_RDWR | O_CREAT | O_APPEND, 0600)) < 0)
                return;
 
        histfd = savefd(fd);
@@ -759,8 +799,8 @@ hist_init(Source *s)
 
                        /* create temporary file */
                        nhname = shf_smprintf("%s.%d", hname, (int)procpid);
-                       if ((fd = open(nhname, O_RDWR | O_CREAT | O_TRUNC |
-                           O_EXCL | O_BINARY, 0600)) < 0) {
+                       if ((fd = binopen3(nhname, O_RDWR | O_CREAT | O_TRUNC |
+                           O_EXCL, 0600)) < 0) {
                                /* just don't truncate then, meh. */
                                goto hist_trunc_dont;
                        }
@@ -864,7 +904,7 @@ histload(Source *s, unsigned char *base, size_t bytes)
                }
        } else {
                s->line = lno--;
-               histsave(&lno, (char *)(base + 4), false, false);
+               histsave(&lno, (char *)(base + 4), HIST_NOTE, false);
        }
        /* advance base pointer past NUL */
        bytes -= ++cp - base;
@@ -980,55 +1020,53 @@ inittraps(void)
        trap_exstat = -1;
 
        /* Populate sigtraps based on sys_signame and sys_siglist. */
-       /*XXX this is idiotic, use a multi-key/value hashtable! */
-       for (i = 0; i <= NSIG; i++) {
+       for (i = 1; i < ksh_NSIG; i++) {
                sigtraps[i].signal = i;
-               if (i == ksh_SIGERR) {
-                       sigtraps[i].name = "ERR";
-                       sigtraps[i].mess = "Error handler";
-               } else {
 #if HAVE_SYS_SIGNAME
-                       cs = sys_signame[i];
+               cs = sys_signame[i];
 #else
-                       const struct mksh_sigpair *pair = mksh_sigpairs;
-                       while ((pair->nr != i) && (pair->name != NULL))
-                               ++pair;
-                       cs = pair->name;
+               const struct mksh_sigpair *pair = mksh_sigpairs;
+               while ((pair->nr != i) && (pair->name != NULL))
+                       ++pair;
+               cs = pair->name;
 #endif
-                       if ((cs == NULL) ||
-                           (cs[0] == '\0'))
-                               sigtraps[i].name = shf_smprintf("%d", i);
-                       else {
-                               char *s;
-
-                               /* this is not optimal, what about SIGSIG1? */
-                               if ((cs[0] & 0xDF) == 'S' &&
-                                   (cs[1] & 0xDF) == 'I' &&
-                                   (cs[2] & 0xDF) == 'G' &&
-                                   cs[3] != '\0') {
-                                       /* skip leading "SIG" */
-                                       cs += 3;
-                               }
-                               strdupx(s, cs, APERM);
-                               sigtraps[i].name = s;
-                               while ((*s = ksh_toupper(*s)))
-                                       ++s;
+               if ((cs == NULL) ||
+                   (cs[0] == '\0'))
+                       sigtraps[i].name = shf_smprintf("%d", i);
+               else {
+                       char *s;
+
+                       /* this is not optimal, what about SIGSIG1? */
+                       if (ksh_eq(cs[0], 'S', 's') &&
+                           ksh_eq(cs[1], 'I', 'i') &&
+                           ksh_eq(cs[2], 'G', 'g') &&
+                           cs[3] != '\0') {
+                               /* skip leading "SIG" */
+                               cs += 3;
                        }
+                       strdupx(s, cs, APERM);
+                       sigtraps[i].name = s;
+                       while ((*s = ksh_toupper(*s)))
+                               ++s;
+               }
 #if HAVE_SYS_SIGLIST
-                       sigtraps[i].mess = sys_siglist[i];
+               sigtraps[i].mess = sys_siglist[i];
 #elif HAVE_STRSIGNAL
-                       sigtraps[i].mess = strsignal(i);
+               sigtraps[i].mess = strsignal(i);
 #else
-                       sigtraps[i].mess = NULL;
+               sigtraps[i].mess = NULL;
 #endif
-                       if ((sigtraps[i].mess == NULL) ||
-                           (sigtraps[i].mess[0] == '\0'))
-                               sigtraps[i].mess = shf_smprintf("%s %d",
-                                   "Signal", i);
-               }
+               if ((sigtraps[i].mess == NULL) ||
+                   (sigtraps[i].mess[0] == '\0'))
+                       sigtraps[i].mess = shf_smprintf("%s %d",
+                           "Signal", i);
        }
-       /* our name for signal 0 */
+       sigtraps[ksh_SIGEXIT].signal = ksh_SIGEXIT;
        sigtraps[ksh_SIGEXIT].name = "EXIT";
+       sigtraps[ksh_SIGEXIT].mess = "Exit trap";
+       sigtraps[ksh_SIGERR].signal = ksh_SIGERR;
+       sigtraps[ksh_SIGERR].name = "ERR";
+       sigtraps[ksh_SIGERR].mess = "Error handler";
 
        (void)sigemptyset(&Sigact_ign.sa_mask);
        Sigact_ign.sa_flags = 0; /* interruptible */
@@ -1076,21 +1114,24 @@ alarm_catcher(int sig MKSH_A_UNUSED)
 }
 
 Trap *
-gettrap(const char *cs, bool igncase)
+gettrap(const char *cs, bool igncase, bool allsigs)
 {
        int i;
        Trap *p;
        char *as;
 
-       if (ksh_isdigit(*cs)) {
-               return ((getn(cs, &i) && 0 <= i && i < NSIG) ?
+       /* signal number (1..ksh_NSIG) or 0? */
+
+       if (ksh_isdigit(*cs))
+               return ((getn(cs, &i) && 0 <= i && i < ksh_NSIG) ?
                    (&sigtraps[i]) : NULL);
-       }
+
+       /* do a lookup by name then */
 
        /* this breaks SIGSIG1, but we do that above anyway */
-       if ((cs[0] & 0xDF) == 'S' &&
-           (cs[1] & 0xDF) == 'I' &&
-           (cs[2] & 0xDF) == 'G' &&
+       if (ksh_eq(cs[0], 'S', 's') &&
+           ksh_eq(cs[1], 'I', 'i') &&
+           ksh_eq(cs[2], 'G', 'g') &&
            cs[3] != '\0') {
                /* skip leading "SIG" */
                cs += 3;
@@ -1105,14 +1146,24 @@ gettrap(const char *cs, bool igncase)
        } else
                as = NULL;
 
+       /* this is idiotic, we really want a hashtable here */
+
        p = sigtraps;
-       for (i = 0; i <= NSIG; i++) {
+       i = ksh_NSIG + 1;
+       do {
                if (!strcmp(p->name, cs))
                        goto found;
                ++p;
-       }
-       p = NULL;
+       } while (--i);
+       goto notfound;
+
  found:
+       if (!allsigs) {
+               if (p->signal == ksh_SIGEXIT || p->signal == ksh_SIGERR) {
+ notfound:
+                       p = NULL;
+               }
+       }
        afree(as, ATEMP);
        return (p);
 }
@@ -1156,14 +1207,16 @@ intrcheck(void)
 int
 fatal_trap_check(void)
 {
-       int i;
-       Trap *p;
+       Trap *p = sigtraps;
+       int i = ksh_NSIG + 1;
 
        /* todo: should check if signal is fatal, not the TF_DFL_INTR flag */
-       for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
+       do {
                if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL)))
                        /* return value is used as an exit code */
                        return (128 + p->signal);
+               ++p;
+       } while (--i);
        return (0);
 }
 
@@ -1175,13 +1228,15 @@ fatal_trap_check(void)
 int
 trap_pending(void)
 {
-       int i;
-       Trap *p;
+       Trap *p = sigtraps;
+       int i = ksh_NSIG + 1;
 
-       for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
+       do {
                if (p->set && ((p->trap && p->trap[0]) ||
                    ((p->flags & (TF_DFL_INTR|TF_FATAL)) && !p->trap)))
                        return (p->signal);
+               ++p;
+       } while (--i);
        return (0);
 }
 
@@ -1192,8 +1247,8 @@ trap_pending(void)
 void
 runtraps(int flag)
 {
-       int i;
-       Trap *p;
+       Trap *p = sigtraps;
+       int i = ksh_NSIG + 1;
 
        if (ksh_tmout_state == TMOUT_LEAVING) {
                ksh_tmout_state = TMOUT_EXECUTING;
@@ -1212,10 +1267,12 @@ runtraps(int flag)
        if (flag & TF_FATAL)
                fatal_trap = 0;
        ++trap_nested;
-       for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
+       do {
                if (p->set && (!flag ||
                    ((p->flags & flag) && p->trap == NULL)))
                        runtrap(p, false);
+               ++p;
+       } while (--i);
        if (!--trap_nested)
                runtrap(NULL, true);
 }
@@ -1234,16 +1291,17 @@ runtrap(Trap *p, bool is_last)
        p->set = 0;
        if (trapstr == NULL) {
                /* SIG_DFL */
-               if (p->flags & TF_FATAL) {
-                       /* eg, SIGHUP */
-                       exstat = (int)ksh_min(128U + (unsigned)i, 255U);
-                       unwind(LLEAVE);
+               if (p->flags & (TF_FATAL | TF_DFL_INTR)) {
+                       exstat = (int)(128U + (unsigned)i);
+                       if ((unsigned)exstat > 255U)
+                               exstat = 255;
                }
-               if (p->flags & TF_DFL_INTR) {
-                       /* eg, SIGINT, SIGQUIT, SIGTERM, etc. */
-                       exstat = (int)ksh_min(128U + (unsigned)i, 255U);
+               /* e.g. SIGHUP */
+               if (p->flags & TF_FATAL)
+                       unwind(LLEAVE);
+               /* e.g. SIGINT, SIGQUIT, SIGTERM, etc. */
+               if (p->flags & TF_DFL_INTR)
                        unwind(LINTR);
-               }
                goto donetrap;
        }
        if (trapstr[0] == '\0')
@@ -1283,30 +1341,34 @@ runtrap(Trap *p, bool is_last)
 void
 cleartraps(void)
 {
-       int i;
-       Trap *p;
+       Trap *p = sigtraps;
+       int i = ksh_NSIG + 1;
 
        trap = 0;
        intrsig = 0;
        fatal_trap = 0;
-       for (i = NSIG+1, p = sigtraps; --i >= 0; p++) {
+
+       do {
                p->set = 0;
                if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0]))
                        settrap(p, NULL);
-       }
+               ++p;
+       } while (--i);
 }
 
 /* restore signals just before an exec(2) */
 void
 restoresigs(void)
 {
-       int i;
-       Trap *p;
+       Trap *p = sigtraps;
+       int i = ksh_NSIG + 1;
 
-       for (i = NSIG+1, p = sigtraps; --i >= 0; p++)
+       do {
                if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL))
                        setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL,
                            SS_RESTORE_CURR|SS_FORCE);
+               ++p;
+       } while (--i);
 }
 
 void
index 7a5b270..8469f83 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105.2.2 2015/04/19 19:18:18 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.112 2015/04/19 14:40:09 tg Exp $");
 
 #if HAVE_KILLPG
 #define mksh_killpg            killpg
@@ -1274,7 +1274,7 @@ j_waitj(Job *j,
                }
        } else if (Flag(FPIPEFAIL)) {
                do {
-                       int i = proc_errorlevel(p);
+                       const int i = proc_errorlevel(p);
 
                        if (i)
                                rv = i;
index 9c1dd6d..f943365 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20.2.1 2015/01/25 15:35:47 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.21 2014/11/25 20:00:39 tg Exp $");
 
 /* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
 #if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
index 305f5a4..fb80244 100644 (file)
--- a/src/lex.c
+++ b/src/lex.c
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193.2.5 2015/04/19 19:18:19 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.204 2015/07/05 19:53:46 tg Exp $");
 
 /*
  * states while lexing word
@@ -920,7 +920,7 @@ yylex(int cf)
                                goto no_iop;
                        if (!ksh_isdigit(dp[c2 + 1]))
                                goto no_iop;
-                       iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0';
+                       iop->unit = iop->unit * 10 + ksh_numdig(dp[c2 + 1]);
                        if (iop->unit >= FDBASE)
                                goto no_iop;
                }
@@ -1461,16 +1461,23 @@ getsc_line(Source *s)
                if (s->type == SFILE)
                        shf_fdclose(s->u.shf);
                s->str = NULL;
-       } else if (interactive && *s->str &&
-           (cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS))) {
-               histsave(&s->line, s->str, true, true);
+       } else if (interactive && *s->str) {
+               if (cur_prompt != PS1)
+                       histsave(&s->line, s->str, HIST_APPEND, true);
+               else if (!ctype(*s->str, C_IFS | C_IFSWS))
+                       histsave(&s->line, s->str, HIST_QUEUE, true);
 #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
+               else
+                       goto check_for_sole_return;
        } else if (interactive && cur_prompt == PS1) {
+ check_for_sole_return:
                cp = Xstring(s->xs, xp);
                while (*cp && ctype(*cp, C_IFSWS))
                        ++cp;
-               if (!*cp)
+               if (!*cp) {
+                       histsave(&s->line, NULL, HIST_FLUSH, true);
                        histsync();
+               }
 #endif
        }
        if (interactive)
@@ -1495,6 +1502,7 @@ set_prompt(int to, Source *s)
                        struct shf *shf;
                        char * volatile ps1;
                        Area *saved_atemp;
+                       int saved_lineno;
 
                        ps1 = str_val(global("PS1"));
                        shf = shf_sopen(NULL, strlen(ps1) * 2,
@@ -1506,6 +1514,9 @@ set_prompt(int to, Source *s)
                                        shf_fprintf(shf, "%lu", s ?
                                            (unsigned long)s->line + 1 : 0UL);
                        ps1 = shf_sclose(shf);
+                       saved_lineno = current_lineno;
+                       if (s)
+                               current_lineno = s->line + 1;
                        saved_atemp = ATEMP;
                        newenv(E_ERRH);
                        if (kshsetjmp(e->jbuf)) {
@@ -1521,6 +1532,7 @@ set_prompt(int to, Source *s)
                                char *cp = substitute(ps1, 0);
                                strdupx(prompt, cp, saved_atemp);
                        }
+                       current_lineno = saved_lineno;
                        quitenv(NULL);
                }
                break;
index fe6d59d..a13d7a0 100644 (file)
@@ -1,4 +1,4 @@
-.\" $MirOS: src/bin/mksh/lksh.1,v 1.5.2.1 2015/03/21 00:12:45 tg Exp $
+.\" $MirOS: src/bin/mksh/lksh.1,v 1.10 2015/04/12 22:32:12 tg Exp $
 .\"-
 .\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015
 .\"    Thorsten “mirabilos” Glaser <tg@mirbsd.org>
@@ -72,7 +72,7 @@
 .\" with -mandoc, it might implement .Mx itself, but we want to
 .\" use our own definition. And .Dd must come *first*, always.
 .\"
-.Dd $Mdocdate: March 21 2015 $
+.Dd $Mdocdate: April 12 2015 $
 .\"
 .\" Check which macro package we use, and do other -mdoc setup.
 .\"
@@ -261,6 +261,23 @@ or
 mode and
 .Nm lksh
 do not keep file descriptors \*(Gt 2 private from sub-processes.
+.It
+.Nm lksh
+undefines an alias when a
+.Tn POSIX
+function with the same name is defined,
+to make that function immediately callable.
+In
+.Nm mksh ,
+aliases have precedence; the name must be quoted or
+.Ic unalias Ns ed
+to access it.
+.It
+Functions defined with the
+.Ic function
+reserved word share the shell options
+.Pq Ic set -o
+instead of locally scoping them.
 .El
 .Sh SEE ALSO
 .Xr mksh 1
index 047aad1..bca8471 100644 (file)
@@ -34,7 +34,7 @@
 #include <locale.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285.2.4 2015/04/19 19:18:20 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.300 2015/07/10 19:36:35 tg Exp $");
 
 extern char **environ;
 
@@ -43,7 +43,7 @@ extern char **environ;
 #endif
 
 #ifndef MKSH_DEFAULT_TMPDIR
-#define MKSH_DEFAULT_TMPDIR    "/tmp"
+#define MKSH_DEFAULT_TMPDIR    MKSH_UNIXROOT "/tmp"
 #endif
 
 static uint8_t isuc(const char *);
@@ -66,28 +66,28 @@ static const char *initcoms[] = {
        Ttypeset, "-x", "HOME", "PATH", "SHELL", NULL,
        Ttypeset, "-i10", "COLUMNS", "LINES", "SECONDS", "TMOUT", NULL,
        Talias,
-       "integer=typeset -i",
-       Tlocal_typeset,
+       "integer=\\typeset -i",
+       "local=\\typeset",
        /* not "alias -t --": hash -r needs to work */
-       "hash=alias -t",
-       "type=whence -v",
+       "hash=\\builtin alias -t",
+       "type=\\builtin whence -v",
 #if !defined(ANDROID) && !defined(MKSH_UNEMPLOYED)
        /* not in Android for political reasons */
        /* not in ARGE mksh due to no job control */
-       "stop=kill -STOP",
+       "stop=\\kill -STOP",
 #endif
-       "autoload=typeset -fu",
-       "functions=typeset -f",
-       "history=fc -l",
-       "nameref=typeset -n",
+       "autoload=\\typeset -fu",
+       "functions=\\typeset -f",
+       "history=\\builtin fc -l",
+       "nameref=\\typeset -n",
        "nohup=nohup ",
-       Tr_fc_e_dash,
-       "source=PATH=$PATH:. command .",
-       "login=exec login",
+       "r=\\builtin fc -e -",
+       "source=PATH=$PATH" MKSH_PATHSEPS ". \\command .",
+       "login=\\exec login",
        NULL,
         /* this is what AT&T ksh seems to track, with the addition of emacs */
        Talias, "-tU",
-       "cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
+       Tcat, "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
        "make", "mv", "pr", "rm", "sed", "sh", "vi", "who", NULL,
        NULL
 };
@@ -193,6 +193,12 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
        ssize_t k;
 #endif
 
+#ifdef __OS2__
+       for (i = 0; i < 3; ++i)
+               if (!isatty(i))
+                       setmode(i, O_BINARY);
+#endif
+
        /* do things like getpgrp() et al. */
        chvt_reinit();
 
@@ -264,7 +270,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
 
 #if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED)
                /* are we called as -sh or /bin/sh or so? */
-               if (!strcmp(ccp, "sh")) {
+               if (!strcmp(ccp, "sh" MKSH_EXE_EXT)) {
                        /* either also turns off braceexpand */
 #ifdef MKSH_BINSHPOSIX
                        /* enable better POSIX conformance */
@@ -318,7 +324,10 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
                 * "keeping a regular /usr"; this is supposed
                 * to be a sane 'basic' default PATH
                 */
-               def_path = "/bin:/usr/bin:/sbin:/usr/sbin";
+               def_path = MKSH_UNIXROOT "/bin" MKSH_PATHSEPS
+                   MKSH_UNIXROOT "/usr/bin" MKSH_PATHSEPS
+                   MKSH_UNIXROOT "/sbin" MKSH_PATHSEPS
+                   MKSH_UNIXROOT "/usr/sbin";
 #endif
 
        /*
@@ -361,7 +370,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
        vp = global("PWD");
        cp = str_val(vp);
        /* Try to use existing $PWD if it is valid */
-       set_current_wd((cp[0] == '/' && test_eval(NULL, TO_FILEQ, cp, ".",
+       set_current_wd((mksh_abspath(cp) && test_eval(NULL, TO_FILEQ, cp, ".",
            true)) ? cp : NULL);
        if (current_wd[0])
                simplify_path(current_wd);
@@ -454,7 +463,19 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
                        kshname = argv[argi++];
        } else if (argi < argc && !Flag(FSTDIN)) {
                s = pushs(SFILE, ATEMP);
+#ifdef __OS2__
+               /*
+                * A bug in OS/2 extproc (like shebang) handling makes
+                * it not pass the full pathname of a script, so we need
+                * to search for it. This changes the behaviour of a
+                * simple "mksh foo", but can't be helped.
+                */
+               s->file = search_path(argv[argi++], path, X_OK, NULL);
+               if (!s->file || !*s->file)
+                       s->file = argv[argi - 1];
+#else
                s->file = argv[argi++];
+#endif
                s->u.shf = shf_open(s->file, O_RDONLY, 0,
                    SHF_MAPHI | SHF_CLEXEC);
                if (s->u.shf == NULL) {
@@ -803,6 +824,8 @@ shell(Source * volatile s, volatile bool toplevel)
                        set_prompt(PS1, s);
                }
                t = compile(s, sfirst);
+               if (interactive)
+                       histsave(&s->line, NULL, HIST_FLUSH, true);
                sfirst = false;
                if (!t)
                        goto source_no_tree;
@@ -1352,7 +1375,7 @@ initio(void)
        shf_fdopen(2, SHF_WR, shl_xtrace);
 #ifdef DF
        if ((lfp = getenv("SDMKSH_PATH")) == NULL) {
-               if ((lfp = getenv("HOME")) == NULL || *lfp != '/')
+               if ((lfp = getenv("HOME")) == NULL || !mksh_abspath(lfp))
                        errorf("cannot get home directory");
                lfp = shf_smprintf("%s/mksh-dbg.txt", lfp);
        }
@@ -1402,7 +1425,7 @@ savefd(int fd)
        int nfd = fd;
 
        if (fd < FDBASE && (nfd = fcntl(fd, F_DUPFD, FDBASE)) < 0 &&
-           errno == EBADF)
+           (errno == EBADF || errno == EPERM))
                return (-1);
        if (nfd < 0 || nfd > SHRT_MAX)
                errorf("too many files open in shell");
@@ -1459,7 +1482,7 @@ check_fd(const char *name, int mode, const char **emsgp)
        if (name[0] == 'p' && !name[1])
                return (coproc_getfd(mode, emsgp));
        while (ksh_isdigit(*name)) {
-               fd = (fd * 10) + *name - '0';
+               fd = fd * 10 + ksh_numdig(*name);
                if (fd >= FDBASE) {
                        if (emsgp)
                                *emsgp = "file descriptor too large";
@@ -1613,28 +1636,20 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist)
        memcpy(cp, "/shXXXXXX.tmp", 14);
        /* point to the first of six Xes */
        cp += 3;
-       /* generate random part of filename */
-       len = -1;
-       do {
-               i = rndget() % 36;
-               cp[++len] = i < 26 ? 'a' + i : '0' + i - 26;
-       } while (len < 5);
 
        /* cyclically attempt to open a temporary file */
-       while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR | O_BINARY,
-           0600)) < 0) {
-               if (errno != EEXIST)
+       do {
+               /* generate random part of filename */
+               len = 0;
+               do {
+                       cp[len++] = digits_lc[rndget() % 36];
+               } while (len < 6);
+
+               /* check if this one works */
+               if ((i = binopen3(tp->tffn, O_CREAT | O_EXCL | O_RDWR,
+                   0600)) < 0 && errno != EEXIST)
                        goto maketemp_out;
-               /* count down from z to a then from 9 to 0 */
-               while (cp[len] == '0')
-                       if (!len--)
-                               goto maketemp_out;
-               if (cp[len] == 'a')
-                       cp[len] = '9';
-               else
-                       --cp[len];
-               /* do another cycle */
-       }
+       } while (i < 0);
 
        if (type == TT_FUNSUB) {
                /* map us high and mark as close-on-exec */
index 05729bc..df4a9dc 100644 (file)
@@ -1,6 +1,6 @@
 /*-
- * Copyright © 2011, 2014
- *     Thorsten Glaser <tg@mirbsd.org>
+ * Copyright © 2011, 2014, 2015
+ *     Thorsten “mirabilos” Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
  * are retained or reproduced in an accompanying document, permission
@@ -44,7 +44,7 @@
 
 #include <sys/types.h>
 
-__RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.4 2015/05/30 22:14:06 tg Exp $");
 
 /*-
  * BAFH itself is defined by the following primitives:
@@ -61,7 +61,8 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
  *   the context is (still) zero, adding a NUL byte is not ignored.
  *
  * • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”,
- *   rotated right by “cl” ∈ [0;31]; no casting, be careful!
+ *   rotated right by “cl” ∈ [0; 31] (no casting, be careful!) where
+ *   “eax” must be uint32_t and “cl” an in-range integer.
  *
  * • BAFHFinish(ctx) avalanches the context around so every sub-byte
  *   depends on all input octets; afterwards, the context variable’s
@@ -88,7 +89,7 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
  * • BAFHHostStr(ctx,buf) does the same for C strings.
  *
  * All macros may use ctx multiple times in their expansion, but all
- * other arguments are always evaluated at most once.
+ * other arguments are always evaluated at most once except BAFHror.
  *
  * To stay portable, never use the BAFHHost*() macros (these are for
  * host-local entropy shuffling), and encode numbers using ULEB128.
@@ -206,6 +207,7 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
        } BAFHHost_v;                                           \
                                                                \
        BAFHUpdate_s = (const void *)(s);                       \
+       BAFHHost_v.as_u32 = 0;                                  \
        if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0)         \
                ++BAFHUpdate_s;                                 \
        if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0)         \
index 74bafbe..deb95c3 100644 (file)
@@ -30,7 +30,7 @@
 #include <grp.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219.2.3 2015/03/20 22:21:04 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.238 2015/07/10 19:36:36 tg Exp $");
 
 #define KSH_CHVT_FLAG
 #ifdef MKSH_SMALL
@@ -52,7 +52,7 @@ static const unsigned char *pat_scan(const unsigned char *,
     const unsigned char *, bool) MKSH_A_PURE;
 static int do_gmatch(const unsigned char *, const unsigned char *,
     const unsigned char *, const unsigned char *) MKSH_A_PURE;
-static const unsigned char *cclass(const unsigned char *, unsigned char)
+static const unsigned char *gmatch_cclass(const unsigned char *, unsigned char)
     MKSH_A_PURE;
 #ifdef KSH_CHVT_CODE
 static void chvt(const Getopt *);
@@ -93,12 +93,8 @@ setctypes(const char *s, int t)
 void
 initctypes(void)
 {
-       int c;
-
-       for (c = 'a'; c <= 'z'; c++)
-               chtypes[c] |= C_ALPHA;
-       for (c = 'A'; c <= 'Z'; c++)
-               chtypes[c] |= C_ALPHA;
+       setctypes(letters_uc, C_ALPHA);
+       setctypes(letters_lc, C_ALPHA);
        chtypes['_'] |= C_ALPHA;
        setctypes("0123456789", C_DIGIT);
        /* \0 added automatically */
@@ -126,6 +122,17 @@ Xcheck_grow(XString *xsp, const char *xp, size_t more)
 
 
 #define SHFLAGS_DEFNS
+#define FN(sname,cname,flags,ochar)            \
+       static const struct {                   \
+               /* character flag (if any) */   \
+               char c;                         \
+               /* OF_* */                      \
+               unsigned char optflags;         \
+               /* long name of option */       \
+               char name[sizeof(sname)];       \
+       } shoptione_ ## cname = {               \
+               ochar, flags, sname             \
+       };
 #include "sh_flags.gen"
 
 #define OFC(i) (options[i][-2])
@@ -166,11 +173,11 @@ struct options_info {
        int opts[NELEM(options)];
 };
 
-static char *options_fmt_entry(char *, size_t, unsigned int, const void *);
+static void options_fmt_entry(char *, size_t, unsigned int, const void *);
 static void printoptions(bool);
 
 /* format a single select menu item */
-static char *
+static void
 options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
 {
        const struct options_info *oi = (const struct options_info *)arg;
@@ -178,7 +185,6 @@ options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
        shf_snprintf(buf, buflen, "%-*s %s",
            oi->opt_width, OFN(oi->opts[i]),
            Flag(oi->opts[i]) ? "on" : "off");
-       return (buf);
 }
 
 static void
@@ -545,7 +551,7 @@ getn(const char *s, int *ai)
                if (num.u > 214748364U)
                        /* overflow on multiplication */
                        return (0);
-               num.u = num.u * 10U + (unsigned int)(c - '0');
+               num.u = num.u * 10U + (unsigned int)ksh_numdig(c);
                /* now: num.u <= 2147483649U */
        } while ((c = *s++));
 
@@ -776,7 +782,7 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
                }
                switch (*p++) {
                case '[':
-                       if (sc == 0 || (p = cclass(p, sc)) == NULL)
+                       if (sc == 0 || (p = gmatch_cclass(p, sc)) == NULL)
                                return (0);
                        break;
 
@@ -889,7 +895,7 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
 }
 
 static const unsigned char *
-cclass(const unsigned char *p, unsigned char sub)
+gmatch_cclass(const unsigned char *p, unsigned char sub)
 {
        unsigned char c, d;
        bool notp, found = false;
@@ -1007,7 +1013,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
                const char *arg = argv[go->optind], flag = arg ? *arg : '\0';
 
                go->p = 1;
-               if (flag == '-' && arg[1] == '-' && arg[2] == '\0') {
+               if (flag == '-' && ksh_isdash(arg + 1)) {
                        go->optind++;
                        go->p = 0;
                        go->info |= GI_MINUSMINUS;
@@ -1220,7 +1226,7 @@ print_value_quoted(struct shf *shf, const char *s)
  */
 void
 print_columns(struct shf *shf, unsigned int n,
-    char *(*func)(char *, size_t, unsigned int, const void *),
+    void (*func)(char *, size_t, unsigned int, const void *),
     const void *arg, size_t max_oct, size_t max_colz, bool prefcol)
 {
        unsigned int i, r, c, rows, cols, nspace, max_col;
@@ -1249,17 +1255,20 @@ print_columns(struct shf *shf, unsigned int n,
        str = alloc(max_oct, ATEMP);
 
        /*
-        * We use (max_col + 1) to consider the space separator.
-        * Note that no space is printed after the last column
-        * to avoid problems with terminals that have auto-wrap.
+        * We use (max_col + 2) to consider the separator space.
+        * Note that no spaces are printed after the last column
+        * to avoid problems with terminals that have auto-wrap,
+        * but we need to also take this into account in x_cols.
         */
-       cols = x_cols / (max_col + 1);
+       cols = (x_cols + 1) / (max_col + 2);
 
        /* if we can only print one column anyway, skip the goo */
        if (cols < 2) {
-               for (i = 0; i < n; ++i)
-                       shf_fprintf(shf, "%s\n",
-                           (*func)(str, max_oct, i, arg));
+               for (i = 0; i < n; ++i) {
+                       (*func)(str, max_oct, i, arg);
+                       shf_puts(str, shf);
+                       shf_putc('\n', shf);
+               }
                goto out;
        }
 
@@ -1270,18 +1279,19 @@ print_columns(struct shf *shf, unsigned int n,
        }
 
        nspace = (x_cols - max_col * cols) / cols;
+       if (nspace < 2)
+               nspace = 2;
        max_col = -max_col;
-       if (nspace <= 0)
-               nspace = 1;
        for (r = 0; r < rows; r++) {
                for (c = 0; c < cols; c++) {
-                       i = c * rows + r;
-                       if (i < n) {
-                               shf_fprintf(shf, "%*s", max_col,
-                                   (*func)(str, max_oct, i, arg));
-                               if (c + 1 < cols)
-                                       shf_fprintf(shf, "%*s", nspace, null);
-                       }
+                       if ((i = c * rows + r) >= n)
+                               break;
+                       (*func)(str, max_oct, i, arg);
+                       if (i + rows >= n)
+                               shf_puts(str, shf);
+                       else
+                               shf_fprintf(shf, "%*s%*s",
+                                   max_col, str, nspace, null);
                }
                shf_putchar('\n', shf);
        }
@@ -1402,12 +1412,12 @@ do_realpath(const char *upath)
        /* max. recursion depth */
        int symlinks = 32;
 
-       if (upath[0] == '/') {
+       if (mksh_abspath(upath)) {
                /* upath is an absolute pathname */
                strdupx(ipath, upath, ATEMP);
        } else {
                /* upath is a relative pathname, prepend cwd */
-               if ((tp = ksh_get_wd()) == NULL || tp[0] != '/')
+               if ((tp = ksh_get_wd()) == NULL || !mksh_abspath(tp))
                        return (NULL);
                ipath = shf_smprintf("%s%s%s", tp, "/", upath);
                afree(tp, ATEMP);
@@ -1510,7 +1520,7 @@ do_realpath(const char *upath)
                        tp = shf_smprintf("%s%s%s", ldest, *ip ? "/" : "", ip);
                        afree(ipath, ATEMP);
                        ip = ipath = tp;
-                       if (ldest[0] != '/') {
+                       if (!mksh_abspath(ldest)) {
                                /* symlink target is a relative path */
                                xp = Xrestpos(xs, xp, pos);
                        } else
@@ -1610,7 +1620,7 @@ make_path(const char *cwd, const char *file,
        if (!file)
                file = null;
 
-       if (file[0] == '/') {
+       if (mksh_abspath(file)) {
                *phys_pathp = 0;
                use_cdpath = false;
        } else {
@@ -1627,15 +1637,15 @@ make_path(const char *cwd, const char *file,
                if (!plist)
                        use_cdpath = false;
                else if (use_cdpath) {
-                       char *pend;
+                       char *pend = plist;
 
-                       for (pend = plist; *pend && *pend != ':'; pend++)
-                               ;
+                       while (*pend && *pend != MKSH_PATHSEPC)
+                               ++pend;
                        plen = pend - plist;
                        *cdpathp = *pend ? pend + 1 : NULL;
                }
 
-               if ((!use_cdpath || !plen || plist[0] != '/') &&
+               if ((!use_cdpath || !plen || !mksh_abspath(plist)) &&
                    (cwd && *cwd)) {
                        len = strlen(cwd);
                        XcheckN(*xsp, xp, len);
@@ -1721,7 +1731,7 @@ simplify_path(char *p)
                                continue;
                        else if (len == 2 && tp[1] == '.') {
                                /* parent level, but how? */
-                               if (*p == '/')
+                               if (mksh_abspath(p))
                                        /* absolute path, only one way */
                                        goto strip_last_component;
                                else if (dp > sp) {
@@ -1921,7 +1931,7 @@ c_cd(const char **wp)
                /* Ignore failure (happens if readonly or integer) */
                setstr(oldpwd_s, current_wd, KSH_RETURN_ERROR);
 
-       if (Xstring(xs, xp)[0] != '/') {
+       if (!mksh_abspath(Xstring(xs, xp))) {
                pwd = NULL;
        } else if (!physical) {
                goto norealpath_PWD;
@@ -1999,9 +2009,9 @@ chvt(const Getopt *go)
 #endif
            }
        }
-       if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) {
+       if ((fd = binopen2(dv, O_RDWR)) < 0) {
                sleep(1);
-               if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) {
+               if ((fd = binopen2(dv, O_RDWR)) < 0) {
                        errorf("%s: %s %s", "chvt", "can't open", dv);
                }
        }
@@ -2194,8 +2204,8 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
                wc = 0;
                i = 3;
                while (i--)
-                       if ((c = (*fg)()) >= '0' && c <= '7')
-                               wc = (wc << 3) + (c - '0');
+                       if ((c = (*fg)()) >= ord('0') && c <= ord('7'))
+                               wc = (wc << 3) + ksh_numdig(c);
                        else {
                                (*fp)(c);
                                break;
@@ -2204,13 +2214,13 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
        case 'U':
                i = 8;
                if (/* CONSTCOND */ 0)
-               /* FALLTHROUGH */
+                       /* FALLTHROUGH */
        case 'u':
-               i = 4;
+                 i = 4;
                if (/* CONSTCOND */ 0)
-               /* FALLTHROUGH */
+                       /* FALLTHROUGH */
        case 'x':
-               i = cstyle ? -1 : 2;
+                 i = cstyle ? -1 : 2;
                /**
                 * x:   look for a hexadecimal number with up to
                 *      two (C style: arbitrary) digits; convert
@@ -2221,12 +2231,12 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
                wc = 0;
                while (i--) {
                        wc <<= 4;
-                       if ((c = (*fg)()) >= '0' && c <= '9')
-                               wc += c - '0';
-                       else if (c >= 'A' && c <= 'F')
-                               wc += c - 'A' + 10;
-                       else if (c >= 'a' && c <= 'f')
-                               wc += c - 'a' + 10;
+                       if ((c = (*fg)()) >= ord('0') && c <= ord('9'))
+                               wc += ksh_numdig(c);
+                       else if (c >= ord('A') && c <= ord('F'))
+                               wc += ksh_numuc(c) + 10;
+                       else if (c >= ord('a') && c <= ord('f'))
+                               wc += ksh_numlc(c) + 10;
                        else {
                                wc >>= 4;
                                (*fp)(c);
index 5e41d13..c612c68 100644 (file)
@@ -1,5 +1,5 @@
-.\" $MirOS: src/bin/mksh/mksh.1,v 1.344.2.5 2015/04/12 22:32:30 tg Exp $
-.\" $OpenBSD: ksh.1,v 1.159 2015/03/25 12:10:52 jca Exp $
+.\" $MirOS: src/bin/mksh/mksh.1,v 1.377 2015/07/10 19:35:39 tg Exp $
+.\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $
 .\"-
 .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
 .\"            2010, 2011, 2012, 2013, 2014, 2015
@@ -74,7 +74,7 @@
 .\" with -mandoc, it might implement .Mx itself, but we want to
 .\" use our own definition. And .Dd must come *first*, always.
 .\"
-.Dd $Mdocdate: April 12 2015 $
+.Dd $Mdocdate: July 10 2015 $
 .\"
 .\" Check which macro package we use, and do other -mdoc setup.
 .\"
@@ -476,7 +476,7 @@ and
 .Ql }
 delimit
 .Xr csh 1 Ns -style
-alterations (see
+alternations (see
 .Sx Brace expansion
 below);
 and finally,
@@ -1120,19 +1120,19 @@ also by newline) may be one same parse tree.
 .Pp
 The following command aliases are defined automatically by the shell:
 .Bd -literal -offset indent
-autoload=\*(aqtypeset \-fu\*(aq
-functions=\*(aqtypeset \-f\*(aq
-hash=\*(aqalias \-t\*(aq
-history=\*(aqfc \-l\*(aq
-integer=\*(aqtypeset \-i\*(aq
-local=typeset
-login=\*(aqexec login\*(aq
-nameref=\*(aqtypeset \-n\*(aq
+autoload=\*(aq\etypeset \-fu\*(aq
+functions=\*(aq\etypeset \-f\*(aq
+hash=\*(aq\ebuiltin alias \-t\*(aq
+history=\*(aq\ebuiltin fc \-l\*(aq
+integer=\*(aq\etypeset \-i\*(aq
+local=\*(aq\etypeset\*(aq
+login=\*(aq\eexec login\*(aq
+nameref=\*(aq\etypeset \-n\*(aq
 nohup=\*(aqnohup \*(aq
-r=\*(aqfc \-e \-\*(aq
-source=\*(aqPATH=$PATH:. command .\*(aq
-stop=\*(aqkill \-STOP\*(aq
-type=\*(aqwhence \-v\*(aq
+r=\*(aq\ebuiltin fc \-e \-\*(aq
+source=\*(aqPATH=$PATH:. \ecommand .\*(aq
+stop=\*(aq\ekill \-STOP\*(aq
+type=\*(aq\ebuiltin whence \-v\*(aq
 .Ed
 .Pp
 Tracked aliases allow the shell to remember where it found a particular
@@ -1143,16 +1143,16 @@ The next
 time the command is executed, the shell checks the saved path to see that it
 is still valid, and if so, avoids repeating the path search.
 Tracked aliases can be listed and created using
-.Ic alias \-t .
+.Ic alias Fl t .
 Note that changing the
 .Ev PATH
 parameter clears the saved paths for all tracked aliases.
 If the
 .Ic trackall
 option is set (i.e.\&
-.Ic set \-o Ic trackall
+.Ic set Fl o Ic trackall
 or
-.Ic set \-h ) ,
+.Ic set Fl h ) ,
 the shell tracks all commands.
 This option is set automatically for non-interactive shells.
 For interactive shells, only the following commands are
@@ -1213,7 +1213,7 @@ share their I/O with the parent; instead, they evaluate to whatever
 the, initially empty, expression-local variable
 .Ev REPLY
 is set to within the
-.Ar command Ns No s .
+.Ar command Ns s .
 .Pp
 If a substitution appears outside of double quotes, the results of the
 substitution are generally subject to word or field splitting according to
@@ -1426,7 +1426,7 @@ loops set parameters as well as the
 .Ic getopts ,
 .Ic read ,
 and
-.Ic set \-A
+.Ic set Fl A
 commands.
 Lastly, parameters can be assigned values using assignment operators
 inside arithmetic expressions (see
@@ -1538,7 +1538,9 @@ is not needed, it is not evaluated.
 .Pp
 The following forms of parameter substitution can also be used (if
 .Ar name
-is an array, its element #0 will be substituted in a scalar context):
+is an array, the element with the key
+.Dq 0
+will be substituted in scalar context):
 .Pp
 .Bl -tag -width Ds -compact
 .It Pf ${# Ns Ar name Ns \&}
@@ -1628,7 +1630,7 @@ Cannot be applied to a vector.
 .Pf // Ar pattern / Ar string No }
 .Xc
 .Sm on
-Like ${..#..} substitution, but it replaces the longest match of
+Similar to ${..##..} substitution, but it replaces the longest match of
 .Ar pattern ,
 anchored anywhere in the value, with
 .Ar string .
@@ -1639,17 +1641,17 @@ begins with
 it is anchored at the beginning of the value; if it begins with
 .Ql % ,
 it is anchored at the end.
-Patterns that are empty or consist only of wildcards are invalid.
-A single
+Empty patterns cause no replacement to happen.
+A single leading
 .Ql /
-replaces the first occurence of the search
-.Ar pattern ,
-and two of them replace all occurences.
-If
+or use of a pattern that matches the empty string causes the
+replacement to happen only once; two leading slashes cause
+all occurrences of matches in the value to be replaced.
+If the trailing
 .Pf / Ar string
-is omitted, the
+is omitted, any matches of
 .Ar pattern
-is replaced by the empty string, i.e. deleted.
+are replaced by the empty string, i.e. deleted.
 Cannot be applied to a vector.
 Inefficiently implemented, may be slow.
 .Pp
@@ -1817,9 +1819,9 @@ is non-zero and sane enough (minimum is 12x3); similar for
 .Ev LINES .
 This parameter is used by the interactive line editing modes, and by the
 .Ic select ,
-.Ic set \-o ,
+.Ic set Fl o ,
 and
-.Ic kill \-l
+.Ic kill Fl l
 commands to format information columns.
 Importing from the environment or unsetting this parameter removes the
 binding to the actual terminal size in favour of the provided value.
@@ -1857,7 +1859,8 @@ below for more information.
 .It Ev HISTFILE
 The name of the file used to store command history.
 When assigned to or unset, the file is opened, history is truncated
-then loaded from the file; subsequent new lines are appended.
+then loaded from the file; subsequent new commands (possibly consisting
+of several lines) are appended once they successfully compiled.
 Also, several invocations of the shell will share history if their
 .Ev HISTFILE
 parameters all point to the same file.
@@ -2010,7 +2013,7 @@ You can tell the shell not to count certain
 sequences (such as escape codes) by prefixing your prompt with a
 character (such as Ctrl-A) followed by a carriage return and then delimiting
 the escape codes with this character.
-Any occurences of that character in the prompt are not printed.
+Any occurrences of that character in the prompt are not printed.
 By the way, don't blame me for
 this hack; it's derived from the original
 .Xr ksh88 1 ,
@@ -2140,10 +2143,10 @@ login names are also delimited by colons.
 .Pp
 The home directory of previously expanded login names are cached and re-used.
 The
-.Ic alias \-d
+.Ic alias Fl d
 command may be used to list, change, and add to this cache (e.g.\&
 .Ic alias \-d fac=/usr/local/facilities; cd \*(TIfac/bin ) .
-.Ss Brace expansion (alteration)
+.Ss Brace expansion (alternation)
 Brace expressions take the following form:
 .Bd -unfilled -offset indent
 .Sm off
@@ -2743,9 +2746,9 @@ The non-result argument is not evaluated.
 A co-process (which is a pipeline created with the
 .Sq \*(Ba&
 operator) is an asynchronous process that the shell can both write to (using
-.Ic print \-p )
+.Ic print Fl p )
 and read from (using
-.Ic read \-p ) .
+.Ic read Fl p ) .
 The input and output of the co-process can also be manipulated using
 .Ic \*(Gt&p
 and
@@ -2783,13 +2786,13 @@ different from the original Korn shell which closes its copy of the write
 portion of the co-process output when the most recently started co-process
 (instead of when all sharing co-processes) exits.
 .It
-.Ic print \-p
+.Ic print Fl p
 will ignore
 .Dv SIGPIPE
 signals during writes if the signal is not being trapped or ignored; the same
 is true if the co-process input has been duplicated to another file descriptor
 and
-.Ic print \-u Ns Ar n
+.Ic print Fl u Ns Ar n
 is used.
 .El
 .Ss Functions
@@ -2818,11 +2821,11 @@ An existing function may be deleted using
 A list of functions can be obtained using
 .Ic typeset +f
 and the function definitions can be listed using
-.Ic typeset \-f .
+.Ic typeset Fl f .
 The
 .Ic autoload
 command (which is an alias for
-.Ic typeset \-fu )
+.Ic typeset Fl fu )
 may be used to create undefined functions: when an undefined function is
 executed, the shell searches the path specified in the
 .Ev FPATH
@@ -2843,9 +2846,9 @@ Functions can have two attributes,
 and
 .Dq export ,
 which can be set with
-.Ic typeset \-ft
+.Ic typeset Fl ft
 and
-.Ic typeset \-fx ,
+.Ic typeset Fl fx ,
 respectively.
 When a traced function is executed, the shell's
 .Ic xtrace
@@ -2904,9 +2907,9 @@ inside a function interferes with using
 .Ic getopts
 outside the function).
 .It
-Bourne-style function definitions take precedence over alias dereferences
-and remove alias definitions upon encounter, while aliases take precedence
-over Korn-style functions.
+Shell options
+.Pq Ic set Fl o
+have local scope, i.e. changes inside a function are reset upon its exit.
 .El
 .Pp
 In the future, the following differences may also be added:
@@ -2920,10 +2923,6 @@ trapped) will have their default effect in a function.
 .It
 The EXIT trap, if set in a function, will be executed after the function
 returns.
-.It
-Shell options
-.Pq Ic set Fl o
-have local scope, i.e. changes inside a function are reset upon its exit.
 .El
 .Ss Command execution
 After evaluation of command-line arguments, redirections, and parameter
@@ -3162,15 +3161,13 @@ If a
 is a single dash
 .Pq Sq -
 or absent, read from standard input.
-Unless compiled with
-.Dv MKSH_NO_EXTERNAL_CAT ,
-if any options are given, an external
-.Xr cat 1
-utility is invoked instead if called from the shell.
 For direct builtin calls, the
 .Tn POSIX
 .Fl u
 option is supported as a no-op.
+For calls from shell, if any options are given, an external
+.Xr cat 1
+utility is preferred over the builtin.
 .Pp
 .It Xo
 .Ic cd
@@ -3298,9 +3295,9 @@ option is given, instead of executing
 .Ar cmd ,
 information about what would be executed is given (and the same is done for
 .Ar arg ... ) .
-For special and regular built-in commands and functions, their names are simply
-printed; for aliases, a command that defines them is printed; and for commands
-found by searching the
+For builtins, functions and keywords, their names are simply printed;
+for aliases, a command that defines them is printed;
+for utilities found by searching the
 .Ev PATH
 parameter, the full path of the command is printed.
 If no command is found
@@ -3694,6 +3691,9 @@ and
 See
 .Xr mknod 8
 for further information.
+This is not normally part of
+.Nm mksh ;
+however, distributors may have added this as builtin as a speed hack.
 .Pp
 .It Xo
 .Ic print
@@ -3754,8 +3754,9 @@ Approximately the same as the
 .Xr printf 1 ,
 utility, except it uses the same
 .Sx Backslash expansion
-and I/O code and does hot handle floating point as the rest of
+and I/O code and does not handle floating point as the rest of
 .Nm mksh .
+An external utility is preferred over the builtin.
 This is not normally part of
 .Nm mksh ;
 however, distributors may have added this as builtin as a speed hack.
@@ -3834,7 +3835,8 @@ if empty, instead of the ASCII newline character as input line delimiter.
 .It Fl N Ar z
 Instead of reading till end-of-line, read exactly
 .Ar z
-bytes; less if EOF or a timeout occurs.
+bytes.
+If EOF or a timeout occurs, a partial read is returned with exit status 1.
 .It Fl n Ar z
 Instead of reading till end-of-line, read up to
 .Ar z
@@ -3853,6 +3855,9 @@ The argument must immediately follow the option character.
 Interrupt reading after
 .Ar n
 seconds (specified as positive decimal value with an optional fractional part).
+The exit status of
+.Nm read
+is 1 if the timeout occurred, but partial reads may still be returned.
 .It Fl r
 Normally, the ASCII backslash character escapes the special
 meaning of the following character and is stripped from the input;
@@ -3899,8 +3904,8 @@ option, use of the
 .Fl r
 option might be prudent; the same applies for:
 .Bd -literal -offset indent
-find . \-type f \-print0 \*(Ba \e
-    while IFS= read \-d \*(aq\*(aq \-r filename; do
+find . \-type f \-print0 \*(Ba& \e
+    while IFS= read \-d \*(aq\*(aq \-pr filename; do
        print \-r \-\- "found \*(Lt${filename#./}\*(Gt"
 done
 .Ed
@@ -4040,23 +4045,6 @@ and also supported by
 .Nm ksh93
 is:
 .Ic foo=(a b c); foo+=(d e)
-.Pp
-Another
-.At
-.Nm ksh93
-and
-.Tn GNU
-.Nm bash
-extension allows specifying the indices used for
-.Ar arg ...
-.Pq from the above example, Ic a b c
-like this:
-.Ic set \-A foo \-\- [0]=a [1]=b [2]=c
-or
-.Ic foo=([0]=a [1]=b [2]=c)
-which can also be written
-.Ic foo=([0]=a b c)
-because indices are incremented automatically.
 .It Fl a \*(Ba Fl o Ic allexport
 All new parameters are created with the export attribute.
 .It Fl b \*(Ba Fl o Ic notify
@@ -4652,54 +4640,60 @@ The format of the output is:
 0m0.00s 0m0.00s
 .Ed
 .Pp
+.It Ic trap Ar n Op Ar signal ...
+If the first operand is a decimal unsigned integer, this resets all
+specified signals to the default action, i.e. is the same as calling
+.Ic trap
+with a minus sign
+.Pq Sq \-
+as
+.Ar handler ,
+followed by the arguments
+.Pq Ar n Op Ar signal ... ,
+all of which are treated as signals.
+.Pp
 .It Ic trap Op Ar handler signal ...
-Sets a trap handler that is to be executed when any of the specified signals are
-received.
+Sets a trap handler that is to be executed when any of the specified
+.Ar signal Ns s
+are received.
 .Ar handler
-is either a
-.Dv NULL
-string, indicating the signals are to be ignored, a minus sign
+is either an empty string, indicating the signals are to be ignored,
+a minus sign
 .Pq Sq \- ,
-indicating that the default action is to be taken for the signals (see
-.Xr signal 3 ) ,
-or a string containing shell commands to be evaluated and executed at the first
-opportunity (i.e. when the current command completes, or before printing the
-next
+indicating that the default action is to be taken for the signals
+.Pq see Xr signal 3 ,
+or a string containing shell commands to be executed at the first opportunity
+(i.e. when the current command completes, or before printing the next
 .Ev PS1
 prompt) after receipt of one of the signals.
 .Ar signal
-is the name of a signal (e.g.\&
-.Dv PIPE
-or
-.Dv ALRM )
+is the name of a signal
+.Pq e.g.\& Dv PIPE or Dv ALRM
 or the number of the signal (see the
-.Ic kill \-l
+.Ic kill Fl l
 command above).
 .Pp
 There are two special signals:
 .Dv EXIT
-(also known as 0) which is executed when the shell is about to exit, and
+.Pq also known as 0 ,
+which is executed when the shell is about to exit, and
 .Dv ERR ,
-which is executed after an error occurs (an error is something that would cause
-the shell to exit if the
-.Fl e
+which is executed after an error occurs; an error is something
+that would cause the shell to exit if the
+.Ic set Fl e
 or
-.Ic errexit
-option were set \*(en see the
-.Ic set
-command above).
+.Ic set Fl o Ic errexit
+option were set.
 .Dv EXIT
 handlers are executed in the environment of the last executed command.
-Note
-that for non-interactive shells, the trap handler cannot be changed for signals
-that were ignored when the shell started.
 .Pp
-With no arguments,
-.Ic trap
-lists, as a series of
+Note that, for non-interactive shells, the trap handler cannot be changed
+for signals that were ignored when the shell started.
+.Pp
+With no arguments, the current state of the traps that have been set since
+the shell started is shown as a series of
 .Ic trap
-commands, the current state of the traps that have been set since the shell
-started.
+commands.
 Note that the output of
 .Ic trap
 cannot be usefully piped to another process (an artifact of the fact that
@@ -5109,7 +5103,7 @@ The exit status of
 .Ic wait
 is that of the last specified job; if the last job is killed by a signal, the
 exit status is 128 + the number of the signal (see
-.Ic kill \-l Ar exit-status
+.Ic kill Fl l Ar exit-status
 above); if the last specified job can't be found (because it never existed, or
 had already finished), the exit status of
 .Ic wait
@@ -5180,9 +5174,9 @@ using the
 .Ic jobs
 commands.
 If job control is fully enabled (using
-.Ic set \-m
+.Ic set Fl m
 or
-.Ic set \-o monitor ) ,
+.Ic set Fl o Ic monitor ) ,
 as it is for interactive shells, the processes of a job are placed in their
 own process group.
 Foreground jobs can be stopped by typing the suspend
@@ -5277,7 +5271,7 @@ The job was stopped by the indicated
 .Dv SIGTSTP ) .
 .It Ar signal-description Op Dq core dumped
 The job was killed by a signal (e.g. memory fault, hangup); use
-.Ic kill \-l
+.Ic kill Fl l
 for a list of signal descriptions.
 The
 .Dq core dumped
@@ -5404,7 +5398,7 @@ Simply causes the character to appear as literal input.
 Most ordinary characters are bound to this.
 .It Xo backward\-char:
 .Op Ar n
-.No \*(haB , \*(haXD , ANSI-CurLeft
+.No \*(haB , \*(haXD , ANSI-CurLeft , PC-CurLeft
 .Xc
 Moves the cursor backward
 .Ar n
@@ -5421,7 +5415,7 @@ and dollar sign
 characters.
 .It beginning\-of\-history: \*(ha[\*(Lt
 Moves to the beginning of the history.
-.It beginning\-of\-line: \*(haA, ANSI-Home
+.It beginning\-of\-line: \*(haA, ANSI-Home, PC-Home
 Moves the cursor to the beginning of the edited input line.
 .It Xo capitalise\-word:
 .Op Ar n
@@ -5477,7 +5471,7 @@ Deletes
 characters before the cursor.
 .It Xo delete\-char\-forward:
 .Op Ar n
-.No ANSI-Del
+.No ANSI-Del , PC-Del
 .Xc
 Deletes
 .Ar n
@@ -5498,7 +5492,7 @@ Deletes characters after the cursor up to the end of
 words.
 .It Xo down\-history:
 .Op Ar n
-.No \*(haN , \*(haXB , ANSI-CurDown
+.No \*(haN , \*(haXB , ANSI-CurDown , PC-CurDown
 .Xc
 Scrolls the history buffer forward
 .Ar n
@@ -5530,7 +5524,7 @@ The actual command executed is
 .Ic fc \-e ${VISUAL:\-${EDITOR:\-vi}} Ar n .
 .It end\-of\-history: \*(ha[\*(Gt
 Moves to the end of the history.
-.It end\-of\-line: \*(haE, ANSI-End
+.It end\-of\-line: \*(haE, ANSI-End, PC-End
 Moves the cursor to the end of the input line.
 .It eot: \*(ha_
 Acts as an end-of-file; this is useful because edit-mode input disables
@@ -5555,7 +5549,7 @@ globbing on the word.
 If no files match the pattern, the bell is rung.
 .It Xo forward\-char:
 .Op Ar n
-.No \*(haF , \*(haXC , ANSI-CurRight
+.No \*(haF , \*(haXC , ANSI-CurRight , PC-CurRight
 .Xc
 Moves the cursor forward
 .Ar n
@@ -5669,12 +5663,12 @@ commands continue searching backward to the next previous occurrence of the
 pattern.
 The history buffer retains only a finite number of lines; the oldest
 are discarded as necessary.
-.It search\-history\-up: ANSI-PgUp
+.It search\-history\-up: ANSI-PgUp, PC-PgUp
 Search backwards through the history buffer for commands whose beginning match
 the portion of the input line before the cursor.
 When used on an empty line, this has the same effect as
 .Ic up\-history .
-.It search\-history\-down: ANSI-PgDn
+.It search\-history\-down: ANSI-PgDn, PC-PgDn
 Search forwards through the history buffer for commands whose beginning match
 the portion of the input line before the cursor.
 When used on an empty line, this has the same effect as
@@ -5694,7 +5688,7 @@ exchanges the previous and current characters and moves the cursor one
 character to the right.
 .It Xo up\-history:
 .Op Ar n
-.No \*(haP , \*(haXA , ANSI-CurUp
+.No \*(haP , \*(haXA , ANSI-CurUp , PC-CurUp
 .Xc
 Scrolls the history buffer backward
 .Ar n
@@ -5806,7 +5800,7 @@ Puts the editor in command mode (see below).
 Optional file name and command completion (see
 .Ic \*(haF
 above), enabled with
-.Ic set \-o vi\-tabcomplete .
+.Ic set Fl o Ic vi\-tabcomplete .
 .El
 .Pp
 In command mode, each character is interpreted as a command.
@@ -5919,7 +5913,7 @@ option is set, while
 is only recognised if the
 .Ic vi\-esccomplete
 option is set (see
-.Ic set \-o ) .
+.Ic set Fl o ) .
 If
 .Ar n
 is specified, the
@@ -6122,7 +6116,7 @@ Search for the
 .Ar n Ns th
 occurrence of the last search string;
 the direction of the search is the opposite of the last search.
-.It Ar ANSI-CurUp
+.It Ar ANSI-CurUp , PC-PgUp
 Take the characters from the beginning of the line to the current
 cursor position as search string and do a backwards history search
 for lines beginning with this string; keep the cursor position.
@@ -6273,6 +6267,8 @@ times.
 Undo the last edit command.
 .It U
 Undo all changes that have been made to the current line.
+.It PC Home, End, Del, and cursor keys
+They move as expected, both in insert and command mode.
 .It Ar intr No and Ar quit
 The interrupt and quit terminal characters cause the current line to be
 deleted and a new prompt to be printed.
@@ -6445,9 +6441,6 @@ The complete legalese is at:
 .\"
 .Sh CAVEATS
 .Nm
-only supports the Unicode BMP (Basic Multilingual Plane).
-.Pp
-.Nm
 has a different scope model from
 .At
 .Nm ksh ,
@@ -6479,7 +6472,7 @@ delete all files on your system, as it's Undefined Behaviour.
 provides a consistent, clear interface normally.
 This may deviate from POSIX in optional or opinionated places, such
 as whether leading-digit-zero numbers should be interpreted as octal.
-.Ic set \-o posix
+.Ic set Fl o Ic posix
 will cause the shell (either
 .Nm mksh
 or
@@ -6492,8 +6485,20 @@ For the purpose of
 supports only the
 .Dq C
 locale.
-For users of UTF-8 locales, the following sh code makes the shell
-match the locale:
+.Nm mksh Ns 's
+.Ic utf8\-mode
+only supports the Unicode BMP (Basic Multilingual Plane) and maps
+raw octets into the U+EF80..U+EFFF wide character range; compare
+.Sx Arithmetic expressions .
+The following
+.Tn POSIX
+.Nm sh
+code toggles the
+.Ic utf8\-mode
+option dependent on the current
+.Tn POSIX
+locale for mksh to allow using the UTF-8 mode, within the constraints
+outlined above, in code portable across various shell implementations:
 .Bd -literal -offset indent
 case ${KSH_VERSION:\-} in
 *MIRBSD\ KSH*\*(Ba*LEGACY\ KSH*)
@@ -6526,7 +6531,7 @@ for the in-memory portion of the history is slow, should use
 .Xr memmove 3 .
 .Pp
 This document attempts to describe
-.Nm mksh\ R50e
+.Nm mksh\ R51
 and up,
 .\" with vendor patches from insert-your-name-here,
 compiled without any options impacting functionality, such as
@@ -6534,9 +6539,9 @@ compiled without any options impacting functionality, such as
 when not called as
 .Pa /bin/sh
 which, on some systems only, enables
-.Ic set \-o posix
+.Ic set Fl o Ic posix
 or
-.Ic set \-o sh
+.Ic set Fl o Ic sh
 automatically (whose behaviour differs across targets),
 for an operating environment supporting all of its advanced needs.
 .Pp
index ef71dab..ddb4cc8 100644 (file)
@@ -1,19 +1,8 @@
 #ifndef RLIMITS_OPTCS
 #if defined(RLIMITS_DEFNS)
-__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.1 2013/11/17 22:21:18 tg Exp $");
-struct limits {
-       /* limit resource */
-       int resource;
-       /* multiply by to get rlim_{cur,max} values */
-       unsigned int factor;
-       /* getopts char */
-       char optchar;
-       /* limit name */
-       char name[1];
-};
-#define FN(lname,lid,lfac,lopt)                                        static const struct {                                           int resource;                                           unsigned int factor;                                    char optchar;                                           char name[sizeof(lname)];                       } rlimits_ ## lid = {                                           lid, lfac, lopt, lname                          };
+__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.2 2015/05/01 23:16:31 tg Exp $");
 #elif defined(RLIMITS_ITEMS)
-#define FN(lname,lid,lfac,lopt)                                        (const struct limits *)(&rlimits_ ## lid),
+#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
 #endif
 #ifndef F0
 #define F0 FN
index 6c3908b..3759da8 100644 (file)
@@ -1,18 +1,7 @@
 @RLIMITS_DEFNS
-__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.1 2013/11/17 22:21:18 tg Exp $");
-struct limits {
-       /* limit resource */
-       int resource;
-       /* multiply by to get rlim_{cur,max} values */
-       unsigned int factor;
-       /* getopts char */
-       char optchar;
-       /* limit name */
-       char name[1];
-};
-#define FN(lname,lid,lfac,lopt)                                        static const struct {                                           int resource;                                           unsigned int factor;                                    char optchar;                                           char name[sizeof(lname)];                       } rlimits_ ## lid = {                                           lid, lfac, lopt, lname                          };
+__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.2 2015/05/01 23:16:31 tg Exp $");
 @RLIMITS_ITEMS
-#define FN(lname,lid,lfac,lopt)                                        (const struct limits *)(&rlimits_ ## lid),
+#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
 @@
 
 /* generic options for the ulimit builtin */
index 91f8961..c3109e5 100644 (file)
--- a/src/sh.h
+++ b/src/sh.h
@@ -64,6 +64,9 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#if HAVE_IO_H
+#include <io.h>
+#endif
 #if HAVE_LIBGEN_H
 #include <libgen.h>
 #endif
 #endif
 
 #ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.701.2.7 2015/04/19 19:18:21 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.739 2015/07/10 19:36:37 tg Exp $");
 #endif
-#define MKSH_VERSION "R50 2015/04/19"
+#define MKSH_VERSION "R51 2015/07/10"
 
 /* arithmetic types: C implementation */
 #if !HAVE_CAN_INTTYPES
@@ -253,7 +256,8 @@ typedef MKSH_TYPEDEF_SSIZE_T ssize_t;
 
 /* extra types */
 
-#if !HAVE_GETRUSAGE
+/* getrusage does not exist on OS/2 kLIBC */
+#if !HAVE_GETRUSAGE && !defined(__OS2__)
 #undef rusage
 #undef RUSAGE_SELF
 #undef RUSAGE_CHILDREN
@@ -298,16 +302,6 @@ struct rusage {
        } while (/* CONSTCOND */ 0)
 #endif
 
-#define ksh_isdigit(c) (((c) >= '0') && ((c) <= '9'))
-#define ksh_islower(c) (((c) >= 'a') && ((c) <= 'z'))
-#define ksh_isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
-#define ksh_tolower(c) (((c) >= 'A') && ((c) <= 'Z') ? (c) - 'A' + 'a' : (c))
-#define ksh_toupper(c) (((c) >= 'a') && ((c) <= 'z') ? (c) - 'a' + 'A' : (c))
-#define ksh_isdash(s)  (((s)[0] == '-') && ((s)[1] == '\0'))
-#define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20))
-#define ksh_min(x,y)   ((x) < (y) ? (x) : (y))
-#define ksh_max(x,y)   ((x) > (y) ? (x) : (y))
-
 #ifdef MKSH__NO_PATH_MAX
 #undef PATH_MAX
 #else
@@ -339,29 +333,69 @@ struct rusage {
 #define DEFFILEMODE    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
 #endif
 
-#ifndef NSIG
-#if defined(_NSIG)
-#define NSIG           _NSIG
+
+/* determine ksh_NSIG: first, use the traditional definitions */
+#undef ksh_NSIG
+#if defined(NSIG)
+#define ksh_NSIG NSIG
+#elif defined(_NSIG)
+#define ksh_NSIG _NSIG
 #elif defined(SIGMAX)
-#define NSIG           (SIGMAX+1)
+#define ksh_NSIG (SIGMAX + 1)
 #elif defined(_SIGMAX)
-#define NSIG           (_SIGMAX+1)
+#define ksh_NSIG (_SIGMAX + 1)
+#elif defined(NSIG_MAX)
+#define ksh_NSIG NSIG_MAX
 #else
 # error Please have your platform define NSIG.
-#define NSIG           64
 #endif
-#endif
-
-/* get rid of this (and awk/printf(1) in Build.sh) later */
-#if (NSIG < 1)
+/* range-check them */
+#if (ksh_NSIG < 1)
 # error Your NSIG value is not positive.
-#unset NSIG
-#define NSIG           64
+#undef ksh_NSIG
+#endif
+/* second, see if the new POSIX definition is available */
+#ifdef NSIG_MAX
+#if (NSIG_MAX < 2)
+/* and usable */
+# error Your NSIG_MAX value is too small.
+#undef NSIG_MAX
+#elif (ksh_NSIG > NSIG_MAX)
+/* and realistic */
+# error Your NSIG value is larger than your NSIG_MAX value.
+#undef NSIG_MAX
+#else
+/* since it’s usable, prefer it */
+#undef ksh_NSIG
+#define ksh_NSIG NSIG_MAX
+#endif
+/* if NSIG_MAX is now still defined, use sysconf(_SC_NSIG) at runtime */
+#endif
+/* third, for cpp without the error directive, default */
+#ifndef ksh_NSIG
+#define ksh_NSIG 64
 #endif
 
 
 /* OS-dependent additions (functions, variables, by OS) */
 
+#ifdef MKSH_EXE_EXT
+#undef MKSH_EXE_EXT
+#define MKSH_EXE_EXT   ".exe"
+#else
+#define MKSH_EXE_EXT   ""
+#endif
+
+#ifdef __OS2__
+#define MKSH_PATHSEPS  ";"
+#define MKSH_PATHSEPC  ';'
+#define MKSH_UNIXROOT  "/@unixroot"
+#else
+#define MKSH_PATHSEPS  ":"
+#define MKSH_PATHSEPC  ':'
+#define MKSH_UNIXROOT  ""
+#endif
+
 #if !HAVE_FLOCK_DECL
 extern int flock(int, int);
 #endif
@@ -476,6 +510,8 @@ EXTERN const char initvsn[] E_INIT("KSH_VERSION=@(#)" KSH_VERSIONNAME \
 
 EXTERN const char digits_uc[] E_INIT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 EXTERN const char digits_lc[] E_INIT("0123456789abcdefghijklmnopqrstuvwxyz");
+#define letters_uc (digits_uc + 10)
+#define letters_lc (digits_lc + 10)
 
 /*
  * Evil hack for const correctness due to API brokenness
@@ -537,7 +573,7 @@ char *ucstrstr(char *, const char *);
 #define mkssert(e)     do { } while (/* CONSTCOND */ 0)
 #endif
 
-#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 506)
+#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 511)
 #error Must run Build.sh to compile this.
 extern void thiswillneverbedefinedIhope(void);
 int
@@ -802,18 +838,19 @@ EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes");
 EXTERN const char Tsynerr[] E_INIT("syntax error");
 #endif
 EXTERN const char Tselect[] E_INIT("select");
-EXTERN const char Tr_fc_e_dash[] E_INIT("r=fc -e -");
-#define Tfc_e_dash     (Tr_fc_e_dash + 2)      /* "fc -e -" */
-#define Zfc_e_dash     7                       /* strlen(Tfc_e_dash) */
-EXTERN const char Tlocal_typeset[] E_INIT("local=typeset");
-#define T_typeset      (Tlocal_typeset + 5)    /* "=typeset" */
-#define Ttypeset       (Tlocal_typeset + 6)    /* "typeset" */
+EXTERN const char T_typeset[] E_INIT("=typeset");
+#define Ttypeset       (T_typeset + 1)         /* "typeset" */
 EXTERN const char Talias[] E_INIT("alias");
 EXTERN const char Tunalias[] E_INIT("unalias");
+EXTERN const char Tcat[] E_INIT("cat");
+#ifdef __OS2__
+EXTERN const char Textproc[] E_INIT("extproc");
+#endif
+#ifdef MKSH_PRINTF_BUILTIN
+EXTERN const char Tprintf[] E_INIT("printf");
+#endif
 EXTERN const char Tsgset[] E_INIT("*=set");
 #define Tset           (Tsgset + 2)            /* "set" */
-EXTERN const char Tsgunset[] E_INIT("*=unset");
-#define Tunset         (Tsgunset + 2)          /* "unset" */
 EXTERN const char Tsgexport[] E_INIT("*=export");
 #define Texport                (Tsgexport + 2)         /* "export" */
 EXTERN const char Tsgreadonly[] E_INIT("*=readonly");
@@ -892,13 +929,13 @@ typedef struct trap {
 #define SS_USER                BIT(4)  /* user is doing the set (ie, trap command) */
 #define SS_SHTRAP      BIT(5)  /* trap for internal use (ALRM, CHLD, WINCH) */
 
-#define ksh_SIGEXIT    0       /* for trap EXIT */
-#define ksh_SIGERR     NSIG    /* for trap ERR */
+#define ksh_SIGEXIT 0          /* for trap EXIT */
+#define ksh_SIGERR  ksh_NSIG   /* for trap ERR */
 
 EXTERN volatile sig_atomic_t trap;     /* traps pending? */
 EXTERN volatile sig_atomic_t intrsig;  /* pending trap interrupts command */
 EXTERN volatile sig_atomic_t fatal_trap; /* received a fatal signal */
-extern Trap    sigtraps[NSIG+1];
+extern Trap sigtraps[ksh_NSIG + 1];
 
 /* got_winch = 1 when we need to re-adjust the window size */
 #ifdef SIGWINCH
@@ -940,8 +977,20 @@ extern unsigned char chtypes[];
 #define ctype(c, t)    tobool( ((t) == C_SUBOP2) ?                     \
                            (((c) == '#' || (c) == '%') ? 1 : 0) :      \
                            (chtypes[(unsigned char)(c)] & (t)) )
+#define ord(c)         ((int)(unsigned char)(c))
 #define ksh_isalphx(c) ctype((c), C_ALPHA)
 #define ksh_isalnux(c) ctype((c), C_ALPHA | C_DIGIT)
+#define ksh_isdigit(c) (((c) >= '0') && ((c) <= '9'))
+#define ksh_islower(c) (((c) >= 'a') && ((c) <= 'z'))
+#define ksh_isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
+#define ksh_tolower(c) (ksh_isupper(c) ? (c) - 'A' + 'a' : (c))
+#define ksh_toupper(c) (ksh_islower(c) ? (c) - 'a' + 'A' : (c))
+#define ksh_isdash(s)  (((s)[0] == '-') && ((s)[1] == '\0'))
+#define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20))
+#define ksh_eq(c,u,l)  (((c) | 0x20) == (l))
+#define ksh_numdig(c)  ((c) - ord('0'))
+#define ksh_numuc(c)   ((c) - ord('A'))
+#define ksh_numlc(c)   ((c) - ord('a'))
 
 EXTERN int ifs0 E_INIT(' ');   /* for "$*" */
 
@@ -1604,6 +1653,13 @@ EXTERN char **history;           /* saved commands */
 EXTERN char **histptr;         /* last history item */
 EXTERN mksh_ari_t histsize;    /* history size */
 
+/* flags to histsave */
+#define HIST_FLUSH     0
+#define HIST_QUEUE     1
+#define HIST_APPEND    2
+#define HIST_STORE     3
+#define HIST_NOTE      4
+
 /* user and system time of last j_waitjed job */
 EXTERN struct timeval j_usrtime, j_systime;
 
@@ -1730,7 +1786,7 @@ void hist_init(Source *);
 #if HAVE_PERSISTENT_HISTORY
 void hist_finish(void);
 #endif
-void histsave(int *, const char *, bool, bool);
+void histsave(int *, const char *, int, bool);
 #if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
 bool histsync(void);
 #endif
@@ -1747,7 +1803,7 @@ int findhist(int, int, const char *, bool) MKSH_A_PURE;
 char **hist_get_newest(bool);
 void inittraps(void);
 void alarm_init(void);
-Trap *gettrap(const char *, bool);
+Trap *gettrap(const char *, bool, bool);
 void trapsig(int);
 void intrcheck(void);
 int fatal_trap_check(void);
@@ -1873,7 +1929,7 @@ int ksh_getopt(const char **, Getopt *, const char *);
 void print_value_quoted(struct shf *, const char *);
 char *quote_value(const char *);
 void print_columns(struct shf *, unsigned int,
-    char *(*)(char *, size_t, unsigned int, const void *),
+    void (*)(char *, size_t, unsigned int, const void *),
     const void *, size_t, size_t, bool);
 void strip_nuls(char *, size_t)
     MKSH_A_BOUNDED(__string__, 1, 2);
@@ -2038,6 +2094,33 @@ EXTERN bool tty_hasstate;        /* true if tty_state is valid */
 
 extern int tty_init_fd(void);  /* initialise tty_fd, tty_devtty */
 
+#ifdef __OS2__
+#ifndef __GNUC__
+# error oops?
+#endif
+#define binopen2(path,flags)           __extension__({                 \
+       int binopen2_fd = open((path), (flags) | O_BINARY);             \
+       if (binopen2_fd >= 0)                                           \
+               setmode(binopen2_fd, O_BINARY);                         \
+       (binopen2_fd);                                                  \
+})
+#define binopen3(path,flags,mode)      __extension__({                 \
+       int binopen3_fd = open((path), (flags) | O_BINARY, (mode));     \
+       if (binopen3_fd >= 0)                                           \
+               setmode(binopen3_fd, O_BINARY);                         \
+       (binopen3_fd);                                                  \
+})
+#define mksh_abspath(s)                        __extension__({                 \
+       const char *mksh_abspath_s = (s);                               \
+       (mksh_abspath_s[0] == '/' || (ksh_isalphx(mksh_abspath_s[0]) && \
+           mksh_abspath_s[1] == ':'));                                 \
+})
+#else
+#define binopen2(path,flags)           open((path), (flags) | O_BINARY)
+#define binopen3(path,flags,mode)      open((path), (flags) | O_BINARY, (mode))
+#define mksh_abspath(s)                        ((s)[0] == '/')
+#endif
+
 /* be sure not to interfere with anyone else's idea about EXTERN */
 #ifdef EXTERN_DEFINED
 # undef EXTERN_DEFINED
index cff2e87..7cd0882 100644 (file)
@@ -1,12 +1,11 @@
 #ifndef SHFLAGS_OPTCS
 #if defined(SHFLAGS_DEFNS)
-__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.2 2014/06/09 12:28:19 tg Exp $");
-#define FN(sname,cname,flags,ochar)                    static const struct {                                   /* character flag (if any) */                   char c;                                         /* OF_* */                                      unsigned char optflags;                         /* long name of option */                       char name[sizeof(sname)];               } shoptione_ ## cname = {                               ochar, flags, sname                     };
+__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.3 2015/05/01 23:16:31 tg Exp $");
 #elif defined(SHFLAGS_ENUMS)
 #define FN(sname,cname,flags,ochar)    cname,
 #define F0(sname,cname,flags,ochar)    cname = 0,
 #elif defined(SHFLAGS_ITEMS)
-#define FN(sname,cname,flags,ochar)            ((const char *)(&shoptione_ ## cname)) + 2,
+#define FN(sname,cname,flags,ochar)    ((const char *)(&shoptione_ ## cname)) + 2,
 #endif
 #ifndef F0
 #define F0 FN
index 99e4a22..1d592c5 100644 (file)
@@ -1,11 +1,10 @@
 @SHFLAGS_DEFNS
-__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.2 2014/06/09 12:28:19 tg Exp $");
-#define FN(sname,cname,flags,ochar)                    static const struct {                                   /* character flag (if any) */                   char c;                                         /* OF_* */                                      unsigned char optflags;                         /* long name of option */                       char name[sizeof(sname)];               } shoptione_ ## cname = {                               ochar, flags, sname                     };
+__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.3 2015/05/01 23:16:31 tg Exp $");
 @SHFLAGS_ENUMS
 #define FN(sname,cname,flags,ochar)    cname,
 #define F0(sname,cname,flags,ochar)    cname = 0,
 @SHFLAGS_ITEMS
-#define FN(sname,cname,flags,ochar)            ((const char *)(&shoptione_ ## cname)) + 2,
+#define FN(sname,cname,flags,ochar)    ((const char *)(&shoptione_ ## cname)) + 2,
 @@
 
 /* special cases */
index cc30442..1c9e3d5 100644 (file)
--- a/src/shf.c
+++ b/src/shf.c
@@ -25,7 +25,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62.2.2 2015/03/01 15:43:07 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.66 2015/07/09 20:52:43 tg Exp $");
 
 /* flags to shf_emptybuf() */
 #define EB_READSW      0x01    /* about to switch to reading */
@@ -62,7 +62,7 @@ shf_open(const char *name, int oflags, int mode, int sflags)
        shf->flags = SHF_ALLOCS;
        /* Rest filled in by reopen. */
 
-       fd = open(name, oflags | O_BINARY, mode);
+       fd = binopen3(name, oflags, mode);
        if (fd < 0) {
                eno = errno;
                afree(shf, shf->areap);
@@ -847,11 +847,11 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
                        if (ksh_isdigit(c)) {
                                bool overflowed = false;
 
-                               tmp = c - '0';
+                               tmp = ksh_numdig(c);
                                while (c = *fmt++, ksh_isdigit(c)) {
                                        if (notok2mul(2147483647, tmp, 10))
                                                overflowed = true;
-                                       tmp = tmp * 10 + c - '0';
+                                       tmp = tmp * 10 + ksh_numdig(c);
                                }
                                --fmt;
                                if (overflowed)
@@ -872,7 +872,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
                        /* nasty format */
                        break;
 
-               if (c >= 'A' && c <= 'Z') {
+               if (ksh_isupper(c)) {
                        flags |= FL_UPPER;
                        c = ksh_tolower(c);
                }
@@ -917,7 +917,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
                                /* FALLTHROUGH */
                        case 'u':
                                do {
-                                       *--cp = lnum % 10 + '0';
+                                       *--cp = digits_lc[lnum % 10];
                                        lnum /= 10;
                                } while (lnum);
 
@@ -933,7 +933,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
 
                        case 'o':
                                do {
-                                       *--cp = (lnum & 0x7) + '0';
+                                       *--cp = digits_lc[lnum & 0x7];
                                        lnum >>= 3;
                                } while (lnum);
 
@@ -945,7 +945,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
                                const char *digits = (flags & FL_UPPER) ?
                                    digits_uc : digits_lc;
                                do {
-                                       *--cp = digits[lnum & 0xf];
+                                       *--cp = digits[lnum & 0xF];
                                        lnum >>= 4;
                                } while (lnum);
 
@@ -1013,7 +1013,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
                                                s++;
                                                nwritten++;
                                                if (--precision > 0 &&
-                                                   (*s | 0x20) == 'x') {
+                                                   ksh_eq(*s, 'X', 'x')) {
                                                        shf_putc(*s, shf);
                                                        s++;
                                                        precision--;
@@ -1025,8 +1025,10 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
                                        c = flags & FL_ZERO ? '0' : ' ';
                                if (field < 0) {
                                        nwritten += -field;
-                                       for ( ; field < 0 ; field++)
+                                       while (field < 0) {
                                                shf_putc(c, shf);
+                                               ++field;
+                                       }
                                }
                        } else
                                c = ' ';
index 67a8ed7..dafeda9 100644 (file)
--- a/src/syn.c
+++ b/src/syn.c
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94.2.3 2015/04/12 22:32:35 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.101 2015/04/29 20:07:35 tg Exp $");
 
 struct nesting_state {
        int start_token;        /* token than began nesting (eg, FOR) */
@@ -214,10 +214,10 @@ synio(int cf)
 
                if (iop->unit > 9) {
                        *cp++ = CHAR;
-                       *cp++ = '0' + (iop->unit / 10);
+                       *cp++ = digits_lc[iop->unit / 10];
                }
                *cp++ = CHAR;
-               *cp++ = '0' + (iop->unit % 10);
+               *cp++ = digits_lc[iop->unit % 10];
                *cp = EOS;
 
                iop->ioflag &= ~IOBASH;
@@ -243,10 +243,10 @@ nested(int type, int smark, int emark)
 }
 
 static const char let_cmd[] = {
-       CHAR, 'l', CHAR, 'e', CHAR, 't', CHAR, ']', EOS
+       QCHAR, 'l', CHAR, 'e', CHAR, 't', CHAR, ']', EOS
 };
 static const char setA_cmd0[] = {
-       CHAR, 's', CHAR, 'e', CHAR, 't', EOS
+       QCHAR, 's', CHAR, 'e', CHAR, 't', EOS
 };
 static const char setA_cmd1[] = {
        CHAR, '-', CHAR, 'A', EOS
@@ -712,7 +712,7 @@ function_body(char *name,
                /* (2 * sizeof(char *)) is small enough */
                t->left->args = alloc(2 * sizeof(char *), ATEMP);
                t->left->args[0] = tv = alloc(3, ATEMP);
-               tv[0] = CHAR;
+               tv[0] = QCHAR;
                tv[1] = ':';
                tv[2] = EOS;
                t->left->args[1] = NULL;
@@ -1074,7 +1074,8 @@ parse_usec(const char *s, struct timeval *tv)
        tv->tv_sec = 0;
        /* parse integral part */
        while (ksh_isdigit(*s)) {
-               tt.tv_sec = tv->tv_sec * 10 + (*s++ - '0');
+               tt.tv_sec = tv->tv_sec * 10 + ksh_numdig(*s++);
+               /*XXX this overflow check maybe UB */
                if (tt.tv_sec / 10 != tv->tv_sec) {
                        errno = EOVERFLOW;
                        return (true);
@@ -1095,7 +1096,7 @@ parse_usec(const char *s, struct timeval *tv)
        /* parse decimal fraction */
        i = 100000;
        while (ksh_isdigit(*s)) {
-               tv->tv_usec += i * (*s++ - '0');
+               tv->tv_usec += i * ksh_numdig(*s++);
                if (i == 1)
                        break;
                i /= 10;
index 3a79c15..c057559 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.72.2.1 2015/04/12 22:32:35 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.73 2015/04/11 22:03:32 tg Exp $");
 
 #define INDENT 8
 
index f4da69a..428192c 100644 (file)
--- a/src/var.c
+++ b/src/var.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: var.c,v 1.38 2013/12/20 17:53:09 zhuk Exp $   */
+/*     $OpenBSD: var.c,v 1.41 2015/04/17 17:20:41 deraadt Exp $        */
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@@ -28,7 +28,7 @@
 #include <sys/sysctl.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183.2.4 2015/04/19 19:18:23 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var.c,v 1.193 2015/07/10 19:36:38 tg Exp $");
 
 /*-
  * Variables
@@ -510,7 +510,7 @@ getint(struct tbl *vp, mksh_ari_u *nump, bool arith)
        }
 
        if (c == '0' && arith) {
-               if ((s[0] | 0x20) == 'x') {
+               if (ksh_eq(s[0], 'X', 'x')) {
                        /* interpret as hexadecimal */
                        base = 16;
                        ++s;
@@ -547,19 +547,19 @@ getint(struct tbl *vp, mksh_ari_u *nump, bool arith)
                                nump->u = (mksh_uari_t)wc;
                                return (1);
                        } else if (base > 36)
-                               return (-1);
+                               base = 10;
                        num = 0;
                        have_base = true;
                        continue;
                }
                if (ksh_isdigit(c))
-                       c -= '0';
-               else {
-                       c |= 0x20;
-                       if (!ksh_islower(c))
-                               return (-1);
-                       c -= 'a' - 10;
-               }
+                       c = ksh_numdig(c);
+               else if (ksh_isupper(c))
+                       c = ksh_numuc(c) + 10;
+               else if (ksh_islower(c))
+                       c = ksh_numlc(c) + 10;
+               else
+                       return (-1);
                if (c >= base)
                        return (-1);
                /* handle overflow as truncation */
@@ -1281,7 +1281,7 @@ setspec(struct tbl *vp)
 
                        s = str_val(vp);
                        /* LINTED use of access */
-                       if (s[0] == '/' && access(s, W_OK|X_OK) == 0 &&
+                       if (mksh_abspath(s) && access(s, W_OK|X_OK) == 0 &&
                            stat(s, &statb) == 0 && S_ISDIR(statb.st_mode))
                                strdupx(tmpdir, s, APERM);
                }