aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miscutils/bc.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 9a3bc2743..fbe671fd3 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -805,30 +805,48 @@ static void bc_vm_info(void);
805 805
806#if ENABLE_BC 806#if ENABLE_BC
807 807
808// This is an array that corresponds to token types. An entry is 808// This is a bit array that corresponds to token types. An entry is
809// true if the token is valid in an expression, false otherwise. 809// true if the token is valid in an expression, false otherwise.
810static const bool bc_parse_exprs[] = { 810enum {
811 false, false, true, true, true, true, true, true, true, true, true, true, 811 BC_PARSE_EXPRS_BITS = 0
812 true, true, true, true, true, true, true, true, true, true, true, true, 812 + ((uint64_t)((0 << 0)+(0 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (0*8))
813 true, true, true, false, false, true, true, false, false, false, false, 813 + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (1*8))
814 false, false, false, true, true, false, false, false, false, false, false, 814 + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (2*8))
815 false, true, false, true, true, true, true, false, false, true, false, true, 815 + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(0 << 3)+(0 << 4)+(1 << 5)+(1 << 6)+(0 << 7)) << (3*8))
816 true, false, 816 + ((uint64_t)((0 << 0)+(0 << 1)+(0 << 2)+(0 << 3)+(0 << 4)+(0 << 5)+(1 << 6)+(1 << 7)) << (4*8))
817 + ((uint64_t)((0 << 0)+(0 << 1)+(0 << 2)+(0 << 3)+(0 << 4)+(0 << 5)+(0 << 6)+(1 << 7)) << (5*8))
818 + ((uint64_t)((0 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(0 << 5)+(0 << 6)+(1 << 7)) << (6*8))
819 + ((uint64_t)((0 << 0)+(1 << 1)+(1 << 2)+(0 << 3) ) << (7*8))
817}; 820};
821static ALWAYS_INLINE long bc_parse_exprs(unsigned i)
822{
823#if ULONG_MAX > 0xffffffff
824 // 64-bit version (will not work correctly for 32-bit longs!)
825 return BC_PARSE_EXPRS_BITS & (1UL << i);
826#else
827 // 32-bit version
828 unsigned long m = (uint32_t)BC_PARSE_EXPRS_BITS;
829 if (i >= 32) {
830 m = (uint32_t)(BC_PARSE_EXPRS_BITS >> 32);
831 i &= 31;
832 }
833 return m & (1UL << i);
834#endif
835}
818 836
819// This is an array of data for operators that correspond to token types. 837// This is an array of data for operators that correspond to token types.
820static const uint8_t bc_parse_ops[] = { 838static const uint8_t bc_parse_ops[] = {
821#define OP(p,l) ((int)(l) * 0x10 + (p)) 839#define OP(p,l) ((int)(l) * 0x10 + (p))
822 OP(0, false), OP( 0, false ), 840 OP(0, false), OP( 0, false ), // inc dec
823 OP(1, false), 841 OP(1, false), // neg
824 OP(2, false), 842 OP(2, false),
825 OP(3, true ), OP( 3, true ), OP( 3, true ), 843 OP(3, true ), OP( 3, true ), OP( 3, true ), // pow mul div
826 OP(4, true ), OP( 4, true ), 844 OP(4, true ), OP( 4, true ), // mod + -
827 OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), 845 OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < >
828 OP(1, false), 846 OP(1, false), // not
829 OP(7, true ), OP( 7, true ), 847 OP(7, true ), OP( 7, true ), // or and
830 OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), 848 OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), // ^= *= /= %= +=
831 OP(5, false), OP( 5, false ), 849 OP(5, false), OP( 5, false ), // -= =
832#undef OP 850#undef OP
833}; 851};
834#define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) 852#define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f)
@@ -4708,7 +4726,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next)
4708 paren_expr = rprn = done = get_token = assign = false; 4726 paren_expr = rprn = done = get_token = assign = false;
4709 bin_last = true; 4727 bin_last = true;
4710 4728
4711 for (; !G_interrupt && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) { 4729 for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.t.t) {
4712 switch (t) { 4730 switch (t) {
4713 4731
4714 case BC_LEX_OP_INC: 4732 case BC_LEX_OP_INC: