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: 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:

4
sh.h
View File

@ -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

126
syn.c
View File

@ -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 ...) */

20
var.c
View File

@ -26,7 +26,7 @@
#include <sys/sysctl.h>
#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) */