1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 03:32:24 +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:
hyenias 2021-05-03 22:13:14 -04:00 committed by GitHub
parent d309d604e7
commit 642a105351
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 3 deletions

2
NEWS
View file

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

View file

@ -76,6 +76,7 @@ struct lval
const char *expr;
const void *ptr;
int nosub;
char *sub;
short flag;
short nargs;
short emode;

View file

@ -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);
np = scope(np,lvalue,1);
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);
}

View file

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

View file

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