aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-06-17 22:43:46 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2023-06-18 18:12:04 +0200
commit182e5a4d000cdb5808830b1f02c59d40c6e61150 (patch)
tree6324aa78cac5689e66f31f2576b97a9edbeb38aa
parent96769486e20fd5f1142cae0db2cbacef31dc75e9 (diff)
downloadbusybox-w32-182e5a4d000cdb5808830b1f02c59d40c6e61150.tar.gz
busybox-w32-182e5a4d000cdb5808830b1f02c59d40c6e61150.tar.bz2
busybox-w32-182e5a4d000cdb5808830b1f02c59d40c6e61150.zip
shell/math: decrease stack usage
function old new delta evaluate_string 1412 1467 +55 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/math.c62
1 files changed, 27 insertions, 35 deletions
diff --git a/shell/math.c b/shell/math.c
index 4b56d1397..f6fed805c 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -579,48 +579,40 @@ static arith_t strto_arith_t(const char *nptr, char **endptr)
579# endif 579# endif
580#endif 580#endif
581 581
582//TODO: much better estimation than expr_len/2? Such as:
583//static unsigned estimate_nums_and_names(const char *expr)
584//{
585// unsigned count = 0;
586// while (*(expr = skip_whitespace(expr)) != '\0') {
587// const char *p;
588// if (isdigit(*expr)) {
589// while (isdigit(*++expr))
590// continue;
591// count++;
592// continue;
593// }
594// p = endofname(expr);
595// if (p != expr) {
596// expr = p;
597// count++;
598// continue;
599// }
600// }
601// return count;
602//}
603
604static arith_t 582static arith_t
605evaluate_string(arith_state_t *math_state, const char *expr) 583evaluate_string(arith_state_t *math_state, const char *expr)
606{ 584{
607 operator lasttok;
608 const char *errmsg = NULL;
609 const char *start_expr = expr = skip_whitespace(expr);
610 unsigned expr_len = strlen(expr) + 2;
611 /* Stack of integers/names */ 585 /* Stack of integers/names */
612 /* There can be no more than strlen(startbuf)/2+1 586 var_or_num_t *numstack, *numstackptr;
613 * integers/names in any given correct or incorrect expression.
614 * (modulo "09v09v09v09v09v" case,
615 * but we have code to detect that early)
616 */
617 var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0]));
618 var_or_num_t *numstackptr = numstack;
619 /* Stack of operator tokens */ 587 /* Stack of operator tokens */
620 operator *const opstack = alloca(expr_len * sizeof(opstack[0])); 588 operator *opstack, *opstackptr;
621 operator *opstackptr = opstack; 589 operator lasttok;
622 operator insert_op = 0xff; 590 operator insert_op = 0xff;
623 unsigned ternary_level = 0; 591 unsigned ternary_level = 0;
592 const char *errmsg;
593 const char *start_expr = expr = skip_whitespace(expr);
594
595 {
596 unsigned expr_len = strlen(expr) + 2;
597 /* If LOTS of whitespace, do not blow up the estimation */
598 const char *p = expr;
599 while (*p) {
600 /* in a run of whitespace, count only 1st char */
601 if (isspace(*p)) {
602 while (p++, isspace(*p))
603 expr_len--;
604 } else {
605 p++;
606 }
607 }
608 /* There can be no more than expr_len/2
609 * integers/names in any given correct or incorrect expression.
610 * (modulo "09v09v09v09v09v" case,
611 * but we have code to detect that early)
612 */
613 numstackptr = numstack = alloca((expr_len / 2) * sizeof(numstack[0]));
614 opstackptr = opstack = alloca(expr_len * sizeof(opstack[0]));
615 }
624 616
625 /* Start with a left paren */ 617 /* Start with a left paren */
626 dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); 618 dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack));