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  */
29da2e3ebdSchin #define putenv	___putenv
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"
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 };
50da2e3ebdSchin #if !_lib_pathnative && _lib_uwin_path
52da2e3ebdSchin #define _lib_pathnative		1
54da2e3ebdSchin extern int	uwin_path(const char*, char*, int);
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 }
62da2e3ebdSchin #endif /* _lib_pathnative */
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);
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 };
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
119da2e3ebdSchin #if ( SFIO_VERSION  <= 20010201L )
120da2e3ebdSchin #   define _data        data
121da2e3ebdSchin #endif
123da2e3ebdSchin #if !SHOPT_MULTIBYTE
124da2e3ebdSchin #   define mbchar(p)       (*(unsigned char*)p++)
125da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
127da2e3ebdSchin /* ========	name value pair routines	======== */
129da2e3ebdSchin #include	"shnodes.h"
130da2e3ebdSchin #include	"builtins.h"
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 }
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
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 }
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 }
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 }
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 }
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 }
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 				}