1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2013 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * David Korn <dgkorn@gmail.com> *
18 * *
19 ***********************************************************************/
20 /*
21 * Shell arithmetic - uses streval library
22 * David Korn
23 * AT&T Labs
24 */
25
26 #include "defs.h"
27 #include "lexstates.h"
28 #include "name.h"
29 #include "streval.h"
30 #include "variables.h"
31 #include "builtins.h"
32
33 #undef SHOPT_FIXEDARRAY
34 #ifndef LLONG_MAX
35 #define LLONG_MAX LONG_MAX
36 #endif
37
38 typedef Sfdouble_t (*Math_f)(Sfdouble_t, ...);
39
40 extern const Namdisc_t ENUM_disc;
41 static bool Varsubscript;
42 static Sfdouble_t NaN, Inf, Fun;
43 static Namval_t Infnod =
44 {
45 { 0 },
46 "Inf",
47 };
48
49 static Namval_t NaNnod =
50 {
51 { 0 },
52 "NaN",
53 };
54
55 static Namval_t FunNode =
56 {
57 { 0 },
58 "?",
59 };
60
61 struct Mathconst
62 {
63 char name[9];
64 Sfdouble_t value;
65 };
66
67 #ifndef M_1_PIl
68 # define M_1_PIl 0.3183098861837906715377675267450287L
69 #endif
70 #ifndef M_2_PIl
71 # define M_2_PIl 0.6366197723675813430755350534900574L
72 #endif
73 #ifndef M_2_SQRTPIl
74 # define M_2_SQRTPIl 1.1283791670955125738961589031215452L
75 #endif
76 #ifndef M_El
77 # define M_El 2.7182818284590452353602874713526625L
78 #endif
79 #ifndef M_LOG2El
80 # define M_LOG2El 1.4426950408889634073599246810018921L
81 #endif
82 #ifndef M_LOG10El
83 # define M_LOG10El 0.4342944819032518276511289189166051L
84 #endif
85 #ifndef M_LN2l
86 # define M_LN2l 0.6931471805599453094172321214581766L
87 #endif
88 #ifndef M_LN10l
89 # define M_LN10l 2.3025850929940456840179914546843642L
90 #endif
91 #ifndef M_PIl
92 # define M_PIl 3.1415926535897932384626433832795029L
93 #endif
94 #ifndef M_PI_2l
95 # define M_PI_2l 1.5707963267948966192313216916397514L
96 #endif
97 #ifndef M_PI_4l
98 # define M_PI_4l 0.7853981633974483096156608458198757L
99 #endif
100 #ifndef M_SQRT2l
101 # define M_SQRT2l 1.4142135623730950488016887242096981L
102 #endif
103 #ifndef M_SQRT1_2l
104 # define M_SQRT1_2l 0.7071067811865475244008443621048490L
105 #endif
106
107 /* The firs three entries cann't be moved or it will break the code */
108 static const struct Mathconst Mtable[]=
109 {
110 "1_PI", M_1_PIl,
111 "2_PI", M_2_PIl,
112 "2_SQRTPI", M_2_SQRTPIl,
113 "E", M_El,
114 "LOG2E", M_LOG2El,
115 "LOG10E", M_LOG10El,
116 "LN2", M_LN2l,
117 "PI", M_PIl,
118 "PI_2", M_PI_2l,
119 "PI_4", M_PI_4l,
120 "SQRT2", M_SQRT2l,
121 "SQRT1_2", M_SQRT1_2l,
122 0, 0
123 };
124
125 typedef struct Intconst_s
126 {
127 const char name[4];
128 short ss;
129 unsigned short us;
130 int si;
131 unsigned int ui;
132 Sflong_t sl;
133 Sfulong_t ul;
134 } Intconst_t;
135
136 typedef struct Fltconst_s
137 {
138 const char name[12];
139 float f;
140 double d;
141 Sfdouble_t l;
142 } Fltconst_t;
143
144 static const Intconst_t intconst[] =
145 {
146 {
147 "DIG",
148 USHRT_DIG, USHRT_DIG,
149 UINT_DIG, UINT_DIG,
150 #ifdef LLONG_DIG
151 ULLONG_DIG, ULLONG_DIG,
152 #else
153 ULONG_DIG, ULONG_DIG,
154 #endif
155 },
156 {
157 "MAX",
158 SHRT_MAX, USHRT_MAX,
159 INT_MAX, UINT_MAX,
160 #ifdef LLONG_MAX
161 LLONG_MAX, ULLONG_MAX,
162 #else
163 LONG_MAX, ULONG_MAX,
164 #endif
165 },
166 {
167 "MIN",
168 SHRT_MIN, 0,
169 INT_MIN, 0,
170 #ifdef LLONG_MIN
171 LLONG_MIN, 0,
172 #else
173 LONG_MIN, 0,
174 #endif
175 },
176 };
177
178 static const Fltconst_t fltconst[] =
179 {
180 {
181 "DIG",
182 FLT_DIG,
183 DBL_DIG,
184 #ifdef LDBL_DIG
185 LDBL_DIG,
186 #else
187 DBL_DIG,
188 #endif
189 },
190 {
191 "EPSILON",
192 FLT_EPSILON,
193 DBL_EPSILON,
194 #ifdef LDBL_EPSILON
195 LDBL_EPSILON,
196 #else
197 DBL_EPSILON,
198 #endif
199 },
200 {
201 "INT_MAX",
202 FLT_INTMAX_MAX,
203 DBL_INTMAX_MAX,
204 #ifdef LDBL_INTMAX_MAX
205 LDBL_INTMAX_MAX,
206 #else
207 DBL_INTMAX_MAX,
208 #endif
209 },
210 {
211 "INT_MIN",
212 FLT_INTMAX_MIN,
213 DBL_INTMAX_MIN,
214 #ifdef LDBL_INTMAX_MIN
215 LDBL_INTMAX_MIN,
216 #else
217 DBL_INTMAX_MIN,
218 #endif
219 },
220 {
221 "MAX",
222 FLT_MAX,
223 DBL_MAX,
224 #ifdef LDBL_MAX
225 LDBL_MAX,
226 #else
227 DBL_MAX,
228 #endif
229 },
230 {
231 "MAX_10_EXP",
232 FLT_MAX_10_EXP,
233 DBL_MAX_10_EXP,
234 #ifdef LDBL_MAX_10_EXP
235 LDBL_MAX_10_EXP,
236 #else
237 DBL_MAX_10_EXP,
238 #endif
239 },
240 {
241 "MAX_EXP",
242 FLT_MAX_EXP,
243 DBL_MAX_EXP,
244 #ifdef LDBL_MAX_EXP
245 LDBL_MAX_EXP,
246 #else
247 DBL_MAX_EXP,
248 #endif
249 },
250 {
251 "MIN",
252 FLT_MIN,
253 DBL_MIN,
254 #ifdef LDBL_MIN
255 LDBL_MIN,
256 #else
257 DBL_MIN,
258 #endif
259 },
260 {
261 "MIN_10_EXP",
262 FLT_MIN_10_EXP,
263 DBL_MIN_10_EXP,
264 #ifdef LDBL_MIN_10_EXP
265 LDBL_MIN_10_EXP,
266 #else
267 DBL_MIN_10_EXP,
268 #endif
269 },
270 {
271 "MIN_EXP",
272 FLT_MIN_EXP,
273 DBL_MIN_EXP,
274 #ifdef LDBL_MIN_EXP
275 LDBL_MIN_EXP,
276 #else
277 DBL_MIN_EXP,
278 #endif
279 },
280 {
281 "UINT_MAX",
282 FLT_UINTMAX_MAX,
283 DBL_UINTMAX_MAX,
284 #ifdef LDBL_UINTMAX_MAX
285 LDBL_UINTMAX_MAX,
286 #else
287 DBL_UINTMAX_MAX,
288 #endif
289 },
290 {
291 "UINT_MIN",
292 0,
293 0,
294 0,
295 },
296 };
297
check_limits(Shell_t * shp,char * cp)298 static Namval_t *check_limits(Shell_t *shp, char *cp)
299 {
300 static Namval_t node;
301 static Sfdouble_t dd;
302 Namval_t *np;
303 char *ep;
304 int n;
305 if(!(ep=strrchr(cp,'.')))
306 return(0);
307 *ep = 0;
308 np = nv_open(cp, shp->var_tree, NV_VARNAME|NV_NOADD|NV_NOFAIL);
309 *ep++ = '.';
310 if(!np || !nv_isattr(np,NV_INTEGER))
311 return(0);
312 if(nv_isattr (np,NV_DOUBLE)==NV_DOUBLE)
313 {
314 const Fltconst_t *fp = fltconst;
315 n = sizeof(fltconst)/sizeof(Fltconst_t);
316 for(; n-->0; fp++)
317 {
318 if(strcmp(fp->name,ep)==0)
319 break;
320 }
321 if(n>=0)
322 {
323 node = *np;
324 node.nvalue.ldp = ⅆ
325 if(nv_isattr(np,NV_SHORT))
326 *node.nvalue.fp = fp->f;
327 else if(nv_isattr(np,NV_LONG))
328 *node.nvalue.ldp = fp->l;
329 else
330 *node.nvalue.dp = fp->d;
331 return(&node);
332 }
333 }
334 else
335 {
336 const Intconst_t *ip = intconst;
337 n = sizeof(intconst)/sizeof(Intconst_t);
338 for(; n-->=0; ip++)
339 {
340 if(strcmp(ip->name,ep)==0)
341 break;
342 }
343 if(n>=0)
344 {
345 int unsign = nv_isattr(np,NV_LTOU);
346 node = *np;
347 node.nvalue.ldp = ⅆ
348 if(nv_isattr(np,NV_SHORT))
349 {
350 if(unsign)
351 node.nvalue.u = ip->us;
352 else
353 node.nvalue.s = ip->ss;
354 }
355 else if(nv_isattr(np,NV_LONG))
356 {
357 if(unsign)
358 *node.nvalue.llp = ip->ul;
359 else
360 *node.nvalue.llp = ip->sl;
361 }
362 else
363 {
364 if(unsign)
365 *node.nvalue.ip = ip->ui;
366 else
367 *node.nvalue.ip = ip->ul;
368 }
369 return(&node);
370 }
371 }
372 return(0);
373 }
374
scope(register Namval_t * np,register struct lval * lvalue,int assign)375 static Namval_t *scope(register Namval_t *np,register struct lval *lvalue,int assign)
376 {
377 register int flag = lvalue->flag;
378 register char *sub=0, *cp=(char*)np;
379 register Namval_t *mp;
380 Shell_t *shp = lvalue->shp;
381 int flags = HASH_NOSCOPE|HASH_SCOPE|HASH_BUCKET;
382 int c=0,nosub = lvalue->nosub;
383 Dt_t *sdict = (shp->st.real_fun? shp->st.real_fun->sdict:0);
384 Dt_t *nsdict = (shp->namespace?nv_dict(shp->namespace):0);
385 Dt_t *root = shp->var_tree;
386 assign = assign?NV_ASSIGN:NV_NOASSIGN;
387 lvalue->nosub = 0;
388 if(nosub<0 && lvalue->ovalue)
389 return((Namval_t*)lvalue->ovalue);
390 lvalue->ovalue = 0;
391 if(cp>=lvalue->expr && cp < lvalue->expr+lvalue->elen)
392 {
393 int offset;
394 /* do binding to node now */
395 int d = cp[flag];
396 cp[flag] = 0;
397 if((!(np = nv_open(cp,root,assign|NV_VARNAME|NV_NOADD|NV_NOFAIL)) || nv_isnull(np)) && sh_macfun(shp,cp, offset = stktell(shp->stk)))
398 {
399 Fun = sh_arith(shp,sub=stkptr(shp->stk,offset));
400 FunNode.nvalue.ldp = &Fun;
401 FunNode.nvshell = shp;
402 nv_onattr(&FunNode,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
403 cp[flag] = d;
404 return(&FunNode);
405 }
406 if(!np)
407 {
408 if(assign)
409 np = nv_open(cp,root,assign|NV_VARNAME);
410 else
411 np = check_limits(shp,cp);
412 }
413 cp[flag] = d;
414 if(!np)
415 return(0);
416 root = shp->last_root;
417 if(cp[flag+1]=='[')
418 flag++;
419 else
420 flag = 0;
421 cp = (char*)np;
422 }
423 else if(assign==NV_ASSIGN && nv_isnull(np) && !nv_isattr(np, ~(NV_MINIMAL|NV_NOFREE)))
424 flags |= NV_ADD;
425 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)))) ))
426 np = mp;
427 while(nv_isref(np))
428 {
429 #if SHOPT_FIXEDARRAY
430 int n,dim;
431 dim = nv_refdimen(np);
432 n = nv_refindex(np);
433 #endif /* SHOPT_FIXEDARRAY */
434 sub = nv_refsub(np);
435 np = nv_refnode(np);
436 #if SHOPT_FIXEDARRAY
437 if(n)
438 {
439 Namarr_t *ap = nv_arrayptr(np);
440 ap->nelem = dim;
441 nv_putsub(np,(char*),n,0);
442 }
443 else
444 #endif /* SHOPT_FIXEDARRAY */
445 if(sub)
446 nv_putsub(np,sub,0,assign==NV_ASSIGN?ARRAY_ADD:0);
447 }
448 if(!nosub && flag)
449 {
450 int hasdot = 0;
451 cp = (char*)&lvalue->expr[flag];
452 if(sub)
453 {
454 goto skip;
455 }
456 sub = cp;
457 while(1)
458 {
459 Namarr_t *ap;
460 Namval_t *nq;
461 cp = nv_endsubscript(np,cp,0,(void*)shp);
462 if(c || *cp=='.')
463 {
464 c = '.';
465 while(*cp=='.')
466 {
467 hasdot=1;
468 cp++;
469 while(c=mbchar(cp),isaname(c));
470 }
471 if(c=='[')
472 continue;
473 }
474 flag = *cp;
475 *cp = 0;
476 if(c || hasdot)
477 {
478 sfprintf(shp->strbuf,"%s%s%c",nv_name(np),sub,0);
479 sub = sfstruse(shp->strbuf);
480 }
481 if(strchr(sub,'$'))
482 sub = sh_mactrim(shp,sub,0);
483 *cp = flag;
484 if(c || hasdot)
485 {
486 np = nv_open(sub,shp->var_tree,NV_VARNAME|assign);
487 return(np);
488 }
489 #if SHOPT_FIXEDARRAY
490 ap = nv_arrayptr(np);
491 cp = nv_endsubscript(np,sub,(assign==NV_ASSIGN?NV_ADD:0)|NV_SUBQUOTE|(ap&&ap->fixed?NV_FARRAY:0),np->nvshell);
492 #else
493 cp = nv_endsubscript(np,sub,(assign==NV_ASSIGN?NV_ADD:0)|NV_SUBQUOTE,np->nvshell);
494 #endif /* SHOPT_FIXEDARRAY */
495 if(*cp!='[')
496 break;
497 skip:
498 if(nq = nv_opensub(np))
499 np = nq;
500 else
501 {
502 ap = nv_arrayptr(np);
503 if(ap && !ap->table)
504 {
505 ap->table = dtopen(&_Nvdisc,Dtoset);
506 dtuserdata(ap->table,shp,1);
507 }
508 if(ap && ap->table && (nq=nv_search(nv_getsub(np),ap->table,NV_ADD)))
509 nq->nvenv = (char*)np;
510 if(nq && nv_isnull(nq))
511 np = nv_arraychild(np,nq,0);
512 }
513 sub = cp;
514 }
515 }
516 else if(nosub>0)
517 nv_putsub(np,(char*)0,nosub-1,0);
518 return(np);
519 }
520
sh_mathstdfun(const char * fname,size_t fsize,short * nargs)521 Math_f sh_mathstdfun(const char *fname, size_t fsize, short * nargs)
522 {
523 register const struct mathtab *tp;
524 register char c = fname[0];
525 for(tp=shtab_math; *tp->fname; tp++)
526 {
527 if(*tp->fname > c)
528 break;
529 if(tp->fname[1]==c && tp->fname[fsize+1]==0 && strncmp(&tp->fname[1],fname,fsize)==0)
530 {
531 if(nargs)
532 *nargs = *tp->fname;
533 return(tp->fnptr);
534 }
535 }
536 return(0);
537 }
538
sh_mathstd(const char * name)539 int sh_mathstd(const char *name)
540 {
541 return(sh_mathstdfun(name,strlen(name),NULL)!=0);
542 }
543
number(const char * s,char ** p,int b,struct lval * lvalue)544 static Sfdouble_t number(const char* s, char** p, int b, struct lval* lvalue)
545 {
546 Sfdouble_t r;
547 char* t;
548 int oerrno;
549 int c;
550 char base;
551 struct lval v;
552
553 oerrno = errno;
554 errno = 0;
555 base = b;
556 if (!lvalue)
557 lvalue = &v;
558 else if (lvalue->shp->bltindata.bnode==SYSLET && !sh_isoption(lvalue->shp, SH_LETOCTAL))
559 while (*s=='0' && isdigit(s[1]))
560 s++;
561 lvalue->eflag = 0;
562 lvalue->isfloat = 0;
563 r = strtonll(s, &t, &base, -1);
564 if (*t=='8' || *t=='9')
565 {
566 base = 10;
567 errno = 0;
568 r = strtonll(s, &t, &base, -1);
569 }
570 if (base <= 1)
571 base = 10;
572 if (*t=='_')
573 {
574 if ((r==1||r==2) && strcmp(t,"_PI")==0)
575 {
576 t += 3;
577 r = Mtable[(int)r-1].value;
578 }
579 else if (r==2 && strcmp(t,"_SQRTPI")==0)
580 {
581 t += 7;
582 r = Mtable[2].value;
583 }
584 }
585 c = r==LLONG_MAX && errno ? 'e' : *t;
586 if (c==GETDECIMAL(0) || c=='e' || c == 'E' || base == 16 && (c == 'p' || c == 'P'))
587 {
588 r = strtold(s, &t);
589 lvalue->isfloat = TYPE_LD;
590 }
591 if (t > s)
592 {
593 if (*t=='f' || *t=='F')
594 {
595 t++;
596 lvalue->isfloat = TYPE_F;
597 r = (float)r;
598 }
599 else if (*t=='l' || *t=='L')
600 {
601 t++;
602 lvalue->isfloat= TYPE_LD;
603 }
604 else if (*t=='d' || *t=='D')
605 {
606 t++;
607 lvalue->isfloat= TYPE_LD;
608 r = (double)r;
609 }
610 }
611 errno = oerrno;
612 *p = t;
613 return r;
614 }
615
arith(const char ** ptr,struct lval * lvalue,int type,Sfdouble_t n)616 static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdouble_t n)
617 {
618 Shell_t *shp = lvalue->shp;
619 register Sfdouble_t r= 0;
620 char *str = (char*)*ptr;
621 register char *cp;
622 switch(type)
623 {
624 case ASSIGN:
625 {
626 register Namval_t *np = (Namval_t*)(lvalue->value);
627 np = scope(np,lvalue,1);
628 nv_putval(np, (char*)&n, NV_LDOUBLE);
629 if(lvalue->eflag)
630 lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
631 lvalue->eflag = 0;
632 r=nv_getnum(np);
633 lvalue->value = (char*)np;
634 break;
635 }
636 case LOOKUP:
637 {
638 register int c = *str;
639 register char *xp=str;
640 lvalue->value = (char*)0;
641 if(c=='.')
642 str++;
643 c = mbchar(str);
644 if(isaletter(c))
645 {
646 register Namval_t *np=0;
647 int dot=0;
648 while(1)
649 {
650 while(xp=str, c=mbchar(str), isaname(c));
651 str = xp;
652 while(c=='[' && dot==NV_NOADD)
653 {
654 str = nv_endsubscript((Namval_t*)0,str,0,shp);
655 c = *str;
656 }
657 if(c!='.')
658 break;
659 dot=NV_NOADD;
660 if((c = *++str) !='[')
661 continue;
662 str = nv_endsubscript((Namval_t*)0,cp=str,NV_SUBQUOTE,shp)-1;
663 if(sh_checkid(cp+1,(char*)0))
664 str -=2;
665 }
666 if(c=='(')
667 {
668 int off=stktell(shp->stk);
669 int fsize = str- (char*)(*ptr);
670 const struct mathtab *tp;
671 Namval_t *nq;
672 c = **ptr;
673 lvalue->fun = 0;
674 sfprintf(shp->stk,".sh.math.%.*s%c",fsize,*ptr,0);
675 stkseek(shp->stk,off);
676 if(nq=nv_search(stkptr(shp->stk,off),shp->fun_tree,0))
677 {
678 lvalue->nargs = -nq->nvalue.rp->argc;
679 lvalue->fun = (Math_f)nq;
680 break;
681 }
682 if(fsize<=(sizeof(tp->fname)-2))
683 lvalue->fun = (Math_f)sh_mathstdfun(*ptr,fsize,&lvalue->nargs);
684 if(lvalue->fun)
685 break;
686 if(lvalue->emode&ARITH_COMP)
687 lvalue->value = (char*)e_function;
688 else
689 lvalue->value = (char*)ERROR_dictionary(e_function);
690 return(r);
691 }
692 if((lvalue->emode&ARITH_COMP) && dot)
693 {
694 lvalue->value = (char*)*ptr;
695 lvalue->flag = str-lvalue->value;
696 break;
697 }
698 *str = 0;
699 if(sh_isoption(shp,SH_NOEXEC))
700 np = L_ARGNOD;
701 else
702 {
703 int offset = stktell(shp->stk);
704 char *saveptr = stkfreeze(shp->stk,0);
705 Dt_t *root = (lvalue->emode&ARITH_COMP)?shp->var_base:shp->var_tree;
706 *str = c;
707 cp = str;
708 while(c=='[' || c=='.')
709 {
710 if(c=='[')
711 {
712 str = nv_endsubscript(np,str,0,(void*)shp);
713 if((c= *str)!='[' && c!='.')
714 {
715 str = cp;
716 c = '[';
717 break;
718 }
719 }
720 else
721 {
722 dot = NV_NOADD|NV_NOFAIL;
723 str++;
724 while(xp=str, c=mbchar(str), isaname(c));
725 str = xp;
726 }
727 }
728 *str = 0;
729 cp = (char*)*ptr;
730 Varsubscript = false;
731 if ((cp[0] == 'i' || cp[0] == 'I') && (cp[1] == 'n' || cp[1] == 'N') && (cp[2] == 'f' || cp[2] == 'F') && cp[3] == 0)
732 {
733 Inf = strtold("Inf", NiL);
734 Infnod.nvalue.ldp = &Inf;
735 np = &Infnod;
736 np->nvshell = shp;
737 nv_onattr(np,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
738 }
739 else if ((cp[0] == 'n' || cp[0] == 'N') && (cp[1] == 'a' || cp[1] == 'A') && (cp[2] == 'n' || cp[2] == 'N') && cp[3] == 0)
740 {
741 NaN = strtold("NaN", NiL);
742 NaNnod.nvalue.ldp = &NaN;
743 np = &NaNnod;
744 np->nvshell = shp;
745 nv_onattr(np,NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
746 }
747 else
748 {
749 const struct Mathconst *mp=0;
750 np = 0;
751 #if 1
752 if(strchr("ELPS12",**ptr))
753 {
754 for(mp=Mtable; *mp->name; mp++)
755 {
756 if(strcmp(mp->name,*ptr)==0)
757 break;
758 }
759 }
760 if(mp && *mp->name)
761 {
762 r = mp->value;
763 lvalue->isfloat = TYPE_LD;
764 goto skip2;
765 }
766 #endif
767 if(shp->namref_root && !(lvalue->emode&ARITH_COMP))
768 np = nv_open(*ptr,shp->namref_root,NV_NOREF|NV_NOASSIGN|NV_VARNAME|NV_NOSCOPE|NV_NOADD|dot);
769 if(!np)
770 np = nv_open(*ptr,root,NV_NOREF|NV_NOASSIGN|NV_VARNAME|dot);
771 if(!np || Varsubscript)
772 {
773 np = 0;
774 lvalue->value = (char*)*ptr;
775 lvalue->flag = str-lvalue->value;
776 }
777 }
778 skip2:
779 if(saveptr != stkptr(shp->stk,0))
780 stkset(shp->stk,saveptr,offset);
781 else
782 stkseek(shp->stk,offset);
783 }
784 *str = c;
785 #if 1
786 if(lvalue->isfloat==TYPE_LD)
787 break;
788 #endif
789 if(!np && lvalue->value)
790 break;
791 lvalue->value = (char*)np;
792 /* bind subscript later */
793 if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
794 lvalue->isfloat=1;
795 lvalue->flag = 0;
796 if(c=='[')
797 {
798 lvalue->flag = (str-lvalue->expr);
799 do
800 {
801 while(c=='.')
802 {
803 str++;
804 while(xp=str, c=mbchar(str), isaname(c));
805 c = *(str = xp);
806 }
807 if(c=='[')
808 str = nv_endsubscript(np,str,0,np->nvshell);
809 }
810 while((c= *str)=='[' || c=='.');
811 break;
812 }
813 }
814 else
815 r = number(xp, &str, 0, lvalue);
816 break;
817 }
818 case VALUE:
819 {
820 register Namval_t *np = (Namval_t*)(lvalue->value);
821 Namarr_t *ap;
822 if(sh_isoption(shp,SH_NOEXEC))
823 return(0);
824 np = scope(np,lvalue,0);
825 if(!np)
826 {
827 if(sh_isoption(shp,SH_NOUNSET))
828 {
829 *ptr = lvalue->value;
830 goto skip;
831 }
832 return(0);
833 }
834 lvalue->ovalue = (char*)np;
835 if(lvalue->eflag)
836 lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
837 else if((Namfun_t*)lvalue->ptr && !nv_hasdisc(np,&ENUM_disc) && !nv_isattr(np,NV_INTEGER))
838 {
839 Namval_t *mp,node;
840 mp = ((Namfun_t*)lvalue->ptr)->type;
841 memset(&node,0,sizeof(node));
842 nv_clone(mp,&node,0);
843 nv_offattr(&node,NV_RDONLY|NV_NOFREE);
844 nv_putval(&node,np->nvname,0);
845 if(nv_isattr(&node,NV_NOFREE))
846 return(r=nv_getnum(&node));
847 }
848 lvalue->eflag = 0;
849 if(((lvalue->emode&2) || lvalue->level>1 || (lvalue->nextop!=A_STORE && sh_isoption(shp,SH_NOUNSET))) && nv_isnull(np) && !nv_isattr(np,NV_INTEGER))
850 {
851 *ptr = nv_name(np);
852 skip:
853 lvalue->value = (char*)ERROR_dictionary(e_notset);
854 lvalue->emode |= 010;
855 return(0);
856 }
857 if(lvalue->userfn && (ap=nv_arrayptr(np)) && (ap->flags&ARRAY_UNDEF))
858 {
859 r = (Sfdouble_t)integralof(np);
860 lvalue->isfloat=5;
861 return(r);
862 }
863 r = nv_getnum(np);
864 if(nv_isattr(np,NV_INTEGER|NV_BINARY)==(NV_INTEGER|NV_BINARY))
865 lvalue->isfloat= (r!=(Sflong_t)r)?TYPE_LD:0;
866 else if(nv_isattr(np,(NV_DOUBLE|NV_SHORT))==(NV_DOUBLE|NV_SHORT))
867 {
868 lvalue->isfloat = TYPE_F;
869 r = (float)r;
870 }
871 else if(nv_isattr(np,(NV_DOUBLE|NV_LONG))==(NV_DOUBLE|NV_LONG))
872 lvalue->isfloat = TYPE_LD;
873 else if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
874 {
875 lvalue->isfloat = TYPE_D;
876 r = (double)r;
877 }
878 if((lvalue->emode&ARITH_ASSIGNOP) && nv_isarray(np))
879 lvalue->nosub = nv_aindex(np)+1;
880 return(r);
881 }
882
883 case MESSAGE:
884 sfsync(NIL(Sfio_t*));
885 #if 0
886 if(warn)
887 errormsg(SH_DICT,ERROR_warn(0),lvalue->value,*ptr);
888 else
889 #endif
890 if(lvalue->emode&ARITH_COMP)
891 return(-1);
892
893 errormsg(SH_DICT,ERROR_exit((lvalue->emode&3)!=0),lvalue->value,*ptr);
894 }
895 *ptr = str;
896 return(r);
897 }
898
sh_arith(Shell_t * shp,register const char * str)899 Sfdouble_t sh_arith(Shell_t *shp,register const char *str)
900 {
901 return(sh_strnum(shp, str, (char**)0, 1));
902 }
903
sh_arithcomp(Shell_t * shp,register char * str)904 void *sh_arithcomp(Shell_t *shp,register char *str)
905 {
906 const char *ptr = str;
907 Arith_t *ep;
908 ep = arith_compile(shp,str,(char**)&ptr,arith,ARITH_COMP|1);
909 if(*ptr)
910 errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*ptr,str);
911 return((void*)ep);
912 }
913
914 /*
915 * convert number defined by string to a Sfdouble_t
916 * ptr is set to the last character processed
917 * if mode>0, an error will be fatal with value <mode>
918 */
sh_strnum_20120720(Shell_t * shp,register const char * str,char ** ptr,int mode)919 Sfdouble_t sh_strnum_20120720(Shell_t *shp,register const char *str, char** ptr, int mode)
920 {
921 register Sfdouble_t d;
922 char *last;
923 if(*str==0)
924 {
925 if(ptr)
926 *ptr = (char*)str;
927 return(0);
928 }
929 errno = 0;
930 d = number(str,&last,shp->inarith?0:10,NiL);
931 if(*last)
932 {
933 if(*last!='.' || last[1]!='.')
934 {
935 d = strval(shp,str,&last,arith,mode);
936 Varsubscript = true;
937 }
938 if(!ptr && *last && mode>0)
939 errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str);
940 }
941 else if (!d && *str=='-')
942 d = -0.0;
943 if(ptr)
944 *ptr = last;
945 return(d);
946 }
947
948 #undef sh_strnum
sh_strnum(register const char * str,char ** ptr,int mode)949 Sfdouble_t sh_strnum(register const char *str, char** ptr, int mode)
950 {
951 return(sh_strnum_20120720(sh_getinterp(),str,ptr,mode));
952 }
953
954