diff --git a/src/cmd/ksh93/bltins/enum.c b/src/cmd/ksh93/bltins/enum.c index f0732d29fe21..fe12a3736ceb 100644 --- a/src/cmd/ksh93/bltins/enum.c +++ b/src/cmd/ksh93/bltins/enum.c @@ -18,7 +18,7 @@ #include "shopt.h" #include "defs.h" -#define ENUM_ID "enum (ksh 93u+m) 2022-03-05" +#define ENUM_ID "enum (ksh 93u+m) 2024-11-28" const char sh_optenum[] = "[-?\n@(#)$Id: " ENUM_ID " $\n]" @@ -183,7 +183,7 @@ static void put_enum(Namval_t* np,const char *val,int flags,Namfun_t *fp) n = strcmp(v,val); if(n==0) { - nv_putv(np, (char*)&i, NV_UINT16, fp); + nv_putv(np, (char*)&i, NV_UINT16P, fp); return; } i++; @@ -260,7 +260,7 @@ int b_enum(int argc, char** argv, Shbltin_t *context) tp = nv_open(sfstruse(sh.strbuf), sh.var_tree, NV_VARNAME); n = sz; i = 0; - nv_onattr(tp, NV_UINT16); + nv_onattr(tp, NV_UINT16P); nv_putval(tp, (char*)&i, NV_INTEGER); nv_putsub(np, NULL, ARRAY_SCAN); do diff --git a/src/cmd/ksh93/include/streval.h b/src/cmd/ksh93/include/streval.h index 76cc2347375a..a1334d3881c8 100644 --- a/src/cmd/ksh93/include/streval.h +++ b/src/cmd/ksh93/include/streval.h @@ -70,7 +70,7 @@ struct lval char *ovalue; Sfdouble_t (*fun)(Sfdouble_t,...); const char *expr; - const void *ptr; + const void *enum_p; /* pointer to the lvalue's enum type */ int nosub; char *sub; short flag; @@ -78,7 +78,7 @@ struct lval short emode; short level; short elen; - char eflag; + char isenum; /* set if the lvalue is of an enum type */ char isfloat; }; diff --git a/src/cmd/ksh93/sh/arith.c b/src/cmd/ksh93/sh/arith.c index 0e22b3bd9295..b9e7f5e05133 100644 --- a/src/cmd/ksh93/sh/arith.c +++ b/src/cmd/ksh93/sh/arith.c @@ -251,9 +251,9 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl } } nv_putval(np, (char*)&n, NV_LDOUBLE); - if(lvalue->eflag) - lvalue->ptr = nv_hasdisc(np,&ENUM_disc); - lvalue->eflag = 0; + if(lvalue->isenum) + lvalue->enum_p = nv_hasdisc(np,&ENUM_disc); + lvalue->isenum = 0; lvalue->value = (char*)np; /* * The result (r) of an assignment is its value (n), cast to the type of the variable @@ -435,7 +435,7 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl else { char lastbase=0, *val = xp, oerrno = errno; - lvalue->eflag = 0; + lvalue->isenum = 0; errno = 0; r = strtonll(val,&str, &lastbase,-1); if(lastbase==8 && *val=='0' && !sh_isoption(sh.bltinfun==b_let ? SH_LETOCTAL : SH_POSIX)) @@ -504,20 +504,24 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl return 0; } lvalue->ovalue = (char*)np; - if(lvalue->eflag) - lvalue->ptr = nv_hasdisc(np,&ENUM_disc); - else if((Namfun_t*)lvalue->ptr && !nv_hasdisc(np,&ENUM_disc) && !nv_isattr(np,NV_INTEGER)) + if(lvalue->isenum) { + lvalue->enum_p = nv_hasdisc(np,&ENUM_disc); + lvalue->isenum = 0; + } + else if(lvalue->enum_p && !nv_hasdisc(np,&ENUM_disc) && !nv_isattr(np,NV_INTEGER)) + { + /* convert the enum rvalue of the lvalue's enum type to its number */ Namval_t *mp,node; - mp = ((Namfun_t*)lvalue->ptr)->type; + mp = ((Namfun_t*)lvalue->enum_p)->type; memset(&node,0,sizeof(node)); nv_clone(mp,&node,0); nv_offattr(&node,NV_RDONLY|NV_NOFREE); nv_putval(&node,np->nvname,0); - if(nv_isattr(&node,NV_NOFREE)) - return r=nv_getnum(&node); + r = nv_getnum(&node); + _nv_unset(&node,0); + return r; } - lvalue->eflag = 0; if(((lvalue->emode&2) || lvalue->level>1 || sh_isoption(SH_NOUNSET)) && nv_isnull(np) && !nv_isattr(np,NV_INTEGER)) { *ptr = nv_name(np); diff --git a/src/cmd/ksh93/sh/array.c b/src/cmd/ksh93/sh/array.c index e7022075e752..ed21d6c10483 100644 --- a/src/cmd/ksh93/sh/array.c +++ b/src/cmd/ksh93/sh/array.c @@ -1593,9 +1593,11 @@ char *nv_getsub(Namval_t* np) if(is_associative(ap)) return (char*)((*ap->header.fun)(np,NULL,NV_ANAME)); if(ap->xp) - { + { /* enum subscript */ np = nv_namptr(ap->xp,0); - np->nvalue.s = ap->cur; + if(!np->nvalue.sp) + np->nvalue.sp = malloc(sizeof(uint16_t)); + *((uint16_t*)np->nvalue.sp) = ap->cur; return nv_getval(np); } if((dot = ap->cur)==0) @@ -1755,11 +1757,11 @@ void *nv_associative(Namval_t *np,const char *sp,int mode) if(sh.subshell) sh_assignok(np,1); /* - * For enum types (NV_UINT16 with discipline ENUM_disc), nelem should not + * For enum types (NV_UINT16P with discipline ENUM_disc), nelem should not * increase or 'unset' will fail to completely unset such an array. */ if((!ap->header.scope || !nv_search(sp,dtvnext(ap->header.table),0)) - && !(type==NV_UINT16 && nv_hasdisc(np, &ENUM_disc))) + && !(type==NV_UINT16P && nv_hasdisc(np, &ENUM_disc))) ap->header.nelem++; if(nv_isnull(mp)) { diff --git a/src/cmd/ksh93/sh/streval.c b/src/cmd/ksh93/sh/streval.c index 0e9736cf1bcb..60b1fd186aff 100644 --- a/src/cmd/ksh93/sh/streval.c +++ b/src/cmd/ksh93/sh/streval.c @@ -162,8 +162,8 @@ Sfdouble_t arith_exec(Arith_t *ep) node.value = 0; node.nosub = 0; node.sub = 0; - node.ptr = 0; - node.eflag = 0; + node.enum_p = 0; + node.isenum = 0; if(sh.arithrecursion++ >= MAXLEVEL) { arith_error(e_recursive,ep->expr,ep->emode); @@ -266,7 +266,7 @@ Sfdouble_t arith_exec(Arith_t *ep) c = 0; break; case A_ENUM: - node.eflag = 1; + node.isenum = 1; continue; case A_ASSIGNOP: node.nosub = lastsub; @@ -282,10 +282,10 @@ Sfdouble_t arith_exec(Arith_t *ep) node.value = (char*)dp; node.flag = c; if(lastval) - node.eflag = 1; - node.ptr = 0; + node.isenum = 1; + node.enum_p = 0; num = (*ep->fun)(&ptr,&node,ASSIGN,num); - if(lastval && node.ptr) + if(lastval && node.enum_p) { Sfdouble_t r; node.flag = 0; @@ -479,7 +479,7 @@ Sfdouble_t arith_exec(Arith_t *ep) lastval = 0; if(c&T_BINARY) { - node.ptr = 0; + node.enum_p = 0; sp--,tp--; type |= (*tp!=0); } diff --git a/src/cmd/ksh93/tests/leaks.sh b/src/cmd/ksh93/tests/leaks.sh index ec882bbeba3c..086f75eebdd5 100755 --- a/src/cmd/ksh93/tests/leaks.sh +++ b/src/cmd/ksh93/tests/leaks.sh @@ -423,5 +423,13 @@ DO unset baz DONE +# ====== +TEST title='assigning and comparing enum rvalue in arithmetic' + enum Test1_t=(lorem ipsum dolor sit amet consectetur adipiscing elit curabitur scelerisque massa nec diam fermentum tempor) + Test1_t foo +DO + (((foo = amet) && foo == amet && foo != fermentum)) +DONE + # ====== exit $((Errors<125?Errors:125))