14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.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 "variables.h" 304887Schin #include "path.h" 314887Schin #include "lexstates.h" 324887Schin #include "timeout.h" 334887Schin #include "FEATURE/externs" 344887Schin #include "streval.h" 354887Schin 368462SApril.Chin@Sun.COM #define NVCACHE 8 /* must be a power of 2 */ 378462SApril.Chin@Sun.COM #define Empty ((char*)(e_sptbnl+3)) 384887Schin static char *savesub = 0; 394887Schin 404887Schin #if !_lib_pathnative && _lib_uwin_path 414887Schin 424887Schin #define _lib_pathnative 1 434887Schin 444887Schin extern int uwin_path(const char*, char*, int); 454887Schin 464887Schin size_t 474887Schin pathnative(const char* path, char* buf, size_t siz) 484887Schin { 494887Schin return uwin_path(path, buf, siz); 504887Schin } 514887Schin 524887Schin #endif /* _lib_pathnative */ 534887Schin 544887Schin static void attstore(Namval_t*,void*); 554887Schin #ifndef _ENV_H 56*12068SRoger.Faulkner@Oracle.COM static void pushnam(Namval_t*,void*); 57*12068SRoger.Faulkner@Oracle.COM static char *staknam(Namval_t*, char*); 584887Schin #endif 598462SApril.Chin@Sun.COM static void ltou(char*); 608462SApril.Chin@Sun.COM static void utol(char*); 614887Schin static void rightjust(char*, int, int); 628462SApril.Chin@Sun.COM static char *lastdot(char*, int); 634887Schin 644887Schin struct adata 654887Schin { 668462SApril.Chin@Sun.COM Shell_t *sh; 678462SApril.Chin@Sun.COM Namval_t *tp; 688462SApril.Chin@Sun.COM char **argnam; 698462SApril.Chin@Sun.COM int attsize; 708462SApril.Chin@Sun.COM char *attval; 714887Schin }; 724887Schin 738462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 748462SApril.Chin@Sun.COM struct sh_type 758462SApril.Chin@Sun.COM { 768462SApril.Chin@Sun.COM void *previous; 778462SApril.Chin@Sun.COM Namval_t **nodes; 788462SApril.Chin@Sun.COM Namval_t *rp; 798462SApril.Chin@Sun.COM short numnodes; 808462SApril.Chin@Sun.COM short maxnodes; 818462SApril.Chin@Sun.COM }; 828462SApril.Chin@Sun.COM #endif /*SHOPT_TYPEDEF */ 838462SApril.Chin@Sun.COM 848462SApril.Chin@Sun.COM #if NVCACHE 858462SApril.Chin@Sun.COM struct Namcache 868462SApril.Chin@Sun.COM { 878462SApril.Chin@Sun.COM struct Cache_entry 888462SApril.Chin@Sun.COM { 898462SApril.Chin@Sun.COM Dt_t *root; 9010898Sroland.mainz@nrubsig.org Dt_t *last_root; 918462SApril.Chin@Sun.COM char *name; 928462SApril.Chin@Sun.COM Namval_t *np; 938462SApril.Chin@Sun.COM Namval_t *last_table; 948462SApril.Chin@Sun.COM int flags; 958462SApril.Chin@Sun.COM short size; 968462SApril.Chin@Sun.COM short len; 978462SApril.Chin@Sun.COM } entries[NVCACHE]; 988462SApril.Chin@Sun.COM short index; 998462SApril.Chin@Sun.COM short ok; 1008462SApril.Chin@Sun.COM }; 1018462SApril.Chin@Sun.COM static struct Namcache nvcache; 1028462SApril.Chin@Sun.COM #endif 1038462SApril.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); 1738462SApril.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 } 1918462SApril.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 2038462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 2048462SApril.Chin@Sun.COM Namval_t *nv_addnode(Namval_t* np, int remove) 2058462SApril.Chin@Sun.COM { 2068462SApril.Chin@Sun.COM register struct sh_type *sp = (struct sh_type*)sh.mktype; 2078462SApril.Chin@Sun.COM register int i; 2088462SApril.Chin@Sun.COM register char *name=0; 2098462SApril.Chin@Sun.COM if(sp->numnodes==0 && !nv_isnull(np) && sh.last_table) 2108462SApril.Chin@Sun.COM { 2118462SApril.Chin@Sun.COM /* could be an redefine */ 2128462SApril.Chin@Sun.COM Dt_t *root = nv_dict(sh.last_table); 2138462SApril.Chin@Sun.COM sp->rp = np; 2148462SApril.Chin@Sun.COM nv_delete(np,root,NV_NOFREE); 2158462SApril.Chin@Sun.COM np = nv_search(sp->rp->nvname,root,NV_ADD); 2168462SApril.Chin@Sun.COM } 2178462SApril.Chin@Sun.COM if(sp->numnodes && memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1)) 2188462SApril.Chin@Sun.COM { 2198462SApril.Chin@Sun.COM name = (sp->nodes[0])->nvname; 2208462SApril.Chin@Sun.COM i = strlen(name); 2218462SApril.Chin@Sun.COM if(memcmp(np->nvname,name,i)) 2228462SApril.Chin@Sun.COM return(np); 2238462SApril.Chin@Sun.COM } 2248462SApril.Chin@Sun.COM if(sp->rp && sp->numnodes) 2258462SApril.Chin@Sun.COM { 2268462SApril.Chin@Sun.COM /* check for a redefine */ 2278462SApril.Chin@Sun.COM if(name && np->nvname[i]=='.' && np->nvname[i+1]=='_' && np->nvname[i+2]==0) 2288462SApril.Chin@Sun.COM sp->rp = 0; 2298462SApril.Chin@Sun.COM else 2308462SApril.Chin@Sun.COM { 2318462SApril.Chin@Sun.COM Dt_t *root = nv_dict(sh.last_table); 2328462SApril.Chin@Sun.COM nv_delete(sp->nodes[0],root,NV_NOFREE); 2338462SApril.Chin@Sun.COM dtinsert(root,sp->rp); 2348462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_redef,sp->nodes[0]->nvname); 2358462SApril.Chin@Sun.COM } 2368462SApril.Chin@Sun.COM } 2378462SApril.Chin@Sun.COM for(i=0; i < sp->numnodes; i++) 2388462SApril.Chin@Sun.COM { 2398462SApril.Chin@Sun.COM if(np == sp->nodes[i]) 2408462SApril.Chin@Sun.COM { 2418462SApril.Chin@Sun.COM if(remove) 2428462SApril.Chin@Sun.COM { 2438462SApril.Chin@Sun.COM while(++i < sp->numnodes) 2448462SApril.Chin@Sun.COM sp->nodes[i-1] = sp->nodes[i]; 2458462SApril.Chin@Sun.COM sp->numnodes--; 2468462SApril.Chin@Sun.COM } 2478462SApril.Chin@Sun.COM return(np); 2488462SApril.Chin@Sun.COM } 2498462SApril.Chin@Sun.COM } 2508462SApril.Chin@Sun.COM if(remove) 2518462SApril.Chin@Sun.COM return(np); 2528462SApril.Chin@Sun.COM if(sp->numnodes==sp->maxnodes) 2538462SApril.Chin@Sun.COM { 2548462SApril.Chin@Sun.COM sp->maxnodes += 20; 2558462SApril.Chin@Sun.COM sp->nodes = (Namval_t**)realloc(sp->nodes,sizeof(Namval_t*)*sp->maxnodes); 2568462SApril.Chin@Sun.COM } 2578462SApril.Chin@Sun.COM sp->nodes[sp->numnodes++] = np; 2588462SApril.Chin@Sun.COM return(np); 2598462SApril.Chin@Sun.COM } 2608462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 2618462SApril.Chin@Sun.COM 2628462SApril.Chin@Sun.COM /* 2638462SApril.Chin@Sun.COM * given a list of assignments, determine <name> is on the list 2648462SApril.Chin@Sun.COM returns a pointer to the argnod on the list or NULL 2658462SApril.Chin@Sun.COM */ 2668462SApril.Chin@Sun.COM struct argnod *nv_onlist(struct argnod *arg, const char *name) 2678462SApril.Chin@Sun.COM { 2688462SApril.Chin@Sun.COM char *cp; 2698462SApril.Chin@Sun.COM int len = strlen(name); 2708462SApril.Chin@Sun.COM for(;arg; arg=arg->argnxt.ap) 2718462SApril.Chin@Sun.COM { 2728462SApril.Chin@Sun.COM if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE))) 2738462SApril.Chin@Sun.COM cp = ((struct fornod*)arg->argchn.ap)->fornam; 2748462SApril.Chin@Sun.COM else 2758462SApril.Chin@Sun.COM cp = arg->argval; 2768462SApril.Chin@Sun.COM if(memcmp(cp,name,len)==0 && (cp[len]==0 || cp[len]=='=')) 2778462SApril.Chin@Sun.COM return(arg); 2788462SApril.Chin@Sun.COM } 2798462SApril.Chin@Sun.COM return(0); 2808462SApril.Chin@Sun.COM } 2818462SApril.Chin@Sun.COM 2824887Schin /* 2834887Schin * Perform parameter assignment for a linked list of parameters 2844887Schin * <flags> contains attributes for the parameters 2854887Schin */ 28610898Sroland.mainz@nrubsig.org void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ) 2874887Schin { 2888462SApril.Chin@Sun.COM Shell_t *shp = &sh; 2894887Schin register char *cp; 2908462SApril.Chin@Sun.COM register Namval_t *np, *mp; 2918462SApril.Chin@Sun.COM char *trap=shp->st.trap[SH_DEBUGTRAP]; 2928462SApril.Chin@Sun.COM char *prefix = shp->prefix; 2934887Schin int traceon = (sh_isoption(SH_XTRACE)!=0); 2944887Schin int array = (flags&(NV_ARRAY|NV_IARRAY)); 2958462SApril.Chin@Sun.COM Namarr_t *ap; 2968462SApril.Chin@Sun.COM Namval_t node; 2978462SApril.Chin@Sun.COM struct Namref nr; 2988462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 2998462SApril.Chin@Sun.COM int maketype = flags&NV_TYPE; 3008462SApril.Chin@Sun.COM struct sh_type shtp; 3018462SApril.Chin@Sun.COM if(maketype) 3028462SApril.Chin@Sun.COM { 3038462SApril.Chin@Sun.COM shtp.previous = shp->mktype; 3048462SApril.Chin@Sun.COM shp->mktype=(void*)&shtp; 3058462SApril.Chin@Sun.COM shtp.numnodes=0; 3068462SApril.Chin@Sun.COM shtp.maxnodes = 20; 3078462SApril.Chin@Sun.COM shtp.rp = 0; 3088462SApril.Chin@Sun.COM shtp.nodes =(Namval_t**)malloc(shtp.maxnodes*sizeof(Namval_t*)); 3098462SApril.Chin@Sun.COM } 3108462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF*/ 3118462SApril.Chin@Sun.COM flags &= ~(NV_TYPE|NV_ARRAY|NV_IARRAY); 3124887Schin if(sh_isoption(SH_ALLEXPORT)) 3134887Schin flags |= NV_EXPORT; 3148462SApril.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 { 3218462SApril.Chin@Sun.COM shp->used_pos = 0; 3224887Schin if(arg->argflag&ARG_MAC) 3238462SApril.Chin@Sun.COM { 3248462SApril.Chin@Sun.COM shp->prefix = 0; 3258462SApril.Chin@Sun.COM cp = sh_mactrim(shp,arg->argval,(flags&NV_NOREF)?-3:-1); 3268462SApril.Chin@Sun.COM shp->prefix = prefix; 3278462SApril.Chin@Sun.COM } 3284887Schin else 3294887Schin { 3304887Schin stakseek(0); 3318462SApril.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); 3348462SApril.Chin@Sun.COM int sub=0; 3354887Schin struct fornod *fp=(struct fornod*)arg->argchn.ap; 3364887Schin register Shnode_t *tp=fp->fortre; 3378462SApril.Chin@Sun.COM flag |= (flags&(NV_NOSCOPE|NV_STATIC)); 3384887Schin if(arg->argflag&ARG_QUOTED) 3398462SApril.Chin@Sun.COM cp = sh_mactrim(shp,fp->fornam,-1); 3404887Schin else 3414887Schin cp = fp->fornam; 3428462SApril.Chin@Sun.COM error_info.line = fp->fortyp-shp->st.firstline; 34310898Sroland.mainz@nrubsig.org if(!array && tp->tre.tretyp!=TLST && tp->com.comset && !tp->com.comarg && tp->com.comset->argval[0]==0 && tp->com.comset->argval[1]=='[') 34410898Sroland.mainz@nrubsig.org array |= (tp->com.comset->argflag&ARG_MESSAGE)?NV_IARRAY:NV_ARRAY; 3458462SApril.Chin@Sun.COM if(shp->fn_depth && (Namval_t*)tp->com.comnamp==SYSTYPESET) 3464887Schin flag |= NV_NOSCOPE; 3474887Schin if(prefix && tp->com.comset && *cp=='[') 3484887Schin { 3498462SApril.Chin@Sun.COM shp->prefix = 0; 3508462SApril.Chin@Sun.COM np = nv_open(prefix,shp->var_tree,flag); 3518462SApril.Chin@Sun.COM shp->prefix = prefix; 3524887Schin if(np) 3534887Schin { 3548462SApril.Chin@Sun.COM if(nv_isvtree(np) && !nv_isarray(np)) 3554887Schin { 3564887Schin stakputc('.'); 3574887Schin stakputs(cp); 3584887Schin cp = stakfreeze(1); 3594887Schin } 3604887Schin nv_close(np); 3614887Schin } 3624887Schin } 3638462SApril.Chin@Sun.COM np = nv_open(cp,shp->var_tree,flag|NV_ASSIGN); 36410898Sroland.mainz@nrubsig.org if(typ && !array && (nv_isnull(np) || nv_isarray(np))) 36510898Sroland.mainz@nrubsig.org nv_settype(np,typ,0); 3668462SApril.Chin@Sun.COM if((flags&NV_STATIC) && !nv_isnull(np)) 3678462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 3688462SApril.Chin@Sun.COM goto check_type; 3698462SApril.Chin@Sun.COM #else 3708462SApril.Chin@Sun.COM continue; 3718462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 37210898Sroland.mainz@nrubsig.org if(array && (!(ap=nv_arrayptr(np)) || !ap->hdr.type)) 3734887Schin { 3748462SApril.Chin@Sun.COM if(!(arg->argflag&ARG_APPEND)) 3754887Schin nv_unset(np); 3764887Schin if(array&NV_ARRAY) 3774887Schin { 3784887Schin nv_setarray(np,nv_associative); 3794887Schin } 3804887Schin else 3814887Schin { 3824887Schin nv_onattr(np,NV_ARRAY); 3834887Schin } 38410898Sroland.mainz@nrubsig.org } 38510898Sroland.mainz@nrubsig.org if(array && tp->tre.tretyp!=TLST && !tp->com.comset && !tp->com.comarg) 38610898Sroland.mainz@nrubsig.org { 3878462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 3888462SApril.Chin@Sun.COM goto check_type; 3898462SApril.Chin@Sun.COM #else 3908462SApril.Chin@Sun.COM continue; 3918462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 3924887Schin } 3934887Schin /* check for array assignment */ 3944887Schin if(tp->tre.tretyp!=TLST && tp->com.comarg && !tp->com.comset && !((mp=tp->com.comnamp) && nv_isattr(mp,BLT_DCL))) 3954887Schin { 3964887Schin int argc; 3978462SApril.Chin@Sun.COM Dt_t *last_root = shp->last_root; 3988462SApril.Chin@Sun.COM char **argv = sh_argbuild(shp,&argc,&tp->com,0); 3998462SApril.Chin@Sun.COM shp->last_root = last_root; 4008462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 4018462SApril.Chin@Sun.COM if(shp->mktype && shp->dot_depth==0 && np==((struct sh_type*)shp->mktype)->nodes[0]) 4028462SApril.Chin@Sun.COM { 4038462SApril.Chin@Sun.COM shp->mktype = 0; 4048462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),"%s: not a known type name",argv[0]); 4058462SApril.Chin@Sun.COM } 4068462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 4074887Schin if(!(arg->argflag&ARG_APPEND)) 4084887Schin { 4098462SApril.Chin@Sun.COM if(!nv_isarray(np) || ((ap=nv_arrayptr(np)) && (ap->nelem&ARRAY_MASK))) 4108462SApril.Chin@Sun.COM nv_unset(np); 4114887Schin } 4124887Schin nv_setvec(np,(arg->argflag&ARG_APPEND),argc,argv); 4134887Schin if(traceon || trap) 4144887Schin { 4154887Schin int n = -1; 4164887Schin char *name = nv_name(np); 4174887Schin if(arg->argflag&ARG_APPEND) 4184887Schin n = '+'; 4194887Schin if(trap) 4208462SApril.Chin@Sun.COM sh_debug(shp,trap,name,(char*)0,argv,(arg->argflag&ARG_APPEND)|ARG_ASSIGN); 4214887Schin if(traceon) 4224887Schin { 4234887Schin sh_trace(NIL(char**),0); 4244887Schin sfputr(sfstderr,name,n); 4254887Schin sfwrite(sfstderr,"=( ",3); 4264887Schin while(cp= *argv++) 4274887Schin sfputr(sfstderr,sh_fmtq(cp),' '); 4284887Schin sfwrite(sfstderr,")\n",2); 4294887Schin } 4304887Schin } 4318462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 4328462SApril.Chin@Sun.COM goto check_type; 4338462SApril.Chin@Sun.COM #else 4344887Schin continue; 4358462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 4364887Schin } 4378462SApril.Chin@Sun.COM if((tp->tre.tretyp&COMMSK)==TFUN) 4388462SApril.Chin@Sun.COM goto skip; 4394887Schin if(tp->tre.tretyp==TLST || !tp->com.comset || tp->com.comset->argval[0]!='[') 4404887Schin { 4418462SApril.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) 4428462SApril.Chin@Sun.COM { 4438462SApril.Chin@Sun.COM if(prefix) 4448462SApril.Chin@Sun.COM cp = stakcopy(nv_name(np)); 4458462SApril.Chin@Sun.COM shp->prefix = cp; 4468462SApril.Chin@Sun.COM if(tp->com.comset->argval[1]=='[') 4478462SApril.Chin@Sun.COM { 4488462SApril.Chin@Sun.COM if((arg->argflag&ARG_APPEND) && (!nv_isarray(np) || (nv_aindex(np)>=0))) 4498462SApril.Chin@Sun.COM nv_unset(np); 4508462SApril.Chin@Sun.COM if(!(array&NV_IARRAY) && !(tp->com.comset->argflag&ARG_MESSAGE)) 4518462SApril.Chin@Sun.COM nv_setarray(np,nv_associative); 4528462SApril.Chin@Sun.COM } 45310898Sroland.mainz@nrubsig.org nv_setlist(tp->com.comset,flags,0); 4548462SApril.Chin@Sun.COM shp->prefix = prefix; 4558462SApril.Chin@Sun.COM if(tp->com.comset->argval[1]!='[') 4568462SApril.Chin@Sun.COM nv_setvtree(np); 4578462SApril.Chin@Sun.COM nv_close(np); 4588462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 4598462SApril.Chin@Sun.COM goto check_type; 4608462SApril.Chin@Sun.COM #else 4618462SApril.Chin@Sun.COM continue; 4628462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 4638462SApril.Chin@Sun.COM } 4644887Schin if(*cp!='.' && *cp!='[' && strchr(cp,'[')) 4654887Schin { 4664887Schin nv_close(np); 4678462SApril.Chin@Sun.COM np = nv_open(cp,shp->var_tree,flag); 4684887Schin } 4698462SApril.Chin@Sun.COM if(arg->argflag&ARG_APPEND) 4708462SApril.Chin@Sun.COM { 4718462SApril.Chin@Sun.COM if(nv_isarray(np)) 4728462SApril.Chin@Sun.COM { 4738462SApril.Chin@Sun.COM if((sub=nv_aimax(np)) < 0 && nv_arrayptr(np)) 4748462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_badappend,nv_name(np)); 4758462SApril.Chin@Sun.COM if(sub>=0) 4768462SApril.Chin@Sun.COM sub++; 4778462SApril.Chin@Sun.COM } 4788462SApril.Chin@Sun.COM if(!nv_isnull(np) && np->nvalue.cp!=Empty && !nv_isvtree(np)) 4798462SApril.Chin@Sun.COM sub=1; 4808462SApril.Chin@Sun.COM } 4818462SApril.Chin@Sun.COM else if(np->nvalue.cp && np->nvalue.cp!=Empty && !nv_type(np)) 4828462SApril.Chin@Sun.COM { 4838462SApril.Chin@Sun.COM _nv_unset(np,NV_EXPORT); 4848462SApril.Chin@Sun.COM } 4854887Schin } 4864887Schin else 4874887Schin { 4888462SApril.Chin@Sun.COM if(!(arg->argflag&ARG_APPEND)) 4898462SApril.Chin@Sun.COM _nv_unset(np,NV_EXPORT); 4908462SApril.Chin@Sun.COM if(!sh_isoption(SH_BASH) && !(array&NV_IARRAY) && !nv_isarray(np)) 4914887Schin nv_setarray(np,nv_associative); 4924887Schin } 4938462SApril.Chin@Sun.COM skip: 4948462SApril.Chin@Sun.COM if(sub>0) 4958462SApril.Chin@Sun.COM { 4968462SApril.Chin@Sun.COM sfprintf(stkstd,"%s[%d]",prefix?nv_name(np):cp,sub); 4978462SApril.Chin@Sun.COM shp->prefix = stakfreeze(1); 4988462SApril.Chin@Sun.COM nv_putsub(np,(char*)0,ARRAY_ADD|ARRAY_FILL|sub); 4998462SApril.Chin@Sun.COM } 5008462SApril.Chin@Sun.COM else if(prefix) 5018462SApril.Chin@Sun.COM shp->prefix = stakcopy(nv_name(np)); 5028462SApril.Chin@Sun.COM else 5038462SApril.Chin@Sun.COM shp->prefix = cp; 5048462SApril.Chin@Sun.COM shp->last_table = 0; 50510898Sroland.mainz@nrubsig.org if(shp->prefix) 50610898Sroland.mainz@nrubsig.org { 50710898Sroland.mainz@nrubsig.org if(*shp->prefix=='_' && shp->prefix[1]=='.' && nv_isref(L_ARGNOD)) 50810898Sroland.mainz@nrubsig.org { 50910898Sroland.mainz@nrubsig.org sfprintf(stkstd,"%s%s",nv_name(L_ARGNOD->nvalue.nrp->np),shp->prefix+1); 51010898Sroland.mainz@nrubsig.org shp->prefix = stkfreeze(stkstd,1); 51110898Sroland.mainz@nrubsig.org } 51210898Sroland.mainz@nrubsig.org memset(&nr,0,sizeof(nr)); 51310898Sroland.mainz@nrubsig.org memcpy(&node,L_ARGNOD,sizeof(node)); 51410898Sroland.mainz@nrubsig.org L_ARGNOD->nvalue.nrp = &nr; 51510898Sroland.mainz@nrubsig.org nr.np = np; 51610898Sroland.mainz@nrubsig.org nr.root = shp->last_root; 51710898Sroland.mainz@nrubsig.org nr.table = shp->last_table; 51810898Sroland.mainz@nrubsig.org L_ARGNOD->nvflag = NV_REF|NV_NOFREE; 51910898Sroland.mainz@nrubsig.org L_ARGNOD->nvfun = 0; 52010898Sroland.mainz@nrubsig.org } 5214887Schin sh_exec(tp,sh_isstate(SH_ERREXIT)); 5228462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 52310898Sroland.mainz@nrubsig.org if(shp->prefix) 5248462SApril.Chin@Sun.COM #endif 5258462SApril.Chin@Sun.COM { 5268462SApril.Chin@Sun.COM L_ARGNOD->nvalue.nrp = node.nvalue.nrp; 5278462SApril.Chin@Sun.COM L_ARGNOD->nvflag = node.nvflag; 5288462SApril.Chin@Sun.COM L_ARGNOD->nvfun = node.nvfun; 5298462SApril.Chin@Sun.COM } 5308462SApril.Chin@Sun.COM shp->prefix = prefix; 5314887Schin if(nv_isarray(np) && (mp=nv_opensub(np))) 5324887Schin np = mp; 5338462SApril.Chin@Sun.COM while(tp->tre.tretyp==TLST) 5348462SApril.Chin@Sun.COM { 5358462SApril.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]!='[') 5368462SApril.Chin@Sun.COM break; 5378462SApril.Chin@Sun.COM tp = tp->lst.lstrit; 5388462SApril.Chin@Sun.COM 5398462SApril.Chin@Sun.COM } 54010898Sroland.mainz@nrubsig.org if(!nv_isarray(np) && !typ && (tp->com.comarg || !tp->com.comset || tp->com.comset->argval[0]!='[')) 541*12068SRoger.Faulkner@Oracle.COM { 5428462SApril.Chin@Sun.COM nv_setvtree(np); 543*12068SRoger.Faulkner@Oracle.COM if(tp->com.comarg || tp->com.comset) 544*12068SRoger.Faulkner@Oracle.COM np->nvfun->dsize = 0; 545*12068SRoger.Faulkner@Oracle.COM } 5468462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 5478462SApril.Chin@Sun.COM goto check_type; 5488462SApril.Chin@Sun.COM #else 5494887Schin continue; 5508462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5514887Schin } 5524887Schin cp = arg->argval; 5538462SApril.Chin@Sun.COM mp = 0; 5544887Schin } 5558462SApril.Chin@Sun.COM np = nv_open(cp,shp->var_tree,flags); 5568462SApril.Chin@Sun.COM if(!np->nvfun && (flags&NV_NOREF)) 5574887Schin { 5588462SApril.Chin@Sun.COM if(shp->used_pos) 5594887Schin nv_onattr(np,NV_PARAM); 5604887Schin else 5614887Schin nv_offattr(np,NV_PARAM); 5624887Schin } 5634887Schin if(traceon || trap) 5644887Schin { 5654887Schin register char *sp=cp; 5664887Schin char *name=nv_name(np); 5674887Schin char *sub=0; 5684887Schin int append = 0; 5694887Schin if(nv_isarray(np)) 5704887Schin sub = savesub; 5718462SApril.Chin@Sun.COM if(cp=lastdot(sp,'=')) 5724887Schin { 5734887Schin if(cp[-1]=='+') 5744887Schin append = ARG_APPEND; 5754887Schin cp++; 5764887Schin } 5774887Schin if(traceon) 5784887Schin { 5794887Schin sh_trace(NIL(char**),0); 5804887Schin nv_outname(sfstderr,name,-1); 5814887Schin if(sub) 5824887Schin sfprintf(sfstderr,"[%s]",sh_fmtq(sub)); 5834887Schin if(cp) 5844887Schin { 5854887Schin if(append) 5864887Schin sfputc(sfstderr,'+'); 5874887Schin sfprintf(sfstderr,"=%s\n",sh_fmtq(cp)); 5884887Schin } 5894887Schin } 5904887Schin if(trap) 5914887Schin { 5924887Schin char *av[2]; 5934887Schin av[0] = cp; 5944887Schin av[1] = 0; 5958462SApril.Chin@Sun.COM sh_debug(shp,trap,name,sub,av,append); 5964887Schin } 5974887Schin } 5988462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 5998462SApril.Chin@Sun.COM check_type: 6008462SApril.Chin@Sun.COM if(maketype) 6018462SApril.Chin@Sun.COM { 6028462SApril.Chin@Sun.COM nv_open(shtp.nodes[0]->nvname,shp->var_tree,NV_ASSIGN|NV_VARNAME|NV_NOADD|NV_NOFAIL); 6038462SApril.Chin@Sun.COM np = nv_mktype(shtp.nodes,shtp.numnodes); 6048462SApril.Chin@Sun.COM free((void*)shtp.nodes); 6058462SApril.Chin@Sun.COM shp->mktype = shtp.previous; 6068462SApril.Chin@Sun.COM maketype = 0; 6078462SApril.Chin@Sun.COM shp->prefix = 0; 6088462SApril.Chin@Sun.COM if(nr.np == np) 6098462SApril.Chin@Sun.COM { 6108462SApril.Chin@Sun.COM L_ARGNOD->nvalue.nrp = node.nvalue.nrp; 6118462SApril.Chin@Sun.COM L_ARGNOD->nvflag = node.nvflag; 6128462SApril.Chin@Sun.COM L_ARGNOD->nvfun = node.nvfun; 6138462SApril.Chin@Sun.COM } 6148462SApril.Chin@Sun.COM } 6158462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 6164887Schin } 6174887Schin } 6184887Schin 6194887Schin /* 6204887Schin * copy the subscript onto the stack 6214887Schin */ 6224887Schin static void stak_subscript(const char *sub, int last) 6234887Schin { 6244887Schin register int c; 6254887Schin stakputc('['); 6264887Schin while(c= *sub++) 6274887Schin { 6284887Schin if(c=='[' || c==']' || c=='\\') 6294887Schin stakputc('\\'); 6304887Schin stakputc(c); 6314887Schin } 6324887Schin stakputc(last); 6334887Schin } 6344887Schin 6354887Schin /* 6364887Schin * construct a new name from a prefix and base name on the stack 6374887Schin */ 6384887Schin static char *copystack(const char *prefix, register const char *name, const char *sub) 6394887Schin { 6404887Schin register int last=0,offset = staktell(); 6414887Schin if(prefix) 6424887Schin { 6434887Schin stakputs(prefix); 6444887Schin if(*stakptr(staktell()-1)=='.') 6454887Schin stakseek(staktell()-1); 6464887Schin if(*name=='.' && name[1]=='[') 6474887Schin last = staktell()+2; 6488462SApril.Chin@Sun.COM if(*name!='[' && *name!='.' && *name!='=' && *name!='+') 6498462SApril.Chin@Sun.COM stakputc('.'); 6508462SApril.Chin@Sun.COM if(*name=='.' && (name[1]=='=' || name[1]==0)) 6514887Schin stakputc('.'); 6524887Schin } 6534887Schin if(last) 6544887Schin { 6554887Schin stakputs(name); 6564887Schin if(sh_checkid(stakptr(last),(char*)0)) 6574887Schin stakseek(staktell()-2); 6584887Schin } 6594887Schin if(sub) 6604887Schin stak_subscript(sub,']'); 6614887Schin if(!last) 6624887Schin stakputs(name); 6634887Schin stakputc(0); 6644887Schin return(stakptr(offset)); 6654887Schin } 6664887Schin 6674887Schin /* 6684887Schin * grow this stack string <name> by <n> bytes and move from cp-1 to end 6694887Schin * right by <n>. Returns beginning of string on the stack 6704887Schin */ 6714887Schin static char *stack_extend(const char *cname, char *cp, int n) 6724887Schin { 6734887Schin register char *name = (char*)cname; 6744887Schin int offset = name - stakptr(0); 6754887Schin int m = cp-name; 6764887Schin stakseek(strlen(name)+n+1); 6774887Schin name = stakptr(offset); 6784887Schin cp = name + m; 6794887Schin m = strlen(cp)+1; 6804887Schin while(m-->0) 6814887Schin cp[n+m]=cp[m]; 6824887Schin return((char*)name); 6834887Schin } 6844887Schin 6858462SApril.Chin@Sun.COM Namval_t *nv_create(const char *name, Dt_t *root, int flags, Namfun_t *dp) 6864887Schin { 6878462SApril.Chin@Sun.COM Shell_t *shp = &sh; 6884887Schin char *cp=(char*)name, *sp, *xp; 6894887Schin register int c; 6904887Schin register Namval_t *np=0, *nq=0; 6914887Schin Namfun_t *fp=0; 6924887Schin long mode, add=0; 6934887Schin int copy=1,isref,top=0,noscope=(flags&NV_NOSCOPE); 6948462SApril.Chin@Sun.COM if(root==shp->var_tree) 6954887Schin { 6964887Schin if(dtvnext(root)) 6974887Schin top = 1; 6984887Schin else 6994887Schin flags &= ~NV_NOSCOPE; 7004887Schin } 7014887Schin if(!dp->disc) 7028462SApril.Chin@Sun.COM copy = dp->nofree&1; 7034887Schin if(*cp=='.') 7044887Schin cp++; 7054887Schin while(1) 7064887Schin { 7074887Schin switch(c = *(unsigned char*)(sp = cp)) 7084887Schin { 7094887Schin case '[': 7104887Schin if(flags&NV_NOARRAY) 7114887Schin { 7124887Schin dp->last = cp; 7134887Schin return(np); 7144887Schin } 7154887Schin cp = nv_endsubscript((Namval_t*)0,sp,0); 7164887Schin if(sp==name || sp[-1]=='.') 7174887Schin c = *(sp = cp); 7184887Schin goto skip; 7194887Schin case '.': 7204887Schin if(flags&NV_IDENT) 7214887Schin return(0); 7228462SApril.Chin@Sun.COM if(root==shp->var_tree) 7234887Schin flags &= ~NV_EXPORT; 7244887Schin if(!copy && !(flags&NV_NOREF)) 7254887Schin { 7264887Schin c = sp-name; 7274887Schin copy = cp-name; 7288462SApril.Chin@Sun.COM dp->nofree |= 1; 7294887Schin name = copystack((const char*)0, name,(const char*)0); 7304887Schin cp = (char*)name+copy; 7314887Schin sp = (char*)name+c; 7324887Schin c = '.'; 7334887Schin } 7344887Schin skip: 7354887Schin case '+': 7364887Schin case '=': 7374887Schin *sp = 0; 7384887Schin case 0: 7394887Schin isref = 0; 7404887Schin dp->last = cp; 7414887Schin mode = (c=='.' || (flags&NV_NOADD))?add:NV_ADD; 7428462SApril.Chin@Sun.COM if((flags&NV_NOSCOPE) && c!='.') 7434887Schin mode |= HASH_NOSCOPE; 7448462SApril.Chin@Sun.COM np=0; 7454887Schin if(top) 7468462SApril.Chin@Sun.COM { 7478462SApril.Chin@Sun.COM struct Ufunction *rp; 7488462SApril.Chin@Sun.COM if((rp=shp->st.real_fun) && !rp->sdict && (flags&NV_STATIC)) 7498462SApril.Chin@Sun.COM { 7508462SApril.Chin@Sun.COM Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0); 7518462SApril.Chin@Sun.COM rp->sdict = dtopen(&_Nvdisc,Dtoset); 7528462SApril.Chin@Sun.COM dtview(rp->sdict,shp->var_base); 7538462SApril.Chin@Sun.COM dtview(shp->var_tree,rp->sdict); 7548462SApril.Chin@Sun.COM } 7558462SApril.Chin@Sun.COM if(np = nv_search(name,shp->var_tree,0)) 7568462SApril.Chin@Sun.COM { 7578462SApril.Chin@Sun.COM if(shp->var_tree->walk == shp->var_base) 7588462SApril.Chin@Sun.COM { 7598462SApril.Chin@Sun.COM nq = np; 760*12068SRoger.Faulkner@Oracle.COM if((flags&NV_NOSCOPE) && *cp!='.') 7618462SApril.Chin@Sun.COM { 7628462SApril.Chin@Sun.COM if(mode==0) 7638462SApril.Chin@Sun.COM root = shp->var_base; 7648462SApril.Chin@Sun.COM else 7658462SApril.Chin@Sun.COM { 7668462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 7678462SApril.Chin@Sun.COM np = 0; 7688462SApril.Chin@Sun.COM } 7698462SApril.Chin@Sun.COM } 7708462SApril.Chin@Sun.COM } 7718462SApril.Chin@Sun.COM else 7728462SApril.Chin@Sun.COM { 7738462SApril.Chin@Sun.COM root = shp->var_tree->walk; 7748462SApril.Chin@Sun.COM flags |= NV_NOSCOPE; 7758462SApril.Chin@Sun.COM noscope = 1; 7768462SApril.Chin@Sun.COM } 7778462SApril.Chin@Sun.COM } 7788462SApril.Chin@Sun.COM if(rp && rp->sdict && (flags&NV_STATIC)) 7798462SApril.Chin@Sun.COM { 7808462SApril.Chin@Sun.COM root = rp->sdict; 7818462SApril.Chin@Sun.COM if(np && shp->var_tree->walk==shp->var_tree) 7828462SApril.Chin@Sun.COM { 7838462SApril.Chin@Sun.COM _nv_unset(np,0); 7848462SApril.Chin@Sun.COM nv_delete(np,shp->var_tree,0); 7858462SApril.Chin@Sun.COM np = 0; 7868462SApril.Chin@Sun.COM } 7878462SApril.Chin@Sun.COM if(!np || shp->var_tree->walk!=root) 7888462SApril.Chin@Sun.COM np = nv_search(name,root,HASH_NOSCOPE|NV_ADD); 7898462SApril.Chin@Sun.COM } 7908462SApril.Chin@Sun.COM } 7918462SApril.Chin@Sun.COM if(np || (np = nv_search(name,root,mode))) 7924887Schin { 7934887Schin isref = nv_isref(np); 7944887Schin if(top) 7954887Schin { 7964887Schin if(nq==np) 79710898Sroland.mainz@nrubsig.org { 7984887Schin flags &= ~NV_NOSCOPE; 79910898Sroland.mainz@nrubsig.org root = shp->var_base; 80010898Sroland.mainz@nrubsig.org } 8014887Schin else if(nq) 8024887Schin { 8034887Schin if(nv_isnull(np) && c!='.' && (np->nvfun=nv_cover(nq))) 8044887Schin np->nvname = nq->nvname; 8054887Schin flags |= NV_NOSCOPE; 8064887Schin } 8074887Schin } 8088462SApril.Chin@Sun.COM else if(add && nv_isnull(np) && c=='.' && cp[1]!='.') 8094887Schin nv_setvtree(np); 8104887Schin } 8114887Schin if(c) 8124887Schin *sp = c; 8134887Schin top = 0; 8144887Schin if(isref) 8154887Schin { 8164887Schin char *sub=0; 8178462SApril.Chin@Sun.COM #if NVCACHE 8188462SApril.Chin@Sun.COM nvcache.ok = 0; 8198462SApril.Chin@Sun.COM #endif 8204887Schin if(c=='.') /* don't optimize */ 8218462SApril.Chin@Sun.COM shp->argaddr = 0; 82210898Sroland.mainz@nrubsig.org else if((flags&NV_NOREF) && (c!='[' && *cp!='.')) 8234887Schin { 8248462SApril.Chin@Sun.COM if(c && !(flags&NV_NOADD)) 8254887Schin nv_unref(np); 8264887Schin return(np); 8274887Schin } 8288462SApril.Chin@Sun.COM while(nv_isref(np) && np->nvalue.cp) 8294887Schin { 8304887Schin root = nv_reftree(np); 8318462SApril.Chin@Sun.COM shp->last_root = root; 8328462SApril.Chin@Sun.COM shp->last_table = nv_reftable(np); 8334887Schin sub = nv_refsub(np); 8344887Schin np = nv_refnode(np); 8354887Schin if(sub && c!='.') 8364887Schin nv_putsub(np,sub,0L); 8374887Schin flags |= NV_NOSCOPE; 8388462SApril.Chin@Sun.COM noscope = 1; 8394887Schin } 8408462SApril.Chin@Sun.COM if(nv_isref(np) && (c=='[' || c=='.' || !(flags&NV_ASSIGN))) 8418462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_noref,nv_name(np)); 8424887Schin if(sub && c==0) 8434887Schin return(np); 8444887Schin if(np==nq) 8454887Schin flags &= ~(noscope?0:NV_NOSCOPE); 8464887Schin else if(c) 8474887Schin { 8484887Schin c = (cp-sp); 8494887Schin copy = strlen(cp=nv_name(np)); 8508462SApril.Chin@Sun.COM dp->nofree |= 1; 8514887Schin name = copystack(cp,sp,sub); 8524887Schin sp = (char*)name + copy; 8534887Schin cp = sp+c; 8544887Schin c = *sp; 8554887Schin if(!noscope) 8564887Schin flags &= ~NV_NOSCOPE; 8574887Schin } 8584887Schin flags |= NV_NOREF; 85910898Sroland.mainz@nrubsig.org if(nv_isnull(np)) 86010898Sroland.mainz@nrubsig.org nv_onattr(np,NV_NOFREE); 86110898Sroland.mainz@nrubsig.org 8624887Schin } 8638462SApril.Chin@Sun.COM shp->last_root = root; 864*12068SRoger.Faulkner@Oracle.COM if(*cp && cp[1]=='.') 8658462SApril.Chin@Sun.COM cp++; 8668462SApril.Chin@Sun.COM if(c=='.' && (cp[1]==0 || cp[1]=='=' || cp[1]=='+')) 8678462SApril.Chin@Sun.COM { 8688462SApril.Chin@Sun.COM nv_local = 1; 8698462SApril.Chin@Sun.COM return(np); 8708462SApril.Chin@Sun.COM } 8718462SApril.Chin@Sun.COM if(cp[-1]=='.') 8728462SApril.Chin@Sun.COM cp--; 8734887Schin do 8744887Schin { 8754887Schin if(!np) 8764887Schin { 8778462SApril.Chin@Sun.COM if(!nq && *sp=='[' && *cp==0 && cp[-1]==']') 8784887Schin { 8794887Schin /* 8804887Schin * for backward compatibility 8814887Schin * evaluate subscript for 8824887Schin * possible side effects 8834887Schin */ 8844887Schin cp[-1] = 0; 8854887Schin sh_arith(sp+1); 8864887Schin cp[-1] = ']'; 8874887Schin } 8884887Schin return(np); 8894887Schin } 8904887Schin if(c=='[' || (c=='.' && nv_isarray(np))) 8914887Schin { 8928462SApril.Chin@Sun.COM char *sub=0; 8934887Schin int n = 0; 89410898Sroland.mainz@nrubsig.org mode &= ~HASH_NOSCOPE; 8954887Schin if(c=='[') 8964887Schin { 89710898Sroland.mainz@nrubsig.org #if 0 89810898Sroland.mainz@nrubsig.org Namarr_t *ap = nv_arrayptr(np); 89910898Sroland.mainz@nrubsig.org int scan = ap?(ap->nelem&ARRAY_SCAN):0; 90010898Sroland.mainz@nrubsig.org #endif 9014887Schin n = mode|nv_isarray(np); 9024887Schin if(!mode && (flags&NV_ARRAY) && ((c=sp[1])=='*' || c=='@') && sp[2]==']') 9034887Schin { 9044887Schin /* not implemented yet */ 9054887Schin dp->last = cp; 9064887Schin return(np); 9074887Schin } 9088462SApril.Chin@Sun.COM if((n&NV_ADD)&&(flags&NV_ARRAY)) 9094887Schin n |= ARRAY_FILL; 9108462SApril.Chin@Sun.COM if(flags&NV_ASSIGN) 9118462SApril.Chin@Sun.COM n |= NV_ADD; 9128462SApril.Chin@Sun.COM cp = nv_endsubscript(np,sp,n|(flags&NV_ASSIGN)); 91310898Sroland.mainz@nrubsig.org #if 0 91410898Sroland.mainz@nrubsig.org if(scan) 91510898Sroland.mainz@nrubsig.org nv_putsub(np,NIL(char*),ARRAY_SCAN); 91610898Sroland.mainz@nrubsig.org #endif 9174887Schin } 9184887Schin else 9194887Schin cp = sp; 9208462SApril.Chin@Sun.COM if((c = *cp)=='.' || (c=='[' && nv_isarray(np)) || (n&ARRAY_FILL) || (flags&NV_ARRAY)) 9214887Schin 9224887Schin { 9234887Schin int m = cp-sp; 9248462SApril.Chin@Sun.COM sub = m?nv_getsub(np):0; 9254887Schin if(!sub) 9268462SApril.Chin@Sun.COM { 9278462SApril.Chin@Sun.COM if(m && !(n&NV_ADD)) 9288462SApril.Chin@Sun.COM return(0); 9294887Schin sub = "0"; 9308462SApril.Chin@Sun.COM } 9314887Schin n = strlen(sub)+2; 9324887Schin if(!copy) 9334887Schin { 9344887Schin copy = cp-name; 9358462SApril.Chin@Sun.COM dp->nofree |= 1; 9364887Schin name = copystack((const char*)0, name,(const char*)0); 9374887Schin cp = (char*)name+copy; 9384887Schin sp = cp-m; 9394887Schin } 9404887Schin if(n <= m) 9414887Schin { 9424887Schin if(n) 9434887Schin { 9444887Schin memcpy(sp+1,sub,n-2); 9454887Schin sp[n-1] = ']'; 9464887Schin } 9474887Schin if(n < m) 9484887Schin cp=strcpy(sp+n,cp); 9494887Schin } 9504887Schin else 9514887Schin { 9524887Schin int r = n-m; 9534887Schin m = sp-name; 9544887Schin name = stack_extend(name, cp-1, r); 9554887Schin sp = (char*)name + m; 9564887Schin *sp = '['; 9574887Schin memcpy(sp+1,sub,n-2); 9584887Schin sp[n-1] = ']'; 9594887Schin cp = sp+n; 9604887Schin 9614887Schin } 9624887Schin } 9634887Schin else if(c==0 && mode && (n=nv_aindex(np))>0) 9648462SApril.Chin@Sun.COM nv_putsub(np,(char*)0,n); 9658462SApril.Chin@Sun.COM else if(n==0 && (c==0 || (c=='[' && !nv_isarray(np)))) 9664887Schin { 9674887Schin /* subscript must be 0*/ 9684887Schin cp[-1] = 0; 9698462SApril.Chin@Sun.COM n = sh_arith(sp+1); 9704887Schin cp[-1] = ']'; 9718462SApril.Chin@Sun.COM if(n) 9728462SApril.Chin@Sun.COM return(0); 9734887Schin if(c) 9748462SApril.Chin@Sun.COM sp = cp; 9754887Schin } 9764887Schin dp->last = cp; 9774887Schin if(nv_isarray(np) && (c=='[' || c=='.' || (flags&NV_ARRAY))) 9784887Schin { 9798462SApril.Chin@Sun.COM sp = cp; 9808462SApril.Chin@Sun.COM if(!(nq = nv_opensub(np))) 9818462SApril.Chin@Sun.COM { 9828462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 9838462SApril.Chin@Sun.COM if(!sub && (flags&NV_NOADD)) 9848462SApril.Chin@Sun.COM return(0); 9858462SApril.Chin@Sun.COM n = mode|((flags&NV_NOADD)?0:NV_ADD); 9868462SApril.Chin@Sun.COM if(!ap && (n&NV_ADD)) 9878462SApril.Chin@Sun.COM { 9888462SApril.Chin@Sun.COM nv_putsub(np,sub,ARRAY_FILL); 9898462SApril.Chin@Sun.COM ap = nv_arrayptr(np); 9908462SApril.Chin@Sun.COM } 9918462SApril.Chin@Sun.COM if(n && ap && !ap->table) 9928462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 9938462SApril.Chin@Sun.COM if(ap && ap->table && (nq=nv_search(sub,ap->table,n))) 9948462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 9958462SApril.Chin@Sun.COM if(nq && nv_isnull(nq)) 9968462SApril.Chin@Sun.COM nq = nv_arraychild(np,nq,c); 9978462SApril.Chin@Sun.COM } 9988462SApril.Chin@Sun.COM if(nq) 9998462SApril.Chin@Sun.COM { 10008462SApril.Chin@Sun.COM if(c=='.' && !nv_isvtree(nq)) 10018462SApril.Chin@Sun.COM { 10028462SApril.Chin@Sun.COM if(flags&NV_NOADD) 10038462SApril.Chin@Sun.COM return(0); 10048462SApril.Chin@Sun.COM nv_setvtree(nq); 10058462SApril.Chin@Sun.COM } 10068462SApril.Chin@Sun.COM np = nq; 10078462SApril.Chin@Sun.COM } 10088462SApril.Chin@Sun.COM else if(memcmp(cp,"[0]",3)) 10098462SApril.Chin@Sun.COM return(nq); 10108462SApril.Chin@Sun.COM else 10118462SApril.Chin@Sun.COM { 10128462SApril.Chin@Sun.COM /* ignore [0] */ 10138462SApril.Chin@Sun.COM dp->last = cp += 3; 10148462SApril.Chin@Sun.COM c = *cp; 10158462SApril.Chin@Sun.COM } 10164887Schin } 10174887Schin } 10184887Schin else if(nv_isarray(np)) 10198462SApril.Chin@Sun.COM { 10208462SApril.Chin@Sun.COM if(c==0 && (flags&NV_MOVE)) 10218462SApril.Chin@Sun.COM return(np); 10224887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 10238462SApril.Chin@Sun.COM } 10244887Schin if(c=='.' && (fp=np->nvfun)) 10254887Schin { 10264887Schin for(; fp; fp=fp->next) 10274887Schin { 10284887Schin if(fp->disc && fp->disc->createf) 10294887Schin break; 10304887Schin } 10314887Schin if(fp) 10324887Schin { 10334887Schin if((nq = (*fp->disc->createf)(np,cp+1,flags,fp)) == np) 10344887Schin { 10354887Schin add = NV_ADD; 103610898Sroland.mainz@nrubsig.org shp->last_table = 0; 10374887Schin break; 10384887Schin } 10398462SApril.Chin@Sun.COM else if(np=nq) 10408462SApril.Chin@Sun.COM { 10418462SApril.Chin@Sun.COM if((c = *(sp=cp=dp->last=fp->last))==0) 10428462SApril.Chin@Sun.COM { 10438462SApril.Chin@Sun.COM if(nv_isarray(np) && sp[-1]!=']') 10448462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),ARRAY_UNDEF); 10458462SApril.Chin@Sun.COM return(np); 10468462SApril.Chin@Sun.COM } 10478462SApril.Chin@Sun.COM } 10484887Schin } 10494887Schin } 10504887Schin } 10514887Schin while(c=='['); 10528462SApril.Chin@Sun.COM if(c!='.' || cp[1]=='.') 10534887Schin return(np); 10544887Schin cp++; 10554887Schin break; 10564887Schin default: 10574887Schin dp->last = cp; 10584887Schin if((c = mbchar(cp)) && !isaletter(c)) 10594887Schin return(np); 10604887Schin while(xp=cp, c=mbchar(cp), isaname(c)); 10614887Schin cp = xp; 10624887Schin } 10634887Schin } 10644887Schin return(np); 10654887Schin } 10664887Schin 10674887Schin /* 10688462SApril.Chin@Sun.COM * delete the node <np> from the dictionary <root> and clear from the cache 10698462SApril.Chin@Sun.COM * if <root> is NULL, only the cache is cleared 10708462SApril.Chin@Sun.COM * if flags does not contain NV_NOFREE, the node is freed 10718462SApril.Chin@Sun.COM */ 10728462SApril.Chin@Sun.COM void nv_delete(Namval_t* np, Dt_t *root, int flags) 10738462SApril.Chin@Sun.COM { 10748462SApril.Chin@Sun.COM #if NVCACHE 10758462SApril.Chin@Sun.COM register int c; 10768462SApril.Chin@Sun.COM struct Cache_entry *xp; 10778462SApril.Chin@Sun.COM for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c]) 10788462SApril.Chin@Sun.COM { 10798462SApril.Chin@Sun.COM if(xp->np==np) 10808462SApril.Chin@Sun.COM xp->root = 0; 10818462SApril.Chin@Sun.COM } 10828462SApril.Chin@Sun.COM #endif 10838462SApril.Chin@Sun.COM if(root) 10848462SApril.Chin@Sun.COM { 10858462SApril.Chin@Sun.COM if(dtdelete(root,np)) 10868462SApril.Chin@Sun.COM { 10878462SApril.Chin@Sun.COM if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np))) 10888462SApril.Chin@Sun.COM free((void*)np); 10898462SApril.Chin@Sun.COM } 10908462SApril.Chin@Sun.COM #if 0 10918462SApril.Chin@Sun.COM else 10928462SApril.Chin@Sun.COM { 10938462SApril.Chin@Sun.COM sfprintf(sfstderr,"%s not deleted\n",nv_name(np)); 10948462SApril.Chin@Sun.COM sfsync(sfstderr); 10958462SApril.Chin@Sun.COM } 10968462SApril.Chin@Sun.COM #endif 10978462SApril.Chin@Sun.COM } 10988462SApril.Chin@Sun.COM } 10998462SApril.Chin@Sun.COM 11008462SApril.Chin@Sun.COM /* 11014887Schin * Put <arg> into associative memory. 11024887Schin * If <flags> & NV_ARRAY then follow array to next subscript 11034887Schin * If <flags> & NV_NOARRAY then subscript is not allowed 11044887Schin * If <flags> & NV_NOSCOPE then use the current scope only 11054887Schin * If <flags> & NV_ASSIGN then assignment is allowed 11064887Schin * If <flags> & NV_IDENT then name must be an identifier 11074887Schin * If <flags> & NV_VARNAME then name must be a valid variable name 11084887Schin * If <flags> & NV_NOADD then node will not be added if not found 11094887Schin * If <flags> & NV_NOREF then don't follow reference 11104887Schin * If <flags> & NV_NOFAIL then don't generate an error message on failure 11118462SApril.Chin@Sun.COM * If <flags> & NV_STATIC then unset before an assignment 111210898Sroland.mainz@nrubsig.org * If <flags> & NV_UNJUST then unset attributes before assignment 11134887Schin * SH_INIT is only set while initializing the environment 11144887Schin */ 11154887Schin Namval_t *nv_open(const char *name, Dt_t *root, int flags) 11164887Schin { 11178462SApril.Chin@Sun.COM Shell_t *shp = &sh; 11184887Schin register char *cp=(char*)name; 11194887Schin register int c; 11204887Schin register Namval_t *np; 11214887Schin Namfun_t fun; 11224887Schin int append=0; 11234887Schin const char *msg = e_varname; 11244887Schin char *fname = 0; 11254887Schin int offset = staktell(); 11264887Schin Dt_t *funroot; 11278462SApril.Chin@Sun.COM #if NVCACHE 11288462SApril.Chin@Sun.COM struct Cache_entry *xp; 11298462SApril.Chin@Sun.COM #endif 11308462SApril.Chin@Sun.COM 11318462SApril.Chin@Sun.COM sh_stats(STAT_NVOPEN); 11324887Schin memset(&fun,0,sizeof(fun)); 11338462SApril.Chin@Sun.COM shp->last_table = shp->namespace; 11344887Schin if(!root) 11358462SApril.Chin@Sun.COM root = shp->var_tree; 11368462SApril.Chin@Sun.COM shp->last_root = root; 11378462SApril.Chin@Sun.COM if(root==shp->fun_tree) 11384887Schin { 11394887Schin flags |= NV_NOREF; 11404887Schin msg = e_badfun; 11418462SApril.Chin@Sun.COM if((np=shp->namespace) || strchr(name,'.')) 11424887Schin { 11434887Schin name = cp = copystack(np?nv_name(np):0,name,(const char*)0); 11444887Schin fname = strrchr(cp,'.'); 11454887Schin *fname = 0; 11468462SApril.Chin@Sun.COM fun.nofree |= 1; 11474887Schin flags &= ~NV_IDENT; 11484887Schin funroot = root; 11498462SApril.Chin@Sun.COM root = shp->var_tree; 11504887Schin } 11514887Schin } 11524887Schin else if(!(flags&(NV_IDENT|NV_VARNAME|NV_ASSIGN))) 11534887Schin { 11544887Schin long mode = ((flags&NV_NOADD)?0:NV_ADD); 11554887Schin if(flags&NV_NOSCOPE) 11564887Schin mode |= HASH_SCOPE|HASH_NOSCOPE; 11574887Schin np = nv_search(name,root,mode); 11584887Schin if(np && !(flags&NV_REF)) 11594887Schin { 11604887Schin while(nv_isref(np)) 11614887Schin { 11628462SApril.Chin@Sun.COM shp->last_table = nv_reftable(np); 11634887Schin np = nv_refnode(np); 11644887Schin } 11654887Schin } 11664887Schin return(np); 11674887Schin } 11688462SApril.Chin@Sun.COM else if(shp->prefix && (flags&NV_ASSIGN)) 11694887Schin { 11708462SApril.Chin@Sun.COM name = cp = copystack(shp->prefix,name,(const char*)0); 11718462SApril.Chin@Sun.COM fun.nofree |= 1; 11724887Schin } 11734887Schin c = *(unsigned char*)cp; 11748462SApril.Chin@Sun.COM if(root==shp->alias_tree) 11754887Schin { 11764887Schin msg = e_aliname; 11774887Schin while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') && 11788462SApril.Chin@Sun.COM (c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON)); 11798462SApril.Chin@Sun.COM if(shp->subshell && c=='=') 11804887Schin root = sh_subaliastree(1); 11814887Schin if(c= *--cp) 11824887Schin *cp = 0; 11834887Schin np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD); 11844887Schin if(c) 11854887Schin *cp = c; 11864887Schin goto skip; 11874887Schin } 11884887Schin else if(flags&NV_IDENT) 11894887Schin msg = e_ident; 11904887Schin else if(c=='.') 11914887Schin { 11924887Schin c = *++cp; 11934887Schin flags |= NV_NOREF; 11948462SApril.Chin@Sun.COM if(root==shp->var_tree) 11958462SApril.Chin@Sun.COM root = shp->var_base; 11968462SApril.Chin@Sun.COM shp->last_table = 0; 11974887Schin } 11984887Schin if(c= !isaletter(c)) 11994887Schin goto skip; 12008462SApril.Chin@Sun.COM #if NVCACHE 12018462SApril.Chin@Sun.COM for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c]) 12028462SApril.Chin@Sun.COM { 12038462SApril.Chin@Sun.COM if(xp->root!=root) 12048462SApril.Chin@Sun.COM continue; 12058462SApril.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]=='+')) 12068462SApril.Chin@Sun.COM { 12078462SApril.Chin@Sun.COM sh_stats(STAT_NVHITS); 12088462SApril.Chin@Sun.COM np = xp->np; 12098462SApril.Chin@Sun.COM cp = (char*)name+xp->len; 12108462SApril.Chin@Sun.COM if(nv_isarray(np)) 12118462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),ARRAY_UNDEF); 12128462SApril.Chin@Sun.COM shp->last_table = xp->last_table; 121310898Sroland.mainz@nrubsig.org shp->last_root = xp->last_root; 12148462SApril.Chin@Sun.COM goto nocache; 12158462SApril.Chin@Sun.COM } 12168462SApril.Chin@Sun.COM } 12178462SApril.Chin@Sun.COM nvcache.ok = 1; 12188462SApril.Chin@Sun.COM #endif 12194887Schin np = nv_create(name, root, flags, &fun); 12204887Schin cp = fun.last; 12218462SApril.Chin@Sun.COM #if NVCACHE 12228462SApril.Chin@Sun.COM if(np && nvcache.ok && cp[-1]!=']') 12238462SApril.Chin@Sun.COM { 12248462SApril.Chin@Sun.COM xp = &nvcache.entries[nvcache.index]; 12258462SApril.Chin@Sun.COM if(*cp) 12268462SApril.Chin@Sun.COM { 12278462SApril.Chin@Sun.COM char *sp = strchr(name,*cp); 12288462SApril.Chin@Sun.COM if(!sp) 12298462SApril.Chin@Sun.COM goto nocache; 12308462SApril.Chin@Sun.COM xp->len = sp-name; 12318462SApril.Chin@Sun.COM } 12328462SApril.Chin@Sun.COM else 12338462SApril.Chin@Sun.COM xp->len = strlen(name); 12348462SApril.Chin@Sun.COM c = roundof(xp->len+1,32); 12358462SApril.Chin@Sun.COM if(c > xp->size) 12368462SApril.Chin@Sun.COM { 12378462SApril.Chin@Sun.COM if(xp->size==0) 12388462SApril.Chin@Sun.COM xp->name = malloc(c); 12398462SApril.Chin@Sun.COM else 12408462SApril.Chin@Sun.COM xp->name = realloc(xp->name,c); 12418462SApril.Chin@Sun.COM xp->size = c; 12428462SApril.Chin@Sun.COM } 12438462SApril.Chin@Sun.COM memcpy(xp->name,name,xp->len); 12448462SApril.Chin@Sun.COM xp->name[xp->len] = 0; 12458462SApril.Chin@Sun.COM xp->root = root; 12468462SApril.Chin@Sun.COM xp->np = np; 12478462SApril.Chin@Sun.COM xp->last_table = shp->last_table; 124810898Sroland.mainz@nrubsig.org xp->last_root = shp->last_root; 12498462SApril.Chin@Sun.COM xp->flags = (flags&(NV_ARRAY|NV_NOSCOPE)); 12508462SApril.Chin@Sun.COM nvcache.index = (nvcache.index+1)&(NVCACHE-1); 12518462SApril.Chin@Sun.COM } 12528462SApril.Chin@Sun.COM nocache: 12538462SApril.Chin@Sun.COM nvcache.ok = 0; 12548462SApril.Chin@Sun.COM #endif 12554887Schin if(fname) 12564887Schin { 12574887Schin c = ((flags&NV_NOSCOPE)?HASH_NOSCOPE:0)|((flags&NV_NOADD)?0:NV_ADD); 12584887Schin *fname = '.'; 12594887Schin np = nv_search(name, funroot, c); 12604887Schin *fname = 0; 12614887Schin } 12628462SApril.Chin@Sun.COM else 12634887Schin { 12648462SApril.Chin@Sun.COM if(*cp=='.' && cp[1]=='.') 12658462SApril.Chin@Sun.COM { 12668462SApril.Chin@Sun.COM append |= NV_NODISC; 12678462SApril.Chin@Sun.COM cp+=2; 12688462SApril.Chin@Sun.COM } 12698462SApril.Chin@Sun.COM if(*cp=='+' && cp[1]=='=') 12708462SApril.Chin@Sun.COM { 12718462SApril.Chin@Sun.COM append |= NV_APPEND; 12728462SApril.Chin@Sun.COM cp++; 12738462SApril.Chin@Sun.COM } 12744887Schin } 12754887Schin c = *cp; 12764887Schin skip: 12778462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 12788462SApril.Chin@Sun.COM if(np && shp->mktype) 12798462SApril.Chin@Sun.COM np = nv_addnode(np,0); 12808462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 12814887Schin if(c=='=' && np && (flags&NV_ASSIGN)) 12824887Schin { 12834887Schin cp++; 12844887Schin if(sh_isstate(SH_INIT)) 12854887Schin { 12864887Schin nv_putval(np, cp, NV_RDONLY); 12874887Schin if(np==PWDNOD) 12884887Schin nv_onattr(np,NV_TAGGED); 12894887Schin } 12904887Schin else 12914887Schin { 12928462SApril.Chin@Sun.COM char *sub=0, *prefix= shp->prefix; 12938462SApril.Chin@Sun.COM int isref; 12948462SApril.Chin@Sun.COM shp->prefix = 0; 12958462SApril.Chin@Sun.COM if((flags&NV_STATIC) && !shp->mktype) 12968462SApril.Chin@Sun.COM { 12978462SApril.Chin@Sun.COM if(!nv_isnull(np)) 129810898Sroland.mainz@nrubsig.org { 129910898Sroland.mainz@nrubsig.org shp->prefix = prefix; 13008462SApril.Chin@Sun.COM return(np); 130110898Sroland.mainz@nrubsig.org } 13028462SApril.Chin@Sun.COM } 13038462SApril.Chin@Sun.COM isref = nv_isref(np); 13044887Schin if(sh_isoption(SH_XTRACE) && nv_isarray(np)) 13054887Schin sub = nv_getsub(np); 13064887Schin c = msg==e_aliname? 0: (append | (flags&NV_EXPORT)); 13078462SApril.Chin@Sun.COM if(isref) 13088462SApril.Chin@Sun.COM nv_offattr(np,NV_REF); 130910898Sroland.mainz@nrubsig.org if(!append && (flags&NV_UNJUST)) 131010898Sroland.mainz@nrubsig.org { 131110898Sroland.mainz@nrubsig.org nv_offattr(np,NV_LJUST|NV_RJUST|NV_ZFILL); 131210898Sroland.mainz@nrubsig.org np->nvsize = 0; 131310898Sroland.mainz@nrubsig.org } 13144887Schin nv_putval(np, cp, c); 13158462SApril.Chin@Sun.COM if(isref) 131610898Sroland.mainz@nrubsig.org { 131710898Sroland.mainz@nrubsig.org if(nv_search((char*)np,shp->var_base,HASH_BUCKET)) 131810898Sroland.mainz@nrubsig.org shp->last_root = shp->var_base; 13198462SApril.Chin@Sun.COM nv_setref(np,(Dt_t*)0,NV_VARNAME); 132010898Sroland.mainz@nrubsig.org } 13214887Schin savesub = sub; 13228462SApril.Chin@Sun.COM shp->prefix = prefix; 13234887Schin } 13244887Schin nv_onattr(np, flags&NV_ATTRIBUTES); 13254887Schin } 13264887Schin else if(c) 13274887Schin { 13284887Schin if(flags&NV_NOFAIL) 13294887Schin return(0); 13304887Schin if(c=='.') 13314887Schin msg = e_noparent; 13324887Schin else if(c=='[') 13334887Schin msg = e_noarray; 13344887Schin errormsg(SH_DICT,ERROR_exit(1),msg,name); 13354887Schin } 13368462SApril.Chin@Sun.COM if(fun.nofree&1) 13374887Schin stakseek(offset); 13384887Schin return(np); 13394887Schin } 13404887Schin 13414887Schin #if SHOPT_MULTIBYTE 13424887Schin static int ja_size(char*, int, int); 13434887Schin static void ja_restore(void); 13444887Schin static char *savep; 13454887Schin static char savechars[8+1]; 13464887Schin #endif /* SHOPT_MULTIBYTE */ 13474887Schin 13484887Schin /* 13494887Schin * put value <string> into name-value node <np>. 13504887Schin * If <np> is an array, then the element given by the 13514887Schin * current index is assigned to. 13524887Schin * If <flags> contains NV_RDONLY, readonly attribute is ignored 13534887Schin * If <flags> contains NV_INTEGER, string is a pointer to a number 13544887Schin * If <flags> contains NV_NOFREE, previous value is freed, and <string> 13554887Schin * becomes value of node and <flags> becomes attributes 13564887Schin */ 13574887Schin void nv_putval(register Namval_t *np, const char *string, int flags) 13584887Schin { 13594887Schin register const char *sp=string; 13604887Schin register union Value *up; 13614887Schin register char *cp; 13624887Schin register int size = 0; 13634887Schin register int dot; 13644887Schin int was_local = nv_local; 13658462SApril.Chin@Sun.COM union Value u; 13664887Schin if(!(flags&NV_RDONLY) && nv_isattr (np, NV_RDONLY)) 13674887Schin errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np)); 13684887Schin /* The following could cause the shell to fork if assignment 13694887Schin * would cause a side effect 13704887Schin */ 13714887Schin sh.argaddr = 0; 13724887Schin if(sh.subshell && !nv_local) 13734887Schin np = sh_assignok(np,1); 137410898Sroland.mainz@nrubsig.org if(np->nvfun && np->nvfun->disc && !(flags&NV_NODISC) && !nv_isref(np)) 13754887Schin { 13764887Schin /* This function contains disc */ 13774887Schin if(!nv_local) 13784887Schin { 13794887Schin nv_local=1; 13804887Schin nv_putv(np,sp,flags,np->nvfun); 13814887Schin if(sp && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT))) 13824887Schin sh_envput(sh.env,np); 13834887Schin return; 13844887Schin } 13854887Schin /* called from disc, assign the actual value */ 13864887Schin } 13874887Schin flags &= ~NV_NODISC; 13888462SApril.Chin@Sun.COM nv_local=0; 13894887Schin if(flags&(NV_NOREF|NV_NOFREE)) 13904887Schin { 13918462SApril.Chin@Sun.COM if(np->nvalue.cp && np->nvalue.cp!=sp && !nv_isattr(np,NV_NOFREE)) 13928462SApril.Chin@Sun.COM free((void*)np->nvalue.cp); 13934887Schin np->nvalue.cp = (char*)sp; 13944887Schin nv_setattr(np,(flags&~NV_RDONLY)|NV_NOFREE); 13954887Schin return; 13964887Schin } 13974887Schin up= &np->nvalue; 13988462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P) == NV_INT16) 13998462SApril.Chin@Sun.COM { 14008462SApril.Chin@Sun.COM if(!np->nvalue.up || !nv_isarray(np)) 14018462SApril.Chin@Sun.COM { 14028462SApril.Chin@Sun.COM up = &u; 14038462SApril.Chin@Sun.COM up->up = &np->nvalue; 14048462SApril.Chin@Sun.COM } 14058462SApril.Chin@Sun.COM } 14068462SApril.Chin@Sun.COM else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np)) 14078462SApril.Chin@Sun.COM up = np->nvalue.up; 14088462SApril.Chin@Sun.COM if(up && up->cp==Empty) 14098462SApril.Chin@Sun.COM up->cp = 0; 14104887Schin if(nv_isattr(np,NV_EXPORT)) 14114887Schin nv_offattr(np,NV_IMPORT); 14124887Schin if(nv_isattr (np, NV_INTEGER)) 14134887Schin { 14148462SApril.Chin@Sun.COM if(nv_isattr(np, NV_DOUBLE) == NV_DOUBLE) 14154887Schin { 14164887Schin if(nv_isattr(np, NV_LONG) && sizeof(double)<sizeof(Sfdouble_t)) 14174887Schin { 14184887Schin Sfdouble_t ld, old=0; 14194887Schin if(flags&NV_INTEGER) 14204887Schin { 14214887Schin if(flags&NV_LONG) 14224887Schin ld = *((Sfdouble_t*)sp); 14234887Schin else if(flags&NV_SHORT) 14244887Schin ld = *((float*)sp); 14254887Schin else 14264887Schin ld = *((double*)sp); 14274887Schin } 14284887Schin else 14294887Schin ld = sh_arith(sp); 14304887Schin if(!up->ldp) 14314887Schin up->ldp = new_of(Sfdouble_t,0); 14324887Schin else if(flags&NV_APPEND) 14334887Schin old = *(up->ldp); 143410898Sroland.mainz@nrubsig.org *(up->ldp) = old?ld+old:ld; 14354887Schin } 14364887Schin else 14374887Schin { 14384887Schin double d,od=0; 14394887Schin if(flags&NV_INTEGER) 14404887Schin { 14414887Schin if(flags&NV_LONG) 14424887Schin d = (double)(*(Sfdouble_t*)sp); 14434887Schin else if(flags&NV_SHORT) 14444887Schin d = (double)(*(float*)sp); 14454887Schin else 14464887Schin d = *(double*)sp; 14474887Schin } 14484887Schin else 14494887Schin d = sh_arith(sp); 14504887Schin if(!up->dp) 14514887Schin up->dp = new_of(double,0); 14524887Schin else if(flags&NV_APPEND) 14534887Schin od = *(up->dp); 145410898Sroland.mainz@nrubsig.org *(up->dp) = od?d+od:d; 14554887Schin } 14564887Schin } 14574887Schin else 14584887Schin { 14594887Schin if(nv_isattr(np, NV_LONG) && sizeof(int32_t)<sizeof(Sflong_t)) 14604887Schin { 14614887Schin Sflong_t ll=0,oll=0; 14624887Schin if(flags&NV_INTEGER) 14634887Schin { 14648462SApril.Chin@Sun.COM if((flags&NV_DOUBLE) == NV_DOUBLE) 14654887Schin { 14664887Schin if(flags&NV_LONG) 14674887Schin ll = *((Sfdouble_t*)sp); 14684887Schin else if(flags&NV_SHORT) 14694887Schin ll = *((float*)sp); 14704887Schin else 14714887Schin ll = *((double*)sp); 14724887Schin } 14734887Schin else if(nv_isattr(np,NV_UNSIGN)) 14744887Schin { 14754887Schin if(flags&NV_LONG) 14764887Schin ll = *((Sfulong_t*)sp); 14774887Schin else if(flags&NV_SHORT) 14784887Schin ll = *((uint16_t*)sp); 14794887Schin else 14804887Schin ll = *((uint32_t*)sp); 14814887Schin } 14824887Schin else 14834887Schin { 14844887Schin if(flags&NV_LONG) 14854887Schin ll = *((Sflong_t*)sp); 14864887Schin else if(flags&NV_SHORT) 14874887Schin ll = *((uint16_t*)sp); 14884887Schin else 14894887Schin ll = *((uint32_t*)sp); 14904887Schin } 14914887Schin } 14924887Schin else if(sp) 14934887Schin ll = (Sflong_t)sh_arith(sp); 14944887Schin if(!up->llp) 14954887Schin up->llp = new_of(Sflong_t,0); 14964887Schin else if(flags&NV_APPEND) 14974887Schin oll = *(up->llp); 14984887Schin *(up->llp) = ll+oll; 14994887Schin } 15004887Schin else 15014887Schin { 15024887Schin int32_t l=0,ol=0; 15034887Schin if(flags&NV_INTEGER) 15044887Schin { 15058462SApril.Chin@Sun.COM if((flags&NV_DOUBLE) == NV_DOUBLE) 15064887Schin { 15074887Schin Sflong_t ll; 15084887Schin if(flags&NV_LONG) 15094887Schin ll = *((Sfdouble_t*)sp); 15104887Schin else if(flags&NV_SHORT) 15114887Schin ll = *((float*)sp); 15124887Schin else 15134887Schin ll = *((double*)sp); 15144887Schin l = (int32_t)ll; 15154887Schin } 15164887Schin else if(nv_isattr(np,NV_UNSIGN)) 15174887Schin { 15184887Schin if(flags&NV_LONG) 15194887Schin l = *((Sfulong_t*)sp); 15204887Schin else if(flags&NV_SHORT) 15214887Schin l = *((uint16_t*)sp); 15224887Schin else 15234887Schin l = *(uint32_t*)sp; 15244887Schin } 15254887Schin else 15264887Schin { 15274887Schin if(flags&NV_LONG) 15284887Schin l = *((Sflong_t*)sp); 15294887Schin else if(flags&NV_SHORT) 15304887Schin l = *((int16_t*)sp); 15314887Schin else 15324887Schin l = *(int32_t*)sp; 15334887Schin } 15344887Schin } 15354887Schin else if(sp) 15364887Schin { 15374887Schin Sfdouble_t ld = sh_arith(sp); 15384887Schin if(ld<0) 15394887Schin l = (int32_t)ld; 15404887Schin else 15414887Schin l = (uint32_t)ld; 15424887Schin } 15434887Schin if(nv_size(np) <= 1) 15444887Schin nv_setsize(np,10); 15454887Schin if(nv_isattr (np, NV_SHORT)) 15464887Schin { 15474887Schin int16_t s=0; 15484887Schin if(flags&NV_APPEND) 15498462SApril.Chin@Sun.COM s = *up->sp; 15508462SApril.Chin@Sun.COM *(up->sp) = s+(int16_t)l; 15514887Schin nv_onattr(np,NV_NOFREE); 15524887Schin } 15534887Schin else 15544887Schin { 15554887Schin if(!up->lp) 15564887Schin up->lp = new_of(int32_t,0); 15574887Schin else if(flags&NV_APPEND) 15584887Schin ol = *(up->lp); 15594887Schin *(up->lp) = l+ol; 15604887Schin } 15614887Schin } 15624887Schin } 15634887Schin } 15644887Schin else 15654887Schin { 15664887Schin const char *tofree=0; 15674887Schin int offset; 15684887Schin #if _lib_pathnative 15694887Schin char buff[PATH_MAX]; 15704887Schin #endif /* _lib_pathnative */ 15714887Schin if(flags&NV_INTEGER) 15724887Schin { 15738462SApril.Chin@Sun.COM if((flags&NV_DOUBLE)==NV_DOUBLE) 15744887Schin { 15754887Schin if(flags&NV_LONG) 15764887Schin sfprintf(sh.strbuf,"%.*Lg",LDBL_DIG,*((Sfdouble_t*)sp)); 15774887Schin else 15784887Schin sfprintf(sh.strbuf,"%.*g",DBL_DIG,*((double*)sp)); 15794887Schin } 15808462SApril.Chin@Sun.COM else if(flags&NV_UNSIGN) 15818462SApril.Chin@Sun.COM { 15828462SApril.Chin@Sun.COM if(flags&NV_LONG) 15838462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%I*lu",sizeof(Sfulong_t),*((Sfulong_t*)sp)); 15848462SApril.Chin@Sun.COM else 15858462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%lu",(unsigned long)((flags&NV_SHORT)?*((uint16_t*)sp):*((uint32_t*)sp))); 15868462SApril.Chin@Sun.COM } 15874887Schin else 15888462SApril.Chin@Sun.COM { 15898462SApril.Chin@Sun.COM if(flags&NV_LONG) 15908462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%I*ld",sizeof(Sflong_t),*((Sflong_t*)sp)); 15918462SApril.Chin@Sun.COM else 15928462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%ld",(long)((flags&NV_SHORT)?*((int16_t*)sp):*((int32_t*)sp))); 15938462SApril.Chin@Sun.COM } 15944887Schin sp = sfstruse(sh.strbuf); 15954887Schin } 15968462SApril.Chin@Sun.COM if(nv_isattr(np, NV_HOST|NV_INTEGER)==NV_HOST && sp) 15974887Schin { 15984887Schin #ifdef _lib_pathnative 15994887Schin /* 16004887Schin * return the host file name given the UNIX name 16014887Schin */ 16024887Schin pathnative(sp,buff,sizeof(buff)); 16034887Schin if(buff[1]==':' && buff[2]=='/') 16044887Schin { 16054887Schin buff[2] = '\\'; 16064887Schin if(*buff>='A' && *buff<='Z') 16074887Schin *buff += 'a'-'A'; 16084887Schin } 16094887Schin sp = buff; 16104887Schin #else 16114887Schin ; 16124887Schin #endif /* _lib_pathnative */ 16134887Schin } 16144887Schin else if((nv_isattr(np, NV_RJUST|NV_ZFILL|NV_LJUST)) && sp) 16154887Schin { 16164887Schin for(;*sp == ' '|| *sp=='\t';sp++); 16174887Schin if((nv_isattr(np,NV_ZFILL)) && (nv_isattr(np,NV_LJUST))) 16184887Schin for(;*sp=='0';sp++); 16194887Schin size = nv_size(np); 16204887Schin #if SHOPT_MULTIBYTE 16214887Schin if(size) 16224887Schin size = ja_size((char*)sp,size,nv_isattr(np,NV_RJUST|NV_ZFILL)); 16234887Schin #endif /* SHOPT_MULTIBYTE */ 16244887Schin } 16254887Schin if(!up->cp) 16264887Schin flags &= ~NV_APPEND; 16274887Schin if((flags&NV_APPEND) && !nv_isattr(np,NV_BINARY)) 16284887Schin { 16294887Schin offset = staktell(); 16304887Schin stakputs(up->cp); 16314887Schin stakputs(sp); 16324887Schin stakputc(0); 16334887Schin sp = stakptr(offset); 16344887Schin } 16354887Schin if(!nv_isattr(np, NV_NOFREE)) 16364887Schin { 16374887Schin /* delay free in case <sp> points into free region */ 16384887Schin tofree = up->cp; 16394887Schin } 16408462SApril.Chin@Sun.COM if(nv_isattr(np,NV_BINARY) && !(flags&NV_RAW)) 16418462SApril.Chin@Sun.COM tofree = 0; 1642*12068SRoger.Faulkner@Oracle.COM if(nv_isattr(np,NV_LJUST|NV_RJUST) && nv_isattr(np,NV_LJUST|NV_RJUST)!=(NV_LJUST|NV_RJUST)) 16438462SApril.Chin@Sun.COM tofree = 0; 16444887Schin if (sp) 16454887Schin { 16464887Schin dot = strlen(sp); 16474887Schin #if (_AST_VERSION>=20030127L) 16484887Schin if(nv_isattr(np,NV_BINARY)) 16494887Schin { 16504887Schin int oldsize = (flags&NV_APPEND)?nv_size(np):0; 16514887Schin if(flags&NV_RAW) 16524887Schin { 16534887Schin if(tofree) 16548462SApril.Chin@Sun.COM { 16554887Schin free((void*)tofree); 16568462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 16578462SApril.Chin@Sun.COM } 16584887Schin up->cp = sp; 16594887Schin return; 16604887Schin } 16614887Schin size = 0; 16624887Schin if(nv_isattr(np,NV_ZFILL)) 16634887Schin size = nv_size(np); 16644887Schin if(size==0) 16654887Schin size = oldsize + (3*dot/4); 16664887Schin cp = (char*)malloc(size+1); 16678462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 16684887Schin if(oldsize) 16694887Schin memcpy((void*)cp,(void*)up->cp,oldsize); 16704887Schin up->cp = cp; 16714887Schin if(size <= oldsize) 16724887Schin return; 16734887Schin dot = base64decode(sp,dot, (void**)0, cp+oldsize, size-oldsize,(void**)0); 16744887Schin dot += oldsize; 16754887Schin if(!nv_isattr(np,NV_ZFILL) || nv_size(np)==0) 16764887Schin nv_setsize(np,dot); 16774887Schin else if(nv_isattr(np,NV_ZFILL) && (size>dot)) 16784887Schin memset((void*)&cp[dot],0,size-dot); 16794887Schin return; 16804887Schin } 16814887Schin else 16824887Schin #endif 1683*12068SRoger.Faulkner@Oracle.COM if(size==0 && nv_isattr(np,NV_HOST)!=NV_HOST &&nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL)) 16844887Schin nv_setsize(np,size=dot); 16854887Schin else if(size > dot) 16864887Schin dot = size; 1687*12068SRoger.Faulkner@Oracle.COM else if(nv_isattr(np,NV_LJUST|NV_RJUST)==NV_LJUST && dot>size) 16888462SApril.Chin@Sun.COM dot = size; 16898462SApril.Chin@Sun.COM if(size==0 || tofree || !(cp=(char*)up->cp)) 16908462SApril.Chin@Sun.COM { 16918462SApril.Chin@Sun.COM cp = (char*)malloc(((unsigned)dot+1)); 16928462SApril.Chin@Sun.COM cp[dot] = 0; 16938462SApril.Chin@Sun.COM nv_offattr(np,NV_NOFREE); 16948462SApril.Chin@Sun.COM } 16958462SApril.Chin@Sun.COM 16964887Schin } 16974887Schin else 16984887Schin cp = 0; 16994887Schin up->cp = cp; 17004887Schin if(sp) 17014887Schin { 17028462SApril.Chin@Sun.COM int c = cp[dot]; 17038462SApril.Chin@Sun.COM memcpy(cp,sp,dot); 17048462SApril.Chin@Sun.COM cp[dot]=0; 17054887Schin if(nv_isattr(np, NV_LTOU)) 17068462SApril.Chin@Sun.COM ltou(cp); 17074887Schin else if(nv_isattr (np, NV_UTOL)) 17088462SApril.Chin@Sun.COM utol(cp); 17098462SApril.Chin@Sun.COM cp[dot] = c; 17104887Schin if(nv_isattr(np, NV_RJUST) && nv_isattr(np, NV_ZFILL)) 17114887Schin rightjust(cp,size,'0'); 1712*12068SRoger.Faulkner@Oracle.COM else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_RJUST) 17134887Schin rightjust(cp,size,' '); 1714*12068SRoger.Faulkner@Oracle.COM else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_LJUST) 17154887Schin { 17164887Schin register char *dp; 17174887Schin dp = strlen (cp) + cp; 17188462SApril.Chin@Sun.COM cp = cp+size; 17194887Schin for (; dp < cp; *dp++ = ' '); 17204887Schin } 17214887Schin #if SHOPT_MULTIBYTE 17224887Schin /* restore original string */ 17234887Schin if(savep) 17244887Schin ja_restore(); 17254887Schin #endif /* SHOPT_MULTIBYTE */ 17264887Schin } 17274887Schin if(flags&NV_APPEND) 17284887Schin stakseek(offset); 17298462SApril.Chin@Sun.COM if(tofree && tofree!=Empty) 17304887Schin free((void*)tofree); 17314887Schin } 17324887Schin if(!was_local && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT))) 17334887Schin sh_envput(sh.env,np); 17344887Schin return; 17354887Schin } 17364887Schin 17374887Schin /* 17384887Schin * 17394887Schin * Right-justify <str> so that it contains no more than 17404887Schin * <size> characters. If <str> contains fewer than <size> 17414887Schin * characters, left-pad with <fill>. Trailing blanks 17424887Schin * in <str> will be ignored. 17434887Schin * 17444887Schin * If the leftmost digit in <str> is not a digit, <fill> 17454887Schin * will default to a blank. 17464887Schin */ 17474887Schin static void rightjust(char *str, int size, int fill) 17484887Schin { 17494887Schin register int n; 17504887Schin register char *cp,*sp; 17514887Schin n = strlen(str); 17524887Schin 17534887Schin /* ignore trailing blanks */ 17544887Schin for(cp=str+n;n && *--cp == ' ';n--); 17554887Schin if (n == size) 17564887Schin return; 17574887Schin if(n > size) 17584887Schin { 17594887Schin *(str+n) = 0; 17604887Schin for (sp = str, cp = str+n-size; sp <= str+size; *sp++ = *cp++); 17614887Schin return; 17624887Schin } 17634887Schin else *(sp = str+size) = 0; 17644887Schin if (n == 0) 17654887Schin { 17664887Schin while (sp > str) 17674887Schin *--sp = ' '; 17684887Schin return; 17694887Schin } 17704887Schin while(n--) 17714887Schin { 17724887Schin sp--; 17734887Schin *sp = *cp--; 17744887Schin } 17754887Schin if(!isdigit(*str)) 17764887Schin fill = ' '; 17774887Schin while(sp>str) 17784887Schin *--sp = fill; 17794887Schin return; 17804887Schin } 17814887Schin 17824887Schin #if SHOPT_MULTIBYTE 17834887Schin /* 17844887Schin * handle left and right justified fields for multi-byte chars 17854887Schin * given physical size, return a logical size which reflects the 17864887Schin * screen width of multi-byte characters 17874887Schin * Multi-width characters replaced by spaces if they cross the boundary 17884887Schin * <type> is non-zero for right justified fields 17894887Schin */ 17904887Schin 17914887Schin static int ja_size(char *str,int size,int type) 17924887Schin { 17934887Schin register char *cp = str; 17944887Schin register int c, n=size; 17954887Schin register int outsize; 17964887Schin register char *oldcp=cp; 17974887Schin int oldn; 17984887Schin wchar_t w; 17994887Schin while(*cp) 18004887Schin { 18014887Schin oldn = n; 18024887Schin w = mbchar(cp); 18034887Schin outsize = mbwidth(w); 18044887Schin size -= outsize; 18054887Schin c = cp-oldcp; 18064887Schin n += (c-outsize); 18074887Schin oldcp = cp; 18084887Schin if(size<=0 && type==0) 18094887Schin break; 18104887Schin } 18114887Schin /* check for right justified fields that need truncating */ 18124887Schin if(size <0) 18134887Schin { 18144887Schin if(type==0) 18154887Schin { 18164887Schin /* left justified and character crosses field boundary */ 18174887Schin n = oldn; 18184887Schin /* save boundary char and replace with spaces */ 18194887Schin size = c; 18204887Schin savechars[size] = 0; 18214887Schin while(size--) 18224887Schin { 18234887Schin savechars[size] = cp[size]; 18244887Schin cp[size] = ' '; 18254887Schin } 18264887Schin savep = cp; 18274887Schin } 18284887Schin size = -size; 18294887Schin if(type) 18304887Schin n -= (ja_size(str,size,0)-size); 18314887Schin } 18324887Schin return(n); 18334887Schin } 18344887Schin 18354887Schin static void ja_restore(void) 18364887Schin { 18374887Schin register char *cp = savechars; 18384887Schin while(*cp) 18394887Schin *savep++ = *cp++; 18404887Schin savep = 0; 18414887Schin } 18424887Schin #endif /* SHOPT_MULTIBYTE */ 18434887Schin 18444887Schin #ifndef _ENV_H 18454887Schin static char *staknam(register Namval_t *np, char *value) 18464887Schin { 18474887Schin register char *p,*q; 18484887Schin q = stakalloc(strlen(nv_name(np))+(value?strlen(value):0)+2); 18494887Schin p=strcopy(q,nv_name(np)); 18504887Schin if(value) 18514887Schin { 18524887Schin *p++ = '='; 18534887Schin strcpy(p,value); 18544887Schin } 18554887Schin return(q); 18564887Schin } 18574887Schin #endif 18584887Schin 18594887Schin /* 18604887Schin * put the name and attribute into value of attributes variable 18614887Schin */ 18624887Schin #ifdef _ENV_H 18634887Schin static void attstore(register Namval_t *np, void *data) 18644887Schin { 18654887Schin register int flag, c = ' '; 18664887Schin NOT_USED(data); 18674887Schin if(!(nv_isattr(np,NV_EXPORT))) 18684887Schin return; 18694887Schin flag = nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER); 18704887Schin stakputc('='); 18718462SApril.Chin@Sun.COM if((flag&NV_DOUBLE) == NV_DOUBLE) 18724887Schin { 18734887Schin /* export doubles as integers for ksh88 compatibility */ 18748462SApril.Chin@Sun.COM stakputc(c+NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE))); 18754887Schin } 18764887Schin else 18774887Schin { 18784887Schin stakputc(c+flag); 18794887Schin if(flag&NV_INTEGER) 18804887Schin c += nv_size(np); 18814887Schin } 18824887Schin stakputc(c); 18834887Schin stakputs(nv_name(np)); 18844887Schin } 18854887Schin #else 18864887Schin static void attstore(register Namval_t *np, void *data) 18874887Schin { 18884887Schin register int flag = np->nvflag; 18894887Schin register struct adata *ap = (struct adata*)data; 18908462SApril.Chin@Sun.COM ap->sh = &sh; 18918462SApril.Chin@Sun.COM ap->tp = 0; 18924887Schin if(!(flag&NV_EXPORT) || (flag&NV_FUNCT)) 18934887Schin return; 18944887Schin flag &= (NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER); 18954887Schin *ap->attval++ = '='; 18968462SApril.Chin@Sun.COM if((flag&NV_DOUBLE) == NV_DOUBLE) 18974887Schin { 18984887Schin /* export doubles as integers for ksh88 compatibility */ 18998462SApril.Chin@Sun.COM *ap->attval++ = ' '+ NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE)); 19004887Schin *ap->attval = ' '; 19014887Schin } 19024887Schin else 19034887Schin { 19044887Schin *ap->attval++ = ' '+flag; 19054887Schin if(flag&NV_INTEGER) 19064887Schin *ap->attval = ' ' + nv_size(np); 19074887Schin else 19084887Schin *ap->attval = ' '; 19094887Schin } 19104887Schin ap->attval = strcopy(++ap->attval,nv_name(np)); 19114887Schin } 19124887Schin #endif 19134887Schin 19144887Schin #ifndef _ENV_H 19154887Schin static void pushnam(Namval_t *np, void *data) 19164887Schin { 19174887Schin register char *value; 19184887Schin register struct adata *ap = (struct adata*)data; 19198462SApril.Chin@Sun.COM ap->sh = &sh; 19208462SApril.Chin@Sun.COM ap->tp = 0; 1921*12068SRoger.Faulkner@Oracle.COM if(nv_isattr(np,NV_IMPORT) && np->nvenv) 1922*12068SRoger.Faulkner@Oracle.COM *ap->argnam++ = np->nvenv; 19234887Schin else if(value=nv_getval(np)) 19244887Schin *ap->argnam++ = staknam(np,value); 19254887Schin if(nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)) 19264887Schin ap->attsize += (strlen(nv_name(np))+4); 19274887Schin } 19284887Schin #endif 19294887Schin 19304887Schin /* 19314887Schin * Generate the environment list for the child. 19324887Schin */ 19334887Schin 19344887Schin #ifdef _ENV_H 19354887Schin char **sh_envgen(void) 19364887Schin { 19374887Schin int offset,tell; 19384887Schin register char **er; 19394887Schin env_delete(sh.env,"_"); 19404887Schin er = env_get(sh.env); 19414887Schin offset = staktell(); 19424887Schin stakputs(e_envmarker); 19434887Schin tell = staktell(); 19444887Schin nv_scan(sh.var_tree, attstore,(void*)0,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)); 19454887Schin if(tell ==staktell()) 19464887Schin stakseek(offset); 19474887Schin else 19484887Schin *--er = stakfreeze(1)+offset; 19494887Schin return(er); 19504887Schin } 19514887Schin #else 19524887Schin char **sh_envgen(void) 19534887Schin { 19544887Schin register char **er; 19554887Schin register int namec; 19564887Schin register char *cp; 19574887Schin struct adata data; 19588462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 19598462SApril.Chin@Sun.COM data.sh = shp; 19608462SApril.Chin@Sun.COM data.tp = 0; 19614887Schin /* L_ARGNOD gets generated automatically as full path name of command */ 19624887Schin nv_offattr(L_ARGNOD,NV_EXPORT); 19634887Schin data.attsize = 6; 19648462SApril.Chin@Sun.COM namec = nv_scan(shp->var_tree,nullscan,(void*)0,NV_EXPORT,NV_EXPORT); 19658462SApril.Chin@Sun.COM namec += shp->nenv; 19664887Schin er = (char**)stakalloc((namec+4)*sizeof(char*)); 19678462SApril.Chin@Sun.COM data.argnam = (er+=2) + shp->nenv; 19688462SApril.Chin@Sun.COM if(shp->nenv) 19698462SApril.Chin@Sun.COM memcpy((void*)er,environ,shp->nenv*sizeof(char*)); 19708462SApril.Chin@Sun.COM nv_scan(shp->var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT); 19714887Schin *data.argnam = (char*)stakalloc(data.attsize); 19724887Schin cp = data.attval = strcopy(*data.argnam,e_envmarker); 19738462SApril.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)); 19744887Schin *data.attval = 0; 19754887Schin if(cp!=data.attval) 19764887Schin data.argnam++; 19774887Schin *data.argnam = 0; 19784887Schin return(er); 19794887Schin } 19804887Schin #endif 19814887Schin 19824887Schin struct scan 19834887Schin { 19844887Schin void (*scanfn)(Namval_t*, void*); 19854887Schin int scanmask; 19864887Schin int scanflags; 19874887Schin int scancount; 19884887Schin void *scandata; 19894887Schin }; 19904887Schin 19914887Schin static int scanfilter(Dt_t *dict, void *arg, void *data) 19924887Schin { 19934887Schin register Namval_t *np = (Namval_t*)arg; 19944887Schin register int k=np->nvflag; 19954887Schin register struct scan *sp = (struct scan*)data; 19968462SApril.Chin@Sun.COM register struct adata *tp = (struct adata*)sp->scandata; 19974887Schin NOT_USED(dict); 19988462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 1999*12068SRoger.Faulkner@Oracle.COM if(!is_abuiltin(np) && tp && tp->tp && nv_type(np)!=tp->tp) 20008462SApril.Chin@Sun.COM return(0); 20018462SApril.Chin@Sun.COM #endif /*SHOPT_TYPEDEF */ 20024887Schin if(sp->scanmask?(k&sp->scanmask)==sp->scanflags:(!sp->scanflags || (k&sp->scanflags))) 20034887Schin { 20048462SApril.Chin@Sun.COM if(!np->nvalue.cp && !np->nvfun && !nv_isattr(np,~NV_DEFAULT)) 20054887Schin return(0); 20064887Schin if(sp->scanfn) 20074887Schin { 20084887Schin if(nv_isarray(np)) 20094887Schin nv_putsub(np,NIL(char*),0L); 20104887Schin (*sp->scanfn)(np,sp->scandata); 20114887Schin } 20124887Schin sp->scancount++; 20134887Schin } 20144887Schin return(0); 20154887Schin } 20164887Schin 20174887Schin /* 20184887Schin * Walk through the name-value pairs 20194887Schin * if <mask> is non-zero, then only nodes with (nvflags&mask)==flags 20204887Schin * are visited 20214887Schin * If <mask> is zero, and <flags> non-zero, then nodes with one or 20224887Schin * more of <flags> is visited 20234887Schin * If <mask> and <flags> are zero, then all nodes are visted 20244887Schin */ 20254887Schin int nv_scan(Dt_t *root, void (*fn)(Namval_t*,void*), void *data,int mask, int flags) 20264887Schin { 20274887Schin Dt_t *base=0; 20284887Schin struct scan sdata; 20294887Schin int (*hashfn)(Dt_t*, void*, void*); 20304887Schin sdata.scanmask = mask; 20314887Schin sdata.scanflags = flags&~NV_NOSCOPE; 20324887Schin sdata.scanfn = fn; 20334887Schin sdata.scancount = 0; 20344887Schin sdata.scandata = data; 20354887Schin hashfn = scanfilter; 20364887Schin if(flags&NV_NOSCOPE) 20374887Schin base = dtview((Dt_t*)root,0); 20384887Schin dtwalk(root, hashfn,&sdata); 20394887Schin if(base) 20404887Schin dtview((Dt_t*)root,base); 20414887Schin return(sdata.scancount); 20424887Schin } 20434887Schin 20444887Schin /* 20454887Schin * create a new environment scope 20464887Schin */ 20478462SApril.Chin@Sun.COM void sh_scope(Shell_t *shp, struct argnod *envlist, int fun) 20484887Schin { 20498462SApril.Chin@Sun.COM register Dt_t *newscope, *newroot=shp->var_base; 20508462SApril.Chin@Sun.COM struct Ufunction *rp; 20514887Schin newscope = dtopen(&_Nvdisc,Dtoset); 20524887Schin if(envlist) 20538462SApril.Chin@Sun.COM { 20548462SApril.Chin@Sun.COM dtview(newscope,(Dt_t*)shp->var_tree); 20558462SApril.Chin@Sun.COM shp->var_tree = newscope; 205610898Sroland.mainz@nrubsig.org nv_setlist(envlist,NV_EXPORT|NV_NOSCOPE|NV_IDENT|NV_ASSIGN,0); 20578462SApril.Chin@Sun.COM if(!fun) 20588462SApril.Chin@Sun.COM return; 20598462SApril.Chin@Sun.COM shp->var_tree = dtview(newscope,0); 20608462SApril.Chin@Sun.COM } 20618462SApril.Chin@Sun.COM if((rp=shp->st.real_fun) && rp->sdict) 20628462SApril.Chin@Sun.COM { 20638462SApril.Chin@Sun.COM dtview(rp->sdict,newroot); 20648462SApril.Chin@Sun.COM newroot = rp->sdict; 20658462SApril.Chin@Sun.COM 20668462SApril.Chin@Sun.COM } 20678462SApril.Chin@Sun.COM dtview(newscope,(Dt_t*)newroot); 20688462SApril.Chin@Sun.COM shp->var_tree = newscope; 20694887Schin } 20704887Schin 20714887Schin /* 20724887Schin * Remove freeable local space associated with the nvalue field 20734887Schin * of nnod. This includes any strings representing the value(s) of the 20744887Schin * node, as well as its dope vector, if it is an array. 20754887Schin */ 20764887Schin 20774887Schin void sh_envnolocal (register Namval_t *np, void *data) 20784887Schin { 20794887Schin char *cp=0; 20804887Schin NOT_USED(data); 208110898Sroland.mainz@nrubsig.org if(np==VERSIONNOD && nv_isref(np)) 208210898Sroland.mainz@nrubsig.org return; 208310898Sroland.mainz@nrubsig.org if(np==L_ARGNOD) 208410898Sroland.mainz@nrubsig.org return; 20854887Schin if(nv_isattr(np,NV_EXPORT) && nv_isarray(np)) 20864887Schin { 20874887Schin nv_putsub(np,NIL(char*),0); 20884887Schin if(cp = nv_getval(np)) 20894887Schin cp = strdup(cp); 20904887Schin } 20914887Schin if(nv_isattr(np,NV_EXPORT|NV_NOFREE)) 20924887Schin { 209310898Sroland.mainz@nrubsig.org if(nv_isref(np) && np!=VERSIONNOD) 20944887Schin { 20954887Schin nv_offattr(np,NV_NOFREE|NV_REF); 20964887Schin free((void*)np->nvalue.nrp); 20974887Schin np->nvalue.cp = 0; 20984887Schin } 20994887Schin if(!cp) 21004887Schin return; 21014887Schin } 21024887Schin if(nv_isarray(np)) 21034887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 21044887Schin _nv_unset(np,NV_RDONLY); 21054887Schin nv_setattr(np,0); 21064887Schin if(cp) 21074887Schin { 21084887Schin nv_putval(np,cp,0); 21094887Schin free((void*)cp); 21104887Schin } 21114887Schin } 21124887Schin 21134887Schin /* 21144887Schin * Currently this is a dummy, but someday will be needed 21154887Schin * for reference counting 21164887Schin */ 21174887Schin void nv_close(Namval_t *np) 21184887Schin { 21194887Schin NOT_USED(np); 21204887Schin } 21214887Schin 21228462SApril.Chin@Sun.COM static void table_unset(Shell_t *shp, register Dt_t *root, int flags, Dt_t *oroot) 21234887Schin { 21248462SApril.Chin@Sun.COM register Namval_t *np,*nq, *npnext; 21258462SApril.Chin@Sun.COM for(np=(Namval_t*)dtfirst(root);np;np=npnext) 21264887Schin { 21278462SApril.Chin@Sun.COM if(nv_isref(np)) 212810898Sroland.mainz@nrubsig.org { 212910898Sroland.mainz@nrubsig.org free((void*)np->nvalue.nrp); 213010898Sroland.mainz@nrubsig.org np->nvalue.cp = 0; 213110898Sroland.mainz@nrubsig.org np->nvflag = 0; 213210898Sroland.mainz@nrubsig.org } 21338462SApril.Chin@Sun.COM if(nq=dtsearch(oroot,np)) 21348462SApril.Chin@Sun.COM { 21358462SApril.Chin@Sun.COM if(nv_cover(nq)) 21368462SApril.Chin@Sun.COM { 21378462SApril.Chin@Sun.COM int subshell = shp->subshell; 21388462SApril.Chin@Sun.COM shp->subshell = 0; 21398462SApril.Chin@Sun.COM if(nv_isattr(nq, NV_INTEGER)) 21408462SApril.Chin@Sun.COM { 21418462SApril.Chin@Sun.COM Sfdouble_t d = nv_getnum(nq); 21428462SApril.Chin@Sun.COM nv_putval(nq,(char*)&d,NV_LDOUBLE); 21438462SApril.Chin@Sun.COM } 214410898Sroland.mainz@nrubsig.org else if(shp->test&4) 214510898Sroland.mainz@nrubsig.org nv_putval(nq, strdup(nv_getval(nq)), NV_RDONLY); 21468462SApril.Chin@Sun.COM else 21478462SApril.Chin@Sun.COM nv_putval(nq, nv_getval(nq), NV_RDONLY); 21488462SApril.Chin@Sun.COM shp->subshell = subshell; 21498462SApril.Chin@Sun.COM np->nvfun = 0; 21508462SApril.Chin@Sun.COM } 21518462SApril.Chin@Sun.COM if(nv_isattr(nq,NV_EXPORT)) 21528462SApril.Chin@Sun.COM sh_envput(shp->env,nq); 21538462SApril.Chin@Sun.COM } 21548462SApril.Chin@Sun.COM npnext = (Namval_t*)dtnext(root,np); 21558462SApril.Chin@Sun.COM shp->last_root = root; 21568462SApril.Chin@Sun.COM shp->last_table = 0; 21578462SApril.Chin@Sun.COM if(nv_isvtree(np)) 21588462SApril.Chin@Sun.COM { 21598462SApril.Chin@Sun.COM int len = strlen(np->nvname); 21608462SApril.Chin@Sun.COM while((nq=npnext) && memcmp(np->nvname,nq->nvname,len)==0 && nq->nvname[len]=='.') 21618462SApril.Chin@Sun.COM 21628462SApril.Chin@Sun.COM { 21638462SApril.Chin@Sun.COM npnext = (Namval_t*)dtnext(root,nq); 21648462SApril.Chin@Sun.COM _nv_unset(nq,flags); 21658462SApril.Chin@Sun.COM nv_delete(nq,root,0); 21668462SApril.Chin@Sun.COM } 21678462SApril.Chin@Sun.COM } 21684887Schin _nv_unset(np,flags); 21698462SApril.Chin@Sun.COM nv_delete(np,root,0); 21704887Schin } 21714887Schin } 21724887Schin 21734887Schin /* 21744887Schin * 21754887Schin * Set the value of <np> to 0, and nullify any attributes 21764887Schin * that <np> may have had. Free any freeable space occupied 21774887Schin * by the value of <np>. If <np> denotes an array member, it 21784887Schin * will retain its attributes. 21794887Schin * <flags> can contain NV_RDONLY to override the readonly attribute 21804887Schin * being cleared. 21818462SApril.Chin@Sun.COM * <flags> can contain NV_EXPORT to override preserve nvenv 21824887Schin */ 21834887Schin void _nv_unset(register Namval_t *np,int flags) 21844887Schin { 21858462SApril.Chin@Sun.COM Shell_t *shp = &sh; 21864887Schin register union Value *up; 21874887Schin if(!(flags&NV_RDONLY) && nv_isattr (np,NV_RDONLY)) 21884887Schin errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np)); 21894887Schin if(is_afunction(np) && np->nvalue.ip) 21904887Schin { 21914887Schin register struct slnod *slp = (struct slnod*)(np->nvenv); 21924887Schin if(slp && !nv_isattr(np,NV_NOFREE)) 21934887Schin { 21948462SApril.Chin@Sun.COM struct Ufunction *rq,*rp = np->nvalue.rp; 21954887Schin /* free function definition */ 21964887Schin register char *name=nv_name(np),*cp= strrchr(name,'.'); 21974887Schin if(cp) 21984887Schin { 21994887Schin Namval_t *npv; 22004887Schin *cp = 0; 22018462SApril.Chin@Sun.COM npv = nv_open(name,shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOADD); 22024887Schin *cp++ = '.'; 22034887Schin if(npv) 22044887Schin nv_setdisc(npv,cp,NIL(Namval_t*),(Namfun_t*)npv); 22054887Schin } 22068462SApril.Chin@Sun.COM if(rp->fname && shp->fpathdict && (rq = (struct Ufunction*)nv_search(rp->fname,shp->fpathdict,0))) 22078462SApril.Chin@Sun.COM { 22088462SApril.Chin@Sun.COM do 22098462SApril.Chin@Sun.COM { 22108462SApril.Chin@Sun.COM if(rq->np != np) 22118462SApril.Chin@Sun.COM continue; 22128462SApril.Chin@Sun.COM dtdelete(shp->fpathdict,rq); 22138462SApril.Chin@Sun.COM break; 22148462SApril.Chin@Sun.COM } 22158462SApril.Chin@Sun.COM while(rq = (struct Ufunction*)dtnext(shp->fpathdict,rq)); 22168462SApril.Chin@Sun.COM } 22178462SApril.Chin@Sun.COM if(rp->sdict) 22188462SApril.Chin@Sun.COM { 22198462SApril.Chin@Sun.COM Namval_t *mp, *nq; 22208462SApril.Chin@Sun.COM for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq) 22218462SApril.Chin@Sun.COM { 22228462SApril.Chin@Sun.COM nq = dtnext(rp->sdict,mp); 22238462SApril.Chin@Sun.COM _nv_unset(mp,NV_RDONLY); 22248462SApril.Chin@Sun.COM nv_delete(mp,rp->sdict,0); 22258462SApril.Chin@Sun.COM } 22268462SApril.Chin@Sun.COM dtclose(rp->sdict); 22278462SApril.Chin@Sun.COM } 22284887Schin stakdelete(slp->slptr); 22294887Schin free((void*)np->nvalue.ip); 22304887Schin np->nvalue.ip = 0; 22314887Schin } 22324887Schin goto done; 22334887Schin } 22348462SApril.Chin@Sun.COM if(shp->subshell && !nv_isnull(np)) 22354887Schin np = sh_assignok(np,0); 22364887Schin nv_offattr(np,NV_NODISC); 22374887Schin if(np->nvfun && !nv_isref(np)) 22384887Schin { 22394887Schin /* This function contains disc */ 22404887Schin if(!nv_local) 22414887Schin { 22424887Schin nv_local=1; 22434887Schin nv_putv(np,NIL(char*),flags,np->nvfun); 22448462SApril.Chin@Sun.COM nv_local=0; 22454887Schin return; 22464887Schin } 22474887Schin /* called from disc, assign the actual value */ 22484887Schin nv_local=0; 22494887Schin } 225010898Sroland.mainz@nrubsig.org if(nv_isattr(np,NV_INT16P) == NV_INT16) 225110898Sroland.mainz@nrubsig.org { 225210898Sroland.mainz@nrubsig.org np->nvalue.cp = nv_isarray(np)?Empty:0; 225310898Sroland.mainz@nrubsig.org goto done; 225410898Sroland.mainz@nrubsig.org } 22558462SApril.Chin@Sun.COM if(nv_isarray(np) && np->nvalue.cp!=Empty && np->nvfun) 22568462SApril.Chin@Sun.COM up = np->nvalue.up; 22578462SApril.Chin@Sun.COM else 22588462SApril.Chin@Sun.COM up = &np->nvalue; 22598462SApril.Chin@Sun.COM if(up && up->cp) 22604887Schin { 22618462SApril.Chin@Sun.COM if(up->cp!=Empty && !nv_isattr(np, NV_NOFREE)) 22624887Schin free((void*)up->cp); 22634887Schin up->cp = 0; 22644887Schin } 22654887Schin done: 22664887Schin if(!nv_isarray(np) || !nv_arrayptr(np)) 22674887Schin { 22688462SApril.Chin@Sun.COM if(nv_isref(np) && !nv_isattr(np,NV_EXPORT)) 22694887Schin free((void*)np->nvalue.nrp); 22704887Schin nv_setsize(np,0); 22714887Schin if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT)) 22724887Schin { 22734887Schin if(nv_isattr(np,NV_EXPORT) && !strchr(np->nvname,'[')) 22748462SApril.Chin@Sun.COM env_delete(shp->env,nv_name(np)); 22758462SApril.Chin@Sun.COM if(!(flags&NV_EXPORT) || nv_isattr(np,NV_IMPORT|NV_EXPORT)==(NV_IMPORT|NV_EXPORT)) 22768462SApril.Chin@Sun.COM np->nvenv = 0; 22774887Schin nv_setattr(np,0); 22784887Schin } 22794887Schin else 22808462SApril.Chin@Sun.COM { 22814887Schin nv_setattr(np,NV_MINIMAL); 22828462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 22838462SApril.Chin@Sun.COM } 22844887Schin } 22854887Schin } 22864887Schin 22874887Schin /* 22884887Schin * return the node pointer in the highest level scope 22894887Schin */ 22908462SApril.Chin@Sun.COM Namval_t *sh_scoped(Shell_t *shp, register Namval_t *np) 22914887Schin { 22928462SApril.Chin@Sun.COM if(!dtvnext(shp->var_tree)) 22934887Schin return(np); 22948462SApril.Chin@Sun.COM return(dtsearch(shp->var_tree,np)); 22954887Schin } 22964887Schin 22974887Schin #if 1 22984887Schin /* 22994887Schin * return space separated list of names of variables in given tree 23004887Schin */ 23014887Schin static char *tableval(Dt_t *root) 23024887Schin { 23034887Schin static Sfio_t *out; 23044887Schin register Namval_t *np; 23054887Schin register int first=1; 23064887Schin register Dt_t *base = dtview(root,0); 23074887Schin if(out) 23084887Schin sfseek(out,(Sfoff_t)0,SEEK_SET); 23094887Schin else 23104887Schin out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING); 23114887Schin for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np)) 23124887Schin { 23134887Schin if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE)) 23144887Schin { 23154887Schin if(!first) 23164887Schin sfputc(out,' '); 23174887Schin else 23184887Schin first = 0; 23194887Schin sfputr(out,np->nvname,-1); 23204887Schin } 23214887Schin } 23224887Schin sfputc(out,0); 23234887Schin if(base) 23244887Schin dtview(root,base); 23254887Schin return((char*)out->_data); 23264887Schin } 23274887Schin #endif 23284887Schin 23294887Schin #if SHOPT_OPTIMIZE 23304887Schin struct optimize 23314887Schin { 23324887Schin Namfun_t hdr; 23338462SApril.Chin@Sun.COM Shell_t *sh; 23344887Schin char **ptr; 23354887Schin struct optimize *next; 23364887Schin Namval_t *np; 23374887Schin }; 23384887Schin 23394887Schin static struct optimize *opt_free; 23404887Schin 23414887Schin static void optimize_clear(Namval_t* np, Namfun_t *fp) 23424887Schin { 23434887Schin struct optimize *op = (struct optimize*)fp; 23444887Schin nv_stack(np,fp); 23454887Schin nv_stack(np,(Namfun_t*)0); 23464887Schin for(;op && op->np==np; op=op->next) 23474887Schin { 23484887Schin if(op->ptr) 23494887Schin { 23504887Schin *op->ptr = 0; 23514887Schin op->ptr = 0; 23524887Schin } 23534887Schin } 23544887Schin } 23554887Schin 23564887Schin static void put_optimize(Namval_t* np,const char *val,int flags,Namfun_t *fp) 23574887Schin { 23584887Schin nv_putv(np,val,flags,fp); 23594887Schin optimize_clear(np,fp); 23604887Schin } 23614887Schin 23628462SApril.Chin@Sun.COM static Namfun_t *clone_optimize(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp) 23638462SApril.Chin@Sun.COM { 23648462SApril.Chin@Sun.COM return((Namfun_t*)0); 23658462SApril.Chin@Sun.COM } 23668462SApril.Chin@Sun.COM 23678462SApril.Chin@Sun.COM static const Namdisc_t optimize_disc = {sizeof(struct optimize),put_optimize,0,0,0,0,clone_optimize}; 23684887Schin 23694887Schin void nv_optimize(Namval_t *np) 23704887Schin { 23714887Schin register Namfun_t *fp; 23724887Schin register struct optimize *op, *xp; 23734887Schin if(sh.argaddr) 23744887Schin { 23758462SApril.Chin@Sun.COM if(np==SH_LINENO) 23768462SApril.Chin@Sun.COM { 23778462SApril.Chin@Sun.COM sh.argaddr = 0; 23788462SApril.Chin@Sun.COM return; 23798462SApril.Chin@Sun.COM } 23804887Schin for(fp=np->nvfun; fp; fp = fp->next) 23814887Schin { 23828462SApril.Chin@Sun.COM if(fp->disc && (fp->disc->getnum || fp->disc->getval)) 23834887Schin { 23844887Schin sh.argaddr = 0; 23854887Schin return; 23864887Schin } 23874887Schin if(fp->disc== &optimize_disc) 23884887Schin break; 23894887Schin } 23904887Schin if((xp= (struct optimize*)fp) && xp->ptr==sh.argaddr) 23914887Schin return; 23924887Schin if(op = opt_free) 23934887Schin opt_free = op->next; 23944887Schin else 23954887Schin op=(struct optimize*)calloc(1,sizeof(struct optimize)); 23964887Schin op->ptr = sh.argaddr; 23974887Schin op->np = np; 23984887Schin if(xp) 23994887Schin { 24004887Schin op->hdr.disc = 0; 24014887Schin op->next = xp->next; 24024887Schin xp->next = op; 24034887Schin } 24044887Schin else 24054887Schin { 24064887Schin op->hdr.disc = &optimize_disc; 24074887Schin op->next = (struct optimize*)sh.optlist; 24084887Schin sh.optlist = (void*)op; 24094887Schin nv_stack(np,&op->hdr); 24104887Schin } 24114887Schin } 24124887Schin } 24134887Schin 24144887Schin void sh_optclear(Shell_t *shp, void *old) 24154887Schin { 24164887Schin register struct optimize *op,*opnext; 24174887Schin for(op=(struct optimize*)shp->optlist; op; op = opnext) 24184887Schin { 24194887Schin opnext = op->next; 24204887Schin if(op->ptr && op->hdr.disc) 24214887Schin { 24224887Schin nv_stack(op->np,&op->hdr); 24234887Schin nv_stack(op->np,(Namfun_t*)0); 24244887Schin } 24254887Schin op->next = opt_free; 24264887Schin opt_free = op; 24274887Schin } 24284887Schin shp->optlist = old; 24294887Schin } 24304887Schin 24314887Schin #else 24324887Schin # define optimize_clear(np,fp) 24334887Schin #endif /* SHOPT_OPTIMIZE */ 24344887Schin 24354887Schin /* 24364887Schin * Return a pointer to a character string that denotes the value 24374887Schin * of <np>. If <np> refers to an array, return a pointer to 24384887Schin * the value associated with the current index. 24394887Schin * 24404887Schin * If the value of <np> is an integer, the string returned will 24414887Schin * be overwritten by the next call to nv_getval. 24424887Schin * 24434887Schin * If <np> has no value, 0 is returned. 24444887Schin */ 24454887Schin 24464887Schin char *nv_getval(register Namval_t *np) 24474887Schin { 24484887Schin register union Value *up= &np->nvalue; 24494887Schin register int numeric; 24504887Schin #if SHOPT_OPTIMIZE 24514887Schin if(!nv_local && sh.argaddr) 24524887Schin nv_optimize(np); 24534887Schin #endif /* SHOPT_OPTIMIZE */ 24548462SApril.Chin@Sun.COM if((!np->nvfun || !np->nvfun->disc) && !nv_isattr(np,NV_ARRAY|NV_INTEGER|NV_FUNCT|NV_REF|NV_TABLE)) 24554887Schin goto done; 24564887Schin if(nv_isref(np)) 24574887Schin { 24588462SApril.Chin@Sun.COM if(!np->nvalue.cp) 24598462SApril.Chin@Sun.COM return(0); 24604887Schin sh.last_table = nv_reftable(np); 24614887Schin return(nv_name(nv_refnode(np))); 24624887Schin } 24638462SApril.Chin@Sun.COM if(np->nvfun && np->nvfun->disc) 24644887Schin { 24654887Schin if(!nv_local) 24664887Schin { 24674887Schin nv_local=1; 24684887Schin return(nv_getv(np, np->nvfun)); 24694887Schin } 24704887Schin nv_local=0; 24714887Schin } 24724887Schin numeric = ((nv_isattr (np, NV_INTEGER)) != 0); 24734887Schin if(numeric) 24744887Schin { 24754887Schin Sflong_t ll; 24764887Schin if(!up->cp) 24774887Schin return("0"); 24788462SApril.Chin@Sun.COM if(nv_isattr (np,NV_DOUBLE)==NV_DOUBLE) 24794887Schin { 24804887Schin Sfdouble_t ld; 24814887Schin double d; 24824887Schin char *format; 24834887Schin if(nv_isattr(np,NV_LONG)) 24844887Schin { 24854887Schin ld = *up->ldp; 24864887Schin if(nv_isattr (np,NV_EXPNOTE)) 24874887Schin format = "%.*Lg"; 24888462SApril.Chin@Sun.COM else if(nv_isattr (np,NV_HEXFLOAT)) 24898462SApril.Chin@Sun.COM format = "%.*La"; 24904887Schin else 24914887Schin format = "%.*Lf"; 24924887Schin sfprintf(sh.strbuf,format,nv_size(np),ld); 24934887Schin } 24944887Schin else 24954887Schin { 24964887Schin d = *up->dp; 24974887Schin if(nv_isattr (np,NV_EXPNOTE)) 24984887Schin format = "%.*g"; 24998462SApril.Chin@Sun.COM else if(nv_isattr (np,NV_HEXFLOAT)) 25008462SApril.Chin@Sun.COM format = "%.*a"; 25014887Schin else 25024887Schin format = "%.*f"; 25034887Schin sfprintf(sh.strbuf,format,nv_size(np),d); 25044887Schin } 25054887Schin return(sfstruse(sh.strbuf)); 25064887Schin } 25074887Schin else if(nv_isattr(np,NV_UNSIGN)) 25084887Schin { 25094887Schin if(nv_isattr (np,NV_LONG)) 25104887Schin ll = *(Sfulong_t*)up->llp; 25114887Schin else if(nv_isattr (np,NV_SHORT)) 25128462SApril.Chin@Sun.COM { 25138462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 25148462SApril.Chin@Sun.COM ll = *(uint16_t*)(up->sp); 25158462SApril.Chin@Sun.COM else 25168462SApril.Chin@Sun.COM ll = (uint16_t)up->s; 25178462SApril.Chin@Sun.COM } 25184887Schin else 25194887Schin ll = *(uint32_t*)(up->lp); 25204887Schin } 25214887Schin else if(nv_isattr (np,NV_LONG)) 25224887Schin ll = *up->llp; 25234887Schin else if(nv_isattr (np,NV_SHORT)) 25248462SApril.Chin@Sun.COM { 25258462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 25268462SApril.Chin@Sun.COM ll = *up->sp; 25278462SApril.Chin@Sun.COM else 25288462SApril.Chin@Sun.COM ll = up->s; 25298462SApril.Chin@Sun.COM } 25304887Schin else 25314887Schin ll = *(up->lp); 25324887Schin if((numeric=nv_size(np))==10) 25334887Schin { 25344887Schin if(nv_isattr(np,NV_UNSIGN)) 25354887Schin { 25364887Schin sfprintf(sh.strbuf,"%I*u",sizeof(ll),ll); 25374887Schin return(sfstruse(sh.strbuf)); 25384887Schin } 25394887Schin numeric = 0; 25404887Schin } 25414887Schin return(fmtbasell(ll,numeric, numeric&&numeric!=10)); 25424887Schin } 25434887Schin done: 25444887Schin #if (_AST_VERSION>=20030127L) 25454887Schin /* 25464887Schin * if NV_RAW flag is on, return pointer to binary data 25474887Schin * otherwise, base64 encode the data and return this string 25484887Schin */ 25494887Schin if(up->cp && nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW)) 25504887Schin { 25514887Schin char *cp; 2552*12068SRoger.Faulkner@Oracle.COM char *ep; 25534887Schin int size= nv_size(np), insize=(4*size)/3+size/45+8; 2554*12068SRoger.Faulkner@Oracle.COM base64encode(up->cp, size, (void**)0, cp=getbuf(insize), insize, (void**)&ep); 2555*12068SRoger.Faulkner@Oracle.COM *ep = 0; 25564887Schin return(cp); 25574887Schin } 25584887Schin #endif 25594887Schin if((numeric=nv_size(np)) && up->cp && up->cp[numeric]) 25604887Schin { 25614887Schin char *cp = getbuf(numeric+1); 25624887Schin memcpy(cp,up->cp,numeric); 25634887Schin cp[numeric]=0; 25644887Schin return(cp); 25654887Schin } 25664887Schin return ((char*)up->cp); 25674887Schin } 25684887Schin 25694887Schin Sfdouble_t nv_getnum(register Namval_t *np) 25704887Schin { 25714887Schin register union Value *up; 25724887Schin register Sfdouble_t r=0; 25734887Schin register char *str; 25744887Schin #if SHOPT_OPTIMIZE 25754887Schin if(!nv_local && sh.argaddr) 25764887Schin nv_optimize(np); 25774887Schin #endif /* SHOPT_OPTIMIZE */ 25784887Schin if(nv_istable(np)) 25794887Schin errormsg(SH_DICT,ERROR_exit(1),e_number,nv_name(np)); 25808462SApril.Chin@Sun.COM if(np->nvfun && np->nvfun->disc) 25814887Schin { 25824887Schin if(!nv_local) 25834887Schin { 25844887Schin nv_local=1; 25854887Schin return(nv_getn(np, np->nvfun)); 25864887Schin } 25874887Schin nv_local=0; 25884887Schin } 25898462SApril.Chin@Sun.COM if(nv_isref(np)) 25908462SApril.Chin@Sun.COM { 25918462SApril.Chin@Sun.COM str = nv_refsub(np); 25928462SApril.Chin@Sun.COM np = nv_refnode(np); 25938462SApril.Chin@Sun.COM if(str) 25948462SApril.Chin@Sun.COM nv_putsub(np,str,0L); 25958462SApril.Chin@Sun.COM } 25964887Schin if(nv_isattr (np, NV_INTEGER)) 25974887Schin { 25984887Schin up= &np->nvalue; 25998462SApril.Chin@Sun.COM if(!up->lp || up->cp==Empty) 26004887Schin r = 0; 26018462SApril.Chin@Sun.COM else if(nv_isattr(np, NV_DOUBLE)==NV_DOUBLE) 26024887Schin { 26034887Schin if(nv_isattr(np, NV_LONG)) 26044887Schin r = *up->ldp; 26054887Schin else 26064887Schin r = *up->dp; 26074887Schin } 26084887Schin else if(nv_isattr(np, NV_UNSIGN)) 26094887Schin { 26104887Schin if(nv_isattr(np, NV_LONG)) 26114887Schin r = (Sflong_t)*((Sfulong_t*)up->llp); 26124887Schin else if(nv_isattr(np, NV_SHORT)) 26138462SApril.Chin@Sun.COM { 26148462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 26158462SApril.Chin@Sun.COM r = (Sflong_t)(*(uint16_t*)up->sp); 26168462SApril.Chin@Sun.COM else 26178462SApril.Chin@Sun.COM r = (Sflong_t)((uint16_t)up->s); 26188462SApril.Chin@Sun.COM } 26194887Schin else 26204887Schin r = *((uint32_t*)up->lp); 26214887Schin } 26224887Schin else 26234887Schin { 26244887Schin if(nv_isattr(np, NV_LONG)) 26254887Schin r = *up->llp; 26264887Schin else if(nv_isattr(np, NV_SHORT)) 26278462SApril.Chin@Sun.COM { 26288462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 26298462SApril.Chin@Sun.COM r = *up->sp; 26308462SApril.Chin@Sun.COM else 26318462SApril.Chin@Sun.COM r = up->s; 26328462SApril.Chin@Sun.COM } 26334887Schin else 26344887Schin r = *up->lp; 26354887Schin } 26364887Schin } 26374887Schin else if((str=nv_getval(np)) && *str!=0) 26384887Schin { 26394887Schin if(np->nvfun || nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL)) 26404887Schin { 26414887Schin while(*str=='0') 26424887Schin str++; 26434887Schin } 26444887Schin r = sh_arith(str); 26454887Schin } 26464887Schin return(r); 26474887Schin } 26484887Schin /* 26494887Schin * Give <np> the attributes <newatts,> and change its current 26504887Schin * value to conform to <newatts>. The <size> of left and right 26514887Schin * justified fields may be given. 26524887Schin */ 26534887Schin void nv_newattr (register Namval_t *np, unsigned newatts, int size) 26544887Schin { 26554887Schin register char *sp; 26564887Schin register char *cp = 0; 26574887Schin register unsigned int n; 26584887Schin Namarr_t *ap = 0; 26594887Schin int oldsize,oldatts; 26608462SApril.Chin@Sun.COM Namfun_t *fp= (newatts&NV_NODISC)?np->nvfun:0; 266110898Sroland.mainz@nrubsig.org char *prefix = sh.prefix; 26628462SApril.Chin@Sun.COM newatts &= ~NV_NODISC; 26634887Schin 26644887Schin /* check for restrictions */ 26654887Schin if(sh_isoption(SH_RESTRICTED) && ((sp=nv_name(np))==nv_name(PATHNOD) || sp==nv_name(SHELLNOD) || sp==nv_name(ENVNOD) || sp==nv_name(FPATHNOD))) 26664887Schin errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np)); 26674887Schin /* handle attributes that do not change data separately */ 26684887Schin n = np->nvflag; 26694887Schin if(newatts&NV_EXPORT) 26704887Schin nv_offattr(np,NV_IMPORT); 26714887Schin if(((n^newatts)&NV_EXPORT)) 26724887Schin { 26734887Schin /* record changes to the environment */ 26744887Schin if(n&NV_EXPORT) 26754887Schin env_delete(sh.env,nv_name(np)); 26764887Schin else 26774887Schin sh_envput(sh.env,np); 26784887Schin } 267910898Sroland.mainz@nrubsig.org oldsize = nv_size(np); 268010898Sroland.mainz@nrubsig.org if((size==oldsize|| (n&NV_INTEGER)) && ((n^newatts)&~NV_NOCHANGE)==0) 26814887Schin { 26824887Schin if(size) 26834887Schin nv_setsize(np,size); 26844887Schin nv_offattr(np, ~NV_NOFREE); 26854887Schin nv_onattr(np, newatts); 26864887Schin return; 26874887Schin } 26884887Schin /* for an array, change all the elements */ 26894887Schin if((ap=nv_arrayptr(np)) && ap->nelem>0) 26904887Schin nv_putsub(np,NIL(char*),ARRAY_SCAN); 26914887Schin oldsize = nv_size(np); 26924887Schin oldatts = np->nvflag; 26938462SApril.Chin@Sun.COM if(fp) 26948462SApril.Chin@Sun.COM np->nvfun = 0; 26954887Schin if(ap) /* add element to prevent array deletion */ 26964887Schin ap->nelem++; 26974887Schin do 26984887Schin { 26994887Schin nv_setsize(np,oldsize); 27004887Schin np->nvflag = oldatts; 27014887Schin if (sp = nv_getval(np)) 27024887Schin { 27034887Schin if(nv_isattr(np,NV_ZFILL)) 27044887Schin while(*sp=='0') sp++; 27054887Schin cp = (char*)malloc((n=strlen (sp)) + 1); 27064887Schin strcpy(cp, sp); 27074887Schin if(ap) 27084887Schin { 27094887Schin Namval_t *mp; 27104887Schin ap->nelem &= ~ARRAY_SCAN; 27114887Schin if(mp=nv_opensub(np)) 27128462SApril.Chin@Sun.COM { 27138462SApril.Chin@Sun.COM nv_unset(mp); 27148462SApril.Chin@Sun.COM mp->nvalue.cp = Empty; 27158462SApril.Chin@Sun.COM } 27168462SApril.Chin@Sun.COM else 27178462SApril.Chin@Sun.COM nv_unset(np); 27188462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 27194887Schin } 27208462SApril.Chin@Sun.COM else 27218462SApril.Chin@Sun.COM nv_unset(np); 2722*12068SRoger.Faulkner@Oracle.COM if(size==0 && (newatts&NV_HOST)!=NV_HOST && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL))) 27234887Schin size = n; 27244887Schin } 27254887Schin else 27264887Schin nv_unset(np); 27274887Schin nv_setsize(np,size); 27284887Schin np->nvflag &= NV_ARRAY; 27294887Schin np->nvflag |= newatts; 27304887Schin if (cp) 27314887Schin { 27324887Schin nv_putval (np, cp, NV_RDONLY); 27334887Schin free(cp); 27344887Schin } 27354887Schin } 27364887Schin while(ap && nv_nextsub(np)); 27378462SApril.Chin@Sun.COM if(fp) 27388462SApril.Chin@Sun.COM np->nvfun = fp; 27394887Schin if(ap) 27404887Schin ap->nelem--; 274110898Sroland.mainz@nrubsig.org sh.prefix = prefix; 27424887Schin return; 27434887Schin } 27444887Schin 27454887Schin static char *oldgetenv(const char *string) 27464887Schin { 27474887Schin register char c0,c1; 27484887Schin register const char *cp, *sp; 27494887Schin register char **av = environ; 27504887Schin if(!string || (c0= *string)==0) 27514887Schin return(0); 27524887Schin if((c1=*++string)==0) 27534887Schin c1= '='; 27544887Schin while(cp = *av++) 27554887Schin { 27564887Schin if(cp[0]!=c0 || cp[1]!=c1) 27574887Schin continue; 27584887Schin sp = string; 27594887Schin while(*sp && *sp++ == *++cp); 27604887Schin if(*sp==0 && *++cp=='=') 27614887Schin return((char*)(cp+1)); 27624887Schin } 27634887Schin return(0); 27644887Schin } 27654887Schin 27664887Schin /* 27674887Schin * This version of getenv uses the hash storage to access environment values 27684887Schin */ 2769*12068SRoger.Faulkner@Oracle.COM char *sh_getenv(const char *name) 27704887Schin /*@ 27714887Schin assume name!=0; 27724887Schin @*/ 27734887Schin { 27744887Schin register Namval_t *np; 27754887Schin if(!sh.var_tree) 2776*12068SRoger.Faulkner@Oracle.COM { 2777*12068SRoger.Faulkner@Oracle.COM #if 0 2778*12068SRoger.Faulkner@Oracle.COM if(name[0] == 'P' && name[1] == 'A' && name[2] == 'T' && name[3] == 'H' && name[4] == 0 || name[0] == 'L' && ((name[1] == 'C' || name[1] == 'D') && name[2] == '_' || name[1] == 'A' && name[1] == 'N') || name[0] == 'V' && name[1] == 'P' && name[2] == 'A' && name[3] == 'T' && name[4] == 'H' && name[5] == 0 || name[0] == '_' && name[1] == 'R' && name[2] == 'L' && name[3] == 'D' || name[0] == '_' && name[1] == 'A' && name[2] == 'S' && name[3] == 'T' && name[4] == '_') 2779*12068SRoger.Faulkner@Oracle.COM #endif 2780*12068SRoger.Faulkner@Oracle.COM return(oldgetenv(name)); 2781*12068SRoger.Faulkner@Oracle.COM } 2782*12068SRoger.Faulkner@Oracle.COM else if((np = nv_search(name,sh.var_tree,0)) && nv_isattr(np,NV_EXPORT)) 27834887Schin return(nv_getval(np)); 27844887Schin return(0); 27854887Schin } 2786*12068SRoger.Faulkner@Oracle.COM 2787*12068SRoger.Faulkner@Oracle.COM #ifndef _NEXT_SOURCE 2788*12068SRoger.Faulkner@Oracle.COM /* 2789*12068SRoger.Faulkner@Oracle.COM * Some dynamic linkers will make this file see the libc getenv(), 2790*12068SRoger.Faulkner@Oracle.COM * so sh_getenv() is used for the astintercept() callback. Plain 2791*12068SRoger.Faulkner@Oracle.COM * getenv() is provided for static links. 2792*12068SRoger.Faulkner@Oracle.COM */ 2793*12068SRoger.Faulkner@Oracle.COM char *getenv(const char *name) 2794*12068SRoger.Faulkner@Oracle.COM { 2795*12068SRoger.Faulkner@Oracle.COM return sh_getenv(name); 2796*12068SRoger.Faulkner@Oracle.COM } 27974887Schin #endif /* _NEXT_SOURCE */ 27984887Schin 27994887Schin #undef putenv 28004887Schin /* 28014887Schin * This version of putenv uses the hash storage to assign environment values 28024887Schin */ 28034887Schin int putenv(const char *name) 28044887Schin { 28054887Schin register Namval_t *np; 28064887Schin if(name) 28074887Schin { 28084887Schin np = nv_open(name,sh.var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN); 28094887Schin if(!strchr(name,'=')) 28104887Schin nv_unset(np); 28114887Schin } 28124887Schin return(0); 28134887Schin } 28144887Schin 28154887Schin /* 2816*12068SRoger.Faulkner@Oracle.COM * Override libast setenviron(). 28174887Schin */ 2818*12068SRoger.Faulkner@Oracle.COM char* sh_setenviron(const char *name) 28194887Schin { 28204887Schin register Namval_t *np; 28214887Schin if(name) 28224887Schin { 28234887Schin np = nv_open(name,sh.var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN); 28244887Schin if(strchr(name,'=')) 28254887Schin return(nv_getval(np)); 28264887Schin nv_unset(np); 28274887Schin } 28284887Schin return(""); 28294887Schin } 28304887Schin 28314887Schin /* 2832*12068SRoger.Faulkner@Oracle.COM * Same linker dance as with getenv() above. 2833*12068SRoger.Faulkner@Oracle.COM */ 2834*12068SRoger.Faulkner@Oracle.COM char* setenviron(const char *name) 2835*12068SRoger.Faulkner@Oracle.COM { 2836*12068SRoger.Faulkner@Oracle.COM return sh_setenviron(name); 2837*12068SRoger.Faulkner@Oracle.COM } 2838*12068SRoger.Faulkner@Oracle.COM 2839*12068SRoger.Faulkner@Oracle.COM /* 28408462SApril.Chin@Sun.COM * convert <str> to upper case 28414887Schin */ 28428462SApril.Chin@Sun.COM static void ltou(register char *str) 28434887Schin { 28444887Schin register int c; 28458462SApril.Chin@Sun.COM for(; c= *((unsigned char*)str); str++) 28464887Schin { 28474887Schin if(islower(c)) 28488462SApril.Chin@Sun.COM *str = toupper(c); 28494887Schin } 28508462SApril.Chin@Sun.COM } 28518462SApril.Chin@Sun.COM 28528462SApril.Chin@Sun.COM /* 28538462SApril.Chin@Sun.COM * convert <str> to lower case 28548462SApril.Chin@Sun.COM */ 28558462SApril.Chin@Sun.COM static void utol(register char *str) 28568462SApril.Chin@Sun.COM { 28578462SApril.Chin@Sun.COM register int c; 28588462SApril.Chin@Sun.COM for(; c= *((unsigned char*)str); str++) 28598462SApril.Chin@Sun.COM { 28608462SApril.Chin@Sun.COM if(isupper(c)) 28618462SApril.Chin@Sun.COM *str = tolower(c); 28628462SApril.Chin@Sun.COM } 28634887Schin } 28644887Schin 28654887Schin /* 28664887Schin * normalize <cp> and return pointer to subscript if any 28678462SApril.Chin@Sun.COM * if <eq> is specified, return pointer to first = not in a subscript 28684887Schin */ 28698462SApril.Chin@Sun.COM static char *lastdot(register char *cp, int eq) 28704887Schin { 28718462SApril.Chin@Sun.COM register char *ep=0; 28724887Schin register int c; 28738462SApril.Chin@Sun.COM if(eq) 28748462SApril.Chin@Sun.COM cp++; 28754887Schin while(c= *cp++) 28764887Schin { 28774887Schin if(c=='[') 287810898Sroland.mainz@nrubsig.org { 287910898Sroland.mainz@nrubsig.org if(*cp==']') 288010898Sroland.mainz@nrubsig.org cp++; 288110898Sroland.mainz@nrubsig.org else 288210898Sroland.mainz@nrubsig.org cp = nv_endsubscript((Namval_t*)0,ep=cp,0); 288310898Sroland.mainz@nrubsig.org } 28844887Schin else if(c=='.') 28854887Schin { 28864887Schin if(*cp=='[') 288710898Sroland.mainz@nrubsig.org { 288810898Sroland.mainz@nrubsig.org cp = nv_endsubscript((Namval_t*)0,ep=cp,0); 288910898Sroland.mainz@nrubsig.org if((ep=sh_checkid(ep+1,cp)) < cp) 289010898Sroland.mainz@nrubsig.org cp=strcpy(ep,cp); 289110898Sroland.mainz@nrubsig.org } 28924887Schin ep = 0; 28934887Schin } 28948462SApril.Chin@Sun.COM else if(eq && c == '=') 28958462SApril.Chin@Sun.COM return(cp-1); 28964887Schin } 28978462SApril.Chin@Sun.COM return(eq?0:ep); 28988462SApril.Chin@Sun.COM } 28998462SApril.Chin@Sun.COM 29008462SApril.Chin@Sun.COM int nv_rename(register Namval_t *np, int flags) 29018462SApril.Chin@Sun.COM { 29028462SApril.Chin@Sun.COM Shell_t *shp = &sh; 29038462SApril.Chin@Sun.COM register Namval_t *mp=0,*nr=0; 29048462SApril.Chin@Sun.COM register char *cp; 29058462SApril.Chin@Sun.COM int index= -1; 29068462SApril.Chin@Sun.COM Namval_t *last_table = shp->last_table; 29078462SApril.Chin@Sun.COM Dt_t *last_root = shp->last_root; 29088462SApril.Chin@Sun.COM Dt_t *hp = 0; 290910898Sroland.mainz@nrubsig.org char *prefix=shp->prefix,*nvenv = 0; 29108462SApril.Chin@Sun.COM if(nv_isattr(np,NV_PARAM) && shp->st.prevst) 29118462SApril.Chin@Sun.COM { 29128462SApril.Chin@Sun.COM if(!(hp=(Dt_t*)shp->st.prevst->save_tree)) 29138462SApril.Chin@Sun.COM hp = dtvnext(shp->var_tree); 29148462SApril.Chin@Sun.COM } 29158462SApril.Chin@Sun.COM if(!(cp=nv_getval(np))) 29168462SApril.Chin@Sun.COM { 29178462SApril.Chin@Sun.COM if(flags&NV_MOVE) 29188462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_varname,""); 29198462SApril.Chin@Sun.COM return(0); 29208462SApril.Chin@Sun.COM } 29218462SApril.Chin@Sun.COM if(lastdot(cp,0) && nv_isattr(np,NV_MINIMAL)) 29228462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_varname,nv_name(np)); 29238462SApril.Chin@Sun.COM if(nv_isarray(np) && !(mp=nv_opensub(np))) 29248462SApril.Chin@Sun.COM index=nv_aindex(np); 292510898Sroland.mainz@nrubsig.org shp->prefix = 0; 29268462SApril.Chin@Sun.COM if(!hp) 29278462SApril.Chin@Sun.COM hp = shp->var_tree; 29288462SApril.Chin@Sun.COM if(!(nr = nv_open(cp, hp, flags|NV_ARRAY|NV_NOREF|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))) 29298462SApril.Chin@Sun.COM hp = shp->var_base; 29308462SApril.Chin@Sun.COM else if(shp->last_root) 29318462SApril.Chin@Sun.COM hp = shp->last_root; 29328462SApril.Chin@Sun.COM if(!nr) 29338462SApril.Chin@Sun.COM nr= nv_open(cp, hp, flags|NV_NOREF|((flags&NV_MOVE)?0:NV_NOFAIL)); 293410898Sroland.mainz@nrubsig.org shp->prefix = prefix; 29358462SApril.Chin@Sun.COM if(!nr) 29368462SApril.Chin@Sun.COM { 29378462SApril.Chin@Sun.COM if(!nv_isvtree(np)) 29388462SApril.Chin@Sun.COM _nv_unset(np,0); 29398462SApril.Chin@Sun.COM return(0); 29408462SApril.Chin@Sun.COM } 29418462SApril.Chin@Sun.COM if(!mp && index>=0 && nv_isvtree(nr)) 29428462SApril.Chin@Sun.COM { 29438462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"%s[%d]%c",nv_name(np),index,0); 29448462SApril.Chin@Sun.COM /* create a virtual node */ 29458462SApril.Chin@Sun.COM if(mp = nv_open(sfstruse(shp->strbuf),shp->var_tree,NV_VARNAME|NV_ADD|NV_ARRAY)) 29468462SApril.Chin@Sun.COM mp->nvenv = (void*)np; 29478462SApril.Chin@Sun.COM } 29488462SApril.Chin@Sun.COM if(mp) 294910898Sroland.mainz@nrubsig.org { 295010898Sroland.mainz@nrubsig.org nvenv = (char*)np; 29518462SApril.Chin@Sun.COM np = mp; 295210898Sroland.mainz@nrubsig.org } 29538462SApril.Chin@Sun.COM if(nr==np) 29548462SApril.Chin@Sun.COM { 29558462SApril.Chin@Sun.COM if(index<0) 29568462SApril.Chin@Sun.COM return(0); 29578462SApril.Chin@Sun.COM if(cp = nv_getval(np)) 29588462SApril.Chin@Sun.COM cp = strdup(cp); 29598462SApril.Chin@Sun.COM } 29608462SApril.Chin@Sun.COM _nv_unset(np,0); 296110898Sroland.mainz@nrubsig.org if(!nv_isattr(np,NV_MINIMAL)) 296210898Sroland.mainz@nrubsig.org np->nvenv = nvenv; 29638462SApril.Chin@Sun.COM if(nr==np) 29648462SApril.Chin@Sun.COM { 29658462SApril.Chin@Sun.COM nv_putsub(np,(char*)0, index); 29668462SApril.Chin@Sun.COM nv_putval(np,cp,0); 29678462SApril.Chin@Sun.COM free((void*)cp); 29688462SApril.Chin@Sun.COM return(1); 29698462SApril.Chin@Sun.COM } 29708462SApril.Chin@Sun.COM shp->prev_table = shp->last_table; 29718462SApril.Chin@Sun.COM shp->prev_root = shp->last_root; 29728462SApril.Chin@Sun.COM shp->last_table = last_table; 29738462SApril.Chin@Sun.COM shp->last_root = last_root; 29748462SApril.Chin@Sun.COM nv_clone(nr,np,(flags&NV_MOVE)|NV_COMVAR); 29758462SApril.Chin@Sun.COM if(flags&NV_MOVE) 29768462SApril.Chin@Sun.COM nv_delete(nr,(Dt_t*)0,NV_NOFREE); 29778462SApril.Chin@Sun.COM return(1); 29784887Schin } 29794887Schin 29804887Schin /* 29814887Schin * Create a reference node from <np> to $np in dictionary <hp> 29824887Schin */ 29834887Schin void nv_setref(register Namval_t *np, Dt_t *hp, int flags) 29844887Schin { 29858462SApril.Chin@Sun.COM Shell_t *shp = &sh; 29868462SApril.Chin@Sun.COM register Namval_t *nq, *nr=0; 298710898Sroland.mainz@nrubsig.org register char *ep,*cp; 298810898Sroland.mainz@nrubsig.org Dt_t *root = shp->last_root; 298910898Sroland.mainz@nrubsig.org Namarr_t *ap; 29904887Schin if(nv_isref(np)) 29914887Schin return; 29924887Schin if(nv_isarray(np)) 29934887Schin errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np)); 29944887Schin if(!(cp=nv_getval(np))) 29958462SApril.Chin@Sun.COM { 29968462SApril.Chin@Sun.COM nv_unset(np); 29978462SApril.Chin@Sun.COM nv_onattr(np,NV_REF); 29988462SApril.Chin@Sun.COM return; 29998462SApril.Chin@Sun.COM } 30008462SApril.Chin@Sun.COM if((ep = lastdot(cp,0)) && nv_isattr(np,NV_MINIMAL)) 30014887Schin errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np)); 30024887Schin if(!hp) 30038462SApril.Chin@Sun.COM hp = shp->var_tree; 30048462SApril.Chin@Sun.COM if(!(nr = nq = nv_open(cp, hp, flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))) 300510898Sroland.mainz@nrubsig.org hp = shp->last_root==shp->var_tree?shp->var_tree:shp->var_base; 30068462SApril.Chin@Sun.COM else if(shp->last_root) 30078462SApril.Chin@Sun.COM hp = shp->last_root; 30088462SApril.Chin@Sun.COM if(nq && ep && nv_isarray(nq) && !nv_getsub(nq)) 30098462SApril.Chin@Sun.COM nv_endsubscript(nq,ep-1,NV_ADD); 30108462SApril.Chin@Sun.COM if(!nr) 301110898Sroland.mainz@nrubsig.org { 30128462SApril.Chin@Sun.COM nr= nq = nv_open(cp, hp, flags); 301310898Sroland.mainz@nrubsig.org hp = shp->last_root; 301410898Sroland.mainz@nrubsig.org } 301510898Sroland.mainz@nrubsig.org if(shp->last_root == shp->var_tree && root!=shp->var_tree) 301610898Sroland.mainz@nrubsig.org { 301710898Sroland.mainz@nrubsig.org _nv_unset(np,NV_RDONLY); 301810898Sroland.mainz@nrubsig.org nv_onattr(np,NV_REF); 301910898Sroland.mainz@nrubsig.org errormsg(SH_DICT,ERROR_exit(1),e_globalref,nv_name(np)); 302010898Sroland.mainz@nrubsig.org } 30214887Schin if(nr==np) 30224887Schin { 30238462SApril.Chin@Sun.COM if(shp->namespace && nv_dict(shp->namespace)==hp) 30244887Schin errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np)); 30254887Schin /* bind to earlier scope, or add to global scope */ 30264887Schin if(!(hp=dtvnext(hp)) || (nq=nv_search((char*)np,hp,NV_ADD|HASH_BUCKET))==np) 30274887Schin errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np)); 30284887Schin } 302910898Sroland.mainz@nrubsig.org if(nq && !ep && (ap=nv_arrayptr(nq)) && !(ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN))) 303010898Sroland.mainz@nrubsig.org ep = nv_getsub(nq); 30314887Schin if(ep) 30324887Schin { 30334887Schin /* cause subscript evaluation and return result */ 30348462SApril.Chin@Sun.COM if(nv_isarray(nq)) 30358462SApril.Chin@Sun.COM ep = nv_getsub(nq); 30368462SApril.Chin@Sun.COM else 30378462SApril.Chin@Sun.COM { 30388462SApril.Chin@Sun.COM ep[strlen(ep)-1] = 0; 30398462SApril.Chin@Sun.COM nv_putsub(nr, ep, 0); 30408462SApril.Chin@Sun.COM ep[strlen(ep)-1] = ']'; 30418462SApril.Chin@Sun.COM if(nq = nv_opensub(nr)) 30428462SApril.Chin@Sun.COM ep = 0; 30438462SApril.Chin@Sun.COM else 30448462SApril.Chin@Sun.COM nq = nr; 30458462SApril.Chin@Sun.COM } 30464887Schin } 30474887Schin nv_unset(np); 30488462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 30494887Schin np->nvalue.nrp = newof(0,struct Namref,1,0); 30504887Schin np->nvalue.nrp->np = nq; 30514887Schin np->nvalue.nrp->root = hp; 30524887Schin if(ep) 30534887Schin np->nvalue.nrp->sub = strdup(ep); 30548462SApril.Chin@Sun.COM np->nvalue.nrp->table = shp->last_table; 30554887Schin nv_onattr(np,NV_REF|NV_NOFREE); 30564887Schin } 30574887Schin 30584887Schin /* 30594887Schin * get the scope corresponding to <index> 30604887Schin * whence uses the same values as lseeek() 30614887Schin */ 30624887Schin Shscope_t *sh_getscope(int index, int whence) 30634887Schin { 30644887Schin register struct sh_scoped *sp, *topmost; 30654887Schin if(whence==SEEK_CUR) 30664887Schin sp = &sh.st; 30674887Schin else 30684887Schin { 30694887Schin if ((struct sh_scoped*)sh.topscope != sh.st.self) 30704887Schin topmost = (struct sh_scoped*)sh.topscope; 30714887Schin else 30724887Schin topmost = &(sh.st); 30734887Schin sp = topmost; 30744887Schin if(whence==SEEK_SET) 30754887Schin { 30764887Schin int n =0; 30774887Schin while(sp = sp->prevst) 30784887Schin n++; 30794887Schin index = n - index; 30804887Schin sp = topmost; 30814887Schin } 30824887Schin } 30834887Schin if(index < 0) 30844887Schin return((Shscope_t*)0); 30854887Schin while(index-- && (sp = sp->prevst)); 30864887Schin return((Shscope_t*)sp); 30874887Schin } 30884887Schin 30894887Schin /* 30904887Schin * make <scoped> the top scope and return previous scope 30914887Schin */ 30924887Schin Shscope_t *sh_setscope(Shscope_t *scope) 30934887Schin { 30944887Schin Shscope_t *old = (Shscope_t*)sh.st.self; 30954887Schin *sh.st.self = sh.st; 30964887Schin sh.st = *((struct sh_scoped*)scope); 30974887Schin sh.var_tree = scope->var_tree; 30988462SApril.Chin@Sun.COM SH_PATHNAMENOD->nvalue.cp = sh.st.filename; 30998462SApril.Chin@Sun.COM SH_FUNNAMENOD->nvalue.cp = sh.st.funname; 31004887Schin return(old); 31014887Schin } 31024887Schin 31038462SApril.Chin@Sun.COM void sh_unscope(Shell_t *shp) 31044887Schin { 31058462SApril.Chin@Sun.COM register Dt_t *root = shp->var_tree; 31064887Schin register Dt_t *dp = dtview(root,(Dt_t*)0); 31078462SApril.Chin@Sun.COM table_unset(shp,root,NV_RDONLY|NV_NOSCOPE,dp); 31088462SApril.Chin@Sun.COM if(shp->st.real_fun && dp==shp->st.real_fun->sdict) 31098462SApril.Chin@Sun.COM { 31108462SApril.Chin@Sun.COM dp = dtview(dp,(Dt_t*)0); 31118462SApril.Chin@Sun.COM shp->st.real_fun->sdict->view = dp; 31128462SApril.Chin@Sun.COM } 31138462SApril.Chin@Sun.COM shp->var_tree=dp; 31144887Schin dtclose(root); 31154887Schin } 31164887Schin 31174887Schin /* 31184887Schin * The inverse of creating a reference node 31194887Schin */ 31204887Schin void nv_unref(register Namval_t *np) 31214887Schin { 31224887Schin Namval_t *nq; 31234887Schin if(!nv_isref(np)) 31244887Schin return; 312510898Sroland.mainz@nrubsig.org nv_offattr(np,NV_NOFREE|NV_REF); 312610898Sroland.mainz@nrubsig.org if(!np->nvalue.nrp) 312710898Sroland.mainz@nrubsig.org return; 31284887Schin nq = nv_refnode(np); 31294887Schin free((void*)np->nvalue.nrp); 31304887Schin np->nvalue.cp = strdup(nv_name(nq)); 31314887Schin #if SHOPT_OPTIMIZE 31324887Schin { 31334887Schin Namfun_t *fp; 31344887Schin for(fp=nq->nvfun; fp; fp = fp->next) 31354887Schin { 31364887Schin if(fp->disc== &optimize_disc) 31374887Schin { 31384887Schin optimize_clear(nq,fp); 31394887Schin return; 31404887Schin } 31414887Schin } 31424887Schin } 31434887Schin #endif 31444887Schin } 31454887Schin 31464887Schin /* 31474887Schin * These following are for binary compatibility with the old hash library 31484887Schin * They will be removed someday 31494887Schin */ 31504887Schin 31514887Schin #if defined(__IMPORT__) && defined(__EXPORT__) 31524887Schin # define extern __EXPORT__ 31534887Schin #endif 31544887Schin 31554887Schin #undef hashscope 31564887Schin 31574887Schin extern Dt_t *hashscope(Dt_t *root) 31584887Schin { 31594887Schin return(dtvnext(root)); 31604887Schin } 31614887Schin 31624887Schin #undef hashfree 31634887Schin 31644887Schin extern Dt_t *hashfree(Dt_t *root) 31654887Schin { 31664887Schin Dt_t *dp = dtvnext(root); 31674887Schin dtclose(root); 31684887Schin return(dp); 31694887Schin } 31704887Schin 31714887Schin #undef hashname 31724887Schin 31734887Schin extern char *hashname(void *obj) 31744887Schin { 31754887Schin Namval_t *np = (Namval_t*)obj; 31764887Schin return(np->nvname); 31774887Schin } 31784887Schin 31794887Schin #undef hashlook 31804887Schin 31814887Schin extern void *hashlook(Dt_t *root, const char *name, int mode,int size) 31824887Schin { 31834887Schin NOT_USED(size); 31844887Schin return((void*)nv_search(name,root,mode)); 31854887Schin } 31864887Schin 31874887Schin char *nv_name(register Namval_t *np) 31884887Schin { 31894887Schin register Namval_t *table; 31904887Schin register Namfun_t *fp; 31914887Schin char *cp; 31924887Schin if(is_abuiltin(np) || is_afunction(np)) 31934887Schin return(np->nvname); 31948462SApril.Chin@Sun.COM if(!nv_isattr(np,NV_MINIMAL|NV_EXPORT) && np->nvenv) 31958462SApril.Chin@Sun.COM { 31968462SApril.Chin@Sun.COM Namval_t *nq= sh.last_table, *mp= (Namval_t*)np->nvenv; 31978462SApril.Chin@Sun.COM if(np==sh.last_table) 31988462SApril.Chin@Sun.COM sh.last_table = 0; 31998462SApril.Chin@Sun.COM if(nv_isarray(mp)) 32008462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s[%s]",nv_name(mp),np->nvname); 32018462SApril.Chin@Sun.COM else 32028462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s.%s",nv_name(mp),np->nvname); 32038462SApril.Chin@Sun.COM sh.last_table = nq; 32048462SApril.Chin@Sun.COM return(sfstruse(sh.strbuf)); 32058462SApril.Chin@Sun.COM } 32064887Schin if(nv_istable(np)) 32074887Schin #if 1 32084887Schin sh.last_table = nv_parent(np); 32094887Schin #else 32104887Schin sh.last_table = nv_create(np,0, NV_LAST,(Namfun_t*)0); 32114887Schin #endif 32124887Schin else if(!nv_isref(np)) 32134887Schin { 32144887Schin for(fp= np->nvfun ; fp; fp=fp->next) 32154887Schin if(fp->disc && fp->disc->namef) 32164887Schin { 32174887Schin if(np==sh.last_table) 32184887Schin sh.last_table = 0; 32194887Schin return((*fp->disc->namef)(np,fp)); 32204887Schin } 32214887Schin } 32224887Schin if(!(table=sh.last_table) || *np->nvname=='.' || table==sh.namespace || np==table) 32234887Schin return(np->nvname); 32244887Schin cp = nv_name(table); 32254887Schin sfprintf(sh.strbuf,"%s.%s",cp,np->nvname); 32264887Schin return(sfstruse(sh.strbuf)); 32274887Schin } 32284887Schin 32294887Schin Namval_t *nv_lastdict(void) 32304887Schin { 32314887Schin return(sh.last_table); 32324887Schin } 32334887Schin 32344887Schin #undef nv_context 32354887Schin /* 32364887Schin * returns the data context for a builtin 32374887Schin */ 32384887Schin void *nv_context(Namval_t *np) 32394887Schin { 32404887Schin return((void*)np->nvfun); 32414887Schin } 32424887Schin 32434887Schin #define DISABLE /* proto workaround */ 32444887Schin 32454887Schin int nv_isnull DISABLE (register Namval_t *np) 32464887Schin { 32474887Schin return(nv_isnull(np)); 32484887Schin } 32494887Schin 32504887Schin #undef nv_setsize 32514887Schin int nv_setsize(register Namval_t *np, int size) 32524887Schin { 32534887Schin int oldsize = nv_size(np); 32544887Schin if(size>=0) 32554887Schin np->nvsize = size; 32564887Schin return(oldsize); 32574887Schin } 32588462SApril.Chin@Sun.COM 32598462SApril.Chin@Sun.COM Shell_t *nv_shell(Namval_t *np) 32608462SApril.Chin@Sun.COM { 32618462SApril.Chin@Sun.COM Namfun_t *fp; 32628462SApril.Chin@Sun.COM for(fp=np->nvfun;fp;fp=fp->next) 32638462SApril.Chin@Sun.COM { 32648462SApril.Chin@Sun.COM if(!fp->disc) 32658462SApril.Chin@Sun.COM return((Shell_t*)fp->last); 32668462SApril.Chin@Sun.COM } 32678462SApril.Chin@Sun.COM return(0); 32688462SApril.Chin@Sun.COM } 32698462SApril.Chin@Sun.COM 32708462SApril.Chin@Sun.COM #undef nv_unset 32718462SApril.Chin@Sun.COM 32728462SApril.Chin@Sun.COM void nv_unset(register Namval_t *np) 32738462SApril.Chin@Sun.COM { 32748462SApril.Chin@Sun.COM _nv_unset(np,0); 32758462SApril.Chin@Sun.COM return; 32768462SApril.Chin@Sun.COM } 3277