xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/name.c (revision b30d1939)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                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)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * AT&T Labs
23da2e3ebdSchin  *
24da2e3ebdSchin  */
25*b30d1939SAndy Fiddaman /*
26*b30d1939SAndy Fiddaman  * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
27*b30d1939SAndy Fiddaman  */
28da2e3ebdSchin 
29da2e3ebdSchin #define putenv	___putenv
30da2e3ebdSchin 
31da2e3ebdSchin #include	"defs.h"
32da2e3ebdSchin #include	"variables.h"
33da2e3ebdSchin #include	"path.h"
34da2e3ebdSchin #include	"lexstates.h"
35da2e3ebdSchin #include	"timeout.h"
36da2e3ebdSchin #include	"FEATURE/externs"
37da2e3ebdSchin #include	"streval.h"
38da2e3ebdSchin 
397c2fbfb3SApril Chin #define NVCACHE		8	/* must be a power of 2 */
407c2fbfb3SApril Chin #define Empty	((char*)(e_sptbnl+3))
41da2e3ebdSchin 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 };
49da2e3ebdSchin 
50da2e3ebdSchin #if !_lib_pathnative && _lib_uwin_path
51da2e3ebdSchin 
52da2e3ebdSchin #define _lib_pathnative		1
53da2e3ebdSchin 
54da2e3ebdSchin extern int	uwin_path(const char*, char*, int);
55da2e3ebdSchin 
56da2e3ebdSchin size_t
pathnative(const char * path,char * buf,size_t siz)57da2e3ebdSchin pathnative(const char* path, char* buf, size_t siz)
58da2e3ebdSchin {
59da2e3ebdSchin 	return uwin_path(path, buf, siz);
60da2e3ebdSchin }
61da2e3ebdSchin 
62da2e3ebdSchin #endif /* _lib_pathnative */
63da2e3ebdSchin 
64da2e3ebdSchin static void	attstore(Namval_t*,void*);
65da2e3ebdSchin #ifndef _ENV_H
663e14f97fSRoger A. Faulkner     static void	pushnam(Namval_t*,void*);
673e14f97fSRoger A. Faulkner     static char	*staknam(Namval_t*, char*);
68da2e3ebdSchin #endif
69da2e3ebdSchin static void	rightjust(char*, int, int);
707c2fbfb3SApril Chin static char	*lastdot(char*, int);
71da2e3ebdSchin 
72da2e3ebdSchin struct adata
73da2e3ebdSchin {
747c2fbfb3SApril Chin 	Shell_t		*sh;
757c2fbfb3SApril Chin 	Namval_t	*tp;
76*b30d1939SAndy Fiddaman 	char		*mapname;
777c2fbfb3SApril Chin 	char		**argnam;
787c2fbfb3SApril Chin 	int		attsize;
797c2fbfb3SApril Chin 	char		*attval;
80da2e3ebdSchin };
81da2e3ebdSchin 
827c2fbfb3SApril Chin #if SHOPT_TYPEDEF
837c2fbfb3SApril Chin     struct sh_type
847c2fbfb3SApril Chin     {
857c2fbfb3SApril Chin 	void		*previous;
867c2fbfb3SApril Chin 	Namval_t	**nodes;
877c2fbfb3SApril Chin 	Namval_t	*rp;
887c2fbfb3SApril Chin 	short		numnodes;
897c2fbfb3SApril Chin 	short		maxnodes;
907c2fbfb3SApril Chin     };
917c2fbfb3SApril Chin #endif /*SHOPT_TYPEDEF */
927c2fbfb3SApril Chin 
937c2fbfb3SApril Chin #if NVCACHE
947c2fbfb3SApril Chin     struct Namcache
957c2fbfb3SApril Chin     {
967c2fbfb3SApril Chin 	struct Cache_entry
977c2fbfb3SApril Chin 	{
987c2fbfb3SApril Chin 		Dt_t		*root;
9934f9b3eeSRoland Mainz 		Dt_t		*last_root;
1007c2fbfb3SApril Chin 		char		*name;
1017c2fbfb3SApril Chin 		Namval_t	*np;
1027c2fbfb3SApril Chin 		Namval_t	*last_table;
103*b30d1939SAndy Fiddaman 		Namval_t	*namespace;
1047c2fbfb3SApril Chin 		int		flags;
1057c2fbfb3SApril Chin 		short		size;
1067c2fbfb3SApril Chin 		short		len;
1077c2fbfb3SApril Chin 	} entries[NVCACHE];
1087c2fbfb3SApril Chin 	short		index;
1097c2fbfb3SApril Chin 	short		ok;
1107c2fbfb3SApril Chin     };
1117c2fbfb3SApril Chin     static struct Namcache nvcache;
1127c2fbfb3SApril Chin #endif
1137c2fbfb3SApril Chin 
114da2e3ebdSchin char		nv_local = 0;
115da2e3ebdSchin #ifndef _ENV_H
116da2e3ebdSchin static void(*nullscan)(Namval_t*,void*);
117da2e3ebdSchin #endif
118da2e3ebdSchin 
119da2e3ebdSchin #if ( SFIO_VERSION  <= 20010201L )
120da2e3ebdSchin #   define _data        data
121da2e3ebdSchin #endif
122da2e3ebdSchin 
123da2e3ebdSchin #if !SHOPT_MULTIBYTE
124da2e3ebdSchin #   define mbchar(p)       (*(unsigned char*)p++)
125da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
126da2e3ebdSchin 
127da2e3ebdSchin /* ========	name value pair routines	======== */
128da2e3ebdSchin 
129da2e3ebdSchin #include	"shnodes.h"
130da2e3ebdSchin #include	"builtins.h"
131da2e3ebdSchin 
getbuf(size_t len)132da2e3ebdSchin static char *getbuf(size_t len)
133da2e3ebdSchin {
134da2e3ebdSchin 	static char *buf;
135da2e3ebdSchin 	static size_t buflen;
136da2e3ebdSchin 	if(buflen < len)
137da2e3ebdSchin 	{
138da2e3ebdSchin 		if(buflen==0)
139da2e3ebdSchin 			buf = (char*)malloc(len);
140da2e3ebdSchin 		else
141da2e3ebdSchin 			buf = (char*)realloc(buf,len);
142da2e3ebdSchin 		buflen = len;
143da2e3ebdSchin 	}
144da2e3ebdSchin 	return(buf);
145da2e3ebdSchin }
146da2e3ebdSchin 
147da2e3ebdSchin #ifdef _ENV_H
sh_envput(Env_t * ep,Namval_t * np)148da2e3ebdSchin void sh_envput(Env_t* ep,Namval_t *np)
149da2e3ebdSchin {
150da2e3ebdSchin 	int offset = staktell();
151da2e3ebdSchin 	Namarr_t *ap = nv_arrayptr(np);
152da2e3ebdSchin 	char *val;
153da2e3ebdSchin 	if(ap)
154da2e3ebdSchin 	{
155da2e3ebdSchin 		if(ap->nelem&ARRAY_UNDEF)
156da2e3ebdSchin 			nv_putsub(np,"0",0L);
157da2e3ebdSchin 		else if(!(val=nv_getsub(np)) || strcmp(val,"0"))
158da2e3ebdSchin 			return;
159da2e3ebdSchin 	}
160da2e3ebdSchin 	if(!(val = nv_getval(np)))
161da2e3ebdSchin 		return;
162da2e3ebdSchin 	stakputs(nv_name(np));
163da2e3ebdSchin 	stakputc('=');
164da2e3ebdSchin 	stakputs(val);
165da2e3ebdSchin 	stakseek(offset);
166da2e3ebdSchin 	env_add(ep,stakptr(offset),ENV_STRDUP);
167da2e3ebdSchin }
168da2e3ebdSchin #endif
169da2e3ebdSchin 
170da2e3ebdSchin /*
171da2e3ebdSchin  * output variable name in format for re-input
172da2e3ebdSchin  */
nv_outname(Sfio_t * out,char * name,int len)173da2e3ebdSchin void nv_outname(Sfio_t *out, char *name, int len)
174da2e3ebdSchin {
175da2e3ebdSchin 	const char *cp=name, *sp;
176da2e3ebdSchin 	int c, offset = staktell();
177da2e3ebdSchin 	while(sp= strchr(cp,'['))
178da2e3ebdSchin 	{
179da2e3ebdSchin 		if(len>0 && cp+len <= sp)
180da2e3ebdSchin 			break;
181da2e3ebdSchin 		sfwrite(out,cp,++sp-cp);
182da2e3ebdSchin 		stakseek(offset);
1837c2fbfb3SApril Chin 		while(c= *sp++)
184da2e3ebdSchin 		{
185da2e3ebdSchin 			if(c==']')
186da2e3ebdSchin 				break;
187da2e3ebdSchin 			else if(c=='\\')
188da2e3ebdSchin 			{
189da2e3ebdSchin 				if(*sp=='[' || *sp==']' || *sp=='\\')
190da2e3ebdSchin 					c = *sp++;
191da2e3ebdSchin 			}
192da2e3ebdSchin 			stakputc(c);
193da2e3ebdSchin 		}
194da2e3ebdSchin 		stakputc(0);
195da2e3ebdSchin 		sfputr(out,sh_fmtq(stakptr(offset)),-1);
196da2e3ebdSchin 		if(len>0)
197da2e3ebdSchin 		{
198da2e3ebdSchin 			sfputc(out,']');
199da2e3ebdSchin 			return;
200da2e3ebdSchin 		}
2017c2fbfb3SApril Chin 		cp = sp-1;
202da2e3ebdSchin 	}
203da2e3ebdSchin 	if(*cp)
204da2e3ebdSchin 	{
205da2e3ebdSchin 		if(len>0)
206da2e3ebdSchin 			sfwrite(out,cp,len);
207da2e3ebdSchin 		else
208da2e3ebdSchin 			sfputr(out,cp,-1);
209da2e3ebdSchin 	}
210da2e3ebdSchin 	stakseek(offset);
211da2e3ebdSchin }
212da2e3ebdSchin 
2137c2fbfb3SApril Chin #if SHOPT_TYPEDEF
nv_addnode(Namval_t * np,int remove)2147c2fbfb3SApril Chin Namval_t *nv_addnode(Namval_t* np, int remove)
2157c2fbfb3SApril Chin {
216*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
217*b30d1939SAndy Fiddaman 	register struct sh_type	*sp = (struct sh_type*)shp->mktype;
2187c2fbfb3SApril Chin 	register int		i;
2197c2fbfb3SApril Chin 	register char		*name=0;
220*b30d1939SAndy Fiddaman 	if(sp->numnodes==0 && !nv_isnull(np) && shp->last_table)
2217c2fbfb3SApril Chin 	{
2227c2fbfb3SApril Chin 		/* could be an redefine */
223*b30d1939SAndy Fiddaman 		Dt_t *root = nv_dict(shp->last_table);
2247c2fbfb3SApril Chin 		sp->rp = np;
2257c2fbfb3SApril Chin 		nv_delete(np,root,NV_NOFREE);
2267c2fbfb3SApril Chin 		np = nv_search(sp->rp->nvname,root,NV_ADD);
2277c2fbfb3SApril Chin 	}
2287c2fbfb3SApril Chin 	if(sp->numnodes && memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1))
2297c2fbfb3SApril Chin 	{
2307c2fbfb3SApril Chin 		name = (sp->nodes[0])->nvname;
2317c2fbfb3SApril Chin 		i = strlen(name);
2327c2fbfb3SApril Chin 		if(memcmp(np->nvname,name,i))
2337c2fbfb3SApril Chin 			return(np);
2347c2fbfb3SApril Chin 	}
2357c2fbfb3SApril Chin 	if(sp->rp && sp->numnodes)
2367c2fbfb3SApril Chin 	{
2377c2fbfb3SApril Chin 		/* check for a redefine */
2387c2fbfb3SApril Chin 		if(name && np->nvname[i]=='.' && np->nvname[i+1]=='_' && np->nvname[i+2]==0)
2397c2fbfb3SApril Chin 			sp->rp = 0;
2407c2fbfb3SApril Chin 		else
2417c2fbfb3SApril Chin 		{
242*b30d1939SAndy Fiddaman 			Dt_t *root = nv_dict(shp->last_table);
2437c2fbfb3SApril Chin 			nv_delete(sp->nodes[0],root,NV_NOFREE);
2447c2fbfb3SApril Chin 			dtinsert(root,sp->rp);
2457c2fbfb3SApril Chin 			errormsg(SH_DICT,ERROR_exit(1),e_redef,sp->nodes[0]->nvname);
2467c2fbfb3SApril Chin 		}
2477c2fbfb3SApril Chin 	}
2487c2fbfb3SApril Chin 	for(i=0; i < sp->numnodes; i++)
2497c2fbfb3SApril Chin 	{
2507c2fbfb3SApril Chin 		if(np == sp->nodes[i])
2517c2fbfb3SApril Chin 		{
2527c2fbfb3SApril Chin 			if(remove)
2537c2fbfb3SApril Chin 			{
2547c2fbfb3SApril Chin 				while(++i < sp->numnodes)
2557c2fbfb3SApril Chin 					sp->nodes[i-1] = sp->nodes[i];
2567c2fbfb3SApril Chin 				sp->numnodes--;
2577c2fbfb3SApril Chin 			}
2587c2fbfb3SApril Chin 			return(np);
2597c2fbfb3SApril Chin 		}
2607c2fbfb3SApril Chin 	}
2617c2fbfb3SApril Chin 	if(remove)
2627c2fbfb3SApril Chin 		return(np);
2637c2fbfb3SApril Chin 	if(sp->numnodes==sp->maxnodes)
2647c2fbfb3SApril Chin 	{
2657c2fbfb3SApril Chin 		sp->maxnodes += 20;
2667c2fbfb3SApril Chin 		sp->nodes = (Namval_t**)realloc(sp->nodes,sizeof(Namval_t*)*sp->maxnodes);
2677c2fbfb3SApril Chin 	}
2687c2fbfb3SApril Chin 	sp->nodes[sp->numnodes++] = np;
2697c2fbfb3SApril Chin 	return(np);
2707c2fbfb3SApril Chin }
2717c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
2727c2fbfb3SApril Chin 
2737c2fbfb3SApril Chin /*
2747c2fbfb3SApril Chin  * given a list of assignments, determine <name> is on the list
2757c2fbfb3SApril Chin    returns a pointer to the argnod on the list or NULL
2767c2fbfb3SApril Chin  */
nv_onlist(struct argnod * arg,const char * name)2777c2fbfb3SApril Chin struct argnod *nv_onlist(struct argnod *arg, const char *name)
2787c2fbfb3SApril Chin {
2797c2fbfb3SApril Chin 	char *cp;
2807c2fbfb3SApril Chin 	int len = strlen(name);
2817c2fbfb3SApril Chin 	for(;arg; arg=arg->argnxt.ap)
2827c2fbfb3SApril Chin 	{
2837c2fbfb3SApril Chin 		if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE)))
2847c2fbfb3SApril Chin 			cp = ((struct fornod*)arg->argchn.ap)->fornam;
2857c2fbfb3SApril Chin 		else
2867c2fbfb3SApril Chin 			cp = arg->argval;
2877c2fbfb3SApril Chin 		if(memcmp(cp,name,len)==0 && (cp[len]==0 || cp[len]=='='))
2887c2fbfb3SApril Chin 			return(arg);
2897c2fbfb3SApril Chin 	}
2907c2fbfb3SApril Chin 	return(0);
2917c2fbfb3SApril Chin }
2927c2fbfb3SApril Chin 
293da2e3ebdSchin /*
294da2e3ebdSchin  * Perform parameter assignment for a linked list of parameters
295da2e3ebdSchin  * <flags> contains attributes for the parameters
296da2e3ebdSchin  */
nv_setlist(register struct argnod * arg,register int flags,Namval_t * typ)29734f9b3eeSRoland Mainz void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
298da2e3ebdSchin {
299*b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
300da2e3ebdSchin 	register char	*cp;
3017c2fbfb3SApril Chin 	register Namval_t *np, *mp;
3027c2fbfb3SApril Chin 	char		*trap=shp->st.trap[SH_DEBUGTRAP];
3037c2fbfb3SApril Chin 	char		*prefix = shp->prefix;
304da2e3ebdSchin 	int		traceon = (sh_isoption(SH_XTRACE)!=0);
305da2e3ebdSchin 	int		array = (flags&(NV_ARRAY|NV_IARRAY));
3067c2fbfb3SApril Chin 	Namarr_t	*ap;
3077c2fbfb3SApril Chin 	Namval_t	node;
3087c2fbfb3SApril Chin 	struct Namref	nr;
3097c2fbfb3SApril Chin #if SHOPT_TYPEDEF
3107c2fbfb3SApril Chin 	int		maketype = flags&NV_TYPE;
3117c2fbfb3SApril Chin 	struct sh_type	shtp;
3127c2fbfb3SApril Chin 	if(maketype)
3137c2fbfb3SApril Chin 	{
3147c2fbfb3SApril Chin 		shtp.previous = shp->mktype;
3157c2fbfb3SApril Chin 		shp->mktype=(void*)&shtp;
3167c2fbfb3SApril Chin 		shtp.numnodes=0;
3177c2fbfb3SApril Chin 		shtp.maxnodes = 20;
3187c2fbfb3SApril Chin 		shtp.rp = 0;
3197c2fbfb3SApril Chin 		shtp.nodes =(Namval_t**)malloc(shtp.maxnodes*sizeof(Namval_t*));
3207c2fbfb3SApril Chin 	}
3217c2fbfb3SApril Chin #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 */
3267c2fbfb3SApril Chin 	flags &= ~(NV_TYPE|NV_ARRAY|NV_IARRAY);
327da2e3ebdSchin 	if(sh_isoption(SH_ALLEXPORT))
328da2e3ebdSchin 		flags |= NV_EXPORT;
3297c2fbfb3SApril Chin 	if(shp->prefix)
330da2e3ebdSchin 	{
331da2e3ebdSchin 		flags &= ~(NV_IDENT|NV_EXPORT);
332da2e3ebdSchin 		flags |= NV_VARNAME;
333da2e3ebdSchin 	}
334*b30d1939SAndy Fiddaman 	else
335*b30d1939SAndy Fiddaman 		shp->prefix_root = shp->first_root = 0;
336da2e3ebdSchin 	for(;arg; arg=arg->argnxt.ap)
337da2e3ebdSchin 	{
3387c2fbfb3SApril Chin 		shp->used_pos = 0;
339da2e3ebdSchin 		if(arg->argflag&ARG_MAC)
3407c2fbfb3SApril Chin 		{
3417c2fbfb3SApril Chin 			shp->prefix = 0;
3427c2fbfb3SApril Chin 			cp = sh_mactrim(shp,arg->argval,(flags&NV_NOREF)?-3:-1);
3437c2fbfb3SApril Chin 			shp->prefix = prefix;
3447c2fbfb3SApril Chin 		}
345da2e3ebdSchin 		else
346da2e3ebdSchin 		{
347da2e3ebdSchin 			stakseek(0);
3487c2fbfb3SApril Chin 			if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE)))
349da2e3ebdSchin 			{
350da2e3ebdSchin 				int flag = (NV_VARNAME|NV_ARRAY|NV_ASSIGN);
3517c2fbfb3SApril Chin 				int sub=0;
352da2e3ebdSchin 				struct fornod *fp=(struct fornod*)arg->argchn.ap;
353da2e3ebdSchin 				register Shnode_t *tp=fp->fortre;
354*b30d1939SAndy Fiddaman 				flag |= (flags&(NV_NOSCOPE|NV_STATIC|NV_FARRAY));
355da2e3ebdSchin 				if(arg->argflag&ARG_QUOTED)
3567c2fbfb3SApril Chin 					cp = sh_mactrim(shp,fp->fornam,-1);
357da2e3ebdSchin 				else
358da2e3ebdSchin 					cp = fp->fornam;
3597c2fbfb3SApril Chin 				error_info.line = fp->fortyp-shp->st.firstline;
36034f9b3eeSRoland Mainz 				if(!array && tp->tre.tretyp!=TLST && tp->com.comset && !tp->com.comarg && tp->com.comset->argval[0]==0 && tp->com.comset->argval[1]=='[')
36134f9b3eeSRoland Mainz 					array |= (tp->com.comset->argflag&ARG_MESSAGE)?NV_IARRAY:NV_ARRAY;
362da2e3ebdSchin 				if(prefix && tp->com.comset && *cp=='[')
363da2e3ebdSchin 				{
3647c2fbfb3SApril Chin 					shp->prefix = 0;
365*b30d1939SAndy Fiddaman 					np = nv_open(prefix,shp->last_root,flag);
3667c2fbfb3SApril Chin 					shp->prefix = prefix;
367da2e3ebdSchin 					if(np)
368da2e3ebdSchin 					{
3697c2fbfb3SApril Chin 						if(nv_isvtree(np) && !nv_isarray(np))
370da2e3ebdSchin 						{
371da2e3ebdSchin 							stakputc('.');
372da2e3ebdSchin 							stakputs(cp);
373da2e3ebdSchin 							cp = stakfreeze(1);
374da2e3ebdSchin 						}
375da2e3ebdSchin 						nv_close(np);
376da2e3ebdSchin 					}
377da2e3ebdSchin 				}
3787c2fbfb3SApril Chin 				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))
4067c2fbfb3SApril Chin #if SHOPT_TYPEDEF
4077c2fbfb3SApril Chin 					goto check_type;
4087c2fbfb3SApril Chin #else
4097c2fbfb3SApril Chin 					continue;
4107c2fbfb3SApril Chin #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))
417da2e3ebdSchin 				{
418*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
419*b30d1939SAndy Fiddaman 					if(!(arg->argflag&ARG_APPEND) && (!ap || !ap->fixed))
420*b30d1939SAndy Fiddaman #else
4217c2fbfb3SApril Chin 					if(!(arg->argflag&ARG_APPEND))
422*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
423*b30d1939SAndy Fiddaman 						_nv_unset(np,NV_EXPORT);
424da2e3ebdSchin 					if(array&NV_ARRAY)
425da2e3ebdSchin 					{
426da2e3ebdSchin 						nv_setarray(np,nv_associative);
427da2e3ebdSchin 					}
428da2e3ebdSchin 					else
429da2e3ebdSchin 					{
430da2e3ebdSchin 						nv_onattr(np,NV_ARRAY);
431da2e3ebdSchin 					}
43234f9b3eeSRoland Mainz 				}
43334f9b3eeSRoland Mainz 				if(array && tp->tre.tretyp!=TLST && !tp->com.comset && !tp->com.comarg)
43434f9b3eeSRoland Mainz 				{
4357c2fbfb3SApril Chin #if SHOPT_TYPEDEF
4367c2fbfb3SApril Chin 						goto check_type;
4377c2fbfb3SApril Chin #else
4387c2fbfb3SApril Chin 						continue;
4397c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
440da2e3ebdSchin 				}
441da2e3ebdSchin 				/* 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))))
443da2e3ebdSchin 				{
444da2e3ebdSchin 					int argc;
4457c2fbfb3SApril Chin 					Dt_t	*last_root = shp->last_root;
4467c2fbfb3SApril Chin 					char **argv = sh_argbuild(shp,&argc,&tp->com,0);
4477c2fbfb3SApril Chin 					shp->last_root = last_root;
4487c2fbfb3SApril Chin #if SHOPT_TYPEDEF
4497c2fbfb3SApril Chin 					if(shp->mktype && shp->dot_depth==0 && np==((struct sh_type*)shp->mktype)->nodes[0])
4507c2fbfb3SApril Chin 					{
4517c2fbfb3SApril Chin 						shp->mktype = 0;
4527c2fbfb3SApril Chin 						errormsg(SH_DICT,ERROR_exit(1),"%s: not a known type name",argv[0]);
4537c2fbfb3SApril Chin 					}
4547c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
455da2e3ebdSchin 					if(!(arg->argflag&ARG_APPEND))
456da2e3ebdSchin 					{
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
4607c2fbfb3SApril Chin 						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 						}
467da2e3ebdSchin 					}
468da2e3ebdSchin 					nv_setvec(np,(arg->argflag&ARG_APPEND),argc,argv);
469da2e3ebdSchin 					if(traceon || trap)
470da2e3ebdSchin 					{
471da2e3ebdSchin 						int n = -1;
472da2e3ebdSchin 						char *name = nv_name(np);
473da2e3ebdSchin 						if(arg->argflag&ARG_APPEND)
474da2e3ebdSchin 							n = '+';
475da2e3ebdSchin 						if(trap)
4767c2fbfb3SApril Chin 							sh_debug(shp,trap,name,(char*)0,argv,(arg->argflag&ARG_APPEND)|ARG_ASSIGN);
477da2e3ebdSchin 						if(traceon)
478da2e3ebdSchin 						{
479*b30d1939SAndy Fiddaman 							sh_trace(shp,NIL(char**),0);
480da2e3ebdSchin 							sfputr(sfstderr,name,n);
481da2e3ebdSchin 							sfwrite(sfstderr,"=( ",3);
482da2e3ebdSchin 							while(cp= *argv++)
483da2e3ebdSchin 								sfputr(sfstderr,sh_fmtq(cp),' ');
484da2e3ebdSchin 							sfwrite(sfstderr,")\n",2);
485da2e3ebdSchin 						}
486da2e3ebdSchin 					}
4877c2fbfb3SApril Chin #if SHOPT_TYPEDEF
4887c2fbfb3SApril Chin 					goto check_type;
4897c2fbfb3SApril Chin #else
490da2e3ebdSchin 					continue;
4917c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
492da2e3ebdSchin 				}
4937c2fbfb3SApril Chin 				if((tp->tre.tretyp&COMMSK)==TFUN)
4947c2fbfb3SApril Chin 					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 				}
501da2e3ebdSchin 				if(tp->tre.tretyp==TLST || !tp->com.comset || tp->com.comset->argval[0]!='[')
502da2e3ebdSchin 				{
5037c2fbfb3SApril Chin 					if(tp->tre.tretyp!=TLST && !tp->com.comnamp && tp->com.comset && tp->com.comset->argval[0]==0 && tp->com.comset->argchn.ap)
5047c2fbfb3SApril Chin 					{
505*b30d1939SAndy Fiddaman 						if(prefix || np)
5067c2fbfb3SApril Chin 							cp = stakcopy(nv_name(np));
5077c2fbfb3SApril Chin 						shp->prefix = cp;
5087c2fbfb3SApril Chin 						if(tp->com.comset->argval[1]=='[')
5097c2fbfb3SApril Chin 						{
5107c2fbfb3SApril Chin 							if((arg->argflag&ARG_APPEND) && (!nv_isarray(np) || (nv_aindex(np)>=0)))
511*b30d1939SAndy Fiddaman 								_nv_unset(np,0);
5127c2fbfb3SApril Chin 							if(!(array&NV_IARRAY) && !(tp->com.comset->argflag&ARG_MESSAGE))
5137c2fbfb3SApril Chin 								nv_setarray(np,nv_associative);
5147c2fbfb3SApril Chin 						}
515*b30d1939SAndy Fiddaman 						nv_setlist(tp->com.comset,flags&~NV_STATIC,0);
5167c2fbfb3SApril Chin 						shp->prefix = prefix;
5177c2fbfb3SApril Chin 						if(tp->com.comset->argval[1]!='[')
5187c2fbfb3SApril Chin 							 nv_setvtree(np);
5197c2fbfb3SApril Chin 						nv_close(np);
5207c2fbfb3SApril Chin #if SHOPT_TYPEDEF
5217c2fbfb3SApril Chin 						goto check_type;
5227c2fbfb3SApril Chin #else
5237c2fbfb3SApril Chin 						continue;
5247c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
5257c2fbfb3SApril Chin 					}
526da2e3ebdSchin 					if(*cp!='.' && *cp!='[' && strchr(cp,'['))
527da2e3ebdSchin 					{
528*b30d1939SAndy Fiddaman 						cp = stakcopy(nv_name(np));
529da2e3ebdSchin 						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);
534da2e3ebdSchin 					}
5357c2fbfb3SApril Chin 					if(arg->argflag&ARG_APPEND)
536da2e3ebdSchin 					{
5377c2fbfb3SApril Chin 						if(nv_isarray(np))
5387c2fbfb3SApril Chin 						{
5397c2fbfb3SApril Chin 							if((sub=nv_aimax(np)) < 0  && nv_arrayptr(np))
5407c2fbfb3SApril Chin 								errormsg(SH_DICT,ERROR_exit(1),e_badappend,nv_name(np));
5417c2fbfb3SApril Chin 							if(sub>=0)
5427c2fbfb3SApril Chin 								sub++;
5437c2fbfb3SApril Chin 						}
5447c2fbfb3SApril Chin 						if(!nv_isnull(np) && np->nvalue.cp!=Empty && !nv_isvtree(np))
5457c2fbfb3SApril Chin 							sub=1;
546da2e3ebdSchin 					}
547*b30d1939SAndy Fiddaman 					else if(((np->nvalue.cp && np->nvalue.cp!=Empty)||nv_isvtree(np)|| nv_arrayptr(np)) && !nv_type(np))
548da2e3ebdSchin 					{
5497c2fbfb3SApril Chin 						_nv_unset(np,NV_EXPORT);
550*b30d1939SAndy Fiddaman 						if(ap && ap->fun)
551*b30d1939SAndy Fiddaman 							 nv_setarray(np,nv_associative);
552*b30d1939SAndy Fiddaman 
553da2e3ebdSchin 					}
5547c2fbfb3SApril Chin 				}
5557c2fbfb3SApril Chin 				else
5567c2fbfb3SApril Chin 				{
5577c2fbfb3SApril Chin 					if(!(arg->argflag&ARG_APPEND))
5587c2fbfb3SApril Chin 						_nv_unset(np,NV_EXPORT);
5597c2fbfb3SApril Chin 					if(!sh_isoption(SH_BASH) && !(array&NV_IARRAY) && !nv_isarray(np))
560da2e3ebdSchin 						nv_setarray(np,nv_associative);
561da2e3ebdSchin 				}
5627c2fbfb3SApril Chin 			skip:
5637c2fbfb3SApril Chin 				if(sub>0)
5647c2fbfb3SApril Chin 				{
5657c2fbfb3SApril Chin 					sfprintf(stkstd,"%s[%d]",prefix?nv_name(np):cp,sub);
5667c2fbfb3SApril Chin 					shp->prefix = stakfreeze(1);
5677c2fbfb3SApril Chin 					nv_putsub(np,(char*)0,ARRAY_ADD|ARRAY_FILL|sub);
5687c2fbfb3SApril Chin 				}
5697c2fbfb3SApril Chin 				else if(prefix)
5707c2fbfb3SApril Chin 					shp->prefix = stakcopy(nv_name(np));
5717c2fbfb3SApril Chin 				else
5727c2fbfb3SApril Chin 					shp->prefix = cp;
5737c2fbfb3SApril Chin 				shp->last_table = 0;
57434f9b3eeSRoland Mainz 				if(shp->prefix)
57534f9b3eeSRoland Mainz 				{
57634f9b3eeSRoland Mainz 					if(*shp->prefix=='_' && shp->prefix[1]=='.' && nv_isref(L_ARGNOD))
57734f9b3eeSRoland Mainz 					{
57834f9b3eeSRoland Mainz 						sfprintf(stkstd,"%s%s",nv_name(L_ARGNOD->nvalue.nrp->np),shp->prefix+1);
57934f9b3eeSRoland Mainz 						shp->prefix = stkfreeze(stkstd,1);
58034f9b3eeSRoland Mainz 					}
58134f9b3eeSRoland Mainz 					memset(&nr,0,sizeof(nr));
58234f9b3eeSRoland Mainz 					memcpy(&node,L_ARGNOD,sizeof(node));
58334f9b3eeSRoland Mainz 					L_ARGNOD->nvalue.nrp = &nr;
58434f9b3eeSRoland Mainz 					nr.np = np;
58534f9b3eeSRoland Mainz 					nr.root = shp->last_root;
58634f9b3eeSRoland Mainz 					nr.table = shp->last_table;
58734f9b3eeSRoland Mainz 					L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
58834f9b3eeSRoland Mainz 					L_ARGNOD->nvfun = 0;
58934f9b3eeSRoland Mainz 				}
590da2e3ebdSchin 				sh_exec(tp,sh_isstate(SH_ERREXIT));
5917c2fbfb3SApril Chin #if SHOPT_TYPEDEF
59234f9b3eeSRoland Mainz 				if(shp->prefix)
5937c2fbfb3SApril Chin #endif
5947c2fbfb3SApril Chin 				{
5957c2fbfb3SApril Chin 					L_ARGNOD->nvalue.nrp = node.nvalue.nrp;
5967c2fbfb3SApril Chin 					L_ARGNOD->nvflag = node.nvflag;
5977c2fbfb3SApril Chin 					L_ARGNOD->nvfun = node.nvfun;
5987c2fbfb3SApril Chin 				}
5997c2fbfb3SApril Chin 				shp->prefix = prefix;
600da2e3ebdSchin 				if(nv_isarray(np) && (mp=nv_opensub(np)))
601da2e3ebdSchin 					np = mp;
6027c2fbfb3SApril Chin 				while(tp->tre.tretyp==TLST)
6037c2fbfb3SApril Chin 				{
6047c2fbfb3SApril Chin 					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]!='[')
6057c2fbfb3SApril Chin 						break;
6067c2fbfb3SApril Chin 					tp = tp->lst.lstrit;
6077c2fbfb3SApril Chin 
6087c2fbfb3SApril Chin 				}
60934f9b3eeSRoland Mainz 				if(!nv_isarray(np) && !typ && (tp->com.comarg || !tp->com.comset || tp->com.comset->argval[0]!='['))
6103e14f97fSRoger A. Faulkner 				{
6117c2fbfb3SApril Chin 					nv_setvtree(np);
6123e14f97fSRoger A. Faulkner 					if(tp->com.comarg || tp->com.comset)
6133e14f97fSRoger A. Faulkner 						np->nvfun->dsize = 0;
6143e14f97fSRoger A. Faulkner 				}
6157c2fbfb3SApril Chin #if SHOPT_TYPEDEF
6167c2fbfb3SApril Chin 				goto check_type;
6177c2fbfb3SApril Chin #else
618da2e3ebdSchin 				continue;
6197c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
620da2e3ebdSchin 			}
621da2e3ebdSchin 			cp = arg->argval;
6227c2fbfb3SApril Chin 			mp = 0;
623da2e3ebdSchin 		}
624*b30d1939SAndy Fiddaman 		np = nv_open(cp,shp->prefix_root?shp->prefix_root:shp->var_tree,flags);
6257c2fbfb3SApril Chin 		if(!np->nvfun && (flags&NV_NOREF))
626da2e3ebdSchin 		{
6277c2fbfb3SApril Chin 			if(shp->used_pos)
628da2e3ebdSchin 				nv_onattr(np,NV_PARAM);
629da2e3ebdSchin 			else
630da2e3ebdSchin 				nv_offattr(np,NV_PARAM);
631da2e3ebdSchin 		}
632da2e3ebdSchin 		if(traceon || trap)
633da2e3ebdSchin 		{
634da2e3ebdSchin 			register char *sp=cp;
635da2e3ebdSchin 			char *name=nv_name(np);
636da2e3ebdSchin 			char *sub=0;
637da2e3ebdSchin 			int append = 0;
638da2e3ebdSchin 			if(nv_isarray(np))
639da2e3ebdSchin 				sub = savesub;
6407c2fbfb3SApril Chin 			if(cp=lastdot(sp,'='))
641da2e3ebdSchin 			{
642da2e3ebdSchin 				if(cp[-1]=='+')
643da2e3ebdSchin 					append = ARG_APPEND;
644da2e3ebdSchin 				cp++;
645da2e3ebdSchin 			}
646da2e3ebdSchin 			if(traceon)
647da2e3ebdSchin 			{
648*b30d1939SAndy Fiddaman 				sh_trace(shp,NIL(char**),0);
649da2e3ebdSchin 				nv_outname(sfstderr,name,-1);
650da2e3ebdSchin 				if(sub)
651da2e3ebdSchin 					sfprintf(sfstderr,"[%s]",sh_fmtq(sub));
652da2e3ebdSchin 				if(cp)
653da2e3ebdSchin 				{
654da2e3ebdSchin 					if(append)
655da2e3ebdSchin 						sfputc(sfstderr,'+');
656da2e3ebdSchin 					sfprintf(sfstderr,"=%s\n",sh_fmtq(cp));
657da2e3ebdSchin 				}
658da2e3ebdSchin 			}
659da2e3ebdSchin 			if(trap)
660da2e3ebdSchin 			{
661da2e3ebdSchin 					char *av[2];
662da2e3ebdSchin 					av[0] = cp;
663da2e3ebdSchin 					av[1] = 0;
6647c2fbfb3SApril Chin 					sh_debug(shp,trap,name,sub,av,append);
665da2e3ebdSchin 			}
666da2e3ebdSchin 		}
6677c2fbfb3SApril Chin #if SHOPT_TYPEDEF
6687c2fbfb3SApril Chin 	check_type:
6697c2fbfb3SApril Chin 		if(maketype)
6707c2fbfb3SApril Chin 		{
6717c2fbfb3SApril Chin 			nv_open(shtp.nodes[0]->nvname,shp->var_tree,NV_ASSIGN|NV_VARNAME|NV_NOADD|NV_NOFAIL);
6727c2fbfb3SApril Chin 			np = nv_mktype(shtp.nodes,shtp.numnodes);
6737c2fbfb3SApril Chin 			free((void*)shtp.nodes);
6747c2fbfb3SApril Chin 			shp->mktype = shtp.previous;
6757c2fbfb3SApril Chin 			maketype = 0;
676*b30d1939SAndy Fiddaman 			if(shp->namespace)
677*b30d1939SAndy Fiddaman 				free(shp->prefix);
6787c2fbfb3SApril Chin 			shp->prefix = 0;
6797c2fbfb3SApril Chin 			if(nr.np == np)
6807c2fbfb3SApril Chin 			{
6817c2fbfb3SApril Chin 				L_ARGNOD->nvalue.nrp = node.nvalue.nrp;
6827c2fbfb3SApril Chin 				L_ARGNOD->nvflag = node.nvflag;
6837c2fbfb3SApril Chin 				L_ARGNOD->nvfun = node.nvfun;
6847c2fbfb3SApril Chin 			}
6857c2fbfb3SApril Chin 		}
6867c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
687da2e3ebdSchin 	}
688da2e3ebdSchin }
689da2e3ebdSchin 
690da2e3ebdSchin /*
691da2e3ebdSchin  * copy the subscript onto the stack
692da2e3ebdSchin  */
stak_subscript(const char * sub,int last)693da2e3ebdSchin static void stak_subscript(const char *sub, int last)
694da2e3ebdSchin {
695da2e3ebdSchin 	register int c;
696da2e3ebdSchin 	stakputc('[');
697da2e3ebdSchin 	while(c= *sub++)
698da2e3ebdSchin 	{
699da2e3ebdSchin 		if(c=='[' || c==']' || c=='\\')
700da2e3ebdSchin 			stakputc('\\');
701da2e3ebdSchin 		stakputc(c);
702da2e3ebdSchin 	}
703da2e3ebdSchin 	stakputc(last);
704da2e3ebdSchin }
705da2e3ebdSchin 
706da2e3ebdSchin /*
707da2e3ebdSchin  * construct a new name from a prefix and base name on the stack
708da2e3ebdSchin  */
copystack(const char * prefix,register const char * name,const char * sub)709da2e3ebdSchin static char *copystack(const char *prefix, register const char *name, const char *sub)
710da2e3ebdSchin {
711da2e3ebdSchin 	register int last=0,offset = staktell();
712da2e3ebdSchin 	if(prefix)
713da2e3ebdSchin 	{
714da2e3ebdSchin 		stakputs(prefix);
715da2e3ebdSchin 		if(*stakptr(staktell()-1)=='.')
716da2e3ebdSchin 			stakseek(staktell()-1);
717da2e3ebdSchin 		if(*name=='.' && name[1]=='[')
718da2e3ebdSchin 			last = staktell()+2;
7197c2fbfb3SApril Chin 		if(*name!='['  && *name!='.' && *name!='=' && *name!='+')
7207c2fbfb3SApril Chin 			stakputc('.');
7217c2fbfb3SApril Chin 		if(*name=='.' && (name[1]=='=' || name[1]==0))
722da2e3ebdSchin 			stakputc('.');
723da2e3ebdSchin 	}
724da2e3ebdSchin 	if(last)
725da2e3ebdSchin 	{
726da2e3ebdSchin 		stakputs(name);
727da2e3ebdSchin 		if(sh_checkid(stakptr(last),(char*)0))
728da2e3ebdSchin 			stakseek(staktell()-2);
729da2e3ebdSchin 	}
730da2e3ebdSchin 	if(sub)
731da2e3ebdSchin 		stak_subscript(sub,']');
732da2e3ebdSchin 	if(!last)
733da2e3ebdSchin 		stakputs(name);
734da2e3ebdSchin 	stakputc(0);
735da2e3ebdSchin 	return(stakptr(offset));
736da2e3ebdSchin }
737da2e3ebdSchin 
738da2e3ebdSchin /*
739da2e3ebdSchin  * grow this stack string <name> by <n> bytes and move from cp-1 to end
740da2e3ebdSchin  * right by <n>.  Returns beginning of string on the stack
741da2e3ebdSchin  */
stack_extend(const char * cname,char * cp,int n)742da2e3ebdSchin static char *stack_extend(const char *cname, char *cp, int n)
743da2e3ebdSchin {
744da2e3ebdSchin 	register char *name = (char*)cname;
745da2e3ebdSchin 	int offset = name - stakptr(0);
746da2e3ebdSchin 	int m = cp-name;
747*b30d1939SAndy Fiddaman 	stakseek(offset + strlen(name)+n+1);
748da2e3ebdSchin 	name = stakptr(offset);
749da2e3ebdSchin 	cp =  name + m;
750da2e3ebdSchin 	m = strlen(cp)+1;
751da2e3ebdSchin 	while(m-->0)
752da2e3ebdSchin 		cp[n+m]=cp[m];
753da2e3ebdSchin 	return((char*)name);
754da2e3ebdSchin }
755da2e3ebdSchin 
nv_create(const char * name,Dt_t * root,int flags,Namfun_t * dp)7567c2fbfb3SApril Chin Namval_t *nv_create(const char *name,  Dt_t *root, int flags, Namfun_t *dp)
757da2e3ebdSchin {
758*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
759*b30d1939SAndy Fiddaman 	char			*sub=0, *cp=(char*)name, *sp, *xp;
760da2e3ebdSchin 	register int		c;
761da2e3ebdSchin 	register Namval_t	*np=0, *nq=0;
762da2e3ebdSchin 	Namfun_t		*fp=0;
763da2e3ebdSchin 	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 */
7697c2fbfb3SApril Chin 	if(root==shp->var_tree)
770da2e3ebdSchin 	{
771da2e3ebdSchin 		if(dtvnext(root))
772da2e3ebdSchin 			top = 1;
773da2e3ebdSchin 		else
774da2e3ebdSchin 			flags &= ~NV_NOSCOPE;
775da2e3ebdSchin 	}
776da2e3ebdSchin 	if(!dp->disc)
7777c2fbfb3SApril Chin 		copy = dp->nofree&1;
778da2e3ebdSchin 	if(*cp=='.')
779da2e3ebdSchin 		cp++;
780da2e3ebdSchin 	while(1)
781da2e3ebdSchin 	{
782da2e3ebdSchin 		switch(c = *(unsigned char*)(sp = cp))
783da2e3ebdSchin 		{
784da2e3ebdSchin 		    case '[':
785da2e3ebdSchin 			if(flags&NV_NOARRAY)
786da2e3ebdSchin 			{
787da2e3ebdSchin 				dp->last = cp;
788da2e3ebdSchin 				return(np);
789da2e3ebdSchin 			}
790da2e3ebdSchin 			cp = nv_endsubscript((Namval_t*)0,sp,0);
791da2e3ebdSchin 			if(sp==name || sp[-1]=='.')
792da2e3ebdSchin 				c = *(sp = cp);
793da2e3ebdSchin 			goto skip;
794da2e3ebdSchin 		    case '.':
795da2e3ebdSchin 			if(flags&NV_IDENT)
796da2e3ebdSchin 				return(0);
7977c2fbfb3SApril Chin 			if(root==shp->var_tree)
798da2e3ebdSchin 				flags &= ~NV_EXPORT;
799da2e3ebdSchin 			if(!copy && !(flags&NV_NOREF))
800da2e3ebdSchin 			{
801da2e3ebdSchin 				c = sp-name;
802da2e3ebdSchin 				copy = cp-name;
8037c2fbfb3SApril Chin 				dp->nofree |= 1;
804da2e3ebdSchin 				name = copystack((const char*)0, name,(const char*)0);
805da2e3ebdSchin 				cp = (char*)name+copy;
806da2e3ebdSchin 				sp = (char*)name+c;
807da2e3ebdSchin 				c = '.';
808da2e3ebdSchin 			}
8095ae8bd53SToomas Soome 			/* FALLTHROUGH */
810da2e3ebdSchin 		skip:
811da2e3ebdSchin 		    case '+':
812da2e3ebdSchin 		    case '=':
813da2e3ebdSchin 			*sp = 0;
8145ae8bd53SToomas Soome 			/* FALLTHROUGH */
815da2e3ebdSchin 		    case 0:
816da2e3ebdSchin 			isref = 0;
817da2e3ebdSchin 			dp->last = cp;
818da2e3ebdSchin 			mode =  (c=='.' || (flags&NV_NOADD))?add:NV_ADD;
819*b30d1939SAndy Fiddaman 			if(level++ || ((flags&NV_NOSCOPE) && c!='.'))
820da2e3ebdSchin 				mode |= HASH_NOSCOPE;
8217c2fbfb3SApril Chin 			np=0;
822da2e3ebdSchin 			if(top)
8237c2fbfb3SApril Chin 			{
8247c2fbfb3SApril Chin 				struct Ufunction *rp;
8257c2fbfb3SApril Chin 				if((rp=shp->st.real_fun) && !rp->sdict && (flags&NV_STATIC))
8267c2fbfb3SApril Chin 				{
8277c2fbfb3SApril Chin 					Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0);
8287c2fbfb3SApril Chin 					rp->sdict = dtopen(&_Nvdisc,Dtoset);
829*b30d1939SAndy Fiddaman 					dtview(rp->sdict,dp);
8307c2fbfb3SApril Chin 					dtview(shp->var_tree,rp->sdict);
8317c2fbfb3SApril Chin 				}
8327c2fbfb3SApril Chin 				if(np = nv_search(name,shp->var_tree,0))
8337c2fbfb3SApril Chin 				{
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 */
8397c2fbfb3SApril Chin 					{
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 */
8437c2fbfb3SApril Chin 						nq = np;
844*b30d1939SAndy Fiddaman 						shp->last_root = shp->var_tree->walk;
8453e14f97fSRoger A. Faulkner 						if((flags&NV_NOSCOPE) && *cp!='.')
8467c2fbfb3SApril Chin 						{
8477c2fbfb3SApril Chin 							if(mode==0)
848*b30d1939SAndy Fiddaman 								root = shp->var_tree->walk;
8497c2fbfb3SApril Chin 							else
8507c2fbfb3SApril Chin 							{
851*b30d1939SAndy Fiddaman 								nv_delete(np,(Dt_t*)0,NV_NOFREE);
8527c2fbfb3SApril Chin 								np = 0;
8537c2fbfb3SApril Chin 							}
8547c2fbfb3SApril Chin 						}
8557c2fbfb3SApril Chin 					}
8567c2fbfb3SApril Chin 					else
8577c2fbfb3SApril Chin 					{
858*b30d1939SAndy Fiddaman 						if(shp->var_tree->walk)
859*b30d1939SAndy Fiddaman 							root = shp->var_tree->walk;
8607c2fbfb3SApril Chin 						flags |= NV_NOSCOPE;
8617c2fbfb3SApril Chin 						noscope = 1;
8627c2fbfb3SApril Chin 					}
8637c2fbfb3SApril Chin 				}
8647c2fbfb3SApril Chin 				if(rp && rp->sdict && (flags&NV_STATIC))
8657c2fbfb3SApril Chin 				{
8667c2fbfb3SApril Chin 					root = rp->sdict;
8677c2fbfb3SApril Chin 					if(np && shp->var_tree->walk==shp->var_tree)
8687c2fbfb3SApril Chin 					{
8697c2fbfb3SApril Chin 						_nv_unset(np,0);
8707c2fbfb3SApril Chin 						nv_delete(np,shp->var_tree,0);
8717c2fbfb3SApril Chin 						np = 0;
8727c2fbfb3SApril Chin 					}
8737c2fbfb3SApril Chin 					if(!np || shp->var_tree->walk!=root)
8747c2fbfb3SApril Chin 						np =  nv_search(name,root,HASH_NOSCOPE|NV_ADD);
8757c2fbfb3SApril Chin 				}
8767c2fbfb3SApril Chin 			}
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 */
8817c2fbfb3SApril Chin 			if(np ||  (np = nv_search(name,root,mode)))
882da2e3ebdSchin 			{
883da2e3ebdSchin 				isref = nv_isref(np);
884*b30d1939SAndy Fiddaman 				shp->openmatch = root->walk?root->walk:root;
885da2e3ebdSchin 				if(top)
886da2e3ebdSchin 				{
887da2e3ebdSchin 					if(nq==np)
88834f9b3eeSRoland Mainz 					{
889da2e3ebdSchin 						flags &= ~NV_NOSCOPE;
890*b30d1939SAndy Fiddaman 						root = shp->last_root;
89134f9b3eeSRoland Mainz 					}
892da2e3ebdSchin 					else if(nq)
893da2e3ebdSchin 					{
894*b30d1939SAndy Fiddaman 						if(nv_isnull(np) && c!='.' && ((np->nvfun=nv_cover(nq)) || nq==OPTINDNOD))
895*b30d1939SAndy Fiddaman 						{
896da2e3ebdSchin 							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 						}
908da2e3ebdSchin 						flags |= NV_NOSCOPE;
909da2e3ebdSchin 					}
910da2e3ebdSchin 				}
9117c2fbfb3SApril Chin 				else if(add && nv_isnull(np) && c=='.' && cp[1]!='.')
912da2e3ebdSchin 					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 */
920da2e3ebdSchin 			}
921da2e3ebdSchin 			if(c)
922da2e3ebdSchin 				*sp = c;
923da2e3ebdSchin 			top = 0;
924da2e3ebdSchin 			if(isref)
925da2e3ebdSchin 			{
926*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
927*b30d1939SAndy Fiddaman 				int n=0,dim;
928*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
9297c2fbfb3SApril Chin #if NVCACHE
9307c2fbfb3SApril Chin 				nvcache.ok = 0;
9317c2fbfb3SApril Chin #endif
932da2e3ebdSchin 				if(c=='.') /* don't optimize */
9337c2fbfb3SApril Chin 					shp->argaddr = 0;
93434f9b3eeSRoland Mainz 				else if((flags&NV_NOREF) && (c!='[' && *cp!='.'))
935da2e3ebdSchin 				{
9367c2fbfb3SApril Chin 					if(c && !(flags&NV_NOADD))
937da2e3ebdSchin 						nv_unref(np);
938da2e3ebdSchin 					return(np);
939da2e3ebdSchin 				}
9407c2fbfb3SApril Chin 				while(nv_isref(np) && np->nvalue.cp)
941da2e3ebdSchin 				{
942da2e3ebdSchin 					root = nv_reftree(np);
9437c2fbfb3SApril Chin 					shp->last_root = root;
9447c2fbfb3SApril Chin 					shp->last_table = nv_reftable(np);
945da2e3ebdSchin 					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 */
950da2e3ebdSchin 					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 */
960da2e3ebdSchin 					if(sub && c!='.')
961da2e3ebdSchin 						nv_putsub(np,sub,0L);
962da2e3ebdSchin 					flags |= NV_NOSCOPE;
9637c2fbfb3SApril Chin 					noscope = 1;
964da2e3ebdSchin 				}
965*b30d1939SAndy Fiddaman 				shp->first_root = root;
9667c2fbfb3SApril Chin 				if(nv_isref(np) && (c=='[' || c=='.' || !(flags&NV_ASSIGN)))
9677c2fbfb3SApril Chin 					errormsg(SH_DICT,ERROR_exit(1),e_noref,nv_name(np));
968da2e3ebdSchin 				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 					}
981da2e3ebdSchin 					return(np);
982*b30d1939SAndy Fiddaman 				}
983da2e3ebdSchin 				if(np==nq)
984da2e3ebdSchin 					flags &= ~(noscope?0:NV_NOSCOPE);
985*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
986*b30d1939SAndy Fiddaman 				else if(c || n)
987*b30d1939SAndy Fiddaman #else
988da2e3ebdSchin 				else if(c)
989*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
990da2e3ebdSchin 				{
991*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
992*b30d1939SAndy Fiddaman 					static char null[1] = "";
993*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
994da2e3ebdSchin 					c = (cp-sp);
995da2e3ebdSchin 					copy = strlen(cp=nv_name(np));
9967c2fbfb3SApril Chin 					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);
1003da2e3ebdSchin 					sp = (char*)name + copy;
1004da2e3ebdSchin 					cp = sp+c;
1005da2e3ebdSchin 					c = *sp;
1006da2e3ebdSchin 					if(!noscope)
1007da2e3ebdSchin 						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 */
1012da2e3ebdSchin 				}
1013da2e3ebdSchin 				flags |= NV_NOREF;
1014*b30d1939SAndy Fiddaman 				if(*cp==0 &&  nv_isnull(np) && !nv_isarray(np))
1015*b30d1939SAndy Fiddaman 					nofree = NV_NOFREE;
1016da2e3ebdSchin 			}
10177c2fbfb3SApril Chin 			shp->last_root = root;
10183e14f97fSRoger A. Faulkner 			if(*cp && cp[1]=='.')
10197c2fbfb3SApril Chin 				cp++;
10207c2fbfb3SApril Chin 			if(c=='.' && (cp[1]==0 ||  cp[1]=='=' || cp[1]=='+'))
10217c2fbfb3SApril Chin 			{
10227c2fbfb3SApril Chin 				nv_local = 1;
1023*b30d1939SAndy Fiddaman 				if(np)
1024*b30d1939SAndy Fiddaman 					nv_onattr(np,nofree);
10257c2fbfb3SApril Chin 				return(np);
10267c2fbfb3SApril Chin 			}
10277c2fbfb3SApril Chin 			if(cp[-1]=='.')
10287c2fbfb3SApril Chin 				cp--;
1029da2e3ebdSchin 			do
1030da2e3ebdSchin 			{
1031*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1032*b30d1939SAndy Fiddaman 				int fixed;
1033*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1034da2e3ebdSchin 				if(!np)
1035da2e3ebdSchin 				{
10367c2fbfb3SApril Chin 					if(!nq && *sp=='[' && *cp==0 && cp[-1]==']')
1037da2e3ebdSchin 					{
1038da2e3ebdSchin 						/*
1039da2e3ebdSchin 						 * for backward compatibility
1040da2e3ebdSchin 						 * evaluate subscript for
1041da2e3ebdSchin 						 * possible side effects
1042da2e3ebdSchin 						 */
1043da2e3ebdSchin 						cp[-1] = 0;
1044*b30d1939SAndy Fiddaman 						sh_arith(shp,sp+1);
1045da2e3ebdSchin 						cp[-1] = ']';
1046da2e3ebdSchin 					}
1047da2e3ebdSchin 					return(np);
1048da2e3ebdSchin 				}
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 */
1054da2e3ebdSchin 				if(c=='[' || (c=='.' && nv_isarray(np)))
1055da2e3ebdSchin 				{
1056da2e3ebdSchin 					int n = 0;
1057*b30d1939SAndy Fiddaman 					sub = 0;
105834f9b3eeSRoland Mainz 					mode &= ~HASH_NOSCOPE;
1059da2e3ebdSchin 					if(c=='[')
1060da2e3ebdSchin 					{
1061*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
106234f9b3eeSRoland Mainz 						Namarr_t *ap = nv_arrayptr(np);
1063*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1064*b30d1939SAndy Fiddaman #if 0
106534f9b3eeSRoland Mainz 						int scan = ap?(ap->nelem&ARRAY_SCAN):0;
106634f9b3eeSRoland Mainz #endif
1067da2e3ebdSchin 						n = mode|nv_isarray(np);
1068da2e3ebdSchin 						if(!mode && (flags&NV_ARRAY) && ((c=sp[1])=='*' || c=='@') && sp[2]==']')
1069da2e3ebdSchin 						{
1070da2e3ebdSchin 							/* not implemented yet */
1071da2e3ebdSchin 							dp->last = cp;
1072da2e3ebdSchin 							return(np);
1073da2e3ebdSchin 						}
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 */
10797c2fbfb3SApril Chin 						if((n&NV_ADD)&&(flags&NV_ARRAY))
1080da2e3ebdSchin 							n |= ARRAY_FILL;
10817c2fbfb3SApril Chin 						if(flags&NV_ASSIGN)
10827c2fbfb3SApril Chin 							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 */
109034f9b3eeSRoland Mainz #if 0
109134f9b3eeSRoland Mainz 						if(scan)
109234f9b3eeSRoland Mainz 							nv_putsub(np,NIL(char*),ARRAY_SCAN);
109334f9b3eeSRoland Mainz #endif
1094da2e3ebdSchin 					}
1095da2e3ebdSchin 					else
1096da2e3ebdSchin 						cp = sp;
1097*b30d1939SAndy Fiddaman 					if((c = *cp)=='.' || (c=='[' && nv_isarray(np)) || (n&ARRAY_FILL) || ((ap || (flags&NV_ASSIGN)) &&  (flags&NV_ARRAY)))
1098da2e3ebdSchin 
1099da2e3ebdSchin 					{
1100da2e3ebdSchin 						int m = cp-sp;
11017c2fbfb3SApril Chin 						sub = m?nv_getsub(np):0;
1102da2e3ebdSchin 						if(!sub)
11037c2fbfb3SApril Chin 						{
11047c2fbfb3SApril Chin 							if(m && !(n&NV_ADD))
11057c2fbfb3SApril Chin 								return(0);
1106da2e3ebdSchin 							sub = "0";
11077c2fbfb3SApril Chin 						}
1108da2e3ebdSchin 						n = strlen(sub)+2;
1109da2e3ebdSchin 						if(!copy)
1110da2e3ebdSchin 						{
1111da2e3ebdSchin 							copy = cp-name;
11127c2fbfb3SApril Chin 							dp->nofree |= 1;
1113da2e3ebdSchin 							name = copystack((const char*)0, name,(const char*)0);
1114da2e3ebdSchin 							cp = (char*)name+copy;
1115da2e3ebdSchin 							sp = cp-m;
1116da2e3ebdSchin 						}
1117da2e3ebdSchin 						if(n <= m)
1118da2e3ebdSchin 						{
1119da2e3ebdSchin 							if(n)
1120da2e3ebdSchin 							{
1121da2e3ebdSchin 								memcpy(sp+1,sub,n-2);
1122da2e3ebdSchin 								sp[n-1] = ']';
1123da2e3ebdSchin 							}
1124da2e3ebdSchin 							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 							}
1130da2e3ebdSchin 						}
1131da2e3ebdSchin 						else
1132da2e3ebdSchin 						{
1133da2e3ebdSchin 							int r = n-m;
1134da2e3ebdSchin 							m = sp-name;
1135da2e3ebdSchin 							name = stack_extend(name, cp-1, r);
1136da2e3ebdSchin 							sp = (char*)name + m;
1137da2e3ebdSchin 							*sp = '[';
1138da2e3ebdSchin 							memcpy(sp+1,sub,n-2);
1139da2e3ebdSchin 							sp[n-1] = ']';
1140da2e3ebdSchin 							cp = sp+n;
1141da2e3ebdSchin 
1142da2e3ebdSchin 						}
1143da2e3ebdSchin 					}
1144da2e3ebdSchin 					else if(c==0 && mode && (n=nv_aindex(np))>0)
11457c2fbfb3SApril Chin 						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
11497c2fbfb3SApril Chin 					else if(n==0 && (c==0 || (c=='[' && !nv_isarray(np))))
1150*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1151da2e3ebdSchin 					{
1152da2e3ebdSchin 						/* subscript must be 0*/
1153da2e3ebdSchin 						cp[-1] = 0;
1154*b30d1939SAndy Fiddaman 						n = sh_arith(shp,sp+1);
1155da2e3ebdSchin 						cp[-1] = ']';
11567c2fbfb3SApril Chin 						if(n)
1157da2e3ebdSchin 							return(0);
11587c2fbfb3SApril Chin 						if(c)
11597c2fbfb3SApril Chin 							sp = cp;
1160da2e3ebdSchin 					}
1161da2e3ebdSchin 					dp->last = cp;
1162da2e3ebdSchin 					if(nv_isarray(np) && (c=='[' || c=='.' || (flags&NV_ARRAY)))
1163da2e3ebdSchin 					{
1164*b30d1939SAndy Fiddaman 					addsub:
11657c2fbfb3SApril Chin 						sp = cp;
11667c2fbfb3SApril Chin 						if(!(nq = nv_opensub(np)))
11677c2fbfb3SApril Chin 						{
11687c2fbfb3SApril Chin 							Namarr_t *ap = nv_arrayptr(np);
11697c2fbfb3SApril Chin 							if(!sub && (flags&NV_NOADD))
11707c2fbfb3SApril Chin 								return(0);
11717c2fbfb3SApril Chin 							n = mode|((flags&NV_NOADD)?0:NV_ADD);
11727c2fbfb3SApril Chin 							if(!ap && (n&NV_ADD))
11737c2fbfb3SApril Chin 							{
11747c2fbfb3SApril Chin 								nv_putsub(np,sub,ARRAY_FILL);
11757c2fbfb3SApril Chin 								ap = nv_arrayptr(np);
11767c2fbfb3SApril Chin 							}
11777c2fbfb3SApril Chin 							if(n && ap && !ap->table)
11787c2fbfb3SApril Chin 								ap->table = dtopen(&_Nvdisc,Dtoset);
11797c2fbfb3SApril Chin 							if(ap && ap->table && (nq=nv_search(sub,ap->table,n)))
11807c2fbfb3SApril Chin 								nq->nvenv = (char*)np;
11817c2fbfb3SApril Chin 							if(nq && nv_isnull(nq))
11827c2fbfb3SApril Chin 								nq = nv_arraychild(np,nq,c);
11837c2fbfb3SApril Chin 						}
11847c2fbfb3SApril Chin 						if(nq)
11857c2fbfb3SApril Chin 						{
11867c2fbfb3SApril Chin 							if(c=='.' && !nv_isvtree(nq))
11877c2fbfb3SApril Chin 							{
11887c2fbfb3SApril Chin 								if(flags&NV_NOADD)
11897c2fbfb3SApril Chin 									return(0);
11907c2fbfb3SApril Chin 								nv_setvtree(nq);
11917c2fbfb3SApril Chin 							}
1192*b30d1939SAndy Fiddaman 							nv_onattr(np,nofree);
1193*b30d1939SAndy Fiddaman 							nofree = 0;
11947c2fbfb3SApril Chin 							np = nq;
11957c2fbfb3SApril Chin 						}
11967c2fbfb3SApril Chin 						else if(memcmp(cp,"[0]",3))
11977c2fbfb3SApril Chin 							return(nq);
11987c2fbfb3SApril Chin 						else
11997c2fbfb3SApril Chin 						{
12007c2fbfb3SApril Chin 							/* ignore [0]  */
12017c2fbfb3SApril Chin 							dp->last = cp += 3;
12027c2fbfb3SApril Chin 							c = *cp;
12037c2fbfb3SApril Chin 						}
1204da2e3ebdSchin 					}
1205da2e3ebdSchin 				}
1206*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1207*b30d1939SAndy Fiddaman 				else if(nv_isarray(np) && (!fixed || cp[-1]!=']'))
1208*b30d1939SAndy Fiddaman #else
1209da2e3ebdSchin 				else if(nv_isarray(np))
1210*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
12117c2fbfb3SApril Chin 				{
12127c2fbfb3SApril Chin 					if(c==0 && (flags&NV_MOVE))
12137c2fbfb3SApril Chin 						return(np);
1214da2e3ebdSchin 					nv_putsub(np,NIL(char*),ARRAY_UNDEF);
12157c2fbfb3SApril Chin 				}
1216*b30d1939SAndy Fiddaman 				nv_onattr(np,nofree);
1217*b30d1939SAndy Fiddaman 				nofree  = 0;
1218da2e3ebdSchin 				if(c=='.' && (fp=np->nvfun))
1219da2e3ebdSchin 				{
1220da2e3ebdSchin 					for(; fp; fp=fp->next)
1221da2e3ebdSchin 					{
1222da2e3ebdSchin 						if(fp->disc && fp->disc->createf)
1223da2e3ebdSchin 							break;
1224da2e3ebdSchin 					}
1225da2e3ebdSchin 					if(fp)
1226da2e3ebdSchin 					{
1227da2e3ebdSchin 						if((nq = (*fp->disc->createf)(np,cp+1,flags,fp)) == np)
1228da2e3ebdSchin 						{
1229da2e3ebdSchin 							add = NV_ADD;
123034f9b3eeSRoland Mainz 							shp->last_table = 0;
1231da2e3ebdSchin 							break;
1232da2e3ebdSchin 						}
12337c2fbfb3SApril Chin 						else if(np=nq)
12347c2fbfb3SApril Chin 						{
12357c2fbfb3SApril Chin 							if((c = *(sp=cp=dp->last=fp->last))==0)
12367c2fbfb3SApril Chin 							{
12377c2fbfb3SApril Chin 								if(nv_isarray(np) && sp[-1]!=']')
12387c2fbfb3SApril Chin 									nv_putsub(np,NIL(char*),ARRAY_UNDEF);
12397c2fbfb3SApril Chin 								return(np);
12407c2fbfb3SApril Chin 							}
12417c2fbfb3SApril Chin 						}
1242da2e3ebdSchin 					}
1243da2e3ebdSchin 				}
1244da2e3ebdSchin 			}
1245da2e3ebdSchin 			while(c=='[');
12467c2fbfb3SApril Chin 			if(c!='.' || cp[1]=='.')
1247da2e3ebdSchin 				return(np);
1248da2e3ebdSchin 			cp++;
1249da2e3ebdSchin 			break;
1250da2e3ebdSchin 		    default:
1251da2e3ebdSchin 			dp->last = cp;
1252da2e3ebdSchin 			if((c = mbchar(cp)) && !isaletter(c))
1253da2e3ebdSchin 				return(np);
1254da2e3ebdSchin 			while(xp=cp, c=mbchar(cp), isaname(c));
1255da2e3ebdSchin 			cp = xp;
1256da2e3ebdSchin 		}
1257da2e3ebdSchin 	}
1258da2e3ebdSchin 	return(np);
1259da2e3ebdSchin }
1260da2e3ebdSchin 
12617c2fbfb3SApril Chin /*
12627c2fbfb3SApril Chin  * delete the node <np> from the dictionary <root> and clear from the cache
12637c2fbfb3SApril Chin  * if <root> is NULL, only the cache is cleared
12647c2fbfb3SApril Chin  * if flags does not contain NV_NOFREE, the node is freed
1265*b30d1939SAndy Fiddaman  * if np==0  && !root && flags==0,  delete the Refdict dictionary
12667c2fbfb3SApril Chin  */
nv_delete(Namval_t * np,Dt_t * root,int flags)12677c2fbfb3SApril Chin void nv_delete(Namval_t* np, Dt_t *root, int flags)
12687c2fbfb3SApril Chin {
12697c2fbfb3SApril Chin #if NVCACHE
12707c2fbfb3SApril Chin 	register int		c;
12717c2fbfb3SApril Chin 	struct Cache_entry	*xp;
12727c2fbfb3SApril Chin 	for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c])
12737c2fbfb3SApril Chin 	{
12747c2fbfb3SApril Chin 		if(xp->np==np)
12757c2fbfb3SApril Chin 			xp->root = 0;
12767c2fbfb3SApril Chin 	}
12777c2fbfb3SApril Chin #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 	}
13017c2fbfb3SApril Chin 	if(root)
13027c2fbfb3SApril Chin 	{
13037c2fbfb3SApril Chin 		if(dtdelete(root,np))
13047c2fbfb3SApril Chin 		{
13057c2fbfb3SApril Chin 			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 				}
13157c2fbfb3SApril Chin 				free((void*)np);
1316*b30d1939SAndy Fiddaman 			}
13177c2fbfb3SApril Chin 		}
13187c2fbfb3SApril Chin #if 0
13197c2fbfb3SApril Chin 		else
13207c2fbfb3SApril Chin 		{
13217c2fbfb3SApril Chin 			sfprintf(sfstderr,"%s not deleted\n",nv_name(np));
13227c2fbfb3SApril Chin 			sfsync(sfstderr);
13237c2fbfb3SApril Chin 		}
13247c2fbfb3SApril Chin #endif
13257c2fbfb3SApril Chin 	}
13267c2fbfb3SApril Chin }
13277c2fbfb3SApril Chin 
1328da2e3ebdSchin /*
1329da2e3ebdSchin  * Put <arg> into associative memory.
1330da2e3ebdSchin  * If <flags> & NV_ARRAY then follow array to next subscript
1331da2e3ebdSchin  * If <flags> & NV_NOARRAY then subscript is not allowed
1332da2e3ebdSchin  * If <flags> & NV_NOSCOPE then use the current scope only
1333da2e3ebdSchin  * If <flags> & NV_ASSIGN then assignment is allowed
1334da2e3ebdSchin  * If <flags> & NV_IDENT then name must be an identifier
1335da2e3ebdSchin  * If <flags> & NV_VARNAME then name must be a valid variable name
1336da2e3ebdSchin  * If <flags> & NV_NOADD then node will not be added if not found
1337da2e3ebdSchin  * If <flags> & NV_NOREF then don't follow reference
1338da2e3ebdSchin  * If <flags> & NV_NOFAIL then don't generate an error message on failure
13397c2fbfb3SApril Chin  * If <flags> & NV_STATIC then unset before an assignment
134034f9b3eeSRoland Mainz  * If <flags> & NV_UNJUST then unset attributes before assignment
1341da2e3ebdSchin  * SH_INIT is only set while initializing the environment
1342da2e3ebdSchin  */
nv_open(const char * name,Dt_t * root,int flags)1343da2e3ebdSchin Namval_t *nv_open(const char *name, Dt_t *root, int flags)
1344da2e3ebdSchin {
1345*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
1346da2e3ebdSchin 	register char		*cp=(char*)name;
1347da2e3ebdSchin 	register int		c;
1348*b30d1939SAndy Fiddaman 	register Namval_t	*np=0;
1349da2e3ebdSchin 	Namfun_t		fun;
1350da2e3ebdSchin 	int			append=0;
1351da2e3ebdSchin 	const char		*msg = e_varname;
1352da2e3ebdSchin 	char			*fname = 0;
1353da2e3ebdSchin 	int			offset = staktell();
1354da2e3ebdSchin 	Dt_t			*funroot;
13557c2fbfb3SApril Chin #if NVCACHE
13567c2fbfb3SApril Chin 	struct Cache_entry	*xp;
13577c2fbfb3SApril Chin #endif
13587c2fbfb3SApril Chin 
13597c2fbfb3SApril Chin 	sh_stats(STAT_NVOPEN);
1360da2e3ebdSchin 	memset(&fun,0,sizeof(fun));
1361*b30d1939SAndy Fiddaman 	shp->openmatch = 0;
1362*b30d1939SAndy Fiddaman 	shp->last_table = 0;
1363da2e3ebdSchin 	if(!root)
13647c2fbfb3SApril Chin 		root = shp->var_tree;
13657c2fbfb3SApril Chin 	shp->last_root = root;
13667c2fbfb3SApril Chin 	if(root==shp->fun_tree)
1367da2e3ebdSchin 	{
1368da2e3ebdSchin 		flags |= NV_NOREF;
1369da2e3ebdSchin 		msg = e_badfun;
1370*b30d1939SAndy Fiddaman 		if(strchr(name,'.'))
1371da2e3ebdSchin 		{
1372*b30d1939SAndy Fiddaman 			name = cp = copystack(0,name,(const char*)0);
1373da2e3ebdSchin 			fname = strrchr(cp,'.');
1374da2e3ebdSchin 			*fname = 0;
13757c2fbfb3SApril Chin 			fun.nofree |= 1;
1376da2e3ebdSchin 			flags &=  ~NV_IDENT;
1377da2e3ebdSchin 			funroot = root;
13787c2fbfb3SApril Chin 			root = shp->var_tree;
1379da2e3ebdSchin 		}
1380da2e3ebdSchin 	}
1381da2e3ebdSchin 	else if(!(flags&(NV_IDENT|NV_VARNAME|NV_ASSIGN)))
1382da2e3ebdSchin 	{
1383da2e3ebdSchin 		long mode = ((flags&NV_NOADD)?0:NV_ADD);
1384da2e3ebdSchin 		if(flags&NV_NOSCOPE)
1385da2e3ebdSchin 			mode |= HASH_SCOPE|HASH_NOSCOPE;
1386da2e3ebdSchin 		np = nv_search(name,root,mode);
1387da2e3ebdSchin 		if(np && !(flags&NV_REF))
1388da2e3ebdSchin 		{
1389da2e3ebdSchin 			while(nv_isref(np))
1390da2e3ebdSchin 			{
13917c2fbfb3SApril Chin 				shp->last_table = nv_reftable(np);
1392da2e3ebdSchin 				np = nv_refnode(np);
1393da2e3ebdSchin 			}
1394da2e3ebdSchin 		}
1395da2e3ebdSchin 		return(np);
1396da2e3ebdSchin 	}
13977c2fbfb3SApril Chin 	else if(shp->prefix && (flags&NV_ASSIGN))
1398da2e3ebdSchin 	{
13997c2fbfb3SApril Chin 		name = cp = copystack(shp->prefix,name,(const char*)0);
14007c2fbfb3SApril Chin 		fun.nofree |= 1;
1401da2e3ebdSchin 	}
1402da2e3ebdSchin 	c = *(unsigned char*)cp;
14037c2fbfb3SApril Chin 	if(root==shp->alias_tree)
1404da2e3ebdSchin 	{
1405da2e3ebdSchin 		msg = e_aliname;
1406da2e3ebdSchin 		while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') &&
14077c2fbfb3SApril Chin 			(c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON));
14087c2fbfb3SApril Chin 		if(shp->subshell && c=='=')
1409da2e3ebdSchin 			root = sh_subaliastree(1);
1410da2e3ebdSchin 		if(c= *--cp)
1411da2e3ebdSchin 			*cp = 0;
1412da2e3ebdSchin 		np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD);
1413da2e3ebdSchin 		if(c)
1414da2e3ebdSchin 			*cp = c;
1415da2e3ebdSchin 		goto skip;
1416da2e3ebdSchin 	}
1417da2e3ebdSchin 	else if(flags&NV_IDENT)
1418da2e3ebdSchin 		msg = e_ident;
1419da2e3ebdSchin 	else if(c=='.')
1420da2e3ebdSchin 	{
1421da2e3ebdSchin 		c = *++cp;
1422da2e3ebdSchin 		flags |= NV_NOREF;
14237c2fbfb3SApril Chin 		if(root==shp->var_tree)
14247c2fbfb3SApril Chin 			root = shp->var_base;
14257c2fbfb3SApril Chin 		shp->last_table = 0;
1426da2e3ebdSchin 	}
1427da2e3ebdSchin 	if(c= !isaletter(c))
1428da2e3ebdSchin 		goto skip;
14297c2fbfb3SApril Chin #if NVCACHE
14307c2fbfb3SApril Chin 	for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c])
14317c2fbfb3SApril Chin 	{
14327c2fbfb3SApril Chin 		if(xp->root!=root)
14337c2fbfb3SApril Chin 			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]=='+'))
14357c2fbfb3SApril Chin 		{
14367c2fbfb3SApril Chin 			sh_stats(STAT_NVHITS);
14377c2fbfb3SApril Chin 			np = xp->np;
14387c2fbfb3SApril Chin 			cp = (char*)name+xp->len;
1439*b30d1939SAndy Fiddaman 			if(nv_isarray(np) && !(flags&NV_MOVE))
14407c2fbfb3SApril Chin 				 nv_putsub(np,NIL(char*),ARRAY_UNDEF);
14417c2fbfb3SApril Chin 			shp->last_table = xp->last_table;
144234f9b3eeSRoland Mainz 			shp->last_root = xp->last_root;
14437c2fbfb3SApril Chin 			goto nocache;
14447c2fbfb3SApril Chin 		}
14457c2fbfb3SApril Chin 	}
14467c2fbfb3SApril Chin 	nvcache.ok = 1;
14477c2fbfb3SApril Chin #endif
1448da2e3ebdSchin 	np = nv_create(name, root, flags, &fun);
1449da2e3ebdSchin 	cp = fun.last;
14507c2fbfb3SApril Chin #if NVCACHE
14517c2fbfb3SApril Chin 	if(np && nvcache.ok && cp[-1]!=']')
14527c2fbfb3SApril Chin 	{
14537c2fbfb3SApril Chin 		xp = &nvcache.entries[nvcache.index];
14547c2fbfb3SApril Chin 		if(*cp)
14557c2fbfb3SApril Chin 		{
14567c2fbfb3SApril Chin 			char *sp = strchr(name,*cp);
14577c2fbfb3SApril Chin 			if(!sp)
14587c2fbfb3SApril Chin 				goto nocache;
14597c2fbfb3SApril Chin 			xp->len = sp-name;
14607c2fbfb3SApril Chin 		}
14617c2fbfb3SApril Chin 		else
14627c2fbfb3SApril Chin 			xp->len = strlen(name);
14637c2fbfb3SApril Chin 		c = roundof(xp->len+1,32);
14647c2fbfb3SApril Chin 		if(c > xp->size)
14657c2fbfb3SApril Chin 		{
14667c2fbfb3SApril Chin 			if(xp->size==0)
14677c2fbfb3SApril Chin 				xp->name = malloc(c);
14687c2fbfb3SApril Chin 			else
14697c2fbfb3SApril Chin 				xp->name = realloc(xp->name,c);
14707c2fbfb3SApril Chin 			xp->size = c;
14717c2fbfb3SApril Chin 		}
14727c2fbfb3SApril Chin 		memcpy(xp->name,name,xp->len);
14737c2fbfb3SApril Chin 		xp->name[xp->len] = 0;
14747c2fbfb3SApril Chin 		xp->root = root;
14757c2fbfb3SApril Chin 		xp->np = np;
1476*b30d1939SAndy Fiddaman 		xp->namespace = shp->namespace;
14777c2fbfb3SApril Chin 		xp->last_table = shp->last_table;
147834f9b3eeSRoland Mainz 		xp->last_root = shp->last_root;
14797c2fbfb3SApril Chin 		xp->flags = (flags&(NV_ARRAY|NV_NOSCOPE));
14807c2fbfb3SApril Chin 		nvcache.index = (nvcache.index+1)&(NVCACHE-1);
14817c2fbfb3SApril Chin 	}
14827c2fbfb3SApril Chin nocache:
14837c2fbfb3SApril Chin 	nvcache.ok = 0;
14847c2fbfb3SApril Chin #endif
1485da2e3ebdSchin 	if(fname)
1486da2e3ebdSchin 	{
1487da2e3ebdSchin 		c = ((flags&NV_NOSCOPE)?HASH_NOSCOPE:0)|((flags&NV_NOADD)?0:NV_ADD);
1488da2e3ebdSchin 		*fname = '.';
1489da2e3ebdSchin 		np = nv_search(name, funroot, c);
1490da2e3ebdSchin 		*fname = 0;
1491da2e3ebdSchin 	}
14927c2fbfb3SApril Chin 	else
1493da2e3ebdSchin 	{
14947c2fbfb3SApril Chin 		if(*cp=='.' && cp[1]=='.')
14957c2fbfb3SApril Chin 		{
14967c2fbfb3SApril Chin 			append |= NV_NODISC;
14977c2fbfb3SApril Chin 			cp+=2;
14987c2fbfb3SApril Chin 		}
14997c2fbfb3SApril Chin 		if(*cp=='+' && cp[1]=='=')
15007c2fbfb3SApril Chin 		{
15017c2fbfb3SApril Chin 			append |= NV_APPEND;
15027c2fbfb3SApril Chin 			cp++;
15037c2fbfb3SApril Chin 		}
1504da2e3ebdSchin 	}
1505da2e3ebdSchin 	c = *cp;
1506da2e3ebdSchin skip:
15077c2fbfb3SApril Chin #if SHOPT_TYPEDEF
15087c2fbfb3SApril Chin 	if(np && shp->mktype)
15097c2fbfb3SApril Chin 		np = nv_addnode(np,0);
15107c2fbfb3SApril Chin #endif /* SHOPT_TYPEDEF */
1511da2e3ebdSchin 	if(c=='=' && np && (flags&NV_ASSIGN))
1512da2e3ebdSchin 	{
1513da2e3ebdSchin 		cp++;
1514da2e3ebdSchin 		if(sh_isstate(SH_INIT))
1515da2e3ebdSchin 		{
1516da2e3ebdSchin 			nv_putval(np, cp, NV_RDONLY);
1517da2e3ebdSchin 			if(np==PWDNOD)
1518da2e3ebdSchin 				nv_onattr(np,NV_TAGGED);
1519da2e3ebdSchin 		}
1520da2e3ebdSchin 		else
1521da2e3ebdSchin 		{
15227c2fbfb3SApril Chin 			char *sub=0, *prefix= shp->prefix;
1523*b30d1939SAndy Fiddaman 			Namval_t *mp;
1524*b30d1939SAndy Fiddaman 			Namarr_t *ap;
15257c2fbfb3SApril Chin 			int isref;
15267c2fbfb3SApril Chin 			shp->prefix = 0;
15277c2fbfb3SApril Chin 			if((flags&NV_STATIC) && !shp->mktype)
15287c2fbfb3SApril Chin 			{
15297c2fbfb3SApril Chin 				if(!nv_isnull(np))
153034f9b3eeSRoland Mainz 				{
153134f9b3eeSRoland Mainz 					shp->prefix = prefix;
15327c2fbfb3SApril Chin 					return(np);
153334f9b3eeSRoland Mainz 				}
15347c2fbfb3SApril Chin 			}
15357c2fbfb3SApril Chin 			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
1539da2e3ebdSchin 			if(sh_isoption(SH_XTRACE) && nv_isarray(np))
1540*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1541da2e3ebdSchin 				sub = nv_getsub(np);
1542da2e3ebdSchin 			c = msg==e_aliname? 0: (append | (flags&NV_EXPORT));
15437c2fbfb3SApril Chin 			if(isref)
15447c2fbfb3SApril Chin 				nv_offattr(np,NV_REF);
154534f9b3eeSRoland Mainz 			if(!append && (flags&NV_UNJUST))
154634f9b3eeSRoland Mainz 			{
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);
156634f9b3eeSRoland Mainz 			}
1567da2e3ebdSchin 			nv_putval(np, cp, c);
15687c2fbfb3SApril Chin 			if(isref)
156934f9b3eeSRoland Mainz 			{
157034f9b3eeSRoland Mainz 				if(nv_search((char*)np,shp->var_base,HASH_BUCKET))
157134f9b3eeSRoland Mainz 					shp->last_root = shp->var_base;
15727c2fbfb3SApril Chin 				nv_setref(np,(Dt_t*)0,NV_VARNAME);
157334f9b3eeSRoland Mainz 			}
1574da2e3ebdSchin 			savesub = sub;
15757c2fbfb3SApril Chin 			shp->prefix = prefix;
1576da2e3ebdSchin 		}
1577da2e3ebdSchin 		nv_onattr(np, flags&NV_ATTRIBUTES);
1578da2e3ebdSchin 	}
1579da2e3ebdSchin 	else if(c)
1580da2e3ebdSchin 	{
1581da2e3ebdSchin 		if(flags&NV_NOFAIL)
1582da2e3ebdSchin 			return(0);
1583da2e3ebdSchin 		if(c=='.')
1584da2e3ebdSchin 			msg = e_noparent;
1585da2e3ebdSchin 		else if(c=='[')
1586da2e3ebdSchin 			msg = e_noarray;
1587da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),msg,name);
1588da2e3ebdSchin 	}
15897c2fbfb3SApril Chin 	if(fun.nofree&1)
1590da2e3ebdSchin 		stakseek(offset);
1591da2e3ebdSchin 	return(np);
1592da2e3ebdSchin }
1593da2e3ebdSchin 
1594da2e3ebdSchin #if SHOPT_MULTIBYTE
1595da2e3ebdSchin     static int ja_size(char*, int, int);
1596da2e3ebdSchin     static void ja_restore(void);
1597da2e3ebdSchin     static char *savep;
1598da2e3ebdSchin     static char savechars[8+1];
1599da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1600da2e3ebdSchin 
1601da2e3ebdSchin /*
1602da2e3ebdSchin  * put value <string> into name-value node <np>.
1603da2e3ebdSchin  * If <np> is an array, then the element given by the
1604da2e3ebdSchin  *   current index is assigned to.
1605da2e3ebdSchin  * If <flags> contains NV_RDONLY, readonly attribute is ignored
1606da2e3ebdSchin  * If <flags> contains NV_INTEGER, string is a pointer to a number
1607da2e3ebdSchin  * If <flags> contains NV_NOFREE, previous value is freed, and <string>
1608da2e3ebdSchin  * becomes value of node and <flags> becomes attributes
1609da2e3ebdSchin  */
nv_putval(register Namval_t * np,const char * string,int flags)1610da2e3ebdSchin void nv_putval(register Namval_t *np, const char *string, int flags)
1611da2e3ebdSchin {
1612*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
1613da2e3ebdSchin 	register const char *sp=string;
1614da2e3ebdSchin 	register union Value *up;
1615da2e3ebdSchin 	register char *cp;
1616da2e3ebdSchin 	register int size = 0;
1617da2e3ebdSchin 	register int dot;
1618da2e3ebdSchin 	int	was_local = nv_local;
16197c2fbfb3SApril Chin 	union Value u;
1620*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
1621*b30d1939SAndy Fiddaman 	Namarr_t	*ap;
1622*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
1623da2e3ebdSchin 	if(!(flags&NV_RDONLY) && nv_isattr (np, NV_RDONLY))
1624da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
1625da2e3ebdSchin 	/* The following could cause the shell to fork if assignment
1626da2e3ebdSchin 	 * would cause a side effect
1627da2e3ebdSchin 	 */
1628*b30d1939SAndy Fiddaman 	shp->argaddr = 0;
1629*b30d1939SAndy Fiddaman 	if(shp->subshell && !nv_local && !(flags&NV_RDONLY))
1630da2e3ebdSchin 		np = sh_assignok(np,1);
163134f9b3eeSRoland Mainz 	if(np->nvfun && np->nvfun->disc && !(flags&NV_NODISC) && !nv_isref(np))
1632da2e3ebdSchin 	{
1633da2e3ebdSchin 		/* This function contains disc */
1634da2e3ebdSchin 		if(!nv_local)
1635da2e3ebdSchin 		{
1636da2e3ebdSchin 			nv_local=1;
1637da2e3ebdSchin 			nv_putv(np,sp,flags,np->nvfun);
1638da2e3ebdSchin 			if(sp && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT)))
1639*b30d1939SAndy Fiddaman 				sh_envput(shp->env,np);
1640da2e3ebdSchin 			return;
1641da2e3ebdSchin 		}
1642da2e3ebdSchin 		/* called from disc, assign the actual value */
1643da2e3ebdSchin 	}
1644da2e3ebdSchin 	flags &= ~NV_NODISC;
16457c2fbfb3SApril Chin 	nv_local=0;
1646da2e3ebdSchin 	if(flags&(NV_NOREF|NV_NOFREE))
1647da2e3ebdSchin 	{
16487c2fbfb3SApril Chin 		if(np->nvalue.cp && np->nvalue.cp!=sp && !nv_isattr(np,NV_NOFREE))
16497c2fbfb3SApril Chin 			free((void*)np->nvalue.cp);
1650da2e3ebdSchin 		np->nvalue.cp = (char*)sp;
1651da2e3ebdSchin 		nv_setattr(np,(flags&~NV_RDONLY)|NV_NOFREE);
1652da2e3ebdSchin 		return;
1653da2e3ebdSchin 	}
1654da2e3ebdSchin 	up= &np->nvalue;
16557c2fbfb3SApril Chin 	if(nv_isattr(np,NV_INT16P) == NV_INT16)
16567c2fbfb3SApril Chin 	{
16577c2fbfb3SApril Chin 		if(!np->nvalue.up || !nv_isarray(np))
16587c2fbfb3SApril Chin 		{
16597c2fbfb3SApril Chin 			up = &u;
16607c2fbfb3SApril Chin 			up->up = &np->nvalue;
16617c2fbfb3SApril Chin 		}
16627c2fbfb3SApril Chin 	}
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
16667c2fbfb3SApril Chin 	else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np))
1667*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
16687c2fbfb3SApril Chin 		up = np->nvalue.up;
16697c2fbfb3SApril Chin 	if(up && up->cp==Empty)
16707c2fbfb3SApril Chin 		up->cp = 0;
1671da2e3ebdSchin 	if(nv_isattr(np,NV_EXPORT))
1672da2e3ebdSchin 		nv_offattr(np,NV_IMPORT);
1673da2e3ebdSchin 	if(nv_isattr (np, NV_INTEGER))
1674da2e3ebdSchin 	{
16757c2fbfb3SApril Chin 		if(nv_isattr(np, NV_DOUBLE) == NV_DOUBLE)
1676da2e3ebdSchin 		{
1677da2e3ebdSchin 			if(nv_isattr(np, NV_LONG) && sizeof(double)<sizeof(Sfdouble_t))
1678da2e3ebdSchin 			{
1679da2e3ebdSchin 				Sfdouble_t ld, old=0;
1680da2e3ebdSchin 				if(flags&NV_INTEGER)
1681da2e3ebdSchin 				{
1682da2e3ebdSchin 					if(flags&NV_LONG)
1683da2e3ebdSchin 						ld = *((Sfdouble_t*)sp);
1684da2e3ebdSchin 					else if(flags&NV_SHORT)
1685da2e3ebdSchin 						ld = *((float*)sp);
1686da2e3ebdSchin 					else
1687da2e3ebdSchin 						ld = *((double*)sp);
1688da2e3ebdSchin 				}
1689da2e3ebdSchin 				else
1690*b30d1939SAndy Fiddaman 					ld = sh_arith(shp,sp);
1691da2e3ebdSchin 				if(!up->ldp)
1692da2e3ebdSchin 					up->ldp = new_of(Sfdouble_t,0);
1693da2e3ebdSchin 				else if(flags&NV_APPEND)
1694da2e3ebdSchin 					old = *(up->ldp);
169534f9b3eeSRoland Mainz 				*(up->ldp) = old?ld+old:ld;
1696da2e3ebdSchin 			}
1697da2e3ebdSchin 			else
1698da2e3ebdSchin 			{
1699da2e3ebdSchin 				double d,od=0;
1700da2e3ebdSchin 				if(flags&NV_INTEGER)
1701da2e3ebdSchin 				{
1702da2e3ebdSchin 					if(flags&NV_LONG)
1703da2e3ebdSchin 						d = (double)(*(Sfdouble_t*)sp);
1704da2e3ebdSchin 					else if(flags&NV_SHORT)
1705da2e3ebdSchin 						d = (double)(*(float*)sp);
1706da2e3ebdSchin 					else
1707da2e3ebdSchin 						d = *(double*)sp;
1708da2e3ebdSchin 				}
1709da2e3ebdSchin 				else
1710*b30d1939SAndy Fiddaman 					d = sh_arith(shp,sp);
1711da2e3ebdSchin 				if(!up->dp)
1712da2e3ebdSchin 					up->dp = new_of(double,0);
1713da2e3ebdSchin 				else if(flags&NV_APPEND)
1714da2e3ebdSchin 					od = *(up->dp);
171534f9b3eeSRoland Mainz 				*(up->dp) = od?d+od:d;
1716da2e3ebdSchin 			}
1717da2e3ebdSchin 		}
1718da2e3ebdSchin 		else
1719da2e3ebdSchin 		{
1720da2e3ebdSchin 			if(nv_isattr(np, NV_LONG) && sizeof(int32_t)<sizeof(Sflong_t))
1721da2e3ebdSchin 			{
1722da2e3ebdSchin 				Sflong_t ll=0,oll=0;
1723da2e3ebdSchin 				if(flags&NV_INTEGER)
1724da2e3ebdSchin 				{
17257c2fbfb3SApril Chin 					if((flags&NV_DOUBLE) == NV_DOUBLE)
1726da2e3ebdSchin 					{
1727da2e3ebdSchin 						if(flags&NV_LONG)
1728da2e3ebdSchin 							ll = *((Sfdouble_t*)sp);
1729da2e3ebdSchin 						else if(flags&NV_SHORT)
1730da2e3ebdSchin 							ll = *((float*)sp);
1731da2e3ebdSchin 						else
1732da2e3ebdSchin 							ll = *((double*)sp);
1733da2e3ebdSchin 					}
1734da2e3ebdSchin 					else if(nv_isattr(np,NV_UNSIGN))
1735da2e3ebdSchin 					{
1736da2e3ebdSchin 						if(flags&NV_LONG)
1737da2e3ebdSchin 							ll = *((Sfulong_t*)sp);
1738da2e3ebdSchin 						else if(flags&NV_SHORT)
1739da2e3ebdSchin 							ll = *((uint16_t*)sp);
1740da2e3ebdSchin 						else
1741da2e3ebdSchin 							ll = *((uint32_t*)sp);
1742da2e3ebdSchin 					}
1743da2e3ebdSchin 					else
1744da2e3ebdSchin 					{
1745da2e3ebdSchin 						if(flags&NV_LONG)
1746da2e3ebdSchin 							ll = *((Sflong_t*)sp);
1747da2e3ebdSchin 						else if(flags&NV_SHORT)
1748da2e3ebdSchin 							ll = *((uint16_t*)sp);
1749da2e3ebdSchin 						else
1750da2e3ebdSchin 							ll = *((uint32_t*)sp);
1751da2e3ebdSchin 					}
1752da2e3ebdSchin 				}
1753da2e3ebdSchin 				else if(sp)
1754*b30d1939SAndy Fiddaman 					ll = (Sflong_t)sh_arith(shp,sp);
1755da2e3ebdSchin 				if(!up->llp)
1756da2e3ebdSchin 					up->llp = new_of(Sflong_t,0);
1757da2e3ebdSchin 				else if(flags&NV_APPEND)
1758da2e3ebdSchin 					oll = *(up->llp);
1759da2e3ebdSchin 				*(up->llp) = ll+oll;
1760da2e3ebdSchin 			}
1761da2e3ebdSchin 			else
1762da2e3ebdSchin 			{
1763da2e3ebdSchin 				int32_t l=0,ol=0;
1764da2e3ebdSchin 				if(flags&NV_INTEGER)
1765da2e3ebdSchin 				{
17667c2fbfb3SApril Chin 					if((flags&NV_DOUBLE) == NV_DOUBLE)
1767da2e3ebdSchin 					{
1768da2e3ebdSchin 						Sflong_t ll;
1769da2e3ebdSchin 						if(flags&NV_LONG)
1770da2e3ebdSchin 							ll = *((Sfdouble_t*)sp);
1771da2e3ebdSchin 						else if(flags&NV_SHORT)
1772da2e3ebdSchin 							ll = *((float*)sp);
1773da2e3ebdSchin 						else
1774da2e3ebdSchin 							ll = *((double*)sp);
1775da2e3ebdSchin 						l = (int32_t)ll;
1776da2e3ebdSchin 					}
1777da2e3ebdSchin 					else if(nv_isattr(np,NV_UNSIGN))
1778da2e3ebdSchin 					{
1779da2e3ebdSchin 						if(flags&NV_LONG)
1780da2e3ebdSchin 							l = *((Sfulong_t*)sp);
1781da2e3ebdSchin 						else if(flags&NV_SHORT)
1782da2e3ebdSchin 							l = *((uint16_t*)sp);
1783da2e3ebdSchin 						else
1784da2e3ebdSchin 							l = *(uint32_t*)sp;
1785da2e3ebdSchin 					}
1786da2e3ebdSchin 					else
1787da2e3ebdSchin 					{
1788da2e3ebdSchin 						if(flags&NV_LONG)
1789da2e3ebdSchin 							l = *((Sflong_t*)sp);
1790da2e3ebdSchin 						else if(flags&NV_SHORT)
1791da2e3ebdSchin 							l = *((int16_t*)sp);
1792da2e3ebdSchin 						else
1793da2e3ebdSchin 							l = *(int32_t*)sp;
1794da2e3ebdSchin 					}
1795da2e3ebdSchin 				}
1796da2e3ebdSchin 				else if(sp)
1797da2e3ebdSchin 				{
1798*b30d1939SAndy Fiddaman 					Sfdouble_t ld = sh_arith(shp,sp);
1799da2e3ebdSchin 					if(ld<0)
1800da2e3ebdSchin 						l = (int32_t)ld;
1801da2e3ebdSchin 					else
1802da2e3ebdSchin 						l = (uint32_t)ld;
1803da2e3ebdSchin 				}
1804da2e3ebdSchin 				if(nv_size(np) <= 1)
1805da2e3ebdSchin 					nv_setsize(np,10);
1806da2e3ebdSchin 				if(nv_isattr (np, NV_SHORT))
1807da2e3ebdSchin 				{
1808da2e3ebdSchin 					int16_t s=0;
1809da2e3ebdSchin 					if(flags&NV_APPEND)
18107c2fbfb3SApril Chin 						s = *up->sp;
18117c2fbfb3SApril Chin 					*(up->sp) = s+(int16_t)l;
1812da2e3ebdSchin 					nv_onattr(np,NV_NOFREE);
1813da2e3ebdSchin 				}
1814da2e3ebdSchin 				else
1815da2e3ebdSchin 				{
1816da2e3ebdSchin 					if(!up->lp)
1817da2e3ebdSchin 						up->lp = new_of(int32_t,0);
1818da2e3ebdSchin 					else if(flags&NV_APPEND)
1819da2e3ebdSchin 						ol =  *(up->lp);
1820da2e3ebdSchin 					*(up->lp) = l+ol;
1821da2e3ebdSchin 				}
1822da2e3ebdSchin 			}
1823da2e3ebdSchin 		}
1824da2e3ebdSchin 	}
1825da2e3ebdSchin 	else
1826da2e3ebdSchin 	{
1827da2e3ebdSchin 		const char *tofree=0;
1828*b30d1939SAndy Fiddaman 		int offset,append;
1829da2e3ebdSchin #if _lib_pathnative
1830da2e3ebdSchin 		char buff[PATH_MAX];
1831da2e3ebdSchin #endif /* _lib_pathnative */
1832da2e3ebdSchin 		if(flags&NV_INTEGER)
1833da2e3ebdSchin 		{
18347c2fbfb3SApril Chin 			if((flags&NV_DOUBLE)==NV_DOUBLE)
1835da2e3ebdSchin 			{
1836da2e3ebdSchin 				if(flags&NV_LONG)
1837*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%.*Lg",LDBL_DIG,*((Sfdouble_t*)sp));
1838da2e3ebdSchin 				else
1839*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%.*g",DBL_DIG,*((double*)sp));
1840da2e3ebdSchin 			}
18417c2fbfb3SApril Chin 			else if(flags&NV_UNSIGN)
18427c2fbfb3SApril Chin 			{
18437c2fbfb3SApril Chin 				if(flags&NV_LONG)
1844*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%I*lu",sizeof(Sfulong_t),*((Sfulong_t*)sp));
18457c2fbfb3SApril Chin 				else
1846*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%lu",(unsigned long)((flags&NV_SHORT)?*((uint16_t*)sp):*((uint32_t*)sp)));
18477c2fbfb3SApril Chin 			}
1848da2e3ebdSchin 			else
18497c2fbfb3SApril Chin 			{
18507c2fbfb3SApril Chin 				if(flags&NV_LONG)
1851*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%I*ld",sizeof(Sflong_t),*((Sflong_t*)sp));
18527c2fbfb3SApril Chin 				else
1853*b30d1939SAndy Fiddaman 					sfprintf(shp->strbuf,"%ld",(long)((flags&NV_SHORT)?*((int16_t*)sp):*((int32_t*)sp)));
18547c2fbfb3SApril Chin 			}
1855*b30d1939SAndy Fiddaman 			sp = sfstruse(shp->strbuf);
1856da2e3ebdSchin 		}
18577c2fbfb3SApril Chin 		if(nv_isattr(np, NV_HOST|NV_INTEGER)==NV_HOST && sp)
1858da2e3ebdSchin 		{
1859da2e3ebdSchin #ifdef _lib_pathnative
1860da2e3ebdSchin 			/*
1861da2e3ebdSchin 			 * return the host file name given the UNIX name
1862da2e3ebdSchin 			 */
1863da2e3ebdSchin 			pathnative(sp,buff,sizeof(buff));
1864da2e3ebdSchin 			if(buff[1]==':' && buff[2]=='/')
1865da2e3ebdSchin 			{
1866da2e3ebdSchin 				buff[2] = '\\';
1867da2e3ebdSchin 				if(*buff>='A' &&  *buff<='Z')
1868da2e3ebdSchin 					*buff += 'a'-'A';
1869da2e3ebdSchin 			}
1870da2e3ebdSchin 			sp = buff;
1871da2e3ebdSchin #else
1872da2e3ebdSchin 			;
1873da2e3ebdSchin #endif /* _lib_pathnative */
1874da2e3ebdSchin 		}
1875da2e3ebdSchin 		else if((nv_isattr(np, NV_RJUST|NV_ZFILL|NV_LJUST)) && sp)
1876da2e3ebdSchin 		{
1877da2e3ebdSchin 			for(;*sp == ' '|| *sp=='\t';sp++);
1878da2e3ebdSchin 	        	if((nv_isattr(np,NV_ZFILL)) && (nv_isattr(np,NV_LJUST)))
1879da2e3ebdSchin 				for(;*sp=='0';sp++);
1880da2e3ebdSchin 			size = nv_size(np);
1881da2e3ebdSchin #if SHOPT_MULTIBYTE
1882da2e3ebdSchin 			if(size)
1883da2e3ebdSchin 				size = ja_size((char*)sp,size,nv_isattr(np,NV_RJUST|NV_ZFILL));
1884da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
1885da2e3ebdSchin 		}
1886*b30d1939SAndy Fiddaman 		if(!up->cp || *up->cp==0)
1887da2e3ebdSchin 			flags &= ~NV_APPEND;
1888da2e3ebdSchin 		if(!nv_isattr(np, NV_NOFREE))
1889da2e3ebdSchin 		{
1890da2e3ebdSchin 			/* delay free in case <sp> points into free region */
1891da2e3ebdSchin 			tofree = up->cp;
1892da2e3ebdSchin 		}
18937c2fbfb3SApril Chin 		if(nv_isattr(np,NV_BINARY) && !(flags&NV_RAW))
18947c2fbfb3SApril Chin 			tofree = 0;
18953e14f97fSRoger A. Faulkner 		if(nv_isattr(np,NV_LJUST|NV_RJUST) && nv_isattr(np,NV_LJUST|NV_RJUST)!=(NV_LJUST|NV_RJUST))
18967c2fbfb3SApril Chin 			tofree = 0;
1897da2e3ebdSchin        	 	if (sp)
1898da2e3ebdSchin 		{
1899*b30d1939SAndy Fiddaman 			append=0;
1900*b30d1939SAndy Fiddaman 			if(sp==up->cp && !(flags&NV_APPEND))
1901*b30d1939SAndy Fiddaman 				return;
1902da2e3ebdSchin 			dot = strlen(sp);
1903da2e3ebdSchin #if (_AST_VERSION>=20030127L)
1904da2e3ebdSchin 			if(nv_isattr(np,NV_BINARY))
1905da2e3ebdSchin 			{
1906da2e3ebdSchin 				int oldsize = (flags&NV_APPEND)?nv_size(np):0;
1907da2e3ebdSchin 				if(flags&NV_RAW)
1908da2e3ebdSchin 				{
1909da2e3ebdSchin 					if(tofree)
19107c2fbfb3SApril Chin 					{
1911da2e3ebdSchin 						free((void*)tofree);
19127c2fbfb3SApril Chin 						nv_offattr(np,NV_NOFREE);
19137c2fbfb3SApril Chin 					}
1914da2e3ebdSchin 					up->cp = sp;
1915da2e3ebdSchin 					return;
1916da2e3ebdSchin 				}
1917da2e3ebdSchin 				size = 0;
1918da2e3ebdSchin 				if(nv_isattr(np,NV_ZFILL))
1919da2e3ebdSchin 					size = nv_size(np);
1920da2e3ebdSchin 				if(size==0)
1921da2e3ebdSchin 					size = oldsize + (3*dot/4);
1922*b30d1939SAndy Fiddaman 				*(cp = (char*)malloc(size+1)) = 0;
19237c2fbfb3SApril Chin 				nv_offattr(np,NV_NOFREE);
1924da2e3ebdSchin 				if(oldsize)
1925da2e3ebdSchin 					memcpy((void*)cp,(void*)up->cp,oldsize);
1926da2e3ebdSchin 				up->cp = cp;
1927da2e3ebdSchin 				if(size <= oldsize)
1928da2e3ebdSchin 					return;
1929da2e3ebdSchin 				dot = base64decode(sp,dot, (void**)0, cp+oldsize, size-oldsize,(void**)0);
1930da2e3ebdSchin 				dot += oldsize;
1931da2e3ebdSchin 				if(!nv_isattr(np,NV_ZFILL) || nv_size(np)==0)
1932da2e3ebdSchin 					nv_setsize(np,dot);
1933da2e3ebdSchin 				else if(nv_isattr(np,NV_ZFILL) && (size>dot))
1934da2e3ebdSchin 					memset((void*)&cp[dot],0,size-dot);
1935da2e3ebdSchin 				return;
1936da2e3ebdSchin 			}
1937da2e3ebdSchin 			else
1938da2e3ebdSchin #endif
19397c2fbfb3SApril Chin 			{
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 				}
19897c2fbfb3SApril Chin 			}
19907c2fbfb3SApril Chin 
1991da2e3ebdSchin 		}
1992da2e3ebdSchin 		else
1993da2e3ebdSchin 			cp = 0;
1994da2e3ebdSchin 		up->cp = cp;
1995da2e3ebdSchin 		if(sp)
1996da2e3ebdSchin 		{
1997*b30d1939SAndy Fiddaman 			int c = cp[dot+append];
1998*b30d1939SAndy Fiddaman 			memmove(cp+append,sp,dot);
1999*b30d1939SAndy Fiddaman 			cp[dot+append] = c;
2000da2e3ebdSchin 			if(nv_isattr(np, NV_RJUST) && nv_isattr(np, NV_ZFILL))
2001da2e3ebdSchin 				rightjust(cp,size,'0');
20023e14f97fSRoger A. Faulkner 			else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_RJUST)
2003da2e3ebdSchin 				rightjust(cp,size,' ');
20043e14f97fSRoger A. Faulkner 			else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_LJUST)
2005da2e3ebdSchin 			{
2006da2e3ebdSchin 				register char *dp;
2007da2e3ebdSchin 				dp = strlen (cp) + cp;
20087c2fbfb3SApril Chin 				cp = cp+size;
2009da2e3ebdSchin 				for (; dp < cp; *dp++ = ' ');
2010da2e3ebdSchin 			 }
2011da2e3ebdSchin #if SHOPT_MULTIBYTE
2012da2e3ebdSchin 			/* restore original string */
2013da2e3ebdSchin 			if(savep)
2014da2e3ebdSchin 				ja_restore();
2015da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
2016da2e3ebdSchin 		}
2017da2e3ebdSchin 		if(flags&NV_APPEND)
2018da2e3ebdSchin 			stakseek(offset);
2019*b30d1939SAndy Fiddaman 		if(tofree && tofree!=Empty && tofree!=Null)
2020da2e3ebdSchin 			free((void*)tofree);
2021da2e3ebdSchin 	}
2022da2e3ebdSchin 	if(!was_local && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT)))
2023*b30d1939SAndy Fiddaman 		sh_envput(shp->env,np);
2024da2e3ebdSchin 	return;
2025da2e3ebdSchin }
2026da2e3ebdSchin 
2027da2e3ebdSchin /*
2028da2e3ebdSchin  *
2029da2e3ebdSchin  *   Right-justify <str> so that it contains no more than
2030da2e3ebdSchin  *   <size> characters.  If <str> contains fewer than <size>
2031da2e3ebdSchin  *   characters, left-pad with <fill>.  Trailing blanks
2032da2e3ebdSchin  *   in <str> will be ignored.
2033da2e3ebdSchin  *
2034da2e3ebdSchin  *   If the leftmost digit in <str> is not a digit, <fill>
2035da2e3ebdSchin  *   will default to a blank.
2036da2e3ebdSchin  */
rightjust(char * str,int size,int fill)2037da2e3ebdSchin static void rightjust(char *str, int size, int fill)
2038da2e3ebdSchin {
2039da2e3ebdSchin 	register int n;
2040da2e3ebdSchin 	register char *cp,*sp;
2041da2e3ebdSchin 	n = strlen(str);
2042da2e3ebdSchin 
2043da2e3ebdSchin 	/* ignore trailing blanks */
2044da2e3ebdSchin 	for(cp=str+n;n && *--cp == ' ';n--);
2045da2e3ebdSchin 	if (n == size)
2046da2e3ebdSchin 		return;
2047da2e3ebdSchin 	if(n > size)
2048da2e3ebdSchin         {
2049da2e3ebdSchin         	*(str+n) = 0;
2050da2e3ebdSchin         	for (sp = str, cp = str+n-size; sp <= str+size; *sp++ = *cp++);
2051da2e3ebdSchin         	return;
2052da2e3ebdSchin         }
2053da2e3ebdSchin 	else *(sp = str+size) = 0;
2054da2e3ebdSchin 	if (n == 0)
2055da2e3ebdSchin         {
2056da2e3ebdSchin         	while (sp > str)
2057da2e3ebdSchin                		*--sp = ' ';
2058da2e3ebdSchin         	return;
2059da2e3ebdSchin         }
2060da2e3ebdSchin 	while(n--)
2061da2e3ebdSchin 	{
2062da2e3ebdSchin 		sp--;
2063da2e3ebdSchin 		*sp = *cp--;
2064da2e3ebdSchin 	}
2065da2e3ebdSchin 	if(!isdigit(*str))
2066da2e3ebdSchin 		fill = ' ';
2067da2e3ebdSchin 	while(sp>str)
2068da2e3ebdSchin 		*--sp = fill;
2069da2e3ebdSchin 	return;
2070da2e3ebdSchin }
2071da2e3ebdSchin 
2072da2e3ebdSchin #if SHOPT_MULTIBYTE
2073da2e3ebdSchin     /*
2074da2e3ebdSchin      * handle left and right justified fields for multi-byte chars
2075da2e3ebdSchin      * given physical size, return a logical size which reflects the
2076da2e3ebdSchin      * screen width of multi-byte characters
2077da2e3ebdSchin      * Multi-width characters replaced by spaces if they cross the boundary
2078da2e3ebdSchin      * <type> is non-zero for right justified  fields
2079da2e3ebdSchin      */
2080da2e3ebdSchin 
ja_size(char * str,int size,int type)2081da2e3ebdSchin     static int ja_size(char *str,int size,int type)
2082da2e3ebdSchin     {
2083da2e3ebdSchin 	register char *cp = str;
2084da2e3ebdSchin 	register int c, n=size;
2085da2e3ebdSchin 	register int outsize;
2086da2e3ebdSchin 	register char *oldcp=cp;
2087da2e3ebdSchin 	int oldn;
2088da2e3ebdSchin 	wchar_t w;
2089da2e3ebdSchin 	while(*cp)
2090da2e3ebdSchin 	{
2091da2e3ebdSchin 		oldn = n;
2092da2e3ebdSchin 		w = mbchar(cp);
2093*b30d1939SAndy Fiddaman 		if((outsize = mbwidth(w)) <0)
2094*b30d1939SAndy Fiddaman 			outsize = 0;
2095da2e3ebdSchin 		size -= outsize;
2096da2e3ebdSchin 		c = cp-oldcp;
2097da2e3ebdSchin 		n += (c-outsize);
2098da2e3ebdSchin 		oldcp = cp;
2099da2e3ebdSchin 		if(size<=0 && type==0)
2100da2e3ebdSchin 			break;
2101da2e3ebdSchin 	}
2102da2e3ebdSchin 	/* check for right justified fields that need truncating */
2103da2e3ebdSchin 	if(size <0)
2104da2e3ebdSchin 	{
2105da2e3ebdSchin 		if(type==0)
2106da2e3ebdSchin 		{
2107da2e3ebdSchin 			/* left justified and character crosses field boundary */
2108da2e3ebdSchin 			n = oldn;
2109da2e3ebdSchin 			/* save boundary char and replace with spaces */
2110da2e3ebdSchin 			size = c;
2111da2e3ebdSchin 			savechars[size] = 0;
2112da2e3ebdSchin 			while(size--)
2113da2e3ebdSchin 			{
2114da2e3ebdSchin 				savechars[size] = cp[size];
2115da2e3ebdSchin 				cp[size] = ' ';
2116da2e3ebdSchin 			}
2117da2e3ebdSchin 			savep = cp;
2118da2e3ebdSchin 		}
2119da2e3ebdSchin 		size = -size;
2120da2e3ebdSchin 		if(type)
2121da2e3ebdSchin 			n -= (ja_size(str,size,0)-size);
2122da2e3ebdSchin 	}
2123da2e3ebdSchin 	return(n);
2124da2e3ebdSchin     }
2125da2e3ebdSchin 
ja_restore(void)2126da2e3ebdSchin     static void ja_restore(void)
2127da2e3ebdSchin     {
2128da2e3ebdSchin 	register char *cp = savechars;
2129da2e3ebdSchin 	while(*cp)
2130da2e3ebdSchin 		*savep++ = *cp++;
2131da2e3ebdSchin 	savep = 0;
2132da2e3ebdSchin     }
2133da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
2134da2e3ebdSchin 
2135da2e3ebdSchin #ifndef _ENV_H
staknam(register Namval_t * np,char * value)2136da2e3ebdSchin static char *staknam(register Namval_t *np, char *value)
2137da2e3ebdSchin {
2138da2e3ebdSchin 	register char *p,*q;
2139da2e3ebdSchin 	q = stakalloc(strlen(nv_name(np))+(value?strlen(value):0)+2);
2140da2e3ebdSchin 	p=strcopy(q,nv_name(np));
2141da2e3ebdSchin 	if(value)
2142da2e3ebdSchin 	{
2143da2e3ebdSchin 		*p++ = '=';
2144da2e3ebdSchin 		strcpy(p,value);
2145da2e3ebdSchin 	}
2146da2e3ebdSchin 	return(q);
2147da2e3ebdSchin }
2148da2e3ebdSchin #endif
2149da2e3ebdSchin 
2150da2e3ebdSchin /*
2151da2e3ebdSchin  * put the name and attribute into value of attributes variable
2152da2e3ebdSchin  */
2153da2e3ebdSchin #ifdef _ENV_H
attstore(register Namval_t * np,void * data)2154da2e3ebdSchin static void attstore(register Namval_t *np, void *data)
2155da2e3ebdSchin {
2156da2e3ebdSchin 	register int flag, c = ' ';
2157da2e3ebdSchin 	NOT_USED(data);
2158da2e3ebdSchin 	if(!(nv_isattr(np,NV_EXPORT)))
2159da2e3ebdSchin 		return;
2160da2e3ebdSchin 	flag = nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER);
2161da2e3ebdSchin 	stakputc('=');
21627c2fbfb3SApril Chin 	if((flag&NV_DOUBLE) == NV_DOUBLE)
2163da2e3ebdSchin 	{
2164da2e3ebdSchin 		/* export doubles as integers for ksh88 compatibility */
21657c2fbfb3SApril Chin 		stakputc(c+NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE)));
2166da2e3ebdSchin 	}
2167da2e3ebdSchin 	else
2168da2e3ebdSchin 	{
2169da2e3ebdSchin 		stakputc(c+flag);
2170da2e3ebdSchin 		if(flag&NV_INTEGER)
2171da2e3ebdSchin 			c +=  nv_size(np);
2172da2e3ebdSchin 	}
2173da2e3ebdSchin 	stakputc(c);
2174da2e3ebdSchin 	stakputs(nv_name(np));
2175da2e3ebdSchin }
2176da2e3ebdSchin #else
attstore(register Namval_t * np,void * data)2177da2e3ebdSchin static void attstore(register Namval_t *np, void *data)
2178da2e3ebdSchin {
2179da2e3ebdSchin 	register int flag = np->nvflag;
2180da2e3ebdSchin 	register struct adata *ap = (struct adata*)data;
2181*b30d1939SAndy Fiddaman 	ap->sh = sh_getinterp();
21827c2fbfb3SApril Chin 	ap->tp = 0;
2183da2e3ebdSchin 	if(!(flag&NV_EXPORT) || (flag&NV_FUNCT))
2184da2e3ebdSchin 		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 	}
2191da2e3ebdSchin 	flag &= (NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER);
2192da2e3ebdSchin 	*ap->attval++ = '=';
21937c2fbfb3SApril Chin 	if((flag&NV_DOUBLE) == NV_DOUBLE)
2194da2e3ebdSchin 	{
2195da2e3ebdSchin 		/* export doubles as integers for ksh88 compatibility */
21967c2fbfb3SApril Chin 		*ap->attval++ = ' '+ NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE));
2197da2e3ebdSchin 		*ap->attval = ' ';
2198da2e3ebdSchin 	}
2199da2e3ebdSchin 	else
2200da2e3ebdSchin 	{
2201da2e3ebdSchin 		*ap->attval++ = ' '+flag;
2202da2e3ebdSchin 		if(flag&NV_INTEGER)
2203da2e3ebdSchin 			*ap->attval = ' ' + nv_size(np);
2204da2e3ebdSchin 		else
2205da2e3ebdSchin 			*ap->attval = ' ';
2206da2e3ebdSchin 	}
2207da2e3ebdSchin 	ap->attval = strcopy(++ap->attval,nv_name(np));
2208da2e3ebdSchin }
2209da2e3ebdSchin #endif
2210da2e3ebdSchin 
2211da2e3ebdSchin #ifndef _ENV_H
pushnam(Namval_t * np,void * data)2212da2e3ebdSchin static void pushnam(Namval_t *np, void *data)
2213da2e3ebdSchin {
2214da2e3ebdSchin 	register char *value;
2215da2e3ebdSchin 	register struct adata *ap = (struct adata*)data;
2216*b30d1939SAndy Fiddaman 	ap->sh = sh_getinterp();
22177c2fbfb3SApril Chin 	ap->tp = 0;
22183e14f97fSRoger A. Faulkner 	if(nv_isattr(np,NV_IMPORT) && np->nvenv)
22193e14f97fSRoger A. Faulkner 		*ap->argnam++ = np->nvenv;
2220da2e3ebdSchin 	else if(value=nv_getval(np))
2221da2e3ebdSchin 		*ap->argnam++ = staknam(np,value);
2222da2e3ebdSchin 	if(nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER))
2223da2e3ebdSchin 		ap->attsize += (strlen(nv_name(np))+4);
2224da2e3ebdSchin }
2225da2e3ebdSchin #endif
2226da2e3ebdSchin 
2227da2e3ebdSchin /*
2228da2e3ebdSchin  * Generate the environment list for the child.
2229da2e3ebdSchin  */
2230da2e3ebdSchin 
2231da2e3ebdSchin #ifdef _ENV_H
sh_envgen(void)2232da2e3ebdSchin char **sh_envgen(void)
2233da2e3ebdSchin {
2234*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2235da2e3ebdSchin 	int offset,tell;
2236da2e3ebdSchin 	register char **er;
2237*b30d1939SAndy Fiddaman 	env_delete(shp->env,"_");
2238*b30d1939SAndy Fiddaman 	er = env_get(shp->env);
2239da2e3ebdSchin 	offset = staktell();
2240da2e3ebdSchin 	stakputs(e_envmarker);
2241da2e3ebdSchin 	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));
2243da2e3ebdSchin 	if(tell ==staktell())
2244da2e3ebdSchin 		stakseek(offset);
2245da2e3ebdSchin 	else
2246da2e3ebdSchin 		*--er = stakfreeze(1)+offset;
2247da2e3ebdSchin 	return(er);
2248da2e3ebdSchin }
2249da2e3ebdSchin #else
sh_envgen(void)2250da2e3ebdSchin char **sh_envgen(void)
2251da2e3ebdSchin {
2252da2e3ebdSchin 	register char **er;
2253da2e3ebdSchin 	register int namec;
2254da2e3ebdSchin 	register char *cp;
2255da2e3ebdSchin 	struct adata data;
22567c2fbfb3SApril Chin 	Shell_t	*shp = sh_getinterp();
22577c2fbfb3SApril Chin 	data.sh = shp;
22587c2fbfb3SApril Chin 	data.tp = 0;
2259*b30d1939SAndy Fiddaman 	data.mapname = 0;
2260da2e3ebdSchin 	/* L_ARGNOD gets generated automatically as full path name of command */
2261da2e3ebdSchin 	nv_offattr(L_ARGNOD,NV_EXPORT);
2262da2e3ebdSchin 	data.attsize = 6;
22637c2fbfb3SApril Chin 	namec = nv_scan(shp->var_tree,nullscan,(void*)0,NV_EXPORT,NV_EXPORT);
22647c2fbfb3SApril Chin 	namec += shp->nenv;
2265da2e3ebdSchin 	er = (char**)stakalloc((namec+4)*sizeof(char*));
22667c2fbfb3SApril Chin 	data.argnam = (er+=2) + shp->nenv;
22677c2fbfb3SApril Chin 	if(shp->nenv)
22687c2fbfb3SApril Chin 		memcpy((void*)er,environ,shp->nenv*sizeof(char*));
22697c2fbfb3SApril Chin 	nv_scan(shp->var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT);
2270da2e3ebdSchin 	*data.argnam = (char*)stakalloc(data.attsize);
2271da2e3ebdSchin 	cp = data.attval = strcopy(*data.argnam,e_envmarker);
22727c2fbfb3SApril Chin 	nv_scan(shp->var_tree, attstore,&data,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER));
2273da2e3ebdSchin 	*data.attval = 0;
2274da2e3ebdSchin 	if(cp!=data.attval)
2275da2e3ebdSchin 		data.argnam++;
2276da2e3ebdSchin 	*data.argnam = 0;
2277da2e3ebdSchin 	return(er);
2278da2e3ebdSchin }
2279da2e3ebdSchin #endif
2280da2e3ebdSchin 
2281da2e3ebdSchin struct scan
2282da2e3ebdSchin {
2283da2e3ebdSchin 	void    (*scanfn)(Namval_t*, void*);
2284da2e3ebdSchin 	int     scanmask;
2285da2e3ebdSchin 	int     scanflags;
2286da2e3ebdSchin 	int     scancount;
2287da2e3ebdSchin 	void    *scandata;
2288da2e3ebdSchin };
2289da2e3ebdSchin 
scanfilter(Dt_t * dict,void * arg,void * data)2290da2e3ebdSchin static int scanfilter(Dt_t *dict, void *arg, void *data)
2291da2e3ebdSchin {
2292da2e3ebdSchin 	register Namval_t *np = (Namval_t*)arg;
2293da2e3ebdSchin 	register int k=np->nvflag;
2294da2e3ebdSchin 	register struct scan *sp = (struct scan*)data;
22957c2fbfb3SApril Chin 	register struct adata *tp = (struct adata*)sp->scandata;
2296*b30d1939SAndy Fiddaman 	char	*cp;
2297da2e3ebdSchin 	NOT_USED(dict);
22987c2fbfb3SApril Chin #if SHOPT_TYPEDEF
22993e14f97fSRoger A. Faulkner 	if(!is_abuiltin(np) && tp && tp->tp && nv_type(np)!=tp->tp)
23007c2fbfb3SApril Chin 		return(0);
23017c2fbfb3SApril Chin #endif /*SHOPT_TYPEDEF */
2302*b30d1939SAndy Fiddaman 	if(sp->scanmask==NV_TABLE && nv_isvtree(np))
2303*b30d1939SAndy Fiddaman 		k = NV_TABLE;
2304da2e3ebdSchin 	if(sp->scanmask?(k&sp->scanmask)==sp->scanflags:(!sp->scanflags || (k&sp->scanflags)))
2305da2e3ebdSchin 	{
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 		}
23177c2fbfb3SApril Chin 		if(!np->nvalue.cp && !np->nvfun && !nv_isattr(np,~NV_DEFAULT))
2318da2e3ebdSchin 			return(0);
2319da2e3ebdSchin 		if(sp->scanfn)
2320da2e3ebdSchin 		{
2321da2e3ebdSchin 			if(nv_isarray(np))
2322da2e3ebdSchin 				nv_putsub(np,NIL(char*),0L);
2323da2e3ebdSchin 			(*sp->scanfn)(np,sp->scandata);
2324da2e3ebdSchin 		}
2325da2e3ebdSchin 		sp->scancount++;
2326da2e3ebdSchin 	}
2327da2e3ebdSchin 	return(0);
2328da2e3ebdSchin }
2329da2e3ebdSchin 
2330da2e3ebdSchin /*
2331da2e3ebdSchin  * Walk through the name-value pairs
2332da2e3ebdSchin  * if <mask> is non-zero, then only nodes with (nvflags&mask)==flags
2333da2e3ebdSchin  *	are visited
2334da2e3ebdSchin  * If <mask> is zero, and <flags> non-zero, then nodes with one or
2335da2e3ebdSchin  *	more of <flags> is visited
2336da2e3ebdSchin  * If <mask> and <flags> are zero, then all nodes are visted
2337da2e3ebdSchin  */
nv_scan(Dt_t * root,void (* fn)(Namval_t *,void *),void * data,int mask,int flags)2338da2e3ebdSchin int nv_scan(Dt_t *root, void (*fn)(Namval_t*,void*), void *data,int mask, int flags)
2339da2e3ebdSchin {
2340*b30d1939SAndy Fiddaman 	Namval_t *np;
2341da2e3ebdSchin 	Dt_t *base=0;
2342da2e3ebdSchin 	struct scan sdata;
2343da2e3ebdSchin 	int (*hashfn)(Dt_t*, void*, void*);
2344da2e3ebdSchin 	sdata.scanmask = mask;
2345da2e3ebdSchin 	sdata.scanflags = flags&~NV_NOSCOPE;
2346da2e3ebdSchin 	sdata.scanfn = fn;
2347da2e3ebdSchin 	sdata.scancount = 0;
2348da2e3ebdSchin 	sdata.scandata = data;
2349da2e3ebdSchin 	hashfn = scanfilter;
2350da2e3ebdSchin 	if(flags&NV_NOSCOPE)
2351da2e3ebdSchin 		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);
2354da2e3ebdSchin 	if(base)
2355da2e3ebdSchin 		 dtview((Dt_t*)root,base);
2356da2e3ebdSchin 	return(sdata.scancount);
2357da2e3ebdSchin }
2358da2e3ebdSchin 
2359da2e3ebdSchin /*
2360da2e3ebdSchin  * create a new environment scope
2361da2e3ebdSchin  */
sh_scope(Shell_t * shp,struct argnod * envlist,int fun)23627c2fbfb3SApril Chin void sh_scope(Shell_t *shp, struct argnod *envlist, int fun)
2363da2e3ebdSchin {
23647c2fbfb3SApril Chin 	register Dt_t		*newscope, *newroot=shp->var_base;
23657c2fbfb3SApril Chin 	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 */
2370da2e3ebdSchin 	newscope = dtopen(&_Nvdisc,Dtoset);
2371da2e3ebdSchin 	if(envlist)
23727c2fbfb3SApril Chin 	{
23737c2fbfb3SApril Chin 		dtview(newscope,(Dt_t*)shp->var_tree);
23747c2fbfb3SApril Chin 		shp->var_tree = newscope;
237534f9b3eeSRoland Mainz 		nv_setlist(envlist,NV_EXPORT|NV_NOSCOPE|NV_IDENT|NV_ASSIGN,0);
23767c2fbfb3SApril Chin 		if(!fun)
23777c2fbfb3SApril Chin 			return;
23787c2fbfb3SApril Chin 		shp->var_tree = dtview(newscope,0);
23797c2fbfb3SApril Chin 	}
23807c2fbfb3SApril Chin 	if((rp=shp->st.real_fun)  && rp->sdict)
23817c2fbfb3SApril Chin 	{
23827c2fbfb3SApril Chin 		dtview(rp->sdict,newroot);
23837c2fbfb3SApril Chin 		newroot = rp->sdict;
23847c2fbfb3SApril Chin 
23857c2fbfb3SApril Chin 	}
23867c2fbfb3SApril Chin 	dtview(newscope,(Dt_t*)newroot);
23877c2fbfb3SApril Chin 	shp->var_tree = newscope;
2388da2e3ebdSchin }
2389da2e3ebdSchin 
2390da2e3ebdSchin /*
2391da2e3ebdSchin  * Remove freeable local space associated with the nvalue field
2392da2e3ebdSchin  * of nnod. This includes any strings representing the value(s) of the
2393da2e3ebdSchin  * node, as well as its dope vector, if it is an array.
2394da2e3ebdSchin  */
2395da2e3ebdSchin 
sh_envnolocal(register Namval_t * np,void * data)2396da2e3ebdSchin void	sh_envnolocal (register Namval_t *np, void *data)
2397da2e3ebdSchin {
2398*b30d1939SAndy Fiddaman 	struct adata *tp = (struct adata*)data;
2399da2e3ebdSchin 	char *cp=0;
240034f9b3eeSRoland Mainz 	if(np==VERSIONNOD && nv_isref(np))
240134f9b3eeSRoland Mainz 		return;
240234f9b3eeSRoland Mainz 	if(np==L_ARGNOD)
240334f9b3eeSRoland Mainz 		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);
2408da2e3ebdSchin 	if(nv_isattr(np,NV_EXPORT) && nv_isarray(np))
2409da2e3ebdSchin 	{
2410da2e3ebdSchin 		nv_putsub(np,NIL(char*),0);
2411da2e3ebdSchin 		if(cp = nv_getval(np))
2412da2e3ebdSchin 			cp = strdup(cp);
2413da2e3ebdSchin 	}
2414da2e3ebdSchin 	if(nv_isattr(np,NV_EXPORT|NV_NOFREE))
2415da2e3ebdSchin 	{
241634f9b3eeSRoland Mainz 		if(nv_isref(np) && np!=VERSIONNOD)
2417da2e3ebdSchin 		{
2418da2e3ebdSchin 			nv_offattr(np,NV_NOFREE|NV_REF);
2419da2e3ebdSchin 			free((void*)np->nvalue.nrp);
2420da2e3ebdSchin 			np->nvalue.cp = 0;
2421da2e3ebdSchin 		}
2422da2e3ebdSchin 		if(!cp)
2423da2e3ebdSchin 			return;
2424da2e3ebdSchin 	}
2425da2e3ebdSchin 	if(nv_isarray(np))
2426da2e3ebdSchin 		nv_putsub(np,NIL(char*),ARRAY_UNDEF);
2427da2e3ebdSchin 	_nv_unset(np,NV_RDONLY);
2428da2e3ebdSchin 	nv_setattr(np,0);
2429da2e3ebdSchin 	if(cp)
2430da2e3ebdSchin 	{
2431da2e3ebdSchin 		nv_putval(np,cp,0);
2432da2e3ebdSchin 		free((void*)cp);
2433da2e3ebdSchin 	}
2434da2e3ebdSchin }
2435da2e3ebdSchin 
2436da2e3ebdSchin /*
2437da2e3ebdSchin  * Currently this is a dummy, but someday will be needed
2438da2e3ebdSchin  * for reference counting
2439da2e3ebdSchin  */
nv_close(Namval_t * np)2440da2e3ebdSchin void	nv_close(Namval_t *np)
2441da2e3ebdSchin {
2442da2e3ebdSchin 	NOT_USED(np);
2443da2e3ebdSchin }
2444da2e3ebdSchin 
table_unset(Shell_t * shp,register Dt_t * root,int flags,Dt_t * oroot)24457c2fbfb3SApril Chin static void table_unset(Shell_t *shp, register Dt_t *root, int flags, Dt_t *oroot)
2446da2e3ebdSchin {
24477c2fbfb3SApril Chin 	register Namval_t *np,*nq, *npnext;
24487c2fbfb3SApril Chin 	for(np=(Namval_t*)dtfirst(root);np;np=npnext)
2449da2e3ebdSchin 	{
24507c2fbfb3SApril Chin 		if(nq=dtsearch(oroot,np))
24517c2fbfb3SApril Chin 		{
24527c2fbfb3SApril Chin 			if(nv_cover(nq))
24537c2fbfb3SApril Chin 			{
24547c2fbfb3SApril Chin 				int subshell = shp->subshell;
24557c2fbfb3SApril Chin 				shp->subshell = 0;
24567c2fbfb3SApril Chin 				if(nv_isattr(nq, NV_INTEGER))
24577c2fbfb3SApril Chin 				{
24587c2fbfb3SApril Chin 					Sfdouble_t d = nv_getnum(nq);
24597c2fbfb3SApril Chin 					nv_putval(nq,(char*)&d,NV_LDOUBLE);
24607c2fbfb3SApril Chin 				}
246134f9b3eeSRoland Mainz 				else if(shp->test&4)
246234f9b3eeSRoland Mainz 					nv_putval(nq, strdup(nv_getval(nq)), NV_RDONLY);
24637c2fbfb3SApril Chin 				else
24647c2fbfb3SApril Chin 					nv_putval(nq, nv_getval(nq), NV_RDONLY);
24657c2fbfb3SApril Chin 				shp->subshell = subshell;
24667c2fbfb3SApril Chin 				np->nvfun = 0;
24677c2fbfb3SApril Chin 			}
24687c2fbfb3SApril Chin 			if(nv_isattr(nq,NV_EXPORT))
24697c2fbfb3SApril Chin 				sh_envput(shp->env,nq);
24707c2fbfb3SApril Chin 		}
24717c2fbfb3SApril Chin 		shp->last_root = root;
24727c2fbfb3SApril Chin 		shp->last_table = 0;
24737c2fbfb3SApril Chin 		if(nv_isvtree(np))
24747c2fbfb3SApril Chin 		{
24757c2fbfb3SApril Chin 			int len = strlen(np->nvname);
2476*b30d1939SAndy Fiddaman 			npnext = (Namval_t*)dtnext(root,np);
24777c2fbfb3SApril Chin 			while((nq=npnext) && memcmp(np->nvname,nq->nvname,len)==0 && nq->nvname[len]=='.')
24787c2fbfb3SApril Chin 
24797c2fbfb3SApril Chin 			{
24807c2fbfb3SApril Chin 				_nv_unset(nq,flags);
2481*b30d1939SAndy Fiddaman 				npnext = (Namval_t*)dtnext(root,nq);
24827c2fbfb3SApril Chin 				nv_delete(nq,root,0);
24837c2fbfb3SApril Chin 			}
24847c2fbfb3SApril Chin 		}
2485*b30d1939SAndy Fiddaman 		npnext = (Namval_t*)dtnext(root,np);
2486da2e3ebdSchin 		_nv_unset(np,flags);
24877c2fbfb3SApril Chin 		nv_delete(np,root,0);
2488da2e3ebdSchin 	}
2489da2e3ebdSchin }
2490da2e3ebdSchin 
2491da2e3ebdSchin /*
2492da2e3ebdSchin  *
2493da2e3ebdSchin  *   Set the value of <np> to 0, and nullify any attributes
2494da2e3ebdSchin  *   that <np> may have had.  Free any freeable space occupied
2495da2e3ebdSchin  *   by the value of <np>.  If <np> denotes an array member, it
2496da2e3ebdSchin  *   will retain its attributes.
2497da2e3ebdSchin  *   <flags> can contain NV_RDONLY to override the readonly attribute
2498da2e3ebdSchin  *	being cleared.
24997c2fbfb3SApril Chin  *   <flags> can contain NV_EXPORT to override preserve nvenv
2500da2e3ebdSchin  */
_nv_unset(register Namval_t * np,int flags)2501da2e3ebdSchin void	_nv_unset(register Namval_t *np,int flags)
2502da2e3ebdSchin {
2503*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
2504da2e3ebdSchin 	register union Value *up;
2505*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
2506*b30d1939SAndy Fiddaman 	Namarr_t	*ap;
2507*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
2508da2e3ebdSchin 	if(!(flags&NV_RDONLY) && nv_isattr (np,NV_RDONLY))
2509da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
2510da2e3ebdSchin 	if(is_afunction(np) && np->nvalue.ip)
2511da2e3ebdSchin 	{
2512da2e3ebdSchin 		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 		}
2518da2e3ebdSchin 		if(slp && !nv_isattr(np,NV_NOFREE))
2519da2e3ebdSchin 		{
25207c2fbfb3SApril Chin 			struct Ufunction *rq,*rp = np->nvalue.rp;
2521da2e3ebdSchin 			/* free function definition */
2522da2e3ebdSchin 			register char *name=nv_name(np),*cp= strrchr(name,'.');
2523da2e3ebdSchin 			if(cp)
2524da2e3ebdSchin 			{
2525da2e3ebdSchin 				Namval_t *npv;
2526da2e3ebdSchin 				*cp = 0;
25277c2fbfb3SApril Chin 				 npv = nv_open(name,shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOADD);
2528da2e3ebdSchin 				*cp++ = '.';
2529*b30d1939SAndy Fiddaman 				if(npv && npv!=shp->namespace)
2530da2e3ebdSchin 					nv_setdisc(npv,cp,NIL(Namval_t*),(Namfun_t*)npv);
2531da2e3ebdSchin 			}
25327c2fbfb3SApril Chin 			if(rp->fname && shp->fpathdict && (rq = (struct Ufunction*)nv_search(rp->fname,shp->fpathdict,0)))
25337c2fbfb3SApril Chin 			{
25347c2fbfb3SApril Chin 				do
25357c2fbfb3SApril Chin 				{
25367c2fbfb3SApril Chin 					if(rq->np != np)
25377c2fbfb3SApril Chin 						continue;
25387c2fbfb3SApril Chin 					dtdelete(shp->fpathdict,rq);
25397c2fbfb3SApril Chin 					break;
25407c2fbfb3SApril Chin 				}
25417c2fbfb3SApril Chin 				while(rq = (struct Ufunction*)dtnext(shp->fpathdict,rq));
25427c2fbfb3SApril Chin 			}
25437c2fbfb3SApril Chin 			if(rp->sdict)
25447c2fbfb3SApril Chin 			{
25457c2fbfb3SApril Chin 				Namval_t *mp, *nq;
25467c2fbfb3SApril Chin 				for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
25477c2fbfb3SApril Chin 				{
25487c2fbfb3SApril Chin 					nq = dtnext(rp->sdict,mp);
25497c2fbfb3SApril Chin 					_nv_unset(mp,NV_RDONLY);
25507c2fbfb3SApril Chin 					nv_delete(mp,rp->sdict,0);
25517c2fbfb3SApril Chin 				}
25527c2fbfb3SApril Chin 				dtclose(rp->sdict);
25537c2fbfb3SApril Chin 			}
2554da2e3ebdSchin 			stakdelete(slp->slptr);
2555da2e3ebdSchin 			free((void*)np->nvalue.ip);
2556da2e3ebdSchin 			np->nvalue.ip = 0;
2557da2e3ebdSchin 		}
2558da2e3ebdSchin 		goto done;
2559da2e3ebdSchin 	}
2560*b30d1939SAndy Fiddaman 	if(shp->subshell)
2561da2e3ebdSchin 		np = sh_assignok(np,0);
2562da2e3ebdSchin 	nv_offattr(np,NV_NODISC);
2563da2e3ebdSchin 	if(np->nvfun && !nv_isref(np))
2564da2e3ebdSchin 	{
2565da2e3ebdSchin 		/* This function contains disc */
2566da2e3ebdSchin 		if(!nv_local)
2567da2e3ebdSchin 		{
2568da2e3ebdSchin 			nv_local=1;
2569da2e3ebdSchin 			nv_putv(np,NIL(char*),flags,np->nvfun);
25707c2fbfb3SApril Chin 			nv_local=0;
2571da2e3ebdSchin 			return;
2572da2e3ebdSchin 		}
2573da2e3ebdSchin 		/* called from disc, assign the actual value */
2574da2e3ebdSchin 		nv_local=0;
2575da2e3ebdSchin 	}
257634f9b3eeSRoland Mainz 	if(nv_isattr(np,NV_INT16P) == NV_INT16)
257734f9b3eeSRoland Mainz 	{
257834f9b3eeSRoland Mainz 		np->nvalue.cp = nv_isarray(np)?Empty:0;
257934f9b3eeSRoland Mainz 		goto done;
258034f9b3eeSRoland Mainz 	}
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 */
25867c2fbfb3SApril Chin 		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 	}
25987c2fbfb3SApril Chin 	else
25997c2fbfb3SApril Chin 		up = &np->nvalue;
26007c2fbfb3SApril Chin 	if(up && up->cp)
2601da2e3ebdSchin 	{
2602*b30d1939SAndy Fiddaman 		if(up->cp!=Empty && up->cp!=Null && !nv_isattr(np, NV_NOFREE))
2603da2e3ebdSchin 			free((void*)up->cp);
2604da2e3ebdSchin 		up->cp = 0;
2605da2e3ebdSchin 	}
2606da2e3ebdSchin done:
2607da2e3ebdSchin 	if(!nv_isarray(np) || !nv_arrayptr(np))
2608da2e3ebdSchin 	{
2609da2e3ebdSchin 		nv_setsize(np,0);
2610da2e3ebdSchin 		if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT))
2611da2e3ebdSchin 		{
2612da2e3ebdSchin 			if(nv_isattr(np,NV_EXPORT) && !strchr(np->nvname,'['))
26137c2fbfb3SApril Chin 				env_delete(shp->env,nv_name(np));
2614*b30d1939SAndy Fiddaman 			if(!(flags&NV_EXPORT) ||  nv_isattr(np,NV_EXPORT))
26157c2fbfb3SApril Chin 				np->nvenv = 0;
2616da2e3ebdSchin 			nv_setattr(np,0);
2617da2e3ebdSchin 		}
2618da2e3ebdSchin 		else
26197c2fbfb3SApril Chin 		{
2620da2e3ebdSchin 			nv_setattr(np,NV_MINIMAL);
26217c2fbfb3SApril Chin 			nv_delete(np,(Dt_t*)0,0);
26227c2fbfb3SApril Chin 		}
2623da2e3ebdSchin 	}
2624da2e3ebdSchin }
2625da2e3ebdSchin 
2626da2e3ebdSchin /*
2627da2e3ebdSchin  * return the node pointer in the highest level scope
2628da2e3ebdSchin  */
sh_scoped(Shell_t * shp,register Namval_t * np)26297c2fbfb3SApril Chin Namval_t *sh_scoped(Shell_t *shp, register Namval_t *np)
2630da2e3ebdSchin {
26317c2fbfb3SApril Chin 	if(!dtvnext(shp->var_tree))
2632da2e3ebdSchin 		return(np);
26337c2fbfb3SApril Chin 	return(dtsearch(shp->var_tree,np));
2634da2e3ebdSchin }
2635da2e3ebdSchin 
2636da2e3ebdSchin #if 1
2637da2e3ebdSchin /*
2638da2e3ebdSchin  * return space separated list of names of variables in given tree
2639da2e3ebdSchin  */
tableval(Dt_t * root)2640da2e3ebdSchin static char *tableval(Dt_t *root)
2641da2e3ebdSchin {
2642da2e3ebdSchin 	static Sfio_t *out;
2643da2e3ebdSchin 	register Namval_t *np;
2644da2e3ebdSchin 	register int first=1;
2645da2e3ebdSchin 	register Dt_t *base = dtview(root,0);
2646da2e3ebdSchin         if(out)
2647da2e3ebdSchin                 sfseek(out,(Sfoff_t)0,SEEK_SET);
2648da2e3ebdSchin         else
2649da2e3ebdSchin                 out =  sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
2650da2e3ebdSchin 	for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np))
2651da2e3ebdSchin 	{
2652da2e3ebdSchin                 if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE))
2653da2e3ebdSchin 		{
2654da2e3ebdSchin 			if(!first)
2655da2e3ebdSchin 				sfputc(out,' ');
2656da2e3ebdSchin 			else
2657da2e3ebdSchin 				first = 0;
2658da2e3ebdSchin 			sfputr(out,np->nvname,-1);
2659da2e3ebdSchin 		}
2660da2e3ebdSchin 	}
2661da2e3ebdSchin 	sfputc(out,0);
2662da2e3ebdSchin 	if(base)
2663da2e3ebdSchin 		dtview(root,base);
2664da2e3ebdSchin 	return((char*)out->_data);
2665da2e3ebdSchin }
2666da2e3ebdSchin #endif
2667da2e3ebdSchin 
2668da2e3ebdSchin #if SHOPT_OPTIMIZE
2669da2e3ebdSchin struct optimize
2670da2e3ebdSchin {
2671da2e3ebdSchin 	Namfun_t	hdr;
26727c2fbfb3SApril Chin 	Shell_t		*sh;
2673da2e3ebdSchin 	char		**ptr;
2674da2e3ebdSchin 	struct optimize	*next;
2675da2e3ebdSchin 	Namval_t	*np;
2676da2e3ebdSchin };
2677da2e3ebdSchin 
2678da2e3ebdSchin static struct optimize *opt_free;
2679da2e3ebdSchin 
optimize_clear(Namval_t * np,Namfun_t * fp)2680da2e3ebdSchin static void optimize_clear(Namval_t* np, Namfun_t *fp)
2681da2e3ebdSchin {
2682da2e3ebdSchin 	struct optimize *op = (struct optimize*)fp;
2683da2e3ebdSchin 	nv_stack(np,fp);
2684da2e3ebdSchin 	nv_stack(np,(Namfun_t*)0);
2685da2e3ebdSchin 	for(;op && op->np==np; op=op->next)
2686da2e3ebdSchin 	{
2687da2e3ebdSchin 		if(op->ptr)
2688da2e3ebdSchin 		{
2689da2e3ebdSchin 			*op->ptr = 0;
2690da2e3ebdSchin 			op->ptr = 0;
2691da2e3ebdSchin 		}
2692da2e3ebdSchin 	}
2693da2e3ebdSchin }
2694da2e3ebdSchin 
put_optimize(Namval_t * np,const char * val,int flags,Namfun_t * fp)2695da2e3ebdSchin static void put_optimize(Namval_t* np,const char *val,int flags,Namfun_t *fp)
2696da2e3ebdSchin {
2697da2e3ebdSchin 	nv_putv(np,val,flags,fp);
2698da2e3ebdSchin 	optimize_clear(np,fp);
2699da2e3ebdSchin }
2700da2e3ebdSchin 
clone_optimize(Namval_t * np,Namval_t * mp,int flags,Namfun_t * fp)27017c2fbfb3SApril Chin static Namfun_t *clone_optimize(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
27027c2fbfb3SApril Chin {
27037c2fbfb3SApril Chin 	return((Namfun_t*)0);
27047c2fbfb3SApril Chin }
27057c2fbfb3SApril Chin 
27067c2fbfb3SApril Chin static const Namdisc_t optimize_disc  = {sizeof(struct optimize),put_optimize,0,0,0,0,clone_optimize};
2707da2e3ebdSchin 
nv_optimize(Namval_t * np)2708da2e3ebdSchin void nv_optimize(Namval_t *np)
2709da2e3ebdSchin {
2710*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2711da2e3ebdSchin 	register Namfun_t *fp;
2712da2e3ebdSchin 	register struct optimize *op, *xp;
2713*b30d1939SAndy Fiddaman 	if(shp->argaddr)
2714da2e3ebdSchin 	{
27157c2fbfb3SApril Chin 		if(np==SH_LINENO)
27167c2fbfb3SApril Chin 		{
2717*b30d1939SAndy Fiddaman 			shp->argaddr = 0;
27187c2fbfb3SApril Chin 			return;
27197c2fbfb3SApril Chin 		}
2720da2e3ebdSchin 		for(fp=np->nvfun; fp; fp = fp->next)
2721da2e3ebdSchin 		{
27227c2fbfb3SApril Chin 			if(fp->disc && (fp->disc->getnum || fp->disc->getval))
2723da2e3ebdSchin 			{
2724*b30d1939SAndy Fiddaman 				shp->argaddr = 0;
2725da2e3ebdSchin 				return;
2726da2e3ebdSchin 			}
2727da2e3ebdSchin 			if(fp->disc== &optimize_disc)
2728da2e3ebdSchin 				break;
2729da2e3ebdSchin 		}
2730*b30d1939SAndy Fiddaman 		if((xp= (struct optimize*)fp) && xp->ptr==shp->argaddr)
2731da2e3ebdSchin 			return;
2732da2e3ebdSchin 		if(op = opt_free)
2733da2e3ebdSchin 			opt_free = op->next;
2734da2e3ebdSchin 		else
2735da2e3ebdSchin 			op=(struct optimize*)calloc(1,sizeof(struct optimize));
2736*b30d1939SAndy Fiddaman 		op->ptr = shp->argaddr;
2737da2e3ebdSchin 		op->np = np;
2738da2e3ebdSchin 		if(xp)
2739da2e3ebdSchin 		{
2740da2e3ebdSchin 			op->hdr.disc = 0;
2741da2e3ebdSchin 			op->next = xp->next;
2742da2e3ebdSchin 			xp->next = op;
2743da2e3ebdSchin 		}
2744da2e3ebdSchin 		else
2745da2e3ebdSchin 		{
2746da2e3ebdSchin 			op->hdr.disc = &optimize_disc;
2747*b30d1939SAndy Fiddaman 			op->next = (struct optimize*)shp->optlist;
2748*b30d1939SAndy Fiddaman 			shp->optlist = (void*)op;
2749da2e3ebdSchin 			nv_stack(np,&op->hdr);
2750da2e3ebdSchin 		}
2751da2e3ebdSchin 	}
2752da2e3ebdSchin }
2753da2e3ebdSchin 
sh_optclear(Shell_t * shp,void * old)2754da2e3ebdSchin void sh_optclear(Shell_t *shp, void *old)
2755da2e3ebdSchin {
2756da2e3ebdSchin 	register struct optimize *op,*opnext;
2757da2e3ebdSchin 	for(op=(struct optimize*)shp->optlist; op; op = opnext)
2758da2e3ebdSchin 	{
2759da2e3ebdSchin 		opnext = op->next;
2760da2e3ebdSchin 		if(op->ptr && op->hdr.disc)
2761da2e3ebdSchin 		{
2762da2e3ebdSchin 			nv_stack(op->np,&op->hdr);
2763da2e3ebdSchin 			nv_stack(op->np,(Namfun_t*)0);
2764da2e3ebdSchin 		}
2765da2e3ebdSchin 		op->next = opt_free;
2766da2e3ebdSchin 		opt_free = op;
2767da2e3ebdSchin 	}
2768da2e3ebdSchin 	shp->optlist = old;
2769da2e3ebdSchin }
2770da2e3ebdSchin 
2771da2e3ebdSchin #else
2772da2e3ebdSchin #   define	optimize_clear(np,fp)
2773da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
2774da2e3ebdSchin 
2775da2e3ebdSchin /*
2776da2e3ebdSchin  *   Return a pointer to a character string that denotes the value
2777da2e3ebdSchin  *   of <np>.  If <np> refers to an array,  return a pointer to
2778da2e3ebdSchin  *   the value associated with the current index.
2779da2e3ebdSchin  *
2780da2e3ebdSchin  *   If the value of <np> is an integer, the string returned will
2781da2e3ebdSchin  *   be overwritten by the next call to nv_getval.
2782da2e3ebdSchin  *
2783da2e3ebdSchin  *   If <np> has no value, 0 is returned.
2784da2e3ebdSchin  */
2785da2e3ebdSchin 
nv_getval(register Namval_t * np)2786da2e3ebdSchin char *nv_getval(register Namval_t *np)
2787da2e3ebdSchin {
2788*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2789da2e3ebdSchin 	register union Value *up= &np->nvalue;
2790da2e3ebdSchin 	register int numeric;
2791da2e3ebdSchin #if SHOPT_OPTIMIZE
2792*b30d1939SAndy Fiddaman 	if(!nv_local && shp->argaddr)
2793da2e3ebdSchin 		nv_optimize(np);
2794da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
2795*b30d1939SAndy Fiddaman 	if((!np->nvfun || !np->nvfun->disc) && !nv_isattr(np,NV_ARRAY|NV_INTEGER|NV_FUNCT|NV_REF))
2796da2e3ebdSchin 		goto done;
2797da2e3ebdSchin 	if(nv_isref(np))
2798da2e3ebdSchin 	{
2799*b30d1939SAndy Fiddaman 		char *sub;
28007c2fbfb3SApril Chin 		if(!np->nvalue.cp)
28017c2fbfb3SApril Chin 			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));
2811da2e3ebdSchin 	}
28127c2fbfb3SApril Chin 	if(np->nvfun && np->nvfun->disc)
2813da2e3ebdSchin 	{
2814da2e3ebdSchin 		if(!nv_local)
2815da2e3ebdSchin 		{
2816da2e3ebdSchin 			nv_local=1;
2817da2e3ebdSchin 			return(nv_getv(np, np->nvfun));
2818da2e3ebdSchin 		}
2819da2e3ebdSchin 		nv_local=0;
2820da2e3ebdSchin 	}
2821da2e3ebdSchin 	numeric = ((nv_isattr (np, NV_INTEGER)) != 0);
2822da2e3ebdSchin 	if(numeric)
2823da2e3ebdSchin 	{
2824da2e3ebdSchin 		Sflong_t  ll;
2825da2e3ebdSchin 		if(!up->cp)
2826da2e3ebdSchin 			return("0");
28277c2fbfb3SApril Chin 		if(nv_isattr (np,NV_DOUBLE)==NV_DOUBLE)
2828da2e3ebdSchin 		{
2829da2e3ebdSchin 			Sfdouble_t ld;
2830da2e3ebdSchin 			double d;
2831da2e3ebdSchin 			char *format;
2832da2e3ebdSchin 			if(nv_isattr(np,NV_LONG))
2833da2e3ebdSchin 			{
2834da2e3ebdSchin 				ld = *up->ldp;
2835da2e3ebdSchin 				if(nv_isattr (np,NV_EXPNOTE))
2836da2e3ebdSchin 					format = "%.*Lg";
28377c2fbfb3SApril Chin 				else if(nv_isattr (np,NV_HEXFLOAT))
28387c2fbfb3SApril Chin 					format = "%.*La";
2839da2e3ebdSchin 				else
2840da2e3ebdSchin 					format = "%.*Lf";
2841*b30d1939SAndy Fiddaman 				sfprintf(shp->strbuf,format,nv_size(np),ld);
2842da2e3ebdSchin 			}
2843da2e3ebdSchin 			else
2844da2e3ebdSchin 			{
2845da2e3ebdSchin 				d = *up->dp;
2846da2e3ebdSchin 				if(nv_isattr (np,NV_EXPNOTE))
2847da2e3ebdSchin 					format = "%.*g";
28487c2fbfb3SApril Chin 				else if(nv_isattr (np,NV_HEXFLOAT))
28497c2fbfb3SApril Chin 					format = "%.*a";
2850da2e3ebdSchin 				else
2851da2e3ebdSchin 					format = "%.*f";
2852*b30d1939SAndy Fiddaman 				sfprintf(shp->strbuf,format,nv_size(np),d);
2853da2e3ebdSchin 			}
2854*b30d1939SAndy Fiddaman 			return(sfstruse(shp->strbuf));
2855da2e3ebdSchin 		}
2856da2e3ebdSchin 		else if(nv_isattr(np,NV_UNSIGN))
2857da2e3ebdSchin 		{
2858da2e3ebdSchin 	        	if(nv_isattr (np,NV_LONG))
2859da2e3ebdSchin 				ll = *(Sfulong_t*)up->llp;
2860da2e3ebdSchin 			else if(nv_isattr (np,NV_SHORT))
28617c2fbfb3SApril Chin 			{
28627c2fbfb3SApril Chin 				if(nv_isattr(np,NV_INT16P)==NV_INT16P)
28637c2fbfb3SApril Chin 					ll = *(uint16_t*)(up->sp);
28647c2fbfb3SApril Chin 				else
28657c2fbfb3SApril Chin 					ll = (uint16_t)up->s;
28667c2fbfb3SApril Chin 			}
2867da2e3ebdSchin 			else
2868da2e3ebdSchin 				ll = *(uint32_t*)(up->lp);
2869da2e3ebdSchin 		}
2870da2e3ebdSchin         	else if(nv_isattr (np,NV_LONG))
2871da2e3ebdSchin 			ll = *up->llp;
2872da2e3ebdSchin         	else if(nv_isattr (np,NV_SHORT))
28737c2fbfb3SApril Chin 		{
28747c2fbfb3SApril Chin 			if(nv_isattr(np,NV_INT16P)==NV_INT16P)
28757c2fbfb3SApril Chin 				ll = *up->sp;
28767c2fbfb3SApril Chin 			else
28777c2fbfb3SApril Chin 				ll = up->s;
28787c2fbfb3SApril Chin 		}
2879da2e3ebdSchin         	else
2880da2e3ebdSchin 			ll = *(up->lp);
2881da2e3ebdSchin 		if((numeric=nv_size(np))==10)
2882da2e3ebdSchin 		{
2883da2e3ebdSchin 			if(nv_isattr(np,NV_UNSIGN))
2884da2e3ebdSchin 			{
2885*b30d1939SAndy Fiddaman 				sfprintf(shp->strbuf,"%I*u",sizeof(ll),ll);
2886*b30d1939SAndy Fiddaman 				return(sfstruse(shp->strbuf));
2887da2e3ebdSchin 			}
2888da2e3ebdSchin 			numeric = 0;
2889da2e3ebdSchin 		}
2890*b30d1939SAndy Fiddaman 		return(fmtbase(ll,numeric, numeric&&numeric!=10));
2891da2e3ebdSchin 	}
2892da2e3ebdSchin done:
2893da2e3ebdSchin #if (_AST_VERSION>=20030127L)
2894da2e3ebdSchin 	/*
2895da2e3ebdSchin 	 * if NV_RAW flag is on, return pointer to binary data
2896da2e3ebdSchin 	 * otherwise, base64 encode the data and return this string
2897da2e3ebdSchin 	 */
2898da2e3ebdSchin 	if(up->cp && nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
2899da2e3ebdSchin 	{
2900da2e3ebdSchin 		char *cp;
29013e14f97fSRoger A. Faulkner 		char *ep;
2902da2e3ebdSchin 		int size= nv_size(np), insize=(4*size)/3+size/45+8;
29033e14f97fSRoger A. Faulkner 		base64encode(up->cp, size, (void**)0, cp=getbuf(insize), insize, (void**)&ep);
29043e14f97fSRoger A. Faulkner 		*ep = 0;
2905da2e3ebdSchin 		return(cp);
2906da2e3ebdSchin 	}
2907da2e3ebdSchin #endif
2908*b30d1939SAndy Fiddaman 	if(!nv_isattr(np,NV_LJUST|NV_RJUST) && (numeric=nv_size(np)) && up->cp && up->cp[numeric])
2909da2e3ebdSchin 	{
2910da2e3ebdSchin 		char *cp = getbuf(numeric+1);
2911da2e3ebdSchin 		memcpy(cp,up->cp,numeric);
2912da2e3ebdSchin 		cp[numeric]=0;
2913da2e3ebdSchin 		return(cp);
2914da2e3ebdSchin 	}
2915da2e3ebdSchin 	return ((char*)up->cp);
2916da2e3ebdSchin }
2917da2e3ebdSchin 
nv_getnum(register Namval_t * np)2918da2e3ebdSchin Sfdouble_t nv_getnum(register Namval_t *np)
2919da2e3ebdSchin {
2920*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
2921da2e3ebdSchin 	register union Value *up;
2922da2e3ebdSchin 	register Sfdouble_t r=0;
2923da2e3ebdSchin 	register char *str;
2924da2e3ebdSchin #if SHOPT_OPTIMIZE
2925*b30d1939SAndy Fiddaman 	if(!nv_local && shp->argaddr)
2926da2e3ebdSchin 		nv_optimize(np);
2927da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
2928da2e3ebdSchin 	if(nv_istable(np))
2929da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_number,nv_name(np));
29307c2fbfb3SApril Chin      	if(np->nvfun && np->nvfun->disc)
2931da2e3ebdSchin 	{
2932da2e3ebdSchin 		if(!nv_local)
2933da2e3ebdSchin 		{
2934da2e3ebdSchin 			nv_local=1;
2935da2e3ebdSchin 			return(nv_getn(np, np->nvfun));
2936da2e3ebdSchin 		}
2937da2e3ebdSchin 		nv_local=0;
2938da2e3ebdSchin 	}
29397c2fbfb3SApril Chin 	if(nv_isref(np))
29407c2fbfb3SApril Chin 	{
29417c2fbfb3SApril Chin 		str = nv_refsub(np);
29427c2fbfb3SApril Chin 		np = nv_refnode(np);
29437c2fbfb3SApril Chin 		if(str)
29447c2fbfb3SApril Chin 			nv_putsub(np,str,0L);
29457c2fbfb3SApril Chin 	}
2946da2e3ebdSchin      	if(nv_isattr (np, NV_INTEGER))
2947da2e3ebdSchin 	{
2948da2e3ebdSchin 		up= &np->nvalue;
29497c2fbfb3SApril Chin 		if(!up->lp || up->cp==Empty)
2950da2e3ebdSchin 			r = 0;
29517c2fbfb3SApril Chin 		else if(nv_isattr(np, NV_DOUBLE)==NV_DOUBLE)
2952da2e3ebdSchin 		{
2953da2e3ebdSchin 			if(nv_isattr(np, NV_LONG))
2954da2e3ebdSchin 	                       	r = *up->ldp;
2955da2e3ebdSchin 			else
2956da2e3ebdSchin        	                	r = *up->dp;
2957da2e3ebdSchin 		}
2958da2e3ebdSchin 		else if(nv_isattr(np, NV_UNSIGN))
2959da2e3ebdSchin 		{
2960da2e3ebdSchin 			if(nv_isattr(np, NV_LONG))
2961da2e3ebdSchin 				r = (Sflong_t)*((Sfulong_t*)up->llp);
2962da2e3ebdSchin 			else if(nv_isattr(np, NV_SHORT))
29637c2fbfb3SApril Chin 			{
29647c2fbfb3SApril Chin 				if(nv_isattr(np,NV_INT16P)==NV_INT16P)
29657c2fbfb3SApril Chin 					r = (Sflong_t)(*(uint16_t*)up->sp);
29667c2fbfb3SApril Chin 				else
29677c2fbfb3SApril Chin 					r = (Sflong_t)((uint16_t)up->s);
29687c2fbfb3SApril Chin 			}
2969da2e3ebdSchin 			else
2970da2e3ebdSchin 				r = *((uint32_t*)up->lp);
2971da2e3ebdSchin 		}
2972da2e3ebdSchin 		else
2973da2e3ebdSchin 		{
2974da2e3ebdSchin 			if(nv_isattr(np, NV_LONG))
2975da2e3ebdSchin 				r = *up->llp;
2976da2e3ebdSchin 			else if(nv_isattr(np, NV_SHORT))
29777c2fbfb3SApril Chin 			{
29787c2fbfb3SApril Chin 				if(nv_isattr(np,NV_INT16P)==NV_INT16P)
29797c2fbfb3SApril Chin 					r = *up->sp;
29807c2fbfb3SApril Chin 				else
29817c2fbfb3SApril Chin 					r = up->s;
29827c2fbfb3SApril Chin 			}
2983da2e3ebdSchin 			else
2984da2e3ebdSchin 				r = *up->lp;
2985da2e3ebdSchin 		}
2986da2e3ebdSchin 	}
2987da2e3ebdSchin 	else if((str=nv_getval(np)) && *str!=0)
2988da2e3ebdSchin 	{
2989*b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_LJUST|NV_RJUST) || (*str=='0' && !(str[1]=='x'||str[1]=='X')))
2990da2e3ebdSchin 		{
2991da2e3ebdSchin 			while(*str=='0')
2992da2e3ebdSchin 				str++;
2993da2e3ebdSchin 		}
2994*b30d1939SAndy Fiddaman 		r = sh_arith(shp,str);
2995da2e3ebdSchin 	}
2996da2e3ebdSchin 	return(r);
2997da2e3ebdSchin }
2998*b30d1939SAndy Fiddaman 
2999da2e3ebdSchin /*
3000da2e3ebdSchin  *   Give <np> the attributes <newatts,> and change its current
3001da2e3ebdSchin  *   value to conform to <newatts>.  The <size> of left and right
3002da2e3ebdSchin  *   justified fields may be given.
3003da2e3ebdSchin  */
nv_newattr(register Namval_t * np,unsigned newatts,int size)3004da2e3ebdSchin void nv_newattr (register Namval_t *np, unsigned newatts, int size)
3005da2e3ebdSchin {
3006*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3007da2e3ebdSchin 	register char *sp;
3008da2e3ebdSchin 	register char *cp = 0;
3009da2e3ebdSchin 	register unsigned int n;
3010*b30d1939SAndy Fiddaman 	Namval_t *mp = 0;
3011da2e3ebdSchin 	Namarr_t *ap = 0;
3012*b30d1939SAndy Fiddaman 	int oldsize,oldatts,trans;
30137c2fbfb3SApril Chin 	Namfun_t *fp= (newatts&NV_NODISC)?np->nvfun:0;
3014*b30d1939SAndy Fiddaman 	char *prefix = shp->prefix;
30157c2fbfb3SApril Chin 	newatts &= ~NV_NODISC;
3016da2e3ebdSchin 
3017da2e3ebdSchin 	/* check for restrictions */
3018da2e3ebdSchin 	if(sh_isoption(SH_RESTRICTED) && ((sp=nv_name(np))==nv_name(PATHNOD) || sp==nv_name(SHELLNOD) || sp==nv_name(ENVNOD) || sp==nv_name(FPATHNOD)))
3019da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
3020da2e3ebdSchin 	/* handle attributes that do not change data separately */
3021da2e3ebdSchin 	n = np->nvflag;
3022*b30d1939SAndy Fiddaman 	trans = !(n&NV_INTEGER) && (n&(NV_LTOU|NV_UTOL));
3023da2e3ebdSchin 	if(newatts&NV_EXPORT)
3024da2e3ebdSchin 		nv_offattr(np,NV_IMPORT);
3025da2e3ebdSchin 	if(((n^newatts)&NV_EXPORT))
3026da2e3ebdSchin 	{
3027da2e3ebdSchin 		/* record changes to the environment */
3028da2e3ebdSchin 		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 		}
3033da2e3ebdSchin 		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;
3040da2e3ebdSchin 	}
304134f9b3eeSRoland Mainz 	oldsize = nv_size(np);
3042*b30d1939SAndy Fiddaman 	if((size==oldsize|| (n&NV_INTEGER)) && !trans && ((n^newatts)&~NV_NOCHANGE)==0)
3043da2e3ebdSchin 	{
3044da2e3ebdSchin 		if(size)
3045da2e3ebdSchin 			nv_setsize(np,size);
3046da2e3ebdSchin 		nv_offattr(np, ~NV_NOFREE);
3047da2e3ebdSchin 		nv_onattr(np, newatts);
3048da2e3ebdSchin 		return;
3049da2e3ebdSchin 	}
3050da2e3ebdSchin 	/* for an array, change all the elements */
3051da2e3ebdSchin 	if((ap=nv_arrayptr(np)) && ap->nelem>0)
3052da2e3ebdSchin 		nv_putsub(np,NIL(char*),ARRAY_SCAN);
3053da2e3ebdSchin 	oldsize = nv_size(np);
3054da2e3ebdSchin 	oldatts = np->nvflag;
30557c2fbfb3SApril Chin 	if(fp)
30567c2fbfb3SApril Chin 		np->nvfun = 0;
3057da2e3ebdSchin 	if(ap) /* add element to prevent array deletion */
3058*b30d1939SAndy Fiddaman 	{
3059da2e3ebdSchin 		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 	}
3070da2e3ebdSchin 	do
3071da2e3ebdSchin 	{
3072da2e3ebdSchin 		nv_setsize(np,oldsize);
3073da2e3ebdSchin 		np->nvflag = oldatts;
3074da2e3ebdSchin 		if (sp = nv_getval(np))
3075da2e3ebdSchin  		{
3076da2e3ebdSchin 			if(nv_isattr(np,NV_ZFILL))
3077da2e3ebdSchin 				while(*sp=='0') sp++;
3078*b30d1939SAndy Fiddaman 			cp = (char*)malloc((n=strlen (sp)) + 8);
3079da2e3ebdSchin 			strcpy(cp, sp);
3080*b30d1939SAndy Fiddaman 			if(sp && (mp=nv_opensub(np)))
3081da2e3ebdSchin 			{
3082*b30d1939SAndy Fiddaman 				if(trans)
30837c2fbfb3SApril Chin 				{
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);
30887c2fbfb3SApril Chin 				}
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;
30997c2fbfb3SApril Chin 			}
31003e14f97fSRoger A. Faulkner 			if(size==0 && (newatts&NV_HOST)!=NV_HOST && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL)))
3101da2e3ebdSchin 				size = n;
3102da2e3ebdSchin 		}
3103*b30d1939SAndy Fiddaman 		else if(!trans)
3104*b30d1939SAndy Fiddaman 			_nv_unset(np,NV_EXPORT);
3105da2e3ebdSchin 		nv_setsize(np,size);
3106*b30d1939SAndy Fiddaman 		np->nvflag &= (NV_ARRAY|NV_NOFREE);
3107da2e3ebdSchin 		np->nvflag |= newatts;
3108da2e3ebdSchin 		if (cp)
3109da2e3ebdSchin 		{
3110*b30d1939SAndy Fiddaman 			if(!mp)
3111*b30d1939SAndy Fiddaman 				nv_putval (np, cp, NV_RDONLY);
3112da2e3ebdSchin 			free(cp);
3113da2e3ebdSchin 		}
3114da2e3ebdSchin 	}
3115da2e3ebdSchin 	while(ap && nv_nextsub(np));
3116*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3117*b30d1939SAndy Fiddaman skip:
3118*b30d1939SAndy Fiddaman #endif /* SHOPT_TYPEDEF */
31197c2fbfb3SApril Chin 	if(fp)
31207c2fbfb3SApril Chin 		np->nvfun = fp;
3121da2e3ebdSchin 	if(ap)
3122da2e3ebdSchin 		ap->nelem--;
3123*b30d1939SAndy Fiddaman 	shp->prefix = prefix;
3124da2e3ebdSchin 	return;
3125da2e3ebdSchin }
3126da2e3ebdSchin 
oldgetenv(const char * string)3127da2e3ebdSchin static char *oldgetenv(const char *string)
3128da2e3ebdSchin {
3129da2e3ebdSchin 	register char c0,c1;
3130da2e3ebdSchin 	register const char *cp, *sp;
3131da2e3ebdSchin 	register char **av = environ;
3132da2e3ebdSchin 	if(!string || (c0= *string)==0)
3133da2e3ebdSchin 		return(0);
3134da2e3ebdSchin 	if((c1=*++string)==0)
3135da2e3ebdSchin 		c1= '=';
3136da2e3ebdSchin 	while(cp = *av++)
3137da2e3ebdSchin 	{
3138da2e3ebdSchin 		if(cp[0]!=c0 || cp[1]!=c1)
3139da2e3ebdSchin 			continue;
3140da2e3ebdSchin 		sp = string;
3141da2e3ebdSchin 		while(*sp && *sp++ == *++cp);
3142da2e3ebdSchin 		if(*sp==0 && *++cp=='=')
3143da2e3ebdSchin 			return((char*)(cp+1));
3144da2e3ebdSchin 	}
3145da2e3ebdSchin 	return(0);
3146da2e3ebdSchin }
3147da2e3ebdSchin 
3148da2e3ebdSchin /*
3149da2e3ebdSchin  * This version of getenv uses the hash storage to access environment values
3150da2e3ebdSchin  */
sh_getenv(const char * name)31513e14f97fSRoger A. Faulkner char *sh_getenv(const char *name)
3152da2e3ebdSchin {
3153*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3154da2e3ebdSchin 	register Namval_t *np;
3155*b30d1939SAndy Fiddaman 	if(!shp->var_tree)
31563e14f97fSRoger A. Faulkner 	{
31573e14f97fSRoger A. Faulkner #if 0
31583e14f97fSRoger A. Faulkner 		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] == '_')
31593e14f97fSRoger A. Faulkner #endif
31603e14f97fSRoger A. Faulkner 			return(oldgetenv(name));
31613e14f97fSRoger A. Faulkner 	}
3162*b30d1939SAndy Fiddaman 	else if((np = nv_search(name,shp->var_tree,0)) && nv_isattr(np,NV_EXPORT))
3163da2e3ebdSchin 		return(nv_getval(np));
3164da2e3ebdSchin 	return(0);
3165da2e3ebdSchin }
31663e14f97fSRoger A. Faulkner 
31673e14f97fSRoger A. Faulkner #ifndef _NEXT_SOURCE
31683e14f97fSRoger A. Faulkner /*
31693e14f97fSRoger A. Faulkner  * Some dynamic linkers will make this file see the libc getenv(),
31703e14f97fSRoger A. Faulkner  * so sh_getenv() is used for the astintercept() callback.  Plain
31713e14f97fSRoger A. Faulkner  * getenv() is provided for static links.
31723e14f97fSRoger A. Faulkner  */
getenv(const char * name)31733e14f97fSRoger A. Faulkner char *getenv(const char *name)
31743e14f97fSRoger A. Faulkner {
31753e14f97fSRoger A. Faulkner 	return sh_getenv(name);
31763e14f97fSRoger A. Faulkner }
3177da2e3ebdSchin #endif /* _NEXT_SOURCE */
3178da2e3ebdSchin 
3179da2e3ebdSchin #undef putenv
3180da2e3ebdSchin /*
3181da2e3ebdSchin  * This version of putenv uses the hash storage to assign environment values
3182da2e3ebdSchin  */
putenv(const char * name)3183da2e3ebdSchin int putenv(const char *name)
3184da2e3ebdSchin {
3185*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3186da2e3ebdSchin 	register Namval_t *np;
3187da2e3ebdSchin 	if(name)
3188da2e3ebdSchin 	{
3189*b30d1939SAndy Fiddaman 		np = nv_open(name,shp->var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN);
3190da2e3ebdSchin 		if(!strchr(name,'='))
3191*b30d1939SAndy Fiddaman 			_nv_unset(np,0);
3192da2e3ebdSchin 	}
3193da2e3ebdSchin 	return(0);
3194da2e3ebdSchin }
3195da2e3ebdSchin 
3196da2e3ebdSchin /*
31973e14f97fSRoger A. Faulkner  * Override libast setenviron().
3198da2e3ebdSchin  */
sh_setenviron(const char * name)31993e14f97fSRoger A. Faulkner char* sh_setenviron(const char *name)
3200da2e3ebdSchin {
3201*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3202da2e3ebdSchin 	register Namval_t *np;
3203da2e3ebdSchin 	if(name)
3204da2e3ebdSchin 	{
3205*b30d1939SAndy Fiddaman 		np = nv_open(name,shp->var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN);
3206da2e3ebdSchin 		if(strchr(name,'='))
3207da2e3ebdSchin 			return(nv_getval(np));
3208*b30d1939SAndy Fiddaman 		_nv_unset(np,0);
3209da2e3ebdSchin 	}
3210da2e3ebdSchin 	return("");
3211da2e3ebdSchin }
3212da2e3ebdSchin 
32133e14f97fSRoger A. Faulkner /*
32143e14f97fSRoger A. Faulkner  * Same linker dance as with getenv() above.
32153e14f97fSRoger A. Faulkner  */
setenviron(const char * name)32163e14f97fSRoger A. Faulkner char* setenviron(const char *name)
32173e14f97fSRoger A. Faulkner {
32183e14f97fSRoger A. Faulkner 	return sh_setenviron(name);
32193e14f97fSRoger A. Faulkner }
32203e14f97fSRoger A. Faulkner 
3221da2e3ebdSchin /*
3222da2e3ebdSchin  * normalize <cp> and return pointer to subscript if any
32237c2fbfb3SApril Chin  * if <eq> is specified, return pointer to first = not in a subscript
3224da2e3ebdSchin  */
lastdot(char * cp,int eq)3225*b30d1939SAndy Fiddaman static char *lastdot(char *cp, int eq)
3226da2e3ebdSchin {
32277c2fbfb3SApril Chin 	register char *ep=0;
3228da2e3ebdSchin 	register int c;
32297c2fbfb3SApril Chin 	if(eq)
32307c2fbfb3SApril Chin 		cp++;
3231*b30d1939SAndy Fiddaman 	while(c= mbchar(cp))
3232da2e3ebdSchin 	{
3233da2e3ebdSchin 		if(c=='[')
323434f9b3eeSRoland Mainz 		{
323534f9b3eeSRoland Mainz 			if(*cp==']')
323634f9b3eeSRoland Mainz 				cp++;
323734f9b3eeSRoland Mainz 			else
323834f9b3eeSRoland Mainz 				cp = nv_endsubscript((Namval_t*)0,ep=cp,0);
323934f9b3eeSRoland Mainz 		}
3240da2e3ebdSchin 		else if(c=='.')
3241da2e3ebdSchin 		{
3242da2e3ebdSchin 			if(*cp=='[')
324334f9b3eeSRoland Mainz 			{
324434f9b3eeSRoland Mainz 				cp = nv_endsubscript((Namval_t*)0,ep=cp,0);
324534f9b3eeSRoland Mainz 				if((ep=sh_checkid(ep+1,cp)) < cp)
324634f9b3eeSRoland Mainz 					cp=strcpy(ep,cp);
324734f9b3eeSRoland Mainz 			}
3248da2e3ebdSchin 			ep = 0;
3249da2e3ebdSchin 		}
32507c2fbfb3SApril Chin 		else if(eq && c == '=')
32517c2fbfb3SApril Chin 			return(cp-1);
3252da2e3ebdSchin 	}
32537c2fbfb3SApril Chin 	return(eq?0:ep);
32547c2fbfb3SApril Chin }
32557c2fbfb3SApril Chin 
nv_rename(register Namval_t * np,int flags)32567c2fbfb3SApril Chin int nv_rename(register Namval_t *np, int flags)
32577c2fbfb3SApril Chin {
3258*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
32597c2fbfb3SApril Chin 	register Namval_t	*mp=0,*nr=0;
32607c2fbfb3SApril Chin 	register char		*cp;
3261*b30d1939SAndy Fiddaman 	int			arraynp=0,arraynr,index= -1;
32627c2fbfb3SApril Chin 	Namval_t		*last_table = shp->last_table;
32637c2fbfb3SApril Chin 	Dt_t			*last_root = shp->last_root;
32647c2fbfb3SApril Chin 	Dt_t			*hp = 0;
3265*b30d1939SAndy Fiddaman 	char			*nvenv=0,*prefix=shp->prefix;
3266*b30d1939SAndy Fiddaman 	Namarr_t		*ap;
32677c2fbfb3SApril Chin 	if(nv_isattr(np,NV_PARAM) && shp->st.prevst)
32687c2fbfb3SApril Chin 	{
32697c2fbfb3SApril Chin 		if(!(hp=(Dt_t*)shp->st.prevst->save_tree))
32707c2fbfb3SApril Chin 			hp = dtvnext(shp->var_tree);
32717c2fbfb3SApril Chin 	}
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;
32767c2fbfb3SApril Chin 	if(!(cp=nv_getval(np)))
32777c2fbfb3SApril Chin 	{
32787c2fbfb3SApril Chin 		if(flags&NV_MOVE)
32797c2fbfb3SApril Chin 			errormsg(SH_DICT,ERROR_exit(1),e_varname,"");
32807c2fbfb3SApril Chin 		return(0);
32817c2fbfb3SApril Chin 	}
32827c2fbfb3SApril Chin 	if(lastdot(cp,0) && nv_isattr(np,NV_MINIMAL))
32837c2fbfb3SApril Chin 		errormsg(SH_DICT,ERROR_exit(1),e_varname,nv_name(np));
3284*b30d1939SAndy Fiddaman 	arraynr = cp[strlen(cp)-1] == ']';
32857c2fbfb3SApril Chin 	if(nv_isarray(np) && !(mp=nv_opensub(np)))
32867c2fbfb3SApril Chin 		index=nv_aindex(np);
328734f9b3eeSRoland Mainz 	shp->prefix = 0;
32887c2fbfb3SApril Chin 	if(!hp)
32897c2fbfb3SApril Chin 		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 */
32977c2fbfb3SApril Chin 		hp = shp->var_base;
3298*b30d1939SAndy Fiddaman 	}
32997c2fbfb3SApril Chin 	else if(shp->last_root)
33007c2fbfb3SApril Chin 		hp = shp->last_root;
33017c2fbfb3SApril Chin 	if(!nr)
33027c2fbfb3SApril Chin 		nr= nv_open(cp, hp, flags|NV_NOREF|((flags&NV_MOVE)?0:NV_NOFAIL));
330334f9b3eeSRoland Mainz 	shp->prefix = prefix;
33047c2fbfb3SApril Chin 	if(!nr)
33057c2fbfb3SApril Chin 	{
33067c2fbfb3SApril Chin 		if(!nv_isvtree(np))
33077c2fbfb3SApril Chin 			_nv_unset(np,0);
33087c2fbfb3SApril Chin 		return(0);
33097c2fbfb3SApril Chin 	}
33107c2fbfb3SApril Chin 	if(!mp && index>=0 && nv_isvtree(nr))
33117c2fbfb3SApril Chin 	{
33127c2fbfb3SApril Chin 		sfprintf(shp->strbuf,"%s[%d]%c",nv_name(np),index,0);
33137c2fbfb3SApril Chin 		/* create a virtual node */
33147c2fbfb3SApril Chin 		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 		}
33207c2fbfb3SApril Chin 	}
33217c2fbfb3SApril Chin 	if(mp)
332234f9b3eeSRoland Mainz 	{
332334f9b3eeSRoland Mainz 		nvenv = (char*)np;
33247c2fbfb3SApril Chin 		np = mp;
332534f9b3eeSRoland Mainz 	}
33267c2fbfb3SApril Chin 	if(nr==np)
33277c2fbfb3SApril Chin 	{
33287c2fbfb3SApril Chin 		if(index<0)
33297c2fbfb3SApril Chin 			return(0);
33307c2fbfb3SApril Chin 		if(cp = nv_getval(np))
33317c2fbfb3SApril Chin 			cp = strdup(cp);
33327c2fbfb3SApril Chin 	}
3333*b30d1939SAndy Fiddaman 	_nv_unset(np,NV_EXPORT);
33347c2fbfb3SApril Chin 	if(nr==np)
33357c2fbfb3SApril Chin 	{
33367c2fbfb3SApril Chin 		nv_putsub(np,(char*)0, index);
33377c2fbfb3SApril Chin 		nv_putval(np,cp,0);
33387c2fbfb3SApril Chin 		free((void*)cp);
33397c2fbfb3SApril Chin 		return(1);
33407c2fbfb3SApril Chin 	}
33417c2fbfb3SApril Chin 	shp->prev_table = shp->last_table;
33427c2fbfb3SApril Chin 	shp->prev_root = shp->last_root;
33437c2fbfb3SApril Chin 	shp->last_table = last_table;
33447c2fbfb3SApril Chin 	shp->last_root = last_root;
33457c2fbfb3SApril Chin 	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 	}
33857c2fbfb3SApril Chin 	return(1);
3386da2e3ebdSchin }
3387da2e3ebdSchin 
3388da2e3ebdSchin /*
3389da2e3ebdSchin  * Create a reference node from <np> to $np in dictionary <hp>
3390da2e3ebdSchin  */
nv_setref(register Namval_t * np,Dt_t * hp,int flags)3391da2e3ebdSchin void nv_setref(register Namval_t *np, Dt_t *hp, int flags)
3392da2e3ebdSchin {
3393*b30d1939SAndy Fiddaman 	Shell_t		*shp = sh_getinterp();
3394*b30d1939SAndy Fiddaman 	register Namval_t *nq=0, *nr=0;
339534f9b3eeSRoland Mainz 	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;
3399da2e3ebdSchin 	if(nv_isref(np))
3400da2e3ebdSchin 		return;
3401da2e3ebdSchin 	if(nv_isarray(np))
3402da2e3ebdSchin 		errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np));
3403da2e3ebdSchin 	if(!(cp=nv_getval(np)))
3404da2e3ebdSchin 	{
3405*b30d1939SAndy Fiddaman 		_nv_unset(np,0);
34067c2fbfb3SApril Chin 		nv_onattr(np,NV_REF);
34077c2fbfb3SApril Chin 		return;
3408da2e3ebdSchin 	}
34097c2fbfb3SApril Chin 	if((ep = lastdot(cp,0)) && nv_isattr(np,NV_MINIMAL))
34107c2fbfb3SApril Chin 		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)
34207c2fbfb3SApril Chin 		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
34367c2fbfb3SApril Chin 	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 	}
34467c2fbfb3SApril Chin 	if(!nr)
344734f9b3eeSRoland Mainz 	{
3448*b30d1939SAndy Fiddaman 		shp->last_root = 0;
34497c2fbfb3SApril Chin 		nr= nq = nv_open(cp, hp, flags);
3450*b30d1939SAndy Fiddaman 		if(shp->last_root)
3451*b30d1939SAndy Fiddaman 			hp = shp->last_root;
345234f9b3eeSRoland Mainz 	}
345334f9b3eeSRoland Mainz 	if(shp->last_root == shp->var_tree && root!=shp->var_tree)
345434f9b3eeSRoland Mainz 	{
345534f9b3eeSRoland Mainz 		_nv_unset(np,NV_RDONLY);
345634f9b3eeSRoland Mainz 		nv_onattr(np,NV_REF);
345734f9b3eeSRoland Mainz 		errormsg(SH_DICT,ERROR_exit(1),e_globalref,nv_name(np));
345834f9b3eeSRoland Mainz 	}
3459*b30d1939SAndy Fiddaman 	shp->instance = 1;
346034f9b3eeSRoland Mainz 	if(nq && !ep && (ap=nv_arrayptr(nq)) && !(ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN)))
346134f9b3eeSRoland Mainz 		ep =  nv_getsub(nq);
3462*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3463*b30d1939SAndy Fiddaman 	if(ep && !(ap && ap->fixed))
3464*b30d1939SAndy Fiddaman #else
3465da2e3ebdSchin 	if(ep)
3466*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3467da2e3ebdSchin 	{
3468da2e3ebdSchin 		/* cause subscript evaluation and return result */
34697c2fbfb3SApril Chin 		if(nv_isarray(nq))
34707c2fbfb3SApril Chin 			ep = nv_getsub(nq);
34717c2fbfb3SApril Chin 		else
34727c2fbfb3SApril Chin 		{
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] = ']';
34777c2fbfb3SApril Chin 			if(nq = nv_opensub(nr))
34787c2fbfb3SApril Chin 				ep = 0;
34797c2fbfb3SApril Chin 			else
3480*b30d1939SAndy Fiddaman 				ep = nv_getsub(nq=nr);
34817c2fbfb3SApril Chin 		}
3482da2e3ebdSchin 	}
3483*b30d1939SAndy Fiddaman 	shp->instance = 0;
3484*b30d1939SAndy Fiddaman 	shp->last_root = root;
3485*b30d1939SAndy Fiddaman 	_nv_unset(np,0);
34867c2fbfb3SApril Chin 	nv_delete(np,(Dt_t*)0,0);
3487*b30d1939SAndy Fiddaman 	np->nvalue.nrp = newof(0,struct Namref,1,sizeof(Dtlink_t));
3488da2e3ebdSchin 	np->nvalue.nrp->np = nq;
3489da2e3ebdSchin 	np->nvalue.nrp->root = hp;
3490da2e3ebdSchin 	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 	}
34997c2fbfb3SApril Chin 	np->nvalue.nrp->table = shp->last_table;
3500da2e3ebdSchin 	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);
3508da2e3ebdSchin }
3509da2e3ebdSchin 
3510da2e3ebdSchin /*
3511da2e3ebdSchin  * get the scope corresponding to <index>
3512da2e3ebdSchin  * whence uses the same values as lseeek()
3513da2e3ebdSchin  */
sh_getscope(int index,int whence)3514da2e3ebdSchin Shscope_t *sh_getscope(int index, int whence)
3515da2e3ebdSchin {
3516*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3517da2e3ebdSchin 	register struct sh_scoped *sp, *topmost;
3518da2e3ebdSchin 	if(whence==SEEK_CUR)
3519*b30d1939SAndy Fiddaman 		sp = &shp->st;
3520da2e3ebdSchin 	else
3521da2e3ebdSchin 	{
3522*b30d1939SAndy Fiddaman 		if ((struct sh_scoped*)shp->topscope != shp->st.self)
3523*b30d1939SAndy Fiddaman 			topmost = (struct sh_scoped*)shp->topscope;
3524da2e3ebdSchin 		else
3525*b30d1939SAndy Fiddaman 			topmost = &(shp->st);
3526da2e3ebdSchin 		sp = topmost;
3527da2e3ebdSchin 		if(whence==SEEK_SET)
3528da2e3ebdSchin 		{
3529da2e3ebdSchin 			int n =0;
3530da2e3ebdSchin 			while(sp = sp->prevst)
3531da2e3ebdSchin 				n++;
3532da2e3ebdSchin 			index = n - index;
3533da2e3ebdSchin 			sp = topmost;
3534da2e3ebdSchin 		}
3535da2e3ebdSchin 	}
3536da2e3ebdSchin 	if(index < 0)
3537da2e3ebdSchin 		return((Shscope_t*)0);
3538da2e3ebdSchin 	while(index-- && (sp = sp->prevst));
3539da2e3ebdSchin 	return((Shscope_t*)sp);
3540da2e3ebdSchin }
3541da2e3ebdSchin 
3542da2e3ebdSchin /*
3543da2e3ebdSchin  * make <scoped> the top scope and return previous scope
3544da2e3ebdSchin  */
sh_setscope(Shscope_t * scope)3545da2e3ebdSchin Shscope_t *sh_setscope(Shscope_t *scope)
3546da2e3ebdSchin {
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;
3554da2e3ebdSchin 	return(old);
3555da2e3ebdSchin }
3556da2e3ebdSchin 
sh_unscope(Shell_t * shp)35577c2fbfb3SApril Chin void sh_unscope(Shell_t *shp)
3558da2e3ebdSchin {
35597c2fbfb3SApril Chin 	register Dt_t *root = shp->var_tree;
3560da2e3ebdSchin 	register Dt_t *dp = dtview(root,(Dt_t*)0);
3561*b30d1939SAndy Fiddaman 	if(dp)
35627c2fbfb3SApril Chin 	{
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);
35717c2fbfb3SApril Chin 	}
3572da2e3ebdSchin }
3573da2e3ebdSchin 
3574da2e3ebdSchin /*
3575da2e3ebdSchin  * The inverse of creating a reference node
3576da2e3ebdSchin  */
nv_unref(register Namval_t * np)3577da2e3ebdSchin void nv_unref(register Namval_t *np)
3578da2e3ebdSchin {
3579da2e3ebdSchin 	Namval_t *nq;
3580da2e3ebdSchin 	if(!nv_isref(np))
3581da2e3ebdSchin 		return;
3582da2e3ebdSchin 	nv_offattr(np,NV_NOFREE|NV_REF);
358334f9b3eeSRoland Mainz 	if(!np->nvalue.nrp)
358434f9b3eeSRoland Mainz 		return;
358534f9b3eeSRoland Mainz 	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 	}
3592da2e3ebdSchin 	free((void*)np->nvalue.nrp);
3593da2e3ebdSchin 	np->nvalue.cp = strdup(nv_name(nq));
3594da2e3ebdSchin #if SHOPT_OPTIMIZE
3595da2e3ebdSchin 	{
3596da2e3ebdSchin 		Namfun_t *fp;
3597da2e3ebdSchin 		for(fp=nq->nvfun; fp; fp = fp->next)
3598da2e3ebdSchin 		{
3599da2e3ebdSchin 			if(fp->disc== &optimize_disc)
3600da2e3ebdSchin 			{
3601da2e3ebdSchin 				optimize_clear(nq,fp);
3602da2e3ebdSchin 				return;
3603da2e3ebdSchin 			}
3604da2e3ebdSchin 		}
3605da2e3ebdSchin 	}
3606da2e3ebdSchin #endif
3607da2e3ebdSchin }
3608da2e3ebdSchin 
3609da2e3ebdSchin /*
3610da2e3ebdSchin  * These following are for binary compatibility with the old hash library
3611da2e3ebdSchin  * They will be removed someday
3612da2e3ebdSchin  */
3613da2e3ebdSchin 
3614da2e3ebdSchin #if defined(__IMPORT__) && defined(__EXPORT__)
3615da2e3ebdSchin #   define extern __EXPORT__
3616da2e3ebdSchin #endif
3617da2e3ebdSchin 
3618da2e3ebdSchin #undef	hashscope
3619da2e3ebdSchin 
hashscope(Dt_t * root)3620da2e3ebdSchin extern Dt_t *hashscope(Dt_t *root)
3621da2e3ebdSchin {
3622da2e3ebdSchin 	return(dtvnext(root));
3623da2e3ebdSchin }
3624da2e3ebdSchin 
3625da2e3ebdSchin #undef	hashfree
3626da2e3ebdSchin 
hashfree(Dt_t * root)3627da2e3ebdSchin extern Dt_t	*hashfree(Dt_t *root)
3628da2e3ebdSchin {
3629da2e3ebdSchin 	Dt_t *dp = dtvnext(root);
3630da2e3ebdSchin 	dtclose(root);
3631da2e3ebdSchin 	return(dp);
3632da2e3ebdSchin }
3633da2e3ebdSchin 
3634da2e3ebdSchin #undef	hashname
3635da2e3ebdSchin 
hashname(void * obj)3636da2e3ebdSchin extern char	*hashname(void *obj)
3637da2e3ebdSchin {
3638da2e3ebdSchin 	Namval_t *np = (Namval_t*)obj;
3639da2e3ebdSchin 	return(np->nvname);
3640da2e3ebdSchin }
3641da2e3ebdSchin 
3642da2e3ebdSchin #undef	hashlook
3643da2e3ebdSchin 
hashlook(Dt_t * root,const char * name,int mode,int size)3644da2e3ebdSchin extern void *hashlook(Dt_t *root, const char *name, int mode,int size)
3645da2e3ebdSchin {
3646da2e3ebdSchin 	NOT_USED(size);
3647da2e3ebdSchin 	return((void*)nv_search(name,root,mode));
3648da2e3ebdSchin }
3649da2e3ebdSchin 
nv_name(register Namval_t * np)3650da2e3ebdSchin char *nv_name(register Namval_t *np)
3651da2e3ebdSchin {
3652*b30d1939SAndy Fiddaman 	Shell_t	 *shp = sh_getinterp();
3653da2e3ebdSchin 	register Namval_t *table;
3654da2e3ebdSchin 	register Namfun_t *fp;
3655*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
3656*b30d1939SAndy Fiddaman 	Namarr_t	*ap;
3657*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
3658da2e3ebdSchin 	char *cp;
3659da2e3ebdSchin 	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 */
3670da2e3ebdSchin 		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 */
36757c2fbfb3SApril Chin 	if(!nv_isattr(np,NV_MINIMAL|NV_EXPORT) && np->nvenv)
36767c2fbfb3SApril Chin 	{
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;
36807c2fbfb3SApril Chin 		if(nv_isarray(mp))
3681*b30d1939SAndy Fiddaman 			sfprintf(shp->strbuf,"%s[%s]",nv_name(mp),np->nvname);
36827c2fbfb3SApril Chin 		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));
36867c2fbfb3SApril Chin 	}
3687da2e3ebdSchin 	if(nv_istable(np))
3688da2e3ebdSchin #if 1
3689*b30d1939SAndy Fiddaman 		shp->last_table = nv_parent(np);
3690da2e3ebdSchin #else
3691*b30d1939SAndy Fiddaman 		shp->last_table = nv_create(np,0, NV_LAST,(Namfun_t*)0);
3692da2e3ebdSchin #endif
3693da2e3ebdSchin 	else if(!nv_isref(np))
3694da2e3ebdSchin 	{
3695da2e3ebdSchin 		for(fp= np->nvfun ; fp; fp=fp->next)
3696da2e3ebdSchin 		if(fp->disc && fp->disc->namef)
3697da2e3ebdSchin 		{
3698*b30d1939SAndy Fiddaman 			if(np==shp->last_table)
3699*b30d1939SAndy Fiddaman 				shp->last_table = 0;
3700da2e3ebdSchin 			return((*fp->disc->namef)(np,fp));
3701da2e3ebdSchin 		}
3702da2e3ebdSchin 	}
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
3710da2e3ebdSchin 		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));
3725da2e3ebdSchin }
3726da2e3ebdSchin 
nv_lastdict(void)3727da2e3ebdSchin Namval_t *nv_lastdict(void)
3728da2e3ebdSchin {
3729*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
3730*b30d1939SAndy Fiddaman 	return(shp->last_table);
3731da2e3ebdSchin }
3732da2e3ebdSchin 
3733da2e3ebdSchin #undef nv_context
3734da2e3ebdSchin /*
3735da2e3ebdSchin  * returns the data context for a builtin
3736da2e3ebdSchin  */
nv_context(Namval_t * np)3737da2e3ebdSchin void *nv_context(Namval_t *np)
3738da2e3ebdSchin {
3739da2e3ebdSchin 	return((void*)np->nvfun);
3740da2e3ebdSchin }
3741da2e3ebdSchin 
3742da2e3ebdSchin #define DISABLE /* proto workaround */
3743da2e3ebdSchin 
DISABLE(register Namval_t * np)3744da2e3ebdSchin int nv_isnull DISABLE (register Namval_t *np)
3745da2e3ebdSchin {
3746da2e3ebdSchin 	return(nv_isnull(np));
3747da2e3ebdSchin }
3748da2e3ebdSchin 
3749da2e3ebdSchin #undef nv_setsize
nv_setsize(register Namval_t * np,int size)3750da2e3ebdSchin int nv_setsize(register Namval_t *np, int size)
3751da2e3ebdSchin {
3752da2e3ebdSchin 	int oldsize = nv_size(np);
3753da2e3ebdSchin 	if(size>=0)
3754da2e3ebdSchin 		np->nvsize = size;
3755da2e3ebdSchin 	return(oldsize);
3756da2e3ebdSchin }
37577c2fbfb3SApril Chin 
nv_shell(Namval_t * np)37587c2fbfb3SApril Chin Shell_t	*nv_shell(Namval_t *np)
37597c2fbfb3SApril Chin {
37607c2fbfb3SApril Chin 	Namfun_t *fp;
37617c2fbfb3SApril Chin 	for(fp=np->nvfun;fp;fp=fp->next)
37627c2fbfb3SApril Chin 	{
37637c2fbfb3SApril Chin 		if(!fp->disc)
37647c2fbfb3SApril Chin 			return((Shell_t*)fp->last);
37657c2fbfb3SApril Chin 	}
37667c2fbfb3SApril Chin 	return(0);
37677c2fbfb3SApril Chin }
37687c2fbfb3SApril Chin 
37697c2fbfb3SApril Chin #undef nv_unset
37707c2fbfb3SApril Chin 
nv_unset(register Namval_t * np)37717c2fbfb3SApril Chin void	nv_unset(register Namval_t *np)
37727c2fbfb3SApril Chin {
37737c2fbfb3SApril Chin 	_nv_unset(np,0);
37747c2fbfb3SApril Chin 	return;
37757c2fbfb3SApril Chin }
3776