1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119#include "libbb.h"
120#include "math.h"
121
122#define a_e_h_t arith_eval_hooks_t
123#define lookupvar (math_hooks->lookupvar)
124#define setvar (math_hooks->setvar )
125#define endofname (math_hooks->endofname)
126
127#define arith_isspace(arithval) \
128 (arithval == ' ' || arithval == '\n' || arithval == '\t')
129
130typedef unsigned char operator;
131
132
133
134
135
136
137
138#define tok_decl(prec,id) (((id)<<5)|(prec))
139#define PREC(op) ((op) & 0x1F)
140
141#define TOK_LPAREN tok_decl(0,0)
142
143#define TOK_COMMA tok_decl(1,0)
144
145#define TOK_ASSIGN tok_decl(2,0)
146#define TOK_AND_ASSIGN tok_decl(2,1)
147#define TOK_OR_ASSIGN tok_decl(2,2)
148#define TOK_XOR_ASSIGN tok_decl(2,3)
149#define TOK_PLUS_ASSIGN tok_decl(2,4)
150#define TOK_MINUS_ASSIGN tok_decl(2,5)
151#define TOK_LSHIFT_ASSIGN tok_decl(2,6)
152#define TOK_RSHIFT_ASSIGN tok_decl(2,7)
153
154#define TOK_MUL_ASSIGN tok_decl(3,0)
155#define TOK_DIV_ASSIGN tok_decl(3,1)
156#define TOK_REM_ASSIGN tok_decl(3,2)
157
158
159#define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
160
161
162#define TOK_CONDITIONAL tok_decl(4,0)
163#define TOK_CONDITIONAL_SEP tok_decl(4,1)
164
165#define TOK_OR tok_decl(5,0)
166
167#define TOK_AND tok_decl(6,0)
168
169#define TOK_BOR tok_decl(7,0)
170
171#define TOK_BXOR tok_decl(8,0)
172
173#define TOK_BAND tok_decl(9,0)
174
175#define TOK_EQ tok_decl(10,0)
176#define TOK_NE tok_decl(10,1)
177
178#define TOK_LT tok_decl(11,0)
179#define TOK_GT tok_decl(11,1)
180#define TOK_GE tok_decl(11,2)
181#define TOK_LE tok_decl(11,3)
182
183#define TOK_LSHIFT tok_decl(12,0)
184#define TOK_RSHIFT tok_decl(12,1)
185
186#define TOK_ADD tok_decl(13,0)
187#define TOK_SUB tok_decl(13,1)
188
189#define TOK_MUL tok_decl(14,0)
190#define TOK_DIV tok_decl(14,1)
191#define TOK_REM tok_decl(14,2)
192
193
194#define TOK_EXPONENT tok_decl(15,1)
195
196
197#define UNARYPREC 16
198#define TOK_BNOT tok_decl(UNARYPREC,0)
199#define TOK_NOT tok_decl(UNARYPREC,1)
200
201#define TOK_UMINUS tok_decl(UNARYPREC+1,0)
202#define TOK_UPLUS tok_decl(UNARYPREC+1,1)
203
204#define PREC_PRE (UNARYPREC+2)
205
206#define TOK_PRE_INC tok_decl(PREC_PRE, 0)
207#define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
208
209#define PREC_POST (UNARYPREC+3)
210
211#define TOK_POST_INC tok_decl(PREC_POST, 0)
212#define TOK_POST_DEC tok_decl(PREC_POST, 1)
213
214#define SPEC_PREC (UNARYPREC+4)
215
216#define TOK_NUM tok_decl(SPEC_PREC, 0)
217#define TOK_RPAREN tok_decl(SPEC_PREC, 1)
218
219#define NUMPTR (*numstackptr)
220
221static int
222tok_have_assign(operator op)
223{
224 operator prec = PREC(op);
225
226 convert_prec_is_assing(prec);
227 return (prec == PREC(TOK_ASSIGN) ||
228 prec == PREC_PRE || prec == PREC_POST);
229}
230
231static int
232is_right_associativity(operator prec)
233{
234 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
235 || prec == PREC(TOK_CONDITIONAL));
236}
237
238typedef struct {
239 arith_t val;
240 arith_t contidional_second_val;
241 char contidional_second_val_initialized;
242 char *var;
243
244} v_n_t;
245
246typedef struct chk_var_recursive_looped_t {
247 const char *var;
248 struct chk_var_recursive_looped_t *next;
249} chk_var_recursive_looped_t;
250
251static chk_var_recursive_looped_t *prev_chk_var_recursive;
252
253static int
254arith_lookup_val(v_n_t *t, a_e_h_t *math_hooks)
255{
256 if (t->var) {
257 const char *p = lookupvar(t->var);
258
259 if (p) {
260 int errcode;
261
262
263 chk_var_recursive_looped_t *cur;
264 chk_var_recursive_looped_t cur_save;
265
266 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
267 if (strcmp(cur->var, t->var) == 0) {
268
269 return -5;
270 }
271 }
272
273 cur = prev_chk_var_recursive;
274 cur_save.var = t->var;
275 cur_save.next = cur;
276 prev_chk_var_recursive = &cur_save;
277
278 t->val = arith (p, &errcode, math_hooks);
279
280 prev_chk_var_recursive = cur;
281 return errcode;
282 }
283
284 t->val = 0;
285 }
286 return 0;
287}
288
289
290
291
292static NOINLINE int
293arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr, a_e_h_t *math_hooks)
294{
295 v_n_t *numptr_m1;
296 arith_t numptr_val, rez;
297 int ret_arith_lookup_val;
298
299
300 if (NUMPTR == numstack) goto err;
301 numptr_m1 = NUMPTR - 1;
302
303
304 ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks);
305 if (ret_arith_lookup_val)
306 return ret_arith_lookup_val;
307
308 rez = numptr_m1->val;
309 if (op == TOK_UMINUS)
310 rez *= -1;
311 else if (op == TOK_NOT)
312 rez = !rez;
313 else if (op == TOK_BNOT)
314 rez = ~rez;
315 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
316 rez++;
317 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
318 rez--;
319 else if (op != TOK_UPLUS) {
320
321
322
323 if (numptr_m1 == numstack) goto err;
324
325
326 --NUMPTR;
327 numptr_val = rez;
328 if (op == TOK_CONDITIONAL) {
329 if (!numptr_m1->contidional_second_val_initialized) {
330
331 goto err;
332 }
333 rez = numptr_m1->contidional_second_val;
334 } else if (numptr_m1->contidional_second_val_initialized) {
335
336 goto err;
337 }
338 numptr_m1 = NUMPTR - 1;
339 if (op != TOK_ASSIGN) {
340
341 ret_arith_lookup_val = arith_lookup_val(numptr_m1, math_hooks);
342 if (ret_arith_lookup_val)
343 return ret_arith_lookup_val;
344 }
345 if (op == TOK_CONDITIONAL) {
346 numptr_m1->contidional_second_val = rez;
347 }
348 rez = numptr_m1->val;
349 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
350 rez |= numptr_val;
351 else if (op == TOK_OR)
352 rez = numptr_val || rez;
353 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
354 rez &= numptr_val;
355 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
356 rez ^= numptr_val;
357 else if (op == TOK_AND)
358 rez = rez && numptr_val;
359 else if (op == TOK_EQ)
360 rez = (rez == numptr_val);
361 else if (op == TOK_NE)
362 rez = (rez != numptr_val);
363 else if (op == TOK_GE)
364 rez = (rez >= numptr_val);
365 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
366 rez >>= numptr_val;
367 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
368 rez <<= numptr_val;
369 else if (op == TOK_GT)
370 rez = (rez > numptr_val);
371 else if (op == TOK_LT)
372 rez = (rez < numptr_val);
373 else if (op == TOK_LE)
374 rez = (rez <= numptr_val);
375 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
376 rez *= numptr_val;
377 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
378 rez += numptr_val;
379 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
380 rez -= numptr_val;
381 else if (op == TOK_ASSIGN || op == TOK_COMMA)
382 rez = numptr_val;
383 else if (op == TOK_CONDITIONAL_SEP) {
384 if (numptr_m1 == numstack) {
385
386 goto err;
387 }
388 numptr_m1->contidional_second_val_initialized = op;
389 numptr_m1->contidional_second_val = numptr_val;
390 } else if (op == TOK_CONDITIONAL) {
391 rez = rez ?
392 numptr_val : numptr_m1->contidional_second_val;
393 } else if (op == TOK_EXPONENT) {
394 if (numptr_val < 0)
395 return -3;
396 else {
397 arith_t c = 1;
398
399 if (numptr_val)
400 while (numptr_val--)
401 c *= rez;
402 rez = c;
403 }
404 } else if (numptr_val==0)
405 return -2;
406 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
407 rez /= numptr_val;
408 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
409 rez %= numptr_val;
410 }
411 if (tok_have_assign(op)) {
412 char buf[sizeof(arith_t)*3 + 2];
413
414 if (numptr_m1->var == NULL) {
415
416 goto err;
417 }
418
419 sprintf(buf, arith_t_fmt, rez);
420 setvar(numptr_m1->var, buf);
421
422 if (op == TOK_POST_INC)
423 rez--;
424 else if (op == TOK_POST_DEC)
425 rez++;
426 }
427 numptr_m1->val = rez;
428
429 numptr_m1->var = NULL;
430 return 0;
431 err:
432 return -1;
433}
434
435
436static const char op_tokens[] ALIGN1 = {
437 '<','<','=',0, TOK_LSHIFT_ASSIGN,
438 '>','>','=',0, TOK_RSHIFT_ASSIGN,
439 '<','<', 0, TOK_LSHIFT,
440 '>','>', 0, TOK_RSHIFT,
441 '|','|', 0, TOK_OR,
442 '&','&', 0, TOK_AND,
443 '!','=', 0, TOK_NE,
444 '<','=', 0, TOK_LE,
445 '>','=', 0, TOK_GE,
446 '=','=', 0, TOK_EQ,
447 '|','=', 0, TOK_OR_ASSIGN,
448 '&','=', 0, TOK_AND_ASSIGN,
449 '*','=', 0, TOK_MUL_ASSIGN,
450 '/','=', 0, TOK_DIV_ASSIGN,
451 '%','=', 0, TOK_REM_ASSIGN,
452 '+','=', 0, TOK_PLUS_ASSIGN,
453 '-','=', 0, TOK_MINUS_ASSIGN,
454 '-','-', 0, TOK_POST_DEC,
455 '^','=', 0, TOK_XOR_ASSIGN,
456 '+','+', 0, TOK_POST_INC,
457 '*','*', 0, TOK_EXPONENT,
458 '!', 0, TOK_NOT,
459 '<', 0, TOK_LT,
460 '>', 0, TOK_GT,
461 '=', 0, TOK_ASSIGN,
462 '|', 0, TOK_BOR,
463 '&', 0, TOK_BAND,
464 '*', 0, TOK_MUL,
465 '/', 0, TOK_DIV,
466 '%', 0, TOK_REM,
467 '+', 0, TOK_ADD,
468 '-', 0, TOK_SUB,
469 '^', 0, TOK_BXOR,
470
471 '~', 0, TOK_BNOT,
472 ',', 0, TOK_COMMA,
473 '?', 0, TOK_CONDITIONAL,
474 ':', 0, TOK_CONDITIONAL_SEP,
475 ')', 0, TOK_RPAREN,
476 '(', 0, TOK_LPAREN,
477 0
478};
479
480#define endexpression (&op_tokens[sizeof(op_tokens)-7])
481
482arith_t
483arith(const char *expr, int *perrcode, a_e_h_t *math_hooks)
484{
485 char arithval;
486 operator lasttok, op;
487 operator prec;
488 operator *stack, *stackptr;
489 const char *p = endexpression;
490 int errcode;
491 v_n_t *numstack, *numstackptr;
492 unsigned datasizes = strlen(expr) + 2;
493
494
495
496
497
498 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
499
500 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
501
502 *stackptr++ = lasttok = TOK_LPAREN;
503 *perrcode = errcode = 0;
504
505 while (1) {
506 arithval = *expr;
507 if (arithval == 0) {
508 if (p == endexpression) {
509
510 return 0;
511 }
512
513
514
515
516
517
518 if (expr != endexpression + 1) {
519
520
521 expr = endexpression;
522
523 continue;
524 }
525
526 if (numstackptr != numstack+1) {
527
528 err:
529 *perrcode = -1;
530 return *perrcode;
531 }
532 if (numstack->var) {
533
534 errcode = arith_lookup_val(numstack, math_hooks);
535 }
536 ret:
537 *perrcode = errcode;
538 return numstack->val;
539 }
540
541
542 if (arith_isspace(arithval)) {
543
544 goto prologue;
545 }
546 p = endofname(expr);
547 if (p != expr) {
548 size_t var_name_size = (p-expr) + 1;
549
550 numstackptr->var = alloca(var_name_size);
551 safe_strncpy(numstackptr->var, expr, var_name_size);
552 expr = p;
553 num:
554 numstackptr->contidional_second_val_initialized = 0;
555 numstackptr++;
556 lasttok = TOK_NUM;
557 continue;
558 }
559 if (isdigit(arithval)) {
560 numstackptr->var = NULL;
561 errno = 0;
562
563 numstackptr->val = strto_arith_t(expr, (char **) &expr, 0);
564 if (errno)
565 numstackptr->val = 0;
566 goto num;
567 }
568 for (p = op_tokens; ; p++) {
569 const char *o;
570
571 if (*p == 0) {
572
573 goto err;
574 }
575 for (o = expr; *p && *o == *p; p++)
576 o++;
577 if (!*p) {
578
579 expr = o - 1;
580 break;
581 }
582
583 while (*p)
584 p++;
585
586 p++;
587 }
588 op = p[1];
589
590
591 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
592 lasttok = TOK_NUM;
593
594
595
596
597
598 if (lasttok != TOK_NUM) {
599 switch (op) {
600 case TOK_ADD:
601 op = TOK_UPLUS;
602 break;
603 case TOK_SUB:
604 op = TOK_UMINUS;
605 break;
606 case TOK_POST_INC:
607 op = TOK_PRE_INC;
608 break;
609 case TOK_POST_DEC:
610 op = TOK_PRE_DEC;
611 break;
612 }
613 }
614
615
616
617
618
619
620
621
622
623
624
625 prec = PREC(op);
626 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
627
628 if (lasttok != TOK_NUM) {
629
630 goto err;
631 }
632 while (stackptr != stack) {
633 if (op == TOK_RPAREN) {
634
635
636
637 if (stackptr[-1] == TOK_LPAREN) {
638 --stackptr;
639
640 lasttok = TOK_NUM;
641
642 goto prologue;
643 }
644 } else {
645 operator prev_prec = PREC(stackptr[-1]);
646
647 convert_prec_is_assing(prec);
648 convert_prec_is_assing(prev_prec);
649 if (prev_prec < prec)
650 break;
651
652 if (prev_prec == prec && is_right_associativity(prec))
653 break;
654 }
655 errcode = arith_apply(*--stackptr, numstack, &numstackptr, math_hooks);
656 if (errcode) goto ret;
657 }
658 if (op == TOK_RPAREN) {
659 goto err;
660 }
661 }
662
663
664 *stackptr++ = lasttok = op;
665 prologue:
666 ++expr;
667 }
668}
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701