promote x=(a b); x+=(c) to standard mksh functionality at cost of 932 MKSH_SMALL .text bytes on MirBSD/i386

This commit is contained in:
tg 2011-11-11 22:14:19 +00:00
parent 7e719a4cc1
commit e20b1295b7
4 changed files with 118 additions and 129 deletions

97
check.t
View File

@ -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: 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: 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 $ # $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 # http://www.research.att.com/~gsf/public/ifs.sh
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R40 2011/11/09 @(#)MIRBSD KSH R40 2011/11/11
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -6177,7 +6177,6 @@ expected-stdout:
name: arrays-2a name: arrays-2a
description: description:
Check if bash-style arrays work as expected Check if bash-style arrays work as expected
category: !smksh
stdin: stdin:
v="c d" v="c d"
foo=(a \$v "$v" '$v' b) foo=(a \$v "$v" '$v' b)
@ -6188,7 +6187,6 @@ expected-stdout:
name: arrays-2b name: arrays-2b
description: description:
Check if bash-style arrays work as expected, with newlines Check if bash-style arrays work as expected, with newlines
category: !smksh
stdin: stdin:
test -n "$ZSH_VERSION" && setopt KSH_ARRAYS test -n "$ZSH_VERSION" && setopt KSH_ARRAYS
v="e f" v="e f"
@ -6229,7 +6227,6 @@ expected-stdout:
name: arrays-4 name: arrays-4
description: description:
Check if Korn Shell arrays with specified indices work as expected Check if Korn Shell arrays with specified indices work as expected
category: !smksh
stdin: stdin:
v="c d" v="c d"
set -A foo -- [1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b set -A foo -- [1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b
@ -6240,7 +6237,6 @@ expected-stdout:
name: arrays-5 name: arrays-5
description: description:
Check if bash-style arrays with specified indices work as expected Check if bash-style arrays with specified indices work as expected
category: !smksh
stdin: stdin:
v="c d" v="c d"
foo=([1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b) foo=([1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b)
@ -6409,7 +6405,6 @@ expected-stdout:
name: arrays-9a name: arrays-9a
description: description:
Check that we can concatenate arrays Check that we can concatenate arrays
category: !smksh
stdin: stdin:
unset foo; foo=(bar); foo+=(baz); echo 1 ${!foo[*]} : ${foo[*]} . unset foo; foo=(bar); foo+=(baz); echo 1 ${!foo[*]} : ${foo[*]} .
unset foo; foo=(foo bar); foo+=(baz); echo 2 ${!foo[*]} : ${foo[*]} . unset foo; foo=(foo bar); foo+=(baz); echo 2 ${!foo[*]} : ${foo[*]} .
@ -7651,46 +7646,39 @@ description:
Fails on: pdksh bash2 bash3 zsh Fails on: pdksh bash2 bash3 zsh
Passes on: bash4 ksh93 mksh(20110313+) Passes on: bash4 ksh93 mksh(20110313+)
stdin: stdin:
echo $(case 1 in (1) echo yes;; (2) echo no;; esac) echo 1 $(case 1 in (1) echo yes;; (2) echo no;; esac) .
echo $(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 ${TEST: $(case 1 in (1) echo 1;; (*) echo 2;; esac)} TEST=1234; echo 3 ${TEST: $(case 1 in (1) echo 1;; (*) echo 2;; esac)} .
TEST=5678; echo ${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: expected-stdout:
yes 1 yes .
yes 2 yes .
234 3 234 .
678 4 678 .
5 1 .
6 1 .
--- ---
name: comsub-1b name: comsub-1b
description: description:
COMSUB are now parsed recursively, so this works 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: stdin:
echo $(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10)) echo 1 $(($(case 1 in (1) echo 1;; (*) echo 2;; esac)+10)) .
echo $(($(case 1 in 1) echo 1;; *) echo 2;; esac)+20)) echo 2 $(($(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 3 $a .
(( a = $(case 1 in 1) echo 1;; *) echo 2;; esac) )); echo $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: expected-stdout:
11 1 11 .
21 2 21 .
1. 3 1 .
1. 4 1 .
--- 5 11 .
name: comsub-1c 6 21 .
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.
--- ---
name: comsub-2 name: comsub-2
description: description:
@ -7732,16 +7720,16 @@ description:
Check the tree dump functions for !MKSH_SMALL functionality Check the tree dump functions for !MKSH_SMALL functionality
category: !smksh category: !smksh
stdin: 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 typeset -f x
expected-stdout: expected-stdout:
x() { x() {
case $1 in case $1 in
(a) (u)
a+=b echo x
;| ;|
(*) (*)
set -A c+ -- d e echo $1
;; ;;
esac esac
} }
@ -7844,6 +7832,8 @@ stdin:
install -c -o root -g wheel -m 664 /dev/null /etc/motd install -c -o root -g wheel -m 664 /dev/null /etc/motd
print -- "$x\n" >/etc/motd print -- "$x\n" >/etc/motd
fi fi
#wdarrassign
a+=b; c+=(d e)
#0 #0
EOD EOD
expected-stdout: expected-stdout:
@ -8409,6 +8399,25 @@ expected-stdout:
EOF 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 ) )" = @(?) ]] && 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 name: test-stnze-1
description: description:

4
sh.h
View File

@ -151,9 +151,9 @@
#endif #endif
#ifdef EXTERN #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 #endif
#define MKSH_VERSION "R40 2011/11/09" #define MKSH_VERSION "R40 2011/11/11"
#ifndef MKSH_INCLUDES_ONLY #ifndef MKSH_INCLUDES_ONLY

102
syn.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #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 short subshell_nesting_level;
extern void yyskiputf8bom(void); extern void yyskiputf8bom(void);
@ -232,13 +232,27 @@ nested(int type, int smark, int emark)
return (block(type, t, NOBLOCK, NOWORDS)); 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 * static struct op *
get_command(int cf) get_command(int cf)
{ {
struct op *t; struct op *t;
int c, iopn = 0, syniocf; int c, iopn = 0, syniocf, lno;
struct ioword *iop, **iops; struct ioword *iop, **iops;
XPtrV args, vars; XPtrV args, vars;
char *tcp;
struct nesting_state old_nesting; struct nesting_state old_nesting;
/* NUFILE is small enough to leave this addition unchecked */ /* NUFILE is small enough to leave this addition unchecked */
@ -292,18 +306,37 @@ get_command(int cf)
XPput(args, yylval.cp); XPput(args, yylval.cp);
break; break;
case '(': case '(' /*)*/:
#ifndef MKSH_SMALL if (XPsize(args) == 0 && XPsize(vars) == 1 &&
if ((XPsize(args) == 0 || Flag(FKEYWORD)) && is_wdvarassign(yylval.cp)) {
XPsize(vars) == 1 && is_wdvarassign(yylval.cp)) /* wdarrassign: foo=(bar) */
goto is_wdarrassign; ACCEPT;
#endif
/* 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 * Check for "> foo (echo hi)"
* allows (not POSIX, but not disallowed) * which AT&T ksh allows (not
* POSIX, but not disallowed)
*/ */
afree(t, ATEMP); afree(t, ATEMP);
if (XPsize(args) == 0 && XPsize(vars) == 0) { if (XPsize(args) == 0 &&
XPsize(vars) == 0) {
ACCEPT; ACCEPT;
goto Subshell; goto Subshell;
} }
@ -315,44 +348,8 @@ get_command(int cf)
ACCEPT; ACCEPT;
musthave(/*(*/')', 0); musthave(/*(*/')', 0);
t = function_body(XPptrv(args)[0], false); 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 goto Leave;
default: default:
goto Leave; goto Leave;
@ -372,13 +369,7 @@ get_command(int cf)
t = nested(TBRACE, '{', '}'); t = nested(TBRACE, '{', '}');
break; break;
case MDPAREN: { case MDPAREN:
int lno;
static const char let_cmd[] = {
CHAR, 'l', CHAR, 'e',
CHAR, 't', EOS
};
/* leave KEYWORD in syniocf (allow if (( 1 )) then ...) */ /* leave KEYWORD in syniocf (allow if (( 1 )) then ...) */
lno = source->line; lno = source->line;
ACCEPT; ACCEPT;
@ -395,7 +386,6 @@ get_command(int cf)
XPput(args, wdcopy(let_cmd, ATEMP)); XPput(args, wdcopy(let_cmd, ATEMP));
XPput(args, yylval.cp); XPput(args, yylval.cp);
break; break;
}
case DBRACKET: /* [[ .. ]] */ case DBRACKET: /* [[ .. ]] */
/* leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */ /* leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */

20
var.c
View File

@ -26,7 +26,7 @@
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #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 * Variables
@ -1379,29 +1379,23 @@ set_array(const char *var, bool reset, const char **vals)
{ {
struct tbl *vp, *vq; struct tbl *vp, *vq;
mksh_uari_t i = 0, j = 0; mksh_uari_t i = 0, j = 0;
const char *ccp; const char *ccp = var;
#ifndef MKSH_SMALL
char *cp = NULL; char *cp = NULL;
size_t n; size_t n;
#endif
/* to get local array, use "typeset foo; set -A foo" */ /* to get local array, use "typeset foo; set -A foo" */
#ifndef MKSH_SMALL
n = strlen(var); n = strlen(var);
if (n > 0 && var[n - 1] == '+') { if (n > 0 && var[n - 1] == '+') {
/* append mode */ /* append mode */
reset = false; reset = false;
strndupx(cp, var, n - 1, ATEMP); strndupx(cp, var, n - 1, ATEMP);
ccp = cp;
} }
#define CPORVAR (cp ? cp : var) vp = global(ccp);
#else
#define CPORVAR var
#endif
vp = global(CPORVAR);
/* Note: AT&T ksh allows set -A but not set +A of a read-only var */ /* Note: AT&T ksh allows set -A but not set +A of a read-only var */
if ((vp->flag&RDONLY)) 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 */ /* This code is quite non-optimal */
if (reset) if (reset)
/* trash existing values and attributes */ /* 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: * completely fail. Only really effects integer arrays:
* evaluation of some of vals[] may fail... * evaluation of some of vals[] may fail...
*/ */
#ifndef MKSH_SMALL
if (cp != NULL) { if (cp != NULL) {
/* find out where to set when appending */ /* find out where to set when appending */
for (vq = vp; vq; vq = vq->u.array) { 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); afree(cp, ATEMP);
} }
#endif
while ((ccp = vals[i])) { while ((ccp = vals[i])) {
#ifndef MKSH_SMALL
if (*ccp == '[') { if (*ccp == '[') {
int level = 0; int level = 0;
@ -1445,7 +1436,6 @@ set_array(const char *var, bool reset, const char **vals)
} else } else
ccp = vals[i]; ccp = vals[i];
} }
#endif
vq = arraysearch(vp, j); vq = arraysearch(vp, j);
/* would be nice to deal with errors here... (see above) */ /* would be nice to deal with errors here... (see above) */