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 * AT&T Labs 23*4887Schin * 24*4887Schin */ 25*4887Schin 26*4887Schin #define putenv ___putenv 27*4887Schin 28*4887Schin #include "defs.h" 29*4887Schin #include <ctype.h> 30*4887Schin #include "variables.h" 31*4887Schin #include "path.h" 32*4887Schin #include "lexstates.h" 33*4887Schin #include "timeout.h" 34*4887Schin #include "FEATURE/externs" 35*4887Schin #include "streval.h" 36*4887Schin 37*4887Schin static char *savesub = 0; 38*4887Schin 39*4887Schin #if !_lib_pathnative && _lib_uwin_path 40*4887Schin 41*4887Schin #define _lib_pathnative 1 42*4887Schin 43*4887Schin extern int uwin_path(const char*, char*, int); 44*4887Schin 45*4887Schin size_t 46*4887Schin pathnative(const char* path, char* buf, size_t siz) 47*4887Schin { 48*4887Schin return uwin_path(path, buf, siz); 49*4887Schin } 50*4887Schin 51*4887Schin #endif /* _lib_pathnative */ 52*4887Schin 53*4887Schin static void attstore(Namval_t*,void*); 54*4887Schin #ifndef _ENV_H 55*4887Schin static void pushnam(Namval_t*,void*); 56*4887Schin static char *staknam(Namval_t*, char*); 57*4887Schin #endif 58*4887Schin static void ltou(const char*,char*); 59*4887Schin static void rightjust(char*, int, int); 60*4887Schin 61*4887Schin struct adata 62*4887Schin { 63*4887Schin char **argnam; 64*4887Schin int attsize; 65*4887Schin char *attval; 66*4887Schin }; 67*4887Schin 68*4887Schin char nv_local = 0; 69*4887Schin #ifndef _ENV_H 70*4887Schin static void(*nullscan)(Namval_t*,void*); 71*4887Schin #endif 72*4887Schin 73*4887Schin #if ( SFIO_VERSION <= 20010201L ) 74*4887Schin # define _data data 75*4887Schin #endif 76*4887Schin 77*4887Schin #if !SHOPT_MULTIBYTE 78*4887Schin # define mbchar(p) (*(unsigned char*)p++) 79*4887Schin #endif /* SHOPT_MULTIBYTE */ 80*4887Schin 81*4887Schin /* ======== name value pair routines ======== */ 82*4887Schin 83*4887Schin #include "shnodes.h" 84*4887Schin #include "builtins.h" 85*4887Schin 86*4887Schin static char *getbuf(size_t len) 87*4887Schin { 88*4887Schin static char *buf; 89*4887Schin static size_t buflen; 90*4887Schin if(buflen < len) 91*4887Schin { 92*4887Schin if(buflen==0) 93*4887Schin buf = (char*)malloc(len); 94*4887Schin else 95*4887Schin buf = (char*)realloc(buf,len); 96*4887Schin buflen = len; 97*4887Schin } 98*4887Schin return(buf); 99*4887Schin } 100*4887Schin 101*4887Schin #ifdef _ENV_H 102*4887Schin void sh_envput(Env_t* ep,Namval_t *np) 103*4887Schin { 104*4887Schin int offset = staktell(); 105*4887Schin Namarr_t *ap = nv_arrayptr(np); 106*4887Schin char *val; 107*4887Schin if(ap) 108*4887Schin { 109*4887Schin if(ap->nelem&ARRAY_UNDEF) 110*4887Schin nv_putsub(np,"0",0L); 111*4887Schin else if(!(val=nv_getsub(np)) || strcmp(val,"0")) 112*4887Schin return; 113*4887Schin } 114*4887Schin if(!(val = nv_getval(np))) 115*4887Schin return; 116*4887Schin stakputs(nv_name(np)); 117*4887Schin stakputc('='); 118*4887Schin stakputs(val); 119*4887Schin stakseek(offset); 120*4887Schin env_add(ep,stakptr(offset),ENV_STRDUP); 121*4887Schin } 122*4887Schin #endif 123*4887Schin 124*4887Schin /* 125*4887Schin * output variable name in format for re-input 126*4887Schin */ 127*4887Schin void nv_outname(Sfio_t *out, char *name, int len) 128*4887Schin { 129*4887Schin const char *cp=name, *sp; 130*4887Schin int c, offset = staktell(); 131*4887Schin while(sp= strchr(cp,'[')) 132*4887Schin { 133*4887Schin if(len>0 && cp+len <= sp) 134*4887Schin break; 135*4887Schin sfwrite(out,cp,++sp-cp); 136*4887Schin stakseek(offset); 137*4887Schin for(; c= *sp; sp++) 138*4887Schin { 139*4887Schin if(c==']') 140*4887Schin break; 141*4887Schin else if(c=='\\') 142*4887Schin { 143*4887Schin if(*sp=='[' || *sp==']' || *sp=='\\') 144*4887Schin c = *sp++; 145*4887Schin } 146*4887Schin stakputc(c); 147*4887Schin } 148*4887Schin stakputc(0); 149*4887Schin sfputr(out,sh_fmtq(stakptr(offset)),-1); 150*4887Schin if(len>0) 151*4887Schin { 152*4887Schin sfputc(out,']'); 153*4887Schin return; 154*4887Schin } 155*4887Schin cp = sp; 156*4887Schin } 157*4887Schin if(*cp) 158*4887Schin { 159*4887Schin if(len>0) 160*4887Schin sfwrite(out,cp,len); 161*4887Schin else 162*4887Schin sfputr(out,cp,-1); 163*4887Schin } 164*4887Schin stakseek(offset); 165*4887Schin } 166*4887Schin 167*4887Schin /* 168*4887Schin * Perform parameter assignment for a linked list of parameters 169*4887Schin * <flags> contains attributes for the parameters 170*4887Schin */ 171*4887Schin void nv_setlist(register struct argnod *arg,register int flags) 172*4887Schin { 173*4887Schin register char *cp; 174*4887Schin register Namval_t *np; 175*4887Schin char *trap=sh.st.trap[SH_DEBUGTRAP]; 176*4887Schin int traceon = (sh_isoption(SH_XTRACE)!=0); 177*4887Schin int array = (flags&(NV_ARRAY|NV_IARRAY)); 178*4887Schin flags &= ~(NV_TYPE|NV_ARRAY); 179*4887Schin if(sh_isoption(SH_ALLEXPORT)) 180*4887Schin flags |= NV_EXPORT; 181*4887Schin if(sh.prefix) 182*4887Schin { 183*4887Schin flags &= ~(NV_IDENT|NV_EXPORT); 184*4887Schin flags |= NV_VARNAME; 185*4887Schin } 186*4887Schin for(;arg; arg=arg->argnxt.ap) 187*4887Schin { 188*4887Schin sh.used_pos = 0; 189*4887Schin if(arg->argflag&ARG_MAC) 190*4887Schin cp = sh_mactrim(arg->argval,-1); 191*4887Schin else 192*4887Schin { 193*4887Schin Namval_t *mp; 194*4887Schin stakseek(0); 195*4887Schin if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED))) 196*4887Schin { 197*4887Schin int flag = (NV_VARNAME|NV_ARRAY|NV_ASSIGN); 198*4887Schin struct fornod *fp=(struct fornod*)arg->argchn.ap; 199*4887Schin register Shnode_t *tp=fp->fortre; 200*4887Schin char *prefix = sh.prefix; 201*4887Schin flag |= (flags&NV_NOSCOPE); 202*4887Schin if(arg->argflag&ARG_QUOTED) 203*4887Schin cp = sh_mactrim(fp->fornam,-1); 204*4887Schin else 205*4887Schin cp = fp->fornam; 206*4887Schin error_info.line = fp->fortyp-sh.st.firstline; 207*4887Schin if(sh.fn_depth && (Namval_t*)tp->com.comnamp==SYSTYPESET) 208*4887Schin flag |= NV_NOSCOPE; 209*4887Schin if(prefix && tp->com.comset && *cp=='[') 210*4887Schin { 211*4887Schin sh.prefix = 0; 212*4887Schin np = nv_open(prefix,sh.var_tree,flag); 213*4887Schin sh.prefix = prefix; 214*4887Schin if(np) 215*4887Schin { 216*4887Schin if(!nv_isarray(np)) 217*4887Schin { 218*4887Schin stakputc('.'); 219*4887Schin stakputs(cp); 220*4887Schin cp = stakfreeze(1); 221*4887Schin } 222*4887Schin nv_close(np); 223*4887Schin } 224*4887Schin } 225*4887Schin np = nv_open(cp,sh.var_tree,flag); 226*4887Schin if(array) 227*4887Schin { 228*4887Schin if(!(flags&NV_APPEND)) 229*4887Schin nv_unset(np); 230*4887Schin if(array&NV_ARRAY) 231*4887Schin { 232*4887Schin nv_setarray(np,nv_associative); 233*4887Schin } 234*4887Schin else 235*4887Schin { 236*4887Schin nv_onattr(np,NV_ARRAY); 237*4887Schin } 238*4887Schin } 239*4887Schin /* check for array assignment */ 240*4887Schin if(tp->tre.tretyp!=TLST && tp->com.comarg && !tp->com.comset && !((mp=tp->com.comnamp) && nv_isattr(mp,BLT_DCL))) 241*4887Schin { 242*4887Schin int argc; 243*4887Schin char **argv = sh_argbuild(&argc,&tp->com,0); 244*4887Schin if(!(arg->argflag&ARG_APPEND)) 245*4887Schin { 246*4887Schin nv_unset(np); 247*4887Schin } 248*4887Schin nv_setvec(np,(arg->argflag&ARG_APPEND),argc,argv); 249*4887Schin if(traceon || trap) 250*4887Schin { 251*4887Schin int n = -1; 252*4887Schin char *name = nv_name(np); 253*4887Schin if(arg->argflag&ARG_APPEND) 254*4887Schin n = '+'; 255*4887Schin if(trap) 256*4887Schin sh_debug(trap,name,(char*)0,argv,(arg->argflag&ARG_APPEND)|ARG_ASSIGN); 257*4887Schin if(traceon) 258*4887Schin { 259*4887Schin sh_trace(NIL(char**),0); 260*4887Schin sfputr(sfstderr,name,n); 261*4887Schin sfwrite(sfstderr,"=( ",3); 262*4887Schin while(cp= *argv++) 263*4887Schin sfputr(sfstderr,sh_fmtq(cp),' '); 264*4887Schin sfwrite(sfstderr,")\n",2); 265*4887Schin } 266*4887Schin } 267*4887Schin continue; 268*4887Schin } 269*4887Schin if(tp->tre.tretyp==TLST || !tp->com.comset || tp->com.comset->argval[0]!='[') 270*4887Schin { 271*4887Schin if(*cp!='.' && *cp!='[' && strchr(cp,'[')) 272*4887Schin { 273*4887Schin nv_close(np); 274*4887Schin np = nv_open(cp,sh.var_tree,flag); 275*4887Schin } 276*4887Schin if((arg->argflag&ARG_APPEND) && !nv_isarray(np)) 277*4887Schin nv_unset(np); 278*4887Schin } 279*4887Schin else 280*4887Schin { 281*4887Schin if(sh_isoption(SH_BASH) || (array&NV_IARRAY)) 282*4887Schin { 283*4887Schin if(!(arg->argflag&ARG_APPEND)) 284*4887Schin nv_unset(np); 285*4887Schin } 286*4887Schin else if((arg->argflag&ARG_APPEND) && (!nv_isarray(np) || (nv_aindex(np)>=0))) 287*4887Schin { 288*4887Schin nv_unset(np); 289*4887Schin nv_setarray(np,nv_associative); 290*4887Schin } 291*4887Schin else 292*4887Schin nv_setarray(np,nv_associative); 293*4887Schin } 294*4887Schin if(prefix) 295*4887Schin cp = stakcopy(nv_name(np)); 296*4887Schin sh.prefix = cp; 297*4887Schin sh_exec(tp,sh_isstate(SH_ERREXIT)); 298*4887Schin sh.prefix = prefix; 299*4887Schin if(nv_isarray(np) && (mp=nv_opensub(np))) 300*4887Schin np = mp; 301*4887Schin nv_setvtree(np); 302*4887Schin continue; 303*4887Schin } 304*4887Schin cp = arg->argval; 305*4887Schin } 306*4887Schin if(sh.prefix && *cp=='.' && cp[1]=='=') 307*4887Schin cp++; 308*4887Schin np = nv_open(cp,sh.var_tree,flags); 309*4887Schin if(!np->nvfun) 310*4887Schin { 311*4887Schin if(sh.used_pos) 312*4887Schin nv_onattr(np,NV_PARAM); 313*4887Schin else 314*4887Schin nv_offattr(np,NV_PARAM); 315*4887Schin } 316*4887Schin if(traceon || trap) 317*4887Schin { 318*4887Schin register char *sp=cp; 319*4887Schin char *name=nv_name(np); 320*4887Schin char *sub=0; 321*4887Schin int append = 0; 322*4887Schin if(nv_isarray(np)) 323*4887Schin sub = savesub; 324*4887Schin if(cp=strchr(sp,'=')) 325*4887Schin { 326*4887Schin if(cp[-1]=='+') 327*4887Schin append = ARG_APPEND; 328*4887Schin cp++; 329*4887Schin } 330*4887Schin if(traceon) 331*4887Schin { 332*4887Schin sh_trace(NIL(char**),0); 333*4887Schin nv_outname(sfstderr,name,-1); 334*4887Schin if(sub) 335*4887Schin sfprintf(sfstderr,"[%s]",sh_fmtq(sub)); 336*4887Schin if(cp) 337*4887Schin { 338*4887Schin if(append) 339*4887Schin sfputc(sfstderr,'+'); 340*4887Schin sfprintf(sfstderr,"=%s\n",sh_fmtq(cp)); 341*4887Schin } 342*4887Schin } 343*4887Schin if(trap) 344*4887Schin { 345*4887Schin char *av[2]; 346*4887Schin av[0] = cp; 347*4887Schin av[1] = 0; 348*4887Schin sh_debug(trap,name,sub,av,append); 349*4887Schin } 350*4887Schin } 351*4887Schin } 352*4887Schin } 353*4887Schin 354*4887Schin /* 355*4887Schin * copy the subscript onto the stack 356*4887Schin */ 357*4887Schin static void stak_subscript(const char *sub, int last) 358*4887Schin { 359*4887Schin register int c; 360*4887Schin stakputc('['); 361*4887Schin while(c= *sub++) 362*4887Schin { 363*4887Schin if(c=='[' || c==']' || c=='\\') 364*4887Schin stakputc('\\'); 365*4887Schin stakputc(c); 366*4887Schin } 367*4887Schin stakputc(last); 368*4887Schin } 369*4887Schin 370*4887Schin /* 371*4887Schin * construct a new name from a prefix and base name on the stack 372*4887Schin */ 373*4887Schin static char *copystack(const char *prefix, register const char *name, const char *sub) 374*4887Schin { 375*4887Schin register int last=0,offset = staktell(); 376*4887Schin if(prefix) 377*4887Schin { 378*4887Schin stakputs(prefix); 379*4887Schin if(*stakptr(staktell()-1)=='.') 380*4887Schin stakseek(staktell()-1); 381*4887Schin if(*name=='.' && name[1]=='[') 382*4887Schin last = staktell()+2; 383*4887Schin if(*name!='[' && *name!='.' && *name!='=' && *name!='+') 384*4887Schin stakputc('.'); 385*4887Schin } 386*4887Schin if(last) 387*4887Schin { 388*4887Schin stakputs(name); 389*4887Schin if(sh_checkid(stakptr(last),(char*)0)) 390*4887Schin stakseek(staktell()-2); 391*4887Schin } 392*4887Schin if(sub) 393*4887Schin stak_subscript(sub,']'); 394*4887Schin if(!last) 395*4887Schin stakputs(name); 396*4887Schin stakputc(0); 397*4887Schin return(stakptr(offset)); 398*4887Schin } 399*4887Schin 400*4887Schin /* 401*4887Schin * grow this stack string <name> by <n> bytes and move from cp-1 to end 402*4887Schin * right by <n>. Returns beginning of string on the stack 403*4887Schin */ 404*4887Schin static char *stack_extend(const char *cname, char *cp, int n) 405*4887Schin { 406*4887Schin register char *name = (char*)cname; 407*4887Schin int offset = name - stakptr(0); 408*4887Schin int m = cp-name; 409*4887Schin stakseek(strlen(name)+n+1); 410*4887Schin name = stakptr(offset); 411*4887Schin cp = name + m; 412*4887Schin m = strlen(cp)+1; 413*4887Schin while(m-->0) 414*4887Schin cp[n+m]=cp[m]; 415*4887Schin return((char*)name); 416*4887Schin } 417*4887Schin 418*4887Schin Namval_t *nv_create(const char *name, Dt_t *root, int flags, Namfun_t *dp) 419*4887Schin { 420*4887Schin char *cp=(char*)name, *sp, *xp; 421*4887Schin register int c; 422*4887Schin register Namval_t *np=0, *nq=0; 423*4887Schin Namfun_t *fp=0; 424*4887Schin long mode, add=0; 425*4887Schin int copy=1,isref,top=0,noscope=(flags&NV_NOSCOPE); 426*4887Schin if(root==sh.var_tree) 427*4887Schin { 428*4887Schin if(dtvnext(root)) 429*4887Schin top = 1; 430*4887Schin else 431*4887Schin flags &= ~NV_NOSCOPE; 432*4887Schin } 433*4887Schin if(!dp->disc) 434*4887Schin copy = dp->nofree; 435*4887Schin if(*cp=='.') 436*4887Schin cp++; 437*4887Schin while(1) 438*4887Schin { 439*4887Schin switch(c = *(unsigned char*)(sp = cp)) 440*4887Schin { 441*4887Schin case '[': 442*4887Schin if(flags&NV_NOARRAY) 443*4887Schin { 444*4887Schin dp->last = cp; 445*4887Schin return(np); 446*4887Schin } 447*4887Schin cp = nv_endsubscript((Namval_t*)0,sp,0); 448*4887Schin if(sp==name || sp[-1]=='.') 449*4887Schin c = *(sp = cp); 450*4887Schin goto skip; 451*4887Schin case '.': 452*4887Schin if(flags&NV_IDENT) 453*4887Schin return(0); 454*4887Schin if(root==sh.var_tree) 455*4887Schin flags &= ~NV_EXPORT; 456*4887Schin if(!copy && !(flags&NV_NOREF)) 457*4887Schin { 458*4887Schin c = sp-name; 459*4887Schin copy = cp-name; 460*4887Schin dp->nofree = 1; 461*4887Schin name = copystack((const char*)0, name,(const char*)0); 462*4887Schin cp = (char*)name+copy; 463*4887Schin sp = (char*)name+c; 464*4887Schin c = '.'; 465*4887Schin } 466*4887Schin skip: 467*4887Schin case '+': 468*4887Schin case '=': 469*4887Schin *sp = 0; 470*4887Schin case 0: 471*4887Schin isref = 0; 472*4887Schin dp->last = cp; 473*4887Schin mode = (c=='.' || (flags&NV_NOADD))?add:NV_ADD; 474*4887Schin if(flags&NV_NOSCOPE) 475*4887Schin mode |= HASH_NOSCOPE; 476*4887Schin if(top) 477*4887Schin nq = nv_search(name,sh.var_base,0); 478*4887Schin if(np = nv_search(name,root,mode)) 479*4887Schin { 480*4887Schin isref = nv_isref(np); 481*4887Schin if(top) 482*4887Schin { 483*4887Schin if(nq==np) 484*4887Schin flags &= ~NV_NOSCOPE; 485*4887Schin else if(nq) 486*4887Schin { 487*4887Schin if(nv_isnull(np) && c!='.' && (np->nvfun=nv_cover(nq))) 488*4887Schin np->nvname = nq->nvname; 489*4887Schin flags |= NV_NOSCOPE; 490*4887Schin } 491*4887Schin } 492*4887Schin else if(add && nv_isnull(np) && c=='.') 493*4887Schin nv_setvtree(np); 494*4887Schin } 495*4887Schin if(c) 496*4887Schin *sp = c; 497*4887Schin top = 0; 498*4887Schin if(isref) 499*4887Schin { 500*4887Schin char *sub=0; 501*4887Schin if(c=='.') /* don't optimize */ 502*4887Schin sh.argaddr = 0; 503*4887Schin else if(flags&NV_NOREF) 504*4887Schin { 505*4887Schin if(c) 506*4887Schin nv_unref(np); 507*4887Schin return(np); 508*4887Schin } 509*4887Schin while(nv_isref(np)) 510*4887Schin { 511*4887Schin root = nv_reftree(np); 512*4887Schin sh.last_table = nv_reftable(np); 513*4887Schin sub = nv_refsub(np); 514*4887Schin np = nv_refnode(np); 515*4887Schin if(sub && c!='.') 516*4887Schin nv_putsub(np,sub,0L); 517*4887Schin flags |= NV_NOSCOPE; 518*4887Schin } 519*4887Schin if(sub && c==0) 520*4887Schin return(np); 521*4887Schin if(np==nq) 522*4887Schin flags &= ~(noscope?0:NV_NOSCOPE); 523*4887Schin else if(c) 524*4887Schin { 525*4887Schin c = (cp-sp); 526*4887Schin copy = strlen(cp=nv_name(np)); 527*4887Schin dp->nofree = 1; 528*4887Schin name = copystack(cp,sp,sub); 529*4887Schin sp = (char*)name + copy; 530*4887Schin cp = sp+c; 531*4887Schin c = *sp; 532*4887Schin if(!noscope) 533*4887Schin flags &= ~NV_NOSCOPE; 534*4887Schin } 535*4887Schin flags |= NV_NOREF; 536*4887Schin } 537*4887Schin sh.last_root = root; 538*4887Schin do 539*4887Schin { 540*4887Schin if(!np) 541*4887Schin { 542*4887Schin if(*sp=='[' && *cp==0 && cp[-1]==']') 543*4887Schin { 544*4887Schin /* 545*4887Schin * for backward compatibility 546*4887Schin * evaluate subscript for 547*4887Schin * possible side effects 548*4887Schin */ 549*4887Schin cp[-1] = 0; 550*4887Schin sh_arith(sp+1); 551*4887Schin cp[-1] = ']'; 552*4887Schin } 553*4887Schin return(np); 554*4887Schin } 555*4887Schin if(c=='[' || (c=='.' && nv_isarray(np))) 556*4887Schin { 557*4887Schin int n = 0; 558*4887Schin if(c=='[') 559*4887Schin { 560*4887Schin n = mode|nv_isarray(np); 561*4887Schin if(!mode && (flags&NV_ARRAY) && ((c=sp[1])=='*' || c=='@') && sp[2]==']') 562*4887Schin { 563*4887Schin /* not implemented yet */ 564*4887Schin dp->last = cp; 565*4887Schin return(np); 566*4887Schin } 567*4887Schin if(n&&(flags&NV_ARRAY)) 568*4887Schin n |= ARRAY_FILL; 569*4887Schin cp = nv_endsubscript(np,sp,n); 570*4887Schin } 571*4887Schin else 572*4887Schin cp = sp; 573*4887Schin if((c = *cp)=='.' || c=='[' || (n&ARRAY_FILL)) 574*4887Schin 575*4887Schin { 576*4887Schin int m = cp-sp; 577*4887Schin char *sub = m?nv_getsub(np):0; 578*4887Schin if(!sub) 579*4887Schin sub = "0"; 580*4887Schin n = strlen(sub)+2; 581*4887Schin if(!copy) 582*4887Schin { 583*4887Schin copy = cp-name; 584*4887Schin dp->nofree = 1; 585*4887Schin name = copystack((const char*)0, name,(const char*)0); 586*4887Schin cp = (char*)name+copy; 587*4887Schin sp = cp-m; 588*4887Schin } 589*4887Schin if(n <= m) 590*4887Schin { 591*4887Schin if(n) 592*4887Schin { 593*4887Schin memcpy(sp+1,sub,n-2); 594*4887Schin sp[n-1] = ']'; 595*4887Schin } 596*4887Schin if(n < m) 597*4887Schin cp=strcpy(sp+n,cp); 598*4887Schin } 599*4887Schin else 600*4887Schin { 601*4887Schin int r = n-m; 602*4887Schin m = sp-name; 603*4887Schin name = stack_extend(name, cp-1, r); 604*4887Schin sp = (char*)name + m; 605*4887Schin *sp = '['; 606*4887Schin memcpy(sp+1,sub,n-2); 607*4887Schin sp[n-1] = ']'; 608*4887Schin cp = sp+n; 609*4887Schin 610*4887Schin } 611*4887Schin } 612*4887Schin else if(c==0 && mode && (n=nv_aindex(np))>0) 613*4887Schin nv_putsub(np,(char*)0,n|ARRAY_FILL); 614*4887Schin else if(n==0 && c==0) 615*4887Schin { 616*4887Schin /* subscript must be 0*/ 617*4887Schin cp[-1] = 0; 618*4887Schin c = sh_arith(sp+1); 619*4887Schin cp[-1] = ']'; 620*4887Schin if(c) 621*4887Schin return(0); 622*4887Schin } 623*4887Schin dp->last = cp; 624*4887Schin if(nv_isarray(np) && (c=='[' || c=='.' || (flags&NV_ARRAY))) 625*4887Schin { 626*4887Schin *(sp=cp) = 0; 627*4887Schin nq = nv_search(name,root,mode); 628*4887Schin *sp = c; 629*4887Schin if(nq && nv_isnull(nq)) 630*4887Schin nq = nv_arraychild(np,nq,c); 631*4887Schin if(!(np=nq)) 632*4887Schin return(np); 633*4887Schin } 634*4887Schin } 635*4887Schin else if(nv_isarray(np)) 636*4887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 637*4887Schin if(c=='.' && (fp=np->nvfun)) 638*4887Schin { 639*4887Schin for(; fp; fp=fp->next) 640*4887Schin { 641*4887Schin if(fp->disc && fp->disc->createf) 642*4887Schin break; 643*4887Schin } 644*4887Schin if(fp) 645*4887Schin { 646*4887Schin if((nq = (*fp->disc->createf)(np,cp+1,flags,fp)) == np) 647*4887Schin { 648*4887Schin add = NV_ADD; 649*4887Schin break; 650*4887Schin } 651*4887Schin else if((np=nq) && (c = *(cp=dp->last=fp->last))==0) 652*4887Schin return(np); 653*4887Schin } 654*4887Schin } 655*4887Schin } 656*4887Schin while(c=='['); 657*4887Schin if(c!='.') 658*4887Schin return(np); 659*4887Schin cp++; 660*4887Schin break; 661*4887Schin default: 662*4887Schin dp->last = cp; 663*4887Schin if((c = mbchar(cp)) && !isaletter(c)) 664*4887Schin return(np); 665*4887Schin while(xp=cp, c=mbchar(cp), isaname(c)); 666*4887Schin cp = xp; 667*4887Schin } 668*4887Schin } 669*4887Schin return(np); 670*4887Schin } 671*4887Schin 672*4887Schin /* 673*4887Schin * Put <arg> into associative memory. 674*4887Schin * If <flags> & NV_ARRAY then follow array to next subscript 675*4887Schin * If <flags> & NV_NOARRAY then subscript is not allowed 676*4887Schin * If <flags> & NV_NOSCOPE then use the current scope only 677*4887Schin * If <flags> & NV_ASSIGN then assignment is allowed 678*4887Schin * If <flags> & NV_IDENT then name must be an identifier 679*4887Schin * If <flags> & NV_VARNAME then name must be a valid variable name 680*4887Schin * If <flags> & NV_NOADD then node will not be added if not found 681*4887Schin * If <flags> & NV_NOREF then don't follow reference 682*4887Schin * If <flags> & NV_NOFAIL then don't generate an error message on failure 683*4887Schin * SH_INIT is only set while initializing the environment 684*4887Schin */ 685*4887Schin Namval_t *nv_open(const char *name, Dt_t *root, int flags) 686*4887Schin { 687*4887Schin register char *cp=(char*)name; 688*4887Schin register int c; 689*4887Schin register Namval_t *np; 690*4887Schin Namfun_t fun; 691*4887Schin int append=0; 692*4887Schin const char *msg = e_varname; 693*4887Schin char *fname = 0; 694*4887Schin int offset = staktell(); 695*4887Schin Dt_t *funroot; 696*4887Schin 697*4887Schin memset(&fun,0,sizeof(fun)); 698*4887Schin sh.last_table = sh.namespace; 699*4887Schin if(!root) 700*4887Schin root = sh.var_tree; 701*4887Schin sh.last_root = root; 702*4887Schin if(root==sh_subfuntree(1)) 703*4887Schin { 704*4887Schin flags |= NV_NOREF; 705*4887Schin msg = e_badfun; 706*4887Schin if((np=sh.namespace) || strchr(name,'.')) 707*4887Schin { 708*4887Schin name = cp = copystack(np?nv_name(np):0,name,(const char*)0); 709*4887Schin fname = strrchr(cp,'.'); 710*4887Schin *fname = 0; 711*4887Schin fun.nofree = 1; 712*4887Schin flags &= ~NV_IDENT; 713*4887Schin funroot = root; 714*4887Schin root = sh.var_tree; 715*4887Schin } 716*4887Schin } 717*4887Schin else if(!(flags&(NV_IDENT|NV_VARNAME|NV_ASSIGN))) 718*4887Schin { 719*4887Schin long mode = ((flags&NV_NOADD)?0:NV_ADD); 720*4887Schin if(flags&NV_NOSCOPE) 721*4887Schin mode |= HASH_SCOPE|HASH_NOSCOPE; 722*4887Schin np = nv_search(name,root,mode); 723*4887Schin if(np && !(flags&NV_REF)) 724*4887Schin { 725*4887Schin while(nv_isref(np)) 726*4887Schin { 727*4887Schin sh.last_table = nv_reftable(np); 728*4887Schin np = nv_refnode(np); 729*4887Schin } 730*4887Schin } 731*4887Schin return(np); 732*4887Schin } 733*4887Schin else if(sh.prefix && /**name!='.' &&*/ (flags&NV_ASSIGN)) 734*4887Schin { 735*4887Schin name = cp = copystack(sh.prefix,name,(const char*)0); 736*4887Schin fun.nofree = 1; 737*4887Schin } 738*4887Schin c = *(unsigned char*)cp; 739*4887Schin if(root==sh.alias_tree) 740*4887Schin { 741*4887Schin msg = e_aliname; 742*4887Schin while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') && 743*4887Schin (c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT)); 744*4887Schin if(sh.subshell && c=='=') 745*4887Schin root = sh_subaliastree(1); 746*4887Schin if(c= *--cp) 747*4887Schin *cp = 0; 748*4887Schin np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD); 749*4887Schin if(c) 750*4887Schin *cp = c; 751*4887Schin goto skip; 752*4887Schin } 753*4887Schin else if(flags&NV_IDENT) 754*4887Schin msg = e_ident; 755*4887Schin else if(c=='.') 756*4887Schin { 757*4887Schin c = *++cp; 758*4887Schin flags |= NV_NOREF; 759*4887Schin if(root==sh.var_tree) 760*4887Schin root = sh.var_base; 761*4887Schin sh.last_table = 0; 762*4887Schin } 763*4887Schin if(c= !isaletter(c)) 764*4887Schin goto skip; 765*4887Schin np = nv_create(name, root, flags, &fun); 766*4887Schin cp = fun.last; 767*4887Schin if(fname) 768*4887Schin { 769*4887Schin c = ((flags&NV_NOSCOPE)?HASH_NOSCOPE:0)|((flags&NV_NOADD)?0:NV_ADD); 770*4887Schin *fname = '.'; 771*4887Schin np = nv_search(name, funroot, c); 772*4887Schin *fname = 0; 773*4887Schin } 774*4887Schin else if(*cp=='+' && cp[1]=='=') 775*4887Schin { 776*4887Schin append=NV_APPEND; 777*4887Schin cp++; 778*4887Schin } 779*4887Schin c = *cp; 780*4887Schin skip: 781*4887Schin if(c=='=' && np && (flags&NV_ASSIGN)) 782*4887Schin { 783*4887Schin cp++; 784*4887Schin if(sh_isstate(SH_INIT)) 785*4887Schin { 786*4887Schin nv_putval(np, cp, NV_RDONLY); 787*4887Schin if(np==PWDNOD) 788*4887Schin nv_onattr(np,NV_TAGGED); 789*4887Schin } 790*4887Schin else 791*4887Schin { 792*4887Schin char *sub=0; 793*4887Schin if(sh_isoption(SH_XTRACE) && nv_isarray(np)) 794*4887Schin sub = nv_getsub(np); 795*4887Schin c = msg==e_aliname? 0: (append | (flags&NV_EXPORT)); 796*4887Schin nv_putval(np, cp, c); 797*4887Schin savesub = sub; 798*4887Schin } 799*4887Schin nv_onattr(np, flags&NV_ATTRIBUTES); 800*4887Schin } 801*4887Schin else if(c) 802*4887Schin { 803*4887Schin if(flags&NV_NOFAIL) 804*4887Schin return(0); 805*4887Schin if(c=='.') 806*4887Schin msg = e_noparent; 807*4887Schin else if(c=='[') 808*4887Schin msg = e_noarray; 809*4887Schin errormsg(SH_DICT,ERROR_exit(1),msg,name); 810*4887Schin } 811*4887Schin if(fun.nofree) 812*4887Schin stakseek(offset); 813*4887Schin return(np); 814*4887Schin } 815*4887Schin 816*4887Schin #if SHOPT_MULTIBYTE 817*4887Schin static int ja_size(char*, int, int); 818*4887Schin static void ja_restore(void); 819*4887Schin static char *savep; 820*4887Schin static char savechars[8+1]; 821*4887Schin #endif /* SHOPT_MULTIBYTE */ 822*4887Schin 823*4887Schin /* 824*4887Schin * put value <string> into name-value node <np>. 825*4887Schin * If <np> is an array, then the element given by the 826*4887Schin * current index is assigned to. 827*4887Schin * If <flags> contains NV_RDONLY, readonly attribute is ignored 828*4887Schin * If <flags> contains NV_INTEGER, string is a pointer to a number 829*4887Schin * If <flags> contains NV_NOFREE, previous value is freed, and <string> 830*4887Schin * becomes value of node and <flags> becomes attributes 831*4887Schin */ 832*4887Schin void nv_putval(register Namval_t *np, const char *string, int flags) 833*4887Schin { 834*4887Schin register const char *sp=string; 835*4887Schin register union Value *up; 836*4887Schin register char *cp; 837*4887Schin register int size = 0; 838*4887Schin register int dot; 839*4887Schin int was_local = nv_local; 840*4887Schin if(!(flags&NV_RDONLY) && nv_isattr (np, NV_RDONLY)) 841*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np)); 842*4887Schin /* The following could cause the shell to fork if assignment 843*4887Schin * would cause a side effect 844*4887Schin */ 845*4887Schin sh.argaddr = 0; 846*4887Schin if(sh.subshell && !nv_local) 847*4887Schin np = sh_assignok(np,1); 848*4887Schin if(np->nvfun && !nv_isattr(np,NV_REF)) 849*4887Schin { 850*4887Schin /* This function contains disc */ 851*4887Schin if(!nv_local) 852*4887Schin { 853*4887Schin nv_local=1; 854*4887Schin nv_putv(np,sp,flags,np->nvfun); 855*4887Schin if(sp && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT))) 856*4887Schin sh_envput(sh.env,np); 857*4887Schin return; 858*4887Schin } 859*4887Schin /* called from disc, assign the actual value */ 860*4887Schin } 861*4887Schin flags &= ~NV_NODISC; 862*4887Schin if(flags&(NV_NOREF|NV_NOFREE)) 863*4887Schin { 864*4887Schin if(!nv_isnull(np) && np->nvalue.cp!=sp) 865*4887Schin nv_unset(np); 866*4887Schin nv_local=0; 867*4887Schin np->nvalue.cp = (char*)sp; 868*4887Schin nv_setattr(np,(flags&~NV_RDONLY)|NV_NOFREE); 869*4887Schin return; 870*4887Schin } 871*4887Schin nv_local=0; 872*4887Schin up= &np->nvalue; 873*4887Schin #if !SHOPT_BSH 874*4887Schin if(nv_isattr(np,NV_EXPORT)) 875*4887Schin nv_offattr(np,NV_IMPORT); 876*4887Schin else if(!nv_isattr(np,NV_MINIMAL)) 877*4887Schin np->nvenv = 0; 878*4887Schin #endif /* SHOPT_BSH */ 879*4887Schin if(nv_isattr (np, NV_INTEGER)) 880*4887Schin { 881*4887Schin if(nv_isattr(np, NV_DOUBLE)) 882*4887Schin { 883*4887Schin if(nv_isattr(np, NV_LONG) && sizeof(double)<sizeof(Sfdouble_t)) 884*4887Schin { 885*4887Schin Sfdouble_t ld, old=0; 886*4887Schin if(flags&NV_INTEGER) 887*4887Schin { 888*4887Schin if(flags&NV_LONG) 889*4887Schin ld = *((Sfdouble_t*)sp); 890*4887Schin else if(flags&NV_SHORT) 891*4887Schin ld = *((float*)sp); 892*4887Schin else 893*4887Schin ld = *((double*)sp); 894*4887Schin } 895*4887Schin else 896*4887Schin ld = sh_arith(sp); 897*4887Schin if(!up->ldp) 898*4887Schin up->ldp = new_of(Sfdouble_t,0); 899*4887Schin else if(flags&NV_APPEND) 900*4887Schin old = *(up->ldp); 901*4887Schin *(up->ldp) = ld+old; 902*4887Schin } 903*4887Schin else 904*4887Schin { 905*4887Schin double d,od=0; 906*4887Schin if(flags&NV_INTEGER) 907*4887Schin { 908*4887Schin if(flags&NV_LONG) 909*4887Schin d = (double)(*(Sfdouble_t*)sp); 910*4887Schin else if(flags&NV_SHORT) 911*4887Schin d = (double)(*(float*)sp); 912*4887Schin else 913*4887Schin d = *(double*)sp; 914*4887Schin } 915*4887Schin else 916*4887Schin d = sh_arith(sp); 917*4887Schin if(!up->dp) 918*4887Schin up->dp = new_of(double,0); 919*4887Schin else if(flags&NV_APPEND) 920*4887Schin od = *(up->dp); 921*4887Schin *(up->dp) = d+od; 922*4887Schin } 923*4887Schin } 924*4887Schin else 925*4887Schin { 926*4887Schin if(nv_isattr(np, NV_LONG) && sizeof(int32_t)<sizeof(Sflong_t)) 927*4887Schin { 928*4887Schin Sflong_t ll=0,oll=0; 929*4887Schin if(flags&NV_INTEGER) 930*4887Schin { 931*4887Schin if(flags&NV_DOUBLE) 932*4887Schin { 933*4887Schin if(flags&NV_LONG) 934*4887Schin ll = *((Sfdouble_t*)sp); 935*4887Schin else if(flags&NV_SHORT) 936*4887Schin ll = *((float*)sp); 937*4887Schin else 938*4887Schin ll = *((double*)sp); 939*4887Schin } 940*4887Schin else if(nv_isattr(np,NV_UNSIGN)) 941*4887Schin { 942*4887Schin if(flags&NV_LONG) 943*4887Schin ll = *((Sfulong_t*)sp); 944*4887Schin else if(flags&NV_SHORT) 945*4887Schin ll = *((uint16_t*)sp); 946*4887Schin else 947*4887Schin ll = *((uint32_t*)sp); 948*4887Schin } 949*4887Schin else 950*4887Schin { 951*4887Schin if(flags&NV_LONG) 952*4887Schin ll = *((Sflong_t*)sp); 953*4887Schin else if(flags&NV_SHORT) 954*4887Schin ll = *((uint16_t*)sp); 955*4887Schin else 956*4887Schin ll = *((uint32_t*)sp); 957*4887Schin } 958*4887Schin } 959*4887Schin else if(sp) 960*4887Schin ll = (Sflong_t)sh_arith(sp); 961*4887Schin if(!up->llp) 962*4887Schin up->llp = new_of(Sflong_t,0); 963*4887Schin else if(flags&NV_APPEND) 964*4887Schin oll = *(up->llp); 965*4887Schin *(up->llp) = ll+oll; 966*4887Schin } 967*4887Schin else 968*4887Schin { 969*4887Schin int32_t l=0,ol=0; 970*4887Schin if(flags&NV_INTEGER) 971*4887Schin { 972*4887Schin if(flags&NV_DOUBLE) 973*4887Schin { 974*4887Schin Sflong_t ll; 975*4887Schin if(flags&NV_LONG) 976*4887Schin ll = *((Sfdouble_t*)sp); 977*4887Schin else if(flags&NV_SHORT) 978*4887Schin ll = *((float*)sp); 979*4887Schin else 980*4887Schin ll = *((double*)sp); 981*4887Schin l = (int32_t)ll; 982*4887Schin } 983*4887Schin else if(nv_isattr(np,NV_UNSIGN)) 984*4887Schin { 985*4887Schin if(flags&NV_LONG) 986*4887Schin l = *((Sfulong_t*)sp); 987*4887Schin else if(flags&NV_SHORT) 988*4887Schin l = *((uint16_t*)sp); 989*4887Schin else 990*4887Schin l = *(uint32_t*)sp; 991*4887Schin } 992*4887Schin else 993*4887Schin { 994*4887Schin if(flags&NV_LONG) 995*4887Schin l = *((Sflong_t*)sp); 996*4887Schin else if(flags&NV_SHORT) 997*4887Schin l = *((int16_t*)sp); 998*4887Schin else 999*4887Schin l = *(int32_t*)sp; 1000*4887Schin } 1001*4887Schin } 1002*4887Schin else if(sp) 1003*4887Schin { 1004*4887Schin Sfdouble_t ld = sh_arith(sp); 1005*4887Schin if(ld<0) 1006*4887Schin l = (int32_t)ld; 1007*4887Schin else 1008*4887Schin l = (uint32_t)ld; 1009*4887Schin } 1010*4887Schin if(nv_size(np) <= 1) 1011*4887Schin nv_setsize(np,10); 1012*4887Schin if(nv_isattr (np, NV_SHORT)) 1013*4887Schin { 1014*4887Schin int16_t s=0; 1015*4887Schin if(flags&NV_APPEND) 1016*4887Schin s = up->s; 1017*4887Schin up->s = s+(int16_t)l; 1018*4887Schin nv_onattr(np,NV_NOFREE); 1019*4887Schin } 1020*4887Schin else 1021*4887Schin { 1022*4887Schin if(!up->lp) 1023*4887Schin up->lp = new_of(int32_t,0); 1024*4887Schin else if(flags&NV_APPEND) 1025*4887Schin ol = *(up->lp); 1026*4887Schin *(up->lp) = l+ol; 1027*4887Schin } 1028*4887Schin } 1029*4887Schin } 1030*4887Schin } 1031*4887Schin else 1032*4887Schin { 1033*4887Schin const char *tofree=0; 1034*4887Schin int offset; 1035*4887Schin #if _lib_pathnative 1036*4887Schin char buff[PATH_MAX]; 1037*4887Schin #endif /* _lib_pathnative */ 1038*4887Schin if(flags&NV_INTEGER) 1039*4887Schin { 1040*4887Schin if(flags&NV_DOUBLE) 1041*4887Schin { 1042*4887Schin if(flags&NV_LONG) 1043*4887Schin sfprintf(sh.strbuf,"%.*Lg",LDBL_DIG,*((Sfdouble_t*)sp)); 1044*4887Schin else 1045*4887Schin sfprintf(sh.strbuf,"%.*g",DBL_DIG,*((double*)sp)); 1046*4887Schin } 1047*4887Schin else if(flags&NV_LONG) 1048*4887Schin sfprintf(sh.strbuf,"%lld\0",*((Sflong_t*)sp)); 1049*4887Schin else 1050*4887Schin sfprintf(sh.strbuf,"%ld\0",*((int32_t*)sp)); 1051*4887Schin sp = sfstruse(sh.strbuf); 1052*4887Schin } 1053*4887Schin if(nv_isattr(np, NV_HOST)==NV_HOST && sp) 1054*4887Schin { 1055*4887Schin #ifdef _lib_pathnative 1056*4887Schin /* 1057*4887Schin * return the host file name given the UNIX name 1058*4887Schin */ 1059*4887Schin pathnative(sp,buff,sizeof(buff)); 1060*4887Schin if(buff[1]==':' && buff[2]=='/') 1061*4887Schin { 1062*4887Schin buff[2] = '\\'; 1063*4887Schin if(*buff>='A' && *buff<='Z') 1064*4887Schin *buff += 'a'-'A'; 1065*4887Schin } 1066*4887Schin sp = buff; 1067*4887Schin #else 1068*4887Schin ; 1069*4887Schin #endif /* _lib_pathnative */ 1070*4887Schin } 1071*4887Schin else if((nv_isattr(np, NV_RJUST|NV_ZFILL|NV_LJUST)) && sp) 1072*4887Schin { 1073*4887Schin for(;*sp == ' '|| *sp=='\t';sp++); 1074*4887Schin if((nv_isattr(np,NV_ZFILL)) && (nv_isattr(np,NV_LJUST))) 1075*4887Schin for(;*sp=='0';sp++); 1076*4887Schin size = nv_size(np); 1077*4887Schin #if SHOPT_MULTIBYTE 1078*4887Schin if(size) 1079*4887Schin size = ja_size((char*)sp,size,nv_isattr(np,NV_RJUST|NV_ZFILL)); 1080*4887Schin #endif /* SHOPT_MULTIBYTE */ 1081*4887Schin } 1082*4887Schin if(!up->cp) 1083*4887Schin flags &= ~NV_APPEND; 1084*4887Schin if((flags&NV_APPEND) && !nv_isattr(np,NV_BINARY)) 1085*4887Schin { 1086*4887Schin offset = staktell(); 1087*4887Schin stakputs(up->cp); 1088*4887Schin stakputs(sp); 1089*4887Schin stakputc(0); 1090*4887Schin sp = stakptr(offset); 1091*4887Schin } 1092*4887Schin if(!nv_isattr(np, NV_NOFREE)) 1093*4887Schin { 1094*4887Schin /* delay free in case <sp> points into free region */ 1095*4887Schin tofree = up->cp; 1096*4887Schin } 1097*4887Schin nv_offattr(np,NV_NOFREE); 1098*4887Schin if (sp) 1099*4887Schin { 1100*4887Schin dot = strlen(sp); 1101*4887Schin #if (_AST_VERSION>=20030127L) 1102*4887Schin if(nv_isattr(np,NV_BINARY)) 1103*4887Schin { 1104*4887Schin int oldsize = (flags&NV_APPEND)?nv_size(np):0; 1105*4887Schin if(flags&NV_RAW) 1106*4887Schin { 1107*4887Schin if(tofree) 1108*4887Schin free((void*)tofree); 1109*4887Schin up->cp = sp; 1110*4887Schin return; 1111*4887Schin } 1112*4887Schin size = 0; 1113*4887Schin if(nv_isattr(np,NV_ZFILL)) 1114*4887Schin size = nv_size(np); 1115*4887Schin if(size==0) 1116*4887Schin size = oldsize + (3*dot/4); 1117*4887Schin cp = (char*)malloc(size+1); 1118*4887Schin if(oldsize) 1119*4887Schin memcpy((void*)cp,(void*)up->cp,oldsize); 1120*4887Schin up->cp = cp; 1121*4887Schin if(size <= oldsize) 1122*4887Schin return; 1123*4887Schin dot = base64decode(sp,dot, (void**)0, cp+oldsize, size-oldsize,(void**)0); 1124*4887Schin dot += oldsize; 1125*4887Schin if(!nv_isattr(np,NV_ZFILL) || nv_size(np)==0) 1126*4887Schin nv_setsize(np,dot); 1127*4887Schin else if(nv_isattr(np,NV_ZFILL) && (size>dot)) 1128*4887Schin memset((void*)&cp[dot],0,size-dot); 1129*4887Schin return; 1130*4887Schin } 1131*4887Schin else 1132*4887Schin #endif 1133*4887Schin if(size==0 && nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL)) 1134*4887Schin nv_setsize(np,size=dot); 1135*4887Schin else if(size > dot) 1136*4887Schin dot = size; 1137*4887Schin cp = (char*)malloc(((unsigned)dot+1)); 1138*4887Schin } 1139*4887Schin else 1140*4887Schin cp = 0; 1141*4887Schin up->cp = cp; 1142*4887Schin if(sp) 1143*4887Schin { 1144*4887Schin if(nv_isattr(np, NV_LTOU)) 1145*4887Schin ltou(sp,cp); 1146*4887Schin else if(nv_isattr (np, NV_UTOL)) 1147*4887Schin sh_utol(sp,cp); 1148*4887Schin else 1149*4887Schin strcpy(cp, sp); 1150*4887Schin if(nv_isattr(np, NV_RJUST) && nv_isattr(np, NV_ZFILL)) 1151*4887Schin rightjust(cp,size,'0'); 1152*4887Schin else if(nv_isattr(np, NV_RJUST)) 1153*4887Schin rightjust(cp,size,' '); 1154*4887Schin else if(nv_isattr(np, NV_LJUST)) 1155*4887Schin { 1156*4887Schin register char *dp; 1157*4887Schin dp = strlen (cp) + cp; 1158*4887Schin *(cp = (cp + size)) = 0; 1159*4887Schin for (; dp < cp; *dp++ = ' '); 1160*4887Schin } 1161*4887Schin #if SHOPT_MULTIBYTE 1162*4887Schin /* restore original string */ 1163*4887Schin if(savep) 1164*4887Schin ja_restore(); 1165*4887Schin #endif /* SHOPT_MULTIBYTE */ 1166*4887Schin } 1167*4887Schin if(flags&NV_APPEND) 1168*4887Schin stakseek(offset); 1169*4887Schin if(tofree) 1170*4887Schin free((void*)tofree); 1171*4887Schin } 1172*4887Schin if(!was_local && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT))) 1173*4887Schin sh_envput(sh.env,np); 1174*4887Schin return; 1175*4887Schin } 1176*4887Schin 1177*4887Schin /* 1178*4887Schin * 1179*4887Schin * Right-justify <str> so that it contains no more than 1180*4887Schin * <size> characters. If <str> contains fewer than <size> 1181*4887Schin * characters, left-pad with <fill>. Trailing blanks 1182*4887Schin * in <str> will be ignored. 1183*4887Schin * 1184*4887Schin * If the leftmost digit in <str> is not a digit, <fill> 1185*4887Schin * will default to a blank. 1186*4887Schin */ 1187*4887Schin static void rightjust(char *str, int size, int fill) 1188*4887Schin { 1189*4887Schin register int n; 1190*4887Schin register char *cp,*sp; 1191*4887Schin n = strlen(str); 1192*4887Schin 1193*4887Schin /* ignore trailing blanks */ 1194*4887Schin for(cp=str+n;n && *--cp == ' ';n--); 1195*4887Schin if (n == size) 1196*4887Schin return; 1197*4887Schin if(n > size) 1198*4887Schin { 1199*4887Schin *(str+n) = 0; 1200*4887Schin for (sp = str, cp = str+n-size; sp <= str+size; *sp++ = *cp++); 1201*4887Schin return; 1202*4887Schin } 1203*4887Schin else *(sp = str+size) = 0; 1204*4887Schin if (n == 0) 1205*4887Schin { 1206*4887Schin while (sp > str) 1207*4887Schin *--sp = ' '; 1208*4887Schin return; 1209*4887Schin } 1210*4887Schin while(n--) 1211*4887Schin { 1212*4887Schin sp--; 1213*4887Schin *sp = *cp--; 1214*4887Schin } 1215*4887Schin if(!isdigit(*str)) 1216*4887Schin fill = ' '; 1217*4887Schin while(sp>str) 1218*4887Schin *--sp = fill; 1219*4887Schin return; 1220*4887Schin } 1221*4887Schin 1222*4887Schin #if SHOPT_MULTIBYTE 1223*4887Schin /* 1224*4887Schin * handle left and right justified fields for multi-byte chars 1225*4887Schin * given physical size, return a logical size which reflects the 1226*4887Schin * screen width of multi-byte characters 1227*4887Schin * Multi-width characters replaced by spaces if they cross the boundary 1228*4887Schin * <type> is non-zero for right justified fields 1229*4887Schin */ 1230*4887Schin 1231*4887Schin static int ja_size(char *str,int size,int type) 1232*4887Schin { 1233*4887Schin register char *cp = str; 1234*4887Schin register int c, n=size; 1235*4887Schin register int outsize; 1236*4887Schin register char *oldcp=cp; 1237*4887Schin int oldn; 1238*4887Schin wchar_t w; 1239*4887Schin while(*cp) 1240*4887Schin { 1241*4887Schin oldn = n; 1242*4887Schin w = mbchar(cp); 1243*4887Schin outsize = mbwidth(w); 1244*4887Schin size -= outsize; 1245*4887Schin c = cp-oldcp; 1246*4887Schin n += (c-outsize); 1247*4887Schin oldcp = cp; 1248*4887Schin if(size<=0 && type==0) 1249*4887Schin break; 1250*4887Schin } 1251*4887Schin /* check for right justified fields that need truncating */ 1252*4887Schin if(size <0) 1253*4887Schin { 1254*4887Schin if(type==0) 1255*4887Schin { 1256*4887Schin /* left justified and character crosses field boundary */ 1257*4887Schin n = oldn; 1258*4887Schin /* save boundary char and replace with spaces */ 1259*4887Schin size = c; 1260*4887Schin savechars[size] = 0; 1261*4887Schin while(size--) 1262*4887Schin { 1263*4887Schin savechars[size] = cp[size]; 1264*4887Schin cp[size] = ' '; 1265*4887Schin } 1266*4887Schin savep = cp; 1267*4887Schin } 1268*4887Schin size = -size; 1269*4887Schin if(type) 1270*4887Schin n -= (ja_size(str,size,0)-size); 1271*4887Schin } 1272*4887Schin return(n); 1273*4887Schin } 1274*4887Schin 1275*4887Schin static void ja_restore(void) 1276*4887Schin { 1277*4887Schin register char *cp = savechars; 1278*4887Schin while(*cp) 1279*4887Schin *savep++ = *cp++; 1280*4887Schin savep = 0; 1281*4887Schin } 1282*4887Schin #endif /* SHOPT_MULTIBYTE */ 1283*4887Schin 1284*4887Schin #ifndef _ENV_H 1285*4887Schin static char *staknam(register Namval_t *np, char *value) 1286*4887Schin { 1287*4887Schin register char *p,*q; 1288*4887Schin q = stakalloc(strlen(nv_name(np))+(value?strlen(value):0)+2); 1289*4887Schin p=strcopy(q,nv_name(np)); 1290*4887Schin if(value) 1291*4887Schin { 1292*4887Schin *p++ = '='; 1293*4887Schin strcpy(p,value); 1294*4887Schin } 1295*4887Schin return(q); 1296*4887Schin } 1297*4887Schin #endif 1298*4887Schin 1299*4887Schin /* 1300*4887Schin * put the name and attribute into value of attributes variable 1301*4887Schin */ 1302*4887Schin #ifdef _ENV_H 1303*4887Schin static void attstore(register Namval_t *np, void *data) 1304*4887Schin { 1305*4887Schin register int flag, c = ' '; 1306*4887Schin NOT_USED(data); 1307*4887Schin if(!(nv_isattr(np,NV_EXPORT))) 1308*4887Schin return; 1309*4887Schin flag = nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER); 1310*4887Schin stakputc('='); 1311*4887Schin if((flag&NV_DOUBLE) && (flag&NV_INTEGER)) 1312*4887Schin { 1313*4887Schin /* export doubles as integers for ksh88 compatibility */ 1314*4887Schin stakputc(c+(flag&~(NV_DOUBLE|NV_EXPNOTE))); 1315*4887Schin } 1316*4887Schin else 1317*4887Schin { 1318*4887Schin stakputc(c+flag); 1319*4887Schin if(flag&NV_INTEGER) 1320*4887Schin c += nv_size(np); 1321*4887Schin } 1322*4887Schin stakputc(c); 1323*4887Schin stakputs(nv_name(np)); 1324*4887Schin } 1325*4887Schin #else 1326*4887Schin static void attstore(register Namval_t *np, void *data) 1327*4887Schin { 1328*4887Schin register int flag = np->nvflag; 1329*4887Schin register struct adata *ap = (struct adata*)data; 1330*4887Schin if(!(flag&NV_EXPORT) || (flag&NV_FUNCT)) 1331*4887Schin return; 1332*4887Schin flag &= (NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER); 1333*4887Schin *ap->attval++ = '='; 1334*4887Schin if((flag&NV_DOUBLE) && (flag&NV_INTEGER)) 1335*4887Schin { 1336*4887Schin /* export doubles as integers for ksh88 compatibility */ 1337*4887Schin *ap->attval++ = ' '+(flag&~(NV_DOUBLE|NV_EXPNOTE)); 1338*4887Schin *ap->attval = ' '; 1339*4887Schin } 1340*4887Schin else 1341*4887Schin { 1342*4887Schin *ap->attval++ = ' '+flag; 1343*4887Schin if(flag&NV_INTEGER) 1344*4887Schin *ap->attval = ' ' + nv_size(np); 1345*4887Schin else 1346*4887Schin *ap->attval = ' '; 1347*4887Schin } 1348*4887Schin ap->attval = strcopy(++ap->attval,nv_name(np)); 1349*4887Schin } 1350*4887Schin #endif 1351*4887Schin 1352*4887Schin #ifndef _ENV_H 1353*4887Schin static void pushnam(Namval_t *np, void *data) 1354*4887Schin { 1355*4887Schin register char *value; 1356*4887Schin register struct adata *ap = (struct adata*)data; 1357*4887Schin if(nv_isattr(np,NV_IMPORT)) 1358*4887Schin { 1359*4887Schin if(np->nvenv) 1360*4887Schin *ap->argnam++ = np->nvenv; 1361*4887Schin } 1362*4887Schin else if(value=nv_getval(np)) 1363*4887Schin *ap->argnam++ = staknam(np,value); 1364*4887Schin if(nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)) 1365*4887Schin ap->attsize += (strlen(nv_name(np))+4); 1366*4887Schin } 1367*4887Schin #endif 1368*4887Schin 1369*4887Schin /* 1370*4887Schin * Generate the environment list for the child. 1371*4887Schin */ 1372*4887Schin 1373*4887Schin #ifdef _ENV_H 1374*4887Schin char **sh_envgen(void) 1375*4887Schin { 1376*4887Schin int offset,tell; 1377*4887Schin register char **er; 1378*4887Schin env_delete(sh.env,"_"); 1379*4887Schin er = env_get(sh.env); 1380*4887Schin offset = staktell(); 1381*4887Schin stakputs(e_envmarker); 1382*4887Schin tell = staktell(); 1383*4887Schin nv_scan(sh.var_tree, attstore,(void*)0,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)); 1384*4887Schin if(tell ==staktell()) 1385*4887Schin stakseek(offset); 1386*4887Schin else 1387*4887Schin *--er = stakfreeze(1)+offset; 1388*4887Schin return(er); 1389*4887Schin } 1390*4887Schin #else 1391*4887Schin char **sh_envgen(void) 1392*4887Schin { 1393*4887Schin register char **er; 1394*4887Schin register int namec; 1395*4887Schin register char *cp; 1396*4887Schin struct adata data; 1397*4887Schin /* L_ARGNOD gets generated automatically as full path name of command */ 1398*4887Schin nv_offattr(L_ARGNOD,NV_EXPORT); 1399*4887Schin data.attsize = 6; 1400*4887Schin namec = nv_scan(sh.var_tree,nullscan,(void*)0,NV_EXPORT,NV_EXPORT); 1401*4887Schin er = (char**)stakalloc((namec+4)*sizeof(char*)); 1402*4887Schin data.argnam = (er+=2); 1403*4887Schin nv_scan(sh.var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT); 1404*4887Schin *data.argnam = (char*)stakalloc(data.attsize); 1405*4887Schin cp = data.attval = strcopy(*data.argnam,e_envmarker); 1406*4887Schin nv_scan(sh.var_tree, attstore,&data,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)); 1407*4887Schin *data.attval = 0; 1408*4887Schin if(cp!=data.attval) 1409*4887Schin data.argnam++; 1410*4887Schin *data.argnam = 0; 1411*4887Schin return(er); 1412*4887Schin } 1413*4887Schin #endif 1414*4887Schin 1415*4887Schin struct scan 1416*4887Schin { 1417*4887Schin void (*scanfn)(Namval_t*, void*); 1418*4887Schin int scanmask; 1419*4887Schin int scanflags; 1420*4887Schin int scancount; 1421*4887Schin void *scandata; 1422*4887Schin }; 1423*4887Schin 1424*4887Schin 1425*4887Schin static int scanfilter(Dt_t *dict, void *arg, void *data) 1426*4887Schin { 1427*4887Schin register Namval_t *np = (Namval_t*)arg; 1428*4887Schin register int k=np->nvflag; 1429*4887Schin register struct scan *sp = (struct scan*)data; 1430*4887Schin NOT_USED(dict); 1431*4887Schin if(sp->scanmask?(k&sp->scanmask)==sp->scanflags:(!sp->scanflags || (k&sp->scanflags))) 1432*4887Schin { 1433*4887Schin if(!np->nvalue.cp && !nv_isattr(np,~NV_DEFAULT)) 1434*4887Schin return(0); 1435*4887Schin if(sp->scanfn) 1436*4887Schin { 1437*4887Schin if(nv_isarray(np)) 1438*4887Schin nv_putsub(np,NIL(char*),0L); 1439*4887Schin (*sp->scanfn)(np,sp->scandata); 1440*4887Schin } 1441*4887Schin sp->scancount++; 1442*4887Schin } 1443*4887Schin return(0); 1444*4887Schin } 1445*4887Schin 1446*4887Schin /* 1447*4887Schin * Walk through the name-value pairs 1448*4887Schin * if <mask> is non-zero, then only nodes with (nvflags&mask)==flags 1449*4887Schin * are visited 1450*4887Schin * If <mask> is zero, and <flags> non-zero, then nodes with one or 1451*4887Schin * more of <flags> is visited 1452*4887Schin * If <mask> and <flags> are zero, then all nodes are visted 1453*4887Schin */ 1454*4887Schin int nv_scan(Dt_t *root, void (*fn)(Namval_t*,void*), void *data,int mask, int flags) 1455*4887Schin { 1456*4887Schin Dt_t *base=0; 1457*4887Schin struct scan sdata; 1458*4887Schin int (*hashfn)(Dt_t*, void*, void*); 1459*4887Schin sdata.scanmask = mask; 1460*4887Schin sdata.scanflags = flags&~NV_NOSCOPE; 1461*4887Schin sdata.scanfn = fn; 1462*4887Schin sdata.scancount = 0; 1463*4887Schin sdata.scandata = data; 1464*4887Schin hashfn = scanfilter; 1465*4887Schin if(flags&NV_NOSCOPE) 1466*4887Schin base = dtview((Dt_t*)root,0); 1467*4887Schin dtwalk(root, hashfn,&sdata); 1468*4887Schin if(base) 1469*4887Schin dtview((Dt_t*)root,base); 1470*4887Schin return(sdata.scancount); 1471*4887Schin } 1472*4887Schin 1473*4887Schin /* 1474*4887Schin * create a new environment scope 1475*4887Schin */ 1476*4887Schin void nv_scope(struct argnod *envlist) 1477*4887Schin { 1478*4887Schin register Dt_t *newscope; 1479*4887Schin newscope = dtopen(&_Nvdisc,Dtoset); 1480*4887Schin dtview(newscope,(Dt_t*)sh.var_tree); 1481*4887Schin sh.var_tree = (Dt_t*)newscope; 1482*4887Schin if(envlist) 1483*4887Schin nv_setlist(envlist,NV_EXPORT|NV_NOSCOPE|NV_IDENT|NV_ASSIGN); 1484*4887Schin } 1485*4887Schin 1486*4887Schin /* 1487*4887Schin * Remove freeable local space associated with the nvalue field 1488*4887Schin * of nnod. This includes any strings representing the value(s) of the 1489*4887Schin * node, as well as its dope vector, if it is an array. 1490*4887Schin */ 1491*4887Schin 1492*4887Schin void sh_envnolocal (register Namval_t *np, void *data) 1493*4887Schin { 1494*4887Schin char *cp=0; 1495*4887Schin NOT_USED(data); 1496*4887Schin if(nv_isattr(np,NV_EXPORT) && nv_isarray(np)) 1497*4887Schin { 1498*4887Schin nv_putsub(np,NIL(char*),0); 1499*4887Schin if(cp = nv_getval(np)) 1500*4887Schin cp = strdup(cp); 1501*4887Schin } 1502*4887Schin if(nv_isattr(np,NV_EXPORT|NV_NOFREE)) 1503*4887Schin { 1504*4887Schin if(nv_isref(np)) 1505*4887Schin { 1506*4887Schin nv_offattr(np,NV_NOFREE|NV_REF); 1507*4887Schin free((void*)np->nvalue.nrp); 1508*4887Schin np->nvalue.cp = 0; 1509*4887Schin } 1510*4887Schin if(!cp) 1511*4887Schin return; 1512*4887Schin } 1513*4887Schin if(nv_isarray(np)) 1514*4887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 1515*4887Schin _nv_unset(np,NV_RDONLY); 1516*4887Schin nv_setattr(np,0); 1517*4887Schin if(cp) 1518*4887Schin { 1519*4887Schin nv_putval(np,cp,0); 1520*4887Schin free((void*)cp); 1521*4887Schin } 1522*4887Schin } 1523*4887Schin 1524*4887Schin /* 1525*4887Schin * Currently this is a dummy, but someday will be needed 1526*4887Schin * for reference counting 1527*4887Schin */ 1528*4887Schin void nv_close(Namval_t *np) 1529*4887Schin { 1530*4887Schin NOT_USED(np); 1531*4887Schin } 1532*4887Schin 1533*4887Schin static void table_unset(register Dt_t *root, int flags, Dt_t *oroot) 1534*4887Schin { 1535*4887Schin register Namval_t *np,*nq; 1536*4887Schin for(np=(Namval_t*)dtfirst(root);np;np=nq) 1537*4887Schin { 1538*4887Schin _nv_unset(np,flags); 1539*4887Schin if(oroot && (nq=nv_search(nv_name(np),oroot,0)) && nv_isattr(nq,NV_EXPORT)) 1540*4887Schin sh_envput(sh.env,nq); 1541*4887Schin nq = (Namval_t*)dtnext(root,np); 1542*4887Schin dtdelete(root,np); 1543*4887Schin free((void*)np); 1544*4887Schin } 1545*4887Schin } 1546*4887Schin 1547*4887Schin /* 1548*4887Schin * 1549*4887Schin * Set the value of <np> to 0, and nullify any attributes 1550*4887Schin * that <np> may have had. Free any freeable space occupied 1551*4887Schin * by the value of <np>. If <np> denotes an array member, it 1552*4887Schin * will retain its attributes. 1553*4887Schin * <flags> can contain NV_RDONLY to override the readonly attribute 1554*4887Schin * being cleared. 1555*4887Schin */ 1556*4887Schin void _nv_unset(register Namval_t *np,int flags) 1557*4887Schin { 1558*4887Schin register union Value *up; 1559*4887Schin if(!(flags&NV_RDONLY) && nv_isattr (np,NV_RDONLY)) 1560*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np)); 1561*4887Schin if(is_afunction(np) && np->nvalue.ip) 1562*4887Schin { 1563*4887Schin register struct slnod *slp = (struct slnod*)(np->nvenv); 1564*4887Schin if(slp && !nv_isattr(np,NV_NOFREE)) 1565*4887Schin { 1566*4887Schin /* free function definition */ 1567*4887Schin register char *name=nv_name(np),*cp= strrchr(name,'.'); 1568*4887Schin if(cp) 1569*4887Schin { 1570*4887Schin Namval_t *npv; 1571*4887Schin *cp = 0; 1572*4887Schin npv = nv_open(name,sh.var_tree,NV_NOARRAY|NV_VARNAME|NV_NOADD); 1573*4887Schin *cp++ = '.'; 1574*4887Schin if(npv) 1575*4887Schin nv_setdisc(npv,cp,NIL(Namval_t*),(Namfun_t*)npv); 1576*4887Schin } 1577*4887Schin stakdelete(slp->slptr); 1578*4887Schin free((void*)np->nvalue.ip); 1579*4887Schin np->nvalue.ip = 0; 1580*4887Schin } 1581*4887Schin goto done; 1582*4887Schin } 1583*4887Schin if(sh.subshell && !nv_isnull(np)) 1584*4887Schin np = sh_assignok(np,0); 1585*4887Schin nv_offattr(np,NV_NODISC); 1586*4887Schin if(np->nvfun && !nv_isref(np)) 1587*4887Schin { 1588*4887Schin /* This function contains disc */ 1589*4887Schin if(!nv_local) 1590*4887Schin { 1591*4887Schin nv_local=1; 1592*4887Schin nv_putv(np,NIL(char*),flags,np->nvfun); 1593*4887Schin return; 1594*4887Schin } 1595*4887Schin /* called from disc, assign the actual value */ 1596*4887Schin nv_local=0; 1597*4887Schin } 1598*4887Schin up = &np->nvalue; 1599*4887Schin if(up->cp) 1600*4887Schin { 1601*4887Schin if(!nv_isattr (np, NV_NOFREE)) 1602*4887Schin free((void*)up->cp); 1603*4887Schin up->cp = 0; 1604*4887Schin } 1605*4887Schin done: 1606*4887Schin if(!nv_isarray(np) || !nv_arrayptr(np)) 1607*4887Schin { 1608*4887Schin if(nv_isref(np)) 1609*4887Schin free((void*)np->nvalue.nrp); 1610*4887Schin nv_setsize(np,0); 1611*4887Schin if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT)) 1612*4887Schin { 1613*4887Schin if(nv_isattr(np,NV_EXPORT) && !strchr(np->nvname,'[')) 1614*4887Schin env_delete(sh.env,nv_name(np)); 1615*4887Schin np->nvenv = 0; 1616*4887Schin nv_setattr(np,0); 1617*4887Schin } 1618*4887Schin else 1619*4887Schin nv_setattr(np,NV_MINIMAL); 1620*4887Schin } 1621*4887Schin } 1622*4887Schin 1623*4887Schin void nv_unset(register Namval_t *np) 1624*4887Schin { 1625*4887Schin _nv_unset(np,0); 1626*4887Schin } 1627*4887Schin 1628*4887Schin /* 1629*4887Schin * return the node pointer in the highest level scope 1630*4887Schin */ 1631*4887Schin Namval_t *nv_scoped(register Namval_t *np) 1632*4887Schin { 1633*4887Schin if(!dtvnext(sh.var_tree)) 1634*4887Schin return(np); 1635*4887Schin return(dtsearch(sh.var_tree,np)); 1636*4887Schin } 1637*4887Schin 1638*4887Schin #if 1 1639*4887Schin /* 1640*4887Schin * return space separated list of names of variables in given tree 1641*4887Schin */ 1642*4887Schin static char *tableval(Dt_t *root) 1643*4887Schin { 1644*4887Schin static Sfio_t *out; 1645*4887Schin register Namval_t *np; 1646*4887Schin register int first=1; 1647*4887Schin register Dt_t *base = dtview(root,0); 1648*4887Schin if(out) 1649*4887Schin sfseek(out,(Sfoff_t)0,SEEK_SET); 1650*4887Schin else 1651*4887Schin out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING); 1652*4887Schin for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np)) 1653*4887Schin { 1654*4887Schin if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE)) 1655*4887Schin { 1656*4887Schin if(!first) 1657*4887Schin sfputc(out,' '); 1658*4887Schin else 1659*4887Schin first = 0; 1660*4887Schin sfputr(out,np->nvname,-1); 1661*4887Schin } 1662*4887Schin } 1663*4887Schin sfputc(out,0); 1664*4887Schin if(base) 1665*4887Schin dtview(root,base); 1666*4887Schin return((char*)out->_data); 1667*4887Schin } 1668*4887Schin #endif 1669*4887Schin 1670*4887Schin #if SHOPT_OPTIMIZE 1671*4887Schin struct optimize 1672*4887Schin { 1673*4887Schin Namfun_t hdr; 1674*4887Schin char **ptr; 1675*4887Schin struct optimize *next; 1676*4887Schin Namval_t *np; 1677*4887Schin }; 1678*4887Schin 1679*4887Schin static struct optimize *opt_free; 1680*4887Schin 1681*4887Schin static void optimize_clear(Namval_t* np, Namfun_t *fp) 1682*4887Schin { 1683*4887Schin struct optimize *op = (struct optimize*)fp; 1684*4887Schin nv_stack(np,fp); 1685*4887Schin nv_stack(np,(Namfun_t*)0); 1686*4887Schin for(;op && op->np==np; op=op->next) 1687*4887Schin { 1688*4887Schin if(op->ptr) 1689*4887Schin { 1690*4887Schin *op->ptr = 0; 1691*4887Schin op->ptr = 0; 1692*4887Schin } 1693*4887Schin } 1694*4887Schin } 1695*4887Schin 1696*4887Schin static void put_optimize(Namval_t* np,const char *val,int flags,Namfun_t *fp) 1697*4887Schin { 1698*4887Schin nv_putv(np,val,flags,fp); 1699*4887Schin optimize_clear(np,fp); 1700*4887Schin } 1701*4887Schin 1702*4887Schin static const Namdisc_t optimize_disc = {sizeof(struct optimize),put_optimize}; 1703*4887Schin 1704*4887Schin void nv_optimize(Namval_t *np) 1705*4887Schin { 1706*4887Schin register Namfun_t *fp; 1707*4887Schin register struct optimize *op, *xp; 1708*4887Schin if(sh.argaddr) 1709*4887Schin { 1710*4887Schin for(fp=np->nvfun; fp; fp = fp->next) 1711*4887Schin { 1712*4887Schin if(fp->disc->getnum || fp->disc->getval) 1713*4887Schin { 1714*4887Schin sh.argaddr = 0; 1715*4887Schin return; 1716*4887Schin } 1717*4887Schin if(fp->disc== &optimize_disc) 1718*4887Schin break; 1719*4887Schin } 1720*4887Schin if((xp= (struct optimize*)fp) && xp->ptr==sh.argaddr) 1721*4887Schin return; 1722*4887Schin if(op = opt_free) 1723*4887Schin opt_free = op->next; 1724*4887Schin else 1725*4887Schin op=(struct optimize*)calloc(1,sizeof(struct optimize)); 1726*4887Schin op->ptr = sh.argaddr; 1727*4887Schin op->np = np; 1728*4887Schin if(xp) 1729*4887Schin { 1730*4887Schin op->hdr.disc = 0; 1731*4887Schin op->next = xp->next; 1732*4887Schin xp->next = op; 1733*4887Schin } 1734*4887Schin else 1735*4887Schin { 1736*4887Schin op->hdr.disc = &optimize_disc; 1737*4887Schin op->next = (struct optimize*)sh.optlist; 1738*4887Schin sh.optlist = (void*)op; 1739*4887Schin nv_stack(np,&op->hdr); 1740*4887Schin } 1741*4887Schin } 1742*4887Schin } 1743*4887Schin 1744*4887Schin void sh_optclear(Shell_t *shp, void *old) 1745*4887Schin { 1746*4887Schin register struct optimize *op,*opnext; 1747*4887Schin for(op=(struct optimize*)shp->optlist; op; op = opnext) 1748*4887Schin { 1749*4887Schin opnext = op->next; 1750*4887Schin if(op->ptr && op->hdr.disc) 1751*4887Schin { 1752*4887Schin nv_stack(op->np,&op->hdr); 1753*4887Schin nv_stack(op->np,(Namfun_t*)0); 1754*4887Schin } 1755*4887Schin op->next = opt_free; 1756*4887Schin opt_free = op; 1757*4887Schin } 1758*4887Schin shp->optlist = old; 1759*4887Schin } 1760*4887Schin 1761*4887Schin #else 1762*4887Schin # define optimize_clear(np,fp) 1763*4887Schin #endif /* SHOPT_OPTIMIZE */ 1764*4887Schin 1765*4887Schin /* 1766*4887Schin * Return a pointer to a character string that denotes the value 1767*4887Schin * of <np>. If <np> refers to an array, return a pointer to 1768*4887Schin * the value associated with the current index. 1769*4887Schin * 1770*4887Schin * If the value of <np> is an integer, the string returned will 1771*4887Schin * be overwritten by the next call to nv_getval. 1772*4887Schin * 1773*4887Schin * If <np> has no value, 0 is returned. 1774*4887Schin */ 1775*4887Schin 1776*4887Schin char *nv_getval(register Namval_t *np) 1777*4887Schin { 1778*4887Schin register union Value *up= &np->nvalue; 1779*4887Schin register int numeric; 1780*4887Schin #if SHOPT_OPTIMIZE 1781*4887Schin if(!nv_local && sh.argaddr) 1782*4887Schin nv_optimize(np); 1783*4887Schin #endif /* SHOPT_OPTIMIZE */ 1784*4887Schin if(!np->nvfun && !nv_isattr(np,NV_ARRAY|NV_INTEGER|NV_FUNCT|NV_REF|NV_TABLE)) 1785*4887Schin goto done; 1786*4887Schin if(nv_isref(np)) 1787*4887Schin { 1788*4887Schin sh.last_table = nv_reftable(np); 1789*4887Schin return(nv_name(nv_refnode(np))); 1790*4887Schin } 1791*4887Schin if(np->nvfun) 1792*4887Schin { 1793*4887Schin if(!nv_local) 1794*4887Schin { 1795*4887Schin nv_local=1; 1796*4887Schin return(nv_getv(np, np->nvfun)); 1797*4887Schin } 1798*4887Schin nv_local=0; 1799*4887Schin } 1800*4887Schin numeric = ((nv_isattr (np, NV_INTEGER)) != 0); 1801*4887Schin if(numeric) 1802*4887Schin { 1803*4887Schin Sflong_t ll; 1804*4887Schin if(!up->cp) 1805*4887Schin return("0"); 1806*4887Schin if(nv_isattr (np,NV_DOUBLE)) 1807*4887Schin { 1808*4887Schin Sfdouble_t ld; 1809*4887Schin double d; 1810*4887Schin char *format; 1811*4887Schin if(nv_isattr(np,NV_LONG)) 1812*4887Schin { 1813*4887Schin ld = *up->ldp; 1814*4887Schin if(nv_isattr (np,NV_EXPNOTE)) 1815*4887Schin format = "%.*Lg"; 1816*4887Schin else 1817*4887Schin format = "%.*Lf"; 1818*4887Schin sfprintf(sh.strbuf,format,nv_size(np),ld); 1819*4887Schin } 1820*4887Schin else 1821*4887Schin { 1822*4887Schin d = *up->dp; 1823*4887Schin if(nv_isattr (np,NV_EXPNOTE)) 1824*4887Schin format = "%.*g"; 1825*4887Schin else 1826*4887Schin format = "%.*f"; 1827*4887Schin sfprintf(sh.strbuf,format,nv_size(np),d); 1828*4887Schin } 1829*4887Schin return(sfstruse(sh.strbuf)); 1830*4887Schin } 1831*4887Schin else if(nv_isattr(np,NV_UNSIGN)) 1832*4887Schin { 1833*4887Schin if(nv_isattr (np,NV_LONG)) 1834*4887Schin ll = *(Sfulong_t*)up->llp; 1835*4887Schin else if(nv_isattr (np,NV_SHORT)) 1836*4887Schin ll = (uint16_t)up->s; 1837*4887Schin else 1838*4887Schin ll = *(uint32_t*)(up->lp); 1839*4887Schin } 1840*4887Schin else if(nv_isattr (np,NV_LONG)) 1841*4887Schin ll = *up->llp; 1842*4887Schin else if(nv_isattr (np,NV_SHORT)) 1843*4887Schin ll = up->s; 1844*4887Schin else 1845*4887Schin ll = *(up->lp); 1846*4887Schin if((numeric=nv_size(np))==10) 1847*4887Schin { 1848*4887Schin if(nv_isattr(np,NV_UNSIGN)) 1849*4887Schin { 1850*4887Schin sfprintf(sh.strbuf,"%I*u",sizeof(ll),ll); 1851*4887Schin return(sfstruse(sh.strbuf)); 1852*4887Schin } 1853*4887Schin numeric = 0; 1854*4887Schin } 1855*4887Schin return(fmtbasell(ll,numeric, numeric&&numeric!=10)); 1856*4887Schin } 1857*4887Schin done: 1858*4887Schin #if (_AST_VERSION>=20030127L) 1859*4887Schin /* 1860*4887Schin * if NV_RAW flag is on, return pointer to binary data 1861*4887Schin * otherwise, base64 encode the data and return this string 1862*4887Schin */ 1863*4887Schin if(up->cp && nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW)) 1864*4887Schin { 1865*4887Schin char *cp; 1866*4887Schin int size= nv_size(np), insize=(4*size)/3+size/45+8; 1867*4887Schin base64encode(up->cp, size, (void**)0, cp=getbuf(insize), insize, (void**)0); 1868*4887Schin return(cp); 1869*4887Schin } 1870*4887Schin #endif 1871*4887Schin if((numeric=nv_size(np)) && up->cp && up->cp[numeric]) 1872*4887Schin { 1873*4887Schin char *cp = getbuf(numeric+1); 1874*4887Schin memcpy(cp,up->cp,numeric); 1875*4887Schin cp[numeric]=0; 1876*4887Schin return(cp); 1877*4887Schin } 1878*4887Schin return ((char*)up->cp); 1879*4887Schin } 1880*4887Schin 1881*4887Schin Sfdouble_t nv_getnum(register Namval_t *np) 1882*4887Schin { 1883*4887Schin register union Value *up; 1884*4887Schin register Sfdouble_t r=0; 1885*4887Schin register char *str; 1886*4887Schin #if SHOPT_OPTIMIZE 1887*4887Schin if(!nv_local && sh.argaddr) 1888*4887Schin nv_optimize(np); 1889*4887Schin #endif /* SHOPT_OPTIMIZE */ 1890*4887Schin if(nv_istable(np)) 1891*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_number,nv_name(np)); 1892*4887Schin if(np->nvfun) 1893*4887Schin { 1894*4887Schin if(!nv_local) 1895*4887Schin { 1896*4887Schin nv_local=1; 1897*4887Schin return(nv_getn(np, np->nvfun)); 1898*4887Schin } 1899*4887Schin nv_local=0; 1900*4887Schin } 1901*4887Schin if(nv_isattr (np, NV_INTEGER)) 1902*4887Schin { 1903*4887Schin up= &np->nvalue; 1904*4887Schin if(!up->lp) 1905*4887Schin r = 0; 1906*4887Schin else if(nv_isattr(np, NV_DOUBLE)) 1907*4887Schin { 1908*4887Schin if(nv_isattr(np, NV_LONG)) 1909*4887Schin r = *up->ldp; 1910*4887Schin else 1911*4887Schin r = *up->dp; 1912*4887Schin } 1913*4887Schin else if(nv_isattr(np, NV_UNSIGN)) 1914*4887Schin { 1915*4887Schin if(nv_isattr(np, NV_LONG)) 1916*4887Schin r = (Sflong_t)*((Sfulong_t*)up->llp); 1917*4887Schin else if(nv_isattr(np, NV_SHORT)) 1918*4887Schin r = (Sflong_t)((uint16_t)up->s); 1919*4887Schin else 1920*4887Schin r = *((uint32_t*)up->lp); 1921*4887Schin } 1922*4887Schin else 1923*4887Schin { 1924*4887Schin if(nv_isattr(np, NV_LONG)) 1925*4887Schin r = *up->llp; 1926*4887Schin else if(nv_isattr(np, NV_SHORT)) 1927*4887Schin r = up->s; 1928*4887Schin else 1929*4887Schin r = *up->lp; 1930*4887Schin } 1931*4887Schin } 1932*4887Schin else if((str=nv_getval(np)) && *str!=0) 1933*4887Schin { 1934*4887Schin if(np->nvfun || nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL)) 1935*4887Schin { 1936*4887Schin while(*str=='0') 1937*4887Schin str++; 1938*4887Schin } 1939*4887Schin r = sh_arith(str); 1940*4887Schin } 1941*4887Schin return(r); 1942*4887Schin } 1943*4887Schin /* 1944*4887Schin * Give <np> the attributes <newatts,> and change its current 1945*4887Schin * value to conform to <newatts>. The <size> of left and right 1946*4887Schin * justified fields may be given. 1947*4887Schin */ 1948*4887Schin void nv_newattr (register Namval_t *np, unsigned newatts, int size) 1949*4887Schin { 1950*4887Schin register char *sp; 1951*4887Schin register char *cp = 0; 1952*4887Schin register unsigned int n; 1953*4887Schin Namarr_t *ap = 0; 1954*4887Schin int oldsize,oldatts; 1955*4887Schin 1956*4887Schin /* check for restrictions */ 1957*4887Schin if(sh_isoption(SH_RESTRICTED) && ((sp=nv_name(np))==nv_name(PATHNOD) || sp==nv_name(SHELLNOD) || sp==nv_name(ENVNOD) || sp==nv_name(FPATHNOD))) 1958*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np)); 1959*4887Schin /* handle attributes that do not change data separately */ 1960*4887Schin n = np->nvflag; 1961*4887Schin #if SHOPT_BSH 1962*4887Schin if(newatts&NV_EXPORT) 1963*4887Schin nv_offattr(np,NV_IMPORT); 1964*4887Schin #endif /* SHOPT_BSH */ 1965*4887Schin if(((n^newatts)&NV_EXPORT)) 1966*4887Schin { 1967*4887Schin /* record changes to the environment */ 1968*4887Schin if(n&NV_EXPORT) 1969*4887Schin env_delete(sh.env,nv_name(np)); 1970*4887Schin else 1971*4887Schin sh_envput(sh.env,np); 1972*4887Schin } 1973*4887Schin if((size==0||(n&NV_INTEGER)) && ((n^newatts)&~NV_NOCHANGE)==0) 1974*4887Schin { 1975*4887Schin if(size) 1976*4887Schin nv_setsize(np,size); 1977*4887Schin nv_offattr(np, ~NV_NOFREE); 1978*4887Schin nv_onattr(np, newatts); 1979*4887Schin return; 1980*4887Schin } 1981*4887Schin /* for an array, change all the elements */ 1982*4887Schin if((ap=nv_arrayptr(np)) && ap->nelem>0) 1983*4887Schin nv_putsub(np,NIL(char*),ARRAY_SCAN); 1984*4887Schin oldsize = nv_size(np); 1985*4887Schin oldatts = np->nvflag; 1986*4887Schin if(ap) /* add element to prevent array deletion */ 1987*4887Schin ap->nelem++; 1988*4887Schin do 1989*4887Schin { 1990*4887Schin nv_setsize(np,oldsize); 1991*4887Schin np->nvflag = oldatts; 1992*4887Schin if (sp = nv_getval(np)) 1993*4887Schin { 1994*4887Schin if(nv_isattr(np,NV_ZFILL)) 1995*4887Schin while(*sp=='0') sp++; 1996*4887Schin cp = (char*)malloc((n=strlen (sp)) + 1); 1997*4887Schin strcpy(cp, sp); 1998*4887Schin if(ap) 1999*4887Schin { 2000*4887Schin Namval_t *mp; 2001*4887Schin ap->nelem &= ~ARRAY_SCAN; 2002*4887Schin if(mp=nv_opensub(np)) 2003*4887Schin nv_onattr(mp,NV_NOFREE); 2004*4887Schin } 2005*4887Schin nv_unset(np); 2006*4887Schin if(ap) 2007*4887Schin ap->nelem |= ARRAY_SCAN; 2008*4887Schin if(size==0 && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL))) 2009*4887Schin size = n; 2010*4887Schin } 2011*4887Schin else 2012*4887Schin nv_unset(np); 2013*4887Schin nv_setsize(np,size); 2014*4887Schin np->nvflag &= NV_ARRAY; 2015*4887Schin np->nvflag |= newatts; 2016*4887Schin if (cp) 2017*4887Schin { 2018*4887Schin nv_putval (np, cp, NV_RDONLY); 2019*4887Schin free(cp); 2020*4887Schin } 2021*4887Schin } 2022*4887Schin while(ap && nv_nextsub(np)); 2023*4887Schin if(ap) 2024*4887Schin ap->nelem--; 2025*4887Schin return; 2026*4887Schin } 2027*4887Schin 2028*4887Schin #ifndef _NEXT_SOURCE 2029*4887Schin static char *oldgetenv(const char *string) 2030*4887Schin { 2031*4887Schin register char c0,c1; 2032*4887Schin register const char *cp, *sp; 2033*4887Schin register char **av = environ; 2034*4887Schin if(!string || (c0= *string)==0) 2035*4887Schin return(0); 2036*4887Schin if((c1=*++string)==0) 2037*4887Schin c1= '='; 2038*4887Schin while(cp = *av++) 2039*4887Schin { 2040*4887Schin if(cp[0]!=c0 || cp[1]!=c1) 2041*4887Schin continue; 2042*4887Schin sp = string; 2043*4887Schin while(*sp && *sp++ == *++cp); 2044*4887Schin if(*sp==0 && *++cp=='=') 2045*4887Schin return((char*)(cp+1)); 2046*4887Schin } 2047*4887Schin return(0); 2048*4887Schin } 2049*4887Schin 2050*4887Schin /* 2051*4887Schin * This version of getenv uses the hash storage to access environment values 2052*4887Schin */ 2053*4887Schin char *getenv(const char *name) 2054*4887Schin /*@ 2055*4887Schin assume name!=0; 2056*4887Schin @*/ 2057*4887Schin { 2058*4887Schin register Namval_t *np; 2059*4887Schin if(!sh.var_tree) 2060*4887Schin return(oldgetenv(name)); 2061*4887Schin if((np = nv_search(name,sh.var_tree,0)) && nv_isattr(np,NV_EXPORT)) 2062*4887Schin return(nv_getval(np)); 2063*4887Schin if(name[0] == 'P' && name[1] == 'A' && name[2] == 'T' && name[3] == 'H' && name[4] == 0) 2064*4887Schin return(oldgetenv(name)); 2065*4887Schin return(0); 2066*4887Schin } 2067*4887Schin #endif /* _NEXT_SOURCE */ 2068*4887Schin 2069*4887Schin #undef putenv 2070*4887Schin /* 2071*4887Schin * This version of putenv uses the hash storage to assign environment values 2072*4887Schin */ 2073*4887Schin int putenv(const char *name) 2074*4887Schin { 2075*4887Schin register Namval_t *np; 2076*4887Schin if(name) 2077*4887Schin { 2078*4887Schin np = nv_open(name,sh.var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN); 2079*4887Schin if(!strchr(name,'=')) 2080*4887Schin nv_unset(np); 2081*4887Schin } 2082*4887Schin return(0); 2083*4887Schin } 2084*4887Schin 2085*4887Schin 2086*4887Schin /* 2087*4887Schin * Override libast setenv() 2088*4887Schin */ 2089*4887Schin char* setenviron(const char *name) 2090*4887Schin { 2091*4887Schin register Namval_t *np; 2092*4887Schin if(name) 2093*4887Schin { 2094*4887Schin np = nv_open(name,sh.var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN); 2095*4887Schin if(strchr(name,'=')) 2096*4887Schin return(nv_getval(np)); 2097*4887Schin nv_unset(np); 2098*4887Schin } 2099*4887Schin return(""); 2100*4887Schin } 2101*4887Schin 2102*4887Schin /* 2103*4887Schin * copy <str1> to <str2> changing lower case to upper case 2104*4887Schin * <str2> must be big enough to hold <str1> 2105*4887Schin * <str1> and <str2> may point to the same place. 2106*4887Schin */ 2107*4887Schin 2108*4887Schin static void ltou(register char const *str1,register char *str2) 2109*4887Schin /*@ 2110*4887Schin assume str1!=0 && str2!=0; 2111*4887Schin return x satisfying strlen(in str1)==strlen(in str2); 2112*4887Schin @*/ 2113*4887Schin { 2114*4887Schin register int c; 2115*4887Schin for(; c= *((unsigned char*)str1); str1++,str2++) 2116*4887Schin { 2117*4887Schin if(islower(c)) 2118*4887Schin *str2 = toupper(c); 2119*4887Schin else 2120*4887Schin *str2 = c; 2121*4887Schin } 2122*4887Schin *str2 = 0; 2123*4887Schin } 2124*4887Schin 2125*4887Schin /* 2126*4887Schin * normalize <cp> and return pointer to subscript if any 2127*4887Schin */ 2128*4887Schin static char *lastdot(register char *cp) 2129*4887Schin { 2130*4887Schin register char *dp=cp, *ep=0; 2131*4887Schin register int c; 2132*4887Schin while(c= *cp++) 2133*4887Schin { 2134*4887Schin *dp++ = c; 2135*4887Schin if(c=='[') 2136*4887Schin ep = cp; 2137*4887Schin else if(c=='.') 2138*4887Schin { 2139*4887Schin if(*cp=='[') 2140*4887Schin { 2141*4887Schin ep = nv_endsubscript((Namval_t*)0,cp,0); 2142*4887Schin c = ep-cp; 2143*4887Schin memcpy(dp,cp,c); 2144*4887Schin dp = sh_checkid(dp+1,dp+c); 2145*4887Schin cp = ep; 2146*4887Schin } 2147*4887Schin ep = 0; 2148*4887Schin } 2149*4887Schin } 2150*4887Schin *dp = 0; 2151*4887Schin return(ep); 2152*4887Schin } 2153*4887Schin 2154*4887Schin /* 2155*4887Schin * Create a reference node from <np> to $np in dictionary <hp> 2156*4887Schin */ 2157*4887Schin void nv_setref(register Namval_t *np, Dt_t *hp, int flags) 2158*4887Schin { 2159*4887Schin register Namval_t *nq, *nr; 2160*4887Schin register char *ep,*cp; 2161*4887Schin if(nv_isref(np)) 2162*4887Schin return; 2163*4887Schin if(nv_isarray(np)) 2164*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np)); 2165*4887Schin if(!(cp=nv_getval(np))) 2166*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_noref,nv_name(np)); 2167*4887Schin if((ep = lastdot(cp)) && nv_isattr(np,NV_MINIMAL)) 2168*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np)); 2169*4887Schin if(!hp) 2170*4887Schin hp = sh.var_tree; 2171*4887Schin nr= nq = nv_open(cp, hp, flags|NV_NOREF); 2172*4887Schin while(nv_isref(nr)) 2173*4887Schin { 2174*4887Schin sh.last_table = nv_reftable(nr); 2175*4887Schin hp = nv_reftree(nr); 2176*4887Schin nr = nv_refnode(nr); 2177*4887Schin } 2178*4887Schin if(nr==np) 2179*4887Schin { 2180*4887Schin if(sh.namespace && nv_dict(sh.namespace)==hp) 2181*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np)); 2182*4887Schin /* bind to earlier scope, or add to global scope */ 2183*4887Schin if(!(hp=dtvnext(hp)) || (nq=nv_search((char*)np,hp,NV_ADD|HASH_BUCKET))==np) 2184*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np)); 2185*4887Schin } 2186*4887Schin if(ep) 2187*4887Schin { 2188*4887Schin /* cause subscript evaluation and return result */ 2189*4887Schin #if 0 2190*4887Schin nv_endsubscript(nq,ep,NV_ADD); 2191*4887Schin #endif 2192*4887Schin ep = nv_getsub(nq); 2193*4887Schin } 2194*4887Schin nv_unset(np); 2195*4887Schin np->nvalue.nrp = newof(0,struct Namref,1,0); 2196*4887Schin np->nvalue.nrp->np = nq; 2197*4887Schin np->nvalue.nrp->root = hp; 2198*4887Schin if(ep) 2199*4887Schin np->nvalue.nrp->sub = strdup(ep); 2200*4887Schin np->nvalue.nrp->table = sh.last_table; 2201*4887Schin nv_onattr(np,NV_REF|NV_NOFREE); 2202*4887Schin } 2203*4887Schin 2204*4887Schin /* 2205*4887Schin * get the scope corresponding to <index> 2206*4887Schin * whence uses the same values as lseeek() 2207*4887Schin */ 2208*4887Schin Shscope_t *sh_getscope(int index, int whence) 2209*4887Schin { 2210*4887Schin register struct sh_scoped *sp, *topmost; 2211*4887Schin if(whence==SEEK_CUR) 2212*4887Schin sp = &sh.st; 2213*4887Schin else 2214*4887Schin { 2215*4887Schin if ((struct sh_scoped*)sh.topscope != sh.st.self) 2216*4887Schin topmost = (struct sh_scoped*)sh.topscope; 2217*4887Schin else 2218*4887Schin topmost = &(sh.st); 2219*4887Schin sp = topmost; 2220*4887Schin if(whence==SEEK_SET) 2221*4887Schin { 2222*4887Schin int n =0; 2223*4887Schin while(sp = sp->prevst) 2224*4887Schin n++; 2225*4887Schin index = n - index; 2226*4887Schin sp = topmost; 2227*4887Schin } 2228*4887Schin } 2229*4887Schin if(index < 0) 2230*4887Schin return((Shscope_t*)0); 2231*4887Schin while(index-- && (sp = sp->prevst)); 2232*4887Schin return((Shscope_t*)sp); 2233*4887Schin } 2234*4887Schin 2235*4887Schin /* 2236*4887Schin * make <scoped> the top scope and return previous scope 2237*4887Schin */ 2238*4887Schin Shscope_t *sh_setscope(Shscope_t *scope) 2239*4887Schin { 2240*4887Schin Shscope_t *old = (Shscope_t*)sh.st.self; 2241*4887Schin *sh.st.self = sh.st; 2242*4887Schin sh.st = *((struct sh_scoped*)scope); 2243*4887Schin sh.var_tree = scope->var_tree; 2244*4887Schin return(old); 2245*4887Schin } 2246*4887Schin 2247*4887Schin void nv_unscope(void) 2248*4887Schin { 2249*4887Schin register Dt_t *root = sh.var_tree; 2250*4887Schin register Dt_t *dp = dtview(root,(Dt_t*)0); 2251*4887Schin table_unset(root,NV_RDONLY|NV_NOSCOPE,dp); 2252*4887Schin sh.var_tree=dp; 2253*4887Schin dtclose(root); 2254*4887Schin } 2255*4887Schin 2256*4887Schin /* 2257*4887Schin * The inverse of creating a reference node 2258*4887Schin */ 2259*4887Schin void nv_unref(register Namval_t *np) 2260*4887Schin { 2261*4887Schin Namval_t *nq; 2262*4887Schin if(!nv_isref(np)) 2263*4887Schin return; 2264*4887Schin nq = nv_refnode(np); 2265*4887Schin nv_offattr(np,NV_NOFREE|NV_REF); 2266*4887Schin free((void*)np->nvalue.nrp); 2267*4887Schin np->nvalue.cp = strdup(nv_name(nq)); 2268*4887Schin #if SHOPT_OPTIMIZE 2269*4887Schin { 2270*4887Schin Namfun_t *fp; 2271*4887Schin for(fp=nq->nvfun; fp; fp = fp->next) 2272*4887Schin { 2273*4887Schin if(fp->disc== &optimize_disc) 2274*4887Schin { 2275*4887Schin optimize_clear(nq,fp); 2276*4887Schin return; 2277*4887Schin } 2278*4887Schin } 2279*4887Schin } 2280*4887Schin #endif 2281*4887Schin } 2282*4887Schin 2283*4887Schin /* 2284*4887Schin * These following are for binary compatibility with the old hash library 2285*4887Schin * They will be removed someday 2286*4887Schin */ 2287*4887Schin 2288*4887Schin #if defined(__IMPORT__) && defined(__EXPORT__) 2289*4887Schin # define extern __EXPORT__ 2290*4887Schin #endif 2291*4887Schin 2292*4887Schin #undef hashscope 2293*4887Schin 2294*4887Schin extern Dt_t *hashscope(Dt_t *root) 2295*4887Schin { 2296*4887Schin return(dtvnext(root)); 2297*4887Schin } 2298*4887Schin 2299*4887Schin #undef hashfree 2300*4887Schin 2301*4887Schin extern Dt_t *hashfree(Dt_t *root) 2302*4887Schin { 2303*4887Schin Dt_t *dp = dtvnext(root); 2304*4887Schin dtclose(root); 2305*4887Schin return(dp); 2306*4887Schin } 2307*4887Schin 2308*4887Schin #undef hashname 2309*4887Schin 2310*4887Schin extern char *hashname(void *obj) 2311*4887Schin { 2312*4887Schin Namval_t *np = (Namval_t*)obj; 2313*4887Schin return(np->nvname); 2314*4887Schin } 2315*4887Schin 2316*4887Schin #undef hashlook 2317*4887Schin 2318*4887Schin extern void *hashlook(Dt_t *root, const char *name, int mode,int size) 2319*4887Schin { 2320*4887Schin NOT_USED(size); 2321*4887Schin return((void*)nv_search(name,root,mode)); 2322*4887Schin } 2323*4887Schin 2324*4887Schin char *nv_name(register Namval_t *np) 2325*4887Schin { 2326*4887Schin register Namval_t *table; 2327*4887Schin register Namfun_t *fp; 2328*4887Schin char *cp; 2329*4887Schin if(is_abuiltin(np) || is_afunction(np)) 2330*4887Schin return(np->nvname); 2331*4887Schin if(nv_istable(np)) 2332*4887Schin #if 1 2333*4887Schin sh.last_table = nv_parent(np); 2334*4887Schin #else 2335*4887Schin sh.last_table = nv_create(np,0, NV_LAST,(Namfun_t*)0); 2336*4887Schin #endif 2337*4887Schin else if(!nv_isref(np)) 2338*4887Schin { 2339*4887Schin for(fp= np->nvfun ; fp; fp=fp->next) 2340*4887Schin if(fp->disc && fp->disc->namef) 2341*4887Schin { 2342*4887Schin if(np==sh.last_table) 2343*4887Schin sh.last_table = 0; 2344*4887Schin return((*fp->disc->namef)(np,fp)); 2345*4887Schin } 2346*4887Schin } 2347*4887Schin if(!(table=sh.last_table) || *np->nvname=='.' || table==sh.namespace || np==table) 2348*4887Schin return(np->nvname); 2349*4887Schin cp = nv_name(table); 2350*4887Schin sfprintf(sh.strbuf,"%s.%s",cp,np->nvname); 2351*4887Schin return(sfstruse(sh.strbuf)); 2352*4887Schin } 2353*4887Schin 2354*4887Schin Namval_t *nv_lastdict(void) 2355*4887Schin { 2356*4887Schin return(sh.last_table); 2357*4887Schin } 2358*4887Schin 2359*4887Schin #undef nv_context 2360*4887Schin /* 2361*4887Schin * returns the data context for a builtin 2362*4887Schin */ 2363*4887Schin void *nv_context(Namval_t *np) 2364*4887Schin { 2365*4887Schin return((void*)np->nvfun); 2366*4887Schin } 2367*4887Schin 2368*4887Schin #define DISABLE /* proto workaround */ 2369*4887Schin 2370*4887Schin int nv_isnull DISABLE (register Namval_t *np) 2371*4887Schin { 2372*4887Schin return(nv_isnull(np)); 2373*4887Schin } 2374*4887Schin 2375*4887Schin #undef nv_setsize 2376*4887Schin int nv_setsize(register Namval_t *np, int size) 2377*4887Schin { 2378*4887Schin int oldsize = nv_size(np); 2379*4887Schin if(size>=0) 2380*4887Schin np->nvsize = size; 2381*4887Schin return(oldsize); 2382*4887Schin } 2383