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  * export [-p] [arg...]
23da2e3ebdSchin  * readonly [-p] [arg...]
24da2e3ebdSchin  * typeset [options]  [arg...]
25da2e3ebdSchin  * alias [-ptx] [arg...]
26da2e3ebdSchin  * unalias [arg...]
27da2e3ebdSchin  * builtin [-sd] [-f file] [name...]
28da2e3ebdSchin  * set [options] [name...]
29da2e3ebdSchin  * unset [-fnv] [name...]
30da2e3ebdSchin  *
31da2e3ebdSchin  *   David Korn
32da2e3ebdSchin  *   AT&T Labs
33da2e3ebdSchin  *
34da2e3ebdSchin  */
35da2e3ebdSchin 
36da2e3ebdSchin #include	"defs.h"
37da2e3ebdSchin #include	<error.h>
38da2e3ebdSchin #include	"path.h"
39da2e3ebdSchin #include	"name.h"
40da2e3ebdSchin #include	"history.h"
41da2e3ebdSchin #include	"builtins.h"
42da2e3ebdSchin #include	"variables.h"
437c2fbfb3SApril Chin #include	"FEATURE/dynamic"
44da2e3ebdSchin 
45da2e3ebdSchin struct tdata
46da2e3ebdSchin {
47da2e3ebdSchin 	Shell_t 	*sh;
48da2e3ebdSchin 	Namval_t	*tp;
49*b30d1939SAndy Fiddaman 	const char	*wctname;
50da2e3ebdSchin 	Sfio_t  	*outfile;
51da2e3ebdSchin 	char    	*prefix;
527c2fbfb3SApril Chin 	char    	*tname;
537c2fbfb3SApril Chin 	char		*help;
547c2fbfb3SApril Chin 	short     	aflag;
557c2fbfb3SApril Chin 	short     	pflag;
56da2e3ebdSchin 	int     	argnum;
57da2e3ebdSchin 	int     	scanmask;
58da2e3ebdSchin 	Dt_t 		*scanroot;
59da2e3ebdSchin 	char    	**argnam;
60*b30d1939SAndy Fiddaman 	int		indent;
61*b30d1939SAndy Fiddaman 	int		noref;
62da2e3ebdSchin };
63da2e3ebdSchin 
64da2e3ebdSchin 
65da2e3ebdSchin static int	print_namval(Sfio_t*, Namval_t*, int, struct tdata*);
66da2e3ebdSchin static void	print_attribute(Namval_t*,void*);
67da2e3ebdSchin static void	print_all(Sfio_t*, Dt_t*, struct tdata*);
687c2fbfb3SApril Chin static void	print_scan(Sfio_t*, int, Dt_t*, int, struct tdata*);
69*b30d1939SAndy Fiddaman static int	unall(int, char**, Dt_t*, Shell_t*);
70*b30d1939SAndy Fiddaman static int	setall(char**, int, Dt_t*, struct tdata*);
71da2e3ebdSchin static void	pushname(Namval_t*,void*);
72da2e3ebdSchin static void(*nullscan)(Namval_t*,void*);
73da2e3ebdSchin 
load_class(const char * name)74da2e3ebdSchin static Namval_t *load_class(const char *name)
75da2e3ebdSchin {
76da2e3ebdSchin 	errormsg(SH_DICT,ERROR_exit(1),"%s: type not loadable",name);
77da2e3ebdSchin 	return(0);
78da2e3ebdSchin }
79da2e3ebdSchin 
80da2e3ebdSchin /*
81da2e3ebdSchin  * Note export and readonly are the same
82da2e3ebdSchin  */
83da2e3ebdSchin #if 0
84da2e3ebdSchin     /* for the dictionary generator */
85*b30d1939SAndy Fiddaman     int    b_export(int argc,char *argv[],Shbltin_t *context){}
86da2e3ebdSchin #endif
b_readonly(int argc,char * argv[],Shbltin_t * context)87*b30d1939SAndy Fiddaman int    b_readonly(int argc,char *argv[],Shbltin_t *context)
88da2e3ebdSchin {
89da2e3ebdSchin 	register int flag;
90da2e3ebdSchin 	char *command = argv[0];
91da2e3ebdSchin 	struct tdata tdata;
92da2e3ebdSchin 	NOT_USED(argc);
93da2e3ebdSchin 	memset((void*)&tdata,0,sizeof(tdata));
94*b30d1939SAndy Fiddaman 	tdata.sh = context->shp;
95da2e3ebdSchin 	tdata.aflag = '-';
96da2e3ebdSchin 	while((flag = optget(argv,*command=='e'?sh_optexport:sh_optreadonly))) switch(flag)
97da2e3ebdSchin 	{
98da2e3ebdSchin 		case 'p':
99da2e3ebdSchin 			tdata.prefix = command;
100da2e3ebdSchin 			break;
101da2e3ebdSchin 		case ':':
102da2e3ebdSchin 			errormsg(SH_DICT,2, "%s", opt_info.arg);
103da2e3ebdSchin 			break;
104da2e3ebdSchin 		case '?':
105da2e3ebdSchin 			errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
106da2e3ebdSchin 			return(2);
107da2e3ebdSchin 	}
108da2e3ebdSchin 	if(error_info.errors)
109da2e3ebdSchin 		errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
110da2e3ebdSchin 	argv += (opt_info.index-1);
111da2e3ebdSchin 	if(*command=='r')
112da2e3ebdSchin 		flag = (NV_ASSIGN|NV_RDONLY|NV_VARNAME);
113da2e3ebdSchin #ifdef _ENV_H
114da2e3ebdSchin 	else if(!argv[1])
115da2e3ebdSchin 	{
116da2e3ebdSchin 		char *cp,**env=env_get(tdata.sh->env);
117da2e3ebdSchin 		while(cp = *env++)
118da2e3ebdSchin 		{
119da2e3ebdSchin 			if(tdata.prefix)
120da2e3ebdSchin 				sfputr(sfstdout,tdata.prefix,' ');
121da2e3ebdSchin 			sfprintf(sfstdout,"%s\n",sh_fmtq(cp));
122da2e3ebdSchin 		}
123da2e3ebdSchin 		return(0);
124da2e3ebdSchin 	}
125da2e3ebdSchin #endif
126da2e3ebdSchin 	else
127da2e3ebdSchin 	{
128da2e3ebdSchin 		flag = (NV_ASSIGN|NV_EXPORT|NV_IDENT);
1297c2fbfb3SApril Chin 		if(!tdata.sh->prefix)
1307c2fbfb3SApril Chin 			tdata.sh->prefix = "";
131da2e3ebdSchin 	}
132*b30d1939SAndy Fiddaman 	return(setall(argv,flag,tdata.sh->var_tree, &tdata));
133da2e3ebdSchin }
134da2e3ebdSchin 
135da2e3ebdSchin 
b_alias(int argc,register char * argv[],Shbltin_t * context)136*b30d1939SAndy Fiddaman int    b_alias(int argc,register char *argv[],Shbltin_t *context)
137da2e3ebdSchin {
138da2e3ebdSchin 	register unsigned flag = NV_NOARRAY|NV_NOSCOPE|NV_ASSIGN;
139da2e3ebdSchin 	register Dt_t *troot;
140da2e3ebdSchin 	register int n;
141da2e3ebdSchin 	struct tdata tdata;
142da2e3ebdSchin 	NOT_USED(argc);
143da2e3ebdSchin 	memset((void*)&tdata,0,sizeof(tdata));
144*b30d1939SAndy Fiddaman 	tdata.sh = context->shp;
145da2e3ebdSchin 	troot = tdata.sh->alias_tree;
146da2e3ebdSchin 	if(*argv[0]=='h')
147da2e3ebdSchin 		flag = NV_TAGGED;
148da2e3ebdSchin 	if(argv[1])
149da2e3ebdSchin 	{
150da2e3ebdSchin 		opt_info.offset = 0;
151da2e3ebdSchin 		opt_info.index = 1;
152da2e3ebdSchin 		*opt_info.option = 0;
153da2e3ebdSchin 		tdata.argnum = 0;
154da2e3ebdSchin 		tdata.aflag = *argv[1];
155da2e3ebdSchin 		while((n = optget(argv,sh_optalias))) switch(n)
156da2e3ebdSchin 		{
157da2e3ebdSchin 		    case 'p':
158da2e3ebdSchin 			tdata.prefix = argv[0];
159da2e3ebdSchin 			break;
160da2e3ebdSchin 		    case 't':
161da2e3ebdSchin 			flag |= NV_TAGGED;
162da2e3ebdSchin 			break;
163da2e3ebdSchin 		    case 'x':
164da2e3ebdSchin 			flag |= NV_EXPORT;
165da2e3ebdSchin 			break;
166da2e3ebdSchin 		    case ':':
167da2e3ebdSchin 			errormsg(SH_DICT,2, "%s", opt_info.arg);
168da2e3ebdSchin 			break;
169da2e3ebdSchin 		    case '?':
170da2e3ebdSchin 			errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
171da2e3ebdSchin 			return(2);
172da2e3ebdSchin 		}
173da2e3ebdSchin 		if(error_info.errors)
174da2e3ebdSchin 			errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
175da2e3ebdSchin 		argv += (opt_info.index-1);
176da2e3ebdSchin 		if(flag&NV_TAGGED)
177da2e3ebdSchin 		{
1787c2fbfb3SApril Chin 			/* hacks to handle hash -r | -- */
1797c2fbfb3SApril Chin 			if(argv[1] && argv[1][0]=='-')
180da2e3ebdSchin 			{
1817c2fbfb3SApril Chin 				if(argv[1][1]=='r' && argv[1][2]==0)
1827c2fbfb3SApril Chin 				{
183*b30d1939SAndy Fiddaman 					Namval_t *np = nv_search((char*)PATHNOD,tdata.sh->var_tree,HASH_BUCKET);
184*b30d1939SAndy Fiddaman 					nv_putval(np,nv_getval(np),NV_RDONLY);
1857c2fbfb3SApril Chin 					argv++;
1867c2fbfb3SApril Chin 					if(!argv[1])
1877c2fbfb3SApril Chin 						return(0);
1887c2fbfb3SApril Chin 				}
1897c2fbfb3SApril Chin 				if(argv[1][0]=='-')
1907c2fbfb3SApril Chin 				{
1917c2fbfb3SApril Chin 					if(argv[1][1]=='-' && argv[1][2]==0)
1927c2fbfb3SApril Chin 						argv++;
1937c2fbfb3SApril Chin 					else
1947c2fbfb3SApril Chin 						errormsg(SH_DICT, ERROR_exit(1), e_option, argv[1]);
1957c2fbfb3SApril Chin 		}
196da2e3ebdSchin 			}
197da2e3ebdSchin 			troot = tdata.sh->track_tree;
198da2e3ebdSchin 		}
199da2e3ebdSchin 	}
200*b30d1939SAndy Fiddaman 	return(setall(argv,flag,troot,&tdata));
201da2e3ebdSchin }
202da2e3ebdSchin 
203da2e3ebdSchin 
204da2e3ebdSchin #if 0
205da2e3ebdSchin     /* for the dictionary generator */
206*b30d1939SAndy Fiddaman     int    b_local(int argc,char *argv[],Shbltin_t *context){}
207da2e3ebdSchin #endif
b_typeset(int argc,register char * argv[],Shbltin_t * context)208*b30d1939SAndy Fiddaman int    b_typeset(int argc,register char *argv[],Shbltin_t *context)
209da2e3ebdSchin {
2107c2fbfb3SApril Chin 	register int	n, flag = NV_VARNAME|NV_ASSIGN;
2117c2fbfb3SApril Chin 	struct tdata	tdata;
2127c2fbfb3SApril Chin 	const char	*optstring = sh_opttypeset;
213*b30d1939SAndy Fiddaman 	Namdecl_t 	*ntp = (Namdecl_t*)context->ptr;
2147c2fbfb3SApril Chin 	Dt_t		*troot;
2157c2fbfb3SApril Chin 	int		isfloat=0, shortint=0, sflag=0;
216da2e3ebdSchin 	NOT_USED(argc);
217da2e3ebdSchin 	memset((void*)&tdata,0,sizeof(tdata));
218*b30d1939SAndy Fiddaman 	tdata.sh = context->shp;
2197c2fbfb3SApril Chin 	if(ntp)
2207c2fbfb3SApril Chin 	{
2217c2fbfb3SApril Chin 		tdata.tp = ntp->tp;
2227c2fbfb3SApril Chin 		opt_info.disc = (Optdisc_t*)ntp->optinfof;
2237c2fbfb3SApril Chin 		optstring = ntp->optstring;
2247c2fbfb3SApril Chin 	}
225da2e3ebdSchin 	troot = tdata.sh->var_tree;
2267c2fbfb3SApril Chin 	while((n = optget(argv,optstring)))
227da2e3ebdSchin 	{
228*b30d1939SAndy Fiddaman 		if(tdata.aflag==0)
229*b30d1939SAndy Fiddaman 			tdata.aflag = *opt_info.option;
230da2e3ebdSchin 		switch(n)
231da2e3ebdSchin 		{
232da2e3ebdSchin 			case 'a':
233da2e3ebdSchin 				flag |= NV_IARRAY;
2347c2fbfb3SApril Chin 				if(opt_info.arg && *opt_info.arg!='[')
2357c2fbfb3SApril Chin 				{
2367c2fbfb3SApril Chin 					opt_info.index--;
2377c2fbfb3SApril Chin 					goto endargs;
2387c2fbfb3SApril Chin 				}
2397c2fbfb3SApril Chin 				tdata.tname = opt_info.arg;
240da2e3ebdSchin 				break;
241da2e3ebdSchin 			case 'A':
242da2e3ebdSchin 				flag |= NV_ARRAY;
243da2e3ebdSchin 				break;
2447c2fbfb3SApril Chin 			case 'C':
2457c2fbfb3SApril Chin 				flag |= NV_COMVAR;
2467c2fbfb3SApril Chin 				break;
247da2e3ebdSchin 			case 'E':
248da2e3ebdSchin 				/* The following is for ksh88 compatibility */
249da2e3ebdSchin 				if(opt_info.offset && !strchr(argv[opt_info.index],'E'))
250da2e3ebdSchin 				{
251da2e3ebdSchin 					tdata.argnum = (int)opt_info.num;
252da2e3ebdSchin 					break;
253da2e3ebdSchin 				}
2545ae8bd53SToomas Soome 				/* FALLTHROUGH */
255da2e3ebdSchin 			case 'F':
2567c2fbfb3SApril Chin 			case 'X':
257da2e3ebdSchin 				if(!opt_info.arg || (tdata.argnum = opt_info.num) <0)
25834f9b3eeSRoland Mainz 					tdata.argnum = (n=='X'?2*sizeof(Sfdouble_t):10);
259da2e3ebdSchin 				isfloat = 1;
260da2e3ebdSchin 				if(n=='E')
2617c2fbfb3SApril Chin 				{
2627c2fbfb3SApril Chin 					flag &= ~NV_HEXFLOAT;
263da2e3ebdSchin 					flag |= NV_EXPNOTE;
2647c2fbfb3SApril Chin 				}
2657c2fbfb3SApril Chin 				else if(n=='X')
2667c2fbfb3SApril Chin 				{
2677c2fbfb3SApril Chin 					flag &= ~NV_EXPNOTE;
2687c2fbfb3SApril Chin 					flag |= NV_HEXFLOAT;
2697c2fbfb3SApril Chin 				}
270da2e3ebdSchin 				break;
271da2e3ebdSchin 			case 'b':
272da2e3ebdSchin 				flag |= NV_BINARY;
273da2e3ebdSchin 				break;
2747c2fbfb3SApril Chin 			case 'm':
2757c2fbfb3SApril Chin 				flag |= NV_MOVE;
2767c2fbfb3SApril Chin 				break;
277da2e3ebdSchin 			case 'n':
278da2e3ebdSchin 				flag &= ~NV_VARNAME;
279da2e3ebdSchin 				flag |= (NV_REF|NV_IDENT);
280da2e3ebdSchin 				break;
281da2e3ebdSchin 			case 'H':
282da2e3ebdSchin 				flag |= NV_HOST;
283da2e3ebdSchin 				break;
284da2e3ebdSchin 			case 'T':
285da2e3ebdSchin 				flag |= NV_TYPE;
286da2e3ebdSchin 				tdata.prefix = opt_info.arg;
287da2e3ebdSchin 				break;
2887c2fbfb3SApril Chin 			case 'L': case 'Z': case 'R':
289da2e3ebdSchin 				if(tdata.argnum==0)
290da2e3ebdSchin 					tdata.argnum = (int)opt_info.num;
291da2e3ebdSchin 				if(tdata.argnum < 0)
292da2e3ebdSchin 					errormsg(SH_DICT,ERROR_exit(1), e_badfield, tdata.argnum);
2937c2fbfb3SApril Chin 				if(n=='Z')
2947c2fbfb3SApril Chin 					flag |= NV_ZFILL;
2957c2fbfb3SApril Chin 				else
2967c2fbfb3SApril Chin 				{
2977c2fbfb3SApril Chin 					flag &= ~(NV_LJUST|NV_RJUST);
2987c2fbfb3SApril Chin 					flag |= (n=='L'?NV_LJUST:NV_RJUST);
2997c2fbfb3SApril Chin 				}
300da2e3ebdSchin 				break;
301*b30d1939SAndy Fiddaman 			case 'M':
302*b30d1939SAndy Fiddaman 				if((tdata.wctname = opt_info.arg) && !nv_mapchar((Namval_t*)0,tdata.wctname))
303*b30d1939SAndy Fiddaman 					errormsg(SH_DICT, ERROR_exit(1),e_unknownmap, tdata.wctname);
304*b30d1939SAndy Fiddaman 				if(tdata.wctname && strcmp(tdata.wctname,e_tolower)==0)
305*b30d1939SAndy Fiddaman 					flag |= NV_UTOL;
306*b30d1939SAndy Fiddaman 				else
307*b30d1939SAndy Fiddaman 					flag |= NV_LTOU;
308*b30d1939SAndy Fiddaman 				if(!tdata.wctname)
309*b30d1939SAndy Fiddaman 					flag |= NV_UTOL;
310*b30d1939SAndy Fiddaman 				break;
311da2e3ebdSchin 			case 'f':
312da2e3ebdSchin 				flag &= ~(NV_VARNAME|NV_ASSIGN);
313da2e3ebdSchin 				troot = tdata.sh->fun_tree;
314da2e3ebdSchin 				break;
315da2e3ebdSchin 			case 'i':
316da2e3ebdSchin 				if(!opt_info.arg || (tdata.argnum = opt_info.num) <0)
317da2e3ebdSchin 					tdata.argnum = 10;
318da2e3ebdSchin 				flag |= NV_INTEGER;
319da2e3ebdSchin 				break;
320da2e3ebdSchin 			case 'l':
321*b30d1939SAndy Fiddaman 				tdata.wctname = e_tolower;
322da2e3ebdSchin 				flag |= NV_UTOL;
323da2e3ebdSchin 				break;
324da2e3ebdSchin 			case 'p':
325da2e3ebdSchin 				tdata.prefix = argv[0];
3267c2fbfb3SApril Chin 				tdata.pflag = 1;
327*b30d1939SAndy Fiddaman 				flag &= ~NV_ASSIGN;
3287c2fbfb3SApril Chin 				break;
329da2e3ebdSchin 			case 'r':
330da2e3ebdSchin 				flag |= NV_RDONLY;
331da2e3ebdSchin 				break;
3327c2fbfb3SApril Chin #ifdef SHOPT_TYPEDEF
3337c2fbfb3SApril Chin 			case 'S':
3347c2fbfb3SApril Chin 				sflag=1;
3357c2fbfb3SApril Chin 				break;
3367c2fbfb3SApril Chin 			case 'h':
3377c2fbfb3SApril Chin 				tdata.help = opt_info.arg;
3387c2fbfb3SApril Chin 				break;
3397c2fbfb3SApril Chin #endif /*SHOPT_TYPEDEF*/
340da2e3ebdSchin 			case 's':
341da2e3ebdSchin 				shortint=1;
342da2e3ebdSchin 				break;
343da2e3ebdSchin 			case 't':
344da2e3ebdSchin 				flag |= NV_TAGGED;
345da2e3ebdSchin 				break;
346da2e3ebdSchin 			case 'u':
347*b30d1939SAndy Fiddaman 				tdata.wctname = e_toupper;
348da2e3ebdSchin 				flag |= NV_LTOU;
349da2e3ebdSchin 				break;
350da2e3ebdSchin 			case 'x':
351da2e3ebdSchin 				flag &= ~NV_VARNAME;
352da2e3ebdSchin 				flag |= (NV_EXPORT|NV_IDENT);
353da2e3ebdSchin 				break;
354da2e3ebdSchin 			case ':':
355da2e3ebdSchin 				errormsg(SH_DICT,2, "%s", opt_info.arg);
356da2e3ebdSchin 				break;
357da2e3ebdSchin 			case '?':
358da2e3ebdSchin 				errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
359da2e3ebdSchin 				opt_info.disc = 0;
360da2e3ebdSchin 				return(2);
361da2e3ebdSchin 		}
362da2e3ebdSchin 	}
3637c2fbfb3SApril Chin endargs:
364da2e3ebdSchin 	argv += opt_info.index;
365da2e3ebdSchin 	opt_info.disc = 0;
366da2e3ebdSchin 	/* handle argument of + and - specially */
367da2e3ebdSchin 	if(*argv && argv[0][1]==0 && (*argv[0]=='+' || *argv[0]=='-'))
368da2e3ebdSchin 		tdata.aflag = *argv[0];
369da2e3ebdSchin 	else
370da2e3ebdSchin 		argv--;
3717c2fbfb3SApril Chin 	if((flag&NV_ZFILL) && !(flag&NV_LJUST))
3727c2fbfb3SApril Chin 		flag |= NV_RJUST;
373da2e3ebdSchin 	if((flag&NV_INTEGER) && (flag&(NV_LJUST|NV_RJUST|NV_ZFILL)))
374da2e3ebdSchin 		error_info.errors++;
375da2e3ebdSchin 	if((flag&NV_BINARY) && (flag&(NV_LJUST|NV_UTOL|NV_LTOU)))
376da2e3ebdSchin 		error_info.errors++;
3777c2fbfb3SApril Chin 	if((flag&NV_MOVE) && (flag&~(NV_MOVE|NV_VARNAME|NV_ASSIGN)))
3787c2fbfb3SApril Chin 		error_info.errors++;
3797c2fbfb3SApril Chin 	if((flag&NV_REF) && (flag&~(NV_REF|NV_IDENT|NV_ASSIGN)))
3807c2fbfb3SApril Chin 		error_info.errors++;
381*b30d1939SAndy Fiddaman 	if((flag&NV_TYPE) && (flag&~(NV_TYPE|NV_VARNAME|NV_ASSIGN)))
382*b30d1939SAndy Fiddaman 		error_info.errors++;
383da2e3ebdSchin 	if(troot==tdata.sh->fun_tree && ((isfloat || flag&~(NV_FUNCT|NV_TAGGED|NV_EXPORT|NV_LTOU))))
384da2e3ebdSchin 		error_info.errors++;
385*b30d1939SAndy Fiddaman 	if(sflag && troot==tdata.sh->fun_tree)
386*b30d1939SAndy Fiddaman 	{
387*b30d1939SAndy Fiddaman 		/* static function */
388*b30d1939SAndy Fiddaman 		sflag = 0;
389*b30d1939SAndy Fiddaman 		flag |= NV_STATICF;
390*b30d1939SAndy Fiddaman 	}
391da2e3ebdSchin 	if(error_info.errors)
392da2e3ebdSchin 		errormsg(SH_DICT,ERROR_usage(2),"%s", optusage(NIL(char*)));
393*b30d1939SAndy Fiddaman 	if(sizeof(char*)<8 && tdata.argnum > SHRT_MAX)
394*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(2),"option argument cannot be greater than %d",SHRT_MAX);
395da2e3ebdSchin 	if(isfloat)
3967c2fbfb3SApril Chin 		flag |= NV_DOUBLE;
397da2e3ebdSchin 	if(shortint)
398*b30d1939SAndy Fiddaman 	{
399*b30d1939SAndy Fiddaman 		flag &= ~NV_LONG;
400da2e3ebdSchin 		flag |= NV_SHORT|NV_INTEGER;
401*b30d1939SAndy Fiddaman 	}
4027c2fbfb3SApril Chin 	if(sflag)
4037c2fbfb3SApril Chin 	{
4047c2fbfb3SApril Chin 		if(tdata.sh->mktype)
4057c2fbfb3SApril Chin 			flag |= NV_REF|NV_TAGGED;
4067c2fbfb3SApril Chin 		else if(!tdata.sh->typeinit)
4077c2fbfb3SApril Chin 			flag |= NV_STATIC|NV_IDENT;
4087c2fbfb3SApril Chin 	}
4097c2fbfb3SApril Chin 	if(tdata.sh->fn_depth && !tdata.pflag)
410da2e3ebdSchin 		flag |= NV_NOSCOPE;
411*b30d1939SAndy Fiddaman 	if(tdata.help)
412*b30d1939SAndy Fiddaman 		tdata.help = strdup(tdata.help);
413da2e3ebdSchin 	if(flag&NV_TYPE)
414da2e3ebdSchin 	{
4157c2fbfb3SApril Chin 		Stk_t *stkp = tdata.sh->stk;
416*b30d1939SAndy Fiddaman 		int off=0,offset = stktell(stkp);
417*b30d1939SAndy Fiddaman 		if(!tdata.prefix)
418*b30d1939SAndy Fiddaman 			return(sh_outtype(tdata.sh,sfstdout));
4197c2fbfb3SApril Chin 		sfputr(stkp,NV_CLASS,-1);
420*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
421*b30d1939SAndy Fiddaman 		if(tdata.sh->namespace)
422*b30d1939SAndy Fiddaman 		{
423*b30d1939SAndy Fiddaman 			off = stktell(stkp)+1;
424*b30d1939SAndy Fiddaman 			sfputr(stkp,nv_name(tdata.sh->namespace),'.');
425*b30d1939SAndy Fiddaman 		}
426*b30d1939SAndy Fiddaman 		else
427*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
428da2e3ebdSchin 		if(NV_CLASS[sizeof(NV_CLASS)-2]!='.')
4297c2fbfb3SApril Chin 			sfputc(stkp,'.');
4307c2fbfb3SApril Chin 		sfputr(stkp,tdata.prefix,0);
4317c2fbfb3SApril Chin 		tdata.tp = nv_open(stkptr(stkp,offset),tdata.sh->var_tree,NV_VARNAME|NV_NOARRAY|NV_NOASSIGN);
432*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
433*b30d1939SAndy Fiddaman 		if(!tdata.tp && off)
434*b30d1939SAndy Fiddaman 		{
435*b30d1939SAndy Fiddaman 			*stkptr(stkp,off)=0;
436*b30d1939SAndy Fiddaman 			tdata.tp = nv_open(stkptr(stkp,offset),tdata.sh->var_tree,NV_VARNAME|NV_NOARRAY|NV_NOASSIGN);
437*b30d1939SAndy Fiddaman 		}
438*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
4397c2fbfb3SApril Chin 		stkseek(stkp,offset);
440da2e3ebdSchin 		if(!tdata.tp)
441da2e3ebdSchin 			errormsg(SH_DICT,ERROR_exit(1),"%s: unknown type",tdata.prefix);
44234f9b3eeSRoland Mainz 		else if(nv_isnull(tdata.tp))
44334f9b3eeSRoland Mainz 			nv_newtype(tdata.tp);
4447c2fbfb3SApril Chin 		tdata.tp->nvenv = tdata.help;
445da2e3ebdSchin 		flag &= ~NV_TYPE;
446*b30d1939SAndy Fiddaman 		if(nv_isattr(tdata.tp,NV_TAGGED))
447*b30d1939SAndy Fiddaman 		{
448*b30d1939SAndy Fiddaman 			nv_offattr(tdata.tp,NV_TAGGED);
449*b30d1939SAndy Fiddaman 			return(0);
450*b30d1939SAndy Fiddaman 		}
451da2e3ebdSchin 	}
4527c2fbfb3SApril Chin 	else if(tdata.aflag==0 && ntp && ntp->tp)
453da2e3ebdSchin 		tdata.aflag = '-';
4547c2fbfb3SApril Chin 	if(!tdata.sh->mktype)
4557c2fbfb3SApril Chin 		tdata.help = 0;
456*b30d1939SAndy Fiddaman 	if(tdata.aflag=='+' && (flag&(NV_ARRAY|NV_IARRAY|NV_COMVAR)) && argv[1])
457*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_nounattr);
458*b30d1939SAndy Fiddaman 	return(setall(argv,flag,troot,&tdata));
459da2e3ebdSchin }
460da2e3ebdSchin 
print_value(Sfio_t * iop,Namval_t * np,struct tdata * tp)4617c2fbfb3SApril Chin static void print_value(Sfio_t *iop, Namval_t *np, struct tdata *tp)
4627c2fbfb3SApril Chin {
4637c2fbfb3SApril Chin 	char	 *name;
46434f9b3eeSRoland Mainz 	int	aflag=tp->aflag;
4657c2fbfb3SApril Chin 	if(nv_isnull(np))
46634f9b3eeSRoland Mainz 	{
46734f9b3eeSRoland Mainz 		if(!np->nvflag)
46834f9b3eeSRoland Mainz 			return;
46934f9b3eeSRoland Mainz 		aflag = '+';
47034f9b3eeSRoland Mainz 	}
471*b30d1939SAndy Fiddaman 	else if(nv_istable(np))
472*b30d1939SAndy Fiddaman 	{
473*b30d1939SAndy Fiddaman 		Dt_t	*root = tp->sh->last_root;
474*b30d1939SAndy Fiddaman 		Namval_t *nsp = tp->sh->namespace;
475*b30d1939SAndy Fiddaman 		char *cp;
476*b30d1939SAndy Fiddaman 		if(!tp->pflag)
477*b30d1939SAndy Fiddaman 			return;
478*b30d1939SAndy Fiddaman 		cp = name = nv_name(np);
479*b30d1939SAndy Fiddaman 		if(*name=='.')
480*b30d1939SAndy Fiddaman 			name++;
481*b30d1939SAndy Fiddaman 		if(tp->indent)
482*b30d1939SAndy Fiddaman 			sfnputc(iop,'\t',tp->indent);
483*b30d1939SAndy Fiddaman 		sfprintf(iop,"namespace %s\n", name);
484*b30d1939SAndy Fiddaman 		if(tp->indent)
485*b30d1939SAndy Fiddaman 			sfnputc(iop,'\t',tp->indent);
486*b30d1939SAndy Fiddaman 		sfprintf(iop,"{\n", name);
487*b30d1939SAndy Fiddaman 		tp->indent++;
488*b30d1939SAndy Fiddaman 		/* output types from namespace */
489*b30d1939SAndy Fiddaman 		tp->sh->namespace = 0;
490*b30d1939SAndy Fiddaman 		tp->sh->prefix = nv_name(np)+1;
491*b30d1939SAndy Fiddaman 		sh_outtype(tp->sh,iop);
492*b30d1939SAndy Fiddaman 		tp->sh->prefix = 0;
493*b30d1939SAndy Fiddaman 		tp->sh->namespace = np;
494*b30d1939SAndy Fiddaman 		tp->sh->last_root = root;
495*b30d1939SAndy Fiddaman 		/* output variables from namespace */
496*b30d1939SAndy Fiddaman 		print_scan(iop,NV_NOSCOPE,nv_dict(np),aflag=='+',tp);
497*b30d1939SAndy Fiddaman 		tp->wctname = cp;
498*b30d1939SAndy Fiddaman 		tp->sh->namespace = 0;
499*b30d1939SAndy Fiddaman 		/* output functions from namespace */
500*b30d1939SAndy Fiddaman 		print_scan(iop,NV_FUNCTION|NV_NOSCOPE,tp->sh->fun_tree,aflag=='+',tp);
501*b30d1939SAndy Fiddaman 		tp->wctname = 0;
502*b30d1939SAndy Fiddaman 		tp->sh->namespace = nsp;
503*b30d1939SAndy Fiddaman 		if(--tp->indent)
504*b30d1939SAndy Fiddaman 			sfnputc(iop,'\t',tp->indent);
505*b30d1939SAndy Fiddaman 		sfwrite(iop,"}\n",2);
506*b30d1939SAndy Fiddaman 		return;
507*b30d1939SAndy Fiddaman 	}
50834f9b3eeSRoland Mainz 	sfputr(iop,nv_name(np),aflag=='+'?'\n':'=');
50934f9b3eeSRoland Mainz 	if(aflag=='+')
5107c2fbfb3SApril Chin 		return;
5117c2fbfb3SApril Chin 	if(nv_isarray(np) && nv_arrayptr(np))
5127c2fbfb3SApril Chin 	{
5137c2fbfb3SApril Chin 		nv_outnode(np,iop,-1,0);
5147c2fbfb3SApril Chin 		sfwrite(iop,")\n",2);
5157c2fbfb3SApril Chin 	}
5167c2fbfb3SApril Chin 	else
5177c2fbfb3SApril Chin 	{
5187c2fbfb3SApril Chin 		if(nv_isvtree(np))
5197c2fbfb3SApril Chin 			nv_onattr(np,NV_EXPORT);
5207c2fbfb3SApril Chin 		if(!(name = nv_getval(np)))
5217c2fbfb3SApril Chin 			name = Empty;
5227c2fbfb3SApril Chin 		if(!nv_isvtree(np))
5237c2fbfb3SApril Chin 			name = sh_fmtq(name);
5247c2fbfb3SApril Chin 		sfputr(iop,name,'\n');
5257c2fbfb3SApril Chin 	}
5267c2fbfb3SApril Chin }
5277c2fbfb3SApril Chin 
setall(char ** argv,register int flag,Dt_t * troot,struct tdata * tp)528*b30d1939SAndy Fiddaman static int     setall(char **argv,register int flag,Dt_t *troot,struct tdata *tp)
529da2e3ebdSchin {
530da2e3ebdSchin 	register char *name;
531da2e3ebdSchin 	char *last = 0;
5327c2fbfb3SApril Chin 	int nvflags=(flag&(NV_ARRAY|NV_NOARRAY|NV_VARNAME|NV_IDENT|NV_ASSIGN|NV_STATIC|NV_MOVE));
5337c2fbfb3SApril Chin 	int r=0, ref=0, comvar=(flag&NV_COMVAR),iarray=(flag&NV_IARRAY);
534da2e3ebdSchin 	Shell_t *shp =tp->sh;
5357c2fbfb3SApril Chin 	if(!shp->prefix)
5367c2fbfb3SApril Chin 	{
5377c2fbfb3SApril Chin 		if(!tp->pflag)
5387c2fbfb3SApril Chin 			nvflags |= NV_NOSCOPE;
5397c2fbfb3SApril Chin 	}
5407c2fbfb3SApril Chin 	else if(*shp->prefix==0)
5417c2fbfb3SApril Chin 		shp->prefix = 0;
542*b30d1939SAndy Fiddaman 	if(*argv[0]=='+')
543*b30d1939SAndy Fiddaman 		nvflags |= NV_NOADD;
5447c2fbfb3SApril Chin 	flag &= ~(NV_NOARRAY|NV_NOSCOPE|NV_VARNAME|NV_IDENT|NV_STATIC|NV_COMVAR|NV_IARRAY);
545da2e3ebdSchin 	if(argv[1])
546da2e3ebdSchin 	{
547da2e3ebdSchin 		if(flag&NV_REF)
548da2e3ebdSchin 		{
549da2e3ebdSchin 			flag &= ~NV_REF;
550da2e3ebdSchin 			ref=1;
551da2e3ebdSchin 			if(tp->aflag!='-')
552da2e3ebdSchin 				nvflags |= NV_NOREF;
553da2e3ebdSchin 		}
5547c2fbfb3SApril Chin 		if(tp->pflag)
555*b30d1939SAndy Fiddaman 			nvflags |= (NV_NOREF|NV_NOADD|NV_NOFAIL);
556da2e3ebdSchin 		while(name = *++argv)
557da2e3ebdSchin 		{
558da2e3ebdSchin 			register unsigned newflag;
559da2e3ebdSchin 			register Namval_t *np;
560*b30d1939SAndy Fiddaman 			Namarr_t	*ap;
561*b30d1939SAndy Fiddaman 			Namval_t	*mp;
562da2e3ebdSchin 			unsigned curflag;
563da2e3ebdSchin 			if(troot == shp->fun_tree)
564da2e3ebdSchin 			{
565da2e3ebdSchin 				/*
566da2e3ebdSchin 				 *functions can be exported or
567da2e3ebdSchin 				 * traced but not set
568da2e3ebdSchin 				 */
569da2e3ebdSchin 				flag &= ~NV_ASSIGN;
570da2e3ebdSchin 				if(flag&NV_LTOU)
571da2e3ebdSchin 				{
572da2e3ebdSchin 					/* Function names cannot be special builtin */
573da2e3ebdSchin 					if((np=nv_search(name,shp->bltin_tree,0)) && nv_isattr(np,BLT_SPC))
574da2e3ebdSchin 						errormsg(SH_DICT,ERROR_exit(1),e_badfun,name);
575*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
576*b30d1939SAndy Fiddaman 					if(shp->namespace)
577*b30d1939SAndy Fiddaman 						np = sh_fsearch(shp,name,NV_ADD|HASH_NOSCOPE);
578*b30d1939SAndy Fiddaman 					else
579*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
5807c2fbfb3SApril Chin 					np = nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE);
581da2e3ebdSchin 				}
582*b30d1939SAndy Fiddaman 				else
583*b30d1939SAndy Fiddaman 				{
584*b30d1939SAndy Fiddaman 					if(shp->prefix)
585*b30d1939SAndy Fiddaman 					{
586*b30d1939SAndy Fiddaman 						sfprintf(shp->strbuf,"%s.%s%c",shp->prefix,name,0);
587*b30d1939SAndy Fiddaman 						name = sfstruse(shp->strbuf);
588*b30d1939SAndy Fiddaman 					}
589*b30d1939SAndy Fiddaman #if SHOPT_NAMESPACE
5907c2fbfb3SApril Chin 					np = 0;
591*b30d1939SAndy Fiddaman 					if(shp->namespace)
592*b30d1939SAndy Fiddaman 						np = sh_fsearch(shp,name,HASH_NOSCOPE);
593*b30d1939SAndy Fiddaman 					if(!np)
594*b30d1939SAndy Fiddaman #endif /* SHOPT_NAMESPACE */
595*b30d1939SAndy Fiddaman 					if(np=nv_search(name,troot,0))
596*b30d1939SAndy Fiddaman 					{
597*b30d1939SAndy Fiddaman 						if(!is_afunction(np))
598*b30d1939SAndy Fiddaman 							np = 0;
599*b30d1939SAndy Fiddaman 					}
600*b30d1939SAndy Fiddaman 					else if(memcmp(name,".sh.math.",9)==0 && sh_mathstd(name+9))
601*b30d1939SAndy Fiddaman 						continue;
602*b30d1939SAndy Fiddaman 				}
603da2e3ebdSchin 				if(np && ((flag&NV_LTOU) || !nv_isnull(np) || nv_isattr(np,NV_LTOU)))
604da2e3ebdSchin 				{
605*b30d1939SAndy Fiddaman 					if(flag==0 && !tp->help)
606da2e3ebdSchin 					{
607da2e3ebdSchin 						print_namval(sfstdout,np,tp->aflag=='+',tp);
608da2e3ebdSchin 						continue;
609da2e3ebdSchin 					}
61034f9b3eeSRoland Mainz 					if(shp->subshell && !shp->subshare)
611da2e3ebdSchin 						sh_subfork();
612da2e3ebdSchin 					if(tp->aflag=='-')
613da2e3ebdSchin 						nv_onattr(np,flag|NV_FUNCTION);
614da2e3ebdSchin 					else if(tp->aflag=='+')
615da2e3ebdSchin 						nv_offattr(np,flag);
616da2e3ebdSchin 				}
617da2e3ebdSchin 				else
618da2e3ebdSchin 					r++;
6197c2fbfb3SApril Chin 				if(tp->help)
6207c2fbfb3SApril Chin 				{
6217c2fbfb3SApril Chin 					int offset = stktell(shp->stk);
622*b30d1939SAndy Fiddaman 					if(!np)
623*b30d1939SAndy Fiddaman 					{
624*b30d1939SAndy Fiddaman 						sfputr(shp->stk,shp->prefix,'.');
625*b30d1939SAndy Fiddaman 						sfputr(shp->stk,name,0);
626*b30d1939SAndy Fiddaman 						np = nv_search(stkptr(shp->stk,offset),troot,0);
627*b30d1939SAndy Fiddaman 						stkseek(shp->stk,offset);
628*b30d1939SAndy Fiddaman 					}
629*b30d1939SAndy Fiddaman 					if(np && np->nvalue.cp)
6307c2fbfb3SApril Chin 						np->nvalue.rp->help = tp->help;
6317c2fbfb3SApril Chin 				}
632da2e3ebdSchin 				continue;
633da2e3ebdSchin 			}
634da2e3ebdSchin 			/* tracked alias */
635da2e3ebdSchin 			if(troot==shp->track_tree && tp->aflag=='-')
636da2e3ebdSchin 			{
6377c2fbfb3SApril Chin 				np = nv_search(name,troot,NV_ADD);
638*b30d1939SAndy Fiddaman 				path_alias(np,path_absolute(shp,nv_name(np),NIL(Pathcomp_t*)));
6397c2fbfb3SApril Chin 				continue;
6407c2fbfb3SApril Chin 			}
641*b30d1939SAndy Fiddaman 			np = nv_open(name,troot,nvflags|((nvflags&NV_ASSIGN)?0:NV_ARRAY)|((iarray|(nvflags&(NV_REF|NV_NOADD)==NV_REF))?NV_FARRAY:0));
642*b30d1939SAndy Fiddaman 			if(!np)
643*b30d1939SAndy Fiddaman 				continue;
644*b30d1939SAndy Fiddaman 			if(nv_isnull(np) && !nv_isarray(np) && nv_isattr(np,NV_NOFREE))
645*b30d1939SAndy Fiddaman 				nv_offattr(np,NV_NOFREE);
646*b30d1939SAndy Fiddaman 			else if(tp->tp && !nv_isattr(np,NV_MINIMAL|NV_EXPORT) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)) && (ap->nelem&ARRAY_TREE))
647*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,ERROR_exit(1),e_typecompat,nv_name(np));
648*b30d1939SAndy Fiddaman 			else if((ap=nv_arrayptr(np)) && nv_aindex(np)>0 && ap->nelem==1 && nv_getval(np)==Empty)
649*b30d1939SAndy Fiddaman 			{
650*b30d1939SAndy Fiddaman 				ap->nelem++;
651*b30d1939SAndy Fiddaman 				_nv_unset(np,0);
652*b30d1939SAndy Fiddaman 				ap->nelem--;
653*b30d1939SAndy Fiddaman 			}
654*b30d1939SAndy Fiddaman 			else if(iarray && ap && ap->fun)
655*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,ERROR_exit(1),"cannot change associative array %s to index array",nv_name(np));
656*b30d1939SAndy Fiddaman 			else if( (iarray||(flag&NV_ARRAY)) && nv_isvtree(np) && !nv_type(np))
657*b30d1939SAndy Fiddaman 				_nv_unset(np,NV_EXPORT);
6587c2fbfb3SApril Chin 			if(tp->pflag)
6597c2fbfb3SApril Chin 			{
660*b30d1939SAndy Fiddaman 				if(!nv_istable(np))
661*b30d1939SAndy Fiddaman 					nv_attribute(np,sfstdout,tp->prefix,1);
6627c2fbfb3SApril Chin 				print_value(sfstdout,np,tp);
663da2e3ebdSchin 				continue;
664da2e3ebdSchin 			}
665da2e3ebdSchin 			if(flag==NV_ASSIGN && !ref && tp->aflag!='-' && !strchr(name,'='))
666da2e3ebdSchin 			{
667da2e3ebdSchin 				if(troot!=shp->var_tree && (nv_isnull(np) || !print_namval(sfstdout,np,0,tp)))
668da2e3ebdSchin 				{
669da2e3ebdSchin 					sfprintf(sfstderr,sh_translate(e_noalias),name);
670da2e3ebdSchin 					r++;
671da2e3ebdSchin 				}
6727c2fbfb3SApril Chin 				if(!comvar && !iarray)
6737c2fbfb3SApril Chin 					continue;
6747c2fbfb3SApril Chin 			}
675*b30d1939SAndy Fiddaman 			if(!nv_isarray(np) && !strchr(name,'=') && !(shp->envlist  && nv_onlist(shp->envlist,name)))
676*b30d1939SAndy Fiddaman 			{
677*b30d1939SAndy Fiddaman 				if(comvar || (shp->last_root==shp->var_tree && (tp->tp || (!shp->st.real_fun && (nvflags&NV_STATIC)) || (!(flag&(NV_EXPORT|NV_RDONLY)) && nv_isattr(np,(NV_EXPORT|NV_IMPORT))==(NV_EXPORT|NV_IMPORT)))))
678*b30d1939SAndy Fiddaman {
679*b30d1939SAndy Fiddaman 					_nv_unset(np,0);
680*b30d1939SAndy Fiddaman }
681*b30d1939SAndy Fiddaman 			}
6827c2fbfb3SApril Chin 			if(troot==shp->var_tree)
6837c2fbfb3SApril Chin 			{
6847c2fbfb3SApril Chin 				if(iarray)
6857c2fbfb3SApril Chin 				{
6867c2fbfb3SApril Chin 					if(tp->tname)
6877c2fbfb3SApril Chin 						nv_atypeindex(np,tp->tname+1);
6887c2fbfb3SApril Chin 					else if(nv_isnull(np))
6897c2fbfb3SApril Chin 						nv_onattr(np,NV_ARRAY|(comvar?NV_NOFREE:0));
6907c2fbfb3SApril Chin 					else
6913e14f97fSRoger A. Faulkner 					{
6923e14f97fSRoger A. Faulkner 						if(ap && comvar)
6933e14f97fSRoger A. Faulkner 							ap->nelem |= ARRAY_TREE;
6947c2fbfb3SApril Chin 						nv_putsub(np, (char*)0, 0);
6953e14f97fSRoger A. Faulkner 					}
6967c2fbfb3SApril Chin 				}
6977c2fbfb3SApril Chin 				else if(nvflags&NV_ARRAY)
6987c2fbfb3SApril Chin 				{
6997c2fbfb3SApril Chin 					if(comvar)
7007c2fbfb3SApril Chin 					{
70134f9b3eeSRoland Mainz 						Namarr_t *ap=nv_arrayptr(np);
70234f9b3eeSRoland Mainz 						if(ap)
70334f9b3eeSRoland Mainz 							ap->nelem |= ARRAY_TREE;
70434f9b3eeSRoland Mainz 						else
70534f9b3eeSRoland Mainz 						{
70634f9b3eeSRoland Mainz 							_nv_unset(np,NV_RDONLY);
70734f9b3eeSRoland Mainz 							nv_onattr(np,NV_NOFREE);
70834f9b3eeSRoland Mainz 						}
7097c2fbfb3SApril Chin 					}
7107c2fbfb3SApril Chin 					nv_setarray(np,nv_associative);
7117c2fbfb3SApril Chin 				}
71234f9b3eeSRoland Mainz 				else if(comvar && !nv_isvtree(np) && !nv_rename(np,flag|NV_COMVAR))
7137c2fbfb3SApril Chin 					nv_setvtree(np);
7147c2fbfb3SApril Chin 			}
7157c2fbfb3SApril Chin 			if(flag&NV_MOVE)
7167c2fbfb3SApril Chin 			{
7177c2fbfb3SApril Chin 				nv_rename(np, flag);
7187c2fbfb3SApril Chin 				nv_close(np);
719da2e3ebdSchin 				continue;
720da2e3ebdSchin 			}
72134f9b3eeSRoland Mainz 			if(tp->tp && nv_type(np)!=tp->tp)
722da2e3ebdSchin 			{
723da2e3ebdSchin 				nv_settype(np,tp->tp,tp->aflag=='-'?0:NV_APPEND);
724da2e3ebdSchin 				flag = (np->nvflag&NV_NOCHANGE);
725da2e3ebdSchin 			}
726da2e3ebdSchin 			flag &= ~NV_ASSIGN;
727da2e3ebdSchin 			if(last=strchr(name,'='))
728da2e3ebdSchin 				*last = 0;
72934f9b3eeSRoland Mainz 			if (shp->typeinit)
73034f9b3eeSRoland Mainz 				continue;
731*b30d1939SAndy Fiddaman 			curflag = np->nvflag;
732*b30d1939SAndy Fiddaman 			if(!(flag&NV_INTEGER) && (flag&(NV_LTOU|NV_UTOL)))
733*b30d1939SAndy Fiddaman 			{
734*b30d1939SAndy Fiddaman 				Namfun_t *fp;
735*b30d1939SAndy Fiddaman 				char  *cp;
736*b30d1939SAndy Fiddaman 				if(!tp->wctname)
737*b30d1939SAndy Fiddaman 					errormsg(SH_DICT,ERROR_exit(1),e_mapchararg,nv_name(np));
738*b30d1939SAndy Fiddaman 				cp = (char*)nv_mapchar(np,0);
739*b30d1939SAndy Fiddaman 				if(fp=nv_mapchar(np,tp->wctname))
740*b30d1939SAndy Fiddaman 				{
741*b30d1939SAndy Fiddaman 					if(tp->aflag=='+')
742*b30d1939SAndy Fiddaman 					{
743*b30d1939SAndy Fiddaman 						if(cp && strcmp(cp,tp->wctname)==0)
744*b30d1939SAndy Fiddaman 						{
745*b30d1939SAndy Fiddaman 							nv_disc(np,fp,NV_POP);
746*b30d1939SAndy Fiddaman 							if(!(fp->nofree&1))
747*b30d1939SAndy Fiddaman 								free((void*)fp);
748*b30d1939SAndy Fiddaman 							nv_offattr(np,flag&(NV_LTOU|NV_UTOL));
749*b30d1939SAndy Fiddaman 						}
750*b30d1939SAndy Fiddaman 					}
751*b30d1939SAndy Fiddaman 					else if(!cp || strcmp(cp,tp->wctname))
752*b30d1939SAndy Fiddaman 					{
753*b30d1939SAndy Fiddaman 						nv_disc(np,fp,NV_LAST);
754*b30d1939SAndy Fiddaman 						nv_onattr(np,flag&(NV_LTOU|NV_UTOL));
755*b30d1939SAndy Fiddaman 					}
756*b30d1939SAndy Fiddaman 				}
757*b30d1939SAndy Fiddaman 			}
758da2e3ebdSchin 			if (tp->aflag == '-')
759da2e3ebdSchin 			{
76034f9b3eeSRoland Mainz 				if((flag&NV_EXPORT) && (strchr(name,'.') || nv_isvtree(np)))
761da2e3ebdSchin 					errormsg(SH_DICT,ERROR_exit(1),e_badexport,name);
762da2e3ebdSchin #if SHOPT_BSH
763da2e3ebdSchin 				if(flag&NV_EXPORT)
764da2e3ebdSchin 					nv_offattr(np,NV_IMPORT);
765da2e3ebdSchin #endif /* SHOPT_BSH */
766da2e3ebdSchin 				newflag = curflag;
767da2e3ebdSchin 				if(flag&~NV_NOCHANGE)
768da2e3ebdSchin 					newflag &= NV_NOCHANGE;
769da2e3ebdSchin 				newflag |= flag;
770da2e3ebdSchin 				if (flag & (NV_LJUST|NV_RJUST))
771da2e3ebdSchin 				{
772da2e3ebdSchin 					if(!(flag&NV_RJUST))
773da2e3ebdSchin 						newflag &= ~NV_RJUST;
774da2e3ebdSchin 
775da2e3ebdSchin 					else if(!(flag&NV_LJUST))
776da2e3ebdSchin 						newflag &= ~NV_LJUST;
777da2e3ebdSchin 				}
778da2e3ebdSchin 			}
779da2e3ebdSchin 			else
780da2e3ebdSchin 			{
781da2e3ebdSchin 				if((flag&NV_RDONLY) && (curflag&NV_RDONLY))
782da2e3ebdSchin 					errormsg(SH_DICT,ERROR_exit(1),e_readonly,nv_name(np));
783da2e3ebdSchin 				newflag = curflag & ~flag;
784da2e3ebdSchin 			}
785da2e3ebdSchin 			if (tp->aflag && (tp->argnum>0 || (curflag!=newflag)))
786da2e3ebdSchin 			{
787da2e3ebdSchin 				if(shp->subshell)
788da2e3ebdSchin 					sh_assignok(np,1);
789da2e3ebdSchin 				if(troot!=shp->var_tree)
790da2e3ebdSchin 					nv_setattr(np,newflag&~NV_ASSIGN);
791da2e3ebdSchin 				else
792da2e3ebdSchin 				{
793da2e3ebdSchin 					char *oldname=0;
7947c2fbfb3SApril Chin 					int len=strlen(name);
795da2e3ebdSchin 					if(tp->argnum==1 && newflag==NV_INTEGER && nv_isattr(np,NV_INTEGER))
796da2e3ebdSchin 						tp->argnum = 10;
7977c2fbfb3SApril Chin 					if(np->nvfun && !nv_isarray(np) && name[len-1]=='.')
7987c2fbfb3SApril Chin 						newflag |= NV_NODISC;
799da2e3ebdSchin 					nv_newattr (np, newflag&~NV_ASSIGN,tp->argnum);
800da2e3ebdSchin 					if(oldname)
801da2e3ebdSchin 						np->nvname = oldname;
802da2e3ebdSchin 				}
803da2e3ebdSchin 			}
8047c2fbfb3SApril Chin 			if(tp->help && !nv_isattr(np,NV_MINIMAL|NV_EXPORT))
8057c2fbfb3SApril Chin 			{
8067c2fbfb3SApril Chin 				np->nvenv = tp->help;
8077c2fbfb3SApril Chin 				nv_onattr(np,NV_EXPORT);
8087c2fbfb3SApril Chin 			}
809da2e3ebdSchin 			if(last)
810da2e3ebdSchin 				*last = '=';
811da2e3ebdSchin 			/* set or unset references */
812da2e3ebdSchin 			if(ref)
813da2e3ebdSchin 			{
814da2e3ebdSchin 				if(tp->aflag=='-')
815da2e3ebdSchin 				{
816da2e3ebdSchin 					Dt_t *hp=0;
817da2e3ebdSchin 					if(nv_isattr(np,NV_PARAM) && shp->st.prevst)
818da2e3ebdSchin 					{
819da2e3ebdSchin 						if(!(hp=(Dt_t*)shp->st.prevst->save_tree))
820da2e3ebdSchin 							hp = dtvnext(shp->var_tree);
821da2e3ebdSchin 					}
8227c2fbfb3SApril Chin 					if(tp->sh->mktype)
8237c2fbfb3SApril Chin 						nv_onattr(np,NV_REF|NV_FUNCT);
8247c2fbfb3SApril Chin 					else
8257c2fbfb3SApril Chin 						nv_setref(np,hp,NV_VARNAME);
826da2e3ebdSchin 				}
827da2e3ebdSchin 				else
828da2e3ebdSchin 					nv_unref(np);
829da2e3ebdSchin 			}
830da2e3ebdSchin 			nv_close(np);
831da2e3ebdSchin 		}
832da2e3ebdSchin 	}
833*b30d1939SAndy Fiddaman 	else
834da2e3ebdSchin 	{
8357c2fbfb3SApril Chin 		if(shp->prefix)
836*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,2, e_subcomvar,shp->prefix);
837da2e3ebdSchin 		if(tp->aflag)
838da2e3ebdSchin 		{
839da2e3ebdSchin 			if(troot==shp->fun_tree)
840da2e3ebdSchin 			{
841da2e3ebdSchin 				flag |= NV_FUNCTION;
842da2e3ebdSchin 				tp->prefix = 0;
843da2e3ebdSchin 			}
844da2e3ebdSchin 			else if(troot==shp->var_tree)
8457c2fbfb3SApril Chin 			{
846da2e3ebdSchin 				flag |= (nvflags&NV_ARRAY);
847*b30d1939SAndy Fiddaman 				if(iarray)
848