xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/name.c (revision b30d1939)
1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
18*b30d1939SAndy Fiddaman *                                                                      *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman /*
22*b30d1939SAndy Fiddaman  * AT&T Labs
23*b30d1939SAndy Fiddaman  *
24*b30d1939SAndy Fiddaman  */
25*b30d1939SAndy Fiddaman /*
26*b30d1939SAndy Fiddaman  * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
27*b30d1939SAndy Fiddaman  */
28*b30d1939SAndy Fiddaman 
29*b30d1939SAndy Fiddaman #define putenv	___putenv
30*b30d1939SAndy Fiddaman 
31*b30d1939SAndy Fiddaman #include	"defs.h"
32*b30d1939SAndy Fiddaman #include	"variables.h"
33*b30d1939SAndy Fiddaman #include	"path.h"
34*b30d1939SAndy Fiddaman #include	"lexstates.h"
35*b30d1939SAndy Fiddaman #include	"timeout.h"
36*b30d1939SAndy Fiddaman #include	"FEATURE/externs"
37*b30d1939SAndy Fiddaman #include	"streval.h"
38*b30d1939SAndy Fiddaman 
39*b30d1939SAndy Fiddaman #define NVCACHE		8	/* must be a power of 2 */
40*b30d1939SAndy Fiddaman #define Empty	((char*)(e_sptbnl+3))
41*b30d1939SAndy Fiddaman static char	*savesub = 0;
42*b30d1939SAndy Fiddaman static char	Null[1];
43*b30d1939SAndy Fiddaman static Namval_t	NullNode;
44*b30d1939SAndy Fiddaman static Dt_t	*Refdict;
45*b30d1939SAndy Fiddaman static Dtdisc_t	_Refdisc =
46*b30d1939SAndy Fiddaman {
47*b30d1939SAndy Fiddaman 	offsetof(struct Namref,np),sizeof(struct Namval_t*),sizeof(struct Namref)
48*b30d1939SAndy Fiddaman };
49*b30d1939SAndy Fiddaman 
50*b30d1939SAndy Fiddaman #if !_lib_pathnative && _lib_uwin_path
51*b30d1939SAndy Fiddaman 
52*b30d1939SAndy Fiddaman #define _lib_pathnative		1
53*b30d1939SAndy Fiddaman 
54*b30d1939SAndy Fiddaman extern int	uwin_path(const char*, char*, int);
55*b30d1939SAndy Fiddaman 
56*b30d1939SAndy Fiddaman size_t
pathnative(const char * path,char * buf,size_t siz)57*b30d1939SAndy Fiddaman pathnative(const char* path, char* buf, size_t siz)
58*b30d1939SAndy Fiddaman {
59*b30d1939SAndy Fiddaman 	return uwin_path(path, buf, siz);
60*b30d1939SAndy Fiddaman }
61*b30d1939SAndy Fiddaman 
62*b30d1939SAndy Fiddaman #endif /* _lib_pathnative */
63*b30d1939SAndy Fiddaman 
64*b30d1939SAndy Fiddaman static void	attstore(Namval_t*,void*);
65*b30d1939SAndy Fiddaman #ifndef _ENV_H
66*b30d1939SAndy Fiddaman     static void	pushnam(Namval_t*,void*);
67*b30d1939SAndy Fiddaman     static char	*staknam(Namval_t*, char*);
68*b30d1939SAndy Fiddaman #endif
69*b30d1939SAndy Fiddaman static void	rightjust(char*, int, int);
70*b30d1939SAndy Fiddaman static char	*lastdot(char*, int);
71*b30d1939SAndy Fiddaman 
72*b30d1939SAndy Fiddaman struct adata
73*b30d1939SAndy Fiddaman {
74*b30d1939SAndy Fiddaman 	Shell_t		*sh;
75*b30d1939SAndy Fiddaman 	Namval_t	*tp;
76*b30d1939SAndy Fiddaman 	char		*mapname;
77*b30d1939SAndy Fiddaman 	char		**argnam;
78*b30d1939SAndy Fiddaman 	int		attsize;
79*b30d1939SAndy Fiddaman 	char		*attval;
80*b30d1939SAndy Fiddaman };
81*b30d1939SAndy Fiddaman 
82*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
83*b30d1939SAndy Fiddaman     struct sh_type
84*b30d1939SAndy Fiddaman     {
85*b30d1939SAndy Fiddaman 	void		*previous;
86*b30d1939SAndy Fiddaman 	Namval_t	**nodes;
87*b30d1939SAndy Fiddaman 	Namval_t	*rp;
88*b30d1939SAndy Fiddaman 	short		numnodes;
89*b30d1939SAndy Fiddaman 	short		maxnodes;
90*b30d1939SAndy Fiddaman     };
91*b30d1939SAndy Fiddaman #endif /*SHOPT_TYPEDEF */
92*b30d1939SAndy Fiddaman 
93*b30d1939SAndy Fiddaman #if NVCACHE
94*b30d1939SAndy Fiddaman     struct Namcache
95*b30d1939SAndy Fiddaman     {
96*b30d1939SAndy Fiddaman 	struct Cache_entry
97*b30d1939SAndy Fiddaman 	{
98*b30d1939SAndy Fiddaman 		Dt_t		*root;
99*b30d1939SAndy Fiddaman 		Dt_t		*last_root;
100*b30d1939SAndy Fiddaman 		char		*name;
101*b30d1939SAndy Fiddaman 		Namval_t	*np;
102*b30d1939SAndy Fiddaman 		Namval_t	*last_table;
103*b30d1939SAndy Fiddaman 		Namval_t	*namespace;
104*b30d1939SAndy Fiddaman 		int		flags;
105*b30d1939SAndy Fiddaman 		short		size;
106*b30d1939SAndy Fiddaman 		short		len;
107*b30d1939SAndy Fiddaman 	} entries[NVCACHE];
108*b30d1939SAndy Fiddaman 	short		index;
109*b30d1939SAndy Fiddaman 	short		ok;
110*b30d1939SAndy Fiddaman     };
111*b30d1939SAndy Fiddaman     static struct Namcache nvcache;
112*b30d1939SAndy Fiddaman #endif
113*b30d1939SAndy Fiddaman 
114*b30d1939SAndy Fiddaman char		nv_local = 0;
115*b30d1939SAndy Fiddaman #ifndef _ENV_H
116*b30d1939SAndy Fiddaman static void(*nullscan)(Namval_t*,void*);
117*b30d1939SAndy Fiddaman #endif
118*b30d1939SAndy Fiddaman 
119*b30d1939SAndy Fiddaman #if ( SFIO_VERSION  <= 20010201L )
120*b30d1939SAndy Fiddaman #   define _data        data
121*b30d1939SAndy Fiddaman #endif
122*b30d1939SAndy Fiddaman 
123*b30d1939SAndy Fiddaman #if !SHOPT_MULTIBYTE
124*b30d1939SAndy Fiddaman #   define mbchar(p)       (*(unsigned char*)p++)
125*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
126*b30d1939SAndy Fiddaman 
127*b30d1939SAndy Fiddaman /* ========	name value pair routines	======== */
128*b30d1939SAndy Fiddaman 
129*b30d1939SAndy Fiddaman #include	"shnodes.h"
130*b30d1939SAndy Fiddaman #include	"builtins.h"
131*b30d1939SAndy Fiddaman 
getbuf(size_t len)132*b30d1939SAndy Fiddaman static char *getbuf(size_t len)
133*b30d1939SAndy Fiddaman {
134*b30d1939SAndy Fiddaman 	static char *buf;
135*b30d1939SAndy Fiddaman 	static size_t buflen;
136*b30d1939SAndy Fiddaman 	if(buflen < len)
137*b30d1939SAndy Fiddaman 	{
138*b30d1939SAndy Fiddaman 		if(buflen==0)
139*b30d1939SAndy Fiddaman 			buf = (char*)malloc(len);
140*b30d1939SAndy Fiddaman 		else
141*b30d1939SAndy Fiddaman 			buf = (char*)realloc(buf,len);
142*b30d1939SAndy Fiddaman 		buflen = len;
143*b30d1939SAndy Fiddaman 	}
144*b30d1939SAndy Fiddaman 	return(buf);
145*b30d1939SAndy Fiddaman }
146*b30d1939SAndy Fiddaman 
147*b30d1939SAndy Fiddaman #ifdef _ENV_H
sh_envput(Env_t * ep,Namval_t * np)148*b30d1939SAndy Fiddaman void sh_envput(Env_t* ep,Namval_t *np)
149*b30d1939SAndy Fiddaman {
150*b30d1939SAndy Fiddaman 	int offset = staktell();
151*b30d1939SAndy Fiddaman 	Namarr_t *ap = nv_arrayptr(np);
152*b30d1939SAndy Fiddaman 	char *val;
153*b30d1939SAndy Fiddaman 	if(ap)
154*b30d1939SAndy Fiddaman 	{
155*b30d1939SAndy Fiddaman 		if(ap->nelem&ARRAY_UNDEF)
156*b30d1939SAndy Fiddaman 			nv_putsub(np,"0",0L);
157*b30d1939SAndy Fiddaman 		else if(!(val=nv_getsub(np)) || strcmp(val,"0"))
158*b30d1939SAndy Fiddaman 			return;
159*b30d1939SAndy Fiddaman 	}
160*b30d1939SAndy Fiddaman 	if(!(val = nv_getval(np)))
161*b30d1939SAndy Fiddaman 		return;
162*b30d1939SAndy Fiddaman 	stakputs(nv_name(np));
163*b30d1939SAndy Fiddaman 	stakputc('=');
164*b30d1939SAndy Fiddaman 	stakputs(val);
165*b30d1939SAndy Fiddaman 	stakseek(offset);
166*b30d1939SAndy Fiddaman 	env_add(ep,stakptr(offset),ENV_STRDUP);
167*b30d1939SAndy Fiddaman }
168*b30d1939SAndy Fiddaman #endif
169*b30d1939SAndy Fiddaman 
170*b30d1939SAndy Fiddaman /*
171*b30d1939SAndy Fiddaman  * output variable name in format for re-input
172*b30d1939SAndy Fiddaman  */
nv_outname(Sfio_t * out,char * name,int len)173*b30d1939SAndy Fiddaman void nv_outname(Sfio_t *out, char *name, int len)
174*b30d1939SAndy Fiddaman {
175*b30d1939SAndy Fiddaman 	const char *cp=name, *sp;
176*b30d1939SAndy Fiddaman 	int c, offset = staktell();
177*b30d1939SAndy Fiddaman 	while(sp= strchr(cp,'['))
178*b30d1939SAndy Fiddaman 	{
179*b30d1939SAndy Fiddaman 		if(len>0 && cp+len <= sp)
180*b30d1939SAndy Fiddaman 			break;
181*b30d1939SAndy Fiddaman 		sfwrite(out,cp,++sp-cp);
182*b30d1939SAndy Fiddaman 		stakseek(offset);
183*b30d1939SAndy Fiddaman 		while(c= *sp++)
184*b30d1939SAndy Fiddaman 		{
185*b30d1939SAndy Fiddaman 			if(c==']')
186*b30d1939SAndy Fiddaman 				break;
187*b30d1939SAndy Fiddaman 			else if(c=='\\')
188*b30d1939SAndy Fiddaman 			{
189*b30d1939SAndy Fiddaman 				if(*sp=='[' || *sp==']' || *sp=='\\')
190*b30d1939SAndy Fiddaman 					c = *sp++;
191*b30d1939SAndy Fiddaman 			}
192*b30d1939SAndy Fiddaman 			stakputc(c);
193*b30d1939SAndy Fiddaman 		}
194*b30d1939SAndy Fiddaman 		stakputc(0);
195*b30d1939SAndy Fiddaman 		sfputr(out,sh_fmtq(stakptr(offset)),-1);
196*b30d1939SAndy Fiddaman 		if(len>0)
197*b30d1939SAndy Fiddaman 		{
198*b30d1939SAndy Fiddaman 			sfputc(out,']');
199*b30d1939SAndy Fiddaman 			return;
200*b30d1939SAndy Fiddaman 		}
201*b30d1939SAndy Fiddaman 		cp = sp-1;
202*b30d1939SAndy Fiddaman 	}
203*b30d1939SAndy Fiddaman 	if(*cp)
204*b30d1939SAndy Fiddaman 	{
205*b30d1939SAndy Fiddaman 		if(len>0)
206*b30d1939SAndy Fiddaman 			sfwrite(out,cp,len);
207*b30d1939SAndy Fiddaman 		else
208*b30d1939SAndy Fiddaman 			sfputr(out,cp,-1);
209*b30d1939SAndy Fiddaman 	}
210*b30d1939SAndy Fiddaman 	stakseek(offset);
211*b30d1939SAndy Fiddaman }
212*b30d1939SAndy Fiddaman 
213*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
nv_addnode(Namval_t * np,int remove)214*b30d1939SAndy Fiddaman Namval_t *nv_addnode(Namval_t* np, int remove)
215*b30d1939SAndy Fiddaman {
216*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
217*b30d1939SAndy Fiddaman 	register struct sh_type	*sp = (struct sh_type*)shp->mktype;
218*b30d1939SAndy Fiddaman 	register int		i;
219*b30d1939SAndy Fiddaman 	register char		*name=0;
220*b30d1939SAndy Fiddaman 	if(sp->numnodes==0 && !nv_isnull(np) && shp->last_table)
221*b30d1939SAndy Fiddaman 	{
222*b30d1939SAndy Fiddaman 		/* could be an redefine */
223*b30d1939SAndy Fiddaman 		Dt_t *root = nv_dict(shp->last_table);
224*b30d1939SAndy Fiddaman 		sp->rp = np;
225*b30d1939SAndy Fiddaman 		nv_delete(np,root,NV_NOFREE);
226*b30d1939SAndy Fiddaman 		np = nv_search(sp->rp->nvname,root,NV_ADD);
227*b30d1939SAndy Fiddaman 	}
228*b30d1939SAndy Fiddaman 	if(sp->numnodes && memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1))
229*b30d1939SAndy Fiddaman 	{
230*b30d1939SAndy Fiddaman 		name = (sp->nodes[0])->nvname;
231*b30d1939SAndy Fiddaman 		i = strlen(name);
232*b30d1939SAndy Fiddaman 		if(memcmp(np->nvname,name,i))
233*b30d1939SAndy Fiddaman 			return(np);
234*b30d1939SAndy Fiddaman 	}
235*b30d1939SAndy Fiddaman 	if(sp->rp && sp->numnodes)
236*b30d1939SAndy Fiddaman 	{
237*b30d1939SAndy Fiddaman 		/* check for a redefine */
238*b30d1939SAndy Fiddaman 		if(name && np->nvname[i]=='.' && np->nvname[i+1]=='_' && np->nvname[i+2]==0)
239*b30d1939SAndy Fiddaman 			sp->rp = 0;
240*b30d1939SAndy Fiddaman 		else
241*b30d1939SAndy Fiddaman 		{
242*b30d1939SAndy Fiddaman 			Dt_t *root = nv_dict(shp->last_table);
243*b30d1939SAndy Fiddaman 			nv_delete(sp->nodes[0],root,NV_NOFREE);
244*b30d1939SAndy Fiddaman 			dtinsert(root,sp->rp);
245*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_redef,sp->nodes[0]->nvname);
246*b30d1939SAndy Fiddaman 		}
247*b30d1939SAndy Fiddaman 	}
248*b30d1939SAndy Fiddaman 	for(i=0; i < sp->numnodes; i++)
249*b30d1939SAndy Fiddaman 	{
250*b30d1939SAndy Fiddaman 		if(np == sp->nodes[i])
251*b30d1939SAndy Fiddaman 		{
252*b30d1939SAndy Fiddaman 			if(remove)
253*b30d1939SAndy Fiddaman 			{
254*b30d1939SAndy Fiddaman 				while(++i < sp->numnodes)
255*b30d1939SAndy Fiddaman 					sp->nodes[i-1] = sp->nodes[i];
256*b30d1939SAndy Fiddaman 				sp->numnodes--;
257*b30d1939SAndy Fiddaman 			}
258*b30d1939SAndy Fiddaman 			return(np);
259*b30d1939SAndy Fiddaman 		}
260*b30d1939SAndy Fiddaman 	}
261*b30d1939SAndy Fiddaman 	if(remove)
262*b30d1939SAndy Fiddaman 		return(np);
263*b30d1939SAndy Fiddaman 	if(sp->numnodes==sp->maxnodes)
264*b30d1939SAndy Fiddaman 	{
265*b30d1939SAndy Fiddaman 		sp->maxnodes += 20;
266*b30d1939SAndy Fiddaman 		sp->nodes = (Namval_t**)realloc(sp->nodes,sizeof(Namval_t*)*sp->maxnodes);
267*b30d1939SAndy Fiddaman 	}
268*b30d1939SAndy Fiddaman 	sp->nodes[sp->numnodes++] = np;
269*b30d1939SAndy Fiddaman 	return(np);
270*b30d1939SAndy Fiddaman }
271*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
272*b30d1939SAndy Fiddaman 
273*b30d1939SAndy Fiddaman /*
274*b30d1939SAndy Fiddaman  * given a list of assignments, determine <name> is on the list
275*b30d1939SAndy Fiddaman    returns a pointer to the argnod on the list or NULL
276*b30d1939SAndy Fiddaman  */
nv_onlist(struct argnod * arg,const char * name)277*b30d1939SAndy Fiddaman struct argnod *nv_onlist(struct argnod *arg, const char *name)
278*b30d1939SAndy Fiddaman {
279*b30d1939SAndy Fiddaman 	char *cp;
280*b30d1939SAndy Fiddaman 	int len = strlen(name);
281*b30d1939SAndy Fiddaman 	for(;arg; arg=arg->argnxt.ap)
282*b30d1939SAndy Fiddaman 	{
283*b30d1939SAndy Fiddaman 		if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE)))
284*b30d1939SAndy Fiddaman 			cp = ((struct fornod*)arg->argchn.ap)->fornam;
285*b30d1939SAndy Fiddaman 		else
286*b30d1939SAndy Fiddaman 			cp = arg->argval;
287*b30d1939SAndy Fiddaman 		if(memcmp(cp,name,len)==0 && (cp[len]==0 || cp[len]=='='))
288*b30d1939SAndy Fiddaman 			return(arg);
289*b30d1939SAndy Fiddaman 	}
290*b30d1939SAndy Fiddaman 	return(0);
291*b30d1939SAndy Fiddaman }
292*b30d1939SAndy Fiddaman 
293*b30d1939SAndy Fiddaman /*
294*b30d1939SAndy Fiddaman  * Perform parameter assignment for a linked list of parameters
295*b30d1939SAndy Fiddaman  * <flags> contains attributes for the parameters
296*b30d1939SAndy Fiddaman  */
nv_setlist(register struct argnod * arg,register int flags,Namval_t * typ)297*b30d1939SAndy Fiddaman void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
298*b30d1939SAndy Fiddaman {
299*b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
300*b30d1939SAndy Fiddaman 	register char	*cp;
301*b30d1939SAndy Fiddaman 	register Namval_t *np, *mp;
302*b30d1939SAndy Fiddaman 	char		*trap=shp->st.trap[SH_DEBUGTRAP];
303*b30d1939SAndy Fiddaman 	char		*prefix = shp->prefix;
304*b30d1939SAndy Fiddaman 	int		traceon = (sh_isoption(SH_XTRACE)!=0);
305*b30d1939SAndy Fiddaman 	int		array = (flags&(NV_ARRAY|NV_IARRAY));
306*b30d1939SAndy Fiddaman 	Namarr_t	*ap;
307*b30d1939SAndy Fiddaman 	Namval_t	node;
308*b30d1939SAndy Fiddaman 	struct Namref	nr;
309*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
310*b30d1939SAndy Fiddaman 	int		maketype = flags&NV_TYPE;
311*b30d1939SAndy Fiddaman 	struct sh_type	shtp;
312*b30d1939SAndy Fiddaman 	if(maketype)
313*b30d1939SAndy Fiddaman 	{
314*b30d1939SAndy Fiddaman 		shtp.previous = shp->mktype;
315*b30d1939SAndy Fiddaman 		shp->mktype=(void*)&shtp;
316*b30d1939SAndy Fiddaman 		shtp.numnodes=0;
317*b30d1939SAndy Fiddaman 		shtp.maxnodes = 20;
318*b30d1939SAndy Fiddaman 		shtp.rp = 0;
319*b30d1939SAndy Fiddaman 		shtp.nodes =(Namval_t**)malloc(shtp.maxnodes*sizeof(Namval_t*));
320*b30d1939SAndy Fiddaman 	}
321*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF*/
322*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
323*b30d1939SAndy Fiddaman 	if(shp->namespace && nv_dict(shp->namespace)==shp->var_tree)
324*b30d1939SAndy Fiddaman 		flags |= NV_NOSCOPE;
325*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
326*b30d1939SAndy Fiddaman 	flags &= ~(NV_TYPE|NV_ARRAY|NV_IARRAY);
327*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_ALLEXPORT))
328*b30d1939SAndy Fiddaman 		flags |= NV_EXPORT;
329*b30d1939SAndy Fiddaman 	if(shp->prefix)
330*b30d1939SAndy Fiddaman 	{
331*b30d1939SAndy Fiddaman 		flags &= ~(NV_IDENT|NV_EXPORT);
332*b30d1939SAndy Fiddaman 		flags |= NV_VARNAME;
333*b30d1939SAndy Fiddaman 	}
334*b30d1939SAndy Fiddaman 	else
335*b30d1939SAndy Fiddaman 		shp->prefix_root = shp->first_root = 0;
336*b30d1939SAndy Fiddaman 	for(;arg; arg=arg->argnxt.ap)
337*b30d1939SAndy Fiddaman 	{
338*b30d1939SAndy Fiddaman 		shp->used_pos = 0;
339*b30d1939SAndy Fiddaman 		if(arg->argflag&ARG_MAC)
340*b30d1939SAndy Fiddaman 		{
341*b30d1939SAndy Fiddaman 			shp->prefix = 0;
342*b30d1939SAndy Fiddaman 			cp = sh_mactrim(shp,arg->argval,(flags&NV_NOREF)?-3:-1);
343*b30d1939SAndy Fiddaman 			shp->prefix = prefix;
344*b30d1939SAndy Fiddaman 		}
345*b30d1939SAndy Fiddaman 		else
346*b30d1939SAndy Fiddaman 		{
347*b30d1939SAndy Fiddaman 			stakseek(0);
348*b30d1939SAndy Fiddaman 			if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE)))
349*b30d1939SAndy Fiddaman 			{
350*b30d1939SAndy Fiddaman 				int flag = (NV_VARNAME|NV_ARRAY|NV_ASSIGN);
351*b30d1939SAndy Fiddaman 				int sub=0;
352*b30d1939SAndy Fiddaman 				struct fornod *fp=(struct fornod*)arg->argchn.ap;
353*b30d1939SAndy Fiddaman 				register Shnode_t *tp=fp->fortre;
354*b30d1939SAndy Fiddaman 				flag |= (flags&(NV_NOSCOPE|NV_STATIC|NV_FARRAY));
355*b30d1939SAndy Fiddaman 				if(arg->argflag&ARG_QUOTED)
356*b30d1939SAndy Fiddaman 					cp = sh_mactrim(shp,fp->fornam,-1);
357*b30d1939SAndy Fiddaman 				else
358*b30d1939SAndy Fiddaman 					cp = fp->fornam;
359*b30d1939SAndy Fiddaman 				error_info.line = fp->fortyp-shp->st.firstline;
360*b30d1939SAndy Fiddaman 				if(!array && tp->tre.tretyp!=TLST && tp->com.comset && !tp->com.comarg && tp->com.comset->argval[0]==0 && tp->com.comset->argval[1]=='[')
361*b30d1939SAndy Fiddaman 					array |= (tp->com.comset->argflag&ARG_MESSAGE)?NV_IARRAY:NV_ARRAY;
362*b30d1939SAndy Fiddaman 				if(prefix && tp->com.comset && *cp=='[')
363*b30d1939SAndy Fiddaman 				{
364*b30d1939SAndy Fiddaman 					shp->prefix = 0;
365*b30d1939SAndy Fiddaman 					np = nv_open(prefix,shp->last_root,flag);
366*b30d1939SAndy Fiddaman 					shp->prefix = prefix;
367*b30d1939SAndy Fiddaman 					if(np)
368*b30d1939SAndy Fiddaman 					{
369*b30d1939SAndy Fiddaman 						if(nv_isvtree(np) && !nv_isarray(np))
370*b30d1939SAndy Fiddaman 						{
371*b30d1939SAndy Fiddaman 							stakputc('.');
372*b30d1939SAndy Fiddaman 							stakputs(cp);
373*b30d1939SAndy Fiddaman 							cp = stakfreeze(1);
374*b30d1939SAndy Fiddaman 						}
375*b30d1939SAndy Fiddaman 						nv_close(np);
376*b30d1939SAndy Fiddaman 					}
377*b30d1939SAndy Fiddaman 				}
378*b30d1939SAndy Fiddaman 				np = nv_open(cp,shp->var_tree,flag|NV_ASSIGN);
379*b30d1939SAndy Fiddaman 				if((arg->argflag&ARG_APPEND) && (tp->tre.tretyp&COMMSK)==TCOM && tp->com.comset && !nv_isvtree(np) && (((ap=nv_arrayptr(np)) && !ap->fun && !nv_opensub(np))  || (!ap && nv_isarray(np) && tp->com.comarg && !((mp=nv_search(tp->com.comarg->argval,shp->fun_tree,0)) && nv_isattr(mp,BLT_DCL)))))
380*b30d1939SAndy Fiddaman 				{
381*b30d1939SAndy Fiddaman 					if(tp->com.comarg)
382*b30d1939SAndy Fiddaman 					{
383*b30d1939SAndy Fiddaman 						struct argnod *ap = tp->com.comset;
384*b30d1939SAndy Fiddaman 						while(ap->argnxt.ap)
385*b30d1939SAndy Fiddaman 							ap = ap->argnxt.ap;
386*b30d1939SAndy Fiddaman 						ap->argnxt.ap = tp->com.comarg;
387*b30d1939SAndy Fiddaman 
388*b30d1939SAndy Fiddaman 					}
389*b30d1939SAndy Fiddaman 					tp->com.comarg = tp->com.comset;
390*b30d1939SAndy Fiddaman 					tp->com.comset = 0;
391*b30d1939SAndy Fiddaman 					tp->com.comtyp = COMSCAN;
392*b30d1939SAndy Fiddaman 				}
393*b30d1939SAndy Fiddaman 				if(nv_isattr(np,NV_RDONLY) && np->nvfun && !(flags&NV_RDONLY))
394*b30d1939SAndy Fiddaman 					errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
395*b30d1939SAndy Fiddaman 				if(nv_isattr(np,NV_NOFREE) && nv_isnull(np))
396*b30d1939SAndy Fiddaman 					nv_offattr(np,NV_NOFREE);
397*b30d1939SAndy Fiddaman 				if(nv_istable(np))
398*b30d1939SAndy Fiddaman 					_nv_unset(np,0);
399*b30d1939SAndy Fiddaman 				if(typ && !array  && (!shp->prefix || nv_isnull(np) || nv_isarray(np)))
400*b30d1939SAndy Fiddaman 				{
401*b30d1939SAndy Fiddaman 					if(!(nv_isnull(np)) && !nv_isarray(np))
402*b30d1939SAndy Fiddaman 						_nv_unset(np,0);
403*b30d1939SAndy Fiddaman 					 nv_settype(np,typ,0);
404*b30d1939SAndy Fiddaman 				}
405*b30d1939SAndy Fiddaman 				if((flags&NV_STATIC) && !nv_isattr(np,NV_EXPORT) && !nv_isnull(np))
406*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
407*b30d1939SAndy Fiddaman 					goto check_type;
408*b30d1939SAndy Fiddaman #else
409*b30d1939SAndy Fiddaman 					continue;
410*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
411*b30d1939SAndy Fiddaman 				ap=nv_arrayptr(np);
412*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
413*b30d1939SAndy Fiddaman 				if(ap && ap->fixed)
414*b30d1939SAndy Fiddaman 					flags |= NV_FARRAY;
415*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
416*b30d1939SAndy Fiddaman 				if(array && (!ap || !ap->hdr.type))
417*b30d1939SAndy Fiddaman 				{
418*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
419*b30d1939SAndy Fiddaman 					if(!(arg->argflag&ARG_APPEND) && (!ap || !ap->fixed))
420*b30d1939SAndy Fiddaman #else
421*b30d1939SAndy Fiddaman 					if(!(arg->argflag&ARG_APPEND))
422*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
423*b30d1939SAndy Fiddaman 						_nv_unset(np,NV_EXPORT);
424*b30d1939SAndy Fiddaman 					if(array&NV_ARRAY)
425*b30d1939SAndy Fiddaman 					{
426*b30d1939SAndy Fiddaman 						nv_setarray(np,nv_associative);
427*b30d1939SAndy Fiddaman 					}
428*b30d1939SAndy Fiddaman 					else
429*b30d1939SAndy Fiddaman 					{
430*b30d1939SAndy Fiddaman 						nv_onattr(np,NV_ARRAY);
431*b30d1939SAndy Fiddaman 					}
432*b30d1939SAndy Fiddaman 				}
433*b30d1939SAndy Fiddaman 				if(array && tp->tre.tretyp!=TLST && !tp->com.comset && !tp->com.comarg)
434*b30d1939SAndy Fiddaman 				{
435*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
436*b30d1939SAndy Fiddaman 						goto check_type;
437*b30d1939SAndy Fiddaman #else
438*b30d1939SAndy Fiddaman 						continue;
439*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
440*b30d1939SAndy Fiddaman 				}
441*b30d1939SAndy Fiddaman 				/* check for array assignment */
442*b30d1939SAndy Fiddaman 				if(tp->tre.tretyp!=TLST && tp->com.comarg && !tp->com.comset && ((array&NV_IARRAY) || !((mp=tp->com.comnamp) && nv_isattr(mp,BLT_DCL))))
443*b30d1939SAndy Fiddaman 				{
444*b30d1939SAndy Fiddaman 					int argc;
445*b30d1939SAndy Fiddaman 					Dt_t	*last_root = shp->last_root;
446*b30d1939SAndy Fiddaman 					char **argv = sh_argbuild(shp,&argc,&tp->com,0);
447*b30d1939SAndy Fiddaman 					shp->last_root = last_root;
448*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
449*b30d1939SAndy Fiddaman 					if(shp->mktype && shp->dot_depth==0 && np==((struct sh_type*)shp->mktype)->nodes[0])
450*b30d1939SAndy Fiddaman 					{
451*b30d1939SAndy Fiddaman 						shp->mktype = 0;
452*b30d1939SAndy Fiddaman 						errormsg(SH_DICT,ERROR_exit(1),"%s: not a known type name",argv[0]);
453*b30d1939SAndy Fiddaman 					}
454*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
455*b30d1939SAndy Fiddaman 					if(!(arg->argflag&ARG_APPEND))
456*b30d1939SAndy Fiddaman 					{
457*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
458*b30d1939SAndy Fiddaman 						if(!nv_isarray(np) || ((ap=nv_arrayptr(np)) && !ap->fixed && (ap->nelem&ARRAY_MASK)))
459*b30d1939SAndy Fiddaman #else
460*b30d1939SAndy Fiddaman 						if(!nv_isarray(np) || ((ap=nv_arrayptr(np)) && (ap->nelem&ARRAY_MASK)))
461*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
462*b30d1939SAndy Fiddaman 						{
463*b30d1939SAndy Fiddaman 							if(ap)
464*b30d1939SAndy Fiddaman 								ap->nelem |= ARRAY_UNDEF;
465*b30d1939SAndy Fiddaman 							_nv_unset(np,NV_EXPORT);
466*b30d1939SAndy Fiddaman 						}
467*b30d1939SAndy Fiddaman 					}
468*b30d1939SAndy Fiddaman 					nv_setvec(np,(arg->argflag&ARG_APPEND),argc,argv);
469*b30d1939SAndy Fiddaman 					if(traceon || trap)
470*b30d1939SAndy Fiddaman 					{
471*b30d1939SAndy Fiddaman 						int n = -1;
472*b30d1939SAndy Fiddaman 						char *name = nv_name(np);
473*b30d1939SAndy Fiddaman 						if(arg->argflag&ARG_APPEND)
474*b30d1939SAndy Fiddaman 							n = '+';
475*b30d1939SAndy Fiddaman 						if(trap)
476*b30d1939SAndy Fiddaman 							sh_debug(shp,trap,name,(char*)0,argv,(arg->argflag&ARG_APPEND)|ARG_ASSIGN);
477*b30d1939SAndy Fiddaman 						if(traceon)
478*b30d1939SAndy Fiddaman 						{
479*b30d1939SAndy Fiddaman 							sh_trace(shp,NIL(char**),0);
480*b30d1939SAndy Fiddaman 							sfputr(sfstderr,name,n);
481*b30d1939SAndy Fiddaman 							sfwrite(sfstderr,"=( ",3);
482*b30d1939SAndy Fiddaman 							while(cp= *argv++)
483*b30d1939SAndy Fiddaman 								sfputr(sfstderr,sh_fmtq(cp),' ');
484*b30d1939SAndy Fiddaman 							sfwrite(sfstderr,")\n",2);
485*b30d1939SAndy Fiddaman 						}
486*b30d1939SAndy Fiddaman 					}
487*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
488*b30d1939SAndy Fiddaman 					goto check_type;
489*b30d1939SAndy Fiddaman #else
490*b30d1939SAndy Fiddaman 					continue;
491*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
492*b30d1939SAndy Fiddaman 				}
493*b30d1939SAndy Fiddaman 				if((tp->tre.tretyp&COMMSK)==TFUN)
494*b30d1939SAndy Fiddaman 					goto skip;
495*b30d1939SAndy Fiddaman 				if(tp->tre.tretyp==0 && !tp->com.comset && !tp->com.comarg)
496*b30d1939SAndy Fiddaman 				{
497*b30d1939SAndy Fiddaman 					if(!(arg->argflag&ARG_APPEND) && nv_isattr(np,NV_BINARY|NV_NOFREE|NV_RAW)!=(NV_BINARY|NV_NOFREE|NV_RAW))
498*b30d1939SAndy Fiddaman 						_nv_unset(np,NV_EXPORT);
499*b30d1939SAndy Fiddaman 					goto skip;
500*b30d1939SAndy Fiddaman 				}
501*b30d1939SAndy Fiddaman 				if(tp->tre.tretyp==TLST || !tp->com.comset || tp->com.comset->argval[0]!='[')
502*b30d1939SAndy Fiddaman 				{
503*b30d1939SAndy Fiddaman 					if(tp->tre.tretyp!=TLST && !tp->com.comnamp && tp->com.comset && tp->com.comset->argval[0]==0 && tp->com.comset->argchn.ap)
504*b30d1939SAndy Fiddaman 					{
505*b30d1939SAndy Fiddaman 						if(prefix || np)
506*b30d1939SAndy Fiddaman 							cp = stakcopy(nv_name(np));
507*b30d1939SAndy Fiddaman 						shp->prefix = cp;
508*b30d1939SAndy Fiddaman 						if(tp->com.comset->argval[1]=='[')
509*b30d1939SAndy Fiddaman 						{
510*b30d1939SAndy Fiddaman 							if((arg->argflag&ARG_APPEND) && (!nv_isarray(np) || (nv_aindex(np)>=0)))
511*b30d1939SAndy Fiddaman 								_nv_unset(np,0);
512*b30d1939SAndy Fiddaman 							if(!(array&NV_IARRAY) && !(tp->com.comset->argflag&ARG_MESSAGE))
513*b30d1939SAndy Fiddaman 								nv_setarray(np,nv_associative);
514*b30d1939SAndy Fiddaman 						}
515*b30d1939SAndy Fiddaman 						nv_setlist(tp->com.comset,flags&~NV_STATIC,0);
516*b30d1939SAndy Fiddaman 						shp->prefix = prefix;
517*b30d1939SAndy Fiddaman 						if(tp->com.comset->argval[1]!='[')
518*b30d1939SAndy Fiddaman 							 nv_setvtree(np);
519*b30d1939SAndy Fiddaman 						nv_close(np);
520*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
521*b30d1939SAndy Fiddaman 						goto check_type;
522*b30d1939SAndy Fiddaman #else
523*b30d1939SAndy Fiddaman 						continue;
524*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
525*b30d1939SAndy Fiddaman 					}
526*b30d1939SAndy Fiddaman 					if(*cp!='.' && *cp!='[' && strchr(cp,'['))
527*b30d1939SAndy Fiddaman 					{
528*b30d1939SAndy Fiddaman 						cp = stakcopy(nv_name(np));
529*b30d1939SAndy Fiddaman 						nv_close(np);
530*b30d1939SAndy Fiddaman 						if(!(arg->argflag&ARG_APPEND))
531*b30d1939SAndy Fiddaman 							flag &= ~NV_ARRAY;
532*b30d1939SAndy Fiddaman 						shp->prefix_root = shp->first_root;
533*b30d1939SAndy Fiddaman 						np = nv_open(cp,shp->prefix_root?shp->prefix_root:shp->var_tree,flag);
534*b30d1939SAndy Fiddaman 					}
535*b30d1939SAndy Fiddaman 					if(arg->argflag&ARG_APPEND)
536*b30d1939SAndy Fiddaman 					{
537*b30d1939SAndy Fiddaman 						if(nv_isarray(np))
538*b30d1939SAndy Fiddaman 						{
539*b30d1939SAndy Fiddaman 							if((sub=nv_aimax(np)) < 0  && nv_arrayptr(np))
540*b30d1939SAndy Fiddaman 								errormsg(SH_DICT,ERROR_exit(1),e_badappend,nv_name(np));
541*b30d1939SAndy Fiddaman 							if(sub>=0)
542*b30d1939SAndy Fiddaman 								sub++;
543*b30d1939SAndy Fiddaman 						}
544*b30d1939SAndy Fiddaman 						if(!nv_isnull(np) && np->nvalue.cp!=Empty && !nv_isvtree(np))
545*b30d1939SAndy Fiddaman 							sub=1;
546*b30d1939SAndy Fiddaman 					}
547*b30d1939SAndy Fiddaman 					else if(((np->nvalue.cp && np->nvalue.cp!=Empty)||nv_isvtree(np)|| nv_arrayptr(np)) && !nv_type(np))
548*b30d1939SAndy Fiddaman 					{
549*b30d1939SAndy Fiddaman 						_nv_unset(np,NV_EXPORT);
550*b30d1939SAndy Fiddaman 						if(ap && ap->fun)
551*b30d1939SAndy Fiddaman 							 nv_setarray(np,nv_associative);
552*b30d1939SAndy Fiddaman 
553*b30d1939SAndy Fiddaman 					}
554*b30d1939SAndy Fiddaman 				}
555*b30d1939SAndy Fiddaman 				else
556*b30d1939SAndy Fiddaman 				{
557*b30d1939SAndy Fiddaman 					if(!(arg->argflag&ARG_APPEND))
558*b30d1939SAndy Fiddaman 						_nv_unset(np,NV_EXPORT);
559*b30d1939SAndy Fiddaman 					if(!sh_isoption(SH_BASH) && !(array&NV_IARRAY) && !nv_isarray(np))
560*b30d1939SAndy Fiddaman 						nv_setarray(np,nv_associative);
561*b30d1939SAndy Fiddaman 				}
562*b30d1939SAndy Fiddaman 			skip:
563*b30d1939SAndy Fiddaman 				if(sub>0)
564*b30d1939SAndy Fiddaman 				{
565*b30d1939SAndy Fiddaman 					sfprintf(stkstd,"%s[%d]",prefix?nv_name(np):cp,sub);
566*b30d1939SAndy Fiddaman 					shp->prefix = stakfreeze(1);
567*b30d1939SAndy Fiddaman 					nv_putsub(np,(char*)0,ARRAY_ADD|ARRAY_FILL|sub);
568*b30d1939SAndy Fiddaman 				}
569*b30d1939SAndy Fiddaman 				else if(prefix)
570*b30d1939SAndy Fiddaman 					shp->prefix = stakcopy(nv_name(np));
571*b30d1939SAndy Fiddaman 				else
572*b30d1939SAndy Fiddaman 					shp->prefix = cp;
573*b30d1939SAndy Fiddaman 				shp->last_table = 0;
574*b30d1939SAndy Fiddaman 				if(shp->prefix)
575*b30d1939SAndy Fiddaman 				{
576*b30d1939SAndy Fiddaman 					if(*shp->prefix=='_' && shp->prefix[1]=='.' && nv_isref(L_ARGNOD))
577*b30d1939SAndy Fiddaman 					{
578*b30d1939SAndy Fiddaman 						sfprintf(stkstd,"%s%s",nv_name(L_ARGNOD->nvalue.nrp->np),shp->prefix+1);
579*b30d1939SAndy Fiddaman 						shp->prefix = stkfreeze(stkstd,1);
580*b30d1939SAndy Fiddaman 					}
581*b30d1939SAndy Fiddaman 					memset(&nr,0,sizeof(nr));
582*b30d1939SAndy Fiddaman 					memcpy(&node,L_ARGNOD,sizeof(node));
583*b30d1939SAndy Fiddaman 					L_ARGNOD->nvalue.nrp = &nr;
584*b30d1939SAndy Fiddaman 					nr.np = np;
585*b30d1939SAndy Fiddaman 					nr.root = shp->last_root;
586*b30d1939SAndy Fiddaman 					nr.table = shp->last_table;
587*b30d1939SAndy Fiddaman 					L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
588*b30d1939SAndy Fiddaman 					L_ARGNOD->nvfun = 0;
589*b30d1939SAndy Fiddaman 				}
590*b30d1939SAndy Fiddaman 				sh_exec(tp,sh_isstate(SH_ERREXIT));
591*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
592*b30d1939SAndy Fiddaman 				if(shp->prefix)
593*b30d1939SAndy Fiddaman #endif
594*b30d1939SAndy Fiddaman 				{
595*b30d1939SAndy Fiddaman 					L_ARGNOD->nvalue.nrp = node.nvalue.nrp;
596*b30d1939SAndy Fiddaman 					L_ARGNOD->nvflag = node.nvflag;
597*b30d1939SAndy Fiddaman 					L_ARGNOD->nvfun = node.nvfun;
598*b30d1939SAndy Fiddaman 				}
599*b30d1939SAndy Fiddaman 				shp->prefix = prefix;
600*b30d1939SAndy Fiddaman 				if(nv_isarray(np) && (mp=nv_opensub(np)))
601*b30d1939SAndy Fiddaman 					np = mp;
602*b30d1939SAndy Fiddaman 				while(tp->tre.tretyp==TLST)
603*b30d1939SAndy Fiddaman 				{
604*b30d1939SAndy Fiddaman 					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]!='[')
605*b30d1939SAndy Fiddaman 						break;
606*b30d1939SAndy Fiddaman 					tp = tp->lst.lstrit;
607*b30d1939SAndy Fiddaman 
608*b30d1939SAndy Fiddaman 				}
609*b30d1939SAndy Fiddaman 				if(!nv_isarray(np) && !typ && (tp->com.comarg || !tp->com.comset || tp->com.comset->argval[0]!='['))
610*b30d1939SAndy Fiddaman 				{
611*b30d1939SAndy Fiddaman 					nv_setvtree(np);
612*b30d1939SAndy Fiddaman 					if(tp->com.comarg || tp->com.comset)
613*b30d1939SAndy Fiddaman 						np->nvfun->dsize = 0;
614*b30d1939SAndy Fiddaman 				}
615*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
616*b30d1939SAndy Fiddaman 				goto check_type;
617*b30d1939SAndy Fiddaman #else
618*b30d1939SAndy Fiddaman 				continue;
619*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
620*b30d1939SAndy Fiddaman 			}
621*b30d1939SAndy Fiddaman 			cp = arg->argval;
622*b30d1939SAndy Fiddaman 			mp = 0;
623*b30d1939SAndy Fiddaman 		}
624*b30d1939SAndy Fiddaman 		np = nv_open(cp,shp->prefix_root?shp->prefix_root:shp->var_tree,flags);
625*b30d1939SAndy Fiddaman 		if(!np->nvfun && (flags&NV_NOREF))
626*b30d1939SAndy Fiddaman 		{
627*b30d1939SAndy Fiddaman 			if(shp->used_pos)
628*b30d1939SAndy Fiddaman 				nv_onattr(np,NV_PARAM);
629*b30d1939SAndy Fiddaman 			else
630*b30d1939SAndy Fiddaman 				nv_offattr(np,NV_PARAM);
631*b30d1939SAndy Fiddaman 		}
632*b30d1939SAndy Fiddaman 		if(traceon || trap)
633*b30d1939SAndy Fiddaman 		{
634*b30d1939SAndy Fiddaman 			register char *sp=cp;
635*b30d1939SAndy Fiddaman 			char *name=nv_name(np);
636*b30d1939SAndy Fiddaman 			char *sub=0;
637*b30d1939SAndy Fiddaman 			int append = 0;
638*b30d1939SAndy Fiddaman 			if(nv_isarray(np))
639*b30d1939SAndy Fiddaman 				sub = savesub;
640*b30d1939SAndy Fiddaman 			if(cp=lastdot(sp,'='))
641*b30d1939SAndy Fiddaman 			{
642*b30d1939SAndy Fiddaman 				if(cp[-1]=='+')
643*b30d1939SAndy Fiddaman 					append = ARG_APPEND;
644*b30d1939SAndy Fiddaman 				cp++;
645*b30d1939SAndy Fiddaman 			}
646*b30d1939SAndy Fiddaman 			if(traceon)
647*b30d1939SAndy Fiddaman 			{
648*b30d1939SAndy Fiddaman 				sh_trace(shp,NIL(char**),0);
649*b30d1939SAndy Fiddaman 				nv_outname(sfstderr,name,-1);
650*b30d1939SAndy Fiddaman 				if(sub)
651*b30d1939SAndy Fiddaman 					sfprintf(sfstderr,"[%s]",sh_fmtq(sub));
652*b30d1939SAndy Fiddaman 				if(cp)
653*b30d1939SAndy Fiddaman 				{
654*b30d1939SAndy Fiddaman 					if(append)
655*b30d1939SAndy Fiddaman 						sfputc(sfstderr,'+');
656*b30d1939SAndy Fiddaman 					sfprintf(sfstderr,"=%s\n",sh_fmtq(cp));
657*b30d1939SAndy Fiddaman 				}
658*b30d1939SAndy Fiddaman 			}
659*b30d1939SAndy Fiddaman 			if(trap)
660*b30d1939SAndy Fiddaman 			{
661*b30d1939SAndy Fiddaman 					char *av[2];
662*b30d1939SAndy Fiddaman 					av[0] = cp;
663*b30d1939SAndy Fiddaman 					av[1] = 0;
664*b30d1939SAndy Fiddaman 					sh_debug(shp,trap,name,sub,av,append);
665*b30d1939SAndy Fiddaman 			}
666*b30d1939SAndy Fiddaman 		}
667*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
668*b30d1939SAndy Fiddaman 	check_type:
669*b30d1939SAndy Fiddaman 		if(maketype)
670*b30d1939SAndy Fiddaman 		{
671*b30d1939SAndy Fiddaman 			nv_open(shtp.nodes[0]->nvname,shp->var_tree,NV_ASSIGN|NV_VARNAME|NV_NOADD|NV_NOFAIL);
672*b30d1939SAndy Fiddaman 			np = nv_mktype(shtp.nodes,shtp.numnodes);
673*b30d1939SAndy Fiddaman 			free((void*)shtp.nodes);
674*b30d1939SAndy Fiddaman 			shp->mktype = shtp.previous;
675*b30d1939SAndy Fiddaman 			maketype = 0;
676*b30d1939SAndy Fiddaman 			if(shp->namespace)
677*b30d1939SAndy Fiddaman 				free(shp->prefix);
678*b30d1939SAndy Fiddaman 			shp->prefix = 0;
679*b30d1939SAndy Fiddaman 			if(nr.np == np)
680*b30d1939SAndy Fiddaman 			{
681*b30d1939SAndy Fiddaman 				L_ARGNOD->nvalue.nrp = node.nvalue.nrp;
682*b30d1939SAndy Fiddaman 				L_ARGNOD->nvflag = node.nvflag;
683*b30d1939SAndy Fiddaman 				L_ARGNOD->nvfun = node.nvfun;
684*b30d1939SAndy Fiddaman 			}
685*b30d1939SAndy Fiddaman 		}
686*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
687*b30d1939SAndy Fiddaman 	}
688*b30d1939SAndy Fiddaman }
689*b30d1939SAndy Fiddaman 
690*b30d1939SAndy Fiddaman /*
691*b30d1939SAndy Fiddaman  * copy the subscript onto the stack
692*b30d1939SAndy Fiddaman  */
stak_subscript(const char * sub,int last)693*b30d1939SAndy Fiddaman static void stak_subscript(const char *sub, int last)
694*b30d1939SAndy Fiddaman {
695*b30d1939SAndy Fiddaman 	register int c;
696*b30d1939SAndy Fiddaman 	stakputc('[');
697*b30d1939SAndy Fiddaman 	while(c= *sub++)
698*b30d1939SAndy Fiddaman 	{
699*b30d1939SAndy Fiddaman 		if(c=='[' || c==']' || c=='\\')
700*b30d1939SAndy Fiddaman 			stakputc('\\');
701*b30d1939SAndy Fiddaman 		stakputc(c);
702*b30d1939SAndy Fiddaman 	}
703*b30d1939SAndy Fiddaman 	stakputc(last);
704*b30d1939SAndy Fiddaman }
705*b30d1939SAndy Fiddaman 
706*b30d1939SAndy Fiddaman /*
707*b30d1939SAndy Fiddaman  * construct a new name from a prefix and base name on the stack
708*b30d1939SAndy Fiddaman  */
copystack(const char * prefix,register const char * name,const char * sub)709*b30d1939SAndy Fiddaman static char *copystack(const char *prefix, register const char *name, const char *sub)
710*b30d1939SAndy Fiddaman {
711*b30d1939SAndy Fiddaman 	register int last=0,offset = staktell();
712*b30d1939SAndy Fiddaman 	if(prefix)
713*b30d1939SAndy Fiddaman 	{
714*b30d1939SAndy Fiddaman 		stakputs(prefix);
715*b30d1939SAndy Fiddaman 		if(*stakptr(staktell()-1)=='.')
716*b30d1939SAndy Fiddaman 			stakseek(staktell()-1);
717*b30d1939SAndy Fiddaman 		if(*name=='.' && name[1]=='[')
718*b30d1939SAndy Fiddaman 			last = staktell()+2;
719*b30d1939SAndy Fiddaman 		if(*name!='['  && *name!='.' && *name!='=' && *name!='+')
720*b30d1939SAndy Fiddaman 			stakputc('.');
721*b30d1939SAndy Fiddaman 		if(*name=='.' && (name[1]=='=' || name[1]==0))
722*b30d1939SAndy Fiddaman 			stakputc('.');
723*b30d1939SAndy Fiddaman 	}
724*b30d1939SAndy Fiddaman 	if(last)
725*b30d1939SAndy Fiddaman 	{
726*b30d1939SAndy Fiddaman 		stakputs(name);
727*b30d1939SAndy Fiddaman 		if(sh_checkid(stakptr(last),(char*)0))
728*b30d1939SAndy Fiddaman 			stakseek(staktell()-2);
729*b30d1939SAndy Fiddaman 	}
730*b30d1939SAndy Fiddaman 	if(sub)
731*b30d1939SAndy Fiddaman 		stak_subscript(sub,']');
732*b30d1939SAndy Fiddaman 	if(!last)
733*b30d1939SAndy Fiddaman 		stakputs(name);
734*b30d1939SAndy Fiddaman 	stakputc(0);
735*b30d1939SAndy Fiddaman 	return(stakptr(offset));
736*b30d1939SAndy Fiddaman }
737*b30d1939SAndy Fiddaman 
738*b30d1939SAndy Fiddaman /*
739*b30d1939SAndy Fiddaman  * grow this stack string <name> by <n> bytes and move from cp-1 to end
740*b30d1939SAndy Fiddaman  * right by <n>.  Returns beginning of string on the stack
741*b30d1939SAndy Fiddaman  */
stack_extend(const char * cname,char * cp,int n)742*b30d1939SAndy Fiddaman static char *stack_extend(const char *cname, char *cp, int n)
743*b30d1939SAndy Fiddaman {
744*b30d1939SAndy Fiddaman 	register char *name = (char*)cname;
745*b30d1939SAndy Fiddaman 	int offset = name - stakptr(0);
746*b30d1939SAndy Fiddaman 	int m = cp-name;
747*b30d1939SAndy Fiddaman 	stakseek(offset + strlen(name)+n+1);
748*b30d1939SAndy Fiddaman 	name = stakptr(offset);
749*b30d1939SAndy Fiddaman 	cp =  name + m;
750*b30d1939SAndy Fiddaman 	m = strlen(cp)+1;
751*b30d1939SAndy Fiddaman 	while(m-->0)
752*b30d1939SAndy Fiddaman 		cp[n+m]=cp[m];
753*b30d1939SAndy Fiddaman 	return((char*)name);
754*b30d1939SAndy Fiddaman }
755*b30d1939SAndy Fiddaman 
nv_create(const char * name,Dt_t * root,int flags,Namfun_t * dp)756*b30d1939SAndy Fiddaman Namval_t *nv_create(const char *name,  Dt_t *root, int flags, Namfun_t *dp)
757*b30d1939SAndy Fiddaman {
758*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
759*b30d1939SAndy Fiddaman 	char			*sub=0, *cp=(char*)name, *sp, *xp;
760*b30d1939SAndy Fiddaman 	register int		c;
761*b30d1939SAndy Fiddaman 	register Namval_t	*np=0, *nq=0;
762*b30d1939SAndy Fiddaman 	Namfun_t		*fp=0;
763*b30d1939SAndy Fiddaman 	long			mode, add=0;
764*b30d1939SAndy Fiddaman 	int			copy=0,isref,top=0,noscope=(flags&NV_NOSCOPE);
765*b30d1939SAndy Fiddaman 	int			nofree=0, level=0;
766*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
767*b30d1939SAndy Fiddaman 	Namarr_t		*ap;
768*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
769*b30d1939SAndy Fiddaman 	if(root==shp->var_tree)
770*b30d1939SAndy Fiddaman 	{
771*b30d1939SAndy Fiddaman 		if(dtvnext(root))
772*b30d1939SAndy Fiddaman 			top = 1;
773*b30d1939SAndy Fiddaman 		else
774*b30d1939SAndy Fiddaman 			flags &= ~NV_NOSCOPE;
775*b30d1939SAndy Fiddaman 	}
776*b30d1939SAndy Fiddaman 	if(!dp->disc)
777*b30d1939SAndy Fiddaman 		copy = dp->nofree&1;
778*b30d1939SAndy Fiddaman 	if(*cp=='.')
779*b30d1939SAndy Fiddaman 		cp++;
780*b30d1939SAndy Fiddaman 	while(1)
781*b30d1939SAndy Fiddaman 	{
782*b30d1939SAndy Fiddaman 		switch(c = *(unsigned char*)(sp = cp))
783*b30d1939SAndy Fiddaman 		{
784*b30d1939SAndy Fiddaman 		    case '[':
785*b30d1939SAndy Fiddaman 			if(flags&NV_NOARRAY)
786*b30d1939SAndy Fiddaman 			{
787*b30d1939SAndy Fiddaman 				dp->last = cp;
788*b30d1939SAndy Fiddaman 				return(np);
789*b30d1939SAndy Fiddaman 			}
790*b30d1939SAndy Fiddaman 			cp = nv_endsubscript((Namval_t*)0,sp,0);
791*b30d1939SAndy Fiddaman 			if(sp==name || sp[-1]=='.')
792*b30d1939SAndy Fiddaman 				c = *(sp = cp);
793*b30d1939SAndy Fiddaman 			goto skip;
794*b30d1939SAndy Fiddaman 		    case '.':
795*b30d1939SAndy Fiddaman 			if(flags&NV_IDENT)
796*b30d1939SAndy Fiddaman 				return(0);
797*b30d1939SAndy Fiddaman 			if(root==shp->var_tree)
798*b30d1939SAndy Fiddaman 				flags &= ~NV_EXPORT;
799*b30d1939SAndy Fiddaman 			if(!copy && !(flags&NV_NOREF))
800*b30d1939SAndy Fiddaman 			{
801*b30d1939SAndy Fiddaman 				c = sp-name;
802*b30d1939SAndy Fiddaman 				copy = cp-name;
803*b30d1939SAndy Fiddaman 				dp->nofree |= 1;
804*b30d1939SAndy Fiddaman 				name = copystack((const char*)0, name,(const char*)0);
805*b30d1939SAndy Fiddaman 				cp = (char*)name+copy;
806*b30d1939SAndy Fiddaman 				sp = (char*)name+c;
807*b30d1939SAndy Fiddaman 				c = '.';
808*b30d1939SAndy Fiddaman 			}
809*b30d1939SAndy Fiddaman 			/* FALLTHROUGH */
810*b30d1939SAndy Fiddaman 		skip:
811*b30d1939SAndy Fiddaman 		    case '+':
812*b30d1939SAndy Fiddaman 		    case '=':
813*b30d1939SAndy Fiddaman 			*sp = 0;
814*b30d1939SAndy Fiddaman 			/* FALLTHROUGH */
815*b30d1939SAndy Fiddaman 		    case 0:
816*b30d1939SAndy Fiddaman 			isref = 0;
817*b30d1939SAndy Fiddaman 			dp->last = cp;
818*b30d1939SAndy Fiddaman 			mode =  (c=='.' || (flags&NV_NOADD))?add:NV_ADD;
819*b30d1939SAndy Fiddaman 			if(level++ || ((flags&NV_NOSCOPE) && c!='.'))
820*b30d1939SAndy Fiddaman 				mode |= HASH_NOSCOPE;
821*b30d1939SAndy Fiddaman 			np=0;
822*b30d1939SAndy Fiddaman 			if(top)
823*b30d1939SAndy Fiddaman 			{
824*b30d1939SAndy Fiddaman 				struct Ufunction *rp;
825*b30d1939SAndy Fiddaman 				if((rp=shp->st.real_fun) && !rp->sdict && (flags&NV_STATIC))
826*b30d1939SAndy Fiddaman 				{
827*b30d1939SAndy Fiddaman 					Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0);
828*b30d1939SAndy Fiddaman 					rp->sdict = dtopen(&_Nvdisc,Dtoset);
829*b30d1939SAndy Fiddaman 					dtview(rp->sdict,dp);
830*b30d1939SAndy Fiddaman 					dtview(shp->var_tree,rp->sdict);
831*b30d1939SAndy Fiddaman 				}
832*b30d1939SAndy Fiddaman 				if(np = nv_search(name,shp->var_tree,0))
833*b30d1939SAndy Fiddaman 				{
834*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
835*b30d1939SAndy Fiddaman 					if(shp->var_tree->walk==shp->var_base || (shp->var_tree->walk!=shp->var_tree && shp->namespace &&  nv_dict(shp->namespace)==shp->var_tree->walk))
836*b30d1939SAndy Fiddaman #else
837*b30d1939SAndy Fiddaman 					if(shp->var_tree->walk==shp->var_base)
838*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
839*b30d1939SAndy Fiddaman 					{
840*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
841*b30d1939SAndy Fiddaman 						if(!(nq = nv_search((char*)np,shp->var_base,HASH_BUCKET)))
842*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
843*b30d1939SAndy Fiddaman 						nq = np;
844*b30d1939SAndy Fiddaman 						shp->last_root = shp->var_tree->walk;
845*b30d1939SAndy Fiddaman 						if((flags&NV_NOSCOPE) && *cp!='.')
846*b30d1939SAndy Fiddaman 						{
847*b30d1939SAndy Fiddaman 							if(mode==0)
848*b30d1939SAndy Fiddaman 								root = shp->var_tree->walk;
849*b30d1939SAndy Fiddaman 							else
850*b30d1939SAndy Fiddaman 							{
851*b30d1939SAndy Fiddaman 								nv_delete(np,(Dt_t*)0,NV_NOFREE);
852*b30d1939SAndy Fiddaman 								np = 0;
853*b30d1939SAndy Fiddaman 							}
854*b30d1939SAndy Fiddaman 						}
855*b30d1939SAndy Fiddaman 					}
856*b30d1939SAndy Fiddaman 					else
857*b30d1939SAndy Fiddaman 					{
858*b30d1939SAndy Fiddaman 						if(shp->var_tree->walk)
859*b30d1939SAndy Fiddaman 							root = shp->var_tree->walk;
860*b30d1939SAndy Fiddaman 						flags |= NV_NOSCOPE;
861*b30d1939SAndy Fiddaman 						noscope = 1;
862*b30d1939SAndy Fiddaman 					}
863*b30d1939SAndy Fiddaman 				}
864*b30d1939SAndy Fiddaman 				if(rp && rp->sdict && (flags&NV_STATIC))
865*b30d1939SAndy Fiddaman 				{
866*b30d1939SAndy Fiddaman 					root = rp->sdict;
867*b30d1939SAndy Fiddaman 					if(np && shp->var_tree->walk==shp->var_tree)
868*b30d1939SAndy Fiddaman 					{
869*b30d1939SAndy Fiddaman 						_nv_unset(np,0);
870*b30d1939SAndy Fiddaman 						nv_delete(np,shp->var_tree,0);
871*b30d1939SAndy Fiddaman 						np = 0;
872*b30d1939SAndy Fiddaman 					}
873*b30d1939SAndy Fiddaman 					if(!np || shp->var_tree->walk!=root)
874*b30d1939SAndy Fiddaman 						np =  nv_search(name,root,HASH_NOSCOPE|NV_ADD);
875*b30d1939SAndy Fiddaman 				}
876*b30d1939SAndy Fiddaman 			}
877*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
878*b30d1939SAndy Fiddaman 			if(!np && !noscope && *name!='.' && shp->namespace && root==shp->var_tree)
879*b30d1939SAndy Fiddaman 				root = nv_dict(shp->namespace);
880*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
881*b30d1939SAndy Fiddaman 			if(np ||  (np = nv_search(name,root,mode)))
882*b30d1939SAndy Fiddaman 			{
883*b30d1939SAndy Fiddaman 				isref = nv_isref(np);
884*b30d1939SAndy Fiddaman 				shp->openmatch = root->walk?root->walk:root;
885*b30d1939SAndy Fiddaman 				if(top)
886*b30d1939SAndy Fiddaman 				{
887*b30d1939SAndy Fiddaman 					if(nq==np)
888*b30d1939SAndy Fiddaman 					{
889*b30d1939SAndy Fiddaman 						flags &= ~NV_NOSCOPE;
890*b30d1939SAndy Fiddaman 						root = shp->last_root;
891*b30d1939SAndy Fiddaman 					}
892*b30d1939SAndy Fiddaman 					else if(nq)
893*b30d1939SAndy Fiddaman 					{
894*b30d1939SAndy Fiddaman 						if(nv_isnull(np) && c!='.' && ((np->nvfun=nv_cover(nq)) || nq==OPTINDNOD))
895*b30d1939SAndy Fiddaman 						{
896*b30d1939SAndy Fiddaman 							np->nvname = nq->nvname;
897*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
898*b30d1939SAndy Fiddaman 							if(shp->namespace && nv_dict(shp->namespace)==shp->var_tree && nv_isattr(nq,NV_EXPORT))
899*b30d1939SAndy Fiddaman 								nv_onattr(np,NV_EXPORT);
900*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
901*b30d1939SAndy Fiddaman 							if(nq==OPTINDNOD)
902*b30d1939SAndy Fiddaman 							{
903*b30d1939SAndy Fiddaman 								np->nvfun = nq->nvfun;
904*b30d1939SAndy Fiddaman 								np->nvalue.lp = (&shp->st.optindex);
905*b30d1939SAndy Fiddaman 								nv_onattr(np,NV_INTEGER|NV_NOFREE);
906*b30d1939SAndy Fiddaman 							}
907*b30d1939SAndy Fiddaman 						}
908*b30d1939SAndy Fiddaman 						flags |= NV_NOSCOPE;
909*b30d1939SAndy Fiddaman 					}
910*b30d1939SAndy Fiddaman 				}
911*b30d1939SAndy Fiddaman 				else if(add && nv_isnull(np) && c=='.' && cp[1]!='.')
912*b30d1939SAndy Fiddaman 					nv_setvtree(np);
913*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
914*b30d1939SAndy Fiddaman 				if(shp->namespace && root==nv_dict(shp->namespace))
915*b30d1939SAndy Fiddaman 				{
916*b30d1939SAndy Fiddaman 					flags |= NV_NOSCOPE;
917*b30d1939SAndy Fiddaman 					shp->last_table = shp->namespace;
918*b30d1939SAndy Fiddaman 				}
919*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
920*b30d1939SAndy Fiddaman 			}
921*b30d1939SAndy Fiddaman 			if(c)
922*b30d1939SAndy Fiddaman 				*sp = c;
923*b30d1939SAndy Fiddaman 			top = 0;
924*b30d1939SAndy Fiddaman 			if(isref)
925*b30d1939SAndy Fiddaman 			{
926*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
927*b30d1939SAndy Fiddaman 				int n=0,dim;
928*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
929*b30d1939SAndy Fiddaman #if NVCACHE
930*b30d1939SAndy Fiddaman 				nvcache.ok = 0;
931*b30d1939SAndy Fiddaman #endif
932*b30d1939SAndy Fiddaman 				if(c=='.') /* don't optimize */
933*b30d1939SAndy Fiddaman 					shp->argaddr = 0;
934*b30d1939SAndy Fiddaman 				else if((flags&NV_NOREF) && (c!='[' && *cp!='.'))
935*b30d1939SAndy Fiddaman 				{
936*b30d1939SAndy Fiddaman 					if(c && !(flags&NV_NOADD))
937*b30d1939SAndy Fiddaman 						nv_unref(np);
938*b30d1939SAndy Fiddaman 					return(np);
939*b30d1939SAndy Fiddaman 				}
940*b30d1939SAndy Fiddaman 				while(nv_isref(np) && np->nvalue.cp)
941*b30d1939SAndy Fiddaman 				{
942*b30d1939SAndy Fiddaman 					root = nv_reftree(np);
943*b30d1939SAndy Fiddaman 					shp->last_root = root;
944*b30d1939SAndy Fiddaman 					shp->last_table = nv_reftable(np);
945*b30d1939SAndy Fiddaman 					sub = nv_refsub(np);
946*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
947*b30d1939SAndy Fiddaman 					n = nv_refindex(np);
948*b30d1939SAndy Fiddaman 					dim = nv_refdimen(np);
949*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
950*b30d1939SAndy Fiddaman 					np = nv_refnode(np);
951*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
952*b30d1939SAndy Fiddaman 					if(n)
953*b30d1939SAndy Fiddaman 					{
954*b30d1939SAndy Fiddaman 						ap = nv_arrayptr(np);
955*b30d1939SAndy Fiddaman 						ap->nelem = dim;
956*b30d1939SAndy Fiddaman 						nv_putsub(np,(char*)0,n);
957*b30d1939SAndy Fiddaman 					}
958*b30d1939SAndy Fiddaman 					else
959*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
960*b30d1939SAndy Fiddaman 					if(sub && c!='.')
961*b30d1939SAndy Fiddaman 						nv_putsub(np,sub,0L);
962*b30d1939SAndy Fiddaman 					flags |= NV_NOSCOPE;
963*b30d1939SAndy Fiddaman 					noscope = 1;
964*b30d1939SAndy Fiddaman 				}
965*b30d1939SAndy Fiddaman 				shp->first_root = root;
966*b30d1939SAndy Fiddaman 				if(nv_isref(np) && (c=='[' || c=='.' || !(flags&NV_ASSIGN)))
967*b30d1939SAndy Fiddaman 					errormsg(SH_DICT,ERROR_exit(1),e_noref,nv_name(np));
968*b30d1939SAndy Fiddaman 				if(sub && c==0)
969*b30d1939SAndy Fiddaman 				{
970*b30d1939SAndy Fiddaman 					if(flags&NV_ARRAY)
971*b30d1939SAndy Fiddaman 					{
972*b30d1939SAndy Fiddaman 						Namarr_t *ap = nv_arrayptr(np);
973*b30d1939SAndy Fiddaman 						nq = nv_opensub(np);
974*b30d1939SAndy Fiddaman 						if((flags&NV_ASSIGN) && (!nq || nv_isnull(nq)))
975*b30d1939SAndy Fiddaman 							ap->nelem++;
976*b30d1939SAndy Fiddaman 						if(!nq)
977*b30d1939SAndy Fiddaman 							goto addsub;
978*b30d1939SAndy Fiddaman 						else
979*b30d1939SAndy Fiddaman 							np = nq;
980*b30d1939SAndy Fiddaman 					}
981*b30d1939SAndy Fiddaman 					return(np);
982*b30d1939SAndy Fiddaman 				}
983*b30d1939SAndy Fiddaman 				if(np==nq)
984*b30d1939SAndy Fiddaman 					flags &= ~(noscope?0:NV_NOSCOPE);
985*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
986*b30d1939SAndy Fiddaman 				else if(c || n)
987*b30d1939SAndy Fiddaman #else
988*b30d1939SAndy Fiddaman 				else if(c)
989*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
990*b30d1939SAndy Fiddaman 				{
991*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
992*b30d1939SAndy Fiddaman 					static char null[1] = "";
993*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
994*b30d1939SAndy Fiddaman 					c = (cp-sp);
995*b30d1939SAndy Fiddaman 					copy = strlen(cp=nv_name(np));
996*b30d1939SAndy Fiddaman 					dp->nofree |= 1;
997*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
998*b30d1939SAndy Fiddaman 					if(*sp==0)
999*b30d1939SAndy Fiddaman 						name = cp;
1000*b30d1939SAndy Fiddaman 					else
1001*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1002*b30d1939SAndy Fiddaman 						name = copystack(cp,sp,sub);
1003*b30d1939SAndy Fiddaman 					sp = (char*)name + copy;
1004*b30d1939SAndy Fiddaman 					cp = sp+c;
1005*b30d1939SAndy Fiddaman 					c = *sp;
1006*b30d1939SAndy Fiddaman 					if(!noscope)
1007*b30d1939SAndy Fiddaman 						flags &= ~NV_NOSCOPE;
1008*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1009*b30d1939SAndy Fiddaman 					if(c==0)
1010*b30d1939SAndy Fiddaman 						nv_endsubscript(np,null,NV_ADD);
1011*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1012*b30d1939SAndy Fiddaman 				}
1013*b30d1939SAndy Fiddaman 				flags |= NV_NOREF;
1014*b30d1939SAndy Fiddaman 				if(*cp==0 &&  nv_isnull(np) && !nv_isarray(np))
1015*b30d1939SAndy Fiddaman 					nofree = NV_NOFREE;
1016*b30d1939SAndy Fiddaman 			}
1017*b30d1939SAndy Fiddaman 			shp->last_root = root;
1018*b30d1939SAndy Fiddaman 			if(*cp && cp[1]=='.')
1019*b30d1939SAndy Fiddaman 				cp++;
1020*b30d1939SAndy Fiddaman 			if(c=='.' && (cp[1]==0 ||  cp[1]=='=' || cp[1]=='+'))
1021*b30d1939SAndy Fiddaman 			{
1022*b30d1939SAndy Fiddaman 				nv_local = 1;
1023*b30d1939SAndy Fiddaman 				if(np)
1024*b30d1939SAndy Fiddaman 					nv_onattr(np,nofree);
1025*b30d1939SAndy Fiddaman 				return(np);
1026*b30d1939SAndy Fiddaman 			}
1027*b30d1939SAndy Fiddaman 			if(cp[-1]=='.')
1028*b30d1939SAndy Fiddaman 				cp--;
1029*b30d1939SAndy Fiddaman 			do
1030*b30d1939SAndy Fiddaman 			{
1031*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1032*b30d1939SAndy Fiddaman 				int fixed;
1033*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1034*b30d1939SAndy Fiddaman 				if(!np)
1035*b30d1939SAndy Fiddaman 				{
1036*b30d1939SAndy Fiddaman 					if(!nq && *sp=='[' && *cp==0 && cp[-1]==']')
1037*b30d1939SAndy Fiddaman 					{
1038*b30d1939SAndy Fiddaman 						/*
1039*b30d1939SAndy Fiddaman 						 * for backward compatibility
1040*b30d1939SAndy Fiddaman 						 * evaluate subscript for
1041*b30d1939SAndy Fiddaman 						 * possible side effects
1042*b30d1939SAndy Fiddaman 						 */
1043*b30d1939SAndy Fiddaman 						cp[-1] = 0;
1044*b30d1939SAndy Fiddaman 						sh_arith(shp,sp+1);
1045*b30d1939SAndy Fiddaman 						cp[-1] = ']';
1046*b30d1939SAndy Fiddaman 					}
1047*b30d1939SAndy Fiddaman 					return(np);
1048*b30d1939SAndy Fiddaman 				}
1049*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1050*b30d1939SAndy Fiddaman 				fixed = 0;
1051*b30d1939SAndy Fiddaman 				if((ap=nv_arrayptr(np)) && ap->fixed)
1052*b30d1939SAndy Fiddaman 					fixed = 1;
1053*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1054*b30d1939SAndy Fiddaman 				if(c=='[' || (c=='.' && nv_isarray(np)))
1055*b30d1939SAndy Fiddaman 				{
1056*b30d1939SAndy Fiddaman 					int n = 0;
1057*b30d1939SAndy Fiddaman 					sub = 0;
1058*b30d1939SAndy Fiddaman 					mode &= ~HASH_NOSCOPE;
1059*b30d1939SAndy Fiddaman 					if(c=='[')
1060*b30d1939SAndy Fiddaman 					{
1061*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1062*b30d1939SAndy Fiddaman 						Namarr_t *ap = nv_arrayptr(np);
1063*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1064*b30d1939SAndy Fiddaman #if 0
1065*b30d1939SAndy Fiddaman 						int scan = ap?(ap->nelem&ARRAY_SCAN):0;
1066*b30d1939SAndy Fiddaman #endif
1067*b30d1939SAndy Fiddaman 						n = mode|nv_isarray(np);
1068*b30d1939SAndy Fiddaman 						if(!mode && (flags&NV_ARRAY) && ((c=sp[1])=='*' || c=='@') && sp[2]==']')
1069*b30d1939SAndy Fiddaman 						{
1070*b30d1939SAndy Fiddaman 							/* not implemented yet */
1071*b30d1939SAndy Fiddaman 							dp->last = cp;
1072*b30d1939SAndy Fiddaman 							return(np);
1073*b30d1939SAndy Fiddaman 						}
1074*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1075*b30d1939SAndy Fiddaman 						if(fixed)
1076*b30d1939SAndy Fiddaman 							flags |= NV_FARRAY;
1077*b30d1939SAndy Fiddaman 						else
1078*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1079*b30d1939SAndy Fiddaman 						if((n&NV_ADD)&&(flags&NV_ARRAY))
1080*b30d1939SAndy Fiddaman 							n |= ARRAY_FILL;
1081*b30d1939SAndy Fiddaman 						if(flags&NV_ASSIGN)
1082*b30d1939SAndy Fiddaman 							n |= NV_ADD;
1083*b30d1939SAndy Fiddaman 						cp = nv_endsubscript(np,sp,n|(flags&(NV_ASSIGN|NV_FARRAY)));
1084*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1085*b30d1939SAndy Fiddaman 						flags &= ~NV_FARRAY;
1086*b30d1939SAndy Fiddaman 						if(fixed)
1087*b30d1939SAndy Fiddaman 							flags &= ~NV_ARRAY;
1088*b30d1939SAndy Fiddaman 
1089*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1090*b30d1939SAndy Fiddaman #if 0
1091*b30d1939SAndy Fiddaman 						if(scan)
1092*b30d1939SAndy Fiddaman 							nv_putsub(np,NIL(char*),ARRAY_SCAN);
1093*b30d1939SAndy Fiddaman #endif
1094*b30d1939SAndy Fiddaman 					}
1095*b30d1939SAndy Fiddaman 					else
1096*b30d1939SAndy Fiddaman 						cp = sp;
1097*b30d1939SAndy Fiddaman 					if((c = *cp)=='.' || (c=='[' && nv_isarray(np)) || (n&ARRAY_FILL) || ((ap || (flags&NV_ASSIGN)) &&  (flags&NV_ARRAY)))
1098*b30d1939SAndy Fiddaman 
1099*b30d1939SAndy Fiddaman 					{
1100*b30d1939SAndy Fiddaman 						int m = cp-sp;
1101*b30d1939SAndy Fiddaman 						sub = m?nv_getsub(np):0;
1102*b30d1939SAndy Fiddaman 						if(!sub)
1103*b30d1939SAndy Fiddaman 						{
1104*b30d1939SAndy Fiddaman 							if(m && !(n&NV_ADD))
1105*b30d1939SAndy Fiddaman 								return(0);
1106*b30d1939SAndy Fiddaman 							sub = "0";
1107*b30d1939SAndy Fiddaman 						}
1108*b30d1939SAndy Fiddaman 						n = strlen(sub)+2;
1109*b30d1939SAndy Fiddaman 						if(!copy)
1110*b30d1939SAndy Fiddaman 						{
1111*b30d1939SAndy Fiddaman 							copy = cp-name;
1112*b30d1939SAndy Fiddaman 							dp->nofree |= 1;
1113*b30d1939SAndy Fiddaman 							name = copystack((const char*)0, name,(const char*)0);
1114*b30d1939SAndy Fiddaman 							cp = (char*)name+copy;
1115*b30d1939SAndy Fiddaman 							sp = cp-m;
1116*b30d1939SAndy Fiddaman 						}
1117*b30d1939SAndy Fiddaman 						if(n <= m)
1118*b30d1939SAndy Fiddaman 						{
1119*b30d1939SAndy Fiddaman 							if(n)
1120*b30d1939SAndy Fiddaman 							{
1121*b30d1939SAndy Fiddaman 								memcpy(sp+1,sub,n-2);
1122*b30d1939SAndy Fiddaman 								sp[n-1] = ']';
1123*b30d1939SAndy Fiddaman 							}
1124*b30d1939SAndy Fiddaman 							if(n < m)
1125*b30d1939SAndy Fiddaman 							{
1126*b30d1939SAndy Fiddaman 								char *dp = sp+n;
1127*b30d1939SAndy Fiddaman 								while(*dp++=*cp++);
1128*b30d1939SAndy Fiddaman 								cp = sp+n;
1129*b30d1939SAndy Fiddaman 							}
1130*b30d1939SAndy Fiddaman 						}
1131*b30d1939SAndy Fiddaman 						else
1132*b30d1939SAndy Fiddaman 						{
1133*b30d1939SAndy Fiddaman 							int r = n-m;
1134*b30d1939SAndy Fiddaman 							m = sp-name;
1135*b30d1939SAndy Fiddaman 							name = stack_extend(name, cp-1, r);
1136*b30d1939SAndy Fiddaman 							sp = (char*)name + m;
1137*b30d1939SAndy Fiddaman 							*sp = '[';
1138*b30d1939SAndy Fiddaman 							memcpy(sp+1,sub,n-2);
1139*b30d1939SAndy Fiddaman 							sp[n-1] = ']';
1140*b30d1939SAndy Fiddaman 							cp = sp+n;
1141*b30d1939SAndy Fiddaman 
1142*b30d1939SAndy Fiddaman 						}
1143*b30d1939SAndy Fiddaman 					}
1144*b30d1939SAndy Fiddaman 					else if(c==0 && mode && (n=nv_aindex(np))>0)
1145*b30d1939SAndy Fiddaman 						nv_putsub(np,(char*)0,n);
1146*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1147*b30d1939SAndy Fiddaman 					else if(n==0 && !fixed && (c==0 || (c=='[' && !nv_isarray(np))))
1148*b30d1939SAndy Fiddaman #else
1149*b30d1939SAndy Fiddaman 					else if(n==0 && (c==0 || (c=='[' && !nv_isarray(np))))
1150*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1151*b30d1939SAndy Fiddaman 					{
1152*b30d1939SAndy Fiddaman 						/* subscript must be 0*/
1153*b30d1939SAndy Fiddaman 						cp[-1] = 0;
1154*b30d1939SAndy Fiddaman 						n = sh_arith(shp,sp+1);
1155*b30d1939SAndy Fiddaman 						cp[-1] = ']';
1156*b30d1939SAndy Fiddaman 						if(n)
1157*b30d1939SAndy Fiddaman 							return(0);
1158*b30d1939SAndy Fiddaman 						if(c)
1159*b30d1939SAndy Fiddaman 							sp = cp;
1160*b30d1939SAndy Fiddaman 					}
1161*b30d1939SAndy Fiddaman 					dp->last = cp;
1162*b30d1939SAndy Fiddaman 					if(nv_isarray(np) && (c=='[' || c=='.' || (flags&NV_ARRAY)))
1163*b30d1939SAndy Fiddaman 					{
1164*b30d1939SAndy Fiddaman 					addsub:
1165*b30d1939SAndy Fiddaman 						sp = cp;
1166*b30d1939SAndy Fiddaman 						if(!(nq = nv_opensub(np)))
1167*b30d1939SAndy Fiddaman 						{
1168*b30d1939SAndy Fiddaman 							Namarr_t *ap = nv_arrayptr(np);
1169*b30d1939SAndy Fiddaman 							if(!sub && (flags&NV_NOADD))
1170*b30d1939SAndy Fiddaman 								return(0);
1171*b30d1939SAndy Fiddaman 							n = mode|((flags&NV_NOADD)?0:NV_ADD);
1172*b30d1939SAndy Fiddaman 							if(!ap && (n&NV_ADD))
1173*b30d1939SAndy Fiddaman 							{
1174*b30d1939SAndy Fiddaman 								nv_putsub(np,sub,ARRAY_FILL);
1175*b30d1939SAndy Fiddaman 								ap = nv_arrayptr(np);
1176*b30d1939SAndy Fiddaman 							}
1177*b30d1939SAndy Fiddaman 							if(n && ap && !ap->table)
1178*b30d1939SAndy Fiddaman 								ap->table = dtopen(&_Nvdisc,Dtoset);
1179*b30d1939SAndy Fiddaman 							if(ap && ap->table && (nq=nv_search(sub,ap->table,n)))
1180*b30d1939SAndy Fiddaman 								nq->nvenv = (char*)np;
1181*b30d1939SAndy Fiddaman 							if(nq && nv_isnull(nq))
1182*b30d1939SAndy Fiddaman 								nq = nv_arraychild(np,nq,c);
1183*b30d1939SAndy Fiddaman 						}
1184*b30d1939SAndy Fiddaman 						if(nq)
1185*b30d1939SAndy Fiddaman 						{
1186*b30d1939SAndy Fiddaman 							if(c=='.' && !nv_isvtree(nq))
1187*b30d1939SAndy Fiddaman 							{
1188*b30d1939SAndy Fiddaman 								if(flags&NV_NOADD)
1189*b30d1939SAndy Fiddaman 									return(0);
1190*b30d1939SAndy Fiddaman 								nv_setvtree(nq);
1191*b30d1939SAndy Fiddaman 							}
1192*b30d1939SAndy Fiddaman 							nv_onattr(np,nofree);
1193*b30d1939SAndy Fiddaman 							nofree = 0;
1194*b30d1939SAndy Fiddaman 							np = nq;
1195*b30d1939SAndy Fiddaman 						}
1196*b30d1939SAndy Fiddaman 						else if(memcmp(cp,"[0]",3))
1197*b30d1939SAndy Fiddaman 							return(nq);
1198*b30d1939SAndy Fiddaman 						else
1199*b30d1939SAndy Fiddaman 						{
1200*b30d1939SAndy Fiddaman 							/* ignore [0]  */
1201*b30d1939SAndy Fiddaman 							dp->last = cp += 3;
1202*b30d1939SAndy Fiddaman 							c = *cp;
1203*b30d1939SAndy Fiddaman 						}
1204*b30d1939SAndy Fiddaman 					}
1205*b30d1939SAndy Fiddaman 				}
1206*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1207*b30d1939SAndy Fiddaman 				else if(nv_isarray(np) && (!fixed || cp[-1]!=']'))
1208*b30d1939SAndy Fiddaman #else
1209*b30d1939SAndy Fiddaman 				else if(nv_isarray(np))
1210*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1211*b30d1939SAndy Fiddaman 				{
1212*b30d1939SAndy Fiddaman 					if(c==0 && (flags&NV_MOVE))
1213*b30d1939SAndy Fiddaman 						return(np);
1214*b30d1939SAndy Fiddaman 					nv_putsub(np,NIL(char*),ARRAY_UNDEF);
1215*b30d1939SAndy Fiddaman 				}
1216*b30d1939SAndy Fiddaman 				nv_onattr(np,nofree);
1217*b30d1939SAndy Fiddaman 				nofree  = 0;
1218*b30d1939SAndy Fiddaman 				if(c=='.' && (fp=np->nvfun))
1219*b30d1939SAndy Fiddaman 				{
1220*b30d1939SAndy Fiddaman 					for(; fp; fp=fp->next)
1221*b30d1939SAndy Fiddaman 					{
1222*b30d1939SAndy Fiddaman 						if(fp->disc && fp->disc->createf)
1223*b30d1939SAndy Fiddaman 							break;
1224*b30d1939SAndy Fiddaman 					}
1225*b30d1939SAndy Fiddaman 					if(fp)
1226*b30d1939SAndy Fiddaman 					{
1227*b30d1939SAndy Fiddaman 						if((nq = (*fp->disc->createf)(np,cp+1,flags,fp)) == np)
1228*b30d1939SAndy Fiddaman 						{
1229*b30d1939SAndy Fiddaman 							add = NV_ADD;
1230*b30d1939SAndy Fiddaman 							shp->last_table = 0;
1231*b30d1939SAndy Fiddaman 							break;
1232*b30d1939SAndy Fiddaman 						}
1233*b30d1939SAndy Fiddaman 						else if(np=nq)
1234*b30d1939SAndy Fiddaman 						{
1235*b30d1939SAndy Fiddaman 							if((c = *(sp=cp=dp->last=fp->last))==0)
1236*b30d1939SAndy Fiddaman 							{
1237*b30d1939SAndy Fiddaman 								if(nv_isarray(np) && sp[-1]!=']')
1238*b30d1939SAndy Fiddaman 									nv_putsub(np,NIL(char*),ARRAY_UNDEF);
1239*b30d1939SAndy Fiddaman 								return(np);
1240*b30d1939SAndy Fiddaman 							}
1241*b30d1939SAndy Fiddaman 						}
1242*b30d1939SAndy Fiddaman 					}
1243*b30d1939SAndy Fiddaman 				}
1244*b30d1939SAndy Fiddaman 			}
1245*b30d1939SAndy Fiddaman 			while(c=='[');
1246*b30d1939SAndy Fiddaman 			if(c!='.' || cp[1]=='.')
1247*b30d1939SAndy Fiddaman 				return(np);
1248*b30d1939SAndy Fiddaman 			cp++;
1249*b30d1939SAndy Fiddaman 			break;
1250*b30d1939SAndy Fiddaman 		    default:
1251*b30d1939SAndy Fiddaman 			dp->last = cp;
1252*b30d1939SAndy Fiddaman 			if((c = mbchar(cp)) && !isaletter(c))
1253*b30d1939SAndy Fiddaman 				return(np);
1254*b30d1939SAndy Fiddaman 			while(xp=cp, c=mbchar(cp), isaname(c));
1255*b30d1939SAndy Fiddaman 			cp = xp;
1256*b30d1939SAndy Fiddaman 		}
1257*b30d1939SAndy Fiddaman 	}
1258*b30d1939SAndy Fiddaman 	return(np);
1259*b30d1939SAndy Fiddaman }
1260*b30d1939SAndy Fiddaman 
1261*b30d1939SAndy Fiddaman /*
1262*b30d1939SAndy Fiddaman  * delete the node <np> from the dictionary <root> and clear from the cache
1263*b30d1939SAndy Fiddaman  * if <root> is NULL, only the cache is cleared
1264*b30d1939SAndy Fiddaman  * if flags does not contain NV_NOFREE, the node is freed
1265*b30d1939SAndy Fiddaman  * if np==0  && !root && flags==0,  delete the Refdict dictionary
1266*b30d1939SAndy Fiddaman  */
nv_delete(Namval_t * np,Dt_t * root,int flags)1267*b30d1939SAndy Fiddaman void nv_delete(Namval_t* np, Dt_t *root, int flags)
1268*b30d1939SAndy Fiddaman {
1269*b30d1939SAndy Fiddaman #if NVCACHE
1270*b30d1939SAndy Fiddaman 	register int		c;
1271*b30d1939SAndy Fiddaman 	struct Cache_entry	*xp;
1272*b30d1939SAndy Fiddaman 	for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c])
1273*b30d1939SAndy Fiddaman 	{
1274*b30d1939SAndy Fiddaman 		if(xp->np==np)
1275*b30d1939SAndy Fiddaman 			xp->root = 0;
1276*b30d1939SAndy Fiddaman 	}
1277*b30d1939SAndy Fiddaman #endif
1278*b30d1939SAndy Fiddaman 	if(!np && !root && flags==0)
1279*b30d1939SAndy Fiddaman 	{
1280*b30d1939SAndy Fiddaman 		if(Refdict)
1281*b30d1939SAndy Fiddaman 			dtclose(Refdict);
1282*b30d1939SAndy Fiddaman 		Refdict = 0;
1283*b30d1939SAndy Fiddaman 		return;
1284*b30d1939SAndy Fiddaman 	}
1285*b30d1939SAndy Fiddaman 	if(root || !(flags&NV_NOFREE))
1286*b30d1939SAndy Fiddaman 	{
1287*b30d1939SAndy Fiddaman 		if(!(flags&NV_FUNCTION) && Refdict)
1288*b30d1939SAndy Fiddaman 		{
1289*b30d1939SAndy Fiddaman 			Namval_t **key = &np;
1290*b30d1939SAndy Fiddaman 			struct Namref *rp;
1291*b30d1939SAndy Fiddaman 			while(rp = (struct Namref*)dtmatch(Refdict,(void*)key))
1292*b30d1939SAndy Fiddaman 			{
1293*b30d1939SAndy Fiddaman 				if(rp->sub)
1294*b30d1939SAndy Fiddaman 					free(rp->sub);
1295*b30d1939SAndy Fiddaman 				rp->sub = 0;
1296*b30d1939SAndy Fiddaman 				rp = dtdelete(Refdict,(void*)rp);
1297*b30d1939SAndy Fiddaman 				rp->np = &NullNode;
1298*b30d1939SAndy Fiddaman 			}
1299*b30d1939SAndy Fiddaman 		}
1300*b30d1939SAndy Fiddaman 	}
1301*b30d1939SAndy Fiddaman 	if(root)
1302*b30d1939SAndy Fiddaman 	{
1303*b30d1939SAndy Fiddaman 		if(dtdelete(root,np))
1304*b30d1939SAndy Fiddaman 		{
1305*b30d1939SAndy Fiddaman 			if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np)))
1306*b30d1939SAndy Fiddaman 			{
1307*b30d1939SAndy Fiddaman 				Namarr_t    *ap;
1308*b30d1939SAndy Fiddaman 				if(nv_isarray(np) && np->nvfun &&
1309*b30d1939SAndy Fiddaman 					(ap=nv_arrayptr(np)) && array_assoc(ap)) {
1310*b30d1939SAndy Fiddaman 					while(nv_associative(np,0,NV_ANEXT))
1311*b30d1939SAndy Fiddaman 						nv_associative(np, 0, NV_ADELETE);
1312*b30d1939SAndy Fiddaman 					nv_associative(np, 0, NV_AFREE);
1313*b30d1939SAndy Fiddaman 					free((void*)np->nvfun);
1314*b30d1939SAndy Fiddaman 				}
1315*b30d1939SAndy Fiddaman 				free((void*)np);
1316*b30d1939SAndy Fiddaman 			}
1317*b30d1939SAndy Fiddaman 		}
1318*b30d1939SAndy Fiddaman #if 0
1319*b30d1939SAndy Fiddaman 		else
1320*b30d1939SAndy Fiddaman 		{
1321*b30d1939SAndy Fiddaman 			sfprintf(sfstderr,"%s not deleted\n",nv_name(np));
1322*b30d1939SAndy Fiddaman 			sfsync(sfstderr);
1323*b30d1939SAndy Fiddaman 		}
1324*b30d1939SAndy Fiddaman #endif
1325*b30d1939SAndy Fiddaman 	}
1326*b30d1939SAndy Fiddaman }
1327*b30d1939SAndy Fiddaman 
1328*b30d1939SAndy Fiddaman /*
1329*b30d1939SAndy Fiddaman  * Put <arg> into associative memory.
1330*b30d1939SAndy Fiddaman  * If <flags> & NV_ARRAY then follow array to next subscript
1331*b30d1939SAndy Fiddaman  * If <flags> & NV_NOARRAY then subscript is not allowed
1332*b30d1939SAndy Fiddaman  * If <flags> & NV_NOSCOPE then use the current scope only
1333*b30d1939SAndy Fiddaman  * If <flags> & NV_ASSIGN then assignment is allowed
1334*b30d1939SAndy Fiddaman  * If <flags> & NV_IDENT then name must be an identifier
1335*b30d1939SAndy Fiddaman  * If <flags> & NV_VARNAME then name must be a valid variable name
1336*b30d1939SAndy Fiddaman  * If <flags> & NV_NOADD then node will not be added if not found
1337*b30d1939SAndy Fiddaman  * If <flags> & NV_NOREF then don't follow reference
1338*b30d1939SAndy Fiddaman  * If <flags> & NV_NOFAIL then don't generate an error message on failure
1339*b30d1939SAndy Fiddaman  * If <flags> & NV_STATIC then unset before an assignment
1340*b30d1939SAndy Fiddaman  * If <flags> & NV_UNJUST then unset attributes before assignment
1341*b30d1939SAndy Fiddaman  * SH_INIT is only set while initializing the environment
1342*b30d1939SAndy Fiddaman  */
nv_open(const char * name,Dt_t * root,int flags)1343*b30d1939SAndy Fiddaman Namval_t *nv_open(const char *name, Dt_t *root, int flags)
1344*b30d1939SAndy Fiddaman {
1345*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
1346*b30d1939SAndy Fiddaman 	register char		*cp=(char*)name;
1347*b30d1939SAndy Fiddaman 	register int		c;
1348*b30d1939SAndy Fiddaman 	register Namval_t	*np=0;
1349*b30d1939SAndy Fiddaman 	Namfun_t		fun;
1350*b30d1939SAndy Fiddaman 	int			append=0;
1351*b30d1939SAndy Fiddaman 	const char		*msg = e_varname;
1352*b30d1939SAndy Fiddaman 	char			*fname = 0;
1353*b30d1939SAndy Fiddaman 	int			offset = staktell();
1354*b30d1939SAndy Fiddaman 	Dt_t			*funroot;
1355*b30d1939SAndy Fiddaman #if NVCACHE
1356*b30d1939SAndy Fiddaman 	struct Cache_entry	*xp;
1357*b30d1939SAndy Fiddaman #endif
1358*b30d1939SAndy Fiddaman 
1359*b30d1939SAndy Fiddaman 	sh_stats(STAT_NVOPEN);
1360*b30d1939SAndy Fiddaman 	memset(&fun,0,sizeof(fun));
1361*b30d1939SAndy Fiddaman 	shp->openmatch = 0;
1362*b30d1939SAndy Fiddaman 	shp->last_table = 0;
1363*b30d1939SAndy Fiddaman 	if(!root)
1364*b30d1939SAndy Fiddaman 		root = shp->var_tree;
1365*b30d1939SAndy Fiddaman 	shp->last_root = root;
1366*b30d1939SAndy Fiddaman 	if(root==shp->fun_tree)
1367*b30d1939SAndy Fiddaman 	{
1368*b30d1939SAndy Fiddaman 		flags |= NV_NOREF;
1369*b30d1939SAndy Fiddaman 		msg = e_badfun;
1370*b30d1939SAndy Fiddaman 		if(strchr(name,'.'))
1371*b30d1939SAndy Fiddaman 		{
1372*b30d1939SAndy Fiddaman 			name = cp = copystack(0,name,(const char*)0);
1373*b30d1939SAndy Fiddaman 			fname = strrchr(cp,'.');
1374*b30d1939SAndy Fiddaman 			*fname = 0;
1375*b30d1939SAndy Fiddaman 			fun.nofree |= 1;
1376*b30d1939SAndy Fiddaman 			flags &=  ~NV_IDENT;
1377*b30d1939SAndy Fiddaman 			funroot = root;
1378*b30d1939SAndy Fiddaman 			root = shp->var_tree;
1379*b30d1939SAndy Fiddaman 		}
1380*b30d1939SAndy Fiddaman 	}
1381*b30d1939SAndy Fiddaman 	else if(!(flags&(NV_IDENT|NV_VARNAME|NV_ASSIGN)))
1382*b30d1939SAndy Fiddaman 	{
1383*b30d1939SAndy Fiddaman 		long mode = ((flags&NV_NOADD)?0:NV_ADD);
1384*b30d1939SAndy Fiddaman 		if(flags&NV_NOSCOPE)
1385*b30d1939SAndy Fiddaman 			mode |= HASH_SCOPE|HASH_NOSCOPE;
1386*b30d1939SAndy Fiddaman 		np = nv_search(name,root,mode);
1387*b30d1939SAndy Fiddaman 		if(np && !(flags&NV_REF))
1388*b30d1939SAndy Fiddaman 		{
1389*b30d1939SAndy Fiddaman 			while(nv_isref(np))
1390*b30d1939SAndy Fiddaman 			{
1391*b30d1939SAndy Fiddaman 				shp->last_table = nv_reftable(np);
1392*b30d1939SAndy Fiddaman 				np = nv_refnode(np);
1393*b30d1939SAndy Fiddaman 			}
1394*b30d1939SAndy Fiddaman 		}
1395*b30d1939SAndy Fiddaman 		return(np);
1396*b30d1939SAndy Fiddaman 	}
1397*b30d1939SAndy Fiddaman 	else if(shp->prefix && (flags&NV_ASSIGN))
1398*b30d1939SAndy Fiddaman 	{
1399*b30d1939SAndy Fiddaman 		name = cp = copystack(shp->prefix,name,(const char*)0);
1400*b30d1939SAndy Fiddaman 		fun.nofree |= 1;
1401*b30d1939SAndy Fiddaman 	}
1402*b30d1939SAndy Fiddaman 	c = *(unsigned char*)cp;
1403*b30d1939SAndy Fiddaman 	if(root==shp->alias_tree)
1404*b30d1939SAndy Fiddaman 	{
1405*b30d1939SAndy Fiddaman 		msg = e_aliname;
1406*b30d1939SAndy Fiddaman 		while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') &&
1407*b30d1939SAndy Fiddaman 			(c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON));
1408*b30d1939SAndy Fiddaman 		if(shp->subshell && c=='=')
1409*b30d1939SAndy Fiddaman 			root = sh_subaliastree(1);
1410*b30d1939SAndy Fiddaman 		if(c= *--cp)
1411*b30d1939SAndy Fiddaman 			*cp = 0;
1412*b30d1939SAndy Fiddaman 		np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD);
1413*b30d1939SAndy Fiddaman 		if(c)
1414*b30d1939SAndy Fiddaman 			*cp = c;
1415*b30d1939SAndy Fiddaman 		goto skip;
1416*b30d1939SAndy Fiddaman 	}
1417*b30d1939SAndy Fiddaman 	else if(flags&NV_IDENT)
1418*b30d1939SAndy Fiddaman 		msg = e_ident;
1419*b30d1939SAndy Fiddaman 	else if(c=='.')
1420*b30d1939SAndy Fiddaman 	{
1421*b30d1939SAndy Fiddaman 		c = *++cp;
1422*b30d1939SAndy Fiddaman 		flags |= NV_NOREF;
1423*b30d1939SAndy Fiddaman 		if(root==shp->var_tree)
1424*b30d1939SAndy Fiddaman 			root = shp->var_base;
1425*b30d1939SAndy Fiddaman 		shp->last_table = 0;
1426*b30d1939SAndy Fiddaman 	}
1427*b30d1939SAndy Fiddaman 	if(c= !isaletter(c))
1428*b30d1939SAndy Fiddaman 		goto skip;
1429*b30d1939SAndy Fiddaman #if NVCACHE
1430*b30d1939SAndy Fiddaman 	for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c])
1431*b30d1939SAndy Fiddaman 	{
1432*b30d1939SAndy Fiddaman 		if(xp->root!=root)
1433*b30d1939SAndy Fiddaman 			continue;
1434*b30d1939SAndy Fiddaman 		if(*name==*xp->name && xp->namespace==shp->namespace && (flags&(NV_ARRAY|NV_NOSCOPE))==xp->flags && memcmp(xp->name,name,xp->len)==0 && (name[xp->len]==0 || name[xp->len]=='=' || name[xp->len]=='+'))
1435*b30d1939SAndy Fiddaman 		{
1436*b30d1939SAndy Fiddaman 			sh_stats(STAT_NVHITS);
1437*b30d1939SAndy Fiddaman 			np = xp->np;
1438*b30d1939SAndy Fiddaman 			cp = (char*)name+xp->len;
1439*b30d1939SAndy Fiddaman 			if(nv_isarray(np) && !(flags&NV_MOVE))
1440*b30d1939SAndy Fiddaman 				 nv_putsub(np,NIL(char*),ARRAY_UNDEF);
1441*b30d1939SAndy Fiddaman 			shp->last_table = xp->last_table;
1442*b30d1939SAndy Fiddaman 			shp->last_root = xp->last_root;
1443*b30d1939SAndy Fiddaman 			goto nocache;
1444*b30d1939SAndy Fiddaman 		}
1445*b30d1939SAndy Fiddaman 	}
1446*b30d1939SAndy Fiddaman 	nvcache.ok = 1;
1447*b30d1939SAndy Fiddaman #endif
1448*b30d1939SAndy Fiddaman 	np = nv_create(name, root, flags, &fun);
1449*b30d1939SAndy Fiddaman 	cp = fun.last;
1450*b30d1939SAndy Fiddaman #if NVCACHE
1451*b30d1939SAndy Fiddaman 	if(np && nvcache.ok && cp[-1]!=']')
1452*b30d1939SAndy Fiddaman 	{
1453*b30d1939SAndy Fiddaman 		xp = &nvcache.entries[nvcache.index];
1454*b30d1939SAndy Fiddaman 		if(*cp)
1455*b30d1939SAndy Fiddaman 		{
1456*b30d1939SAndy Fiddaman 			char *sp = strchr(name,*cp);
1457*b30d1939SAndy Fiddaman 			if(!sp)
1458*b30d1939SAndy Fiddaman 				goto nocache;
1459*b30d1939SAndy Fiddaman 			xp->len = sp-name;
1460*b30d1939SAndy Fiddaman 		}
1461*b30d1939SAndy Fiddaman 		else
1462*b30d1939SAndy Fiddaman 			xp->len = strlen(name);
1463*b30d1939SAndy Fiddaman 		c = roundof(xp->len+1,32);
1464*b30d1939SAndy Fiddaman 		if(c > xp->size)
1465*b30d1939SAndy Fiddaman 		{
1466*b30d1939SAndy Fiddaman 			if(xp->size==0)
1467*b30d1939SAndy Fiddaman 				xp->name = malloc(c);
1468*b30d1939SAndy Fiddaman 			else
1469*b30d1939SAndy Fiddaman 				xp->name = realloc(xp->name,c);
1470*b30d1939SAndy Fiddaman 			xp->size = c;
1471*b30d1939SAndy Fiddaman 		}
1472*b30d1939SAndy Fiddaman 		memcpy(xp->name,name,xp->len);
1473*b30d1939SAndy Fiddaman 		xp->name[xp->len] = 0;
1474*b30d1939SAndy Fiddaman 		xp->root = root;
1475*b30d1939SAndy Fiddaman 		xp->np = np;
1476*b30d1939SAndy Fiddaman 		xp->namespace = shp->namespace;
1477*b30d1939SAndy Fiddaman 		xp->last_table = shp->last_table;
1478*b30d1939SAndy Fiddaman 		xp->last_root = shp->last_root;
1479*b30d1939SAndy Fiddaman 		xp->flags = (flags&(NV_ARRAY|NV_NOSCOPE));
1480*b30d1939SAndy Fiddaman 		nvcache.index = (nvcache.index+1)&(NVCACHE-1);
1481*b30d1939SAndy Fiddaman 	}
1482*b30d1939SAndy Fiddaman nocache:
1483*b30d1939SAndy Fiddaman 	nvcache.ok = 0;
1484*b30d1939SAndy Fiddaman #endif
1485*b30d1939SAndy Fiddaman 	if(fname)
1486*b30d1939SAndy Fiddaman 	{
1487*b30d1939SAndy Fiddaman 		c = ((flags&NV_NOSCOPE)?HASH_NOSCOPE:0)|((flags&NV_NOADD)?0:NV_ADD);
1488*b30d1939SAndy Fiddaman 		*fname = '.';
1489*b30d1939SAndy Fiddaman 		np = nv_search(name, funroot, c);
1490*b30d1939SAndy Fiddaman 		*fname = 0;
1491*b30d1939SAndy Fiddaman 	}
1492*b30d1939SAndy Fiddaman 	else
1493*b30d1939SAndy Fiddaman 	{
1494*b30d1939SAndy Fiddaman 		if(*cp=='.' && cp[1]=='.')
1495*b30d1939SAndy Fiddaman 		{
1496*b30d1939SAndy Fiddaman 			append |= NV_NODISC;
1497*b30d1939SAndy Fiddaman 			cp+=2;
1498*b30d1939SAndy Fiddaman 		}
1499*b30d1939SAndy Fiddaman 		if(*cp=='+' && cp[1]=='=')
1500*b30d1939SAndy Fiddaman 		{
1501*b30d1939SAndy Fiddaman 			append |= NV_APPEND;
1502*b30d1939SAndy Fiddaman 			cp++;
1503*b30d1939SAndy Fiddaman 		}
1504*b30d1939SAndy Fiddaman 	}
1505*b30d1939SAndy Fiddaman 	c = *cp;
1506*b30d1939SAndy Fiddaman skip:
1507*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
1508*b30d1939SAndy Fiddaman 	if(np && shp->mktype)
1509*b30d1939SAndy Fiddaman 		np = nv_addnode(np,0);
1510*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
1511*b30d1939SAndy Fiddaman 	if(c=='=' && np && (flags&NV_ASSIGN))
1512*b30d1939SAndy Fiddaman 	{
1513*b30d1939SAndy Fiddaman 		cp++;
1514*b30d1939SAndy Fiddaman 		if(sh_isstate(SH_INIT))
1515*b30d1939SAndy Fiddaman 		{
1516*b30d1939SAndy Fiddaman 			nv_putval(np, cp, NV_RDONLY);
1517*b30d1939SAndy Fiddaman 			if(np==PWDNOD)
1518*b30d1939SAndy Fiddaman 				nv_onattr(np,NV_TAGGED);
1519*b30d1939SAndy Fiddaman 		}
1520*b30d1939SAndy Fiddaman 		else
1521*b30d1939SAndy Fiddaman 		{
1522*b30d1939SAndy Fiddaman 			char *sub=0, *prefix= shp->prefix;
1523*b30d1939SAndy Fiddaman 			Namval_t *mp;
1524*b30d1939SAndy Fiddaman 			Namarr_t *ap;
1525*b30d1939SAndy Fiddaman 			int isref;
1526*b30d1939SAndy Fiddaman 			shp->prefix = 0;
1527*b30d1939SAndy Fiddaman 			if((flags&NV_STATIC) && !shp->mktype)
1528*b30d1939SAndy Fiddaman 			{
1529*b30d1939SAndy Fiddaman 				if(!nv_isnull(np))
1530*b30d1939SAndy Fiddaman 				{
1531*b30d1939SAndy Fiddaman 					shp->prefix = prefix;
1532*b30d1939SAndy Fiddaman 					return(np);
1533*b30d1939SAndy Fiddaman 				}
1534*b30d1939SAndy Fiddaman 			}
1535*b30d1939SAndy Fiddaman 			isref = nv_isref(np);
1536*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1537*b30d1939SAndy Fiddaman 			if(sh_isoption(SH_XTRACE) && (ap=nv_arrayptr(np)) && !ap->fixed)
1538*b30d1939SAndy Fiddaman #else
1539*b30d1939SAndy Fiddaman 			if(sh_isoption(SH_XTRACE) && nv_isarray(np))
1540*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1541*b30d1939SAndy Fiddaman 				sub = nv_getsub(np);
1542*b30d1939SAndy Fiddaman 			c = msg==e_aliname? 0: (append | (flags&NV_EXPORT));
1543*b30d1939SAndy Fiddaman 			if(isref)
1544*b30d1939SAndy Fiddaman 				nv_offattr(np,NV_REF);
1545*b30d1939SAndy Fiddaman 			if(!append && (flags&NV_UNJUST))
1546*b30d1939SAndy Fiddaman 			{
1547*b30d1939SAndy Fiddaman 				if(!np->nvfun)
1548*b30d1939SAndy Fiddaman 					_nv_unset(np,NV_EXPORT);
1549*b30d1939SAndy Fiddaman 			}
1550*b30d1939SAndy Fiddaman 			if(flags&NV_MOVE)
1551*b30d1939SAndy Fiddaman 			{
1552*b30d1939SAndy Fiddaman 				if(ap=nv_arrayptr(np))
1553*b30d1939SAndy Fiddaman 				{
1554*b30d1939SAndy Fiddaman 					if(mp=nv_opensub(np))
1555*b30d1939SAndy Fiddaman 						np = mp;
1556*b30d1939SAndy Fiddaman 					else if(!array_assoc(ap) && (mp = nv_open(cp,shp->var_tree,NV_NOFAIL|NV_VARNAME|NV_NOARRAY|NV_NOASSIGN|NV_NOADD)) && nv_isvtree(np))
1557*b30d1939SAndy Fiddaman 					{
1558*b30d1939SAndy Fiddaman 						ap->nelem |= ARRAY_TREE;
1559*b30d1939SAndy Fiddaman 						nv_putsub(np,(char*)0,ARRAY_ADD|nv_aindex(np));
1560*b30d1939SAndy Fiddaman 						np = nv_opensub(np);
1561*b30d1939SAndy Fiddaman 						ap->nelem &= ~ARRAY_TREE;
1562*b30d1939SAndy Fiddaman 						ap->nelem -= 1;
1563*b30d1939SAndy Fiddaman 					}
1564*b30d1939SAndy Fiddaman 				}
1565*b30d1939SAndy Fiddaman 				_nv_unset(np,NV_EXPORT);
1566*b30d1939SAndy Fiddaman 			}
1567*b30d1939SAndy Fiddaman 			nv_putval(np, cp, c);
1568*b30d1939SAndy Fiddaman 			if(isref)
1569*b30d1939SAndy Fiddaman 			{
1570*b30d1939SAndy Fiddaman 				if(nv_search((char*)np,shp->var_base,HASH_BUCKET))
1571*b30d1939SAndy Fiddaman 					shp->last_root = shp->var_base;
1572*b30d1939SAndy Fiddaman 				nv_setref(np,(Dt_t*)0,NV_VARNAME);
1573*b30d1939SAndy Fiddaman 			}
1574*b30d1939SAndy Fiddaman 			savesub = sub;
1575*b30d1939SAndy Fiddaman 			shp->prefix = prefix;
1576*b30d1939SAndy Fiddaman 		}
1577*b30d1939SAndy Fiddaman 		nv_onattr(np, flags&NV_ATTRIBUTES);
1578*b30d1939SAndy Fiddaman 	}
1579*b30d1939SAndy Fiddaman 	else if(c)
1580*b30d1939SAndy Fiddaman 	{
1581*b30d1939SAndy Fiddaman 		if(flags&NV_NOFAIL)
1582*b30d1939SAndy Fiddaman 			return(0);
1583*b30d1939SAndy Fiddaman 		if(c=='.')
1584*b30d1939SAndy Fiddaman 			msg = e_noparent;
1585*b30d1939SAndy Fiddaman 		else if(c=='[')
1586*b30d1939SAndy Fiddaman 			msg = e_noarray;
1587*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),msg,name);
1588*b30d1939SAndy Fiddaman 	}
1589*b30d1939SAndy Fiddaman 	if(fun.nofree&1)
1590*b30d1939SAndy Fiddaman 		stakseek(offset);
1591*b30d1939SAndy Fiddaman 	return(np);
1592*b30d1939SAndy Fiddaman }
1593*b30d1939SAndy Fiddaman 
1594*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
1595*b30d1939SAndy Fiddaman     static int ja_size(char*, int, int);
1596*b30d1939SAndy Fiddaman     static void ja_restore(void);
1597*b30d1939SAndy Fiddaman     static char *savep;
1598*b30d1939SAndy Fiddaman     static char savechars[8+1];
1599*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
1600*b30d1939SAndy Fiddaman 
1601*b30d1939SAndy Fiddaman /*
1602*b30d1939SAndy Fiddaman  * put value <string> into name-value node <np>.
1603*b30d1939SAndy Fiddaman  * If <np> is an array, then the element given by the
1604*b30d1939SAndy Fiddaman  *   current index is assigned to.
1605*b30d1939SAndy Fiddaman  * If <flags> contains NV_RDONLY, readonly attribute is ignored
1606*b30d1939SAndy Fiddaman  * If <flags> contains NV_INTEGER, string is a pointer to a number
1607*b30d1939SAndy Fiddaman  * If <flags> contains NV_NOFREE, previous value is freed, and <string>
1608*b30d1939SAndy Fiddaman  * becomes value of node and <flags> becomes attributes
1609*b30d1939SAndy Fiddaman  */
nv_putval(register Namval_t * np,const char * string,int flags)1610*b30d1939SAndy Fiddaman void nv_putval(register Namval_t *np, const char *string, int flags)
1611*b30d1939SAndy Fiddaman {
1612*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
1613*b30d1939SAndy Fiddaman 	register const char *sp=string;
1614*b30d1939SAndy Fiddaman 	register union Value *up;
1615*b30d1939SAndy Fiddaman 	register char *cp;
1616*b30d1939SAndy Fiddaman 	register int size = 0;
1617*b30d1939SAndy Fiddaman 	register int dot;
1618*b30d1939SAndy Fiddaman 	int	was_local = nv_local;
1619*b30d1939SAndy Fiddaman 	union Value u;
1620*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1621*b30d1939SAndy Fiddaman 	Namarr_t	*ap;
1622*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1623*b30d1939SAndy Fiddaman 	if(!(flags&NV_RDONLY) && nv_isattr (np, NV_RDONLY))
1624*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
1625*b30d1939SAndy Fiddaman 	/* The following could cause the shell to fork if assignment
1626*b30d1939SAndy Fiddaman 	 * would cause a side effect
1627*b30d1939SAndy Fiddaman 	 */
1628*b30d1939SAndy Fiddaman 	shp->argaddr = 0;
1629*b30d1939SAndy Fiddaman 	if(shp->subshell && !nv_local && !(flags&NV_RDONLY))
1630*b30d1939SAndy Fiddaman 		np = sh_assignok(np,1);
1631*b30d1939SAndy Fiddaman 	if(np->nvfun && np->nvfun->disc && !(flags&NV_NODISC) && !nv_isref(np))
1632*b30d1939SAndy Fiddaman 	{
1633*b30d1939SAndy Fiddaman 		/* This function contains disc */
1634*b30d1939SAndy Fiddaman 		if(!nv_local)
1635*b30d1939SAndy Fiddaman 		{
1636*b30d1939SAndy Fiddaman 			nv_local=1;
1637*b30d1939SAndy Fiddaman 			nv_putv(np,sp,flags,np->nvfun);
1638*b30d1939SAndy Fiddaman 			if(sp && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT)))
1639*b30d1939SAndy Fiddaman 				sh_envput(shp->env,np);
1640*b30d1939SAndy Fiddaman 			return;
1641*b30d1939SAndy Fiddaman 		}
1642*b30d1939SAndy Fiddaman 		/* called from disc, assign the actual value */
1643*b30d1939SAndy Fiddaman 	}
1644*b30d1939SAndy Fiddaman 	flags &= ~NV_NODISC;
1645*b30d1939SAndy Fiddaman 	nv_local=0;
1646*b30d1939SAndy Fiddaman 	if(flags&(NV_NOREF|NV_NOFREE))
1647*b30d1939SAndy Fiddaman 	{
1648*b30d1939SAndy Fiddaman 		if(np->nvalue.cp && np->nvalue.cp!=sp && !nv_isattr(np,NV_NOFREE))
1649*b30d1939SAndy Fiddaman 			free((void*)np->nvalue.cp);
1650*b30d1939SAndy Fiddaman 		np->nvalue.cp = (char*)sp;
1651*b30d1939SAndy Fiddaman 		nv_setattr(np,(flags&~NV_RDONLY)|NV_NOFREE);
1652*b30d1939SAndy Fiddaman 		return;
1653*b30d1939SAndy Fiddaman 	}
1654*b30d1939SAndy Fiddaman 	up= &np->nvalue;
1655*b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_INT16P) == NV_INT16)
1656*b30d1939SAndy Fiddaman 	{
1657*b30d1939SAndy Fiddaman 		if(!np->nvalue.up || !nv_isarray(np))
1658*b30d1939SAndy Fiddaman 		{
1659*b30d1939SAndy Fiddaman 			up = &u;
1660*b30d1939SAndy Fiddaman 			up->up = &np->nvalue;
1661*b30d1939SAndy Fiddaman 		}
1662*b30d1939SAndy Fiddaman 	}
1663*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1664*b30d1939SAndy Fiddaman 	else if(np->nvalue.up && nv_isarray(np) && (ap=nv_arrayptr(np)) && !ap->fixed)
1665*b30d1939SAndy Fiddaman #else
1666*b30d1939SAndy Fiddaman 	else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np))
1667*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1668*b30d1939SAndy Fiddaman 		up = np->nvalue.up;
1669*b30d1939SAndy Fiddaman 	if(up && up->cp==Empty)
1670*b30d1939SAndy Fiddaman 		up->cp = 0;
1671*b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_EXPORT))
1672*b30d1939SAndy Fiddaman 		nv_offattr(np,NV_IMPORT);
1673*b30d1939SAndy Fiddaman 	if(nv_isattr (np, NV_INTEGER))
1674*b30d1939SAndy Fiddaman 	{
1675*b30d1939SAndy Fiddaman 		if(nv_isattr(np, NV_DOUBLE) == NV_DOUBLE)
1676*b30d1939SAndy Fiddaman 		{
1677*b30d1939SAndy Fiddaman 			if(nv_isattr(np, NV_LONG) && sizeof(double)<sizeof(Sfdouble_t))
1678*b30d1939SAndy Fiddaman 			{
1679*b30d1939SAndy Fiddaman 				Sfdouble_t ld, old=0;
1680*b30d1939SAndy Fiddaman 				if(flags&NV_INTEGER)
1681*b30d1939SAndy Fiddaman 				{
1682*b30d1939SAndy Fiddaman 					if(flags&NV_LONG)
1683*b30d1939SAndy Fiddaman 						ld = *((Sfdouble_t*)sp);
1684*b30d1939SAndy Fiddaman 					else if(flags&NV_SHORT)
1685*b30d1939SAndy Fiddaman 						ld = *((float*)sp);
1686*b30d1939SAndy Fiddaman 					else
1687*b30d1939SAndy Fiddaman 						ld = *((double*)sp);
1688*b30d1939SAndy Fiddaman 				}
1689*b30d1939SAndy Fiddaman 				else
1690*b30d1939SAndy Fiddaman 					ld = sh_arith(shp,sp);
1691*b30d1939SAndy Fiddaman 				if(!up->ldp)
1692*b30d1939SAndy Fiddaman 					up->ldp = new_of(Sfdouble_t,0);
1693*b30d1939SAndy Fiddaman 				else if(flags&NV_APPEND)
1694*b30d1939SAndy Fiddaman 					old = *(up->ldp);
1695*b30d1939SAndy Fiddaman 				*(up->ldp) = old?ld+old:ld;
1696*b30d1939SAndy Fiddaman 			}
1697*b30d1939SAndy Fiddaman 			else
1698*b30d1939SAndy Fiddaman 			{
1699*b30d1939SAndy Fiddaman 				double d,od=0;
1700*b30d1939SAndy Fiddaman 				if(flags&NV_INTEGER)
1701*b30d1939SAndy Fiddaman 				{
1702*b30d1939SAndy Fiddaman 					if(flags&NV_LONG)
1703*b30d1939SAndy Fiddaman 						d = (double)(*(Sfdouble_t*)sp);
1704*b30d1939SAndy Fiddaman 					else if(flags&NV_SHORT)
1705*b30d1939SAndy Fiddaman 						d = (double)(*(float*)sp);
1706*b30d1939SAndy Fiddaman 					else
1707*b30d1939SAndy Fiddaman 						d = *(double*)sp;
1708*b30d1939SAndy Fiddaman 				}
1709*b30d1939SAndy Fiddaman 				else
1710*b30d1939SAndy Fiddaman 					d = sh_arith(shp,sp);
1711*b30d1939SAndy Fiddaman 				if(!up->dp)
1712*b30d1939SAndy Fiddaman 					up->dp = new_of(double,0);
1713*b30d1939SAndy Fiddaman 				else if(flags&NV_APPEND)
1714*b30d1939SAndy Fiddaman 					od = *(up->dp);
1715*b30d1939SAndy Fiddaman 				*(up->dp) = od?d+od:d;
1716*b30d1939SAndy Fiddaman 			}
1717*b30d1939SAndy Fiddaman 		}
1718*b30d1939SAndy Fiddaman 		else
1719*b30d1939SAndy Fiddaman 		{
1720*b30d1939SAndy Fiddaman 			if(nv_isattr(np, NV_LONG) && sizeof(int32_t)<sizeof(Sflong_t))
1721*b30d1939SAndy Fiddaman 			{
1722*b30d1939SAndy Fiddaman 				Sflong_t ll=0,oll=0;
1723*b30d1939SAndy Fiddaman 				if(flags&NV_INTEGER)
1724*b30d1939SAndy Fiddaman 				{
1725*b30d1939SAndy Fiddaman 					if((flags&NV_DOUBLE) == NV_DOUBLE)
1726*b30d1939SAndy Fiddaman 					{
1727*b30d1939SAndy Fiddaman 						if(flags&NV_LONG)
1728*b30d1939SAndy Fiddaman 							ll = *((Sfdouble_t*)sp);
1729*b30d1939SAndy Fiddaman 						else if(flags&NV_SHORT)
1730*b30d1939SAndy Fiddaman 							ll = *((float*)sp);
1731*b30d1939SAndy Fiddaman 						else
1732*b30d1939SAndy Fiddaman 							ll = *((double*)sp);
1733*b30d1939SAndy Fiddaman 					}
1734*b30d1939SAndy Fiddaman 					else if(nv_isattr(np,NV_UNSIGN))
1735*b30d1939SAndy Fiddaman 					{
1736*b30d1939SAndy Fiddaman 						if(flags&NV_LONG)
1737*b30d1939SAndy Fiddaman 							ll = *((Sfulong_t*)sp);
1738*b30d1939SAndy Fiddaman 						else if(flags&NV_SHORT)
1739*b30d1939SAndy Fiddaman 							ll = *((uint16_t*)sp);
1740*b30d1939SAndy Fiddaman 						else
1741*b30d1939SAndy Fiddaman 							ll = *((uint32_t*)sp);
1742*b30d1939SAndy Fiddaman 					}
1743*b30d1939SAndy Fiddaman 					else
1744*b30d1939SAndy Fiddaman 					{
1745*b30d1939SAndy Fiddaman 						if(flags&NV_LONG)
1746*b30d1939SAndy Fiddaman 							ll = *((Sflong_t*)sp);
1747*b30d1939SAndy Fiddaman 						else if(flags&NV_SHORT)
1748*b30d1939SAndy Fiddaman 							ll = *((uint16_t*)sp);
1749*b30d1939SAndy Fiddaman 						else
1750*b30d1939SAndy Fiddaman 							ll = *((uint32_t*)sp);
1751*b30d1939SAndy Fiddaman 					}
1752*b30d1939SAndy Fiddaman 				}
1753*b30d1939SAndy Fiddaman 				else if(sp)
1754*b30d1939SAndy Fiddaman 					ll = (Sflong_t)sh_arith(shp,sp);
1755*b30d1939SAndy Fiddaman 				if(!up->llp)
1756*b30d1939SAndy Fiddaman 					up->llp = new_of(Sflong_t,0);
1757*b30d1939SAndy Fiddaman 				else if(flags&NV_APPEND)
1758*b30d1939SAndy Fiddaman 					oll = *(up->llp);
1759*b30d1939SAndy Fiddaman 				*(up->llp) = ll+oll;
1760*b30d1939SAndy Fiddaman 			}
1761*b30d1939SAndy Fiddaman 			else
1762*b30d1939SAndy Fiddaman 			{
1763*b30d1939SAndy Fiddaman 				int32_t l=0,ol=0;
1764*b30d1939SAndy Fiddaman 				if(flags&NV_INTEGER)
1765*b30d1939SAndy Fiddaman 				{
1766*b30d1939SAndy Fiddaman 					if((flags&NV_DOUBLE) == NV_DOUBLE)
1767*b30d1939SAndy Fiddaman 					{
1768*b30d1939SAndy Fiddaman 						Sflong_t ll;
1769*b30d1939SAndy Fiddaman 						if(flags&NV_LONG)
1770*b30d1939SAndy Fiddaman 							ll = *((Sfdouble_t*)sp);
1771*b30d1939SAndy Fiddaman 						else if(flags&NV_SHORT)
1772*b30d1939SAndy Fiddaman 							ll = *((float*)sp);
1773*b30d1939SAndy Fiddaman 						else
1774*b30d1939SAndy Fiddaman 							ll = *((double*)sp);
1775*b30d1939SAndy Fiddaman 						l = (int32_t)ll;
1776*b30d1939SAndy Fiddaman 					}
1777*b30d1939SAndy Fiddaman 					else if(nv_isattr(np,NV_UNSIGN))
1778*b30d1939SAndy Fiddaman 					{
1779*b30d1939SAndy Fiddaman 						if(flags&NV_LONG)
1780*b30d1939SAndy Fiddaman 							l = *((Sfulong_t*)sp);
1781*b30d1939SAndy Fiddaman 						else if(flags&NV_SHORT)
1782*b30d1939SAndy Fiddaman 							l = *((uint16_t*)sp);
1783*b30d1939SAndy Fiddaman 						else
1784*b30d1939SAndy Fiddaman 							l = *(uint32_t*)sp;
1785*b30d1939SAndy Fiddaman 					}
1786*b30d1939SAndy Fiddaman 					else
1787*b30d1939SAndy Fiddaman 					{
1788*b30d1939SAndy Fiddaman 						if(flags&NV_LONG)
1789*b30d1939SAndy Fiddaman 							l = *((Sflong_t*)sp);
1790*b30d1939SAndy Fiddaman 						else if(flags&NV_SHORT)
1791*b30d1939SAndy Fiddaman 							l = *((int16_t*)sp);
1792*b30d1939SAndy Fiddaman 						else
1793*b30d1939SAndy Fiddaman 							l = *(int32_t*)sp;
1794*b30d1939SAndy Fiddaman 					}
1795*b30d1939SAndy Fiddaman 				}
1796*b30d1939SAndy Fiddaman 				else if(sp)
1797*b30d1939SAndy Fiddaman 				{
1798*b30d1939SAndy Fiddaman 					Sfdouble_t ld = sh_arith(shp,sp);
1799*b30d1939SAndy Fiddaman 					if(ld<0)
1800*b30d1939SAndy Fiddaman 						l = (int32_t)ld;
1801*b30d1939SAndy Fiddaman 					else
1802*b30d1939SAndy Fiddaman 						l = (uint32_t)ld;
1803*b30d1939SAndy Fiddaman 				}
1804*b30d1939SAndy Fiddaman 				if(nv_size(np) <= 1)
1805*b30d1939SAndy Fiddaman 					nv_setsize(np,10);
1806*b30d1939SAndy Fiddaman 				if(nv_isattr (np, NV_SHORT))
1807*b30d1939SAndy Fiddaman 				{
1808*b30d1939SAndy Fiddaman 					int16_t s=0;
1809*b30d1939SAndy Fiddaman 					if(flags&NV_APPEND)
1810*b30d1939SAndy Fiddaman 						s = *up->sp;
1811*b30d1939SAndy Fiddaman 					*(up->sp) = s+(int16_t)l;
1812*b30d1939SAndy Fiddaman 					nv_onattr(np,NV_NOFREE);
1813*b30d1939SAndy Fiddaman 				}
1814*b30d1939SAndy Fiddaman 				else
1815*b30d1939SAndy Fiddaman 				{
1816*b30d1939SAndy Fiddaman 					if(!up->lp)
1817*b30d1939SAndy Fiddaman 						up->lp = new_of(int32_t,0);
1818*b30d1939SAndy Fiddaman 					else if(flags&NV_APPEND)
1819*b30d1939SAndy Fiddaman 						ol =  *(up->lp);
1820*b30d1939SAndy Fiddaman 					*(up->lp) = l+ol;
1821*b30d1939SAndy Fiddaman 				}
1822*b30d1939SAndy Fiddaman 			}
1823*b30d1939SAndy Fiddaman 		}
1824*b30d1939SAndy Fiddaman 	}
1825*b30d1939SAndy Fiddaman 	else
1826*b30d1939SAndy Fiddaman 	{
1827*b30d1939SAndy Fiddaman 		const char *tofree=0;
1828*b30d1939SAndy Fiddaman 		int offset,append;
1829*b30d1939SAndy Fiddaman #if _lib_pathnative
1830*b30d1939SAndy Fiddaman 		char buff[PATH_MAX];
1831*b30d1939SAndy Fiddaman #endif /* _lib_pathnative */
1832*b30d1939SAndy Fiddaman 		if(flags&NV_INTEGER)
1833*b30d1939SAndy Fiddaman 		{
1834*b30d1939SAndy Fiddaman 			if((flags&NV_DOUBLE)==NV_DOUBLE)
1835*b30d1939SAndy Fiddaman 			{
1836*b30d1939SAndy Fiddaman 				if(flags&NV_LONG)
1837*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%.*Lg",LDBL_DIG,*((Sfdouble_t*)sp));
1838*b30d1939SAndy Fiddaman 				else
1839*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%.*g",DBL_DIG,*((double*)sp));
1840*b30d1939SAndy Fiddaman 			}
1841*b30d1939SAndy Fiddaman 			else if(flags&NV_UNSIGN)
1842*b30d1939SAndy Fiddaman 			{
1843*b30d1939SAndy Fiddaman 				if(flags&NV_LONG)
1844*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%I*lu",sizeof(Sfulong_t),*((Sfulong_t*)sp));
1845*b30d1939SAndy Fiddaman 				else
1846*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%lu",(unsigned long)((flags&NV_SHORT)?*((uint16_t*)sp):*((uint32_t*)sp)));
1847*b30d1939SAndy Fiddaman 			}
1848*b30d1939SAndy Fiddaman 			else
1849*b30d1939SAndy Fiddaman 			{
1850*b30d1939SAndy Fiddaman 				if(flags&NV_LONG)
1851*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%I*ld",sizeof(Sflong_t),*((Sflong_t*)sp));
1852*b30d1939SAndy Fiddaman 				else
1853*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%ld",(long)((flags&NV_SHORT)?*((int16_t*)sp):*((int32_t*)sp)));
1854*b30d1939SAndy Fiddaman 			}
1855*b30d1939SAndy Fiddaman 			sp = sfstruse(shp->strbuf);
1856*b30d1939SAndy Fiddaman 		}
1857*b30d1939SAndy Fiddaman 		if(nv_isattr(np, NV_HOST|NV_INTEGER)==NV_HOST && sp)
1858*b30d1939SAndy Fiddaman 		{
1859*b30d1939SAndy Fiddaman #ifdef _lib_pathnative
1860*b30d1939SAndy Fiddaman 			/*
1861*b30d1939SAndy Fiddaman 			 * return the host file name given the UNIX name
1862*b30d1939SAndy Fiddaman 			 */
1863*b30d1939SAndy Fiddaman 			pathnative(sp,buff,sizeof(buff));
1864*b30d1939SAndy Fiddaman 			if(buff[1]==':' && buff[2]=='/')
1865*b30d1939SAndy Fiddaman 			{
1866*b30d1939SAndy Fiddaman 				buff[2] = '\\';
1867*b30d1939SAndy Fiddaman 				if(*buff>='A' &&  *buff<='Z')
1868*b30d1939SAndy Fiddaman 					*buff += 'a'-'A';
1869*b30d1939SAndy Fiddaman 			}
1870*b30d1939SAndy Fiddaman 			sp = buff;
1871*b30d1939SAndy Fiddaman #else
1872*b30d1939SAndy Fiddaman 			;
1873*b30d1939SAndy Fiddaman #endif /* _lib_pathnative */
1874*b30d1939SAndy Fiddaman 		}
1875*b30d1939SAndy Fiddaman 		else if((nv_isattr(np, NV_RJUST|NV_ZFILL|NV_LJUST)) && sp)
1876*b30d1939SAndy Fiddaman 		{
1877*b30d1939SAndy Fiddaman 			for(;*sp == ' '|| *sp=='\t';sp++);
1878*b30d1939SAndy Fiddaman 	        	if((nv_isattr(np,NV_ZFILL)) && (nv_isattr(np,NV_LJUST)))
1879*b30d1939SAndy Fiddaman 				for(;*sp=='0';sp++);
1880*b30d1939SAndy Fiddaman 			size = nv_size(np);
1881*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
1882*b30d1939SAndy Fiddaman 			if(size)
1883*b30d1939SAndy Fiddaman 				size = ja_size((char*)sp,size,nv_isattr(np,NV_RJUST|NV_ZFILL));
1884*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
1885*b30d1939SAndy Fiddaman 		}
1886*b30d1939SAndy Fiddaman 		if(!up->cp || *up->cp==0)
1887*b30d1939SAndy Fiddaman 			flags &= ~NV_APPEND;
1888*b30d1939SAndy Fiddaman 		if(!nv_isattr(np, NV_NOFREE))
1889*b30d1939SAndy Fiddaman 		{
1890*b30d1939SAndy Fiddaman 			/* delay free in case <sp> points into free region */
1891*b30d1939SAndy Fiddaman 			tofree = up->cp;
1892*b30d1939SAndy Fiddaman 		}
1893*b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_BINARY) && !(flags&NV_RAW))
1894*b30d1939SAndy Fiddaman 			tofree = 0;
1895*b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_LJUST|NV_RJUST) && nv_isattr(np,NV_LJUST|NV_RJUST)!=(NV_LJUST|NV_RJUST))
1896*b30d1939SAndy Fiddaman 			tofree = 0;
1897*b30d1939SAndy Fiddaman        	 	if (sp)
1898*b30d1939SAndy Fiddaman 		{
1899*b30d1939SAndy Fiddaman 			append=0;
1900*b30d1939SAndy Fiddaman 			if(sp==up->cp && !(flags&NV_APPEND))
1901*b30d1939SAndy Fiddaman 				return;
1902*b30d1939SAndy Fiddaman 			dot = strlen(sp);
1903*b30d1939SAndy Fiddaman #if (_AST_VERSION>=20030127L)
1904*b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_BINARY))
1905*b30d1939SAndy Fiddaman 			{
1906*b30d1939SAndy Fiddaman 				int oldsize = (flags&NV_APPEND)?nv_size(np):0;
1907*b30d1939SAndy Fiddaman 				if(flags&NV_RAW)
1908*b30d1939SAndy Fiddaman 				{
1909*b30d1939SAndy Fiddaman 					if(tofree)
1910*b30d1939SAndy Fiddaman 					{
1911*b30d1939SAndy Fiddaman 						free((void*)tofree);
1912*b30d1939SAndy Fiddaman 						nv_offattr(np,NV_NOFREE);
1913*b30d1939SAndy Fiddaman 					}
1914*b30d1939SAndy Fiddaman 					up->cp = sp;
1915*b30d1939SAndy Fiddaman 					return;
1916*b30d1939SAndy Fiddaman 				}
1917*b30d1939SAndy Fiddaman 				size = 0;
1918*b30d1939SAndy Fiddaman 				if(nv_isattr(np,NV_ZFILL))
1919*b30d1939SAndy Fiddaman 					size = nv_size(np);
1920*b30d1939SAndy Fiddaman 				if(size==0)
1921*b30d1939SAndy Fiddaman 					size = oldsize + (3*dot/4);
1922*b30d1939SAndy Fiddaman 				*(cp = (char*)malloc(size+1)) = 0;
1923*b30d1939SAndy Fiddaman 				nv_offattr(np,NV_NOFREE);
1924*b30d1939SAndy Fiddaman 				if(oldsize)
1925*b30d1939SAndy Fiddaman 					memcpy((void*)cp,(void*)up->cp,oldsize);
1926*b30d1939SAndy Fiddaman 				up->cp = cp;
1927*b30d1939SAndy Fiddaman 				if(size <= oldsize)
1928*b30d1939SAndy Fiddaman 					return;
1929*b30d1939SAndy Fiddaman 				dot = base64decode(sp,dot, (void**)0, cp+oldsize, size-oldsize,(void**)0);
1930*b30d1939SAndy Fiddaman 				dot += oldsize;
1931*b30d1939SAndy Fiddaman 				if(!nv_isattr(np,NV_ZFILL) || nv_size(np)==0)
1932*b30d1939SAndy Fiddaman 					nv_setsize(np,dot);
1933*b30d1939SAndy Fiddaman 				else if(nv_isattr(np,NV_ZFILL) && (size>dot))
1934*b30d1939SAndy Fiddaman 					memset((void*)&cp[dot],0,size-dot);
1935*b30d1939SAndy Fiddaman 				return;
1936*b30d1939SAndy Fiddaman 			}
1937*b30d1939SAndy Fiddaman 			else
1938*b30d1939SAndy Fiddaman #endif
1939*b30d1939SAndy Fiddaman 			{
1940*b30d1939SAndy Fiddaman 				if(size==0 && nv_isattr(np,NV_HOST)!=NV_HOST &&nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL))
1941*b30d1939SAndy Fiddaman 				{
1942*b30d1939SAndy Fiddaman 					nv_setsize(np,size=dot);
1943*b30d1939SAndy Fiddaman 					tofree = up->cp;
1944*b30d1939SAndy Fiddaman 				}
1945*b30d1939SAndy Fiddaman 				else if(size > dot)
1946*b30d1939SAndy Fiddaman 					dot = size;
1947*b30d1939SAndy Fiddaman 				else if(nv_isattr(np,NV_LJUST|NV_RJUST)==NV_LJUST && dot>size)
1948*b30d1939SAndy Fiddaman 					dot = size;
1949*b30d1939SAndy Fiddaman 				if(flags&NV_APPEND)
1950*b30d1939SAndy Fiddaman 				{
1951*b30d1939SAndy Fiddaman 					if(dot==0)
1952*b30d1939SAndy Fiddaman 						return;
1953*b30d1939SAndy Fiddaman 					append = strlen(up->cp);
1954*b30d1939SAndy Fiddaman 					if(!tofree || size)
1955*b30d1939SAndy Fiddaman 					{
1956*b30d1939SAndy Fiddaman 						offset = staktell();
1957*b30d1939SAndy Fiddaman 						stakputs(up->cp);
1958*b30d1939SAndy Fiddaman 						stakputs(sp);
1959*b30d1939SAndy Fiddaman 						stakputc(0);
1960*b30d1939SAndy Fiddaman 						sp = stakptr(offset);
1961*b30d1939SAndy Fiddaman 						dot += append;
1962*b30d1939SAndy Fiddaman 						append = 0;
1963*b30d1939SAndy Fiddaman 					}
1964*b30d1939SAndy Fiddaman 					else
1965*b30d1939SAndy Fiddaman 					{
1966*b30d1939SAndy Fiddaman 						flags &= ~NV_APPEND;
1967*b30d1939SAndy Fiddaman 					}
1968*b30d1939SAndy Fiddaman 				}
1969*b30d1939SAndy Fiddaman 			}
1970*b30d1939SAndy Fiddaman 			if(size==0 || tofree || dot || !(cp=(char*)up->cp))
1971*b30d1939SAndy Fiddaman 			{
1972*b30d1939SAndy Fiddaman 				if(dot==0 && !nv_isattr(np,NV_LJUST|NV_RJUST))
1973*b30d1939SAndy Fiddaman 				{
1974*b30d1939SAndy Fiddaman 					cp = Null;
1975*b30d1939SAndy Fiddaman 					nv_onattr(np,NV_NOFREE);
1976*b30d1939SAndy Fiddaman 				}
1977*b30d1939SAndy Fiddaman 				else
1978*b30d1939SAndy Fiddaman 				{
1979*b30d1939SAndy Fiddaman 					if(tofree && tofree!=Empty && tofree!=Null)
1980*b30d1939SAndy Fiddaman 					{
1981*b30d1939SAndy Fiddaman 						cp = (char*)realloc((void*)tofree,((unsigned)dot+append+8));
1982*b30d1939SAndy Fiddaman 						tofree = 0;
1983*b30d1939SAndy Fiddaman 					}
1984*b30d1939SAndy Fiddaman 					else
1985*b30d1939SAndy Fiddaman 						cp = (char*)malloc(((unsigned)dot+8));
1986*b30d1939SAndy Fiddaman 					cp[dot+append] = 0;
1987*b30d1939SAndy Fiddaman 					nv_offattr(np,NV_NOFREE);
1988*b30d1939SAndy Fiddaman 				}
1989*b30d1939SAndy Fiddaman 			}
1990*b30d1939SAndy Fiddaman 
1991*b30d1939SAndy Fiddaman 		}
1992*b30d1939SAndy Fiddaman 		else
1993*b30d1939SAndy Fiddaman 			cp = 0;
1994*b30d1939SAndy Fiddaman 		up->cp = cp;
1995*b30d1939SAndy Fiddaman 		if(sp)
1996*b30d1939SAndy Fiddaman 		{
1997*b30d1939SAndy Fiddaman 			int c = cp[dot+append];
1998*b30d1939SAndy Fiddaman 			memmove(cp+append,sp,dot);
1999*b30d1939SAndy Fiddaman 			cp[dot+append] = c;
2000*b30d1939SAndy Fiddaman 			if(nv_isattr(np, NV_RJUST) && nv_isattr(np, NV_ZFILL))
2001*b30d1939SAndy Fiddaman 				rightjust(cp,size,'0');
2002*b30d1939SAndy Fiddaman 			else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_RJUST)
2003*b30d1939SAndy Fiddaman 				rightjust(cp,size,' ');
2004*b30d1939SAndy Fiddaman 			else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_LJUST)
2005*b30d1939SAndy Fiddaman 			{
2006*b30d1939SAndy Fiddaman 				register char *dp;
2007*b30d1939SAndy Fiddaman 				dp = strlen (cp) + cp;
2008*b30d1939SAndy Fiddaman 				cp = cp+size;
2009*b30d1939SAndy Fiddaman 				for (; dp < cp; *dp++ = ' ');
2010*b30d1939SAndy Fiddaman 			 }
2011*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2012*b30d1939SAndy Fiddaman 			/* restore original string */
2013*b30d1939SAndy Fiddaman 			if(savep)
2014*b30d1939SAndy Fiddaman 				ja_restore();
2015*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2016*b30d1939SAndy Fiddaman 		}
2017*b30d1939SAndy Fiddaman 		if(flags&NV_APPEND)
2018*b30d1939SAndy Fiddaman 			stakseek(offset);
2019*b30d1939SAndy Fiddaman 		if(tofree && tofree!=Empty && tofree!=Null)
2020*b30d1939SAndy Fiddaman 			free((void*)tofree);
2021*b30d1939SAndy Fiddaman 	}
2022*b30d1939SAndy Fiddaman 	if(!was_local && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT)))
2023*b30d1939SAndy Fiddaman 		sh_envput(shp->env,np);
2024*b30d1939SAndy Fiddaman 	return;
2025*b30d1939SAndy Fiddaman }
2026*b30d1939SAndy Fiddaman 
2027*b30d1939SAndy Fiddaman /*
2028*b30d1939SAndy Fiddaman  *
2029*b30d1939SAndy Fiddaman  *   Right-justify <str> so that it contains no more than
2030*b30d1939SAndy Fiddaman  *   <size> characters.  If <str> contains fewer than <size>
2031*b30d1939SAndy Fiddaman  *   characters, left-pad with <fill>.  Trailing blanks
2032*b30d1939SAndy Fiddaman  *   in <str> will be ignored.
2033*b30d1939SAndy Fiddaman  *
2034*b30d1939SAndy Fiddaman  *   If the leftmost digit in <str> is not a digit, <fill>
2035*b30d1939SAndy Fiddaman  *   will default to a blank.
2036*b30d1939SAndy Fiddaman  */
rightjust(char * str,int size,int fill)2037*b30d1939SAndy Fiddaman static void rightjust(char *str, int size, int fill)
2038*b30d1939SAndy Fiddaman {
2039*b30d1939SAndy Fiddaman 	register int n;
2040*b30d1939SAndy Fiddaman 	register char *cp,*sp;
2041*b30d1939SAndy Fiddaman 	n = strlen(str);
2042*b30d1939SAndy Fiddaman 
2043*b30d1939SAndy Fiddaman 	/* ignore trailing blanks */
2044*b30d1939SAndy Fiddaman 	for(cp=str+n;n && *--cp == ' ';n--);
2045*b30d1939SAndy Fiddaman 	if (n == size)
2046*b30d1939SAndy Fiddaman 		return;
2047*b30d1939SAndy Fiddaman 	if(n > size)
2048*b30d1939SAndy Fiddaman         {
2049*b30d1939SAndy Fiddaman         	*(str+n) = 0;
2050*b30d1939SAndy Fiddaman         	for (sp = str, cp = str+n-size; sp <= str+size; *sp++ = *cp++);
2051*b30d1939SAndy Fiddaman         	return;
2052*b30d1939SAndy Fiddaman         }
2053*b30d1939SAndy Fiddaman 	else *(sp = str+size) = 0;
2054*b30d1939SAndy Fiddaman 	if (n == 0)
2055*b30d1939SAndy Fiddaman         {
2056*b30d1939SAndy Fiddaman         	while (sp > str)
2057*b30d1939SAndy Fiddaman                		*--sp = ' ';
2058*b30d1939SAndy Fiddaman         	return;
2059*b30d1939SAndy Fiddaman         }
2060*b30d1939SAndy Fiddaman 	while(n--)
2061*b30d1939SAndy Fiddaman 	{
2062*b30d1939SAndy Fiddaman 		sp--;
2063*b30d1939SAndy Fiddaman 		*sp = *cp--;
2064*b30d1939SAndy Fiddaman 	}
2065*b30d1939SAndy Fiddaman 	if(!isdigit(*str))
2066*b30d1939SAndy Fiddaman 		fill = ' ';
2067*b30d1939SAndy Fiddaman 	while(sp>str)
2068*b30d1939SAndy Fiddaman 		*--sp = fill;
2069*b30d1939SAndy Fiddaman 	return;
2070*b30d1939SAndy Fiddaman }
2071*b30d1939SAndy Fiddaman 
2072*b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
2073*b30d1939SAndy Fiddaman     /*
2074*b30d1939SAndy Fiddaman      * handle left and right justified fields for multi-byte chars
2075*b30d1939SAndy Fiddaman      * given physical size, return a logical size which reflects the
2076*b30d1939SAndy Fiddaman      * screen width of multi-byte characters
2077*b30d1939SAndy Fiddaman      * Multi-width characters replaced by spaces if they cross the boundary
2078*b30d1939SAndy Fiddaman      * <type> is non-zero for right justified  fields
2079*b30d1939SAndy Fiddaman      */
2080*b30d1939SAndy Fiddaman 
ja_size(char * str,int size,int type)2081*b30d1939SAndy Fiddaman     static int ja_size(char *str,int size,int type)
2082*b30d1939SAndy Fiddaman     {
2083*b30d1939SAndy Fiddaman 	register char *cp = str;
2084*b30d1939SAndy Fiddaman 	register int c, n=size;
2085*b30d1939SAndy Fiddaman 	register int outsize;
2086*b30d1939SAndy Fiddaman 	register char *oldcp=cp;
2087*b30d1939SAndy Fiddaman 	int oldn;
2088*b30d1939SAndy Fiddaman 	wchar_t w;
2089*b30d1939SAndy Fiddaman 	while(*cp)
2090*b30d1939SAndy Fiddaman 	{
2091*b30d1939SAndy Fiddaman 		oldn = n;
2092*b30d1939SAndy Fiddaman 		w = mbchar(cp);
2093*b30d1939SAndy Fiddaman 		if((outsize = mbwidth(w)) <0)
2094*b30d1939SAndy Fiddaman 			outsize = 0;
2095*b30d1939SAndy Fiddaman 		size -= outsize;
2096*b30d1939SAndy Fiddaman 		c = cp-oldcp;
2097*b30d1939SAndy Fiddaman 		n += (c-outsize);
2098*b30d1939SAndy Fiddaman 		oldcp = cp;
2099*b30d1939SAndy Fiddaman 		if(size<=0 && type==0)
2100*b30d1939SAndy Fiddaman 			break;
2101*b30d1939SAndy Fiddaman 	}
2102*b30d1939SAndy Fiddaman 	/* check for right justified fields that need truncating */
2103*b30d1939SAndy Fiddaman 	if(size <0)
2104*b30d1939SAndy Fiddaman 	{
2105*b30d1939SAndy Fiddaman 		if(type==0)
2106*b30d1939SAndy Fiddaman 		{
2107*b30d1939SAndy Fiddaman 			/* left justified and character crosses field boundary */
2108*b30d1939SAndy Fiddaman 			n = oldn;
2109*b30d1939SAndy Fiddaman 			/* save boundary char and replace with spaces */
2110*b30d1939SAndy Fiddaman 			size = c;
2111*b30d1939SAndy Fiddaman 			savechars[size] = 0;
2112*b30d1939SAndy Fiddaman 			while(size--)
2113*b30d1939SAndy Fiddaman 			{
2114*b30d1939SAndy Fiddaman 				savechars[size] = cp[size];
2115*b30d1939SAndy Fiddaman 				cp[size] = ' ';
2116*b30d1939SAndy Fiddaman 			}
2117*b30d1939SAndy Fiddaman 			savep = cp;
2118*b30d1939SAndy Fiddaman 		}
2119*b30d1939SAndy Fiddaman 		size = -size;
2120*b30d1939SAndy Fiddaman 		if(type)
2121*b30d1939SAndy Fiddaman 			n -= (ja_size(str,size,0)-size);
2122*b30d1939SAndy Fiddaman 	}
2123*b30d1939SAndy Fiddaman 	return(n);
2124*b30d1939SAndy Fiddaman     }
2125*b30d1939SAndy Fiddaman 
ja_restore(void)2126*b30d1939SAndy Fiddaman     static void ja_restore(void)
2127*b30d1939SAndy Fiddaman     {
2128*b30d1939SAndy Fiddaman 	register char *cp = savechars;
2129*b30d1939SAndy Fiddaman 	while(*cp)
2130*b30d1939SAndy Fiddaman 		*savep++ = *cp++;
2131*b30d1939SAndy Fiddaman 	savep = 0;
2132*b30d1939SAndy Fiddaman     }
2133*b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
2134*b30d1939SAndy Fiddaman 
2135*b30d1939SAndy Fiddaman #ifndef _ENV_H
staknam(register Namval_t * np,char * value)2136*b30d1939SAndy Fiddaman static char *staknam(register Namval_t *np, char *value)
2137*b30d1939SAndy Fiddaman {
2138*b30d1939SAndy Fiddaman 	register char *p,*q;
2139*b30d1939SAndy Fiddaman 	q = stakalloc(strlen(nv_name(np))+(value?strlen(value):0)+2);
2140*b30d1939SAndy Fiddaman 	p=strcopy(q,nv_name(np));
2141*b30d1939SAndy Fiddaman 	if(value)
2142*b30d1939SAndy Fiddaman 	{
2143*b30d1939SAndy Fiddaman 		*p++ = '=';
2144*b30d1939SAndy Fiddaman 		strcpy(p,value);
2145*b30d1939SAndy Fiddaman 	}
2146*b30d1939SAndy Fiddaman 	return(q);
2147*b30d1939SAndy Fiddaman }
2148*b30d1939SAndy Fiddaman #endif
2149*b30d1939SAndy Fiddaman 
2150*b30d1939SAndy Fiddaman /*
2151*b30d1939SAndy Fiddaman  * put the name and attribute into value of attributes variable
2152*b30d1939SAndy Fiddaman  */
2153*b30d1939SAndy Fiddaman #ifdef _ENV_H
attstore(register Namval_t * np,void * data)2154*b30d1939SAndy Fiddaman static void attstore(register Namval_t *np, void *data)
2155*b30d1939SAndy Fiddaman {
2156*b30d1939SAndy Fiddaman 	register int flag, c = ' ';
2157*b30d1939SAndy Fiddaman 	NOT_USED(data);
2158*b30d1939SAndy Fiddaman 	if(!(nv_isattr(np,NV_EXPORT)))
2159*b30d1939SAndy Fiddaman 		return;
2160*b30d1939SAndy Fiddaman 	flag = nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER);
2161*b30d1939SAndy Fiddaman 	stakputc('=');
2162*b30d1939SAndy Fiddaman 	if((flag&NV_DOUBLE) == NV_DOUBLE)
2163*b30d1939SAndy Fiddaman 	{
2164*b30d1939SAndy Fiddaman 		/* export doubles as integers for ksh88 compatibility */
2165*b30d1939SAndy Fiddaman 		stakputc(c+NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE)));
2166*b30d1939SAndy Fiddaman 	}
2167*b30d1939SAndy Fiddaman 	else
2168*b30d1939SAndy Fiddaman 	{
2169*b30d1939SAndy Fiddaman 		stakputc(c+flag);
2170*b30d1939SAndy Fiddaman 		if(flag&NV_INTEGER)
2171*b30d1939SAndy Fiddaman 			c +=  nv_size(np);
2172*b30d1939SAndy Fiddaman 	}
2173*b30d1939SAndy Fiddaman 	stakputc(c);
2174*b30d1939SAndy Fiddaman 	stakputs(nv_name(np));
2175*b30d1939SAndy Fiddaman }
2176*b30d1939SAndy Fiddaman #else
attstore(register Namval_t * np,void * data)2177*b30d1939SAndy Fiddaman static void attstore(register Namval_t *np, void *data)
2178*b30d1939SAndy Fiddaman {
2179*b30d1939SAndy Fiddaman 	register int flag = np->nvflag;
2180*b30d1939SAndy Fiddaman 	register struct adata *ap = (struct adata*)data;
2181*b30d1939SAndy Fiddaman 	ap->sh = sh_getinterp();
2182*b30d1939SAndy Fiddaman 	ap->tp = 0;
2183*b30d1939SAndy Fiddaman 	if(!(flag&NV_EXPORT) || (flag&NV_FUNCT))
2184*b30d1939SAndy Fiddaman 		return;
2185*b30d1939SAndy Fiddaman 	if((flag&(NV_UTOL|NV_LTOU|NV_INTEGER)) == (NV_UTOL|NV_LTOU))
2186*b30d1939SAndy Fiddaman 	{
2187*b30d1939SAndy Fiddaman 		data = (void*)nv_mapchar(np,0);
2188*b30d1939SAndy Fiddaman 		if(strcmp(data,e_tolower) && strcmp(data,e_toupper))
2189*b30d1939SAndy Fiddaman 			return;
2190*b30d1939SAndy Fiddaman 	}
2191*b30d1939SAndy Fiddaman 	flag &= (NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER);
2192*b30d1939SAndy Fiddaman 	*ap->attval++ = '=';
2193*b30d1939SAndy Fiddaman 	if((flag&NV_DOUBLE) == NV_DOUBLE)
2194*b30d1939SAndy Fiddaman 	{
2195*b30d1939SAndy Fiddaman 		/* export doubles as integers for ksh88 compatibility */
2196*b30d1939SAndy Fiddaman 		*ap->attval++ = ' '+ NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE));
2197*b30d1939SAndy Fiddaman 		*ap->attval = ' ';
2198*b30d1939SAndy Fiddaman 	}
2199*b30d1939SAndy Fiddaman 	else
2200*b30d1939SAndy Fiddaman 	{
2201*b30d1939SAndy Fiddaman 		*ap->attval++ = ' '+flag;
2202*b30d1939SAndy Fiddaman 		if(flag&NV_INTEGER)
2203*b30d1939SAndy Fiddaman 			*ap->attval = ' ' + nv_size(np);
2204*b30d1939SAndy Fiddaman 		else
2205*b30d1939SAndy Fiddaman 			*ap->attval = ' ';
2206*b30d1939SAndy Fiddaman 	}
2207*b30d1939SAndy Fiddaman 	ap->attval = strcopy(++ap->attval,nv_name(np));
2208*b30d1939SAndy Fiddaman }
2209*b30d1939SAndy Fiddaman #endif
2210*b30d1939SAndy Fiddaman 
2211*b30d1939SAndy Fiddaman #ifndef _ENV_H
pushnam(Namval_t * np,void * data)2212*b30d1939SAndy Fiddaman static void pushnam(Namval_t *np, void *data)
2213*b30d1939SAndy Fiddaman {
2214*b30d1939SAndy Fiddaman 	register char *value;
2215*b30d1939SAndy Fiddaman 	register struct adata *ap = (struct adata*)data;
2216*b30d1939SAndy Fiddaman 	ap->sh = sh_getinterp();
2217*b30d1939SAndy Fiddaman 	ap->tp = 0;
2218*b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_IMPORT) && np->nvenv)
2219*b30d1939SAndy Fiddaman 		*ap->argnam++ = np->nvenv;
2220*b30d1939SAndy Fiddaman 	else if(value=nv_getval(np))
2221*b30d1939SAndy Fiddaman 		*ap->argnam++ = staknam(np,value);
2222*b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER))
2223*b30d1939SAndy Fiddaman 		ap->attsize += (strlen(nv_name(np))+4);
2224*b30d1939SAndy Fiddaman }
2225*b30d1939SAndy Fiddaman #endif
2226*b30d1939SAndy Fiddaman 
2227*b30d1939SAndy Fiddaman /*
2228*b30d1939SAndy Fiddaman  * Generate the environment list for the child.
2229*b30d1939SAndy Fiddaman  */
2230*b30d1939SAndy Fiddaman 
2231*b30d1939SAndy Fiddaman #ifdef _ENV_H
sh_envgen(void)2232*b30d1939SAndy Fiddaman char **sh_envgen(void)
2233*b30d1939SAndy Fiddaman {
2234*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2235*b30d1939SAndy Fiddaman 	int offset,tell;
2236*b30d1939SAndy Fiddaman 	register char **er;
2237*b30d1939SAndy Fiddaman 	env_delete(shp->env,"_");
2238*b30d1939SAndy Fiddaman 	er = env_get(shp->env);
2239*b30d1939SAndy Fiddaman 	offset = staktell();
2240*b30d1939SAndy Fiddaman 	stakputs(e_envmarker);
2241*b30d1939SAndy Fiddaman 	tell = staktell();
2242*b30d1939SAndy Fiddaman 	nv_scan(shp->var_tree, attstore,(void*)0,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER));
2243*b30d1939SAndy Fiddaman 	if(tell ==staktell())
2244*b30d1939SAndy Fiddaman 		stakseek(offset);
2245*b30d1939SAndy Fiddaman 	else
2246*b30d1939SAndy Fiddaman 		*--er = stakfreeze(1)+offset;
2247*b30d1939SAndy Fiddaman 	return(er);
2248*b30d1939SAndy Fiddaman }
2249*b30d1939SAndy Fiddaman #else
sh_envgen(void)2250*b30d1939SAndy Fiddaman char **sh_envgen(void)
2251*b30d1939SAndy Fiddaman {
2252*b30d1939SAndy Fiddaman 	register char **er;
2253*b30d1939SAndy Fiddaman 	register int namec;
2254*b30d1939SAndy Fiddaman 	register char *cp;
2255*b30d1939SAndy Fiddaman 	struct adata data;
2256*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
2257*b30d1939SAndy Fiddaman 	data.sh = shp;
2258*b30d1939SAndy Fiddaman 	data.tp = 0;
2259*b30d1939SAndy Fiddaman 	data.mapname = 0;
2260*b30d1939SAndy Fiddaman 	/* L_ARGNOD gets generated automatically as full path name of command */
2261*b30d1939SAndy Fiddaman 	nv_offattr(L_ARGNOD,NV_EXPORT);
2262*b30d1939SAndy Fiddaman 	data.attsize = 6;
2263*b30d1939SAndy Fiddaman 	namec = nv_scan(shp->var_tree,nullscan,(void*)0,NV_EXPORT,NV_EXPORT);
2264*b30d1939SAndy Fiddaman 	namec += shp->nenv;
2265*b30d1939SAndy Fiddaman 	er = (char**)stakalloc((namec+4)*sizeof(char*));
2266*b30d1939SAndy Fiddaman 	data.argnam = (er+=2) + shp->nenv;
2267*b30d1939SAndy Fiddaman 	if(shp->nenv)
2268*b30d1939SAndy Fiddaman 		memcpy((void*)er,environ,shp->nenv*sizeof(char*));
2269*b30d1939SAndy Fiddaman 	nv_scan(shp->var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT);
2270*b30d1939SAndy Fiddaman 	*data.argnam = (char*)stakalloc(data.attsize);
2271*b30d1939SAndy Fiddaman 	cp = data.attval = strcopy(*data.argnam,e_envmarker);
2272*b30d1939SAndy Fiddaman 	nv_scan(shp->var_tree, attstore,&data,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER));
2273*b30d1939SAndy Fiddaman 	*data.attval = 0;
2274*b30d1939SAndy Fiddaman 	if(cp!=data.attval)
2275*b30d1939SAndy Fiddaman 		data.argnam++;
2276*b30d1939SAndy Fiddaman 	*data.argnam = 0;
2277*b30d1939SAndy Fiddaman 	return(er);
2278*b30d1939SAndy Fiddaman }
2279*b30d1939SAndy Fiddaman #endif
2280*b30d1939SAndy Fiddaman 
2281*b30d1939SAndy Fiddaman struct scan
2282*b30d1939SAndy Fiddaman {
2283*b30d1939SAndy Fiddaman 	void    (*scanfn)(Namval_t*, void*);
2284*b30d1939SAndy Fiddaman 	int     scanmask;
2285*b30d1939SAndy Fiddaman 	int     scanflags;
2286*b30d1939SAndy Fiddaman 	int     scancount;
2287*b30d1939SAndy Fiddaman 	void    *scandata;
2288*b30d1939SAndy Fiddaman };
2289*b30d1939SAndy Fiddaman 
scanfilter(Dt_t * dict,void * arg,void * data)2290*b30d1939SAndy Fiddaman static int scanfilter(Dt_t *dict, void *arg, void *data)
2291*b30d1939SAndy Fiddaman {
2292*b30d1939SAndy Fiddaman 	register Namval_t *np = (Namval_t*)arg;
2293*b30d1939SAndy Fiddaman 	register int k=np->nvflag;
2294*b30d1939SAndy Fiddaman 	register struct scan *sp = (struct scan*)data;
2295*b30d1939SAndy Fiddaman 	register struct adata *tp = (struct adata*)sp->scandata;
2296*b30d1939SAndy Fiddaman 	char	*cp;
2297*b30d1939SAndy Fiddaman 	NOT_USED(dict);
2298*b30d1939SAndy Fiddaman #if SHOPT_TYPEDEF
2299*b30d1939SAndy Fiddaman 	if(!is_abuiltin(np) && tp && tp->tp && nv_type(np)!=tp->tp)
2300*b30d1939SAndy Fiddaman 		return(0);
2301*b30d1939SAndy Fiddaman #endif /*SHOPT_TYPEDEF */
2302*b30d1939SAndy Fiddaman 	if(sp->scanmask==NV_TABLE && nv_isvtree(np))
2303*b30d1939SAndy Fiddaman 		k = NV_TABLE;
2304*b30d1939SAndy Fiddaman 	if(sp->scanmask?(k&sp->scanmask)==sp->scanflags:(!sp->scanflags || (k&sp->scanflags)))
2305*b30d1939SAndy Fiddaman 	{
2306*b30d1939SAndy Fiddaman 		if(tp && tp->mapname)
2307*b30d1939SAndy Fiddaman 		{
2308*b30d1939SAndy Fiddaman 			if(sp->scanflags==NV_FUNCTION || sp->scanflags==(NV_NOFREE|NV_BINARY|NV_RAW))
2309*b30d1939SAndy Fiddaman 			{
2310*b30d1939SAndy Fiddaman 				int n = strlen(tp->mapname);
2311*b30d1939SAndy Fiddaman 				if(memcmp(np->nvname,tp->mapname,n) || np->nvname[n]!='.' || strchr(&np->nvname[n+1],'.'))
2312*b30d1939SAndy Fiddaman 					return(0);
2313*b30d1939SAndy Fiddaman 			}
2314*b30d1939SAndy Fiddaman 			else if((sp->scanflags==NV_UTOL||sp->scanflags==NV_LTOU) && (cp=(char*)nv_mapchar(np,0)) && strcmp(cp,tp->mapname))
2315*b30d1939SAndy Fiddaman 				return(0);
2316*b30d1939SAndy Fiddaman 		}
2317*b30d1939SAndy Fiddaman 		if(!np->nvalue.cp && !np->nvfun && !nv_isattr(np,~NV_DEFAULT))
2318*b30d1939SAndy Fiddaman 			return(0);
2319*b30d1939SAndy Fiddaman 		if(sp->scanfn)
2320*b30d1939SAndy Fiddaman 		{
2321*b30d1939SAndy Fiddaman 			if(nv_isarray(np))
2322*b30d1939SAndy Fiddaman 				nv_putsub(np,NIL(char*),0L);
2323*b30d1939SAndy Fiddaman 			(*sp->scanfn)(np,sp->scandata);
2324*b30d1939SAndy Fiddaman 		}
2325*b30d1939SAndy Fiddaman 		sp->scancount++;
2326*b30d1939SAndy Fiddaman 	}
2327*b30d1939SAndy Fiddaman 	return(0);
2328*b30d1939SAndy Fiddaman }
2329*b30d1939SAndy Fiddaman 
2330*b30d1939SAndy Fiddaman /*
2331*b30d1939SAndy Fiddaman  * Walk through the name-value pairs
2332*b30d1939SAndy Fiddaman  * if <mask> is non-zero, then only nodes with (nvflags&mask)==flags
2333*b30d1939SAndy Fiddaman  *	are visited
2334*b30d1939SAndy Fiddaman  * If <mask> is zero, and <flags> non-zero, then nodes with one or
2335*b30d1939SAndy Fiddaman  *	more of <flags> is visited
2336*b30d1939SAndy Fiddaman  * If <mask> and <flags> are zero, then all nodes are visted
2337*b30d1939SAndy Fiddaman  */
nv_scan(Dt_t * root,void (* fn)(Namval_t *,void *),void * data,int mask,int flags)2338*b30d1939SAndy Fiddaman int nv_scan(Dt_t *root, void (*fn)(Namval_t*,void*), void *data,int mask, int flags)
2339*b30d1939SAndy Fiddaman {
2340*b30d1939SAndy Fiddaman 	Namval_t *np;
2341*b30d1939SAndy Fiddaman 	Dt_t *base=0;
2342*b30d1939SAndy Fiddaman 	struct scan sdata;
2343*b30d1939SAndy Fiddaman 	int (*hashfn)(Dt_t*, void*, void*);
2344*b30d1939SAndy Fiddaman 	sdata.scanmask = mask;
2345*b30d1939SAndy Fiddaman 	sdata.scanflags = flags&~NV_NOSCOPE;
2346*b30d1939SAndy Fiddaman 	sdata.scanfn = fn;
2347*b30d1939SAndy Fiddaman 	sdata.scancount = 0;
2348*b30d1939SAndy Fiddaman 	sdata.scandata = data;
2349*b30d1939SAndy Fiddaman 	hashfn = scanfilter;
2350*b30d1939SAndy Fiddaman 	if(flags&NV_NOSCOPE)
2351*b30d1939SAndy Fiddaman 		base = dtview((Dt_t*)root,0);
2352*b30d1939SAndy Fiddaman 	for(np=(Namval_t*)dtfirst(root);np; np=(Namval_t*)dtnext(root,np))
2353*b30d1939SAndy Fiddaman 		hashfn(root, np, &sdata);
2354*b30d1939SAndy Fiddaman 	if(base)
2355*b30d1939SAndy Fiddaman 		 dtview((Dt_t*)root,base);
2356*b30d1939SAndy Fiddaman 	return(sdata.scancount);
2357*b30d1939SAndy Fiddaman }
2358*b30d1939SAndy Fiddaman 
2359*b30d1939SAndy Fiddaman /*
2360*b30d1939SAndy Fiddaman  * create a new environment scope
2361*b30d1939SAndy Fiddaman  */
sh_scope(Shell_t * shp,struct argnod * envlist,int fun)2362*b30d1939SAndy Fiddaman void sh_scope(Shell_t *shp, struct argnod *envlist, int fun)
2363*b30d1939SAndy Fiddaman {
2364*b30d1939SAndy Fiddaman 	register Dt_t		*newscope, *newroot=shp->var_base;
2365*b30d1939SAndy Fiddaman 	struct Ufunction	*rp;
2366*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
2367*b30d1939SAndy Fiddaman 	if(shp->namespace)
2368*b30d1939SAndy Fiddaman 		newroot = nv_dict(shp->namespace);
2369*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
2370*b30d1939SAndy Fiddaman 	newscope = dtopen(&_Nvdisc,Dtoset);
2371*b30d1939SAndy Fiddaman 	if(envlist)
2372*b30d1939SAndy Fiddaman 	{
2373*b30d1939SAndy Fiddaman 		dtview(newscope,(Dt_t*)shp->var_tree);
2374*b30d1939SAndy Fiddaman 		shp->var_tree = newscope;
2375*b30d1939SAndy Fiddaman 		nv_setlist(envlist,NV_EXPORT|NV_NOSCOPE|NV_IDENT|NV_ASSIGN,0);
2376*b30d1939SAndy Fiddaman 		if(!fun)
2377*b30d1939SAndy Fiddaman 			return;
2378*b30d1939SAndy Fiddaman 		shp->var_tree = dtview(newscope,0);
2379*b30d1939SAndy Fiddaman 	}
2380*b30d1939SAndy Fiddaman 	if((rp=shp->st.real_fun)  && rp->sdict)
2381*b30d1939SAndy Fiddaman 	{
2382*b30d1939SAndy Fiddaman 		dtview(rp->sdict,newroot);
2383*b30d1939SAndy Fiddaman 		newroot = rp->sdict;
2384*b30d1939SAndy Fiddaman 
2385*b30d1939SAndy Fiddaman 	}
2386*b30d1939SAndy Fiddaman 	dtview(newscope,(Dt_t*)newroot);
2387*b30d1939SAndy Fiddaman 	shp->var_tree = newscope;
2388*b30d1939SAndy Fiddaman }
2389*b30d1939SAndy Fiddaman 
2390*b30d1939SAndy Fiddaman /*
2391*b30d1939SAndy Fiddaman  * Remove freeable local space associated with the nvalue field
2392*b30d1939SAndy Fiddaman  * of nnod. This includes any strings representing the value(s) of the
2393*b30d1939SAndy Fiddaman  * node, as well as its dope vector, if it is an array.
2394*b30d1939SAndy Fiddaman  */
2395*b30d1939SAndy Fiddaman 
sh_envnolocal(register Namval_t * np,void * data)2396*b30d1939SAndy Fiddaman void	sh_envnolocal (register Namval_t *np, void *data)
2397*b30d1939SAndy Fiddaman {
2398*b30d1939SAndy Fiddaman 	struct adata *tp = (struct adata*)data;
2399*b30d1939SAndy Fiddaman 	char *cp=0;
2400*b30d1939SAndy Fiddaman 	if(np==VERSIONNOD && nv_isref(np))
2401*b30d1939SAndy Fiddaman 		return;
2402*b30d1939SAndy Fiddaman 	if(np==L_ARGNOD)
2403*b30d1939SAndy Fiddaman 		return;
2404*b30d1939SAndy Fiddaman 	if(np == tp->sh->namespace)
2405*b30d1939SAndy Fiddaman 		return;
2406*b30d1939SAndy Fiddaman 	if(nv_isref(np))
2407*b30d1939SAndy Fiddaman 		nv_unref(np);
2408*b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_EXPORT) && nv_isarray(np))
2409*b30d1939SAndy Fiddaman 	{
2410*b30d1939SAndy Fiddaman 		nv_putsub(np,NIL(char*),0);
2411*b30d1939SAndy Fiddaman 		if(cp = nv_getval(np))
2412*b30d1939SAndy Fiddaman 			cp = strdup(cp);
2413*b30d1939SAndy Fiddaman 	}
2414*b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_EXPORT|NV_NOFREE))
2415*b30d1939SAndy Fiddaman 	{
2416*b30d1939SAndy Fiddaman 		if(nv_isref(np) && np!=VERSIONNOD)
2417*b30d1939SAndy Fiddaman 		{
2418*b30d1939SAndy Fiddaman 			nv_offattr(np,NV_NOFREE|NV_REF);
2419*b30d1939SAndy Fiddaman 			free((void*)np->nvalue.nrp);
2420*b30d1939SAndy Fiddaman 			np->nvalue.cp = 0;
2421*b30d1939SAndy Fiddaman 		}
2422*b30d1939SAndy Fiddaman 		if(!cp)
2423*b30d1939SAndy Fiddaman 			return;
2424*b30d1939SAndy Fiddaman 	}
2425*b30d1939SAndy Fiddaman 	if(nv_isarray(np))
2426*b30d1939SAndy Fiddaman 		nv_putsub(np,NIL(char*),ARRAY_UNDEF);
2427*b30d1939SAndy Fiddaman 	_nv_unset(np,NV_RDONLY);
2428*b30d1939SAndy Fiddaman 	nv_setattr(np,0);
2429*b30d1939SAndy Fiddaman 	if(cp)
2430*b30d1939SAndy Fiddaman 	{
2431*b30d1939SAndy Fiddaman 		nv_putval(np,cp,0);
2432*b30d1939SAndy Fiddaman 		free((void*)cp);
2433*b30d1939SAndy Fiddaman 	}
2434*b30d1939SAndy Fiddaman }
2435*b30d1939SAndy Fiddaman 
2436*b30d1939SAndy Fiddaman /*
2437*b30d1939SAndy Fiddaman  * Currently this is a dummy, but someday will be needed
2438*b30d1939SAndy Fiddaman  * for reference counting
2439*b30d1939SAndy Fiddaman  */
nv_close(Namval_t * np)2440*b30d1939SAndy Fiddaman void	nv_close(Namval_t *np)
2441*b30d1939SAndy Fiddaman {
2442*b30d1939SAndy Fiddaman 	NOT_USED(np);
2443*b30d1939SAndy Fiddaman }
2444*b30d1939SAndy Fiddaman 
table_unset(Shell_t * shp,register Dt_t * root,int flags,Dt_t * oroot)2445*b30d1939SAndy Fiddaman static void table_unset(Shell_t *shp, register Dt_t *root, int flags, Dt_t *oroot)
2446*b30d1939SAndy Fiddaman {
2447*b30d1939SAndy Fiddaman 	register Namval_t *np,*nq, *npnext;
2448*b30d1939SAndy Fiddaman 	for(np=(Namval_t*)dtfirst(root);np;np=npnext)
2449*b30d1939SAndy Fiddaman 	{
2450*b30d1939SAndy Fiddaman 		if(nq=dtsearch(oroot,np))
2451*b30d1939SAndy Fiddaman 		{
2452*b30d1939SAndy Fiddaman 			if(nv_cover(nq))
2453*b30d1939SAndy Fiddaman 			{
2454*b30d1939SAndy Fiddaman 				int subshell = shp->subshell;
2455*b30d1939SAndy Fiddaman 				shp->subshell = 0;
2456*b30d1939SAndy Fiddaman 				if(nv_isattr(nq, NV_INTEGER))
2457*b30d1939SAndy Fiddaman 				{
2458*b30d1939SAndy Fiddaman 					Sfdouble_t d = nv_getnum(nq);
2459*b30d1939SAndy Fiddaman 					nv_putval(nq,(char*)&d,NV_LDOUBLE);
2460*b30d1939SAndy Fiddaman 				}
2461*b30d1939SAndy Fiddaman 				else if(shp->test&4)
2462*b30d1939SAndy Fiddaman 					nv_putval(nq, strdup(nv_getval(nq)), NV_RDONLY);
2463*b30d1939SAndy Fiddaman 				else
2464*b30d1939SAndy Fiddaman 					nv_putval(nq, nv_getval(nq), NV_RDONLY);
2465*b30d1939SAndy Fiddaman 				shp->subshell = subshell;
2466*b30d1939SAndy Fiddaman 				np->nvfun = 0;
2467*b30d1939SAndy Fiddaman 			}
2468*b30d1939SAndy Fiddaman 			if(nv_isattr(nq,NV_EXPORT))
2469*b30d1939SAndy Fiddaman 				sh_envput(shp->env,nq);
2470*b30d1939SAndy Fiddaman 		}
2471*b30d1939SAndy Fiddaman 		shp->last_root = root;
2472*b30d1939SAndy Fiddaman 		shp->last_table = 0;
2473*b30d1939SAndy Fiddaman 		if(nv_isvtree(np))
2474*b30d1939SAndy Fiddaman 		{
2475*b30d1939SAndy Fiddaman 			int len = strlen(np->nvname);
2476*b30d1939SAndy Fiddaman 			npnext = (Namval_t*)dtnext(root,np);
2477*b30d1939SAndy Fiddaman 			while((nq=npnext) && memcmp(np->nvname,nq->nvname,len)==0 && nq->nvname[len]=='.')
2478*b30d1939SAndy Fiddaman 
2479*b30d1939SAndy Fiddaman 			{
2480*b30d1939SAndy Fiddaman 				_nv_unset(nq,flags);
2481*b30d1939SAndy Fiddaman 				npnext = (Namval_t*)dtnext(root,nq);
2482*b30d1939SAndy Fiddaman 				nv_delete(nq,root,0);
2483*b30d1939SAndy Fiddaman 			}
2484*b30d1939SAndy Fiddaman 		}
2485*b30d1939SAndy Fiddaman 		npnext = (Namval_t*)dtnext(root,np);
2486*b30d1939SAndy Fiddaman 		_nv_unset(np,flags);
2487*b30d1939SAndy Fiddaman 		nv_delete(np,root,0);
2488*b30d1939SAndy Fiddaman 	}
2489*b30d1939SAndy Fiddaman }
2490*b30d1939SAndy Fiddaman 
2491*b30d1939SAndy Fiddaman /*
2492*b30d1939SAndy Fiddaman  *
2493*b30d1939SAndy Fiddaman  *   Set the value of <np> to 0, and nullify any attributes
2494*b30d1939SAndy Fiddaman  *   that <np> may have had.  Free any freeable space occupied
2495*b30d1939SAndy Fiddaman  *   by the value of <np>.  If <np> denotes an array member, it
2496*b30d1939SAndy Fiddaman  *   will retain its attributes.
2497*b30d1939SAndy Fiddaman  *   <flags> can contain NV_RDONLY to override the readonly attribute
2498*b30d1939SAndy Fiddaman  *	being cleared.
2499*b30d1939SAndy Fiddaman  *   <flags> can contain NV_EXPORT to override preserve nvenv
2500*b30d1939SAndy Fiddaman  */
_nv_unset(register Namval_t * np,int flags)2501*b30d1939SAndy Fiddaman void	_nv_unset(register Namval_t *np,int flags)
2502*b30d1939SAndy Fiddaman {
2503*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
2504*b30d1939SAndy Fiddaman 	register union Value *up;
2505*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
2506*b30d1939SAndy Fiddaman 	Namarr_t	*ap;
2507*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
2508*b30d1939SAndy Fiddaman 	if(!(flags&NV_RDONLY) && nv_isattr (np,NV_RDONLY))
2509*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
2510*b30d1939SAndy Fiddaman 	if(is_afunction(np) && np->nvalue.ip)
2511*b30d1939SAndy Fiddaman 	{
2512*b30d1939SAndy Fiddaman 		register struct slnod *slp = (struct slnod*)(np->nvenv);
2513*b30d1939SAndy Fiddaman 		if(shp->st.real_fun == np->nvalue.rp)
2514*b30d1939SAndy Fiddaman 		{
2515*b30d1939SAndy Fiddaman 			np->nvalue.rp->running |= 1;
2516*b30d1939SAndy Fiddaman 			return;
2517*b30d1939SAndy Fiddaman 		}
2518*b30d1939SAndy Fiddaman 		if(slp && !nv_isattr(np,NV_NOFREE))
2519*b30d1939SAndy Fiddaman 		{
2520*b30d1939SAndy Fiddaman 			struct Ufunction *rq,*rp = np->nvalue.rp;
2521*b30d1939SAndy Fiddaman 			/* free function definition */
2522*b30d1939SAndy Fiddaman 			register char *name=nv_name(np),*cp= strrchr(name,'.');
2523*b30d1939SAndy Fiddaman 			if(cp)
2524*b30d1939SAndy Fiddaman 			{
2525*b30d1939SAndy Fiddaman 				Namval_t *npv;
2526*b30d1939SAndy Fiddaman 				*cp = 0;
2527*b30d1939SAndy Fiddaman 				 npv = nv_open(name,shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOADD);
2528*b30d1939SAndy Fiddaman 				*cp++ = '.';
2529*b30d1939SAndy Fiddaman 				if(npv && npv!=shp->namespace)
2530*b30d1939SAndy Fiddaman 					nv_setdisc(npv,cp,NIL(Namval_t*),(Namfun_t*)npv);
2531*b30d1939SAndy Fiddaman 			}
2532*b30d1939SAndy Fiddaman 			if(rp->fname && shp->fpathdict && (rq = (struct Ufunction*)nv_search(rp->fname,shp->fpathdict,0)))
2533*b30d1939SAndy Fiddaman 			{
2534*b30d1939SAndy Fiddaman 				do
2535*b30d1939SAndy Fiddaman 				{
2536*b30d1939SAndy Fiddaman 					if(rq->np != np)
2537*b30d1939SAndy Fiddaman 						continue;
2538*b30d1939SAndy Fiddaman 					dtdelete(shp->fpathdict,rq);
2539*b30d1939SAndy Fiddaman 					break;
2540*b30d1939SAndy Fiddaman 				}
2541*b30d1939SAndy Fiddaman 				while(rq = (struct Ufunction*)dtnext(shp->fpathdict,rq));
2542*b30d1939SAndy Fiddaman 			}
2543*b30d1939SAndy Fiddaman 			if(rp->sdict)
2544*b30d1939SAndy Fiddaman 			{
2545*b30d1939SAndy Fiddaman 				Namval_t *mp, *nq;
2546*b30d1939SAndy Fiddaman 				for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
2547*b30d1939SAndy Fiddaman 				{
2548*b30d1939SAndy Fiddaman 					nq = dtnext(rp->sdict,mp);
2549*b30d1939SAndy Fiddaman 					_nv_unset(mp,NV_RDONLY);
2550*b30d1939SAndy Fiddaman 					nv_delete(mp,rp->sdict,0);
2551*b30d1939SAndy Fiddaman 				}
2552*b30d1939SAndy Fiddaman 				dtclose(rp->sdict);
2553*b30d1939SAndy Fiddaman 			}
2554*b30d1939SAndy Fiddaman 			stakdelete(slp->slptr);
2555*b30d1939SAndy Fiddaman 			free((void*)np->nvalue.ip);
2556*b30d1939SAndy Fiddaman 			np->nvalue.ip = 0;
2557*b30d1939SAndy Fiddaman 		}
2558*b30d1939SAndy Fiddaman 		goto done;
2559*b30d1939SAndy Fiddaman 	}
2560*b30d1939SAndy Fiddaman 	if(shp->subshell)
2561*b30d1939SAndy Fiddaman 		np = sh_assignok(np,0);
2562*b30d1939SAndy Fiddaman 	nv_offattr(np,NV_NODISC);
2563*b30d1939SAndy Fiddaman 	if(np->nvfun && !nv_isref(np))
2564*b30d1939SAndy Fiddaman 	{
2565*b30d1939SAndy Fiddaman 		/* This function contains disc */
2566*b30d1939SAndy Fiddaman 		if(!nv_local)
2567*b30d1939SAndy Fiddaman 		{
2568*b30d1939SAndy Fiddaman 			nv_local=1;
2569*b30d1939SAndy Fiddaman 			nv_putv(np,NIL(char*),flags,np->nvfun);
2570*b30d1939SAndy Fiddaman 			nv_local=0;
2571*b30d1939SAndy Fiddaman 			return;
2572*b30d1939SAndy Fiddaman 		}
2573*b30d1939SAndy Fiddaman 		/* called from disc, assign the actual value */
2574*b30d1939SAndy Fiddaman 		nv_local=0;
2575*b30d1939SAndy Fiddaman 	}
2576*b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_INT16P) == NV_INT16)
2577*b30d1939SAndy Fiddaman 	{
2578*b30d1939SAndy Fiddaman 		np->nvalue.cp = nv_isarray(np)?Empty:0;
2579*b30d1939SAndy Fiddaman 		goto done;
2580*b30d1939SAndy Fiddaman 	}
2581*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
2582*b30d1939SAndy Fiddaman 	else if(np->nvalue.up && nv_isarray(np) && (ap=nv_arrayptr(np)) && !ap->fixed)
2583*b30d1939SAndy Fiddaman #else
2584*b30d1939SAndy Fiddaman 	else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np))
2585*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
2586*b30d1939SAndy Fiddaman 		up = np->nvalue.up;
2587*b30d1939SAndy Fiddaman 	else if(nv_isref(np) && !nv_isattr(np,NV_EXPORT|NV_MINIMAL) && np->nvalue.nrp)
2588*b30d1939SAndy Fiddaman 	{
2589*b30d1939SAndy Fiddaman 
2590*b30d1939SAndy Fiddaman 		if(np->nvalue.nrp->root)
2591*b30d1939SAndy Fiddaman 			dtdelete(Refdict,(void*)np->nvalue.nrp);
2592*b30d1939SAndy Fiddaman 		if(np->nvalue.nrp->sub)
2593*b30d1939SAndy Fiddaman 			free(np->nvalue.nrp->sub);
2594*b30d1939SAndy Fiddaman 		free((void*)np->nvalue.nrp);
2595*b30d1939SAndy Fiddaman 		np->nvalue.cp = 0;
2596*b30d1939SAndy Fiddaman 		up = 0;
2597*b30d1939SAndy Fiddaman 	}
2598*b30d1939SAndy Fiddaman 	else
2599*b30d1939SAndy Fiddaman 		up = &np->nvalue;
2600*b30d1939SAndy Fiddaman 	if(up && up->cp)
2601*b30d1939SAndy Fiddaman 	{
2602*b30d1939SAndy Fiddaman 		if(up->cp!=Empty && up->cp!=Null && !nv_isattr(np, NV_NOFREE))
2603*b30d1939SAndy Fiddaman 			free((void*)up->cp);
2604*b30d1939SAndy Fiddaman 		up->cp = 0;
2605*b30d1939SAndy Fiddaman 	}
2606*b30d1939SAndy Fiddaman done:
2607*b30d1939SAndy Fiddaman 	if(!nv_isarray(np) || !nv_arrayptr(np))
2608*b30d1939SAndy Fiddaman 	{
2609*b30d1939SAndy Fiddaman 		nv_setsize(np,0);
2610*b30d1939SAndy Fiddaman 		if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT))
2611*b30d1939SAndy Fiddaman 		{
2612*b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_EXPORT) && !strchr(np->nvname,'['))
2613*b30d1939SAndy Fiddaman 				env_delete(shp->env,nv_name(np));
2614*b30d1939SAndy Fiddaman 			if(!(flags&NV_EXPORT) ||  nv_isattr(np,NV_EXPORT))
2615*b30d1939SAndy Fiddaman 				np->nvenv = 0;
2616*b30d1939SAndy Fiddaman 			nv_setattr(np,0);
2617*b30d1939SAndy Fiddaman 		}
2618*b30d1939SAndy Fiddaman 		else
2619*b30d1939SAndy Fiddaman 		{
2620*b30d1939SAndy Fiddaman 			nv_setattr(np,NV_MINIMAL);
2621*b30d1939SAndy Fiddaman 			nv_delete(np,(Dt_t*)0,0);
2622*b30d1939SAndy Fiddaman 		}
2623*b30d1939SAndy Fiddaman 	}
2624*b30d1939SAndy Fiddaman }
2625*b30d1939SAndy Fiddaman 
2626*b30d1939SAndy Fiddaman /*
2627*b30d1939SAndy Fiddaman  * return the node pointer in the highest level scope
2628*b30d1939SAndy Fiddaman  */
sh_scoped(Shell_t * shp,register Namval_t * np)2629*b30d1939SAndy Fiddaman Namval_t *sh_scoped(Shell_t *shp, register Namval_t *np)
2630*b30d1939SAndy Fiddaman {
2631*b30d1939SAndy Fiddaman 	if(!dtvnext(shp->var_tree))
2632*b30d1939SAndy Fiddaman 		return(np);
2633*b30d1939SAndy Fiddaman 	return(dtsearch(shp->var_tree,np));
2634*b30d1939SAndy Fiddaman }
2635*b30d1939SAndy Fiddaman 
2636*b30d1939SAndy Fiddaman #if 1
2637*b30d1939SAndy Fiddaman /*
2638*b30d1939SAndy Fiddaman  * return space separated list of names of variables in given tree
2639*b30d1939SAndy Fiddaman  */
tableval(Dt_t * root)2640*b30d1939SAndy Fiddaman static char *tableval(Dt_t *root)
2641*b30d1939SAndy Fiddaman {
2642*b30d1939SAndy Fiddaman 	static Sfio_t *out;
2643*b30d1939SAndy Fiddaman 	register Namval_t *np;
2644*b30d1939SAndy Fiddaman 	register int first=1;
2645*b30d1939SAndy Fiddaman 	register Dt_t *base = dtview(root,0);
2646*b30d1939SAndy Fiddaman         if(out)
2647*b30d1939SAndy Fiddaman                 sfseek(out,(Sfoff_t)0,SEEK_SET);
2648*b30d1939SAndy Fiddaman         else
2649*b30d1939SAndy Fiddaman                 out =  sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
2650*b30d1939SAndy Fiddaman 	for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np))
2651*b30d1939SAndy Fiddaman 	{
2652*b30d1939SAndy Fiddaman                 if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE))
2653*b30d1939SAndy Fiddaman 		{
2654*b30d1939SAndy Fiddaman 			if(!first)
2655*b30d1939SAndy Fiddaman 				sfputc(out,' ');
2656*b30d1939SAndy Fiddaman 			else
2657*b30d1939SAndy Fiddaman 				first = 0;
2658*b30d1939SAndy Fiddaman 			sfputr(out,np->nvname,-1);
2659*b30d1939SAndy Fiddaman 		}
2660*b30d1939SAndy Fiddaman 	}
2661*b30d1939SAndy Fiddaman 	sfputc(out,0);
2662*b30d1939SAndy Fiddaman 	if(base)
2663*b30d1939SAndy Fiddaman 		dtview(root,base);
2664*b30d1939SAndy Fiddaman 	return((char*)out->_data);
2665*b30d1939SAndy Fiddaman }
2666*b30d1939SAndy Fiddaman #endif
2667*b30d1939SAndy Fiddaman 
2668*b30d1939SAndy Fiddaman #if SHOPT_OPTIMIZE
2669*b30d1939SAndy Fiddaman struct optimize
2670*b30d1939SAndy Fiddaman {
2671*b30d1939SAndy Fiddaman 	Namfun_t	hdr;
2672*b30d1939SAndy Fiddaman 	Shell_t		*sh;
2673*b30d1939SAndy Fiddaman 	char		**ptr;
2674*b30d1939SAndy Fiddaman 	struct optimize	*next;
2675*b30d1939SAndy Fiddaman 	Namval_t	*np;
2676*b30d1939SAndy Fiddaman };
2677*b30d1939SAndy Fiddaman 
2678*b30d1939SAndy Fiddaman static struct optimize *opt_free;
2679*b30d1939SAndy Fiddaman 
optimize_clear(Namval_t * np,Namfun_t * fp)2680*b30d1939SAndy Fiddaman static void optimize_clear(Namval_t* np, Namfun_t *fp)
2681*b30d1939SAndy Fiddaman {
2682*b30d1939SAndy Fiddaman 	struct optimize *op = (struct optimize*)fp;
2683*b30d1939SAndy Fiddaman 	nv_stack(np,fp);
2684*b30d1939SAndy Fiddaman 	nv_stack(np,(Namfun_t*)0);
2685*b30d1939SAndy Fiddaman 	for(;op && op->np==np; op=op->next)
2686*b30d1939SAndy Fiddaman 	{
2687*b30d1939SAndy Fiddaman 		if(op->ptr)
2688*b30d1939SAndy Fiddaman 		{
2689*b30d1939SAndy Fiddaman 			*op->ptr = 0;
2690*b30d1939SAndy Fiddaman 			op->ptr = 0;
2691*b30d1939SAndy Fiddaman 		}
2692*b30d1939SAndy Fiddaman 	}
2693*b30d1939SAndy Fiddaman }
2694*b30d1939SAndy Fiddaman 
put_optimize(Namval_t * np,const char * val,int flags,Namfun_t * fp)2695*b30d1939SAndy Fiddaman static void put_optimize(Namval_t* np,const char *val,int flags,Namfun_t *fp)
2696*b30d1939SAndy Fiddaman {
2697*b30d1939SAndy Fiddaman 	nv_putv(np,val,flags,fp);
2698*b30d1939SAndy Fiddaman 	optimize_clear(np,fp);
2699*b30d1939SAndy Fiddaman }
2700*b30d1939SAndy Fiddaman 
clone_optimize(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)2701*b30d1939SAndy Fiddaman static Namfun_t *clone_optimize(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
2702*b30d1939SAndy Fiddaman {
2703*b30d1939SAndy Fiddaman 	return((Namfun_t*)0);
2704*b30d1939SAndy Fiddaman }
2705*b30d1939SAndy Fiddaman 
2706*b30d1939SAndy Fiddaman static const Namdisc_t optimize_disc  = {sizeof(struct optimize),put_optimize,0,0,0,0,clone_optimize};
2707*b30d1939SAndy Fiddaman 
nv_optimize(Namval_t * np)2708*b30d1939SAndy Fiddaman void nv_optimize(Namval_t *np)
2709*b30d1939SAndy Fiddaman {
2710*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2711*b30d1939SAndy Fiddaman 	register Namfun_t *fp;
2712*b30d1939SAndy Fiddaman 	register struct optimize *op, *xp;
2713*b30d1939SAndy Fiddaman 	if(shp->argaddr)
2714*b30d1939SAndy Fiddaman 	{
2715*b30d1939SAndy Fiddaman 		if(np==SH_LINENO)
2716*b30d1939SAndy Fiddaman 		{
2717*b30d1939SAndy Fiddaman 			shp->argaddr = 0;
2718*b30d1939SAndy Fiddaman 			return;
2719*b30d1939SAndy Fiddaman 		}
2720*b30d1939SAndy Fiddaman 		for(fp=np->nvfun; fp; fp = fp->next)
2721*b30d1939SAndy Fiddaman 		{
2722*b30d1939SAndy Fiddaman 			if(fp->disc && (fp->disc->getnum || fp->disc->getval))
2723*b30d1939SAndy Fiddaman 			{
2724*b30d1939SAndy Fiddaman 				shp->argaddr = 0;
2725*b30d1939SAndy Fiddaman 				return;
2726*b30d1939SAndy Fiddaman 			}
2727*b30d1939SAndy Fiddaman 			if(fp->disc== &optimize_disc)
2728*b30d1939SAndy Fiddaman 				break;
2729*b30d1939SAndy Fiddaman 		}
2730*b30d1939SAndy Fiddaman 		if((xp= (struct optimize*)fp) && xp->ptr==shp->argaddr)
2731*b30d1939SAndy Fiddaman 			return;
2732*b30d1939SAndy Fiddaman 		if(op = opt_free)
2733*b30d1939SAndy Fiddaman 			opt_free = op->next;
2734*b30d1939SAndy Fiddaman 		else
2735*b30d1939SAndy Fiddaman 			op=(struct optimize*)calloc(1,sizeof(struct optimize));
2736*b30d1939SAndy Fiddaman 		op->ptr = shp->argaddr;
2737*b30d1939SAndy Fiddaman 		op->np = np;
2738*b30d1939SAndy Fiddaman 		if(xp)
2739*b30d1939SAndy Fiddaman 		{
2740*b30d1939SAndy Fiddaman 			op->hdr.disc = 0;
2741*b30d1939SAndy Fiddaman 			op->next = xp->next;
2742*b30d1939SAndy Fiddaman 			xp->next = op;
2743*b30d1939SAndy Fiddaman 		}
2744*b30d1939SAndy Fiddaman 		else
2745*b30d1939SAndy Fiddaman 		{
2746*b30d1939SAndy Fiddaman 			op->hdr.disc = &optimize_disc;
2747*b30d1939SAndy Fiddaman 			op->next = (struct optimize*)shp->optlist;
2748*b30d1939SAndy Fiddaman 			shp->optlist = (void*)op;
2749*b30d1939SAndy Fiddaman 			nv_stack(np,&op->hdr);
2750*b30d1939SAndy Fiddaman 		}
2751*b30d1939SAndy Fiddaman 	}
2752*b30d1939SAndy Fiddaman }
2753*b30d1939SAndy Fiddaman 
sh_optclear(Shell_t * shp,void * old)2754*b30d1939SAndy Fiddaman void sh_optclear(Shell_t *shp, void *old)
2755*b30d1939SAndy Fiddaman {
2756*b30d1939SAndy Fiddaman 	register struct optimize *op,*opnext;
2757*b30d1939SAndy Fiddaman 	for(op=(struct optimize*)shp->optlist; op; op = opnext)
2758*b30d1939SAndy Fiddaman 	{
2759*b30d1939SAndy Fiddaman 		opnext = op->next;
2760*b30d1939SAndy Fiddaman 		if(op->ptr && op->hdr.disc)
2761*b30d1939SAndy Fiddaman 		{
2762*b30d1939SAndy Fiddaman 			nv_stack(op->np,&op->hdr);
2763*b30d1939SAndy Fiddaman 			nv_stack(op->np,(Namfun_t*)0);
2764*b30d1939SAndy Fiddaman 		}
2765*b30d1939SAndy Fiddaman 		op->next = opt_free;
2766*b30d1939SAndy Fiddaman 		opt_free = op;
2767*b30d1939SAndy Fiddaman 	}
2768*b30d1939SAndy Fiddaman 	shp->optlist = old;
2769*b30d1939SAndy Fiddaman }
2770*b30d1939SAndy Fiddaman 
2771*b30d1939SAndy Fiddaman #else
2772*b30d1939SAndy Fiddaman #   define	optimize_clear(np,fp)
2773*b30d1939SAndy Fiddaman #endif /* SHOPT_OPTIMIZE */
2774*b30d1939SAndy Fiddaman 
2775*b30d1939SAndy Fiddaman /*
2776*b30d1939SAndy Fiddaman  *   Return a pointer to a character string that denotes the value
2777*b30d1939SAndy Fiddaman  *   of <np>.  If <np> refers to an array,  return a pointer to
2778*b30d1939SAndy Fiddaman  *   the value associated with the current index.
2779*b30d1939SAndy Fiddaman  *
2780*b30d1939SAndy Fiddaman  *   If the value of <np> is an integer, the string returned will
2781*b30d1939SAndy Fiddaman  *   be overwritten by the next call to nv_getval.
2782*b30d1939SAndy Fiddaman  *
2783*b30d1939SAndy Fiddaman  *   If <np> has no value, 0 is returned.
2784*b30d1939SAndy Fiddaman  */
2785*b30d1939SAndy Fiddaman 
nv_getval(register Namval_t * np)2786*b30d1939SAndy Fiddaman char *nv_getval(register Namval_t *np)
2787*b30d1939SAndy Fiddaman {
2788*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2789*b30d1939SAndy Fiddaman 	register union Value *up= &np->nvalue;
2790*b30d1939SAndy Fiddaman 	register int numeric;
2791*b30d1939SAndy Fiddaman #if SHOPT_OPTIMIZE
2792*b30d1939SAndy Fiddaman 	if(!nv_local && shp->argaddr)
2793*b30d1939SAndy Fiddaman 		nv_optimize(np);
2794*b30d1939SAndy Fiddaman #endif /* SHOPT_OPTIMIZE */
2795*b30d1939SAndy Fiddaman 	if((!np->nvfun || !np->nvfun->disc) && !nv_isattr(np,NV_ARRAY|NV_INTEGER|NV_FUNCT|NV_REF))
2796*b30d1939SAndy Fiddaman 		goto done;
2797*b30d1939SAndy Fiddaman 	if(nv_isref(np))
2798*b30d1939SAndy Fiddaman 	{
2799*b30d1939SAndy Fiddaman 		char *sub;
2800*b30d1939SAndy Fiddaman 		if(!np->nvalue.cp)
2801*b30d1939SAndy Fiddaman 			return(0);
2802*b30d1939SAndy Fiddaman 		shp->last_table = nv_reftable(np);
2803*b30d1939SAndy Fiddaman 		sub=nv_refsub(np);
2804*b30d1939SAndy Fiddaman 		np = nv_refnode(np);
2805*b30d1939SAndy Fiddaman 		if(sub)
2806*b30d1939SAndy Fiddaman 		{
2807*b30d1939SAndy Fiddaman 			sfprintf(shp->strbuf,"%s[%s]",nv_name(np),sub);
2808*b30d1939SAndy Fiddaman 			return(sfstruse(shp->strbuf));
2809*b30d1939SAndy Fiddaman 		}
2810*b30d1939SAndy Fiddaman 		return(nv_name(np));
2811*b30d1939SAndy Fiddaman 	}
2812*b30d1939SAndy Fiddaman 	if(np->nvfun && np->nvfun->disc)
2813*b30d1939SAndy Fiddaman 	{
2814*b30d1939SAndy Fiddaman 		if(!nv_local)
2815*b30d1939SAndy Fiddaman 		{
2816*b30d1939SAndy Fiddaman 			nv_local=1;
2817*b30d1939SAndy Fiddaman 			return(nv_getv(np, np->nvfun));
2818*b30d1939SAndy Fiddaman 		}
2819*b30d1939SAndy Fiddaman 		nv_local=0;
2820*b30d1939SAndy Fiddaman 	}
2821*b30d1939SAndy Fiddaman 	numeric = ((nv_isattr (np, NV_INTEGER)) != 0);
2822*b30d1939SAndy Fiddaman 	if(numeric)
2823*b30d1939SAndy Fiddaman 	{
2824*b30d1939SAndy Fiddaman 		Sflong_t  ll;
2825*b30d1939SAndy Fiddaman 		if(!up->cp)
2826*b30d1939SAndy Fiddaman 			return("0");
2827*b30d1939SAndy Fiddaman 		if(nv_isattr (np,NV_DOUBLE)==NV_DOUBLE)
2828*b30d1939SAndy Fiddaman 		{
2829*b30d1939SAndy Fiddaman 			Sfdouble_t ld;
2830*b30d1939SAndy Fiddaman 			double d;
2831*b30d1939SAndy Fiddaman 			char *format;
2832*b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_LONG))
2833*b30d1939SAndy Fiddaman 			{
2834*b30d1939SAndy Fiddaman 				ld = *up->ldp;
2835*b30d1939SAndy Fiddaman 				if(nv_isattr (np,NV_EXPNOTE))
2836*b30d1939SAndy Fiddaman 					format = "%.*Lg";
2837*b30d1939SAndy Fiddaman 				else if(nv_isattr (np,NV_HEXFLOAT))
2838*b30d1939SAndy Fiddaman 					format = "%.*La";
2839*b30d1939SAndy Fiddaman 				else
2840*b30d1939SAndy Fiddaman 					format = "%.*Lf";
2841*b30d1939SAndy Fiddaman 				sfprintf(shp->strbuf,format,nv_size(np),ld);
2842*b30d1939SAndy Fiddaman 			}
2843*b30d1939SAndy Fiddaman 			else
2844*b30d1939SAndy Fiddaman 			{
2845*b30d1939SAndy Fiddaman 				d = *up->dp;
2846*b30d1939SAndy Fiddaman 				if(nv_isattr (np,NV_EXPNOTE))
2847*b30d1939SAndy Fiddaman 					format = "%.*g";
2848*b30d1939SAndy Fiddaman 				else if(nv_isattr (np,NV_HEXFLOAT))
2849*b30d1939SAndy Fiddaman 					format = "%.*a";
2850*b30d1939SAndy Fiddaman 				else
2851*b30d1939SAndy Fiddaman 					format = "%.*f";
2852*b30d1939SAndy Fiddaman 				sfprintf(shp->strbuf,format,nv_size(np),d);
2853*b30d1939SAndy Fiddaman 			}
2854*b30d1939SAndy Fiddaman 			return(sfstruse(shp->strbuf));
2855*b30d1939SAndy Fiddaman 		}
2856*b30d1939SAndy Fiddaman 		else if(nv_isattr(np,NV_UNSIGN))
2857*b30d1939SAndy Fiddaman 		{
2858*b30d1939SAndy Fiddaman 	        	if(nv_isattr (np,NV_LONG))
2859*b30d1939SAndy Fiddaman 				ll = *(Sfulong_t*)up->llp;
2860*b30d1939SAndy Fiddaman 			else if(nv_isattr (np,NV_SHORT))
2861*b30d1939SAndy Fiddaman 			{
2862*b30d1939SAndy Fiddaman 				if(nv_isattr(np,NV_INT16P)==NV_INT16P)
2863*b30d1939SAndy Fiddaman 					ll = *(uint16_t*)(up->sp);
2864*b30d1939SAndy Fiddaman 				else
2865*b30d1939SAndy Fiddaman 					ll = (uint16_t)up->s;
2866*b30d1939SAndy Fiddaman 			}
2867*b30d1939SAndy Fiddaman 			else
2868*b30d1939SAndy Fiddaman 				ll = *(uint32_t*)(up->lp);
2869*b30d1939SAndy Fiddaman 		}
2870*b30d1939SAndy Fiddaman         	else if(nv_isattr (np,NV_LONG))
2871*b30d1939SAndy Fiddaman 			ll = *up->llp;
2872*b30d1939SAndy Fiddaman         	else if(nv_isattr (np,NV_SHORT))
2873*b30d1939SAndy Fiddaman 		{
2874*b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_INT16P)==NV_INT16P)
2875*b30d1939SAndy Fiddaman 				ll = *up->sp;
2876*b30d1939SAndy Fiddaman 			else
2877*b30d1939SAndy Fiddaman 				ll = up->s;
2878*b30d1939SAndy Fiddaman 		}
2879*b30d1939SAndy Fiddaman         	else
2880*b30d1939SAndy Fiddaman 			ll = *(up->lp);
2881*b30d1939SAndy Fiddaman 		if((numeric=nv_size(np))==10)
2882*b30d1939SAndy Fiddaman 		{
2883*b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_UNSIGN))
2884*b30d1939SAndy Fiddaman 			{
2885*b30d1939SAndy Fiddaman 				sfprintf(shp->strbuf,"%I*u",sizeof(ll),ll);
2886*b30d1939SAndy Fiddaman 				return(sfstruse(shp->strbuf));
2887*b30d1939SAndy Fiddaman 			}
2888*b30d1939SAndy Fiddaman 			numeric = 0;
2889*b30d1939SAndy Fiddaman 		}
2890*b30d1939SAndy Fiddaman 		return(fmtbase(ll,numeric, numeric&&numeric!=10));
2891*b30d1939SAndy Fiddaman 	}
2892*b30d1939SAndy Fiddaman done:
2893*b30d1939SAndy Fiddaman #if (_AST_VERSION>=20030127L)
2894*b30d1939SAndy Fiddaman 	/*
2895*b30d1939SAndy Fiddaman 	 * if NV_RAW flag is on, return pointer to binary data
2896*b30d1939SAndy Fiddaman 	 * otherwise, base64 encode the data and return this string
2897*b30d1939SAndy Fiddaman 	 */
2898*b30d1939SAndy Fiddaman 	if(up->cp && nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
2899*b30d1939SAndy Fiddaman 	{
2900*b30d1939SAndy Fiddaman 		char *cp;
2901*b30d1939SAndy Fiddaman 		char *ep;
2902*b30d1939SAndy Fiddaman 		int size= nv_size(np), insize=(4*size)/3+size/45+8;
2903*b30d1939SAndy Fiddaman 		base64encode(up->cp, size, (void**)0, cp=getbuf(insize), insize, (void**)&ep);
2904*b30d1939SAndy Fiddaman 		*ep = 0;
2905*b30d1939SAndy Fiddaman 		return(cp);
2906*b30d1939SAndy Fiddaman 	}
2907*b30d1939SAndy Fiddaman #endif
2908*b30d1939SAndy Fiddaman 	if(!nv_isattr(np,NV_LJUST|NV_RJUST) && (numeric=nv_size(np)) && up->cp && up->cp[numeric])
2909*b30d1939SAndy Fiddaman 	{
2910*b30d1939SAndy Fiddaman 		char *cp = getbuf(numeric+1);
2911*b30d1939SAndy Fiddaman 		memcpy(cp,up->cp,numeric);
2912*b30d1939SAndy Fiddaman 		cp[numeric]=0;
2913*b30d1939SAndy Fiddaman 		return(cp);
2914*b30d1939SAndy Fiddaman 	}
2915*b30d1939SAndy Fiddaman 	return ((char*)up->cp);
2916*b30d1939SAndy Fiddaman }
2917*b30d1939SAndy Fiddaman 
nv_getnum(register Namval_t * np)2918*b30d1939SAndy Fiddaman Sfdouble_t nv_getnum(register Namval_t *np)
2919*b30d1939SAndy Fiddaman {
2920*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
2921*b30d1939SAndy Fiddaman 	register union Value *up;
2922*b30d1939SAndy Fiddaman 	register Sfdouble_t r=0;
2923*b30d1939SAndy Fiddaman 	register char *str;
2924*b30d1939SAndy Fiddaman #if SHOPT_OPTIMIZE
2925*b30d1939SAndy Fiddaman 	if(!nv_local && shp->argaddr)
2926*b30d1939SAndy Fiddaman 		nv_optimize(np);
2927*b30d1939SAndy Fiddaman #endif /* SHOPT_OPTIMIZE */
2928*b30d1939SAndy Fiddaman 	if(nv_istable(np))
2929*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_number,nv_name(np));
2930*b30d1939SAndy Fiddaman      	if(np->nvfun && np->nvfun->disc)
2931*b30d1939SAndy Fiddaman 	{
2932*b30d1939SAndy Fiddaman 		if(!nv_local)
2933*b30d1939SAndy Fiddaman 		{
2934*b30d1939SAndy Fiddaman 			nv_local=1;
2935*b30d1939SAndy Fiddaman 			return(nv_getn(np, np->nvfun));
2936*b30d1939SAndy Fiddaman 		}
2937*b30d1939SAndy Fiddaman 		nv_local=0;
2938*b30d1939SAndy Fiddaman 	}
2939*b30d1939SAndy Fiddaman 	if(nv_isref(np))
2940*b30d1939SAndy Fiddaman 	{
2941*b30d1939SAndy Fiddaman 		str = nv_refsub(np);
2942*b30d1939SAndy Fiddaman 		np = nv_refnode(np);
2943*b30d1939SAndy Fiddaman 		if(str)
2944*b30d1939SAndy Fiddaman 			nv_putsub(np,str,0L);
2945*b30d1939SAndy Fiddaman 	}
2946*b30d1939SAndy Fiddaman      	if(nv_isattr (np, NV_INTEGER))
2947*b30d1939SAndy Fiddaman 	{
2948*b30d1939SAndy Fiddaman 		up= &np->nvalue;
2949*b30d1939SAndy Fiddaman 		if(!up->lp || up->cp==Empty)
2950*b30d1939SAndy Fiddaman 			r = 0;
2951*b30d1939SAndy Fiddaman 		else if(nv_isattr(np, NV_DOUBLE)==NV_DOUBLE)
2952*b30d1939SAndy Fiddaman 		{
2953*b30d1939SAndy Fiddaman 			if(nv_isattr(np, NV_LONG))
2954*b30d1939SAndy Fiddaman 	                       	r = *up->ldp;
2955*b30d1939SAndy Fiddaman 			else
2956*b30d1939SAndy Fiddaman        	                	r = *up->dp;
2957*b30d1939SAndy Fiddaman 		}
2958*b30d1939SAndy Fiddaman 		else if(nv_isattr(np, NV_UNSIGN))
2959*b30d1939SAndy Fiddaman 		{
2960*b30d1939SAndy Fiddaman 			if(nv_isattr(np, NV_LONG))
2961*b30d1939SAndy Fiddaman 				r = (Sflong_t)*((Sfulong_t*)up->llp);
2962*b30d1939SAndy Fiddaman 			else if(nv_isattr(np, NV_SHORT))
2963*b30d1939SAndy Fiddaman 			{
2964*b30d1939SAndy Fiddaman 				if(nv_isattr(np,NV_INT16P)==NV_INT16P)
2965*b30d1939SAndy Fiddaman 					r = (Sflong_t)(*(uint16_t*)up->sp);
2966*b30d1939SAndy Fiddaman 				else
2967*b30d1939SAndy Fiddaman 					r = (Sflong_t)((uint16_t)up->s);
2968*b30d1939SAndy Fiddaman 			}
2969*b30d1939SAndy Fiddaman 			else
2970*b30d1939SAndy Fiddaman 				r = *((uint32_t*)up->lp);
2971*b30d1939SAndy Fiddaman 		}
2972*b30d1939SAndy Fiddaman 		else
2973*b30d1939SAndy Fiddaman 		{
2974*b30d1939SAndy Fiddaman 			if(nv_isattr(np, NV_LONG))
2975*b30d1939SAndy Fiddaman 				r = *up->llp;
2976*b30d1939SAndy Fiddaman 			else if(nv_isattr(np, NV_SHORT))
2977*b30d1939SAndy Fiddaman 			{
2978*b30d1939SAndy Fiddaman 				if(nv_isattr(np,NV_INT16P)==NV_INT16P)
2979*b30d1939SAndy Fiddaman 					r = *up->sp;
2980*b30d1939SAndy Fiddaman 				else
2981*b30d1939SAndy Fiddaman 					r = up->s;
2982*b30d1939SAndy Fiddaman 			}
2983*b30d1939SAndy Fiddaman 			else
2984*b30d1939SAndy Fiddaman 				r = *up->lp;
2985*b30d1939SAndy Fiddaman 		}
2986*b30d1939SAndy Fiddaman 	}
2987*b30d1939SAndy Fiddaman 	else if((str=nv_getval(np)) && *str!=0)
2988*b30d1939SAndy Fiddaman 	{
2989*b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_LJUST|NV_RJUST) || (*str=='0' && !(str[1]=='x'||str[1]=='X')))
2990*b30d1939SAndy Fiddaman 		{
2991*b30d1939SAndy Fiddaman 			while(*str=='0')
2992*b30d1939SAndy Fiddaman 				str++;
2993*b30d1939SAndy Fiddaman 		}
2994*b30d1939SAndy Fiddaman 		r = sh_arith(shp,str);
2995*b30d1939SAndy Fiddaman 	}
2996*b30d1939SAndy Fiddaman 	return(r);
2997*b30d1939SAndy Fiddaman }
2998*b30d1939SAndy Fiddaman 
2999*b30d1939SAndy Fiddaman /*
3000*b30d1939SAndy Fiddaman  *   Give <np> the attributes <newatts,> and change its current
3001*b30d1939SAndy Fiddaman  *   value to conform to <newatts>.  The <size> of left and right
3002*b30d1939SAndy Fiddaman  *   justified fields may be given.
3003*b30d1939SAndy Fiddaman  */
nv_newattr(register Namval_t * np,unsigned newatts,int size)3004*b30d1939SAndy Fiddaman void nv_newattr (register Namval_t *np, unsigned newatts, int size)
3005*b30d1939SAndy Fiddaman {
3006*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3007*b30d1939SAndy Fiddaman 	register char *sp;
3008*b30d1939SAndy Fiddaman 	register char *cp = 0;
3009*b30d1939SAndy Fiddaman 	register unsigned int n;
3010*b30d1939SAndy Fiddaman 	Namval_t *mp = 0;
3011*b30d1939SAndy Fiddaman 	Namarr_t *ap = 0;
3012*b30d1939SAndy Fiddaman 	int oldsize,oldatts,trans;
3013*b30d1939SAndy Fiddaman 	Namfun_t *fp= (newatts&NV_NODISC)?np->nvfun:0;
3014*b30d1939SAndy Fiddaman 	char *prefix = shp->prefix;
3015*b30d1939SAndy Fiddaman 	newatts &= ~NV_NODISC;
3016*b30d1939SAndy Fiddaman 
3017*b30d1939SAndy Fiddaman 	/* check for restrictions */
3018*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_RESTRICTED) && ((sp=nv_name(np))==nv_name(PATHNOD) || sp==nv_name(SHELLNOD) || sp==nv_name(ENVNOD) || sp==nv_name(FPATHNOD)))
3019*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
3020*b30d1939SAndy Fiddaman 	/* handle attributes that do not change data separately */
3021*b30d1939SAndy Fiddaman 	n = np->nvflag;
3022*b30d1939SAndy Fiddaman 	trans = !(n&NV_INTEGER) && (n&(NV_LTOU|NV_UTOL));
3023*b30d1939SAndy Fiddaman 	if(newatts&NV_EXPORT)
3024*b30d1939SAndy Fiddaman 		nv_offattr(np,NV_IMPORT);
3025*b30d1939SAndy Fiddaman 	if(((n^newatts)&NV_EXPORT))
3026*b30d1939SAndy Fiddaman 	{
3027*b30d1939SAndy Fiddaman 		/* record changes to the environment */
3028*b30d1939SAndy Fiddaman 		if(n&NV_EXPORT)
3029*b30d1939SAndy Fiddaman 		{
3030*b30d1939SAndy Fiddaman 			nv_offattr(np,NV_EXPORT);
3031*b30d1939SAndy Fiddaman 			env_delete(shp->env,nv_name(np));
3032*b30d1939SAndy Fiddaman 		}
3033*b30d1939SAndy Fiddaman 		else
3034*b30d1939SAndy Fiddaman 		{
3035*b30d1939SAndy Fiddaman 			nv_onattr(np,NV_EXPORT);
3036*b30d1939SAndy Fiddaman 			sh_envput(shp->env,np);
3037*b30d1939SAndy Fiddaman 		}
3038*b30d1939SAndy Fiddaman 		if((n^newatts)==NV_EXPORT)
3039*b30d1939SAndy Fiddaman 			return;
3040*b30d1939SAndy Fiddaman 	}
3041*b30d1939SAndy Fiddaman 	oldsize = nv_size(np);
3042*b30d1939SAndy Fiddaman 	if((size==oldsize|| (n&NV_INTEGER)) && !trans && ((n^newatts)&~NV_NOCHANGE)==0)
3043*b30d1939SAndy Fiddaman 	{
3044*b30d1939SAndy Fiddaman 		if(size)
3045*b30d1939SAndy Fiddaman 			nv_setsize(np,size);
3046*b30d1939SAndy Fiddaman 		nv_offattr(np, ~NV_NOFREE);
3047*b30d1939SAndy Fiddaman 		nv_onattr(np, newatts);
3048*b30d1939SAndy Fiddaman 		return;
3049*b30d1939SAndy Fiddaman 	}
3050*b30d1939SAndy Fiddaman 	/* for an array, change all the elements */
3051*b30d1939SAndy Fiddaman 	if((ap=nv_arrayptr(np)) && ap->nelem>0)
3052*b30d1939SAndy Fiddaman 		nv_putsub(np,NIL(char*),ARRAY_SCAN);
3053*b30d1939SAndy Fiddaman 	oldsize = nv_size(np);
3054*b30d1939SAndy Fiddaman 	oldatts = np->nvflag;
3055*b30d1939SAndy Fiddaman 	if(fp)
3056*b30d1939SAndy Fiddaman 		np->nvfun = 0;
3057*b30d1939SAndy Fiddaman 	if(ap) /* add element to prevent array deletion */
3058*b30d1939SAndy Fiddaman 	{
3059*b30d1939SAndy Fiddaman 		ap->nelem++;
3060*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3061*b30d1939SAndy Fiddaman 		if(ap->fixed)
3062*b30d1939SAndy Fiddaman 		{
3063*b30d1939SAndy Fiddaman 			nv_setsize(np,size);
3064*b30d1939SAndy Fiddaman 			np->nvflag &= NV_ARRAY;
3065*b30d1939SAndy Fiddaman 			np->nvflag |= newatts;
3066*b30d1939SAndy Fiddaman 			goto skip;
3067*b30d1939SAndy Fiddaman 		}
3068*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
3069*b30d1939SAndy Fiddaman 	}
3070*b30d1939SAndy Fiddaman 	do
3071*b30d1939SAndy Fiddaman 	{
3072*b30d1939SAndy Fiddaman 		nv_setsize(np,oldsize);
3073*b30d1939SAndy Fiddaman 		np->nvflag = oldatts;
3074*b30d1939SAndy Fiddaman 		if (sp = nv_getval(np))
3075*b30d1939SAndy Fiddaman  		{
3076*b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_ZFILL))
3077*b30d1939SAndy Fiddaman 				while(*sp=='0') sp++;
3078*b30d1939SAndy Fiddaman 			cp = (char*)malloc((n=strlen (sp)) + 8);
3079*b30d1939SAndy Fiddaman 			strcpy(cp, sp);
3080*b30d1939SAndy Fiddaman 			if(sp && (mp=nv_opensub(np)))
3081*b30d1939SAndy Fiddaman 			{
3082*b30d1939SAndy Fiddaman 				if(trans)
3083*b30d1939SAndy Fiddaman 				{
3084*b30d1939SAndy Fiddaman 					nv_disc(np, &ap->hdr,NV_POP);
3085*b30d1939SAndy Fiddaman 					nv_clone(np,mp,0);
3086*b30d1939SAndy Fiddaman 					nv_disc(np, &ap->hdr,NV_FIRST);
3087*b30d1939SAndy Fiddaman 					nv_offattr(mp,NV_ARRAY);
3088*b30d1939SAndy Fiddaman 				}
3089*b30d1939SAndy Fiddaman 				nv_newattr(mp,newatts&~NV_ARRAY,size);
3090*b30d1939SAndy Fiddaman 			}
3091*b30d1939SAndy Fiddaman 			if(!mp)
3092*b30d1939SAndy Fiddaman 			{
3093*b30d1939SAndy Fiddaman 				if(ap)
3094*b30d1939SAndy Fiddaman 					ap->nelem &= ~ARRAY_SCAN;
3095*b30d1939SAndy Fiddaman 				if(!trans)
3096*b30d1939SAndy Fiddaman 					_nv_unset(np,NV_RDONLY|NV_EXPORT);
3097*b30d1939SAndy Fiddaman 				if(ap)
3098*b30d1939SAndy Fiddaman 					ap->nelem |= ARRAY_SCAN;
3099*b30d1939SAndy Fiddaman 			}
3100*b30d1939SAndy Fiddaman 			if(size==0 && (newatts&NV_HOST)!=NV_HOST && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL)))
3101*b30d1939SAndy Fiddaman 				size = n;
3102*b30d1939SAndy Fiddaman 		}
3103*b30d1939SAndy Fiddaman 		else if(!trans)
3104*b30d1939SAndy Fiddaman 			_nv_unset(np,NV_EXPORT);
3105*b30d1939SAndy Fiddaman 		nv_setsize(np,size);
3106*b30d1939SAndy Fiddaman 		np->nvflag &= (NV_ARRAY|NV_NOFREE);
3107*b30d1939SAndy Fiddaman 		np->nvflag |= newatts;
3108*b30d1939SAndy Fiddaman 		if (cp)
3109*b30d1939SAndy Fiddaman 		{
3110*b30d1939SAndy Fiddaman 			if(!mp)
3111*b30d1939SAndy Fiddaman 				nv_putval (np, cp, NV_RDONLY);
3112*b30d1939SAndy Fiddaman 			free(cp);
3113*b30d1939SAndy Fiddaman 		}
3114*b30d1939SAndy Fiddaman 	}
3115*b30d1939SAndy Fiddaman 	while(ap && nv_nextsub(np));
3116*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3117*b30d1939SAndy Fiddaman skip:
3118*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
3119*b30d1939SAndy Fiddaman 	if(fp)
3120*b30d1939SAndy Fiddaman 		np->nvfun = fp;
3121*b30d1939SAndy Fiddaman 	if(ap)
3122*b30d1939SAndy Fiddaman 		ap->nelem--;
3123*b30d1939SAndy Fiddaman 	shp->prefix = prefix;
3124*b30d1939SAndy Fiddaman 	return;
3125*b30d1939SAndy Fiddaman }
3126*b30d1939SAndy Fiddaman 
oldgetenv(const char * string)3127*b30d1939SAndy Fiddaman static char *oldgetenv(const char *string)
3128*b30d1939SAndy Fiddaman {
3129*b30d1939SAndy Fiddaman 	register char c0,c1;
3130*b30d1939SAndy Fiddaman 	register const char *cp, *sp;
3131*b30d1939SAndy Fiddaman 	register char **av = environ;
3132*b30d1939SAndy Fiddaman 	if(!string || (c0= *string)==0)
3133*b30d1939SAndy Fiddaman 		return(0);
3134*b30d1939SAndy Fiddaman 	if((c1=*++string)==0)
3135*b30d1939SAndy Fiddaman 		c1= '=';
3136*b30d1939SAndy Fiddaman 	while(cp = *av++)
3137*b30d1939SAndy Fiddaman 	{
3138*b30d1939SAndy Fiddaman 		if(cp[0]!=c0 || cp[1]!=c1)
3139*b30d1939SAndy Fiddaman 			continue;
3140*b30d1939SAndy Fiddaman 		sp = string;
3141*b30d1939SAndy Fiddaman 		while(*sp && *sp++ == *++cp);
3142*b30d1939SAndy Fiddaman 		if(*sp==0 && *++cp=='=')
3143*b30d1939SAndy Fiddaman 			return((char*)(cp+1));
3144*b30d1939SAndy Fiddaman 	}
3145*b30d1939SAndy Fiddaman 	return(0);
3146*b30d1939SAndy Fiddaman }
3147*b30d1939SAndy Fiddaman 
3148*b30d1939SAndy Fiddaman /*
3149*b30d1939SAndy Fiddaman  * This version of getenv uses the hash storage to access environment values
3150*b30d1939SAndy Fiddaman  */
sh_getenv(const char * name)3151*b30d1939SAndy Fiddaman char *sh_getenv(const char *name)
3152*b30d1939SAndy Fiddaman {
3153*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3154*b30d1939SAndy Fiddaman 	register Namval_t *np;
3155*b30d1939SAndy Fiddaman 	if(!shp->var_tree)
3156*b30d1939SAndy Fiddaman 	{
3157*b30d1939SAndy Fiddaman #if 0
3158*b30d1939SAndy Fiddaman 		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] == '_')
3159*b30d1939SAndy Fiddaman #endif
3160*b30d1939SAndy Fiddaman 			return(oldgetenv(name));
3161*b30d1939SAndy Fiddaman 	}
3162*b30d1939SAndy Fiddaman 	else if((np = nv_search(name,shp->var_tree,0)) && nv_isattr(np,NV_EXPORT))
3163*b30d1939SAndy Fiddaman 		return(nv_getval(np));
3164*b30d1939SAndy Fiddaman 	return(0);
3165*b30d1939SAndy Fiddaman }
3166*b30d1939SAndy Fiddaman 
3167*b30d1939SAndy Fiddaman #ifndef _NEXT_SOURCE
3168*b30d1939SAndy Fiddaman /*
3169*b30d1939SAndy Fiddaman  * Some dynamic linkers will make this file see the libc getenv(),
3170*b30d1939SAndy Fiddaman  * so sh_getenv() is used for the astintercept() callback.  Plain
3171*b30d1939SAndy Fiddaman  * getenv() is provided for static links.
3172*b30d1939SAndy Fiddaman  */
getenv(const char * name)3173*b30d1939SAndy Fiddaman char *getenv(const char *name)
3174*b30d1939SAndy Fiddaman {
3175*b30d1939SAndy Fiddaman 	return sh_getenv(name);
3176*b30d1939SAndy Fiddaman }
3177*b30d1939SAndy Fiddaman #endif /* _NEXT_SOURCE */
3178*b30d1939SAndy Fiddaman 
3179*b30d1939SAndy Fiddaman #undef putenv
3180*b30d1939SAndy Fiddaman /*
3181*b30d1939SAndy Fiddaman  * This version of putenv uses the hash storage to assign environment values
3182*b30d1939SAndy Fiddaman  */
putenv(const char * name)3183*b30d1939SAndy Fiddaman int putenv(const char *name)
3184*b30d1939SAndy Fiddaman {
3185*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3186*b30d1939SAndy Fiddaman 	register Namval_t *np;
3187*b30d1939SAndy Fiddaman 	if(name)
3188*b30d1939SAndy Fiddaman 	{
3189*b30d1939SAndy Fiddaman 		np = nv_open(name,shp->var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN);
3190*b30d1939SAndy Fiddaman 		if(!strchr(name,'='))
3191*b30d1939SAndy Fiddaman 			_nv_unset(np,0);
3192*b30d1939SAndy Fiddaman 	}
3193*b30d1939SAndy Fiddaman 	return(0);
3194*b30d1939SAndy Fiddaman }
3195*b30d1939SAndy Fiddaman 
3196*b30d1939SAndy Fiddaman /*
3197*b30d1939SAndy Fiddaman  * Override libast setenviron().
3198*b30d1939SAndy Fiddaman  */
sh_setenviron(const char * name)3199*b30d1939SAndy Fiddaman char* sh_setenviron(const char *name)
3200*b30d1939SAndy Fiddaman {
3201*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3202*b30d1939SAndy Fiddaman 	register Namval_t *np;
3203*b30d1939SAndy Fiddaman 	if(name)
3204*b30d1939SAndy Fiddaman 	{
3205*b30d1939SAndy Fiddaman 		np = nv_open(name,shp->var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN);
3206*b30d1939SAndy Fiddaman 		if(strchr(name,'='))
3207*b30d1939SAndy Fiddaman 			return(nv_getval(np));
3208*b30d1939SAndy Fiddaman 		_nv_unset(np,0);
3209*b30d1939SAndy Fiddaman 	}
3210*b30d1939SAndy Fiddaman 	return("");
3211*b30d1939SAndy Fiddaman }
3212*b30d1939SAndy Fiddaman 
3213*b30d1939SAndy Fiddaman /*
3214*b30d1939SAndy Fiddaman  * Same linker dance as with getenv() above.
3215*b30d1939SAndy Fiddaman  */
setenviron(const char * name)3216*b30d1939SAndy Fiddaman char* setenviron(const char *name)
3217*b30d1939SAndy Fiddaman {
3218*b30d1939SAndy Fiddaman 	return sh_setenviron(name);
3219*b30d1939SAndy Fiddaman }
3220*b30d1939SAndy Fiddaman 
3221*b30d1939SAndy Fiddaman /*
3222*b30d1939SAndy Fiddaman  * normalize <cp> and return pointer to subscript if any
3223*b30d1939SAndy Fiddaman  * if <eq> is specified, return pointer to first = not in a subscript
3224*b30d1939SAndy Fiddaman  */
lastdot(char * cp,int eq)3225*b30d1939SAndy Fiddaman static char *lastdot(char *cp, int eq)
3226*b30d1939SAndy Fiddaman {
3227*b30d1939SAndy Fiddaman 	register char *ep=0;
3228*b30d1939SAndy Fiddaman 	register int c;
3229*b30d1939SAndy Fiddaman 	if(eq)
3230*b30d1939SAndy Fiddaman 		cp++;
3231*b30d1939SAndy Fiddaman 	while(c= mbchar(cp))
3232*b30d1939SAndy Fiddaman 	{
3233*b30d1939SAndy Fiddaman 		if(c=='[')
3234*b30d1939SAndy Fiddaman 		{
3235*b30d1939SAndy Fiddaman 			if(*cp==']')
3236*b30d1939SAndy Fiddaman 				cp++;
3237*b30d1939SAndy Fiddaman 			else
3238*b30d1939SAndy Fiddaman 				cp = nv_endsubscript((Namval_t*)0,ep=cp,0);
3239*b30d1939SAndy Fiddaman 		}
3240*b30d1939SAndy Fiddaman 		else if(c=='.')
3241*b30d1939SAndy Fiddaman 		{
3242*b30d1939SAndy Fiddaman 			if(*cp=='[')
3243*b30d1939SAndy Fiddaman 			{
3244*b30d1939SAndy Fiddaman 				cp = nv_endsubscript((Namval_t*)0,ep=cp,0);
3245*b30d1939SAndy Fiddaman 				if((ep=sh_checkid(ep+1,cp)) < cp)
3246*b30d1939SAndy Fiddaman 					cp=strcpy(ep,cp);
3247*b30d1939SAndy Fiddaman 			}
3248*b30d1939SAndy Fiddaman 			ep = 0;
3249*b30d1939SAndy Fiddaman 		}
3250*b30d1939SAndy Fiddaman 		else if(eq && c == '=')
3251*b30d1939SAndy Fiddaman 			return(cp-1);
3252*b30d1939SAndy Fiddaman 	}
3253*b30d1939SAndy Fiddaman 	return(eq?0:ep);
3254*b30d1939SAndy Fiddaman }
3255*b30d1939SAndy Fiddaman 
nv_rename(register Namval_t * np,int flags)3256*b30d1939SAndy Fiddaman int nv_rename(register Namval_t *np, int flags)
3257*b30d1939SAndy Fiddaman {
3258*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
3259*b30d1939SAndy Fiddaman 	register Namval_t	*mp=0,*nr=0;
3260*b30d1939SAndy Fiddaman 	register char		*cp;
3261*b30d1939SAndy Fiddaman 	int			arraynp=0,arraynr,index= -1;
3262*b30d1939SAndy Fiddaman 	Namval_t		*last_table = shp->last_table;
3263*b30d1939SAndy Fiddaman 	Dt_t			*last_root = shp->last_root;
3264*b30d1939SAndy Fiddaman 	Dt_t			*hp = 0;
3265*b30d1939SAndy Fiddaman 	char			*nvenv=0,*prefix=shp->prefix;
3266*b30d1939SAndy Fiddaman 	Namarr_t		*ap;
3267*b30d1939SAndy Fiddaman 	if(nv_isattr(np,NV_PARAM) && shp->st.prevst)
3268*b30d1939SAndy Fiddaman 	{
3269*b30d1939SAndy Fiddaman 		if(!(hp=(Dt_t*)shp->st.prevst->save_tree))
3270*b30d1939SAndy Fiddaman 			hp = dtvnext(shp->var_tree);
3271*b30d1939SAndy Fiddaman 	}
3272*b30d1939SAndy Fiddaman 	if(!nv_isattr(np,NV_MINIMAL))
3273*b30d1939SAndy Fiddaman 		nvenv = np->nvenv;
3274*b30d1939SAndy Fiddaman 	if(nvenv || (cp = nv_name(np)) && nv_isarray(np) && cp[strlen(cp)-1] == ']')
3275*b30d1939SAndy Fiddaman 		arraynp = 1;
3276*b30d1939SAndy Fiddaman 	if(!(cp=nv_getval(np)))
3277*b30d1939SAndy Fiddaman 	{
3278*b30d1939SAndy Fiddaman 		if(flags&NV_MOVE)
3279*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_varname,"");
3280*b30d1939SAndy Fiddaman 		return(0);
3281*b30d1939SAndy Fiddaman 	}
3282*b30d1939SAndy Fiddaman 	if(lastdot(cp,0) && nv_isattr(np,NV_MINIMAL))
3283*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_varname,nv_name(np));
3284*b30d1939SAndy Fiddaman 	arraynr = cp[strlen(cp)-1] == ']';
3285*b30d1939SAndy Fiddaman 	if(nv_isarray(np) && !(mp=nv_opensub(np)))
3286*b30d1939SAndy Fiddaman 		index=nv_aindex(np);
3287*b30d1939SAndy Fiddaman 	shp->prefix = 0;
3288*b30d1939SAndy Fiddaman 	if(!hp)
3289*b30d1939SAndy Fiddaman 		hp = shp->var_tree;
3290*b30d1939SAndy Fiddaman 	if(!(nr = nv_open(cp, hp, flags|NV_ARRAY|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
3291*b30d1939SAndy Fiddaman 	{
3292*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
3293*b30d1939SAndy Fiddaman 		if(shp->namespace)
3294*b30d1939SAndy Fiddaman 			hp = nv_dict(shp->namespace);
3295*b30d1939SAndy Fiddaman 		else
3296*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
3297*b30d1939SAndy Fiddaman 		hp = shp->var_base;
3298*b30d1939SAndy Fiddaman 	}
3299*b30d1939SAndy Fiddaman 	else if(shp->last_root)
3300*b30d1939SAndy Fiddaman 		hp = shp->last_root;
3301*b30d1939SAndy Fiddaman 	if(!nr)
3302*b30d1939SAndy Fiddaman 		nr= nv_open(cp, hp, flags|NV_NOREF|((flags&NV_MOVE)?0:NV_NOFAIL));
3303*b30d1939SAndy Fiddaman 	shp->prefix = prefix;
3304*b30d1939SAndy Fiddaman 	if(!nr)
3305*b30d1939SAndy Fiddaman 	{
3306*b30d1939SAndy Fiddaman 		if(!nv_isvtree(np))
3307*b30d1939SAndy Fiddaman 			_nv_unset(np,0);
3308*b30d1939SAndy Fiddaman 		return(0);
3309*b30d1939SAndy Fiddaman 	}
3310*b30d1939SAndy Fiddaman 	if(!mp && index>=0 && nv_isvtree(nr))
3311*b30d1939SAndy Fiddaman 	{
3312*b30d1939SAndy Fiddaman 		sfprintf(shp->strbuf,"%s[%d]%c",nv_name(np),index,0);
3313*b30d1939SAndy Fiddaman 		/* create a virtual node */
3314*b30d1939SAndy Fiddaman 		if(mp = nv_open(sfstruse(shp->strbuf),shp->var_tree,NV_VARNAME|NV_ADD|NV_ARRAY))
3315*b30d1939SAndy Fiddaman 		{
3316*b30d1939SAndy Fiddaman 			if(ap = nv_arrayptr(np))
3317*b30d1939SAndy Fiddaman 				ap->nelem++;
3318*b30d1939SAndy Fiddaman 			mp->nvenv = nvenv = (void*)np;
3319*b30d1939SAndy Fiddaman 		}
3320*b30d1939SAndy Fiddaman 	}
3321*b30d1939SAndy Fiddaman 	if(mp)
3322*b30d1939SAndy Fiddaman 	{
3323*b30d1939SAndy Fiddaman 		nvenv = (char*)np;
3324*b30d1939SAndy Fiddaman 		np = mp;
3325*b30d1939SAndy Fiddaman 	}
3326*b30d1939SAndy Fiddaman 	if(nr==np)
3327*b30d1939SAndy Fiddaman 	{
3328*b30d1939SAndy Fiddaman 		if(index<0)
3329*b30d1939SAndy Fiddaman 			return(0);
3330*b30d1939SAndy Fiddaman 		if(cp = nv_getval(np))
3331*b30d1939SAndy Fiddaman 			cp = strdup(cp);
3332*b30d1939SAndy Fiddaman 	}
3333*b30d1939SAndy Fiddaman 	_nv_unset(np,NV_EXPORT);
3334*b30d1939SAndy Fiddaman 	if(nr==np)
3335*b30d1939SAndy Fiddaman 	{
3336*b30d1939SAndy Fiddaman 		nv_putsub(np,(char*)0, index);
3337*b30d1939SAndy Fiddaman 		nv_putval(np,cp,0);
3338*b30d1939SAndy Fiddaman 		free((void*)cp);
3339*b30d1939SAndy Fiddaman 		return(1);
3340*b30d1939SAndy Fiddaman 	}
3341*b30d1939SAndy Fiddaman 	shp->prev_table = shp->last_table;
3342*b30d1939SAndy Fiddaman 	shp->prev_root = shp->last_root;
3343*b30d1939SAndy Fiddaman 	shp->last_table = last_table;
3344*b30d1939SAndy Fiddaman 	shp->last_root = last_root;
3345*b30d1939SAndy Fiddaman 	if(flags&NV_MOVE)
3346*b30d1939SAndy Fiddaman 	{
3347*b30d1939SAndy Fiddaman 		if(arraynp && !nv_isattr(np,NV_MINIMAL) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)))
3348*b30d1939SAndy Fiddaman 			ap->nelem++;
3349*b30d1939SAndy Fiddaman 	}
3350*b30d1939SAndy Fiddaman 	if((nv_arrayptr(nr) && !arraynr) || nv_isvtree(nr))
3351*b30d1939SAndy Fiddaman 	{
3352*b30d1939SAndy Fiddaman 		if(ap=nv_arrayptr(np))
3353*b30d1939SAndy Fiddaman 		{
3354*b30d1939SAndy Fiddaman 			if(!ap->table)
3355*b30d1939SAndy Fiddaman 				ap->table = dtopen(&_Nvdisc,Dtoset);
3356*b30d1939SAndy Fiddaman 			if(ap->table)
3357*b30d1939SAndy Fiddaman 				mp = nv_search(nv_getsub(np),ap->table,NV_ADD);
3358*b30d1939SAndy Fiddaman 			nv_arraychild(np,mp,0);
3359*b30d1939SAndy Fiddaman 			nvenv = (void*)np;
3360*b30d1939SAndy Fiddaman 		}
3361*b30d1939SAndy Fiddaman 		else
3362*b30d1939SAndy Fiddaman 			mp = np;
3363*b30d1939SAndy Fiddaman 		nv_clone(nr,mp,(flags&NV_MOVE)|NV_COMVAR);
3364*b30d1939SAndy Fiddaman 		mp->nvenv = nvenv;
3365*b30d1939SAndy Fiddaman 		if(flags&NV_MOVE)
3366*b30d1939SAndy Fiddaman 		{
3367*b30d1939SAndy Fiddaman 			if(arraynr && !nv_isattr(nr,NV_MINIMAL) && (mp=(Namval_t*)nr->nvenv) && (ap=nv_arrayptr(mp)))
3368*b30d1939SAndy Fiddaman 			{
3369*b30d1939SAndy Fiddaman 				nv_putsub(mp,nr->nvname,0);
3370*b30d1939SAndy Fiddaman 				_nv_unset(mp,0);
3371*b30d1939SAndy Fiddaman 			}
3372*b30d1939SAndy Fiddaman 			nv_delete(nr,(Dt_t*)0,NV_NOFREE);
3373*b30d1939SAndy Fiddaman 		}
3374*b30d1939SAndy Fiddaman 	}
3375*b30d1939SAndy Fiddaman 	else
3376*b30d1939SAndy Fiddaman 	{
3377*b30d1939SAndy Fiddaman 		nv_putval(np,nv_getval(nr),0);
3378*b30d1939SAndy Fiddaman 		if(flags&NV_MOVE)
3379*b30d1939SAndy Fiddaman 		{
3380*b30d1939SAndy Fiddaman 			if(!nv_isattr(nr,NV_MINIMAL) && (mp=(Namval_t*)(nr->nvenv)) && (ap=nv_arrayptr(mp)))
3381*b30d1939SAndy Fiddaman 				ap->nelem--;
3382*b30d1939SAndy Fiddaman 			_nv_unset(nr,0);
3383*b30d1939SAndy Fiddaman 		}
3384*b30d1939SAndy Fiddaman 	}
3385*b30d1939SAndy Fiddaman 	return(1);
3386*b30d1939SAndy Fiddaman }
3387*b30d1939SAndy Fiddaman 
3388*b30d1939SAndy Fiddaman /*
3389*b30d1939SAndy Fiddaman  * Create a reference node from <np> to $np in dictionary <hp>
3390*b30d1939SAndy Fiddaman  */
nv_setref(register Namval_t * np,Dt_t * hp,int flags)3391*b30d1939SAndy Fiddaman void nv_setref(register Namval_t *np, Dt_t *hp, int flags)
3392*b30d1939SAndy Fiddaman {
3393*b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
3394*b30d1939SAndy Fiddaman 	register Namval_t *nq=0, *nr=0;
3395*b30d1939SAndy Fiddaman 	register char	*ep,*cp;
3396*b30d1939SAndy Fiddaman 	Dt_t		*root = shp->last_root, *hpnext=0;
3397*b30d1939SAndy Fiddaman 	Namarr_t	*ap=0;
3398*b30d1939SAndy Fiddaman 	Dt_t		*openmatch;
3399*b30d1939SAndy Fiddaman 	if(nv_isref(np))
3400*b30d1939SAndy Fiddaman 		return;
3401*b30d1939SAndy Fiddaman 	if(nv_isarray(np))
3402*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np));
3403*b30d1939SAndy Fiddaman 	if(!(cp=nv_getval(np)))
3404*b30d1939SAndy Fiddaman 	{
3405*b30d1939SAndy Fiddaman 		_nv_unset(np,0);
3406*b30d1939SAndy Fiddaman 		nv_onattr(np,NV_REF);
3407*b30d1939SAndy Fiddaman 		return;
3408*b30d1939SAndy Fiddaman 	}
3409*b30d1939SAndy Fiddaman 	if((ep = lastdot(cp,0)) && nv_isattr(np,NV_MINIMAL))
3410*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np));
3411*b30d1939SAndy Fiddaman 	if(hp)
3412*b30d1939SAndy Fiddaman 		hpnext = dtvnext(hp);
3413*b30d1939SAndy Fiddaman 	if((nr=nv_open(cp, hp?hp:shp->var_tree, flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
3414*b30d1939SAndy Fiddaman 		nq = nr;
3415*b30d1939SAndy Fiddaman 	else if(hpnext && dtvnext(hpnext)==shp->var_base && (nr=nv_open(cp,hpnext,flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
3416*b30d1939SAndy Fiddaman 		nq = nr;
3417*b30d1939SAndy Fiddaman 	else if((openmatch=shp->openmatch) && hpnext==shp->var_base && (nr=nv_open(cp,hpnext,flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
3418*b30d1939SAndy Fiddaman 		nq = nr;
3419*b30d1939SAndy Fiddaman 	if(nq)
3420*b30d1939SAndy Fiddaman 		hp = shp->last_root;
3421*b30d1939SAndy Fiddaman 	else
3422*b30d1939SAndy Fiddaman 		hp = hp?(openmatch?openmatch:shp->var_base):shp->var_tree;
3423*b30d1939SAndy Fiddaman 	if(nr==np)
3424*b30d1939SAndy Fiddaman 	{
3425*b30d1939SAndy Fiddaman 		if(shp->namespace && nv_dict(shp->namespace)==hp)
3426*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np));
3427*b30d1939SAndy Fiddaman 		/* bind to earlier scope, or add to global scope */
3428*b30d1939SAndy Fiddaman 		if(!(hp=dtvnext(hp)) || (nq=nv_search((char*)np,hp,NV_ADD|HASH_BUCKET))==np)
3429*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np));
3430*b30d1939SAndy Fiddaman 		if(nv_isarray(nq))
3431*b30d1939SAndy Fiddaman 			nv_putsub(nq,(char*)0,ARRAY_UNDEF);
3432*b30d1939SAndy Fiddaman 	}
3433*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3434*b30d1939SAndy Fiddaman 	if(nq && ep && nv_isarray(nq) && !((ap=nv_arrayptr(nq)) && ap->fixed) && !nv_getsub(nq))
3435*b30d1939SAndy Fiddaman #else
3436*b30d1939SAndy Fiddaman 	if(nq && ep && nv_isarray(nq) && !nv_getsub(nq))
3437*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3438*b30d1939SAndy Fiddaman 	{
3439*b30d1939SAndy Fiddaman 		if(!nv_arrayptr(nq))
3440*b30d1939SAndy Fiddaman 		{
3441*b30d1939SAndy Fiddaman 			nv_putsub(nq,"1",ARRAY_FILL);
3442*b30d1939SAndy Fiddaman 			_nv_unset(nq,NV_RDONLY);
3443*b30d1939SAndy Fiddaman 		}
3444*b30d1939SAndy Fiddaman 		nv_endsubscript(nq,ep-1,NV_ARRAY);
3445*b30d1939SAndy Fiddaman 	}
3446*b30d1939SAndy Fiddaman 	if(!nr)
3447*b30d1939SAndy Fiddaman 	{
3448*b30d1939SAndy Fiddaman 		shp->last_root = 0;
3449*b30d1939SAndy Fiddaman 		nr= nq = nv_open(cp, hp, flags);
3450*b30d1939SAndy Fiddaman 		if(shp->last_root)
3451*b30d1939SAndy Fiddaman 			hp = shp->last_root;
3452*b30d1939SAndy Fiddaman 	}
3453*b30d1939SAndy Fiddaman 	if(shp->last_root == shp->var_tree && root!=shp->var_tree)
3454*b30d1939SAndy Fiddaman 	{
3455*b30d1939SAndy Fiddaman 		_nv_unset(np,NV_RDONLY);
3456*b30d1939SAndy Fiddaman 		nv_onattr(np,NV_REF);
3457*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_globalref,nv_name(np));
3458*b30d1939SAndy Fiddaman 	}
3459*b30d1939SAndy Fiddaman 	shp->instance = 1;
3460*b30d1939SAndy Fiddaman 	if(nq && !ep && (ap=nv_arrayptr(nq)) && !(ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN)))
3461*b30d1939SAndy Fiddaman 		ep =  nv_getsub(nq);
3462*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3463*b30d1939SAndy Fiddaman 	if(ep && !(ap && ap->fixed))
3464*b30d1939SAndy Fiddaman #else
3465*b30d1939SAndy Fiddaman 	if(ep)
3466*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3467*b30d1939SAndy Fiddaman 	{
3468*b30d1939SAndy Fiddaman 		/* cause subscript evaluation and return result */
3469*b30d1939SAndy Fiddaman 		if(nv_isarray(nq))
3470*b30d1939SAndy Fiddaman 			ep = nv_getsub(nq);
3471*b30d1939SAndy Fiddaman 		else
3472*b30d1939SAndy Fiddaman 		{
3473*b30d1939SAndy Fiddaman 			int n;
3474*b30d1939SAndy Fiddaman 			ep[n=strlen(ep)-1] = 0;
3475*b30d1939SAndy Fiddaman 			nv_putsub(nr, ep, ARRAY_FILL);
3476*b30d1939SAndy Fiddaman 			ep[n] = ']';
3477*b30d1939SAndy Fiddaman 			if(nq = nv_opensub(nr))
3478*b30d1939SAndy Fiddaman 				ep = 0;
3479*b30d1939SAndy Fiddaman 			else
3480*b30d1939SAndy Fiddaman 				ep = nv_getsub(nq=nr);
3481*b30d1939SAndy Fiddaman 		}
3482*b30d1939SAndy Fiddaman 	}
3483*b30d1939SAndy Fiddaman 	shp->instance = 0;
3484*b30d1939SAndy Fiddaman 	shp->last_root = root;
3485*b30d1939SAndy Fiddaman 	_nv_unset(np,0);
3486*b30d1939SAndy Fiddaman 	nv_delete(np,(Dt_t*)0,0);
3487*b30d1939SAndy Fiddaman 	np->nvalue.nrp = newof(0,struct Namref,1,sizeof(Dtlink_t));
3488*b30d1939SAndy Fiddaman 	np->nvalue.nrp->np = nq;
3489*b30d1939SAndy Fiddaman 	np->nvalue.nrp->root = hp;
3490*b30d1939SAndy Fiddaman 	if(ep)
3491*b30d1939SAndy Fiddaman 	{
3492*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3493*b30d1939SAndy Fiddaman 		if(ap && ap->fixed)
3494*b30d1939SAndy Fiddaman 			np->nvalue.nrp->curi = ARRAY_FIXED|nv_arrfixed(nq,(Sfio_t*)0,1,&np->nvalue.nrp->dim);
3495*b30d1939SAndy Fiddaman 		else
3496*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3497*b30d1939SAndy Fiddaman 			np->nvalue.nrp->sub = strdup(ep);
3498*b30d1939SAndy Fiddaman 	}
3499*b30d1939SAndy Fiddaman 	np->nvalue.nrp->table = shp->last_table;
3500*b30d1939SAndy Fiddaman 	nv_onattr(np,NV_REF|NV_NOFREE);
3501*b30d1939SAndy Fiddaman 	if(!Refdict)
3502*b30d1939SAndy Fiddaman 	{
3503*b30d1939SAndy Fiddaman 		NullNode.nvname = ".deleted";
3504*b30d1939SAndy Fiddaman 		NullNode.nvflag = NV_RDONLY;
3505*b30d1939SAndy Fiddaman 		Refdict = dtopen(&_Refdisc,Dtobag);
3506*b30d1939SAndy Fiddaman 	}
3507*b30d1939SAndy Fiddaman 	dtinsert(Refdict,np->nvalue.nrp);
3508*b30d1939SAndy Fiddaman }
3509*b30d1939SAndy Fiddaman 
3510*b30d1939SAndy Fiddaman /*
3511*b30d1939SAndy Fiddaman  * get the scope corresponding to <index>
3512*b30d1939SAndy Fiddaman  * whence uses the same values as lseeek()
3513*b30d1939SAndy Fiddaman  */
sh_getscope(int index,int whence)3514*b30d1939SAndy Fiddaman Shscope_t *sh_getscope(int index, int whence)
3515*b30d1939SAndy Fiddaman {
3516*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3517*b30d1939SAndy Fiddaman 	register struct sh_scoped *sp, *topmost;
3518*b30d1939SAndy Fiddaman 	if(whence==SEEK_CUR)
3519*b30d1939SAndy Fiddaman 		sp = &shp->st;
3520*b30d1939SAndy Fiddaman 	else
3521*b30d1939SAndy Fiddaman 	{
3522*b30d1939SAndy Fiddaman 		if ((struct sh_scoped*)shp->topscope != shp->st.self)
3523*b30d1939SAndy Fiddaman 			topmost = (struct sh_scoped*)shp->topscope;
3524*b30d1939SAndy Fiddaman 		else
3525*b30d1939SAndy Fiddaman 			topmost = &(shp->st);
3526*b30d1939SAndy Fiddaman 		sp = topmost;
3527*b30d1939SAndy Fiddaman 		if(whence==SEEK_SET)
3528*b30d1939SAndy Fiddaman 		{
3529*b30d1939SAndy Fiddaman 			int n =0;
3530*b30d1939SAndy Fiddaman 			while(sp = sp->prevst)
3531*b30d1939SAndy Fiddaman 				n++;
3532*b30d1939SAndy Fiddaman 			index = n - index;
3533*b30d1939SAndy Fiddaman 			sp = topmost;
3534*b30d1939SAndy Fiddaman 		}
3535*b30d1939SAndy Fiddaman 	}
3536*b30d1939SAndy Fiddaman 	if(index < 0)
3537*b30d1939SAndy Fiddaman 		return((Shscope_t*)0);
3538*b30d1939SAndy Fiddaman 	while(index-- && (sp = sp->prevst));
3539*b30d1939SAndy Fiddaman 	return((Shscope_t*)sp);
3540*b30d1939SAndy Fiddaman }
3541*b30d1939SAndy Fiddaman 
3542*b30d1939SAndy Fiddaman /*
3543*b30d1939SAndy Fiddaman  * make <scoped> the top scope and return previous scope
3544*b30d1939SAndy Fiddaman  */
sh_setscope(Shscope_t * scope)3545*b30d1939SAndy Fiddaman Shscope_t *sh_setscope(Shscope_t *scope)
3546*b30d1939SAndy Fiddaman {
3547*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3548*b30d1939SAndy Fiddaman 	Shscope_t *old = (Shscope_t*)shp->st.self;
3549*b30d1939SAndy Fiddaman 	*shp->st.self = shp->st;
3550*b30d1939SAndy Fiddaman 	shp->st = *((struct sh_scoped*)scope);
3551*b30d1939SAndy Fiddaman 	shp->var_tree = scope->var_tree;
3552*b30d1939SAndy Fiddaman 	SH_PATHNAMENOD->nvalue.cp = shp->st.filename;
3553*b30d1939SAndy Fiddaman 	SH_FUNNAMENOD->nvalue.cp = shp->st.funname;
3554*b30d1939SAndy Fiddaman 	return(old);
3555*b30d1939SAndy Fiddaman }
3556*b30d1939SAndy Fiddaman 
sh_unscope(Shell_t * shp)3557*b30d1939SAndy Fiddaman void sh_unscope(Shell_t *shp)
3558*b30d1939SAndy Fiddaman {
3559*b30d1939SAndy Fiddaman 	register Dt_t *root = shp->var_tree;
3560*b30d1939SAndy Fiddaman 	register Dt_t *dp = dtview(root,(Dt_t*)0);
3561*b30d1939SAndy Fiddaman 	if(dp)
3562*b30d1939SAndy Fiddaman 	{
3563*b30d1939SAndy Fiddaman 		table_unset(shp,root,NV_RDONLY|NV_NOSCOPE,dp);
3564*b30d1939SAndy Fiddaman 		if(shp->st.real_fun  && dp==shp->st.real_fun->sdict)
3565*b30d1939SAndy Fiddaman 		{
3566*b30d1939SAndy Fiddaman 			dp = dtview(dp,(Dt_t*)0);
3567*b30d1939SAndy Fiddaman 			shp->st.real_fun->sdict->view = dp;
3568*b30d1939SAndy Fiddaman 		}
3569*b30d1939SAndy Fiddaman 		shp->var_tree=dp;
3570*b30d1939SAndy Fiddaman 		dtclose(root);
3571*b30d1939SAndy Fiddaman 	}
3572*b30d1939SAndy Fiddaman }
3573*b30d1939SAndy Fiddaman 
3574*b30d1939SAndy Fiddaman /*
3575*b30d1939SAndy Fiddaman  * The inverse of creating a reference node
3576*b30d1939SAndy Fiddaman  */
nv_unref(register Namval_t * np)3577*b30d1939SAndy Fiddaman void nv_unref(register Namval_t *np)
3578*b30d1939SAndy Fiddaman {
3579*b30d1939SAndy Fiddaman 	Namval_t *nq;
3580*b30d1939SAndy Fiddaman 	if(!nv_isref(np))
3581*b30d1939SAndy Fiddaman 		return;
3582*b30d1939SAndy Fiddaman 	nv_offattr(np,NV_NOFREE|NV_REF);
3583*b30d1939SAndy Fiddaman 	if(!np->nvalue.nrp)
3584*b30d1939SAndy Fiddaman 		return;
3585*b30d1939SAndy Fiddaman 	nq = nv_refnode(np);
3586*b30d1939SAndy Fiddaman 	if(Refdict)
3587*b30d1939SAndy Fiddaman 	{
3588*b30d1939SAndy Fiddaman 		if(np->nvalue.nrp->sub)
3589*b30d1939SAndy Fiddaman 			free(np->nvalue.nrp->sub);
3590*b30d1939SAndy Fiddaman 		dtdelete(Refdict,(void*)np->nvalue.nrp);
3591*b30d1939SAndy Fiddaman 	}
3592*b30d1939SAndy Fiddaman 	free((void*)np->nvalue.nrp);
3593*b30d1939SAndy Fiddaman 	np->nvalue.cp = strdup(nv_name(nq));
3594*b30d1939SAndy Fiddaman #if SHOPT_OPTIMIZE
3595*b30d1939SAndy Fiddaman 	{
3596*b30d1939SAndy Fiddaman 		Namfun_t *fp;
3597*b30d1939SAndy Fiddaman 		for(fp=nq->nvfun; fp; fp = fp->next)
3598*b30d1939SAndy Fiddaman 		{
3599*b30d1939SAndy Fiddaman 			if(fp->disc== &optimize_disc)
3600*b30d1939SAndy Fiddaman 			{
3601*b30d1939SAndy Fiddaman 				optimize_clear(nq,fp);
3602*b30d1939SAndy Fiddaman 				return;
3603*b30d1939SAndy Fiddaman 			}
3604*b30d1939SAndy Fiddaman 		}
3605*b30d1939SAndy Fiddaman 	}
3606*b30d1939SAndy Fiddaman #endif
3607*b30d1939SAndy Fiddaman }
3608*b30d1939SAndy Fiddaman 
3609*b30d1939SAndy Fiddaman /*
3610*b30d1939SAndy Fiddaman  * These following are for binary compatibility with the old hash library
3611*b30d1939SAndy Fiddaman  * They will be removed someday
3612*b30d1939SAndy Fiddaman  */
3613*b30d1939SAndy Fiddaman 
3614*b30d1939SAndy Fiddaman #if defined(__IMPORT__) && defined(__EXPORT__)
3615*b30d1939SAndy Fiddaman #   define extern __EXPORT__
3616*b30d1939SAndy Fiddaman #endif
3617*b30d1939SAndy Fiddaman 
3618*b30d1939SAndy Fiddaman #undef	hashscope
3619*b30d1939SAndy Fiddaman 
hashscope(Dt_t * root)3620*b30d1939SAndy Fiddaman extern Dt_t *hashscope(Dt_t *root)
3621*b30d1939SAndy Fiddaman {
3622*b30d1939SAndy Fiddaman 	return(dtvnext(root));
3623*b30d1939SAndy Fiddaman }
3624*b30d1939SAndy Fiddaman 
3625*b30d1939SAndy Fiddaman #undef	hashfree
3626*b30d1939SAndy Fiddaman 
hashfree(Dt_t * root)3627*b30d1939SAndy Fiddaman extern Dt_t	*hashfree(Dt_t *root)
3628*b30d1939SAndy Fiddaman {
3629*b30d1939SAndy Fiddaman 	Dt_t *dp = dtvnext(root);
3630*b30d1939SAndy Fiddaman 	dtclose(root);
3631*b30d1939SAndy Fiddaman 	return(dp);
3632*b30d1939SAndy Fiddaman }
3633*b30d1939SAndy Fiddaman 
3634*b30d1939SAndy Fiddaman #undef	hashname
3635*b30d1939SAndy Fiddaman 
hashname(void * obj)3636*b30d1939SAndy Fiddaman extern char	*hashname(void *obj)
3637*b30d1939SAndy Fiddaman {
3638*b30d1939SAndy Fiddaman 	Namval_t *np = (Namval_t*)obj;
3639*b30d1939SAndy Fiddaman 	return(np->nvname);
3640*b30d1939SAndy Fiddaman }
3641*b30d1939SAndy Fiddaman 
3642*b30d1939SAndy Fiddaman #undef	hashlook
3643*b30d1939SAndy Fiddaman 
hashlook(Dt_t * root,const char * name,int mode,int size)3644*b30d1939SAndy Fiddaman extern void *hashlook(Dt_t *root, const char *name, int mode,int size)
3645*b30d1939SAndy Fiddaman {
3646*b30d1939SAndy Fiddaman 	NOT_USED(size);
3647*b30d1939SAndy Fiddaman 	return((void*)nv_search(name,root,mode));
3648*b30d1939SAndy Fiddaman }
3649*b30d1939SAndy Fiddaman 
nv_name(register Namval_t * np)3650*b30d1939SAndy Fiddaman char *nv_name(register Namval_t *np)
3651*b30d1939SAndy Fiddaman {
3652*b30d1939SAndy Fiddaman 	Shell_t	 *shp = sh_getinterp();
3653*b30d1939SAndy Fiddaman 	register Namval_t *table;
3654*b30d1939SAndy Fiddaman 	register Namfun_t *fp;
3655*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3656*b30d1939SAndy Fiddaman 	Namarr_t	*ap;
3657*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3658*b30d1939SAndy Fiddaman 	char *cp;
3659*b30d1939SAndy Fiddaman 	if(is_abuiltin(np) || is_afunction(np))
3660*b30d1939SAndy Fiddaman 	{
3661*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
3662*b30d1939SAndy Fiddaman 		if(shp->namespace && is_afunction(np))
3663*b30d1939SAndy Fiddaman 		{
3664*b30d1939SAndy Fiddaman 			char *name = nv_name(shp->namespace);
3665*b30d1939SAndy Fiddaman 			int n = strlen(name);
3666*b30d1939SAndy Fiddaman 			if(memcmp(np->nvname,name,n)==0 && np->nvname[n]=='.')
3667*b30d1939SAndy Fiddaman 				return(np->nvname+n+1);
3668*b30d1939SAndy Fiddaman 		}
3669*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
3670*b30d1939SAndy Fiddaman 		return(np->nvname);
3671*b30d1939SAndy Fiddaman 	}
3672*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3673*b30d1939SAndy Fiddaman 	ap = nv_arrayptr(np);
3674*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3675*b30d1939SAndy Fiddaman 	if(!nv_isattr(np,NV_MINIMAL|NV_EXPORT) && np->nvenv)
3676*b30d1939SAndy Fiddaman 	{
3677*b30d1939SAndy Fiddaman 		Namval_t *nq= shp->last_table, *mp= (Namval_t*)np->nvenv;
3678*b30d1939SAndy Fiddaman 		if(np==shp->last_table)
3679*b30d1939SAndy Fiddaman 			shp->last_table = 0;
3680*b30d1939SAndy Fiddaman 		if(nv_isarray(mp))
3681*b30d1939SAndy Fiddaman 			sfprintf(shp->strbuf,"%s[%s]",nv_name(mp),np->nvname);
3682*b30d1939SAndy Fiddaman 		else
3683*b30d1939SAndy Fiddaman 			sfprintf(shp->strbuf,"%s.%s",nv_name(mp),np->nvname);
3684*b30d1939SAndy Fiddaman 		shp->last_table = nq;
3685*b30d1939SAndy Fiddaman 		return(sfstruse(shp->strbuf));
3686*b30d1939SAndy Fiddaman 	}
3687*b30d1939SAndy Fiddaman 	if(nv_istable(np))
3688*b30d1939SAndy Fiddaman #if 1
3689*b30d1939SAndy Fiddaman 		shp->last_table = nv_parent(np);
3690*b30d1939SAndy Fiddaman #else
3691*b30d1939SAndy Fiddaman 		shp->last_table = nv_create(np,0, NV_LAST,(Namfun_t*)0);
3692*b30d1939SAndy Fiddaman #endif
3693*b30d1939SAndy Fiddaman 	else if(!nv_isref(np))
3694*b30d1939SAndy Fiddaman 	{
3695*b30d1939SAndy Fiddaman 		for(fp= np->nvfun ; fp; fp=fp->next)
3696*b30d1939SAndy Fiddaman 		if(fp->disc && fp->disc->namef)
3697*b30d1939SAndy Fiddaman 		{
3698*b30d1939SAndy Fiddaman 			if(np==shp->last_table)
3699*b30d1939SAndy Fiddaman 				shp->last_table = 0;
3700*b30d1939SAndy Fiddaman 			return((*fp->disc->namef)(np,fp));
3701*b30d1939SAndy Fiddaman 		}
3702*b30d1939SAndy Fiddaman 	}
3703*b30d1939SAndy Fiddaman 	if(!(table=shp->last_table) || *np->nvname=='.' || table==shp->namespace || np==table)
3704*b30d1939SAndy Fiddaman 	{
3705*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3706*b30d1939SAndy Fiddaman 		if(!ap || !ap->fixed || (ap->nelem&ARRAY_UNDEF))
3707*b30d1939SAndy Fiddaman 			return(np->nvname);
3708*b30d1939SAndy Fiddaman 		table = 0;
3709*b30d1939SAndy Fiddaman #else
3710*b30d1939SAndy Fiddaman 		return(np->nvname);
3711*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3712*b30d1939SAndy Fiddaman 	}
3713*b30d1939SAndy Fiddaman 	if(table)
3714*b30d1939SAndy Fiddaman 	{
3715*b30d1939SAndy Fiddaman 		cp = nv_name(table);
3716*b30d1939SAndy Fiddaman 		sfprintf(shp->strbuf,"%s.%s",cp,np->nvname);
3717*b30d1939SAndy Fiddaman 	}
3718*b30d1939SAndy Fiddaman 	else
3719*b30d1939SAndy Fiddaman 		sfprintf(shp->strbuf,"%s",np->nvname);
3720*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3721*b30d1939SAndy Fiddaman 	if(ap && ap->fixed)
3722*b30d1939SAndy Fiddaman 		nv_arrfixed(np,shp->strbuf,1,(char*)0);
3723*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3724*b30d1939SAndy Fiddaman 	return(sfstruse(shp->strbuf));
3725*b30d1939SAndy Fiddaman }
3726*b30d1939SAndy Fiddaman 
nv_lastdict(void)3727*b30d1939SAndy Fiddaman Namval_t *nv_lastdict(void)
3728*b30d1939SAndy Fiddaman {
3729*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3730*b30d1939SAndy Fiddaman 	return(shp->last_table);
3731*b30d1939SAndy Fiddaman }
3732*b30d1939SAndy Fiddaman 
3733*b30d1939SAndy Fiddaman #undef nv_context
3734*b30d1939SAndy Fiddaman /*
3735*b30d1939SAndy Fiddaman  * returns the data context for a builtin
3736*b30d1939SAndy Fiddaman  */
nv_context(Namval_t * np)3737*b30d1939SAndy Fiddaman void *nv_context(Namval_t *np)
3738*b30d1939SAndy Fiddaman {
3739*b30d1939SAndy Fiddaman 	return((void*)np->nvfun);
3740*b30d1939SAndy Fiddaman }
3741*b30d1939SAndy Fiddaman 
3742*b30d1939SAndy Fiddaman #define DISABLE /* proto workaround */
3743*b30d1939SAndy Fiddaman 
DISABLE(register Namval_t * np)3744*b30d1939SAndy Fiddaman int nv_isnull DISABLE (register Namval_t *np)
3745*b30d1939SAndy Fiddaman {
3746*b30d1939SAndy Fiddaman 	return(nv_isnull(np));
3747*b30d1939SAndy Fiddaman }
3748*b30d1939SAndy Fiddaman 
3749*b30d1939SAndy Fiddaman #undef nv_setsize
nv_setsize(register Namval_t * np,int size)3750*b30d1939SAndy Fiddaman int nv_setsize(register Namval_t *np, int size)
3751*b30d1939SAndy Fiddaman {
3752*b30d1939SAndy Fiddaman 	int oldsize = nv_size(np);
3753*b30d1939SAndy Fiddaman 	if(size>=0)
3754*b30d1939SAndy Fiddaman 		np->nvsize = size;
3755*b30d1939SAndy Fiddaman 	return(oldsize);
3756*b30d1939SAndy Fiddaman }
3757*b30d1939SAndy Fiddaman 
nv_shell(Namval_t * np)3758*b30d1939SAndy Fiddaman Shell_t	*nv_shell(Namval_t *np)
3759*b30d1939SAndy Fiddaman {
3760*b30d1939SAndy Fiddaman 	Namfun_t *fp;
3761*b30d1939SAndy Fiddaman 	for(fp=np->nvfun;fp;fp=fp->next)
3762*b30d1939SAndy Fiddaman 	{
3763*b30d1939SAndy Fiddaman 		if(!fp->disc)
3764*b30d1939SAndy Fiddaman 			return((Shell_t*)fp->last);
3765*b30d1939SAndy Fiddaman 	}
3766*b30d1939SAndy Fiddaman 	return(0);
3767*b30d1939SAndy Fiddaman }
3768*b30d1939SAndy Fiddaman 
3769*b30d1939SAndy Fiddaman #undef nv_unset
3770*b30d1939SAndy Fiddaman 
nv_unset(register Namval_t * np)3771*b30d1939SAndy Fiddaman void	nv_unset(register Namval_t *np)
3772*b30d1939SAndy Fiddaman {
3773*b30d1939SAndy Fiddaman 	_nv_unset(np,0);
3774*b30d1939SAndy Fiddaman 	return;
3775*b30d1939SAndy Fiddaman }
3776