Upgrade to mksh R56c.

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
This commit is contained in:
Elliott Hughes 2018-02-05 15:55:19 -08:00
parent ab3794bf03
commit dd4abe0a6a
19 changed files with 939 additions and 643 deletions

View file

@ -108,7 +108,7 @@ cc_defaults {
"-DHAVE_SYS_ERRLIST_DECL=0", "-DHAVE_SYS_ERRLIST_DECL=0",
"-DHAVE_SYS_SIGLIST_DECL=1", "-DHAVE_SYS_SIGLIST_DECL=1",
"-DHAVE_PERSISTENT_HISTORY=0", "-DHAVE_PERSISTENT_HISTORY=0",
"-DMKSH_BUILD_R=562", "-DMKSH_BUILD_R=563",
// Additional flags // Additional flags
"-DMKSH_DEFAULT_PROFILEDIR=\"/system/etc\"", "-DMKSH_DEFAULT_PROFILEDIR=\"/system/etc\"",

23
src/Build.sh Normal file → Executable file
View file

@ -1,5 +1,5 @@
#!/bin/sh #!/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, # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015, 2016, 2017 # 2011, 2012, 2013, 2014, 2015, 2016, 2017
@ -796,6 +796,8 @@ Harvey)
add_cppflags -DMKSH_ASSUME_UTF8 add_cppflags -DMKSH_ASSUME_UTF8
HAVE_ISSET_MKSH_ASSUME_UTF8=1 HAVE_ISSET_MKSH_ASSUME_UTF8=1
HAVE_ISOFF_MKSH_ASSUME_UTF8=0 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_CMDLINE_EDITING
add_cppflags -DMKSH__NO_SETEUGID add_cppflags -DMKSH__NO_SETEUGID
oswarn=' and will currently not work' oswarn=' and will currently not work'
@ -819,6 +821,20 @@ Interix)
IRIX*) IRIX*)
: "${HAVE_SETLOCALE_CTYPE=0}" : "${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) Linux)
case $CC in case $CC in
*tendracc*) ;; *tendracc*) ;;
@ -947,6 +963,8 @@ Plan9)
add_cppflags -DMKSH_ASSUME_UTF8 add_cppflags -DMKSH_ASSUME_UTF8
HAVE_ISSET_MKSH_ASSUME_UTF8=1 HAVE_ISSET_MKSH_ASSUME_UTF8=1
HAVE_ISOFF_MKSH_ASSUME_UTF8=0 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_CMDLINE_EDITING
add_cppflags -DMKSH__NO_SETEUGID add_cppflags -DMKSH__NO_SETEUGID
oswarn=' and will currently not work' oswarn=' and will currently not work'
@ -2409,7 +2427,7 @@ addsrcs '!' HAVE_STRLCPY strlcpy.c
addsrcs USE_PRINTF_BUILTIN printf.c addsrcs USE_PRINTF_BUILTIN printf.c
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose" 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 $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_EXPERIMENTAL disable code not yet comfy for (LTS) snapshots
MKSH_DISABLE_TTY_WARNING shut up warning about ctty if OS cant be fixed MKSH_DISABLE_TTY_WARNING shut up warning about ctty if OS cant be fixed
MKSH_DONT_EMIT_IDSTRING omit RCS IDs from binary 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_MIDNIGHTBSD01ASH_COMPAT set -o sh: additional compatibility quirk
MKSH_NOPROSPECTOFWORK disable jobs, co-processes, etc. (do not use) MKSH_NOPROSPECTOFWORK disable jobs, co-processes, etc. (do not use)
MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris

View file

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.797 2017/08/29 13:38:29 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.801 2018/01/14 01:47:33 tg Exp $
# -*- mode: sh -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 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 # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R56 2017/08/29 @(#)MIRBSD KSH R56 2018/01/14
description: description:
Check base version of full shell Check base version of full shell
stdin: stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: !shell:legacy-yes category: !shell:legacy-yes
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R56 2017/08/29 @(#)LEGACY KSH R56 2018/01/14
description: description:
Check base version of legacy shell Check base version of legacy shell
stdin: stdin:
@ -3328,7 +3328,7 @@ stdin:
echo B echo B
) & ) &
' & ' &
sleep 2 sleep 5
echo Left overs: * echo Left overs: *
expected-stdout: expected-stdout:
A A
@ -3392,7 +3392,7 @@ stdin:
(sleep 1; foo) & (sleep 1; foo) &
foo foo
' & ' &
sleep 2 sleep 5
echo Left overs: * echo Left overs: *
expected-stdout: expected-stdout:
hi hi
@ -6702,7 +6702,7 @@ name: regression-65
description: description:
check for a regression with sleep builtin and signal mask check for a regression with sleep builtin and signal mask
category: !nojsig category: !nojsig
time-limit: 3 time-limit: 5
stdin: stdin:
sleep 1 sleep 1
echo blub |& echo blub |&
@ -9026,6 +9026,15 @@ expected-stdout:
.c:a b.c d..: .c:a b.c d..:
.d: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 name: arrassign-fnc-none
description: description:
Check locality of array access inside a function Check locality of array access inside a function

View file

