142
135
* but there are 11 of them, which doesn't fit into 3 bits for unique id.
143
136
* Abusing another precedence level:
145
#define PREC_ASSIGN1 2
146
138
#define TOK_ASSIGN tok_decl(2,0)
147
139
#define TOK_AND_ASSIGN tok_decl(2,1)
148
140
#define TOK_OR_ASSIGN tok_decl(2,2)
149
141
#define TOK_XOR_ASSIGN tok_decl(2,3)
150
#define TOK_ADD_ASSIGN tok_decl(2,4)
151
#define TOK_SUB_ASSIGN tok_decl(2,5)
142
#define TOK_PLUS_ASSIGN tok_decl(2,4)
143
#define TOK_MINUS_ASSIGN tok_decl(2,5)
152
144
#define TOK_LSHIFT_ASSIGN tok_decl(2,6)
153
145
#define TOK_RSHIFT_ASSIGN tok_decl(2,7)
155
#define PREC_ASSIGN2 3
156
147
#define TOK_MUL_ASSIGN tok_decl(3,0)
157
/* "/" and "/=" ops have the same id bits */
159
#define TOK_DIV_ASSIGN tok_decl(3,DIV_ID1)
148
#define TOK_DIV_ASSIGN tok_decl(3,1)
160
149
#define TOK_REM_ASSIGN tok_decl(3,2)
162
#define fix_assignment_prec(prec) do { prec -= (prec == 3); } while (0)
151
#define fix_assignment_prec(prec) do { if (prec == 3) prec = 2; } while (0)
164
153
/* Ternary conditional operator is right associative too */
166
* bash documentation says that precedence order is:
168
* expr ? expr1 : expr2
169
* = *= /= %= += -= <<= >>= &= ^= |=
171
* What it omits is that expr1 is parsed as if parenthesized
172
* (this matches the rules of ?: in C language):
173
* "v ? 1,2 : 3,4" is parsed as "(v ? (1,2) : 3),4"
174
* "v ? a=2 : b=4" is parsed as "(v ? (a=1) : b)=4" (thus, this is a syntax error)
176
154
#define TOK_CONDITIONAL tok_decl(4,0)
177
155
#define TOK_CONDITIONAL_SEP tok_decl(4,1)
216
194
#define TOK_UPLUS tok_decl(UNARYPREC+1,1)
218
196
#define PREC_PRE (UNARYPREC+2)
219
#define TOK_PRE_INC tok_decl(PREC_PRE,0)
220
#define TOK_PRE_DEC tok_decl(PREC_PRE,1)
198
#define TOK_PRE_INC tok_decl(PREC_PRE, 0)
199
#define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
222
201
#define PREC_POST (UNARYPREC+3)
223
#define TOK_POST_INC tok_decl(PREC_POST,0)
224
#define TOK_POST_DEC tok_decl(PREC_POST,1)
226
/* TOK_VALUE marks a number, name, name++/name--, or (EXPR):
227
* IOW: something which can be used as the left side of a binary op.
228
* Since it's never pushed to opstack, its precedence does not matter.
230
#define TOK_VALUE tok_decl(PREC_POST,2)
203
#define TOK_POST_INC tok_decl(PREC_POST, 0)
204
#define TOK_POST_DEC tok_decl(PREC_POST, 1)
206
#define SPEC_PREC (UNARYPREC+4)
208
#define TOK_NUM tok_decl(SPEC_PREC, 0)
209
#define TOK_RPAREN tok_decl(SPEC_PREC, 1)
233
212
is_assign_op(operator op)
235
214
operator prec = PREC(op);
236
return prec == PREC_ASSIGN1
237
|| prec == PREC_ASSIGN2
215
fix_assignment_prec(prec);
216
return prec == PREC(TOK_ASSIGN)
238
217
|| prec == PREC_PRE
239
218
|| prec == PREC_POST;
247
226
|| prec == PREC(TOK_CONDITIONAL);
252
const char *var_name;
232
/* We acquire second_val only when "expr1 : expr2" part
233
* of ternary ?: op is evaluated.
234
* We treat ?: as two binary ops: (expr ? (expr1 : expr2)).
235
* ':' produces a new value which has two parts, val and second_val;
236
* then '?' selects one of them based on its left side.
239
char second_val_present;
240
/* If NULL then it's just a number, else it's a named variable */
255
#define VALID_NAME(name) (name)
256
#define NOT_NAME(name) (!(name))
258
244
typedef struct remembered_name {
259
245
struct remembered_name *next;
260
const char *var_name;
261
247
} remembered_name;
263
static ALWAYS_INLINE int isalnum_(int c)
265
return (isalnum(c) || c == '_');
269
251
evaluate_string(arith_state_t *math_state, const char *expr);
272
arith_lookup_val(arith_state_t *math_state, const char *name, char *endname)
254
arith_lookup_val(arith_state_t *math_state, var_or_num_t *t)
279
p = math_state->lookupvar(name);
283
size_t len = endname - name;
284
remembered_name *cur;
285
remembered_name remember;
287
/* did we already see this name?
288
* testcase: a=b; b=a; echo $((a))
290
for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) {
291
if (strncmp(cur->var_name, name, len) == 0
292
&& !isalnum_(cur->var_name[len])
295
math_state->errmsg = "expression recursion loop detected";
257
const char *p = math_state->lookupvar(t->var);
259
remembered_name *cur;
260
remembered_name cur_save;
262
/* did we already see this name?
263
* testcase: a=b; b=a; echo $((a))
265
for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) {
266
if (strcmp(cur->var, t->var) == 0) {
268
return "expression recursion loop detected";
272
/* push current var name */
273
cur = math_state->list_of_recursed_names;
274
cur_save.var = t->var;
276
math_state->list_of_recursed_names = &cur_save;
278
/* recursively evaluate p as expression */
279
t->val = evaluate_string(math_state, p);
281
/* pop current var name */
282
math_state->list_of_recursed_names = cur;
284
return math_state->errmsg;
300
/* push current var name */
301
remember.var_name = name;
302
remember.next = math_state->list_of_recursed_names;
303
math_state->list_of_recursed_names = &remember;
305
/* recursively evaluate p as expression */
306
/* this sets math_state->errmsg on error */
307
val = evaluate_string(math_state, p);
309
/* pop current var name */
310
math_state->list_of_recursed_names = remember.next;
286
/* treat undefined var as 0 */
314
/* treat undefined var as 0 */
318
292
/* "Applying" a token means performing it on the top elements on the integer
319
* stack. For an unary operator it will only change the top element,
320
* a binary operator will pop two arguments and push the result,
321
* the ternary ?: op will pop three arguments and push the result.
293
* stack. For an unary operator it will only change the top element, but a
294
* binary operator will pop two arguments and push the result */
323
295
static NOINLINE const char*
324
296
arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_or_num_t **numstackptr)
326
#define NUMSTACKPTR (*numstackptr)
298
#define NUMPTR (*numstackptr)
328
300
var_or_num_t *top_of_stack;
331
304
/* There is no operator that can work without arguments */
332
if (NUMSTACKPTR == numstack)
335
top_of_stack = NUMSTACKPTR - 1;
337
if (op == TOK_CONDITIONAL_SEP) {
338
/* "expr1 ? expr2 : expr3" operation */
339
var_or_num_t *expr1 = &top_of_stack[-2];
340
NUMSTACKPTR = expr1 + 1;
341
if (expr1 < numstack) /* Example: $((2:3)) */
342
return "malformed ?: operator";
343
if (expr1->val != 0) /* select expr2 or expr3 */
345
rez = top_of_stack->val;
346
top_of_stack = expr1;
349
if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */
350
return "malformed ?: operator";
305
if (NUMPTR == numstack)
308
top_of_stack = NUMPTR - 1;
310
/* Resolve name to value, if needed */
311
err = arith_lookup_val(math_state, top_of_stack);
352
315
rez = top_of_stack->val;
353
316
if (op == TOK_UMINUS)
361
324
else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
363
else /*if (op != TOK_UPLUS) - always true, we drop TOK_UPLUS earlier */ {
326
else if (op != TOK_UPLUS) {
364
327
/* Binary operators */
365
328
arith_t right_side_val;
367
if (top_of_stack == numstack) /* have two arguments? */
368
goto syntax_err; /* no */
371
NUMSTACKPTR = top_of_stack; /* this decrements NUMSTACKPTR */
373
if (math_state->evaluation_disabled) {
374
dbg("binary op %02x skipped", op);
376
/* bash 5.2.12 does not execute "2/0" in disabled
377
* branches of ?: (and thus does not complain),
378
* but complains about negative exp: "2**-1".
379
* I don't think we need to emulate that.
331
/* Binary operators need two arguments */
332
if (top_of_stack == numstack)
334
/* ...and they pop one */
335
NUMPTR = top_of_stack; /* this decrements NUMPTR */
337
bad_second_val = top_of_stack->second_val_present;
338
if (op == TOK_CONDITIONAL) { /* ? operation */
339
/* Make next if (...) protect against
340
* $((expr1 ? expr2)) - that is, missing ": expr" */
341
bad_second_val = !bad_second_val;
343
if (bad_second_val) {
344
/* Protect against $((expr <not_?_op> expr1 : expr2)) */
345
return "malformed ?: operator";
383
348
top_of_stack--; /* now points to left side */
350
if (op != TOK_ASSIGN) {
351
/* Resolve left side value (unless the op is '=') */
352
err = arith_lookup_val(math_state, top_of_stack);
384
357
right_side_val = rez;
385
358
rez = top_of_stack->val;
386
if (op == TOK_BOR || op == TOK_OR_ASSIGN)
359
if (op == TOK_CONDITIONAL) /* ? operation */
360
rez = (rez ? right_side_val : top_of_stack[1].second_val);
361
else if (op == TOK_CONDITIONAL_SEP) { /* : operation */
362
if (top_of_stack == numstack) {
363
/* Protect against $((expr : expr)) */
364
return "malformed ?: operator";
366
top_of_stack->second_val_present = op;
367
top_of_stack->second_val = right_side_val;
369
else if (op == TOK_BOR || op == TOK_OR_ASSIGN)
387
370
rez |= right_side_val;
388
371
else if (op == TOK_OR)
389
372
rez = right_side_val || rez;
453
424
* Make sure to at least not SEGV here:
455
426
if (right_side_val == -1
456
&& (rez << 1) == 0 /* MAX_NEGATIVE_INT or 0 */
427
&& rez << 1 == 0 /* MAX_NEGATIVE_INT or 0 */
458
429
right_side_val = 1;
460
if (op & (DIV_ID1 << ID_SHIFT)) /* DIV or DIV_ASSIGN? */
431
if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
461
432
rez /= right_side_val;
463
434
rez %= right_side_val;
467
if (math_state->evaluation_disabled) {
468
dbg("unary op %02x skipped", op);
472
439
if (is_assign_op(op)) {
473
440
char buf[sizeof(arith_t)*3 + 2];
475
if (NOT_NAME(top_of_stack->var_name)) {
442
if (top_of_stack->var == NULL) {
479
446
/* Save to shell variable */
480
447
sprintf(buf, ARITH_FMT, rez);
482
char *e = (char*)endofname(top_of_stack->var_name);
485
math_state->setvar(top_of_stack->var_name, buf);
488
/* VAR++ or VAR--? */
489
if (PREC(op) == PREC_POST) {
490
/* Do not store new value to stack (keep old value) */
448
math_state->setvar(top_of_stack->var, buf);
449
/* After saving, make previous value for v++ or v-- */
450
if (op == TOK_POST_INC)
452
if (op == TOK_POST_DEC)
495
456
top_of_stack->val = rez;
497
457
/* Erase var name, it is just a number now */
498
top_of_stack->var_name = NULL;
458
top_of_stack->var = NULL;
501
461
return "arithmetic syntax error";
505
465
/* longest must be first */
519
479
'*','=', 0, TOK_MUL_ASSIGN,
520
480
'/','=', 0, TOK_DIV_ASSIGN,
521
481
'%','=', 0, TOK_REM_ASSIGN,
522
'+','=', 0, TOK_ADD_ASSIGN,
523
'-','=', 0, TOK_SUB_ASSIGN,
482
'+','=', 0, TOK_PLUS_ASSIGN,
483
'-','=', 0, TOK_MINUS_ASSIGN,
524
484
'-','-', 0, TOK_POST_DEC,
525
485
'^','=', 0, TOK_XOR_ASSIGN,
526
486
'+','+', 0, TOK_POST_INC,
545
506
'(', 0, TOK_LPAREN,
548
#define END_POINTER (&op_tokens[sizeof(op_tokens)-1])
509
#define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7])
550
511
#if ENABLE_FEATURE_SH_MATH_BASE
551
static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base)
512
static arith_t strto_arith_t(const char *nptr, char **endptr)
554
const char *start = nptr;
517
# if ENABLE_FEATURE_SH_MATH_64
518
n = strtoull(nptr, endptr, 0);
520
n = strtoul(nptr, endptr, 0);
523
|| (*nptr < '1' || *nptr > '9')
529
/* It's "N#nnnn" or "NN#nnnn" syntax, NN can't start with 0,
530
* NN is in 2..64 range.
557
536
unsigned digit = (unsigned)*nptr - '0';
558
537
if (digit >= 10 /* not 0..9 */
559
&& digit <= 'z' - '0' /* reject e.g. $((64#~)) */
538
&& digit <= 'z' - '0' /* needed to reject e.g. $((64#~)) */
561
/* current char is one of :;<=>?@A..Z[\]^_`a..z */
563
/* in bases up to 36, case does not matter for a-z,
564
* map @A..Z and `a..z to 9..35: */
540
/* in bases up to 36, case does not matter for a-z */
565
541
digit = (unsigned)(*nptr | 0x20) - ('a' - 10);
566
542
if (base > 36 && *nptr <= '_') {
567
/* base > 36: A-Z,@,_ are 36-61,62,63 */
543
/* otherwise, A-Z,@,_ are 36-61,62,63 */
568
544
if (*nptr == '_')
570
546
else if (*nptr == '@')
584
560
n = n * base + digit;
563
/* Note: we do not set errno on bad chars, we just set a pointer
564
* to the first invalid char. For example, this allows
565
* "N#" (empty "nnnn" part): 64#+1 is a valid expression,
566
* it means 64# + 1, whereas 64#~... is not, since ~ is not a valid
587
569
*endptr = (char*)nptr;
588
/* "64#" and "64#+1" used to be valid expressions, but bash 5.2.15
589
* no longer allow such, detect this:
591
// NB: bash allows $((0x)), this is probably a bug...
593
*endptr = NULL; /* there weren't any digits, bad */
597
static arith_t strto_arith_t(const char *nptr, char **endptr)
599
/* NB: we do not use strtoull here to be bash-compatible:
600
* $((99999999999999999999)) is 7766279631452241919
601
* (the 64-bit truncated value).
605
/* nptr[0] is '0'..'9' here */
607
base = nptr[0] - '0';
608
if (base == 0) { /* nptr[0] is '0' */
610
if ((nptr[1] | 0x20) == 'x') {
614
// NB: bash allows $((0x)), this is probably a bug...
615
return parse_with_base(nptr, endptr, base);
618
/* base is 1..9 here */
620
if (nptr[1] == '#') {
622
return parse_with_base(nptr + 2, endptr, base);
623
/* else: "1#NN", bash says "invalid arithmetic base" */
626
if (isdigit(nptr[1]) && nptr[2] == '#') {
627
base = 10 * base + (nptr[1] - '0');
628
/* base is at least 10 here */
630
return parse_with_base(nptr + 3, endptr, base);
631
/* else: bash says "invalid arithmetic base" */
634
return parse_with_base(nptr, endptr, 10);
636
572
#else /* !ENABLE_FEATURE_SH_MATH_BASE */
637
573
# if ENABLE_FEATURE_SH_MATH_64
638
574
# define strto_arith_t(nptr, endptr) strtoull(nptr, endptr, 0)
645
581
evaluate_string(arith_state_t *math_state, const char *expr)
647
/* Stack of integers/names */
648
var_or_num_t *numstack, *numstackptr;
649
/* Stack of operator tokens */
650
operator *opstack, *opstackptr;
651
/* To detect whether we are after a "value": */
652
583
operator lasttok;
653
/* To insert implicit () in ?: ternary op: */
654
operator insert_op = 0xff;
655
unsigned ternary_level = 0;
656
584
const char *errmsg;
657
585
const char *start_expr = expr = skip_whitespace(expr);
660
unsigned expr_len = strlen(expr);
661
/* If LOTS of whitespace, do not blow up the estimation */
662
const char *p = expr;
664
/* in a run of whitespace, count only 1st char */
666
while (p++, isspace(*p))
672
dbg("expr:'%s' expr_len:%u", expr, expr_len);
673
/* expr_len deep opstack is needed. Think "------------7".
674
* Only "?" operator temporarily needs two opstack slots
675
* (IOW: more than one slot), but its second slot (LPAREN)
676
* is popped off when ":" is reached.
678
expr_len++; /* +1 for 1st LPAREN. See what $((1?)) pushes to opstack */
679
opstackptr = opstack = alloca(expr_len * sizeof(opstack[0]));
680
/* There can be no more than (expr_len/2 + 1)
681
* integers/names in any given correct or incorrect expression.
682
* (modulo "09", "0v" cases where 2 chars are 2 ints/names,
683
* but we have code to detect that early)
685
expr_len = (expr_len / 2)
686
+ 1 /* "1+2" has two nums, 2 = len/2+1, NOT len/2 */;
687
numstackptr = numstack = alloca(expr_len * sizeof(numstack[0]));
586
unsigned expr_len = strlen(expr) + 2;
587
/* Stack of integers */
588
/* The proof that there can be no more than strlen(startbuf)/2+1
589
* integers in any given correct or incorrect expression
590
* is left as an exercise to the reader. */
591
var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0]));
592
var_or_num_t *numstackptr = numstack;
593
/* Stack of operator tokens */
594
operator *const stack = alloca(expr_len * sizeof(stack[0]));
595
operator *stackptr = stack;
690
597
/* Start with a left paren */
691
dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack));
692
*opstackptr++ = lasttok = TOK_LPAREN;
598
*stackptr++ = lasttok = TOK_LPAREN;
708
616
* are to be applied in order. At the end, there should be a final
709
617
* result on the integer stack */
711
if (expr != END_POINTER) {
619
if (expr != ptr_to_rparen + 1) {
712
620
/* If we haven't done so already,
713
621
* append a closing right paren
714
622
* and let the loop process it */
623
expr = ptr_to_rparen;
624
//bb_error_msg("expr=')'");
719
627
/* At this point, we're done with the expression */
720
628
if (numstackptr != numstack + 1) {
721
/* if there is not exactly one result, it's bad */
722
/* Example: $((1 2)) */
629
/* ...but if there isn't, it's bad */
725
return numstack->val;
728
635
p = endofname(expr);
731
if (!math_state->evaluation_disabled) {
732
numstackptr->var_name = expr;
733
dbg("[%d] var:'%.*s'", (int)(numstackptr - numstack), (int)(p - expr), expr);
734
expr = skip_whitespace(p);
735
/* If it is not followed by "=" operator... */
736
if (expr[0] != '=' /* not "=..." */
737
|| expr[1] == '=' /* or "==..." */
739
/* Evaluate variable to value */
740
arith_t val = arith_lookup_val(math_state, numstackptr->var_name, (char*)p);
741
if (math_state->errmsg)
743
numstackptr->val = val;
746
dbg("[%d] var:IGNORED", (int)(numstackptr - numstack));
748
numstackptr->var_name = NULL; /* not needed, paranoia */
749
numstackptr->val = 0; /* not needed, paranoia */
638
size_t var_name_size = (p - expr) + 1; /* +1 for NUL */
639
numstackptr->var = alloca(var_name_size);
640
safe_strncpy(numstackptr->var, expr, var_name_size);
641
//bb_error_msg("var:'%s'", numstackptr->var);
644
numstackptr->second_val_present = 0;
757
650
if (isdigit(*expr)) {
760
numstackptr->var_name = NULL;
761
/* code is smaller compared to using &expr here: */
762
numstackptr->val = strto_arith_t(expr, &end);
764
dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val);
765
if (!expr) /* example: $((10#)) */
767
/* A number can't be followed by another number, or a variable name.
768
* We'd catch this later anyway, but this would require numstack[]
769
* to be ~twice as deep to handle strings where _every_ char is
770
* a new number or name.
771
* Examples: "09" is two numbers, "0v" is number and name.
773
if (isalnum(*expr) || *expr == '_')
652
numstackptr->var = NULL;
654
numstackptr->val = strto_arith_t(expr, (char**) &expr);
655
//bb_error_msg("val:%lld", numstackptr->val);
657
numstackptr->val = 0; /* bash compat */
778
661
/* Should be an operator */
822
704
if (*p == '\0') {
823
705
/* No next element, operator not found */
824
706
//math_state->syntax_error_at = expr;
828
/* NB: expr now points past the operator */
830
711
op = p[1]; /* fetch TOK_foo value */
832
/* Special rule for "? EXPR :"
833
* "EXPR in the middle of ? : is parsed as if parenthesized"
834
* (this quirk originates in C grammar, I think).
836
if (op == TOK_CONDITIONAL) {
837
insert_op = TOK_LPAREN;
838
dbg("insert_op=%02x", insert_op);
840
if (op == TOK_CONDITIONAL_SEP) {
843
dbg("insert_op=%02x op=%02x", insert_op, op);
846
/* NAME++ is a "value" (something suitable for a binop) */
847
if (PREC(lasttok) == PREC_POST)
713
/* NB: expr now points past the operator */
715
/* post grammar: a++ reduce to num */
716
if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
850
719
/* Plus and minus are binary (not unary) _only_ if the last
851
* token was a "value". Think about it. It makes sense.
853
if (lasttok != TOK_VALUE) {
720
* token was a number, or a right paren (which pretends to be
721
* a number, since it evaluates to one). Think about it.
723
if (lasttok != TOK_NUM) {
858
/* Unary plus does nothing, do not even push it to opstack */
876
744
* stack until we find an operator with a lesser priority than the
877
745
* one we have just extracted. If op is right-associative,
878
746
* then stop "applying" on the equal priority too.
879
* Left paren will never be "applied" in this way.
747
* Left paren is given the lowest priority so it will never be
748
* "applied" in this way.
882
if (prec != PREC_LPAREN && prec < UNARYPREC) {
883
/* Binary, ternary or RPAREN */
884
if (lasttok != TOK_VALUE) {
885
/* Must be preceded by a value.
886
* $((2 2 + * 3)) would be accepted without this.
751
//bb_error_msg("prec:%02x", prec);
752
if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
753
/* not left paren or unary */
754
if (lasttok != TOK_NUM) {
755
/* binary op must be preceded by a num */
891
* while opstack is not empty:
893
* if prev_op is LPAREN (finished evaluating (EXPR)):
895
* evaluate prev_op on top of numstack
896
* BUG (unpaired RPAREN)
897
* else (op is not RPAREN):
898
* while opstack is not empty:
900
* if can't evaluate prev_op (it is lower precedence than op):
903
* evaluate prev_op on top of numstack
904
* C:if op is "?": check result, set disable flag if needed
906
* N:loop to parse the rest of string
908
while (opstackptr != opstack) {
909
operator prev_op = *--opstackptr;
758
/* The algorithm employed here is simple: while we don't
759
* hit an open paren nor the bottom of the stack, pop
760
* tokens and apply them */
761
while (stackptr != stack) {
762
operator prev_op = *--stackptr;
910
763
if (op == TOK_RPAREN) {
764
//bb_error_msg("op == TOK_RPAREN");
911
765
if (prev_op == TOK_LPAREN) {
912
/* Erase var name: for example, (VAR) = 1 is not valid */
913
numstackptr[-1].var_name = NULL;
914
/* (EXPR) is a "value": next operator directly after
915
* close paren should be considered binary
766
//bb_error_msg("prev_op == TOK_LPAREN");
767
//bb_error_msg(" %p %p numstackptr[-1].var:'%s'", numstack, numstackptr-1, numstackptr[-1].var);
768
if (numstackptr[-1].var) {
769
/* Expression is (var), lookup now */
770
errmsg = arith_lookup_val(math_state, &numstackptr[-1]);
772
goto err_with_custom_msg;
773
/* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */
774
numstackptr[-1].var = NULL;
776
/* Any operator directly after a
777
* close paren should consider itself binary */
920
/* Not (y), but ...x~y). Fall through to evaluate x~y */
781
//bb_error_msg("prev_op != TOK_LPAREN");
922
783
operator prev_prec = PREC(prev_op);
784
//bb_error_msg("op != TOK_RPAREN");
923
785
fix_assignment_prec(prec);
924
786
fix_assignment_prec(prev_prec);
925
787
if (prev_prec < prec
926
788
|| (prev_prec == prec && is_right_associative(prec))
928
/* ...x~y@. push @ on opstack */
929
opstackptr++; /* undo removal of ~ op */
932
/* else: ...x~y@. Evaluate x~y, replace it on stack with result. Then repeat */
934
dbg("arith_apply(prev_op:%02x, numstack:%d)", prev_op, (int)(numstackptr - numstack));
794
//bb_error_msg("arith_apply(prev_op:%02x)", prev_op);
935
795
errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr);
937
797
goto err_with_custom_msg;
938
dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[-1].val, numstackptr[-1].var_name);
939
if (prev_op == TOK_CONDITIONAL_SEP) {
940
/* We just executed ":" */
941
/* Remove "?" from opstack too, not just ":" */
943
if (*opstackptr != TOK_CONDITIONAL) {
944
/* Example: $((1,2:3)) */
945
errmsg = "malformed ?: operator";
946
goto err_with_custom_msg;
948
/* Example: a=1?2:3,a. We just executed ":".
949
* Prevent assignment from being still disabled.
951
if (ternary_level == math_state->evaluation_disabled) {
952
math_state->evaluation_disabled = 0;
953
dbg("':' executed: evaluation_disabled=CLEAR");
957
} /* while (opstack not empty) */
959
if (op == TOK_RPAREN) /* unpaired RPAREN? */
962
if (op == TOK_CONDITIONAL) {
963
/* We just now evaluated EXPR before "?".
964
* Should we disable evaluation now?
967
if (numstackptr[-1].val == 0 && !math_state->evaluation_disabled) {
968
math_state->evaluation_disabled = ternary_level;
969
dbg("'?' entered: evaluation_disabled=%u", math_state->evaluation_disabled);
973
/* else: LPAREN or UNARY: push it on opstack */
975
/* Push this operator to opstack */
976
dbg("(%d) op:%02x insert_op:%02x", (int)(opstackptr - opstack), op, insert_op);
977
*opstackptr++ = lasttok = op;
979
if (insert_op != 0xff) {
982
dbg("inserting %02x", op);
983
if (op == TOK_CONDITIONAL_SEP) {
984
/* The next token is ":". Toggle "do not evaluate" state */
985
if (!math_state->evaluation_disabled) {
986
math_state->evaluation_disabled = ternary_level;
987
dbg("':' entered: evaluation_disabled=%u", math_state->evaluation_disabled);
988
} else if (ternary_level == math_state->evaluation_disabled) {
989
math_state->evaluation_disabled = 0;
990
dbg("':' entered: evaluation_disabled=CLEAR");
991
} /* else: ternary_level > evaluation_disabled && evaluation_disabled != 0 */
992
/* We are in nested "?:" while in outer "?:" disabled branch */
799
if (op == TOK_RPAREN)
803
/* Push this operator to the stack and remember it */
804
//bb_error_msg("push op:%02x", op);
805
*stackptr++ = lasttok = op;
997
807
} /* while (1) */
1000
810
errmsg = "arithmetic syntax error";
1001
811
err_with_custom_msg:
1002
814
math_state->errmsg = errmsg;
815
return numstack->val;
1006
818
arith_t FAST_FUNC
1007
819
arith(arith_state_t *math_state, const char *expr)
1009
math_state->evaluation_disabled = 0;
1010
821
math_state->errmsg = NULL;
1011
822
math_state->list_of_recursed_names = NULL;
1012
823
return evaluate_string(math_state, expr);