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 * Shell arithmetic - uses streval library
23da2e3ebdSchin * David Korn
24da2e3ebdSchin * AT&T Labs
25da2e3ebdSchin */
26da2e3ebdSchin
27da2e3ebdSchin #include "defs.h"
28da2e3ebdSchin #include "lexstates.h"
29da2e3ebdSchin #include "name.h"
30da2e3ebdSchin #include "streval.h"
31da2e3ebdSchin #include "variables.h"
32*b30d1939SAndy Fiddaman #include "builtins.h"
33da2e3ebdSchin
34da2e3ebdSchin #ifndef LLONG_MAX
35da2e3ebdSchin #define LLONG_MAX LONG_MAX
36da2e3ebdSchin #endif
37da2e3ebdSchin
38*b30d1939SAndy Fiddaman typedef Sfdouble_t (*Math_f)(Sfdouble_t, ...);
39*b30d1939SAndy Fiddaman
40*b30d1939SAndy Fiddaman extern const Namdisc_t ENUM_disc;
417c2fbfb3SApril Chin static Sfdouble_t NaN, Inf, Fun;
42da2e3ebdSchin static Namval_t Infnod =
43da2e3ebdSchin {
44da2e3ebdSchin { 0 },
45da2e3ebdSchin "Inf",
46da2e3ebdSchin };
47da2e3ebdSchin
48da2e3ebdSchin static Namval_t NaNnod =
49da2e3ebdSchin {
50da2e3ebdSchin { 0 },
51da2e3ebdSchin "NaN",
52da2e3ebdSchin };
53da2e3ebdSchin
547c2fbfb3SApril Chin static Namval_t FunNode =
557c2fbfb3SApril Chin {
567c2fbfb3SApril Chin { 0 },
577c2fbfb3SApril Chin "?",
587c2fbfb3SApril Chin };
597c2fbfb3SApril Chin
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)
61da2e3ebdSchin {
62da2e3ebdSchin register int flag = lvalue->flag;
637c2fbfb3SApril Chin register char *sub=0, *cp=(char*)np;
647c2fbfb3SApril Chin register Namval_t *mp;
65*b30d1939SAndy Fiddaman Shell_t *shp = lvalue->shp;
667c2fbfb3SApril Chin int flags = HASH_NOSCOPE|HASH_SCOPE|HASH_BUCKET;
67*b30d1939SAndy Fiddaman int c=0,nosub = lvalue->nosub;
687c2fbfb3SApril Chin 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);
7034f9b3eeSRoland Mainz Dt_t *root = shp->var_tree;
717c2fbfb3SApril Chin assign = assign?NV_ASSIGN:NV_NOASSIGN;
723e14f97fSRoger A. Faulkner 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;
767c2fbfb3SApril Chin if(cp>=lvalue->expr && cp < lvalue->expr+lvalue->elen)
77da2e3ebdSchin {
787c2fbfb3SApril Chin int offset;
797c2fbfb3SApril Chin /* do binding to node now */
807c2fbfb3SApril Chin int c = cp[flag];
817c2fbfb3SApril Chin cp[flag] = 0;
827c2fbfb3SApril Chin if((!(np = nv_open(cp,shp->var_tree,assign|NV_VARNAME|NV_NOADD|NV_NOFAIL)) || nv_isnull(np)) && sh_macfun(shp,cp, offset = staktell()))
83da2e3ebdSchin {
84*b30d1939SAndy Fiddaman Fun = sh_arith(shp,sub=stakptr(offset));
857c2fbfb3SApril Chin FunNode.nvalue.ldp = &Fun;
86*b30d1939SAndy Fiddaman nv_onattr(&FunNode,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
87da2e3ebdSchin cp[flag] = c;
887c2fbfb3SApril Chin return(&FunNode);
89da2e3ebdSchin }
9034f9b3eeSRoland Mainz if(!np && assign)
9134f9b3eeSRoland Mainz np = nv_open(cp,shp->var_tree,assign|NV_VARNAME);
92*b30d1939SAndy Fiddaman cp[flag] = c;
9334f9b3eeSRoland Mainz if(!np)
9434f9b3eeSRoland Mainz return(0);
9534f9b3eeSRoland Mainz root = shp->last_root;
967c2fbfb3SApril Chin if(cp[flag+1]=='[')
977c2fbfb3SApril Chin flag++;
987c2fbfb3SApril Chin else
997c2fbfb3SApril Chin flag = 0;
1007c2fbfb3SApril Chin cp = (char*)np;
1017c2fbfb3SApril Chin }
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))
1077c2fbfb3SApril Chin {
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)
117da2e3ebdSchin {
118*b30d1939SAndy Fiddaman Namarr_t *ap = nv_arrayptr(np);
119*b30d1939SAndy Fiddaman ap->nelem = dim;
120*b30d1939SAndy Fiddaman nv_putsub(np,(char*)0,n);
121da2e3ebdSchin }
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);
126da2e3ebdSchin }
127*b30d1939SAndy Fiddaman if(!nosub && flag)
128da2e3ebdSchin {
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 }
191da2e3ebdSchin }
192*b30d1939SAndy Fiddaman else if(nosub>0)
193*b30d1939SAndy Fiddaman nv_putsub(np,(char*)0,nosub-1);
194da2e3ebdSchin return(np);
195da2e3ebdSchin }
196da2e3ebdSchin
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)220da2e3ebdSchin static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdouble_t n)
221da2e3ebdSchin {
222*b30d1939SAndy Fiddaman Shell_t *shp = lvalue->shp;
223da2e3ebdSchin register Sfdouble_t r= 0;
224da2e3ebdSchin char *str = (char*)*ptr;
2257c2fbfb3SApril Chin register char *cp;
226da2e3ebdSchin switch(type)
227da2e3ebdSchin {
228da2e3ebdSchin case ASSIGN:
229da2e3ebdSchin {
230da2e3ebdSchin register Namval_t *np = (Namval_t*)(lvalue->value);
231*b30d1939SAndy Fiddaman np = scope(np,lvalue,1);
232da2e3ebdSchin 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;
236da2e3ebdSchin r=nv_getnum(np);
2373e14f97fSRoger A. Faulkner lvalue->value = (char*)np;
238da2e3ebdSchin break;
239da2e3ebdSchin }
240da2e3ebdSchin case LOOKUP:
241da2e3ebdSchin {
242da2e3ebdSchin register int c = *str;
243da2e3ebdSchin register char *xp=str;
244da2e3ebdSchin lvalue->value = (char*)0;
245da2e3ebdSchin if(c=='.')
246da2e3ebdSchin str++;
247da2e3ebdSchin c = mbchar(str);
248da2e3ebdSchin if(isaletter(c))
249da2e3ebdSchin {
250da2e3ebdSchin register Namval_t *np;
251da2e3ebdSchin int dot=0;
252da2e3ebdSchin while(1)
253da2e3ebdSchin {
254da2e3ebdSchin while(xp=str, c=mbchar(str), isaname(c));
255da2e3ebdSchin str = xp;
256*b30d1939SAndy Fiddaman while(c=='[' && dot==NV_NOADD)
2577c2fbfb3SApril Chin {
2587c2fbfb3SApril Chin str = nv_endsubscript((Namval_t*)0,str,0);
2597c2fbfb3SApril Chin c = *str;
2607c2fbfb3SApril Chin }
261da2e3ebdSchin if(c!='.')
262da2e3ebdSchin break;
2637c2fbfb3SApril Chin dot=NV_NOADD;
264da2e3ebdSchin if((c = *++str) !='[')
265da2e3ebdSchin continue;
266da2e3ebdSchin str = nv_endsubscript((Namval_t*)0,cp=str,NV_SUBQUOTE)-1;
267da2e3ebdSchin if(sh_checkid(cp+1,(char*)0))
268da2e3ebdSchin str -=2;
269da2e3ebdSchin }
270da2e3ebdSchin if(c=='(')
271da2e3ebdSchin {
272*b30d1939SAndy Fiddaman int off=stktell(shp->stk);
273da2e3ebdSchin int fsize = str- (char*)(*ptr);
274da2e3ebdSchin const struct mathtab *tp;
275*b30d1939SAndy Fiddaman Namval_t *np;
276da2e3ebdSchin c = **ptr;
277da2e3ebdSchin 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))
281da2e3ebdSchin {
282*b30d1939SAndy Fiddaman lvalue->nargs = -np->nvalue.rp->argc;
283*b30d1939SAndy Fiddaman lvalue->fun = (Math_f)np;
284da2e3ebdSchin break;
285da2e3ebdSchin }
286*b30d1939SAndy Fiddaman if(fsize<=(sizeof(tp->fname)-2))
287*b30d1939SAndy Fiddaman lvalue->fun = (Math_f)sh_mathstdfun(*ptr,fsize,&lvalue->nargs);
288da2e3ebdSchin if(lvalue->fun)
289da2e3ebdSchin 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);
294da2e3ebdSchin return(r);
295da2e3ebdSchin }
296da2e3ebdSchin if((lvalue->emode&ARITH_COMP) && dot)
297da2e3ebdSchin {
298da2e3ebdSchin lvalue->value = (char*)*ptr;
299da2e3ebdSchin lvalue->flag = str-lvalue->value;
300da2e3ebdSchin break;
301da2e3ebdSchin }
302da2e3ebdSchin *str = 0;
303da2e3ebdSchin if(sh_isoption(SH_NOEXEC))
304da2e3ebdSchin np = L_ARGNOD;
305da2e3ebdSchin else
306da2e3ebdSchin {
307da2e3ebdSchin int offset = staktell();
308da2e3ebdSchin char *saveptr = stakfreeze(0);
3097c2fbfb3SApril Chin Dt_t *root = (lvalue->emode&ARITH_COMP)?shp->var_base:shp->var_tree;
310da2e3ebdSchin *str = c;
311*b30d1939SAndy Fiddaman cp = str;
312da2e3ebdSchin while(c=='[' || c=='.')
313da2e3ebdSchin {
314da2e3ebdSchin if(c=='[')
315da2e3ebdSchin {
316*b30d1939SAndy Fiddaman str = nv_endsubscript(np,str,0);
317da2e3ebdSchin if((c= *str)!='[' && c!='.')
318da2e3ebdSchin {
319da2e3ebdSchin str = cp;
320da2e3ebdSchin c = '[';
321da2e3ebdSchin break;
322da2e3ebdSchin }
323da2e3ebdSchin }
324da2e3ebdSchin else
325da2e3ebdSchin {
3267c2fbfb3SApril Chin dot = NV_NOADD|NV_NOFAIL;
327da2e3ebdSchin str++;
328da2e3ebdSchin while(xp=str, c=mbchar(str), isaname(c));
329da2e3ebdSchin str = xp;
330da2e3ebdSchin }
331da2e3ebdSchin }
332da2e3ebdSchin *str = 0;
3337c2fbfb3SApril Chin cp = (char*)*ptr;
3347c2fbfb3SApril Chin if ((cp[0] == 'i' || cp[0] == 'I') && (cp[1] == 'n' || cp[1] == 'N') && (cp[2] == 'f' || cp[2] == 'F') && cp[3] == 0)
335da2e3ebdSchin {
3367c2fbfb3SApril Chin Inf = strtold("Inf", NiL);
337da2e3ebdSchin Infnod.nvalue.ldp = &Inf;
338da2e3ebdSchin np = &Infnod;
339*b30d1939SAndy Fiddaman nv_onattr(np,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
340da2e3ebdSchin }
3417c2fbfb3SApril Chin else if ((cp[0] == 'n' || cp[0] == 'N') && (cp[1] == 'a' || cp[1] == 'A') && (cp[2] == 'n' || cp[2] == 'N') && cp[3] == 0)
342da2e3ebdSchin {
3437c2fbfb3SApril Chin NaN = strtold("NaN", NiL);
344da2e3ebdSchin NaNnod.nvalue.ldp = &NaN;
345da2e3ebdSchin np = &NaNnod;
346*b30d1939SAndy Fiddaman nv_onattr(np,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
347da2e3ebdSchin }
348*b30d1939SAndy Fiddaman else if(!(np = nv_open(*ptr,root,NV_NOREF|NV_NOASSIGN|NV_VARNAME|dot)))
3497c2fbfb3SApril Chin {
3507c2fbfb3SApril Chin lvalue->value = (char*)*ptr;
3517c2fbfb3SApril Chin lvalue->flag = str-lvalue->value;
3527c2fbfb3SApril Chin }
353da2e3ebdSchin if(saveptr != stakptr(0))
354da2e3ebdSchin stakset(saveptr,offset);
355da2e3ebdSchin else
356da2e3ebdSchin stakseek(offset);
357da2e3ebdSchin }
358da2e3ebdSchin *str = c;
3597c2fbfb3SApril Chin if(!np && lvalue->value)
3607c2fbfb3SApril Chin break;
361da2e3ebdSchin lvalue->value = (char*)np;
36234f9b3eeSRoland Mainz /* bind subscript later */
36334f9b3eeSRoland Mainz if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
36434f9b3eeSRoland Mainz lvalue->isfloat=1;
36534f9b3eeSRoland Mainz lvalue->flag = 0;
366da2e3ebdSchin if(c=='[')
367da2e3ebdSchin {
36834f9b3eeSRoland Mainz lvalue->flag = (str-lvalue->expr);
369da2e3ebdSchin 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=='.');
38134f9b3eeSRoland Mainz break;
382da2e3ebdSchin }
383da2e3ebdSchin }
384da2e3ebdSchin else
385da2e3ebdSchin {
386da2e3ebdSchin char lastbase=0, *val = xp, oerrno = errno;
387*b30d1939SAndy Fiddaman lvalue->eflag = 0;
388da2e3ebdSchin 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 }
394da2e3ebdSchin r = strtonll(val,&str, &lastbase,-1);
395da2e3ebdSchin if(*str=='8' || *str=='9')
396da2e3ebdSchin {
397da2e3ebdSchin lastbase=10;
398da2e3ebdSchin errno = 0;
399da2e3ebdSchin r = strtonll(val,&str, &lastbase,-1);
400da2e3ebdSchin }
401da2e3ebdSchin if(lastbase<=1)
402da2e3ebdSchin lastbase=10;
403da2e3ebdSchin if(*val=='0')
404da2e3ebdSchin {
405da2e3ebdSchin while(*val=='0')
406da2e3ebdSchin val++;
407da2e3ebdSchin if(*val==0 || *val=='.' || *val=='x' || *val=='X')
408da2e3ebdSchin val--;
409da2e3ebdSchin }
410da2e3ebdSchin if(r==LLONG_MAX && errno)
411da2e3ebdSchin c='e';
412da2e3ebdSchin else
413da2e3ebdSchin c = *str;
4147c2fbfb3SApril Chin if(c==GETDECIMAL(0) || c=='e' || c == 'E' || lastbase ==
4157c2fbfb3SApril Chin 16 && (c == 'p' || c == 'P'))
416da2e3ebdSchin {
417da2e3ebdSchin lvalue->isfloat=1;
418da2e3ebdSchin r = strtold(val,&str);
419da2e3ebdSchin }
420da2e3ebdSchin else if(lastbase==10 && val[1])
421da2e3ebdSchin {
422da2e3ebdSchin if(val[2]=='#')
423da2e3ebdSchin val += 3;
424da2e3ebdSchin if((str-val)>2*sizeof(Sflong_t))
425da2e3ebdSchin {
426da2e3ebdSchin Sfdouble_t rr;
427da2e3ebdSchin rr = strtold(val,&str);
428da2e3ebdSchin if(rr!=r)
429da2e3ebdSchin {
430da2e3ebdSchin r = rr;
431da2e3ebdSchin lvalue->isfloat=1;
432da2e3ebdSchin }
433da2e3ebdSchin }
434da2e3ebdSchin }
435da2e3ebdSchin errno = oerrno;
436da2e3ebdSchin }
437da2e3ebdSchin break;
438da2e3ebdSchin }
439da2e3ebdSchin case VALUE:
440da2e3ebdSchin {
441da2e3ebdSchin register Namval_t *np = (Namval_t*)(lvalue->value);
442da2e3ebdSchin if(sh_isoption(SH_NOEXEC))
443da2e3ebdSchin return(0);
444*b30d1939SAndy Fiddaman np = scope(np,lvalue,0);
44534f9b3eeSRoland Mainz if(!np)
44634f9b3eeSRoland Mainz {
44734f9b3eeSRoland Mainz if(sh_isoption(SH_NOUNSET))
44834f9b3eeSRoland Mainz {
44934f9b3eeSRoland Mainz *ptr = lvalue->value;
45034f9b3eeSRoland Mainz goto skip;
45134f9b3eeSRoland Mainz }
45234f9b3eeSRoland Mainz return(0);
45334f9b3eeSRoland Mainz }
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;
469da2e3ebdSchin if(((lvalue->emode&2) || lvalue->level>1 || sh_isoption(SH_NOUNSET)) && nv_isnull(np) && !nv_isattr(np,NV_INTEGER))
470da2e3ebdSchin {
471da2e3ebdSchin *ptr = nv_name(np);
47234f9b3eeSRoland Mainz skip:
473da2e3ebdSchin lvalue->value = (char*)ERROR_dictionary(e_notset);
474da2e3ebdSchin lvalue->emode |= 010;
475da2e3ebdSchin return(0);
476da2e3ebdSchin }
477da2e3ebdSchin r = nv_getnum(np);
478da2e3ebdSchin if(nv_isattr(np,NV_INTEGER|NV_BINARY)==(NV_INTEGER|NV_BINARY))
479da2e3ebdSchin lvalue->isfloat= (r!=(Sflong_t)r);
4807c2fbfb3SApril Chin else if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
481da2e3ebdSchin lvalue->isfloat=1;
482*b30d1939SAndy Fiddaman if((lvalue->emode&ARITH_ASSIGNOP) && nv_isarray(np))
483*b30d1939SAndy Fiddaman lvalue->nosub = nv_aindex(np)+1;
484da2e3ebdSchin return(r);
485da2e3ebdSchin }
486da2e3ebdSchin
487da2e3ebdSchin case MESSAGE:
488da2e3ebdSchin sfsync(NIL(Sfio_t*));
489da2e3ebdSchin #if 0
490da2e3ebdSchin if(warn)
491da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),lvalue->value,*ptr);
492da2e3ebdSchin else
493da2e3ebdSchin #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);
498da2e3ebdSchin }
499da2e3ebdSchin *ptr = str;
500da2e3ebdSchin return(r);
501da2e3ebdSchin }
502da2e3ebdSchin
503da2e3ebdSchin /*
504da2e3ebdSchin * convert number defined by string to a Sfdouble_t
505da2e3ebdSchin * ptr is set to the last character processed
506da2e3ebdSchin * if mode>0, an error will be fatal with value <mode>
507da2e3ebdSchin */
508da2e3ebdSchin
sh_strnum(register const char * str,char ** ptr,int mode)509da2e3ebdSchin Sfdouble_t sh_strnum(register const char *str, char** ptr, int mode)
510da2e3ebdSchin {
511*b30d1939SAndy Fiddaman Shell_t *shp = sh_getinterp();
512da2e3ebdSchin register Sfdouble_t d;
513*b30d1939SAndy Fiddaman char base=(shp->inarith?0:10), *last;
514da2e3ebdSchin if(*str==0)
515da2e3ebdSchin {
516da2e3ebdSchin if(ptr)
517da2e3ebdSchin *ptr = (char*)str;
518da2e3ebdSchin return(0);
519da2e3ebdSchin }
520da2e3ebdSchin errno = 0;
521da2e3ebdSchin d = strtonll(str,&last,&base,-1);
522da2e3ebdSchin if(*last || errno)
523da2e3ebdSchin {
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 }
537da2e3ebdSchin }
5387c2fbfb3SApril Chin else if (!d && *str=='-')
5397c2fbfb3SApril Chin d = -0.0;
540da2e3ebdSchin if(ptr)
541da2e3ebdSchin *ptr = last;
542da2e3ebdSchin return(d);
543da2e3ebdSchin }
544da2e3ebdSchin
sh_arith(Shell_t * shp,register const char * str)545*b30d1939SAndy Fiddaman Sfdouble_t sh_arith(Shell_t *shp,register const char *str)
546da2e3ebdSchin {
547da2e3ebdSchin return(sh_strnum(str, (char**)0, 1));
548da2e3ebdSchin }
549da2e3ebdSchin
sh_arithcomp(Shell_t * shp,register char * str)550*b30d1939SAndy Fiddaman void *sh_arithcomp(Shell_t *shp,register char *str)
551da2e3ebdSchin {
552da2e3ebdSchin const char *ptr = str;
553da2e3ebdSchin Arith_t *ep;
554*b30d1939SAndy Fiddaman ep = arith_compile(shp,str,(char**)&ptr,arith,ARITH_COMP|1);
555da2e3ebdSchin if(*ptr)
556da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*ptr,str);
557da2e3ebdSchin return((void*)ep);
558da2e3ebdSchin }
559