Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/sh/streval.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1982-2012 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 <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* D. G. Korn
24
* AT&T Labs
25
*
26
* arithmetic expression evaluator
27
*
28
* this version compiles the expression onto a stack
29
* and has a separate executor
30
*/
31
32
#include "streval.h"
33
#include <ctype.h>
34
#include <error.h>
35
#include <stak.h>
36
#include "FEATURE/externs"
37
#include "defs.h" /* for sh.decomma */
38
39
#ifndef ERROR_dictionary
40
# define ERROR_dictionary(s) (s)
41
#endif
42
#ifndef SH_DICT
43
# define SH_DICT "libshell"
44
#endif
45
46
#define MAXLEVEL 9
47
#define SMALL_STACK 12
48
49
/*
50
* The following are used with tokenbits() macro
51
*/
52
#define T_OP 0x3f /* mask for operator number */
53
#define T_BINARY 0x40 /* binary operators */
54
#define T_NOFLOAT 0x80 /* non floating point operator */
55
#define A_LVALUE (2*MAXPREC+2)
56
57
#define pow2size(x) ((x)<=2?2:(x)<=4?4:(x)<=8?8:(x)<=16?16:(x)<=32?32:64)
58
#define round(x,size) (((x)+(size)-1)&~((size)-1))
59
#define stakpush(v,val,type) ((((v)->offset=round(staktell(),pow2size(sizeof(type)))),\
60
stakseek((v)->offset+sizeof(type)), \
61
*((type*)stakptr((v)->offset)) = (val)),(v)->offset)
62
#define roundptr(ep,cp,type) (((unsigned char*)(ep))+round(cp-((unsigned char*)(ep)),pow2size(sizeof(type))))
63
64
static int level;
65
66
struct vars /* vars stacked per invocation */
67
{
68
Shell_t *shp;
69
const char *expr; /* current expression */
70
const char *nextchr; /* next char in current expression */
71
const char *errchr; /* next char after error */
72
const char *errstr; /* error string */
73
struct lval errmsg; /* error message text */
74
int offset; /* offset for pushchr macro */
75
int staksize; /* current stack size needed */
76
int stakmaxsize; /* maximum stack size needed */
77
unsigned char paren; /* parenthesis level */
78
char infun; /* incremented by comma inside function */
79
int emode;
80
Sfdouble_t (*convert)(const char**,struct lval*,int,Sfdouble_t);
81
};
82
83
typedef Sfdouble_t (*Math_f)(Sfdouble_t,...);
84
typedef Sfdouble_t (*Math_1f_f)(Sfdouble_t);
85
typedef int (*Math_1i_f)(Sfdouble_t);
86
typedef Sfdouble_t (*Math_2f_f)(Sfdouble_t,Sfdouble_t);
87
typedef Sfdouble_t (*Math_2f_i)(Sfdouble_t,int);
88
typedef int (*Math_2i_f)(Sfdouble_t,Sfdouble_t);
89
typedef Sfdouble_t (*Math_3f_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
90
typedef int (*Math_3i_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
91
92
#define getchr(vp) (*(vp)->nextchr++)
93
#define peekchr(vp) (*(vp)->nextchr)
94
#define ungetchr(vp) ((vp)->nextchr--)
95
96
#if ('a'==97) /* ASCII encodings */
97
# define getop(c) (((c) >= sizeof(strval_states))? \
98
((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\
99
strval_states[(c)])
100
#else
101
# define getop(c) (isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \
102
(c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \
103
(c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \
104
(c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \
105
(c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \
106
(c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \
107
(c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \
108
(c=='\''?A_LIT: \
109
(c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG)))))))))))))))))))))))
110
#endif
111
112
#define seterror(v,msg) _seterror(v,ERROR_dictionary(msg))
113
#define ERROR(vp,msg) return(seterror((vp),msg))
114
115
/*
116
* set error message string and return(0)
117
*/
118
static int _seterror(struct vars *vp,const char *msg)
119
{
120
if(!vp->errmsg.value)
121
vp->errmsg.value = (char*)msg;
122
vp->errchr = vp->nextchr;
123
vp->nextchr = "";
124
level = 0;
125
return(0);
126
}
127
128
129
static void arith_error(const char *message,const char *expr, int mode)
130
{
131
level = 0;
132
mode = (mode&3)!=0;
133
errormsg(SH_DICT,ERROR_exit(mode),message,expr);
134
}
135
136
#if _ast_no_um2fm
137
static Sfdouble_t U2F(Sfulong_t u)
138
{
139
Sflong_t s = u;
140
Sfdouble_t f;
141
142
if (s >= 0)
143
return s;
144
s = u / 2;
145
f = s;
146
f *= 2;
147
if (u & 1)
148
f++;
149
return f;
150
}
151
#else
152
#define U2F(x) x
153
#endif
154
155
Sfdouble_t arith_exec(Arith_t *ep)
156
{
157
register Sfdouble_t num=0,*dp,*sp;
158
register unsigned char *cp = ep->code;
159
register int c,type=0;
160
register char *tp;
161
Sfdouble_t small_stack[SMALL_STACK+1],arg[9];
162
const char *ptr = "";
163
char *lastval=0;
164
int lastsub;
165
Math_f fun;
166
struct lval node;
167
Shell_t *shp = ep->shp;
168
node.shp = shp;
169
node.emode = ep->emode;
170
node.expr = ep->expr;
171
node.elen = ep->elen;
172
node.value = 0;
173
node.nosub = 0;
174
node.ptr = 0;
175
node.eflag = 0;
176
if(level++ >=MAXLEVEL)
177
{
178
arith_error(e_recursive,ep->expr,ep->emode);
179
return(0);
180
}
181
if(ep->staksize < SMALL_STACK)
182
sp = small_stack;
183
else
184
sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1));
185
tp = (char*)(sp+ep->staksize);
186
tp--,sp--;
187
while(c = *cp++)
188
{
189
if(c&T_NOFLOAT)
190
{
191
if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD && tp[-1]==1))
192
arith_error(e_incompatible,ep->expr,ep->emode);
193
}
194
switch(c&T_OP)
195
{
196
case A_JMP: case A_JMPZ: case A_JMPNZ:
197
c &= T_OP;
198
cp = roundptr(ep,cp,short);
199
if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num))
200
cp += sizeof(short);
201
else
202
cp = (unsigned char*)ep + *((short*)cp);
203
continue;
204
case A_NOTNOT:
205
num = (num!=0);
206
type=0;
207
break;
208
case A_PLUSPLUS:
209
node.nosub = -1;
210
(*ep->fun)(&ptr,&node,ASSIGN,num+1);
211
break;
212
case A_MINUSMINUS:
213
node.nosub = -1;
214
(*ep->fun)(&ptr,&node,ASSIGN,num-1);
215
break;
216
case A_INCR:
217
num = num+1;
218
node.nosub = -1;
219
num = (*ep->fun)(&ptr,&node,ASSIGN,num);
220
break;
221
case A_DECR:
222
num = num-1;
223
node.nosub = -1;
224
num = (*ep->fun)(&ptr,&node,ASSIGN,num);
225
break;
226
case A_SWAP:
227
num = sp[-1];
228
sp[-1] = *sp;
229
type = tp[-1];
230
tp[-1] = *tp;
231
break;
232
case A_POP:
233
sp--;
234
continue;
235
case A_ASSIGNOP1:
236
node.emode |= ARITH_ASSIGNOP;
237
case A_PUSHV:
238
cp = roundptr(ep,cp,Sfdouble_t*);
239
dp = *((Sfdouble_t**)cp);
240
cp += sizeof(Sfdouble_t*);
241
c = *(short*)cp;
242
cp += sizeof(short);
243
lastval = node.value = (char*)dp;
244
if(node.flag = c)
245
lastval = 0;
246
node.isfloat=0;
247
node.level = level;
248
node.nosub = 0;
249
num = (*ep->fun)(&ptr,&node,VALUE,num);
250
if(node.emode&ARITH_ASSIGNOP)
251
{
252
lastsub = node.nosub;
253
node.nosub = 0;
254
node.emode &= ~ARITH_ASSIGNOP;
255
}
256
if(node.value != (char*)dp)
257
arith_error(node.value,ptr,ep->emode);
258
*++sp = num;
259
type = node.isfloat;
260
if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN)
261
type = 1;
262
else
263
{
264
Sfdouble_t d=num;
265
if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX)
266
{
267
type = 2;
268
d -= LDBL_LLONG_MAX;
269
}
270
if((Sflong_t)d!=d)
271
type = 1;
272
}
273
*++tp = type;
274
c = 0;
275
break;
276
case A_ENUM:
277
node.eflag = 1;
278
continue;
279
case A_ASSIGNOP:
280
node.nosub = lastsub;
281
case A_STORE:
282
cp = roundptr(ep,cp,Sfdouble_t*);
283
dp = *((Sfdouble_t**)cp);
284
cp += sizeof(Sfdouble_t*);
285
c = *(short*)cp;
286
if(c<0)
287
c = 0;
288
cp += sizeof(short);
289
node.value = (char*)dp;
290
node.flag = c;
291
if(lastval)
292
node.eflag = 1;
293
node.ptr = 0;
294
num = (*ep->fun)(&ptr,&node,ASSIGN,num);
295
if(lastval && node.ptr)
296
{
297
Sfdouble_t r;
298
node.flag = 0;
299
node.value = lastval;
300
r = (*ep->fun)(&ptr,&node,VALUE,num);
301
if(r!=num)
302
{
303
node.flag=c;
304
node.value = (char*)dp;
305
num = (*ep->fun)(&ptr,&node,ASSIGN,r);
306
}
307
308
}
309
lastval = 0;
310
c=0;
311
break;
312
case A_PUSHF:
313
cp = roundptr(ep,cp,Math_f);
314
*++sp = (Sfdouble_t)(cp-ep->code);
315
cp += sizeof(Math_f);
316
*++tp = *cp++;
317
continue;
318
case A_PUSHN:
319
cp = roundptr(ep,cp,Sfdouble_t);
320
num = *((Sfdouble_t*)cp);
321
cp += sizeof(Sfdouble_t);
322
*++sp = num;
323
*++tp = type = *cp++;
324
break;
325
case A_NOT:
326
type=0;
327
num = !num;
328
break;
329
case A_UMINUS:
330
num = -num;
331
break;
332
case A_TILDE:
333
num = ~((Sflong_t)(num));
334
break;
335
case A_PLUS:
336
num += sp[-1];
337
break;
338
case A_MINUS:
339
num = sp[-1] - num;
340
break;
341
case A_TIMES:
342
num *= sp[-1];
343
break;
344
case A_POW:
345
num = pow(sp[-1],num);
346
break;
347
case A_MOD:
348
if(!(Sflong_t)num)
349
arith_error(e_divzero,ep->expr,ep->emode);
350
if(type==2 || tp[-1]==2)
351
num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num));
352
else
353
num = (Sflong_t)(sp[-1]) % (Sflong_t)(num);
354
break;
355
case A_DIV:
356
if(type==1 || tp[-1]==1)
357
{
358
num = sp[-1]/num;
359
type = 1;
360
}
361
else if((Sfulong_t)(num)==0)
362
arith_error(e_divzero,ep->expr,ep->emode);
363
else if(type==2 || tp[-1]==2)
364
num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num));
365
else
366
num = (Sflong_t)(sp[-1]) / (Sflong_t)(num);
367
break;
368
case A_LSHIFT:
369
if(tp[-1]==2)
370
num = U2F((Sfulong_t)(sp[-1]) << (long)(num));
371
else
372
num = (Sflong_t)(sp[-1]) << (long)(num);
373
break;
374
case A_RSHIFT:
375
if(tp[-1]==2)
376
num = U2F((Sfulong_t)(sp[-1]) >> (long)(num));
377
else
378
num = (Sflong_t)(sp[-1]) >> (long)(num);
379
break;
380
case A_XOR:
381
if(type==2 || tp[-1]==2)
382
num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num));
383
else
384
num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num);
385
break;
386
case A_OR:
387
if(type==2 || tp[-1]==2)
388
num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num));
389
else
390
num = (Sflong_t)(sp[-1]) | (Sflong_t)(num);
391
break;
392
case A_AND:
393
if(type==2 || tp[-1]==2)
394
num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num));
395
else
396
num = (Sflong_t)(sp[-1]) & (Sflong_t)(num);
397
break;
398
case A_EQ:
399
num = (sp[-1]==num);
400
type=0;
401
break;
402
case A_NEQ:
403
num = (sp[-1]!=num);
404
type=0;
405
break;
406
case A_LE:
407
num = (sp[-1]<=num);
408
type=0;
409
break;
410
case A_GE:
411
num = (sp[-1]>=num);
412
type=0;
413
break;
414
case A_GT:
415
num = (sp[-1]>num);
416
type=0;
417
break;
418
case A_LT:
419
num = (sp[-1]<num);
420
type=0;
421
break;
422
case A_CALL1F:
423
sp--,tp--;
424
fun = *((Math_f*)(ep->code+(int)(*sp)));
425
type = *tp;
426
if(c&T_BINARY)
427
{
428
c &= ~T_BINARY;
429
arg[0] = num;
430
arg[1] = 0;
431
num = sh_mathfun(shp,(void*)fun,1,arg);
432
break;
433
}
434
num = (*((Math_1f_f)fun))(num);
435
break;
436
case A_CALL1I:
437
sp--,tp--;
438
fun = *((Math_f*)(ep->code+(int)(*sp)));
439
type = *tp;
440
num = (*((Math_1i_f)fun))(num);
441
break;
442
case A_CALL2F:
443
sp-=2,tp-=2;
444
fun = *((Math_f*)(ep->code+(int)(*sp)));
445
type = *tp;
446
if(c&T_BINARY)
447
{
448
c &= ~T_BINARY;
449
arg[0] = sp[1];
450
arg[1] = num;
451
arg[2] = 0;
452
num = sh_mathfun(shp,(void*)fun,2,arg);
453
break;
454
}
455
if(c&T_NOFLOAT)
456
num = (*((Math_2f_i)fun))(sp[1],(int)num);
457
else
458
num = (*((Math_2f_f)fun))(sp[1],num);
459
break;
460
case A_CALL2I:
461
sp-=2,tp-=2;
462
fun = *((Math_f*)(ep->code+(int)(*sp)));
463
type = *tp;
464
num = (*((Math_2i_f)fun))(sp[1],num);
465
break;
466
case A_CALL3F:
467
sp-=3,tp-=3;
468
fun = *((Math_f*)(ep->code+(int)(*sp)));
469
type = *tp;
470
if(c&T_BINARY)
471
{
472
c &= ~T_BINARY;
473
arg[0] = sp[1];
474
arg[1] = sp[2];
475
arg[2] = num;
476
arg[3] = 0;
477
num = sh_mathfun(shp,(void*)fun,3,arg);
478
break;
479
}
480
num = (*((Math_3f_f)fun))(sp[1],sp[2],num);
481
break;
482
}
483
if(c)
484
lastval = 0;
485
if(c&T_BINARY)
486
{
487
node.ptr = 0;
488
sp--,tp--;
489
type |= (*tp!=0);
490
}
491
*sp = num;
492
*tp = type;
493
}
494
if(level>0)
495
level--;
496
if(type==0 && !num)
497
num = 0;
498
return(num);
499
}
500
501
/*
502
* This returns operator tokens or A_REG or A_NUM
503
*/
504
static int gettok(register struct vars *vp)
505
{
506
register int c,op;
507
vp->errchr = vp->nextchr;
508
while(1)
509
{
510
c = getchr(vp);
511
switch(op=getop(c))
512
{
513
case 0:
514
vp->errchr = vp->nextchr;
515
continue;
516
case A_EOF:
517
vp->nextchr--;
518
break;
519
case A_COMMA:
520
if(vp->shp->decomma && (c=peekchr(vp))>='0' && c<='9')
521
{
522
op = A_DIG;
523
goto keep;
524
}
525
break;
526
case A_DOT:
527
if((c=peekchr(vp))>='0' && c<='9')
528
op = A_DIG;
529
else
530
op = A_REG;
531
/*FALL THRU*/
532
case A_DIG: case A_REG: case A_LIT:
533
keep:
534
ungetchr(vp);
535
break;
536
case A_QUEST:
537
if(peekchr(vp)==':')
538
{
539
getchr(vp);
540
op = A_QCOLON;
541
}
542
break;
543
case A_LT: case A_GT:
544
if(peekchr(vp)==c)
545
{
546
getchr(vp);
547
op -= 2;
548
break;
549
}
550
/* FALL THRU */
551
case A_NOT: case A_COLON:
552
c = '=';
553
/* FALL THRU */
554
case A_ASSIGN:
555
case A_TIMES:
556
case A_PLUS: case A_MINUS:
557
case A_OR: case A_AND:
558
if(peekchr(vp)==c)
559
{
560
getchr(vp);
561
op--;
562
}
563
}
564
return(op);
565
}
566
}
567
568
/*
569
* evaluate a subexpression with precedence
570
*/
571
572
static int expr(register struct vars *vp,register int precedence)
573
{
574
register int c, op;
575
int invalid,wasop=0;
576
struct lval lvalue,assignop;
577
const char *pos;
578
Sfdouble_t d;
579
580
lvalue.value = 0;
581
lvalue.nargs = 0;
582
lvalue.fun = 0;
583
lvalue.shp = vp->shp;
584
again:
585
op = gettok(vp);
586
c = 2*MAXPREC+1;
587
switch(op)
588
{
589
case A_PLUS:
590
goto again;
591
case A_EOF:
592
if(precedence>2)
593
ERROR(vp,e_moretokens);
594
return(1);
595
case A_MINUS:
596
op = A_UMINUS;
597
goto common;
598
case A_NOT:
599
goto common;
600
case A_MINUSMINUS:
601
c = A_LVALUE;
602
op = A_DECR|T_NOFLOAT;
603
goto common;
604
case A_PLUSPLUS:
605
c = A_LVALUE;
606
op = A_INCR|T_NOFLOAT;
607
/* FALL THRU */
608
case A_TILDE:
609
op |= T_NOFLOAT;
610
common:
611
if(!expr(vp,c))
612
return(0);
613
stakputc(op);
614
break;
615
default:
616
vp->nextchr = vp->errchr;
617
wasop = 1;
618
}
619
invalid = wasop;
620
while(1)
621
{
622
assignop.value = 0;
623
op = gettok(vp);
624
if(op==A_DIG || op==A_REG || op==A_LIT)
625
{
626
if(!wasop)
627
ERROR(vp,e_synbad);
628
goto number;
629
}
630
if(wasop++ && op!=A_LPAR)
631
ERROR(vp,e_synbad);
632
/* check for assignment operation */
633
if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN))
634
{
635
if((!lvalue.value || precedence > 3))
636
ERROR(vp,e_notlvalue);
637
if(precedence==3)
638
precedence = 2;
639
assignop = lvalue;
640
getchr(vp);
641
c = 3;
642
}
643
else
644
{
645
c = (strval_precedence[op]&PRECMASK);
646
if(c==MAXPREC || op==A_POW)
647
c++;
648
c *= 2;
649
}
650
/* from here on c is the new precedence level */
651
if(lvalue.value && (op!=A_ASSIGN))
652
{
653
if(vp->staksize++>=vp->stakmaxsize)
654
vp->stakmaxsize = vp->staksize;
655
if(op==A_EQ || op==A_NEQ)
656
stakputc(A_ENUM);
657
stakputc(assignop.value?A_ASSIGNOP1:A_PUSHV);
658
stakpush(vp,lvalue.value,char*);
659
if(lvalue.flag<0)
660
lvalue.flag = 0;
661
stakpush(vp,lvalue.flag,short);
662
if(vp->nextchr==0)
663
ERROR(vp,e_badnum);
664
if(!(strval_precedence[op]&SEQPOINT))
665
lvalue.value = 0;
666
invalid = 0;
667
}
668
else if(precedence==A_LVALUE)
669
ERROR(vp,e_notlvalue);
670
if(invalid && op>A_ASSIGN)
671
ERROR(vp,e_synbad);
672
if(precedence >= c)
673
goto done;
674
if(strval_precedence[op]&RASSOC)
675
c--;
676
if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT))
677
{
678
wasop = 0;
679
if(!expr(vp,c))
680
return(0);
681
}
682
switch(op)
683
{
684
case A_RPAR:
685
if(!vp->paren)
686
ERROR(vp,e_paren);
687
if(invalid)
688
ERROR(vp,e_synbad);
689
goto done;
690
691
case A_COMMA:
692
wasop = 0;
693
if(vp->infun)
694
vp->infun++;
695
else
696
{
697
stakputc(A_POP);
698
vp->staksize--;
699
}
700
if(!expr(vp,c))
701
{
702
stakseek(staktell()-1);
703
return(0);
704
}
705
lvalue.value = 0;
706
break;
707
708
case A_LPAR:
709
{
710
int infun = vp->infun;
711
int userfun=0;
712
Sfdouble_t (*fun)(Sfdouble_t,...);
713
int nargs = lvalue.nargs;
714
if(nargs<0)
715
nargs = -nargs;
716
fun = lvalue.fun;
717
lvalue.fun = 0;
718
if(fun)
719
{
720
if(vp->staksize++>=vp->stakmaxsize)
721
vp->stakmaxsize = vp->staksize;
722
vp->infun=1;
723
if((int)lvalue.nargs<0)
724
userfun = T_BINARY;
725
else if((int)lvalue.nargs&040)
726
userfun = T_NOFLOAT;
727
stakputc(A_PUSHF);
728
stakpush(vp,fun,Math_f);
729
stakputc(1);
730
}
731
else
732
vp->infun = 0;
733
if(!invalid)
734
ERROR(vp,e_synbad);
735
vp->paren++;
736
if(!expr(vp,1))
737
return(0);
738
vp->paren--;
739
if(fun)
740
{
741
int x= (nargs&010)?2:-1;
742
nargs &= 7;
743
if(vp->infun != nargs)
744
ERROR(vp,e_argcount);
745
if((vp->staksize+=nargs)>=vp->stakmaxsize)
746
vp->stakmaxsize = vp->staksize+nargs;
747
stakputc(A_CALL1F+userfun+nargs+x);
748
vp->staksize -= nargs;
749
}
750
vp->infun = infun;
751
if (gettok(vp) != A_RPAR)
752
ERROR(vp,e_paren);
753
wasop = 0;
754
break;
755
}
756
757
case A_PLUSPLUS:
758
case A_MINUSMINUS:
759
wasop=0;
760
op |= T_NOFLOAT;
761
case A_ASSIGN:
762
if(!lvalue.value)
763
ERROR(vp,e_notlvalue);
764
if(op==A_ASSIGN)
765
{
766
stakputc(A_STORE);
767
stakpush(vp,lvalue.value,char*);
768
stakpush(vp,lvalue.flag,short);
769
vp->staksize--;
770
}
771
else
772
stakputc(op);
773
lvalue.value = 0;
774
break;
775
776
case A_QUEST:
777
{
778
int offset1,offset2;
779
stakputc(A_JMPZ);
780
offset1 = stakpush(vp,0,short);
781
stakputc(A_POP);
782
if(!expr(vp,1))
783
return(0);
784
if(gettok(vp)!=A_COLON)
785
ERROR(vp,e_questcolon);
786
stakputc(A_JMP);
787
offset2 = stakpush(vp,0,short);
788
*((short*)stakptr(offset1)) = staktell();
789
stakputc(A_POP);
790
if(!expr(vp,3))
791
return(0);
792
*((short*)stakptr(offset2)) = staktell();
793
lvalue.value = 0;
794
wasop = 0;
795
break;
796
}
797
798
case A_COLON:
799
ERROR(vp,e_badcolon);
800
break;
801
802
case A_QCOLON:
803
case A_ANDAND:
804
case A_OROR:
805
{
806
int offset;
807
if(op==A_ANDAND)
808
op = A_JMPZ;
809
else
810
op = A_JMPNZ;
811
stakputc(op);
812
offset = stakpush(vp,0,short);
813
stakputc(A_POP);
814
if(!expr(vp,c))
815
return(0);
816
*((short*)stakptr(offset)) = staktell();
817
if(op!=A_QCOLON)
818
stakputc(A_NOTNOT);
819
lvalue.value = 0;
820
wasop=0;
821
break;
822
}
823
case A_AND: case A_OR: case A_XOR: case A_LSHIFT:
824
case A_RSHIFT: case A_MOD:
825
op |= T_NOFLOAT;
826
/* FALL THRU */
827
case A_PLUS: case A_MINUS: case A_TIMES: case A_DIV:
828
case A_EQ: case A_NEQ: case A_LT: case A_LE:
829
case A_GT: case A_GE: case A_POW:
830
stakputc(op|T_BINARY);
831
vp->staksize--;
832
break;
833
case A_NOT: case A_TILDE:
834
default:
835
ERROR(vp,e_synbad);
836
number:
837
wasop = 0;
838
if(*vp->nextchr=='L' && vp->nextchr[1]=='\'')
839
{
840
vp->nextchr++;
841
op = A_LIT;
842
}
843
pos = vp->nextchr;
844
lvalue.isfloat = 0;
845
lvalue.expr = vp->expr;
846
lvalue.emode = vp->emode;
847
if(op==A_LIT)
848
{
849
/* character constants */
850
if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'')
851
{
852
d = '\\';
853
vp->nextchr +=2;
854
}
855
else
856
d = chresc(pos+1,(char**)&vp->nextchr);
857
/* posix allows the trailing ' to be optional */
858
if(*vp->nextchr=='\'')
859
vp->nextchr++;
860
}
861
else
862
d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0);
863
if (vp->nextchr == pos)
864
{
865
if(vp->errmsg.value = lvalue.value)
866
vp->errstr = pos;
867
ERROR(vp,op==A_LIT?e_charconst:e_synbad);
868
}
869
if(op==A_DIG || op==A_LIT)
870
{
871
stakputc(A_PUSHN);
872
if(vp->staksize++>=vp->stakmaxsize)
873
vp->stakmaxsize = vp->staksize;
874
stakpush(vp,d,Sfdouble_t);
875
stakputc(lvalue.isfloat);
876
}
877
878
/* check for function call */
879
if(lvalue.fun)
880
continue;
881
break;
882
}
883
invalid = 0;
884
if(assignop.value)
885
{
886
if(vp->staksize++>=vp->stakmaxsize)
887
vp->stakmaxsize = vp->staksize;
888
if(assignop.flag<0)
889
assignop.flag = 0;
890
stakputc(c&1?A_ASSIGNOP:A_STORE);
891
stakpush(vp,assignop.value,char*);
892
stakpush(vp,assignop.flag,short);
893
}
894
}
895
done:
896
vp->nextchr = vp->errchr;
897
return(1);
898
}
899
900
Arith_t *arith_compile(Shell_t *shp,const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode)
901
{
902
struct vars cur;
903
register Arith_t *ep;
904
int offset;
905
memset((void*)&cur,0,sizeof(cur));
906
cur.shp = shp;
907
cur.expr = cur.nextchr = string;
908
cur.convert = fun;
909
cur.emode = emode;
910
cur.errmsg.value = 0;
911
cur.errmsg.emode = emode;
912
stakseek(sizeof(Arith_t));
913
if(!expr(&cur,0) && cur.errmsg.value)
914
{
915
if(cur.errstr)
916
string = cur.errstr;
917
if((*fun)( &string , &cur.errmsg, MESSAGE, 0) < 0)
918
{
919
stakseek(0);
920
*last = (char*)Empty;
921
return(0);
922
}
923
cur.nextchr = cur.errchr;
924
}
925
stakputc(0);
926
offset = staktell();
927
ep = (Arith_t*)stakfreeze(0);
928
ep->shp = shp;
929
ep->expr = string;
930
ep->elen = strlen(string);
931
ep->code = (unsigned char*)(ep+1);
932
ep->fun = fun;
933
ep->emode = emode;
934
ep->size = offset - sizeof(Arith_t);
935
ep->staksize = cur.stakmaxsize+1;
936
if(last)
937
*last = (char*)(cur.nextchr);
938
return(ep);
939
}
940
941
/*
942
* evaluate an integer arithmetic expression in s
943
*
944
* (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value)
945
* is a user supplied conversion routine that is called when unknown
946
* chars are encountered.
947
* *end points to the part to be converted and must be adjusted by convert to
948
* point to the next non-converted character; if typ is MESSAGE then string
949
* points to an error message string
950
*
951
* NOTE: (*convert)() may call strval()
952
*/
953
954
Sfdouble_t strval(Shell_t *shp,const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode)
955
{
956
Arith_t *ep;
957
Sfdouble_t d;
958
char *sp=0;
959
int offset;
960
if(offset=staktell())
961
sp = stakfreeze(1);
962
ep = arith_compile(shp,s,end,conv,emode);
963
ep->emode = emode;
964
d = arith_exec(ep);
965
stakset(sp?sp:(char*)ep,offset);
966
return(d);
967
}
968
969
#if _mem_name__exception
970
#undef _mem_name_exception
971
#define _mem_name_exception 1
972
#undef exception
973
#define exception _exception
974
#undef matherr
975
#endif
976
977
#if _mem_name_exception
978
979
#undef error
980
981
#if _BLD_shell && defined(__EXPORT__)
982
#define extern __EXPORT__
983
#endif
984
985
#ifndef DOMAIN
986
#define DOMAIN _DOMAIN
987
#endif
988
#ifndef OVERFLOW
989
#define OVERFLOW _OVERFLOW
990
#endif
991
#ifndef SING
992
#define SING _SING
993
#endif
994
995
extern int matherr(struct exception *ep)
996
{
997
const char *message;
998
switch(ep->type)
999
{
1000
#ifdef DOMAIN
1001
case DOMAIN:
1002
message = ERROR_dictionary(e_domain);
1003
break;
1004
#endif
1005
#ifdef OVERFLOW
1006
case OVERFLOW:
1007
message = ERROR_dictionary(e_overflow);
1008
break;
1009
#endif
1010
#ifdef SING
1011
case SING:
1012
message = ERROR_dictionary(e_singularity);
1013
break;
1014
#endif
1015
default:
1016
return(1);
1017
}
1018
level=0;
1019
errormsg(SH_DICT,ERROR_exit(1),message,ep->name);
1020
return(0);
1021
}
1022
1023
#undef extern
1024
1025
#endif /* _mem_name_exception */
1026
1027