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