From dd4abe0a6aa4badb34480972d393466bf0e4c66b Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 5 Feb 2018 15:55:19 -0800 Subject: [PATCH] Upgrade to mksh R56c. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- Android.bp | 2 +- src/Build.sh | 23 +++++- src/check.t | 21 +++-- src/edit.c | 160 ++++++++++++++++++------------------ src/eval.c | 248 ++++++++++++++++++++++++++++---------------------------- src/exec.c | 16 ++-- src/expr.c | 23 +++--- src/funcs.c | 16 ++-- src/jobs.c | 23 +++++- src/lex.c | 250 ++++++++++++++++++++++++++++----------------------------- src/main.c | 131 +++++++++++++++++++++++++----- src/misc.c | 177 +++++++++++++++++++++++++++------------- src/os2.c | 172 +++++++++++++++++++++------------------ src/sh.h | 71 +++++++++++----- src/shf.c | 8 +- src/syn.c | 83 ++++++++++--------- src/tree.c | 65 +++++++-------- src/var.c | 82 +++++++++++++------ src/var_spec.h | 9 ++- 19 files changed, 938 insertions(+), 642 deletions(-) mode change 100644 => 100755 src/Build.sh diff --git a/Android.bp b/Android.bp index 9926e18..2bca561 100644 --- a/Android.bp +++ b/Android.bp @@ -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\"", diff --git a/src/Build.sh b/src/Build.sh old mode 100644 new mode 100755 index 78fe347..ebf4e1c --- a/src/Build.sh +++ b/src/Build.sh @@ -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 diff --git a/src/check.t b/src/check.t index 4473c08..ea414d3 100644 --- a/src/check.t +++ b/src/check.t @@ -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 diff --git a/src/edit.c b/src/edit.c index 8bccf13..0e51780 100644 --- a/src/edit.c +++ b/src/edit.c @@ -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 * * 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: diff --git a/src/eval.c b/src/eval.c index 7a892c0..6aa1844 100644 --- a/src/eval.c +++ b/src/eval.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 * * 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; diff --git a/src/exec.c b/src/exec.c index 56a42f6..8330174 100644 --- a/src/exec.c +++ b/src/exec.c @@ -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; diff --git a/src/expr.c b/src/expr.c index 12989d4..499b961 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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 * * 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 }, diff --git a/src/funcs.c b/src/funcs.c index 38e66f8..5179192 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -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 */ diff --git a/src/jobs.c b/src/jobs.c index 4df98b7..a0b9b79 100644 --- a/src/jobs.c +++ b/src/jobs.c @@ -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 * * 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; diff --git a/src/lex.c b/src/lex.c index f450221..9300311 100644 --- 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 * * 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'); diff --git a/src/main.c b/src/main.c index b4d7244..ad20c94 100644 --- a/src/main.c +++ b/src/main.c @@ -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 * * Provided that these terms and disclaimer and all copyright notices @@ -34,9 +34,7 @@ #include #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 diff --git a/src/misc.c b/src/misc.c index 1205072..e51dcb1 100644 --- a/src/misc.c +++ b/src/misc.c @@ -32,7 +32,7 @@ #include #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); diff --git a/src/os2.c b/src/os2.c index fc27d5a..2bc63ed 100644 --- a/src/os2.c +++ b/src/os2.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2015 + * Copyright (c) 2015, 2017 * KO Myung-Hun * Copyright (c) 2017 * mirabilos @@ -26,18 +26,18 @@ #include "sh.h" #include +#include #include #include #include -__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); +} diff --git a/src/sh.h b/src/sh.h index 88883cb..53629b1 100644 --- 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 * * Provided that these terms and disclaimer and all copyright notices @@ -182,9 +182,9 @@ #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 diff --git a/src/shf.c b/src/shf.c index 7e53352..2ee0ec1 100644 --- 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 * Copyright (c) 2015 * Daniel Richard G. @@ -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. diff --git a/src/syn.c b/src/syn.c index c50c2ab..e4c38e3 100644 --- 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 * * 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); diff --git a/src/tree.c b/src/tree.c index 1062feb..5e7326b 100644 --- a/src/tree.c +++ b/src/tree.c @@ -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; diff --git a/src/var.c b/src/var.c index a53fae8..5219507 100644 --- 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 * * Provided that these terms and disclaimer and all copyright notices @@ -28,7 +28,7 @@ #include #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, diff --git a/src/var_spec.h b/src/var_spec.h index 45fa0eb..d8444dd 100644 --- a/src/var_spec.h +++ b/src/var_spec.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009, 2011, 2012, 2016 + * Copyright (c) 2009, 2011, 2012, 2016, 2018 * mirabilos * * 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 -- 2.11.0