aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-07 12:57:32 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-07 12:57:32 +0100
commit18c6b54f820923549135724fee6cf66c26929b07 (patch)
tree60030a7234fd7e5d6eed7e1093a263bfe1c55e09
parentb9c321d6d94fc8bbae5fe657e141cbd9f2397037 (diff)
downloadbusybox-w32-18c6b54f820923549135724fee6cf66c26929b07.tar.gz
busybox-w32-18c6b54f820923549135724fee6cf66c26929b07.tar.bz2
busybox-w32-18c6b54f820923549135724fee6cf66c26929b07.zip
bc: use more compact parsing data structures
function old new delta dc_lex_token 697 701 +4 bc_parse_next_rel 20 - -20 bc_parse_next_read 20 - -20 bc_parse_next_print 20 - -20 bc_parse_next_param 20 - -20 bc_parse_next_for 20 - -20 bc_parse_next_expr 20 - -20 bc_parse_next_elem 20 - -20 common_parse_expr 62 40 -22 bc_parse_expr 49 24 -25 dc_lex_regs 52 13 -39 bc_parse_name 581 539 -42 bc_parse_expr_empty_ok 2157 2108 -49 dc_parse_insts 332 83 -249 dc_lex_tokens 364 91 -273 bc_parse_stmt 2261 1868 -393 ------------------------------------------------------------------------------ (add/remove: 0/7 grow/shrink: 1/8 up/down: 4/-1232) Total: -1228 bytes text data bss dec hex filename 987037 485 7296 994818 f2e02 busybox_old 985814 485 7296 993595 f293b busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/bc.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 0330c43e5..685427e58 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -632,11 +632,6 @@ typedef struct BcLex {
632 BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER | BC_PARSE_FLAG_IF | \ 632 BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER | BC_PARSE_FLAG_IF | \
633 BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_IF_END))) 633 BC_PARSE_FLAG_ELSE | BC_PARSE_FLAG_IF_END)))
634 634
635typedef struct BcParseNext {
636 uint32_t len;
637 BcLexType tokens[4];
638} BcParseNext;
639
640struct BcParse; 635struct BcParse;
641 636
642struct BcProgram; 637struct BcProgram;
@@ -834,34 +829,40 @@ static const uint8_t bc_parse_ops[] = {
834#define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f) 829#define bc_parse_op_PREC(i) (bc_parse_ops[i] & 0x0f)
835#define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10) 830#define bc_parse_op_LEFT(i) (bc_parse_ops[i] & 0x10)
836 831
832// Byte array of up to 4 BC_LEX's, packed into 32-bit word
833typedef uint32_t BcParseNext;
834
837// These identify what tokens can come after expressions in certain cases. 835// These identify what tokens can come after expressions in certain cases.
838#define BC_PARSE_NEXT_TOKENS(...) .tokens = { __VA_ARGS__ } 836enum {
839#define BC_PARSE_NEXT(a, ...) \ 837#define BC_PARSE_NEXT4(a,b,c,d) ( (a) | ((b)<<8) | ((c)<<16) | ((((d)|0x80)<<24)) )
840 { \ 838#define BC_PARSE_NEXT2(a,b) BC_PARSE_NEXT4(a,b,0xff,0xff)
841 .len = (a), BC_PARSE_NEXT_TOKENS(__VA_ARGS__) \ 839#define BC_PARSE_NEXT1(a) BC_PARSE_NEXT4(a,0xff,0xff,0xff)
842 } 840 bc_parse_next_expr = BC_PARSE_NEXT4(BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF),
843static const BcParseNext bc_parse_next_expr = 841 bc_parse_next_param = BC_PARSE_NEXT2(BC_LEX_RPAREN, BC_LEX_COMMA),
844 BC_PARSE_NEXT(4, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_RBRACE, BC_LEX_EOF); 842 bc_parse_next_print = BC_PARSE_NEXT4(BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF),
845static const BcParseNext bc_parse_next_param = 843 bc_parse_next_rel = BC_PARSE_NEXT1(BC_LEX_RPAREN),
846 BC_PARSE_NEXT(2, BC_LEX_RPAREN, BC_LEX_COMMA); 844 bc_parse_next_elem = BC_PARSE_NEXT1(BC_LEX_RBRACKET),
847static const BcParseNext bc_parse_next_print = 845 bc_parse_next_for = BC_PARSE_NEXT1(BC_LEX_SCOLON),
848 BC_PARSE_NEXT(4, BC_LEX_COMMA, BC_LEX_NLINE, BC_LEX_SCOLON, BC_LEX_EOF); 846 bc_parse_next_read = BC_PARSE_NEXT2(BC_LEX_NLINE, BC_LEX_EOF),
849static const BcParseNext bc_parse_next_rel = BC_PARSE_NEXT(1, BC_LEX_RPAREN); 847#undef BC_PARSE_NEXT4
850static const BcParseNext bc_parse_next_elem = BC_PARSE_NEXT(1, BC_LEX_RBRACKET); 848#undef BC_PARSE_NEXT2
851static const BcParseNext bc_parse_next_for = BC_PARSE_NEXT(1, BC_LEX_SCOLON); 849#undef BC_PARSE_NEXT1
852static const BcParseNext bc_parse_next_read = 850};
853 BC_PARSE_NEXT(2, BC_LEX_NLINE, BC_LEX_EOF);
854#endif // ENABLE_BC 851#endif // ENABLE_BC
855 852
856#if ENABLE_DC 853#if ENABLE_DC
857static const BcLexType dc_lex_regs[] = { 854static const //BcLexType - should be this type, but narrower type saves size:
855uint8_t
856dc_lex_regs[] = {
858 BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE, 857 BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE,
859 BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON, 858 BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON,
860 BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN, 859 BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN,
861 BC_LEX_STORE_PUSH, 860 BC_LEX_STORE_PUSH,
862}; 861};
863 862
864static const BcLexType dc_lex_tokens[] = { 863static const //BcLexType - should be this type
864uint8_t
865dc_lex_tokens[] = {
865 BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN, 866 BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN,
866 BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID, 867 BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID,
867 BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE, 868 BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE,
@@ -889,7 +890,9 @@ static const BcLexType dc_lex_tokens[] = {
889 BC_LEX_INVALID 890 BC_LEX_INVALID
890}; 891};
891 892
892static const BcInst dc_parse_insts[] = { 893static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1
894int8_t
895dc_parse_insts[] = {
893 BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE, 896 BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID, BC_INST_REL_GE,
894 BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE, 897 BC_INST_INVALID, BC_INST_POWER, BC_INST_MULTIPLY, BC_INST_DIVIDE,
895 BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS, 898 BC_INST_MODULUS, BC_INST_PLUS, BC_INST_MINUS,
@@ -4768,7 +4771,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne
4768 BcInst prev = BC_INST_PRINT; 4771 BcInst prev = BC_INST_PRINT;
4769 BcLexType top, t = p->l.t.t; 4772 BcLexType top, t = p->l.t.t;
4770 size_t nexprs = 0, ops_bgn = p->ops.len; 4773 size_t nexprs = 0, ops_bgn = p->ops.len;
4771 uint32_t i, nparens, nrelops; 4774 unsigned nparens, nrelops;
4772 bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last; 4775 bool paren_first, paren_expr, rprn, done, get_token, assign, bin_last;
4773 4776
4774 paren_first = p->l.t.t == BC_LEX_LPAREN; 4777 paren_first = p->l.t.t == BC_LEX_LPAREN;
@@ -4993,9 +4996,14 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne
4993 if (prev == BC_INST_BOOL_NOT || nexprs != 1) 4996 if (prev == BC_INST_BOOL_NOT || nexprs != 1)
4994 return bc_error_bad_expression(); 4997 return bc_error_bad_expression();
4995 4998
4996 for (i = 0; i < next.len; ++i) 4999 // next is BcParseNext, byte array of up to 4 BC_LEX's, packed into 32-bit word
4997 if (t == next.tokens[i]) 5000 for (;;) {
5001 if (t == (next & 0x7f))
4998 goto ok; 5002 goto ok;
5003 if (next & 0x80) // last element?
5004 break;
5005 next >>= 8;
5006 }
4999 return bc_error_bad_expression(); 5007 return bc_error_bad_expression();
5000 ok: 5008 ok:
5001 5009