1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * David Korn <dgk@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin /* 22*4887Schin * Shell arithmetic - uses streval library 23*4887Schin * David Korn 24*4887Schin * AT&T Labs 25*4887Schin */ 26*4887Schin 27*4887Schin #include "defs.h" 28*4887Schin #include <ctype.h> 29*4887Schin #include "lexstates.h" 30*4887Schin #include "name.h" 31*4887Schin #include "streval.h" 32*4887Schin #include "variables.h" 33*4887Schin 34*4887Schin #ifndef LLONG_MAX 35*4887Schin #define LLONG_MAX LONG_MAX 36*4887Schin #endif 37*4887Schin 38*4887Schin static Sfdouble_t Zero, NaN, Inf; 39*4887Schin static Namval_t Infnod = 40*4887Schin { 41*4887Schin { 0 }, 42*4887Schin "Inf", 43*4887Schin NV_NOFREE|NV_LDOUBLE,NV_RDONLY 44*4887Schin }; 45*4887Schin 46*4887Schin static Namval_t NaNnod = 47*4887Schin { 48*4887Schin { 0 }, 49*4887Schin "NaN", 50*4887Schin NV_NOFREE|NV_LDOUBLE,NV_RDONLY 51*4887Schin }; 52*4887Schin 53*4887Schin static Namval_t *scope(register Namval_t *np,register struct lval *lvalue,int assign) 54*4887Schin { 55*4887Schin register Namarr_t *ap; 56*4887Schin register int flag = lvalue->flag; 57*4887Schin register char *sub=0; 58*4887Schin if(lvalue->emode&ARITH_COMP) 59*4887Schin { 60*4887Schin char *cp = (char*)np; 61*4887Schin register Namval_t *mp; 62*4887Schin if(cp>=lvalue->expr && cp < lvalue->expr+lvalue->elen) 63*4887Schin { 64*4887Schin /* do bindiing to node now */ 65*4887Schin int c = cp[flag]; 66*4887Schin cp[flag] = 0; 67*4887Schin np = nv_open(cp,sh.var_tree,NV_NOASSIGN|NV_VARNAME); 68*4887Schin cp[flag] = c; 69*4887Schin if(cp[flag+1]=='[') 70*4887Schin flag++; 71*4887Schin else 72*4887Schin flag = 0; 73*4887Schin } 74*4887Schin else if(dtvnext(sh.var_tree) && (mp=nv_search((char*)np,sh.var_tree,HASH_NOSCOPE|HASH_SCOPE|HASH_BUCKET))) 75*4887Schin { 76*4887Schin while(nv_isref(mp)) 77*4887Schin { 78*4887Schin sub = nv_refsub(mp); 79*4887Schin mp = nv_refnode(mp); 80*4887Schin } 81*4887Schin np = mp; 82*4887Schin } 83*4887Schin } 84*4887Schin if(flag || sub) 85*4887Schin { 86*4887Schin if(!sub) 87*4887Schin sub = (char*)&lvalue->expr[flag]; 88*4887Schin if(((ap=nv_arrayptr(np)) && array_assoc(ap)) || (lvalue->emode&ARITH_COMP)) 89*4887Schin nv_endsubscript(np,sub,NV_ADD|NV_SUBQUOTE); 90*4887Schin else 91*4887Schin nv_putsub(np, NIL(char*),flag); 92*4887Schin } 93*4887Schin return(np); 94*4887Schin } 95*4887Schin 96*4887Schin static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdouble_t n) 97*4887Schin { 98*4887Schin register Sfdouble_t r= 0; 99*4887Schin char *str = (char*)*ptr; 100*4887Schin switch(type) 101*4887Schin { 102*4887Schin case ASSIGN: 103*4887Schin { 104*4887Schin register Namval_t *np = (Namval_t*)(lvalue->value); 105*4887Schin np = scope(np,lvalue,1); 106*4887Schin nv_putval(np, (char*)&n, NV_LDOUBLE); 107*4887Schin r=nv_getnum(np); 108*4887Schin break; 109*4887Schin } 110*4887Schin case LOOKUP: 111*4887Schin { 112*4887Schin register int c = *str; 113*4887Schin register char *xp=str; 114*4887Schin lvalue->value = (char*)0; 115*4887Schin if(c=='.') 116*4887Schin str++; 117*4887Schin c = mbchar(str); 118*4887Schin if(isaletter(c)) 119*4887Schin { 120*4887Schin register Namval_t *np; 121*4887Schin int dot=0; 122*4887Schin char *cp; 123*4887Schin while(1) 124*4887Schin { 125*4887Schin while(xp=str, c=mbchar(str), isaname(c)); 126*4887Schin str = xp; 127*4887Schin if(c!='.') 128*4887Schin break; 129*4887Schin dot=1; 130*4887Schin if((c = *++str) !='[') 131*4887Schin continue; 132*4887Schin str = nv_endsubscript((Namval_t*)0,cp=str,NV_SUBQUOTE)-1; 133*4887Schin if(sh_checkid(cp+1,(char*)0)) 134*4887Schin str -=2; 135*4887Schin } 136*4887Schin if(c=='(') 137*4887Schin { 138*4887Schin int fsize = str- (char*)(*ptr); 139*4887Schin const struct mathtab *tp; 140*4887Schin c = **ptr; 141*4887Schin lvalue->fun = 0; 142*4887Schin if(fsize<=(sizeof(tp->fname)-2)) for(tp=shtab_math; *tp->fname; tp++) 143*4887Schin { 144*4887Schin if(*tp->fname > c) 145*4887Schin break; 146*4887Schin if(tp->fname[1]==c && tp->fname[fsize+1]==0 && strncmp(&tp->fname[1],*ptr,fsize)==0) 147*4887Schin { 148*4887Schin lvalue->fun = tp->fnptr; 149*4887Schin lvalue->nargs = *tp->fname; 150*4887Schin break; 151*4887Schin } 152*4887Schin } 153*4887Schin if(lvalue->fun) 154*4887Schin break; 155*4887Schin lvalue->value = (char*)ERROR_dictionary(e_function); 156*4887Schin return(r); 157*4887Schin } 158*4887Schin if((lvalue->emode&ARITH_COMP) && dot) 159*4887Schin { 160*4887Schin lvalue->value = (char*)*ptr; 161*4887Schin lvalue->flag = str-lvalue->value; 162*4887Schin break; 163*4887Schin } 164*4887Schin *str = 0; 165*4887Schin if(sh_isoption(SH_NOEXEC)) 166*4887Schin np = L_ARGNOD; 167*4887Schin else 168*4887Schin { 169*4887Schin int offset = staktell(); 170*4887Schin char *saveptr = stakfreeze(0); 171*4887Schin Dt_t *root = (lvalue->emode&ARITH_COMP)?sh.var_base:sh.var_tree; 172*4887Schin *str = c; 173*4887Schin while(c=='[' || c=='.') 174*4887Schin { 175*4887Schin if(c=='[') 176*4887Schin { 177*4887Schin str = nv_endsubscript(np,cp=str,0); 178*4887Schin if((c= *str)!='[' && c!='.') 179*4887Schin { 180*4887Schin str = cp; 181*4887Schin c = '['; 182*4887Schin break; 183*4887Schin } 184*4887Schin } 185*4887Schin else 186*4887Schin { 187*4887Schin str++; 188*4887Schin while(xp=str, c=mbchar(str), isaname(c)); 189*4887Schin str = xp; 190*4887Schin } 191*4887Schin } 192*4887Schin *str = 0; 193*4887Schin if(strcasecmp(*ptr,"Inf")==0) 194*4887Schin { 195*4887Schin Inf = 1.0/Zero; 196*4887Schin Infnod.nvalue.ldp = &Inf; 197*4887Schin np = &Infnod; 198*4887Schin } 199*4887Schin else if(strcasecmp(*ptr,"NaN")==0) 200*4887Schin { 201*4887Schin NaN = 0.0/Zero; 202*4887Schin NaNnod.nvalue.ldp = &NaN; 203*4887Schin np = &NaNnod; 204*4887Schin } 205*4887Schin else 206*4887Schin np = nv_open(*ptr,root,NV_NOASSIGN|NV_VARNAME); 207*4887Schin if(saveptr != stakptr(0)) 208*4887Schin stakset(saveptr,offset); 209*4887Schin else 210*4887Schin stakseek(offset); 211*4887Schin } 212*4887Schin *str = c; 213*4887Schin lvalue->value = (char*)np; 214*4887Schin if((lvalue->emode&ARITH_COMP) || (nv_isarray(np) && nv_aindex(np)<0)) 215*4887Schin { 216*4887Schin /* bind subscript later */ 217*4887Schin lvalue->flag = 0; 218*4887Schin if(c=='[') 219*4887Schin { 220*4887Schin lvalue->flag = (str-lvalue->expr); 221*4887Schin do 222*4887Schin str = nv_endsubscript(np,str,0); 223*4887Schin while((c= *str)=='['); 224*4887Schin } 225*4887Schin break; 226*4887Schin } 227*4887Schin if(c=='[') 228*4887Schin { 229*4887Schin do 230*4887Schin str = nv_endsubscript(np,str,NV_ADD|NV_SUBQUOTE); 231*4887Schin while((c=*str)=='['); 232*4887Schin } 233*4887Schin else if(nv_isarray(np)) 234*4887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 235*4887Schin if(nv_isattr(np,NV_INTEGER|NV_DOUBLE)==(NV_INTEGER|NV_DOUBLE)) 236*4887Schin lvalue->isfloat=1; 237*4887Schin lvalue->flag = nv_aindex(np); 238*4887Schin } 239*4887Schin else 240*4887Schin { 241*4887Schin char lastbase=0, *val = xp, oerrno = errno; 242*4887Schin errno = 0; 243*4887Schin r = strtonll(val,&str, &lastbase,-1); 244*4887Schin if(*str=='8' || *str=='9') 245*4887Schin { 246*4887Schin lastbase=10; 247*4887Schin errno = 0; 248*4887Schin r = strtonll(val,&str, &lastbase,-1); 249*4887Schin } 250*4887Schin if(lastbase<=1) 251*4887Schin lastbase=10; 252*4887Schin if(*val=='0') 253*4887Schin { 254*4887Schin while(*val=='0') 255*4887Schin val++; 256*4887Schin if(*val==0 || *val=='.' || *val=='x' || *val=='X') 257*4887Schin val--; 258*4887Schin } 259*4887Schin if(r==LLONG_MAX && errno) 260*4887Schin c='e'; 261*4887Schin else 262*4887Schin c = *str; 263*4887Schin if(c==GETDECIMAL(0) || c=='e' || c == 'E') 264*4887Schin { 265*4887Schin lvalue->isfloat=1; 266*4887Schin r = strtold(val,&str); 267*4887Schin } 268*4887Schin else if(lastbase==10 && val[1]) 269*4887Schin { 270*4887Schin if(val[2]=='#') 271*4887Schin val += 3; 272*4887Schin if((str-val)>2*sizeof(Sflong_t)) 273*4887Schin { 274*4887Schin Sfdouble_t rr; 275*4887Schin rr = strtold(val,&str); 276*4887Schin if(rr!=r) 277*4887Schin { 278*4887Schin r = rr; 279*4887Schin lvalue->isfloat=1; 280*4887Schin } 281*4887Schin } 282*4887Schin } 283*4887Schin errno = oerrno; 284*4887Schin } 285*4887Schin break; 286*4887Schin } 287*4887Schin case VALUE: 288*4887Schin { 289*4887Schin register Namval_t *np = (Namval_t*)(lvalue->value); 290*4887Schin if(sh_isoption(SH_NOEXEC)) 291*4887Schin return(0); 292*4887Schin np = scope(np,lvalue,0); 293*4887Schin if(((lvalue->emode&2) || lvalue->level>1 || sh_isoption(SH_NOUNSET)) && nv_isnull(np) && !nv_isattr(np,NV_INTEGER)) 294*4887Schin { 295*4887Schin *ptr = nv_name(np); 296*4887Schin lvalue->value = (char*)ERROR_dictionary(e_notset); 297*4887Schin lvalue->emode |= 010; 298*4887Schin return(0); 299*4887Schin } 300*4887Schin r = nv_getnum(np); 301*4887Schin if(nv_isattr(np,NV_INTEGER|NV_BINARY)==(NV_INTEGER|NV_BINARY)) 302*4887Schin lvalue->isfloat= (r!=(Sflong_t)r); 303*4887Schin else if(nv_isattr(np,NV_INTEGER|NV_DOUBLE)==(NV_INTEGER|NV_DOUBLE)) 304*4887Schin lvalue->isfloat=1; 305*4887Schin return(r); 306*4887Schin } 307*4887Schin 308*4887Schin case MESSAGE: 309*4887Schin sfsync(NIL(Sfio_t*)); 310*4887Schin #if 0 311*4887Schin if(warn) 312*4887Schin errormsg(SH_DICT,ERROR_warn(0),lvalue->value,*ptr); 313*4887Schin else 314*4887Schin #endif 315*4887Schin errormsg(SH_DICT,ERROR_exit((lvalue->emode&3)!=0),lvalue->value,*ptr); 316*4887Schin } 317*4887Schin *ptr = str; 318*4887Schin return(r); 319*4887Schin } 320*4887Schin 321*4887Schin /* 322*4887Schin * convert number defined by string to a Sfdouble_t 323*4887Schin * ptr is set to the last character processed 324*4887Schin * if mode>0, an error will be fatal with value <mode> 325*4887Schin */ 326*4887Schin 327*4887Schin Sfdouble_t sh_strnum(register const char *str, char** ptr, int mode) 328*4887Schin { 329*4887Schin register Sfdouble_t d; 330*4887Schin char base=0, *last; 331*4887Schin if(*str==0) 332*4887Schin { 333*4887Schin if(ptr) 334*4887Schin *ptr = (char*)str; 335*4887Schin return(0); 336*4887Schin } 337*4887Schin errno = 0; 338*4887Schin d = strtonll(str,&last,&base,-1); 339*4887Schin if(*last || errno) 340*4887Schin { 341*4887Schin d = strval(str,&last,arith,mode); 342*4887Schin if(!ptr && *last && mode>0) 343*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str); 344*4887Schin } 345*4887Schin if(ptr) 346*4887Schin *ptr = last; 347*4887Schin return(d); 348*4887Schin } 349*4887Schin 350*4887Schin Sfdouble_t sh_arith(register const char *str) 351*4887Schin { 352*4887Schin return(sh_strnum(str, (char**)0, 1)); 353*4887Schin } 354*4887Schin 355*4887Schin void *sh_arithcomp(register char *str) 356*4887Schin { 357*4887Schin const char *ptr = str; 358*4887Schin Arith_t *ep; 359*4887Schin ep = arith_compile(str,(char**)&ptr,arith,ARITH_COMP|1); 360*4887Schin if(*ptr) 361*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*ptr,str); 362*4887Schin return((void*)ep); 363*4887Schin } 364