OSDN Git Service

Upgrade to mksh R56c.
authorElliott Hughes <enh@google.com>
Mon, 5 Feb 2018 23:55:19 +0000 (15:55 -0800)
committerElliott Hughes <enh@google.com>
Wed, 7 Feb 2018 20:46:26 +0000 (12:46 -0800)
R56c is a bugfix-only release everyone must upgrade to:

[komh] Remove redundant OS/2-specific code, clean up others
[komh, tg] Fix drive-qualified (absolute and relative) DOS-style path support in realpath functionality, partially other places
[tg] Don’t substitute ${ENV:-~/.mkshrc} result again
[tg] Improve OS/2 $PATH (et al.) handling, drive-relative paths
[tg] Add MKSH_ENVDIR compile-time option for Jehanne and Plan 9
[tg] Limit nesting when parsing malformed code (Debian #878947)
[tg] Update wcwidth data with bugfixed script (still Unicode 10; resulting values are identical to glibc git master for extant chars)
[Dr. Werner Fink] Raise some time limits in the testsuite
[Shamar] Add support for the Jehanne operating system
[komh] Set stdin to text mode before executing child processes on OS/2
[komh] Pass arguments via a resonse file if executing a child fails
[Dr. Werner Fink] Early locale tracking as a compile-time option
[tg] Fix regressions introduced with new fast character classes

Bug: N/A
Test: builds and boots
Change-Id: I44da7a8bb9859a0357bcd59891dd4f2cfc199733

19 files changed:
Android.bp
src/Build.sh [changed mode: 0644->0755]
src/check.t
src/edit.c
src/eval.c
src/exec.c
src/expr.c
src/funcs.c
src/jobs.c
src/lex.c
src/main.c
src/misc.c
src/os2.c
src/sh.h
src/shf.c
src/syn.c
src/tree.c
src/var.c
src/var_spec.h

index 9926e18..2bca561 100644 (file)
@@ -108,7 +108,7 @@ cc_defaults {
         "-DHAVE_SYS_ERRLIST_DECL=0",
         "-DHAVE_SYS_SIGLIST_DECL=1",
         "-DHAVE_PERSISTENT_HISTORY=0",
-        "-DMKSH_BUILD_R=562",
+        "-DMKSH_BUILD_R=563",
 
         // Additional flags
         "-DMKSH_DEFAULT_PROFILEDIR=\"/system/etc\"",
old mode 100644 (file)
new mode 100755 (executable)
index 78fe347..ebf4e1c
@@ -1,5 +1,5 @@
 #!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.727 2017/08/29 13:38:28 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.731 2018/01/13 21:38:06 tg Exp $'
 #-
 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 #              2011, 2012, 2013, 2014, 2015, 2016, 2017
@@ -796,6 +796,8 @@ Harvey)
        add_cppflags -DMKSH_ASSUME_UTF8
        HAVE_ISSET_MKSH_ASSUME_UTF8=1
        HAVE_ISOFF_MKSH_ASSUME_UTF8=0
+       add_cppflags -DMKSH__NO_SYMLINK
+       check_categories="$check_categories nosymlink"
        add_cppflags -DMKSH_NO_CMDLINE_EDITING
        add_cppflags -DMKSH__NO_SETEUGID
        oswarn=' and will currently not work'
@@ -819,6 +821,20 @@ Interix)
 IRIX*)
        : "${HAVE_SETLOCALE_CTYPE=0}"
        ;;
+Jehanne)
+       add_cppflags -DMKSH_ASSUME_UTF8
+       HAVE_ISSET_MKSH_ASSUME_UTF8=1
+       HAVE_ISOFF_MKSH_ASSUME_UTF8=0
+       add_cppflags -DMKSH__NO_SYMLINK
+       check_categories="$check_categories nosymlink"
+       add_cppflags -DMKSH_NO_CMDLINE_EDITING
+       add_cppflags -DMKSH_DISABLE_REVOKE_WARNING
+       add_cppflags '-D_PATH_DEFPATH=\"/cmd\"'
+       add_cppflags '-DMKSH_DEFAULT_EXECSHELL=\"/cmd/mksh\"'
+       add_cppflags '-DMKSH_DEFAULT_PROFILEDIR=\"/cfg/mksh\"'
+       add_cppflags '-DMKSH_ENVDIR=\"/env\"'
+       SRCS="$SRCS jehanne.c"
+       ;;
 Linux)
        case $CC in
        *tendracc*) ;;
@@ -947,6 +963,8 @@ Plan9)
        add_cppflags -DMKSH_ASSUME_UTF8
        HAVE_ISSET_MKSH_ASSUME_UTF8=1
        HAVE_ISOFF_MKSH_ASSUME_UTF8=0
+       add_cppflags -DMKSH__NO_SYMLINK
+       check_categories="$check_categories nosymlink"
        add_cppflags -DMKSH_NO_CMDLINE_EDITING
        add_cppflags -DMKSH__NO_SETEUGID
        oswarn=' and will currently not work'
@@ -2409,7 +2427,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=562
+add_cppflags -DMKSH_BUILD_R=563
 
 $e $bi$me: Finished configuration testing, now producing output.$ao
 
@@ -2733,6 +2751,7 @@ MKSH_DISABLE_DEPRECATED           disable code paths scheduled for later removal
 MKSH_DISABLE_EXPERIMENTAL      disable code not yet comfy for (LTS) snapshots
 MKSH_DISABLE_TTY_WARNING       shut up warning about ctty if OS cant be fixed
 MKSH_DONT_EMIT_IDSTRING                omit RCS IDs from binary
+MKSH_EARLY_LOCALE_TRACKING     track utf8-mode from POSIX locale, for SuSE
 MKSH_MIDNIGHTBSD01ASH_COMPAT   set -o sh: additional compatibility quirk
 MKSH_NOPROSPECTOFWORK          disable jobs, co-processes, etc. (do not use)
 MKSH_NOPWNAM                   skip PAM calls, for -static on glibc or Solaris
index 4473c08..ea414d3 100644 (file)
@@ -1,4 +1,4 @@
-# $MirOS: src/bin/mksh/check.t,v 1.797 2017/08/29 13:38:29 tg Exp $
+# $MirOS: src/bin/mksh/check.t,v 1.801 2018/01/14 01:47:33 tg Exp $
 # -*- mode: sh -*-
 #-
 # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@@ -30,7 +30,7 @@
 # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
 
 expected-stdout:
-       @(#)MIRBSD KSH R56 2017/08/29
+       @(#)MIRBSD KSH R56 2018/01/14
 description:
        Check base version of full shell
 stdin:
@@ -39,7 +39,7 @@ name: KSH_VERSION
 category: !shell:legacy-yes
 ---
 expected-stdout:
-       @(#)LEGACY KSH R56 2017/08/29
+       @(#)LEGACY KSH R56 2018/01/14
 description:
        Check base version of legacy shell
 stdin:
@@ -3328,7 +3328,7 @@ stdin:
                echo B
              ) &
            ' &
-       sleep 2
+       sleep 5
        echo Left overs: *
 expected-stdout:
        A
@@ -3392,7 +3392,7 @@ stdin:
                (sleep 1; foo) &
                foo
            ' &
-       sleep 2
+       sleep 5
        echo Left overs: *
 expected-stdout:
        hi
@@ -6702,7 +6702,7 @@ name: regression-65
 description:
        check for a regression with sleep builtin and signal mask
 category: !nojsig
-time-limit: 3
+time-limit: 5
 stdin:
        sleep 1
        echo blub |&
@@ -9026,6 +9026,15 @@ expected-stdout:
        .c:a  b.c  d..:
        .d:a b.c d..:
 ---
+name: arrassign-eol
+description:
+       Commands after array assignments are not permitted
+stdin:
+       foo=(a b) env
+expected-exit: e != 0
+expected-stderr-pattern:
+       /syntax error: unexpected 'env'/
+---
 name: arrassign-fnc-none
 description:
        Check locality of array access inside a function
index 8bccf13..0e51780 100644 (file)
@@ -5,7 +5,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013, 2014, 2015, 2016, 2017
+ *              2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -28,7 +28,7 @@
 
 #ifndef MKSH_NO_CMDLINE_EDITING
 
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.340 2017/08/27 23:33:50 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.342 2018/01/14 00:03:00 tg Exp $");
 
 /*
  * in later versions we might use libtermcap for this, but since external
@@ -312,12 +312,12 @@ x_glob_hlp_add_qchar(char *cp)
                         */
                        switch (ord(ch)) {
                        case QCHAR:
-                       case ord('$'):
-                       case ord('*'):
-                       case ord('?'):
-                       case ord('['):
-                       case ord('\\'):
-                       case ord('`'):
+                       case ORD('$'):
+                       case ORD('*'):
+                       case ORD('?'):
+                       case ORD('['):
+                       case ORD('\\'):
+                       case ORD('`'):
                                *dp++ = QCHAR;
                                break;
                        }
@@ -650,11 +650,11 @@ x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
                        if (*s == '\\' && s[1])
                                s++;
                        else if (ctype(*s, C_QUEST | C_DOLAR) ||
-                           ord(*s) == ord('*') || ord(*s) == ord('[') ||
+                           ord(*s) == ORD('*') || ord(*s) == ORD('[') ||
                            /* ?() *() +() @() !() but two already checked */
-                           (ord(s[1]) == ord('(' /*)*/) &&
-                           (ord(*s) == ord('+') || ord(*s) == ord('@') ||
-                           ord(*s) == ord('!')))) {
+                           (ord(s[1]) == ORD('(' /*)*/) &&
+                           (ord(*s) == ORD('+') || ord(*s) == ORD('@') ||
+                           ord(*s) == ORD('!')))) {
                                /*
                                 * just expand based on the extglob
                                 * or parameter
@@ -3688,7 +3688,7 @@ vi_hook(int ch)
                                return (1);
                        cmdlen = 0;
                        argc1 = 0;
-                       if (ctype(ch, C_DIGIT) && ord(ch) != ord('0')) {
+                       if (ctype(ch, C_DIGIT) && ord(ch) != ORD('0')) {
                                argc1 = ksh_numdig(ch);
                                state = VARG1;
                        } else {
@@ -3743,7 +3743,7 @@ vi_hook(int ch)
 
        case VEXTCMD:
                argc2 = 0;
-               if (ctype(ch, C_DIGIT) && ord(ch) != ord('0')) {
+               if (ctype(ch, C_DIGIT) && ord(ch) != ORD('0')) {
                        argc2 = ksh_numdig(ch);
                        state = VARG2;
                        return (0);
@@ -4128,7 +4128,7 @@ vi_cmd(int argcnt, const char *cmd)
                        redraw_line(true);
                        break;
 
-               case ord('@'):
+               case ORD('@'):
                        {
                                static char alias[] = "_\0";
                                struct tbl *ap;
@@ -4169,7 +4169,7 @@ vi_cmd(int argcnt, const char *cmd)
                        }
                        break;
 
-               case ord('a'):
+               case ORD('a'):
                        modified = 1;
                        hnum = hlast;
                        if (vs->linelen != 0)
@@ -4177,7 +4177,7 @@ vi_cmd(int argcnt, const char *cmd)
                        insert = INSERT;
                        break;
 
-               case ord('A'):
+               case ORD('A'):
                        modified = 1;
                        hnum = hlast;
                        del_range(0, 0);
@@ -4185,7 +4185,7 @@ vi_cmd(int argcnt, const char *cmd)
                        insert = INSERT;
                        break;
 
-               case ord('S'):
+               case ORD('S'):
                        vs->cursor = domovebeg();
                        del_range(vs->cursor, vs->linelen);
                        modified = 1;
@@ -4193,14 +4193,14 @@ vi_cmd(int argcnt, const char *cmd)
                        insert = INSERT;
                        break;
 
-               case ord('Y'):
+               case ORD('Y'):
                        cmd = "y$";
                        /* ahhhhhh... */
 
                        /* FALLTHROUGH */
-               case ord('c'):
-               case ord('d'):
-               case ord('y'):
+               case ORD('c'):
+               case ORD('d'):
+               case ORD('y'):
                        if (*cmd == cmd[1]) {
                                c1 = *cmd == 'c' ? domovebeg() : 0;
                                c2 = vs->linelen;
@@ -4239,7 +4239,7 @@ vi_cmd(int argcnt, const char *cmd)
                        }
                        break;
 
-               case ord('p'):
+               case ORD('p'):
                        modified = 1;
                        hnum = hlast;
                        if (vs->linelen != 0)
@@ -4253,7 +4253,7 @@ vi_cmd(int argcnt, const char *cmd)
                                return (-1);
                        break;
 
-               case ord('P'):
+               case ORD('P'):
                        modified = 1;
                        hnum = hlast;
                        any = 0;
@@ -4266,25 +4266,25 @@ vi_cmd(int argcnt, const char *cmd)
                                return (-1);
                        break;
 
-               case ord('C'):
+               case ORD('C'):
                        modified = 1;
                        hnum = hlast;
                        del_range(vs->cursor, vs->linelen);
                        insert = INSERT;
                        break;
 
-               case ord('D'):
+               case ORD('D'):
                        yank_range(vs->cursor, vs->linelen);
                        del_range(vs->cursor, vs->linelen);
                        if (vs->cursor != 0)
                                vs->cursor--;
                        break;
 
-               case ord('g'):
+               case ORD('g'):
                        if (!argcnt)
                                argcnt = hlast;
                        /* FALLTHROUGH */
-               case ord('G'):
+               case ORD('G'):
                        if (!argcnt)
                                argcnt = 1;
                        else
@@ -4297,21 +4297,21 @@ vi_cmd(int argcnt, const char *cmd)
                        }
                        break;
 
-               case ord('i'):
+               case ORD('i'):
                        modified = 1;
                        hnum = hlast;
                        insert = INSERT;
                        break;
 
-               case ord('I'):
+               case ORD('I'):
                        modified = 1;
                        hnum = hlast;
                        vs->cursor = domovebeg();
                        insert = INSERT;
                        break;
 
-               case ord('j'):
-               case ord('+'):
+               case ORD('j'):
+               case ORD('+'):
                case CTRL_N:
                        if (grabhist(modified, hnum + argcnt) < 0)
                                return (-1);
@@ -4321,8 +4321,8 @@ vi_cmd(int argcnt, const char *cmd)
                        }
                        break;
 
-               case ord('k'):
-               case ord('-'):
+               case ORD('k'):
+               case ORD('-'):
                case CTRL_P:
                        if (grabhist(modified, hnum - argcnt) < 0)
                                return (-1);
@@ -4332,7 +4332,7 @@ vi_cmd(int argcnt, const char *cmd)
                        }
                        break;
 
-               case ord('r'):
+               case ORD('r'):
                        if (vs->linelen == 0)
                                return (-1);
                        modified = 1;
@@ -4350,13 +4350,13 @@ vi_cmd(int argcnt, const char *cmd)
                        }
                        break;
 
-               case ord('R'):
+               case ORD('R'):
                        modified = 1;
                        hnum = hlast;
                        insert = REPLACE;
                        break;
 
-               case ord('s'):
+               case ORD('s'):
                        if (vs->linelen == 0)
                                return (-1);
                        modified = 1;
@@ -4367,7 +4367,7 @@ vi_cmd(int argcnt, const char *cmd)
                        insert = INSERT;
                        break;
 
