diff options
-rw-r--r-- | miscutils/bc.c | 269 |
1 files changed, 121 insertions, 148 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 3815b7f09..f942d42ac 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -3584,9 +3584,14 @@ static void bc_parse_create(BcParse *p, size_t func, | |||
3584 | #define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) | 3584 | #define BC_PARSE_TOKEN_INST(t) ((char) ((t) -BC_LEX_NEG + BC_INST_NEG)) |
3585 | 3585 | ||
3586 | static BC_STATUS zbc_parse_else(BcParse *p); | 3586 | static BC_STATUS zbc_parse_else(BcParse *p); |
3587 | static BcStatus bc_parse_stmt(BcParse *p); | 3587 | static BC_STATUS zbc_parse_stmt(BcParse *p); |
3588 | static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); | 3588 | static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next); |
3589 | static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); | 3589 | static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext next); |
3590 | #if ERRORS_ARE_FATAL | ||
3591 | # define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
3592 | # define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
3593 | # define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
3594 | #endif | ||
3590 | 3595 | ||
3591 | static BC_STATUS zbc_parse_operator(BcParse *p, BcLexType type, size_t start, | 3596 | static BC_STATUS zbc_parse_operator(BcParse *p, BcLexType type, size_t start, |
3592 | size_t *nexprs, bool next) | 3597 | size_t *nexprs, bool next) |
@@ -3657,7 +3662,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags) | |||
3657 | for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) { | 3662 | for (nparams = 0; p->l.t.t != BC_LEX_RPAREN; ++nparams) { |
3658 | 3663 | ||
3659 | flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; | 3664 | flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; |
3660 | s = bc_parse_expr(p, flags, bc_parse_next_param); | 3665 | s = zbc_parse_expr(p, flags, bc_parse_next_param); |
3661 | if (s) return s; | 3666 | if (s) return s; |
3662 | 3667 | ||
3663 | comma = p->l.t.t == BC_LEX_COMMA; | 3668 | comma = p->l.t.t == BC_LEX_COMMA; |
@@ -3739,7 +3744,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) | |||
3739 | *type = BC_INST_ARRAY_ELEM; | 3744 | *type = BC_INST_ARRAY_ELEM; |
3740 | 3745 | ||
3741 | flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); | 3746 | flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); |
3742 | s = bc_parse_expr(p, flags, bc_parse_next_elem); | 3747 | s = zbc_parse_expr(p, flags, bc_parse_next_elem); |
3743 | if (s) goto err; | 3748 | if (s) goto err; |
3744 | } | 3749 | } |
3745 | 3750 | ||
@@ -3805,7 +3810,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, | |||
3805 | s = zbc_lex_next(&p->l); | 3810 | s = zbc_lex_next(&p->l); |
3806 | if (s) return s; | 3811 | if (s) return s; |
3807 | 3812 | ||
3808 | s = bc_parse_expr(p, flags, bc_parse_next_rel); | 3813 | s = zbc_parse_expr(p, flags, bc_parse_next_rel); |
3809 | if (s) return s; | 3814 | if (s) return s; |
3810 | 3815 | ||
3811 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); | 3816 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); |
@@ -3835,7 +3840,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) | |||
3835 | s = zbc_lex_next(&p->l); | 3840 | s = zbc_lex_next(&p->l); |
3836 | if (s) return s; | 3841 | if (s) return s; |
3837 | 3842 | ||
3838 | s = bc_parse_expr(p, flags, bc_parse_next_rel); | 3843 | s = zbc_parse_expr(p, flags, bc_parse_next_rel); |
3839 | if (s) return s; | 3844 | if (s) return s; |
3840 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); | 3845 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); |
3841 | bc_parse_push(p, BC_INST_SCALE_FUNC); | 3846 | bc_parse_push(p, BC_INST_SCALE_FUNC); |
@@ -3957,55 +3962,57 @@ static BC_STATUS zbc_parse_string(BcParse *p, char inst) | |||
3957 | # define zbc_parse_string(...) (zbc_parse_string(__VA_ARGS__), BC_STATUS_SUCCESS) | 3962 | # define zbc_parse_string(...) (zbc_parse_string(__VA_ARGS__), BC_STATUS_SUCCESS) |
3958 | #endif | 3963 | #endif |
3959 | 3964 | ||
3960 | static BcStatus bc_parse_print(BcParse *p) | 3965 | static BC_STATUS zbc_parse_print(BcParse *p) |
3961 | { | 3966 | { |
3962 | BcStatus s; | 3967 | BcStatus s; |
3963 | BcLexType type; | 3968 | BcLexType type; |
3964 | bool comma; | 3969 | bool comma; |
3965 | 3970 | ||
3966 | s = zbc_lex_next(&p->l); | 3971 | s = zbc_lex_next(&p->l); |
3967 | if (s) return s; | 3972 | if (s) RETURN_STATUS(s); |
3968 | 3973 | ||
3969 | type = p->l.t.t; | 3974 | type = p->l.t.t; |
3970 | 3975 | ||
3971 | if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) | 3976 | if (type == BC_LEX_SCOLON || type == BC_LEX_NLINE) |
3972 | return bc_error("bad print statement"); | 3977 | RETURN_STATUS(bc_error("bad print statement")); |
3973 | 3978 | ||
3974 | comma = false; | 3979 | comma = false; |
3975 | while (type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { | 3980 | while (type != BC_LEX_SCOLON && type != BC_LEX_NLINE) { |
3976 | |||
3977 | if (type == BC_LEX_STR) { | 3981 | if (type == BC_LEX_STR) { |
3978 | s = zbc_parse_string(p, BC_INST_PRINT_POP); | 3982 | s = zbc_parse_string(p, BC_INST_PRINT_POP); |
3979 | if (s) return s; | 3983 | if (s) RETURN_STATUS(s); |
3980 | } else { | 3984 | } else { |
3981 | s = bc_parse_expr(p, 0, bc_parse_next_print); | 3985 | s = zbc_parse_expr(p, 0, bc_parse_next_print); |
3982 | if (s) return s; | 3986 | if (s) RETURN_STATUS(s); |
3983 | bc_parse_push(p, BC_INST_PRINT_POP); | 3987 | bc_parse_push(p, BC_INST_PRINT_POP); |
3984 | } | 3988 | } |
3985 | 3989 | ||
3986 | comma = p->l.t.t == BC_LEX_COMMA; | 3990 | comma = p->l.t.t == BC_LEX_COMMA; |
3987 | if (comma) { | 3991 | if (comma) { |
3988 | s = zbc_lex_next(&p->l); | 3992 | s = zbc_lex_next(&p->l); |
3989 | if (s) return s; | 3993 | if (s) RETURN_STATUS(s); |
3990 | } | 3994 | } |
3991 | type = p->l.t.t; | 3995 | type = p->l.t.t; |
3992 | } | 3996 | } |
3993 | 3997 | ||
3994 | if (comma) return bc_error_bad_token(); | 3998 | if (comma) RETURN_STATUS(bc_error_bad_token()); |
3995 | 3999 | ||
3996 | return zbc_lex_next(&p->l); | 4000 | RETURN_STATUS(zbc_lex_next(&p->l)); |
3997 | } | 4001 | } |
4002 | #if ERRORS_ARE_FATAL | ||
4003 | # define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
4004 | #endif | ||
3998 | 4005 | ||
3999 | static BcStatus bc_parse_return(BcParse *p) | 4006 | static BC_STATUS zbc_parse_return(BcParse *p) |
4000 | { | 4007 | { |
4001 | BcStatus s; | 4008 | BcStatus s; |
4002 | BcLexType t; | 4009 | BcLexType t; |
4003 | bool paren; | 4010 | bool paren; |
4004 | 4011 | ||
4005 | if (!BC_PARSE_FUNC(p)) return bc_error_bad_token(); | 4012 | if (!BC_PARSE_FUNC(p)) RETURN_STATUS(bc_error_bad_token()); |
4006 | 4013 | ||
4007 | s = zbc_lex_next(&p->l); | 4014 | s = zbc_lex_next(&p->l); |
4008 | if (s) return s; | 4015 | if (s) RETURN_STATUS(s); |
4009 | 4016 | ||
4010 | t = p->l.t.t; | 4017 | t = p->l.t.t; |
4011 | paren = t == BC_LEX_LPAREN; | 4018 | paren = t == BC_LEX_LPAREN; |
@@ -4013,24 +4020,26 @@ static BcStatus bc_parse_return(BcParse *p) | |||
4013 | if (t == BC_LEX_NLINE || t == BC_LEX_SCOLON) | 4020 | if (t == BC_LEX_NLINE || t == BC_LEX_SCOLON) |
4014 | bc_parse_push(p, BC_INST_RET0); | 4021 | bc_parse_push(p, BC_INST_RET0); |
4015 | else { | 4022 | else { |
4016 | |||
4017 | s = bc_parse_expr_empty_ok(p, 0, bc_parse_next_expr); | 4023 | s = bc_parse_expr_empty_ok(p, 0, bc_parse_next_expr); |
4018 | if (s == BC_STATUS_PARSE_EMPTY_EXP) { | 4024 | if (s == BC_STATUS_PARSE_EMPTY_EXP) { |
4019 | bc_parse_push(p, BC_INST_RET0); | 4025 | bc_parse_push(p, BC_INST_RET0); |
4020 | s = zbc_lex_next(&p->l); | 4026 | s = zbc_lex_next(&p->l); |
4021 | } | 4027 | } |
4022 | if (s) return s; | 4028 | if (s) RETURN_STATUS(s); |
4023 | 4029 | ||
4024 | if (!paren || p->l.t.last != BC_LEX_RPAREN) { | 4030 | if (!paren || p->l.t.last != BC_LEX_RPAREN) { |
4025 | s = bc_POSIX_requires("parentheses around return expressions"); | 4031 | s = bc_POSIX_requires("parentheses around return expressions"); |
4026 | ERROR_RETURN(if (s) return s;) | 4032 | ERROR_RETURN(if (s) RETURN_STATUS(s);) |
4027 | } | 4033 | } |
4028 | 4034 | ||
4029 | bc_parse_push(p, BC_INST_RET); | 4035 | bc_parse_push(p, BC_INST_RET); |
4030 | } | 4036 | } |
4031 | 4037 | ||
4032 | return s; | 4038 | RETURN_STATUS(s); |
4033 | } | 4039 | } |
4040 | #if ERRORS_ARE_FATAL | ||
4041 | # define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
4042 | #endif | ||
4034 | 4043 | ||
4035 | static BC_STATUS zbc_parse_endBody(BcParse *p, bool brace) | 4044 | static BC_STATUS zbc_parse_endBody(BcParse *p, bool brace) |
4036 | { | 4045 | { |
@@ -4063,7 +4072,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p, bool brace) | |||
4063 | *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END); | 4072 | *flag_ptr = (*flag_ptr | BC_PARSE_FLAG_IF_END); |
4064 | 4073 | ||
4065 | if (p->l.t.t == BC_LEX_KEY_ELSE) | 4074 | if (p->l.t.t == BC_LEX_KEY_ELSE) |
4066 | ERROR_RETURN(s =) zbc_parse_else(p); | 4075 | s = zbc_parse_else(p); |
4067 | } | 4076 | } |
4068 | else if (BC_PARSE_ELSE(p)) { | 4077 | else if (BC_PARSE_ELSE(p)) { |
4069 | BcInstPtr *ip; | 4078 | BcInstPtr *ip; |
@@ -4126,23 +4135,23 @@ static void bc_parse_noElse(BcParse *p) | |||
4126 | bc_vec_pop(&p->exits); | 4135 | bc_vec_pop(&p->exits); |
4127 | } | 4136 | } |
4128 | 4137 | ||
4129 | static BcStatus bc_parse_if(BcParse *p) | 4138 | static BC_STATUS zbc_parse_if(BcParse *p) |
4130 | { | 4139 | { |
4131 | BcStatus s; | 4140 | BcStatus s; |
4132 | BcInstPtr ip; | 4141 | BcInstPtr ip; |
4133 | 4142 | ||
4134 | s = zbc_lex_next(&p->l); | 4143 | s = zbc_lex_next(&p->l); |
4135 | if (s) return s; | 4144 | if (s) RETURN_STATUS(s); |
4136 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); | 4145 | if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); |
4137 | 4146 | ||
4138 | s = zbc_lex_next(&p->l); | 4147 | s = zbc_lex_next(&p->l); |
4139 | if (s) return s; | 4148 | if (s) RETURN_STATUS(s); |
4140 | s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); | 4149 | s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); |
4141 | if (s) return s; | 4150 | if (s) RETURN_STATUS(s); |
4142 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); | 4151 | if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
4143 | 4152 | ||
4144 | s = zbc_lex_next(&p->l); | 4153 | s = zbc_lex_next(&p->l); |
4145 | if (s) return s; | 4154 | if (s) RETURN_STATUS(s); |
4146 | bc_parse_push(p, BC_INST_JUMP_ZERO); | 4155 | bc_parse_push(p, BC_INST_JUMP_ZERO); |
4147 | 4156 | ||
4148 | ip.idx = p->func->labels.len; | 4157 | ip.idx = p->func->labels.len; |
@@ -4153,9 +4162,13 @@ static BcStatus bc_parse_if(BcParse *p) | |||
4153 | bc_vec_push(&p->func->labels, &ip.idx); | 4162 | bc_vec_push(&p->func->labels, &ip.idx); |
4154 | bc_parse_startBody(p, BC_PARSE_FLAG_IF); | 4163 | bc_parse_startBody(p, BC_PARSE_FLAG_IF); |
4155 | 4164 | ||
4156 | return BC_STATUS_SUCCESS; | 4165 | RETURN_STATUS(BC_STATUS_SUCCESS); |
4157 | } | 4166 | } |
4167 | #if ERRORS_ARE_FATAL | ||
4168 | # define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
4169 | #endif | ||
4158 | 4170 | ||
4171 | #undef zbc_parse_else | ||
4159 | static BC_STATUS zbc_parse_else(BcParse *p) | 4172 | static BC_STATUS zbc_parse_else(BcParse *p) |
4160 | { | 4173 | { |
4161 | BcInstPtr ip; | 4174 | BcInstPtr ip; |
@@ -4180,16 +4193,16 @@ static BC_STATUS zbc_parse_else(BcParse *p) | |||
4180 | # define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) | 4193 | # define zbc_parse_else(...) (zbc_parse_else(__VA_ARGS__), BC_STATUS_SUCCESS) |
4181 | #endif | 4194 | #endif |
4182 | 4195 | ||
4183 | static BcStatus bc_parse_while(BcParse *p) | 4196 | static BC_STATUS zbc_parse_while(BcParse *p) |
4184 | { | 4197 | { |
4185 | BcStatus s; | 4198 | BcStatus s; |
4186 | BcInstPtr ip; | 4199 | BcInstPtr ip; |
4187 | 4200 | ||
4188 | s = zbc_lex_next(&p->l); | 4201 | s = zbc_lex_next(&p->l); |
4189 | if (s) return s; | 4202 | if (s) RETURN_STATUS(s); |
4190 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); | 4203 | if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); |
4191 | s = zbc_lex_next(&p->l); | 4204 | s = zbc_lex_next(&p->l); |
4192 | if (s) return s; | 4205 | if (s) RETURN_STATUS(s); |
4193 | 4206 | ||
4194 | ip.idx = p->func->labels.len; | 4207 | ip.idx = p->func->labels.len; |
4195 | 4208 | ||
@@ -4203,40 +4216,43 @@ static BcStatus bc_parse_while(BcParse *p) | |||
4203 | bc_vec_push(&p->exits, &ip); | 4216 | bc_vec_push(&p->exits, &ip); |
4204 | bc_vec_push(&p->func->labels, &ip.idx); | 4217 | bc_vec_push(&p->func->labels, &ip.idx); |
4205 | 4218 | ||
4206 | s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); | 4219 | s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); |
4207 | if (s) return s; | 4220 | if (s) RETURN_STATUS(s); |
4208 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); | 4221 | if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
4209 | s = zbc_lex_next(&p->l); | 4222 | s = zbc_lex_next(&p->l); |
4210 | if (s) return s; | 4223 | if (s) RETURN_STATUS(s); |
4211 | 4224 | ||
4212 | bc_parse_push(p, BC_INST_JUMP_ZERO); | 4225 | bc_parse_push(p, BC_INST_JUMP_ZERO); |
4213 | bc_parse_pushIndex(p, ip.idx); | 4226 | bc_parse_pushIndex(p, ip.idx); |
4214 | bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); | 4227 | bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); |
4215 | 4228 | ||
4216 | return BC_STATUS_SUCCESS; | 4229 | RETURN_STATUS(BC_STATUS_SUCCESS); |
4217 | } | 4230 | } |
4231 | #if ERRORS_ARE_FATAL | ||
4232 | # define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
4233 | #endif | ||
4218 | 4234 | ||
4219 | static BcStatus bc_parse_for(BcParse *p) | 4235 | static BC_STATUS zbc_parse_for(BcParse *p) |
4220 | { | 4236 | { |
4221 | BcStatus s; | 4237 | BcStatus s; |
4222 | BcInstPtr ip; | 4238 | BcInstPtr ip; |
4223 | size_t cond_idx, exit_idx, body_idx, update_idx; | 4239 | size_t cond_idx, exit_idx, body_idx, update_idx; |
4224 | 4240 | ||
4225 | s = zbc_lex_next(&p->l); | 4241 | s = zbc_lex_next(&p->l); |
4226 | if (s) return s; | 4242 | if (s) RETURN_STATUS(s); |
4227 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); | 4243 | if (p->l.t.t != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); |
4228 | s = zbc_lex_next(&p->l); | 4244 | s = zbc_lex_next(&p->l); |
4229 | if (s) return s; | 4245 | if (s) RETURN_STATUS(s); |
4230 | 4246 | ||
4231 | if (p->l.t.t != BC_LEX_SCOLON) | 4247 | if (p->l.t.t != BC_LEX_SCOLON) |
4232 | s = bc_parse_expr(p, 0, bc_parse_next_for); | 4248 | s = zbc_parse_expr(p, 0, bc_parse_next_for); |
4233 | else | 4249 | else |
4234 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); | 4250 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); |
4235 | 4251 | ||
4236 | if (s) return s; | 4252 | if (s) RETURN_STATUS(s); |
4237 | if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); | 4253 | if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); |
4238 | s = zbc_lex_next(&p->l); | 4254 | s = zbc_lex_next(&p->l); |
4239 | if (s) return s; | 4255 | if (s) RETURN_STATUS(s); |
4240 | 4256 | ||
4241 | cond_idx = p->func->labels.len; | 4257 | cond_idx = p->func->labels.len; |
4242 | update_idx = cond_idx + 1; | 4258 | update_idx = cond_idx + 1; |
@@ -4246,15 +4262,15 @@ static BcStatus bc_parse_for(BcParse *p) | |||
4246 | bc_vec_push(&p->func->labels, &p->func->code.len); | 4262 | bc_vec_push(&p->func->labels, &p->func->code.len); |
4247 | 4263 | ||
4248 | if (p->l.t.t != BC_LEX_SCOLON) | 4264 | if (p->l.t.t != BC_LEX_SCOLON) |
4249 | s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for); | 4265 | s = zbc_parse_expr(p, BC_PARSE_REL, bc_parse_next_for); |
4250 | else | 4266 | else |
4251 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); | 4267 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); |
4252 | 4268 | ||
4253 | if (s) return s; | 4269 | if (s) RETURN_STATUS(s); |
4254 | if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); | 4270 | if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); |
4255 | 4271 | ||
4256 | s = zbc_lex_next(&p->l); | 4272 | s = zbc_lex_next(&p->l); |
4257 | if (s) return s; | 4273 | if (s) RETURN_STATUS(s); |
4258 | 4274 | ||
4259 | bc_parse_push(p, BC_INST_JUMP_ZERO); | 4275 | bc_parse_push(p, BC_INST_JUMP_ZERO); |
4260 | bc_parse_pushIndex(p, exit_idx); | 4276 | bc_parse_pushIndex(p, exit_idx); |
@@ -4267,13 +4283,13 @@ static BcStatus bc_parse_for(BcParse *p) | |||
4267 | bc_vec_push(&p->func->labels, &p->func->code.len); | 4283 | bc_vec_push(&p->func->labels, &p->func->code.len); |
4268 | 4284 | ||
4269 | if (p->l.t.t != BC_LEX_RPAREN) | 4285 | if (p->l.t.t != BC_LEX_RPAREN) |
4270 | s = bc_parse_expr(p, 0, bc_parse_next_rel); | 4286 | s = zbc_parse_expr(p, 0, bc_parse_next_rel); |
4271 | else | 4287 | else |
4272 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); | 4288 | s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); |
4273 | 4289 | ||
4274 | if (s) return s; | 4290 | if (s) RETURN_STATUS(s); |
4275 | 4291 | ||
4276 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); | 4292 | if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
4277 | bc_parse_push(p, BC_INST_JUMP); | 4293 | bc_parse_push(p, BC_INST_JUMP); |
4278 | bc_parse_pushIndex(p, cond_idx); | 4294 | bc_parse_pushIndex(p, cond_idx); |
4279 | bc_vec_push(&p->func->labels, &p->func->code.len); | 4295 | bc_vec_push(&p->func->labels, &p->func->code.len); |
@@ -4285,11 +4301,14 @@ static BcStatus bc_parse_for(BcParse *p) | |||
4285 | bc_vec_push(&p->exits, &ip); | 4301 | bc_vec_push(&p->exits, &ip); |
4286 | bc_vec_push(&p->func->labels, &ip.idx); | 4302 | bc_vec_push(&p->func->labels, &ip.idx); |
4287 | s = zbc_lex_next(&p->l); | 4303 | s = zbc_lex_next(&p->l); |
4288 | if (s) return s; | 4304 | if (s) RETURN_STATUS(s); |
4289 | bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); | 4305 | bc_parse_startBody(p, BC_PARSE_FLAG_LOOP | BC_PARSE_FLAG_LOOP_INNER); |
4290 | 4306 | ||
4291 | return BC_STATUS_SUCCESS; | 4307 | RETURN_STATUS(BC_STATUS_SUCCESS); |
4292 | } | 4308 | } |
4309 | #if ERRORS_ARE_FATAL | ||
4310 | # define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
4311 | #endif | ||
4293 | 4312 | ||
4294 | static BC_STATUS zbc_parse_loopExit(BcParse *p, BcLexType type) | 4313 | static BC_STATUS zbc_parse_loopExit(BcParse *p, BcLexType type) |
4295 | { | 4314 | { |
@@ -4487,7 +4506,7 @@ static BC_STATUS zbc_parse_body(BcParse *p, bool brace) | |||
4487 | if (p->l.t.t == BC_LEX_NLINE) s = zbc_lex_next(&p->l); | 4506 | if (p->l.t.t == BC_LEX_NLINE) s = zbc_lex_next(&p->l); |
4488 | } | 4507 | } |
4489 | else { | 4508 | else { |
4490 | s = bc_parse_stmt(p); | 4509 | s = zbc_parse_stmt(p); |
4491 | if (!s && !brace) s = zbc_parse_endBody(p, false); | 4510 | if (!s && !brace) s = zbc_parse_endBody(p, false); |
4492 | } | 4511 | } |
4493 | 4512 | ||
@@ -4497,56 +4516,41 @@ static BC_STATUS zbc_parse_body(BcParse *p, bool brace) | |||
4497 | # define zbc_parse_body(...) (zbc_parse_body(__VA_ARGS__), BC_STATUS_SUCCESS) | 4516 | # define zbc_parse_body(...) (zbc_parse_body(__VA_ARGS__), BC_STATUS_SUCCESS) |
4498 | #endif | 4517 | #endif |
4499 | 4518 | ||
4500 | static BcStatus bc_parse_stmt(BcParse *p) | 4519 | #undef zbc_parse_stmt |
4520 | static BC_STATUS zbc_parse_stmt(BcParse *p) | ||
4501 | { | 4521 | { |
4502 | BcStatus s = BC_STATUS_SUCCESS; | 4522 | BcStatus s = BC_STATUS_SUCCESS; |
4503 | 4523 | ||
4504 | switch (p->l.t.t) { | 4524 | switch (p->l.t.t) { |
4505 | |||
4506 | case BC_LEX_NLINE: | 4525 | case BC_LEX_NLINE: |
4507 | { | 4526 | RETURN_STATUS(zbc_lex_next(&p->l)); |
4508 | return zbc_lex_next(&p->l); | ||
4509 | } | ||
4510 | 4527 | ||
4511 | case BC_LEX_KEY_ELSE: | 4528 | case BC_LEX_KEY_ELSE: |
4512 | { | ||
4513 | p->auto_part = false; | 4529 | p->auto_part = false; |
4514 | break; | 4530 | break; |
4515 | } | ||
4516 | 4531 | ||
4517 | case BC_LEX_LBRACE: | 4532 | case BC_LEX_LBRACE: |
4518 | { | 4533 | if (!BC_PARSE_BODY(p)) RETURN_STATUS(bc_error_bad_token()); |
4519 | if (!BC_PARSE_BODY(p)) return bc_error_bad_token(); | ||
4520 | |||
4521 | ++p->nbraces; | 4534 | ++p->nbraces; |
4522 | s = zbc_lex_next(&p->l); | 4535 | s = zbc_lex_next(&p->l); |
4523 | if (s) return s; | 4536 | if (s) RETURN_STATUS(s); |
4524 | 4537 | RETURN_STATUS(zbc_parse_body(p, true)); | |
4525 | return zbc_parse_body(p, true); | ||
4526 | } | ||
4527 | 4538 | ||
4528 | case BC_LEX_KEY_AUTO: | 4539 | case BC_LEX_KEY_AUTO: |
4529 | { | 4540 | RETURN_STATUS(zbc_parse_auto(p)); |
4530 | return zbc_parse_auto(p); | ||
4531 | } | ||
4532 | 4541 | ||
4533 | default: | 4542 | default: |
4534 | { | ||
4535 | p->auto_part = false; | 4543 | p->auto_part = false; |
4536 | |||
4537 | if (BC_PARSE_IF_END(p)) { | 4544 | if (BC_PARSE_IF_END(p)) { |
4538 | bc_parse_noElse(p); | 4545 | bc_parse_noElse(p); |
4539 | return BC_STATUS_SUCCESS; | 4546 | RETURN_STATUS(BC_STATUS_SUCCESS); |
4540 | } | 4547 | } |
4541 | else if (BC_PARSE_BODY(p)) | 4548 | if (BC_PARSE_BODY(p)) |
4542 | return zbc_parse_body(p, false); | 4549 | RETURN_STATUS(zbc_parse_body(p, false)); |
4543 | |||
4544 | break; | 4550 | break; |
4545 | } | ||
4546 | } | 4551 | } |
4547 | 4552 | ||
4548 | switch (p->l.t.t) { | 4553 | switch (p->l.t.t) { |
4549 | |||
4550 | case BC_LEX_OP_INC: | 4554 | case BC_LEX_OP_INC: |
4551 | case BC_LEX_OP_DEC: | 4555 | case BC_LEX_OP_DEC: |
4552 | case BC_LEX_OP_MINUS: | 4556 | case BC_LEX_OP_MINUS: |
@@ -4561,67 +4565,39 @@ static BcStatus bc_parse_stmt(BcParse *p) | |||
4561 | case BC_LEX_KEY_READ: | 4565 | case BC_LEX_KEY_READ: |
4562 | case BC_LEX_KEY_SCALE: | 4566 | case BC_LEX_KEY_SCALE: |
4563 | case BC_LEX_KEY_SQRT: | 4567 | case BC_LEX_KEY_SQRT: |
4564 | { | 4568 | s = zbc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr); |
4565 | s = bc_parse_expr(p, BC_PARSE_PRINT, bc_parse_next_expr); | ||
4566 | break; | 4569 | break; |
4567 | } | ||
4568 | |||
4569 | case BC_LEX_KEY_ELSE: | 4570 | case BC_LEX_KEY_ELSE: |
4570 | { | ||
4571 | s = zbc_parse_else(p); | 4571 | s = zbc_parse_else(p); |
4572 | break; | 4572 | break; |
4573 | } | ||
4574 | |||
4575 | case BC_LEX_SCOLON: | 4573 | case BC_LEX_SCOLON: |
4576 | { | ||
4577 | while (!s && p->l.t.t == BC_LEX_SCOLON) s = zbc_lex_next(&p->l); | 4574 | while (!s && p->l.t.t == BC_LEX_SCOLON) s = zbc_lex_next(&p->l); |
4578 | break; | 4575 | break; |
4579 | } | ||
4580 | |||
4581 | case BC_LEX_RBRACE: | 4576 | case BC_LEX_RBRACE: |
4582 | { | ||
4583 | s = zbc_parse_endBody(p, true); | 4577 | s = zbc_parse_endBody(p, true); |
4584 | break; | 4578 | break; |
4585 | } | ||
4586 | |||
4587 | case BC_LEX_STR: | 4579 | case BC_LEX_STR: |
4588 | { | ||
4589 | s = zbc_parse_string(p, BC_INST_PRINT_STR); | 4580 | s = zbc_parse_string(p, BC_INST_PRINT_STR); |
4590 | break; | 4581 | break; |
4591 | } | ||
4592 | |||
4593 | case BC_LEX_KEY_BREAK: | 4582 | case BC_LEX_KEY_BREAK: |
4594 | case BC_LEX_KEY_CONTINUE: | 4583 | case BC_LEX_KEY_CONTINUE: |
4595 | { | ||
4596 | s = zbc_parse_loopExit(p, p->l.t.t); | 4584 | s = zbc_parse_loopExit(p, p->l.t.t); |
4597 | break; | 4585 | break; |
4598 | } | ||
4599 | |||
4600 | case BC_LEX_KEY_FOR: | 4586 | case BC_LEX_KEY_FOR: |
4601 | { | 4587 | s = zbc_parse_for(p); |
4602 | s = bc_parse_for(p); | ||
4603 | break; | 4588 | break; |
4604 | } | ||
4605 | |||
4606 | case BC_LEX_KEY_HALT: | 4589 | case BC_LEX_KEY_HALT: |
4607 | { | ||
4608 | bc_parse_push(p, BC_INST_HALT); | 4590 | bc_parse_push(p, BC_INST_HALT); |
4609 | s = zbc_lex_next(&p->l); | 4591 | s = zbc_lex_next(&p->l); |
4610 | break; | 4592 | break; |
4611 | } | ||
4612 | |||
4613 | case BC_LEX_KEY_IF: | 4593 | case BC_LEX_KEY_IF: |
4614 | { | 4594 | s = zbc_parse_if(p); |
4615 | s = bc_parse_if(p); | ||
4616 | break; | 4595 | break; |
4617 | } | ||
4618 | |||
4619 | case BC_LEX_KEY_LIMITS: | 4596 | case BC_LEX_KEY_LIMITS: |
4620 | { | ||
4621 | // "limits" is a compile-time command, | 4597 | // "limits" is a compile-time command, |
4622 | // the output is produced at _parse time_. | 4598 | // the output is produced at _parse time_. |
4623 | s = zbc_lex_next(&p->l); | 4599 | s = zbc_lex_next(&p->l); |
4624 | if (s) return s; | 4600 | if (s) RETURN_STATUS(s); |
4625 | printf( | 4601 | printf( |
4626 | "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n" | 4602 | "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n" |
4627 | "BC_DIM_MAX = "BC_MAX_DIM_STR "\n" | 4603 | "BC_DIM_MAX = "BC_MAX_DIM_STR "\n" |
@@ -4633,43 +4609,30 @@ static BcStatus bc_parse_stmt(BcParse *p) | |||
4633 | "Number of vars = "BC_MAX_VARS_STR "\n" | 4609 | "Number of vars = "BC_MAX_VARS_STR "\n" |
4634 | ); | 4610 | ); |
4635 | break; | 4611 | break; |
4636 | } | ||
4637 | |||
4638 | case BC_LEX_KEY_PRINT: | 4612 | case BC_LEX_KEY_PRINT: |
4639 | { | 4613 | s = zbc_parse_print(p); |
4640 | s = bc_parse_print(p); | ||
4641 | break; | 4614 | break; |
4642 | } | ||
4643 | |||
4644 | case BC_LEX_KEY_QUIT: | 4615 | case BC_LEX_KEY_QUIT: |
4645 | { | ||
4646 | // "quit" is a compile-time command. For example, | 4616 | // "quit" is a compile-time command. For example, |
4647 | // "if (0 == 1) quit" terminates when parsing the statement, | 4617 | // "if (0 == 1) quit" terminates when parsing the statement, |
4648 | // not when it is executed | 4618 | // not when it is executed |
4649 | QUIT_OR_RETURN_TO_MAIN; | 4619 | QUIT_OR_RETURN_TO_MAIN; |
4650 | } | ||
4651 | |||
4652 | case BC_LEX_KEY_RETURN: | 4620 | case BC_LEX_KEY_RETURN: |
4653 | { | 4621 | s = zbc_parse_return(p); |
4654 | s = bc_parse_return(p); | ||
4655 | break; | 4622 | break; |
4656 | } | ||
4657 | |||
4658 | case BC_LEX_KEY_WHILE: | 4623 | case BC_LEX_KEY_WHILE: |
4659 | { | 4624 | s = zbc_parse_while(p); |
4660 | s = bc_parse_while(p); | ||
4661 | break; | 4625 | break; |
4662 | } | ||
4663 | |||
4664 | default: | 4626 | default: |
4665 | { | ||
4666 | s = bc_error_bad_token(); | 4627 | s = bc_error_bad_token(); |
4667 | break; | 4628 | break; |
4668 | } | ||
4669 | } | 4629 | } |
4670 | 4630 | ||
4671 | return s; | 4631 | RETURN_STATUS(s); |
4672 | } | 4632 | } |
4633 | #if ERRORS_ARE_FATAL | ||
4634 | # define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
4635 | #endif | ||
4673 | 4636 | ||
4674 | static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) | 4637 | static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) |
4675 | { | 4638 | { |
@@ -4682,7 +4645,7 @@ static FAST_FUNC BcStatus bc_parse_parse(BcParse *p) | |||
4682 | s = zbc_parse_func(p); | 4645 | s = zbc_parse_func(p); |
4683 | } | 4646 | } |
4684 | else | 4647 | else |
4685 | s = bc_parse_stmt(p); | 4648 | s = zbc_parse_stmt(p); |
4686 | 4649 | ||
4687 | if (s || G_interrupt) { | 4650 | if (s || G_interrupt) { |
4688 | bc_parse_reset(p); | 4651 | bc_parse_reset(p); |
@@ -4952,25 +4915,32 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne | |||
4952 | return s; | 4915 | return s; |
4953 | } | 4916 | } |
4954 | 4917 | ||
4955 | static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | 4918 | #undef zbc_parse_expr |
4919 | static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | ||
4956 | { | 4920 | { |
4957 | BcStatus s; | 4921 | BcStatus s; |
4958 | 4922 | ||
4959 | s = bc_parse_expr_empty_ok(p, flags, next); | 4923 | s = bc_parse_expr_empty_ok(p, flags, next); |
4960 | if (s == BC_STATUS_PARSE_EMPTY_EXP) | 4924 | if (s == BC_STATUS_PARSE_EMPTY_EXP) |
4961 | return bc_error("empty expression"); | 4925 | RETURN_STATUS(bc_error("empty expression")); |
4962 | return s; | 4926 | RETURN_STATUS(s); |
4963 | } | 4927 | } |
4928 | #if ERRORS_ARE_FATAL | ||
4929 | # define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
4930 | #endif | ||
4964 | 4931 | ||
4965 | static void bc_parse_init(BcParse *p, size_t func) | 4932 | static void bc_parse_init(BcParse *p, size_t func) |
4966 | { | 4933 | { |
4967 | bc_parse_create(p, func, bc_parse_parse, zbc_lex_token); | 4934 | bc_parse_create(p, func, bc_parse_parse, zbc_lex_token); |
4968 | } | 4935 | } |
4969 | 4936 | ||
4970 | static BcStatus bc_parse_expression(BcParse *p, uint8_t flags) | 4937 | static BC_STATUS zbc_parse_expression(BcParse *p, uint8_t flags) |
4971 | { | 4938 | { |
4972 | return bc_parse_expr(p, flags, bc_parse_next_read); | 4939 | RETURN_STATUS(zbc_parse_expr(p, flags, bc_parse_next_read)); |
4973 | } | 4940 | } |
4941 | #if ERRORS_ARE_FATAL | ||
4942 | # define zbc_parse_expression(...) (zbc_parse_expression(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
4943 | #endif | ||
4974 | 4944 | ||
4975 | #endif // ENABLE_BC | 4945 | #endif // ENABLE_BC |
4976 | 4946 | ||
@@ -5198,14 +5168,17 @@ static void common_parse_init(BcParse *p, size_t func) | |||
5198 | } | 5168 | } |
5199 | } | 5169 | } |
5200 | 5170 | ||
5201 | static BcStatus common_parse_expr(BcParse *p, uint8_t flags) | 5171 | static BC_STATUS zcommon_parse_expr(BcParse *p, uint8_t flags) |
5202 | { | 5172 | { |
5203 | if (IS_BC) { | 5173 | if (IS_BC) { |
5204 | IF_BC(return bc_parse_expression(p, flags);) | 5174 | IF_BC(RETURN_STATUS(zbc_parse_expression(p, flags));) |
5205 | } else { | 5175 | } else { |
5206 | IF_DC(return zdc_parse_expr(p, flags);) | 5176 | IF_DC(RETURN_STATUS(zdc_parse_expr(p, flags));) |
5207 | } | 5177 | } |
5208 | } | 5178 | } |
5179 | #if ERRORS_ARE_FATAL | ||
5180 | # define zcommon_parse_expr(...) (zcommon_parse_expr(__VA_ARGS__), BC_STATUS_SUCCESS) | ||
5181 | #endif | ||
5209 | 5182 | ||
5210 | static BcVec* bc_program_search(char *id, bool var) | 5183 | static BcVec* bc_program_search(char *id, bool var) |
5211 | { | 5184 | { |
@@ -5440,7 +5413,7 @@ static BcStatus bc_program_read(void) | |||
5440 | 5413 | ||
5441 | s = bc_parse_text(&parse, buf.v); | 5414 | s = bc_parse_text(&parse, buf.v); |
5442 | if (s) goto exec_err; | 5415 | if (s) goto exec_err; |
5443 | s = common_parse_expr(&parse, BC_PARSE_NOREAD); | 5416 | s = zcommon_parse_expr(&parse, BC_PARSE_NOREAD); |
5444 | if (s) goto exec_err; | 5417 | if (s) goto exec_err; |
5445 | 5418 | ||
5446 | if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { | 5419 | if (parse.l.t.t != BC_LEX_NLINE && parse.l.t.t != BC_LEX_EOF) { |
@@ -6639,7 +6612,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, | |||
6639 | common_parse_init(&prs, fidx); | 6612 | common_parse_init(&prs, fidx); |
6640 | s = bc_parse_text(&prs, *str); | 6613 | s = bc_parse_text(&prs, *str); |
6641 | if (s) goto err; | 6614 | if (s) goto err; |
6642 | s = common_parse_expr(&prs, BC_PARSE_NOCALL); | 6615 | s = zcommon_parse_expr(&prs, BC_PARSE_NOCALL); |
6643 | if (s) goto err; | 6616 | if (s) goto err; |
6644 | 6617 | ||
6645 | if (prs.l.t.t != BC_LEX_EOF) { | 6618 | if (prs.l.t.t != BC_LEX_EOF) { |