aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-06-15 16:46:31 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2023-06-15 16:46:31 +0200
commit38f423cc9c6419f86e8ab602f195a9035a879001 (patch)
tree56dff563b158a58bc9c4280212114c954ed541ee
parentea6dcbe2839fb21049baadd0d5da903ae11661ec (diff)
downloadbusybox-w32-38f423cc9c6419f86e8ab602f195a9035a879001.tar.gz
busybox-w32-38f423cc9c6419f86e8ab602f195a9035a879001.tar.bz2
busybox-w32-38f423cc9c6419f86e8ab602f195a9035a879001.zip
shell/math: explain the logic, small tweak to make code smaller
function old new delta evaluate_string 1258 1257 -1 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/math.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/shell/math.c b/shell/math.c
index 7e2bf5ea5..4623c979e 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -133,7 +133,10 @@ typedef unsigned char operator;
133#define tok_decl(prec,id) (((id)<<5) | (prec)) 133#define tok_decl(prec,id) (((id)<<5) | (prec))
134#define PREC(op) ((op) & 0x1F) 134#define PREC(op) ((op) & 0x1F)
135 135
136#define PREC_LPAREN 0
136#define TOK_LPAREN tok_decl(0,0) 137#define TOK_LPAREN tok_decl(0,0)
138/* Precedence value of RPAREN is used only to distinguish it from LPAREN */
139#define TOK_RPAREN tok_decl(1,1)
137 140
138#define TOK_COMMA tok_decl(1,0) 141#define TOK_COMMA tok_decl(1,0)
139 142
@@ -223,7 +226,6 @@ typedef unsigned char operator;
223#define SPEC_PREC (UNARYPREC+4) 226#define SPEC_PREC (UNARYPREC+4)
224 227
225#define TOK_NUM tok_decl(SPEC_PREC, 0) 228#define TOK_NUM tok_decl(SPEC_PREC, 0)
226#define TOK_RPAREN tok_decl(SPEC_PREC, 1)
227 229
228static int 230static int
229is_assign_op(operator op) 231is_assign_op(operator op)
@@ -789,19 +791,32 @@ evaluate_string(arith_state_t *math_state, const char *expr)
789 * stack until we find an operator with a lesser priority than the 791 * stack until we find an operator with a lesser priority than the
790 * one we have just extracted. If op is right-associative, 792 * one we have just extracted. If op is right-associative,
791 * then stop "applying" on the equal priority too. 793 * then stop "applying" on the equal priority too.
792 * Left paren is given the lowest priority so it will never be 794 * Left paren will never be "applied" in this way.
793 * "applied" in this way.
794 */ 795 */
795 prec = PREC(op); 796 prec = PREC(op);
796 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { 797 if (prec != PREC_LPAREN && prec < UNARYPREC) {
797 /* not left paren or unary */ 798 /* binary, ternary or RPAREN */
798 if (lasttok != TOK_NUM) { 799 if (lasttok != TOK_NUM) {
799 /* binary op must be preceded by a num */ 800 /* must be preceded by a num */
800 goto err; 801 goto err;
801 } 802 }
802 /* The algorithm employed here is simple: while we don't 803 /* if op is RPAREN:
803 * hit an open paren nor the bottom of the stack, pop 804 * while opstack is not empty:
804 * tokens and apply them */ 805 * pop prev_op
806 * if prev_op is LPAREN (finished evaluating (EXPR)):
807 * goto N
808 * evaluate prev_op on top of numstack
809 * BUG (unpaired RPAREN)
810 * else (op is not RPAREN):
811 * while opstack is not empty:
812 * pop prev_op
813 * if can't evaluate prev_op (it is lower precedence than op):
814 * push prev_op back
815 * goto P
816 * evaluate prev_op on top of numstack
817 * P: push op
818 * N: loop to parse the rest of string
819 */
805 while (opstackptr != opstack) { 820 while (opstackptr != opstack) {
806 operator prev_op = *--opstackptr; 821 operator prev_op = *--opstackptr;
807 if (op == TOK_RPAREN) { 822 if (op == TOK_RPAREN) {
@@ -821,7 +836,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
821 if (prev_prec < prec 836 if (prev_prec < prec
822 || (prev_prec == prec && is_right_associative(prec)) 837 || (prev_prec == prec && is_right_associative(prec))
823 ) { 838 ) {
824 /* ...x~y@: push @ on opstack */ 839 /* ...x~y@. push @ on opstack */
825 opstackptr++; /* undo removal of ~ op */ 840 opstackptr++; /* undo removal of ~ op */
826 goto push_op; 841 goto push_op;
827 } 842 }