-               case ord('v'):
+               case ORD('v'):
                        if (!argcnt) {
                                if (vs->linelen == 0)
                                        return (-1);
@@ -4390,7 +4390,7 @@ vi_cmd(int argcnt, const char *cmd)
                        vs->linelen = strlen(vs->cbuf);
                        return (2);
 
-               case ord('x'):
+               case ORD('x'):
                        if (vs->linelen == 0)
                                return (-1);
                        modified = 1;
@@ -4401,7 +4401,7 @@ vi_cmd(int argcnt, const char *cmd)
                        del_range(vs->cursor, vs->cursor + argcnt);
                        break;
 
-               case ord('X'):
+               case ORD('X'):
                        if (vs->cursor > 0) {
                                modified = 1;
                                hnum = hlast;
@@ -4414,13 +4414,13 @@ vi_cmd(int argcnt, const char *cmd)
                                return (-1);
                        break;
 
-               case ord('u'):
+               case ORD('u'):
                        t = vs;
                        vs = undo;
                        undo = t;
                        break;
 
-               case ord('U'):
+               case ORD('U'):
                        if (!modified)
                                return (-1);
                        if (grabhist(modified, ohnum) < 0)
@@ -4429,19 +4429,19 @@ vi_cmd(int argcnt, const char *cmd)
                        hnum = ohnum;
                        break;
 
-               case ord('?'):
+               case ORD('?'):
                        if (hnum == hlast)
                                hnum = -1;
                        /* ahhh */
 
                        /* FALLTHROUGH */
-               case ord('/'):
+               case ORD('/'):
                        c3 = 1;
                        srchlen = 0;
                        lastsearch = *cmd;
                        /* FALLTHROUGH */
-               case ord('n'):
-               case ord('N'):
+               case ORD('n'):
+               case ORD('N'):
                        if (lastsearch == ' ')
                                return (-1);
                        if (lastsearch == '?')
@@ -4468,7 +4468,7 @@ vi_cmd(int argcnt, const char *cmd)
                                return (0);
                        }
                        break;
-               case ord('_'):
+               case ORD('_'):
                        {
                                bool inspace;
                                char *p, *sp;
@@ -4520,7 +4520,7 @@ vi_cmd(int argcnt, const char *cmd)
                        }
                        break;
 
-               case ord('~'):
+               case ORD('~'):
                        {
                                char *p;
                                int i;
@@ -4544,7 +4544,7 @@ vi_cmd(int argcnt, const char *cmd)
                                break;
                        }
 
-               case ord('#'):
+               case ORD('#'):
                        {
                                int ret = x_do_comment(vs->cbuf, vs->cbufsize,
                                    &vs->linelen);
@@ -4554,7 +4554,7 @@ vi_cmd(int argcnt, const char *cmd)
                        }
 
                /* AT&T ksh */
-               case ord('='):
+               case ORD('='):
                /* Nonstandard vi/ksh */
                case CTRL_E:
                        print_expansions(vs, 1);
@@ -4574,7 +4574,7 @@ vi_cmd(int argcnt, const char *cmd)
                                return (-1);
                        /* FALLTHROUGH */
                /* AT&T ksh */
-               case ord('\\'):
+               case ORD('\\'):
                /* Nonstandard vi/ksh */
                case CTRL_F:
                        complete_word(1, argcnt);
@@ -4582,7 +4582,7 @@ vi_cmd(int argcnt, const char *cmd)
 
 
                /* AT&T ksh */
-               case ord('*'):
+               case ORD('*'):
                /* Nonstandard vi/ksh */
                case CTRL_X:
                        expand_word(1);
@@ -4590,8 +4590,8 @@ vi_cmd(int argcnt, const char *cmd)
 
 
                /* mksh: cursor movement */
-               case ord('['):
-               case ord('O'):
+               case ORD('['):
+               case ORD('O'):
                        state = VPREFIX2;
                        if (vs->linelen != 0)
                                vs->cursor++;
@@ -4611,19 +4611,19 @@ domove(int argcnt, const char *cmd, int sub)
        unsigned int bcount;
 
        switch (ord(*cmd)) {
-       case ord('b'):
+       case ORD('b'):
                if (!sub && vs->cursor == 0)
                        return (-1);
                ncursor = backword(argcnt);
                break;
 
-       case ord('B'):
+       case ORD('B'):
                if (!sub && vs->cursor == 0)
                        return (-1);
                ncursor = Backword(argcnt);
                break;
 
-       case ord('e'):
+       case ORD('e'):
                if (!sub && vs->cursor + 1 >= vs->linelen)
                        return (-1);
                ncursor = endword(argcnt);
@@ -4631,7 +4631,7 @@ domove(int argcnt, const char *cmd, int sub)
                        ncursor++;
                break;
 
-       case ord('E'):
+       case ORD('E'):
                if (!sub && vs->cursor + 1 >= vs->linelen)
                        return (-1);
                ncursor = Endword(argcnt);
@@ -4639,15 +4639,15 @@ domove(int argcnt, const char *cmd, int sub)
                        ncursor++;
                break;
 
-       case ord('f'):
-       case ord('F'):
-       case ord('t'):
-       case ord('T'):
+       case ORD('f'):
+       case ORD('F'):
+       case ORD('t'):
+       case ORD('T'):
                fsavecmd = *cmd;
                fsavech = cmd[1];
                /* FALLTHROUGH */
-       case ord(','):
-       case ord(';'):
+       case ORD(','):
+       case ORD(';'):
                if (fsavecmd == ' ')
                        return (-1);
                i = ksh_eq(fsavecmd, 'F', 'f');
@@ -4661,7 +4661,7 @@ domove(int argcnt, const char *cmd, int sub)
                        ncursor++;
                break;
 
-       case ord('h'):
+       case ORD('h'):
        case CTRL_H:
                if (!sub && vs->cursor == 0)
                        return (-1);
@@ -4670,8 +4670,8 @@ domove(int argcnt, const char *cmd, int sub)
                        ncursor = 0;
                break;
 
-       case ord(' '):
-       case ord('l'):
+       case ORD(' '):
+       case ORD('l'):
                if (!sub && vs->cursor + 1 >= vs->linelen)
                        return (-1);
                if (vs->linelen != 0) {
@@ -4681,27 +4681,27 @@ domove(int argcnt, const char *cmd, int sub)
                }
                break;
 
-       case ord('w'):
+       case ORD('w'):
                if (!sub && vs->cursor + 1 >= vs->linelen)
                        return (-1);
                ncursor = forwword(argcnt);
                break;
 
-       case ord('W'):
+       case ORD('W'):
                if (!sub && vs->cursor + 1 >= vs->linelen)
                        return (-1);
                ncursor = Forwword(argcnt);
                break;
 
-       case ord('0'):
+       case ORD('0'):
                ncursor = 0;
                break;
 
-       case ord('^'):
+       case ORD('^'):
                ncursor = domovebeg();
                break;
 
-       case ord('|'):
+       case ORD('|'):
                ncursor = argcnt;
                if (ncursor > vs->linelen)
                        ncursor = vs->linelen;
@@ -4709,14 +4709,14 @@ domove(int argcnt, const char *cmd, int sub)
                        ncursor--;
                break;
 
-       case ord('$'):
+       case ORD('$'):
                if (vs->linelen != 0)
                        ncursor = vs->linelen;
                else
                        ncursor = 0;
                break;
 
-       case ord('%'):
+       case ORD('%'):
                ncursor = vs->cursor;
                while (ncursor < vs->linelen &&
                    (i = bracktype(vs->cbuf[ncursor])) == 0)
@@ -4784,22 +4784,22 @@ bracktype(int ch)
 {
        switch (ord(ch)) {
 
-       case ord('('):
+       case ORD('('):
                return (1);
 
-       case ord('['):
+       case ORD('['):
                return (2);
 
-       case ord('{'):
+       case ORD('{'):
                return (3);
 
-       case ord(')'):
+       case ORD(')'):
                return (-1);
 
-       case ord(']'):
+       case ORD(']'):
                return (-2);
 
-       case ord('}'):
+       case ORD('}'):
                return (-3);
 
        default:
index 7a892c0..6aa1844 100644 (file)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013, 2014, 2015, 2016, 2017
+ *              2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.215 2017/08/28 23:27:51 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.219 2018/01/14 01:29:47 tg Exp $");
 
 /*
  * string expansion
@@ -320,21 +320,21 @@ expand(
                                        case COMASUB:
                                        case COMSUB:
                                                *dp++ = '(';
-                                               c = ord(')');
+                                               c = ORD(')');
                                                break;
                                        case FUNASUB:
                                        case FUNSUB:
                                        case VALSUB:
                                                *dp++ = '{';
                                                *dp++ = c == VALSUB ? '|' : ' ';
-                                               c = ord('}');
+                                               c = ORD('}');
                                                break;
                                        }
                                        while (*sp != '\0') {
                                                Xcheck(ds, dp);
                                                *dp++ = *sp++;
                                        }
-                                       if (c == ord('}'))
+                                       if ((unsigned int)c == ORD('}'))
                                                *dp++ = ';';
                                        *dp++ = c;
                                } else {
@@ -436,11 +436,11 @@ expand(
                                        if (stype)
                                                sp += slen;
                                        switch (stype & STYPE_SINGLE) {
-                                       case ord('#') | STYPE_AT:
+                                       case ORD('#') | STYPE_AT:
                                                x.str = shf_smprintf("%08X",
                                                    (unsigned int)hash(str_val(st->var)));
                                                break;
-                                       case ord('Q') | STYPE_AT: {
+                                       case ORD('Q') | STYPE_AT: {
                                                struct shf shf;
 
                                                shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf);
@@ -448,7 +448,7 @@ expand(
                                                x.str = shf_sclose(&shf);
                                                break;
                                            }
-                                       case ord('0'): {
+                                       case ORD('0'): {
                                                char *beg, *mid, *end, *stg;
                                                mksh_ari_t from = 0, num = -1, flen, finc = 0;
 
@@ -456,13 +456,13 @@ expand(
                                                mid = beg + (wdscan(sp, ADELIM) - sp);
                                                stg = beg + (wdscan(sp, CSUBST) - sp);
                                                mid[-2] = EOS;
-                                               if (ord(mid[-1]) == ord(/*{*/ '}')) {
+                                               if (ord(mid[-1]) == ORD(/*{*/ '}')) {
                                                        sp += mid - beg - 1;
                                                        end = NULL;
                                                } else {
                                                        end = mid +
                                                            (wdscan(mid, ADELIM) - mid);
-                                                       if (ord(end[-1]) != ord(/*{*/ '}'))
+                                                       if (ord(end[-1]) != ORD(/*{*/ '}'))
                                                                /* more than max delimiters */
                                                                goto unwind_substsyn;
                                                        end[-2] = EOS;
@@ -495,8 +495,8 @@ expand(
                                                strndupx(x.str, beg, num, ATEMP);
                                                goto do_CSUBST;
                                            }
-                                       case ord('/') | STYPE_AT:
-                                       case ord('/'): {
+                                       case ORD('/') | STYPE_AT:
+                                       case ORD('/'): {
                                                char *s, *p, *d, *sbeg, *end;
                                                char *pat = NULL, *rrep = null;
                                                char fpat = 0, *tpat1, *tpat2;
@@ -506,7 +506,7 @@ expand(
                                                p = s + (wdscan(sp, ADELIM) - sp);
                                                d = s + (wdscan(sp, CSUBST) - sp);
                                                p[-2] = EOS;
-                                               if (ord(p[-1]) == ord(/*{*/ '}'))
+                                               if (ord(p[-1]) == ORD(/*{*/ '}'))
                                                        d = NULL;
                                                else
                                                        d[-2] = EOS;
@@ -547,11 +547,11 @@ expand(
                                                }
 
                                                /* first see if we have any match at all */
-                                               if (ord(fpat) == ord('#')) {
+                                               if (ord(fpat) == ORD('#')) {
                                                        /* anchor at the beginning */
                                                        tpat1 = shf_smprintf("%s%c*", pat, MAGIC);
                                                        tpat2 = tpat1;
-                                               } else if (ord(fpat) == ord('%')) {
+                                               } else if (ord(fpat) == ORD('%')) {
                                                        /* anchor at the end */
                                                        tpat1 = shf_smprintf("%c*%s", MAGIC, pat);
                                                        tpat2 = pat;
@@ -569,7 +569,7 @@ expand(
                                                        goto end_repl;
                                                end = strnul(s);
                                                /* now anchor the beginning of the match */
-                                               if (ord(fpat) != ord('#'))
+                                               if (ord(fpat) != ORD('#'))
                                                        while (sbeg <= end) {
                                                                if (gmatchx(sbeg, tpat2, false))
                                                                        break;
@@ -578,11 +578,11 @@ expand(
                                                        }
                                                /* now anchor the end of the match */
                                                p = end;
-                                               if (ord(fpat) != ord('%'))
+                                               if (ord(fpat) != ORD('%'))
                                                        while (p >= sbeg) {
                                                                bool gotmatch;
 
-                                                               c = *p;
+                                                               c = ord(*p);
                                                                *p = '\0';
                                                                gotmatch = tobool(gmatchx(sbeg, pat, false));
                                                                *p = c;
@@ -622,8 +622,8 @@ expand(
                                                afree(ws, ATEMP);
                                                goto do_CSUBST;
                                            }
-                                       case ord('#'):
-                                       case ord('%'):
+                                       case ORD('#'):
+                                       case ORD('%'):
                                                /* ! DOBLANK,DOBRACE */
                                                f = (f & DONTRUNCOMMAND) |
                                                    DOPAT | DOTILDE |
@@ -637,10 +637,10 @@ expand(
                                                 */
                                                if (!Flag(FSH)) {
                                                        *dp++ = MAGIC;
-                                                       *dp++ = ord(0x80 | '@');
+                                                       *dp++ = ORD(0x80 | '@');
                                                }
                                                break;
-                                       case ord('='):
+                                       case ORD('='):
                                                /*
                                                 * Tilde expansion for string
                                                 * variables in POSIX mode is
@@ -664,7 +664,7 @@ expand(
                                                f &= ~(DOBLANK|DOGLOB|DOBRACE);
                                                tilde_ok = 1;
                                                break;
-                                       case ord('?'):
+                                       case ORD('?'):
                                                if (*sp == CSUBST)
                                                        errorf("%s: parameter null or not set",
                                                            st->var->name);
@@ -699,8 +699,8 @@ expand(
                                if (f & DOBLANK)
                                        doblank--;
                                switch (st->stype & STYPE_SINGLE) {
-                               case ord('#'):
-                               case ord('%'):
+                               case ORD('#'):
+                               case ORD('%'):
                                        if (!Flag(FSH)) {
                                                /* Append end-pattern */
                                                *dp++ = MAGIC;
@@ -730,7 +730,7 @@ expand(
                                                doblank++;
                                        st = st->prev;
                                        continue;
-                               case ord('='):
+                               case ORD('='):
                                        /*
                                         * Restore our position and substitute
                                         * the value of st->var (may not be
@@ -763,17 +763,17 @@ expand(
                                        st = st->prev;
                                        word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
                                        continue;
-                               case ord('?'):
+                               case ORD('?'):
                                        dp = Xrestpos(ds, dp, st->base);
 
                                        errorf(Tf_sD_s, st->var->name,
                                            debunk(dp, dp, strlen(dp) + 1));
                                        break;
-                               case ord('0'):
-                               case ord('/') | STYPE_AT:
-                               case ord('/'):
-                               case ord('#') | STYPE_AT:
-                               case ord('Q') | STYPE_AT:
+                               case ORD('0'):
+                               case ORD('/') | STYPE_AT:
+                               case ORD('/'):
+                               case ORD('#') | STYPE_AT:
+                               case ORD('Q') | STYPE_AT:
                                        dp = Xrestpos(ds, dp, st->base);
                                        type = XSUB;
                                        word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
@@ -791,19 +791,19 @@ expand(
                                /* open pattern: *(foo|bar) */
                                /* Next char is the type of pattern */
                                make_magic = true;
-                               c = *sp++ | 0x80;
+                               c = ord(*sp++) | 0x80U;
                                break;
 
                        case SPAT:
                                /* pattern separator (|) */
                                make_magic = true;
-                               c = '|';
+                               c = ORD('|');
                                break;
 
                        case CPAT:
                                /* close pattern */
                                make_magic = true;
-                               c = /*(*/ ')';
+                               c = ORD(/*(*/ ')');
                                break;
                        }
                        break;
@@ -824,7 +824,7 @@ expand(
 
                case XSUB:
                case XSUBMID:
-                       if ((c = *x.str++) == 0) {
+                       if ((c = ord(*x.str++)) == 0) {
                                type = XBASE;
                                if (f & DOBLANK)
                                        doblank--;
@@ -837,7 +837,7 @@ expand(
                        quote = 1;
                        /* FALLTHROUGH */
                case XARG:
-                       if ((c = *x.str++) == '\0') {
+                       if ((c = ord(*x.str++)) == '\0') {
                                /*
                                 * force null words to be created so
                                 * set -- "" 2 ""; echo "$@" will do
@@ -855,13 +855,13 @@ expand(
                                if ((f & DOHEREDOC)) {
                                        /* pseudo-field-split reliably */
                                        if (c == 0)
-                                               c = ' ';
+                                               c = ORD(' ');
                                        break;
                                }
                                if ((f & DOSCALAR)) {
                                        /* do not field-split */
                                        if (x.split) {
-                                               c = ' ';
+                                               c = ORD(' ');
                                                break;
                                        }
                                        if (c == 0)
@@ -873,7 +873,7 @@ expand(
                                        if (!quote && word == IFS_WS)
                                                continue;
                                        /* this is so we don't terminate */
-                                       c = ' ';
+                                       c = ORD(' ');
                                        /* now force-emit a word */
                                        goto emit_word;
                                }
@@ -893,33 +893,33 @@ expand(
                                c = -1;
                        } else if (newlines) {
                                /* spit out saved NLs */
-                               c = '\n';
+                               c = ORD('\n');
                                --newlines;
                        } else {
                                while ((c = shf_getc(x.u.shf)) == 0 ||
-                                   ctype(c, C_NL)) {
+                                   cinttype(c, C_NL)) {
 #ifdef MKSH_WITH_TEXTMODE
-                                       if (c == '\r') {
+                                       if (c == ORD('\r')) {
                                                c = shf_getc(x.u.shf);
                                                switch (c) {
-                                               case '\n':
+                                               case ORD('\n'):
                                                        break;
                                                default:
                                                        shf_ungetc(c, x.u.shf);
                                                        /* FALLTHROUGH */
                                                case -1:
-                                                       c = '\r';
+                                                       c = ORD('\r');
                                                        break;
                                                }
                                        }
 #endif
-                                       if (c == '\n')
+                                       if (c == ORD('\n'))
                                                /* save newlines */
                                                newlines++;
                                }
                                if (newlines && c != -1) {
                                        shf_ungetc(c, x.u.shf);
-                                       c = '\n';
+                                       c = ORD('\n');
                                        --newlines;
                                }
                        }
@@ -1003,10 +1003,10 @@ expand(
                        /* mark any special second pass chars */
                        if (!quote)
                                switch (ord(c)) {
-                               case ord('['):
-                               case ord('!'):
-                               case ord('-'):
-                               case ord(']'):
+                               case ORD('['):
+                               case ORD('!'):
+                               case ORD('-'):
+                               case ORD(']'):
                                        /*
                                         * For character classes - doesn't hurt
                                         * to have magic !,-,]s outside of
@@ -1014,29 +1014,29 @@ expand(
                                         */
                                        if (f & (DOPAT | DOGLOB)) {
                                                fdo |= DOMAGIC;
-                                               if (c == ord('['))
+                                               if ((unsigned int)c == ORD('['))
                                                        fdo |= f & DOGLOB;
                                                *dp++ = MAGIC;
                                        }
                                        break;
-                               case ord('*'):
-                               case ord('?'):
+                               case ORD('*'):
+                               case ORD('?'):
                                        if (f & (DOPAT | DOGLOB)) {
                                                fdo |= DOMAGIC | (f & DOGLOB);
                                                *dp++ = MAGIC;
                                        }
                                        break;
-                               case ord('{'):
-                               case ord('}'):
-                               case ord(','):
+                               case ORD('{'):
+                               case ORD('}'):
+                               case ORD(','):
                                        if ((f & DOBRACE) &&
-                                           (ord(c) == ord('{' /*}*/) ||
+                                           (ord(c) == ORD('{' /*}*/) ||
                                            (fdo & DOBRACE))) {
                                                fdo |= DOBRACE|DOMAGIC;
                                                *dp++ = MAGIC;
                                        }
                                        break;
-                               case ord('='):
+                               case ORD('='):
                                        /* Note first unquoted = for ~ */
                                        if (!(f & DOTEMP) && (!Flag(FPOSIX) ||
                                            (f & DOASNTILDE)) && !saw_eq) {
@@ -1044,13 +1044,13 @@ expand(
                                                tilde_ok = 1;
                                        }
                                        break;
-                               case ord(':'):
+                               case ORD(':'):
                                        /* : */
                                        /* Note unquoted : for ~ */
                                        if (!(f & DOTEMP) && (f & DOASNTILDE))
                                                tilde_ok = 1;
                                        break;
-                               case ord('~'):
+                               case ORD('~'):
                                        /*
                                         * tilde_ok is reset whenever
                                         * any of ' " $( $(( ${ } are seen.
@@ -1133,7 +1133,7 @@ varsub(Expand *xp, const char *sp, const char *word,
         * ${%var}, string width (-U: screen columns, +U: octets)
         */
        c = ord(sp[1]);
-       if (stype == ord('%') && c == '\0')
+       if ((unsigned int)stype == ORD('%') && c == '\0')
                return (-1);
        if (ctype(stype, C_SUB2) && c != '\0') {
                /* Can't have any modifiers for ${#...} or ${%...} */
@@ -1141,11 +1141,11 @@ varsub(Expand *xp, const char *sp, const char *word,
                        return (-1);
                sp++;
                /* Check for size of array */
-               if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ord('*') ||
-                   ord(p[1]) == ord('@')) && ord(p[2]) == ord(']')) {
+               if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') ||
+                   ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) {
                        int n = 0;
 
-                       if (stype != ord('#'))
+                       if ((unsigned int)stype != ORD('#'))
                                return (-1);
                        vp = global(arrayname(sp));
                        if (vp->flag & (ISSET|ARRAY))
@@ -1154,14 +1154,15 @@ varsub(Expand *xp, const char *sp, const char *word,
                                if (vp->flag & ISSET)
                                        n++;
                        c = n;
-               } else if (c == ord('*') || c == ord('@')) {
-                       if (stype != ord('#'))
+               } else if ((unsigned int)c == ORD('*') ||
+                   (unsigned int)c == ORD('@')) {
+                       if ((unsigned int)stype != ORD('#'))
                                return (-1);
                        c = e->loc->argc;
                } else {
                        p = str_val(global(sp));
                        zero_ok = p != null;
-                       if (stype == ord('#'))
+                       if ((unsigned int)stype == ORD('#'))
                                c = utflen(p);
                        else {
                                /* partial utf_mbswidth reimplementation */
@@ -1196,11 +1197,11 @@ varsub(Expand *xp, const char *sp, const char *word,
                xp->str = shf_smprintf(Tf_d, c);
                return (XSUB);
        }
-       if (stype == ord('!') && c != '\0' && *word == CSUBST) {
+       if ((unsigned int)stype == ORD('!') && c != '\0' && *word == CSUBST) {
                sp++;
-               if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ord('*') ||
-                   ord(p[1]) == ord('@')) && ord(p[2]) == ord(']')) {
-                       c = ord('!');
+               if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') ||
+                   ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) {
+                       c = ORD('!');
                        stype = 0;
                        goto arraynames;
                }
@@ -1214,12 +1215,12 @@ varsub(Expand *xp, const char *sp, const char *word,
        /* Check for qualifiers in word part */
        stype = 0;
        c = word[slen + 0] == CHAR ? ord(word[slen + 1]) : 0;
-       if (c == ord(':')) {
+       if ((unsigned int)c == ORD(':')) {
                slen += 2;
                stype = STYPE_DBL;
                c = word[slen + 0] == CHAR ? ord(word[slen + 1]) : 0;
        }
-       if (!stype && c == ord('/')) {
+       if (!stype && (unsigned int)c == ORD('/')) {
                slen += 2;
                stype = c;
                if (word[slen] == ADELIM &&
@@ -1227,8 +1228,9 @@ varsub(Expand *xp, const char *sp, const char *word,
                        slen += 2;
                        stype |= STYPE_DBL;
                }
-       } else if (stype == STYPE_DBL && (c == ord(' ') || c == ord('0'))) {
-               stype |= ord('0');
+       } else if (stype == STYPE_DBL && ((unsigned int)c == ORD(' ') ||
+           (unsigned int)c == ORD('0'))) {
+               stype |= ORD('0');
        } else if (ctype(c, C_SUB1)) {
                slen += 2;
                stype |= c;
@@ -1241,13 +1243,13 @@ varsub(Expand *xp, const char *sp, const char *word,
                        stype |= STYPE_DBL;
                        slen += 2;
                }
-       } else if (c == ord('@')) {
+       } else if ((unsigned int)c == ORD('@')) {
                /* @x where x is command char */
                switch (c = ord(word[slen + 2]) == CHAR ?
                    ord(word[slen + 3]) : 0) {
-               case ord('#'):
-               case ord('/'):
-               case ord('Q'):
+               case ORD('#'):
+               case ORD('/'):
+               case ORD('Q'):
                        break;
                default:
                        return (-1);
@@ -1261,50 +1263,50 @@ varsub(Expand *xp, const char *sp, const char *word,
                return (-1);
 
        c = ord(sp[0]);
-       if (c == ord('*') || c == ord('@')) {
+       if ((unsigned int)c == ORD('*') || (unsigned int)c == ORD('@')) {
                switch (stype & STYPE_SINGLE) {
                /* can't assign to a vector */
-               case ord('='):
+               case ORD('='):
                /* can't trim a vector (yet) */
-               case ord('%'):
-               case ord('#'):
-               case ord('?'):
-               case ord('0'):
-               case ord('/') | STYPE_AT:
-               case ord('/'):
-               case ord('#') | STYPE_AT:
-               case ord('Q') | STYPE_AT:
+               case ORD('%'):
+               case ORD('#'):
+               case ORD('?'):
+               case ORD('0'):
+               case ORD('/') | STYPE_AT:
+               case ORD('/'):
+               case ORD('#') | STYPE_AT:
+               case ORD('Q') | STYPE_AT:
                        return (-1);
                }
                if (e->loc->argc == 0) {
                        xp->str = null;
                        xp->var = global(sp);
-                       state = c == ord('@') ? XNULLSUB : XSUB;
+                       state = (unsigned int)c == ORD('@') ? XNULLSUB : XSUB;
                } else {
                        xp->u.strv = (const char **)e->loc->argv + 1;
                        xp->str = *xp->u.strv++;
                        /* $@ */
-                       xp->split = tobool(c == ord('@'));
+                       xp->split = tobool((unsigned int)c == ORD('@'));
                        state = XARG;
                }
                /* POSIX 2009? */
                zero_ok = true;
-       } else if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ord('*') ||
-           ord(p[1]) == ord('@')) && ord(p[2]) == ord(']')) {
+       } else if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') ||
+           ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) {
                XPtrV wv;
 
                switch (stype & STYPE_SINGLE) {
                /* can't assign to a vector */
-               case ord('='):
+               case ORD('='):
                /* can't trim a vector (yet) */
-               case ord('%'):
-               case ord('#'):
-               case ord('?'):
-               case ord('0'):
-               case ord('/') | STYPE_AT:
-               case ord('/'):
-               case ord('#') | STYPE_AT:
-               case ord('Q') | STYPE_AT:
+               case ORD('%'):
+               case ORD('#'):
+               case ORD('?'):
+               case ORD('0'):
+               case ORD('/') | STYPE_AT:
+               case ORD('/'):
+               case ORD('#') | STYPE_AT:
+               case ORD('Q') | STYPE_AT:
                        return (-1);
                }
                c = 0;
@@ -1314,28 +1316,28 @@ varsub(Expand *xp, const char *sp, const char *word,
                for (; vp; vp = vp->u.array) {
                        if (!(vp->flag&ISSET))
                                continue;
-                       XPput(wv, c == ord('!') ? shf_smprintf(Tf_lu,
-                           arrayindex(vp)) :
+                       XPput(wv, (unsigned int)c == ORD('!') ?
+                           shf_smprintf(Tf_lu, arrayindex(vp)) :
                            str_val(vp));
                }
                if (XPsize(wv) == 0) {
                        xp->str = null;
-                       state = ord(p[1]) == ord('@') ? XNULLSUB : XSUB;
+                       state = ord(p[1]) == ORD('@') ? XNULLSUB : XSUB;
                        XPfree(wv);
                } else {
                        XPput(wv, 0);
                        xp->u.strv = (const char **)XPptrv(wv);
                        xp->str = *xp->u.strv++;
                        /* ${foo[@]} */
-                       xp->split = tobool(ord(p[1]) == ord('@'));
+                       xp->split = tobool(ord(p[1]) == ORD('@'));
                        state = XARG;
                }
        } else {
                xp->var = global(sp);
                xp->str = str_val(xp->var);
                /* can't assign things like $! or $1 */
-               if ((stype & STYPE_SINGLE) == ord('=') && !*xp->str &&
-                   ctype(*sp, C_VAR1 | C_DIGIT))
+               if ((unsigned int)(stype & STYPE_SINGLE) == ORD('=') &&
+                   !*xp->str && ctype(*sp, C_VAR1 | C_DIGIT))
                        return (-1);
                state = XSUB;
        }
@@ -1346,13 +1348,15 @@ varsub(Expand *xp, const char *sp, const char *word,
            (((stype & STYPE_DBL) ? *xp->str == '\0' : xp->str == null) &&
            (state != XARG || (ifs0 || xp->split ?
            (xp->u.strv[0] == NULL) : !hasnonempty(xp->u.strv))) ?
-           ctype(c, C_EQUAL | C_MINUS | C_QUEST) : c == ord('+')))) ||
-           stype == (ord('0') | STYPE_DBL) || stype == (ord('#') | STYPE_AT) ||
-           stype == (ord('Q') | STYPE_AT) || (stype & STYPE_CHAR) == ord('/'))
+           ctype(c, C_EQUAL | C_MINUS | C_QUEST) : (unsigned int)c == ORD('+')))) ||
+           (unsigned int)stype == (ORD('0') | STYPE_DBL) ||
+           (unsigned int)stype == (ORD('#') | STYPE_AT) ||
+           (unsigned int)stype == (ORD('Q') | STYPE_AT) ||
+           (unsigned int)(stype & STYPE_CHAR) == ORD('/'))
                /* expand word instead of variable value */
                state = XBASE;
        if (Flag(FNOUNSET) && xp->str == null && !zero_ok &&
-           (ctype(c, C_SUB2) || (state != XBASE && c != ord('+'))))
+           (ctype(c, C_SUB2) || (state != XBASE && (unsigned int)c != ORD('+'))))
                errorf(Tf_parm, sp);
        *stypep = stype;
        *slenp = slen;
@@ -1491,7 +1495,7 @@ trimsub(char *str, char *pat, int how)
        char *p, c;
 
        switch (how & (STYPE_CHAR | STYPE_DBL)) {
-       case ord('#'):
+       case ORD('#'):
                /* shortest match at beginning */
                for (p = str; p <= end; p += utf_ptradj(p)) {
                        c = *p; *p = '\0';
@@ -1503,7 +1507,7 @@ trimsub(char *str, char *pat, int how)
                        *p = c;
                }
                break;
-       case ord('#') | STYPE_DBL:
+       case ORD('#') | STYPE_DBL:
                /* longest match at beginning */
                for (p = end; p >= str; p--) {
                        c = *p; *p = '\0';
@@ -1515,7 +1519,7 @@ trimsub(char *str, char *pat, int how)
                        *p = c;
                }
                break;
-       case ord('%'):
+       case ORD('%'):
                /* shortest match at end */
                p = end;
                while (p >= str) {
@@ -1531,7 +1535,7 @@ trimsub(char *str, char *pat, int how)
                                --p;
                }
                break;
-       case ord('%') | STYPE_DBL:
+       case ORD('%') | STYPE_DBL:
                /* longest match at end */
                for (p = str; p <= end; p++)
                        if (gmatchx(p, pat, false)) {
@@ -1863,7 +1867,7 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
        char *p = exp_start;
 
        /* search for open brace */
-       while ((p = strchr(p, MAGIC)) && ord(p[1]) != ord('{' /*}*/))
+       while ((p = strchr(p, MAGIC)) && ord(p[1]) != ORD('{' /*}*/))
                p += 2;
        brace_start = p;
 
@@ -1874,9 +1878,9 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
                p += 2;
                while (*p && count) {
                        if (ISMAGIC(*p++)) {
-                               if (ord(*p) == ord('{' /*}*/))
+                               if (ord(*p) == ORD('{' /*}*/))
                                        ++count;
-                               else if (ord(*p) == ord(/*{*/ '}'))
+                               else if (ord(*p) == ORD(/*{*/ '}'))
                                        --count;
                                else if (*p == ',' && count == 1)
                                        comma = p;
@@ -1908,9 +1912,9 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
        count = 1;
        for (p = brace_start + 2; p != brace_end; p++) {
                if (ISMAGIC(*p)) {
-                       if (ord(*++p) == ord('{' /*}*/))
+                       if (ord(*++p) == ORD('{' /*}*/))
                                ++count;
-                       else if ((ord(*p) == ord(/*{*/ '}') && --count == 0) ||
+                       else if ((ord(*p) == ORD(/*{*/ '}') && --count == 0) ||
                            (*p == ',' && count == 1)) {
                                char *news;
                                int l1, l2, l3;
index 56a42f6..8330174 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.199 2017/08/07 21:16:31 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.201 2017/10/11 21:09:24 tg Exp $");
 
 #ifndef MKSH_DEFAULT_EXECSHELL
 #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@@ -953,8 +953,12 @@ scriptexec(struct op *tp, const char **ap)
                }
 #ifdef __OS2__
                /*
-                * Search shell/interpreter name without directory in PATH
-                * if specified path does not exist
+                * On OS/2, the directory structure differs from normal
+                * Unix, which can make many scripts whose shebang
+                * hardcodes the path to an interpreter fail (and there
+                * might be no /usr/bin/env); for user convenience, if
+                * the specified interpreter is not usable, do a PATH
+                * search to find it.
                 */
                if (mksh_vdirsep(sh) && !search_path(sh, path, X_OK, NULL)) {
                        cp = search_path(_getname(sh), path, X_OK, NULL);
@@ -1168,11 +1172,7 @@ findcom(const char *name, int flags)
        char *fpath;
        union mksh_cchack npath;
 
-       if (mksh_vdirsep(name)
-#ifdef MKSH_DOSPATH
-           && (strcmp(name, T_builtin) != 0)
-#endif
-           ) {
+       if (mksh_vdirsep(name)) {
                insert = 0;
                /* prevent FPATH search below */
                flags &= ~FC_FUNC;
index 12989d4..499b961 100644 (file)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013, 2014, 2016, 2017
+ *              2011, 2012, 2013, 2014, 2016, 2017, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.100 2017/08/07 21:38:55 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.103 2018/01/14 01:29:47 tg Exp $");
 
 #define EXPRTOK_DEFNS
 #include "exprtok.h"
@@ -558,9 +558,11 @@ exprtoken(Expr_state *es)
 
        /* skip whitespace */
  skip_spaces:
-       while (ctype(ord((c = *cp)), C_SPACE))
-               ++cp;
-       if (es->tokp == es->expression && c == ord('#')) {
+       --cp;
+       do {
+               c = ord(*++cp);
+       } while (ctype(c, C_SPACE));
+       if (es->tokp == es->expression && (unsigned int)c == ORD('#')) {
                /* expression begins with # */
                /* switch to unsigned */
                es->natural = true;
@@ -575,7 +577,7 @@ exprtoken(Expr_state *es)
                do {
                        c = ord(*++cp);
                } while (ctype(c, C_ALNUX));
-               if (c == ord('[')) {
+               if ((unsigned int)c == ORD('[')) {
                        size_t len;
 
                        len = array_ref_len(cp);
@@ -884,7 +886,7 @@ static int mb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems,
 
 /*
  * Generated from the Unicode Character Database, Version 10.0.0, by
- * MirOS: contrib/code/Snippets/eawparse,v 1.10 2017/07/12 22:47:26 tg Exp $
+ * MirOS: contrib/code/Snippets/eawparse,v 1.12 2017/09/06 16:05:45 tg Exp $
  */
 
 static const struct mb_ucsrange mb_ucs_combining[] = {
@@ -895,16 +897,14 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0x05C1, 0x05C2 },
        { 0x05C4, 0x05C5 },
        { 0x05C7, 0x05C7 },
-       { 0x0600, 0x0605 },
        { 0x0610, 0x061A },
        { 0x061C, 0x061C },
        { 0x064B, 0x065F },
        { 0x0670, 0x0670 },
-       { 0x06D6, 0x06DD },
+       { 0x06D6, 0x06DC },
        { 0x06DF, 0x06E4 },
        { 0x06E7, 0x06E8 },
        { 0x06EA, 0x06ED },
-       { 0x070F, 0x070F },
        { 0x0711, 0x0711 },
        { 0x0730, 0x074A },
        { 0x07A6, 0x07B0 },
@@ -914,7 +914,8 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0x0825, 0x0827 },
        { 0x0829, 0x082D },
        { 0x0859, 0x085B },
-       { 0x08D4, 0x0902 },
+       { 0x08D4, 0x08E1 },
+       { 0x08E3, 0x0902 },
        { 0x093A, 0x093A },
        { 0x093C, 0x093C },
        { 0x0941, 0x0948 },
index 38e66f8..5179192 100644 (file)
@@ -38,7 +38,7 @@
 #endif
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.350 2017/05/05 22:53:28 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.353 2018/01/14 01:26:49 tg Exp $");
 
 #if HAVE_KILLPG
 /*
@@ -594,7 +594,7 @@ c_print(const char **wp)
 static int
 s_get(void)
 {
-       return (*s_ptr++);
+       return (ord(*s_ptr++));
 }
 
 static void
@@ -751,9 +751,9 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
 bool
 valid_alias_name(const char *cp)
 {
-       if (ord(*cp) == ord('-'))
+       if (ord(*cp) == ORD('-'))
                return (false);
-       if (ord(cp[0]) == ord('[') && ord(cp[1]) == ord('[') && !cp[2])
+       if (ord(cp[0]) == ORD('[') && ord(cp[1]) == ORD('[') && !cp[2])
                return (false);
        while (*cp)
                if (ctype(*cp, C_ALIAS))
@@ -2304,9 +2304,9 @@ c_unset(const char **wp)
                        size_t n;
 
                        n = strlen(id);
-                       if (n > 3 && ord(id[n - 3]) == ord('[') &&
-                           ord(id[n - 2]) == ord('*') &&
-                           ord(id[n - 1]) == ord(']')) {
+                       if (n > 3 && ord(id[n - 3]) == ORD('[') &&
+                           ord(id[n - 2]) == ORD('*') &&
+                           ord(id[n - 1]) == ORD(']')) {
                                strndupx(cp, id, n - 3, ATEMP);
                                id = cp;
                                optc = 3;
@@ -3539,7 +3539,7 @@ c_cat(const char **wp)
                                        continue;
                                }
                                if (errno == EPIPE) {
-                                       /* fake receiving signel */
+                                       /* fake receiving signal */
                                        rv = ksh_sigmask(SIGPIPE);
                                } else {
                                        /* an error occured during writing */
index 4df98b7..a0b9b79 100644 (file)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
- *              2012, 2013, 2014, 2015, 2016
+ *              2012, 2013, 2014, 2015, 2016, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.124 2017/08/08 14:30:10 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.125 2018/01/05 20:08:34 tg Exp $");
 
 #if HAVE_KILLPG
 #define mksh_killpg            killpg
@@ -1545,7 +1545,9 @@ j_print(Job *j, int how, struct shf *shf)
        Proc *p;
        int state;
        int status;
+#ifdef WCOREDUMP
        bool coredumped;
+#endif
        char jobchar = ' ';
        char buf[64];
        const char *filler;
@@ -1569,7 +1571,9 @@ j_print(Job *j, int how, struct shf *shf)
                jobchar = '-';
 
        for (p = j->proc_list; p != NULL;) {
+#ifdef WCOREDUMP
                coredumped = false;
+#endif
                switch (p->state) {
                case PRUNNING:
                        memcpy(buf, "Running", 8);
@@ -1603,7 +1607,10 @@ j_print(Job *j, int how, struct shf *shf)
                         * kludge for not reporting 'normal termination
                         * signals' (i.e. SIGINT, SIGPIPE)
                         */
-                       if (how == JP_SHORT && !coredumped &&
+                       if (how == JP_SHORT &&
+#ifdef WCOREDUMP
+                           !coredumped &&
+#endif
                            (termsig == SIGINT || termsig == SIGPIPE)) {
                                buf[0] = '\0';
                        } else
@@ -1629,14 +1636,22 @@ j_print(Job *j, int how, struct shf *shf)
                if (how == JP_SHORT) {
                        if (buf[0]) {
                                output = 1;
+#ifdef WCOREDUMP
                                shf_fprintf(shf, "%s%s ",
                                    buf, coredumped ? " (core dumped)" : null);
+#else
+                               shf_puts(buf, shf);
+                               shf_putchar(' ', shf);
+#endif
                        }
                } else {
                        output = 1;
                        shf_fprintf(shf, "%-20s %s%s%s", buf, p->command,
                            p->next ? "|" : null,
-                           coredumped ? " (core dumped)" : null);
+#ifdef WCOREDUMP
+                           coredumped ? " (core dumped)" :
+#endif
+                            null);
                }
 
                state = p->state;
index f450221..9300311 100644 (file)
--- a/src/lex.c
+++ b/src/lex.c
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013, 2014, 2015, 2016, 2017
+ *              2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.239 2017/05/05 22:53:29 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.247 2018/01/14 01:44:01 tg Exp $");
 
 /*
  * states while lexing word
@@ -127,11 +127,11 @@ static int ignore_backslash_newline;
 static int
 getsc_i(void)
 {
-       o_getsc_r(o_getsc());
+       o_getsc_r((unsigned int)(unsigned char)o_getsc());
 }
 
 #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
-#define getsc()                ord(getsc_i())
+#define getsc()                getsc_i()
 #else
 static int getsc_r(int);
 
@@ -141,7 +141,7 @@ getsc_r(int c)
        o_getsc_r(c);
 }
 
-#define getsc()                ord(getsc_r(o_getsc()))
+#define getsc()                getsc_r((unsigned int)(unsigned char)o_getsc())
 #endif
 
 #define STATE_BSIZE    8
@@ -220,12 +220,14 @@ yylex(int cf)
        } else {
                /* normal lexing */
                state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
-               while (ctype((c = getsc()), C_BLANK))
-                       ;
+               do {
+                       c = getsc();
+               } while (ctype(c, C_BLANK));
                if (c == '#') {
                        ignore_backslash_newline++;
-                       while (!ctype((c = getsc()), C_NUL | C_LF))
-                               ;
+                       do {
+                               c = getsc();
+                       } while (!ctype(c, C_NUL | C_LF));
                        ignore_backslash_newline--;
                }
                ungetsc(c);
@@ -245,30 +247,32 @@ yylex(int cf)
        while (!((c = getsc()) == 0 ||
            ((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
                if (state == SBASE &&
-                   subshell_nesting_type == ord(/*{*/ '}') &&
-                   c == ord(/*{*/ '}'))
+                   subshell_nesting_type == ORD(/*{*/ '}') &&
+                   (unsigned int)c == ORD(/*{*/ '}'))
                        /* possibly end ${ :;} */
                        break;
                Xcheck(ws, wp);
                switch (state) {
                case SADELIM:
-                       if (c == ord('('))
+                       if ((unsigned int)c == ORD('('))
                                statep->nparen++;
-                       else if (c == ord(')'))
+                       else if ((unsigned int)c == ORD(')'))
                                statep->nparen--;
-                       else if (statep->nparen == 0 && (c == ord(/*{*/ '}') ||
+                       else if (statep->nparen == 0 &&
+                           ((unsigned int)c == ORD(/*{*/ '}') ||
                            c == (int)statep->ls_adelim.delimiter)) {
                                *wp++ = ADELIM;
                                *wp++ = c;
-                               if (c == ord(/*{*/ '}') || --statep->ls_adelim.num == 0)
+                               if ((unsigned int)c == ORD(/*{*/ '}') ||
+                                   --statep->ls_adelim.num == 0)
                                        POP_STATE();
-                               if (c == ord(/*{*/ '}'))
+                               if ((unsigned int)c == ORD(/*{*/ '}'))
                                        POP_STATE();
                                break;
                        }
                        /* FALLTHROUGH */
                case SBASE:
-                       if (c == ord('[') && (cf & CMDASN)) {
+                       if ((unsigned int)c == ORD('[') && (cf & CMDASN)) {
                                /* temporary */
                                *wp = EOS;
                                if (is_wdvarname(Xstring(ws, wp), false)) {
@@ -284,15 +288,6 @@ yylex(int cf)
                                                }
                                                afree(tmp, ATEMP);
                                                break;
-                                       } else {
-                                               Source *s;
-
-                                               s = pushs(SREREAD,
-                                                   source->areap);
-                                               s->start = s->str =
-                                                   s->u.freeme = tmp;
-                                               s->next = source;
-                                               source = s;
                                        }
                                }
                                *wp++ = CHAR;
@@ -303,7 +298,7 @@ yylex(int cf)
  Sbase1:               /* includes *(...|...) pattern (*+?@!) */
                        if (ctype(c, C_PATMO)) {
                                c2 = getsc();
-                               if (c2 == ord('(' /*)*/)) {
+                               if ((unsigned int)c2 == ORD('(' /*)*/)) {
                                        *wp++ = OPAT;
                                        *wp++ = c;
                                        PUSH_STATE(SPATTERN);
@@ -314,7 +309,7 @@ yylex(int cf)
                        /* FALLTHROUGH */
  Sbase2:               /* doesn't include *(...|...) pattern (*+?@!) */
                        switch (c) {
-                       case ord('\\'):
+                       case ORD('\\'):
  getsc_qchar:
                                if ((c = getsc())) {
                                        /* trailing \ is lost */
@@ -322,7 +317,7 @@ yylex(int cf)
                                        *wp++ = c;
                                }
                                break;
-                       case ord('\''):
+                       case ORD('\''):
  open_ssquote_unless_heredoc:
                                if ((cf & HEREDOC))
                                        goto store_char;
@@ -330,12 +325,12 @@ yylex(int cf)
                                ignore_backslash_newline++;
                                PUSH_STATE(SSQUOTE);
                                break;
-                       case ord('"'):
+                       case ORD('"'):
  open_sdquote:
                                *wp++ = OQUOTE;
                                PUSH_STATE(SDQUOTE);
                                break;
-                       case ord('$'):
+                       case ORD('$'):
                                /*
                                 * processing of dollar sign belongs into
                                 * Subst, except for those which can open
@@ -344,9 +339,9 @@ yylex(int cf)
  subst_dollar_ex:
                                c = getsc();
                                switch (c) {
-                               case ord('"'):
+                               case ORD('"'):
                                        goto open_sdquote;
-                               case ord('\''):
+                               case ORD('\''):
                                        goto open_sequote;
                                default:
                                        goto SubstS;
@@ -358,16 +353,16 @@ yylex(int cf)
 
  Subst:
                        switch (c) {
-                       case ord('\\'):
+                       case ORD('\\'):
                                c = getsc();
                                switch (c) {
-                               case ord('"'):
+                               case ORD('"'):
                                        if ((cf & HEREDOC))
                                                goto heredocquote;
                                        /* FALLTHROUGH */
-                               case ord('\\'):
-                               case ord('$'):
-                               case ord('`'):
+                               case ORD('\\'):
+                               case ORD('$'):
+                               case ORD('`'):
  store_qchar:
                                        *wp++ = QCHAR;
                                        *wp++ = c;
@@ -385,12 +380,12 @@ yylex(int cf)
                                        break;
                                }
                                break;
-                       case ord('$'):
+                       case ORD('$'):
                                c = getsc();
  SubstS:
-                               if (c == ord('(' /*)*/)) {
+                               if ((unsigned int)c == ORD('(' /*)*/)) {
                                        c = getsc();
-                                       if (c == ord('(' /*)*/)) {
+                                       if ((unsigned int)c == ORD('(' /*)*/)) {
                                                *wp++ = EXPRSUB;
                                                PUSH_SRETRACE(SASPAREN);
                                                statep->nparen = 2;
@@ -407,8 +402,8 @@ yylex(int cf)
                                                memcpy(wp, sp, cz);
                                                wp += cz;
                                        }
-                               } else if (c == ord('{' /*}*/)) {
-                                       if ((c = getsc()) == ord('|')) {
+                               } else if ((unsigned int)c == ORD('{' /*}*/)) {
+                                       if ((unsigned int)(c = getsc()) == ORD('|')) {
                                                /*
                                                 * non-subenvironment
                                                 * value substitution
@@ -429,11 +424,11 @@ yylex(int cf)
                                        wp = get_brace_var(&ws, wp);
                                        c = getsc();
                                        /* allow :# and :% (ksh88 compat) */
-                                       if (c == ord(':')) {
+                                       if ((unsigned int)c == ORD(':')) {
                                                *wp++ = CHAR;
                                                *wp++ = c;
                                                c = getsc();
-                                               if (c == ord(':')) {
+                                               if ((unsigned int)c == ORD(':')) {
                                                        *wp++ = CHAR;
                                                        *wp++ = '0';
                                                        *wp++ = ADELIM;
@@ -465,7 +460,7 @@ yylex(int cf)
  parse_adelim_slash:
                                                *wp++ = CHAR;
                                                *wp++ = c;
-                                               if ((c = getsc()) == ord('/')) {
+                                               if ((unsigned int)(c = getsc()) == ORD('/')) {
                                                        *wp++ = c2;
                                                        *wp++ = c;
                                                } else
@@ -479,7 +474,7 @@ yylex(int cf)
                                        } else if (c == '@') {
                                                c2 = getsc();
                                                ungetsc(c2);
-                                               if (c2 == ord('/')) {
+                                               if ((unsigned int)c2 == ORD('/')) {
                                                        c2 = CHAR;
                                                        goto parse_adelim_slash;
                                                }
@@ -528,7 +523,7 @@ yylex(int cf)
                                        ungetsc(c);
                                }
                                break;
-                       case ord('`'):
+                       case ORD('`'):
  subst_gravis:
                                PUSH_STATE(SBQUOTE);
                                *wp++ = COMASUB;
@@ -572,11 +567,11 @@ yylex(int cf)
                        break;
 
                case SEQUOTE:
-                       if (c == ord('\'')) {
+                       if ((unsigned int)c == ORD('\'')) {
                                POP_STATE();
                                *wp++ = CQUOTE;
                                ignore_backslash_newline--;
-                       } else if (c == ord('\\')) {
+                       } else if ((unsigned int)c == ORD('\\')) {
                                if ((c2 = unbksl(true, getsc_i, ungetsc)) == -1)
                                        c2 = getsc();
                                if (c2 == 0)
@@ -604,7 +599,7 @@ yylex(int cf)
                        break;
 
                case SSQUOTE:
-                       if (c == ord('\'')) {
+                       if ((unsigned int)c == ORD('\'')) {
                                POP_STATE();
                                if ((cf & HEREDOC) || state == SQBRACE)
                                        goto store_char;
@@ -617,7 +612,7 @@ yylex(int cf)
                        break;
 
                case SDQUOTE:
-                       if (c == ord('"')) {
+                       if ((unsigned int)c == ORD('"')) {
                                POP_STATE();
                                *wp++ = CQUOTE;
                        } else
@@ -626,15 +621,15 @@ yylex(int cf)
 
                /* $(( ... )) */
                case SASPAREN:
-                       if (c == ord('('))
+                       if ((unsigned int)c == ORD('('))
                                statep->nparen++;
-                       else if (c == ord(')')) {
+                       else if ((unsigned int)c == ORD(')')) {
                                statep->nparen--;
                                if (statep->nparen == 1) {
                                        /* end of EXPRSUB */
                                        POP_SRETRACE();
 
-                                       if ((c2 = getsc()) == ord(/*(*/ ')')) {
+                                       if ((unsigned int)(c2 = getsc()) == ORD(/*(*/ ')')) {
                                                cz = strlen(sp) - 2;
                                                XcheckN(ws, wp, cz);
                                                memcpy(wp, sp + 1, cz);
@@ -666,7 +661,7 @@ yylex(int cf)
                        goto Sbase2;
 
                case SQBRACE:
-                       if (c == ord('\\')) {
+                       if ((unsigned int)c == ORD('\\')) {
                                /*
                                 * perform POSIX "quote removal" if the back-
                                 * slash is "special", i.e. same cases as the
@@ -675,26 +670,28 @@ yylex(int cf)
                                 * write QCHAR+c, otherwise CHAR+\+CHAR+c are
                                 * emitted (in heredocquote:)
                                 */
-                               if ((c = getsc()) == ord('"') || c == ord('\\') ||
-                                   ctype(c, C_DOLAR | C_GRAVE) || c == ord(/*{*/ '}'))
+                               if ((unsigned int)(c = getsc()) == ORD('"') ||
+                                   (unsigned int)c == ORD('\\') ||
+                                   ctype(c, C_DOLAR | C_GRAVE) ||
+                                   (unsigned int)c == ORD(/*{*/ '}'))
                                        goto store_qchar;
                                goto heredocquote;
                        }
                        goto common_SQBRACE;
 
                case SBRACE:
-                       if (c == ord('\''))
+                       if ((unsigned int)c == ORD('\''))
                                goto open_ssquote_unless_heredoc;
-                       else if (c == ord('\\'))
+                       else if ((unsigned int)c == ORD('\\'))
                                goto getsc_qchar;
  common_SQBRACE:
-                       if (c == ord('"'))
+                       if ((unsigned int)c == ORD('"'))
                                goto open_sdquote;
-                       else if (c == ord('$'))
+                       else if ((unsigned int)c == ORD('$'))
                                goto subst_dollar_ex;
-                       else if (c == ord('`'))
+                       else if ((unsigned int)c == ORD('`'))
                                goto subst_gravis;
-                       else if (c != ord(/*{*/ '}'))
+                       else if ((unsigned int)c != ORD(/*{*/ '}'))
                                goto store_char;
                        POP_STATE();
                        *wp++ = CSUBST;
@@ -703,16 +700,16 @@ yylex(int cf)
 
                /* Same as SBASE, except (,|,) treated specially */
                case STBRACEKORN:
-                       if (c == ord('|'))
+                       if ((unsigned int)c == ORD('|'))
                                *wp++ = SPAT;
-                       else if (c == ord('(')) {
+                       else if ((unsigned int)c == ORD('(')) {
                                *wp++ = OPAT;
                                /* simile for @ */
                                *wp++ = ' ';
                                PUSH_STATE(SPATTERN);
                        } else /* FALLTHROUGH */
                case STBRACEBOURNE:
-                         if (c == ord(/*{*/ '}')) {
+                         if ((unsigned int)c == ORD(/*{*/ '}')) {
                                POP_STATE();
                                *wp++ = CSUBST;
                                *wp++ = /*{*/ '}';
@@ -721,20 +718,20 @@ yylex(int cf)
                        break;
 
                case SBQUOTE:
-                       if (c == ord('`')) {
+                       if ((unsigned int)c == ORD('`')) {
                                *wp++ = 0;
                                POP_STATE();
-                       } else if (c == ord('\\')) {
+                       } else if ((unsigned int)c == ORD('\\')) {
                                switch (c = getsc()) {
                                case 0:
                                        /* trailing \ is lost */
                                        break;
-                               case ord('$'):
-                               case ord('`'):
-                               case ord('\\'):
+                               case ORD('$'):
+                               case ORD('`'):
+                               case ORD('\\'):
                                        *wp++ = c;
                                        break;
-                               case ord('"'):
+                               case ORD('"'):
                                        if (statep->ls_bool) {
                                                *wp++ = c;
                                                break;
@@ -755,10 +752,10 @@ yylex(int cf)
 
                /* LETEXPR: (( ... )) */
                case SLETPAREN:
-                       if (c == ord(/*(*/ ')')) {
+                       if ((unsigned int)c == ORD(/*(*/ ')')) {
                                if (statep->nparen > 0)
                                        --statep->nparen;
-                               else if ((c2 = getsc()) == ord(/*(*/ ')')) {
+                               else if ((unsigned int)(c2 = getsc()) == ORD(/*(*/ ')')) {
                                        c = 0;
                                        *wp++ = CQUOTE;
                                        goto Done;
@@ -780,9 +777,9 @@ yylex(int cf)
                                        s->next = source;
                                        source = s;
                                        ungetsc('(' /*)*/);
-                                       return (ord('(' /*)*/));
+                                       return (ORD('(' /*)*/));
                                }
-                       } else if (c == ord('('))
+                       } else if ((unsigned int)c == ORD('('))
                                /*
                                 * parentheses inside quotes and
                                 * backslashes are lost, but AT&T ksh
@@ -798,26 +795,26 @@ yylex(int cf)
                         * $ and `...` are not to be treated specially
                         */
                        switch (c) {
-                       case ord('\\'):
+                       case ORD('\\'):
                                if ((c = getsc())) {
                                        /* trailing \ is lost */
                                        *wp++ = QCHAR;
                                        *wp++ = c;
                                }
                                break;
-                       case ord('\''):
+                       case ORD('\''):
                                goto open_ssquote_unless_heredoc;
-                       case ord('$'):
-                               if ((c2 = getsc()) == ord('\'')) {
+                       case ORD('$'):
+                               if ((unsigned int)(c2 = getsc()) == ORD('\'')) {
  open_sequote:
                                        *wp++ = OQUOTE;
                                        ignore_backslash_newline++;
                                        PUSH_STATE(SEQUOTE);
                                        statep->ls_bool = false;
                                        break;
-                               } else if (c2 == ord('"')) {
+                               } else if ((unsigned int)c2 == ORD('"')) {
                                        /* FALLTHROUGH */
-                       case ord('"'):
+                       case ORD('"'):
                                        PUSH_SRETRACE(SHEREDQUOTE);
                                        break;
                                }
@@ -831,7 +828,7 @@ yylex(int cf)
 
                /* " in << or <<- delimiter */
                case SHEREDQUOTE:
-                       if (c != ord('"'))
+                       if ((unsigned int)c != ORD('"'))
                                goto Subst;
                        POP_SRETRACE();
                        dp = strnul(sp) - 1;
@@ -844,10 +841,10 @@ yylex(int cf)
                        while ((c = *dp++)) {
                                if (c == '\\') {
                                        switch ((c = *dp++)) {
-                                       case ord('\\'):
-                                       case ord('"'):
-                                       case ord('$'):
-                                       case ord('`'):
+                                       case ORD('\\'):
+                                       case ORD('"'):
+                                       case ORD('$'):
+                                       case ORD('`'):
                                                break;
                                        default:
                                                *wp++ = CHAR;
@@ -865,12 +862,12 @@ yylex(int cf)
 
                /* in *(...|...) pattern (*+?@!) */
                case SPATTERN:
-                       if (c == ord(/*(*/ ')')) {
+                       if ((unsigned int)c == ORD(/*(*/ ')')) {
                                *wp++ = CPAT;
                                POP_STATE();
-                       } else if (c == ord('|')) {
+                       } else if ((unsigned int)c == ORD('|')) {
                                *wp++ = SPAT;
-                       } else if (c == ord('(')) {
+                       } else if ((unsigned int)c == ORD('(')) {
                                *wp++ = OPAT;
                                /* simile for @ */
                                *wp++ = ' ';
@@ -900,7 +897,7 @@ yylex(int cf)
                iop->unit = c2 == 2 ? ksh_numdig(dp[1]) : c == '<' ? 0 : 1;
 
                if (c == '&') {
-                       if ((c2 = getsc()) != ord('>')) {
+                       if ((unsigned int)(c2 = getsc()) != ORD('>')) {
                                ungetsc(c2);
                                goto no_iop;
                        }
@@ -911,22 +908,23 @@ yylex(int cf)
 
                c2 = getsc();
                /* <<, >>, <> are ok, >< is not */
-               if (c == c2 || (c == ord('<') && c2 == ord('>'))) {
+               if (c == c2 || ((unsigned int)c == ORD('<') &&
+                   (unsigned int)c2 == ORD('>'))) {
                        iop->ioflag |= c == c2 ?
-                           (c == ord('>') ? IOCAT : IOHERE) : IORDWR;
+                           ((unsigned int)c == ORD('>') ? IOCAT : IOHERE) : IORDWR;
                        if (iop->ioflag == IOHERE) {
-                               if ((c2 = getsc()) == ord('-'))
+                               if ((unsigned int)(c2 = getsc()) == ORD('-'))
                                        iop->ioflag |= IOSKIP;
-                               else if (c2 == ord('<'))
+                               else if ((unsigned int)c2 == ORD('<'))
                                        iop->ioflag |= IOHERESTR;
                                else
                                        ungetsc(c2);
                        }
-               } else if (c2 == ord('&'))
-                       iop->ioflag |= IODUP | (c == ord('<') ? IORDUP : 0);
+               } else if ((unsigned int)c2 == ORD('&'))
+                       iop->ioflag |= IODUP | ((unsigned int)c == ORD('<') ? IORDUP : 0);
                else {
-                       iop->ioflag |= c == ord('>') ? IOWRITE : IOREAD;
-                       if (c == ord('>') && c2 == ord('|'))
+                       iop->ioflag |= (unsigned int)c == ORD('>') ? IOWRITE : IOREAD;
+                       if ((unsigned int)c == ORD('>') && (unsigned int)c2 == ORD('|'))
                                iop->ioflag |= IOCLOB;
                        else
                                ungetsc(c2);
@@ -947,30 +945,32 @@ yylex(int cf)
                /* free word */
                Xfree(ws, wp);
                /* no word, process LEX1 character */
-               if ((c == ord('|')) || (c == ord('&')) || (c == ord(';')) ||
-                   (c == ord('(' /*)*/))) {
+               if (((unsigned int)c == ORD('|')) ||
+                   ((unsigned int)c == ORD('&')) ||
+                   ((unsigned int)c == ORD(';')) ||
+                   ((unsigned int)c == ORD('(' /*)*/))) {
                        if ((c2 = getsc()) == c)
-                               c = (c == ord(';')) ? BREAK :
-                                   (c == ord('|')) ? LOGOR :
-                                   (c == ord('&')) ? LOGAND :
-                                   /* c == ord('(' )) */ MDPAREN;
-                       else if (c == ord('|') && c2 == ord('&'))
+                               c = ((unsigned int)c == ORD(';')) ? BREAK :
+                                   ((unsigned int)c == ORD('|')) ? LOGOR :
+                                   ((unsigned int)c == ORD('&')) ? LOGAND :
+                                   /* (unsigned int)c == ORD('(' )) */ MDPAREN;
+                       else if ((unsigned int)c == ORD('|') && (unsigned int)c2 == ORD('&'))
                                c = COPROC;
-                       else if (c == ord(';') && c2 == ord('|'))
+                       else if ((unsigned int)c == ORD(';') && (unsigned int)c2 == ORD('|'))
                                c = BRKEV;
-                       else if (c == ord(';') && c2 == ord('&'))
+                       else if ((unsigned int)c == ORD(';') && (unsigned int)c2 == ORD('&'))
                                c = BRKFT;
                        else
                                ungetsc(c2);
 #ifndef MKSH_SMALL
                        if (c == BREAK) {
-                               if ((c2 = getsc()) == ord('&'))
+                               if ((unsigned int)(c2 = getsc()) == ORD('&'))
                                        c = BRKEV;
                                else
                                        ungetsc(c2);
                        }
 #endif
-               } else if (c == ord('\n')) {
+               } else if ((unsigned int)c == ORD('\n')) {
                        if (cf & HEREDELIM)
                                ungetsc(c);
                        else {
@@ -1025,7 +1025,7 @@ yylex(int cf)
 
                if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) &&
                    (!(cf & ESACONLY) || p->val.i == ESAC ||
-                   p->val.i == ord(/*{*/ '}'))) {
+                   (unsigned int)p->val.i == ORD(/*{*/ '}'))) {
                        afree(yylval.cp, ATEMP);
                        return (p->val.i);
                }
@@ -1136,7 +1136,7 @@ readhere(struct ioword *iop)
        if (!*eofp) {
                /* end of here document marker, what to do? */
                switch (c) {
-               case ord(/*(*/ ')'):
+               case ORD(/*(*/ ')'):
                        if (!subshell_nesting_type)
                                /*-
                                 * not allowed outside $(...) or (...)
@@ -1151,7 +1151,7 @@ readhere(struct ioword *iop)
                         * Allow EOF here to commands without trailing
                         * newlines (mksh -c '...') will work as well.
                         */
-               case ord('\n'):
+               case ORD('\n'):
                        /* Newline terminates here document marker */
                        goto heredoc_found_terminator;
                }
@@ -1580,7 +1580,7 @@ get_brace_var(XString *wsp, char *wp)
 
                                c2 = getsc();
                                ungetsc(c2);
-                               if (ord(c2) != ord(/*{*/ '}')) {
+                               if (ord(c2) != ORD(/*{*/ '}')) {
                                        ungetsc(c);
                                        goto out;
                                }
@@ -1588,22 +1588,22 @@ get_brace_var(XString *wsp, char *wp)
                        goto ps_common;
                case PS_SAW_BANG:
                        switch (ord(c)) {
-                       case ord('@'):
-                       case ord('#'):
-                       case ord('-'):
-                       case ord('?'):
+                       case ORD('@'):
+                       case ORD('#'):
+                       case ORD('-'):
+                       case ORD('?'):
                                goto out;
                        }
                        goto ps_common;
                case PS_INITIAL:
                        switch (ord(c)) {
-                       case ord('%'):
+                       case ORD('%'):
                                state = PS_SAW_PERCENT;
                                goto next;
-                       case ord('#'):
+                       case ORD('#'):
                                state = PS_SAW_HASH;
                                goto next;
-                       case ord('!'):
+                       case ORD('!'):
                                state = PS_SAW_BANG;
                                goto next;
                        }
@@ -1621,7 +1621,7 @@ get_brace_var(XString *wsp, char *wp)
                        break;
                case PS_IDENT:
                        if (!ctype(c, C_ALNUX)) {
-                               if (ord(c) == ord('[')) {
+                               if (ord(c) == ORD('[')) {
                                        char *tmp, *p;
 
                                        if (!arraysub(&tmp))
@@ -1676,9 +1676,9 @@ arraysub(char **strp)
                c = getsc();
                Xcheck(ws, wp);
                *wp++ = c;
-               if (ord(c) == ord('['))
+               if (ord(c) == ORD('['))
                        depth++;
-               else if (ord(c) == ord(']'))
+               else if (ord(c) == ORD(']'))
                        depth--;
        } while (depth > 0 && c && c != '\n');
 
index b4d7244..ad20c94 100644 (file)
@@ -5,7 +5,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013, 2014, 2015, 2016, 2017
+ *              2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -34,9 +34,7 @@
 #include <locale.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.342 2017/04/28 11:13:47 tg Exp $");
-
-extern char **environ;
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.347 2018/01/13 21:45:07 tg Exp $");
 
 #ifndef MKSHRC_PATH
 #define MKSHRC_PATH    "~/.mkshrc"
@@ -52,6 +50,7 @@ void chvt_reinit(void);
 static void reclaim(void);
 static void remove_temps(struct temp *);
 static mksh_uari_t rndsetup(void);
+static void init_environ(void);
 #ifdef SIGWINCH
 static void x_sigwinch(int);
 #endif
@@ -242,10 +241,6 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
        set_ifs(TC_IFSWS);
 
 #ifdef __OS2__
-       for (i = 0; i < 3; ++i)
-               if (!isatty(i))
-                       setmode(i, O_BINARY);
-
        os2_init(&argc, &argv);
 #endif
 
@@ -401,14 +396,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
 #endif
 
        /* import environment */
-       if (environ != NULL) {
-               wp = (const char **)environ;
-               while (*wp != NULL) {
-                       rndpush(*wp);
-                       typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
-                       ++wp;
-               }
-       }
+       init_environ();
 
        /* override default PATH regardless of environment */
 #ifdef MKSH_DEFPATH_OVERRIDE
@@ -671,8 +659,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
                if (Flag(FLOGIN))
                        include(substitute("$HOME/.profile", 0), 0, NULL, true);
                if (Flag(FTALKING)) {
-                       cp = substitute(substitute("${ENV:-" MKSHRC_PATH "}",
-                           0), DOTILDE);
+                       cp = substitute("${ENV:-" MKSHRC_PATH "}", DOTILDE);
                        if (cp[0] != '\0')
                                include(cp, 0, NULL, true);
                }
@@ -1987,3 +1974,111 @@ x_mkraw(int fd, mksh_ttyst *ocb, bool forread)
 
        mksh_tcset(fd, &cb);
 }
+
+#ifdef MKSH_ENVDIR
+static void
+init_environ(void)
+{
+       char *xp;
+       ssize_t n;
+       XString xs;
+       struct shf *shf;
+       DIR *dirp;
+       struct dirent *dent;
+
+       if ((dirp = opendir(MKSH_ENVDIR)) == NULL) {
+               warningf(false, "cannot read environment from %s: %s",
+                   MKSH_ENVDIR, cstrerror(errno));
+               return;
+       }
+       XinitN(xs, 256, ATEMP);
+ read_envfile:
+       errno = 0;
+       if ((dent = readdir(dirp)) != NULL) {
+               if (skip_varname(dent->d_name, true)[0] == '\0') {
+                       xp = shf_smprintf(Tf_sSs, MKSH_ENVDIR, dent->d_name);
+                       if (!(shf = shf_open(xp, O_RDONLY, 0, 0))) {
+                               warningf(false,
+                                   "cannot read environment %s from %s: %s",
+                                   dent->d_name, MKSH_ENVDIR,
+                                   cstrerror(errno));
+                               goto read_envfile;
+                       }
+                       afree(xp, ATEMP);
+                       n = strlen(dent->d_name);
+                       xp = Xstring(xs, xp);
+                       XcheckN(xs, xp, n + 32);
+                       memcpy(xp, dent->d_name, n);
+                       xp += n;
+                       *xp++ = '=';
+                       while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) {
+                               xp += n;
+                               if (Xnleft(xs, xp) <= 0)
+                                       XcheckN(xs, xp, Xlength(xs, xp));
+                       }
+                       if (n < 0) {
+                               warningf(false,
+                                   "cannot read environment %s from %s: %s",
+                                   dent->d_name, MKSH_ENVDIR,
+                                   cstrerror(shf_errno(shf)));
+                       } else {
+                               *xp = '\0';
+                               xp = Xstring(xs, xp);
+                               rndpush(xp);
+                               typeset(xp, IMPORT | EXPORT, 0, 0, 0);
+                       }
+                       shf_close(shf);
+               }
+               goto read_envfile;
+       } else if (errno)
+               warningf(false, "cannot read environment from %s: %s",
+                   MKSH_ENVDIR, cstrerror(errno));
+       closedir(dirp);
+       Xfree(xs, xp);
+}
+#else
+extern char **environ;
+
+static void
+init_environ(void)
+{
+       const char **wp;
+
+       if (environ == NULL)
+               return;
+
+       wp = (const char **)environ;
+       while (*wp != NULL) {
+               rndpush(*wp);
+               typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
+               ++wp;
+       }
+}
+#endif
+
+#ifdef MKSH_EARLY_LOCALE_TRACKING
+void
+recheck_ctype(void)
+{
+       const char *ccp;
+
+       ccp = str_val(global("LC_ALL"));
+       if (ccp == null)
+               ccp = str_val(global("LC_CTYPE"));
+       if (ccp == null)
+               ccp = str_val(global("LANG"));
+       UTFMODE = isuc(ccp);
+#if HAVE_SETLOCALE_CTYPE
+       ccp = setlocale(LC_CTYPE, ccp);
+#if HAVE_LANGINFO_CODESET
+       if (!isuc(ccp))
+               ccp = nl_langinfo(CODESET);
+#endif
+       if (isuc(ccp))
+               UTFMODE = 1;
+#endif
+
+       if (Flag(FPOSIX))
+               warningf(true, "early locale tracking enabled UTF-8 mode while in POSIX mode, you are now noncompliant");
+}
+#endif
index 1205072..e51dcb1 100644 (file)
@@ -32,7 +32,7 @@
 #include <grp.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.279 2017/08/07 21:39:25 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.291 2018/01/14 00:03:03 tg Exp $");
 
 #define KSH_CHVT_FLAG
 #ifdef MKSH_SMALL
@@ -696,14 +696,14 @@ has_globbing(const char *pat)
                if (!(c = *p++))
                        return (false);
                /* some specials */
-               if (ord(c) == ord('*') || ord(c) == ord('?')) {
+               if (ord(c) == ORD('*') || ord(c) == ORD('?')) {
                        /* easy glob, accept */
                        saw_glob = true;
-               } else if (ord(c) == ord('[')) {
+               } else if (ord(c) == ORD('[')) {
                        /* bracket expression; eat negation and initial ] */
-                       if (ISMAGIC(p[0]) && ord(p[1]) == ord('!'))
+                       if (ISMAGIC(p[0]) && ord(p[1]) == ORD('!'))
                                p += 2;
-                       if (ISMAGIC(p[0]) && ord(p[1]) == ord(']'))
+                       if (ISMAGIC(p[0]) && ord(p[1]) == ORD(']'))
                                p += 2;
                        /* check next string part */
                        s = p;
@@ -715,27 +715,27 @@ has_globbing(const char *pat)
                                if (!(c = *s++))
                                        return (false);
                                /* terminating bracket? */
-                               if (ord(c) == ord(']')) {
+                               if (ord(c) == ORD(']')) {
                                        /* accept and continue */
                                        p = s;
                                        saw_glob = true;
                                        break;
                                }
                                /* sub-bracket expressions */
-                               if (ord(c) == ord('[') && (
+                               if (ord(c) == ORD('[') && (
                                    /* collating element? */
-                                   ord(*s) == ord('.') ||
+                                   ord(*s) == ORD('.') ||
                                    /* equivalence class? */
-                                   ord(*s) == ord('=') ||
+                                   ord(*s) == ORD('=') ||
                                    /* character class? */
-                                   ord(*s) == ord(':'))) {
+                                   ord(*s) == ORD(':'))) {
                                        /* must stop with exactly the same c */
                                        subc = *s++;
                                        /* arbitrarily many chars in betwixt */
                                        while ((c = *s++))
                                                /* but only this sequence... */
                                                if (c == subc && ISMAGIC(*s) &&
-                                                   ord(s[1]) == ord(']')) {
+                                                   ord(s[1]) == ORD(']')) {
                                                        /* accept, terminate */
                                                        s += 2;
                                                        break;
@@ -751,7 +751,7 @@ has_globbing(const char *pat)
                        /* opening pattern */
                        saw_glob = true;
                        ++nest;
-               } else if (ord(c) == ord(/*(*/ ')')) {
+               } else if (ord(c) == ORD(/*(*/ ')')) {
                        /* closing pattern */
                        if (nest)
                                --nest;
@@ -785,24 +785,24 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
                        continue;
                }
                switch (ord(*p++)) {
-               case ord('['):
+               case ORD('['):
                        /* BSD cclass extension? */
-                       if (ISMAGIC(p[0]) && ord(p[1]) == ord('[') &&
-                           ord(p[2]) == ord(':') &&
+                       if (ISMAGIC(p[0]) && ord(p[1]) == ORD('[') &&
+                           ord(p[2]) == ORD(':') &&
                            ctype((pc = p[3]), C_ANGLE) &&
-                           ord(p[4]) == ord(':') &&
-                           ISMAGIC(p[5]) && ord(p[6]) == ord(']') &&
-                           ISMAGIC(p[7]) && ord(p[8]) == ord(']')) {
+                           ord(p[4]) == ORD(':') &&
+                           ISMAGIC(p[5]) && ord(p[6]) == ORD(']') &&
+                           ISMAGIC(p[7]) && ord(p[8]) == ORD(']')) {
                                /* zero-length match */
                                --s;
                                p += 9;
                                /* word begin? */
-                               if (ord(pc) == ord('<') &&
+                               if (ord(pc) == ORD('<') &&
                                    !ctype(sl, C_ALNUX) &&
                                    ctype(sc, C_ALNUX))
                                        break;
                                /* word end? */
-                               if (ord(pc) == ord('>') &&
+                               if (ord(pc) == ORD('>') &&
                                    ctype(sl, C_ALNUX) &&
                                    !ctype(sc, C_ALNUX))
                                        break;
@@ -813,7 +813,7 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
                                return (0);
                        break;
 
-               case ord('?'):
+               case ORD('?'):
                        if (sc == 0)
                                return (0);
                        if (UTFMODE) {
@@ -822,7 +822,7 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
                        }
                        break;
 
-               case ord('*'):
+               case ORD('*'):
                        if (p == pe)
                                return (1);
                        s--;
@@ -838,14 +838,14 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
                 */
 
                /* matches one or more times */
-               case 0x80|ord('+'):
+               case ORD('+') | 0x80:
                /* matches zero or more times */
-               case 0x80|ord('*'):
+               case ORD('*') | 0x80:
                        if (!(prest = pat_scan(p, pe, false)))
                                return (0);
                        s--;
                        /* take care of zero matches */
-                       if (ord(p[-1]) == (0x80 | ord('*')) &&
+                       if (ord(p[-1]) == (0x80 | ORD('*')) &&
                            do_gmatch(s, se, prest, pe, smin))
                                return (1);
                        for (psub = p; ; psub = pnext) {
@@ -863,16 +863,16 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
                        return (0);
 
                /* matches zero or once */
-               case 0x80|ord('?'):
+               case ORD('?') | 0x80:
                /* matches one of the patterns */
-               case 0x80|ord('@'):
+               case ORD('@') | 0x80:
                /* simile for @ */
-               case 0x80|ord(' '):
+               case ORD(' ') | 0x80:
                        if (!(prest = pat_scan(p, pe, false)))
                                return (0);
                        s--;
                        /* Take care of zero matches */
-                       if (ord(p[-1]) == (0x80 | ord('?')) &&
+                       if (ord(p[-1]) == (0x80 | ORD('?')) &&
                            do_gmatch(s, se, prest, pe, smin))
                                return (1);
                        for (psub = p; ; psub = pnext) {
@@ -889,7 +889,7 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
                        return (0);
 
                /* matches none of the patterns */
-               case 0x80|ord('!'):
+               case ORD('!') | 0x80:
                        if (!(prest = pat_scan(p, pe, false)))
                                return (0);
                        s--;
@@ -966,12 +966,12 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
        char *subp;
 
        /* check for negation */
-       if (ISMAGIC(p[0]) && ord(p[1]) == ord('!')) {
+       if (ISMAGIC(p[0]) && ord(p[1]) == ORD('!')) {
                p += 2;
                negated = true;
        }
        /* make initial ] non-MAGIC */
-       if (ISMAGIC(p[0]) && ord(p[1]) == ord(']'))
+       if (ISMAGIC(p[0]) && ord(p[1]) == ORD(']'))
                ++p;
        /* iterate over bracket expression, debunk()ing on the fly */
        while ((c = *p++)) {
@@ -982,18 +982,18 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
                        if (!(c = *p++))
                                break;
                        /* terminating bracket? */
-                       if (ord(c) == ord(']')) {
+                       if (ord(c) == ORD(']')) {
                                /* accept and return */
                                return (found != negated ? p : NULL);
                        }
                        /* sub-bracket expressions */
-                       if (ord(c) == ord('[') && (
+                       if (ord(c) == ORD('[') && (
                            /* collating element? */
-                           ord(*p) == ord('.') ||
+                           ord(*p) == ORD('.') ||
                            /* equivalence class? */
-                           ord(*p) == ord('=') ||
+                           ord(*p) == ORD('=') ||
                            /* character class? */
-                           ord(*p) == ord(':'))) {
+                           ord(*p) == ORD(':'))) {
                                /* must stop with exactly the same c */
                                subc = *p++;
                                /* save away start of substring */
@@ -1002,7 +1002,7 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
                                while ((c = *p++))
                                        /* but only this sequence... */
                                        if (c == subc && ISMAGIC(*p) &&
-                                           ord(p[1]) == ord(']')) {
+                                           ord(p[1]) == ORD(']')) {
                                                /* accept, terminate */
                                                p += 2;
                                                break;
@@ -1015,7 +1015,7 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
                                debunk(subp, subp, p - s - 3 + 1);
  cclass_common:
                                /* whither subexpression */
-                               if (ord(subc) == ord(':')) {
+                               if (ord(subc) == ORD(':')) {
                                        const struct cclass *cls = cclasses;
 
                                        /* search for name in cclass list */
@@ -1055,9 +1055,9 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
                        }
                }
                /* range expression? */
-               if (!(ISMAGIC(p[0]) && ord(p[1]) == ord('-') &&
+               if (!(ISMAGIC(p[0]) && ord(p[1]) == ORD('-') &&
                    /* not terminating bracket? */
-                   (!ISMAGIC(p[2]) || ord(p[3]) != ord(']')))) {
+                   (!ISMAGIC(p[2]) || ord(p[3]) != ORD(']')))) {
                        /* no, check single match */
                        if (sc == c)
                                /* note: sc is never NUL */
@@ -1079,13 +1079,13 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
                        if (!(c = *p++))
                                break;
                        /* sub-bracket expressions */
-                       if (ord(c) == ord('[') && (
+                       if (ord(c) == ORD('[') && (
                            /* collating element? */
-                           ord(*p) == ord('.') ||
+                           ord(*p) == ORD('.') ||
                            /* equivalence class? */
-                           ord(*p) == ord('=') ||
+                           ord(*p) == ORD('=') ||
                            /* character class? */
-                           ord(*p) == ord(':'))) {
+                           ord(*p) == ORD(':'))) {
                                /* must stop with exactly the same c */
                                subc = *p++;
                                /* save away start of substring */
@@ -1094,7 +1094,7 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
                                while ((c = *p++))
                                        /* but only this sequence... */
                                        if (c == subc && ISMAGIC(*p) &&
-                                           ord(p[1]) == ord(']')) {
+                                           ord(p[1]) == ORD(']')) {
                                                /* accept, terminate */
                                                p += 2;
                                                break;
@@ -1106,14 +1106,14 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
                                strndupx(subp, s, p - s - 3, ATEMP);
                                debunk(subp, subp, p - s - 3 + 1);
                                /* whither subexpression */
-                               if (ord(subc) == ord(':')) {
+                               if (ord(subc) == ORD(':')) {
                                        /* oops, not a range */
 
                                        /* match single previous char */
                                        if (lc && (sc == lc))
                                                found = true;
                                        /* match hyphen-minus */
-                                       if (ord(sc) == ord('-'))
+                                       if (ord(sc) == ORD('-'))
                                                found = true;
                                        /* handle cclass common part */
                                        goto cclass_common;
@@ -1151,7 +1151,7 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
                /* otherwise, just go on with the pattern string */
        }
        /* if we broke here, the bracket expression was invalid */
-       if (ord(sc) == ord('['))
+       if (ord(sc) == ORD('['))
                /* initial opening bracket as literal match */
                return (pat);
        /* or rather no match */
@@ -1661,6 +1661,15 @@ do_realpath(const char *upath)
        if (mksh_abspath(upath)) {
                /* upath is an absolute pathname */
                strdupx(ipath, upath, ATEMP);
+#ifdef MKSH_DOSPATH
+       } else if (mksh_drvltr(upath)) {
+               /* upath is a drive-relative pathname */
+               if (getdrvwd(&ldest, ord(*upath)))
+                       return (NULL);
+               /* A:foo -> A:/cwd/foo; A: -> A:/cwd */
+               ipath = shf_smprintf(Tf_sss, ldest,
+                   upath[2] ? "/" : "", upath + 2);
+#endif
        } else {
                /* upath is a relative pathname, prepend cwd */
                if ((tp = ksh_get_wd()) == NULL || !mksh_abspath(tp))
@@ -1695,6 +1704,7 @@ do_realpath(const char *upath)
                                continue;
                        else if (len == 2 && tp[1] == '.') {
                                /* strip off last pathname component */
+                               /*XXX consider a rooted pathname */
                                while (xp > Xstring(xs, xp))
                                        if (mksh_cdirsep(*--xp))
                                                break;
@@ -1762,11 +1772,23 @@ do_realpath(const char *upath)
                         * restart if symlink target is an absolute path,
                         * otherwise continue with currently resolved prefix
                         */
+#ifdef MKSH_DOSPATH
+ assemble_symlink:
+#endif
                        /* append rest of current input path to link target */
                        tp = shf_smprintf(Tf_sss, ldest, *ip ? "/" : "", ip);
                        afree(ipath, ATEMP);
                        ip = ipath = tp;
-                       if (!mksh_abspath(ldest)) {
+                       if (!mksh_abspath(ipath)) {
+#ifdef MKSH_DOSPATH
+                               /* symlink target might be drive-relative */
+                               if (mksh_drvltr(ipath)) {
+                                       if (getdrvwd(&ldest, ord(*ipath)))
+                                               goto notfound;
+                                       ip += 2;
+                                       goto assemble_symlink;
+                               }
+#endif
                                /* symlink target is a relative path */
                                xp = Xrestpos(xs, xp, pos);
                        } else
@@ -1775,7 +1797,7 @@ do_realpath(const char *upath)
                                /* symlink target is an absolute path */
                                xp = Xstring(xs, xp);
  beginning_of_a_pathname:
-                               /* assert: mksh_cdirsep((ip == ipath)[0]) */
+                               /* assert: mksh_abspath(ip == ipath) */
                                /* assert: xp == xs.beg => start of path */
 
                                /* exactly two leading slashes? (SUSv4 3.266) */
@@ -1783,6 +1805,14 @@ do_realpath(const char *upath)
                                        /* keep them, e.g. for UNC pathnames */
                                        Xput(xs, xp, '/');
                                }
+#ifdef MKSH_DOSPATH
+                               /* drive letter? */
+                               if (mksh_drvltr(ip)) {
+                                       /* keep it */
+                                       Xput(xs, xp, *ip++);
+                                       Xput(xs, xp, *ip++);
+                               }
+#endif
                        }
                }
                /* otherwise (no symlink) merely go on */
@@ -1932,6 +1962,15 @@ make_path(const char *cwd, const char *file,
  * ..                                  ..
  * ./foo                               foo
  * foo/../../../bar                    ../../bar
+ * C:/foo/../..                                C:/
+ * C:.                                 C:
+ * C:..                                        C:..
+ * C:foo/../../blah                    C:../blah
+ *
+ * XXX consider a rooted pathname: we cannot really 'cd ..' for
+ * pathnames like: '/', 'c:/', '//foo', '//foo/', '/@unixroot/'
+ * (no effect), 'c:', 'c:.' (effect is retaining the '../') but
+ * we need to honour this throughout the shell
  */
 void
 simplify_path(char *p)
@@ -1939,6 +1978,17 @@ simplify_path(char *p)
        char *dp, *ip, *sp, *tp;
        size_t len;
        bool needslash;
+#ifdef MKSH_DOSPATH
+       bool needdot = true;
+
+       /* keep drive letter */
+       if (mksh_drvltr(p)) {
+               p += 2;
+               needdot = false;
+       }
+#else
+#define needdot true
+#endif
 
        switch (*p) {
        case 0:
@@ -1977,7 +2027,7 @@ simplify_path(char *p)
                                /* just continue with the next one */
                                continue;
                        else if (len == 2 && tp[1] == '.') {
-                               /* parent level, but how? */
+                               /* parent level, but how? (see above) */
                                if (mksh_abspath(p))
                                        /* absolute path, only one way */
                                        goto strip_last_component;
@@ -2016,10 +2066,15 @@ simplify_path(char *p)
                needslash = true;
                /* try next component */
        }
-       if (dp == p)
-               /* empty path -> dot */
-               *dp++ = needslash ? '/' : '.';
+       if (dp == p) {
+               /* empty path -> dot (or slash, when absolute) */
+               if (needslash)
+                       *dp++ = '/';
+               else if (needdot)
+                       *dp++ = '.';
+       }
        *dp = '\0';
+#undef needdot
 }
 
 void
@@ -2133,6 +2188,18 @@ c_cd(const char **wp)
                return (2);
        }
 
+#ifdef MKSH_DOSPATH
+       tryp = NULL;
+       if (mksh_drvltr(dir) && !mksh_cdirsep(dir[2]) &&
+           !getdrvwd(&tryp, ord(*dir))) {
+               dir = shf_smprintf(Tf_sss, tryp,
+                   dir[2] ? "/" : "", dir + 2);
+               afree(tryp, ATEMP);
+               afree(allocd, ATEMP);
+               allocd = dir;
+       }
+#endif
+
 #ifdef MKSH__NO_PATH_MAX
        /* only a first guess; make_path will enlarge xs if necessary */
        XinitN(xs, 1024, ATEMP);
index fc27d5a..2bc63ed 100644 (file)
--- a/src/os2.c
+++ b/src/os2.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2015
+ * Copyright (c) 2015, 2017
  *     KO Myung-Hun <komh@chollian.net>
  * Copyright (c) 2017
  *     mirabilos <m@mirbsd.org>
 #include "sh.h"
 
 #include <klibc/startup.h>
+#include <errno.h>
 #include <io.h>
 #include <unistd.h>
 #include <process.h>
 
-__RCSID("$MirOS: src/bin/mksh/os2.c,v 1.2 2017/04/29 22:04:29 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/os2.c,v 1.8 2017/12/22 16:41:42 tg Exp $");
 
 static char *remove_trailing_dots(char *);
 static int access_stat_ex(int (*)(), const char *, void *);
 static int test_exec_exist(const char *, char *);
 static void response(int *, const char ***);
 static char *make_response_file(char * const *);
-static void env_slashify(void);
 static void add_temp(const char *);
 static void cleanup_temps(void);
 static void cleanup(void);
@@ -169,44 +169,12 @@ init_extlibpath(void)
        }
 }
 
-/*
- * Convert backslashes of environmental variables to forward slahes.
- * A backslash may be used as an escaped character when doing 'echo'.
- * This leads to an unexpected behavior.
- */
-static void
-env_slashify(void)
-{
-       /*
-        * PATH and TMPDIR are used by OS/2 as well. That is, they may
-        * have backslashes as a directory separator.
-        * BEGINLIBPATH and ENDLIBPATH are special variables on OS/2.
-        */
-       const char *var_list[] = {
-               "PATH",
-               "TMPDIR",
-               "BEGINLIBPATH",
-               "ENDLIBPATH",
-               NULL
-       };
-       const char **var;
-       char *value;
-
-       for (var = var_list; *var; var++) {
-               value = getenv(*var);
-
-               if (value)
-                       _fnslashify(value);
-       }
-}
-
 void
 os2_init(int *argcp, const char ***argvp)
 {
        response(argcp, argvp);
 
        init_extlibpath();
-       env_slashify();
 
        if (!isatty(STDIN_FILENO))
                setmode(STDIN_FILENO, O_BINARY);
@@ -361,49 +329,30 @@ real_exec_name(const char *name)
        return (real_name);
 }
 
-/* OS/2 can process a command line up to 32 KiB */
-#define MAX_CMD_LINE_LEN 32768
-
 /* make a response file to pass a very long command line */
 static char *
 make_response_file(char * const *argv)
 {
        char rsp_name_arg[] = "@mksh-rsp-XXXXXX";
        char *rsp_name = &rsp_name_arg[1];
-       int arg_len = 0;
        int i;
+       int fd;
+       char *result;
 
-       for (i = 0; argv[i]; i++)
-               arg_len += strlen(argv[i]) + 1;
-
-       /*
-        * If a length of command line is longer than MAX_CMD_LINE_LEN, then
-        * use a response file. OS/2 cannot process a command line longer
-        * than 32K. Of course, a response file cannot be recognised by a
-        * normal OS/2 program, that is, neither non-EMX or non-kLIBC. But
-        * it cannot accept a command line longer than 32K in itself. So
-        * using a response file in this case, is an acceptable solution.
-        */
-       if (arg_len > MAX_CMD_LINE_LEN) {
-               int fd;
-               char *result;
-
-               if ((fd = mkstemp(rsp_name)) == -1)
-                       return (NULL);
-
-               /* write all the arguments except a 0th program name */
-               for (i = 1; argv[i]; i++) {
-                       write(fd, argv[i], strlen(argv[i]));
-                       write(fd, "\n", 1);
-               }
+       if ((fd = mkstemp(rsp_name)) == -1)
+               return (NULL);
 
-               close(fd);
-               add_temp(rsp_name);
-               strdupx(result, rsp_name_arg, ATEMP);
-               return (result);
+       /* write all the arguments except a 0th program name */
+       for (i = 1; argv[i]; i++) {
+               write(fd, argv[i], strlen(argv[i]));
+               write(fd, "\n", 1);
        }
 
-       return (NULL);
+       close(fd);
+       add_temp(rsp_name);
+       strdupx(result, rsp_name_arg, ATEMP);
+
+       return (result);
 }
 
 /* alias of execve() */
@@ -416,12 +365,12 @@ execve(const char *name, char * const *argv, char * const *envp)
        const char *exec_name;
        FILE *fp;
        char sign[2];
-       char *rsp_argv[3];
-       char *rsp_name_arg;
        int pid;
        int status;
        int fd;
        int rc;
+       int saved_mode;
+       int saved_errno;
 
        /*
         * #! /bin/sh : append .exe
@@ -461,23 +410,41 @@ execve(const char *name, char * const *argv, char * const *envp)
        if (errno == ENOEXEC)
                return (-1);
 
-       rsp_name_arg = make_response_file(argv);
+       /*
+        * Normal OS/2 programs expect that standard IOs, especially stdin,
+        * are opened in text mode at the startup. By the way, on OS/2 kLIBC
+        * child processes inherit a translation mode of a parent process.
+        * As a result, if stdin is set to binary mode in a parent process,
+        * stdin of child processes is opened in binary mode as well at the
+        * startup. In this case, some programs such as sed suffer from CR.
+        */
+       saved_mode = setmode(STDIN_FILENO, O_TEXT);
 
-       if (rsp_name_arg) {
-               rsp_argv[0] = argv[0];
-               rsp_argv[1] = rsp_name_arg;
-               rsp_argv[2] = NULL;
+       pid = spawnve(P_NOWAIT, exec_name, argv, envp);
+       saved_errno = errno;
 
-               argv = rsp_argv;
-       }
+       /* arguments too long? */
+       if (pid == -1 && saved_errno == EINVAL) {
+               /* retry with a response file */
+               char *rsp_name_arg = make_response_file(argv);
 
-       pid = spawnve(P_NOWAIT, exec_name, argv, envp);
+               if (rsp_name_arg) {
+                       char *rsp_argv[3] = { argv[0], rsp_name_arg, NULL };
+
+                       pid = spawnve(P_NOWAIT, exec_name, rsp_argv, envp);
+                       saved_errno = errno;
+
+                       afree(rsp_name_arg, ATEMP);
+               }
+       }
 
-       afree(rsp_name_arg, ATEMP);
+       /* restore translation mode of stdin */
+       setmode(STDIN_FILENO, saved_mode);
 
        if (pid == -1) {
                cleanup_temps();
 
+               errno = saved_errno;
                return (-1);
        }
 
@@ -557,3 +524,52 @@ cleanup(void)
 {
        cleanup_temps();
 }
+
+int
+getdrvwd(char **cpp, unsigned int drvltr)
+{
+       PBYTE cp;
+       ULONG sz;
+       APIRET rc;
+       ULONG drvno;
+
+       if (DosQuerySysInfo(QSV_MAX_PATH_LENGTH, QSV_MAX_PATH_LENGTH,
+           &sz, sizeof(sz)) != 0) {
+               errno = EDOOFUS;
+               return (-1);
+       }
+
+       /* allocate 'X:/' plus sz plus NUL */
+       checkoktoadd((size_t)sz, (size_t)4);
+       cp = aresize(*cpp, (size_t)sz + (size_t)4, ATEMP);
+       cp[0] = ksh_toupper(drvltr);
+       cp[1] = ':';
+       cp[2] = '/';
+       drvno = ksh_numuc(cp[0]) + 1;
+       /* NUL is part of space within buffer passed */
+       ++sz;
+       if ((rc = DosQueryCurrentDir(drvno, cp + 3, &sz)) == 0) {
+               /* success! */
+               *cpp = cp;
+               return (0);
+       }
+       afree(cp, ATEMP);
+       *cpp = NULL;
+       switch (rc) {
+       case 15: /* invalid drive */
+               errno = ENOTBLK;
+               break;
+       case 26: /* not dos disk */
+               errno = ENODEV;
+               break;
+       case 108: /* drive locked */
+               errno = EDEADLK;
+               break;
+       case 111: /* buffer overflow */
+               errno = ENAMETOOLONG;
+               break;
+       default:
+               errno = EINVAL;
+       }
+       return (-1);
+}
index 88883cb..53629b1 100644 (file)
--- a/src/sh.h
+++ b/src/sh.h
@@ -10,7 +10,7 @@
 
 /*-
  * Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *            2011, 2012, 2013, 2014, 2015, 2016, 2017
+ *            2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
 #endif
 
 #ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.841 2017/08/29 13:38:31 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.858 2018/01/14 01:47:36 tg Exp $");
 #endif
-#define MKSH_VERSION "R56 2017/08/29"
+#define MKSH_VERSION "R56 2018/01/14"
 
 /* arithmetic types: C implementation */
 #if !HAVE_CAN_INTTYPES
@@ -556,7 +556,7 @@ extern int __cdecl setegid(gid_t);
  * low-bit7 at least on cp1047 so YMMV
  */
 #define MAGIC          KSH_BEL /* prefix for *?[!{,} during expand */
-#define ISMAGIC(c)     (ord(c) == ord(MAGIC))
+#define ISMAGIC(c)     (ord(c) == ORD(MAGIC))
 
 EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */
 
@@ -643,7 +643,7 @@ char *ucstrstr(char *, const char *);
 #endif
 #endif
 
-#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 562)
+#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 563)
 #error Must run Build.sh to compile this.
 extern void thiswillneverbedefinedIhope(void);
 int
@@ -804,7 +804,7 @@ struct sretrace_info;
 struct yyrecursive_state;
 
 EXTERN struct sretrace_info *retrace_info;
-EXTERN int subshell_nesting_type;
+EXTERN unsigned int subshell_nesting_type;
 
 extern struct env {
        ALLOC_ITEM alloc_INT;   /* internal, do not touch */
@@ -1469,7 +1469,26 @@ EXTERN char ifs0;
 #define C_UNDER        CiUNDER         /* _    underscore */
 
 /* identity transform of octet */
-#define ord(c)         ((unsigned int)(unsigned char)(c))
+#if defined(DEBUG) && defined(__GNUC__) && !defined(__ICC) && \
+    !defined(__INTEL_COMPILER) && !defined(__SUNPRO_C)
+extern unsigned int eek_ord;
+#define ORD(c) ((size_t)(c) > 0xFF ? eek_ord : \
+                   ((unsigned int)(unsigned char)(c)))
+#define ord(c) __builtin_choose_expr(                          \
+    __builtin_types_compatible_p(__typeof__(c), char) ||       \
+    __builtin_types_compatible_p(__typeof__(c), unsigned char),        \
+    ((unsigned int)(unsigned char)(c)), ({                     \
+       size_t ord_c = (c);                                     \
+                                                               \
+       if (ord_c > (size_t)0xFFU)                              \
+               internal_errorf("%s:%d:ord(%zX)",               \
+                   __FILE__, __LINE__, ord_c);                 \
+       ((unsigned int)(unsigned char)(ord_c));                 \
+}))
+#else
+#define ord(c) ((unsigned int)(unsigned char)(c))
+#define ORD(c) ord(c) /* may evaluate arguments twice */
+#endif
 #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC)
 EXTERN unsigned short ebcdic_map[256];
 EXTERN unsigned char ebcdic_rtt_toascii[256];
@@ -1492,20 +1511,22 @@ extern void ebcdic_init(void);
 #ifdef MKSH_EBCDIC
 #define ksh_isctrl(c)  (ord(c) < 0x40 || ord(c) == 0xFF)
 #else
-#define ksh_isctrl(c)  ((ord(c) & 0x7F) < 0x20 || (c) == 0x7F)
+#define ksh_isctrl(c)  ((ord(c) & 0x7F) < 0x20 || ord(c) == 0x7F)
 #endif
 /* new fast character classes */
 #define ctype(c,t)     tobool(ksh_ctypes[ord(c)] & (t))
+#define cinttype(c,t)  ((c) >= 0 && (c) <= 0xFF ? \
+                       tobool(ksh_ctypes[(unsigned char)(c)] & (t)) : false)
 /* helper functions */
 #define ksh_isdash(s)  tobool(ord((s)[0]) == '-' && ord((s)[1]) == '\0')
 /* invariant distance even in EBCDIC */
 #define ksh_tolower(c) (ctype(c, C_UPPER) ? (c) - 'A' + 'a' : (c))
 #define ksh_toupper(c) (ctype(c, C_LOWER) ? (c) - 'a' + 'A' : (c))
 /* strictly speaking rtt2asc() here, but this works even in EBCDIC */
-#define ksh_numdig(c)  (ord(c) - ord('0'))
+#define ksh_numdig(c)  (ord(c) - ORD('0'))
 #define ksh_numuc(c)   (rtt2asc(c) - rtt2asc('A'))
 #define ksh_numlc(c)   (rtt2asc(c) - rtt2asc('a'))
-#define ksh_toctrl(c)  asc2rtt(ord(c) == ord('?') ? 0x7F : rtt2asc(c) & 0x9F)
+#define ksh_toctrl(c)  asc2rtt(ord(c) == ORD('?') ? 0x7F : rtt2asc(c) & 0x9F)
 #define ksh_unctrl(c)  asc2rtt(rtt2asc(c) ^ 0x40U)
 
 /* Argument parsing for built-in commands and getopts command */
@@ -1599,7 +1620,7 @@ EXTERN mksh_ari_t x_lins E_INIT(24);
 #define shf_fileno(shf)                ((shf)->fd)
 #define shf_setfileno(shf,nfd) ((shf)->fd = (nfd))
 #define shf_getc_i(shf)                ((shf)->rnleft > 0 ? \
-                                   (shf)->rnleft--, *(shf)->rp++ : \
+                                   (shf)->rnleft--, (int)ord(*(shf)->rp++) : \
                                    shf_getchar(shf))
 #define shf_putc_i(c, shf)     ((shf)->wnleft == 0 ? \
                                    shf_putchar((uint8_t)(c), (shf)) : \
@@ -2500,6 +2521,7 @@ void shprintf(const char *, ...)
     MKSH_A_FORMAT(__printf__, 1, 2);
 int can_seek(int);
 void initio(void);
+void recheck_ctype(void);
 int ksh_dup2(int, int, bool);
 short savefd(int);
 void restfd(int, int);
@@ -2734,27 +2756,32 @@ extern int tty_init_fd(void);   /* initialise tty_fd, tty_devtty */
 #endif
 
 #ifdef MKSH_DOSPATH
+#define mksh_drvltr(s)                 __extension__({                 \
+       const char *mksh_drvltr_s = (s);                                \
+       (ctype(mksh_drvltr_s[0], C_ALPHA) && mksh_drvltr_s[1] == ':');  \
+})
 #define mksh_abspath(s)                        __extension__({                 \
        const char *mksh_abspath_s = (s);                               \
        (mksh_cdirsep(mksh_abspath_s[0]) ||                             \
-           (ctype(mksh_abspath_s[0], C_ALPHA) &&                       \
-           mksh_abspath_s[1] == ':'));                                 \
+           (mksh_drvltr(mksh_abspath_s) &&                             \
+           mksh_cdirsep(mksh_abspath_s[2])));                          \
 })
 #define mksh_cdirsep(c)                        __extension__({                 \
        char mksh_cdirsep_c = (c);                                      \
        (mksh_cdirsep_c == '/' || mksh_cdirsep_c == '\\');              \
 })
-#define mksh_sdirsep(s)                        __extension__({                 \
-       const char *mksh_sdirsep_s = (s);                               \
-       ((char *)((ctype(mksh_sdirsep_s[0], C_ALPHA) &&                 \
-           mksh_sdirsep_s[1] == ':' &&                                 \
-           !mksh_cdirsep(mksh_sdirsep_s[2])) ?                         \
-           (mksh_sdirsep_s + 1) : strpbrk(mksh_sdirsep_s, "/\\")));    \
+#define mksh_sdirsep(s)                        strpbrk((s), "/\\")
+#define mksh_vdirsep(s)                        __extension__({                 \
+       const char *mksh_vdirsep_s = (s);                               \
+       (((mksh_drvltr(mksh_vdirsep_s) &&                               \
+           !mksh_cdirsep(mksh_vdirsep_s[2])) ? (!0) :                  \
+           (mksh_sdirsep(mksh_vdirsep_s) != NULL)) &&                  \
+           (strcmp(mksh_vdirsep_s, T_builtin) != 0));                  \
 })
-#define mksh_vdirsep(s)                        (mksh_sdirsep((s)) != NULL)
+int getdrvwd(char **, unsigned int);
 #else
-#define mksh_abspath(s)                        (ord((s)[0]) == ord('/'))
-#define mksh_cdirsep(c)                        (ord(c) == ord('/'))
+#define mksh_abspath(s)                        (ord((s)[0]) == ORD('/'))
+#define mksh_cdirsep(c)                        (ord(c) == ORD('/'))
 #define mksh_sdirsep(s)                        strchr((s), '/')
 #define mksh_vdirsep(s)                        vstrchr((s), '/')
 #endif
index 7e53352..2ee0ec1 100644 (file)
--- a/src/shf.c
+++ b/src/shf.c
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
- *              2012, 2013, 2015, 2016, 2017
+ *              2012, 2013, 2015, 2016, 2017, 2018
  *     mirabilos <m@mirbsd.org>
  * Copyright (c) 2015
  *     Daniel Richard G. <skunk@iSKUNK.ORG>
@@ -27,7 +27,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.95 2017/05/05 22:45:58 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.97 2018/01/14 01:28:16 tg Exp $");
 
 /* flags to shf_emptybuf() */
 #define EB_READSW      0x01    /* about to switch to reading */
@@ -554,7 +554,7 @@ shf_getchar(struct shf *shf)
        if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
                return (-1);
        --shf->rnleft;
-       return (*shf->rp++);
+       return (ord(*shf->rp++));
 }
 
 /*
@@ -1253,7 +1253,7 @@ set_ifs(const char *s)
  *    Not only do they require all 8 bits instead of 7, if chars are
  *    signed, they will have negative integer values! Something like
  *    (c - 'A') could actually become (c + 63)! Use the ord() macro to
- *    ensure you're getting a value in [0, 255].
+ *    ensure you're getting a value in [0, 255] (ORD for constants).
  * 4. '\n' is actually NL (0x15, U+0085) instead of LF (0x25, U+000A).
  *    EBCDIC has a proper newline character instead of "emulating" one
  *    with line feeds, although this is mapped to LF for our purposes.
index c50c2ab..e4c38e3 100644 (file)
--- a/src/syn.c
+++ b/src/syn.c
@@ -2,7 +2,8 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- *              2011, 2012, 2013, 2014, 2015, 2016, 2017
+ *              2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ *              2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +24,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.124 2017/05/05 22:53:31 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.127 2018/01/14 00:22:30 tg Exp $");
 
 struct nesting_state {
        int start_token;        /* token than began nesting (eg, FOR) */
@@ -35,7 +36,7 @@ struct yyrecursive_state {
        struct yyrecursive_state *next;
        struct ioword **old_herep;
        int old_symbol;
-       int old_nesting_type;
+       unsigned int old_nesting_type;
        bool old_reject;
 };
 
@@ -75,7 +76,10 @@ static int symbol;                   /* yylex value */
 #define ACCEPT         (reject = false)
 #define token(cf)      ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
 #define tpeek(cf)      ((reject) ? (symbol) : (REJECT, symbol = yylex(cf)))
-#define musthave(c,cf) do { if (token(cf) != (c)) syntaxerr(NULL); } while (/* CONSTCOND */ 0)
+#define musthave(c,cf) do {                                    \
+       if ((unsigned int)token(cf) != (unsigned int)(c))       \
+               syntaxerr(NULL);                                \
+} while (/* CONSTCOND */ 0)
 
 static const char Tcbrace[] = "}";
 static const char Tesac[] = "esac";
@@ -91,7 +95,7 @@ yyparse(bool doalias)
        c = tpeek(0);
        if (c == 0 && !outtree)
                outtree = newtp(TEOF);
-       else if (!ctype(c, C_LF | C_NUL))
+       else if (!cinttype(c, C_LF | C_NUL))
                syntaxerr(NULL);
 }
 
@@ -330,7 +334,7 @@ get_command(int cf, int sALIAS)
                                        XPput(args, yylval.cp);
                                break;
 
-                       case ord('(' /*)*/):
+                       case ORD('(' /*)*/):
                                if (XPsize(args) == 0 && XPsize(vars) == 1 &&
                                    is_wdvarassign(yylval.cp)) {
                                        char *tcp;
@@ -386,18 +390,18 @@ get_command(int cf, int sALIAS)
  Leave:
                break;
 
-       case ord('(' /*)*/): {
-               int subshell_nesting_type_saved;
+       case ORD('(' /*)*/): {
+               unsigned int subshell_nesting_type_saved;
  Subshell:
                subshell_nesting_type_saved = subshell_nesting_type;
-               subshell_nesting_type = ord(')');
-               t = nested(TPAREN, ord('('), ord(')'), sALIAS);
+               subshell_nesting_type = ORD(')');
+               t = nested(TPAREN, ORD('('), ORD(')'), sALIAS);
                subshell_nesting_type = subshell_nesting_type_saved;
                break;
            }
 
-       case ord('{' /*}*/):
-               t = nested(TBRACE, ord('{'), ord('}'), sALIAS);
+       case ORD('{' /*}*/):
+               t = nested(TBRACE, ORD('{'), ORD('}'), sALIAS);
                break;
 
        case MDPAREN:
@@ -407,8 +411,8 @@ get_command(int cf, int sALIAS)
                switch (token(LETEXPR)) {
                case LWORD:
                        break;
-               case ord('(' /*)*/):
-                       c = ord('(');
+               case ORD('(' /*)*/):
+                       c = ORD('(');
                        goto Subshell;
                default:
                        syntaxerr(NULL);
@@ -554,8 +558,8 @@ dogroup(int sALIAS)
         */
        if (c == DO)
                c = DONE;
-       else if (c == ord('{'))
-               c = ord('}');
+       else if ((unsigned int)c == ORD('{'))
+               c = ORD('}');
        else
                syntaxerr(NULL);
        list = c_list(sALIAS, true);
@@ -610,8 +614,8 @@ caselist(int sALIAS)
        /* A {...} can be used instead of in...esac for case statements */
        if (c == IN)
                c = ESAC;
-       else if (c == ord('{'))
-               c = ord('}');
+       else if ((unsigned int)c == ORD('{'))
+               c = ORD('}');
        else
                syntaxerr(NULL);
        t = tl = NULL;
@@ -636,18 +640,17 @@ casepart(int endtok, int sALIAS)
        XPinit(ptns, 16);
        t = newtp(TPAT);
        /* no ALIAS here */
-       if (token(CONTIN | KEYWORD) != ord('('))
+       if ((unsigned int)token(CONTIN | KEYWORD) != ORD('('))
                REJECT;
        do {
                switch (token(0)) {
                case LWORD:
                        break;
-               case ord('}'):
+               case ORD('}'):
                case ESAC:
                        if (symbol != endtok) {
-                               strdupx(yylval.cp,
-                                   symbol == ord('}') ? Tcbrace : Tesac,
-                                   ATEMP);
+                               strdupx(yylval.cp, (unsigned int)symbol ==
+                                   ORD('}') ? Tcbrace : Tesac, ATEMP);
                                break;
                        }
                        /* FALLTHROUGH */
@@ -659,23 +662,23 @@ casepart(int endtok, int sALIAS)
        REJECT;
        XPput(ptns, NULL);
        t->vars = (char **)XPclose(ptns);
-       musthave(ord(')'), 0);
+       musthave(ORD(')'), 0);
 
        t->left = c_list(sALIAS, true);
 
        /* initialise to default for ;; or omitted */
-       t->u.charflag = ord(';');
+       t->u.charflag = ORD(';');
        /* SUSv4 requires the ;; except in the last casepart */
        if ((tpeek(CONTIN|KEYWORD|sALIAS)) != endtok)
                switch (symbol) {
                default:
                        syntaxerr(NULL);
                case BRKEV:
-                       t->u.charflag = ord('|');
+                       t->u.charflag = ORD('|');
                        if (0)
                                /* FALLTHROUGH */
                case BRKFT:
-                         t->u.charflag = ord('&');
+                         t->u.charflag = ORD('&');
                        /* FALLTHROUGH */
                case BREAK:
                        /* initialised above, but we need to eat the token */
@@ -711,14 +714,14 @@ function_body(char *name, int sALIAS,
         * only accepts an open-brace.
         */
        if (ksh_func) {
-               if (tpeek(CONTIN|KEYWORD|sALIAS) == ord('(' /*)*/)) {
+               if ((unsigned int)tpeek(CONTIN|KEYWORD|sALIAS) == ORD('(' /*)*/)) {
                        /* function foo () { //}*/
                        ACCEPT;
-                       musthave(ord(/*(*/ ')'), 0);
+                       musthave(ORD(/*(*/ ')'), 0);
                        /* degrade to POSIX function */
                        ksh_func = false;
                }
-               musthave(ord('{' /*}*/), CONTIN|KEYWORD|sALIAS);
+               musthave(ORD('{' /*}*/), CONTIN|KEYWORD|sALIAS);
                REJECT;
        }
 
@@ -810,8 +813,8 @@ static const struct tokeninfo {
        { "in",         IN,     true },
        { Tfunction,    FUNCTION, true },
        { Ttime,        TIME,   true },
-       { "{",          ord('{'), true },
-       { Tcbrace,      ord('}'), true },
+       { "{",          ORD('{'), true },
+       { Tcbrace,      ORD('}'), true },
        { "!",          BANG,   true },
        { "[[",         DBRACKET, true },
        /* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */
@@ -823,7 +826,7 @@ static const struct tokeninfo {
        { "((",         MDPAREN, false },
        { "|&",         COPROC, false },
        /* and some special cases... */
-       { "newline",    ord('\n'), false },
+       { "newline",    ORD('\n'), false },
        { NULL,         0,      false }
 };
 
@@ -998,9 +1001,9 @@ dbtestp_isa(Test_env *te, Test_meta meta)
                ret = (uqword && !strcmp(yylval.cp,
                    dbtest_tokens[(int)TM_NOT])) ? TO_NONNULL : TO_NONOP;
        else if (meta == TM_OPAREN)
-               ret = c == ord('(') /*)*/ ? TO_NONNULL : TO_NONOP;
+               ret = (unsigned int)c == ORD('(') /*)*/ ? TO_NONNULL : TO_NONOP;
        else if (meta == TM_CPAREN)
-               ret = c == /*(*/ ord(')') ? TO_NONNULL : TO_NONOP;
+               ret = (unsigned int)c == /*(*/ ORD(')') ? TO_NONNULL : TO_NONOP;
        else if (meta == TM_UNOP || meta == TM_BINOP) {
                if (meta == TM_BINOP && c == REDIR &&
                    (yylval.iop->ioflag == IOREAD ||
@@ -1131,14 +1134,14 @@ yyrecursive(int subtype)
        struct op *t;
        char *cp;
        struct yyrecursive_state *ys;
-       int stok, etok;
+       unsigned int stok, etok;
 
        if (subtype != COMSUB) {
-               stok = ord('{');
-               etok = ord('}');
+               stok = ORD('{');
+               etok = ORD('}');
        } else {
-               stok = ord('(');
-               etok = ord(')');
+               stok = ORD('(');
+               etok = ORD(')');
        }
 
        ys = alloc(sizeof(struct yyrecursive_state), ATEMP);
index 1062feb..5e7326b 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.93 2017/05/05 22:53:32 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.95 2018/01/14 00:03:05 tg Exp $");
 
 #define INDENT 8
 
@@ -329,7 +329,7 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
                case EOS:
                        return (--wp);
                case ADELIM:
-                       if (ord(*wp) == ord(/*{*/ '}')) {
+                       if (ord(*wp) == ORD(/*{*/ '}')) {
                                ++wp;
                                goto wdvarput_csubst;
                        }
@@ -342,21 +342,21 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
                        c = ord(*wp++);
                        if (opmode & WDS_TPUTS)
                                switch (c) {
-                               case ord('\n'):
+                               case ORD('\n'):
                                        if (quotelevel == 0) {
-                                               c = ord('\'');
+                                               c = ORD('\'');
                                                shf_putc(c, shf);
-                                               shf_putc(ord('\n'), shf);
+                                               shf_putc(ORD('\n'), shf);
                                        }
                                        break;
                                default:
                                        if (quotelevel == 0)
                                                /* FALLTHROUGH */
-                               case ord('"'):
-                               case ord('`'):
-                               case ord('$'):
-                               case ord('\\'):
-                                         shf_putc(ord('\\'), shf);
+                               case ORD('"'):
+                               case ORD('`'):
+                               case ORD('$'):
+                               case ORD('\\'):
+                                         shf_putc(ORD('\\'), shf);
                                        break;
                                }
                        shf_putc(c, shf);
@@ -365,7 +365,7 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
                case COMSUB:
                        shf_puts("$(", shf);
                        cs = ")";
-                       if (ord(*wp) == ord('(' /*)*/))
+                       if (ord(*wp) == ORD('(' /*)*/))
                                shf_putc(' ', shf);
  pSUB:
                        while ((c = *wp++) != 0)
@@ -374,11 +374,11 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
                        break;
                case FUNASUB:
                case FUNSUB:
-                       c = ord(' ');
+                       c = ORD(' ');
                        if (0)
                                /* FALLTHROUGH */
                case VALSUB:
-                         c = ord('|');
+                         c = ORD('|');
                        shf_putc('$', shf);
                        shf_putc('{', shf);
                        shf_putc(c, shf);
@@ -403,14 +403,14 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
                        break;
                case OSUBST:
                        shf_putc('$', shf);
-                       if (ord(*wp++) == ord('{'))
+                       if (ord(*wp++) == ORD('{'))
                                shf_putc('{', shf);
                        while ((c = *wp++) != 0)
                                shf_putc(c, shf);
                        wp = wdvarput(shf, wp, 0, opmode);
                        break;
                case CSUBST:
-                       if (ord(*wp++) == ord('}')) {
+                       if (ord(*wp++) == ORD('}')) {
  wdvarput_csubst:
                                shf_putc('}', shf);
                        }
@@ -420,11 +420,11 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
                        shf_putc('(', shf);
                        break;
                case SPAT:
-                       c = ord('|');
+                       c = ORD('|');
                        if (0)
                                /* FALLTHROUGH */
                case CPAT:
-                         c = ord(/*(*/ ')');
+                         c = ORD(/*(*/ ')');
                        shf_putc(c, shf);
                        break;
                }
@@ -470,36 +470,37 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
        while ((c = ord(*fmt++))) {
                if (c == '%') {
                        switch ((c = ord(*fmt++))) {
-                       case ord('c'):
+                       case ORD('c'):
                                /* character (octet, probably) */
                                shf_putchar(va_arg(va, int), shf);
                                break;
-                       case ord('s'):
+                       case ORD('s'):
                                /* string */
                                shf_puts(va_arg(va, char *), shf);
                                break;
-                       case ord('S'):
+                       case ORD('S'):
                                /* word */
                                wdvarput(shf, va_arg(va, char *), 0, WDS_TPUTS);
                                break;
-                       case ord('d'):
+                       case ORD('d'):
                                /* signed decimal */
                                shf_fprintf(shf, Tf_d, va_arg(va, int));
                                break;
-                       case ord('u'):
+                       case ORD('u'):
                                /* unsigned decimal */
                                shf_fprintf(shf, "%u", va_arg(va, unsigned int));
                                break;
-                       case ord('T'):
+                       case ORD('T'):
                                /* format tree */
                                ptree(va_arg(va, struct op *), indent, shf);
                                goto dont_trash_prevent_semicolon;
-                       case ord(';'):
+                       case ORD(';'):
                                /* newline or ; */
-                       case ord('N'):
+                       case ORD('N'):
                                /* newline or space */
                                if (shf->flags & SHF_STRING) {
-                                       if (c == ord(';') && !prevent_semicolon)
+                                       if ((unsigned int)c == ORD(';') &&
+                                           !prevent_semicolon)
                                                shf_putc(';', shf);
                                        shf_putc(' ', shf);
                                } else {
@@ -515,7 +516,7 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
                                                shf_putc(' ', shf);
                                }
                                break;
-                       case ord('R'):
+                       case ORD('R'):
                                /* I/O redirection */
                                pioact(shf, va_arg(va, struct ioword *));
                                break;
@@ -613,7 +614,7 @@ wdscan(const char *wp, int c)
                case ADELIM:
                        if (c == ADELIM && nest == 0)
                                return (wp + 1);
-                       if (ord(*wp) == ord(/*{*/ '}'))
+                       if (ord(*wp) == ORD(/*{*/ '}'))
                                goto wdscan_csubst;
                        /* FALLTHROUGH */
                case CHAR:
@@ -808,7 +809,7 @@ vistree(char *dst, size_t sz, struct op *t)
        } else if (UTFMODE && rtt2asc(c) > 0x7F) {
                /* better not try to display broken multibyte chars */
                /* also go easy on the Unicode: no U+FFFD here */
-               c = ord('?');
+               c = ORD('?');
        }
        *dst++ = c;
        goto vist_loop;
@@ -842,7 +843,7 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
                        shf_puts("EOS", shf);
                        return (--wp);
                case ADELIM:
-                       if (ord(*wp) == ord(/*{*/ '}')) {
+                       if (ord(*wp) == ORD(/*{*/ '}')) {
                                shf_puts(/*{*/ "]ADELIM(})", shf);
                                return (wp + 1);
                        }
@@ -856,8 +857,8 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
                case QCHAR:
                        shf_puts("QCHAR<", shf);
                        c = ord(*wp++);
-                       if (quotelevel == 0 || c == ord('"') ||
-                           c == ord('\\') || ctype(c, C_DOLAR | C_GRAVE))
+                       if (quotelevel == 0 || c == ORD('"') ||
+                           c == ORD('\\') || ctype(c, C_DOLAR | C_GRAVE))
                                shf_putc('\\', shf);
                        dumpchar(shf, c);
                        goto closeandout;
index a53fae8..5219507 100644 (file)
--- a/src/var.c
+++ b/src/var.c
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013, 2014, 2015, 2016, 2017
+ *              2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -28,7 +28,7 @@
 #include <sys/sysctl.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/var.c,v 1.220 2017/07/26 23:02:28 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var.c,v 1.223 2018/01/13 23:55:15 tg Exp $");
 
 /*-
  * Variables
@@ -136,7 +136,7 @@ initvar(void)
        struct tbl *tp;
 
        ktinit(APERM, &specials,
-           /* currently 18 specials: 75% of 32 = 2^5 */
+           /* currently 21 specials: 75% of 32 = 2^5 */
            5);
        while (i < V_MAX - 1) {
                tp = ktenter(&specials, initvar_names[i],
@@ -204,7 +204,7 @@ array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
        }
        innermost_refflag = SRF_NOP;
 
-       if (p != n && ord(*p) == ord('[') && (len = array_ref_len(p))) {
+       if (p != n && ord(*p) == ORD('[') && (len = array_ref_len(p))) {
                char *sub, *tmp;
                mksh_ari_t rval;
 
@@ -780,7 +780,7 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
                /* no variable name given */
                return (NULL);
        }
-       if (ord(*val) == ord('[')) {
+       if (ord(*val) == ORD('[')) {
                if (new_refflag != SRF_NOP)
                        errorf(Tf_sD_s, var,
                            "reference variable can't be an array");
@@ -803,13 +803,13 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
                }
                val += len;
        }
-       if (ord(val[0]) == ord('=')) {
+       if (ord(val[0]) == ORD('=')) {
                strndupx(tvar, var, val - var, ATEMP);
                ++val;
        } else if (set & IMPORT) {
                /* environment invalid variable name or no assignment */
                return (NULL);
-       } else if (ord(val[0]) == ord('+') && ord(val[1]) == ord('=')) {
+       } else if (ord(val[0]) == ORD('+') && ord(val[1]) == ORD('=')) {
                strndupx(tvar, var, val - var, ATEMP);
                val += 2;
                vappend = true;
@@ -822,9 +822,9 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
                val = NULL;
                /* handle foo[*] => foo (whole array) mapping for R39b */
                len = strlen(tvar);
-               if (len > 3 && ord(tvar[len - 3]) == ord('[') &&
-                   ord(tvar[len - 2]) == ord('*') &&
-                   ord(tvar[len - 1]) == ord(']'))
+               if (len > 3 && ord(tvar[len - 3]) == ORD('[') &&
+                   ord(tvar[len - 2]) == ORD('*') &&
+                   ord(tvar[len - 1]) == ORD(']'))
                        tvar[len - 3] = '\0';
        }
 
@@ -861,7 +861,7 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
  nameref_empty:
                        errorf(Tf_sD_s, var, "empty nameref target");
                }
-               len = (ord(*ccp) == ord('[')) ? array_ref_len(ccp) : 0;
+               len = (ord(*ccp) == ORD('[')) ? array_ref_len(ccp) : 0;
                if (ccp[len]) {
                        /*
                         * works for cases "no array", "valid array with
@@ -1071,7 +1071,7 @@ skip_varname(const char *s, bool aok)
                do {
                        ++s;
                } while (ctype(*s, C_ALNUX));
-               if (aok && ord(*s) == ord('[') && (alen = array_ref_len(s)))
+               if (aok && ord(*s) == ORD('[') && (alen = array_ref_len(s)))
                        s += alen;
        }
        return (s);
@@ -1087,7 +1087,7 @@ skip_wdvarname(const char *s,
                do {
                        s += 2;
                } while (s[0] == CHAR && ctype(s[1], C_ALNUX));
-               if (aok && s[0] == CHAR && ord(s[1]) == ord('[')) {
+               if (aok && s[0] == CHAR && ord(s[1]) == ORD('[')) {
                        /* skip possible array de-reference */
                        const char *p = s;
                        char c;
@@ -1098,9 +1098,9 @@ skip_wdvarname(const char *s,
                                        break;
                                c = p[1];
                                p += 2;
-                               if (ord(c) == ord('['))
+                               if (ord(c) == ORD('['))
                                        depth++;
-                               else if (ord(c) == ord(']') && --depth == 0) {
+                               else if (ord(c) == ORD(']') && --depth == 0) {
                                        s = p;
                                        break;
                                }
@@ -1294,9 +1294,29 @@ setspec(struct tbl *vp)
 {
        mksh_ari_u num;
        char *s;
-       int st;
+       int st = special(vp->name);
 
-       switch ((st = special(vp->name))) {
+#ifdef MKSH_DOSPATH
+       switch (st) {
+       case V_PATH:
+       case V_TMPDIR:
+#ifdef __OS2__
+       case V_BEGINLIBPATH:
+       case V_ENDLIBPATH:
+#endif
+               /* convert backslashes to slashes for convenience */
+               if (!(vp->flag&INTEGER)) {
+                       s = str_val(vp);
+                       do {
+                               if (*s == ORD('\\'))
+                                       *s = '/';
+                       } while (*s++);
+               }
+               break;
+       }
+#endif
+
+       switch (st) {
 #ifdef __OS2__
        case V_BEGINLIBPATH:
        case V_ENDLIBPATH:
@@ -1366,6 +1386,13 @@ setspec(struct tbl *vp)
                }
                vp->flag |= SPECIAL;
                break;
+#ifdef MKSH_EARLY_LOCALE_TRACKING
+       case V_LANG:
+       case V_LC_ALL:
+       case V_LC_CTYPE:
+               recheck_ctype();
+               return;
+#endif
        default:
                /* do nothing, do not touch vp at all */
                return;
@@ -1465,6 +1492,13 @@ unsetspec(struct tbl *vp)
                /* AT&T ksh leaves previous value in place */
                unspecial(vp->name);
                break;
+#ifdef MKSH_EARLY_LOCALE_TRACKING
+       case V_LANG:
+       case V_LC_ALL:
+       case V_LC_CTYPE:
+               recheck_ctype();
+               return;
+#endif
        }
 }
 
@@ -1528,8 +1562,8 @@ array_ref_len(const char *cp)
        char c;
        int depth = 0;
 
-       while ((c = *s++) && (ord(c) != ord(']') || --depth))
-               if (ord(c) == ord('['))
+       while ((c = *s++) && (ord(c) != ORD(']') || --depth))
+               if (ord(c) == ORD('['))
                        depth++;
        if (!c)
                return (0);
@@ -1601,18 +1635,18 @@ set_array(const char *var, bool reset, const char **vals)
        }
        while ((ccp = vals[i])) {
 #if 0 /* temporarily taken out due to regression */
-               if (ord(*ccp) == ord('[')) {
+               if (ord(*ccp) == ORD('[')) {
                        int level = 0;
 
                        while (*ccp) {
-                               if (ord(*ccp) == ord(']') && --level == 0)
+                               if (ord(*ccp) == ORD(']') && --level == 0)
                                        break;
-                               if (ord(*ccp) == ord('['))
+                               if (ord(*ccp) == ORD('['))
                                        ++level;
                                ++ccp;
                        }
-                       if (ord(*ccp) == ord(']') && level == 0 &&
-                           ord(ccp[1]) == ord('=')) {
+                       if (ord(*ccp) == ORD(']') && level == 0 &&
+                           ord(ccp[1]) == ORD('=')) {
                                strndupx(cp, vals[i] + 1, ccp - (vals[i] + 1),
                                    ATEMP);
                                evaluate(substitute(cp, 0), (mksh_ari_t *)&j,
index 45fa0eb..d8444dd 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009, 2011, 2012, 2016
+ * Copyright (c) 2009, 2011, 2012, 2016, 2018
  *     mirabilos <m@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -19,7 +19,7 @@
  */
 
 #if defined(VARSPEC_DEFNS)
-__RCSID("$MirOS: src/bin/mksh/var_spec.h,v 1.10 2016/11/11 23:31:39 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var_spec.h,v 1.11 2018/01/13 21:38:10 tg Exp $");
 #define FN(name)                       /* nothing */
 #elif defined(VARSPEC_ENUMS)
 #define FN(name)                       V_##name,
@@ -53,6 +53,11 @@ FN(HISTFILE)
 #endif
 FN(HISTSIZE)
 FN(IFS)
+#ifdef MKSH_EARLY_LOCALE_TRACKING
+FN(LANG)
+FN(LC_ALL)
+FN(LC_CTYPE)
+#endif
 #ifdef __OS2__
 FN(LIBPATHSTRICT)
 #endif