1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
18*b30d1939SAndy Fiddaman *                                                                      *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman /*
22*b30d1939SAndy Fiddaman  * Shell arithmetic - uses streval library
23*b30d1939SAndy Fiddaman  *   David Korn
24*b30d1939SAndy Fiddaman  *   AT&T Labs
25*b30d1939SAndy Fiddaman  */
26*b30d1939SAndy Fiddaman 
27*b30d1939SAndy Fiddaman #include	"defs.h"
28*b30d1939SAndy Fiddaman #include	"lexstates.h"
29*b30d1939SAndy Fiddaman #include	"name.h"
30*b30d1939SAndy Fiddaman #include	"streval.h"
31*b30d1939SAndy Fiddaman #include	"variables.h"
32*b30d1939SAndy Fiddaman #include	"builtins.h"
33*b30d1939SAndy Fiddaman 
34*b30d1939SAndy Fiddaman #ifndef LLONG_MAX
35*b30d1939SAndy Fiddaman #define LLONG_MAX	LONG_MAX
36*b30d1939SAndy Fiddaman #endif
37*b30d1939SAndy Fiddaman 
38*b30d1939SAndy Fiddaman typedef Sfdouble_t (*Math_f)(Sfdouble_t, ...);
39*b30d1939SAndy Fiddaman 
40*b30d1939SAndy Fiddaman extern const Namdisc_t	ENUM_disc;
41*b30d1939SAndy Fiddaman static Sfdouble_t	NaN, Inf, Fun;
42*b30d1939SAndy Fiddaman static Namval_t Infnod =
43*b30d1939SAndy Fiddaman {
44*b30d1939SAndy Fiddaman 	{ 0 },
45*b30d1939SAndy Fiddaman 	"Inf",
46*b30d1939SAndy Fiddaman };
47*b30d1939SAndy Fiddaman 
48*b30d1939SAndy Fiddaman static Namval_t NaNnod =
49*b30d1939SAndy Fiddaman {
50*b30d1939SAndy Fiddaman 	{ 0 },
51*b30d1939SAndy Fiddaman 	"NaN",
52*b30d1939SAndy Fiddaman };
53*b30d1939SAndy Fiddaman 
54*b30d1939SAndy Fiddaman static Namval_t FunNode =
55*b30d1939SAndy Fiddaman {
56*b30d1939SAndy Fiddaman 	{ 0 },
57*b30d1939SAndy Fiddaman 	"?",
58*b30d1939SAndy Fiddaman };
59*b30d1939SAndy Fiddaman 
scope(register Namval_t * np,register struct lval * lvalue,int assign)60*b30d1939SAndy Fiddaman static Namval_t *scope(register Namval_t *np,register struct lval *lvalue,int assign)
61*b30d1939SAndy Fiddaman {
62*b30d1939SAndy Fiddaman 	register int flag = lvalue->flag;
63*b30d1939SAndy Fiddaman 	register char *sub=0, *cp=(char*)np;
64*b30d1939SAndy Fiddaman 	register Namval_t *mp;
65*b30d1939SAndy Fiddaman 	Shell_t		*shp = lvalue->shp;
66*b30d1939SAndy Fiddaman 	int	flags = HASH_NOSCOPE|HASH_SCOPE|HASH_BUCKET;
67*b30d1939SAndy Fiddaman 	int	c=0,nosub = lvalue->nosub;
68*b30d1939SAndy Fiddaman 	Dt_t	*sdict = (shp->st.real_fun? shp->st.real_fun->sdict:0);
69*b30d1939SAndy Fiddaman 	Dt_t	*nsdict = (shp->namespace?nv_dict(shp->namespace):0);
70*b30d1939SAndy Fiddaman 	Dt_t	*root = shp->var_tree;
71*b30d1939SAndy Fiddaman 	assign = assign?NV_ASSIGN:NV_NOASSIGN;
72*b30d1939SAndy Fiddaman 	lvalue->nosub = 0;
73*b30d1939SAndy Fiddaman 	if(nosub<0 && lvalue->ovalue)
74*b30d1939SAndy Fiddaman 		return((Namval_t*)lvalue->ovalue);
75*b30d1939SAndy Fiddaman 	lvalue->ovalue = 0;
76*b30d1939SAndy Fiddaman 	if(cp>=lvalue->expr &&  cp < lvalue->expr+lvalue->elen)
77*b30d1939SAndy Fiddaman 	{
78*b30d1939SAndy Fiddaman 		int offset;
79*b30d1939SAndy Fiddaman 		/* do binding to node now */
80*b30d1939SAndy Fiddaman 		int c = cp[flag];
81*b30d1939SAndy Fiddaman 		cp[flag] = 0;
82*b30d1939SAndy Fiddaman 		if((!(np = nv_open(cp,shp->var_tree,assign|NV_VARNAME|NV_NOADD|NV_NOFAIL)) || nv_isnull(np)) && sh_macfun(shp,cp, offset = staktell()))
83*b30d1939SAndy Fiddaman 		{
84*b30d1939SAndy Fiddaman 			Fun = sh_arith(shp,sub=stakptr(offset));
85*b30d1939SAndy Fiddaman 			FunNode.nvalue.ldp = &Fun;
86*b30d1939SAndy Fiddaman 			nv_onattr(&FunNode,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
87*b30d1939SAndy Fiddaman 			cp[flag] = c;
88*b30d1939SAndy Fiddaman 			return(&FunNode);
89*b30d1939SAndy Fiddaman 		}
90*b30d1939SAndy Fiddaman 		if(!np && assign)
91*b30d1939SAndy Fiddaman 			np = nv_open(cp,shp->var_tree,assign|NV_VARNAME);
92*b30d1939SAndy Fiddaman 		cp[flag] = c;
93*b30d1939SAndy Fiddaman 		if(!np)
94*b30d1939SAndy Fiddaman 			return(0);
95*b30d1939SAndy Fiddaman 		root = shp->last_root;
96*b30d1939SAndy Fiddaman 		if(cp[flag+1]=='[')
97*b30d1939SAndy Fiddaman 			flag++;
98*b30d1939SAndy Fiddaman 		else
99*b30d1939SAndy Fiddaman 			flag = 0;
100*b30d1939SAndy Fiddaman 		cp = (char*)np;
101*b30d1939SAndy Fiddaman 	}
102*b30d1939SAndy Fiddaman 	else if(assign==NV_ASSIGN  && nv_isnull(np) && !nv_isattr(np, ~(NV_MINIMAL|NV_NOFREE)))
103*b30d1939SAndy Fiddaman 		flags |= NV_ADD;
104*b30d1939SAndy Fiddaman 	if((lvalue->emode&ARITH_COMP) && dtvnext(root) && ((sdict && (mp=nv_search(cp,sdict,flags&~NV_ADD))) || (mp=nv_search(cp,root,flags&~(NV_ADD))) || (nsdict && (mp=nv_search(cp,nsdict,flags&~(NV_ADD|HASH_NOSCOPE)))) ))
105*b30d1939SAndy Fiddaman 		np = mp;
106*b30d1939SAndy Fiddaman 	while(nv_isref(np))
107*b30d1939SAndy Fiddaman 	{
108*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
109*b30d1939SAndy Fiddaman 		int n,dim;
110*b30d1939SAndy Fiddaman 		dim = nv_refdimen(np);
111*b30d1939SAndy Fiddaman 		n = nv_refindex(np);
112*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
113*b30d1939SAndy Fiddaman 		sub = nv_refsub(np);
114*b30d1939SAndy Fiddaman 		np = nv_refnode(np);
115*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
116*b30d1939SAndy Fiddaman 		if(n)
117*b30d1939SAndy Fiddaman 		{
118*b30d1939SAndy Fiddaman 			Namarr_t *ap = nv_arrayptr(np);
119*b30d1939SAndy Fiddaman 			ap->nelem = dim;
120*b30d1939SAndy Fiddaman 			nv_putsub(np,(char*)0,n);
121*b30d1939SAndy Fiddaman 		}
122*b30d1939SAndy Fiddaman 		else
123*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
124*b30d1939SAndy Fiddaman 		if(sub)
125*b30d1939SAndy Fiddaman 			nv_putsub(np,sub,assign==NV_ASSIGN?ARRAY_ADD:0);
126*b30d1939SAndy Fiddaman 	}
127*b30d1939SAndy Fiddaman 	if(!nosub && flag)
128*b30d1939SAndy Fiddaman 	{
129*b30d1939SAndy Fiddaman 		int		hasdot = 0;
130*b30d1939SAndy Fiddaman 		cp = (char*)&lvalue->expr[flag];
131*b30d1939SAndy Fiddaman 		if(sub)
132*b30d1939SAndy Fiddaman 		{
133*b30d1939SAndy Fiddaman 			goto skip;
134*b30d1939SAndy Fiddaman 		}
135*b30d1939SAndy Fiddaman 		sub = cp;
136*b30d1939SAndy Fiddaman 		while(1)
137*b30d1939SAndy Fiddaman 		{
138*b30d1939SAndy Fiddaman 			Namarr_t	*ap;
139*b30d1939SAndy Fiddaman 			Namval_t	*nq;
140*b30d1939SAndy Fiddaman 			cp = nv_endsubscript(np,cp,0);
141*b30d1939SAndy Fiddaman 			if(c || *cp=='.')
142*b30d1939SAndy Fiddaman 			{
143*b30d1939SAndy Fiddaman 				c = '.';
144*b30d1939SAndy Fiddaman 				while(*cp=='.')
145*b30d1939SAndy Fiddaman 				{
146*b30d1939SAndy Fiddaman 					hasdot=1;
147*b30d1939SAndy Fiddaman 					cp++;
148*b30d1939SAndy Fiddaman 					while(c=mbchar(cp),isaname(c));
149*b30d1939SAndy Fiddaman 				}
150*b30d1939SAndy Fiddaman 				if(c=='[')
151*b30d1939SAndy Fiddaman 					continue;
152*b30d1939SAndy Fiddaman 			}
153*b30d1939SAndy Fiddaman 			flag = *cp;
154*b30d1939SAndy Fiddaman 			*cp = 0;
155*b30d1939SAndy Fiddaman 			if(c || hasdot)
156*b30d1939SAndy Fiddaman 			{
157*b30d1939SAndy Fiddaman 				sfprintf(shp->strbuf,"%s%s%c",nv_name(np),sub,0);
158*b30d1939SAndy Fiddaman 				sub = sfstruse(shp->strbuf);
159*b30d1939SAndy Fiddaman 			}
160*b30d1939SAndy Fiddaman 			if(strchr(sub,'$'))
161*b30d1939SAndy Fiddaman 				sub = sh_mactrim(shp,sub,0);
162*b30d1939SAndy Fiddaman 			*cp = flag;
163*b30d1939SAndy Fiddaman 			if(c || hasdot)
164*b30d1939SAndy Fiddaman 			{
165*b30d1939SAndy Fiddaman 				np = nv_open(sub,shp->var_tree,NV_VARNAME|assign);
166*b30d1939SAndy Fiddaman 				return(np);
167*b30d1939SAndy Fiddaman 			}
168*b30d1939SAndy Fiddaman #if SHOPT_FIXEDARRAY
169*b30d1939SAndy Fiddaman 			ap = nv_arrayptr(np);
170*b30d1939SAndy Fiddaman 			cp = nv_endsubscript(np,sub,NV_ADD|NV_SUBQUOTE|(ap&&ap->fixed?NV_FARRAY:0));
171*b30d1939SAndy Fiddaman #else
172*b30d1939SAndy Fiddaman 			cp = nv_endsubscript(np,sub,NV_ADD|NV_SUBQUOTE);
173*b30d1939SAndy Fiddaman #endif /* SHOPT_FIXEDARRAY */
174*b30d1939SAndy Fiddaman 			if(*cp!='[')
175*b30d1939SAndy Fiddaman 				break;
176*b30d1939SAndy Fiddaman 		skip:
177*b30d1939SAndy Fiddaman 			if(nq = nv_opensub(np))
178*b30d1939SAndy Fiddaman 				np = nq;
179*b30d1939SAndy Fiddaman 			else
180*b30d1939SAndy Fiddaman 			{
181*b30d1939SAndy Fiddaman 				ap = nv_arrayptr(np);
182*b30d1939SAndy Fiddaman 				if(ap && !ap->table)
183*b30d1939SAndy Fiddaman 					ap->table = dtopen(&_Nvdisc,Dtoset);
184*b30d1939SAndy Fiddaman 				if(ap && ap->table && (nq=nv_search(nv_getsub(np),ap->table,NV_ADD)))
185*b30d1939SAndy Fiddaman 					nq->nvenv = (char*)np;
186*b30d1939SAndy Fiddaman 				if(nq && nv_isnull(nq))
187*b30d1939SAndy Fiddaman 					np = nv_arraychild(np,nq,0);
188*b30d1939SAndy Fiddaman 			}
189*b30d1939SAndy Fiddaman 			sub = cp;
190*b30d1939SAndy Fiddaman 		}
191*b30d1939SAndy Fiddaman 	}
192*b30d1939SAndy Fiddaman 	else if(nosub>0)
193*b30d1939SAndy Fiddaman 		nv_putsub(np,(char*)0,nosub-1);
194*b30d1939SAndy Fiddaman 	return(np);
195*b30d1939SAndy Fiddaman }
196*b30d1939SAndy Fiddaman 
sh_mathstdfun(const char * fname,size_t fsize,short * nargs)197*b30d1939SAndy Fiddaman static Math_f sh_mathstdfun(const char *fname, size_t fsize, short * nargs)
198*b30d1939SAndy Fiddaman {
199*b30d1939SAndy Fiddaman 	register const struct mathtab *tp;
200*b30d1939SAndy Fiddaman 	register char c = fname[0];
201*b30d1939SAndy Fiddaman 	for(tp=shtab_math; *tp->fname; tp++)
202*b30d1939SAndy Fiddaman 	{
203*b30d1939SAndy Fiddaman 		if(*tp->fname > c)
204*b30d1939SAndy Fiddaman 			break;
205*b30d1939SAndy Fiddaman 		if(tp->fname[1]==c && tp->fname[fsize+1]==0 && strncmp(&tp->fname[1],fname,fsize)==0)
206*b30d1939SAndy Fiddaman 		{
207*b30d1939SAndy Fiddaman 			if(nargs)
208*b30d1939SAndy Fiddaman 				*nargs = *tp->fname;
209*b30d1939SAndy Fiddaman 			return(tp->fnptr);
210*b30d1939SAndy Fiddaman 		}
211*b30d1939SAndy Fiddaman 	}
212*b30d1939SAndy Fiddaman 	return(0);
213*b30d1939SAndy Fiddaman }
214*b30d1939SAndy Fiddaman 
sh_mathstd(const char * name)215*b30d1939SAndy Fiddaman int	sh_mathstd(const char *name)
216*b30d1939SAndy Fiddaman {
217*b30d1939SAndy Fiddaman 	return(sh_mathstdfun(name,strlen(name),NULL)!=0);
218*b30d1939SAndy Fiddaman }
219*b30d1939SAndy Fiddaman 
arith(const char ** ptr,struct lval * lvalue,int type,Sfdouble_t n)220*b30d1939SAndy Fiddaman static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdouble_t n)
221*b30d1939SAndy Fiddaman {
222*b30d1939SAndy Fiddaman 	Shell_t		*shp = lvalue->shp;
223*b30d1939SAndy Fiddaman 	register Sfdouble_t r= 0;
224*b30d1939SAndy Fiddaman 	char *str = (char*)*ptr;
225*b30d1939SAndy Fiddaman 	register char *cp;
226*b30d1939SAndy Fiddaman 	switch(type)
227*b30d1939SAndy Fiddaman 	{
228*b30d1939SAndy Fiddaman 	    case ASSIGN:
229*b30d1939SAndy Fiddaman 	    {
230*b30d1939SAndy Fiddaman 		register Namval_t *np = (Namval_t*)(lvalue->value);
231*b30d1939SAndy Fiddaman 		np = scope(np,lvalue,1);
232*b30d1939SAndy Fiddaman 		nv_putval(np, (char*)&n, NV_LDOUBLE);
233*b30d1939SAndy Fiddaman 		if(lvalue->eflag)
234*b30d1939SAndy Fiddaman 			lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
235*b30d1939SAndy Fiddaman 		lvalue->eflag = 0;
236*b30d1939SAndy Fiddaman 		r=nv_getnum(np);
237*b30d1939SAndy Fiddaman 		lvalue->value = (char*)np;
238*b30d1939SAndy Fiddaman 		break;
239*b30d1939SAndy Fiddaman 	    }
240*b30d1939SAndy Fiddaman 	    case LOOKUP:
241*b30d1939SAndy Fiddaman 	    {
242*b30d1939SAndy Fiddaman 		register int c = *str;
243*b30d1939SAndy Fiddaman 		register char *xp=str;
244*b30d1939SAndy Fiddaman 		lvalue->value = (char*)0;
245*b30d1939SAndy Fiddaman 		if(c=='.')
246*b30d1939SAndy Fiddaman 			str++;
247*b30d1939SAndy Fiddaman 		c = mbchar(str);
248*b30d1939SAndy Fiddaman 		if(isaletter(c))
249*b30d1939SAndy Fiddaman 		{
250*b30d1939SAndy Fiddaman 			register Namval_t *np;
251*b30d1939SAndy Fiddaman 			int dot=0;
252*b30d1939SAndy Fiddaman 			while(1)
253*b30d1939SAndy Fiddaman 			{
254*b30d1939SAndy Fiddaman 				while(xp=str, c=mbchar(str), isaname(c));
255*b30d1939SAndy Fiddaman 				str = xp;
256*b30d1939SAndy Fiddaman 				while(c=='[' && dot==NV_NOADD)
257*b30d1939SAndy Fiddaman 				{
258*b30d1939SAndy Fiddaman 					str = nv_endsubscript((Namval_t*)0,str,0);
259*b30d1939SAndy Fiddaman 					c = *str;
260*b30d1939SAndy Fiddaman 				}
261*b30d1939SAndy Fiddaman 				if(c!='.')
262*b30d1939SAndy Fiddaman 					break;
263*b30d1939SAndy Fiddaman 				dot=NV_NOADD;
264*b30d1939SAndy Fiddaman 				if((c = *++str) !='[')
265*b30d1939SAndy Fiddaman 					continue;
266*b30d1939SAndy Fiddaman 				str = nv_endsubscript((Namval_t*)0,cp=str,NV_SUBQUOTE)-1;
267*b30d1939SAndy Fiddaman 				if(sh_checkid(cp+1,(char*)0))
268*b30d1939SAndy Fiddaman 					str -=2;
269*b30d1939SAndy Fiddaman 			}
270*b30d1939SAndy Fiddaman 			if(c=='(')
271*b30d1939SAndy Fiddaman 			{
272*b30d1939SAndy Fiddaman 				int off=stktell(shp->stk);
273*b30d1939SAndy Fiddaman 				int fsize = str- (char*)(*ptr);
274*b30d1939SAndy Fiddaman 				const struct mathtab *tp;
275*b30d1939SAndy Fiddaman 				Namval_t	*np;
276*b30d1939SAndy Fiddaman 				c = **ptr;
277*b30d1939SAndy Fiddaman 				lvalue->fun = 0;
278*b30d1939SAndy Fiddaman 				sfprintf(shp->stk,".sh.math.%.*s%c",fsize,*ptr,0);
279*b30d1939SAndy Fiddaman 				stkseek(shp->stk,off);
280*b30d1939SAndy Fiddaman 				if(np=nv_search(stkptr(shp->stk,off),shp->fun_tree,0))
281*b30d1939SAndy Fiddaman 				{
282*b30d1939SAndy Fiddaman 						lvalue->nargs = -np->nvalue.rp->argc;
283*b30d1939SAndy Fiddaman 						lvalue->fun = (Math_f)np;
284*b30d1939SAndy Fiddaman 						break;
285*b30d1939SAndy Fiddaman 				}
286*b30d1939SAndy Fiddaman 				if(fsize<=(sizeof(tp->fname)-2))
287*b30d1939SAndy Fiddaman 					lvalue->fun = (Math_f)sh_mathstdfun(*ptr,fsize,&lvalue->nargs);
288*b30d1939SAndy Fiddaman 				if(lvalue->fun)
289*b30d1939SAndy Fiddaman 					break;
290*b30d1939SAndy Fiddaman 				if(lvalue->emode&ARITH_COMP)
291*b30d1939SAndy Fiddaman 					lvalue->value = (char*)e_function;
292*b30d1939SAndy Fiddaman 				else
293*b30d1939SAndy Fiddaman 					lvalue->value = (char*)ERROR_dictionary(e_function);
294*b30d1939SAndy Fiddaman 				return(r);
295*b30d1939SAndy Fiddaman 			}
296*b30d1939SAndy Fiddaman 			if((lvalue->emode&ARITH_COMP) && dot)
297*b30d1939SAndy Fiddaman 			{
298*b30d1939SAndy Fiddaman 				lvalue->value = (char*)*ptr;
299*b30d1939SAndy Fiddaman 				lvalue->flag =  str-lvalue->value;
300*b30d1939SAndy Fiddaman 				break;
301*b30d1939SAndy Fiddaman 			}
302*b30d1939SAndy Fiddaman 			*str = 0;
303*b30d1939SAndy Fiddaman 			if(sh_isoption(SH_NOEXEC))
304*b30d1939SAndy Fiddaman 				np = L_ARGNOD;
305*b30d1939SAndy Fiddaman 			else
306*b30d1939SAndy Fiddaman 			{
307*b30d1939SAndy Fiddaman 				int offset = staktell();
308*b30d1939SAndy Fiddaman 				char *saveptr = stakfreeze(0);
309*b30d1939SAndy Fiddaman 				Dt_t  *root = (lvalue->emode&ARITH_COMP)?shp->var_base:shp->var_tree;
310*b30d1939SAndy Fiddaman 				*str = c;
311*b30d1939SAndy Fiddaman 				cp = str;
312*b30d1939SAndy Fiddaman 				while(c=='[' || c=='.')
313*b30d1939SAndy Fiddaman 				{
314*b30d1939SAndy Fiddaman 					if(c=='[')
315*b30d1939SAndy Fiddaman 					{
316*b30d1939SAndy Fiddaman 						str = nv_endsubscript(np,str,0);
317*b30d1939SAndy Fiddaman 						if((c= *str)!='[' &&  c!='.')
318*b30d1939SAndy Fiddaman 						{
319*b30d1939SAndy Fiddaman 							str = cp;
320*b30d1939SAndy Fiddaman 							c = '[';
321*b30d1939SAndy Fiddaman 							break;
322*b30d1939SAndy Fiddaman 						}
323*b30d1939SAndy Fiddaman 					}
324*b30d1939SAndy Fiddaman 					else
325*b30d1939SAndy Fiddaman 					{
326*b30d1939SAndy Fiddaman 						dot = NV_NOADD|NV_NOFAIL;
327*b30d1939SAndy Fiddaman 						str++;
328*b30d1939SAndy Fiddaman 						while(xp=str, c=mbchar(str), isaname(c));
329*b30d1939SAndy Fiddaman 						str = xp;
330*b30d1939SAndy Fiddaman 					}
331*b30d1939SAndy Fiddaman 				}
332*b30d1939SAndy Fiddaman 				*str = 0;
333*b30d1939SAndy Fiddaman 				cp = (char*)*ptr;
334*b30d1939SAndy Fiddaman 				if ((cp[0] == 'i' || cp[0] == 'I') && (cp[1] == 'n' || cp[1] == 'N') && (cp[2] == 'f' || cp[2] == 'F') && cp[3] == 0)
335*b30d1939SAndy Fiddaman 				{
336*b30d1939SAndy Fiddaman 					Inf = strtold("Inf", NiL);
337*b30d1939SAndy Fiddaman 					Infnod.nvalue.ldp = &Inf;
338*b30d1939SAndy Fiddaman 					np = &Infnod;
339*b30d1939SAndy Fiddaman 					nv_onattr(np,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
340*b30d1939SAndy Fiddaman 				}
341*b30d1939SAndy Fiddaman 				else if ((cp[0] == 'n' || cp[0] == 'N') && (cp[1] == 'a' || cp[1] == 'A') && (cp[2] == 'n' || cp[2] == 'N') && cp[3] == 0)
342*b30d1939SAndy Fiddaman 				{
343*b30d1939SAndy Fiddaman 					NaN = strtold("NaN", NiL);
344*b30d1939SAndy Fiddaman 					NaNnod.nvalue.ldp = &NaN;
345*b30d1939SAndy Fiddaman 					np = &NaNnod;
346*b30d1939SAndy Fiddaman 					nv_onattr(np,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
347*b30d1939SAndy Fiddaman 				}
348*b30d1939SAndy Fiddaman 				else if(!(np = nv_open(*ptr,root,NV_NOREF|NV_NOASSIGN|NV_VARNAME|dot)))
349*b30d1939SAndy Fiddaman 				{
350*b30d1939SAndy Fiddaman 					lvalue->value = (char*)*ptr;
351*b30d1939SAndy Fiddaman 					lvalue->flag =  str-lvalue->value;
352*b30d1939SAndy Fiddaman 				}
353*b30d1939SAndy Fiddaman 				if(saveptr != stakptr(0))
354*b30d1939SAndy Fiddaman 					stakset(saveptr,offset);
355*b30d1939SAndy Fiddaman 				else
356*b30d1939SAndy Fiddaman 					stakseek(offset);
357*b30d1939SAndy Fiddaman 			}
358*b30d1939SAndy Fiddaman 			*str = c;
359*b30d1939SAndy Fiddaman 			if(!np && lvalue->value)
360*b30d1939SAndy Fiddaman 				break;
361*b30d1939SAndy Fiddaman 			lvalue->value = (char*)np;
362*b30d1939SAndy Fiddaman 			/* bind subscript later */
363*b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
364*b30d1939SAndy Fiddaman 				lvalue->isfloat=1;
365*b30d1939SAndy Fiddaman 			lvalue->flag = 0;
366*b30d1939SAndy Fiddaman 			if(c=='[')
367*b30d1939SAndy Fiddaman 			{
368*b30d1939SAndy Fiddaman 				lvalue->flag = (str-lvalue->expr);
369*b30d1939SAndy Fiddaman 				do
370*b30d1939SAndy Fiddaman 				{
371*b30d1939SAndy Fiddaman 					while(c=='.')
372*b30d1939SAndy Fiddaman 					{
373*b30d1939SAndy Fiddaman 						str++;
374*b30d1939SAndy Fiddaman 						while(xp=str, c=mbchar(str), isaname(c));
375*b30d1939SAndy Fiddaman 						c = *(str = xp);
376*b30d1939SAndy Fiddaman 					}
377*b30d1939SAndy Fiddaman 					if(c=='[')
378*b30d1939SAndy Fiddaman 						str = nv_endsubscript(np,str,0);
379*b30d1939SAndy Fiddaman 				}
380*b30d1939SAndy Fiddaman 				while((c= *str)=='[' || c=='.');
381*b30d1939SAndy Fiddaman 				break;
382*b30d1939SAndy Fiddaman 			}
383*b30d1939SAndy Fiddaman 		}
384*b30d1939SAndy Fiddaman 		else
385*b30d1939SAndy Fiddaman 		{
386*b30d1939SAndy Fiddaman 			char	lastbase=0, *val = xp, oerrno = errno;
387*b30d1939SAndy Fiddaman 			lvalue->eflag = 0;
388*b30d1939SAndy Fiddaman 			errno = 0;
389*b30d1939SAndy Fiddaman 			if(shp->bltindata.bnode==SYSLET && !sh_isoption(SH_LETOCTAL))
390*b30d1939SAndy Fiddaman 			{
391*b30d1939SAndy Fiddaman 				while(*val=='0' && isdigit(val[1]))
392*b30d1939SAndy Fiddaman 					val++;
393*b30d1939SAndy Fiddaman 			}
394*b30d1939SAndy Fiddaman 			r = strtonll(val,&str, &lastbase,-1);
395*b30d1939SAndy Fiddaman 			if(*str=='8' || *str=='9')
396*b30d1939SAndy Fiddaman 			{
397*b30d1939SAndy Fiddaman 				lastbase=10;
398*b30d1939SAndy Fiddaman 				errno = 0;
399*b30d1939SAndy Fiddaman 				r = strtonll(val,&str, &lastbase,-1);
400*b30d1939SAndy Fiddaman 			}
401*b30d1939SAndy Fiddaman 			if(lastbase<=1)
402*b30d1939SAndy Fiddaman 				lastbase=10;
403*b30d1939SAndy Fiddaman 			if(*val=='0')
404*b30d1939SAndy Fiddaman 			{
405*b30d1939SAndy Fiddaman 				while(*val=='0')
406*b30d1939SAndy Fiddaman 					val++;
407*b30d1939SAndy Fiddaman 				if(*val==0 || *val=='.' || *val=='x' || *val=='X')
408*b30d1939SAndy Fiddaman 					val--;
409*b30d1939SAndy Fiddaman 			}
410*b30d1939SAndy Fiddaman 			if(r==LLONG_MAX && errno)
411*b30d1939SAndy Fiddaman 				c='e';
412*b30d1939SAndy Fiddaman 			else
413*b30d1939SAndy Fiddaman 				c = *str;
414*b30d1939SAndy Fiddaman 			if(c==GETDECIMAL(0) || c=='e' || c == 'E' || lastbase ==
415*b30d1939SAndy Fiddaman  16 && (c == 'p' || c == 'P'))
416*b30d1939SAndy Fiddaman 			{
417*b30d1939SAndy Fiddaman 				lvalue->isfloat=1;
418*b30d1939SAndy Fiddaman 				r = strtold(val,&str);
419*b30d1939SAndy Fiddaman 			}
420*b30d1939SAndy Fiddaman 			else if(lastbase==10 && val[1])
421*b30d1939SAndy Fiddaman 			{
422*b30d1939SAndy Fiddaman 				if(val[2]=='#')
423*b30d1939SAndy Fiddaman 					val += 3;
424*b30d1939SAndy Fiddaman 				if((str-val)>2*sizeof(Sflong_t))
425*b30d1939SAndy Fiddaman 				{
426*b30d1939SAndy Fiddaman 					Sfdouble_t rr;
427*b30d1939SAndy Fiddaman 					rr = strtold(val,&str);
428*b30d1939SAndy Fiddaman 					if(rr!=r)
429*b30d1939SAndy Fiddaman 					{
430*b30d1939SAndy Fiddaman 						r = rr;
431*b30d1939SAndy Fiddaman 						lvalue->isfloat=1;
432*b30d1939SAndy Fiddaman 					}
433*b30d1939SAndy Fiddaman 				}
434*b30d1939SAndy Fiddaman 			}
435*b30d1939SAndy Fiddaman 			errno = oerrno;
436*b30d1939SAndy Fiddaman 		}
437*b30d1939SAndy Fiddaman 		break;
438*b30d1939SAndy Fiddaman 	    }
439*b30d1939SAndy Fiddaman 	    case VALUE:
440*b30d1939SAndy Fiddaman 	    {
441*b30d1939SAndy Fiddaman 		register Namval_t *np = (Namval_t*)(lvalue->value);
442*b30d1939SAndy Fiddaman 		if(sh_isoption(SH_NOEXEC))
443*b30d1939SAndy Fiddaman 			return(0);
444*b30d1939SAndy Fiddaman 		np = scope(np,lvalue,0);
445*b30d1939SAndy Fiddaman 		if(!np)
446*b30d1939SAndy Fiddaman 		{
447*b30d1939SAndy Fiddaman 			if(sh_isoption(SH_NOUNSET))
448*b30d1939SAndy Fiddaman 			{
449*b30d1939SAndy Fiddaman 				*ptr = lvalue->value;
450*b30d1939SAndy Fiddaman 				goto skip;
451*b30d1939SAndy Fiddaman 			}
452*b30d1939SAndy Fiddaman 			return(0);
453*b30d1939SAndy Fiddaman 		}
454*b30d1939SAndy Fiddaman 		lvalue->ovalue = (char*)np;
455*b30d1939SAndy Fiddaman 		if(lvalue->eflag)
456*b30d1939SAndy Fiddaman 			lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
457*b30d1939SAndy Fiddaman 		else if((Namfun_t*)lvalue->ptr && !nv_hasdisc(np,&ENUM_disc) && !nv_isattr(np,NV_INTEGER))
458*b30d1939SAndy Fiddaman 		{
459*b30d1939SAndy Fiddaman 			Namval_t *mp,node;
460*b30d1939SAndy Fiddaman 			mp = ((Namfun_t*)lvalue->ptr)->type;
461*b30d1939SAndy Fiddaman 			memset(&node,0,sizeof(node));
462*b30d1939SAndy Fiddaman 			nv_clone(mp,&node,0);
463*b30d1939SAndy Fiddaman 			nv_offattr(&node,NV_RDONLY|NV_NOFREE);
464*b30d1939SAndy Fiddaman 			nv_putval(&node,np->nvname,0);
465*b30d1939SAndy Fiddaman 			if(nv_isattr(&node,NV_NOFREE))
466*b30d1939SAndy Fiddaman 				return(r=nv_getnum(&node));
467*b30d1939SAndy Fiddaman 		}
468*b30d1939SAndy Fiddaman 		lvalue->eflag = 0;
469*b30d1939SAndy Fiddaman 		if(((lvalue->emode&2) || lvalue->level>1 || sh_isoption(SH_NOUNSET)) && nv_isnull(np) && !nv_isattr(np,NV_INTEGER))
470*b30d1939SAndy Fiddaman 		{
471*b30d1939SAndy Fiddaman 			*ptr = nv_name(np);
472*b30d1939SAndy Fiddaman 		skip:
473*b30d1939SAndy Fiddaman 			lvalue->value = (char*)ERROR_dictionary(e_notset);
474*b30d1939SAndy Fiddaman 			lvalue->emode |= 010;
475*b30d1939SAndy Fiddaman 			return(0);
476*b30d1939SAndy Fiddaman 		}
477*b30d1939SAndy Fiddaman 		r = nv_getnum(np);
478*b30d1939SAndy Fiddaman 		if(nv_isattr(np,NV_INTEGER|NV_BINARY)==(NV_INTEGER|NV_BINARY))
479*b30d1939SAndy Fiddaman 			lvalue->isfloat= (r!=(Sflong_t)r);
480*b30d1939SAndy Fiddaman 		else if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
481*b30d1939SAndy Fiddaman 			lvalue->isfloat=1;
482*b30d1939SAndy Fiddaman 		if((lvalue->emode&ARITH_ASSIGNOP) && nv_isarray(np))
483*b30d1939SAndy Fiddaman 			lvalue->nosub = nv_aindex(np)+1;
484*b30d1939SAndy Fiddaman 		return(r);
485*b30d1939SAndy Fiddaman 	    }
486*b30d1939SAndy Fiddaman 
487*b30d1939SAndy Fiddaman 	    case MESSAGE:
488*b30d1939SAndy Fiddaman 		sfsync(NIL(Sfio_t*));
489*b30d1939SAndy Fiddaman #if 0
490*b30d1939SAndy Fiddaman 		if(warn)
491*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_warn(0),lvalue->value,*ptr);
492*b30d1939SAndy Fiddaman 		else
493*b30d1939SAndy Fiddaman #endif
494*b30d1939SAndy Fiddaman 		if(lvalue->emode&ARITH_COMP)
495*b30d1939SAndy Fiddaman 			return(-1);
496*b30d1939SAndy Fiddaman 
497*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit((lvalue->emode&3)!=0),lvalue->value,*ptr);
498*b30d1939SAndy Fiddaman 	}
499*b30d1939SAndy Fiddaman 	*ptr = str;
500*b30d1939SAndy Fiddaman 	return(r);
501*b30d1939SAndy Fiddaman }
502*b30d1939SAndy Fiddaman 
503*b30d1939SAndy Fiddaman /*
504*b30d1939SAndy Fiddaman  * convert number defined by string to a Sfdouble_t
505*b30d1939SAndy Fiddaman  * ptr is set to the last character processed
506*b30d1939SAndy Fiddaman  * if mode>0, an error will be fatal with value <mode>
507*b30d1939SAndy Fiddaman  */
508*b30d1939SAndy Fiddaman 
sh_strnum(register const char * str,char ** ptr,int mode)509*b30d1939SAndy Fiddaman Sfdouble_t sh_strnum(register const char *str, char** ptr, int mode)
510*b30d1939SAndy Fiddaman {
511*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
512*b30d1939SAndy Fiddaman 	register Sfdouble_t d;
513*b30d1939SAndy Fiddaman 	char base=(shp->inarith?0:10), *last;
514*b30d1939SAndy Fiddaman 	if(*str==0)
515*b30d1939SAndy Fiddaman 	{
516*b30d1939SAndy Fiddaman 		if(ptr)
517*b30d1939SAndy Fiddaman 			*ptr = (char*)str;
518*b30d1939SAndy Fiddaman 		return(0);
519*b30d1939SAndy Fiddaman 	}
520*b30d1939SAndy Fiddaman 	errno = 0;
521*b30d1939SAndy Fiddaman 	d = strtonll(str,&last,&base,-1);
522*b30d1939SAndy Fiddaman 	if(*last || errno)
523*b30d1939SAndy Fiddaman 	{
524*b30d1939SAndy Fiddaman 		if (sh_isstate(SH_INIT)) {
525*b30d1939SAndy Fiddaman 			// Initializing means importing untrusted env vars.
526*b30d1939SAndy Fiddaman 			// Since the string does not appear to be a recognized
527*b30d1939SAndy Fiddaman 			// numeric literal give up. We can't safely call
528*b30d1939SAndy Fiddaman 			// strval() since that allows arbitrary expressions
529*b30d1939SAndy Fiddaman 			// which would create a security vulnerability.
530*b30d1939SAndy Fiddaman 			d = 0.0;
531*b30d1939SAndy Fiddaman 		} else {
532*b30d1939SAndy Fiddaman 			if(!last || *last!='.' || last[1]!='.')
533*b30d1939SAndy Fiddaman 				d = strval(shp,str,&last,arith,mode);
534*b30d1939SAndy Fiddaman 			if(!ptr && *last && mode>0)
535*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str);
536*b30d1939SAndy Fiddaman 		}
537*b30d1939SAndy Fiddaman 	}
538*b30d1939SAndy Fiddaman 	else if (!d && *str=='-')
539*b30d1939SAndy Fiddaman 		d = -0.0;
540*b30d1939SAndy Fiddaman 	if(ptr)
541*b30d1939SAndy Fiddaman 		*ptr = last;
542*b30d1939SAndy Fiddaman 	return(d);
543*b30d1939SAndy Fiddaman }
544*b30d1939SAndy Fiddaman 
sh_arith(Shell_t * shp,register const char * str)545*b30d1939SAndy Fiddaman Sfdouble_t sh_arith(Shell_t *shp,register const char *str)
546*b30d1939SAndy Fiddaman {
547*b30d1939SAndy Fiddaman 	return(sh_strnum(str, (char**)0, 1));
548*b30d1939SAndy Fiddaman }
549*b30d1939SAndy Fiddaman 
sh_arithcomp(Shell_t * shp,register char * str)550*b30d1939SAndy Fiddaman void	*sh_arithcomp(Shell_t *shp,register char *str)
551*b30d1939SAndy Fiddaman {
552*b30d1939SAndy Fiddaman 	const char *ptr = str;
553*b30d1939SAndy Fiddaman 	Arith_t *ep;
554*b30d1939SAndy Fiddaman 	ep = arith_compile(shp,str,(char**)&ptr,arith,ARITH_COMP|1);
555*b30d1939SAndy Fiddaman 	if(*ptr)
556*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*ptr,str);
557*b30d1939SAndy Fiddaman 	return((void*)ep);
558*b30d1939SAndy Fiddaman }
559