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);
#if ENABLE_BC
-// This is an array that corresponds to token types. An entry is
+// This is a bit array that corresponds to token types. An entry is
// true if the token is valid in an expression, false otherwise.
-static const bool bc_parse_exprs[] = {
- false, false, true, true, true, true, true, true, true, true, true, true,
- true, true, true, true, true, true, true, true, true, true, true, true,
- true, true, true, false, false, true, true, false, false, false, false,
- false, false, false, true, true, false, false, false, false, false, false,
- false, true, false, true, true, true, true, false, false, true, false, true,
- true, false,
+enum {
+ BC_PARSE_EXPRS_BITS = 0
+ + ((uint64_t)((0 << 0)+(0 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (0*8))
+ + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (1*8))
+ + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(1 << 5)+(1 << 6)+(1 << 7)) << (2*8))
+ + ((uint64_t)((1 << 0)+(1 << 1)+(1 << 2)+(0 << 3)+(0 << 4)+(1 << 5)+(1 << 6)+(0 << 7)) << (3*8))
+ + ((uint64_t)((0 << 0)+(0 << 1)+(0 << 2)+(0 << 3)+(0 << 4)+(0 << 5)+(1 << 6)+(1 << 7)) << (4*8))
+ + ((uint64_t)((0 << 0)+(0 << 1)+(0 << 2)+(0 << 3)+(0 << 4)+(0 << 5)+(0 << 6)+(1 << 7)) << (5*8))
+ + ((uint64_t)((0 << 0)+(1 << 1)+(1 << 2)+(1 << 3)+(1 << 4)+(0 << 5)+(0 << 6)+(1 << 7)) << (6*8))
+ + ((uint64_t)((0 << 0)+(1 << 1)+(1 << 2)+(0 << 3) ) << (7*8))
};
+static ALWAYS_INLINE long bc_parse_exprs(unsigned i)
+{
+#if ULONG_MAX > 0xffffffff
+ // 64-bit version (will not work correctly for 32-bit longs!)
+ return BC_PARSE_EXPRS_BITS & (1UL << i);
+#else
+ // 32-bit version
+ unsigned long m = (uint32_t)BC_PARSE_EXPRS_BITS;
+ if (i >= 32) {
+ m = (uint32_t)(BC_PARSE_EXPRS_BITS >> 32);
+ i &= 31;
+ }
+ return m & (1UL << i);
+#endif
+}
// This is an array of data for operators that correspond to token types.
static const uint8_t bc_parse_ops[] = {
#define OP(p,l) ((int)(l) * 0x10 + (p))
- OP(0, false), OP( 0, false ),
- OP(1, false),
+ OP(0, false), OP( 0, false ), // inc dec
+ OP(1, false), // neg
OP(2, false),
- OP(3, true ), OP( 3, true ), OP( 3, true ),
- OP(4, true ), OP( 4, true ),
- OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ),
- OP(1, false),
- OP(7, true ), OP( 7, true ),
- OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ),
- OP(5, false), OP( 5, false ),
+ OP(3, true ), OP( 3, true ), OP( 3, true ), // pow mul div
+ OP(4, true ), OP( 4, true ), // mod + -
+ OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < >
+ OP(1, false), // not
+ OP(7, true ), OP( 7, true ), // or and
+ OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), // ^= *= /= %= +=
+ OP(5, false), OP( 5, false ), // -= =
#undef OP
};
#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)
paren_expr = rprn = done = get_token = assign = false;
bin_last = true;
- for (; !G_interrupt && !s && !done && bc_parse_exprs[t]; t = p->l.t.t) {
+ for (; !G_interrupt && !s && !done && bc_parse_exprs(t); t = p->l.t.t) {
switch (t) {
case BC_LEX_OP_INC: