diff --git a/check.t b/check.t index e560d7f..8e4c1d3 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.489 2011/11/09 22:17:23 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.490 2011/11/11 22:14:15 tg Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ @@ -25,7 +25,7 @@ # http://www.research.att.com/~gsf/public/ifs.sh expected-stdout: - @(#)MIRBSD KSH R40 2011/11/09 + @(#)MIRBSD KSH R40 2011/11/11 description: Check version of shell. stdin: @@ -6177,7 +6177,6 @@ expected-stdout: name: arrays-2a description: Check if bash-style arrays work as expected -category: !smksh stdin: v="c d" foo=(a \$v "$v" '$v' b) @@ -6188,7 +6187,6 @@ expected-stdout: name: arrays-2b description: Check if bash-style arrays work as expected, with newlines -category: !smksh stdin: test -n "$ZSH_VERSION" && setopt KSH_ARRAYS v="e f" @@ -6229,7 +6227,6 @@ expected-stdout: name: arrays-4 description: Check if Korn Shell arrays with specified indices work as expected -category: !smksh stdin: v="c d" set -A foo -- [1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b @@ -6240,7 +6237,6 @@ expected-stdout: name: arrays-5 description: Check if bash-style arrays with specified indices work as expected -category: !smksh stdin: v="c d" foo=([1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b) @@ -6409,7 +6405,6 @@ expected-stdout: name: arrays-9a description: Check that we can concatenate arrays -category: !smksh stdin: unset foo; foo=(bar); foo+=(baz); echo 1 ${!foo[*]} : ${foo[*]} . unset foo; foo=(foo bar); foo+=(baz); echo 2 ${!foo[*]} : ${foo[*]} . @@ -7651,46 +7646,39 @@ description: Fails on: pdksh bash2 bash3 zsh Passes on: bash4 ksh93 mksh(20110313+) stdin: - echo $(case 1 in (1) echo yes;; (2) echo no;; esac) - echo $(case 1 in 1) echo yes;; 2) echo no;; esac) - TEST=1234; echo ${TEST: $(case 1 in (1) echo 1;; (*) echo 2;; esac)} - TEST=5678; echo ${TEST: $(case 1 in 1) echo 1;; *) echo 2;; esac)} + echo 1 $(case 1 in (1) echo yes;; (2) echo no;; esac) . + echo 2 $(case 1 in 1) echo yes;; 2) echo no;; esac) . + TEST=1234; echo 3 ${TEST: $(case 1 in (1) echo 1;; (*) echo 2;; esac)} . + TEST=5678; echo 4 ${TEST: $(case 1 in 1) echo 1;; *) echo 2;; esac)} . + a=($(case 1 in (1) echo 1;; (*) echo 2;; esac)); echo 5 ${a[0]} . + a=($(case 1 in 1) echo 1;; *) echo 2;; esac)); echo 6 ${a[0]} . expected-stdout: - yes - yes - 234 - 678 + 1 yes . + 2 yes . + 3 234 . + 4 678 . + 5 1 . + 6 1 . --- name: comsub-1b description: COMSUB are now parsed recursively, so this works - Fails on GNU bash even, ksh93 passes + Fails on: pdksh bash2 bash3 bash4 zsh + Passes on: ksh93 mksh(20110313+) stdin: - echo $(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10)) - echo $(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20)) - (( a = $(case 1 in (1) echo 1;; (*) echo 2;; esac) )); echo $a. - (( a = $(case 1 in 1) echo 1;; *) echo 2;; esac) )); echo $a. + echo 1 $(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10)) . + echo 2 $(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20)) . + (( a = $(case 1 in (1) echo 1;; (*) echo 2;; esac) )); echo 3 $a . + (( a = $(case 1 in 1) echo 1;; *) echo 2;; esac) )); echo 4 $a . + a=($(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10))); echo 5 ${a[0]} . + a=($(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20))); echo 6 ${a[0]} . expected-stdout: - 11 - 21 - 1. - 1. ---- -name: comsub-1c -description: - COMSUB are now parsed recursively, so this works (ksh93, mksh) - First test passes on bash4, second fails there -category: !smksh -stdin: - a=($(case 1 in (1) echo 1;; (*) echo 2;; esac)); echo ${a[0]}. - a=($(case 1 in 1) echo 1;; *) echo 2;; esac)); echo ${a[0]}. - a=($(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10))); echo ${a[0]}. - a=($(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20))); echo ${a[0]}. -expected-stdout: - 1. - 1. - 11. - 21. + 1 11 . + 2 21 . + 3 1 . + 4 1 . + 5 11 . + 6 21 . --- name: comsub-2 description: @@ -7732,16 +7720,16 @@ description: Check the tree dump functions for !MKSH_SMALL functionality category: !smksh stdin: - x() { case $1 in a) a+=b ;;& *) c+=(d e) ;; esac; } + x() { case $1 in u) echo x ;;& *) echo $1 ;; esac; } typeset -f x expected-stdout: x() { case $1 in - (a) - a+=b + (u) + echo x ;| (*) - set -A c+ -- d e + echo $1 ;; esac } @@ -7844,6 +7832,8 @@ stdin: install -c -o root -g wheel -m 664 /dev/null /etc/motd print -- "$x\n" >/etc/motd fi + #wdarrassign + a+=b; c+=(d e) #0 EOD expected-stdout: @@ -8409,6 +8399,25 @@ expected-stdout: EOF )" = @(?) ]] && rm -f /etc/motd ; if [[ ! -s /etc/motd ]] ; then install -c -o root -g wheel -m 664 /dev/null /etc/motd ; print -- "$x\n" >/etc/motd ; fi ) | tr u x ) } + inline_wdarrassign() { + a+=b; c+=(d e) + } + inline_wdarrassign() { + a+=b + set -A c+ -- d e + } + function comsub_wdarrassign { x=$( + a+=b; c+=(d e) + ); } + function comsub_wdarrassign { + x=$(a+=b ; set -A c+ -- d e ) + } + function reread_wdarrassign { x=$(( + a+=b; c+=(d e) + )|tr u x); } + function reread_wdarrassign { + x=$(( a+=b ; set -A c+ -- d e ) | tr u x ) + } --- name: test-stnze-1 description: diff --git a/sh.h b/sh.h index 722ba8d..a993a97 100644 --- a/sh.h +++ b/sh.h @@ -151,9 +151,9 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.501 2011/11/09 22:17:26 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.502 2011/11/11 22:14:17 tg Exp $"); #endif -#define MKSH_VERSION "R40 2011/11/09" +#define MKSH_VERSION "R40 2011/11/11" #ifndef MKSH_INCLUDES_ONLY diff --git a/syn.c b/syn.c index b2a3f8b..bfe984f 100644 --- a/syn.c +++ b/syn.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.69 2011/09/07 15:24:21 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.70 2011/11/11 22:14:19 tg Exp $"); extern short subshell_nesting_level; extern void yyskiputf8bom(void); @@ -232,13 +232,27 @@ nested(int type, int smark, int emark) return (block(type, t, NOBLOCK, NOWORDS)); } +static const char let_cmd[] = { + CHAR, 'l', CHAR, 'e', CHAR, 't', EOS +}; +static const char setA_cmd0[] = { + CHAR, 's', CHAR, 'e', CHAR, 't', EOS +}; +static const char setA_cmd1[] = { + CHAR, '-', CHAR, 'A', EOS +}; +static const char setA_cmd2[] = { + CHAR, '-', CHAR, '-', EOS +}; + static struct op * get_command(int cf) { struct op *t; - int c, iopn = 0, syniocf; + int c, iopn = 0, syniocf, lno; struct ioword *iop, **iops; XPtrV args, vars; + char *tcp; struct nesting_state old_nesting; /* NUFILE is small enough to leave this addition unchecked */ @@ -292,67 +306,50 @@ get_command(int cf) XPput(args, yylval.cp); break; - case '(': -#ifndef MKSH_SMALL - if ((XPsize(args) == 0 || Flag(FKEYWORD)) && - XPsize(vars) == 1 && is_wdvarassign(yylval.cp)) - goto is_wdarrassign; -#endif - /* - * Check for "> foo (echo hi)" which AT&T ksh - * allows (not POSIX, but not disallowed) - */ - afree(t, ATEMP); - if (XPsize(args) == 0 && XPsize(vars) == 0) { + case '(' /*)*/: + if (XPsize(args) == 0 && XPsize(vars) == 1 && + is_wdvarassign(yylval.cp)) { + /* wdarrassign: foo=(bar) */ ACCEPT; - goto Subshell; + + /* manipulate the vars string */ + tcp = *(--vars.cur); + /* 'varname=' -> 'varname' */ + tcp[wdscan(tcp, EOS) - tcp - 3] = EOS; + + /* construct new args strings */ + XPput(args, wdcopy(setA_cmd0, ATEMP)); + XPput(args, wdcopy(setA_cmd1, ATEMP)); + XPput(args, tcp); + XPput(args, wdcopy(setA_cmd2, ATEMP)); + + /* slurp in words till closing paren */ + while (token(CONTIN) == LWORD) + XPput(args, yylval.cp); + if (symbol != /*(*/ ')') + syntaxerr(NULL); + } else { + /* + * Check for "> foo (echo hi)" + * which AT&T ksh allows (not + * POSIX, but not disallowed) + */ + afree(t, ATEMP); + if (XPsize(args) == 0 && + XPsize(vars) == 0) { + ACCEPT; + goto Subshell; + } + + /* must be a function */ + if (iopn != 0 || XPsize(args) != 1 || + XPsize(vars) != 0) + syntaxerr(NULL); + ACCEPT; + musthave(/*(*/')', 0); + t = function_body(XPptrv(args)[0], false); } - - /* must be a function */ - if (iopn != 0 || XPsize(args) != 1 || - XPsize(vars) != 0) - syntaxerr(NULL); - ACCEPT; - musthave(/*(*/')', 0); - t = function_body(XPptrv(args)[0], false); goto Leave; -#ifndef MKSH_SMALL - is_wdarrassign: - { - static const char set_cmd0[] = { - CHAR, 's', CHAR, 'e', - CHAR, 't', EOS - }; - static const char set_cmd1[] = { - CHAR, '-', CHAR, 'A', EOS - }; - static const char set_cmd2[] = { - CHAR, '-', CHAR, '-', EOS - }; - char *tcp; - - ACCEPT; - - /* manipulate the vars string */ - tcp = *(--vars.cur); - /* 'varname=' -> 'varname' */ - tcp[wdscan(tcp, EOS) - tcp - 3] = EOS; - - /* construct new args strings */ - XPput(args, wdcopy(set_cmd0, ATEMP)); - XPput(args, wdcopy(set_cmd1, ATEMP)); - XPput(args, tcp); - XPput(args, wdcopy(set_cmd2, ATEMP)); - - /* slurp in words till closing paren */ - while (token(CONTIN) == LWORD) - XPput(args, yylval.cp); - if (symbol != /*(*/ ')') - syntaxerr(NULL); - - goto Leave; - } -#endif default: goto Leave; @@ -372,13 +369,7 @@ get_command(int cf) t = nested(TBRACE, '{', '}'); break; - case MDPAREN: { - int lno; - static const char let_cmd[] = { - CHAR, 'l', CHAR, 'e', - CHAR, 't', EOS - }; - + case MDPAREN: /* leave KEYWORD in syniocf (allow if (( 1 )) then ...) */ lno = source->line; ACCEPT; @@ -395,7 +386,6 @@ get_command(int cf) XPput(args, wdcopy(let_cmd, ATEMP)); XPput(args, yylval.cp); break; - } case DBRACKET: /* [[ .. ]] */ /* leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */ diff --git a/var.c b/var.c index 646af33..f3409ce 100644 --- a/var.c +++ b/var.c @@ -26,7 +26,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/var.c,v 1.134 2011/11/08 22:07:15 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/var.c,v 1.135 2011/11/11 22:14:19 tg Exp $"); /*- * Variables @@ -1379,29 +1379,23 @@ set_array(const char *var, bool reset, const char **vals) { struct tbl *vp, *vq; mksh_uari_t i = 0, j = 0; - const char *ccp; -#ifndef MKSH_SMALL + const char *ccp = var; char *cp = NULL; size_t n; -#endif /* to get local array, use "typeset foo; set -A foo" */ -#ifndef MKSH_SMALL n = strlen(var); if (n > 0 && var[n - 1] == '+') { /* append mode */ reset = false; strndupx(cp, var, n - 1, ATEMP); + ccp = cp; } -#define CPORVAR (cp ? cp : var) -#else -#define CPORVAR var -#endif - vp = global(CPORVAR); + vp = global(ccp); /* Note: AT&T ksh allows set -A but not set +A of a read-only var */ if ((vp->flag&RDONLY)) - errorfx(2, "%s: %s", CPORVAR, "is read only"); + errorfx(2, "%s: %s", ccp, "is read only"); /* This code is quite non-optimal */ if (reset) /* trash existing values and attributes */ @@ -1411,7 +1405,6 @@ set_array(const char *var, bool reset, const char **vals) * completely fail. Only really effects integer arrays: * evaluation of some of vals[] may fail... */ -#ifndef MKSH_SMALL if (cp != NULL) { /* find out where to set when appending */ for (vq = vp; vq; vq = vq->u.array) { @@ -1422,9 +1415,7 @@ set_array(const char *var, bool reset, const char **vals) } afree(cp, ATEMP); } -#endif while ((ccp = vals[i])) { -#ifndef MKSH_SMALL if (*ccp == '[') { int level = 0; @@ -1445,7 +1436,6 @@ set_array(const char *var, bool reset, const char **vals) } else ccp = vals[i]; } -#endif vq = arraysearch(vp, j); /* would be nice to deal with errors here... (see above) */