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