14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1982-2009 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 564887Schin static void pushnam(Namval_t*,void*); 574887Schin 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; 90*10898Sroland.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 */ 286*10898Sroland.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; 343*10898Sroland.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]=='[') 344*10898Sroland.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); 364*10898Sroland.mainz@nrubsig.org if(typ && !array && (nv_isnull(np) || nv_isarray(np))) 365*10898Sroland.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 */ 372*10898Sroland.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 } 384*10898Sroland.mainz@nrubsig.org } 385*10898Sroland.mainz@nrubsig.org if(array && tp->tre.tretyp!=TLST && !tp->com.comset && !tp->com.comarg) 386*10898Sroland.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 } 453*10898Sroland.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; 505*10898Sroland.mainz@nrubsig.org if(shp->prefix) 506*10898Sroland.mainz@nrubsig.org { 507*10898Sroland.mainz@nrubsig.org if(*shp->prefix=='_' && shp->prefix[1]=='.' && nv_isref(L_ARGNOD)) 508*10898Sroland.mainz@nrubsig.org { 509*10898Sroland.mainz@nrubsig.org sfprintf(stkstd,"%s%s",nv_name(L_ARGNOD->nvalue.nrp->np),shp->prefix+1); 510*10898Sroland.mainz@nrubsig.org shp->prefix = stkfreeze(stkstd,1); 511*10898Sroland.mainz@nrubsig.org } 512*10898Sroland.mainz@nrubsig.org memset(&nr,0,sizeof(nr)); 513*10898Sroland.mainz@nrubsig.org memcpy(&node,L_ARGNOD,sizeof(node)); 514*10898Sroland.mainz@nrubsig.org L_ARGNOD->nvalue.nrp = &nr; 515*10898Sroland.mainz@nrubsig.org nr.np = np; 516*10898Sroland.mainz@nrubsig.org nr.root = shp->last_root; 517*10898Sroland.mainz@nrubsig.org nr.table = shp->last_table; 518*10898Sroland.mainz@nrubsig.org L_ARGNOD->nvflag = NV_REF|NV_NOFREE; 519*10898Sroland.mainz@nrubsig.org L_ARGNOD->nvfun = 0; 520*10898Sroland.mainz@nrubsig.org } 5214887Schin sh_exec(tp,sh_isstate(SH_ERREXIT)); 5228462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 523*10898Sroland.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 } 540*10898Sroland.mainz@nrubsig.org if(!nv_isarray(np) && !typ && (tp->com.comarg || !tp->com.comset || tp->com.comset->argval[0]!='[')) 5418462SApril.Chin@Sun.COM nv_setvtree(np); 5428462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 5438462SApril.Chin@Sun.COM goto check_type; 5448462SApril.Chin@Sun.COM #else 5454887Schin continue; 5468462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 5474887Schin } 5484887Schin cp = arg->argval; 5498462SApril.Chin@Sun.COM mp = 0; 5504887Schin } 5518462SApril.Chin@Sun.COM np = nv_open(cp,shp->var_tree,flags); 5528462SApril.Chin@Sun.COM if(!np->nvfun && (flags&NV_NOREF)) 5534887Schin { 5548462SApril.Chin@Sun.COM if(shp->used_pos) 5554887Schin nv_onattr(np,NV_PARAM); 5564887Schin else 5574887Schin nv_offattr(np,NV_PARAM); 5584887Schin } 5594887Schin if(traceon || trap) 5604887Schin { 5614887Schin register char *sp=cp; 5624887Schin char *name=nv_name(np); 5634887Schin char *sub=0; 5644887Schin int append = 0; 5654887Schin if(nv_isarray(np)) 5664887Schin sub = savesub; 5678462SApril.Chin@Sun.COM if(cp=lastdot(sp,'=')) 5684887Schin { 5694887Schin if(cp[-1]=='+') 5704887Schin append = ARG_APPEND; 5714887Schin cp++; 5724887Schin } 5734887Schin if(traceon) 5744887Schin { 5754887Schin sh_trace(NIL(char**),0); 5764887Schin nv_outname(sfstderr,name,-1); 5774887Schin if(sub) 5784887Schin sfprintf(sfstderr,"[%s]",sh_fmtq(sub)); 5794887Schin if(cp) 5804887Schin { 5814887Schin if(append) 5824887Schin sfputc(sfstderr,'+'); 5834887Schin sfprintf(sfstderr,"=%s\n",sh_fmtq(cp)); 5844887Schin } 5854887Schin } 5864887Schin if(trap) 5874887Schin { 5884887Schin char *av[2]; 5894887Schin av[0] = cp; 5904887Schin av[1] = 0; 5918462SApril.Chin@Sun.COM sh_debug(shp,trap,name,sub,av,append); 5924887Schin } 5934887Schin } 5948462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 5958462SApril.Chin@Sun.COM check_type: 5968462SApril.Chin@Sun.COM if(maketype) 5978462SApril.Chin@Sun.COM { 5988462SApril.Chin@Sun.COM nv_open(shtp.nodes[0]->nvname,shp->var_tree,NV_ASSIGN|NV_VARNAME|NV_NOADD|NV_NOFAIL); 5998462SApril.Chin@Sun.COM np = nv_mktype(shtp.nodes,shtp.numnodes); 6008462SApril.Chin@Sun.COM free((void*)shtp.nodes); 6018462SApril.Chin@Sun.COM shp->mktype = shtp.previous; 6028462SApril.Chin@Sun.COM maketype = 0; 6038462SApril.Chin@Sun.COM shp->prefix = 0; 6048462SApril.Chin@Sun.COM if(nr.np == np) 6058462SApril.Chin@Sun.COM { 6068462SApril.Chin@Sun.COM L_ARGNOD->nvalue.nrp = node.nvalue.nrp; 6078462SApril.Chin@Sun.COM L_ARGNOD->nvflag = node.nvflag; 6088462SApril.Chin@Sun.COM L_ARGNOD->nvfun = node.nvfun; 6098462SApril.Chin@Sun.COM } 6108462SApril.Chin@Sun.COM } 6118462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 6124887Schin } 6134887Schin } 6144887Schin 6154887Schin /* 6164887Schin * copy the subscript onto the stack 6174887Schin */ 6184887Schin static void stak_subscript(const char *sub, int last) 6194887Schin { 6204887Schin register int c; 6214887Schin stakputc('['); 6224887Schin while(c= *sub++) 6234887Schin { 6244887Schin if(c=='[' || c==']' || c=='\\') 6254887Schin stakputc('\\'); 6264887Schin stakputc(c); 6274887Schin } 6284887Schin stakputc(last); 6294887Schin } 6304887Schin 6314887Schin /* 6324887Schin * construct a new name from a prefix and base name on the stack 6334887Schin */ 6344887Schin static char *copystack(const char *prefix, register const char *name, const char *sub) 6354887Schin { 6364887Schin register int last=0,offset = staktell(); 6374887Schin if(prefix) 6384887Schin { 6394887Schin stakputs(prefix); 6404887Schin if(*stakptr(staktell()-1)=='.') 6414887Schin stakseek(staktell()-1); 6424887Schin if(*name=='.' && name[1]=='[') 6434887Schin last = staktell()+2; 6448462SApril.Chin@Sun.COM if(*name!='[' && *name!='.' && *name!='=' && *name!='+') 6458462SApril.Chin@Sun.COM stakputc('.'); 6468462SApril.Chin@Sun.COM if(*name=='.' && (name[1]=='=' || name[1]==0)) 6474887Schin stakputc('.'); 6484887Schin } 6494887Schin if(last) 6504887Schin { 6514887Schin stakputs(name); 6524887Schin if(sh_checkid(stakptr(last),(char*)0)) 6534887Schin stakseek(staktell()-2); 6544887Schin } 6554887Schin if(sub) 6564887Schin stak_subscript(sub,']'); 6574887Schin if(!last) 6584887Schin stakputs(name); 6594887Schin stakputc(0); 6604887Schin return(stakptr(offset)); 6614887Schin } 6624887Schin 6634887Schin /* 6644887Schin * grow this stack string <name> by <n> bytes and move from cp-1 to end 6654887Schin * right by <n>. Returns beginning of string on the stack 6664887Schin */ 6674887Schin static char *stack_extend(const char *cname, char *cp, int n) 6684887Schin { 6694887Schin register char *name = (char*)cname; 6704887Schin int offset = name - stakptr(0); 6714887Schin int m = cp-name; 6724887Schin stakseek(strlen(name)+n+1); 6734887Schin name = stakptr(offset); 6744887Schin cp = name + m; 6754887Schin m = strlen(cp)+1; 6764887Schin while(m-->0) 6774887Schin cp[n+m]=cp[m]; 6784887Schin return((char*)name); 6794887Schin } 6804887Schin 6818462SApril.Chin@Sun.COM Namval_t *nv_create(const char *name, Dt_t *root, int flags, Namfun_t *dp) 6824887Schin { 6838462SApril.Chin@Sun.COM Shell_t *shp = &sh; 6844887Schin char *cp=(char*)name, *sp, *xp; 6854887Schin register int c; 6864887Schin register Namval_t *np=0, *nq=0; 6874887Schin Namfun_t *fp=0; 6884887Schin long mode, add=0; 6894887Schin int copy=1,isref,top=0,noscope=(flags&NV_NOSCOPE); 6908462SApril.Chin@Sun.COM if(root==shp->var_tree) 6914887Schin { 6924887Schin if(dtvnext(root)) 6934887Schin top = 1; 6944887Schin else 6954887Schin flags &= ~NV_NOSCOPE; 6964887Schin } 6974887Schin if(!dp->disc) 6988462SApril.Chin@Sun.COM copy = dp->nofree&1; 6994887Schin if(*cp=='.') 7004887Schin cp++; 7014887Schin while(1) 7024887Schin { 7034887Schin switch(c = *(unsigned char*)(sp = cp)) 7044887Schin { 7054887Schin case '[': 7064887Schin if(flags&NV_NOARRAY) 7074887Schin { 7084887Schin dp->last = cp; 7094887Schin return(np); 7104887Schin } 7114887Schin cp = nv_endsubscript((Namval_t*)0,sp,0); 7124887Schin if(sp==name || sp[-1]=='.') 7134887Schin c = *(sp = cp); 7144887Schin goto skip; 7154887Schin case '.': 7164887Schin if(flags&NV_IDENT) 7174887Schin return(0); 7188462SApril.Chin@Sun.COM if(root==shp->var_tree) 7194887Schin flags &= ~NV_EXPORT; 7204887Schin if(!copy && !(flags&NV_NOREF)) 7214887Schin { 7224887Schin c = sp-name; 7234887Schin copy = cp-name; 7248462SApril.Chin@Sun.COM dp->nofree |= 1; 7254887Schin name = copystack((const char*)0, name,(const char*)0); 7264887Schin cp = (char*)name+copy; 7274887Schin sp = (char*)name+c; 7284887Schin c = '.'; 7294887Schin } 7304887Schin skip: 7314887Schin case '+': 7324887Schin case '=': 7334887Schin *sp = 0; 7344887Schin case 0: 7354887Schin isref = 0; 7364887Schin dp->last = cp; 7374887Schin mode = (c=='.' || (flags&NV_NOADD))?add:NV_ADD; 7388462SApril.Chin@Sun.COM if((flags&NV_NOSCOPE) && c!='.') 7394887Schin mode |= HASH_NOSCOPE; 7408462SApril.Chin@Sun.COM np=0; 7414887Schin if(top) 7428462SApril.Chin@Sun.COM { 7438462SApril.Chin@Sun.COM struct Ufunction *rp; 7448462SApril.Chin@Sun.COM if((rp=shp->st.real_fun) && !rp->sdict && (flags&NV_STATIC)) 7458462SApril.Chin@Sun.COM { 7468462SApril.Chin@Sun.COM Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0); 7478462SApril.Chin@Sun.COM rp->sdict = dtopen(&_Nvdisc,Dtoset); 7488462SApril.Chin@Sun.COM dtview(rp->sdict,shp->var_base); 7498462SApril.Chin@Sun.COM dtview(shp->var_tree,rp->sdict); 7508462SApril.Chin@Sun.COM } 7518462SApril.Chin@Sun.COM if(np = nv_search(name,shp->var_tree,0)) 7528462SApril.Chin@Sun.COM { 7538462SApril.Chin@Sun.COM if(shp->var_tree->walk == shp->var_base) 7548462SApril.Chin@Sun.COM { 7558462SApril.Chin@Sun.COM nq = np; 7568462SApril.Chin@Sun.COM if(flags&NV_NOSCOPE) 7578462SApril.Chin@Sun.COM { 7588462SApril.Chin@Sun.COM if(mode==0) 7598462SApril.Chin@Sun.COM root = shp->var_base; 7608462SApril.Chin@Sun.COM else 7618462SApril.Chin@Sun.COM { 7628462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 7638462SApril.Chin@Sun.COM np = 0; 7648462SApril.Chin@Sun.COM } 7658462SApril.Chin@Sun.COM } 7668462SApril.Chin@Sun.COM } 7678462SApril.Chin@Sun.COM else 7688462SApril.Chin@Sun.COM { 7698462SApril.Chin@Sun.COM root = shp->var_tree->walk; 7708462SApril.Chin@Sun.COM flags |= NV_NOSCOPE; 7718462SApril.Chin@Sun.COM noscope = 1; 7728462SApril.Chin@Sun.COM } 7738462SApril.Chin@Sun.COM } 7748462SApril.Chin@Sun.COM if(rp && rp->sdict && (flags&NV_STATIC)) 7758462SApril.Chin@Sun.COM { 7768462SApril.Chin@Sun.COM root = rp->sdict; 7778462SApril.Chin@Sun.COM if(np && shp->var_tree->walk==shp->var_tree) 7788462SApril.Chin@Sun.COM { 7798462SApril.Chin@Sun.COM _nv_unset(np,0); 7808462SApril.Chin@Sun.COM nv_delete(np,shp->var_tree,0); 7818462SApril.Chin@Sun.COM np = 0; 7828462SApril.Chin@Sun.COM } 7838462SApril.Chin@Sun.COM if(!np || shp->var_tree->walk!=root) 7848462SApril.Chin@Sun.COM np = nv_search(name,root,HASH_NOSCOPE|NV_ADD); 7858462SApril.Chin@Sun.COM } 7868462SApril.Chin@Sun.COM } 7878462SApril.Chin@Sun.COM if(np || (np = nv_search(name,root,mode))) 7884887Schin { 7894887Schin isref = nv_isref(np); 7904887Schin if(top) 7914887Schin { 7924887Schin if(nq==np) 793*10898Sroland.mainz@nrubsig.org { 7944887Schin flags &= ~NV_NOSCOPE; 795*10898Sroland.mainz@nrubsig.org root = shp->var_base; 796*10898Sroland.mainz@nrubsig.org } 7974887Schin else if(nq) 7984887Schin { 7994887Schin if(nv_isnull(np) && c!='.' && (np->nvfun=nv_cover(nq))) 8004887Schin np->nvname = nq->nvname; 8014887Schin flags |= NV_NOSCOPE; 8024887Schin } 8034887Schin } 8048462SApril.Chin@Sun.COM else if(add && nv_isnull(np) && c=='.' && cp[1]!='.') 8054887Schin nv_setvtree(np); 8064887Schin } 8074887Schin if(c) 8084887Schin *sp = c; 8094887Schin top = 0; 8104887Schin if(isref) 8114887Schin { 8124887Schin char *sub=0; 8138462SApril.Chin@Sun.COM #if NVCACHE 8148462SApril.Chin@Sun.COM nvcache.ok = 0; 8158462SApril.Chin@Sun.COM #endif 8164887Schin if(c=='.') /* don't optimize */ 8178462SApril.Chin@Sun.COM shp->argaddr = 0; 818*10898Sroland.mainz@nrubsig.org else if((flags&NV_NOREF) && (c!='[' && *cp!='.')) 8194887Schin { 8208462SApril.Chin@Sun.COM if(c && !(flags&NV_NOADD)) 8214887Schin nv_unref(np); 8224887Schin return(np); 8234887Schin } 8248462SApril.Chin@Sun.COM while(nv_isref(np) && np->nvalue.cp) 8254887Schin { 8264887Schin root = nv_reftree(np); 8278462SApril.Chin@Sun.COM shp->last_root = root; 8288462SApril.Chin@Sun.COM shp->last_table = nv_reftable(np); 8294887Schin sub = nv_refsub(np); 8304887Schin np = nv_refnode(np); 8314887Schin if(sub && c!='.') 8324887Schin nv_putsub(np,sub,0L); 8334887Schin flags |= NV_NOSCOPE; 8348462SApril.Chin@Sun.COM noscope = 1; 8354887Schin } 8368462SApril.Chin@Sun.COM if(nv_isref(np) && (c=='[' || c=='.' || !(flags&NV_ASSIGN))) 8378462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_noref,nv_name(np)); 8384887Schin if(sub && c==0) 8394887Schin return(np); 8404887Schin if(np==nq) 8414887Schin flags &= ~(noscope?0:NV_NOSCOPE); 8424887Schin else if(c) 8434887Schin { 8444887Schin c = (cp-sp); 8454887Schin copy = strlen(cp=nv_name(np)); 8468462SApril.Chin@Sun.COM dp->nofree |= 1; 8474887Schin name = copystack(cp,sp,sub); 8484887Schin sp = (char*)name + copy; 8494887Schin cp = sp+c; 8504887Schin c = *sp; 8514887Schin if(!noscope) 8524887Schin flags &= ~NV_NOSCOPE; 8534887Schin } 8544887Schin flags |= NV_NOREF; 855*10898Sroland.mainz@nrubsig.org if(nv_isnull(np)) 856*10898Sroland.mainz@nrubsig.org nv_onattr(np,NV_NOFREE); 857*10898Sroland.mainz@nrubsig.org 8584887Schin } 8598462SApril.Chin@Sun.COM shp->last_root = root; 8608462SApril.Chin@Sun.COM if(cp[1]=='.') 8618462SApril.Chin@Sun.COM cp++; 8628462SApril.Chin@Sun.COM if(c=='.' && (cp[1]==0 || cp[1]=='=' || cp[1]=='+')) 8638462SApril.Chin@Sun.COM { 8648462SApril.Chin@Sun.COM nv_local = 1; 8658462SApril.Chin@Sun.COM return(np); 8668462SApril.Chin@Sun.COM } 8678462SApril.Chin@Sun.COM if(cp[-1]=='.') 8688462SApril.Chin@Sun.COM cp--; 8694887Schin do 8704887Schin { 8714887Schin if(!np) 8724887Schin { 8738462SApril.Chin@Sun.COM if(!nq && *sp=='[' && *cp==0 && cp[-1]==']') 8744887Schin { 8754887Schin /* 8764887Schin * for backward compatibility 8774887Schin * evaluate subscript for 8784887Schin * possible side effects 8794887Schin */ 8804887Schin cp[-1] = 0; 8814887Schin sh_arith(sp+1); 8824887Schin cp[-1] = ']'; 8834887Schin } 8844887Schin return(np); 8854887Schin } 8864887Schin if(c=='[' || (c=='.' && nv_isarray(np))) 8874887Schin { 8888462SApril.Chin@Sun.COM char *sub=0; 8894887Schin int n = 0; 890*10898Sroland.mainz@nrubsig.org mode &= ~HASH_NOSCOPE; 8914887Schin if(c=='[') 8924887Schin { 893*10898Sroland.mainz@nrubsig.org #if 0 894*10898Sroland.mainz@nrubsig.org Namarr_t *ap = nv_arrayptr(np); 895*10898Sroland.mainz@nrubsig.org int scan = ap?(ap->nelem&ARRAY_SCAN):0; 896*10898Sroland.mainz@nrubsig.org #endif 8974887Schin n = mode|nv_isarray(np); 8984887Schin if(!mode && (flags&NV_ARRAY) && ((c=sp[1])=='*' || c=='@') && sp[2]==']') 8994887Schin { 9004887Schin /* not implemented yet */ 9014887Schin dp->last = cp; 9024887Schin return(np); 9034887Schin } 9048462SApril.Chin@Sun.COM if((n&NV_ADD)&&(flags&NV_ARRAY)) 9054887Schin n |= ARRAY_FILL; 9068462SApril.Chin@Sun.COM if(flags&NV_ASSIGN) 9078462SApril.Chin@Sun.COM n |= NV_ADD; 9088462SApril.Chin@Sun.COM cp = nv_endsubscript(np,sp,n|(flags&NV_ASSIGN)); 909*10898Sroland.mainz@nrubsig.org #if 0 910*10898Sroland.mainz@nrubsig.org if(scan) 911*10898Sroland.mainz@nrubsig.org nv_putsub(np,NIL(char*),ARRAY_SCAN); 912*10898Sroland.mainz@nrubsig.org #endif 9134887Schin } 9144887Schin else 9154887Schin cp = sp; 9168462SApril.Chin@Sun.COM if((c = *cp)=='.' || (c=='[' && nv_isarray(np)) || (n&ARRAY_FILL) || (flags&NV_ARRAY)) 9174887Schin 9184887Schin { 9194887Schin int m = cp-sp; 9208462SApril.Chin@Sun.COM sub = m?nv_getsub(np):0; 9214887Schin if(!sub) 9228462SApril.Chin@Sun.COM { 9238462SApril.Chin@Sun.COM if(m && !(n&NV_ADD)) 9248462SApril.Chin@Sun.COM return(0); 9254887Schin sub = "0"; 9268462SApril.Chin@Sun.COM } 9274887Schin n = strlen(sub)+2; 9284887Schin if(!copy) 9294887Schin { 9304887Schin copy = cp-name; 9318462SApril.Chin@Sun.COM dp->nofree |= 1; 9324887Schin name = copystack((const char*)0, name,(const char*)0); 9334887Schin cp = (char*)name+copy; 9344887Schin sp = cp-m; 9354887Schin } 9364887Schin if(n <= m) 9374887Schin { 9384887Schin if(n) 9394887Schin { 9404887Schin memcpy(sp+1,sub,n-2); 9414887Schin sp[n-1] = ']'; 9424887Schin } 9434887Schin if(n < m) 9444887Schin cp=strcpy(sp+n,cp); 9454887Schin } 9464887Schin else 9474887Schin { 9484887Schin int r = n-m; 9494887Schin m = sp-name; 9504887Schin name = stack_extend(name, cp-1, r); 9514887Schin sp = (char*)name + m; 9524887Schin *sp = '['; 9534887Schin memcpy(sp+1,sub,n-2); 9544887Schin sp[n-1] = ']'; 9554887Schin cp = sp+n; 9564887Schin 9574887Schin } 9584887Schin } 9594887Schin else if(c==0 && mode && (n=nv_aindex(np))>0) 9608462SApril.Chin@Sun.COM nv_putsub(np,(char*)0,n); 9618462SApril.Chin@Sun.COM else if(n==0 && (c==0 || (c=='[' && !nv_isarray(np)))) 9624887Schin { 9634887Schin /* subscript must be 0*/ 9644887Schin cp[-1] = 0; 9658462SApril.Chin@Sun.COM n = sh_arith(sp+1); 9664887Schin cp[-1] = ']'; 9678462SApril.Chin@Sun.COM if(n) 9688462SApril.Chin@Sun.COM return(0); 9694887Schin if(c) 9708462SApril.Chin@Sun.COM sp = cp; 9714887Schin } 9724887Schin dp->last = cp; 9734887Schin if(nv_isarray(np) && (c=='[' || c=='.' || (flags&NV_ARRAY))) 9744887Schin { 9758462SApril.Chin@Sun.COM sp = cp; 9768462SApril.Chin@Sun.COM if(!(nq = nv_opensub(np))) 9778462SApril.Chin@Sun.COM { 9788462SApril.Chin@Sun.COM Namarr_t *ap = nv_arrayptr(np); 9798462SApril.Chin@Sun.COM if(!sub && (flags&NV_NOADD)) 9808462SApril.Chin@Sun.COM return(0); 9818462SApril.Chin@Sun.COM n = mode|((flags&NV_NOADD)?0:NV_ADD); 9828462SApril.Chin@Sun.COM if(!ap && (n&NV_ADD)) 9838462SApril.Chin@Sun.COM { 9848462SApril.Chin@Sun.COM nv_putsub(np,sub,ARRAY_FILL); 9858462SApril.Chin@Sun.COM ap = nv_arrayptr(np); 9868462SApril.Chin@Sun.COM } 9878462SApril.Chin@Sun.COM if(n && ap && !ap->table) 9888462SApril.Chin@Sun.COM ap->table = dtopen(&_Nvdisc,Dtoset); 9898462SApril.Chin@Sun.COM if(ap && ap->table && (nq=nv_search(sub,ap->table,n))) 9908462SApril.Chin@Sun.COM nq->nvenv = (char*)np; 9918462SApril.Chin@Sun.COM if(nq && nv_isnull(nq)) 9928462SApril.Chin@Sun.COM nq = nv_arraychild(np,nq,c); 9938462SApril.Chin@Sun.COM } 9948462SApril.Chin@Sun.COM if(nq) 9958462SApril.Chin@Sun.COM { 9968462SApril.Chin@Sun.COM if(c=='.' && !nv_isvtree(nq)) 9978462SApril.Chin@Sun.COM { 9988462SApril.Chin@Sun.COM if(flags&NV_NOADD) 9998462SApril.Chin@Sun.COM return(0); 10008462SApril.Chin@Sun.COM nv_setvtree(nq); 10018462SApril.Chin@Sun.COM } 10028462SApril.Chin@Sun.COM np = nq; 10038462SApril.Chin@Sun.COM } 10048462SApril.Chin@Sun.COM else if(memcmp(cp,"[0]",3)) 10058462SApril.Chin@Sun.COM return(nq); 10068462SApril.Chin@Sun.COM else 10078462SApril.Chin@Sun.COM { 10088462SApril.Chin@Sun.COM /* ignore [0] */ 10098462SApril.Chin@Sun.COM dp->last = cp += 3; 10108462SApril.Chin@Sun.COM c = *cp; 10118462SApril.Chin@Sun.COM } 10124887Schin } 10134887Schin } 10144887Schin else if(nv_isarray(np)) 10158462SApril.Chin@Sun.COM { 10168462SApril.Chin@Sun.COM if(c==0 && (flags&NV_MOVE)) 10178462SApril.Chin@Sun.COM return(np); 10184887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 10198462SApril.Chin@Sun.COM } 10204887Schin if(c=='.' && (fp=np->nvfun)) 10214887Schin { 10224887Schin for(; fp; fp=fp->next) 10234887Schin { 10244887Schin if(fp->disc && fp->disc->createf) 10254887Schin break; 10264887Schin } 10274887Schin if(fp) 10284887Schin { 10294887Schin if((nq = (*fp->disc->createf)(np,cp+1,flags,fp)) == np) 10304887Schin { 10314887Schin add = NV_ADD; 1032*10898Sroland.mainz@nrubsig.org shp->last_table = 0; 10334887Schin break; 10344887Schin } 10358462SApril.Chin@Sun.COM else if(np=nq) 10368462SApril.Chin@Sun.COM { 10378462SApril.Chin@Sun.COM if((c = *(sp=cp=dp->last=fp->last))==0) 10388462SApril.Chin@Sun.COM { 10398462SApril.Chin@Sun.COM if(nv_isarray(np) && sp[-1]!=']') 10408462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),ARRAY_UNDEF); 10418462SApril.Chin@Sun.COM return(np); 10428462SApril.Chin@Sun.COM } 10438462SApril.Chin@Sun.COM } 10444887Schin } 10454887Schin } 10464887Schin } 10474887Schin while(c=='['); 10488462SApril.Chin@Sun.COM if(c!='.' || cp[1]=='.') 10494887Schin return(np); 10504887Schin cp++; 10514887Schin break; 10524887Schin default: 10534887Schin dp->last = cp; 10544887Schin if((c = mbchar(cp)) && !isaletter(c)) 10554887Schin return(np); 10564887Schin while(xp=cp, c=mbchar(cp), isaname(c)); 10574887Schin cp = xp; 10584887Schin } 10594887Schin } 10604887Schin return(np); 10614887Schin } 10624887Schin 10634887Schin /* 10648462SApril.Chin@Sun.COM * delete the node <np> from the dictionary <root> and clear from the cache 10658462SApril.Chin@Sun.COM * if <root> is NULL, only the cache is cleared 10668462SApril.Chin@Sun.COM * if flags does not contain NV_NOFREE, the node is freed 10678462SApril.Chin@Sun.COM */ 10688462SApril.Chin@Sun.COM void nv_delete(Namval_t* np, Dt_t *root, int flags) 10698462SApril.Chin@Sun.COM { 10708462SApril.Chin@Sun.COM #if NVCACHE 10718462SApril.Chin@Sun.COM register int c; 10728462SApril.Chin@Sun.COM struct Cache_entry *xp; 10738462SApril.Chin@Sun.COM for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c]) 10748462SApril.Chin@Sun.COM { 10758462SApril.Chin@Sun.COM if(xp->np==np) 10768462SApril.Chin@Sun.COM xp->root = 0; 10778462SApril.Chin@Sun.COM } 10788462SApril.Chin@Sun.COM #endif 10798462SApril.Chin@Sun.COM if(root) 10808462SApril.Chin@Sun.COM { 10818462SApril.Chin@Sun.COM if(dtdelete(root,np)) 10828462SApril.Chin@Sun.COM { 10838462SApril.Chin@Sun.COM if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np))) 10848462SApril.Chin@Sun.COM free((void*)np); 10858462SApril.Chin@Sun.COM } 10868462SApril.Chin@Sun.COM #if 0 10878462SApril.Chin@Sun.COM else 10888462SApril.Chin@Sun.COM { 10898462SApril.Chin@Sun.COM sfprintf(sfstderr,"%s not deleted\n",nv_name(np)); 10908462SApril.Chin@Sun.COM sfsync(sfstderr); 10918462SApril.Chin@Sun.COM } 10928462SApril.Chin@Sun.COM #endif 10938462SApril.Chin@Sun.COM } 10948462SApril.Chin@Sun.COM } 10958462SApril.Chin@Sun.COM 10968462SApril.Chin@Sun.COM /* 10974887Schin * Put <arg> into associative memory. 10984887Schin * If <flags> & NV_ARRAY then follow array to next subscript 10994887Schin * If <flags> & NV_NOARRAY then subscript is not allowed 11004887Schin * If <flags> & NV_NOSCOPE then use the current scope only 11014887Schin * If <flags> & NV_ASSIGN then assignment is allowed 11024887Schin * If <flags> & NV_IDENT then name must be an identifier 11034887Schin * If <flags> & NV_VARNAME then name must be a valid variable name 11044887Schin * If <flags> & NV_NOADD then node will not be added if not found 11054887Schin * If <flags> & NV_NOREF then don't follow reference 11064887Schin * If <flags> & NV_NOFAIL then don't generate an error message on failure 11078462SApril.Chin@Sun.COM * If <flags> & NV_STATIC then unset before an assignment 1108*10898Sroland.mainz@nrubsig.org * If <flags> & NV_UNJUST then unset attributes before assignment 11094887Schin * SH_INIT is only set while initializing the environment 11104887Schin */ 11114887Schin Namval_t *nv_open(const char *name, Dt_t *root, int flags) 11124887Schin { 11138462SApril.Chin@Sun.COM Shell_t *shp = &sh; 11144887Schin register char *cp=(char*)name; 11154887Schin register int c; 11164887Schin register Namval_t *np; 11174887Schin Namfun_t fun; 11184887Schin int append=0; 11194887Schin const char *msg = e_varname; 11204887Schin char *fname = 0; 11214887Schin int offset = staktell(); 11224887Schin Dt_t *funroot; 11238462SApril.Chin@Sun.COM #if NVCACHE 11248462SApril.Chin@Sun.COM struct Cache_entry *xp; 11258462SApril.Chin@Sun.COM #endif 11268462SApril.Chin@Sun.COM 11278462SApril.Chin@Sun.COM sh_stats(STAT_NVOPEN); 11284887Schin memset(&fun,0,sizeof(fun)); 11298462SApril.Chin@Sun.COM shp->last_table = shp->namespace; 11304887Schin if(!root) 11318462SApril.Chin@Sun.COM root = shp->var_tree; 11328462SApril.Chin@Sun.COM shp->last_root = root; 11338462SApril.Chin@Sun.COM if(root==shp->fun_tree) 11344887Schin { 11354887Schin flags |= NV_NOREF; 11364887Schin msg = e_badfun; 11378462SApril.Chin@Sun.COM if((np=shp->namespace) || strchr(name,'.')) 11384887Schin { 11394887Schin name = cp = copystack(np?nv_name(np):0,name,(const char*)0); 11404887Schin fname = strrchr(cp,'.'); 11414887Schin *fname = 0; 11428462SApril.Chin@Sun.COM fun.nofree |= 1; 11434887Schin flags &= ~NV_IDENT; 11444887Schin funroot = root; 11458462SApril.Chin@Sun.COM root = shp->var_tree; 11464887Schin } 11474887Schin } 11484887Schin else if(!(flags&(NV_IDENT|NV_VARNAME|NV_ASSIGN))) 11494887Schin { 11504887Schin long mode = ((flags&NV_NOADD)?0:NV_ADD); 11514887Schin if(flags&NV_NOSCOPE) 11524887Schin mode |= HASH_SCOPE|HASH_NOSCOPE; 11534887Schin np = nv_search(name,root,mode); 11544887Schin if(np && !(flags&NV_REF)) 11554887Schin { 11564887Schin while(nv_isref(np)) 11574887Schin { 11588462SApril.Chin@Sun.COM shp->last_table = nv_reftable(np); 11594887Schin np = nv_refnode(np); 11604887Schin } 11614887Schin } 11624887Schin return(np); 11634887Schin } 11648462SApril.Chin@Sun.COM else if(shp->prefix && (flags&NV_ASSIGN)) 11654887Schin { 11668462SApril.Chin@Sun.COM name = cp = copystack(shp->prefix,name,(const char*)0); 11678462SApril.Chin@Sun.COM fun.nofree |= 1; 11684887Schin } 11694887Schin c = *(unsigned char*)cp; 11708462SApril.Chin@Sun.COM if(root==shp->alias_tree) 11714887Schin { 11724887Schin msg = e_aliname; 11734887Schin while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') && 11748462SApril.Chin@Sun.COM (c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON)); 11758462SApril.Chin@Sun.COM if(shp->subshell && c=='=') 11764887Schin root = sh_subaliastree(1); 11774887Schin if(c= *--cp) 11784887Schin *cp = 0; 11794887Schin np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD); 11804887Schin if(c) 11814887Schin *cp = c; 11824887Schin goto skip; 11834887Schin } 11844887Schin else if(flags&NV_IDENT) 11854887Schin msg = e_ident; 11864887Schin else if(c=='.') 11874887Schin { 11884887Schin c = *++cp; 11894887Schin flags |= NV_NOREF; 11908462SApril.Chin@Sun.COM if(root==shp->var_tree) 11918462SApril.Chin@Sun.COM root = shp->var_base; 11928462SApril.Chin@Sun.COM shp->last_table = 0; 11934887Schin } 11944887Schin if(c= !isaletter(c)) 11954887Schin goto skip; 11968462SApril.Chin@Sun.COM #if NVCACHE 11978462SApril.Chin@Sun.COM for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c]) 11988462SApril.Chin@Sun.COM { 11998462SApril.Chin@Sun.COM if(xp->root!=root) 12008462SApril.Chin@Sun.COM continue; 12018462SApril.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]=='+')) 12028462SApril.Chin@Sun.COM { 12038462SApril.Chin@Sun.COM sh_stats(STAT_NVHITS); 12048462SApril.Chin@Sun.COM np = xp->np; 12058462SApril.Chin@Sun.COM cp = (char*)name+xp->len; 12068462SApril.Chin@Sun.COM if(nv_isarray(np)) 12078462SApril.Chin@Sun.COM nv_putsub(np,NIL(char*),ARRAY_UNDEF); 12088462SApril.Chin@Sun.COM shp->last_table = xp->last_table; 1209*10898Sroland.mainz@nrubsig.org shp->last_root = xp->last_root; 12108462SApril.Chin@Sun.COM goto nocache; 12118462SApril.Chin@Sun.COM } 12128462SApril.Chin@Sun.COM } 12138462SApril.Chin@Sun.COM nvcache.ok = 1; 12148462SApril.Chin@Sun.COM #endif 12154887Schin np = nv_create(name, root, flags, &fun); 12164887Schin cp = fun.last; 12178462SApril.Chin@Sun.COM #if NVCACHE 12188462SApril.Chin@Sun.COM if(np && nvcache.ok && cp[-1]!=']') 12198462SApril.Chin@Sun.COM { 12208462SApril.Chin@Sun.COM xp = &nvcache.entries[nvcache.index]; 12218462SApril.Chin@Sun.COM if(*cp) 12228462SApril.Chin@Sun.COM { 12238462SApril.Chin@Sun.COM char *sp = strchr(name,*cp); 12248462SApril.Chin@Sun.COM if(!sp) 12258462SApril.Chin@Sun.COM goto nocache; 12268462SApril.Chin@Sun.COM xp->len = sp-name; 12278462SApril.Chin@Sun.COM } 12288462SApril.Chin@Sun.COM else 12298462SApril.Chin@Sun.COM xp->len = strlen(name); 12308462SApril.Chin@Sun.COM c = roundof(xp->len+1,32); 12318462SApril.Chin@Sun.COM if(c > xp->size) 12328462SApril.Chin@Sun.COM { 12338462SApril.Chin@Sun.COM if(xp->size==0) 12348462SApril.Chin@Sun.COM xp->name = malloc(c); 12358462SApril.Chin@Sun.COM else 12368462SApril.Chin@Sun.COM xp->name = realloc(xp->name,c); 12378462SApril.Chin@Sun.COM xp->size = c; 12388462SApril.Chin@Sun.COM } 12398462SApril.Chin@Sun.COM memcpy(xp->name,name,xp->len); 12408462SApril.Chin@Sun.COM xp->name[xp->len] = 0; 12418462SApril.Chin@Sun.COM xp->root = root; 12428462SApril.Chin@Sun.COM xp->np = np; 12438462SApril.Chin@Sun.COM xp->last_table = shp->last_table; 1244*10898Sroland.mainz@nrubsig.org xp->last_root = shp->last_root; 12458462SApril.Chin@Sun.COM xp->flags = (flags&(NV_ARRAY|NV_NOSCOPE)); 12468462SApril.Chin@Sun.COM nvcache.index = (nvcache.index+1)&(NVCACHE-1); 12478462SApril.Chin@Sun.COM } 12488462SApril.Chin@Sun.COM nocache: 12498462SApril.Chin@Sun.COM nvcache.ok = 0; 12508462SApril.Chin@Sun.COM #endif 12514887Schin if(fname) 12524887Schin { 12534887Schin c = ((flags&NV_NOSCOPE)?HASH_NOSCOPE:0)|((flags&NV_NOADD)?0:NV_ADD); 12544887Schin *fname = '.'; 12554887Schin np = nv_search(name, funroot, c); 12564887Schin *fname = 0; 12574887Schin } 12588462SApril.Chin@Sun.COM else 12594887Schin { 12608462SApril.Chin@Sun.COM if(*cp=='.' && cp[1]=='.') 12618462SApril.Chin@Sun.COM { 12628462SApril.Chin@Sun.COM append |= NV_NODISC; 12638462SApril.Chin@Sun.COM cp+=2; 12648462SApril.Chin@Sun.COM } 12658462SApril.Chin@Sun.COM if(*cp=='+' && cp[1]=='=') 12668462SApril.Chin@Sun.COM { 12678462SApril.Chin@Sun.COM append |= NV_APPEND; 12688462SApril.Chin@Sun.COM cp++; 12698462SApril.Chin@Sun.COM } 12704887Schin } 12714887Schin c = *cp; 12724887Schin skip: 12738462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 12748462SApril.Chin@Sun.COM if(np && shp->mktype) 12758462SApril.Chin@Sun.COM np = nv_addnode(np,0); 12768462SApril.Chin@Sun.COM #endif /* SHOPT_TYPEDEF */ 12774887Schin if(c=='=' && np && (flags&NV_ASSIGN)) 12784887Schin { 12794887Schin cp++; 12804887Schin if(sh_isstate(SH_INIT)) 12814887Schin { 12824887Schin nv_putval(np, cp, NV_RDONLY); 12834887Schin if(np==PWDNOD) 12844887Schin nv_onattr(np,NV_TAGGED); 12854887Schin } 12864887Schin else 12874887Schin { 12888462SApril.Chin@Sun.COM char *sub=0, *prefix= shp->prefix; 12898462SApril.Chin@Sun.COM int isref; 12908462SApril.Chin@Sun.COM shp->prefix = 0; 12918462SApril.Chin@Sun.COM if((flags&NV_STATIC) && !shp->mktype) 12928462SApril.Chin@Sun.COM { 12938462SApril.Chin@Sun.COM if(!nv_isnull(np)) 1294*10898Sroland.mainz@nrubsig.org { 1295*10898Sroland.mainz@nrubsig.org shp->prefix = prefix; 12968462SApril.Chin@Sun.COM return(np); 1297*10898Sroland.mainz@nrubsig.org } 12988462SApril.Chin@Sun.COM } 12998462SApril.Chin@Sun.COM isref = nv_isref(np); 13004887Schin if(sh_isoption(SH_XTRACE) && nv_isarray(np)) 13014887Schin sub = nv_getsub(np); 13024887Schin c = msg==e_aliname? 0: (append | (flags&NV_EXPORT)); 13038462SApril.Chin@Sun.COM if(isref) 13048462SApril.Chin@Sun.COM nv_offattr(np,NV_REF); 1305*10898Sroland.mainz@nrubsig.org if(!append && (flags&NV_UNJUST)) 1306*10898Sroland.mainz@nrubsig.org { 1307*10898Sroland.mainz@nrubsig.org nv_offattr(np,NV_LJUST|NV_RJUST|NV_ZFILL); 1308*10898Sroland.mainz@nrubsig.org np->nvsize = 0; 1309*10898Sroland.mainz@nrubsig.org } 13104887Schin nv_putval(np, cp, c); 13118462SApril.Chin@Sun.COM if(isref) 1312*10898Sroland.mainz@nrubsig.org { 1313*10898Sroland.mainz@nrubsig.org if(nv_search((char*)np,shp->var_base,HASH_BUCKET)) 1314*10898Sroland.mainz@nrubsig.org shp->last_root = shp->var_base; 13158462SApril.Chin@Sun.COM nv_setref(np,(Dt_t*)0,NV_VARNAME); 1316*10898Sroland.mainz@nrubsig.org } 13174887Schin savesub = sub; 13188462SApril.Chin@Sun.COM shp->prefix = prefix; 13194887Schin } 13204887Schin nv_onattr(np, flags&NV_ATTRIBUTES); 13214887Schin } 13224887Schin else if(c) 13234887Schin { 13244887Schin if(flags&NV_NOFAIL) 13254887Schin return(0); 13264887Schin if(c=='.') 13274887Schin msg = e_noparent; 13284887Schin else if(c=='[') 13294887Schin msg = e_noarray; 13304887Schin errormsg(SH_DICT,ERROR_exit(1),msg,name); 13314887Schin } 13328462SApril.Chin@Sun.COM if(fun.nofree&1) 13334887Schin stakseek(offset); 13344887Schin return(np); 13354887Schin } 13364887Schin 13374887Schin #if SHOPT_MULTIBYTE 13384887Schin static int ja_size(char*, int, int); 13394887Schin static void ja_restore(void); 13404887Schin static char *savep; 13414887Schin static char savechars[8+1]; 13424887Schin #endif /* SHOPT_MULTIBYTE */ 13434887Schin 13444887Schin /* 13454887Schin * put value <string> into name-value node <np>. 13464887Schin * If <np> is an array, then the element given by the 13474887Schin * current index is assigned to. 13484887Schin * If <flags> contains NV_RDONLY, readonly attribute is ignored 13494887Schin * If <flags> contains NV_INTEGER, string is a pointer to a number 13504887Schin * If <flags> contains NV_NOFREE, previous value is freed, and <string> 13514887Schin * becomes value of node and <flags> becomes attributes 13524887Schin */ 13534887Schin void nv_putval(register Namval_t *np, const char *string, int flags) 13544887Schin { 13554887Schin register const char *sp=string; 13564887Schin register union Value *up; 13574887Schin register char *cp; 13584887Schin register int size = 0; 13594887Schin register int dot; 13608462SApril.Chin@Sun.COM #ifdef _ENV_H 13614887Schin int was_local = nv_local; 13628462SApril.Chin@Sun.COM #endif 13638462SApril.Chin@Sun.COM union Value u; 13644887Schin if(!(flags&NV_RDONLY) && nv_isattr (np, NV_RDONLY)) 13654887Schin errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np)); 13664887Schin /* The following could cause the shell to fork if assignment 13674887Schin * would cause a side effect 13684887Schin */ 13694887Schin sh.argaddr = 0; 13704887Schin if(sh.subshell && !nv_local) 13714887Schin np = sh_assignok(np,1); 1372*10898Sroland.mainz@nrubsig.org if(np->nvfun && np->nvfun->disc && !(flags&NV_NODISC) && !nv_isref(np)) 13734887Schin { 13744887Schin /* This function contains disc */ 13754887Schin if(!nv_local) 13764887Schin { 13774887Schin nv_local=1; 13784887Schin nv_putv(np,sp,flags,np->nvfun); 13798462SApril.Chin@Sun.COM #ifdef _ENV_H 13804887Schin if(sp && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT))) 13814887Schin sh_envput(sh.env,np); 13828462SApril.Chin@Sun.COM #endif 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); 1434*10898Sroland.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); 1454*10898Sroland.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; 16428462SApril.Chin@Sun.COM if(nv_isattr(np,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 16834887Schin if(size==0 && nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL)) 16844887Schin nv_setsize(np,size=dot); 16854887Schin else if(size > dot) 16864887Schin dot = size; 16878462SApril.Chin@Sun.COM else if(nv_isattr(np,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'); 17124887Schin else if(nv_isattr(np, NV_RJUST)) 17134887Schin rightjust(cp,size,' '); 17144887Schin else if(nv_isattr(np, 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 } 17328462SApril.Chin@Sun.COM #ifdef _ENV_H 17334887Schin if(!was_local && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT))) 17344887Schin sh_envput(sh.env,np); 17358462SApril.Chin@Sun.COM #endif 17364887Schin return; 17374887Schin } 17384887Schin 17394887Schin /* 17404887Schin * 17414887Schin * Right-justify <str> so that it contains no more than 17424887Schin * <size> characters. If <str> contains fewer than <size> 17434887Schin * characters, left-pad with <fill>. Trailing blanks 17444887Schin * in <str> will be ignored. 17454887Schin * 17464887Schin * If the leftmost digit in <str> is not a digit, <fill> 17474887Schin * will default to a blank. 17484887Schin */ 17494887Schin static void rightjust(char *str, int size, int fill) 17504887Schin { 17514887Schin register int n; 17524887Schin register char *cp,*sp; 17534887Schin n = strlen(str); 17544887Schin 17554887Schin /* ignore trailing blanks */ 17564887Schin for(cp=str+n;n && *--cp == ' ';n--); 17574887Schin if (n == size) 17584887Schin return; 17594887Schin if(n > size) 17604887Schin { 17614887Schin *(str+n) = 0; 17624887Schin for (sp = str, cp = str+n-size; sp <= str+size; *sp++ = *cp++); 17634887Schin return; 17644887Schin } 17654887Schin else *(sp = str+size) = 0; 17664887Schin if (n == 0) 17674887Schin { 17684887Schin while (sp > str) 17694887Schin *--sp = ' '; 17704887Schin return; 17714887Schin } 17724887Schin while(n--) 17734887Schin { 17744887Schin sp--; 17754887Schin *sp = *cp--; 17764887Schin } 17774887Schin if(!isdigit(*str)) 17784887Schin fill = ' '; 17794887Schin while(sp>str) 17804887Schin *--sp = fill; 17814887Schin return; 17824887Schin } 17834887Schin 17844887Schin #if SHOPT_MULTIBYTE 17854887Schin /* 17864887Schin * handle left and right justified fields for multi-byte chars 17874887Schin * given physical size, return a logical size which reflects the 17884887Schin * screen width of multi-byte characters 17894887Schin * Multi-width characters replaced by spaces if they cross the boundary 17904887Schin * <type> is non-zero for right justified fields 17914887Schin */ 17924887Schin 17934887Schin static int ja_size(char *str,int size,int type) 17944887Schin { 17954887Schin register char *cp = str; 17964887Schin register int c, n=size; 17974887Schin register int outsize; 17984887Schin register char *oldcp=cp; 17994887Schin int oldn; 18004887Schin wchar_t w; 18014887Schin while(*cp) 18024887Schin { 18034887Schin oldn = n; 18044887Schin w = mbchar(cp); 18054887Schin outsize = mbwidth(w); 18064887Schin size -= outsize; 18074887Schin c = cp-oldcp; 18084887Schin n += (c-outsize); 18094887Schin oldcp = cp; 18104887Schin if(size<=0 && type==0) 18114887Schin break; 18124887Schin } 18134887Schin /* check for right justified fields that need truncating */ 18144887Schin if(size <0) 18154887Schin { 18164887Schin if(type==0) 18174887Schin { 18184887Schin /* left justified and character crosses field boundary */ 18194887Schin n = oldn; 18204887Schin /* save boundary char and replace with spaces */ 18214887Schin size = c; 18224887Schin savechars[size] = 0; 18234887Schin while(size--) 18244887Schin { 18254887Schin savechars[size] = cp[size]; 18264887Schin cp[size] = ' '; 18274887Schin } 18284887Schin savep = cp; 18294887Schin } 18304887Schin size = -size; 18314887Schin if(type) 18324887Schin n -= (ja_size(str,size,0)-size); 18334887Schin } 18344887Schin return(n); 18354887Schin } 18364887Schin 18374887Schin static void ja_restore(void) 18384887Schin { 18394887Schin register char *cp = savechars; 18404887Schin while(*cp) 18414887Schin *savep++ = *cp++; 18424887Schin savep = 0; 18434887Schin } 18444887Schin #endif /* SHOPT_MULTIBYTE */ 18454887Schin 18464887Schin #ifndef _ENV_H 18474887Schin static char *staknam(register Namval_t *np, char *value) 18484887Schin { 18494887Schin register char *p,*q; 18504887Schin q = stakalloc(strlen(nv_name(np))+(value?strlen(value):0)+2); 18514887Schin p=strcopy(q,nv_name(np)); 18524887Schin if(value) 18534887Schin { 18544887Schin *p++ = '='; 18554887Schin strcpy(p,value); 18564887Schin } 18574887Schin return(q); 18584887Schin } 18594887Schin #endif 18604887Schin 18614887Schin /* 18624887Schin * put the name and attribute into value of attributes variable 18634887Schin */ 18644887Schin #ifdef _ENV_H 18654887Schin static void attstore(register Namval_t *np, void *data) 18664887Schin { 18674887Schin register int flag, c = ' '; 18684887Schin NOT_USED(data); 18694887Schin if(!(nv_isattr(np,NV_EXPORT))) 18704887Schin return; 18714887Schin flag = nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER); 18724887Schin stakputc('='); 18738462SApril.Chin@Sun.COM if((flag&NV_DOUBLE) == NV_DOUBLE) 18744887Schin { 18754887Schin /* export doubles as integers for ksh88 compatibility */ 18768462SApril.Chin@Sun.COM stakputc(c+NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE))); 18774887Schin } 18784887Schin else 18794887Schin { 18804887Schin stakputc(c+flag); 18814887Schin if(flag&NV_INTEGER) 18824887Schin c += nv_size(np); 18834887Schin } 18844887Schin stakputc(c); 18854887Schin stakputs(nv_name(np)); 18864887Schin } 18874887Schin #else 18884887Schin static void attstore(register Namval_t *np, void *data) 18894887Schin { 18904887Schin register int flag = np->nvflag; 18914887Schin register struct adata *ap = (struct adata*)data; 18928462SApril.Chin@Sun.COM ap->sh = &sh; 18938462SApril.Chin@Sun.COM ap->tp = 0; 18944887Schin if(!(flag&NV_EXPORT) || (flag&NV_FUNCT)) 18954887Schin return; 18964887Schin flag &= (NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER); 18974887Schin *ap->attval++ = '='; 18988462SApril.Chin@Sun.COM if((flag&NV_DOUBLE) == NV_DOUBLE) 18994887Schin { 19004887Schin /* export doubles as integers for ksh88 compatibility */ 19018462SApril.Chin@Sun.COM *ap->attval++ = ' '+ NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE)); 19024887Schin *ap->attval = ' '; 19034887Schin } 19044887Schin else 19054887Schin { 19064887Schin *ap->attval++ = ' '+flag; 19074887Schin if(flag&NV_INTEGER) 19084887Schin *ap->attval = ' ' + nv_size(np); 19094887Schin else 19104887Schin *ap->attval = ' '; 19114887Schin } 19124887Schin ap->attval = strcopy(++ap->attval,nv_name(np)); 19134887Schin } 19144887Schin #endif 19154887Schin 19164887Schin #ifndef _ENV_H 19174887Schin static void pushnam(Namval_t *np, void *data) 19184887Schin { 19194887Schin register char *value; 19204887Schin register struct adata *ap = (struct adata*)data; 19218462SApril.Chin@Sun.COM ap->sh = &sh; 19228462SApril.Chin@Sun.COM ap->tp = 0; 19234887Schin if(nv_isattr(np,NV_IMPORT)) 19244887Schin { 19254887Schin if(np->nvenv) 19264887Schin *ap->argnam++ = np->nvenv; 19274887Schin } 19284887Schin else if(value=nv_getval(np)) 19294887Schin *ap->argnam++ = staknam(np,value); 19304887Schin if(nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)) 19314887Schin ap->attsize += (strlen(nv_name(np))+4); 19324887Schin } 19334887Schin #endif 19344887Schin 19354887Schin /* 19364887Schin * Generate the environment list for the child. 19374887Schin */ 19384887Schin 19394887Schin #ifdef _ENV_H 19404887Schin char **sh_envgen(void) 19414887Schin { 19424887Schin int offset,tell; 19434887Schin register char **er; 19444887Schin env_delete(sh.env,"_"); 19454887Schin er = env_get(sh.env); 19464887Schin offset = staktell(); 19474887Schin stakputs(e_envmarker); 19484887Schin tell = staktell(); 19494887Schin nv_scan(sh.var_tree, attstore,(void*)0,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)); 19504887Schin if(tell ==staktell()) 19514887Schin stakseek(offset); 19524887Schin else 19534887Schin *--er = stakfreeze(1)+offset; 19544887Schin return(er); 19554887Schin } 19564887Schin #else 19574887Schin char **sh_envgen(void) 19584887Schin { 19594887Schin register char **er; 19604887Schin register int namec; 19614887Schin register char *cp; 19624887Schin struct adata data; 19638462SApril.Chin@Sun.COM Shell_t *shp = sh_getinterp(); 19648462SApril.Chin@Sun.COM data.sh = shp; 19658462SApril.Chin@Sun.COM data.tp = 0; 19664887Schin /* L_ARGNOD gets generated automatically as full path name of command */ 19674887Schin nv_offattr(L_ARGNOD,NV_EXPORT); 19684887Schin data.attsize = 6; 19698462SApril.Chin@Sun.COM namec = nv_scan(shp->var_tree,nullscan,(void*)0,NV_EXPORT,NV_EXPORT); 19708462SApril.Chin@Sun.COM namec += shp->nenv; 19714887Schin er = (char**)stakalloc((namec+4)*sizeof(char*)); 19728462SApril.Chin@Sun.COM data.argnam = (er+=2) + shp->nenv; 19738462SApril.Chin@Sun.COM if(shp->nenv) 19748462SApril.Chin@Sun.COM memcpy((void*)er,environ,shp->nenv*sizeof(char*)); 19758462SApril.Chin@Sun.COM nv_scan(shp->var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT); 19764887Schin *data.argnam = (char*)stakalloc(data.attsize); 19774887Schin cp = data.attval = strcopy(*data.argnam,e_envmarker); 19788462SApril.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)); 19794887Schin *data.attval = 0; 19804887Schin if(cp!=data.attval) 19814887Schin data.argnam++; 19824887Schin *data.argnam = 0; 19834887Schin return(er); 19844887Schin } 19854887Schin #endif 19864887Schin 19874887Schin struct scan 19884887Schin { 19894887Schin void (*scanfn)(Namval_t*, void*); 19904887Schin int scanmask; 19914887Schin int scanflags; 19924887Schin int scancount; 19934887Schin void *scandata; 19944887Schin }; 19954887Schin 19964887Schin static int scanfilter(Dt_t *dict, void *arg, void *data) 19974887Schin { 19984887Schin register Namval_t *np = (Namval_t*)arg; 19994887Schin register int k=np->nvflag; 20004887Schin register struct scan *sp = (struct scan*)data; 20018462SApril.Chin@Sun.COM register struct adata *tp = (struct adata*)sp->scandata; 20024887Schin NOT_USED(dict); 20038462SApril.Chin@Sun.COM #if SHOPT_TYPEDEF 2004*10898Sroland.mainz@nrubsig.org if(tp && !is_abuiltin(np) && tp && tp->tp && nv_type(np)!=tp->tp) 20058462SApril.Chin@Sun.COM return(0); 20068462SApril.Chin@Sun.COM #endif /*SHOPT_TYPEDEF */ 20074887Schin if(sp->scanmask?(k&sp->scanmask)==sp->scanflags:(!sp->scanflags || (k&sp->scanflags))) 20084887Schin { 20098462SApril.Chin@Sun.COM if(!np->nvalue.cp && !np->nvfun && !nv_isattr(np,~NV_DEFAULT)) 20104887Schin return(0); 20114887Schin if(sp->scanfn) 20124887Schin { 20134887Schin if(nv_isarray(np)) 20144887Schin nv_putsub(np,NIL(char*),0L); 20154887Schin (*sp->scanfn)(np,sp->scandata); 20164887Schin } 20174887Schin sp->scancount++; 20184887Schin } 20194887Schin return(0); 20204887Schin } 20214887Schin 20224887Schin /* 20234887Schin * Walk through the name-value pairs 20244887Schin * if <mask> is non-zero, then only nodes with (nvflags&mask)==flags 20254887Schin * are visited 20264887Schin * If <mask> is zero, and <flags> non-zero, then nodes with one or 20274887Schin * more of <flags> is visited 20284887Schin * If <mask> and <flags> are zero, then all nodes are visted 20294887Schin */ 20304887Schin int nv_scan(Dt_t *root, void (*fn)(Namval_t*,void*), void *data,int mask, int flags) 20314887Schin { 20324887Schin Dt_t *base=0; 20334887Schin struct scan sdata; 20344887Schin int (*hashfn)(Dt_t*, void*, void*); 20354887Schin sdata.scanmask = mask; 20364887Schin sdata.scanflags = flags&~NV_NOSCOPE; 20374887Schin sdata.scanfn = fn; 20384887Schin sdata.scancount = 0; 20394887Schin sdata.scandata = data; 20404887Schin hashfn = scanfilter; 20414887Schin if(flags&NV_NOSCOPE) 20424887Schin base = dtview((Dt_t*)root,0); 20434887Schin dtwalk(root, hashfn,&sdata); 20444887Schin if(base) 20454887Schin dtview((Dt_t*)root,base); 20464887Schin return(sdata.scancount); 20474887Schin } 20484887Schin 20494887Schin /* 20504887Schin * create a new environment scope 20514887Schin */ 20528462SApril.Chin@Sun.COM void sh_scope(Shell_t *shp, struct argnod *envlist, int fun) 20534887Schin { 20548462SApril.Chin@Sun.COM register Dt_t *newscope, *newroot=shp->var_base; 20558462SApril.Chin@Sun.COM struct Ufunction *rp; 20564887Schin newscope = dtopen(&_Nvdisc,Dtoset); 20574887Schin if(envlist) 20588462SApril.Chin@Sun.COM { 20598462SApril.Chin@Sun.COM dtview(newscope,(Dt_t*)shp->var_tree); 20608462SApril.Chin@Sun.COM shp->var_tree = newscope; 2061*10898Sroland.mainz@nrubsig.org nv_setlist(envlist,NV_EXPORT|NV_NOSCOPE|NV_IDENT|NV_ASSIGN,0); 20628462SApril.Chin@Sun.COM if(!fun) 20638462SApril.Chin@Sun.COM return; 20648462SApril.Chin@Sun.COM shp->var_tree = dtview(newscope,0); 20658462SApril.Chin@Sun.COM } 20668462SApril.Chin@Sun.COM if((rp=shp->st.real_fun) && rp->sdict) 20678462SApril.Chin@Sun.COM { 20688462SApril.Chin@Sun.COM dtview(rp->sdict,newroot); 20698462SApril.Chin@Sun.COM newroot = rp->sdict; 20708462SApril.Chin@Sun.COM 20718462SApril.Chin@Sun.COM } 20728462SApril.Chin@Sun.COM dtview(newscope,(Dt_t*)newroot); 20738462SApril.Chin@Sun.COM shp->var_tree = newscope; 20744887Schin } 20754887Schin 20764887Schin /* 20774887Schin * Remove freeable local space associated with the nvalue field 20784887Schin * of nnod. This includes any strings representing the value(s) of the 20794887Schin * node, as well as its dope vector, if it is an array. 20804887Schin */ 20814887Schin 20824887Schin void sh_envnolocal (register Namval_t *np, void *data) 20834887Schin { 20844887Schin char *cp=0; 20854887Schin NOT_USED(data); 2086*10898Sroland.mainz@nrubsig.org if(np==VERSIONNOD && nv_isref(np)) 2087*10898Sroland.mainz@nrubsig.org return; 2088*10898Sroland.mainz@nrubsig.org if(np==L_ARGNOD) 2089*10898Sroland.mainz@nrubsig.org return; 20904887Schin if(nv_isattr(np,NV_EXPORT) && nv_isarray(np)) 20914887Schin { 20924887Schin nv_putsub(np,NIL(char*),0); 20934887Schin if(cp = nv_getval(np)) 20944887Schin cp = strdup(cp); 20954887Schin } 20964887Schin if(nv_isattr(np,NV_EXPORT|NV_NOFREE)) 20974887Schin { 2098*10898Sroland.mainz@nrubsig.org if(nv_isref(np) && np!=VERSIONNOD) 20994887Schin { 21004887Schin nv_offattr(np,NV_NOFREE|NV_REF); 21014887Schin free((void*)np->nvalue.nrp); 21024887Schin np->nvalue.cp = 0; 21034887Schin } 21044887Schin if(!cp) 21054887Schin return; 21064887Schin } 21074887Schin if(nv_isarray(np)) 21084887Schin nv_putsub(np,NIL(char*),ARRAY_UNDEF); 21094887Schin _nv_unset(np,NV_RDONLY); 21104887Schin nv_setattr(np,0); 21114887Schin if(cp) 21124887Schin { 21134887Schin nv_putval(np,cp,0); 21144887Schin free((void*)cp); 21154887Schin } 21164887Schin } 21174887Schin 21184887Schin /* 21194887Schin * Currently this is a dummy, but someday will be needed 21204887Schin * for reference counting 21214887Schin */ 21224887Schin void nv_close(Namval_t *np) 21234887Schin { 21244887Schin NOT_USED(np); 21254887Schin } 21264887Schin 21278462SApril.Chin@Sun.COM static void table_unset(Shell_t *shp, register Dt_t *root, int flags, Dt_t *oroot) 21284887Schin { 21298462SApril.Chin@Sun.COM register Namval_t *np,*nq, *npnext; 21308462SApril.Chin@Sun.COM for(np=(Namval_t*)dtfirst(root);np;np=npnext) 21314887Schin { 21328462SApril.Chin@Sun.COM if(nv_isref(np)) 2133*10898Sroland.mainz@nrubsig.org { 2134*10898Sroland.mainz@nrubsig.org free((void*)np->nvalue.nrp); 2135*10898Sroland.mainz@nrubsig.org np->nvalue.cp = 0; 2136*10898Sroland.mainz@nrubsig.org np->nvflag = 0; 2137*10898Sroland.mainz@nrubsig.org } 21388462SApril.Chin@Sun.COM if(nq=dtsearch(oroot,np)) 21398462SApril.Chin@Sun.COM { 21408462SApril.Chin@Sun.COM if(nv_cover(nq)) 21418462SApril.Chin@Sun.COM { 21428462SApril.Chin@Sun.COM int subshell = shp->subshell; 21438462SApril.Chin@Sun.COM shp->subshell = 0; 21448462SApril.Chin@Sun.COM if(nv_isattr(nq, NV_INTEGER)) 21458462SApril.Chin@Sun.COM { 21468462SApril.Chin@Sun.COM Sfdouble_t d = nv_getnum(nq); 21478462SApril.Chin@Sun.COM nv_putval(nq,(char*)&d,NV_LDOUBLE); 21488462SApril.Chin@Sun.COM } 2149*10898Sroland.mainz@nrubsig.org else if(shp->test&4) 2150*10898Sroland.mainz@nrubsig.org nv_putval(nq, strdup(nv_getval(nq)), NV_RDONLY); 21518462SApril.Chin@Sun.COM else 21528462SApril.Chin@Sun.COM nv_putval(nq, nv_getval(nq), NV_RDONLY); 21538462SApril.Chin@Sun.COM shp->subshell = subshell; 21548462SApril.Chin@Sun.COM np->nvfun = 0; 21558462SApril.Chin@Sun.COM } 21568462SApril.Chin@Sun.COM #ifdef _ENV_H 21578462SApril.Chin@Sun.COM if(nv_isattr(nq,NV_EXPORT)) 21588462SApril.Chin@Sun.COM sh_envput(shp->env,nq); 21598462SApril.Chin@Sun.COM #endif 21608462SApril.Chin@Sun.COM } 21618462SApril.Chin@Sun.COM npnext = (Namval_t*)dtnext(root,np); 21628462SApril.Chin@Sun.COM shp->last_root = root; 21638462SApril.Chin@Sun.COM shp->last_table = 0; 21648462SApril.Chin@Sun.COM if(nv_isvtree(np)) 21658462SApril.Chin@Sun.COM { 21668462SApril.Chin@Sun.COM int len = strlen(np->nvname); 21678462SApril.Chin@Sun.COM while((nq=npnext) && memcmp(np->nvname,nq->nvname,len)==0 && nq->nvname[len]=='.') 21688462SApril.Chin@Sun.COM 21698462SApril.Chin@Sun.COM { 21708462SApril.Chin@Sun.COM npnext = (Namval_t*)dtnext(root,nq); 21718462SApril.Chin@Sun.COM _nv_unset(nq,flags); 21728462SApril.Chin@Sun.COM nv_delete(nq,root,0); 21738462SApril.Chin@Sun.COM } 21748462SApril.Chin@Sun.COM } 21754887Schin _nv_unset(np,flags); 21768462SApril.Chin@Sun.COM nv_delete(np,root,0); 21774887Schin } 21784887Schin } 21794887Schin 21804887Schin /* 21814887Schin * 21824887Schin * Set the value of <np> to 0, and nullify any attributes 21834887Schin * that <np> may have had. Free any freeable space occupied 21844887Schin * by the value of <np>. If <np> denotes an array member, it 21854887Schin * will retain its attributes. 21864887Schin * <flags> can contain NV_RDONLY to override the readonly attribute 21874887Schin * being cleared. 21888462SApril.Chin@Sun.COM * <flags> can contain NV_EXPORT to override preserve nvenv 21894887Schin */ 21904887Schin void _nv_unset(register Namval_t *np,int flags) 21914887Schin { 21928462SApril.Chin@Sun.COM Shell_t *shp = &sh; 21934887Schin register union Value *up; 21944887Schin if(!(flags&NV_RDONLY) && nv_isattr (np,NV_RDONLY)) 21954887Schin errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np)); 21964887Schin if(is_afunction(np) && np->nvalue.ip) 21974887Schin { 21984887Schin register struct slnod *slp = (struct slnod*)(np->nvenv); 21994887Schin if(slp && !nv_isattr(np,NV_NOFREE)) 22004887Schin { 22018462SApril.Chin@Sun.COM struct Ufunction *rq,*rp = np->nvalue.rp; 22024887Schin /* free function definition */ 22034887Schin register char *name=nv_name(np),*cp= strrchr(name,'.'); 22044887Schin if(cp) 22054887Schin { 22064887Schin Namval_t *npv; 22074887Schin *cp = 0; 22088462SApril.Chin@Sun.COM npv = nv_open(name,shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOADD); 22094887Schin *cp++ = '.'; 22104887Schin if(npv) 22114887Schin nv_setdisc(npv,cp,NIL(Namval_t*),(Namfun_t*)npv); 22124887Schin } 22138462SApril.Chin@Sun.COM if(rp->fname && shp->fpathdict && (rq = (struct Ufunction*)nv_search(rp->fname,shp->fpathdict,0))) 22148462SApril.Chin@Sun.COM { 22158462SApril.Chin@Sun.COM do 22168462SApril.Chin@Sun.COM { 22178462SApril.Chin@Sun.COM if(rq->np != np) 22188462SApril.Chin@Sun.COM continue; 22198462SApril.Chin@Sun.COM dtdelete(shp->fpathdict,rq); 22208462SApril.Chin@Sun.COM break; 22218462SApril.Chin@Sun.COM } 22228462SApril.Chin@Sun.COM while(rq = (struct Ufunction*)dtnext(shp->fpathdict,rq)); 22238462SApril.Chin@Sun.COM } 22248462SApril.Chin@Sun.COM if(rp->sdict) 22258462SApril.Chin@Sun.COM { 22268462SApril.Chin@Sun.COM Namval_t *mp, *nq; 22278462SApril.Chin@Sun.COM for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq) 22288462SApril.Chin@Sun.COM { 22298462SApril.Chin@Sun.COM nq = dtnext(rp->sdict,mp); 22308462SApril.Chin@Sun.COM _nv_unset(mp,NV_RDONLY); 22318462SApril.Chin@Sun.COM nv_delete(mp,rp->sdict,0); 22328462SApril.Chin@Sun.COM } 22338462SApril.Chin@Sun.COM dtclose(rp->sdict); 22348462SApril.Chin@Sun.COM } 22354887Schin stakdelete(slp->slptr); 22364887Schin free((void*)np->nvalue.ip); 22374887Schin np->nvalue.ip = 0; 22384887Schin } 22394887Schin goto done; 22404887Schin } 22418462SApril.Chin@Sun.COM if(shp->subshell && !nv_isnull(np)) 22424887Schin np = sh_assignok(np,0); 22434887Schin nv_offattr(np,NV_NODISC); 22444887Schin if(np->nvfun && !nv_isref(np)) 22454887Schin { 22464887Schin /* This function contains disc */ 22474887Schin if(!nv_local) 22484887Schin { 22494887Schin nv_local=1; 22504887Schin nv_putv(np,NIL(char*),flags,np->nvfun); 22518462SApril.Chin@Sun.COM nv_local=0; 22524887Schin return; 22534887Schin } 22544887Schin /* called from disc, assign the actual value */ 22554887Schin nv_local=0; 22564887Schin } 2257*10898Sroland.mainz@nrubsig.org if(nv_isattr(np,NV_INT16P) == NV_INT16) 2258*10898Sroland.mainz@nrubsig.org { 2259*10898Sroland.mainz@nrubsig.org np->nvalue.cp = nv_isarray(np)?Empty:0; 2260*10898Sroland.mainz@nrubsig.org goto done; 2261*10898Sroland.mainz@nrubsig.org } 22628462SApril.Chin@Sun.COM if(nv_isarray(np) && np->nvalue.cp!=Empty && np->nvfun) 22638462SApril.Chin@Sun.COM up = np->nvalue.up; 22648462SApril.Chin@Sun.COM else 22658462SApril.Chin@Sun.COM up = &np->nvalue; 22668462SApril.Chin@Sun.COM if(up && up->cp) 22674887Schin { 22688462SApril.Chin@Sun.COM if(up->cp!=Empty && !nv_isattr(np, NV_NOFREE)) 22694887Schin free((void*)up->cp); 22704887Schin up->cp = 0; 22714887Schin } 22724887Schin done: 22734887Schin if(!nv_isarray(np) || !nv_arrayptr(np)) 22744887Schin { 22758462SApril.Chin@Sun.COM if(nv_isref(np) && !nv_isattr(np,NV_EXPORT)) 22764887Schin free((void*)np->nvalue.nrp); 22774887Schin nv_setsize(np,0); 22784887Schin if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT)) 22794887Schin { 22804887Schin if(nv_isattr(np,NV_EXPORT) && !strchr(np->nvname,'[')) 22818462SApril.Chin@Sun.COM env_delete(shp->env,nv_name(np)); 22828462SApril.Chin@Sun.COM if(!(flags&NV_EXPORT) || nv_isattr(np,NV_IMPORT|NV_EXPORT)==(NV_IMPORT|NV_EXPORT)) 22838462SApril.Chin@Sun.COM np->nvenv = 0; 22844887Schin nv_setattr(np,0); 22854887Schin } 22864887Schin else 22878462SApril.Chin@Sun.COM { 22884887Schin nv_setattr(np,NV_MINIMAL); 22898462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 22908462SApril.Chin@Sun.COM } 22914887Schin } 22924887Schin } 22934887Schin 22944887Schin /* 22954887Schin * return the node pointer in the highest level scope 22964887Schin */ 22978462SApril.Chin@Sun.COM Namval_t *sh_scoped(Shell_t *shp, register Namval_t *np) 22984887Schin { 22998462SApril.Chin@Sun.COM if(!dtvnext(shp->var_tree)) 23004887Schin return(np); 23018462SApril.Chin@Sun.COM return(dtsearch(shp->var_tree,np)); 23024887Schin } 23034887Schin 23044887Schin #if 1 23054887Schin /* 23064887Schin * return space separated list of names of variables in given tree 23074887Schin */ 23084887Schin static char *tableval(Dt_t *root) 23094887Schin { 23104887Schin static Sfio_t *out; 23114887Schin register Namval_t *np; 23124887Schin register int first=1; 23134887Schin register Dt_t *base = dtview(root,0); 23144887Schin if(out) 23154887Schin sfseek(out,(Sfoff_t)0,SEEK_SET); 23164887Schin else 23174887Schin out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING); 23184887Schin for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np)) 23194887Schin { 23204887Schin if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE)) 23214887Schin { 23224887Schin if(!first) 23234887Schin sfputc(out,' '); 23244887Schin else 23254887Schin first = 0; 23264887Schin sfputr(out,np->nvname,-1); 23274887Schin } 23284887Schin } 23294887Schin sfputc(out,0); 23304887Schin if(base) 23314887Schin dtview(root,base); 23324887Schin return((char*)out->_data); 23334887Schin } 23344887Schin #endif 23354887Schin 23364887Schin #if SHOPT_OPTIMIZE 23374887Schin struct optimize 23384887Schin { 23394887Schin Namfun_t hdr; 23408462SApril.Chin@Sun.COM Shell_t *sh; 23414887Schin char **ptr; 23424887Schin struct optimize *next; 23434887Schin Namval_t *np; 23444887Schin }; 23454887Schin 23464887Schin static struct optimize *opt_free; 23474887Schin 23484887Schin static void optimize_clear(Namval_t* np, Namfun_t *fp) 23494887Schin { 23504887Schin struct optimize *op = (struct optimize*)fp; 23514887Schin nv_stack(np,fp); 23524887Schin nv_stack(np,(Namfun_t*)0); 23534887Schin for(;op && op->np==np; op=op->next) 23544887Schin { 23554887Schin if(op->ptr) 23564887Schin { 23574887Schin *op->ptr = 0; 23584887Schin op->ptr = 0; 23594887Schin } 23604887Schin } 23614887Schin } 23624887Schin 23634887Schin static void put_optimize(Namval_t* np,const char *val,int flags,Namfun_t *fp) 23644887Schin { 23654887Schin nv_putv(np,val,flags,fp); 23664887Schin optimize_clear(np,fp); 23674887Schin } 23684887Schin 23698462SApril.Chin@Sun.COM static Namfun_t *clone_optimize(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp) 23708462SApril.Chin@Sun.COM { 23718462SApril.Chin@Sun.COM return((Namfun_t*)0); 23728462SApril.Chin@Sun.COM } 23738462SApril.Chin@Sun.COM 23748462SApril.Chin@Sun.COM static const Namdisc_t optimize_disc = {sizeof(struct optimize),put_optimize,0,0,0,0,clone_optimize}; 23754887Schin 23764887Schin void nv_optimize(Namval_t *np) 23774887Schin { 23784887Schin register Namfun_t *fp; 23794887Schin register struct optimize *op, *xp; 23804887Schin if(sh.argaddr) 23814887Schin { 23828462SApril.Chin@Sun.COM if(np==SH_LINENO) 23838462SApril.Chin@Sun.COM { 23848462SApril.Chin@Sun.COM sh.argaddr = 0; 23858462SApril.Chin@Sun.COM return; 23868462SApril.Chin@Sun.COM } 23874887Schin for(fp=np->nvfun; fp; fp = fp->next) 23884887Schin { 23898462SApril.Chin@Sun.COM if(fp->disc && (fp->disc->getnum || fp->disc->getval)) 23904887Schin { 23914887Schin sh.argaddr = 0; 23924887Schin return; 23934887Schin } 23944887Schin if(fp->disc== &optimize_disc) 23954887Schin break; 23964887Schin } 23974887Schin if((xp= (struct optimize*)fp) && xp->ptr==sh.argaddr) 23984887Schin return; 23994887Schin if(op = opt_free) 24004887Schin opt_free = op->next; 24014887Schin else 24024887Schin op=(struct optimize*)calloc(1,sizeof(struct optimize)); 24034887Schin op->ptr = sh.argaddr; 24044887Schin op->np = np; 24054887Schin if(xp) 24064887Schin { 24074887Schin op->hdr.disc = 0; 24084887Schin op->next = xp->next; 24094887Schin xp->next = op; 24104887Schin } 24114887Schin else 24124887Schin { 24134887Schin op->hdr.disc = &optimize_disc; 24144887Schin op->next = (struct optimize*)sh.optlist; 24154887Schin sh.optlist = (void*)op; 24164887Schin nv_stack(np,&op->hdr); 24174887Schin } 24184887Schin } 24194887Schin } 24204887Schin 24214887Schin void sh_optclear(Shell_t *shp, void *old) 24224887Schin { 24234887Schin register struct optimize *op,*opnext; 24244887Schin for(op=(struct optimize*)shp->optlist; op; op = opnext) 24254887Schin { 24264887Schin opnext = op->next; 24274887Schin if(op->ptr && op->hdr.disc) 24284887Schin { 24294887Schin nv_stack(op->np,&op->hdr); 24304887Schin nv_stack(op->np,(Namfun_t*)0); 24314887Schin } 24324887Schin op->next = opt_free; 24334887Schin opt_free = op; 24344887Schin } 24354887Schin shp->optlist = old; 24364887Schin } 24374887Schin 24384887Schin #else 24394887Schin # define optimize_clear(np,fp) 24404887Schin #endif /* SHOPT_OPTIMIZE */ 24414887Schin 24424887Schin /* 24434887Schin * Return a pointer to a character string that denotes the value 24444887Schin * of <np>. If <np> refers to an array, return a pointer to 24454887Schin * the value associated with the current index. 24464887Schin * 24474887Schin * If the value of <np> is an integer, the string returned will 24484887Schin * be overwritten by the next call to nv_getval. 24494887Schin * 24504887Schin * If <np> has no value, 0 is returned. 24514887Schin */ 24524887Schin 24534887Schin char *nv_getval(register Namval_t *np) 24544887Schin { 24554887Schin register union Value *up= &np->nvalue; 24564887Schin register int numeric; 24574887Schin #if SHOPT_OPTIMIZE 24584887Schin if(!nv_local && sh.argaddr) 24594887Schin nv_optimize(np); 24604887Schin #endif /* SHOPT_OPTIMIZE */ 24618462SApril.Chin@Sun.COM if((!np->nvfun || !np->nvfun->disc) && !nv_isattr(np,NV_ARRAY|NV_INTEGER|NV_FUNCT|NV_REF|NV_TABLE)) 24624887Schin goto done; 24634887Schin if(nv_isref(np)) 24644887Schin { 24658462SApril.Chin@Sun.COM if(!np->nvalue.cp) 24668462SApril.Chin@Sun.COM return(0); 24674887Schin sh.last_table = nv_reftable(np); 24684887Schin return(nv_name(nv_refnode(np))); 24694887Schin } 24708462SApril.Chin@Sun.COM if(np->nvfun && np->nvfun->disc) 24714887Schin { 24724887Schin if(!nv_local) 24734887Schin { 24744887Schin nv_local=1; 24754887Schin return(nv_getv(np, np->nvfun)); 24764887Schin } 24774887Schin nv_local=0; 24784887Schin } 24794887Schin numeric = ((nv_isattr (np, NV_INTEGER)) != 0); 24804887Schin if(numeric) 24814887Schin { 24824887Schin Sflong_t ll; 24834887Schin if(!up->cp) 24844887Schin return("0"); 24858462SApril.Chin@Sun.COM if(nv_isattr (np,NV_DOUBLE)==NV_DOUBLE) 24864887Schin { 24874887Schin Sfdouble_t ld; 24884887Schin double d; 24894887Schin char *format; 24904887Schin if(nv_isattr(np,NV_LONG)) 24914887Schin { 24924887Schin ld = *up->ldp; 24934887Schin if(nv_isattr (np,NV_EXPNOTE)) 24944887Schin format = "%.*Lg"; 24958462SApril.Chin@Sun.COM else if(nv_isattr (np,NV_HEXFLOAT)) 24968462SApril.Chin@Sun.COM format = "%.*La"; 24974887Schin else 24984887Schin format = "%.*Lf"; 24994887Schin sfprintf(sh.strbuf,format,nv_size(np),ld); 25004887Schin } 25014887Schin else 25024887Schin { 25034887Schin d = *up->dp; 25044887Schin if(nv_isattr (np,NV_EXPNOTE)) 25054887Schin format = "%.*g"; 25068462SApril.Chin@Sun.COM else if(nv_isattr (np,NV_HEXFLOAT)) 25078462SApril.Chin@Sun.COM format = "%.*a"; 25084887Schin else 25094887Schin format = "%.*f"; 25104887Schin sfprintf(sh.strbuf,format,nv_size(np),d); 25114887Schin } 25124887Schin return(sfstruse(sh.strbuf)); 25134887Schin } 25144887Schin else if(nv_isattr(np,NV_UNSIGN)) 25154887Schin { 25164887Schin if(nv_isattr (np,NV_LONG)) 25174887Schin ll = *(Sfulong_t*)up->llp; 25184887Schin else if(nv_isattr (np,NV_SHORT)) 25198462SApril.Chin@Sun.COM { 25208462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 25218462SApril.Chin@Sun.COM ll = *(uint16_t*)(up->sp); 25228462SApril.Chin@Sun.COM else 25238462SApril.Chin@Sun.COM ll = (uint16_t)up->s; 25248462SApril.Chin@Sun.COM } 25254887Schin else 25264887Schin ll = *(uint32_t*)(up->lp); 25274887Schin } 25284887Schin else if(nv_isattr (np,NV_LONG)) 25294887Schin ll = *up->llp; 25304887Schin else if(nv_isattr (np,NV_SHORT)) 25318462SApril.Chin@Sun.COM { 25328462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 25338462SApril.Chin@Sun.COM ll = *up->sp; 25348462SApril.Chin@Sun.COM else 25358462SApril.Chin@Sun.COM ll = up->s; 25368462SApril.Chin@Sun.COM } 25374887Schin else 25384887Schin ll = *(up->lp); 25394887Schin if((numeric=nv_size(np))==10) 25404887Schin { 25414887Schin if(nv_isattr(np,NV_UNSIGN)) 25424887Schin { 25434887Schin sfprintf(sh.strbuf,"%I*u",sizeof(ll),ll); 25444887Schin return(sfstruse(sh.strbuf)); 25454887Schin } 25464887Schin numeric = 0; 25474887Schin } 25484887Schin return(fmtbasell(ll,numeric, numeric&&numeric!=10)); 25494887Schin } 25504887Schin done: 25514887Schin #if (_AST_VERSION>=20030127L) 25524887Schin /* 25534887Schin * if NV_RAW flag is on, return pointer to binary data 25544887Schin * otherwise, base64 encode the data and return this string 25554887Schin */ 25564887Schin if(up->cp && nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW)) 25574887Schin { 25584887Schin char *cp; 25594887Schin int size= nv_size(np), insize=(4*size)/3+size/45+8; 25604887Schin base64encode(up->cp, size, (void**)0, cp=getbuf(insize), insize, (void**)0); 25614887Schin return(cp); 25624887Schin } 25634887Schin #endif 25644887Schin if((numeric=nv_size(np)) && up->cp && up->cp[numeric]) 25654887Schin { 25664887Schin char *cp = getbuf(numeric+1); 25674887Schin memcpy(cp,up->cp,numeric); 25684887Schin cp[numeric]=0; 25694887Schin return(cp); 25704887Schin } 25714887Schin return ((char*)up->cp); 25724887Schin } 25734887Schin 25744887Schin Sfdouble_t nv_getnum(register Namval_t *np) 25754887Schin { 25764887Schin register union Value *up; 25774887Schin register Sfdouble_t r=0; 25784887Schin register char *str; 25794887Schin #if SHOPT_OPTIMIZE 25804887Schin if(!nv_local && sh.argaddr) 25814887Schin nv_optimize(np); 25824887Schin #endif /* SHOPT_OPTIMIZE */ 25834887Schin if(nv_istable(np)) 25844887Schin errormsg(SH_DICT,ERROR_exit(1),e_number,nv_name(np)); 25858462SApril.Chin@Sun.COM if(np->nvfun && np->nvfun->disc) 25864887Schin { 25874887Schin if(!nv_local) 25884887Schin { 25894887Schin nv_local=1; 25904887Schin return(nv_getn(np, np->nvfun)); 25914887Schin } 25924887Schin nv_local=0; 25934887Schin } 25948462SApril.Chin@Sun.COM if(nv_isref(np)) 25958462SApril.Chin@Sun.COM { 25968462SApril.Chin@Sun.COM str = nv_refsub(np); 25978462SApril.Chin@Sun.COM np = nv_refnode(np); 25988462SApril.Chin@Sun.COM if(str) 25998462SApril.Chin@Sun.COM nv_putsub(np,str,0L); 26008462SApril.Chin@Sun.COM } 26014887Schin if(nv_isattr (np, NV_INTEGER)) 26024887Schin { 26034887Schin up= &np->nvalue; 26048462SApril.Chin@Sun.COM if(!up->lp || up->cp==Empty) 26054887Schin r = 0; 26068462SApril.Chin@Sun.COM else if(nv_isattr(np, NV_DOUBLE)==NV_DOUBLE) 26074887Schin { 26084887Schin if(nv_isattr(np, NV_LONG)) 26094887Schin r = *up->ldp; 26104887Schin else 26114887Schin r = *up->dp; 26124887Schin } 26134887Schin else if(nv_isattr(np, NV_UNSIGN)) 26144887Schin { 26154887Schin if(nv_isattr(np, NV_LONG)) 26164887Schin r = (Sflong_t)*((Sfulong_t*)up->llp); 26174887Schin else if(nv_isattr(np, NV_SHORT)) 26188462SApril.Chin@Sun.COM { 26198462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 26208462SApril.Chin@Sun.COM r = (Sflong_t)(*(uint16_t*)up->sp); 26218462SApril.Chin@Sun.COM else 26228462SApril.Chin@Sun.COM r = (Sflong_t)((uint16_t)up->s); 26238462SApril.Chin@Sun.COM } 26244887Schin else 26254887Schin r = *((uint32_t*)up->lp); 26264887Schin } 26274887Schin else 26284887Schin { 26294887Schin if(nv_isattr(np, NV_LONG)) 26304887Schin r = *up->llp; 26314887Schin else if(nv_isattr(np, NV_SHORT)) 26328462SApril.Chin@Sun.COM { 26338462SApril.Chin@Sun.COM if(nv_isattr(np,NV_INT16P)==NV_INT16P) 26348462SApril.Chin@Sun.COM r = *up->sp; 26358462SApril.Chin@Sun.COM else 26368462SApril.Chin@Sun.COM r = up->s; 26378462SApril.Chin@Sun.COM } 26384887Schin else 26394887Schin r = *up->lp; 26404887Schin } 26414887Schin } 26424887Schin else if((str=nv_getval(np)) && *str!=0) 26434887Schin { 26444887Schin if(np->nvfun || nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL)) 26454887Schin { 26464887Schin while(*str=='0') 26474887Schin str++; 26484887Schin } 26494887Schin r = sh_arith(str); 26504887Schin } 26514887Schin return(r); 26524887Schin } 26534887Schin /* 26544887Schin * Give <np> the attributes <newatts,> and change its current 26554887Schin * value to conform to <newatts>. The <size> of left and right 26564887Schin * justified fields may be given. 26574887Schin */ 26584887Schin void nv_newattr (register Namval_t *np, unsigned newatts, int size) 26594887Schin { 26604887Schin register char *sp; 26614887Schin register char *cp = 0; 26624887Schin register unsigned int n; 26634887Schin Namarr_t *ap = 0; 26644887Schin int oldsize,oldatts; 26658462SApril.Chin@Sun.COM Namfun_t *fp= (newatts&NV_NODISC)?np->nvfun:0; 2666*10898Sroland.mainz@nrubsig.org char *prefix = sh.prefix; 26678462SApril.Chin@Sun.COM newatts &= ~NV_NODISC; 26684887Schin 26694887Schin /* check for restrictions */ 26704887Schin if(sh_isoption(SH_RESTRICTED) && ((sp=nv_name(np))==nv_name(PATHNOD) || sp==nv_name(SHELLNOD) || sp==nv_name(ENVNOD) || sp==nv_name(FPATHNOD))) 26714887Schin errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np)); 26724887Schin /* handle attributes that do not change data separately */ 26734887Schin n = np->nvflag; 26744887Schin if(newatts&NV_EXPORT) 26754887Schin nv_offattr(np,NV_IMPORT); 26768462SApril.Chin@Sun.COM #ifdef _ENV_H 26774887Schin if(((n^newatts)&NV_EXPORT)) 26784887Schin { 26794887Schin /* record changes to the environment */ 26804887Schin if(n&NV_EXPORT) 26814887Schin env_delete(sh.env,nv_name(np)); 26824887Schin else 26834887Schin sh_envput(sh.env,np); 26844887Schin } 26858462SApril.Chin@Sun.COM #endif 2686*10898Sroland.mainz@nrubsig.org oldsize = nv_size(np); 2687*10898Sroland.mainz@nrubsig.org if((size==oldsize|| (n&NV_INTEGER)) && ((n^newatts)&~NV_NOCHANGE)==0) 26884887Schin { 26894887Schin if(size) 26904887Schin nv_setsize(np,size); 26914887Schin nv_offattr(np, ~NV_NOFREE); 26924887Schin nv_onattr(np, newatts); 26934887Schin return; 26944887Schin } 26954887Schin /* for an array, change all the elements */ 26964887Schin if((ap=nv_arrayptr(np)) && ap->nelem>0) 26974887Schin nv_putsub(np,NIL(char*),ARRAY_SCAN); 26984887Schin oldsize = nv_size(np); 26994887Schin oldatts = np->nvflag; 27008462SApril.Chin@Sun.COM if(fp) 27018462SApril.Chin@Sun.COM np->nvfun = 0; 27024887Schin if(ap) /* add element to prevent array deletion */ 27034887Schin ap->nelem++; 27044887Schin do 27054887Schin { 27064887Schin nv_setsize(np,oldsize); 27074887Schin np->nvflag = oldatts; 27084887Schin if (sp = nv_getval(np)) 27094887Schin { 27104887Schin if(nv_isattr(np,NV_ZFILL)) 27114887Schin while(*sp=='0') sp++; 27124887Schin cp = (char*)malloc((n=strlen (sp)) + 1); 27134887Schin strcpy(cp, sp); 27144887Schin if(ap) 27154887Schin { 27164887Schin Namval_t *mp; 27174887Schin ap->nelem &= ~ARRAY_SCAN; 27184887Schin if(mp=nv_opensub(np)) 27198462SApril.Chin@Sun.COM { 27208462SApril.Chin@Sun.COM nv_unset(mp); 27218462SApril.Chin@Sun.COM mp->nvalue.cp = Empty; 27228462SApril.Chin@Sun.COM } 27238462SApril.Chin@Sun.COM else 27248462SApril.Chin@Sun.COM nv_unset(np); 27258462SApril.Chin@Sun.COM ap->nelem |= ARRAY_SCAN; 27264887Schin } 27278462SApril.Chin@Sun.COM else 27288462SApril.Chin@Sun.COM nv_unset(np); 27294887Schin if(size==0 && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL))) 27304887Schin size = n; 27314887Schin } 27324887Schin else 27334887Schin nv_unset(np); 27344887Schin nv_setsize(np,size); 27354887Schin np->nvflag &= NV_ARRAY; 27364887Schin np->nvflag |= newatts; 27374887Schin if (cp) 27384887Schin { 27394887Schin nv_putval (np, cp, NV_RDONLY); 27404887Schin free(cp); 27414887Schin } 27424887Schin } 27434887Schin while(ap && nv_nextsub(np)); 27448462SApril.Chin@Sun.COM if(fp) 27458462SApril.Chin@Sun.COM np->nvfun = fp; 27464887Schin if(ap) 27474887Schin ap->nelem--; 2748*10898Sroland.mainz@nrubsig.org sh.prefix = prefix; 27494887Schin return; 27504887Schin } 27514887Schin 27524887Schin #ifndef _NEXT_SOURCE 27534887Schin static char *oldgetenv(const char *string) 27544887Schin { 27554887Schin register char c0,c1; 27564887Schin register const char *cp, *sp; 27574887Schin register char **av = environ; 27584887Schin if(!string || (c0= *string)==0) 27594887Schin return(0); 27604887Schin if((c1=*++string)==0) 27614887Schin c1= '='; 27624887Schin while(cp = *av++) 27634887Schin { 27644887Schin if(cp[0]!=c0 || cp[1]!=c1) 27654887Schin continue; 27664887Schin sp = string; 27674887Schin while(*sp && *sp++ == *++cp); 27684887Schin if(*sp==0 && *++cp=='=') 27694887Schin return((char*)(cp+1)); 27704887Schin } 27714887Schin return(0); 27724887Schin } 27734887Schin 27744887Schin /* 27754887Schin * This version of getenv uses the hash storage to access environment values 27764887Schin */ 27774887Schin char *getenv(const char *name) 27784887Schin /*@ 27794887Schin assume name!=0; 27804887Schin @*/ 27814887Schin { 27824887Schin register Namval_t *np; 27834887Schin if(!sh.var_tree) 27844887Schin return(oldgetenv(name)); 27854887Schin if((np = nv_search(name,sh.var_tree,0)) && nv_isattr(np,NV_EXPORT)) 27864887Schin return(nv_getval(np)); 27874887Schin if(name[0] == 'P' && name[1] == 'A' && name[2] == 'T' && name[3] == 'H' && name[4] == 0) 27884887Schin return(oldgetenv(name)); 27894887Schin return(0); 27904887Schin } 27914887Schin #endif /* _NEXT_SOURCE */ 27924887Schin 27934887Schin #undef putenv 27944887Schin /* 27954887Schin * This version of putenv uses the hash storage to assign environment values 27964887Schin */ 27974887Schin int putenv(const char *name) 27984887Schin { 27994887Schin register Namval_t *np; 28004887Schin if(name) 28014887Schin { 28024887Schin np = nv_open(name,sh.var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN); 28034887Schin if(!strchr(name,'=')) 28044887Schin nv_unset(np); 28054887Schin } 28064887Schin return(0); 28074887Schin } 28084887Schin 28094887Schin 28104887Schin /* 28114887Schin * Override libast setenv() 28124887Schin */ 28134887Schin char* setenviron(const char *name) 28144887Schin { 28154887Schin register Namval_t *np; 28164887Schin if(name) 28174887Schin { 28184887Schin np = nv_open(name,sh.var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN); 28194887Schin if(strchr(name,'=')) 28204887Schin return(nv_getval(np)); 28214887Schin nv_unset(np); 28224887Schin } 28234887Schin return(""); 28244887Schin } 28254887Schin 28264887Schin /* 28278462SApril.Chin@Sun.COM * convert <str> to upper case 28284887Schin */ 28298462SApril.Chin@Sun.COM static void ltou(register char *str) 28304887Schin { 28314887Schin register int c; 28328462SApril.Chin@Sun.COM for(; c= *((unsigned char*)str); str++) 28334887Schin { 28344887Schin if(islower(c)) 28358462SApril.Chin@Sun.COM *str = toupper(c); 28364887Schin } 28378462SApril.Chin@Sun.COM } 28388462SApril.Chin@Sun.COM 28398462SApril.Chin@Sun.COM /* 28408462SApril.Chin@Sun.COM * convert <str> to lower case 28418462SApril.Chin@Sun.COM */ 28428462SApril.Chin@Sun.COM static void utol(register char *str) 28438462SApril.Chin@Sun.COM { 28448462SApril.Chin@Sun.COM register int c; 28458462SApril.Chin@Sun.COM for(; c= *((unsigned char*)str); str++) 28468462SApril.Chin@Sun.COM { 28478462SApril.Chin@Sun.COM if(isupper(c)) 28488462SApril.Chin@Sun.COM *str = tolower(c); 28498462SApril.Chin@Sun.COM } 28504887Schin } 28514887Schin 28524887Schin /* 28534887Schin * normalize <cp> and return pointer to subscript if any 28548462SApril.Chin@Sun.COM * if <eq> is specified, return pointer to first = not in a subscript 28554887Schin */ 28568462SApril.Chin@Sun.COM static char *lastdot(register char *cp, int eq) 28574887Schin { 28588462SApril.Chin@Sun.COM register char *ep=0; 28594887Schin register int c; 28608462SApril.Chin@Sun.COM if(eq) 28618462SApril.Chin@Sun.COM cp++; 28624887Schin while(c= *cp++) 28634887Schin { 28644887Schin if(c=='[') 2865*10898Sroland.mainz@nrubsig.org { 2866*10898Sroland.mainz@nrubsig.org if(*cp==']') 2867*10898Sroland.mainz@nrubsig.org cp++; 2868*10898Sroland.mainz@nrubsig.org else 2869*10898Sroland.mainz@nrubsig.org cp = nv_endsubscript((Namval_t*)0,ep=cp,0); 2870*10898Sroland.mainz@nrubsig.org } 28714887Schin else if(c=='.') 28724887Schin { 28734887Schin if(*cp=='[') 2874*10898Sroland.mainz@nrubsig.org { 2875*10898Sroland.mainz@nrubsig.org cp = nv_endsubscript((Namval_t*)0,ep=cp,0); 2876*10898Sroland.mainz@nrubsig.org if((ep=sh_checkid(ep+1,cp)) < cp) 2877*10898Sroland.mainz@nrubsig.org cp=strcpy(ep,cp); 2878*10898Sroland.mainz@nrubsig.org } 28794887Schin ep = 0; 28804887Schin } 28818462SApril.Chin@Sun.COM else if(eq && c == '=') 28828462SApril.Chin@Sun.COM return(cp-1); 28834887Schin } 28848462SApril.Chin@Sun.COM return(eq?0:ep); 28858462SApril.Chin@Sun.COM } 28868462SApril.Chin@Sun.COM 28878462SApril.Chin@Sun.COM int nv_rename(register Namval_t *np, int flags) 28888462SApril.Chin@Sun.COM { 28898462SApril.Chin@Sun.COM Shell_t *shp = &sh; 28908462SApril.Chin@Sun.COM register Namval_t *mp=0,*nr=0; 28918462SApril.Chin@Sun.COM register char *cp; 28928462SApril.Chin@Sun.COM int index= -1; 28938462SApril.Chin@Sun.COM Namval_t *last_table = shp->last_table; 28948462SApril.Chin@Sun.COM Dt_t *last_root = shp->last_root; 28958462SApril.Chin@Sun.COM Dt_t *hp = 0; 2896*10898Sroland.mainz@nrubsig.org char *prefix=shp->prefix,*nvenv = 0; 28978462SApril.Chin@Sun.COM if(nv_isattr(np,NV_PARAM) && shp->st.prevst) 28988462SApril.Chin@Sun.COM { 28998462SApril.Chin@Sun.COM if(!(hp=(Dt_t*)shp->st.prevst->save_tree)) 29008462SApril.Chin@Sun.COM hp = dtvnext(shp->var_tree); 29018462SApril.Chin@Sun.COM } 29028462SApril.Chin@Sun.COM if(!(cp=nv_getval(np))) 29038462SApril.Chin@Sun.COM { 29048462SApril.Chin@Sun.COM if(flags&NV_MOVE) 29058462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_varname,""); 29068462SApril.Chin@Sun.COM return(0); 29078462SApril.Chin@Sun.COM } 29088462SApril.Chin@Sun.COM if(lastdot(cp,0) && nv_isattr(np,NV_MINIMAL)) 29098462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(1),e_varname,nv_name(np)); 29108462SApril.Chin@Sun.COM if(nv_isarray(np) && !(mp=nv_opensub(np))) 29118462SApril.Chin@Sun.COM index=nv_aindex(np); 2912*10898Sroland.mainz@nrubsig.org shp->prefix = 0; 29138462SApril.Chin@Sun.COM if(!hp) 29148462SApril.Chin@Sun.COM hp = shp->var_tree; 29158462SApril.Chin@Sun.COM if(!(nr = nv_open(cp, hp, flags|NV_ARRAY|NV_NOREF|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))) 29168462SApril.Chin@Sun.COM hp = shp->var_base; 29178462SApril.Chin@Sun.COM else if(shp->last_root) 29188462SApril.Chin@Sun.COM hp = shp->last_root; 29198462SApril.Chin@Sun.COM if(!nr) 29208462SApril.Chin@Sun.COM nr= nv_open(cp, hp, flags|NV_NOREF|((flags&NV_MOVE)?0:NV_NOFAIL)); 2921*10898Sroland.mainz@nrubsig.org shp->prefix = prefix; 29228462SApril.Chin@Sun.COM if(!nr) 29238462SApril.Chin@Sun.COM { 29248462SApril.Chin@Sun.COM if(!nv_isvtree(np)) 29258462SApril.Chin@Sun.COM _nv_unset(np,0); 29268462SApril.Chin@Sun.COM return(0); 29278462SApril.Chin@Sun.COM } 29288462SApril.Chin@Sun.COM if(!mp && index>=0 && nv_isvtree(nr)) 29298462SApril.Chin@Sun.COM { 29308462SApril.Chin@Sun.COM sfprintf(shp->strbuf,"%s[%d]%c",nv_name(np),index,0); 29318462SApril.Chin@Sun.COM /* create a virtual node */ 29328462SApril.Chin@Sun.COM if(mp = nv_open(sfstruse(shp->strbuf),shp->var_tree,NV_VARNAME|NV_ADD|NV_ARRAY)) 29338462SApril.Chin@Sun.COM mp->nvenv = (void*)np; 29348462SApril.Chin@Sun.COM } 29358462SApril.Chin@Sun.COM if(mp) 2936*10898Sroland.mainz@nrubsig.org { 2937*10898Sroland.mainz@nrubsig.org nvenv = (char*)np; 29388462SApril.Chin@Sun.COM np = mp; 2939*10898Sroland.mainz@nrubsig.org } 29408462SApril.Chin@Sun.COM if(nr==np) 29418462SApril.Chin@Sun.COM { 29428462SApril.Chin@Sun.COM if(index<0) 29438462SApril.Chin@Sun.COM return(0); 29448462SApril.Chin@Sun.COM if(cp = nv_getval(np)) 29458462SApril.Chin@Sun.COM cp = strdup(cp); 29468462SApril.Chin@Sun.COM } 29478462SApril.Chin@Sun.COM _nv_unset(np,0); 2948*10898Sroland.mainz@nrubsig.org if(!nv_isattr(np,NV_MINIMAL)) 2949*10898Sroland.mainz@nrubsig.org np->nvenv = nvenv; 29508462SApril.Chin@Sun.COM if(nr==np) 29518462SApril.Chin@Sun.COM { 29528462SApril.Chin@Sun.COM nv_putsub(np,(char*)0, index); 29538462SApril.Chin@Sun.COM nv_putval(np,cp,0); 29548462SApril.Chin@Sun.COM free((void*)cp); 29558462SApril.Chin@Sun.COM return(1); 29568462SApril.Chin@Sun.COM } 29578462SApril.Chin@Sun.COM shp->prev_table = shp->last_table; 29588462SApril.Chin@Sun.COM shp->prev_root = shp->last_root; 29598462SApril.Chin@Sun.COM shp->last_table = last_table; 29608462SApril.Chin@Sun.COM shp->last_root = last_root; 29618462SApril.Chin@Sun.COM nv_clone(nr,np,(flags&NV_MOVE)|NV_COMVAR); 29628462SApril.Chin@Sun.COM if(flags&NV_MOVE) 29638462SApril.Chin@Sun.COM nv_delete(nr,(Dt_t*)0,NV_NOFREE); 29648462SApril.Chin@Sun.COM return(1); 29654887Schin } 29664887Schin 29674887Schin /* 29684887Schin * Create a reference node from <np> to $np in dictionary <hp> 29694887Schin */ 29704887Schin void nv_setref(register Namval_t *np, Dt_t *hp, int flags) 29714887Schin { 29728462SApril.Chin@Sun.COM Shell_t *shp = &sh; 29738462SApril.Chin@Sun.COM register Namval_t *nq, *nr=0; 2974*10898Sroland.mainz@nrubsig.org register char *ep,*cp; 2975*10898Sroland.mainz@nrubsig.org Dt_t *root = shp->last_root; 2976*10898Sroland.mainz@nrubsig.org Namarr_t *ap; 29774887Schin if(nv_isref(np)) 29784887Schin return; 29794887Schin if(nv_isarray(np)) 29804887Schin errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np)); 29814887Schin if(!(cp=nv_getval(np))) 29828462SApril.Chin@Sun.COM { 29838462SApril.Chin@Sun.COM nv_unset(np); 29848462SApril.Chin@Sun.COM nv_onattr(np,NV_REF); 29858462SApril.Chin@Sun.COM return; 29868462SApril.Chin@Sun.COM } 29878462SApril.Chin@Sun.COM if((ep = lastdot(cp,0)) && nv_isattr(np,NV_MINIMAL)) 29884887Schin errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np)); 29894887Schin if(!hp) 29908462SApril.Chin@Sun.COM hp = shp->var_tree; 29918462SApril.Chin@Sun.COM if(!(nr = nq = nv_open(cp, hp, flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL))) 2992*10898Sroland.mainz@nrubsig.org hp = shp->last_root==shp->var_tree?shp->var_tree:shp->var_base; 29938462SApril.Chin@Sun.COM else if(shp->last_root) 29948462SApril.Chin@Sun.COM hp = shp->last_root; 29958462SApril.Chin@Sun.COM if(nq && ep && nv_isarray(nq) && !nv_getsub(nq)) 29968462SApril.Chin@Sun.COM nv_endsubscript(nq,ep-1,NV_ADD); 29978462SApril.Chin@Sun.COM if(!nr) 2998*10898Sroland.mainz@nrubsig.org { 29998462SApril.Chin@Sun.COM nr= nq = nv_open(cp, hp, flags); 3000*10898Sroland.mainz@nrubsig.org hp = shp->last_root; 3001*10898Sroland.mainz@nrubsig.org } 3002*10898Sroland.mainz@nrubsig.org if(shp->last_root == shp->var_tree && root!=shp->var_tree) 3003*10898Sroland.mainz@nrubsig.org { 3004*10898Sroland.mainz@nrubsig.org _nv_unset(np,NV_RDONLY); 3005*10898Sroland.mainz@nrubsig.org nv_onattr(np,NV_REF); 3006*10898Sroland.mainz@nrubsig.org errormsg(SH_DICT,ERROR_exit(1),e_globalref,nv_name(np)); 3007*10898Sroland.mainz@nrubsig.org } 30084887Schin if(nr==np) 30094887Schin { 30108462SApril.Chin@Sun.COM if(shp->namespace && nv_dict(shp->namespace)==hp) 30114887Schin errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np)); 30124887Schin /* bind to earlier scope, or add to global scope */ 30134887Schin if(!(hp=dtvnext(hp)) || (nq=nv_search((char*)np,hp,NV_ADD|HASH_BUCKET))==np) 30144887Schin errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np)); 30154887Schin } 3016*10898Sroland.mainz@nrubsig.org if(nq && !ep && (ap=nv_arrayptr(nq)) && !(ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN))) 3017*10898Sroland.mainz@nrubsig.org ep = nv_getsub(nq); 30184887Schin if(ep) 30194887Schin { 30204887Schin /* cause subscript evaluation and return result */ 30218462SApril.Chin@Sun.COM if(nv_isarray(nq)) 30228462SApril.Chin@Sun.COM ep = nv_getsub(nq); 30238462SApril.Chin@Sun.COM else 30248462SApril.Chin@Sun.COM { 30258462SApril.Chin@Sun.COM ep[strlen(ep)-1] = 0; 30268462SApril.Chin@Sun.COM nv_putsub(nr, ep, 0); 30278462SApril.Chin@Sun.COM ep[strlen(ep)-1] = ']'; 30288462SApril.Chin@Sun.COM if(nq = nv_opensub(nr)) 30298462SApril.Chin@Sun.COM ep = 0; 30308462SApril.Chin@Sun.COM else 30318462SApril.Chin@Sun.COM nq = nr; 30328462SApril.Chin@Sun.COM } 30334887Schin } 30344887Schin nv_unset(np); 30358462SApril.Chin@Sun.COM nv_delete(np,(Dt_t*)0,0); 30364887Schin np->nvalue.nrp = newof(0,struct Namref,1,0); 30374887Schin np->nvalue.nrp->np = nq; 30384887Schin np->nvalue.nrp->root = hp; 30394887Schin if(ep) 30404887Schin np->nvalue.nrp->sub = strdup(ep); 30418462SApril.Chin@Sun.COM np->nvalue.nrp->table = shp->last_table; 30424887Schin nv_onattr(np,NV_REF|NV_NOFREE); 30434887Schin } 30444887Schin 30454887Schin /* 30464887Schin * get the scope corresponding to <index> 30474887Schin * whence uses the same values as lseeek() 30484887Schin */ 30494887Schin Shscope_t *sh_getscope(int index, int whence) 30504887Schin { 30514887Schin register struct sh_scoped *sp, *topmost; 30524887Schin if(whence==SEEK_CUR) 30534887Schin sp = &sh.st; 30544887Schin else 30554887Schin { 30564887Schin if ((struct sh_scoped*)sh.topscope != sh.st.self) 30574887Schin topmost = (struct sh_scoped*)sh.topscope; 30584887Schin else 30594887Schin topmost = &(sh.st); 30604887Schin sp = topmost; 30614887Schin if(whence==SEEK_SET) 30624887Schin { 30634887Schin int n =0; 30644887Schin while(sp = sp->prevst) 30654887Schin n++; 30664887Schin index = n - index; 30674887Schin sp = topmost; 30684887Schin } 30694887Schin } 30704887Schin if(index < 0) 30714887Schin return((Shscope_t*)0); 30724887Schin while(index-- && (sp = sp->prevst)); 30734887Schin return((Shscope_t*)sp); 30744887Schin } 30754887Schin 30764887Schin /* 30774887Schin * make <scoped> the top scope and return previous scope 30784887Schin */ 30794887Schin Shscope_t *sh_setscope(Shscope_t *scope) 30804887Schin { 30814887Schin Shscope_t *old = (Shscope_t*)sh.st.self; 30824887Schin *sh.st.self = sh.st; 30834887Schin sh.st = *((struct sh_scoped*)scope); 30844887Schin sh.var_tree = scope->var_tree; 30858462SApril.Chin@Sun.COM SH_PATHNAMENOD->nvalue.cp = sh.st.filename; 30868462SApril.Chin@Sun.COM SH_FUNNAMENOD->nvalue.cp = sh.st.funname; 30874887Schin return(old); 30884887Schin } 30894887Schin 30908462SApril.Chin@Sun.COM void sh_unscope(Shell_t *shp) 30914887Schin { 30928462SApril.Chin@Sun.COM register Dt_t *root = shp->var_tree; 30934887Schin register Dt_t *dp = dtview(root,(Dt_t*)0); 30948462SApril.Chin@Sun.COM table_unset(shp,root,NV_RDONLY|NV_NOSCOPE,dp); 30958462SApril.Chin@Sun.COM if(shp->st.real_fun && dp==shp->st.real_fun->sdict) 30968462SApril.Chin@Sun.COM { 30978462SApril.Chin@Sun.COM dp = dtview(dp,(Dt_t*)0); 30988462SApril.Chin@Sun.COM shp->st.real_fun->sdict->view = dp; 30998462SApril.Chin@Sun.COM } 31008462SApril.Chin@Sun.COM shp->var_tree=dp; 31014887Schin dtclose(root); 31024887Schin } 31034887Schin 31044887Schin /* 31054887Schin * The inverse of creating a reference node 31064887Schin */ 31074887Schin void nv_unref(register Namval_t *np) 31084887Schin { 31094887Schin Namval_t *nq; 31104887Schin if(!nv_isref(np)) 31114887Schin return; 3112*10898Sroland.mainz@nrubsig.org nv_offattr(np,NV_NOFREE|NV_REF); 3113*10898Sroland.mainz@nrubsig.org if(!np->nvalue.nrp) 3114*10898Sroland.mainz@nrubsig.org return; 31154887Schin nq = nv_refnode(np); 31164887Schin free((void*)np->nvalue.nrp); 31174887Schin np->nvalue.cp = strdup(nv_name(nq)); 31184887Schin #if SHOPT_OPTIMIZE 31194887Schin { 31204887Schin Namfun_t *fp; 31214887Schin for(fp=nq->nvfun; fp; fp = fp->next) 31224887Schin { 31234887Schin if(fp->disc== &optimize_disc) 31244887Schin { 31254887Schin optimize_clear(nq,fp); 31264887Schin return; 31274887Schin } 31284887Schin } 31294887Schin } 31304887Schin #endif 31314887Schin } 31324887Schin 31334887Schin /* 31344887Schin * These following are for binary compatibility with the old hash library 31354887Schin * They will be removed someday 31364887Schin */ 31374887Schin 31384887Schin #if defined(__IMPORT__) && defined(__EXPORT__) 31394887Schin # define extern __EXPORT__ 31404887Schin #endif 31414887Schin 31424887Schin #undef hashscope 31434887Schin 31444887Schin extern Dt_t *hashscope(Dt_t *root) 31454887Schin { 31464887Schin return(dtvnext(root)); 31474887Schin } 31484887Schin 31494887Schin #undef hashfree 31504887Schin 31514887Schin extern Dt_t *hashfree(Dt_t *root) 31524887Schin { 31534887Schin Dt_t *dp = dtvnext(root); 31544887Schin dtclose(root); 31554887Schin return(dp); 31564887Schin } 31574887Schin 31584887Schin #undef hashname 31594887Schin 31604887Schin extern char *hashname(void *obj) 31614887Schin { 31624887Schin Namval_t *np = (Namval_t*)obj; 31634887Schin return(np->nvname); 31644887Schin } 31654887Schin 31664887Schin #undef hashlook 31674887Schin 31684887Schin extern void *hashlook(Dt_t *root, const char *name, int mode,int size) 31694887Schin { 31704887Schin NOT_USED(size); 31714887Schin return((void*)nv_search(name,root,mode)); 31724887Schin } 31734887Schin 31744887Schin char *nv_name(register Namval_t *np) 31754887Schin { 31764887Schin register Namval_t *table; 31774887Schin register Namfun_t *fp; 31784887Schin char *cp; 31794887Schin if(is_abuiltin(np) || is_afunction(np)) 31804887Schin return(np->nvname); 31818462SApril.Chin@Sun.COM if(!nv_isattr(np,NV_MINIMAL|NV_EXPORT) && np->nvenv) 31828462SApril.Chin@Sun.COM { 31838462SApril.Chin@Sun.COM Namval_t *nq= sh.last_table, *mp= (Namval_t*)np->nvenv; 31848462SApril.Chin@Sun.COM if(np==sh.last_table) 31858462SApril.Chin@Sun.COM sh.last_table = 0; 31868462SApril.Chin@Sun.COM if(nv_isarray(mp)) 31878462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s[%s]",nv_name(mp),np->nvname); 31888462SApril.Chin@Sun.COM else 31898462SApril.Chin@Sun.COM sfprintf(sh.strbuf,"%s.%s",nv_name(mp),np->nvname); 31908462SApril.Chin@Sun.COM sh.last_table = nq; 31918462SApril.Chin@Sun.COM return(sfstruse(sh.strbuf)); 31928462SApril.Chin@Sun.COM } 31934887Schin if(nv_istable(np)) 31944887Schin #if 1 31954887Schin sh.last_table = nv_parent(np); 31964887Schin #else 31974887Schin sh.last_table = nv_create(np,0, NV_LAST,(Namfun_t*)0); 31984887Schin #endif 31994887Schin else if(!nv_isref(np)) 32004887Schin { 32014887Schin for(fp= np->nvfun ; fp; fp=fp->next) 32024887Schin if(fp->disc && fp->disc->namef) 32034887Schin { 32044887Schin if(np==sh.last_table) 32054887Schin sh.last_table = 0; 32064887Schin return((*fp->disc->namef)(np,fp)); 32074887Schin } 32084887Schin } 32094887Schin if(!(table=sh.last_table) || *np->nvname=='.' || table==sh.namespace || np==table) 32104887Schin return(np->nvname); 32114887Schin cp = nv_name(table); 32124887Schin sfprintf(sh.strbuf,"%s.%s",cp,np->nvname); 32134887Schin return(sfstruse(sh.strbuf)); 32144887Schin } 32154887Schin 32164887Schin Namval_t *nv_lastdict(void) 32174887Schin { 32184887Schin return(sh.last_table); 32194887Schin } 32204887Schin 32214887Schin #undef nv_context 32224887Schin /* 32234887Schin * returns the data context for a builtin 32244887Schin */ 32254887Schin void *nv_context(Namval_t *np) 32264887Schin { 32274887Schin return((void*)np->nvfun); 32284887Schin } 32294887Schin 32304887Schin #define DISABLE /* proto workaround */ 32314887Schin 32324887Schin int nv_isnull DISABLE (register Namval_t *np) 32334887Schin { 32344887Schin return(nv_isnull(np)); 32354887Schin } 32364887Schin 32374887Schin #undef nv_setsize 32384887Schin int nv_setsize(register Namval_t *np, int size) 32394887Schin { 32404887Schin int oldsize = nv_size(np); 32414887Schin if(size>=0) 32424887Schin np->nvsize = size; 32434887Schin return(oldsize); 32444887Schin } 32458462SApril.Chin@Sun.COM 32468462SApril.Chin@Sun.COM Shell_t *nv_shell(Namval_t *np) 32478462SApril.Chin@Sun.COM { 32488462SApril.Chin@Sun.COM Namfun_t *fp; 32498462SApril.Chin@Sun.COM for(fp=np->nvfun;fp;fp=fp->next) 32508462SApril.Chin@Sun.COM { 32518462SApril.Chin@Sun.COM if(!fp->disc) 32528462SApril.Chin@Sun.COM return((Shell_t*)fp->last); 32538462SApril.Chin@Sun.COM } 32548462SApril.Chin@Sun.COM return(0); 32558462SApril.Chin@Sun.COM } 32568462SApril.Chin@Sun.COM 32578462SApril.Chin@Sun.COM #undef nv_unset 32588462SApril.Chin@Sun.COM 32598462SApril.Chin@Sun.COM void nv_unset(register Namval_t *np) 32608462SApril.Chin@Sun.COM { 32618462SApril.Chin@Sun.COM _nv_unset(np,0); 32628462SApril.Chin@Sun.COM return; 32638462SApril.Chin@Sun.COM } 3264