aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miscutils/bc.c113
1 files changed, 64 insertions, 49 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 1fb1b00b3..214ea44ab 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -806,45 +806,6 @@ enum {
#endif // ENABLE_BC
#if ENABLE_DC
-static const //BcLexType - should be this type, but narrower type saves size:
-uint8_t
-dc_lex_regs[] = {
- BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE,
- BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON,
- BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN,
- BC_LEX_STORE_PUSH,
-};
-
-static const //BcLexType - should be this type
-uint8_t
-dc_lex_tokens[] = {
- BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN,
- BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID,
- BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE,
- BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
- BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
- BC_LEX_INVALID, BC_LEX_INVALID,
- BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ,
- BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID,
- BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
- BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID,
- BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP,
- BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM,
- BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID,
- BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID,
- BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
- BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID,
- BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE,
- BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID,
- BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD,
- BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT,
- BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID,
- BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE,
- BC_LEX_INVALID, BC_LEX_STACK_LEVEL,
- BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD,
- BC_LEX_INVALID
-};
-
static const //BcInst - should be this type. Using signed narrow type since BC_INST_INVALID is -1
int8_t
dc_parse_insts[] = {
@@ -1063,6 +1024,8 @@ static ERRORFUNC int bc_error(const char *msg)
}
static ERRORFUNC int bc_error_bad_character(char c)
{
+ if (!c)
+ IF_ERROR_RETURN_POSSIBLE(return) bc_error("NUL character");
IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("bad character '%c'", c);
}
static ERRORFUNC int bc_error_bad_expression(void)
@@ -1376,7 +1339,7 @@ static void bc_read_line(BcVec *vec, FILE *fp)
goto intr;
}
#endif
- c = fgetc(fp);
+ do c = fgetc(fp); while (c == '\0');
if (c == EOF) {
if (ferror(fp))
bb_perror_msg_and_die("input error");
@@ -3125,11 +3088,11 @@ static BC_STATUS zbc_lex_token(BcLex *l)
// This is the workhorse of the lexer.
switch (c) {
- case '\0': // probably never reached
- l->i--;
- l->t.t = BC_LEX_EOF;
- l->newline = true;
- break;
+// case '\0': // probably never reached
+// l->i--;
+// l->t.t = BC_LEX_EOF;
+// l->newline = true;
+// break;
case '\n':
l->t.t = BC_LEX_NLINE;
l->newline = true;
@@ -3370,6 +3333,58 @@ static BC_STATUS zdc_lex_string(BcLex *l)
static BC_STATUS zdc_lex_token(BcLex *l)
{
+ static const //BcLexType - should be this type, but narrower type saves size:
+ uint8_t
+ dc_lex_regs[] = {
+ BC_LEX_OP_REL_EQ, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_NE,
+ BC_LEX_OP_REL_LT, BC_LEX_OP_REL_GT, BC_LEX_SCOLON, BC_LEX_COLON,
+ BC_LEX_ELSE, BC_LEX_LOAD, BC_LEX_LOAD_POP, BC_LEX_OP_ASSIGN,
+ BC_LEX_STORE_PUSH,
+ };
+ static const //BcLexType - should be this type
+ uint8_t
+ dc_lex_tokens[] = {
+ /* %&'( */
+ BC_LEX_OP_MODULUS, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_LPAREN,
+ /* )*+, */
+ BC_LEX_INVALID, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS, BC_LEX_INVALID,
+ /* -./ */
+ BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE,
+ /* 0123456789 */
+ BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
+ BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
+ BC_LEX_INVALID, BC_LEX_INVALID,
+ /* :;<=>?@ */
+ BC_LEX_COLON, BC_LEX_SCOLON, BC_LEX_OP_REL_GT, BC_LEX_OP_REL_EQ,
+ BC_LEX_OP_REL_LT, BC_LEX_KEY_READ, BC_LEX_INVALID,
+ /* ABCDEFGH */
+ BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
+ BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_EQ_NO_REG, BC_LEX_INVALID,
+ /* IJKLMNOP */
+ BC_LEX_KEY_IBASE, BC_LEX_INVALID, BC_LEX_KEY_SCALE, BC_LEX_LOAD_POP,
+ BC_LEX_INVALID, BC_LEX_OP_BOOL_NOT, BC_LEX_KEY_OBASE, BC_LEX_PRINT_STREAM,
+ /* QRSTUVWXY */
+ BC_LEX_NQUIT, BC_LEX_POP, BC_LEX_STORE_PUSH, BC_LEX_INVALID, BC_LEX_INVALID,
+ BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_SCALE_FACTOR, BC_LEX_INVALID,
+ /* Z[\] */
+ BC_LEX_KEY_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
+ /* ^_` */
+ BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID,
+ /* abcdefgh */
+ BC_LEX_ASCIIFY, BC_LEX_INVALID, BC_LEX_CLEAR_STACK, BC_LEX_DUPLICATE,
+ BC_LEX_ELSE, BC_LEX_PRINT_STACK, BC_LEX_INVALID, BC_LEX_INVALID,
+ /* ijklmnop */
+ BC_LEX_STORE_IBASE, BC_LEX_INVALID, BC_LEX_STORE_SCALE, BC_LEX_LOAD,
+ BC_LEX_INVALID, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KEY_PRINT,
+ /* qrstuvwx */
+ BC_LEX_KEY_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID,
+ BC_LEX_INVALID, BC_LEX_KEY_SQRT, BC_LEX_INVALID, BC_LEX_EXECUTE,
+ /* yz */
+ BC_LEX_INVALID, BC_LEX_STACK_LEVEL,
+ /* {|}~ */
+ BC_LEX_LBRACE, BC_LEX_OP_MODEXP, BC_LEX_INVALID, BC_LEX_OP_DIVMOD,
+ };
+
BcStatus s = BC_STATUS_SUCCESS;
char c = l->buf[l->i++], c2;
size_t i;
@@ -3380,16 +3395,16 @@ static BC_STATUS zdc_lex_token(BcLex *l)
}
if (c >= '%' && c <= '~'
- && (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID
+ && (l->t.t = dc_lex_tokens[c - '%']) != BC_LEX_INVALID
) {
RETURN_STATUS(s);
}
// This is the workhorse of the lexer.
switch (c) {
- case '\0':
- l->t.t = BC_LEX_EOF;
- break;
+// case '\0': // probably never reached
+// l->t.t = BC_LEX_EOF;
+// break;
case '\n':
case '\t':
case '\v':