@ -5,7 +5,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015, 2016, 2017 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING #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 * 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)) { switch (ord(ch)) {
case QCHAR: 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; *dp++ = QCHAR;
break; break;
} }
@ -650,11 +650,11 @@ x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
if (*s == '\\' && s[1]) if (*s == '\\' && s[1])
s++; s++;
else if (ctype(*s, C_QUEST | C_DOLAR) || else if (ctype(*s, C_QUEST | C_DOLAR) ||
ord(*s) == ord('*') || ord(*s) == ord('[') || ord(*s) == ORD('*') || ord(*s) == ORD('[') ||
/* ?() *() +() @() !() but two already checked */ /* ?() *() +() @() !() but two already checked */
(ord(s[1]) == ord('(' /*)*/) && (ord(s[1]) == ORD('(' /*)*/) &&
(ord(*s) == ord('+') || ord(*s) == ord('@') || (ord(*s) == ORD('+') || ord(*s) == ORD('@') ||
ord(*s) == ord('!')))) { ord(*s) == ORD('!')))) {
/* /*
* just expand based on the extglob * just expand based on the extglob
* or parameter * or parameter
@ -3688,7 +3688,7 @@ vi_hook(int ch)
return (1); return (1);
cmdlen = 0; cmdlen = 0;
argc1 = 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); argc1 = ksh_numdig(ch);
state = VARG1; state = VARG1;
} else { } else {
@ -3743,7 +3743,7 @@ vi_hook(int ch)
case VEXTCMD: case VEXTCMD:
argc2 = 0; argc2 = 0;
if (ctype(ch, C_DIGIT) && ord(ch) != ord('0')) { if (ctype(ch, C_DIGIT) && ord(ch) != ORD('0')) {
argc2 = ksh_numdig(ch); argc2 = ksh_numdig(ch);
state = VARG2; state = VARG2;
return (0); return (0);
@ -4128,7 +4128,7 @@ vi_cmd(int argcnt, const char *cmd)
redraw_line(true); redraw_line(true);
break; break;
case ord('@'): case ORD('@'):
{ {
static char alias[] = "_\0"; static char alias[] = "_\0";
struct tbl *ap; struct tbl *ap;
@ -4169,7 +4169,7 @@ vi_cmd(int argcnt, const char *cmd)
} }
break; break;
case ord('a'): case ORD('a'):
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
if (vs->linelen != 0) if (vs->linelen != 0)
@ -4177,7 +4177,7 @@ vi_cmd(int argcnt, const char *cmd)
insert = INSERT; insert = INSERT;
break; break;
case ord('A'): case ORD('A'):
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
del_range(0, 0); del_range(0, 0);
@ -4185,7 +4185,7 @@ vi_cmd(int argcnt, const char *cmd)
insert = INSERT; insert = INSERT;
break; break;
case ord('S'): case ORD('S'):
vs->cursor = domovebeg(); vs->cursor = domovebeg();
del_range(vs->cursor, vs->linelen); del_range(vs->cursor, vs->linelen);
modified = 1; modified = 1;
@ -4193,14 +4193,14 @@ vi_cmd(int argcnt, const char *cmd)
insert = INSERT; insert = INSERT;
break; break;
case ord('Y'): case ORD('Y'):
cmd = "y$"; cmd = "y$";
/* ahhhhhh... */ /* ahhhhhh... */
/* FALLTHROUGH */ /* FALLTHROUGH */
case ord('c'): case ORD('c'):
case ord('d'): case ORD('d'):
case ord('y'): case ORD('y'):
if (*cmd == cmd[1]) { if (*cmd == cmd[1]) {
c1 = *cmd == 'c' ? domovebeg() : 0; c1 = *cmd == 'c' ? domovebeg() : 0;
c2 = vs->linelen; c2 = vs->linelen;
@ -4239,7 +4239,7 @@ vi_cmd(int argcnt, const char *cmd)
} }
break; break;
case ord('p'): case ORD('p'):
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
if (vs->linelen != 0) if (vs->linelen != 0)
@ -4253,7 +4253,7 @@ vi_cmd(int argcnt, const char *cmd)
return (-1); return (-1);
break; break;
case ord('P'): case ORD('P'):
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
any = 0; any = 0;
@ -4266,25 +4266,25 @@ vi_cmd(int argcnt, const char *cmd)
return (-1); return (-1);
break; break;
case ord('C'): case ORD('C'):
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
del_range(vs->cursor, vs->linelen); del_range(vs->cursor, vs->linelen);
insert = INSERT; insert = INSERT;
break; break;
case ord('D'): case ORD('D'):
yank_range(vs->cursor, vs->linelen); yank_range(vs->cursor, vs->linelen);
del_range(vs->cursor, vs->linelen); del_range(vs->cursor, vs->linelen);
if (vs->cursor != 0) if (vs->cursor != 0)
vs->cursor--; vs->cursor--;
break; break;
case ord('g'): case ORD('g'):
if (!argcnt) if (!argcnt)
argcnt = hlast; argcnt = hlast;
/* FALLTHROUGH */ /* FALLTHROUGH */
case ord('G'): case ORD('G'):
if (!argcnt) if (!argcnt)
argcnt = 1; argcnt = 1;
else else
@ -4297,21 +4297,21 @@ vi_cmd(int argcnt, const char *cmd)
} }
break; break;
case ord('i'): case ORD('i'):
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
insert = INSERT; insert = INSERT;
break; break;
case ord('I'): case ORD('I'):
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
vs->cursor = domovebeg(); vs->cursor = domovebeg();
insert = INSERT; insert = INSERT;
break; break;
case ord('j'): case ORD('j'):
case ord('+'): case ORD('+'):
case CTRL_N: case CTRL_N:
if (grabhist(modified, hnum + argcnt) < 0) if (grabhist(modified, hnum + argcnt) < 0)
return (-1); return (-1);
@ -4321,8 +4321,8 @@ vi_cmd(int argcnt, const char *cmd)
} }
break; break;
case ord('k'): case ORD('k'):
case ord('-'): case ORD('-'):
case CTRL_P: case CTRL_P:
if (grabhist(modified, hnum - argcnt) < 0) if (grabhist(modified, hnum - argcnt) < 0)
return (-1); return (-1);
@ -4332,7 +4332,7 @@ vi_cmd(int argcnt, const char *cmd)
} }
break; break;
case ord('r'): case ORD('r'):
if (vs->linelen == 0) if (vs->linelen == 0)
return (-1); return (-1);
modified = 1; modified = 1;
@ -4350,13 +4350,13 @@ vi_cmd(int argcnt, const char *cmd)
} }
break; break;
case ord('R'): case ORD('R'):
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
insert = REPLACE; insert = REPLACE;
break; break;
case ord('s'): case ORD('s'):
if (vs->linelen == 0) if (vs->linelen == 0)
return (-1); return (-1);
modified = 1; modified = 1;
@ -4367,7 +4367,7 @@ vi_cmd(int argcnt, const char *cmd)
insert = INSERT; insert = INSERT;
break; break;
case ord('v'): case ORD('v'):
if (!argcnt) { if (!argcnt) {
if (vs->linelen == 0) if (vs->linelen == 0)
return (-1); return (-1);
@ -4390,7 +4390,7 @@ vi_cmd(int argcnt, const char *cmd)
vs->linelen = strlen(vs->cbuf); vs->linelen = strlen(vs->cbuf);
return (2); return (2);
case ord('x'): case ORD('x'):
if (vs->linelen == 0) if (vs->linelen == 0)
return (-1); return (-1);
modified = 1; modified = 1;
@ -4401,7 +4401,7 @@ vi_cmd(int argcnt, const char *cmd)
del_range(vs->cursor, vs->cursor + argcnt); del_range(vs->cursor, vs->cursor + argcnt);
break; break;
case ord('X'): case ORD('X'):
if (vs->cursor > 0) { if (vs->cursor > 0) {
modified = 1; modified = 1;
hnum = hlast; hnum = hlast;
@ -4414,13 +4414,13 @@ vi_cmd(int argcnt, const char *cmd)
return (-1); return (-1);
break; break;
case ord('u'): case ORD('u'):
t = vs; t = vs;
vs = undo; vs = undo;
undo = t; undo = t;
break; break;
case ord('U'): case ORD('U'):
if (!modified) if (!modified)
return (-1); return (-1);
if (grabhist(modified, ohnum) < 0) if (grabhist(modified, ohnum) < 0)
@ -4429,19 +4429,19 @@ vi_cmd(int argcnt, const char *cmd)
hnum = ohnum; hnum = ohnum;
break; break;
case ord('?'): case ORD('?'):
if (hnum == hlast) if (hnum == hlast)
hnum = -1; hnum = -1;
/* ahhh */ /* ahhh */
/* FALLTHROUGH */ /* FALLTHROUGH */
case ord('/'): case ORD('/'):
c3 = 1; c3 = 1;
srchlen = 0; srchlen = 0;
lastsearch = *cmd; lastsearch = *cmd;
/* FALLTHROUGH */ /* FALLTHROUGH */
case ord('n'): case ORD('n'):
case ord('N'): case ORD('N'):
if (lastsearch == ' ') if (lastsearch == ' ')
return (-1); return (-1);
if (lastsearch == '?') if (lastsearch == '?')
@ -4468,7 +4468,7 @@ vi_cmd(int argcnt, const char *cmd)
return (0); return (0);
} }
break; break;
case ord('_'): case ORD('_'):
{ {
bool inspace; bool inspace;
char *p, *sp; char *p, *sp;
@ -4520,7 +4520,7 @@ vi_cmd(int argcnt, const char *cmd)
} }
break; break;
case ord('~'): case ORD('~'):
{ {
char *p; char *p;
int i; int i;
@ -4544,7 +4544,7 @@ vi_cmd(int argcnt, const char *cmd)
break; break;
} }
case ord('#'): case ORD('#'):
{ {
int ret = x_do_comment(vs->cbuf, vs->cbufsize, int ret = x_do_comment(vs->cbuf, vs->cbufsize,
&vs->linelen); &vs->linelen);
@ -4554,7 +4554,7 @@ vi_cmd(int argcnt, const char *cmd)
} }
/* AT&T ksh */ /* AT&T ksh */
case ord('='): case ORD('='):
/* Nonstandard vi/ksh */ /* Nonstandard vi/ksh */
case CTRL_E: case CTRL_E:
print_expansions(vs, 1); print_expansions(vs, 1);
@ -4574,7 +4574,7 @@ vi_cmd(int argcnt, const char *cmd)
return (-1); return (-1);
/* FALLTHROUGH */ /* FALLTHROUGH */
/* AT&T ksh */ /* AT&T ksh */
case ord('\\'): case ORD('\\'):
/* Nonstandard vi/ksh */ /* Nonstandard vi/ksh */
case CTRL_F: case CTRL_F:
complete_word(1, argcnt); complete_word(1, argcnt);
@ -4582,7 +4582,7 @@ vi_cmd(int argcnt, const char *cmd)
/* AT&T ksh */ /* AT&T ksh */
case ord('*'): case ORD('*'):
/* Nonstandard vi/ksh */ /* Nonstandard vi/ksh */
case CTRL_X: case CTRL_X:
expand_word(1); expand_word(1);
@ -4590,8 +4590,8 @@ vi_cmd(int argcnt, const char *cmd)
/* mksh: cursor movement */ /* mksh: cursor movement */
case ord('['): case ORD('['):
case ord('O'): case ORD('O'):
state = VPREFIX2; state = VPREFIX2;
if (vs->linelen != 0) if (vs->linelen != 0)
vs->cursor++; vs->cursor++;
@ -4611,19 +4611,19 @@ domove(int argcnt, const char *cmd, int sub)
unsigned int bcount; unsigned int bcount;
switch (ord(*cmd)) { switch (ord(*cmd)) {
case ord('b'): case ORD('b'):
if (!sub && vs->cursor == 0) if (!sub && vs->cursor == 0)
return (-1); return (-1);
ncursor = backword(argcnt); ncursor = backword(argcnt);
break; break;
case ord('B'): case ORD('B'):
if (!sub && vs->cursor == 0) if (!sub && vs->cursor == 0)
return (-1); return (-1);
ncursor = Backword(argcnt); ncursor = Backword(argcnt);
break; break;
case ord('e'): case ORD('e'):
if (!sub && vs->cursor + 1 >= vs->linelen) if (!sub && vs->cursor + 1 >= vs->linelen)
return (-1); return (-1);
ncursor = endword(argcnt); ncursor = endword(argcnt);
@ -4631,7 +4631,7 @@ domove(int argcnt, const char *cmd, int sub)
ncursor++; ncursor++;
break; break;
case ord('E'): case ORD('E'):
if (!sub && vs->cursor + 1 >= vs->linelen) if (!sub && vs->cursor + 1 >= vs->linelen)
return (-1); return (-1);
ncursor = Endword(argcnt); ncursor = Endword(argcnt);
@ -4639,15 +4639,15 @@ domove(int argcnt, const char *cmd, int sub)
ncursor++; ncursor++;
break; break;
case ord('f'): case ORD('f'):
case ord('F'): case ORD('F'):
case ord('t'): case ORD('t'):
case ord('T'): case ORD('T'):
fsavecmd = *cmd; fsavecmd = *cmd;
fsavech = cmd[1]; fsavech = cmd[1];
/* FALLTHROUGH */ /* FALLTHROUGH */
case ord(','): case ORD(','):
case ord(';'): case ORD(';'):
if (fsavecmd == ' ') if (fsavecmd == ' ')
return (-1); return (-1);
i = ksh_eq(fsavecmd, 'F', 'f'); i = ksh_eq(fsavecmd, 'F', 'f');
@ -4661,7 +4661,7 @@ domove(int argcnt, const char *cmd, int sub)
ncursor++; ncursor++;
break; break;
case ord('h'): case ORD('h'):
case CTRL_H: case CTRL_H:
if (!sub && vs->cursor == 0) if (!sub && vs->cursor == 0)
return (-1); return (-1);
@ -4670,8 +4670,8 @@ domove(int argcnt, const char *cmd, int sub)
ncursor = 0; ncursor = 0;
break; break;
case ord(' '): case ORD(' '):
case ord('l'): case ORD('l'):
if (!sub && vs->cursor + 1 >= vs->linelen) if (!sub && vs->cursor + 1 >= vs->linelen)
return (-1); return (-1);
if (vs->linelen != 0) { if (vs->linelen != 0) {
@ -4681,27 +4681,27 @@ domove(int argcnt, const char *cmd, int sub)
} }
break; break;
case ord('w'): case ORD('w'):
if (!sub && vs->cursor + 1 >= vs->linelen) if (!sub && vs->cursor + 1 >= vs->linelen)
return (-1); return (-1);
ncursor = forwword(argcnt); ncursor = forwword(argcnt);
break; break;
case ord('W'): case ORD('W'):
if (!sub && vs->cursor + 1 >= vs->linelen) if (!sub && vs->cursor + 1 >= vs->linelen)
return (-1); return (-1);
ncursor = Forwword(argcnt); ncursor = Forwword(argcnt);
break; break;
case ord('0'): case ORD('0'):
ncursor = 0; ncursor = 0;
break; break;
case ord('^'): case ORD('^'):
ncursor = domovebeg(); ncursor = domovebeg();
break; break;
case ord('|'): case ORD('|'):
ncursor = argcnt; ncursor = argcnt;
if (ncursor > vs->linelen) if (ncursor > vs->linelen)
ncursor = vs->linelen; ncursor = vs->linelen;
@ -4709,14 +4709,14 @@ domove(int argcnt, const char *cmd, int sub)
ncursor--; ncursor--;
break; break;
case ord('$'): case ORD('$'):
if (vs->linelen != 0) if (vs->linelen != 0)
ncursor = vs->linelen; ncursor = vs->linelen;
else else
ncursor = 0; ncursor = 0;
break; break;
case ord('%'): case ORD('%'):
ncursor = vs->cursor; ncursor = vs->cursor;
while (ncursor < vs->linelen && while (ncursor < vs->linelen &&
(i = bracktype(vs->cbuf[ncursor])) == 0) (i = bracktype(vs->cbuf[ncursor])) == 0)
@ -4784,22 +4784,22 @@ bracktype(int ch)
{ {
switch (ord(ch)) { switch (ord(ch)) {
case ord('('): case ORD('('):
return (1); return (1);
case ord('['): case ORD('['):
return (2); return (2);
case ord('{'): case ORD('{'):
return (3); return (3);
case ord(')'): case ORD(')'):
return (-1); return (-1);
case ord(']'): case ORD(']'):
return (-2); return (-2);
case ord('}'): case ORD('}'):
return (-3); return (-3);
default: default:

View file

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015, 2016, 2017 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -23,7 +23,7 @@
#include "sh.h" #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 * string expansion
@ -320,21 +320,21 @@ expand(
case COMASUB: case COMASUB:
case COMSUB: case COMSUB:
*dp++ = '('; *dp++ = '(';
c = ord(')'); c = ORD(')');
break; break;
case FUNASUB: case FUNASUB:
case FUNSUB: case FUNSUB:
case VALSUB: case VALSUB:
*dp++ = '{'; *dp++ = '{';
*dp++ = c == VALSUB ? '|' : ' '; *dp++ = c == VALSUB ? '|' : ' ';
c = ord('}'); c = ORD('}');
break; break;
} }
while (*sp != '\0') { while (*sp != '\0') {
Xcheck(ds, dp); Xcheck(ds, dp);
*dp++ = *sp++; *dp++ = *sp++;
} }
if (c == ord('}')) if ((unsigned int)c == ORD('}'))
*dp++ = ';'; *dp++ = ';';
*dp++ = c; *dp++ = c;
} else { } else {
@ -436,11 +436,11 @@ expand(
if (stype) if (stype)
sp += slen; sp += slen;
switch (stype & STYPE_SINGLE) { switch (stype & STYPE_SINGLE) {
case ord('#') | STYPE_AT: case ORD('#') | STYPE_AT:
x.str = shf_smprintf("%08X", x.str = shf_smprintf("%08X",
(unsigned int)hash(str_val(st->var))); (unsigned int)hash(str_val(st->var)));
break; break;
case ord('Q') | STYPE_AT: { case ORD('Q') | STYPE_AT: {
struct shf shf; struct shf shf;
shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf); shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf);
@ -448,7 +448,7 @@ expand(
x.str = shf_sclose(&shf); x.str = shf_sclose(&shf);
break; break;
} }
case ord('0'): { case ORD('0'): {
char *beg, *mid, *end, *stg; char *beg, *mid, *end, *stg;
mksh_ari_t from = 0, num = -1, flen, finc = 0; mksh_ari_t from = 0, num = -1, flen, finc = 0;
@ -456,13 +456,13 @@ expand(
mid = beg + (wdscan(sp, ADELIM) - sp); mid = beg + (wdscan(sp, ADELIM) - sp);
stg = beg + (wdscan(sp, CSUBST) - sp); stg = beg + (wdscan(sp, CSUBST) - sp);
mid[-2] = EOS; mid[-2] = EOS;
if (ord(mid[-1]) == ord(/*{*/ '}')) { if (ord(mid[-1]) == ORD(/*{*/ '}')) {
sp += mid - beg - 1; sp += mid - beg - 1;
end = NULL; end = NULL;
} else { } else {
end = mid + end = mid +
(wdscan(mid, ADELIM) - mid); (wdscan(mid, ADELIM) - mid);
if (ord(end[-1]) != ord(/*{*/ '}')) if (ord(end[-1]) != ORD(/*{*/ '}'))
/* more than max delimiters */ /* more than max delimiters */
goto unwind_substsyn; goto unwind_substsyn;
end[-2] = EOS; end[-2] = EOS;
@ -495,8 +495,8 @@ expand(
strndupx(x.str, beg, num, ATEMP); strndupx(x.str, beg, num, ATEMP);
goto do_CSUBST; goto do_CSUBST;
} }
case ord('/') | STYPE_AT: case ORD('/') | STYPE_AT:
case ord('/'): { case ORD('/'): {
char *s, *p, *d, *sbeg, *end; char *s, *p, *d, *sbeg, *end;
char *pat = NULL, *rrep = null; char *pat = NULL, *rrep = null;
char fpat = 0, *tpat1, *tpat2; char fpat = 0, *tpat1, *tpat2;
@ -506,7 +506,7 @@ expand(
p = s + (wdscan(sp, ADELIM) - sp); p = s + (wdscan(sp, ADELIM) - sp);
d = s + (wdscan(sp, CSUBST) - sp); d = s + (wdscan(sp, CSUBST) - sp);
p[-2] = EOS; p[-2] = EOS;
if (ord(p[-1]) == ord(/*{*/ '}')) if (ord(p[-1]) == ORD(/*{*/ '}'))
d = NULL; d = NULL;
else else
d[-2] = EOS; d[-2] = EOS;
@ -547,11 +547,11 @@ expand(
} }
/* first see if we have any match at all */ /* first see if we have any match at all */
if (ord(fpat) == ord('#')) { if (ord(fpat) == ORD('#')) {
/* anchor at the beginning */ /* anchor at the beginning */
tpat1 = shf_smprintf("%s%c*", pat, MAGIC); tpat1 = shf_smprintf("%s%c*", pat, MAGIC);
tpat2 = tpat1; tpat2 = tpat1;
} else if (ord(fpat) == ord('%')) { } else if (ord(fpat) == ORD('%')) {
/* anchor at the end */ /* anchor at the end */
tpat1 = shf_smprintf("%c*%s", MAGIC, pat); tpat1 = shf_smprintf("%c*%s", MAGIC, pat);
tpat2 = pat; tpat2 = pat;
@ -569,7 +569,7 @@ expand(
goto end_repl; goto end_repl;
end = strnul(s); end = strnul(s);
/* now anchor the beginning of the match */ /* now anchor the beginning of the match */
if (ord(fpat) != ord('#')) if (ord(fpat) != ORD('#'))
while (sbeg <= end) { while (sbeg <= end) {
if (gmatchx(sbeg, tpat2, false)) if (gmatchx(sbeg, tpat2, false))
break; break;
@ -578,11 +578,11 @@ expand(
} }
/* now anchor the end of the match */ /* now anchor the end of the match */
p = end; p = end;
if (ord(fpat) != ord('%')) if (ord(fpat) != ORD('%'))
while (p >= sbeg) { while (p >= sbeg) {
bool gotmatch; bool gotmatch;
c = *p; c = ord(*p);
*p = '\0'; *p = '\0';
gotmatch = tobool(gmatchx(sbeg, pat, false)); gotmatch = tobool(gmatchx(sbeg, pat, false));
*p = c; *p = c;
@ -622,8 +622,8 @@ expand(
afree(ws, ATEMP); afree(ws, ATEMP);
goto do_CSUBST; goto do_CSUBST;
} }
case ord('#'): case ORD('#'):
case ord('%'): case ORD('%'):
/* ! DOBLANK,DOBRACE */ /* ! DOBLANK,DOBRACE */
f = (f & DONTRUNCOMMAND) | f = (f & DONTRUNCOMMAND) |
DOPAT | DOTILDE | DOPAT | DOTILDE |
@ -637,10 +637,10 @@ expand(
*/ */
if (!Flag(FSH)) { if (!Flag(FSH)) {
*dp++ = MAGIC; *dp++ = MAGIC;
*dp++ = ord(0x80 | '@'); *dp++ = ORD(0x80 | '@');
} }
break; break;
case ord('='): case ORD('='):
/* /*
* Tilde expansion for string * Tilde expansion for string
* variables in POSIX mode is * variables in POSIX mode is
@ -664,7 +664,7 @@ expand(
f &= ~(DOBLANK|DOGLOB|DOBRACE); f &= ~(DOBLANK|DOGLOB|DOBRACE);
tilde_ok = 1; tilde_ok = 1;
break; break;
case ord('?'): case ORD('?'):
if (*sp == CSUBST) if (*sp == CSUBST)
errorf("%s: parameter null or not set", errorf("%s: parameter null or not set",
st->var->name); st->var->name);
@ -699,8 +699,8 @@ expand(
if (f & DOBLANK) if (f & DOBLANK)
doblank--; doblank--;
switch (st->stype & STYPE_SINGLE) { switch (st->stype & STYPE_SINGLE) {
case ord('#'): case ORD('#'):
case ord('%'): case ORD('%'):
if (!Flag(FSH)) { if (!Flag(FSH)) {
/* Append end-pattern */ /* Append end-pattern */
*dp++ = MAGIC; *dp++ = MAGIC;
@ -730,7 +730,7 @@ expand(
doblank++; doblank++;
st = st->prev; st = st->prev;
continue; continue;
case ord('='): case ORD('='):
/* /*
* Restore our position and substitute * Restore our position and substitute
* the value of st->var (may not be * the value of st->var (may not be
@ -763,17 +763,17 @@ expand(
st = st->prev; st = st->prev;
word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
continue; continue;
case ord('?'): case ORD('?'):
dp = Xrestpos(ds, dp, st->base); dp = Xrestpos(ds, dp, st->base);
errorf(Tf_sD_s, st->var->name, errorf(Tf_sD_s, st->var->name,
debunk(dp, dp, strlen(dp) + 1)); debunk(dp, dp, strlen(dp) + 1));
break; break;
case ord('0'): case ORD('0'):
case ord('/') | STYPE_AT: case ORD('/') | STYPE_AT:
case ord('/'): case ORD('/'):
case ord('#') | STYPE_AT: case ORD('#') | STYPE_AT:
case ord('Q') | STYPE_AT: case ORD('Q') | STYPE_AT:
dp = Xrestpos(ds, dp, st->base); dp = Xrestpos(ds, dp, st->base);
type = XSUB; type = XSUB;
word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS; word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
@ -791,19 +791,19 @@ expand(
/* open pattern: *(foo|bar) */ /* open pattern: *(foo|bar) */
/* Next char is the type of pattern */ /* Next char is the type of pattern */
make_magic = true; make_magic = true;
c = *sp++ | 0x80; c = ord(*sp++) | 0x80U;
break; break;
case SPAT: case SPAT:
/* pattern separator (|) */ /* pattern separator (|) */
make_magic = true; make_magic = true;
c = '|'; c = ORD('|');
break; break;
case CPAT: case CPAT:
/* close pattern */ /* close pattern */
make_magic = true; make_magic = true;
c = /*(*/ ')'; c = ORD(/*(*/ ')');
break; break;
} }
break; break;
@ -824,7 +824,7 @@ expand(
case XSUB: case XSUB:
case XSUBMID: case XSUBMID:
if ((c = *x.str++) == 0) { if ((c = ord(*x.str++)) == 0) {
type = XBASE; type = XBASE;
if (f & DOBLANK) if (f & DOBLANK)
doblank--; doblank--;
@ -837,7 +837,7 @@ expand(
quote = 1; quote = 1;
/* FALLTHROUGH */ /* FALLTHROUGH */
case XARG: case XARG:
if ((c = *x.str++) == '\0') { if ((c = ord(*x.str++)) == '\0') {
/* /*
* force null words to be created so * force null words to be created so
* set -- "" 2 ""; echo "$@" will do * set -- "" 2 ""; echo "$@" will do
@ -855,13 +855,13 @@ expand(
if ((f & DOHEREDOC)) { if ((f & DOHEREDOC)) {
/* pseudo-field-split reliably */ /* pseudo-field-split reliably */
if (c == 0) if (c == 0)
c = ' '; c = ORD(' ');
break; break;
} }
if ((f & DOSCALAR)) { if ((f & DOSCALAR)) {
/* do not field-split */ /* do not field-split */
if (x.split) { if (x.split) {
c = ' '; c = ORD(' ');
break; break;
} }
if (c == 0) if (c == 0)
@ -873,7 +873,7 @@ expand(
if (!quote && word == IFS_WS) if (!quote && word == IFS_WS)
continue; continue;
/* this is so we don't terminate */ /* this is so we don't terminate */
c = ' '; c = ORD(' ');
/* now force-emit a word */ /* now force-emit a word */
goto emit_word; goto emit_word;
} }
@ -893,33 +893,33 @@ expand(
c = -1; c = -1;
} else if (newlines) { } else if (newlines) {
/* spit out saved NLs */ /* spit out saved NLs */
c = '\n'; c = ORD('\n');
--newlines; --newlines;
} else { } else {
while ((c = shf_getc(x.u.shf)) == 0 || while ((c = shf_getc(x.u.shf)) == 0 ||
ctype(c, C_NL)) { cinttype(c, C_NL)) {
#ifdef MKSH_WITH_TEXTMODE #ifdef MKSH_WITH_TEXTMODE
if (c == '\r') { if (c == ORD('\r')) {
c = shf_getc(x.u.shf); c = shf_getc(x.u.shf);
switch (c) { switch (c) {
case '\n': case ORD('\n'):
break; break;
default: default:
shf_ungetc(c, x.u.shf); shf_ungetc(c, x.u.shf);
/* FALLTHROUGH */ /* FALLTHROUGH */
case -1: case -1:
c = '\r'; c = ORD('\r');
break; break;
} }
} }
#endif #endif
if (c == '\n') if (c == ORD('\n'))
/* save newlines */ /* save newlines */
newlines++; newlines++;
} }
if (newlines && c != -1) { if (newlines && c != -1) {
shf_ungetc(c, x.u.shf); shf_ungetc(c, x.u.shf);
c = '\n'; c = ORD('\n');
--newlines; --newlines;
} }
} }
@ -1003,10 +1003,10 @@ expand(
/* mark any special second pass chars */ /* mark any special second pass chars */
if (!quote) if (!quote)
switch (ord(c)) { 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 * For character classes - doesn't hurt
* to have magic !,-,]s outside of * to have magic !,-,]s outside of
@ -1014,29 +1014,29 @@ expand(
*/ */
if (f & (DOPAT | DOGLOB)) { if (f & (DOPAT | DOGLOB)) {
fdo |= DOMAGIC; fdo |= DOMAGIC;
if (c == ord('[')) if ((unsigned int)c == ORD('['))
fdo |= f & DOGLOB; fdo |= f & DOGLOB;
*dp++ = MAGIC; *dp++ = MAGIC;
} }
break; break;
case ord('*'): case ORD('*'):
case ord('?'): case ORD('?'):
if (f & (DOPAT | DOGLOB)) { if (f & (DOPAT | DOGLOB)) {
fdo |= DOMAGIC | (f & DOGLOB); fdo |= DOMAGIC | (f & DOGLOB);
*dp++ = MAGIC; *dp++ = MAGIC;
} }
break; break;
case ord('{'): case ORD('{'):
case ord('}'): case ORD('}'):
case ord(','): case ORD(','):
if ((f & DOBRACE) && if ((f & DOBRACE) &&
(ord(c) == ord('{' /*}*/) || (ord(c) == ORD('{' /*}*/) ||
(fdo & DOBRACE))) { (fdo & DOBRACE))) {
fdo |= DOBRACE|DOMAGIC; fdo |= DOBRACE|DOMAGIC;
*dp++ = MAGIC; *dp++ = MAGIC;
} }
break; break;
case ord('='): case ORD('='):
/* Note first unquoted = for ~ */ /* Note first unquoted = for ~ */
if (!(f & DOTEMP) && (!Flag(FPOSIX) || if (!(f & DOTEMP) && (!Flag(FPOSIX) ||
(f & DOASNTILDE)) && !saw_eq) { (f & DOASNTILDE)) && !saw_eq) {
@ -1044,13 +1044,13 @@ expand(
tilde_ok = 1; tilde_ok = 1;
} }
break; break;
case ord(':'): case ORD(':'):
/* : */ /* : */
/* Note unquoted : for ~ */ /* Note unquoted : for ~ */
if (!(f & DOTEMP) && (f & DOASNTILDE)) if (!(f & DOTEMP) && (f & DOASNTILDE))
tilde_ok = 1; tilde_ok = 1;
break; break;
case ord('~'): case ORD('~'):
/* /*
* tilde_ok is reset whenever * tilde_ok is reset whenever
* any of ' " $( $(( ${ } are seen. * 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) * ${%var}, string width (-U: screen columns, +U: octets)
*/ */
c = ord(sp[1]); c = ord(sp[1]);
if (stype == ord('%') && c == '\0') if ((unsigned int)stype == ORD('%') && c == '\0')
return (-1); return (-1);
if (ctype(stype, C_SUB2) && c != '\0') { if (ctype(stype, C_SUB2) && c != '\0') {
/* Can't have any modifiers for ${#...} or ${%...} */ /* Can't have any modifiers for ${#...} or ${%...} */
@ -1141,11 +1141,11 @@ varsub(Expand *xp, const char *sp, const char *word,
return (-1); return (-1);
sp++; sp++;
/* Check for size of array */ /* Check for size of array */
if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ord('*') || if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') ||
ord(p[1]) == ord('@')) && ord(p[2]) == ord(']')) { ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) {
int n = 0; int n = 0;
if (stype != ord('#')) if ((unsigned int)stype != ORD('#'))
return (-1); return (-1);
vp = global(arrayname(sp)); vp = global(arrayname(sp));
if (vp->flag & (ISSET|ARRAY)) if (vp->flag & (ISSET|ARRAY))
@ -1154,14 +1154,15 @@ varsub(Expand *xp, const char *sp, const char *word,
if (vp->flag & ISSET) if (vp->flag & ISSET)
n++; n++;
c = n; c = n;
} else if (c == ord('*') || c == ord('@')) { } else if ((unsigned int)c == ORD('*') ||
if (stype != ord('#')) (unsigned int)c == ORD('@')) {
if ((unsigned int)stype != ORD('#'))
return (-1); return (-1);
c = e->loc->argc; c = e->loc->argc;
} else { } else {
p = str_val(global(sp)); p = str_val(global(sp));
zero_ok = p != null; zero_ok = p != null;
if (stype == ord('#')) if ((unsigned int)stype == ORD('#'))
c = utflen(p); c = utflen(p);
else { else {
/* partial utf_mbswidth reimplementation */ /* partial utf_mbswidth reimplementation */
@ -1196,11 +1197,11 @@ varsub(Expand *xp, const char *sp, const char *word,
xp->str = shf_smprintf(Tf_d, c); xp->str = shf_smprintf(Tf_d, c);
return (XSUB); return (XSUB);
} }
if (stype == ord('!') && c != '\0' && *word == CSUBST) { if ((unsigned int)stype == ORD('!') && c != '\0' && *word == CSUBST) {
sp++; sp++;
if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ord('*') || if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') ||
ord(p[1]) == ord('@')) && ord(p[2]) == ord(']')) { ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) {
c = ord('!'); c = ORD('!');
stype = 0; stype = 0;
goto arraynames; goto arraynames;
} }
@ -1214,12 +1215,12 @@ varsub(Expand *xp, const char *sp, const char *word,
/* Check for qualifiers in word part */ /* Check for qualifiers in word part */
stype = 0; stype = 0;
c = word[slen + 0] == CHAR ? ord(word[slen + 1]) : 0; c = word[slen + 0] == CHAR ? ord(word[slen + 1]) : 0;
if (c == ord(':')) { if ((unsigned int)c == ORD(':')) {
slen += 2; slen += 2;
stype = STYPE_DBL; stype = STYPE_DBL;
c = word[slen + 0] == CHAR ? ord(word[slen + 1]) : 0; c = word[slen + 0] == CHAR ? ord(word[slen + 1]) : 0;
} }
if (!stype && c == ord('/')) { if (!stype && (unsigned int)c == ORD('/')) {
slen += 2; slen += 2;
stype = c; stype = c;
if (word[slen] == ADELIM && if (word[slen] == ADELIM &&
@ -1227,8 +1228,9 @@ varsub(Expand *xp, const char *sp, const char *word,
slen += 2; slen += 2;
stype |= STYPE_DBL; stype |= STYPE_DBL;
} }
} else if (stype == STYPE_DBL && (c == ord(' ') || c == ord('0'))) { } else if (stype == STYPE_DBL && ((unsigned int)c == ORD(' ') ||
stype |= ord('0'); (unsigned int)c == ORD('0'))) {
stype |= ORD('0');
} else if (ctype(c, C_SUB1)) { } else if (ctype(c, C_SUB1)) {
slen += 2; slen += 2;
stype |= c; stype |= c;
@ -1241,13 +1243,13 @@ varsub(Expand *xp, const char *sp, const char *word,
stype |= STYPE_DBL; stype |= STYPE_DBL;
slen += 2; slen += 2;
} }
} else if (c == ord('@')) { } else if ((unsigned int)c == ORD('@')) {
/* @x where x is command char */ /* @x where x is command char */
switch (c = ord(word[slen + 2]) == CHAR ? switch (c = ord(word[slen + 2]) == CHAR ?
ord(word[slen + 3]) : 0) { ord(word[slen + 3]) : 0) {
case ord('#'): case ORD('#'):
case ord('/'): case ORD('/'):
case ord('Q'): case ORD('Q'):
break; break;
default: default:
return (-1); return (-1);
@ -1261,50 +1263,50 @@ varsub(Expand *xp, const char *sp, const char *word,
return (-1); return (-1);
c = ord(sp[0]); c = ord(sp[0]);
if (c == ord('*') || c == ord('@')) { if ((unsigned int)c == ORD('*') || (unsigned int)c == ORD('@')) {
switch (stype & STYPE_SINGLE) { switch (stype & STYPE_SINGLE) {
/* can't assign to a vector */ /* can't assign to a vector */
case ord('='): case ORD('='):
/* can't trim a vector (yet) */ /* can't trim a vector (yet) */
case ord('%'): case ORD('%'):
case ord('#'): case ORD('#'):
case ord('?'): case ORD('?'):
case ord('0'): case ORD('0'):
case ord('/') | STYPE_AT: case ORD('/') | STYPE_AT:
case ord('/'): case ORD('/'):
case ord('#') | STYPE_AT: case ORD('#') | STYPE_AT:
case ord('Q') | STYPE_AT: case ORD('Q') | STYPE_AT:
return (-1); return (-1);
} }
if (e->loc->argc == 0) { if (e->loc->argc == 0) {
xp->str = null; xp->str = null;
xp->var = global(sp); xp->var = global(sp);
state = c == ord('@') ? XNULLSUB : XSUB; state = (unsigned int)c == ORD('@') ? XNULLSUB : XSUB;
} else { } else {
xp->u.strv = (const char **)e->loc->argv + 1; xp->u.strv = (const char **)e->loc->argv + 1;
xp->str = *xp->u.strv++; xp->str = *xp->u.strv++;
/* $@ */ /* $@ */
xp->split = tobool(c == ord('@')); xp->split = tobool((unsigned int)c == ORD('@'));
state = XARG; state = XARG;
} }
/* POSIX 2009? */ /* POSIX 2009? */
zero_ok = true; zero_ok = true;
} else if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ord('*') || } else if ((p = cstrchr(sp, '[')) && (ord(p[1]) == ORD('*') ||
ord(p[1]) == ord('@')) && ord(p[2]) == ord(']')) { ord(p[1]) == ORD('@')) && ord(p[2]) == ORD(']')) {
XPtrV wv; XPtrV wv;
switch (stype & STYPE_SINGLE) { switch (stype & STYPE_SINGLE) {
/* can't assign to a vector */ /* can't assign to a vector */
case ord('='): case ORD('='):
/* can't trim a vector (yet) */ /* can't trim a vector (yet) */
case ord('%'): case ORD('%'):
case ord('#'): case ORD('#'):
case ord('?'): case ORD('?'):
case ord('0'): case ORD('0'):
case ord('/') | STYPE_AT: case ORD('/') | STYPE_AT:
case ord('/'): case ORD('/'):
case ord('#') | STYPE_AT: case ORD('#') | STYPE_AT:
case ord('Q') | STYPE_AT: case ORD('Q') | STYPE_AT:
return (-1); return (-1);
} }
c = 0; c = 0;
@ -1314,28 +1316,28 @@ varsub(Expand *xp, const char *sp, const char *word,
for (; vp; vp = vp->u.array) { for (; vp; vp = vp->u.array) {
if (!(vp->flag&ISSET)) if (!(vp->flag&ISSET))
continue; continue;
XPput(wv, c == ord('!') ? shf_smprintf(Tf_lu, XPput(wv, (unsigned int)c == ORD('!') ?
arrayindex(vp)) : shf_smprintf(Tf_lu, arrayindex(vp)) :
str_val(vp)); str_val(vp));
} }
if (XPsize(wv) == 0) { if (XPsize(wv) == 0) {
xp->str = null; xp->str = null;
state = ord(p[1]) == ord('@') ? XNULLSUB : XSUB; state = ord(p[1]) == ORD('@') ? XNULLSUB : XSUB;
XPfree(wv); XPfree(wv);
} else { } else {
XPput(wv, 0); XPput(wv, 0);
xp->u.strv = (const char **)XPptrv(wv); xp->u.strv = (const char **)XPptrv(wv);
xp->str = *xp->u.strv++; xp->str = *xp->u.strv++;
/* ${foo[@]} */ /* ${foo[@]} */
xp->split = tobool(ord(p[1]) == ord('@')); xp->split = tobool(ord(p[1]) == ORD('@'));
state = XARG; state = XARG;
} }
} else { } else {
xp->var = global(sp); xp->var = global(sp);
xp->str = str_val(xp->var); xp->str = str_val(xp->var);
/* can't assign things like $! or $1 */ /* can't assign things like $! or $1 */
if ((stype & STYPE_SINGLE) == ord('=') && !*xp->str && if ((unsigned int)(stype & STYPE_SINGLE) == ORD('=') &&
ctype(*sp, C_VAR1 | C_DIGIT)) !*xp->str && ctype(*sp, C_VAR1 | C_DIGIT))
return (-1); return (-1);
state = XSUB; state = XSUB;
} }
@ -1346,13 +1348,15 @@ varsub(Expand *xp, const char *sp, const char *word,
(((stype & STYPE_DBL) ? *xp->str == '\0' : xp->str == null) && (((stype & STYPE_DBL) ? *xp->str == '\0' : xp->str == null) &&
(state != XARG || (ifs0 || xp->split ? (state != XARG || (ifs0 || xp->split ?
(xp->u.strv[0] == NULL) : !hasnonempty(xp->u.strv))) ? (xp->u.strv[0] == NULL) : !hasnonempty(xp->u.strv))) ?
ctype(c, C_EQUAL | C_MINUS | C_QUEST) : c == ord('+')))) || ctype(c, C_EQUAL | C_MINUS | C_QUEST) : (unsigned int)c == ORD('+')))) ||
stype == (ord('0') | STYPE_DBL) || stype == (ord('#') | STYPE_AT) || (unsigned int)stype == (ORD('0') | STYPE_DBL) ||
stype == (ord('Q') | STYPE_AT) || (stype & STYPE_CHAR) == ord('/')) (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 */ /* expand word instead of variable value */
state = XBASE; state = XBASE;
if (Flag(FNOUNSET) && xp->str == null && !zero_ok && 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); errorf(Tf_parm, sp);
*stypep = stype; *stypep = stype;
*slenp = slen; *slenp = slen;
@ -1491,7 +1495,7 @@ trimsub(char *str, char *pat, int how)
char *p, c; char *p, c;
switch (how & (STYPE_CHAR | STYPE_DBL)) { switch (how & (STYPE_CHAR | STYPE_DBL)) {
case ord('#'): case ORD('#'):
/* shortest match at beginning */ /* shortest match at beginning */
for (p = str; p <= end; p += utf_ptradj(p)) { for (p = str; p <= end; p += utf_ptradj(p)) {
c = *p; *p = '\0'; c = *p; *p = '\0';
@ -1503,7 +1507,7 @@ trimsub(char *str, char *pat, int how)
*p = c; *p = c;
} }
break; break;
case ord('#') | STYPE_DBL: case ORD('#') | STYPE_DBL:
/* longest match at beginning */ /* longest match at beginning */
for (p = end; p >= str; p--) { for (p = end; p >= str; p--) {
c = *p; *p = '\0'; c = *p; *p = '\0';
@ -1515,7 +1519,7 @@ trimsub(char *str, char *pat, int how)
*p = c; *p = c;
} }
break; break;
case ord('%'): case ORD('%'):
/* shortest match at end */ /* shortest match at end */
p = end; p = end;
while (p >= str) { while (p >= str) {
@ -1531,7 +1535,7 @@ trimsub(char *str, char *pat, int how)
--p; --p;
} }
break; break;
case ord('%') | STYPE_DBL: case ORD('%') | STYPE_DBL:
/* longest match at end */ /* longest match at end */
for (p = str; p <= end; p++) for (p = str; p <= end; p++)
if (gmatchx(p, pat, false)) { 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; char *p = exp_start;
/* search for open brace */ /* search for open brace */
while ((p = strchr(p, MAGIC)) && ord(p[1]) != ord('{' /*}*/)) while ((p = strchr(p, MAGIC)) && ord(p[1]) != ORD('{' /*}*/))
p += 2; p += 2;
brace_start = p; brace_start = p;
@ -1874,9 +1878,9 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
p += 2; p += 2;
while (*p && count) { while (*p && count) {
if (ISMAGIC(*p++)) { if (ISMAGIC(*p++)) {
if (ord(*p) == ord('{' /*}*/)) if (ord(*p) == ORD('{' /*}*/))
++count; ++count;
else if (ord(*p) == ord(/*{*/ '}')) else if (ord(*p) == ORD(/*{*/ '}'))
--count; --count;
else if (*p == ',' && count == 1) else if (*p == ',' && count == 1)
comma = p; comma = p;
@ -1908,9 +1912,9 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
count = 1; count = 1;
for (p = brace_start + 2; p != brace_end; p++) { for (p = brace_start + 2; p != brace_end; p++) {
if (ISMAGIC(*p)) { if (ISMAGIC(*p)) {
if (ord(*++p) == ord('{' /*}*/)) if (ord(*++p) == ORD('{' /*}*/))
++count; ++count;
else if ((ord(*p) == ord(/*{*/ '}') && --count == 0) || else if ((ord(*p) == ORD(/*{*/ '}') && --count == 0) ||
(*p == ',' && count == 1)) { (*p == ',' && count == 1)) {
char *news; char *news;
int l1, l2, l3; int l1, l2, l3;

View file

@ -23,7 +23,7 @@
#include "sh.h" #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 #ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@ -953,8 +953,12 @@ scriptexec(struct op *tp, const char **ap)
} }
#ifdef __OS2__ #ifdef __OS2__
/* /*
* Search shell/interpreter name without directory in PATH * On OS/2, the directory structure differs from normal
* if specified path does not exist * 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)) { if (mksh_vdirsep(sh) && !search_path(sh, path, X_OK, NULL)) {
cp = search_path(_getname(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; char *fpath;
union mksh_cchack npath; union mksh_cchack npath;
if (mksh_vdirsep(name) if (mksh_vdirsep(name)) {
#ifdef MKSH_DOSPATH
&& (strcmp(name, T_builtin) != 0)
#endif
) {
insert = 0; insert = 0;
/* prevent FPATH search below */ /* prevent FPATH search below */
flags &= ~FC_FUNC; flags &= ~FC_FUNC;

View file

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2016, 2017 * 2011, 2012, 2013, 2014, 2016, 2017, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -23,7 +23,7 @@
#include "sh.h" #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 #define EXPRTOK_DEFNS
#include "exprtok.h" #include "exprtok.h"
@ -558,9 +558,11 @@ exprtoken(Expr_state *es)
/* skip whitespace */ /* skip whitespace */
skip_spaces: skip_spaces:
while (ctype(ord((c = *cp)), C_SPACE)) --cp;
++cp; do {
if (es->tokp == es->expression && c == ord('#')) { c = ord(*++cp);
} while (ctype(c, C_SPACE));
if (es->tokp == es->expression && (unsigned int)c == ORD('#')) {
/* expression begins with # */ /* expression begins with # */
/* switch to unsigned */ /* switch to unsigned */
es->natural = true; es->natural = true;
@ -575,7 +577,7 @@ exprtoken(Expr_state *es)
do { do {
c = ord(*++cp); c = ord(*++cp);
} while (ctype(c, C_ALNUX)); } while (ctype(c, C_ALNUX));
if (c == ord('[')) { if ((unsigned int)c == ORD('[')) {
size_t len; size_t len;
len = array_ref_len(cp); 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 * 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[] = { static const struct mb_ucsrange mb_ucs_combining[] = {
@ -895,16 +897,14 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x05C1, 0x05C2 }, { 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C5 }, { 0x05C4, 0x05C5 },
{ 0x05C7, 0x05C7 }, { 0x05C7, 0x05C7 },
{ 0x0600, 0x0605 },
{ 0x0610, 0x061A }, { 0x0610, 0x061A },
{ 0x061C, 0x061C }, { 0x061C, 0x061C },
{ 0x064B, 0x065F }, { 0x064B, 0x065F },
{ 0x0670, 0x0670 }, { 0x0670, 0x0670 },
{ 0x06D6, 0x06DD }, { 0x06D6, 0x06DC },
{ 0x06DF, 0x06E4 }, { 0x06DF, 0x06E4 },
{ 0x06E7, 0x06E8 }, { 0x06E7, 0x06E8 },
{ 0x06EA, 0x06ED }, { 0x06EA, 0x06ED },
{ 0x070F, 0x070F },
{ 0x0711, 0x0711 }, { 0x0711, 0x0711 },
{ 0x0730, 0x074A }, { 0x0730, 0x074A },
{ 0x07A6, 0x07B0 }, { 0x07A6, 0x07B0 },
@ -914,7 +914,8 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x0825, 0x0827 }, { 0x0825, 0x0827 },
{ 0x0829, 0x082D }, { 0x0829, 0x082D },
{ 0x0859, 0x085B }, { 0x0859, 0x085B },
{ 0x08D4, 0x0902 }, { 0x08D4, 0x08E1 },
{ 0x08E3, 0x0902 },
{ 0x093A, 0x093A }, { 0x093A, 0x093A },
{ 0x093C, 0x093C }, { 0x093C, 0x093C },
{ 0x0941, 0x0948 }, { 0x0941, 0x0948 },

View file

@ -38,7 +38,7 @@
#endif #endif
#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 #if HAVE_KILLPG
/* /*
@ -594,7 +594,7 @@ c_print(const char **wp)
static int static int
s_get(void) s_get(void)
{ {
return (*s_ptr++); return (ord(*s_ptr++));
} }
static void static void
@ -751,9 +751,9 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
bool bool
valid_alias_name(const char *cp) valid_alias_name(const char *cp)
{ {
if (ord(*cp) == ord('-')) if (ord(*cp) == ORD('-'))
return (false); 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); return (false);
while (*cp) while (*cp)
if (ctype(*cp, C_ALIAS)) if (ctype(*cp, C_ALIAS))
@ -2304,9 +2304,9 @@ c_unset(const char **wp)
size_t n; size_t n;
n = strlen(id); n = strlen(id);
if (n > 3 && ord(id[n - 3]) == ord('[') && if (n > 3 && ord(id[n - 3]) == ORD('[') &&
ord(id[n - 2]) == ord('*') && ord(id[n - 2]) == ORD('*') &&
ord(id[n - 1]) == ord(']')) { ord(id[n - 1]) == ORD(']')) {
strndupx(cp, id, n - 3, ATEMP); strndupx(cp, id, n - 3, ATEMP);
id = cp; id = cp;
optc = 3; optc = 3;
@ -3539,7 +3539,7 @@ c_cat(const char **wp)
continue; continue;
} }
if (errno == EPIPE) { if (errno == EPIPE) {
/* fake receiving signel */ /* fake receiving signal */
rv = ksh_sigmask(SIGPIPE); rv = ksh_sigmask(SIGPIPE);
} else { } else {
/* an error occured during writing */ /* an error occured during writing */

View file

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
* 2012, 2013, 2014, 2015, 2016 * 2012, 2013, 2014, 2015, 2016, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -23,7 +23,7 @@
#include "sh.h" #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 #if HAVE_KILLPG
#define mksh_killpg killpg #define mksh_killpg killpg
@ -1545,7 +1545,9 @@ j_print(Job *j, int how, struct shf *shf)
Proc *p; Proc *p;
int state; int state;
int status; int status;
#ifdef WCOREDUMP
bool coredumped; bool coredumped;
#endif
char jobchar = ' '; char jobchar = ' ';
char buf[64]; char buf[64];
const char *filler; const char *filler;
@ -1569,7 +1571,9 @@ j_print(Job *j, int how, struct shf *shf)
jobchar = '-'; jobchar = '-';
for (p = j->proc_list; p != NULL;) { for (p = j->proc_list; p != NULL;) {
#ifdef WCOREDUMP
coredumped = false; coredumped = false;
#endif
switch (p->state) { switch (p->state) {
case PRUNNING: case PRUNNING:
memcpy(buf, "Running", 8); memcpy(buf, "Running", 8);
@ -1603,7 +1607,10 @@ j_print(Job *j, int how, struct shf *shf)
* kludge for not reporting 'normal termination * kludge for not reporting 'normal termination
* signals' (i.e. SIGINT, SIGPIPE) * signals' (i.e. SIGINT, SIGPIPE)
*/ */
if (how == JP_SHORT && !coredumped && if (how == JP_SHORT &&
#ifdef WCOREDUMP
!coredumped &&
#endif
(termsig == SIGINT || termsig == SIGPIPE)) { (termsig == SIGINT || termsig == SIGPIPE)) {
buf[0] = '\0'; buf[0] = '\0';
} else } else
@ -1629,14 +1636,22 @@ j_print(Job *j, int how, struct shf *shf)
if (how == JP_SHORT) { if (how == JP_SHORT) {
if (buf[0]) { if (buf[0]) {
output = 1; output = 1;
#ifdef WCOREDUMP
shf_fprintf(shf, "%s%s ", shf_fprintf(shf, "%s%s ",
buf, coredumped ? " (core dumped)" : null); buf, coredumped ? " (core dumped)" : null);
#else
shf_puts(buf, shf);
shf_putchar(' ', shf);
#endif
} }
} else { } else {
output = 1; output = 1;
shf_fprintf(shf, "%-20s %s%s%s", buf, p->command, shf_fprintf(shf, "%-20s %s%s%s", buf, p->command,
p->next ? "|" : null, p->next ? "|" : null,
coredumped ? " (core dumped)" : null); #ifdef WCOREDUMP
coredumped ? " (core dumped)" :
#endif
null);
} }
state = p->state; state = p->state;

250
src/lex.c
View file

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015, 2016, 2017 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -23,7 +23,7 @@
#include "sh.h" #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 * states while lexing word
@ -127,11 +127,11 @@ static int ignore_backslash_newline;
static int static int
getsc_i(void) 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) #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
#define getsc() ord(getsc_i()) #define getsc() getsc_i()
#else #else
static int getsc_r(int); static int getsc_r(int);
@ -141,7 +141,7 @@ getsc_r(int c)
o_getsc_r(c); o_getsc_r(c);
} }
#define getsc() ord(getsc_r(o_getsc())) #define getsc() getsc_r((unsigned int)(unsigned char)o_getsc())
#endif #endif
#define STATE_BSIZE 8 #define STATE_BSIZE 8
@ -220,12 +220,14 @@ yylex(int cf)
} else { } else {
/* normal lexing */ /* normal lexing */
state = (cf & HEREDELIM) ? SHEREDELIM : SBASE; state = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
while (ctype((c = getsc()), C_BLANK)) do {
; c = getsc();
} while (ctype(c, C_BLANK));
if (c == '#') { if (c == '#') {
ignore_backslash_newline++; ignore_backslash_newline++;
while (!ctype((c = getsc()), C_NUL | C_LF)) do {
; c = getsc();
} while (!ctype(c, C_NUL | C_LF));
ignore_backslash_newline--; ignore_backslash_newline--;
} }
ungetsc(c); ungetsc(c);
@ -245,30 +247,32 @@ yylex(int cf)
while (!((c = getsc()) == 0 || while (!((c = getsc()) == 0 ||
((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) { ((state == SBASE || state == SHEREDELIM) && ctype(c, C_LEX1)))) {
if (state == SBASE && if (state == SBASE &&
subshell_nesting_type == ord(/*{*/ '}') && subshell_nesting_type == ORD(/*{*/ '}') &&
c == ord(/*{*/ '}')) (unsigned int)c == ORD(/*{*/ '}'))
/* possibly end ${ :;} */ /* possibly end ${ :;} */
break; break;
Xcheck(ws, wp); Xcheck(ws, wp);
switch (state) { switch (state) {
case SADELIM: case SADELIM:
if (c == ord('(')) if ((unsigned int)c == ORD('('))
statep->nparen++; statep->nparen++;
else if (c == ord(')')) else if ((unsigned int)c == ORD(')'))
statep->nparen--; statep->nparen--;
else if (statep->nparen == 0 && (c == ord(/*{*/ '}') || else if (statep->nparen == 0 &&
((unsigned int)c == ORD(/*{*/ '}') ||
c == (int)statep->ls_adelim.delimiter)) { c == (int)statep->ls_adelim.delimiter)) {
*wp++ = ADELIM; *wp++ = ADELIM;
*wp++ = c; *wp++ = c;
if (c == ord(/*{*/ '}') || --statep->ls_adelim.num == 0) if ((unsigned int)c == ORD(/*{*/ '}') ||
--statep->ls_adelim.num == 0)
POP_STATE(); POP_STATE();
if (c == ord(/*{*/ '}')) if ((unsigned int)c == ORD(/*{*/ '}'))
POP_STATE(); POP_STATE();
break; break;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case SBASE: case SBASE:
if (c == ord('[') && (cf & CMDASN)) { if ((unsigned int)c == ORD('[') && (cf & CMDASN)) {
/* temporary */ /* temporary */
*wp = EOS; *wp = EOS;
if (is_wdvarname(Xstring(ws, wp), false)) { if (is_wdvarname(Xstring(ws, wp), false)) {
@ -284,15 +288,6 @@ yylex(int cf)
} }
afree(tmp, ATEMP); afree(tmp, ATEMP);
break; break;
} else {
Source *s;
s = pushs(SREREAD,
source->areap);
s->start = s->str =
s->u.freeme = tmp;
s->next = source;
source = s;
} }
} }
*wp++ = CHAR; *wp++ = CHAR;
@ -303,7 +298,7 @@ yylex(int cf)
Sbase1: /* includes *(...|...) pattern (*+?@!) */ Sbase1: /* includes *(...|...) pattern (*+?@!) */
if (ctype(c, C_PATMO)) { if (ctype(c, C_PATMO)) {
c2 = getsc(); c2 = getsc();
if (c2 == ord('(' /*)*/)) { if ((unsigned int)c2 == ORD('(' /*)*/)) {
*wp++ = OPAT; *wp++ = OPAT;
*wp++ = c; *wp++ = c;
PUSH_STATE(SPATTERN); PUSH_STATE(SPATTERN);
@ -314,7 +309,7 @@ yylex(int cf)
/* FALLTHROUGH */ /* FALLTHROUGH */
Sbase2: /* doesn't include *(...|...) pattern (*+?@!) */ Sbase2: /* doesn't include *(...|...) pattern (*+?@!) */
switch (c) { switch (c) {
case ord('\\'): case ORD('\\'):
getsc_qchar: getsc_qchar:
if ((c = getsc())) { if ((c = getsc())) {
/* trailing \ is lost */ /* trailing \ is lost */
@ -322,7 +317,7 @@ yylex(int cf)
*wp++ = c; *wp++ = c;
} }
break; break;
case ord('\''): case ORD('\''):
open_ssquote_unless_heredoc: open_ssquote_unless_heredoc:
if ((cf & HEREDOC)) if ((cf & HEREDOC))
goto store_char; goto store_char;
@ -330,12 +325,12 @@ yylex(int cf)
ignore_backslash_newline++; ignore_backslash_newline++;
PUSH_STATE(SSQUOTE); PUSH_STATE(SSQUOTE);
break; break;
case ord('"'): case ORD('"'):
open_sdquote: open_sdquote:
*wp++ = OQUOTE; *wp++ = OQUOTE;
PUSH_STATE(SDQUOTE); PUSH_STATE(SDQUOTE);
break; break;
case ord('$'): case ORD('$'):
/* /*
* processing of dollar sign belongs into * processing of dollar sign belongs into
* Subst, except for those which can open * Subst, except for those which can open
@ -344,9 +339,9 @@ yylex(int cf)
subst_dollar_ex: subst_dollar_ex:
c = getsc(); c = getsc();
switch (c) { switch (c) {
case ord('"'): case ORD('"'):
goto open_sdquote; goto open_sdquote;
case ord('\''): case ORD('\''):
goto open_sequote; goto open_sequote;
default: default:
goto SubstS; goto SubstS;
@ -358,16 +353,16 @@ yylex(int cf)
Subst: Subst:
switch (c) { switch (c) {
case ord('\\'): case ORD('\\'):
c = getsc(); c = getsc();
switch (c) { switch (c) {
case ord('"'): case ORD('"'):
if ((cf & HEREDOC)) if ((cf & HEREDOC))
goto heredocquote; goto heredocquote;
/* FALLTHROUGH */ /* FALLTHROUGH */
case ord('\\'): case ORD('\\'):
case ord('$'): case ORD('$'):
case ord('`'): case ORD('`'):
store_qchar: store_qchar:
*wp++ = QCHAR; *wp++ = QCHAR;
*wp++ = c; *wp++ = c;
@ -385,12 +380,12 @@ yylex(int cf)
break; break;
} }
break; break;
case ord('$'): case ORD('$'):
c = getsc(); c = getsc();
SubstS: SubstS:
if (c == ord('(' /*)*/)) { if ((unsigned int)c == ORD('(' /*)*/)) {
c = getsc(); c = getsc();
if (c == ord('(' /*)*/)) { if ((unsigned int)c == ORD('(' /*)*/)) {
*wp++ = EXPRSUB; *wp++ = EXPRSUB;
PUSH_SRETRACE(SASPAREN); PUSH_SRETRACE(SASPAREN);
statep->nparen = 2; statep->nparen = 2;
@ -407,8 +402,8 @@ yylex(int cf)
memcpy(wp, sp, cz); memcpy(wp, sp, cz);
wp += cz; wp += cz;
} }
} else if (c == ord('{' /*}*/)) { } else if ((unsigned int)c == ORD('{' /*}*/)) {
if ((c = getsc()) == ord('|')) { if ((unsigned int)(c = getsc()) == ORD('|')) {
/* /*
* non-subenvironment * non-subenvironment
* value substitution * value substitution
@ -429,11 +424,11 @@ yylex(int cf)
wp = get_brace_var(&ws, wp); wp = get_brace_var(&ws, wp);
c = getsc(); c = getsc();
/* allow :# and :% (ksh88 compat) */ /* allow :# and :% (ksh88 compat) */
if (c == ord(':')) { if ((unsigned int)c == ORD(':')) {
*wp++ = CHAR; *wp++ = CHAR;
*wp++ = c; *wp++ = c;
c = getsc(); c = getsc();
if (c == ord(':')) { if ((unsigned int)c == ORD(':')) {
*wp++ = CHAR; *wp++ = CHAR;
*wp++ = '0'; *wp++ = '0';
*wp++ = ADELIM; *wp++ = ADELIM;
@ -465,7 +460,7 @@ yylex(int cf)
parse_adelim_slash: parse_adelim_slash:
*wp++ = CHAR; *wp++ = CHAR;
*wp++ = c; *wp++ = c;
if ((c = getsc()) == ord('/')) { if ((unsigned int)(c = getsc()) == ORD('/')) {
*wp++ = c2; *wp++ = c2;
*wp++ = c; *wp++ = c;
} else } else
@ -479,7 +474,7 @@ yylex(int cf)
} else if (c == '@') { } else if (c == '@') {
c2 = getsc(); c2 = getsc();
ungetsc(c2); ungetsc(c2);
if (c2 == ord('/')) { if ((unsigned int)c2 == ORD('/')) {
c2 = CHAR; c2 = CHAR;
goto parse_adelim_slash; goto parse_adelim_slash;
} }
@ -528,7 +523,7 @@ yylex(int cf)
ungetsc(c); ungetsc(c);
} }
break; break;
case ord('`'): case ORD('`'):
subst_gravis: subst_gravis:
PUSH_STATE(SBQUOTE); PUSH_STATE(SBQUOTE);
*wp++ = COMASUB; *wp++ = COMASUB;
@ -572,11 +567,11 @@ yylex(int cf)
break; break;
case SEQUOTE: case SEQUOTE:
if (c == ord('\'')) { if ((unsigned int)c == ORD('\'')) {
POP_STATE(); POP_STATE();
*wp++ = CQUOTE; *wp++ = CQUOTE;
ignore_backslash_newline--; ignore_backslash_newline--;
} else if (c == ord('\\')) { } else if ((unsigned int)c == ORD('\\')) {
if ((c2 = unbksl(true, getsc_i, ungetsc)) == -1) if ((c2 = unbksl(true, getsc_i, ungetsc)) == -1)
c2 = getsc(); c2 = getsc();
if (c2 == 0) if (c2 == 0)
@ -604,7 +599,7 @@ yylex(int cf)
break; break;
case SSQUOTE: case SSQUOTE:
if (c == ord('\'')) { if ((unsigned int)c == ORD('\'')) {
POP_STATE(); POP_STATE();
if ((cf & HEREDOC) || state == SQBRACE) if ((cf & HEREDOC) || state == SQBRACE)
goto store_char; goto store_char;
@ -617,7 +612,7 @@ yylex(int cf)
break; break;
case SDQUOTE: case SDQUOTE:
if (c == ord('"')) { if ((unsigned int)c == ORD('"')) {
POP_STATE(); POP_STATE();
*wp++ = CQUOTE; *wp++ = CQUOTE;
} else } else
@ -626,15 +621,15 @@ yylex(int cf)
/* $(( ... )) */ /* $(( ... )) */
case SASPAREN: case SASPAREN:
if (c == ord('(')) if ((unsigned int)c == ORD('('))
statep->nparen++; statep->nparen++;
else if (c == ord(')')) { else if ((unsigned int)c == ORD(')')) {
statep->nparen--; statep->nparen--;
if (statep->nparen == 1) { if (statep->nparen == 1) {
/* end of EXPRSUB */ /* end of EXPRSUB */
POP_SRETRACE(); POP_SRETRACE();
if ((c2 = getsc()) == ord(/*(*/ ')')) { if ((unsigned int)(c2 = getsc()) == ORD(/*(*/ ')')) {
cz = strlen(sp) - 2; cz = strlen(sp) - 2;
XcheckN(ws, wp, cz); XcheckN(ws, wp, cz);
memcpy(wp, sp + 1, cz); memcpy(wp, sp + 1, cz);
@ -666,7 +661,7 @@ yylex(int cf)
goto Sbase2; goto Sbase2;
case SQBRACE: case SQBRACE:
if (c == ord('\\')) { if ((unsigned int)c == ORD('\\')) {
/* /*
* perform POSIX "quote removal" if the back- * perform POSIX "quote removal" if the back-
* slash is "special", i.e. same cases as the * slash is "special", i.e. same cases as the
@ -675,26 +670,28 @@ yylex(int cf)
* write QCHAR+c, otherwise CHAR+\+CHAR+c are * write QCHAR+c, otherwise CHAR+\+CHAR+c are
* emitted (in heredocquote:) * emitted (in heredocquote:)
*/ */
if ((c = getsc()) == ord('"') || c == ord('\\') || if ((unsigned int)(c = getsc()) == ORD('"') ||
ctype(c, C_DOLAR | C_GRAVE) || c == ord(/*{*/ '}')) (unsigned int)c == ORD('\\') ||
ctype(c, C_DOLAR | C_GRAVE) ||
(unsigned int)c == ORD(/*{*/ '}'))
goto store_qchar; goto store_qchar;
goto heredocquote; goto heredocquote;
} }
goto common_SQBRACE; goto common_SQBRACE;
case SBRACE: case SBRACE:
if (c == ord('\'')) if ((unsigned int)c == ORD('\''))
goto open_ssquote_unless_heredoc; goto open_ssquote_unless_heredoc;
else if (c == ord('\\')) else if ((unsigned int)c == ORD('\\'))
goto getsc_qchar; goto getsc_qchar;
common_SQBRACE: common_SQBRACE:
if (c == ord('"')) if ((unsigned int)c == ORD('"'))
goto open_sdquote; goto open_sdquote;
else if (c == ord('$')) else if ((unsigned int)c == ORD('$'))
goto subst_dollar_ex; goto subst_dollar_ex;
else if (c == ord('`')) else if ((unsigned int)c == ORD('`'))
goto subst_gravis; goto subst_gravis;
else if (c != ord(/*{*/ '}')) else if ((unsigned int)c != ORD(/*{*/ '}'))
goto store_char; goto store_char;
POP_STATE(); POP_STATE();
*wp++ = CSUBST; *wp++ = CSUBST;
@ -703,16 +700,16 @@ yylex(int cf)
/* Same as SBASE, except (,|,) treated specially */ /* Same as SBASE, except (,|,) treated specially */
case STBRACEKORN: case STBRACEKORN:
if (c == ord('|')) if ((unsigned int)c == ORD('|'))
*wp++ = SPAT; *wp++ = SPAT;
else if (c == ord('(')) { else if ((unsigned int)c == ORD('(')) {
*wp++ = OPAT; *wp++ = OPAT;
/* simile for @ */ /* simile for @ */
*wp++ = ' '; *wp++ = ' ';
PUSH_STATE(SPATTERN); PUSH_STATE(SPATTERN);
} else /* FALLTHROUGH */ } else /* FALLTHROUGH */
case STBRACEBOURNE: case STBRACEBOURNE:
if (c == ord(/*{*/ '}')) { if ((unsigned int)c == ORD(/*{*/ '}')) {
POP_STATE(); POP_STATE();
*wp++ = CSUBST; *wp++ = CSUBST;
*wp++ = /*{*/ '}'; *wp++ = /*{*/ '}';
@ -721,20 +718,20 @@ yylex(int cf)
break; break;
case SBQUOTE: case SBQUOTE:
if (c == ord('`')) { if ((unsigned int)c == ORD('`')) {
*wp++ = 0; *wp++ = 0;
POP_STATE(); POP_STATE();
} else if (c == ord('\\')) { } else if ((unsigned int)c == ORD('\\')) {
switch (c = getsc()) { switch (c = getsc()) {
case 0: case 0:
/* trailing \ is lost */ /* trailing \ is lost */
break; break;
case ord('$'): case ORD('$'):
case ord('`'): case ORD('`'):
case ord('\\'): case ORD('\\'):
*wp++ = c; *wp++ = c;
break; break;
case ord('"'): case ORD('"'):
if (statep->ls_bool) { if (statep->ls_bool) {
*wp++ = c; *wp++ = c;
break; break;
@ -755,10 +752,10 @@ yylex(int cf)
/* LETEXPR: (( ... )) */ /* LETEXPR: (( ... )) */
case SLETPAREN: case SLETPAREN:
if (c == ord(/*(*/ ')')) { if ((unsigned int)c == ORD(/*(*/ ')')) {
if (statep->nparen > 0) if (statep->nparen > 0)
--statep->nparen; --statep->nparen;
else if ((c2 = getsc()) == ord(/*(*/ ')')) { else if ((unsigned int)(c2 = getsc()) == ORD(/*(*/ ')')) {
c = 0; c = 0;
*wp++ = CQUOTE; *wp++ = CQUOTE;
goto Done; goto Done;
@ -780,9 +777,9 @@ yylex(int cf)
s->next = source; s->next = source;
source = s; source = s;
ungetsc('(' /*)*/); ungetsc('(' /*)*/);
return (ord('(' /*)*/)); return (ORD('(' /*)*/));
} }
} else if (c == ord('(')) } else if ((unsigned int)c == ORD('('))
/* /*
* parentheses inside quotes and * parentheses inside quotes and
* backslashes are lost, but AT&T ksh * backslashes are lost, but AT&T ksh
@ -798,26 +795,26 @@ yylex(int cf)
* $ and `...` are not to be treated specially * $ and `...` are not to be treated specially
*/ */
switch (c) { switch (c) {
case ord('\\'): case ORD('\\'):
if ((c = getsc())) { if ((c = getsc())) {
/* trailing \ is lost */ /* trailing \ is lost */
*wp++ = QCHAR; *wp++ = QCHAR;
*wp++ = c; *wp++ = c;
} }
break; break;
case ord('\''): case ORD('\''):
goto open_ssquote_unless_heredoc; goto open_ssquote_unless_heredoc;
case ord('$'): case ORD('$'):
if ((c2 = getsc()) == ord('\'')) { if ((unsigned int)(c2 = getsc()) == ORD('\'')) {
open_sequote: open_sequote:
*wp++ = OQUOTE; *wp++ = OQUOTE;
ignore_backslash_newline++; ignore_backslash_newline++;
PUSH_STATE(SEQUOTE); PUSH_STATE(SEQUOTE);
statep->ls_bool = false; statep->ls_bool = false;
break; break;
} else if (c2 == ord('"')) { } else if ((unsigned int)c2 == ORD('"')) {
/* FALLTHROUGH */ /* FALLTHROUGH */
case ord('"'): case ORD('"'):
PUSH_SRETRACE(SHEREDQUOTE); PUSH_SRETRACE(SHEREDQUOTE);
break; break;
} }
@ -831,7 +828,7 @@ yylex(int cf)
/* " in << or <<- delimiter */ /* " in << or <<- delimiter */
case SHEREDQUOTE: case SHEREDQUOTE:
if (c != ord('"')) if ((unsigned int)c != ORD('"'))
goto Subst; goto Subst;
POP_SRETRACE(); POP_SRETRACE();
dp = strnul(sp) - 1; dp = strnul(sp) - 1;
@ -844,10 +841,10 @@ yylex(int cf)
while ((c = *dp++)) { while ((c = *dp++)) {
if (c == '\\') { if (c == '\\') {
switch ((c = *dp++)) { switch ((c = *dp++)) {
case ord('\\'): case ORD('\\'):
case ord('"'): case ORD('"'):
case ord('$'): case ORD('$'):
case ord('`'): case ORD('`'):
break; break;
default: default:
*wp++ = CHAR; *wp++ = CHAR;
@ -865,12 +862,12 @@ yylex(int cf)
/* in *(...|...) pattern (*+?@!) */ /* in *(...|...) pattern (*+?@!) */
case SPATTERN: case SPATTERN:
if (c == ord(/*(*/ ')')) { if ((unsigned int)c == ORD(/*(*/ ')')) {
*wp++ = CPAT; *wp++ = CPAT;
POP_STATE(); POP_STATE();
} else if (c == ord('|')) { } else if ((unsigned int)c == ORD('|')) {
*wp++ = SPAT; *wp++ = SPAT;
} else if (c == ord('(')) { } else if ((unsigned int)c == ORD('(')) {
*wp++ = OPAT; *wp++ = OPAT;
/* simile for @ */ /* simile for @ */
*wp++ = ' '; *wp++ = ' ';
@ -900,7 +897,7 @@ yylex(int cf)
iop->unit = c2 == 2 ? ksh_numdig(dp[1]) : c == '<' ? 0 : 1; iop->unit = c2 == 2 ? ksh_numdig(dp[1]) : c == '<' ? 0 : 1;
if (c == '&') { if (c == '&') {
if ((c2 = getsc()) != ord('>')) { if ((unsigned int)(c2 = getsc()) != ORD('>')) {
ungetsc(c2); ungetsc(c2);
goto no_iop; goto no_iop;
} }
@ -911,22 +908,23 @@ yylex(int cf)
c2 = getsc(); c2 = getsc();
/* <<, >>, <> are ok, >< is not */ /* <<, >>, <> 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 ? iop->ioflag |= c == c2 ?
(c == ord('>') ? IOCAT : IOHERE) : IORDWR; ((unsigned int)c == ORD('>') ? IOCAT : IOHERE) : IORDWR;
if (iop->ioflag == IOHERE) { if (iop->ioflag == IOHERE) {
if ((c2 = getsc()) == ord('-')) if ((unsigned int)(c2 = getsc()) == ORD('-'))
iop->ioflag |= IOSKIP; iop->ioflag |= IOSKIP;
else if (c2 == ord('<')) else if ((unsigned int)c2 == ORD('<'))
iop->ioflag |= IOHERESTR; iop->ioflag |= IOHERESTR;
else else
ungetsc(c2); ungetsc(c2);
} }
} else if (c2 == ord('&')) } else if ((unsigned int)c2 == ORD('&'))
iop->ioflag |= IODUP | (c == ord('<') ? IORDUP : 0); iop->ioflag |= IODUP | ((unsigned int)c == ORD('<') ? IORDUP : 0);
else { else {
iop->ioflag |= c == ord('>') ? IOWRITE : IOREAD; iop->ioflag |= (unsigned int)c == ORD('>') ? IOWRITE : IOREAD;
if (c == ord('>') && c2 == ord('|')) if ((unsigned int)c == ORD('>') && (unsigned int)c2 == ORD('|'))
iop->ioflag |= IOCLOB; iop->ioflag |= IOCLOB;
else else
ungetsc(c2); ungetsc(c2);
@ -947,30 +945,32 @@ yylex(int cf)
/* free word */ /* free word */
Xfree(ws, wp); Xfree(ws, wp);
/* no word, process LEX1 character */ /* no word, process LEX1 character */
if ((c == ord('|')) || (c == ord('&')) || (c == ord(';')) || if (((unsigned int)c == ORD('|')) ||
(c == ord('(' /*)*/))) { ((unsigned int)c == ORD('&')) ||
((unsigned int)c == ORD(';')) ||
((unsigned int)c == ORD('(' /*)*/))) {
if ((c2 = getsc()) == c) if ((c2 = getsc()) == c)
c = (c == ord(';')) ? BREAK : c = ((unsigned int)c == ORD(';')) ? BREAK :
(c == ord('|')) ? LOGOR : ((unsigned int)c == ORD('|')) ? LOGOR :
(c == ord('&')) ? LOGAND : ((unsigned int)c == ORD('&')) ? LOGAND :
/* c == ord('(' )) */ MDPAREN; /* (unsigned int)c == ORD('(' )) */ MDPAREN;
else if (c == ord('|') && c2 == ord('&')) else if ((unsigned int)c == ORD('|') && (unsigned int)c2 == ORD('&'))
c = COPROC; c = COPROC;
else if (c == ord(';') && c2 == ord('|')) else if ((unsigned int)c == ORD(';') && (unsigned int)c2 == ORD('|'))
c = BRKEV; c = BRKEV;
else if (c == ord(';') && c2 == ord('&')) else if ((unsigned int)c == ORD(';') && (unsigned int)c2 == ORD('&'))
c = BRKFT; c = BRKFT;
else else
ungetsc(c2); ungetsc(c2);
#ifndef MKSH_SMALL #ifndef MKSH_SMALL
if (c == BREAK) { if (c == BREAK) {
if ((c2 = getsc()) == ord('&')) if ((unsigned int)(c2 = getsc()) == ORD('&'))
c = BRKEV; c = BRKEV;
else else
ungetsc(c2); ungetsc(c2);
} }
#endif #endif
} else if (c == ord('\n')) { } else if ((unsigned int)c == ORD('\n')) {
if (cf & HEREDELIM) if (cf & HEREDELIM)
ungetsc(c); ungetsc(c);
else { else {
@ -1025,7 +1025,7 @@ yylex(int cf)
if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) && if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) &&
(!(cf & ESACONLY) || p->val.i == ESAC || (!(cf & ESACONLY) || p->val.i == ESAC ||
p->val.i == ord(/*{*/ '}'))) { (unsigned int)p->val.i == ORD(/*{*/ '}'))) {
afree(yylval.cp, ATEMP); afree(yylval.cp, ATEMP);
return (p->val.i); return (p->val.i);
} }
@ -1136,7 +1136,7 @@ readhere(struct ioword *iop)
if (!*eofp) { if (!*eofp) {
/* end of here document marker, what to do? */ /* end of here document marker, what to do? */
switch (c) { switch (c) {
case ord(/*(*/ ')'): case ORD(/*(*/ ')'):
if (!subshell_nesting_type) if (!subshell_nesting_type)
/*- /*-
* not allowed outside $(...) or (...) * not allowed outside $(...) or (...)
@ -1151,7 +1151,7 @@ readhere(struct ioword *iop)
* Allow EOF here to commands without trailing * Allow EOF here to commands without trailing
* newlines (mksh -c '...') will work as well. * newlines (mksh -c '...') will work as well.
*/ */
case ord('\n'): case ORD('\n'):
/* Newline terminates here document marker */ /* Newline terminates here document marker */
goto heredoc_found_terminator; goto heredoc_found_terminator;
} }
@ -1580,7 +1580,7 @@ get_brace_var(XString *wsp, char *wp)
c2 = getsc(); c2 = getsc();
ungetsc(c2); ungetsc(c2);
if (ord(c2) != ord(/*{*/ '}')) { if (ord(c2) != ORD(/*{*/ '}')) {
ungetsc(c); ungetsc(c);
goto out; goto out;
} }
@ -1588,22 +1588,22 @@ get_brace_var(XString *wsp, char *wp)
goto ps_common; goto ps_common;
case PS_SAW_BANG: case PS_SAW_BANG:
switch (ord(c)) { switch (ord(c)) {
case ord('@'): case ORD('@'):
case ord('#'): case ORD('#'):
case ord('-'): case ORD('-'):
case ord('?'): case ORD('?'):
goto out; goto out;
} }
goto ps_common; goto ps_common;
case PS_INITIAL: case PS_INITIAL:
switch (ord(c)) { switch (ord(c)) {
case ord('%'): case ORD('%'):
state = PS_SAW_PERCENT; state = PS_SAW_PERCENT;
goto next; goto next;
case ord('#'): case ORD('#'):
state = PS_SAW_HASH; state = PS_SAW_HASH;
goto next; goto next;
case ord('!'): case ORD('!'):
state = PS_SAW_BANG; state = PS_SAW_BANG;
goto next; goto next;
} }
@ -1621,7 +1621,7 @@ get_brace_var(XString *wsp, char *wp)
break; break;
case PS_IDENT: case PS_IDENT:
if (!ctype(c, C_ALNUX)) { if (!ctype(c, C_ALNUX)) {
if (ord(c) == ord('[')) { if (ord(c) == ORD('[')) {
char *tmp, *p; char *tmp, *p;
if (!arraysub(&tmp)) if (!arraysub(&tmp))
@ -1676,9 +1676,9 @@ arraysub(char **strp)
c = getsc(); c = getsc();
Xcheck(ws, wp); Xcheck(ws, wp);
*wp++ = c; *wp++ = c;
if (ord(c) == ord('[')) if (ord(c) == ORD('['))
depth++; depth++;
else if (ord(c) == ord(']')) else if (ord(c) == ORD(']'))
depth--; depth--;
} while (depth > 0 && c && c != '\n'); } while (depth > 0 && c && c != '\n');

View file

@ -5,7 +5,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015, 2016, 2017 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -34,9 +34,7 @@
#include <locale.h> #include <locale.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.342 2017/04/28 11:13:47 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/main.c,v 1.347 2018/01/13 21:45:07 tg Exp $");
extern char **environ;
#ifndef MKSHRC_PATH #ifndef MKSHRC_PATH
#define MKSHRC_PATH "~/.mkshrc" #define MKSHRC_PATH "~/.mkshrc"
@ -52,6 +50,7 @@ void chvt_reinit(void);
static void reclaim(void); static void reclaim(void);
static void remove_temps(struct temp *); static void remove_temps(struct temp *);
static mksh_uari_t rndsetup(void); static mksh_uari_t rndsetup(void);
static void init_environ(void);
#ifdef SIGWINCH #ifdef SIGWINCH
static void x_sigwinch(int); static void x_sigwinch(int);
#endif #endif
@ -242,10 +241,6 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
set_ifs(TC_IFSWS); set_ifs(TC_IFSWS);
#ifdef __OS2__ #ifdef __OS2__
for (i = 0; i < 3; ++i)
if (!isatty(i))
setmode(i, O_BINARY);
os2_init(&argc, &argv); os2_init(&argc, &argv);
#endif #endif
@ -401,14 +396,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
#endif #endif
/* import environment */ /* import environment */
if (environ != NULL) { init_environ();
wp = (const char **)environ;
while (*wp != NULL) {
rndpush(*wp);
typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
++wp;
}
}
/* override default PATH regardless of environment */ /* override default PATH regardless of environment */
#ifdef MKSH_DEFPATH_OVERRIDE #ifdef MKSH_DEFPATH_OVERRIDE
@ -671,8 +659,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
if (Flag(FLOGIN)) if (Flag(FLOGIN))
include(substitute("$HOME/.profile", 0), 0, NULL, true); include(substitute("$HOME/.profile", 0), 0, NULL, true);
if (Flag(FTALKING)) { if (Flag(FTALKING)) {
cp = substitute(substitute("${ENV:-" MKSHRC_PATH "}", cp = substitute("${ENV:-" MKSHRC_PATH "}", DOTILDE);
0), DOTILDE);
if (cp[0] != '\0') if (cp[0] != '\0')
include(cp, 0, NULL, true); include(cp, 0, NULL, true);
} }
@ -1987,3 +1974,111 @@ x_mkraw(int fd, mksh_ttyst *ocb, bool forread)
mksh_tcset(fd, &cb); 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

View file

@ -32,7 +32,7 @@
#include <grp.h> #include <grp.h>
#endif #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 #define KSH_CHVT_FLAG
#ifdef MKSH_SMALL #ifdef MKSH_SMALL
@ -696,14 +696,14 @@ has_globbing(const char *pat)
if (!(c = *p++)) if (!(c = *p++))
return (false); return (false);
/* some specials */ /* some specials */
if (ord(c) == ord('*') || ord(c) == ord('?')) { if (ord(c) == ORD('*') || ord(c) == ORD('?')) {
/* easy glob, accept */ /* easy glob, accept */
saw_glob = true; saw_glob = true;
} else if (ord(c) == ord('[')) { } else if (ord(c) == ORD('[')) {
/* bracket expression; eat negation and initial ] */ /* bracket expression; eat negation and initial ] */
if (ISMAGIC(p[0]) && ord(p[1]) == ord('!')) if (ISMAGIC(p[0]) && ord(p[1]) == ORD('!'))
p += 2; p += 2;
if (ISMAGIC(p[0]) && ord(p[1]) == ord(']')) if (ISMAGIC(p[0]) && ord(p[1]) == ORD(']'))
p += 2; p += 2;
/* check next string part */ /* check next string part */
s = p; s = p;
@ -715,27 +715,27 @@ has_globbing(const char *pat)
if (!(c = *s++)) if (!(c = *s++))
return (false); return (false);
/* terminating bracket? */ /* terminating bracket? */
if (ord(c) == ord(']')) { if (ord(c) == ORD(']')) {
/* accept and continue */ /* accept and continue */
p = s; p = s;
saw_glob = true; saw_glob = true;
break; break;
} }
/* sub-bracket expressions */ /* sub-bracket expressions */
if (ord(c) == ord('[') && ( if (ord(c) == ORD('[') && (
/* collating element? */ /* collating element? */
ord(*s) == ord('.') || ord(*s) == ORD('.') ||
/* equivalence class? */ /* equivalence class? */
ord(*s) == ord('=') || ord(*s) == ORD('=') ||
/* character class? */ /* character class? */
ord(*s) == ord(':'))) { ord(*s) == ORD(':'))) {
/* must stop with exactly the same c */ /* must stop with exactly the same c */
subc = *s++; subc = *s++;
/* arbitrarily many chars in betwixt */ /* arbitrarily many chars in betwixt */
while ((c = *s++)) while ((c = *s++))
/* but only this sequence... */ /* but only this sequence... */
if (c == subc && ISMAGIC(*s) && if (c == subc && ISMAGIC(*s) &&
ord(s[1]) == ord(']')) { ord(s[1]) == ORD(']')) {
/* accept, terminate */ /* accept, terminate */
s += 2; s += 2;
break; break;
@ -751,7 +751,7 @@ has_globbing(const char *pat)
/* opening pattern */ /* opening pattern */
saw_glob = true; saw_glob = true;
++nest; ++nest;
} else if (ord(c) == ord(/*(*/ ')')) { } else if (ord(c) == ORD(/*(*/ ')')) {
/* closing pattern */ /* closing pattern */
if (nest) if (nest)
--nest; --nest;
@ -785,24 +785,24 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
continue; continue;
} }
switch (ord(*p++)) { switch (ord(*p++)) {
case ord('['): case ORD('['):
/* BSD cclass extension? */ /* BSD cclass extension? */
if (ISMAGIC(p[0]) && ord(p[1]) == ord('[') && if (ISMAGIC(p[0]) && ord(p[1]) == ORD('[') &&
ord(p[2]) == ord(':') && ord(p[2]) == ORD(':') &&
ctype((pc = p[3]), C_ANGLE) && ctype((pc = p[3]), C_ANGLE) &&
ord(p[4]) == ord(':') && ord(p[4]) == ORD(':') &&
ISMAGIC(p[5]) && ord(p[6]) == ord(']') && ISMAGIC(p[5]) && ord(p[6]) == ORD(']') &&
ISMAGIC(p[7]) && ord(p[8]) == ord(']')) { ISMAGIC(p[7]) && ord(p[8]) == ORD(']')) {
/* zero-length match */ /* zero-length match */
--s; --s;
p += 9; p += 9;
/* word begin? */ /* word begin? */
if (ord(pc) == ord('<') && if (ord(pc) == ORD('<') &&
!ctype(sl, C_ALNUX) && !ctype(sl, C_ALNUX) &&
ctype(sc, C_ALNUX)) ctype(sc, C_ALNUX))
break; break;
/* word end? */ /* word end? */
if (ord(pc) == ord('>') && if (ord(pc) == ORD('>') &&
ctype(sl, C_ALNUX) && ctype(sl, C_ALNUX) &&
!ctype(sc, C_ALNUX)) !ctype(sc, C_ALNUX))
break; break;
@ -813,7 +813,7 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
return (0); return (0);
break; break;
case ord('?'): case ORD('?'):
if (sc == 0) if (sc == 0)
return (0); return (0);
if (UTFMODE) { if (UTFMODE) {
@ -822,7 +822,7 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
} }
break; break;
case ord('*'): case ORD('*'):
if (p == pe) if (p == pe)
return (1); return (1);
s--; s--;
@ -838,14 +838,14 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
*/ */
/* matches one or more times */ /* matches one or more times */
case 0x80|ord('+'): case ORD('+') | 0x80:
/* matches zero or more times */ /* matches zero or more times */
case 0x80|ord('*'): case ORD('*') | 0x80:
if (!(prest = pat_scan(p, pe, false))) if (!(prest = pat_scan(p, pe, false)))
return (0); return (0);
s--; s--;
/* take care of zero matches */ /* take care of zero matches */
if (ord(p[-1]) == (0x80 | ord('*')) && if (ord(p[-1]) == (0x80 | ORD('*')) &&
do_gmatch(s, se, prest, pe, smin)) do_gmatch(s, se, prest, pe, smin))
return (1); return (1);
for (psub = p; ; psub = pnext) { for (psub = p; ; psub = pnext) {
@ -863,16 +863,16 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
return (0); return (0);
/* matches zero or once */ /* matches zero or once */
case 0x80|ord('?'): case ORD('?') | 0x80:
/* matches one of the patterns */ /* matches one of the patterns */
case 0x80|ord('@'): case ORD('@') | 0x80:
/* simile for @ */ /* simile for @ */
case 0x80|ord(' '): case ORD(' ') | 0x80:
if (!(prest = pat_scan(p, pe, false))) if (!(prest = pat_scan(p, pe, false)))
return (0); return (0);
s--; s--;
/* Take care of zero matches */ /* Take care of zero matches */
if (ord(p[-1]) == (0x80 | ord('?')) && if (ord(p[-1]) == (0x80 | ORD('?')) &&
do_gmatch(s, se, prest, pe, smin)) do_gmatch(s, se, prest, pe, smin))
return (1); return (1);
for (psub = p; ; psub = pnext) { for (psub = p; ; psub = pnext) {
@ -889,7 +889,7 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
return (0); return (0);
/* matches none of the patterns */ /* matches none of the patterns */
case 0x80|ord('!'): case ORD('!') | 0x80:
if (!(prest = pat_scan(p, pe, false))) if (!(prest = pat_scan(p, pe, false)))
return (0); return (0);
s--; s--;
@ -966,12 +966,12 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
char *subp; char *subp;
/* check for negation */ /* check for negation */
if (ISMAGIC(p[0]) && ord(p[1]) == ord('!')) { if (ISMAGIC(p[0]) && ord(p[1]) == ORD('!')) {
p += 2; p += 2;
negated = true; negated = true;
} }
/* make initial ] non-MAGIC */ /* make initial ] non-MAGIC */
if (ISMAGIC(p[0]) && ord(p[1]) == ord(']')) if (ISMAGIC(p[0]) && ord(p[1]) == ORD(']'))
++p; ++p;
/* iterate over bracket expression, debunk()ing on the fly */ /* iterate over bracket expression, debunk()ing on the fly */
while ((c = *p++)) { while ((c = *p++)) {
@ -982,18 +982,18 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
if (!(c = *p++)) if (!(c = *p++))
break; break;
/* terminating bracket? */ /* terminating bracket? */
if (ord(c) == ord(']')) { if (ord(c) == ORD(']')) {
/* accept and return */ /* accept and return */
return (found != negated ? p : NULL); return (found != negated ? p : NULL);
} }
/* sub-bracket expressions */ /* sub-bracket expressions */
if (ord(c) == ord('[') && ( if (ord(c) == ORD('[') && (
/* collating element? */ /* collating element? */
ord(*p) == ord('.') || ord(*p) == ORD('.') ||
/* equivalence class? */ /* equivalence class? */
ord(*p) == ord('=') || ord(*p) == ORD('=') ||
/* character class? */ /* character class? */
ord(*p) == ord(':'))) { ord(*p) == ORD(':'))) {
/* must stop with exactly the same c */ /* must stop with exactly the same c */
subc = *p++; subc = *p++;
/* save away start of substring */ /* save away start of substring */
@ -1002,7 +1002,7 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
while ((c = *p++)) while ((c = *p++))
/* but only this sequence... */ /* but only this sequence... */
if (c == subc && ISMAGIC(*p) && if (c == subc && ISMAGIC(*p) &&
ord(p[1]) == ord(']')) { ord(p[1]) == ORD(']')) {
/* accept, terminate */ /* accept, terminate */
p += 2; p += 2;
break; break;
@ -1015,7 +1015,7 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
debunk(subp, subp, p - s - 3 + 1); debunk(subp, subp, p - s - 3 + 1);
cclass_common: cclass_common:
/* whither subexpression */ /* whither subexpression */
if (ord(subc) == ord(':')) { if (ord(subc) == ORD(':')) {
const struct cclass *cls = cclasses; const struct cclass *cls = cclasses;
/* search for name in cclass list */ /* search for name in cclass list */
@ -1055,9 +1055,9 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
} }
} }
/* range expression? */ /* range expression? */
if (!(ISMAGIC(p[0]) && ord(p[1]) == ord('-') && if (!(ISMAGIC(p[0]) && ord(p[1]) == ORD('-') &&
/* not terminating bracket? */ /* not terminating bracket? */
(!ISMAGIC(p[2]) || ord(p[3]) != ord(']')))) { (!ISMAGIC(p[2]) || ord(p[3]) != ORD(']')))) {
/* no, check single match */ /* no, check single match */
if (sc == c) if (sc == c)
/* note: sc is never NUL */ /* note: sc is never NUL */
@ -1079,13 +1079,13 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
if (!(c = *p++)) if (!(c = *p++))
break; break;
/* sub-bracket expressions */ /* sub-bracket expressions */
if (ord(c) == ord('[') && ( if (ord(c) == ORD('[') && (
/* collating element? */ /* collating element? */
ord(*p) == ord('.') || ord(*p) == ORD('.') ||
/* equivalence class? */ /* equivalence class? */
ord(*p) == ord('=') || ord(*p) == ORD('=') ||
/* character class? */ /* character class? */
ord(*p) == ord(':'))) { ord(*p) == ORD(':'))) {
/* must stop with exactly the same c */ /* must stop with exactly the same c */
subc = *p++; subc = *p++;
/* save away start of substring */ /* save away start of substring */
@ -1094,7 +1094,7 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
while ((c = *p++)) while ((c = *p++))
/* but only this sequence... */ /* but only this sequence... */
if (c == subc && ISMAGIC(*p) && if (c == subc && ISMAGIC(*p) &&
ord(p[1]) == ord(']')) { ord(p[1]) == ORD(']')) {
/* accept, terminate */ /* accept, terminate */
p += 2; p += 2;
break; break;
@ -1106,14 +1106,14 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
strndupx(subp, s, p - s - 3, ATEMP); strndupx(subp, s, p - s - 3, ATEMP);
debunk(subp, subp, p - s - 3 + 1); debunk(subp, subp, p - s - 3 + 1);
/* whither subexpression */ /* whither subexpression */
if (ord(subc) == ord(':')) { if (ord(subc) == ORD(':')) {
/* oops, not a range */ /* oops, not a range */
/* match single previous char */ /* match single previous char */
if (lc && (sc == lc)) if (lc && (sc == lc))
found = true; found = true;
/* match hyphen-minus */ /* match hyphen-minus */
if (ord(sc) == ord('-')) if (ord(sc) == ORD('-'))
found = true; found = true;
/* handle cclass common part */ /* handle cclass common part */
goto cclass_common; goto cclass_common;
@ -1151,7 +1151,7 @@ gmatch_cclass(const unsigned char *pat, unsigned char sc)
/* otherwise, just go on with the pattern string */ /* otherwise, just go on with the pattern string */
} }
/* if we broke here, the bracket expression was invalid */ /* if we broke here, the bracket expression was invalid */
if (ord(sc) == ord('[')) if (ord(sc) == ORD('['))
/* initial opening bracket as literal match */ /* initial opening bracket as literal match */
return (pat); return (pat);
/* or rather no match */ /* or rather no match */
@ -1661,6 +1661,15 @@ do_realpath(const char *upath)
if (mksh_abspath(upath)) { if (mksh_abspath(upath)) {
/* upath is an absolute pathname */ /* upath is an absolute pathname */
strdupx(ipath, upath, ATEMP); 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 { } else {
/* upath is a relative pathname, prepend cwd */ /* upath is a relative pathname, prepend cwd */
if ((tp = ksh_get_wd()) == NULL || !mksh_abspath(tp)) if ((tp = ksh_get_wd()) == NULL || !mksh_abspath(tp))
@ -1695,6 +1704,7 @@ do_realpath(const char *upath)
continue; continue;
else if (len == 2 && tp[1] == '.') { else if (len == 2 && tp[1] == '.') {
/* strip off last pathname component */ /* strip off last pathname component */
/*XXX consider a rooted pathname */
while (xp > Xstring(xs, xp)) while (xp > Xstring(xs, xp))
if (mksh_cdirsep(*--xp)) if (mksh_cdirsep(*--xp))
break; break;
@ -1762,11 +1772,23 @@ do_realpath(const char *upath)
* restart if symlink target is an absolute path, * restart if symlink target is an absolute path,
* otherwise continue with currently resolved prefix * otherwise continue with currently resolved prefix
*/ */
#ifdef MKSH_DOSPATH
assemble_symlink:
#endif
/* append rest of current input path to link target */ /* append rest of current input path to link target */
tp = shf_smprintf(Tf_sss, ldest, *ip ? "/" : "", ip); tp = shf_smprintf(Tf_sss, ldest, *ip ? "/" : "", ip);
afree(ipath, ATEMP); afree(ipath, ATEMP);
ip = ipath = tp; 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 */ /* symlink target is a relative path */
xp = Xrestpos(xs, xp, pos); xp = Xrestpos(xs, xp, pos);
} else } else
@ -1775,7 +1797,7 @@ do_realpath(const char *upath)
/* symlink target is an absolute path */ /* symlink target is an absolute path */
xp = Xstring(xs, xp); xp = Xstring(xs, xp);
beginning_of_a_pathname: beginning_of_a_pathname:
/* assert: mksh_cdirsep((ip == ipath)[0]) */ /* assert: mksh_abspath(ip == ipath) */
/* assert: xp == xs.beg => start of path */ /* assert: xp == xs.beg => start of path */
/* exactly two leading slashes? (SUSv4 3.266) */ /* exactly two leading slashes? (SUSv4 3.266) */
@ -1783,6 +1805,14 @@ do_realpath(const char *upath)
/* keep them, e.g. for UNC pathnames */ /* keep them, e.g. for UNC pathnames */
Xput(xs, xp, '/'); 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 */ /* otherwise (no symlink) merely go on */
@ -1932,6 +1962,15 @@ make_path(const char *cwd, const char *file,
* .. .. * .. ..
* ./foo foo * ./foo foo
* foo/../../../bar ../../bar * 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 void
simplify_path(char *p) simplify_path(char *p)
@ -1939,6 +1978,17 @@ simplify_path(char *p)
char *dp, *ip, *sp, *tp; char *dp, *ip, *sp, *tp;
size_t len; size_t len;
bool needslash; 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) { switch (*p) {
case 0: case 0:
@ -1977,7 +2027,7 @@ simplify_path(char *p)
/* just continue with the next one */ /* just continue with the next one */
continue; continue;
else if (len == 2 && tp[1] == '.') { else if (len == 2 && tp[1] == '.') {
/* parent level, but how? */ /* parent level, but how? (see above) */
if (mksh_abspath(p)) if (mksh_abspath(p))
/* absolute path, only one way */ /* absolute path, only one way */
goto strip_last_component; goto strip_last_component;
@ -2016,10 +2066,15 @@ simplify_path(char *p)
needslash = true; needslash = true;
/* try next component */ /* try next component */
} }
if (dp == p) if (dp == p) {
/* empty path -> dot */ /* empty path -> dot (or slash, when absolute) */
*dp++ = needslash ? '/' : '.'; if (needslash)
*dp++ = '/';
else if (needdot)
*dp++ = '.';
}
*dp = '\0'; *dp = '\0';
#undef needdot
} }
void void
@ -2133,6 +2188,18 @@ c_cd(const char **wp)
return (2); 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 #ifdef MKSH__NO_PATH_MAX
/* only a first guess; make_path will enlarge xs if necessary */ /* only a first guess; make_path will enlarge xs if necessary */
XinitN(xs, 1024, ATEMP); XinitN(xs, 1024, ATEMP);

174
src/os2.c
View file

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2015 * Copyright (c) 2015, 2017
* KO Myung-Hun <komh@chollian.net> * KO Myung-Hun <komh@chollian.net>
* Copyright (c) 2017 * Copyright (c) 2017
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
@ -26,18 +26,18 @@
#include "sh.h" #include "sh.h"
#include <klibc/startup.h> #include <klibc/startup.h>
#include <errno.h>
#include <io.h> #include <io.h>
#include <unistd.h> #include <unistd.h>
#include <process.h> #include <process.h>
__RCSID("$MirOS: src/bin/mksh/os2.c,v 1.2 2017/04/29 22:04:29 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/os2.c,v 1.8 2017/12/22 16:41:42 tg Exp $");
static char *remove_trailing_dots(char *); static char *remove_trailing_dots(char *);
static int access_stat_ex(int (*)(), const char *, void *); static int access_stat_ex(int (*)(), const char *, void *);
static int test_exec_exist(const char *, char *); static int test_exec_exist(const char *, char *);
static void response(int *, const char ***); static void response(int *, const char ***);
static char *make_response_file(char * const *); static char *make_response_file(char * const *);
static void env_slashify(void);
static void add_temp(const char *); static void add_temp(const char *);
static void cleanup_temps(void); static void cleanup_temps(void);
static void cleanup(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 void
os2_init(int *argcp, const char ***argvp) os2_init(int *argcp, const char ***argvp)
{ {
response(argcp, argvp); response(argcp, argvp);
init_extlibpath(); init_extlibpath();
env_slashify();
if (!isatty(STDIN_FILENO)) if (!isatty(STDIN_FILENO))
setmode(STDIN_FILENO, O_BINARY); setmode(STDIN_FILENO, O_BINARY);
@ -361,49 +329,30 @@ real_exec_name(const char *name)
return (real_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 */ /* make a response file to pass a very long command line */
static char * static char *
make_response_file(char * const *argv) make_response_file(char * const *argv)
{ {
char rsp_name_arg[] = "@mksh-rsp-XXXXXX"; char rsp_name_arg[] = "@mksh-rsp-XXXXXX";
char *rsp_name = &rsp_name_arg[1]; char *rsp_name = &rsp_name_arg[1];
int arg_len = 0;
int i; int i;
int fd;
char *result;
for (i = 0; argv[i]; i++) if ((fd = mkstemp(rsp_name)) == -1)
arg_len += strlen(argv[i]) + 1; return (NULL);
/* /* write all the arguments except a 0th program name */
* If a length of command line is longer than MAX_CMD_LINE_LEN, then for (i = 1; argv[i]; i++) {
* use a response file. OS/2 cannot process a command line longer write(fd, argv[i], strlen(argv[i]));
* than 32K. Of course, a response file cannot be recognised by a write(fd, "\n", 1);
* 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);
}
close(fd);
add_temp(rsp_name);
strdupx(result, rsp_name_arg, ATEMP);
return (result);
} }
return (NULL); close(fd);
add_temp(rsp_name);
strdupx(result, rsp_name_arg, ATEMP);
return (result);
} }
/* alias of execve() */ /* alias of execve() */
@ -416,12 +365,12 @@ execve(const char *name, char * const *argv, char * const *envp)
const char *exec_name; const char *exec_name;
FILE *fp; FILE *fp;
char sign[2]; char sign[2];
char *rsp_argv[3];
char *rsp_name_arg;
int pid; int pid;
int status; int status;
int fd; int fd;
int rc; int rc;
int saved_mode;
int saved_errno;
/* /*
* #! /bin/sh : append .exe * #! /bin/sh : append .exe
@ -461,23 +410,41 @@ execve(const char *name, char * const *argv, char * const *envp)
if (errno == ENOEXEC) if (errno == ENOEXEC)
return (-1); return (-1);
rsp_name_arg = make_response_file(argv); /*
* Normal OS/2 programs expect that standard IOs, especially stdin,
if (rsp_name_arg) { * are opened in text mode at the startup. By the way, on OS/2 kLIBC
rsp_argv[0] = argv[0]; * child processes inherit a translation mode of a parent process.
rsp_argv[1] = rsp_name_arg; * As a result, if stdin is set to binary mode in a parent process,
rsp_argv[2] = NULL; * 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.
argv = rsp_argv; */
} saved_mode = setmode(STDIN_FILENO, O_TEXT);
pid = spawnve(P_NOWAIT, exec_name, argv, envp); pid = spawnve(P_NOWAIT, exec_name, argv, envp);
saved_errno = errno;
afree(rsp_name_arg, ATEMP); /* arguments too long? */
if (pid == -1 && saved_errno == EINVAL) {
/* retry with a response file */
char *rsp_name_arg = make_response_file(argv);
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);
}
}
/* restore translation mode of stdin */
setmode(STDIN_FILENO, saved_mode);
if (pid == -1) { if (pid == -1) {
cleanup_temps(); cleanup_temps();
errno = saved_errno;
return (-1); return (-1);
} }
@ -557,3 +524,52 @@ cleanup(void)
{ {
cleanup_temps(); 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);
}

View file

@ -10,7 +10,7 @@
/*- /*-
* Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015, 2016, 2017 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -182,9 +182,9 @@
#endif #endif
#ifdef EXTERN #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 #endif
#define MKSH_VERSION "R56 2017/08/29" #define MKSH_VERSION "R56 2018/01/14"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -556,7 +556,7 @@ extern int __cdecl setegid(gid_t);
* low-bit7 at least on cp1047 so YMMV * low-bit7 at least on cp1047 so YMMV
*/ */
#define MAGIC KSH_BEL /* prefix for *?[!{,} during expand */ #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 */ EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */
@ -643,7 +643,7 @@ char *ucstrstr(char *, const char *);
#endif #endif
#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. #error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void); extern void thiswillneverbedefinedIhope(void);
int int
@ -804,7 +804,7 @@ struct sretrace_info;
struct yyrecursive_state; struct yyrecursive_state;
EXTERN struct sretrace_info *retrace_info; EXTERN struct sretrace_info *retrace_info;
EXTERN int subshell_nesting_type; EXTERN unsigned int subshell_nesting_type;
extern struct env { extern struct env {
ALLOC_ITEM alloc_INT; /* internal, do not touch */ ALLOC_ITEM alloc_INT; /* internal, do not touch */
@ -1469,7 +1469,26 @@ EXTERN char ifs0;
#define C_UNDER CiUNDER /* _ underscore */ #define C_UNDER CiUNDER /* _ underscore */
/* identity transform of octet */ /* 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) #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC)
EXTERN unsigned short ebcdic_map[256]; EXTERN unsigned short ebcdic_map[256];
EXTERN unsigned char ebcdic_rtt_toascii[256]; EXTERN unsigned char ebcdic_rtt_toascii[256];
@ -1492,20 +1511,22 @@ extern void ebcdic_init(void);
#ifdef MKSH_EBCDIC #ifdef MKSH_EBCDIC
#define ksh_isctrl(c) (ord(c) < 0x40 || ord(c) == 0xFF) #define ksh_isctrl(c) (ord(c) < 0x40 || ord(c) == 0xFF)
#else #else
#define ksh_isctrl(c) ((ord(c) & 0x7F) < 0x20 || (c) == 0x7F) #define ksh_isctrl(c) ((ord(c) & 0x7F) < 0x20 || ord(c) == 0x7F)
#endif #endif
/* new fast character classes */ /* new fast character classes */
#define ctype(c,t) tobool(ksh_ctypes[ord(c)] & (t)) #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 */ /* helper functions */
#define ksh_isdash(s) tobool(ord((s)[0]) == '-' && ord((s)[1]) == '\0') #define ksh_isdash(s) tobool(ord((s)[0]) == '-' && ord((s)[1]) == '\0')
/* invariant distance even in EBCDIC */ /* invariant distance even in EBCDIC */
#define ksh_tolower(c) (ctype(c, C_UPPER) ? (c) - 'A' + 'a' : (c)) #define ksh_tolower(c) (ctype(c, C_UPPER) ? (c) - 'A' + 'a' : (c))
#define ksh_toupper(c) (ctype(c, C_LOWER) ? (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 */ /* 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_numuc(c) (rtt2asc(c) - rtt2asc('A'))
#define ksh_numlc(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) #define ksh_unctrl(c) asc2rtt(rtt2asc(c) ^ 0x40U)
/* Argument parsing for built-in commands and getopts command */ /* 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_fileno(shf) ((shf)->fd)
#define shf_setfileno(shf,nfd) ((shf)->fd = (nfd)) #define shf_setfileno(shf,nfd) ((shf)->fd = (nfd))
#define shf_getc_i(shf) ((shf)->rnleft > 0 ? \ #define shf_getc_i(shf) ((shf)->rnleft > 0 ? \
(shf)->rnleft--, *(shf)->rp++ : \ (shf)->rnleft--, (int)ord(*(shf)->rp++) : \
shf_getchar(shf)) shf_getchar(shf))
#define shf_putc_i(c, shf) ((shf)->wnleft == 0 ? \ #define shf_putc_i(c, shf) ((shf)->wnleft == 0 ? \
shf_putchar((uint8_t)(c), (shf)) : \ shf_putchar((uint8_t)(c), (shf)) : \
@ -2500,6 +2521,7 @@ void shprintf(const char *, ...)
MKSH_A_FORMAT(__printf__, 1, 2); MKSH_A_FORMAT(__printf__, 1, 2);
int can_seek(int); int can_seek(int);
void initio(void); void initio(void);
void recheck_ctype(void);
int ksh_dup2(int, int, bool); int ksh_dup2(int, int, bool);
short savefd(int); short savefd(int);
void restfd(int, int); void restfd(int, int);
@ -2734,27 +2756,32 @@ extern int tty_init_fd(void); /* initialise tty_fd, tty_devtty */
#endif #endif
#ifdef MKSH_DOSPATH #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__({ \ #define mksh_abspath(s) __extension__({ \
const char *mksh_abspath_s = (s); \ const char *mksh_abspath_s = (s); \
(mksh_cdirsep(mksh_abspath_s[0]) || \ (mksh_cdirsep(mksh_abspath_s[0]) || \
(ctype(mksh_abspath_s[0], C_ALPHA) && \ (mksh_drvltr(mksh_abspath_s) && \
mksh_abspath_s[1] == ':')); \ mksh_cdirsep(mksh_abspath_s[2]))); \
}) })
#define mksh_cdirsep(c) __extension__({ \ #define mksh_cdirsep(c) __extension__({ \
char mksh_cdirsep_c = (c); \ char mksh_cdirsep_c = (c); \
(mksh_cdirsep_c == '/' || mksh_cdirsep_c == '\\'); \ (mksh_cdirsep_c == '/' || mksh_cdirsep_c == '\\'); \
}) })
#define mksh_sdirsep(s) __extension__({ \ #define mksh_sdirsep(s) strpbrk((s), "/\\")
const char *mksh_sdirsep_s = (s); \ #define mksh_vdirsep(s) __extension__({ \
((char *)((ctype(mksh_sdirsep_s[0], C_ALPHA) && \ const char *mksh_vdirsep_s = (s); \
mksh_sdirsep_s[1] == ':' && \ (((mksh_drvltr(mksh_vdirsep_s) && \
!mksh_cdirsep(mksh_sdirsep_s[2])) ? \ !mksh_cdirsep(mksh_vdirsep_s[2])) ? (!0) : \
(mksh_sdirsep_s + 1) : strpbrk(mksh_sdirsep_s, "/\\"))); \ (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 #else
#define mksh_abspath(s) (ord((s)[0]) == ord('/')) #define mksh_abspath(s) (ord((s)[0]) == ORD('/'))
#define mksh_cdirsep(c) (ord(c) == ord('/')) #define mksh_cdirsep(c) (ord(c) == ORD('/'))
#define mksh_sdirsep(s) strchr((s), '/') #define mksh_sdirsep(s) strchr((s), '/')
#define mksh_vdirsep(s) vstrchr((s), '/') #define mksh_vdirsep(s) vstrchr((s), '/')
#endif #endif

View file

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
* 2012, 2013, 2015, 2016, 2017 * 2012, 2013, 2015, 2016, 2017, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* Copyright (c) 2015 * Copyright (c) 2015
* Daniel Richard G. <skunk@iSKUNK.ORG> * Daniel Richard G. <skunk@iSKUNK.ORG>
@ -27,7 +27,7 @@
#include "sh.h" #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() */ /* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */ #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)) if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
return (-1); return (-1);
--shf->rnleft; --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 * Not only do they require all 8 bits instead of 7, if chars are
* signed, they will have negative integer values! Something like * signed, they will have negative integer values! Something like
* (c - 'A') could actually become (c + 63)! Use the ord() macro to * (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). * 4. '\n' is actually NL (0x15, U+0085) instead of LF (0x25, U+000A).
* EBCDIC has a proper newline character instead of "emulating" one * EBCDIC has a proper newline character instead of "emulating" one
* with line feeds, although this is mapped to LF for our purposes. * with line feeds, although this is mapped to LF for our purposes.

View file

@ -2,7 +2,8 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
* 2011, 2012, 2013, 2014, 2015, 2016, 2017 * 2011, 2012, 2013, 2014, 2015, 2016, 2017,
* 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -23,7 +24,7 @@
#include "sh.h" #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 { struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */ int start_token; /* token than began nesting (eg, FOR) */
@ -35,7 +36,7 @@ struct yyrecursive_state {
struct yyrecursive_state *next; struct yyrecursive_state *next;
struct ioword **old_herep; struct ioword **old_herep;
int old_symbol; int old_symbol;
int old_nesting_type; unsigned int old_nesting_type;
bool old_reject; bool old_reject;
}; };
@ -75,7 +76,10 @@ static int symbol; /* yylex value */
#define ACCEPT (reject = false) #define ACCEPT (reject = false)
#define token(cf) ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf))) #define token(cf) ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf)))
#define tpeek(cf) ((reject) ? (symbol) : (REJECT, 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 Tcbrace[] = "}";
static const char Tesac[] = "esac"; static const char Tesac[] = "esac";
@ -91,7 +95,7 @@ yyparse(bool doalias)
c = tpeek(0); c = tpeek(0);
if (c == 0 && !outtree) if (c == 0 && !outtree)
outtree = newtp(TEOF); outtree = newtp(TEOF);
else if (!ctype(c, C_LF | C_NUL)) else if (!cinttype(c, C_LF | C_NUL))
syntaxerr(NULL); syntaxerr(NULL);
} }
@ -330,7 +334,7 @@ get_command(int cf, int sALIAS)
XPput(args, yylval.cp); XPput(args, yylval.cp);
break; break;
case ord('(' /*)*/): case ORD('(' /*)*/):
if (XPsize(args) == 0 && XPsize(vars) == 1 && if (XPsize(args) == 0 && XPsize(vars) == 1 &&
is_wdvarassign(yylval.cp)) { is_wdvarassign(yylval.cp)) {
char *tcp; char *tcp;
@ -386,18 +390,18 @@ get_command(int cf, int sALIAS)
Leave: Leave:
break; break;
case ord('(' /*)*/): { case ORD('(' /*)*/): {
int subshell_nesting_type_saved; unsigned int subshell_nesting_type_saved;
Subshell: Subshell:
subshell_nesting_type_saved = subshell_nesting_type; subshell_nesting_type_saved = subshell_nesting_type;
subshell_nesting_type = ord(')'); subshell_nesting_type = ORD(')');
t = nested(TPAREN, ord('('), ord(')'), sALIAS); t = nested(TPAREN, ORD('('), ORD(')'), sALIAS);
subshell_nesting_type = subshell_nesting_type_saved; subshell_nesting_type = subshell_nesting_type_saved;
break; break;
} }
case ord('{' /*}*/): case ORD('{' /*}*/):
t = nested(TBRACE, ord('{'), ord('}'), sALIAS); t = nested(TBRACE, ORD('{'), ORD('}'), sALIAS);
break; break;
case MDPAREN: case MDPAREN:
@ -407,8 +411,8 @@ get_command(int cf, int sALIAS)
switch (token(LETEXPR)) { switch (token(LETEXPR)) {
case LWORD: case LWORD:
break; break;
case ord('(' /*)*/): case ORD('(' /*)*/):
c = ord('('); c = ORD('(');
goto Subshell; goto Subshell;
default: default:
syntaxerr(NULL); syntaxerr(NULL);
@ -554,8 +558,8 @@ dogroup(int sALIAS)
*/ */
if (c == DO) if (c == DO)
c = DONE; c = DONE;
else if (c == ord('{')) else if ((unsigned int)c == ORD('{'))
c = ord('}'); c = ORD('}');
else else
syntaxerr(NULL); syntaxerr(NULL);
list = c_list(sALIAS, true); list = c_list(sALIAS, true);
@ -610,8 +614,8 @@ caselist(int sALIAS)
/* A {...} can be used instead of in...esac for case statements */ /* A {...} can be used instead of in...esac for case statements */
if (c == IN) if (c == IN)
c = ESAC; c = ESAC;
else if (c == ord('{')) else if ((unsigned int)c == ORD('{'))
c = ord('}'); c = ORD('}');
else else
syntaxerr(NULL); syntaxerr(NULL);
t = tl = NULL; t = tl = NULL;
@ -636,18 +640,17 @@ casepart(int endtok, int sALIAS)
XPinit(ptns, 16); XPinit(ptns, 16);
t = newtp(TPAT); t = newtp(TPAT);
/* no ALIAS here */ /* no ALIAS here */
if (token(CONTIN | KEYWORD) != ord('(')) if ((unsigned int)token(CONTIN | KEYWORD) != ORD('('))
REJECT; REJECT;
do { do {
switch (token(0)) { switch (token(0)) {
case LWORD: case LWORD:
break; break;
case ord('}'): case ORD('}'):
case ESAC: case ESAC:
if (symbol != endtok) { if (symbol != endtok) {
strdupx(yylval.cp, strdupx(yylval.cp, (unsigned int)symbol ==
symbol == ord('}') ? Tcbrace : Tesac, ORD('}') ? Tcbrace : Tesac, ATEMP);
ATEMP);
break; break;
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -659,23 +662,23 @@ casepart(int endtok, int sALIAS)
REJECT; REJECT;
XPput(ptns, NULL); XPput(ptns, NULL);
t->vars = (char **)XPclose(ptns); t->vars = (char **)XPclose(ptns);
musthave(ord(')'), 0); musthave(ORD(')'), 0);
t->left = c_list(sALIAS, true); t->left = c_list(sALIAS, true);
/* initialise to default for ;; or omitted */ /* initialise to default for ;; or omitted */
t->u.charflag = ord(';'); t->u.charflag = ORD(';');
/* SUSv4 requires the ;; except in the last casepart */ /* SUSv4 requires the ;; except in the last casepart */
if ((tpeek(CONTIN|KEYWORD|sALIAS)) != endtok) if ((tpeek(CONTIN|KEYWORD|sALIAS)) != endtok)
switch (symbol) { switch (symbol) {
default: default:
syntaxerr(NULL); syntaxerr(NULL);
case BRKEV: case BRKEV:
t->u.charflag = ord('|'); t->u.charflag = ORD('|');
if (0) if (0)
/* FALLTHROUGH */ /* FALLTHROUGH */
case BRKFT: case BRKFT:
t->u.charflag = ord('&'); t->u.charflag = ORD('&');
/* FALLTHROUGH */ /* FALLTHROUGH */
case BREAK: case BREAK:
/* initialised above, but we need to eat the token */ /* initialised above, but we need to eat the token */
@ -711,14 +714,14 @@ function_body(char *name, int sALIAS,
* only accepts an open-brace. * only accepts an open-brace.
*/ */
if (ksh_func) { if (ksh_func) {
if (tpeek(CONTIN|KEYWORD|sALIAS) == ord('(' /*)*/)) { if ((unsigned int)tpeek(CONTIN|KEYWORD|sALIAS) == ORD('(' /*)*/)) {
/* function foo () { //}*/ /* function foo () { //}*/
ACCEPT; ACCEPT;
musthave(ord(/*(*/ ')'), 0); musthave(ORD(/*(*/ ')'), 0);
/* degrade to POSIX function */ /* degrade to POSIX function */
ksh_func = false; ksh_func = false;
} }
musthave(ord('{' /*}*/), CONTIN|KEYWORD|sALIAS); musthave(ORD('{' /*}*/), CONTIN|KEYWORD|sALIAS);
REJECT; REJECT;
} }
@ -810,8 +813,8 @@ static const struct tokeninfo {
{ "in", IN, true }, { "in", IN, true },
{ Tfunction, FUNCTION, true }, { Tfunction, FUNCTION, true },
{ Ttime, TIME, true }, { Ttime, TIME, true },
{ "{", ord('{'), true }, { "{", ORD('{'), true },
{ Tcbrace, ord('}'), true }, { Tcbrace, ORD('}'), true },
{ "!", BANG, true }, { "!", BANG, true },
{ "[[", DBRACKET, true }, { "[[", DBRACKET, true },
/* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */ /* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */
@ -823,7 +826,7 @@ static const struct tokeninfo {
{ "((", MDPAREN, false }, { "((", MDPAREN, false },
{ "|&", COPROC, false }, { "|&", COPROC, false },
/* and some special cases... */ /* and some special cases... */
{ "newline", ord('\n'), false }, { "newline", ORD('\n'), false },
{ NULL, 0, false } { NULL, 0, false }
}; };
@ -998,9 +1001,9 @@ dbtestp_isa(Test_env *te, Test_meta meta)
ret = (uqword && !strcmp(yylval.cp, ret = (uqword && !strcmp(yylval.cp,
dbtest_tokens[(int)TM_NOT])) ? TO_NONNULL : TO_NONOP; dbtest_tokens[(int)TM_NOT])) ? TO_NONNULL : TO_NONOP;
else if (meta == TM_OPAREN) 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) 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) { else if (meta == TM_UNOP || meta == TM_BINOP) {
if (meta == TM_BINOP && c == REDIR && if (meta == TM_BINOP && c == REDIR &&
(yylval.iop->ioflag == IOREAD || (yylval.iop->ioflag == IOREAD ||
@ -1131,14 +1134,14 @@ yyrecursive(int subtype)
struct op *t; struct op *t;
char *cp; char *cp;
struct yyrecursive_state *ys; struct yyrecursive_state *ys;
int stok, etok; unsigned int stok, etok;
if (subtype != COMSUB) { if (subtype != COMSUB) {
stok = ord('{'); stok = ORD('{');
etok = ord('}'); etok = ORD('}');
} else { } else {
stok = ord('('); stok = ORD('(');
etok = ord(')'); etok = ORD(')');
} }
ys = alloc(sizeof(struct yyrecursive_state), ATEMP); ys = alloc(sizeof(struct yyrecursive_state), ATEMP);

View file

@ -23,7 +23,7 @@
#include "sh.h" #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 #define INDENT 8
@ -329,7 +329,7 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
case EOS: case EOS:
return (--wp); return (--wp);
case ADELIM: case ADELIM:
if (ord(*wp) == ord(/*{*/ '}')) { if (ord(*wp) == ORD(/*{*/ '}')) {
++wp; ++wp;
goto wdvarput_csubst; goto wdvarput_csubst;
} }
@ -342,21 +342,21 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
c = ord(*wp++); c = ord(*wp++);
if (opmode & WDS_TPUTS) if (opmode & WDS_TPUTS)
switch (c) { switch (c) {
case ord('\n'): case ORD('\n'):
if (quotelevel == 0) { if (quotelevel == 0) {
c = ord('\''); c = ORD('\'');
shf_putc(c, shf); shf_putc(c, shf);
shf_putc(ord('\n'), shf); shf_putc(ORD('\n'), shf);
} }
break; break;
default: default:
if (quotelevel == 0) if (quotelevel == 0)
/* FALLTHROUGH */ /* FALLTHROUGH */
case ord('"'): case ORD('"'):
case ord('`'): case ORD('`'):
case ord('$'): case ORD('$'):
case ord('\\'): case ORD('\\'):
shf_putc(ord('\\'), shf); shf_putc(ORD('\\'), shf);
break; break;
} }
shf_putc(c, shf); shf_putc(c, shf);
@ -365,7 +365,7 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
case COMSUB: case COMSUB:
shf_puts("$(", shf); shf_puts("$(", shf);
cs = ")"; cs = ")";
if (ord(*wp) == ord('(' /*)*/)) if (ord(*wp) == ORD('(' /*)*/))
shf_putc(' ', shf); shf_putc(' ', shf);
pSUB: pSUB:
while ((c = *wp++) != 0) while ((c = *wp++) != 0)
@ -374,11 +374,11 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
break; break;
case FUNASUB: case FUNASUB:
case FUNSUB: case FUNSUB:
c = ord(' '); c = ORD(' ');
if (0) if (0)
/* FALLTHROUGH */ /* FALLTHROUGH */
case VALSUB: case VALSUB:
c = ord('|'); c = ORD('|');
shf_putc('$', shf); shf_putc('$', shf);
shf_putc('{', shf); shf_putc('{', shf);
shf_putc(c, shf); shf_putc(c, shf);
@ -403,14 +403,14 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
break; break;
case OSUBST: case OSUBST:
shf_putc('$', shf); shf_putc('$', shf);
if (ord(*wp++) == ord('{')) if (ord(*wp++) == ORD('{'))
shf_putc('{', shf); shf_putc('{', shf);
while ((c = *wp++) != 0) while ((c = *wp++) != 0)
shf_putc(c, shf); shf_putc(c, shf);
wp = wdvarput(shf, wp, 0, opmode); wp = wdvarput(shf, wp, 0, opmode);
break; break;
case CSUBST: case CSUBST:
if (ord(*wp++) == ord('}')) { if (ord(*wp++) == ORD('}')) {
wdvarput_csubst: wdvarput_csubst:
shf_putc('}', shf); shf_putc('}', shf);
} }
@ -420,11 +420,11 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
shf_putc('(', shf); shf_putc('(', shf);
break; break;
case SPAT: case SPAT:
c = ord('|'); c = ORD('|');
if (0) if (0)
/* FALLTHROUGH */ /* FALLTHROUGH */
case CPAT: case CPAT:
c = ord(/*(*/ ')'); c = ORD(/*(*/ ')');
shf_putc(c, shf); shf_putc(c, shf);
break; break;
} }
@ -470,36 +470,37 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
while ((c = ord(*fmt++))) { while ((c = ord(*fmt++))) {
if (c == '%') { if (c == '%') {
switch ((c = ord(*fmt++))) { switch ((c = ord(*fmt++))) {
case ord('c'): case ORD('c'):
/* character (octet, probably) */ /* character (octet, probably) */
shf_putchar(va_arg(va, int), shf); shf_putchar(va_arg(va, int), shf);
break; break;
case ord('s'): case ORD('s'):
/* string */ /* string */
shf_puts(va_arg(va, char *), shf); shf_puts(va_arg(va, char *), shf);
break; break;
case ord('S'): case ORD('S'):
/* word */ /* word */
wdvarput(shf, va_arg(va, char *), 0, WDS_TPUTS); wdvarput(shf, va_arg(va, char *), 0, WDS_TPUTS);
break; break;
case ord('d'): case ORD('d'):
/* signed decimal */ /* signed decimal */
shf_fprintf(shf, Tf_d, va_arg(va, int)); shf_fprintf(shf, Tf_d, va_arg(va, int));
break; break;
case ord('u'): case ORD('u'):
/* unsigned decimal */ /* unsigned decimal */
shf_fprintf(shf, "%u", va_arg(va, unsigned int)); shf_fprintf(shf, "%u", va_arg(va, unsigned int));
break; break;
case ord('T'): case ORD('T'):
/* format tree */ /* format tree */
ptree(va_arg(va, struct op *), indent, shf); ptree(va_arg(va, struct op *), indent, shf);
goto dont_trash_prevent_semicolon; goto dont_trash_prevent_semicolon;
case ord(';'): case ORD(';'):
/* newline or ; */ /* newline or ; */
case ord('N'): case ORD('N'):
/* newline or space */ /* newline or space */
if (shf->flags & SHF_STRING) { if (shf->flags & SHF_STRING) {
if (c == ord(';') && !prevent_semicolon) if ((unsigned int)c == ORD(';') &&
!prevent_semicolon)
shf_putc(';', shf); shf_putc(';', shf);
shf_putc(' ', shf); shf_putc(' ', shf);
} else { } else {
@ -515,7 +516,7 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
shf_putc(' ', shf); shf_putc(' ', shf);
} }
break; break;
case ord('R'): case ORD('R'):
/* I/O redirection */ /* I/O redirection */
pioact(shf, va_arg(va, struct ioword *)); pioact(shf, va_arg(va, struct ioword *));
break; break;
@ -613,7 +614,7 @@ wdscan(const char *wp, int c)
case ADELIM: case ADELIM:
if (c == ADELIM && nest == 0) if (c == ADELIM && nest == 0)
return (wp + 1); return (wp + 1);
if (ord(*wp) == ord(/*{*/ '}')) if (ord(*wp) == ORD(/*{*/ '}'))
goto wdscan_csubst; goto wdscan_csubst;
/* FALLTHROUGH */ /* FALLTHROUGH */
case CHAR: case CHAR:
@ -808,7 +809,7 @@ vistree(char *dst, size_t sz, struct op *t)
} else if (UTFMODE && rtt2asc(c) > 0x7F) { } else if (UTFMODE && rtt2asc(c) > 0x7F) {
/* better not try to display broken multibyte chars */ /* better not try to display broken multibyte chars */
/* also go easy on the Unicode: no U+FFFD here */ /* also go easy on the Unicode: no U+FFFD here */
c = ord('?'); c = ORD('?');
} }
*dst++ = c; *dst++ = c;
goto vist_loop; goto vist_loop;
@ -842,7 +843,7 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
shf_puts("EOS", shf); shf_puts("EOS", shf);
return (--wp); return (--wp);
case ADELIM: case ADELIM:
if (ord(*wp) == ord(/*{*/ '}')) { if (ord(*wp) == ORD(/*{*/ '}')) {
shf_puts(/*{*/ "]ADELIM(})", shf); shf_puts(/*{*/ "]ADELIM(})", shf);
return (wp + 1); return (wp + 1);
} }
@ -856,8 +857,8 @@ dumpwdvar_i(struct shf *shf, const char *wp, int quotelevel)
case QCHAR: case QCHAR:
shf_puts("QCHAR<", shf); shf_puts("QCHAR<", shf);
c = ord(*wp++); c = ord(*wp++);
if (quotelevel == 0 || c == ord('"') || if (quotelevel == 0 || c == ORD('"') ||
c == ord('\\') || ctype(c, C_DOLAR | C_GRAVE)) c == ORD('\\') || ctype(c, C_DOLAR | C_GRAVE))
shf_putc('\\', shf); shf_putc('\\', shf);
dumpchar(shf, c); dumpchar(shf, c);
goto closeandout; goto closeandout;

View file

@ -2,7 +2,7 @@
/*- /*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015, 2016, 2017 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -28,7 +28,7 @@
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #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 * Variables
@ -136,7 +136,7 @@ initvar(void)
struct tbl *tp; struct tbl *tp;
ktinit(APERM, &specials, ktinit(APERM, &specials,
/* currently 18 specials: 75% of 32 = 2^5 */ /* currently 21 specials: 75% of 32 = 2^5 */
5); 5);
while (i < V_MAX - 1) { while (i < V_MAX - 1) {
tp = ktenter(&specials, initvar_names[i], 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; 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; char *sub, *tmp;
mksh_ari_t rval; 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 */ /* no variable name given */
return (NULL); return (NULL);
} }
if (ord(*val) == ord('[')) { if (ord(*val) == ORD('[')) {
if (new_refflag != SRF_NOP) if (new_refflag != SRF_NOP)
errorf(Tf_sD_s, var, errorf(Tf_sD_s, var,
"reference variable can't be an array"); "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; val += len;
} }
if (ord(val[0]) == ord('=')) { if (ord(val[0]) == ORD('=')) {
strndupx(tvar, var, val - var, ATEMP); strndupx(tvar, var, val - var, ATEMP);
++val; ++val;
} else if (set & IMPORT) { } else if (set & IMPORT) {
/* environment invalid variable name or no assignment */ /* environment invalid variable name or no assignment */
return (NULL); 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); strndupx(tvar, var, val - var, ATEMP);
val += 2; val += 2;
vappend = true; vappend = true;
@ -822,9 +822,9 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
val = NULL; val = NULL;
/* handle foo[*] => foo (whole array) mapping for R39b */ /* handle foo[*] => foo (whole array) mapping for R39b */
len = strlen(tvar); len = strlen(tvar);
if (len > 3 && ord(tvar[len - 3]) == ord('[') && if (len > 3 && ord(tvar[len - 3]) == ORD('[') &&
ord(tvar[len - 2]) == ord('*') && ord(tvar[len - 2]) == ORD('*') &&
ord(tvar[len - 1]) == ord(']')) ord(tvar[len - 1]) == ORD(']'))
tvar[len - 3] = '\0'; tvar[len - 3] = '\0';
} }
@ -861,7 +861,7 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
nameref_empty: nameref_empty:
errorf(Tf_sD_s, var, "empty nameref target"); 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]) { if (ccp[len]) {
/* /*
* works for cases "no array", "valid array with * works for cases "no array", "valid array with
@ -1071,7 +1071,7 @@ skip_varname(const char *s, bool aok)
do { do {
++s; ++s;
} while (ctype(*s, C_ALNUX)); } 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; s += alen;
} }
return (s); return (s);
@ -1087,7 +1087,7 @@ skip_wdvarname(const char *s,
do { do {
s += 2; s += 2;
} while (s[0] == CHAR && ctype(s[1], C_ALNUX)); } 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 */ /* skip possible array de-reference */
const char *p = s; const char *p = s;
char c; char c;
@ -1098,9 +1098,9 @@ skip_wdvarname(const char *s,
break; break;
c = p[1]; c = p[1];
p += 2; p += 2;
if (ord(c) == ord('[')) if (ord(c) == ORD('['))
depth++; depth++;
else if (ord(c) == ord(']') && --depth == 0) { else if (ord(c) == ORD(']') && --depth == 0) {
s = p; s = p;
break; break;
} }
@ -1294,9 +1294,29 @@ setspec(struct tbl *vp)
{ {
mksh_ari_u num; mksh_ari_u num;
char *s; 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__ #ifdef __OS2__
case V_BEGINLIBPATH: case V_BEGINLIBPATH:
case V_ENDLIBPATH: case V_ENDLIBPATH:
@ -1366,6 +1386,13 @@ setspec(struct tbl *vp)
} }
vp->flag |= SPECIAL; vp->flag |= SPECIAL;
break; break;
#ifdef MKSH_EARLY_LOCALE_TRACKING
case V_LANG:
case V_LC_ALL:
case V_LC_CTYPE:
recheck_ctype();
return;
#endif
default: default:
/* do nothing, do not touch vp at all */ /* do nothing, do not touch vp at all */
return; return;
@ -1465,6 +1492,13 @@ unsetspec(struct tbl *vp)
/* AT&T ksh leaves previous value in place */ /* AT&T ksh leaves previous value in place */
unspecial(vp->name); unspecial(vp->name);
break; 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; char c;
int depth = 0; int depth = 0;
while ((c = *s++) && (ord(c) != ord(']') || --depth)) while ((c = *s++) && (ord(c) != ORD(']') || --depth))
if (ord(c) == ord('[')) if (ord(c) == ORD('['))
depth++; depth++;
if (!c) if (!c)
return (0); return (0);
@ -1601,18 +1635,18 @@ set_array(const char *var, bool reset, const char **vals)
} }
while ((ccp = vals[i])) { while ((ccp = vals[i])) {
#if 0 /* temporarily taken out due to regression */ #if 0 /* temporarily taken out due to regression */
if (ord(*ccp) == ord('[')) { if (ord(*ccp) == ORD('[')) {
int level = 0; int level = 0;
while (*ccp) { while (*ccp) {
if (ord(*ccp) == ord(']') && --level == 0) if (ord(*ccp) == ORD(']') && --level == 0)
break; break;
if (ord(*ccp) == ord('[')) if (ord(*ccp) == ORD('['))
++level; ++level;
++ccp; ++ccp;
} }
if (ord(*ccp) == ord(']') && level == 0 && if (ord(*ccp) == ORD(']') && level == 0 &&
ord(ccp[1]) == ord('=')) { ord(ccp[1]) == ORD('=')) {
strndupx(cp, vals[i] + 1, ccp - (vals[i] + 1), strndupx(cp, vals[i] + 1, ccp - (vals[i] + 1),
ATEMP); ATEMP);
evaluate(substitute(cp, 0), (mksh_ari_t *)&j, evaluate(substitute(cp, 0), (mksh_ari_t *)&j,

View file

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2009, 2011, 2012, 2016 * Copyright (c) 2009, 2011, 2012, 2016, 2018
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -19,7 +19,7 @@
*/ */
#if defined(VARSPEC_DEFNS) #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 */ #define FN(name) /* nothing */
#elif defined(VARSPEC_ENUMS) #elif defined(VARSPEC_ENUMS)
#define FN(name) V_##name, #define FN(name) V_##name,
@ -53,6 +53,11 @@ FN(HISTFILE)
#endif #endif
FN(HISTSIZE) FN(HISTSIZE)
FN(IFS) FN(IFS)
#ifdef MKSH_EARLY_LOCALE_TRACKING
FN(LANG)
FN(LC_ALL)
FN(LC_CTYPE)
#endif
#ifdef __OS2__ #ifdef __OS2__
FN(LIBPATHSTRICT) FN(LIBPATHSTRICT)
#endif #endif