mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-13 11:42:21 +00:00
Fix arithmetic assignment operations for multidimensional indexed arrays (#296)
This PR corrects #168 for indexed arrays having more than one level. Turns out ksh was only keeping track of the subscript number for assignment in lvalue's nosub variable. By saving the actual subscript reference, the result can be assigned to its proper destination instead of putting the result into the last looked value or subscript location. src/cmd/ksh93/include/streval.h: struct lval: - Create a new pointer named sub to hold the reference that nosub describes. src/cmd/ksh93/sh/arith.c: arith(): - Adjust LOOKUP: for lvalue ARITH_ASSIGNOP operations on indexed arrays to save the np of the destination subscript for later use. - Adjust ASSIGN: to act when lvalue's nosub > 0 which happens as the last step in the arithmetic parsing loop for assignment operations. Only indexed arrays will have a nosub value > 0. All others have a nosub of 0 unless they are involved in a unary operation (++, --) which sets nosub to -1. All said in the context of assignment operations like (( arr[0][1] += 1 )). src/cmd/ksh93/sh/streval.c: - Initialize the new sub pointer to 0. src/cmd/ksh93/tests/arrays2.sh: - Created a few multidimensional indexed array tests for assignment operations like += as an example. Resolves: https://github.com/ksh93/ksh/issues/168
This commit is contained in:
parent
d309d604e7
commit
642a105351
5 changed files with 38 additions and 3 deletions
2
NEWS
2
NEWS
|
@ -23,6 +23,8 @@ Any uppercase BUG_* names are modernish shell bug IDs.
|
|||
of declaration built-ins. This reverts a change introduced on 2020-09-11.
|
||||
[*] https://austingroupbugs.net/view.php?id=1393
|
||||
|
||||
- Fixed arithmetic assignment operations for multidimensional indexed arrays
|
||||
|
||||
2021-04-30:
|
||||
|
||||
- The emacs 'ESC .' (M-.) and vi '_' commands now take shell quoting into
|
||||
|
|
|
@ -76,6 +76,7 @@ struct lval
|
|||
const char *expr;
|
||||
const void *ptr;
|
||||
int nosub;
|
||||
char *sub;
|
||||
short flag;
|
||||
short nargs;
|
||||
short emode;
|
||||
|
|
|
@ -233,8 +233,17 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl
|
|||
{
|
||||
case ASSIGN:
|
||||
{
|
||||
register Namval_t *np = (Namval_t*)(lvalue->value);
|
||||
register Namval_t *np;
|
||||
if (lvalue->nosub > 0 && lvalue->sub) /* indexed array ARITH_ASSIGNOP */
|
||||
{
|
||||
np = (Namval_t*)lvalue->sub; /* use saved subscript reference instead of last worked value */
|
||||
nv_putsub(np, NIL(char*), lvalue->nosub-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
np = (Namval_t*)lvalue->value;
|
||||
np = scope(np, lvalue, 1);
|
||||
}
|
||||
nv_putval(np, (char*)&n, NV_LDOUBLE);
|
||||
if(lvalue->eflag)
|
||||
lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
|
||||
|
@ -494,7 +503,10 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl
|
|||
else if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
|
||||
lvalue->isfloat=1;
|
||||
if((lvalue->emode&ARITH_ASSIGNOP) && nv_isarray(np))
|
||||
lvalue->nosub = nv_aindex(np)+1;
|
||||
{
|
||||
lvalue->nosub = nv_aindex(np)+1; /* subscript number of array */
|
||||
lvalue->sub = (char*)np; /* store subscript reference for upcoming iteration of ASSIGN */
|
||||
}
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
|
|
@ -172,6 +172,7 @@ Sfdouble_t arith_exec(Arith_t *ep)
|
|||
node.elen = ep->elen;
|
||||
node.value = 0;
|
||||
node.nosub = 0;
|
||||
node.sub = 0;
|
||||
node.ptr = 0;
|
||||
node.eflag = 0;
|
||||
if(shp->arithrecursion++ >= MAXLEVEL)
|
||||
|
|
|
@ -240,5 +240,24 @@ foo
|
|||
EOF
|
||||
$SHELL "$multiarray_unset" > /dev/null || err_exit 'Multidimensional arrays with an unset method crash ksh'
|
||||
|
||||
# ======
|
||||
# Multidimensional indexed array arithmetic assignment operation tests
|
||||
ini() { unset arr; typeset -a arr=((10 20) 6 8); }
|
||||
[[ $( ini; ((arr[0][0]+=1)); typeset -p arr) == 'typeset -a arr=((11 20) 6 8)' ]] || err_exit 'ASSIGNOP: arr[0][0]+=1 failed.'
|
||||
[[ $( ini; ((arr[0][1]+=1)); typeset -p arr) == 'typeset -a arr=((10 21) 6 8)' ]] || err_exit 'ASSIGNOP: arr[0][1]+=1 failed.'
|
||||
[[ $( ini; ((arr[0][2]+=1)); typeset -p arr) == 'typeset -a arr=((10 20 1) 6 8)' ]] || err_exit 'ASSIGNOP: arr[0][2]+=1 failed.'
|
||||
[[ $( ini; ((arr[0][1]+=arr[1])); typeset -p arr) == 'typeset -a arr=((10 26) 6 8)' ]] || err_exit 'ASSIGNOP: arr[0][1]+=arr[1] failed.'
|
||||
[[ $( ini; ((arr[0][2]+=arr[1])); typeset -p arr) == 'typeset -a arr=((10 20 6) 6 8)' ]] || err_exit 'ASSIGNOP: arr[0][2]+=arr[1] failed.'
|
||||
[[ $( ini; ((arr[1]+=1)); typeset -p arr) == 'typeset -a arr=((10 20) 7 8)' ]] || err_exit 'ASSIGNOP: arr[1]+=1 failed.'
|
||||
[[ $( ini; ((arr[2]+=1)); typeset -p arr) == 'typeset -a arr=((10 20) 6 9)' ]] || err_exit 'ASSIGNOP: arr[2]+=1 failed.'
|
||||
[[ $( ini; ((arr[3]+=1)); typeset -p arr) == 'typeset -a arr=((10 20) 6 8 1)' ]] || err_exit 'ASSIGNOP: arr[3]+=1 failed.'
|
||||
[[ $( ini; ((arr[1]+=arr[0][0])); typeset -p arr) == 'typeset -a arr=((10 20) 16 8)' ]] || err_exit 'ASSIGNOP: arr[1]+=arr[0][0] failed.'
|
||||
[[ $( ini; ((arr[1]+=arr[0][1])); typeset -p arr) == 'typeset -a arr=((10 20) 26 8)' ]] || err_exit 'ASSIGNOP: arr[1]+=arr[0][1] failed.'
|
||||
[[ $( ini; ((arr[2]+=arr[0][0])); typeset -p arr) == 'typeset -a arr=((10 20) 6 18)' ]] || err_exit 'ASSIGNOP: arr[2]+=arr[0][0] failed.'
|
||||
[[ $( ini; ((arr[2]+=arr[0][1])); typeset -p arr) == 'typeset -a arr=((10 20) 6 28)' ]] || err_exit 'ASSIGNOP: arr[2]+=arr[0][1] failed.'
|
||||
[[ $( ini; ((arr[3]+=arr[0][1])); typeset -p arr) == 'typeset -a arr=((10 20) 6 8 20)' ]] || err_exit 'ASSIGNOP: arr[2]+=arr[0][1] failed.'
|
||||
unset arr
|
||||
unset -f ini
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
Loading…
Reference in a new issue