14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1982-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin /* 224887Schin * AT&T Labs 234887Schin * 244887Schin */ 254887Schin 264887Schin #define putenv ___putenv 274887Schin 284887Schin #include "defs.h" 294887Schin #include <ctype.h> 304887Schin #include "variables.h" 314887Schin #include "path.h" 324887Schin #include "lexstates.h" 334887Schin #include "timeout.h" 344887Schin #include "FEATURE/externs" 354887Schin #include "streval.h" 364887Schin 37*8462SApril.Chin@Sun.COM #define NVCACHE 8 /* must be a power of 2 */ 38*8462SApril.Chin@Sun.COM #define Empty ((char*)(e_sptbnl+3)) 394887Schin static char *savesub = 0; 404887Schin 414887Schin #if !_lib_pathnative && _lib_uwin_path 424887Schin 434887Schin #define _lib_pathnative 1 444887Schin 454887Schin extern int uwin_path(const char*, char*, int); 464887Schin 474887Schin size_t 484887Schin pathnative(const char* path, char* buf, size_t siz) 494887Schin { 504887Schin return uwin_path(path, buf, siz); 514887Schin } 524887Schin 534887Schin #endif /* _lib_pathnative */ 544887Schin 554887Schin static void attstore(Namval_t*,void*); 564887Schin #ifndef _ENV_H 574887Schin static void pushnam(Namval_t*,void*); 584887Schin static char *staknam(Namval_t*, char*); 594887Schin #endif 60*8462SApril.Chin@Sun.COM static void ltou(char*); 61*8462SApril.Chin@Sun.COM static void utol(char*); 624887Schin static void rightjust(char*, int, int); 63*8462SApril.Chin@Sun.COM static char *lastdot(char*, int); 644887Schin 654887Schin struct adata 664887Schin { 67*8462SApril.Chin@Sun.COM Shell_t *sh; 68*8462SApril.Chin@Sun.COM Namval_t *tp; 69*8462SApril.Chin@Sun.COM char **argnam; 70*8462SApril.Chin@Sun.COM int attsize; 71*8462SApril.Chin@Sun.COM char *attval; 724887Schin }; 734887Schin 74*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 75*8462SApril.Chin@Sun.COM struct sh_type 76*8462SApril.Chin@Sun.COM { 77*8462SApril.Chin@Sun.COM void *previous; 78*8462SApril.Chin@Sun.COM Namval_t **nodes; 79*8462SApril.Chin@Sun.COM Namval_t *rp; 80*8462SApril.Chin@Sun.COM short numnodes; 81*8462SApril.Chin@Sun.COM short maxnodes; 82*8462SApril.Chin@Sun.COM }; 83*8462SApril.Chin@Sun.COM #endif /*SHOPT_TYPEDEF */ 84*8462SApril.Chin@Sun.COM 85*8462SApril.Chin@Sun.COM #if NVCACHE 86*8462SApril.Chin@Sun.COM struct Namcache 87*8462SApril.Chin@Sun.COM { 88*8462SApril.Chin@Sun.COM struct Cache_entry 89*8462SApril.Chin@Sun.COM { 90*8462SApril.Chin@Sun.COM Dt_t *root; 91*8462SApril.Chin@Sun.COM char *name; 92*8462SApril.Chin@Sun.COM Namval_t *np; 93*8462SApril.Chin@Sun.COM Namval_t *last_table; 94*8462SApril.Chin@Sun.COM int flags; 95*8462SApril.Chin@Sun.COM short size; 96*8462SApril.Chin@Sun.COM short len; 97*8462SApril.Chin@Sun.COM } entries[NVCACHE]; 98*8462SApril.Chin@Sun.COM short index; 99*8462SApril.Chin@Sun.COM short ok; 100*8462SApril.Chin@Sun.COM }; 101*8462SApril.Chin@Sun.COM static struct Namcache nvcache; 102*8462SApril.Chin@Sun.COM #endif 103*8462SApril.Chin@Sun.COM 1044887Schin char nv_local = 0; 1054887Schin #ifndef _ENV_H 1064887Schin static void(*nullscan)(Namval_t*,void*); 1074887Schin #endif 1084887Schin 1094887Schin #if ( SFIO_VERSION <= 20010201L ) 1104887Schin # define _data data 1114887Schin #endif 1124887Schin 1134887Schin #if !SHOPT_MULTIBYTE 1144887Schin # define mbchar(p) (*(unsigned char*)p++) 1154887Schin #endif /* SHOPT_MULTIBYTE */ 1164887Schin 1174887Schin /* ======== name value pair routines ======== */ 1184887Schin 1194887Schin #include "shnodes.h" 1204887Schin #include "builtins.h" 1214887Schin 1224887Schin static char *getbuf(size_t len) 1234887Schin { 1244887Schin static char *buf; 1254887Schin static size_t buflen; 1264887Schin if(buflen < len) 1274887Schin { 1284887Schin if(buflen==0) 1294887Schin buf = (char*)malloc(len); 1304887Schin else 1314887Schin buf = (char*)realloc(buf,len); 1324887Schin buflen = len; 1334887Schin } 1344887Schin return(buf); 1354887Schin } 1364887Schin 1374887Schin #ifdef _ENV_H 1384887Schin void sh_envput(Env_t* ep,Namval_t *np) 1394887Schin { 1404887Schin int offset = staktell(); 1414887Schin Namarr_t *ap = nv_arrayptr(np); 1424887Schin char *val; 1434887Schin if(ap) 1444887Schin { 1454887Schin if(ap->nelem&ARRAY_UNDEF) 1464887Schin nv_putsub(np,"0",0L); 1474887Schin else if(!(val=nv_getsub(np)) || strcmp(val,"0")) 1484887Schin return; 1494887Schin } 1504887Schin if(!(val = nv_getval(np))) 1514887Schin return; 1524887Schin stakputs(nv_name(np)); 1534887Schin stakputc('='); 1544887Schin stakputs(val); 1554887Schin stakseek(offset); 1564887Schin env_add(ep,stakptr(offset),ENV_STRDUP); 1574887Schin } 1584887Schin #endif 1594887Schin 1604887Schin /* 1614887Schin * output variable name in format for re-input 1624887Schin */ 1634887Schin void nv_outname(Sfio_t *out, char *name, int len) 1644887Schin { 1654887Schin const char *cp=name, *sp; 1664887Schin int c, offset = staktell(); 1674887Schin while(sp= strchr(cp,'[')) 1684887Schin { 1694887Schin if(len>0 && cp+len <= sp) 1704887Schin break; 1714887Schin sfwrite(out,cp,++sp-cp); 1724887Schin stakseek(offset); 173*8462SApril.Chin@Sun.COM while(c= *sp++) 1744887Schin { 1754887Schin if(c==']') 1764887Schin break; 1774887Schin else if(c=='\\') 1784887Schin { 1794887Schin if(*sp=='[' || *sp==']' || *sp=='\\') 1804887Schin c = *sp++; 1814887Schin } 1824887Schin stakputc(c); 1834887Schin } 1844887Schin stakputc(0); 1854887Schin sfputr(out,sh_fmtq(stakptr(offset)),-1); 1864887Schin if(len>0) 1874887Schin { 1884887Schin sfputc(out,']'); 1894887Schin return; 1904887Schin } 191*8462SApril.Chin@Sun.COM cp = sp-1; 1924887Schin } 1934887Schin if(*cp) 1944887Schin { 1954887Schin if(len>0) 1964887Schin sfwrite(out,cp,len); 1974887Schin else 1984887Schin sfputr(out,cp,-1); 1994887Schin } 2004887Schin stakseek(offset); 2014887Schin } 2024887Schin 203*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 204*8462SApril.Chin@Sun.COM Namval_t *nv_addnode(Namval_t* np, int remove) 205*8462SApril.Chin@Sun.COM { 206*8462SApril.Chin@Sun.COM register struct sh_type *sp = (struct sh_type*)sh.mktype; 207*8462SApril.Chin@Sun.COM register int i; 208*8462SApril.Chin@Sun.COM register char *name=0; 209*8462SApril.Chin@Sun.COM if(sp->numnodes==0 && !nv_isnull(np) && sh.last_table) 210*8462SApril.Chin@Sun.COM { 211*8462SApril.Chin@Sun.COM /* could be an redefine */ 212*8462SApril.Chin@Sun.COM Dt_t *root = nv_dict(sh.last_table); 213*8462SApril.Chin@Sun.COM sp->rp = np; 214*8462SApril.Chin@Sun.COM nv_delete(np,root,NV_NOFREE); 215*8462SApril.Chin@Sun.COM np = nv_search(sp->rp->nvname,root,NV_ADD); 216*8462SApril.Chin@Sun.COM } 217*8462SApril.Chin@Sun.COM if(sp->numnodes && memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1)) 218*8462SApril.Chin@Sun.COM { 219*8462SApril.Chin@Sun.COM name = (sp->nodes[0])->nvname; 220*8462SApril.Chin@Sun.COM i = strlen(name); 221*8462SApril.Chin@Sun.COM if(memcmp(np->nvname,name,i)) 222*8462SApril.Chin@Sun.COM return(np); 223*8462SApril.Chin@Sun.COM } 224*8462SApril.Chin@Sun.COM if(sp->rp && sp->numnodes) 225*8462SApril.Chin@Sun.COM { 226*8462SApril.Chin@Sun.COM /* check for a redefine */ 227*8462SApril.Chin@Sun.COM if(name && np->nvname[i]=='.' && np->nvname[i+1]=='_' && np->nvname[i+2]==0) 228*8462SApril.Chin@Sun.COM sp->rp = 0; 229*8462SApril.Chin@Sun.COM else 230*8462SApril.Chin@Sun.COM { 231*8462SApril.Chin@Sun.COM Dt_t *root = nv_dict(sh.last_table); 232*8462SApril.Chin@Sun.COM nv_delete(sp->nodes[0],root,NV_NOFREE); 233*8462SApril.Chin@Sun.COM dtinsert(root,sp->rp); 234*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_redef,sp->nodes[0]->nvname); 235*8462SApril.Chin@Sun.COM } 236*8462SApril.Chin@Sun.COM } 237*8462SApril.Chin@Sun.COM for(i=0; i < sp->numnodes; i++) 238*8462SApril.Chin@Sun.COM { 239*8462SApril.Chin@Sun.COM if(np == sp->nodes[i]) 240*8462SApril.Chin@Sun.COM { 241*8462SApril.Chin@Sun.COM if(remove) 242*8462SApril.Chin@Sun.COM { 243*8462SApril.Chin@Sun.COM while(++i < sp->numnodes) 244*8462SApril.Chin@Sun.COM sp->nodes[i-1] = sp->nodes[i]; 245*8462SApril.Chin@Sun.COM sp->numnodes--; 246*8462SApril.Chin@Sun.COM } 247*8462SApril.Chin@Sun.COM return(np); 248*8462SApril.Chin@Sun.COM } 249*8462SApril.Chin@Sun.COM } 250*8462SApril.Chin@Sun.COM if(remove) 251*8462SApril.Chin@Sun.COM return(np); 252*8462SApril.Chin@Sun.COM if(sp->numnodes==sp->maxnodes) 253*8462SApril.Chin@Sun.COM { 254*8462SApril.Chin@Sun.COM sp->maxnodes += 20; 255*8462SApril.Chin@Sun.COM sp->nodes = (Namval_t**)realloc(sp->nodes,sizeof(Namval_t*)*sp->maxnodes); 256*8462SApril.Chin@Sun.COM } 257*8462SApril.Chin@Sun.COM sp->nodes[sp->numnodes++] = np; 258*8462SApril.Chin@Sun.COM return(np); 259*8462SApril.Chin@Sun.COM } 260*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 261*8462SApril.Chin@Sun.COM 262*8462SApril.Chin@Sun.COM /* 263*8462SApril.Chin@Sun.COM * given a list of assignments, determine <name> is on the list 264*8462SApril.Chin@Sun.COM returns a pointer to the argnod on the list or NULL 265*8462SApril.Chin@Sun.COM */ 266*8462SApril.Chin@Sun.COM struct argnod *nv_onlist(struct argnod *arg, const char *name) 267*8462SApril.Chin@Sun.COM { 268*8462SApril.Chin@Sun.COM char *cp; 269*8462SApril.Chin@Sun.COM int len = strlen(name); 270*8462SApril.Chin@Sun.COM for(;arg; arg=arg->argnxt.ap) 271*8462SApril.Chin@Sun.COM { 272*8462SApril.Chin@Sun.COM if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE))) 273*8462SApril.Chin@Sun.COM cp = ((struct fornod*)arg->argchn.ap)->fornam; 274*8462SApril.Chin@Sun.COM else 275*8462SApril.Chin@Sun.COM cp = arg->argval; 276*8462SApril.Chin@Sun.COM if(memcmp(cp,name,len)==0 && (cp[len]==0 || cp[len]=='=')) 277*8462SApril.Chin@Sun.COM return(arg); 278*8462SApril.Chin@Sun.COM } 279*8462SApril.Chin@Sun.COM return(0); 280*8462SApril.Chin@Sun.COM } 281*8462SApril.Chin@Sun.COM 2824887Schin /* 2834887Schin * Perform parameter assignment for a linked list of parameters 2844887Schin * <flags> contains attributes for the parameters 2854887Schin */ 2864887Schin void nv_setlist(register struct argnod *arg,register int flags) 2874887Schin { 288*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 2894887Schin register char *cp; 290*8462SApril.Chin@Sun.COM register Namval_t *np, *mp; 291*8462SApril.Chin@Sun.COM char *trap=shp->st.trap[SH_DEBUGTRAP]; 292*8462SApril.Chin@Sun.COM char *prefix = shp->prefix; 2934887Schin int traceon = (sh_isoption(SH_XTRACE)!=0); 2944887Schin int array = (flags&(NV_ARRAY|NV_IARRAY)); 295*8462SApril.Chin@Sun.COM Namarr_t *ap; 296*8462SApril.Chin@Sun.COM Namval_t node; 297*8462SApril.Chin@Sun.COM struct Namref nr; 298*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 299*8462SApril.Chin@Sun.COM int maketype = flags&NV_TYPE; 300*8462SApril.Chin@Sun.COM struct sh_type shtp; 301*8462SApril.Chin@Sun.COM if(maketype) 302*8462SApril.Chin@Sun.COM { 303*8462SApril.Chin@Sun.COM shtp.previous = shp->mktype; 304*8462SApril.Chin@Sun.COM shp->mktype=(void*)&shtp; 305*8462SApril.Chin@Sun.COM shtp.numnodes=0; 306*8462SApril.Chin@Sun.COM shtp.maxnodes = 20; 307*8462SApril.Chin@Sun.COM shtp.rp = 0; 308*8462SApril.Chin@Sun.COM shtp.nodes =(Namval_t**)malloc(shtp.maxnodes*sizeof(Namval_t*)); 309*8462SApril.Chin@Sun.COM } 310*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF*/ 311*8462SApril.Chin@Sun.COM flags &= ~(NV_TYPE|NV_ARRAY|NV_IARRAY); 3124887Schin if(sh_isoption(SH_ALLEXPORT)) 3134887Schin flags |= NV_EXPORT; 314*8462SApril.Chin@Sun.COM if(shp->prefix) 3154887Schin { 3164887Schin flags &= ~(NV_IDENT|NV_EXPORT); 3174887Schin flags |= NV_VARNAME; 3184887Schin } 3194887Schin for(;arg; arg=arg->argnxt.ap) 3204887Schin { 321*8462SApril.Chin@Sun.COM shp->used_pos = 0; 3224887Schin if(arg->argflag&ARG_MAC) 323*8462SApril.Chin@Sun.COM { 324*8462SApril.Chin@Sun.COM shp->prefix = 0; 325*8462SApril.Chin@Sun.COM cp = sh_mactrim(shp,arg->argval,(flags&NV_NOREF)?-3:-1); 326*8462SApril.Chin@Sun.COM shp->prefix = prefix; 327*8462SApril.Chin@Sun.COM } 3284887Schin else 3294887Schin { 3304887Schin stakseek(0); 331*8462SApril.Chin@Sun.COM if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE))) 3324887Schin { 3334887Schin int flag = (NV_VARNAME|NV_ARRAY|NV_ASSIGN); 334*8462SApril.Chin@Sun.COM int sub=0; 3354887Schin struct fornod *fp=(struct fornod*)arg->argchn.ap; 3364887Schin register Shnode_t *tp=fp->fortre; 337*8462SApril.Chin@Sun.COM flag |= (flags&(NV_NOSCOPE|NV_STATIC)); 3384887Schin if(arg->argflag&ARG_QUOTED) 339*8462SApril.Chin@Sun.COM cp = sh_mactrim(shp,fp->fornam,-1); 3404887Schin else 3414887Schin cp = fp->fornam; 342*8462SApril.Chin@Sun.COM error_info.line = fp->fortyp-shp->st.firstline; 343*8462SApril.Chin@Sun.COM if(shp->fn_depth && (Namval_t*)tp->com.comnamp==SYSTYPESET) 3444887Schin flag |= NV_NOSCOPE; 3454887Schin if(prefix && tp->com.comset && *cp=='[') 3464887Schin { 347*8462SApril.Chin@Sun.COM shp->prefix = 0; 348*8462SApril.Chin@Sun.COM np = nv_open(prefix,shp->var_tree,flag); 349*8462SApril.Chin@Sun.COM shp->prefix = prefix; 3504887Schin if(np) 3514887Schin { 352*8462SApril.Chin@Sun.COM if(nv_isvtree(np) && !nv_isarray(np)) 3534887Schin { 3544887Schin stakputc('.'); 3554887Schin stakputs(cp); 3564887Schin cp = stakfreeze(1); 3574887Schin } 3584887Schin nv_close(np); 3594887Schin } 3604887Schin } 361*8462SApril.Chin@Sun.COM np = nv_open(cp,shp->var_tree,flag|NV_ASSIGN); 362*8462SApril.Chin@Sun.COM if((flags&NV_STATIC) && !nv_isnull(np)) 363*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 364*8462SApril.Chin@Sun.COM goto check_type; 365*8462SApril.Chin@Sun.COM #else 366*8462SApril.Chin@Sun.COM continue; 367*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 3684887Schin if(array) 3694887Schin { 370*8462SApril.Chin@Sun.COM if(!(arg->argflag&ARG_APPEND)) 3714887Schin nv_unset(np); 3724887Schin if(array&NV_ARRAY) 3734887Schin { 3744887Schin nv_setarray(np,nv_associative); 3754887Schin } 3764887Schin else 3774887Schin { 3784887Schin nv_onattr(np,NV_ARRAY); 3794887Schin } 380*8462SApril.Chin@Sun.COM if(tp->tre.tretyp!=TLST && !tp->com.comset && !tp->com.comarg) 381*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 382*8462SApril.Chin@Sun.COM goto check_type; 383*8462SApril.Chin@Sun.COM #else 384*8462SApril.Chin@Sun.COM continue; 385*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 3864887Schin } 3874887Schin /* check for array assignment */ 3884887Schin if(tp->tre.tretyp!=TLST && tp->com.comarg && !tp->com.comset && !((mp=tp->com.comnamp) && nv_isattr(mp,BLT_DCL))) 3894887Schin { 3904887Schin int argc; 391*8462SApril.Chin@Sun.COM Dt_t *last_root = shp->last_root; 392*8462SApril.Chin@Sun.COM char **argv = sh_argbuild(shp,&argc,&tp->com,0); 393*8462SApril.Chin@Sun.COM shp->last_root = last_root; 394*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 395*8462SApril.Chin@Sun.COM if(shp->mktype && shp->dot_depth==0 && np==((struct sh_type*)shp->mktype)->nodes[0]) 396*8462SApril.Chin@Sun.COM { 397*8462SApril.Chin@Sun.COM shp->mktype = 0; 398*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),"%s: not a known type name",argv[0]); 399*8462SApril.Chin@Sun.COM } 400*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 4014887Schin if(!(arg->argflag&ARG_APPEND)) 4024887Schin { 403*8462SApril.Chin@Sun.COM if(!nv_isarray(np) || ((ap=nv_arrayptr(np)) && (ap->nelem&ARRAY_MASK))) 404*8462SApril.Chin@Sun.COM nv_unset(np); 4054887Schin } 4064887Schin nv_setvec(np,(arg->argflag&ARG_APPEND),argc,argv); 4074887Schin if(traceon || trap) 4084887Schin { 4094887Schin int n = -1; 4104887Schin char *name = nv_name(np); 4114887Schin if(arg->argflag&ARG_APPEND) 4124887Schin n = '+'; 4134887Schin if(trap) 414*8462SApril.Chin@Sun.COM sh_debug(shp,trap,name,(char*)0,argv,(arg->argflag&ARG_APPEND)|ARG_ASSIGN); 4154887Schin if(traceon) 4164887Schin { 4174887Schin sh_trace(NIL(char**),0); 4184887Schin sfputr(sfstderr,name,n); 4194887Schin sfwrite(sfstderr,"=( ",3); 4204887Schin while(cp= *argv++) 4214887Schin sfputr(sfstderr,sh_fmtq(cp),' '); 4224887Schin sfwrite(sfstderr,")\n",2); 4234887Schin } 4244887Schin } 425*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 426*8462SApril.Chin@Sun.COM goto check_type; 427*8462SApril.Chin@Sun.COM #else 4284887Schin continue; 429*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 4304887Schin } 431*8462SApril.Chin@Sun.COM if((tp->tre.tretyp&COMMSK)==TFUN) 432*8462SApril.Chin@Sun.COM goto skip; 4334887Schin if(tp->tre.tretyp==TLST || !tp->com.comset || tp->com.comset->argval[0]!='[') 4344887Schin { 435*8462SApril.Chin@Sun.COM if(tp->tre.tretyp!=TLST && !tp->com.comnamp && tp->com.comset && tp->com.comset->argval[0]==0 && tp->com.comset->argchn.ap) 436*8462SApril.Chin@Sun.COM { 437*8462SApril.Chin@Sun.COM if(prefix) 438*8462SApril.Chin@Sun.COM cp = stakcopy(nv_name(np)); 439*8462SApril.Chin@Sun.COM shp->prefix = cp; 440*8462SApril.Chin@Sun.COM if(tp->com.comset->argval[1]=='[') 441*8462SApril.Chin@Sun.COM { 442*8462SApril.Chin@Sun.COM if((arg->argflag&ARG_APPEND) && (!nv_isarray(np) || (nv_aindex(np)>=0))) 443*8462SApril.Chin@Sun.COM nv_unset(np); 444*8462SApril.Chin@Sun.COM if(!(array&NV_IARRAY) && !(tp->com.comset->argflag&ARG_MESSAGE)) 445*8462SApril.Chin@Sun.COM nv_setarray(np,nv_associative); 446*8462SApril.Chin@Sun.COM } 447*8462SApril.Chin@Sun.COM nv_setlist(tp->com.comset,flags); 448*8462SApril.Chin@Sun.COM shp->prefix = prefix; 449*8462SApril.Chin@Sun.COM if(tp->com.comset->argval[1]!='[') 450*8462SApril.Chin@Sun.COM nv_setvtree(np); 451*8462SApril.Chin@Sun.COM nv_close(np); 452*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 453*8462SApril.Chin@Sun.COM goto check_type; 454*8462SApril.Chin@Sun.COM #else 455*8462SApril.Chin@Sun.COM continue; 456*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 457*8462SApril.Chin@Sun.COM } 4584887Schin if(*cp!='.' && *cp!='[' && strchr(cp,'[')) 4594887Schin { 4604887Schin nv_close(np); 461*8462SApril.Chin@Sun.COM np = nv_open(cp,shp->var_tree,flag); 4624887Schin } 463*8462SApril.Chin@Sun.COM if(arg->argflag&ARG_APPEND) 464*8462SApril.Chin@Sun.COM { 465*8462SApril.Chin@Sun.COM if(nv_isarray(np)) 466*8462SApril.Chin@Sun.COM { 467*8462SApril.Chin@Sun.COM if((sub=nv_aimax(np)) < 0 && nv_arrayptr(np)) 468*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_badappend,nv_name(np)); 469*8462SApril.Chin@Sun.COM if(sub>=0) 470*8462SApril.Chin@Sun.COM sub++; 471*8462SApril.Chin@Sun.COM } 472*8462SApril.Chin@Sun.COM if(!nv_isnull(np) && np->nvalue.cp!=Empty && !nv_isvtree(np)) 473*8462SApril.Chin@Sun.COM sub=1; 474*8462SApril.Chin@Sun.COM } 475*8462SApril.Chin@Sun.COM else if(np->nvalue.cp && np->nvalue.cp!=Empty && !nv_type(np)) 476*8462SApril.Chin@Sun.COM { 477*8462SApril.Chin@Sun.COM _nv_unset(np,NV_EXPORT); 478*8462SApril.Chin@Sun.COM } 4794887Schin } 4804887Schin else 4814887Schin { 482*8462SApril.Chin@Sun.COM if(!(arg->argflag&ARG_APPEND)) 483*8462SApril.Chin@Sun.COM _nv_unset(np,NV_EXPORT); 484*8462SApril.Chin@Sun.COM if(!sh_isoption(SH_BASH) && !(array&NV_IARRAY) && !nv_isarray(np)) 4854887Schin nv_setarray(np,nv_associative); 4864887Schin } 487*8462SApril.Chin@Sun.COM skip: 488*8462SApril.Chin@Sun.COM if(sub>0) 489*8462SApril.Chin@Sun.COM { 490*8462SApril.Chin@Sun.COM sfprintf(stkstd,"%s[%d]",prefix?nv_name(np):cp,sub); 491*8462SApril.Chin@Sun.COM shp->prefix = stakfreeze(1); 492*8462SApril.Chin@Sun.COM nv_putsub(np,(char*)0,ARRAY_ADD|ARRAY_FILL|sub); 493*8462SApril.Chin@Sun.COM } 494*8462SApril.Chin@Sun.COM else if(prefix) 495*8462SApril.Chin@Sun.COM shp->prefix = stakcopy(nv_name(np)); 496*8462SApril.Chin@Sun.COM else 497*8462SApril.Chin@Sun.COM shp->prefix = cp; 498*8462SApril.Chin@Sun.COM shp->last_table = 0; 499*8462SApril.Chin@Sun.COM memset(&nr,0,sizeof(nr)); 500*8462SApril.Chin@Sun.COM memcpy(&node,L_ARGNOD,sizeof(node)); 501*8462SApril.Chin@Sun.COM L_ARGNOD->nvalue.nrp = &nr; 502*8462SApril.Chin@Sun.COM nr.np = np; 503*8462SApril.Chin@Sun.COM nr.root = shp->last_root; 504*8462SApril.Chin@Sun.COM nr.table = shp->last_table; 505*8462SApril.Chin@Sun.COM L_ARGNOD->nvflag = NV_REF|NV_NOFREE; 506*8462SApril.Chin@Sun.COM L_ARGNOD->nvfun = 0; 5074887Schin sh_exec(tp,sh_isstate(SH_ERREXIT)); 508*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 509*8462SApril.Chin@Sun.COM if(!maketype) 510*8462SApril.Chin@Sun.COM #endif 511*8462SApril.Chin@Sun.COM { 512*8462SApril.Chin@Sun.COM L_ARGNOD->nvalue.nrp = node.nvalue.nrp; 513*8462SApril.Chin@Sun.COM L_ARGNOD->nvflag = node.nvflag; 514*8462SApril.Chin@Sun.COM L_ARGNOD->nvfun = node.nvfun; 515*8462SApril.Chin@Sun.COM } 516*8462SApril.Chin@Sun.COM shp->prefix = prefix; 5174887Schin if(nv_isarray(np) && (mp=nv_opensub(np))) 5184887Schin np = mp; 519*8462SApril.Chin@Sun.COM while(tp->tre.tretyp==TLST) 520*8462SApril.Chin@Sun.COM { 521*8462SApril.Chin@Sun.COM if(!tp->lst.lstlef || !tp->lst.lstlef->tre.tretyp==TCOM || tp->lst.lstlef->com.comarg || tp->lst.lstlef->com.comset && tp->lst.lstlef->com.comset->argval[0]!='[') 522*8462SApril.Chin@Sun.COM break; 523*8462SApril.Chin@Sun.COM tp = tp->lst.lstrit; 524*8462SApril.Chin@Sun.COM 525*8462SApril.Chin@Sun.COM } 526*8462SApril.Chin@Sun.COM if(!nv_isarray(np) && (tp->com.comarg || !tp->com.comset || tp->com.comset->argval[0]!='[')) 527*8462SApril.Chin@Sun.COM nv_setvtree(np); 528*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 529*8462SApril.Chin@Sun.COM goto check_type; 530*8462SApril.Chin@Sun.COM #else 5314887Schin continue; 532*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5334887Schin } 5344887Schin cp = arg->argval; 535*8462SApril.Chin@Sun.COM mp = 0; 5364887Schin } 537*8462SApril.Chin@Sun.COM np = nv_open(cp,shp->var_tree,flags); 538*8462SApril.Chin@Sun.COM if(!np->nvfun && (flags&NV_NOREF)) 5394887Schin { 540*8462SApril.Chin@Sun.COM if(shp->used_pos) 5414887Schin nv_onattr(np,NV_PARAM); 5424887Schin else 5434887Schin nv_offattr(np,NV_PARAM); 5444887Schin } 5454887Schin if(traceon || trap) 5464887Schin { 5474887Schin register char *sp=cp; 5484887Schin char *name=nv_name(np); 5494887Schin char *sub=0; 5504887Schin int append = 0; 5514887Schin if(nv_isarray(np)) 5524887Schin sub = savesub; 553*8462SApril.Chin@Sun.COM if(cp=lastdot(sp,'=')) 5544887Schin { 5554887Schin if(cp[-1]=='+') 5564887Schin append = ARG_APPEND; 5574887Schin cp++; 5584887Schin } 5594887Schin if(traceon) 5604887Schin { 5614887Schin sh_trace(NIL(char**),0); 5624887Schin nv_outname(sfstderr,name,-1); 5634887Schin if(sub) 5644887Schin sfprintf(sfstderr,"[%s]",sh_fmtq(sub)); 5654887Schin if(cp) 5664887Schin { 5674887Schin if(append) 5684887Schin sfputc(sfstderr,'+'); 5694887Schin sfprintf(sfstderr,"=%s\n",sh_fmtq(cp)); 5704887Schin } 5714887Schin } 5724887Schin if(trap) 5734887Schin { 5744887Schin char *av[2]; 5754887Schin av[0] = cp; 5764887Schin av[1] = 0; 577*8462SApril.Chin@Sun.COM sh_debug(shp,trap,name,sub,av,append); 5784887Schin } 5794887Schin } 580*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 581*8462SApril.Chin@Sun.COM check_type: 582*8462SApril.Chin@Sun.COM if(maketype) 583*8462SApril.Chin@Sun.COM { 584*8462SApril.Chin@Sun.COM nv_open(shtp.nodes[0]->nvname,shp->var_tree,NV_ASSIGN|NV_VARNAME|NV_NOADD|NV_NOFAIL); 585*8462SApril.Chin@Sun.COM np = nv_mktype(shtp.nodes,shtp.numnodes); 586*8462SApril.Chin@Sun.COM free((void*)shtp.nodes); 587*8462SApril.Chin@Sun.COM shp->mktype = shtp.previous; 588*8462SApril.Chin@Sun.COM maketype = 0; 589*8462SApril.Chin@Sun.COM shp->prefix = 0; 590*8462SApril.Chin@Sun.COM if(nr.np == np) 591*8462SApril.Chin@Sun.COM { 592*8462SApril.Chin@Sun.COM L_ARGNOD->nvalue.nrp = node.nvalue.nrp; 593*8462SApril.Chin@Sun.COM L_ARGNOD->nvflag = node.nvflag; 594*8462SApril.Chin@Sun.COM L_ARGNOD->nvfun = node.nvfun; 595*8462SApril.Chin@Sun.COM } 596*8462SApril.Chin@Sun.COM } 597*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5984887Schin } 5994887Schin } 6004887Schin 6014887Schin /* 6024887Schin * copy the subscript onto the stack 6034887Schin */ 6044887Schin static void stak_subscript(const char *sub, int last) 6054887Schin { 6064887Schin register int c; 6074887Schin stakputc('['); 6084887Schin while(c= *sub++) 6094887Schin { 6104887Schin if(c=='[' || c==']' || c=='\\') 6114887Schin stakputc('\\'); 6124887Schin stakputc(c); 6134887Schin } 6144887Schin stakputc(last); 6154887Schin } 6164887Schin 6174887Schin /* 6184887Schin * construct a new name from a prefix and base name on the stack 6194887Schin */ 6204887Schin static char *copystack(const char *prefix, register const char *name, const char *sub) 6214887Schin { 6224887Schin register int last=0,offset = staktell(); 6234887Schin if(prefix) 6244887Schin { 6254887Schin stakputs(prefix); 6264887Schin if(*stakptr(staktell()-1)=='.') 6274887Schin stakseek(staktell()-1); 6284887Schin if(*name=='.' && name[1]=='[') 6294887Schin last = staktell()+2; 630*8462SApril.Chin@Sun.COM if(*name!='[' && *name!='.' && *name!='=' && *name!='+') 631*8462SApril.Chin@Sun.COM stakputc('.'); 632*8462SApril.Chin@Sun.COM if(*name=='.' && (name[1]=='=' || name[1]==0)) 6334887Schin stakputc('.'); 6344887Schin } 6354887Schin if(last) 6364887Schin { 6374887Schin stakputs(name); 6384887Schin if(sh_checkid(stakptr(last),(char*)0)) 6394887Schin stakseek(staktell()-2); 6404887Schin } 6414887Schin if(sub) 6424887Schin stak_subscript(sub,']'); 6434887Schin if(!last) 6444887Schin stakputs(name); 6454887Schin stakputc(0); 6464887Schin return(stakptr(offset)); 6474887Schin } 6484887Schin 6494887Schin /* 6504887Schin * grow this stack string <name> by <n> bytes and move from cp-1 to end 6514887Schin * right by <n>. Returns beginning of string on the stack 6524887Schin */ 6534887Schin static char *stack_extend(const char *cname, char *cp, int n) 6544887Schin { 6554887Schin register char *name = (char*)cname; 6564887Schin int offset = name - stakptr(0); 6574887Schin int m = cp-name; 6584887Schin stakseek(strlen(name)+n+1); 6594887Schin name = stakptr(offset); 6604887Schin cp = name + m; 6614887Schin m = strlen(cp)+1; 6624887Schin while(m-->0) 6634887Schin cp[n+m]=cp[m]; 6644887Schin return((char*)name); 6654887Schin } 6664887Schin 667*8462SApril.Chin@Sun.COM Namval_t *nv_create(const char *name, Dt_t *root, int flags, Namfun_t *dp) 6684887Schin { 669*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 6704887Schin char *cp=(char*)name, *sp, *xp; 6714887Schin register int c; 6724887Schin register Namval_t *np=0, *nq=0; 6734887Schin Namfun_t *fp=0; 6744887Schin long mode, add=0; 6754887Schin int copy=1,isref,top=0,noscope=(flags&NV_NOSCOPE); 676*8462SApril.Chin@Sun.COM if(root==shp->var_tree) 6774887Schin { 6784887Schin if(dtvnext(root)) 6794887Schin top = 1; 6804887Schin else 6814887Schin flags &= ~NV_NOSCOPE; 6824887Schin } 6834887Schin if(!dp->disc) 684*8462SApril.Chin@Sun.COM copy = dp->nofree&1; 6854887Schin if(*cp=='.') 6864887Schin cp++; 6874887Schin while(1) 6884887Schin { 6894887Schin switch(c = *(unsigned char*)(sp = cp)) 6904887Schin { 6914887Schin case '[': 6924887Schin if(flags&NV_NOARRAY) 6934887Schin { 6944887Schin dp->last = cp; 6954887Schin return(np); 6964887Schin } 6974887Schin cp = nv_endsubscript((Namval_t*)0,sp,0); 6984887Schin if(sp==name || sp[-1]=='.') 6994887Schin c = *(sp = cp); 7004887Schin goto skip; 7014887Schin case '.': 7024887Schin if(flags&NV_IDENT) 7034887Schin return(0); 704*8462SApril.Chin@Sun.COM if(root==shp->var_tree) 7054887Schin flags &= ~NV_EXPORT; 7064887Schin if(!copy && !(flags&NV_NOREF)) 7074887Schin { 7084887Schin c = sp-name; 7094887Schin copy = cp-name; 710*8462SApril.Chin@Sun.COM dp->nofree |= 1; 7114887Schin name = copystack((const char*)0, name,(const char*)0); 7124887Schin cp = (char*)name+copy; 7134887Schin sp = (char*)name+c; 7144887Schin c = '.'; 7154887Schin } 7164887Schin skip: 7174887Schin case '+': 7184887Schin case '=': 7194887Schin *sp = 0; 7204887Schin case 0: 7214887Schin isref = 0; 7224887Schin dp->last = cp; 7234887Schin mode = (c=='.' || (flags&NV_NOADD))?add:NV_ADD; 724*8462SApril.Chin@Sun.COM if((flags&NV_NOSCOPE) && c!='.') 7254887Schin mode |= HASH_NOSCOPE; 726*8462SApril.Chin@Sun.COM np=0; 7274887Schin if(top) 728*8462SApril.Chin@Sun.COM { 729*8462SApril.Chin@Sun.COM struct Ufunction *rp; 730*8462SApril.Chin@Sun.COM if((rp=shp->st.real_fun) && !rp->sdict && (flags&NV_STATIC)) 731*8462SApril.Chin@Sun.COM { 732*8462SApril.Chin@Sun.COM Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0); 733*8462SApril.Chin@Sun.COM rp->sdict = dtopen(&_Nvdisc,Dtoset); 734*8462SApril.Chin@Sun.COM dtview(rp->sdict,shp->var_base); 735*8462SApril.Chin@Sun.COM dtview(shp->var_tree,rp->sdict); 736*8462SApril.Chin@Sun.COM } 737*8462SApril.Chin@Sun.COM if(np = nv_search(name,shp->var_tree,0)) 738*8462SApril.Chin@Sun.COM { 739*8462SApril.Chin@Sun.COM if(shp->var_tree->walk == shp->var_base) 740*8462SApril.Chin@Sun.COM { 741*8462SApril.Chin@Sun.COM nq = np; 742*8462SApril.Chin@Sun.COM if(flags&NV_NOSCOPE) 743*8462SApril.Chin@Sun.COM { 744*8462SApril.Chin@Sun.COM if(mode==0) 745*8462SApril.Chin@Sun.COM root = shp->var_base; 746*8462SApril.Chin@Sun.COM else 747*8462SApril.Chin@Sun.COM { 748*8462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 749*8462SApril.Chin@Sun.COM np = 0; 750*8462SApril.Chin@Sun.COM } 751*8462SApril.Chin@Sun.COM } 752*8462SApril.Chin@Sun.COM } 753*8462SApril.Chin@Sun.COM else 754*8462SApril.Chin@Sun.COM { 755*8462SApril.Chin@Sun.COM root = shp->var_tree->walk; 756*8462SApril.Chin@Sun.COM flags |= NV_NOSCOPE; 757*8462SApril.Chin@Sun.COM noscope = 1; 758*8462SApril.Chin@Sun.COM } 759*8462SApril.Chin@Sun.COM } 760*8462SApril.Chin@Sun.COM if(rp && rp->sdict && (flags&NV_STATIC)) 761*8462SApril.Chin@Sun.COM { 762*8462SApril.Chin@Sun.COM root = rp->sdict; 763*8462SApril.Chin@Sun.COM if(np && shp->var_tree->walk==shp->var_tree) 764*8462SApril.Chin@Sun.COM { 765*8462SApril.Chin@Sun.COM _nv_unset(np,0); 766*8462SApril.Chin@Sun.COM nv_delete(np,shp->var_tree,0); 767*8462SApril.Chin@Sun.COM np = 0; 768*8462SApril.Chin@Sun.COM } 769*8462SApril.Chin@Sun.COM if(!np || shp->var_tree->walk!=root) 770*8462SApril.Chin@Sun.COM np = nv_search(name,root,HASH_NOSCOPE|NV_ADD); 771*8462SApril.Chin@Sun.COM } 772*8462SApril.Chin@Sun.COM } 773*8462SApril.Chin@Sun.COM if(np || (np = nv_search(name,root,mode))) 7744887Schin { 7754887Schin isref = nv_isref(np); 7764887Schin if(top) 7774887Schin { 7784887Schin if(nq==np) 7794887Schin flags &= ~NV_NOSCOPE; 7804887Schin else if(nq) 7814887Schin { 7824887Schin if(nv_isnull(np) && c!='.' && (np->nvfun=nv_cover(nq))) 7834887Schin np->nvname = nq->nvname; 7844887Schin flags |= NV_NOSCOPE; 7854887Schin } 7864887Schin } 787*8462SApril.Chin@Sun.COM else if(add && nv_isnull(np) && c=='.' && cp[1]!='.') 7884887Schin nv_setvtree(np); 7894887Schin } 7904887Schin if(c) 7914887Schin *sp = c; 7924887Schin top = 0; 7934887Schin if(isref) 7944887Schin { 7954887Schin char *sub=0; 796*8462SApril.Chin@Sun.COM #if NVCACHE 797*8462SApril.Chin@Sun.COM nvcache.ok = 0; 798*8462SApril.Chin@Sun.COM #endif 7994887Schin if(c=='.') /* don't optimize */ 800*8462SApril.Chin@Sun.COM shp->argaddr = 0; 801*8462SApril.Chin@Sun.COM else if((flags&NV_NOREF) && (c!='[' || *cp!='.')) 8024887Schin { 803*8462SApril.Chin@Sun.COM if(c && !(flags&NV_NOADD)) 8044887Schin nv_unref(np); 8054887Schin return(np); 8064887Schin } 807*8462SApril.Chin@Sun.COM while(nv_isref(np) && np->nvalue.cp) 8084887Schin { 8094887Schin root = nv_reftree(np); 810*8462SApril.Chin@Sun.COM shp->last_root = root; 811*8462SApril.Chin@Sun.COM shp->last_table = nv_reftable(np); 8124887Schin sub = nv_refsub(np); 8134887Schin np = nv_refnode(np); 8144887Schin if(sub && c!='.') 8154887Schin nv_putsub(np,sub,0L); 8164887Schin flags |= NV_NOSCOPE; 817*8462SApril.Chin@Sun.COM noscope = 1; 8184887Schin } 819*8462SApril.Chin@Sun.COM if(nv_isref(np) && (c=='[' || c=='.' || !(flags&NV_ASSIGN))) 820*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_noref,nv_name(np)); 8214887Schin if(sub && c==0) 8224887Schin return(np); 8234887Schin if(np==nq) 8244887Schin flags &= ~(noscope?0:NV_NOSCOPE); 8254887Schin else if(c) 8264887Schin { 8274887Schin c = (cp-sp); 8284887Schin copy = strlen(cp=nv_name(np)); 829*8462SApril.Chin@Sun.COM dp->nofree |= 1; 8304887Schin name = copystack(cp,sp,sub); 8314887Schin sp = (char*)name + copy; 8324887Schin cp = sp+c; 8334887Schin c = *sp; 8344887Schin if(!noscope) 8354887Schin flags &= ~NV_NOSCOPE; 8364887Schin } 8374887Schin flags |= NV_NOREF; 8384887Schin } 839*8462SApril.Chin@Sun.COM shp->last_root = root; 840*8462SApril.Chin@Sun.COM if(cp[1]=='.') 841*8462SApril.Chin@Sun.COM cp++; 842*8462SApril.Chin@Sun.COM if(c=='.' && (cp[1]==0 || cp[1]=='=' || cp[1]=='+')) 843*8462SApril.Chin@Sun.COM { 844*8462SApril.Chin@Sun.COM nv_local = 1; 845*8462SApril.Chin@Sun.COM return(np); 846*8462SApril.Chin@Sun.COM } 847*8462SApril.Chin@Sun.COM if(cp[-1]=='.') 848*8462SApril.Chin@Sun.COM cp--; 8494887Schin do 8504887Schin { 8514887Schin if(!np) 8524887Schin { 853*8462SApril.Chin@Sun.COM if(!nq && *sp=='[' && *cp==0 && cp[-1]==']') 8544887Schin { 8554887Schin /* 8564887Schin * for backward compatibility 8574887Schin * evaluate subscript for 8584887Schin * possible side effects 8594887Schin */ 8604887Schin cp[-1] = 0; 8614887Schin sh_arith(sp+1); 8624887Schin cp[-1] = ']'; 8634887Schin } 8644887Schin return(np); 8654887Schin } 8664887Schin if(c=='[' || (c=='.' && nv_isarray(np))) 8674887Schin { 868*8462SApril.Chin@Sun.COM char *sub=0; 8694887Schin int n = 0; 8704887Schin if(c=='[') 8714887Schin { 8724887Schin n = mode|nv_isarray(np); 8734887Schin if(!mode && (flags&NV_ARRAY) && ((c=sp[1])=='*' || c=='@') && sp[2]==']') 8744887Schin { 8754887Schin /* not implemented yet */ 8764887Schin dp->last = cp; 8774887Schin return(np); 8784887Schin } 879*8462SApril.Chin@Sun.COM if((n&NV_ADD)&&(flags&NV_ARRAY)) 8804887Schin n |= ARRAY_FILL; 881*8462SApril.Chin@Sun.COM if(flags&NV_ASSIGN) 882*8462SApril.Chin@Sun.COM n |= NV_ADD; 883*8462SApril.Chin@Sun.COM cp = nv_endsubscript(np,sp,n|(flags&NV_ASSIGN)); 8844887Schin } 8854887Schin else 8864887Schin cp = sp; 887*8462SApril.Chin@Sun.COM if((c = *cp)=='.' || (c=='[' && nv_isarray(np)) || (n&ARRAY_FILL) || (flags&NV_ARRAY)) 8884887Schin 8894887Schin { 8904887Schin int m = cp-sp; 891*8462SApril.Chin@Sun.COM sub = m?nv_getsub(np):0; 8924887Schin if(!sub) 893*8462SApril.Chin@Sun.COM { 894*8462SApril.Chin@Sun.COM if(m && !(n&NV_ADD)) 895*8462SApril.Chin@Sun.COM return(0); 8964887Schin sub = "0"; 897*8462SApril.Chin@Sun.COM } 8984887Schin n = strlen(sub)+2; 8994887Schin if(!copy) 9004887Schin { 9014887Schin copy = cp-name; 902*8462SApril.Chin@Sun.COM dp->nofree |= 1; 9034887Schin name = copystack((const char*)0, name,(const char*)0); 9044887Schin cp = (char*)name+copy; 9054887Schin sp = cp-m; 9064887Schin } 9074887Schin if(n <= m) 9084887Schin { 9094887Schin if(n) 9104887Schin { 9114887Schin memcpy(sp+1,sub,n-2); 9124887Schin sp[n-1] = ']'; 9134887Schin } 9144887Schin if(n < m) 9154887Schin cp=strcpy(sp+n,cp); 9164887Schin } 9174887Schin else 9184887Schin { 9194887Schin int r = n-m; 9204887Schin m = sp-name; 9214887Schin name = stack_extend(name, cp-1, r); 9224887Schin sp = (char*)name + m; 9234887Schin *sp = '['; 9244887Schin memcpy(sp+1,sub,n-2); 9254887Schin sp[n-1] = ']'; 9264887Schin cp = sp+n; 9274887Schin 9284887Schin } 9294887Schin } 9304887Schin else if(c==0 && mode && (n=nv_aindex(np))>0) 931*8462SApril.Chin@Sun.COM nv_putsub(np,(char*)0,n); 932*8462SApril.Chin@Sun.COM else if(n==0 && (c==0 || (c=='[' && !nv_isarray(np)))) 9334887Schin { 9344887Schin /* subscript must be 0*/ 9354887Schin cp[-1] = 0; 936*8462SApril.Chin@Sun.COM n = sh_arith(sp+1); 9374887Schin cp[-1] = ']'; 938*8462SApril.Chin@Sun.COM if(n) 939*8462SApril.Chin@Sun.COM return(0); 9404887Schin if(c) 941*8462SApril.Chin@Sun.COM sp = cp; 9424887Schin } 9434887Schin dp->last = cp; 9444887Schin if(nv_isarray(np) && (c=='[' || c=='.' || (flags&NV_ARRAY))) 9454887Schin { 946*8462SApril.Chin@Sun.COM sp = cp; 947*8462SApril.Chin@Sun.COM if(!(nq = nv_opensub(np))) 948*8462SApril.Chin@Sun.COM { 949*8462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 950*8462SApril.Chin@Sun.COM if(!sub && (flags&NV_NOADD)) 951*8462SApril.Chin@Sun.COM return(0); 952*8462SApril.Chin@Sun.COM n = mode|((flags&NV_NOADD)?0:NV_ADD); 953*8462SApril.Chin@Sun.COM if(!ap && (n&NV_ADD)) 954*8462SApril.Chin@Sun.COM { 955*8462SApril.Chin@Sun.COM nv_putsub(np,sub,ARRAY_FILL); 956*8462SApril.Chin@Sun.COM ap = nv_arrayptr(np); 957*8462SApril.Chin@Sun.COM } 958*8462SApril.Chin@Sun.COM if(n && ap && !ap->table) 959*8462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 960*8462SApril.Chin@Sun.COM if(ap && ap->table && (nq=nv_search(sub,ap->table,n))) 961*8462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 962*8462SApril.Chin@Sun.COM if(nq && nv_isnull(nq)) 963*8462SApril.Chin@Sun.COM nq = nv_arraychild(np,nq,c); 964*8462SApril.Chin@Sun.COM } 965*8462SApril.Chin@Sun.COM if(nq) 966*8462SApril.Chin@Sun.COM { 967*8462SApril.Chin@Sun.COM if(c=='.' && !nv_isvtree(nq)) 968*8462SApril.Chin@Sun.COM { 969*8462SApril.Chin@Sun.COM if(flags&NV_NOADD) 970*8462SApril.Chin@Sun.COM return(0); 971*8462SApril.Chin@Sun.COM nv_setvtree(nq); 972*8462SApril.Chin@Sun.COM } 973*8462SApril.Chin@Sun.COM np = nq; 974*8462SApril.Chin@Sun.COM } 975*8462SApril.Chin@Sun.COM else if(memcmp(cp,"[0]",3)) 976*8462SApril.Chin@Sun.COM return(nq); 977*8462SApril.Chin@Sun.COM else 978*8462SApril.Chin@Sun.COM { 979*8462SApril.Chin@Sun.COM /* ignore [0] */ 980*8462SApril.Chin@Sun.COM dp->last = cp += 3; 981*8462SApril.Chin@Sun.COM c = *cp; 982*8462SApril.Chin@Sun.COM } 9834887Schin } 9844887Schin } 9854887Schin else if(nv_isarray(np)) 986*8462SApril.Chin@Sun.COM { 987*8462SApril.Chin@Sun.COM if(c==0 && (flags&NV_MOVE)) 988*8462SApril.Chin@Sun.COM return(np); 9894887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 990*8462SApril.Chin@Sun.COM } 9914887Schin if(c=='.' && (fp=np->nvfun)) 9924887Schin { 9934887Schin for(; fp; fp=fp->next) 9944887Schin { 9954887Schin if(fp->disc && fp->disc->createf) 9964887Schin break; 9974887Schin } 9984887Schin if(fp) 9994887Schin { 10004887Schin if((nq = (*fp->disc->createf)(np,cp+1,flags,fp)) == np) 10014887Schin { 10024887Schin add = NV_ADD; 10034887Schin break; 10044887Schin } 1005*8462SApril.Chin@Sun.COM else if(np=nq) 1006*8462SApril.Chin@Sun.COM { 1007*8462SApril.Chin@Sun.COM if((c = *(sp=cp=dp->last=fp->last))==0) 1008*8462SApril.Chin@Sun.COM { 1009*8462SApril.Chin@Sun.COM if(nv_isarray(np) && sp[-1]!=']') 1010*8462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),ARRAY_UNDEF); 1011*8462SApril.Chin@Sun.COM return(np); 1012*8462SApril.Chin@Sun.COM } 1013*8462SApril.Chin@Sun.COM } 10144887Schin } 10154887Schin } 10164887Schin } 10174887Schin while(c=='['); 1018*8462SApril.Chin@Sun.COM if(c!='.' || cp[1]=='.') 10194887Schin return(np); 10204887Schin cp++; 10214887Schin break; 10224887Schin default: 10234887Schin dp->last = cp; 10244887Schin if((c = mbchar(cp)) && !isaletter(c)) 10254887Schin return(np); 10264887Schin while(xp=cp, c=mbchar(cp), isaname(c)); 10274887Schin cp = xp; 10284887Schin } 10294887Schin } 10304887Schin return(np); 10314887Schin } 10324887Schin 10334887Schin /* 1034*8462SApril.Chin@Sun.COM * delete the node <np> from the dictionary <root> and clear from the cache 1035*8462SApril.Chin@Sun.COM * if <root> is NULL, only the cache is cleared 1036*8462SApril.Chin@Sun.COM * if flags does not contain NV_NOFREE, the node is freed 1037*8462SApril.Chin@Sun.COM */ 1038*8462SApril.Chin@Sun.COM void nv_delete(Namval_t* np, Dt_t *root, int flags) 1039*8462SApril.Chin@Sun.COM { 1040*8462SApril.Chin@Sun.COM #if NVCACHE 1041*8462SApril.Chin@Sun.COM register int c; 1042*8462SApril.Chin@Sun.COM struct Cache_entry *xp; 1043*8462SApril.Chin@Sun.COM for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c]) 1044*8462SApril.Chin@Sun.COM { 1045*8462SApril.Chin@Sun.COM if(xp->np==np) 1046*8462SApril.Chin@Sun.COM xp->root = 0; 1047*8462SApril.Chin@Sun.COM } 1048*8462SApril.Chin@Sun.COM #endif 1049*8462SApril.Chin@Sun.COM if(root) 1050*8462SApril.Chin@Sun.COM { 1051*8462SApril.Chin@Sun.COM if(dtdelete(root,np)) 1052*8462SApril.Chin@Sun.COM { 1053*8462SApril.Chin@Sun.COM if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np))) 1054*8462SApril.Chin@Sun.COM free((void*)np); 1055*8462SApril.Chin@Sun.COM } 1056*8462SApril.Chin@Sun.COM #if 0 1057*8462SApril.Chin@Sun.COM else 1058*8462SApril.Chin@Sun.COM { 1059*8462SApril.Chin@Sun.COM sfprintf(sfstderr,"%s not deleted\n",nv_name(np)); 1060*8462SApril.Chin@Sun.COM sfsync(sfstderr); 1061*8462SApril.Chin@Sun.COM } 1062*8462SApril.Chin@Sun.COM #endif 1063*8462SApril.Chin@Sun.COM } 1064*8462SApril.Chin@Sun.COM } 1065*8462SApril.Chin@Sun.COM 1066*8462SApril.Chin@Sun.COM /* 10674887Schin * Put <arg> into associative memory. 10684887Schin * If <flags> & NV_ARRAY then follow array to next subscript 10694887Schin * If <flags> & NV_NOARRAY then subscript is not allowed 10704887Schin * If <flags> & NV_NOSCOPE then use the current scope only 10714887Schin * If <flags> & NV_ASSIGN then assignment is allowed 10724887Schin * If <flags> & NV_IDENT then name must be an identifier 10734887Schin * If <flags> & NV_VARNAME then name must be a valid variable name 10744887Schin * If <flags> & NV_NOADD then node will not be added if not found 10754887Schin * If <flags> & NV_NOREF then don't follow reference 10764887Schin * If <flags> & NV_NOFAIL then don't generate an error message on failure 1077*8462SApril.Chin@Sun.COM * If <flags> & NV_STATIC then unset before an assignment 10784887Schin * SH_INIT is only set while initializing the environment 10794887Schin */ 10804887Schin Namval_t *nv_open(const char *name, Dt_t *root, int flags) 10814887Schin { 1082*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 10834887Schin register char *cp=(char*)name; 10844887Schin register int c; 10854887Schin register Namval_t *np; 10864887Schin Namfun_t fun; 10874887Schin int append=0; 10884887Schin const char *msg = e_varname; 10894887Schin char *fname = 0; 10904887Schin int offset = staktell(); 10914887Schin Dt_t *funroot; 1092*8462SApril.Chin@Sun.COM #if NVCACHE 1093*8462SApril.Chin@Sun.COM struct Cache_entry *xp; 1094*8462SApril.Chin@Sun.COM #endif 1095*8462SApril.Chin@Sun.COM 1096*8462SApril.Chin@Sun.COM sh_stats(STAT_NVOPEN); 10974887Schin memset(&fun,0,sizeof(fun)); 1098*8462SApril.Chin@Sun.COM shp->last_table = shp->namespace; 10994887Schin if(!root) 1100*8462SApril.Chin@Sun.COM root = shp->var_tree; 1101*8462SApril.Chin@Sun.COM shp->last_root = root; 1102*8462SApril.Chin@Sun.COM if(root==shp->fun_tree) 11034887Schin { 11044887Schin flags |= NV_NOREF; 11054887Schin msg = e_badfun; 1106*8462SApril.Chin@Sun.COM if((np=shp->namespace) || strchr(name,'.')) 11074887Schin { 11084887Schin name = cp = copystack(np?nv_name(np):0,name,(const char*)0); 11094887Schin fname = strrchr(cp,'.'); 11104887Schin *fname = 0; 1111*8462SApril.Chin@Sun.COM fun.nofree |= 1; 11124887Schin flags &= ~NV_IDENT; 11134887Schin funroot = root; 1114*8462SApril.Chin@Sun.COM root = shp->var_tree; 11154887Schin } 11164887Schin } 11174887Schin else if(!(flags&(NV_IDENT|NV_VARNAME|NV_ASSIGN))) 11184887Schin { 11194887Schin long mode = ((flags&NV_NOADD)?0:NV_ADD); 11204887Schin if(flags&NV_NOSCOPE) 11214887Schin mode |= HASH_SCOPE|HASH_NOSCOPE; 11224887Schin np = nv_search(name,root,mode); 11234887Schin if(np && !(flags&NV_REF)) 11244887Schin { 11254887Schin while(nv_isref(np)) 11264887Schin { 1127*8462SApril.Chin@Sun.COM shp->last_table = nv_reftable(np); 11284887Schin np = nv_refnode(np); 11294887Schin } 11304887Schin } 11314887Schin return(np); 11324887Schin } 1133*8462SApril.Chin@Sun.COM else if(shp->prefix && (flags&NV_ASSIGN)) 11344887Schin { 1135*8462SApril.Chin@Sun.COM name = cp = copystack(shp->prefix,name,(const char*)0); 1136*8462SApril.Chin@Sun.COM fun.nofree |= 1; 11374887Schin } 11384887Schin c = *(unsigned char*)cp; 1139*8462SApril.Chin@Sun.COM if(root==shp->alias_tree) 11404887Schin { 11414887Schin msg = e_aliname; 11424887Schin while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') && 1143*8462SApril.Chin@Sun.COM (c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON)); 1144*8462SApril.Chin@Sun.COM if(shp->subshell && c=='=') 11454887Schin root = sh_subaliastree(1); 11464887Schin if(c= *--cp) 11474887Schin *cp = 0; 11484887Schin np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD); 11494887Schin if(c) 11504887Schin *cp = c; 11514887Schin goto skip; 11524887Schin } 11534887Schin else if(flags&NV_IDENT) 11544887Schin msg = e_ident; 11554887Schin else if(c=='.') 11564887Schin { 11574887Schin c = *++cp; 11584887Schin flags |= NV_NOREF; 1159*8462SApril.Chin@Sun.COM if(root==shp->var_tree) 1160*8462SApril.Chin@Sun.COM root = shp->var_base; 1161*8462SApril.Chin@Sun.COM shp->last_table = 0; 11624887Schin } 11634887Schin if(c= !isaletter(c)) 11644887Schin goto skip; 1165*8462SApril.Chin@Sun.COM #if NVCACHE 1166*8462SApril.Chin@Sun.COM for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c]) 1167*8462SApril.Chin@Sun.COM { 1168*8462SApril.Chin@Sun.COM if(xp->root!=root) 1169*8462SApril.Chin@Sun.COM continue; 1170*8462SApril.Chin@Sun.COM if(*name==*xp->name && (flags&(NV_ARRAY|NV_NOSCOPE))==xp->flags && memcmp(xp->name,name,xp->len)==0 && (name[xp->len]==0 || name[xp->len]=='=' || name[xp->len]=='+')) 1171*8462SApril.Chin@Sun.COM { 1172*8462SApril.Chin@Sun.COM sh_stats(STAT_NVHITS); 1173*8462SApril.Chin@Sun.COM np = xp->np; 1174*8462SApril.Chin@Sun.COM cp = (char*)name+xp->len; 1175*8462SApril.Chin@Sun.COM if(nv_isarray(np)) 1176*8462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),ARRAY_UNDEF); 1177*8462SApril.Chin@Sun.COM shp->last_table = xp->last_table; 1178*8462SApril.Chin@Sun.COM goto nocache; 1179*8462SApril.Chin@Sun.COM } 1180*8462SApril.Chin@Sun.COM } 1181*8462SApril.Chin@Sun.COM nvcache.ok = 1; 1182*8462SApril.Chin@Sun.COM #endif 11834887Schin np = nv_create(name, root, flags, &fun); 11844887Schin cp = fun.last; 1185*8462SApril.Chin@Sun.COM #if NVCACHE 1186*8462SApril.Chin@Sun.COM if(np && nvcache.ok && cp[-1]!=']') 1187*8462SApril.Chin@Sun.COM { 1188*8462SApril.Chin@Sun.COM xp = &nvcache.entries[nvcache.index]; 1189*8462SApril.Chin@Sun.COM if(*cp) 1190*8462SApril.Chin@Sun.COM { 1191*8462SApril.Chin@Sun.COM char *sp = strchr(name,*cp); 1192*8462SApril.Chin@Sun.COM if(!sp) 1193*8462SApril.Chin@Sun.COM goto nocache; 1194*8462SApril.Chin@Sun.COM xp->len = sp-name; 1195*8462SApril.Chin@Sun.COM } 1196*8462SApril.Chin@Sun.COM else 1197*8462SApril.Chin@Sun.COM xp->len = strlen(name); 1198*8462SApril.Chin@Sun.COM c = roundof(xp->len+1,32); 1199*8462SApril.Chin@Sun.COM if(c > xp->size) 1200*8462SApril.Chin@Sun.COM { 1201*8462SApril.Chin@Sun.COM if(xp->size==0) 1202*8462SApril.Chin@Sun.COM xp->name = malloc(c); 1203*8462SApril.Chin@Sun.COM else 1204*8462SApril.Chin@Sun.COM xp->name = realloc(xp->name,c); 1205*8462SApril.Chin@Sun.COM xp->size = c; 1206*8462SApril.Chin@Sun.COM } 1207*8462SApril.Chin@Sun.COM memcpy(xp->name,name,xp->len); 1208*8462SApril.Chin@Sun.COM xp->name[xp->len] = 0; 1209*8462SApril.Chin@Sun.COM xp->root = root; 1210*8462SApril.Chin@Sun.COM xp->np = np; 1211*8462SApril.Chin@Sun.COM xp->last_table = shp->last_table; 1212*8462SApril.Chin@Sun.COM xp->flags = (flags&(NV_ARRAY|NV_NOSCOPE)); 1213*8462SApril.Chin@Sun.COM nvcache.index = (nvcache.index+1)&(NVCACHE-1); 1214*8462SApril.Chin@Sun.COM } 1215*8462SApril.Chin@Sun.COM nocache: 1216*8462SApril.Chin@Sun.COM nvcache.ok = 0; 1217*8462SApril.Chin@Sun.COM #endif 12184887Schin if(fname) 12194887Schin { 12204887Schin c = ((flags&NV_NOSCOPE)?HASH_NOSCOPE:0)|((flags&NV_NOADD)?0:NV_ADD); 12214887Schin *fname = '.'; 12224887Schin np = nv_search(name, funroot, c); 12234887Schin *fname = 0; 12244887Schin } 1225*8462SApril.Chin@Sun.COM else 12264887Schin { 1227*8462SApril.Chin@Sun.COM if(*cp=='.' && cp[1]=='.') 1228*8462SApril.Chin@Sun.COM { 1229*8462SApril.Chin@Sun.COM append |= NV_NODISC; 1230*8462SApril.Chin@Sun.COM cp+=2; 1231*8462SApril.Chin@Sun.COM } 1232*8462SApril.Chin@Sun.COM if(*cp=='+' && cp[1]=='=') 1233*8462SApril.Chin@Sun.COM { 1234*8462SApril.Chin@Sun.COM append |= NV_APPEND; 1235*8462SApril.Chin@Sun.COM cp++; 1236*8462SApril.Chin@Sun.COM } 12374887Schin } 12384887Schin c = *cp; 12394887Schin skip: 1240*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 1241*8462SApril.Chin@Sun.COM if(np && shp->mktype) 1242*8462SApril.Chin@Sun.COM np = nv_addnode(np,0); 1243*8462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 1244*8462SApril.Chin@Sun.COM 12454887Schin if(c=='=' && np && (flags&NV_ASSIGN)) 12464887Schin { 12474887Schin cp++; 12484887Schin if(sh_isstate(SH_INIT)) 12494887Schin { 12504887Schin nv_putval(np, cp, NV_RDONLY); 12514887Schin if(np==PWDNOD) 12524887Schin nv_onattr(np,NV_TAGGED); 12534887Schin } 12544887Schin else 12554887Schin { 1256*8462SApril.Chin@Sun.COM char *sub=0, *prefix= shp->prefix; 1257*8462SApril.Chin@Sun.COM int isref; 1258*8462SApril.Chin@Sun.COM shp->prefix = 0; 1259*8462SApril.Chin@Sun.COM if((flags&NV_STATIC) && !shp->mktype) 1260*8462SApril.Chin@Sun.COM { 1261*8462SApril.Chin@Sun.COM if(!nv_isnull(np)) 1262*8462SApril.Chin@Sun.COM return(np); 1263*8462SApril.Chin@Sun.COM } 1264*8462SApril.Chin@Sun.COM isref = nv_isref(np); 12654887Schin if(sh_isoption(SH_XTRACE) && nv_isarray(np)) 12664887Schin sub = nv_getsub(np); 12674887Schin c = msg==e_aliname? 0: (append | (flags&NV_EXPORT)); 1268*8462SApril.Chin@Sun.COM if(isref) 1269*8462SApril.Chin@Sun.COM nv_offattr(np,NV_REF); 12704887Schin nv_putval(np, cp, c); 1271*8462SApril.Chin@Sun.COM if(isref) 1272*8462SApril.Chin@Sun.COM nv_setref(np,(Dt_t*)0,NV_VARNAME); 12734887Schin savesub = sub; 1274*8462SApril.Chin@Sun.COM shp->prefix = prefix; 12754887Schin } 12764887Schin nv_onattr(np, flags&NV_ATTRIBUTES); 12774887Schin } 12784887Schin else if(c) 12794887Schin { 12804887Schin if(flags&NV_NOFAIL) 12814887Schin return(0); 12824887Schin if(c=='.') 12834887Schin msg = e_noparent; 12844887Schin else if(c=='[') 12854887Schin msg = e_noarray; 12864887Schin errormsg(SH_DICT,ERROR_exit(1),msg,name); 12874887Schin } 1288*8462SApril.Chin@Sun.COM if(fun.nofree&1) 12894887Schin stakseek(offset); 12904887Schin return(np); 12914887Schin } 12924887Schin 12934887Schin #if SHOPT_MULTIBYTE 12944887Schin static int ja_size(char*, int, int); 12954887Schin static void ja_restore(void); 12964887Schin static char *savep; 12974887Schin static char savechars[8+1]; 12984887Schin #endif /* SHOPT_MULTIBYTE */ 12994887Schin 13004887Schin /* 13014887Schin * put value <string> into name-value node <np>. 13024887Schin * If <np> is an array, then the element given by the 13034887Schin * current index is assigned to. 13044887Schin * If <flags> contains NV_RDONLY, readonly attribute is ignored 13054887Schin * If <flags> contains NV_INTEGER, string is a pointer to a number 13064887Schin * If <flags> contains NV_NOFREE, previous value is freed, and <string> 13074887Schin * becomes value of node and <flags> becomes attributes 13084887Schin */ 13094887Schin void nv_putval(register Namval_t *np, const char *string, int flags) 13104887Schin { 13114887Schin register const char *sp=string; 13124887Schin register union Value *up; 13134887Schin register char *cp; 13144887Schin register int size = 0; 13154887Schin register int dot; 1316*8462SApril.Chin@Sun.COM #ifdef _ENV_H 13174887Schin int was_local = nv_local; 1318*8462SApril.Chin@Sun.COM #endif 1319*8462SApril.Chin@Sun.COM union Value u; 13204887Schin if(!(flags&NV_RDONLY) && nv_isattr (np, NV_RDONLY)) 13214887Schin errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np)); 13224887Schin /* The following could cause the shell to fork if assignment 13234887Schin * would cause a side effect 13244887Schin */ 13254887Schin sh.argaddr = 0; 13264887Schin if(sh.subshell && !nv_local) 13274887Schin np = sh_assignok(np,1); 1328*8462SApril.Chin@Sun.COM if(np->nvfun && np->nvfun->disc && !(flags&NV_NODISC) && !nv_isattr(np,NV_REF)) 13294887Schin { 13304887Schin /* This function contains disc */ 13314887Schin if(!nv_local) 13324887Schin { 13334887Schin nv_local=1; 13344887Schin nv_putv(np,sp,flags,np->nvfun); 1335*8462SApril.Chin@Sun.COM #ifdef _ENV_H 13364887Schin if(sp && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT))) 13374887Schin sh_envput(sh.env,np); 1338*8462SApril.Chin@Sun.COM #endif 13394887Schin return; 13404887Schin } 13414887Schin /* called from disc, assign the actual value */ 13424887Schin } 13434887Schin flags &= ~NV_NODISC; 1344*8462SApril.Chin@Sun.COM nv_local=0; 13454887Schin if(flags&(NV_NOREF|NV_NOFREE)) 13464887Schin { 1347*8462SApril.Chin@Sun.COM if(np->nvalue.cp && np->nvalue.cp!=sp && !nv_isattr(np,NV_NOFREE)) 1348*8462SApril.Chin@Sun.COM free((void*)np->nvalue.cp); 13494887Schin np->nvalue.cp = (char*)sp; 13504887Schin nv_setattr(np,(flags&~NV_RDONLY)|NV_NOFREE); 13514887Schin return; 13524887Schin } 13534887Schin up= &np->nvalue; 1354*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P) == NV_INT16) 1355*8462SApril.Chin@Sun.COM { 1356*8462SApril.Chin@Sun.COM if(!np->nvalue.up || !nv_isarray(np)) 1357*8462SApril.Chin@Sun.COM { 1358*8462SApril.Chin@Sun.COM up = &u; 1359*8462SApril.Chin@Sun.COM up->up = &np->nvalue; 1360*8462SApril.Chin@Sun.COM } 1361*8462SApril.Chin@Sun.COM } 1362*8462SApril.Chin@Sun.COM else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np)) 1363*8462SApril.Chin@Sun.COM up = np->nvalue.up; 1364*8462SApril.Chin@Sun.COM if(up && up->cp==Empty) 1365*8462SApril.Chin@Sun.COM up->cp = 0; 13664887Schin if(nv_isattr(np,NV_EXPORT)) 13674887Schin nv_offattr(np,NV_IMPORT); 13684887Schin if(nv_isattr (np, NV_INTEGER)) 13694887Schin { 1370*8462SApril.Chin@Sun.COM if(nv_isattr(np, NV_DOUBLE) == NV_DOUBLE) 13714887Schin { 13724887Schin if(nv_isattr(np, NV_LONG) && sizeof(double)<sizeof(Sfdouble_t)) 13734887Schin { 13744887Schin Sfdouble_t ld, old=0; 13754887Schin if(flags&NV_INTEGER) 13764887Schin { 13774887Schin if(flags&NV_LONG) 13784887Schin ld = *((Sfdouble_t*)sp); 13794887Schin else if(flags&NV_SHORT) 13804887Schin ld = *((float*)sp); 13814887Schin else 13824887Schin ld = *((double*)sp); 13834887Schin } 13844887Schin else 13854887Schin ld = sh_arith(sp); 13864887Schin if(!up->ldp) 13874887Schin up->ldp = new_of(Sfdouble_t,0); 13884887Schin else if(flags&NV_APPEND) 13894887Schin old = *(up->ldp); 13904887Schin *(up->ldp) = ld+old; 13914887Schin } 13924887Schin else 13934887Schin { 13944887Schin double d,od=0; 13954887Schin if(flags&NV_INTEGER) 13964887Schin { 13974887Schin if(flags&NV_LONG) 13984887Schin d = (double)(*(Sfdouble_t*)sp); 13994887Schin else if(flags&NV_SHORT) 14004887Schin d = (double)(*(float*)sp); 14014887Schin else 14024887Schin d = *(double*)sp; 14034887Schin } 14044887Schin else 14054887Schin d = sh_arith(sp); 14064887Schin if(!up->dp) 14074887Schin up->dp = new_of(double,0); 14084887Schin else if(flags&NV_APPEND) 14094887Schin od = *(up->dp); 14104887Schin *(up->dp) = d+od; 14114887Schin } 14124887Schin } 14134887Schin else 14144887Schin { 14154887Schin if(nv_isattr(np, NV_LONG) && sizeof(int32_t)<sizeof(Sflong_t)) 14164887Schin { 14174887Schin Sflong_t ll=0,oll=0; 14184887Schin if(flags&NV_INTEGER) 14194887Schin { 1420*8462SApril.Chin@Sun.COM if((flags&NV_DOUBLE) == NV_DOUBLE) 14214887Schin { 14224887Schin if(flags&NV_LONG) 14234887Schin ll = *((Sfdouble_t*)sp); 14244887Schin else if(flags&NV_SHORT) 14254887Schin ll = *((float*)sp); 14264887Schin else 14274887Schin ll = *((double*)sp); 14284887Schin } 14294887Schin else if(nv_isattr(np,NV_UNSIGN)) 14304887Schin { 14314887Schin if(flags&NV_LONG) 14324887Schin ll = *((Sfulong_t*)sp); 14334887Schin else if(flags&NV_SHORT) 14344887Schin ll = *((uint16_t*)sp); 14354887Schin else 14364887Schin ll = *((uint32_t*)sp); 14374887Schin } 14384887Schin else 14394887Schin { 14404887Schin if(flags&NV_LONG) 14414887Schin ll = *((Sflong_t*)sp); 14424887Schin else if(flags&NV_SHORT) 14434887Schin ll = *((uint16_t*)sp); 14444887Schin else 14454887Schin ll = *((uint32_t*)sp); 14464887Schin } 14474887Schin } 14484887Schin else if(sp) 14494887Schin ll = (Sflong_t)sh_arith(sp); 14504887Schin if(!up->llp) 14514887Schin up->llp = new_of(Sflong_t,0); 14524887Schin else if(flags&NV_APPEND) 14534887Schin oll = *(up->llp); 14544887Schin *(up->llp) = ll+oll; 14554887Schin } 14564887Schin else 14574887Schin { 14584887Schin int32_t l=0,ol=0; 14594887Schin if(flags&NV_INTEGER) 14604887Schin { 1461*8462SApril.Chin@Sun.COM if((flags&NV_DOUBLE) == NV_DOUBLE) 14624887Schin { 14634887Schin Sflong_t ll; 14644887Schin if(flags&NV_LONG) 14654887Schin ll = *((Sfdouble_t*)sp); 14664887Schin else if(flags&NV_SHORT) 14674887Schin ll = *((float*)sp); 14684887Schin else 14694887Schin ll = *((double*)sp); 14704887Schin l = (int32_t)ll; 14714887Schin } 14724887Schin else if(nv_isattr(np,NV_UNSIGN)) 14734887Schin { 14744887Schin if(flags&NV_LONG) 14754887Schin l = *((Sfulong_t*)sp); 14764887Schin else if(flags&NV_SHORT) 14774887Schin l = *((uint16_t*)sp); 14784887Schin else 14794887Schin l = *(uint32_t*)sp; 14804887Schin } 14814887Schin else 14824887Schin { 14834887Schin if(flags&NV_LONG) 14844887Schin l = *((Sflong_t*)sp); 14854887Schin else if(flags&NV_SHORT) 14864887Schin l = *((int16_t*)sp); 14874887Schin else 14884887Schin l = *(int32_t*)sp; 14894887Schin } 14904887Schin } 14914887Schin else if(sp) 14924887Schin { 14934887Schin Sfdouble_t ld = sh_arith(sp); 14944887Schin if(ld<0) 14954887Schin l = (int32_t)ld; 14964887Schin else 14974887Schin l = (uint32_t)ld; 14984887Schin } 14994887Schin if(nv_size(np) <= 1) 15004887Schin nv_setsize(np,10); 15014887Schin if(nv_isattr (np, NV_SHORT)) 15024887Schin { 15034887Schin int16_t s=0; 15044887Schin if(flags&NV_APPEND) 1505*8462SApril.Chin@Sun.COM s = *up->sp; 1506*8462SApril.Chin@Sun.COM *(up->sp) = s+(int16_t)l; 15074887Schin nv_onattr(np,NV_NOFREE); 15084887Schin } 15094887Schin else 15104887Schin { 15114887Schin if(!up->lp) 15124887Schin up->lp = new_of(int32_t,0); 15134887Schin else if(flags&NV_APPEND) 15144887Schin ol = *(up->lp); 15154887Schin *(up->lp) = l+ol; 15164887Schin } 15174887Schin } 15184887Schin } 15194887Schin } 15204887Schin else 15214887Schin { 15224887Schin const char *tofree=0; 15234887Schin int offset; 15244887Schin #if _lib_pathnative 15254887Schin char buff[PATH_MAX]; 15264887Schin #endif /* _lib_pathnative */ 15274887Schin if(flags&NV_INTEGER) 15284887Schin { 1529*8462SApril.Chin@Sun.COM if((flags&NV_DOUBLE)==NV_DOUBLE) 15304887Schin { 15314887Schin if(flags&NV_LONG) 15324887Schin sfprintf(sh.strbuf,"%.*Lg",LDBL_DIG,*((Sfdouble_t*)sp)); 15334887Schin else 15344887Schin sfprintf(sh.strbuf,"%.*g",DBL_DIG,*((double*)sp)); 15354887Schin } 1536*8462SApril.Chin@Sun.COM else if(flags&NV_UNSIGN) 1537*8462SApril.Chin@Sun.COM { 1538*8462SApril.Chin@Sun.COM if(flags&NV_LONG) 1539*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%I*lu",sizeof(Sfulong_t),*((Sfulong_t*)sp)); 1540*8462SApril.Chin@Sun.COM else 1541*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%lu",(unsigned long)((flags&NV_SHORT)?*((uint16_t*)sp):*((uint32_t*)sp))); 1542*8462SApril.Chin@Sun.COM } 15434887Schin else 1544*8462SApril.Chin@Sun.COM { 1545*8462SApril.Chin@Sun.COM if(flags&NV_LONG) 1546*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%I*ld",sizeof(Sflong_t),*((Sflong_t*)sp)); 1547*8462SApril.Chin@Sun.COM else 1548*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%ld",(long)((flags&NV_SHORT)?*((int16_t*)sp):*((int32_t*)sp))); 1549*8462SApril.Chin@Sun.COM } 15504887Schin sp = sfstruse(sh.strbuf); 15514887Schin } 1552*8462SApril.Chin@Sun.COM if(nv_isattr(np, NV_HOST|NV_INTEGER)==NV_HOST && sp) 15534887Schin { 15544887Schin #ifdef _lib_pathnative 15554887Schin /* 15564887Schin * return the host file name given the UNIX name 15574887Schin */ 15584887Schin pathnative(sp,buff,sizeof(buff)); 15594887Schin if(buff[1]==':' && buff[2]=='/') 15604887Schin { 15614887Schin buff[2] = '\\'; 15624887Schin if(*buff>='A' && *buff<='Z') 15634887Schin *buff += 'a'-'A'; 15644887Schin } 15654887Schin sp = buff; 15664887Schin #else 15674887Schin ; 15684887Schin #endif /* _lib_pathnative */ 15694887Schin } 15704887Schin else if((nv_isattr(np, NV_RJUST|NV_ZFILL|NV_LJUST)) && sp) 15714887Schin { 15724887Schin for(;*sp == ' '|| *sp=='\t';sp++); 15734887Schin if((nv_isattr(np,NV_ZFILL)) && (nv_isattr(np,NV_LJUST))) 15744887Schin for(;*sp=='0';sp++); 15754887Schin size = nv_size(np); 15764887Schin #if SHOPT_MULTIBYTE 15774887Schin if(size) 15784887Schin size = ja_size((char*)sp,size,nv_isattr(np,NV_RJUST|NV_ZFILL)); 15794887Schin #endif /* SHOPT_MULTIBYTE */ 15804887Schin } 15814887Schin if(!up->cp) 15824887Schin flags &= ~NV_APPEND; 15834887Schin if((flags&NV_APPEND) && !nv_isattr(np,NV_BINARY)) 15844887Schin { 15854887Schin offset = staktell(); 15864887Schin stakputs(up->cp); 15874887Schin stakputs(sp); 15884887Schin stakputc(0); 15894887Schin sp = stakptr(offset); 15904887Schin } 15914887Schin if(!nv_isattr(np, NV_NOFREE)) 15924887Schin { 15934887Schin /* delay free in case <sp> points into free region */ 15944887Schin tofree = up->cp; 15954887Schin } 1596*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_BINARY) && !(flags&NV_RAW)) 1597*8462SApril.Chin@Sun.COM tofree = 0; 1598*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_LJUST|NV_RJUST)) 1599*8462SApril.Chin@Sun.COM tofree = 0; 16004887Schin if (sp) 16014887Schin { 16024887Schin dot = strlen(sp); 16034887Schin #if (_AST_VERSION>=20030127L) 16044887Schin if(nv_isattr(np,NV_BINARY)) 16054887Schin { 16064887Schin int oldsize = (flags&NV_APPEND)?nv_size(np):0; 16074887Schin if(flags&NV_RAW) 16084887Schin { 16094887Schin if(tofree) 1610*8462SApril.Chin@Sun.COM { 16114887Schin free((void*)tofree); 1612*8462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 1613*8462SApril.Chin@Sun.COM } 16144887Schin up->cp = sp; 16154887Schin return; 16164887Schin } 16174887Schin size = 0; 16184887Schin if(nv_isattr(np,NV_ZFILL)) 16194887Schin size = nv_size(np); 16204887Schin if(size==0) 16214887Schin size = oldsize + (3*dot/4); 16224887Schin cp = (char*)malloc(size+1); 1623*8462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 16244887Schin if(oldsize) 16254887Schin memcpy((void*)cp,(void*)up->cp,oldsize); 16264887Schin up->cp = cp; 16274887Schin if(size <= oldsize) 16284887Schin return; 16294887Schin dot = base64decode(sp,dot, (void**)0, cp+oldsize, size-oldsize,(void**)0); 16304887Schin dot += oldsize; 16314887Schin if(!nv_isattr(np,NV_ZFILL) || nv_size(np)==0) 16324887Schin nv_setsize(np,dot); 16334887Schin else if(nv_isattr(np,NV_ZFILL) && (size>dot)) 16344887Schin memset((void*)&cp[dot],0,size-dot); 16354887Schin return; 16364887Schin } 16374887Schin else 16384887Schin #endif 16394887Schin if(size==0 && nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL)) 16404887Schin nv_setsize(np,size=dot); 16414887Schin else if(size > dot) 16424887Schin dot = size; 1643*8462SApril.Chin@Sun.COM else if(nv_isattr(np,NV_LJUST) && dot>size) 1644*8462SApril.Chin@Sun.COM dot = size; 1645*8462SApril.Chin@Sun.COM if(size==0 || tofree || !(cp=(char*)up->cp)) 1646*8462SApril.Chin@Sun.COM { 1647*8462SApril.Chin@Sun.COM cp = (char*)malloc(((unsigned)dot+1)); 1648*8462SApril.Chin@Sun.COM cp[dot] = 0; 1649*8462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 1650*8462SApril.Chin@Sun.COM } 1651*8462SApril.Chin@Sun.COM 16524887Schin } 16534887Schin else 16544887Schin cp = 0; 16554887Schin up->cp = cp; 16564887Schin if(sp) 16574887Schin { 1658*8462SApril.Chin@Sun.COM int c = cp[dot]; 1659*8462SApril.Chin@Sun.COM memcpy(cp,sp,dot); 1660*8462SApril.Chin@Sun.COM cp[dot]=0; 16614887Schin if(nv_isattr(np, NV_LTOU)) 1662*8462SApril.Chin@Sun.COM ltou(cp); 16634887Schin else if(nv_isattr (np, NV_UTOL)) 1664*8462SApril.Chin@Sun.COM utol(cp); 1665*8462SApril.Chin@Sun.COM cp[dot] = c; 16664887Schin if(nv_isattr(np, NV_RJUST) && nv_isattr(np, NV_ZFILL)) 16674887Schin rightjust(cp,size,'0'); 16684887Schin else if(nv_isattr(np, NV_RJUST)) 16694887Schin rightjust(cp,size,' '); 16704887Schin else if(nv_isattr(np, NV_LJUST)) 16714887Schin { 16724887Schin register char *dp; 16734887Schin dp = strlen (cp) + cp; 1674*8462SApril.Chin@Sun.COM cp = cp+size; 16754887Schin for (; dp < cp; *dp++ = ' '); 16764887Schin } 16774887Schin #if SHOPT_MULTIBYTE 16784887Schin /* restore original string */ 16794887Schin if(savep) 16804887Schin ja_restore(); 16814887Schin #endif /* SHOPT_MULTIBYTE */ 16824887Schin } 16834887Schin if(flags&NV_APPEND) 16844887Schin stakseek(offset); 1685*8462SApril.Chin@Sun.COM if(tofree && tofree!=Empty) 16864887Schin free((void*)tofree); 16874887Schin } 1688*8462SApril.Chin@Sun.COM #ifdef _ENV_H 16894887Schin if(!was_local && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT))) 16904887Schin sh_envput(sh.env,np); 1691*8462SApril.Chin@Sun.COM #endif 16924887Schin return; 16934887Schin } 16944887Schin 16954887Schin /* 16964887Schin * 16974887Schin * Right-justify <str> so that it contains no more than 16984887Schin * <size> characters. If <str> contains fewer than <size> 16994887Schin * characters, left-pad with <fill>. Trailing blanks 17004887Schin * in <str> will be ignored. 17014887Schin * 17024887Schin * If the leftmost digit in <str> is not a digit, <fill> 17034887Schin * will default to a blank. 17044887Schin */ 17054887Schin static void rightjust(char *str, int size, int fill) 17064887Schin { 17074887Schin register int n; 17084887Schin register char *cp,*sp; 17094887Schin n = strlen(str); 17104887Schin 17114887Schin /* ignore trailing blanks */ 17124887Schin for(cp=str+n;n && *--cp == ' ';n--); 17134887Schin if (n == size) 17144887Schin return; 17154887Schin if(n > size) 17164887Schin { 17174887Schin *(str+n) = 0; 17184887Schin for (sp = str, cp = str+n-size; sp <= str+size; *sp++ = *cp++); 17194887Schin return; 17204887Schin } 17214887Schin else *(sp = str+size) = 0; 17224887Schin if (n == 0) 17234887Schin { 17244887Schin while (sp > str) 17254887Schin *--sp = ' '; 17264887Schin return; 17274887Schin } 17284887Schin while(n--) 17294887Schin { 17304887Schin sp--; 17314887Schin *sp = *cp--; 17324887Schin } 17334887Schin if(!isdigit(*str)) 17344887Schin fill = ' '; 17354887Schin while(sp>str) 17364887Schin *--sp = fill; 17374887Schin return; 17384887Schin } 17394887Schin 17404887Schin #if SHOPT_MULTIBYTE 17414887Schin /* 17424887Schin * handle left and right justified fields for multi-byte chars 17434887Schin * given physical size, return a logical size which reflects the 17444887Schin * screen width of multi-byte characters 17454887Schin * Multi-width characters replaced by spaces if they cross the boundary 17464887Schin * <type> is non-zero for right justified fields 17474887Schin */ 17484887Schin 17494887Schin static int ja_size(char *str,int size,int type) 17504887Schin { 17514887Schin register char *cp = str; 17524887Schin register int c, n=size; 17534887Schin register int outsize; 17544887Schin register char *oldcp=cp; 17554887Schin int oldn; 17564887Schin wchar_t w; 17574887Schin while(*cp) 17584887Schin { 17594887Schin oldn = n; 17604887Schin w = mbchar(cp); 17614887Schin outsize = mbwidth(w); 17624887Schin size -= outsize; 17634887Schin c = cp-oldcp; 17644887Schin n += (c-outsize); 17654887Schin oldcp = cp; 17664887Schin if(size<=0 && type==0) 17674887Schin break; 17684887Schin } 17694887Schin /* check for right justified fields that need truncating */ 17704887Schin if(size <0) 17714887Schin { 17724887Schin if(type==0) 17734887Schin { 17744887Schin /* left justified and character crosses field boundary */ 17754887Schin n = oldn; 17764887Schin /* save boundary char and replace with spaces */ 17774887Schin size = c; 17784887Schin savechars[size] = 0; 17794887Schin while(size--) 17804887Schin { 17814887Schin savechars[size] = cp[size]; 17824887Schin cp[size] = ' '; 17834887Schin } 17844887Schin savep = cp; 17854887Schin } 17864887Schin size = -size; 17874887Schin if(type) 17884887Schin n -= (ja_size(str,size,0)-size); 17894887Schin } 17904887Schin return(n); 17914887Schin } 17924887Schin 17934887Schin static void ja_restore(void) 17944887Schin { 17954887Schin register char *cp = savechars; 17964887Schin while(*cp) 17974887Schin *savep++ = *cp++; 17984887Schin savep = 0; 17994887Schin } 18004887Schin #endif /* SHOPT_MULTIBYTE */ 18014887Schin 18024887Schin #ifndef _ENV_H 18034887Schin static char *staknam(register Namval_t *np, char *value) 18044887Schin { 18054887Schin register char *p,*q; 18064887Schin q = stakalloc(strlen(nv_name(np))+(value?strlen(value):0)+2); 18074887Schin p=strcopy(q,nv_name(np)); 18084887Schin if(value) 18094887Schin { 18104887Schin *p++ = '='; 18114887Schin strcpy(p,value); 18124887Schin } 18134887Schin return(q); 18144887Schin } 18154887Schin #endif 18164887Schin 18174887Schin /* 18184887Schin * put the name and attribute into value of attributes variable 18194887Schin */ 18204887Schin #ifdef _ENV_H 18214887Schin static void attstore(register Namval_t *np, void *data) 18224887Schin { 18234887Schin register int flag, c = ' '; 18244887Schin NOT_USED(data); 18254887Schin if(!(nv_isattr(np,NV_EXPORT))) 18264887Schin return; 18274887Schin flag = nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER); 18284887Schin stakputc('='); 1829*8462SApril.Chin@Sun.COM if((flag&NV_DOUBLE) == NV_DOUBLE) 18304887Schin { 18314887Schin /* export doubles as integers for ksh88 compatibility */ 1832*8462SApril.Chin@Sun.COM stakputc(c+NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE))); 18334887Schin } 18344887Schin else 18354887Schin { 18364887Schin stakputc(c+flag); 18374887Schin if(flag&NV_INTEGER) 18384887Schin c += nv_size(np); 18394887Schin } 18404887Schin stakputc(c); 18414887Schin stakputs(nv_name(np)); 18424887Schin } 18434887Schin #else 18444887Schin static void attstore(register Namval_t *np, void *data) 18454887Schin { 18464887Schin register int flag = np->nvflag; 18474887Schin register struct adata *ap = (struct adata*)data; 1848*8462SApril.Chin@Sun.COM ap->sh = &sh; 1849*8462SApril.Chin@Sun.COM ap->tp = 0; 18504887Schin if(!(flag&NV_EXPORT) || (flag&NV_FUNCT)) 18514887Schin return; 18524887Schin flag &= (NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER); 18534887Schin *ap->attval++ = '='; 1854*8462SApril.Chin@Sun.COM if((flag&NV_DOUBLE) == NV_DOUBLE) 18554887Schin { 18564887Schin /* export doubles as integers for ksh88 compatibility */ 1857*8462SApril.Chin@Sun.COM *ap->attval++ = ' '+ NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE)); 18584887Schin *ap->attval = ' '; 18594887Schin } 18604887Schin else 18614887Schin { 18624887Schin *ap->attval++ = ' '+flag; 18634887Schin if(flag&NV_INTEGER) 18644887Schin *ap->attval = ' ' + nv_size(np); 18654887Schin else 18664887Schin *ap->attval = ' '; 18674887Schin } 18684887Schin ap->attval = strcopy(++ap->attval,nv_name(np)); 18694887Schin } 18704887Schin #endif 18714887Schin 18724887Schin #ifndef _ENV_H 18734887Schin static void pushnam(Namval_t *np, void *data) 18744887Schin { 18754887Schin register char *value; 18764887Schin register struct adata *ap = (struct adata*)data; 1877*8462SApril.Chin@Sun.COM ap->sh = &sh; 1878*8462SApril.Chin@Sun.COM ap->tp = 0; 18794887Schin if(nv_isattr(np,NV_IMPORT)) 18804887Schin { 18814887Schin if(np->nvenv) 18824887Schin *ap->argnam++ = np->nvenv; 18834887Schin } 18844887Schin else if(value=nv_getval(np)) 18854887Schin *ap->argnam++ = staknam(np,value); 18864887Schin if(nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)) 18874887Schin ap->attsize += (strlen(nv_name(np))+4); 18884887Schin } 18894887Schin #endif 18904887Schin 18914887Schin /* 18924887Schin * Generate the environment list for the child. 18934887Schin */ 18944887Schin 18954887Schin #ifdef _ENV_H 18964887Schin char **sh_envgen(void) 18974887Schin { 18984887Schin int offset,tell; 18994887Schin register char **er; 19004887Schin env_delete(sh.env,"_"); 19014887Schin er = env_get(sh.env); 19024887Schin offset = staktell(); 19034887Schin stakputs(e_envmarker); 19044887Schin tell = staktell(); 19054887Schin nv_scan(sh.var_tree, attstore,(void*)0,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)); 19064887Schin if(tell ==staktell()) 19074887Schin stakseek(offset); 19084887Schin else 19094887Schin *--er = stakfreeze(1)+offset; 19104887Schin return(er); 19114887Schin } 19124887Schin #else 19134887Schin char **sh_envgen(void) 19144887Schin { 19154887Schin register char **er; 19164887Schin register int namec; 19174887Schin register char *cp; 19184887Schin struct adata data; 1919*8462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 1920*8462SApril.Chin@Sun.COM data.sh = shp; 1921*8462SApril.Chin@Sun.COM data.tp = 0; 19224887Schin /* L_ARGNOD gets generated automatically as full path name of command */ 19234887Schin nv_offattr(L_ARGNOD,NV_EXPORT); 19244887Schin data.attsize = 6; 1925*8462SApril.Chin@Sun.COM namec = nv_scan(shp->var_tree,nullscan,(void*)0,NV_EXPORT,NV_EXPORT); 1926*8462SApril.Chin@Sun.COM namec += shp->nenv; 19274887Schin er = (char**)stakalloc((namec+4)*sizeof(char*)); 1928*8462SApril.Chin@Sun.COM data.argnam = (er+=2) + shp->nenv; 1929*8462SApril.Chin@Sun.COM if(shp->nenv) 1930*8462SApril.Chin@Sun.COM memcpy((void*)er,environ,shp->nenv*sizeof(char*)); 1931*8462SApril.Chin@Sun.COM nv_scan(shp->var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT); 19324887Schin *data.argnam = (char*)stakalloc(data.attsize); 19334887Schin cp = data.attval = strcopy(*data.argnam,e_envmarker); 1934*8462SApril.Chin@Sun.COM nv_scan(shp->var_tree, attstore,&data,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)); 19354887Schin *data.attval = 0; 19364887Schin if(cp!=data.attval) 19374887Schin data.argnam++; 19384887Schin *data.argnam = 0; 19394887Schin return(er); 19404887Schin } 19414887Schin #endif 19424887Schin 19434887Schin struct scan 19444887Schin { 19454887Schin void (*scanfn)(Namval_t*, void*); 19464887Schin int scanmask; 19474887Schin int scanflags; 19484887Schin int scancount; 19494887Schin void *scandata; 19504887Schin }; 19514887Schin 19524887Schin static int scanfilter(Dt_t *dict, void *arg, void *data) 19534887Schin { 19544887Schin register Namval_t *np = (Namval_t*)arg; 19554887Schin register int k=np->nvflag; 19564887Schin register struct scan *sp = (struct scan*)data; 1957*8462SApril.Chin@Sun.COM register struct adata *tp = (struct adata*)sp->scandata; 19584887Schin NOT_USED(dict); 1959*8462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 1960*8462SApril.Chin@Sun.COM if(tp && tp->tp && nv_type(np)!=tp->tp) 1961*8462SApril.Chin@Sun.COM return(0); 1962*8462SApril.Chin@Sun.COM #endif /*SHOPT_TYPEDEF */ 19634887Schin if(sp->scanmask?(k&sp->scanmask)==sp->scanflags:(!sp->scanflags || (k&sp->scanflags))) 19644887Schin { 1965*8462SApril.Chin@Sun.COM if(!np->nvalue.cp && !np->nvfun && !nv_isattr(np,~NV_DEFAULT)) 19664887Schin return(0); 19674887Schin if(sp->scanfn) 19684887Schin { 19694887Schin if(nv_isarray(np)) 19704887Schin nv_putsub(np,NIL(char*),0L); 19714887Schin (*sp->scanfn)(np,sp->scandata); 19724887Schin } 19734887Schin sp->scancount++; 19744887Schin } 19754887Schin return(0); 19764887Schin } 19774887Schin 19784887Schin /* 19794887Schin * Walk through the name-value pairs 19804887Schin * if <mask> is non-zero, then only nodes with (nvflags&mask)==flags 19814887Schin * are visited 19824887Schin * If <mask> is zero, and <flags> non-zero, then nodes with one or 19834887Schin * more of <flags> is visited 19844887Schin * If <mask> and <flags> are zero, then all nodes are visted 19854887Schin */ 19864887Schin int nv_scan(Dt_t *root, void (*fn)(Namval_t*,void*), void *data,int mask, int flags) 19874887Schin { 19884887Schin Dt_t *base=0; 19894887Schin struct scan sdata; 19904887Schin int (*hashfn)(Dt_t*, void*, void*); 19914887Schin sdata.scanmask = mask; 19924887Schin sdata.scanflags = flags&~NV_NOSCOPE; 19934887Schin sdata.scanfn = fn; 19944887Schin sdata.scancount = 0; 19954887Schin sdata.scandata = data; 19964887Schin hashfn = scanfilter; 19974887Schin if(flags&NV_NOSCOPE) 19984887Schin base = dtview((Dt_t*)root,0); 19994887Schin dtwalk(root, hashfn,&sdata); 20004887Schin if(base) 20014887Schin dtview((Dt_t*)root,base); 20024887Schin return(sdata.scancount); 20034887Schin } 20044887Schin 20054887Schin /* 20064887Schin * create a new environment scope 20074887Schin */ 2008*8462SApril.Chin@Sun.COM void sh_scope(Shell_t *shp, struct argnod *envlist, int fun) 20094887Schin { 2010*8462SApril.Chin@Sun.COM register Dt_t *newscope, *newroot=shp->var_base; 2011*8462SApril.Chin@Sun.COM struct Ufunction *rp; 20124887Schin newscope = dtopen(&_Nvdisc,Dtoset); 20134887Schin if(envlist) 2014*8462SApril.Chin@Sun.COM { 2015*8462SApril.Chin@Sun.COM dtview(newscope,(Dt_t*)shp->var_tree); 2016*8462SApril.Chin@Sun.COM shp->var_tree = newscope; 20174887Schin nv_setlist(envlist,NV_EXPORT|NV_NOSCOPE|NV_IDENT|NV_ASSIGN); 2018*8462SApril.Chin@Sun.COM if(!fun) 2019*8462SApril.Chin@Sun.COM return; 2020*8462SApril.Chin@Sun.COM shp->var_tree = dtview(newscope,0); 2021*8462SApril.Chin@Sun.COM } 2022*8462SApril.Chin@Sun.COM if((rp=shp->st.real_fun) && rp->sdict) 2023*8462SApril.Chin@Sun.COM { 2024*8462SApril.Chin@Sun.COM dtview(rp->sdict,newroot); 2025*8462SApril.Chin@Sun.COM newroot = rp->sdict; 2026*8462SApril.Chin@Sun.COM 2027*8462SApril.Chin@Sun.COM } 2028*8462SApril.Chin@Sun.COM dtview(newscope,(Dt_t*)newroot); 2029*8462SApril.Chin@Sun.COM shp->var_tree = newscope; 20304887Schin } 20314887Schin 20324887Schin /* 20334887Schin * Remove freeable local space associated with the nvalue field 20344887Schin * of nnod. This includes any strings representing the value(s) of the 20354887Schin * node, as well as its dope vector, if it is an array. 20364887Schin */ 20374887Schin 20384887Schin void sh_envnolocal (register Namval_t *np, void *data) 20394887Schin { 20404887Schin char *cp=0; 20414887Schin NOT_USED(data); 20424887Schin if(nv_isattr(np,NV_EXPORT) && nv_isarray(np)) 20434887Schin { 20444887Schin nv_putsub(np,NIL(char*),0); 20454887Schin if(cp = nv_getval(np)) 20464887Schin cp = strdup(cp); 20474887Schin } 20484887Schin if(nv_isattr(np,NV_EXPORT|NV_NOFREE)) 20494887Schin { 20504887Schin if(nv_isref(np)) 20514887Schin { 20524887Schin nv_offattr(np,NV_NOFREE|NV_REF); 20534887Schin free((void*)np->nvalue.nrp); 20544887Schin np->nvalue.cp = 0; 20554887Schin } 20564887Schin if(!cp) 20574887Schin return; 20584887Schin } 20594887Schin if(nv_isarray(np)) 20604887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 20614887Schin _nv_unset(np,NV_RDONLY); 20624887Schin nv_setattr(np,0); 20634887Schin if(cp) 20644887Schin { 20654887Schin nv_putval(np,cp,0); 20664887Schin free((void*)cp); 20674887Schin } 20684887Schin } 20694887Schin 20704887Schin /* 20714887Schin * Currently this is a dummy, but someday will be needed 20724887Schin * for reference counting 20734887Schin */ 20744887Schin void nv_close(Namval_t *np) 20754887Schin { 20764887Schin NOT_USED(np); 20774887Schin } 20784887Schin 2079*8462SApril.Chin@Sun.COM static void table_unset(Shell_t *shp, register Dt_t *root, int flags, Dt_t *oroot) 20804887Schin { 2081*8462SApril.Chin@Sun.COM register Namval_t *np,*nq, *npnext; 2082*8462SApril.Chin@Sun.COM for(np=(Namval_t*)dtfirst(root);np;np=npnext) 20834887Schin { 2084*8462SApril.Chin@Sun.COM if(nv_isref(np)) 2085*8462SApril.Chin@Sun.COM nv_unref(np); 2086*8462SApril.Chin@Sun.COM if(nq=dtsearch(oroot,np)) 2087*8462SApril.Chin@Sun.COM { 2088*8462SApril.Chin@Sun.COM if(nv_cover(nq)) 2089*8462SApril.Chin@Sun.COM { 2090*8462SApril.Chin@Sun.COM int subshell = shp->subshell; 2091*8462SApril.Chin@Sun.COM shp->subshell = 0; 2092*8462SApril.Chin@Sun.COM if(nv_isattr(nq, NV_INTEGER)) 2093*8462SApril.Chin@Sun.COM { 2094*8462SApril.Chin@Sun.COM Sfdouble_t d = nv_getnum(nq); 2095*8462SApril.Chin@Sun.COM nv_putval(nq,(char*)&d,NV_LDOUBLE); 2096*8462SApril.Chin@Sun.COM } 2097*8462SApril.Chin@Sun.COM else 2098*8462SApril.Chin@Sun.COM nv_putval(nq, nv_getval(nq), NV_RDONLY); 2099*8462SApril.Chin@Sun.COM shp->subshell = subshell; 2100*8462SApril.Chin@Sun.COM np->nvfun = 0; 2101*8462SApril.Chin@Sun.COM } 2102*8462SApril.Chin@Sun.COM #ifdef _ENV_H 2103*8462SApril.Chin@Sun.COM if(nv_isattr(nq,NV_EXPORT)) 2104*8462SApril.Chin@Sun.COM sh_envput(shp->env,nq); 2105*8462SApril.Chin@Sun.COM #endif 2106*8462SApril.Chin@Sun.COM } 2107*8462SApril.Chin@Sun.COM npnext = (Namval_t*)dtnext(root,np); 2108*8462SApril.Chin@Sun.COM shp->last_root = root; 2109*8462SApril.Chin@Sun.COM shp->last_table = 0; 2110*8462SApril.Chin@Sun.COM if(nv_isvtree(np)) 2111*8462SApril.Chin@Sun.COM { 2112*8462SApril.Chin@Sun.COM int len = strlen(np->nvname); 2113*8462SApril.Chin@Sun.COM while((nq=npnext) && memcmp(np->nvname,nq->nvname,len)==0 && nq->nvname[len]=='.') 2114*8462SApril.Chin@Sun.COM 2115*8462SApril.Chin@Sun.COM { 2116*8462SApril.Chin@Sun.COM npnext = (Namval_t*)dtnext(root,nq); 2117*8462SApril.Chin@Sun.COM _nv_unset(nq,flags); 2118*8462SApril.Chin@Sun.COM nv_delete(nq,root,0); 2119*8462SApril.Chin@Sun.COM } 2120*8462SApril.Chin@Sun.COM } 21214887Schin _nv_unset(np,flags); 2122*8462SApril.Chin@Sun.COM nv_delete(np,root,0); 21234887Schin } 21244887Schin } 21254887Schin 21264887Schin /* 21274887Schin * 21284887Schin * Set the value of <np> to 0, and nullify any attributes 21294887Schin * that <np> may have had. Free any freeable space occupied 21304887Schin * by the value of <np>. If <np> denotes an array member, it 21314887Schin * will retain its attributes. 21324887Schin * <flags> can contain NV_RDONLY to override the readonly attribute 21334887Schin * being cleared. 2134*8462SApril.Chin@Sun.COM * <flags> can contain NV_EXPORT to override preserve nvenv 21354887Schin */ 21364887Schin void _nv_unset(register Namval_t *np,int flags) 21374887Schin { 2138*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 21394887Schin register union Value *up; 21404887Schin if(!(flags&NV_RDONLY) && nv_isattr (np,NV_RDONLY)) 21414887Schin errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np)); 21424887Schin if(is_afunction(np) && np->nvalue.ip) 21434887Schin { 21444887Schin register struct slnod *slp = (struct slnod*)(np->nvenv); 21454887Schin if(slp && !nv_isattr(np,NV_NOFREE)) 21464887Schin { 2147*8462SApril.Chin@Sun.COM struct Ufunction *rq,*rp = np->nvalue.rp; 21484887Schin /* free function definition */ 21494887Schin register char *name=nv_name(np),*cp= strrchr(name,'.'); 21504887Schin if(cp) 21514887Schin { 21524887Schin Namval_t *npv; 21534887Schin *cp = 0; 2154*8462SApril.Chin@Sun.COM npv = nv_open(name,shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOADD); 21554887Schin *cp++ = '.'; 21564887Schin if(npv) 21574887Schin nv_setdisc(npv,cp,NIL(Namval_t*),(Namfun_t*)npv); 21584887Schin } 2159*8462SApril.Chin@Sun.COM if(rp->fname && shp->fpathdict && (rq = (struct Ufunction*)nv_search(rp->fname,shp->fpathdict,0))) 2160*8462SApril.Chin@Sun.COM { 2161*8462SApril.Chin@Sun.COM do 2162*8462SApril.Chin@Sun.COM { 2163*8462SApril.Chin@Sun.COM if(rq->np != np) 2164*8462SApril.Chin@Sun.COM continue; 2165*8462SApril.Chin@Sun.COM dtdelete(shp->fpathdict,rq); 2166*8462SApril.Chin@Sun.COM break; 2167*8462SApril.Chin@Sun.COM } 2168*8462SApril.Chin@Sun.COM while(rq = (struct Ufunction*)dtnext(shp->fpathdict,rq)); 2169*8462SApril.Chin@Sun.COM } 2170*8462SApril.Chin@Sun.COM if(rp->sdict) 2171*8462SApril.Chin@Sun.COM { 2172*8462SApril.Chin@Sun.COM Namval_t *mp, *nq; 2173*8462SApril.Chin@Sun.COM for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq) 2174*8462SApril.Chin@Sun.COM { 2175*8462SApril.Chin@Sun.COM nq = dtnext(rp->sdict,mp); 2176*8462SApril.Chin@Sun.COM _nv_unset(mp,NV_RDONLY); 2177*8462SApril.Chin@Sun.COM nv_delete(mp,rp->sdict,0); 2178*8462SApril.Chin@Sun.COM } 2179*8462SApril.Chin@Sun.COM dtclose(rp->sdict); 2180*8462SApril.Chin@Sun.COM } 21814887Schin stakdelete(slp->slptr); 21824887Schin free((void*)np->nvalue.ip); 21834887Schin np->nvalue.ip = 0; 21844887Schin } 21854887Schin goto done; 21864887Schin } 2187*8462SApril.Chin@Sun.COM if(shp->subshell && !nv_isnull(np)) 21884887Schin np = sh_assignok(np,0); 21894887Schin nv_offattr(np,NV_NODISC); 21904887Schin if(np->nvfun && !nv_isref(np)) 21914887Schin { 21924887Schin /* This function contains disc */ 21934887Schin if(!nv_local) 21944887Schin { 21954887Schin nv_local=1; 21964887Schin nv_putv(np,NIL(char*),flags,np->nvfun); 2197*8462SApril.Chin@Sun.COM nv_local=0; 21984887Schin return; 21994887Schin } 22004887Schin /* called from disc, assign the actual value */ 22014887Schin nv_local=0; 22024887Schin } 2203*8462SApril.Chin@Sun.COM if(nv_isarray(np) && np->nvalue.cp!=Empty && np->nvfun) 2204*8462SApril.Chin@Sun.COM up = np->nvalue.up; 2205*8462SApril.Chin@Sun.COM else 2206*8462SApril.Chin@Sun.COM up = &np->nvalue; 2207*8462SApril.Chin@Sun.COM if(up && up->cp) 22084887Schin { 2209*8462SApril.Chin@Sun.COM if(up->cp!=Empty && !nv_isattr(np, NV_NOFREE)) 22104887Schin free((void*)up->cp); 22114887Schin up->cp = 0; 22124887Schin } 22134887Schin done: 22144887Schin if(!nv_isarray(np) || !nv_arrayptr(np)) 22154887Schin { 2216*8462SApril.Chin@Sun.COM if(nv_isref(np) && !nv_isattr(np,NV_EXPORT)) 22174887Schin free((void*)np->nvalue.nrp); 22184887Schin nv_setsize(np,0); 22194887Schin if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT)) 22204887Schin { 22214887Schin if(nv_isattr(np,NV_EXPORT) && !strchr(np->nvname,'[')) 2222*8462SApril.Chin@Sun.COM env_delete(shp->env,nv_name(np)); 2223*8462SApril.Chin@Sun.COM if(!(flags&NV_EXPORT) || nv_isattr(np,NV_IMPORT|NV_EXPORT)==(NV_IMPORT|NV_EXPORT)) 2224*8462SApril.Chin@Sun.COM np->nvenv = 0; 22254887Schin nv_setattr(np,0); 22264887Schin } 22274887Schin else 2228*8462SApril.Chin@Sun.COM { 22294887Schin nv_setattr(np,NV_MINIMAL); 2230*8462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 2231*8462SApril.Chin@Sun.COM } 22324887Schin } 22334887Schin } 22344887Schin 22354887Schin /* 22364887Schin * return the node pointer in the highest level scope 22374887Schin */ 2238*8462SApril.Chin@Sun.COM Namval_t *sh_scoped(Shell_t *shp, register Namval_t *np) 22394887Schin { 2240*8462SApril.Chin@Sun.COM if(!dtvnext(shp->var_tree)) 22414887Schin return(np); 2242*8462SApril.Chin@Sun.COM return(dtsearch(shp->var_tree,np)); 22434887Schin } 22444887Schin 22454887Schin #if 1 22464887Schin /* 22474887Schin * return space separated list of names of variables in given tree 22484887Schin */ 22494887Schin static char *tableval(Dt_t *root) 22504887Schin { 22514887Schin static Sfio_t *out; 22524887Schin register Namval_t *np; 22534887Schin register int first=1; 22544887Schin register Dt_t *base = dtview(root,0); 22554887Schin if(out) 22564887Schin sfseek(out,(Sfoff_t)0,SEEK_SET); 22574887Schin else 22584887Schin out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING); 22594887Schin for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np)) 22604887Schin { 22614887Schin if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE)) 22624887Schin { 22634887Schin if(!first) 22644887Schin sfputc(out,' '); 22654887Schin else 22664887Schin first = 0; 22674887Schin sfputr(out,np->nvname,-1); 22684887Schin } 22694887Schin } 22704887Schin sfputc(out,0); 22714887Schin if(base) 22724887Schin dtview(root,base); 22734887Schin return((char*)out->_data); 22744887Schin } 22754887Schin #endif 22764887Schin 22774887Schin #if SHOPT_OPTIMIZE 22784887Schin struct optimize 22794887Schin { 22804887Schin Namfun_t hdr; 2281*8462SApril.Chin@Sun.COM Shell_t *sh; 22824887Schin char **ptr; 22834887Schin struct optimize *next; 22844887Schin Namval_t *np; 22854887Schin }; 22864887Schin 22874887Schin static struct optimize *opt_free; 22884887Schin 22894887Schin static void optimize_clear(Namval_t* np, Namfun_t *fp) 22904887Schin { 22914887Schin struct optimize *op = (struct optimize*)fp; 22924887Schin nv_stack(np,fp); 22934887Schin nv_stack(np,(Namfun_t*)0); 22944887Schin for(;op && op->np==np; op=op->next) 22954887Schin { 22964887Schin if(op->ptr) 22974887Schin { 22984887Schin *op->ptr = 0; 22994887Schin op->ptr = 0; 23004887Schin } 23014887Schin } 23024887Schin } 23034887Schin 23044887Schin static void put_optimize(Namval_t* np,const char *val,int flags,Namfun_t *fp) 23054887Schin { 23064887Schin nv_putv(np,val,flags,fp); 23074887Schin optimize_clear(np,fp); 23084887Schin } 23094887Schin 2310*8462SApril.Chin@Sun.COM static Namfun_t *clone_optimize(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp) 2311*8462SApril.Chin@Sun.COM { 2312*8462SApril.Chin@Sun.COM return((Namfun_t*)0); 2313*8462SApril.Chin@Sun.COM } 2314*8462SApril.Chin@Sun.COM 2315*8462SApril.Chin@Sun.COM static const Namdisc_t optimize_disc = {sizeof(struct optimize),put_optimize,0,0,0,0,clone_optimize}; 23164887Schin 23174887Schin void nv_optimize(Namval_t *np) 23184887Schin { 23194887Schin register Namfun_t *fp; 23204887Schin register struct optimize *op, *xp; 23214887Schin if(sh.argaddr) 23224887Schin { 2323*8462SApril.Chin@Sun.COM if(np==SH_LINENO) 2324*8462SApril.Chin@Sun.COM { 2325*8462SApril.Chin@Sun.COM sh.argaddr = 0; 2326*8462SApril.Chin@Sun.COM return; 2327*8462SApril.Chin@Sun.COM } 23284887Schin for(fp=np->nvfun; fp; fp = fp->next) 23294887Schin { 2330*8462SApril.Chin@Sun.COM if(fp->disc && (fp->disc->getnum || fp->disc->getval)) 23314887Schin { 23324887Schin sh.argaddr = 0; 23334887Schin return; 23344887Schin } 23354887Schin if(fp->disc== &optimize_disc) 23364887Schin break; 23374887Schin } 23384887Schin if((xp= (struct optimize*)fp) && xp->ptr==sh.argaddr) 23394887Schin return; 23404887Schin if(op = opt_free) 23414887Schin opt_free = op->next; 23424887Schin else 23434887Schin op=(struct optimize*)calloc(1,sizeof(struct optimize)); 23444887Schin op->ptr = sh.argaddr; 23454887Schin op->np = np; 23464887Schin if(xp) 23474887Schin { 23484887Schin op->hdr.disc = 0; 23494887Schin op->next = xp->next; 23504887Schin xp->next = op; 23514887Schin } 23524887Schin else 23534887Schin { 23544887Schin op->hdr.disc = &optimize_disc; 23554887Schin op->next = (struct optimize*)sh.optlist; 23564887Schin sh.optlist = (void*)op; 23574887Schin nv_stack(np,&op->hdr); 23584887Schin } 23594887Schin } 23604887Schin } 23614887Schin 23624887Schin void sh_optclear(Shell_t *shp, void *old) 23634887Schin { 23644887Schin register struct optimize *op,*opnext; 23654887Schin for(op=(struct optimize*)shp->optlist; op; op = opnext) 23664887Schin { 23674887Schin opnext = op->next; 23684887Schin if(op->ptr && op->hdr.disc) 23694887Schin { 23704887Schin nv_stack(op->np,&op->hdr); 23714887Schin nv_stack(op->np,(Namfun_t*)0); 23724887Schin } 23734887Schin op->next = opt_free; 23744887Schin opt_free = op; 23754887Schin } 23764887Schin shp->optlist = old; 23774887Schin } 23784887Schin 23794887Schin #else 23804887Schin # define optimize_clear(np,fp) 23814887Schin #endif /* SHOPT_OPTIMIZE */ 23824887Schin 23834887Schin /* 23844887Schin * Return a pointer to a character string that denotes the value 23854887Schin * of <np>. If <np> refers to an array, return a pointer to 23864887Schin * the value associated with the current index. 23874887Schin * 23884887Schin * If the value of <np> is an integer, the string returned will 23894887Schin * be overwritten by the next call to nv_getval. 23904887Schin * 23914887Schin * If <np> has no value, 0 is returned. 23924887Schin */ 23934887Schin 23944887Schin char *nv_getval(register Namval_t *np) 23954887Schin { 23964887Schin register union Value *up= &np->nvalue; 23974887Schin register int numeric; 23984887Schin #if SHOPT_OPTIMIZE 23994887Schin if(!nv_local && sh.argaddr) 24004887Schin nv_optimize(np); 24014887Schin #endif /* SHOPT_OPTIMIZE */ 2402*8462SApril.Chin@Sun.COM if((!np->nvfun || !np->nvfun->disc) && !nv_isattr(np,NV_ARRAY|NV_INTEGER|NV_FUNCT|NV_REF|NV_TABLE)) 24034887Schin goto done; 24044887Schin if(nv_isref(np)) 24054887Schin { 2406*8462SApril.Chin@Sun.COM if(!np->nvalue.cp) 2407*8462SApril.Chin@Sun.COM return(0); 24084887Schin sh.last_table = nv_reftable(np); 24094887Schin return(nv_name(nv_refnode(np))); 24104887Schin } 2411*8462SApril.Chin@Sun.COM if(np->nvfun && np->nvfun->disc) 24124887Schin { 24134887Schin if(!nv_local) 24144887Schin { 24154887Schin nv_local=1; 24164887Schin return(nv_getv(np, np->nvfun)); 24174887Schin } 24184887Schin nv_local=0; 24194887Schin } 24204887Schin numeric = ((nv_isattr (np, NV_INTEGER)) != 0); 24214887Schin if(numeric) 24224887Schin { 24234887Schin Sflong_t ll; 24244887Schin if(!up->cp) 24254887Schin return("0"); 2426*8462SApril.Chin@Sun.COM if(nv_isattr (np,NV_DOUBLE)==NV_DOUBLE) 24274887Schin { 24284887Schin Sfdouble_t ld; 24294887Schin double d; 24304887Schin char *format; 24314887Schin if(nv_isattr(np,NV_LONG)) 24324887Schin { 24334887Schin ld = *up->ldp; 24344887Schin if(nv_isattr (np,NV_EXPNOTE)) 24354887Schin format = "%.*Lg"; 2436*8462SApril.Chin@Sun.COM else if(nv_isattr (np,NV_HEXFLOAT)) 2437*8462SApril.Chin@Sun.COM format = "%.*La"; 24384887Schin else 24394887Schin format = "%.*Lf"; 24404887Schin sfprintf(sh.strbuf,format,nv_size(np),ld); 24414887Schin } 24424887Schin else 24434887Schin { 24444887Schin d = *up->dp; 24454887Schin if(nv_isattr (np,NV_EXPNOTE)) 24464887Schin format = "%.*g"; 2447*8462SApril.Chin@Sun.COM else if(nv_isattr (np,NV_HEXFLOAT)) 2448*8462SApril.Chin@Sun.COM format = "%.*a"; 24494887Schin else 24504887Schin format = "%.*f"; 24514887Schin sfprintf(sh.strbuf,format,nv_size(np),d); 24524887Schin } 24534887Schin return(sfstruse(sh.strbuf)); 24544887Schin } 24554887Schin else if(nv_isattr(np,NV_UNSIGN)) 24564887Schin { 24574887Schin if(nv_isattr (np,NV_LONG)) 24584887Schin ll = *(Sfulong_t*)up->llp; 24594887Schin else if(nv_isattr (np,NV_SHORT)) 2460*8462SApril.Chin@Sun.COM { 2461*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 2462*8462SApril.Chin@Sun.COM ll = *(uint16_t*)(up->sp); 2463*8462SApril.Chin@Sun.COM else 2464*8462SApril.Chin@Sun.COM ll = (uint16_t)up->s; 2465*8462SApril.Chin@Sun.COM } 24664887Schin else 24674887Schin ll = *(uint32_t*)(up->lp); 24684887Schin } 24694887Schin else if(nv_isattr (np,NV_LONG)) 24704887Schin ll = *up->llp; 24714887Schin else if(nv_isattr (np,NV_SHORT)) 2472*8462SApril.Chin@Sun.COM { 2473*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 2474*8462SApril.Chin@Sun.COM ll = *up->sp; 2475*8462SApril.Chin@Sun.COM else 2476*8462SApril.Chin@Sun.COM ll = up->s; 2477*8462SApril.Chin@Sun.COM } 24784887Schin else 24794887Schin ll = *(up->lp); 24804887Schin if((numeric=nv_size(np))==10) 24814887Schin { 24824887Schin if(nv_isattr(np,NV_UNSIGN)) 24834887Schin { 24844887Schin sfprintf(sh.strbuf,"%I*u",sizeof(ll),ll); 24854887Schin return(sfstruse(sh.strbuf)); 24864887Schin } 24874887Schin numeric = 0; 24884887Schin } 24894887Schin return(fmtbasell(ll,numeric, numeric&&numeric!=10)); 24904887Schin } 24914887Schin done: 24924887Schin #if (_AST_VERSION>=20030127L) 24934887Schin /* 24944887Schin * if NV_RAW flag is on, return pointer to binary data 24954887Schin * otherwise, base64 encode the data and return this string 24964887Schin */ 24974887Schin if(up->cp && nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW)) 24984887Schin { 24994887Schin char *cp; 25004887Schin int size= nv_size(np), insize=(4*size)/3+size/45+8; 25014887Schin base64encode(up->cp, size, (void**)0, cp=getbuf(insize), insize, (void**)0); 25024887Schin return(cp); 25034887Schin } 25044887Schin #endif 25054887Schin if((numeric=nv_size(np)) && up->cp && up->cp[numeric]) 25064887Schin { 25074887Schin char *cp = getbuf(numeric+1); 25084887Schin memcpy(cp,up->cp,numeric); 25094887Schin cp[numeric]=0; 25104887Schin return(cp); 25114887Schin } 25124887Schin return ((char*)up->cp); 25134887Schin } 25144887Schin 25154887Schin Sfdouble_t nv_getnum(register Namval_t *np) 25164887Schin { 25174887Schin register union Value *up; 25184887Schin register Sfdouble_t r=0; 25194887Schin register char *str; 25204887Schin #if SHOPT_OPTIMIZE 25214887Schin if(!nv_local && sh.argaddr) 25224887Schin nv_optimize(np); 25234887Schin #endif /* SHOPT_OPTIMIZE */ 25244887Schin if(nv_istable(np)) 25254887Schin errormsg(SH_DICT,ERROR_exit(1),e_number,nv_name(np)); 2526*8462SApril.Chin@Sun.COM if(np->nvfun && np->nvfun->disc) 25274887Schin { 25284887Schin if(!nv_local) 25294887Schin { 25304887Schin nv_local=1; 25314887Schin return(nv_getn(np, np->nvfun)); 25324887Schin } 25334887Schin nv_local=0; 25344887Schin } 2535*8462SApril.Chin@Sun.COM if(nv_isref(np)) 2536*8462SApril.Chin@Sun.COM { 2537*8462SApril.Chin@Sun.COM str = nv_refsub(np); 2538*8462SApril.Chin@Sun.COM np = nv_refnode(np); 2539*8462SApril.Chin@Sun.COM if(str) 2540*8462SApril.Chin@Sun.COM nv_putsub(np,str,0L); 2541*8462SApril.Chin@Sun.COM } 25424887Schin if(nv_isattr (np, NV_INTEGER)) 25434887Schin { 25444887Schin up= &np->nvalue; 2545*8462SApril.Chin@Sun.COM if(!up->lp || up->cp==Empty) 25464887Schin r = 0; 2547*8462SApril.Chin@Sun.COM else if(nv_isattr(np, NV_DOUBLE)==NV_DOUBLE) 25484887Schin { 25494887Schin if(nv_isattr(np, NV_LONG)) 25504887Schin r = *up->ldp; 25514887Schin else 25524887Schin r = *up->dp; 25534887Schin } 25544887Schin else if(nv_isattr(np, NV_UNSIGN)) 25554887Schin { 25564887Schin if(nv_isattr(np, NV_LONG)) 25574887Schin r = (Sflong_t)*((Sfulong_t*)up->llp); 25584887Schin else if(nv_isattr(np, NV_SHORT)) 2559*8462SApril.Chin@Sun.COM { 2560*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 2561*8462SApril.Chin@Sun.COM r = (Sflong_t)(*(uint16_t*)up->sp); 2562*8462SApril.Chin@Sun.COM else 2563*8462SApril.Chin@Sun.COM r = (Sflong_t)((uint16_t)up->s); 2564*8462SApril.Chin@Sun.COM } 25654887Schin else 25664887Schin r = *((uint32_t*)up->lp); 25674887Schin } 25684887Schin else 25694887Schin { 25704887Schin if(nv_isattr(np, NV_LONG)) 25714887Schin r = *up->llp; 25724887Schin else if(nv_isattr(np, NV_SHORT)) 2573*8462SApril.Chin@Sun.COM { 2574*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 2575*8462SApril.Chin@Sun.COM r = *up->sp; 2576*8462SApril.Chin@Sun.COM else 2577*8462SApril.Chin@Sun.COM r = up->s; 2578*8462SApril.Chin@Sun.COM } 25794887Schin else 25804887Schin r = *up->lp; 25814887Schin } 25824887Schin } 25834887Schin else if((str=nv_getval(np)) && *str!=0) 25844887Schin { 25854887Schin if(np->nvfun || nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL)) 25864887Schin { 25874887Schin while(*str=='0') 25884887Schin str++; 25894887Schin } 25904887Schin r = sh_arith(str); 25914887Schin } 25924887Schin return(r); 25934887Schin } 25944887Schin /* 25954887Schin * Give <np> the attributes <newatts,> and change its current 25964887Schin * value to conform to <newatts>. The <size> of left and right 25974887Schin * justified fields may be given. 25984887Schin */ 25994887Schin void nv_newattr (register Namval_t *np, unsigned newatts, int size) 26004887Schin { 26014887Schin register char *sp; 26024887Schin register char *cp = 0; 26034887Schin register unsigned int n; 26044887Schin Namarr_t *ap = 0; 26054887Schin int oldsize,oldatts; 2606*8462SApril.Chin@Sun.COM Namfun_t *fp= (newatts&NV_NODISC)?np->nvfun:0; 2607*8462SApril.Chin@Sun.COM newatts &= ~NV_NODISC; 26084887Schin 26094887Schin /* check for restrictions */ 26104887Schin if(sh_isoption(SH_RESTRICTED) && ((sp=nv_name(np))==nv_name(PATHNOD) || sp==nv_name(SHELLNOD) || sp==nv_name(ENVNOD) || sp==nv_name(FPATHNOD))) 26114887Schin errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np)); 26124887Schin /* handle attributes that do not change data separately */ 26134887Schin n = np->nvflag; 26144887Schin if(newatts&NV_EXPORT) 26154887Schin nv_offattr(np,NV_IMPORT); 2616*8462SApril.Chin@Sun.COM #ifdef _ENV_H 26174887Schin if(((n^newatts)&NV_EXPORT)) 26184887Schin { 26194887Schin /* record changes to the environment */ 26204887Schin if(n&NV_EXPORT) 26214887Schin env_delete(sh.env,nv_name(np)); 26224887Schin else 26234887Schin sh_envput(sh.env,np); 26244887Schin } 2625*8462SApril.Chin@Sun.COM #endif 26264887Schin if((size==0||(n&NV_INTEGER)) && ((n^newatts)&~NV_NOCHANGE)==0) 26274887Schin { 26284887Schin if(size) 26294887Schin nv_setsize(np,size); 26304887Schin nv_offattr(np, ~NV_NOFREE); 26314887Schin nv_onattr(np, newatts); 26324887Schin return; 26334887Schin } 26344887Schin /* for an array, change all the elements */ 26354887Schin if((ap=nv_arrayptr(np)) && ap->nelem>0) 26364887Schin nv_putsub(np,NIL(char*),ARRAY_SCAN); 26374887Schin oldsize = nv_size(np); 26384887Schin oldatts = np->nvflag; 2639*8462SApril.Chin@Sun.COM if(fp) 2640*8462SApril.Chin@Sun.COM np->nvfun = 0; 26414887Schin if(ap) /* add element to prevent array deletion */ 26424887Schin ap->nelem++; 26434887Schin do 26444887Schin { 26454887Schin nv_setsize(np,oldsize); 26464887Schin np->nvflag = oldatts; 26474887Schin if (sp = nv_getval(np)) 26484887Schin { 26494887Schin if(nv_isattr(np,NV_ZFILL)) 26504887Schin while(*sp=='0') sp++; 26514887Schin cp = (char*)malloc((n=strlen (sp)) + 1); 26524887Schin strcpy(cp, sp); 26534887Schin if(ap) 26544887Schin { 26554887Schin Namval_t *mp; 26564887Schin ap->nelem &= ~ARRAY_SCAN; 26574887Schin if(mp=nv_opensub(np)) 2658*8462SApril.Chin@Sun.COM { 2659*8462SApril.Chin@Sun.COM nv_unset(mp); 2660*8462SApril.Chin@Sun.COM mp->nvalue.cp = Empty; 2661*8462SApril.Chin@Sun.COM } 2662*8462SApril.Chin@Sun.COM else 2663*8462SApril.Chin@Sun.COM nv_unset(np); 2664*8462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 26654887Schin } 2666*8462SApril.Chin@Sun.COM else 2667*8462SApril.Chin@Sun.COM nv_unset(np); 26684887Schin if(size==0 && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL))) 26694887Schin size = n; 26704887Schin } 26714887Schin else 26724887Schin nv_unset(np); 26734887Schin nv_setsize(np,size); 26744887Schin np->nvflag &= NV_ARRAY; 26754887Schin np->nvflag |= newatts; 26764887Schin if (cp) 26774887Schin { 26784887Schin nv_putval (np, cp, NV_RDONLY); 26794887Schin free(cp); 26804887Schin } 26814887Schin } 26824887Schin while(ap && nv_nextsub(np)); 2683*8462SApril.Chin@Sun.COM if(fp) 2684*8462SApril.Chin@Sun.COM np->nvfun = fp; 26854887Schin if(ap) 26864887Schin ap->nelem--; 26874887Schin return; 26884887Schin } 26894887Schin 26904887Schin #ifndef _NEXT_SOURCE 26914887Schin static char *oldgetenv(const char *string) 26924887Schin { 26934887Schin register char c0,c1; 26944887Schin register const char *cp, *sp; 26954887Schin register char **av = environ; 26964887Schin if(!string || (c0= *string)==0) 26974887Schin return(0); 26984887Schin if((c1=*++string)==0) 26994887Schin c1= '='; 27004887Schin while(cp = *av++) 27014887Schin { 27024887Schin if(cp[0]!=c0 || cp[1]!=c1) 27034887Schin continue; 27044887Schin sp = string; 27054887Schin while(*sp && *sp++ == *++cp); 27064887Schin if(*sp==0 && *++cp=='=') 27074887Schin return((char*)(cp+1)); 27084887Schin } 27094887Schin return(0); 27104887Schin } 27114887Schin 27124887Schin /* 27134887Schin * This version of getenv uses the hash storage to access environment values 27144887Schin */ 27154887Schin char *getenv(const char *name) 27164887Schin /*@ 27174887Schin assume name!=0; 27184887Schin @*/ 27194887Schin { 27204887Schin register Namval_t *np; 27214887Schin if(!sh.var_tree) 27224887Schin return(oldgetenv(name)); 27234887Schin if((np = nv_search(name,sh.var_tree,0)) && nv_isattr(np,NV_EXPORT)) 27244887Schin return(nv_getval(np)); 27254887Schin if(name[0] == 'P' && name[1] == 'A' && name[2] == 'T' && name[3] == 'H' && name[4] == 0) 27264887Schin return(oldgetenv(name)); 27274887Schin return(0); 27284887Schin } 27294887Schin #endif /* _NEXT_SOURCE */ 27304887Schin 27314887Schin #undef putenv 27324887Schin /* 27334887Schin * This version of putenv uses the hash storage to assign environment values 27344887Schin */ 27354887Schin int putenv(const char *name) 27364887Schin { 27374887Schin register Namval_t *np; 27384887Schin if(name) 27394887Schin { 27404887Schin np = nv_open(name,sh.var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN); 27414887Schin if(!strchr(name,'=')) 27424887Schin nv_unset(np); 27434887Schin } 27444887Schin return(0); 27454887Schin } 27464887Schin 27474887Schin 27484887Schin /* 27494887Schin * Override libast setenv() 27504887Schin */ 27514887Schin char* setenviron(const char *name) 27524887Schin { 27534887Schin register Namval_t *np; 27544887Schin if(name) 27554887Schin { 27564887Schin np = nv_open(name,sh.var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN); 27574887Schin if(strchr(name,'=')) 27584887Schin return(nv_getval(np)); 27594887Schin nv_unset(np); 27604887Schin } 27614887Schin return(""); 27624887Schin } 27634887Schin 27644887Schin /* 2765*8462SApril.Chin@Sun.COM * convert <str> to upper case 27664887Schin */ 2767*8462SApril.Chin@Sun.COM static void ltou(register char *str) 27684887Schin { 27694887Schin register int c; 2770*8462SApril.Chin@Sun.COM for(; c= *((unsigned char*)str); str++) 27714887Schin { 27724887Schin if(islower(c)) 2773*8462SApril.Chin@Sun.COM *str = toupper(c); 27744887Schin } 2775*8462SApril.Chin@Sun.COM } 2776*8462SApril.Chin@Sun.COM 2777*8462SApril.Chin@Sun.COM /* 2778*8462SApril.Chin@Sun.COM * convert <str> to lower case 2779*8462SApril.Chin@Sun.COM */ 2780*8462SApril.Chin@Sun.COM static void utol(register char *str) 2781*8462SApril.Chin@Sun.COM { 2782*8462SApril.Chin@Sun.COM register int c; 2783*8462SApril.Chin@Sun.COM for(; c= *((unsigned char*)str); str++) 2784*8462SApril.Chin@Sun.COM { 2785*8462SApril.Chin@Sun.COM if(isupper(c)) 2786*8462SApril.Chin@Sun.COM *str = tolower(c); 2787*8462SApril.Chin@Sun.COM } 27884887Schin } 27894887Schin 27904887Schin /* 27914887Schin * normalize <cp> and return pointer to subscript if any 2792*8462SApril.Chin@Sun.COM * if <eq> is specified, return pointer to first = not in a subscript 27934887Schin */ 2794*8462SApril.Chin@Sun.COM static char *lastdot(register char *cp, int eq) 27954887Schin { 2796*8462SApril.Chin@Sun.COM register char *ep=0; 27974887Schin register int c; 2798*8462SApril.Chin@Sun.COM if(eq) 2799*8462SApril.Chin@Sun.COM cp++; 28004887Schin while(c= *cp++) 28014887Schin { 28024887Schin if(c=='[') 2803*8462SApril.Chin@Sun.COM cp = nv_endsubscript((Namval_t*)0,ep=cp,0); 28044887Schin else if(c=='.') 28054887Schin { 28064887Schin if(*cp=='[') 2807*8462SApril.Chin@Sun.COM cp = nv_endsubscript((Namval_t*)0,cp,0); 28084887Schin ep = 0; 28094887Schin } 2810*8462SApril.Chin@Sun.COM else if(eq && c == '=') 2811*8462SApril.Chin@Sun.COM return(cp-1); 28124887Schin } 2813*8462SApril.Chin@Sun.COM return(eq?0:ep); 2814*8462SApril.Chin@Sun.COM } 2815*8462SApril.Chin@Sun.COM 2816*8462SApril.Chin@Sun.COM int nv_rename(register Namval_t *np, int flags) 2817*8462SApril.Chin@Sun.COM { 2818*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 2819*8462SApril.Chin@Sun.COM register Namval_t *mp=0,*nr=0; 2820*8462SApril.Chin@Sun.COM register char *cp; 2821*8462SApril.Chin@Sun.COM int index= -1; 2822*8462SApril.Chin@Sun.COM Namval_t *last_table = shp->last_table; 2823*8462SApril.Chin@Sun.COM Dt_t *last_root = shp->last_root; 2824*8462SApril.Chin@Sun.COM Dt_t *hp = 0; 2825*8462SApril.Chin@Sun.COM if(nv_isattr(np,NV_PARAM) && shp->st.prevst) 2826*8462SApril.Chin@Sun.COM { 2827*8462SApril.Chin@Sun.COM if(!(hp=(Dt_t*)shp->st.prevst->save_tree)) 2828*8462SApril.Chin@Sun.COM hp = dtvnext(shp->var_tree); 2829*8462SApril.Chin@Sun.COM } 2830*8462SApril.Chin@Sun.COM if(!(cp=nv_getval(np))) 2831*8462SApril.Chin@Sun.COM { 2832*8462SApril.Chin@Sun.COM if(flags&NV_MOVE) 2833*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_varname,""); 2834*8462SApril.Chin@Sun.COM return(0); 2835*8462SApril.Chin@Sun.COM } 2836*8462SApril.Chin@Sun.COM if(lastdot(cp,0) && nv_isattr(np,NV_MINIMAL)) 2837*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_varname,nv_name(np)); 2838*8462SApril.Chin@Sun.COM if(nv_isarray(np) && !(mp=nv_opensub(np))) 2839*8462SApril.Chin@Sun.COM index=nv_aindex(np); 2840*8462SApril.Chin@Sun.COM if(!hp) 2841*8462SApril.Chin@Sun.COM hp = shp->var_tree; 2842*8462SApril.Chin@Sun.COM if(!(nr = nv_open(cp, hp, flags|NV_ARRAY|NV_NOREF|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))) 2843*8462SApril.Chin@Sun.COM hp = shp->var_base; 2844*8462SApril.Chin@Sun.COM else if(shp->last_root) 2845*8462SApril.Chin@Sun.COM hp = shp->last_root; 2846*8462SApril.Chin@Sun.COM if(!nr) 2847*8462SApril.Chin@Sun.COM nr= nv_open(cp, hp, flags|NV_NOREF|((flags&NV_MOVE)?0:NV_NOFAIL)); 2848*8462SApril.Chin@Sun.COM if(!nr) 2849*8462SApril.Chin@Sun.COM { 2850*8462SApril.Chin@Sun.COM if(!nv_isvtree(np)) 2851*8462SApril.Chin@Sun.COM _nv_unset(np,0); 2852*8462SApril.Chin@Sun.COM return(0); 2853*8462SApril.Chin@Sun.COM } 2854*8462SApril.Chin@Sun.COM if(!mp && index>=0 && nv_isvtree(nr)) 2855*8462SApril.Chin@Sun.COM { 2856*8462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"%s[%d]%c",nv_name(np),index,0); 2857*8462SApril.Chin@Sun.COM /* create a virtual node */ 2858*8462SApril.Chin@Sun.COM if(mp = nv_open(sfstruse(shp->strbuf),shp->var_tree,NV_VARNAME|NV_ADD|NV_ARRAY)) 2859*8462SApril.Chin@Sun.COM mp->nvenv = (void*)np; 2860*8462SApril.Chin@Sun.COM } 2861*8462SApril.Chin@Sun.COM if(mp) 2862*8462SApril.Chin@Sun.COM np = mp; 2863*8462SApril.Chin@Sun.COM if(nr==np) 2864*8462SApril.Chin@Sun.COM { 2865*8462SApril.Chin@Sun.COM if(index<0) 2866*8462SApril.Chin@Sun.COM return(0); 2867*8462SApril.Chin@Sun.COM if(cp = nv_getval(np)) 2868*8462SApril.Chin@Sun.COM cp = strdup(cp); 2869*8462SApril.Chin@Sun.COM } 2870*8462SApril.Chin@Sun.COM _nv_unset(np,0); 2871*8462SApril.Chin@Sun.COM if(nr==np) 2872*8462SApril.Chin@Sun.COM { 2873*8462SApril.Chin@Sun.COM nv_putsub(np,(char*)0, index); 2874*8462SApril.Chin@Sun.COM nv_putval(np,cp,0); 2875*8462SApril.Chin@Sun.COM free((void*)cp); 2876*8462SApril.Chin@Sun.COM return(1); 2877*8462SApril.Chin@Sun.COM } 2878*8462SApril.Chin@Sun.COM shp->prev_table = shp->last_table; 2879*8462SApril.Chin@Sun.COM shp->prev_root = shp->last_root; 2880*8462SApril.Chin@Sun.COM shp->last_table = last_table; 2881*8462SApril.Chin@Sun.COM shp->last_root = last_root; 2882*8462SApril.Chin@Sun.COM nv_clone(nr,np,(flags&NV_MOVE)|NV_COMVAR); 2883*8462SApril.Chin@Sun.COM if(flags&NV_MOVE) 2884*8462SApril.Chin@Sun.COM nv_delete(nr,(Dt_t*)0,NV_NOFREE); 2885*8462SApril.Chin@Sun.COM return(1); 28864887Schin } 28874887Schin 28884887Schin /* 28894887Schin * Create a reference node from <np> to $np in dictionary <hp> 28904887Schin */ 28914887Schin void nv_setref(register Namval_t *np, Dt_t *hp, int flags) 28924887Schin { 2893*8462SApril.Chin@Sun.COM Shell_t *shp = &sh; 2894*8462SApril.Chin@Sun.COM register Namval_t *nq, *nr=0; 28954887Schin register char *ep,*cp; 28964887Schin if(nv_isref(np)) 28974887Schin return; 28984887Schin if(nv_isarray(np)) 28994887Schin errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np)); 29004887Schin if(!(cp=nv_getval(np))) 2901*8462SApril.Chin@Sun.COM { 2902*8462SApril.Chin@Sun.COM nv_unset(np); 2903*8462SApril.Chin@Sun.COM nv_onattr(np,NV_REF); 2904*8462SApril.Chin@Sun.COM return; 2905*8462SApril.Chin@Sun.COM } 2906*8462SApril.Chin@Sun.COM if((ep = lastdot(cp,0)) && nv_isattr(np,NV_MINIMAL)) 29074887Schin errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np)); 29084887Schin if(!hp) 2909*8462SApril.Chin@Sun.COM hp = shp->var_tree; 2910*8462SApril.Chin@Sun.COM if(!(nr = nq = nv_open(cp, hp, flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))) 2911*8462SApril.Chin@Sun.COM hp = shp->var_base; 2912*8462SApril.Chin@Sun.COM else if(shp->last_root) 2913*8462SApril.Chin@Sun.COM hp = shp->last_root; 2914*8462SApril.Chin@Sun.COM if(nq && ep && nv_isarray(nq) && !nv_getsub(nq)) 2915*8462SApril.Chin@Sun.COM nv_endsubscript(nq,ep-1,NV_ADD); 2916*8462SApril.Chin@Sun.COM if(!nr) 2917*8462SApril.Chin@Sun.COM nr= nq = nv_open(cp, hp, flags); 29184887Schin if(nr==np) 29194887Schin { 2920*8462SApril.Chin@Sun.COM if(shp->namespace && nv_dict(shp->namespace)==hp) 29214887Schin errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np)); 29224887Schin /* bind to earlier scope, or add to global scope */ 29234887Schin if(!(hp=dtvnext(hp)) || (nq=nv_search((char*)np,hp,NV_ADD|HASH_BUCKET))==np) 29244887Schin errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np)); 29254887Schin } 29264887Schin if(ep) 29274887Schin { 29284887Schin /* cause subscript evaluation and return result */ 2929*8462SApril.Chin@Sun.COM if(nv_isarray(nq)) 2930*8462SApril.Chin@Sun.COM ep = nv_getsub(nq); 2931*8462SApril.Chin@Sun.COM else 2932*8462SApril.Chin@Sun.COM { 2933*8462SApril.Chin@Sun.COM ep[strlen(ep)-1] = 0; 2934*8462SApril.Chin@Sun.COM nv_putsub(nr, ep, 0); 2935*8462SApril.Chin@Sun.COM ep[strlen(ep)-1] = ']'; 2936*8462SApril.Chin@Sun.COM if(nq = nv_opensub(nr)) 2937*8462SApril.Chin@Sun.COM ep = 0; 2938*8462SApril.Chin@Sun.COM else 2939*8462SApril.Chin@Sun.COM nq = nr; 2940*8462SApril.Chin@Sun.COM } 29414887Schin } 29424887Schin nv_unset(np); 2943*8462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 29444887Schin np->nvalue.nrp = newof(0,struct Namref,1,0); 29454887Schin np->nvalue.nrp->np = nq; 29464887Schin np->nvalue.nrp->root = hp; 29474887Schin if(ep) 29484887Schin np->nvalue.nrp->sub = strdup(ep); 2949*8462SApril.Chin@Sun.COM np->nvalue.nrp->table = shp->last_table; 29504887Schin nv_onattr(np,NV_REF|NV_NOFREE); 29514887Schin } 29524887Schin 29534887Schin /* 29544887Schin * get the scope corresponding to <index> 29554887Schin * whence uses the same values as lseeek() 29564887Schin */ 29574887Schin Shscope_t *sh_getscope(int index, int whence) 29584887Schin { 29594887Schin register struct sh_scoped *sp, *topmost; 29604887Schin if(whence==SEEK_CUR) 29614887Schin sp = &sh.st; 29624887Schin else 29634887Schin { 29644887Schin if ((struct sh_scoped*)sh.topscope != sh.st.self) 29654887Schin topmost = (struct sh_scoped*)sh.topscope; 29664887Schin else 29674887Schin topmost = &(sh.st); 29684887Schin sp = topmost; 29694887Schin if(whence==SEEK_SET) 29704887Schin { 29714887Schin int n =0; 29724887Schin while(sp = sp->prevst) 29734887Schin n++; 29744887Schin index = n - index; 29754887Schin sp = topmost; 29764887Schin } 29774887Schin } 29784887Schin if(index < 0) 29794887Schin return((Shscope_t*)0); 29804887Schin while(index-- && (sp = sp->prevst)); 29814887Schin return((Shscope_t*)sp); 29824887Schin } 29834887Schin 29844887Schin /* 29854887Schin * make <scoped> the top scope and return previous scope 29864887Schin */ 29874887Schin Shscope_t *sh_setscope(Shscope_t *scope) 29884887Schin { 29894887Schin Shscope_t *old = (Shscope_t*)sh.st.self; 29904887Schin *sh.st.self = sh.st; 29914887Schin sh.st = *((struct sh_scoped*)scope); 29924887Schin sh.var_tree = scope->var_tree; 2993*8462SApril.Chin@Sun.COM SH_PATHNAMENOD->nvalue.cp = sh.st.filename; 2994*8462SApril.Chin@Sun.COM SH_FUNNAMENOD->nvalue.cp = sh.st.funname; 29954887Schin return(old); 29964887Schin } 29974887Schin 2998*8462SApril.Chin@Sun.COM void sh_unscope(Shell_t *shp) 29994887Schin { 3000*8462SApril.Chin@Sun.COM register Dt_t *root = shp->var_tree; 30014887Schin register Dt_t *dp = dtview(root,(Dt_t*)0); 3002*8462SApril.Chin@Sun.COM table_unset(shp,root,NV_RDONLY|NV_NOSCOPE,dp); 3003*8462SApril.Chin@Sun.COM if(shp->st.real_fun && dp==shp->st.real_fun->sdict) 3004*8462SApril.Chin@Sun.COM { 3005*8462SApril.Chin@Sun.COM dp = dtview(dp,(Dt_t*)0); 3006*8462SApril.Chin@Sun.COM shp->st.real_fun->sdict->view = dp; 3007*8462SApril.Chin@Sun.COM } 3008*8462SApril.Chin@Sun.COM shp->var_tree=dp; 30094887Schin dtclose(root); 30104887Schin } 30114887Schin 30124887Schin /* 30134887Schin * The inverse of creating a reference node 30144887Schin */ 30154887Schin void nv_unref(register Namval_t *np) 30164887Schin { 30174887Schin Namval_t *nq; 30184887Schin if(!nv_isref(np)) 30194887Schin return; 30204887Schin nq = nv_refnode(np); 30214887Schin nv_offattr(np,NV_NOFREE|NV_REF); 30224887Schin free((void*)np->nvalue.nrp); 30234887Schin np->nvalue.cp = strdup(nv_name(nq)); 30244887Schin #if SHOPT_OPTIMIZE 30254887Schin { 30264887Schin Namfun_t *fp; 30274887Schin for(fp=nq->nvfun; fp; fp = fp->next) 30284887Schin { 30294887Schin if(fp->disc== &optimize_disc) 30304887Schin { 30314887Schin optimize_clear(nq,fp); 30324887Schin return; 30334887Schin } 30344887Schin } 30354887Schin } 30364887Schin #endif 30374887Schin } 30384887Schin 30394887Schin /* 30404887Schin * These following are for binary compatibility with the old hash library 30414887Schin * They will be removed someday 30424887Schin */ 30434887Schin 30444887Schin #if defined(__IMPORT__) && defined(__EXPORT__) 30454887Schin # define extern __EXPORT__ 30464887Schin #endif 30474887Schin 30484887Schin #undef hashscope 30494887Schin 30504887Schin extern Dt_t *hashscope(Dt_t *root) 30514887Schin { 30524887Schin return(dtvnext(root)); 30534887Schin } 30544887Schin 30554887Schin #undef hashfree 30564887Schin 30574887Schin extern Dt_t *hashfree(Dt_t *root) 30584887Schin { 30594887Schin Dt_t *dp = dtvnext(root); 30604887Schin dtclose(root); 30614887Schin return(dp); 30624887Schin } 30634887Schin 30644887Schin #undef hashname 30654887Schin 30664887Schin extern char *hashname(void *obj) 30674887Schin { 30684887Schin Namval_t *np = (Namval_t*)obj; 30694887Schin return(np->nvname); 30704887Schin } 30714887Schin 30724887Schin #undef hashlook 30734887Schin 30744887Schin extern void *hashlook(Dt_t *root, const char *name, int mode,int size) 30754887Schin { 30764887Schin NOT_USED(size); 30774887Schin return((void*)nv_search(name,root,mode)); 30784887Schin } 30794887Schin 30804887Schin char *nv_name(register Namval_t *np) 30814887Schin { 30824887Schin register Namval_t *table; 30834887Schin register Namfun_t *fp; 30844887Schin char *cp; 30854887Schin if(is_abuiltin(np) || is_afunction(np)) 30864887Schin return(np->nvname); 3087*8462SApril.Chin@Sun.COM if(!nv_isattr(np,NV_MINIMAL|NV_EXPORT) && np->nvenv) 3088*8462SApril.Chin@Sun.COM { 3089*8462SApril.Chin@Sun.COM Namval_t *nq= sh.last_table, *mp= (Namval_t*)np->nvenv; 3090*8462SApril.Chin@Sun.COM if(np==sh.last_table) 3091*8462SApril.Chin@Sun.COM sh.last_table = 0; 3092*8462SApril.Chin@Sun.COM if(nv_isarray(mp)) 3093*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s[%s]",nv_name(mp),np->nvname); 3094*8462SApril.Chin@Sun.COM else 3095*8462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s.%s",nv_name(mp),np->nvname); 3096*8462SApril.Chin@Sun.COM sh.last_table = nq; 3097*8462SApril.Chin@Sun.COM return(sfstruse(sh.strbuf)); 3098*8462SApril.Chin@Sun.COM } 30994887Schin if(nv_istable(np)) 31004887Schin #if 1 31014887Schin sh.last_table = nv_parent(np); 31024887Schin #else 31034887Schin sh.last_table = nv_create(np,0, NV_LAST,(Namfun_t*)0); 31044887Schin #endif 31054887Schin else if(!nv_isref(np)) 31064887Schin { 31074887Schin for(fp= np->nvfun ; fp; fp=fp->next) 31084887Schin if(fp->disc && fp->disc->namef) 31094887Schin { 31104887Schin if(np==sh.last_table) 31114887Schin sh.last_table = 0; 31124887Schin return((*fp->disc->namef)(np,fp)); 31134887Schin } 31144887Schin } 31154887Schin if(!(table=sh.last_table) || *np->nvname=='.' || table==sh.namespace || np==table) 31164887Schin return(np->nvname); 31174887Schin cp = nv_name(table); 31184887Schin sfprintf(sh.strbuf,"%s.%s",cp,np->nvname); 31194887Schin return(sfstruse(sh.strbuf)); 31204887Schin } 31214887Schin 31224887Schin Namval_t *nv_lastdict(void) 31234887Schin { 31244887Schin return(sh.last_table); 31254887Schin } 31264887Schin 31274887Schin #undef nv_context 31284887Schin /* 31294887Schin * returns the data context for a builtin 31304887Schin */ 31314887Schin void *nv_context(Namval_t *np) 31324887Schin { 31334887Schin return((void*)np->nvfun); 31344887Schin } 31354887Schin 31364887Schin #define DISABLE /* proto workaround */ 31374887Schin 31384887Schin int nv_isnull DISABLE (register Namval_t *np) 31394887Schin { 31404887Schin return(nv_isnull(np)); 31414887Schin } 31424887Schin 31434887Schin #undef nv_setsize 31444887Schin int nv_setsize(register Namval_t *np, int size) 31454887Schin { 31464887Schin int oldsize = nv_size(np); 31474887Schin if(size>=0) 31484887Schin np->nvsize = size; 31494887Schin return(oldsize); 31504887Schin } 3151*8462SApril.Chin@Sun.COM 3152*8462SApril.Chin@Sun.COM Shell_t *nv_shell(Namval_t *np) 3153*8462SApril.Chin@Sun.COM { 3154*8462SApril.Chin@Sun.COM Namfun_t *fp; 3155*8462SApril.Chin@Sun.COM for(fp=np->nvfun;fp;fp=fp->next) 3156*8462SApril.Chin@Sun.COM { 3157*8462SApril.Chin@Sun.COM if(!fp->disc) 3158*8462SApril.Chin@Sun.COM return((Shell_t*)fp->last); 3159*8462SApril.Chin@Sun.COM } 3160*8462SApril.Chin@Sun.COM return(0); 3161*8462SApril.Chin@Sun.COM } 3162*8462SApril.Chin@Sun.COM 3163*8462SApril.Chin@Sun.COM #undef nv_unset 3164*8462SApril.Chin@Sun.COM 3165*8462SApril.Chin@Sun.COM void nv_unset(register Namval_t *np) 3166*8462SApril.Chin@Sun.COM { 3167*8462SApril.Chin@Sun.COM _nv_unset(np,0); 3168*8462SApril.Chin@Sun.COM return; 3169*8462SApril.Chin@Sun.COM } 3170