diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-05 16:03:46 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-05 16:03:46 +0100 |
commit | 24fb2cd62fcc2c422692df4138e0f1e333a52c42 (patch) | |
tree | 2e0abfd8cb3578409c60cb7d880a8ba2c0df31de | |
parent | f359e004b0ce4a5ac361f553c13e876123fd4ebb (diff) | |
download | busybox-w32-24fb2cd62fcc2c422692df4138e0f1e333a52c42.tar.gz busybox-w32-24fb2cd62fcc2c422692df4138e0f1e333a52c42.tar.bz2 busybox-w32-24fb2cd62fcc2c422692df4138e0f1e333a52c42.zip |
bc: shrink error handling code by enabling tail-call optimization
function old new delta
bc_posix_error_fmt - 60 +60
bc_error_fmt - 38 +38
bc_error_bad_character - 17 +17
bc_parse_auto 302 313 +11
bc_num_ulong 93 103 +10
bc_error_variable_is_wrong_type - 10 +10
bc_error_stack_has_too_few_elements - 10 +10
bc_error_nested_read_call - 10 +10
bc_error_bad_token - 10 +10
bc_error_bad_expression - 10 +10
bc_num_d 561 564 +3
bc_program_assign 484 486 +2
dc_parse_parse 60 59 -1
bc_program_num 1130 1129 -1
bc_program_call 367 366 -1
bc_parse_stmt 2277 2276 -1
bc_lex_number 299 298 -1
bc_lex_name 91 90 -1
bc_func_insert 98 97 -1
bc_num_shift 74 72 -2
bc_vm_run 1924 1921 -3
bc_parse_endBody 424 420 -4
bc_lex_next 81 77 -4
bc_program_read 343 338 -5
bc_program_asciify 469 464 -5
bc_program_pushVar 221 215 -6
bc_program_print 784 778 -6
bc_program_prep 99 93 -6
bc_program_assignStr 167 161 -6
bc_parse_else 143 137 -6
bc_parse_body 124 118 -6
dc_parse_register 61 53 -8
dc_lex_token 699 691 -8
bc_program_modexp 756 746 -10
bc_parse_name 593 581 -12
dc_parse_expr 775 762 -13
bc_program_copyToVar 336 323 -13
bc_program_binOpPrep 324 311 -13
bc_program_execStr 561 543 -18
bc_program_exec 4150 4132 -18
bc_parse_parse 483 464 -19
bc_error 38 14 -24
bc_lex_token 1266 1237 -29
bc_posix_error 60 14 -46
bc_parse_expr 2194 2146 -48
------------------------------------------------------------------------------
(add/remove: 8/0 grow/shrink: 4/33 up/down: 191/-345) Total: -154 bytes
text data bss dec hex filename
987226 485 7296 995007 f2ebf busybox_old
987072 485 7296 994853 f2e25 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/bc.c | 233 |
1 files changed, 136 insertions, 97 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index b392b05a3..6f2606c79 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -1110,7 +1110,7 @@ static void quit(void) | |||
1110 | exit(0); | 1110 | exit(0); |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | static int bc_error(const char *fmt, ...) | 1113 | static NOINLINE int bc_error_fmt(const char *fmt, ...) |
1114 | { | 1114 | { |
1115 | va_list p; | 1115 | va_list p; |
1116 | 1116 | ||
@@ -1122,12 +1122,13 @@ static int bc_error(const char *fmt, ...) | |||
1122 | return BC_STATUS_FAILURE; | 1122 | return BC_STATUS_FAILURE; |
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | static int bc_posix_error(const char *fmt, ...) | 1125 | static NOINLINE int bc_posix_error_fmt(const char *fmt, ...) |
1126 | { | 1126 | { |
1127 | va_list p; | 1127 | va_list p; |
1128 | 1128 | ||
1129 | // Are non-POSIX constructs totally ok? | ||
1129 | if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W))) | 1130 | if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W))) |
1130 | return BC_STATUS_SUCCESS; | 1131 | return BC_STATUS_SUCCESS; // yes |
1131 | 1132 | ||
1132 | va_start(p, fmt); | 1133 | va_start(p, fmt); |
1133 | bb_verror_msg(fmt, p, NULL); | 1134 | bb_verror_msg(fmt, p, NULL); |
@@ -1141,6 +1142,44 @@ static int bc_posix_error(const char *fmt, ...) | |||
1141 | return BC_STATUS_FAILURE; | 1142 | return BC_STATUS_FAILURE; |
1142 | } | 1143 | } |
1143 | 1144 | ||
1145 | // We use error functions with "return bc_error(FMT[, PARAMS])" idiom. | ||
1146 | // This idiom begs for tail-call optimization, but for it to work, | ||
1147 | // function must not have calller-cleaned parameters on stack. | ||
1148 | // Unfortunately, vararg functions do exactly that on most arches. | ||
1149 | // Thus, these shims for the cases when we have no PARAMS: | ||
1150 | static int bc_error(const char *msg) | ||
1151 | { | ||
1152 | return bc_error_fmt("%s", msg); | ||
1153 | } | ||
1154 | static int bc_posix_error(const char *msg) | ||
1155 | { | ||
1156 | return bc_posix_error_fmt("%s", msg); | ||
1157 | } | ||
1158 | static int bc_error_bad_character(char c) | ||
1159 | { | ||
1160 | return bc_error_fmt("bad character '%c'", c); | ||
1161 | } | ||
1162 | static int bc_error_bad_expression(void) | ||
1163 | { | ||
1164 | return bc_error("bad expression"); | ||
1165 | } | ||
1166 | static int bc_error_bad_token(void) | ||
1167 | { | ||
1168 | return bc_error("bad token"); | ||
1169 | } | ||
1170 | static int bc_error_stack_has_too_few_elements(void) | ||
1171 | { | ||
1172 | return bc_error("stack has too few elements"); | ||
1173 | } | ||
1174 | static int bc_error_variable_is_wrong_type(void) | ||
1175 | { | ||
1176 | return bc_error("variable is wrong type"); | ||
1177 | } | ||
1178 | static int bc_error_nested_read_call(void) | ||
1179 | { | ||
1180 | return bc_error("read() call inside of a read() call"); | ||
1181 | } | ||
1182 | |||
1144 | static void bc_vec_grow(BcVec *v, size_t n) | 1183 | static void bc_vec_grow(BcVec *v, size_t n) |
1145 | { | 1184 | { |
1146 | size_t cap = v->cap * 2; | 1185 | size_t cap = v->cap * 2; |
@@ -1349,7 +1388,7 @@ static BcStatus bc_read_line(BcVec *vec, const char *prompt) | |||
1349 | || i > 0x7e | 1388 | || i > 0x7e |
1350 | ) { | 1389 | ) { |
1351 | // Bad chars on this line, ignore entire line | 1390 | // Bad chars on this line, ignore entire line |
1352 | bc_error("illegal character 0x%02x", i); | 1391 | bc_error_fmt("illegal character 0x%02x", i); |
1353 | bad_chars = 1; | 1392 | bad_chars = 1; |
1354 | } | 1393 | } |
1355 | c = (char) i; | 1394 | c = (char) i; |
@@ -3214,7 +3253,7 @@ static BcStatus bc_lex_token(BcLex *l) | |||
3214 | } | 3253 | } |
3215 | else { | 3254 | else { |
3216 | l->t.t = BC_LEX_INVALID; | 3255 | l->t.t = BC_LEX_INVALID; |
3217 | s = bc_error("bad character '%c'", '&'); | 3256 | s = bc_error_bad_character('&'); |
3218 | } | 3257 | } |
3219 | 3258 | ||
3220 | break; | 3259 | break; |
@@ -3343,7 +3382,7 @@ static BcStatus bc_lex_token(BcLex *l) | |||
3343 | ++l->i; | 3382 | ++l->i; |
3344 | } | 3383 | } |
3345 | else | 3384 | else |
3346 | s = bc_error("bad character '%c'", c); | 3385 | s = bc_error_bad_character(c); |
3347 | break; | 3386 | break; |
3348 | } | 3387 | } |
3349 | 3388 | ||
@@ -3404,7 +3443,7 @@ static BcStatus bc_lex_token(BcLex *l) | |||
3404 | } | 3443 | } |
3405 | else { | 3444 | else { |
3406 | l->t.t = BC_LEX_INVALID; | 3445 | l->t.t = BC_LEX_INVALID; |
3407 | s = bc_error("bad character '%c'", c); | 3446 | s = bc_error_bad_character(c); |
3408 | } | 3447 | } |
3409 | 3448 | ||
3410 | break; | 3449 | break; |
@@ -3413,7 +3452,7 @@ static BcStatus bc_lex_token(BcLex *l) | |||
3413 | default: | 3452 | default: |
3414 | { | 3453 | { |
3415 | l->t.t = BC_LEX_INVALID; | 3454 | l->t.t = BC_LEX_INVALID; |
3416 | s = bc_error("bad character '%c'", c); | 3455 | s = bc_error_bad_character(c); |
3417 | break; | 3456 | break; |
3418 | } | 3457 | } |
3419 | } | 3458 | } |
@@ -3526,7 +3565,7 @@ static BcStatus dc_lex_token(BcLex *l) | |||
3526 | else if (c2 == '>') | 3565 | else if (c2 == '>') |
3527 | l->t.t = BC_LEX_OP_REL_GE; | 3566 | l->t.t = BC_LEX_OP_REL_GE; |
3528 | else | 3567 | else |
3529 | return bc_error("bad character '%c'", c); | 3568 | return bc_error_bad_character(c); |
3530 | 3569 | ||
3531 | ++l->i; | 3570 | ++l->i; |
3532 | break; | 3571 | break; |
@@ -3543,7 +3582,7 @@ static BcStatus dc_lex_token(BcLex *l) | |||
3543 | if (isdigit(l->buf[l->i])) | 3582 | if (isdigit(l->buf[l->i])) |
3544 | s = bc_lex_number(l, c); | 3583 | s = bc_lex_number(l, c); |
3545 | else | 3584 | else |
3546 | s = bc_error("bad character '%c'", c); | 3585 | s = bc_error_bad_character(c); |
3547 | break; | 3586 | break; |
3548 | } | 3587 | } |
3549 | 3588 | ||
@@ -3577,7 +3616,7 @@ static BcStatus dc_lex_token(BcLex *l) | |||
3577 | default: | 3616 | default: |
3578 | { | 3617 | { |
3579 | l->t.t = BC_LEX_INVALID; | 3618 | l->t.t = BC_LEX_INVALID; |
3580 | s = bc_error("bad character '%c'", c); | 3619 | s = bc_error_bad_character(c); |
3581 | break; | 3620 | break; |
3582 | } | 3621 | } |
3583 | } | 3622 | } |
@@ -3733,7 +3772,7 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) | |||
3733 | BcLexType top; | 3772 | BcLexType top; |
3734 | 3773 | ||
3735 | if (p->ops.len <= ops_bgn) | 3774 | if (p->ops.len <= ops_bgn) |
3736 | return bc_error("bad expression"); | 3775 | return bc_error_bad_expression(); |
3737 | top = BC_PARSE_TOP_OP(p); | 3776 | top = BC_PARSE_TOP_OP(p); |
3738 | 3777 | ||
3739 | while (top != BC_LEX_LPAREN) { | 3778 | while (top != BC_LEX_LPAREN) { |
@@ -3744,7 +3783,7 @@ static BcStatus bc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) | |||
3744 | *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; | 3783 | *nexs -= top != BC_LEX_OP_BOOL_NOT && top != BC_LEX_NEG; |
3745 | 3784 | ||
3746 | if (p->ops.len <= ops_bgn) | 3785 | if (p->ops.len <= ops_bgn) |
3747 | return bc_error("bad expression"); | 3786 | return bc_error_bad_expression(); |
3748 | top = BC_PARSE_TOP_OP(p); | 3787 | top = BC_PARSE_TOP_OP(p); |
3749 | } | 3788 | } |
3750 | 3789 | ||
@@ -3775,7 +3814,7 @@ static BcStatus bc_parse_params(BcParse *p, uint8_t flags) | |||
3775 | } | 3814 | } |
3776 | } | 3815 | } |
3777 | 3816 | ||
3778 | if (comma) return bc_error("bad token"); | 3817 | if (comma) return bc_error_bad_token(); |
3779 | bc_parse_push(p, BC_INST_CALL); | 3818 | bc_parse_push(p, BC_INST_CALL); |
3780 | bc_parse_pushIndex(p, nparams); | 3819 | bc_parse_pushIndex(p, nparams); |
3781 | 3820 | ||
@@ -3794,7 +3833,7 @@ static BcStatus bc_parse_call(BcParse *p, char *name, uint8_t flags) | |||
3794 | if (s) goto err; | 3833 | if (s) goto err; |
3795 | 3834 | ||
3796 | if (p->l.t.t != BC_LEX_RPAREN) { | 3835 | if (p->l.t.t != BC_LEX_RPAREN) { |
3797 | s = bc_error("bad token"); | 3836 | s = bc_error_bad_token(); |
3798 | goto err; | 3837 | goto err; |
3799 | } | 3838 | } |
3800 | 3839 | ||
@@ -3836,7 +3875,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) | |||
3836 | if (p->l.t.t == BC_LEX_RBRACKET) { | 3875 | if (p->l.t.t == BC_LEX_RBRACKET) { |
3837 | 3876 | ||
3838 | if (!(flags & BC_PARSE_ARRAY)) { | 3877 | if (!(flags & BC_PARSE_ARRAY)) { |
3839 | s = bc_error("bad expression"); | 3878 | s = bc_error_bad_expression(); |
3840 | goto err; | 3879 | goto err; |
3841 | } | 3880 | } |
3842 | 3881 | ||
@@ -3859,7 +3898,7 @@ static BcStatus bc_parse_name(BcParse *p, BcInst *type, uint8_t flags) | |||
3859 | else if (p->l.t.t == BC_LEX_LPAREN) { | 3898 | else if (p->l.t.t == BC_LEX_LPAREN) { |
3860 | 3899 | ||
3861 | if (flags & BC_PARSE_NOCALL) { | 3900 | if (flags & BC_PARSE_NOCALL) { |
3862 | s = bc_error("bad token"); | 3901 | s = bc_error_bad_token(); |
3863 | goto err; | 3902 | goto err; |
3864 | } | 3903 | } |
3865 | 3904 | ||
@@ -3885,11 +3924,11 @@ static BcStatus bc_parse_read(BcParse *p) | |||
3885 | 3924 | ||
3886 | s = bc_lex_next(&p->l); | 3925 | s = bc_lex_next(&p->l); |
3887 | if (s) return s; | 3926 | if (s) return s; |
3888 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); | 3927 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); |
3889 | 3928 | ||
3890 | s = bc_lex_next(&p->l); | 3929 | s = bc_lex_next(&p->l); |
3891 | if (s) return s; | 3930 | if (s) return s; |
3892 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); | 3931 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); |
3893 | 3932 | ||
3894 | bc_parse_push(p, BC_INST_READ); | 3933 | bc_parse_push(p, BC_INST_READ); |
3895 | 3934 | ||
@@ -3903,7 +3942,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, | |||
3903 | 3942 | ||
3904 | s = bc_lex_next(&p->l); | 3943 | s = bc_lex_next(&p->l); |
3905 | if (s) return s; | 3944 | if (s) return s; |
3906 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); | 3945 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); |
3907 | 3946 | ||
3908 | flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; | 3947 | flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; |
3909 | 3948 | ||
@@ -3913,7 +3952,7 @@ static BcStatus bc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, | |||
3913 | s = bc_parse_expr(p, flags, bc_parse_next_rel); | 3952 | s = bc_parse_expr(p, flags, bc_parse_next_rel); |
3914 | if (s) return s; | 3953 | if (s) return s; |
3915 | 3954 | ||
3916 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); | 3955 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); |
3917 | 3956 | ||
3918 | *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; | 3957 | *prev = (type == BC_LEX_KEY_LENGTH) ? BC_INST_LENGTH : BC_INST_SQRT; |
3919 | bc_parse_push(p, *prev); | 3958 | bc_parse_push(p, *prev); |
@@ -3942,7 +3981,7 @@ static BcStatus bc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) | |||
3942 | 3981 | ||
3943 | s = bc_parse_expr(p, flags, bc_parse_next_rel); | 3982 | s = bc_parse_expr(p, flags, bc_parse_next_rel); |
3944 | if (s) return s; | 3983 | if (s) return s; |
3945 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); | 3984 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); |
3946 | bc_parse_push(p, BC_INST_SCALE_FUNC); | 3985 | bc_parse_push(p, BC_INST_SCALE_FUNC); |
3947 | 3986 | ||
3948 | return bc_lex_next(&p->l); | 3987 | return bc_lex_next(&p->l); |
@@ -3999,7 +4038,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, | |||
3999 | s = bc_lex_next(&p->l); | 4038 | s = bc_lex_next(&p->l); |
4000 | if (s) return s; | 4039 | if (s) return s; |
4001 | if (p->l.t.t == BC_LEX_LPAREN) | 4040 | if (p->l.t.t == BC_LEX_LPAREN) |
4002 | s = bc_error("bad token"); | 4041 | s = bc_error_bad_token(); |
4003 | else | 4042 | else |
4004 | bc_parse_push(p, BC_INST_SCALE); | 4043 | bc_parse_push(p, BC_INST_SCALE); |
4005 | break; | 4044 | break; |
@@ -4007,7 +4046,7 @@ static BcStatus bc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, | |||
4007 | 4046 | ||
4008 | default: | 4047 | default: |
4009 | { | 4048 | { |
4010 | s = bc_error("bad token"); | 4049 | s = bc_error_bad_token(); |
4011 | break; | 4050 | break; |
4012 | } | 4051 | } |
4013 | } | 4052 | } |
@@ -4088,7 +4127,7 @@ static BcStatus bc_parse_print(BcParse *p) | |||
4088 | } | 4127 | } |
4089 | 4128 | ||
4090 | if (s) return s; | 4129 | if (s) return s; |
4091 | if (comma) return bc_error("bad token"); | 4130 | if (comma) return bc_error_bad_token(); |
4092 | 4131 | ||
4093 | return bc_lex_next(&p->l); | 4132 | return bc_lex_next(&p->l); |
4094 | } | 4133 | } |
@@ -4099,7 +4138,7 @@ static BcStatus bc_parse_return(BcParse *p) | |||
4099 | BcLexType t; | 4138 | BcLexType t; |
4100 | bool paren; | 4139 | bool paren; |
4101 | 4140 | ||
4102 | if (!BC_PARSE_FUNC(p)) return bc_error("bad token"); | 4141 | if (!BC_PARSE_FUNC(p)) return bc_error_bad_token(); |
4103 | 4142 | ||
4104 | s = bc_lex_next(&p->l); | 4143 | s = bc_lex_next(&p->l); |
4105 | if (s) return s; | 4144 | if (s) return s; |
@@ -4137,18 +4176,18 @@ static BcStatus bc_parse_endBody(BcParse *p, bool brace) | |||
4137 | BcStatus s = BC_STATUS_SUCCESS; | 4176 | BcStatus s = BC_STATUS_SUCCESS; |
4138 | 4177 | ||
4139 | if (p->flags.len <= 1 || (brace && p->nbraces == 0)) | 4178 | if (p->flags.len <= 1 || (brace && p->nbraces == 0)) |
4140 | return bc_error("bad token"); | 4179 | return bc_error_bad_token(); |
4141 | 4180 | ||
4142 | if (brace) { | 4181 | if (brace) { |
4143 | 4182 | ||
4144 | if (p->l.t.t == BC_LEX_RBRACE) { | 4183 | if (p->l.t.t == BC_LEX_RBRACE) { |
4145 | if (!p->nbraces) return bc_error("bad token"); | 4184 | if (!p->nbraces) return bc_error_bad_token(); |
4146 | --p->nbraces; | 4185 | --p->nbraces; |
4147 | s = bc_lex_next(&p->l); | 4186 | s = bc_lex_next(&p->l); |
4148 | if (s) return s; | 4187 | if (s) return s; |
4149 | } | 4188 | } |
4150 | else | 4189 | else |
4151 | return bc_error("bad token"); | 4190 | return bc_error_bad_token(); |
4152 | } | 4191 | } |
4153 | 4192 | ||
4154 | if (BC_PARSE_IF(p)) { | 4193 | if (BC_PARSE_IF(p)) { |
@@ -4234,13 +4273,13 @@ static BcStatus bc_parse_if(BcParse *p) | |||
4234 | 4273 | ||
4235 | s = bc_lex_next(&p->l); | 4274 | s = bc_lex_next(&p->l); |
4236 | if (s) return s; | 4275 | if (s) return s; |
4237 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); | 4276 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); |
4238 | 4277 | ||
4239 | s = bc_lex_next(&p->l); | 4278 | s = bc_lex_next(&p->l); |
4240 | if (s) return s; | 4279 | if (s) return s; |
4241 | s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); | 4280 | s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); |
4242 | if (s) return s; | 4281 | if (s) return s; |
4243 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); | 4282 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); |
4244 | 4283 | ||
4245 | s = bc_lex_next(&p->l); | 4284 | s = bc_lex_next(&p->l); |
4246 | if (s) return s; | 4285 | if (s) return s; |
@@ -4261,7 +4300,7 @@ static BcStatus bc_parse_else(BcParse *p) | |||
4261 | { | 4300 | { |
4262 | BcInstPtr ip; | 4301 | BcInstPtr ip; |
4263 | 4302 | ||
4264 | if (!BC_PARSE_IF_END(p)) return bc_error("bad token"); | 4303 | if (!BC_PARSE_IF_END(p)) return bc_error_bad_token(); |
4265 | 4304 | ||
4266 | ip.idx = p->func->labels.len; | 4305 | ip.idx = p->func->labels.len; |
4267 | ip.func = ip.len = 0; | 4306 | ip.func = ip.len = 0; |
@@ -4285,7 +4324,7 @@ static BcStatus bc_parse_while(BcParse *p) | |||
4285 | 4324 | ||
4286 | s = bc_lex_next(&p->l); | 4325 | s = bc_lex_next(&p->l); |
4287 | if (s) return s; | 4326 | if (s) return s; |
4288 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); | 4327 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); |
4289 | s = bc_lex_next(&p->l); | 4328 | s = bc_lex_next(&p->l); |
4290 | if (s) return s; | 4329 | if (s) return s; |
4291 | 4330 | ||
@@ -4303,7 +4342,7 @@ static BcStatus bc_parse_while(BcParse *p) | |||
4303 | 4342 | ||
4304 | s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); | 4343 | s = bc_parse_expr(p, BC_PARSE_REL, bc_parse_next_rel); |
4305 | if (s) return s; | 4344 | if (s) return s; |
4306 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); | 4345 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); |
4307 | s = bc_lex_next(&p->l); | 4346 | s = bc_lex_next(&p->l); |
4308 | if (s) return s; | 4347 | if (s) return s; |
4309 | 4348 | ||
@@ -4322,7 +4361,7 @@ static BcStatus bc_parse_for(BcParse *p) | |||
4322 | 4361 | ||
4323 | s = bc_lex_next(&p->l); | 4362 | s = bc_lex_next(&p->l); |
4324 | if (s) return s; | 4363 | if (s) return s; |
4325 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error("bad token"); | 4364 | if (p->l.t.t != BC_LEX_LPAREN) return bc_error_bad_token(); |
4326 | s = bc_lex_next(&p->l); | 4365 | s = bc_lex_next(&p->l); |
4327 | if (s) return s; | 4366 | if (s) return s; |
4328 | 4367 | ||
@@ -4332,7 +4371,7 @@ static BcStatus bc_parse_for(BcParse *p) | |||
4332 | s = bc_posix_error("POSIX does not allow an empty init expression in a for loop"); | 4371 | s = bc_posix_error("POSIX does not allow an empty init expression in a for loop"); |
4333 | 4372 | ||
4334 | if (s) return s; | 4373 | if (s) return s; |
4335 | if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); | 4374 | if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); |
4336 | s = bc_lex_next(&p->l); | 4375 | s = bc_lex_next(&p->l); |
4337 | if (s) return s; | 4376 | if (s) return s; |
4338 | 4377 | ||
@@ -4349,7 +4388,7 @@ static BcStatus bc_parse_for(BcParse *p) | |||
4349 | s = bc_posix_error("POSIX does not allow an empty condition expression in a for loop"); | 4388 | s = bc_posix_error("POSIX does not allow an empty condition expression in a for loop"); |
4350 | 4389 | ||
4351 | if (s) return s; | 4390 | if (s) return s; |
4352 | if (p->l.t.t != BC_LEX_SCOLON) return bc_error("bad token"); | 4391 | if (p->l.t.t != BC_LEX_SCOLON) return bc_error_bad_token(); |
4353 | 4392 | ||
4354 | s = bc_lex_next(&p->l); | 4393 | s = bc_lex_next(&p->l); |
4355 | if (s) return s; | 4394 | if (s) return s; |
@@ -4371,7 +4410,7 @@ static BcStatus bc_parse_for(BcParse *p) | |||
4371 | 4410 | ||
4372 | if (s) return s; | 4411 | if (s) return s; |
4373 | 4412 | ||
4374 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error("bad token"); | 4413 | if (p->l.t.t != BC_LEX_RPAREN) return bc_error_bad_token(); |
4375 | bc_parse_push(p, BC_INST_JUMP); | 4414 | bc_parse_push(p, BC_INST_JUMP); |
4376 | bc_parse_pushIndex(p, cond_idx); | 4415 | bc_parse_pushIndex(p, cond_idx); |
4377 | bc_vec_push(&p->func->labels, &p->func->code.len); | 4416 | bc_vec_push(&p->func->labels, &p->func->code.len); |
@@ -4394,17 +4433,17 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) | |||
4394 | size_t i; | 4433 | size_t i; |
4395 | BcInstPtr *ip; | 4434 | BcInstPtr *ip; |
4396 | 4435 | ||
4397 | if (!BC_PARSE_LOOP(p)) return bc_error("bad token"); | 4436 | if (!BC_PARSE_LOOP(p)) return bc_error_bad_token(); |
4398 | 4437 | ||
4399 | if (type == BC_LEX_KEY_BREAK) { | 4438 | if (type == BC_LEX_KEY_BREAK) { |
4400 | 4439 | ||
4401 | if (p->exits.len == 0) return bc_error("bad token"); | 4440 | if (p->exits.len == 0) return bc_error_bad_token(); |
4402 | 4441 | ||
4403 | i = p->exits.len - 1; | 4442 | i = p->exits.len - 1; |
4404 | ip = bc_vec_item(&p->exits, i); | 4443 | ip = bc_vec_item(&p->exits, i); |
4405 | 4444 | ||
4406 | while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); | 4445 | while (!ip->func && i < p->exits.len) ip = bc_vec_item(&p->exits, i--); |
4407 | if (i >= p->exits.len && !ip->func) return bc_error("bad token"); | 4446 | if (i >= p->exits.len && !ip->func) return bc_error_bad_token(); |
4408 | 4447 | ||
4409 | i = ip->idx; | 4448 | i = ip->idx; |
4410 | } | 4449 | } |
@@ -4418,7 +4457,7 @@ static BcStatus bc_parse_loopExit(BcParse *p, BcLexType type) | |||
4418 | if (s) return s; | 4457 | if (s) return s; |
4419 | 4458 | ||
4420 | if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) | 4459 | if (p->l.t.t != BC_LEX_SCOLON && p->l.t.t != BC_LEX_NLINE) |
4421 | return bc_error("bad token"); | 4460 | return bc_error_bad_token(); |
4422 | 4461 | ||
4423 | return bc_lex_next(&p->l); | 4462 | return bc_lex_next(&p->l); |
4424 | } | 4463 | } |
@@ -4506,7 +4545,7 @@ static BcStatus bc_parse_auto(BcParse *p) | |||
4506 | bool comma, var, one; | 4545 | bool comma, var, one; |
4507 | char *name; | 4546 | char *name; |
4508 | 4547 | ||
4509 | if (!p->auto_part) return bc_error("bad token"); | 4548 | if (!p->auto_part) return bc_error_bad_token(); |
4510 | s = bc_lex_next(&p->l); | 4549 | s = bc_lex_next(&p->l); |
4511 | if (s) return s; | 4550 | if (s) return s; |
4512 | 4551 | ||
@@ -4548,7 +4587,7 @@ static BcStatus bc_parse_auto(BcParse *p) | |||
4548 | if (!one) return bc_error("no auto variable found"); | 4587 | if (!one) return bc_error("no auto variable found"); |
4549 | 4588 | ||
4550 | if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) | 4589 | if (p->l.t.t != BC_LEX_NLINE && p->l.t.t != BC_LEX_SCOLON) |
4551 | return bc_error("bad token"); | 4590 | return bc_error_bad_token(); |
4552 | 4591 | ||
4553 | return bc_lex_next(&p->l); | 4592 | return bc_lex_next(&p->l); |
4554 | 4593 | ||
@@ -4566,7 +4605,7 @@ static BcStatus bc_parse_body(BcParse *p, bool brace) | |||
4566 | 4605 | ||
4567 | if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { | 4606 | if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) { |
4568 | 4607 | ||
4569 | if (!brace) return bc_error("bad token"); | 4608 | if (!brace) return bc_error_bad_token(); |
4570 | p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; | 4609 | p->auto_part = p->l.t.t != BC_LEX_KEY_AUTO; |
4571 | 4610 | ||
4572 | if (!p->auto_part) { | 4611 | if (!p->auto_part) { |
@@ -4603,7 +4642,7 @@ static BcStatus bc_parse_stmt(BcParse *p) | |||
4603 | 4642 | ||
4604 | case BC_LEX_LBRACE: | 4643 | case BC_LEX_LBRACE: |
4605 | { | 4644 | { |
4606 | if (!BC_PARSE_BODY(p)) return bc_error("bad token"); | 4645 | if (!BC_PARSE_BODY(p)) return bc_error_bad_token(); |
4607 | 4646 | ||
4608 | ++p->nbraces; | 4647 | ++p->nbraces; |
4609 | s = bc_lex_next(&p->l); | 4648 | s = bc_lex_next(&p->l); |
@@ -4748,7 +4787,7 @@ static BcStatus bc_parse_stmt(BcParse *p) | |||
4748 | 4787 | ||
4749 | default: | 4788 | default: |
4750 | { | 4789 | { |
4751 | s = bc_error("bad token"); | 4790 | s = bc_error_bad_token(); |
4752 | break; | 4791 | break; |
4753 | } | 4792 | } |
4754 | } | 4793 | } |
@@ -4763,7 +4802,7 @@ static BcStatus bc_parse_parse(BcParse *p) | |||
4763 | if (p->l.t.t == BC_LEX_EOF) | 4802 | if (p->l.t.t == BC_LEX_EOF) |
4764 | s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); | 4803 | s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); |
4765 | else if (p->l.t.t == BC_LEX_KEY_DEFINE) { | 4804 | else if (p->l.t.t == BC_LEX_KEY_DEFINE) { |
4766 | if (!BC_PARSE_CAN_EXEC(p)) return bc_error("bad token"); | 4805 | if (!BC_PARSE_CAN_EXEC(p)) return bc_error_bad_token(); |
4767 | s = bc_parse_func(p); | 4806 | s = bc_parse_func(p); |
4768 | } | 4807 | } |
4769 | else | 4808 | else |
@@ -4849,7 +4888,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4849 | if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) | 4888 | if (((t == BC_LEX_OP_BOOL_NOT) != bin_last) |
4850 | || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT) | 4889 | || (t != BC_LEX_OP_BOOL_NOT && prev == BC_INST_BOOL_NOT) |
4851 | ) { | 4890 | ) { |
4852 | return bc_error("bad expression"); | 4891 | return bc_error_bad_expression(); |
4853 | } | 4892 | } |
4854 | 4893 | ||
4855 | nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; | 4894 | nrelops += t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT; |
@@ -4864,7 +4903,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4864 | case BC_LEX_LPAREN: | 4903 | case BC_LEX_LPAREN: |
4865 | { | 4904 | { |
4866 | if (BC_PARSE_LEAF(prev, rprn)) | 4905 | if (BC_PARSE_LEAF(prev, rprn)) |
4867 | return bc_error("bad expression"); | 4906 | return bc_error_bad_expression(); |
4868 | ++nparens; | 4907 | ++nparens; |
4869 | paren_expr = rprn = bin_last = false; | 4908 | paren_expr = rprn = bin_last = false; |
4870 | get_token = true; | 4909 | get_token = true; |
@@ -4876,7 +4915,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4876 | case BC_LEX_RPAREN: | 4915 | case BC_LEX_RPAREN: |
4877 | { | 4916 | { |
4878 | if (bin_last || prev == BC_INST_BOOL_NOT) | 4917 | if (bin_last || prev == BC_INST_BOOL_NOT) |
4879 | return bc_error("bad expression"); | 4918 | return bc_error_bad_expression(); |
4880 | 4919 | ||
4881 | if (nparens == 0) { | 4920 | if (nparens == 0) { |
4882 | s = BC_STATUS_SUCCESS; | 4921 | s = BC_STATUS_SUCCESS; |
@@ -4899,7 +4938,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4899 | case BC_LEX_NAME: | 4938 | case BC_LEX_NAME: |
4900 | { | 4939 | { |
4901 | if (BC_PARSE_LEAF(prev, rprn)) | 4940 | if (BC_PARSE_LEAF(prev, rprn)) |
4902 | return bc_error("bad expression"); | 4941 | return bc_error_bad_expression(); |
4903 | paren_expr = true; | 4942 | paren_expr = true; |
4904 | rprn = get_token = bin_last = false; | 4943 | rprn = get_token = bin_last = false; |
4905 | s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); | 4944 | s = bc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); |
@@ -4911,7 +4950,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4911 | case BC_LEX_NUMBER: | 4950 | case BC_LEX_NUMBER: |
4912 | { | 4951 | { |
4913 | if (BC_PARSE_LEAF(prev, rprn)) | 4952 | if (BC_PARSE_LEAF(prev, rprn)) |
4914 | return bc_error("bad expression"); | 4953 | return bc_error_bad_expression(); |
4915 | bc_parse_number(p, &prev, &nexprs); | 4954 | bc_parse_number(p, &prev, &nexprs); |
4916 | paren_expr = get_token = true; | 4955 | paren_expr = get_token = true; |
4917 | rprn = bin_last = false; | 4956 | rprn = bin_last = false; |
@@ -4924,7 +4963,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4924 | case BC_LEX_KEY_OBASE: | 4963 | case BC_LEX_KEY_OBASE: |
4925 | { | 4964 | { |
4926 | if (BC_PARSE_LEAF(prev, rprn)) | 4965 | if (BC_PARSE_LEAF(prev, rprn)) |
4927 | return bc_error("bad expression"); | 4966 | return bc_error_bad_expression(); |
4928 | prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); | 4967 | prev = (char) (t - BC_LEX_KEY_IBASE + BC_INST_IBASE); |
4929 | bc_parse_push(p, (char) prev); | 4968 | bc_parse_push(p, (char) prev); |
4930 | 4969 | ||
@@ -4939,7 +4978,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4939 | case BC_LEX_KEY_SQRT: | 4978 | case BC_LEX_KEY_SQRT: |
4940 | { | 4979 | { |
4941 | if (BC_PARSE_LEAF(prev, rprn)) | 4980 | if (BC_PARSE_LEAF(prev, rprn)) |
4942 | return bc_error("bad expression"); | 4981 | return bc_error_bad_expression(); |
4943 | s = bc_parse_builtin(p, t, flags, &prev); | 4982 | s = bc_parse_builtin(p, t, flags, &prev); |
4944 | paren_expr = true; | 4983 | paren_expr = true; |
4945 | rprn = get_token = bin_last = false; | 4984 | rprn = get_token = bin_last = false; |
@@ -4951,9 +4990,9 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4951 | case BC_LEX_KEY_READ: | 4990 | case BC_LEX_KEY_READ: |
4952 | { | 4991 | { |
4953 | if (BC_PARSE_LEAF(prev, rprn)) | 4992 | if (BC_PARSE_LEAF(prev, rprn)) |
4954 | return bc_error("bad expression"); | 4993 | return bc_error_bad_expression(); |
4955 | else if (flags & BC_PARSE_NOREAD) | 4994 | else if (flags & BC_PARSE_NOREAD) |
4956 | s = bc_error("read() call inside of a read() call"); | 4995 | s = bc_error_nested_read_call(); |
4957 | else | 4996 | else |
4958 | s = bc_parse_read(p); | 4997 | s = bc_parse_read(p); |
4959 | 4998 | ||
@@ -4968,7 +5007,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4968 | case BC_LEX_KEY_SCALE: | 5007 | case BC_LEX_KEY_SCALE: |
4969 | { | 5008 | { |
4970 | if (BC_PARSE_LEAF(prev, rprn)) | 5009 | if (BC_PARSE_LEAF(prev, rprn)) |
4971 | return bc_error("bad expression"); | 5010 | return bc_error_bad_expression(); |
4972 | s = bc_parse_scale(p, &prev, flags); | 5011 | s = bc_parse_scale(p, &prev, flags); |
4973 | paren_expr = true; | 5012 | paren_expr = true; |
4974 | rprn = get_token = bin_last = false; | 5013 | rprn = get_token = bin_last = false; |
@@ -4980,7 +5019,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4980 | 5019 | ||
4981 | default: | 5020 | default: |
4982 | { | 5021 | { |
4983 | s = bc_error("bad token"); | 5022 | s = bc_error_bad_token(); |
4984 | break; | 5023 | break; |
4985 | } | 5024 | } |
4986 | } | 5025 | } |
@@ -4997,7 +5036,7 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
4997 | assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; | 5036 | assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN; |
4998 | 5037 | ||
4999 | if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) | 5038 | if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) |
5000 | return bc_error("bad expression"); | 5039 | return bc_error_bad_expression(); |
5001 | 5040 | ||
5002 | bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); | 5041 | bc_parse_push(p, BC_PARSE_TOKEN_INST(top)); |
5003 | 5042 | ||
@@ -5006,12 +5045,12 @@ static BcStatus bc_parse_expr(BcParse *p, uint8_t flags, BcParseNext next) | |||
5006 | } | 5045 | } |
5007 | 5046 | ||
5008 | if (prev == BC_INST_BOOL_NOT || nexprs != 1) | 5047 | if (prev == BC_INST_BOOL_NOT || nexprs != 1) |
5009 | return bc_error("bad expression"); | 5048 | return bc_error_bad_expression(); |
5010 | 5049 | ||
5011 | for (i = 0; i < next.len; ++i) | 5050 | for (i = 0; i < next.len; ++i) |
5012 | if (t == next.tokens[i]) | 5051 | if (t == next.tokens[i]) |
5013 | goto ok; | 5052 | goto ok; |
5014 | return bc_error("bad expression"); | 5053 | return bc_error_bad_expression(); |
5015 | ok: | 5054 | ok: |
5016 | 5055 | ||
5017 | if (!(flags & BC_PARSE_REL) && nrelops) { | 5056 | if (!(flags & BC_PARSE_REL) && nrelops) { |
@@ -5050,7 +5089,7 @@ static BcStatus dc_parse_register(BcParse *p) | |||
5050 | 5089 | ||
5051 | s = bc_lex_next(&p->l); | 5090 | s = bc_lex_next(&p->l); |
5052 | if (s) return s; | 5091 | if (s) return s; |
5053 | if (p->l.t.t != BC_LEX_NAME) return bc_error("bad token"); | 5092 | if (p->l.t.t != BC_LEX_NAME) return bc_error_bad_token(); |
5054 | 5093 | ||
5055 | name = xstrdup(p->l.t.v.v); | 5094 | name = xstrdup(p->l.t.v.v); |
5056 | bc_parse_pushName(p, name); | 5095 | bc_parse_pushName(p, name); |
@@ -5158,7 +5197,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) | |||
5158 | s = bc_lex_next(&p->l); | 5197 | s = bc_lex_next(&p->l); |
5159 | if (s) return s; | 5198 | if (s) return s; |
5160 | if (p->l.t.t != BC_LEX_NUMBER) | 5199 | if (p->l.t.t != BC_LEX_NUMBER) |
5161 | return bc_error("bad token"); | 5200 | return bc_error_bad_token(); |
5162 | } | 5201 | } |
5163 | 5202 | ||
5164 | bc_parse_number(p, &prev, &p->nbraces); | 5203 | bc_parse_number(p, &prev, &p->nbraces); |
@@ -5172,7 +5211,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) | |||
5172 | case BC_LEX_KEY_READ: | 5211 | case BC_LEX_KEY_READ: |
5173 | { | 5212 | { |
5174 | if (flags & BC_PARSE_NOREAD) | 5213 | if (flags & BC_PARSE_NOREAD) |
5175 | s = bc_error("read() call inside of a read() call"); | 5214 | s = bc_error_nested_read_call(); |
5176 | else | 5215 | else |
5177 | bc_parse_push(p, BC_INST_READ); | 5216 | bc_parse_push(p, BC_INST_READ); |
5178 | get_token = true; | 5217 | get_token = true; |
@@ -5207,7 +5246,7 @@ static BcStatus dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) | |||
5207 | 5246 | ||
5208 | default: | 5247 | default: |
5209 | { | 5248 | { |
5210 | s = bc_error("bad token"); | 5249 | s = bc_error_bad_token(); |
5211 | get_token = true; | 5250 | get_token = true; |
5212 | break; | 5251 | break; |
5213 | } | 5252 | } |
@@ -5393,7 +5432,7 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, | |||
5393 | BcResultType lt, rt; | 5432 | BcResultType lt, rt; |
5394 | 5433 | ||
5395 | if (!BC_PROG_STACK(&G.prog.results, 2)) | 5434 | if (!BC_PROG_STACK(&G.prog.results, 2)) |
5396 | return bc_error("stack has too few elements"); | 5435 | return bc_error_stack_has_too_few_elements(); |
5397 | 5436 | ||
5398 | *r = bc_vec_item_rev(&G.prog.results, 0); | 5437 | *r = bc_vec_item_rev(&G.prog.results, 0); |
5399 | *l = bc_vec_item_rev(&G.prog.results, 1); | 5438 | *l = bc_vec_item_rev(&G.prog.results, 1); |
@@ -5415,9 +5454,9 @@ static BcStatus bc_program_binOpPrep(BcResult **l, BcNum **ln, | |||
5415 | } | 5454 | } |
5416 | 5455 | ||
5417 | if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) | 5456 | if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != BC_RESULT_VAR)) |
5418 | return bc_error("variable is wrong type"); | 5457 | return bc_error_variable_is_wrong_type(); |
5419 | if (!assign && !BC_PROG_NUM((*r), (*ln))) | 5458 | if (!assign && !BC_PROG_NUM((*r), (*ln))) |
5420 | return bc_error("variable is wrong type"); | 5459 | return bc_error_variable_is_wrong_type(); |
5421 | 5460 | ||
5422 | return s; | 5461 | return s; |
5423 | } | 5462 | } |
@@ -5435,14 +5474,14 @@ static BcStatus bc_program_prep(BcResult **r, BcNum **n) | |||
5435 | BcStatus s; | 5474 | BcStatus s; |
5436 | 5475 | ||
5437 | if (!BC_PROG_STACK(&G.prog.results, 1)) | 5476 | if (!BC_PROG_STACK(&G.prog.results, 1)) |
5438 | return bc_error("stack has too few elements"); | 5477 | return bc_error_stack_has_too_few_elements(); |
5439 | *r = bc_vec_top(&G.prog.results); | 5478 | *r = bc_vec_top(&G.prog.results); |
5440 | 5479 | ||
5441 | s = bc_program_num(*r, n, false); | 5480 | s = bc_program_num(*r, n, false); |
5442 | if (s) return s; | 5481 | if (s) return s; |
5443 | 5482 | ||
5444 | if (!BC_PROG_NUM((*r), (*n))) | 5483 | if (!BC_PROG_NUM((*r), (*n))) |
5445 | return bc_error("variable is wrong type"); | 5484 | return bc_error_variable_is_wrong_type(); |
5446 | 5485 | ||
5447 | return s; | 5486 | return s; |
5448 | } | 5487 | } |
@@ -5487,7 +5526,7 @@ static BcStatus bc_program_read(void) | |||
5487 | for (i = 0; i < G.prog.stack.len; ++i) { | 5526 | for (i = 0; i < G.prog.stack.len; ++i) { |
5488 | BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); | 5527 | BcInstPtr *ip_ptr = bc_vec_item(&G.prog.stack, i); |
5489 | if (ip_ptr->func == BC_PROG_READ) | 5528 | if (ip_ptr->func == BC_PROG_READ) |
5490 | return bc_error("read() call inside of a read() call"); | 5529 | return bc_error_nested_read_call(); |
5491 | } | 5530 | } |
5492 | 5531 | ||
5493 | bc_vec_pop_all(&f->code); | 5532 | bc_vec_pop_all(&f->code); |
@@ -5649,7 +5688,7 @@ static BcStatus bc_program_print(char inst, size_t idx) | |||
5649 | bool pop = inst != BC_INST_PRINT; | 5688 | bool pop = inst != BC_INST_PRINT; |
5650 | 5689 | ||
5651 | if (!BC_PROG_STACK(&G.prog.results, idx + 1)) | 5690 | if (!BC_PROG_STACK(&G.prog.results, idx + 1)) |
5652 | return bc_error("stack has too few elements"); | 5691 | return bc_error_stack_has_too_few_elements(); |
5653 | 5692 | ||
5654 | r = bc_vec_item_rev(&G.prog.results, idx); | 5693 | r = bc_vec_item_rev(&G.prog.results, idx); |
5655 | s = bc_program_num(r, &num, false); | 5694 | s = bc_program_num(r, &num, false); |
@@ -5781,7 +5820,7 @@ static BcStatus bc_program_assignStr(BcResult *r, BcVec *v, | |||
5781 | 5820 | ||
5782 | if (!push) { | 5821 | if (!push) { |
5783 | if (!BC_PROG_STACK(&G.prog.results, 2)) | 5822 | if (!BC_PROG_STACK(&G.prog.results, 2)) |
5784 | return bc_error("stack has too few elements"); | 5823 | return bc_error_stack_has_too_few_elements(); |
5785 | bc_vec_pop(v); | 5824 | bc_vec_pop(v); |
5786 | bc_vec_pop(&G.prog.results); | 5825 | bc_vec_pop(&G.prog.results); |
5787 | } | 5826 | } |
@@ -5803,16 +5842,16 @@ static BcStatus bc_program_copyToVar(char *name, bool var) | |||
5803 | BcNum *n; | 5842 | BcNum *n; |
5804 | 5843 | ||
5805 | if (!BC_PROG_STACK(&G.prog.results, 1)) | 5844 | if (!BC_PROG_STACK(&G.prog.results, 1)) |
5806 | return bc_error("stack has too few elements"); | 5845 | return bc_error_stack_has_too_few_elements(); |
5807 | 5846 | ||
5808 | ptr = bc_vec_top(&G.prog.results); | 5847 | ptr = bc_vec_top(&G.prog.results); |
5809 | if ((ptr->t == BC_RESULT_ARRAY) != !var) | 5848 | if ((ptr->t == BC_RESULT_ARRAY) != !var) |
5810 | return bc_error("variable is wrong type"); | 5849 | return bc_error_variable_is_wrong_type(); |
5811 | v = bc_program_search(name, var); | 5850 | v = bc_program_search(name, var); |
5812 | 5851 | ||
5813 | #if ENABLE_DC | 5852 | #if ENABLE_DC |
5814 | if (ptr->t == BC_RESULT_STR && !var) | 5853 | if (ptr->t == BC_RESULT_STR && !var) |
5815 | return bc_error("variable is wrong type"); | 5854 | return bc_error_variable_is_wrong_type(); |
5816 | if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true); | 5855 | if (ptr->t == BC_RESULT_STR) return bc_program_assignStr(ptr, v, true); |
5817 | #endif | 5856 | #endif |
5818 | 5857 | ||
@@ -5858,7 +5897,7 @@ static BcStatus bc_program_assign(char inst) | |||
5858 | BcVec *v; | 5897 | BcVec *v; |
5859 | 5898 | ||
5860 | if (left->t != BC_RESULT_VAR) | 5899 | if (left->t != BC_RESULT_VAR) |
5861 | return bc_error("variable is wrong type"); | 5900 | return bc_error_variable_is_wrong_type(); |
5862 | v = bc_program_search(left->d.id.name, true); | 5901 | v = bc_program_search(left->d.id.name, true); |
5863 | 5902 | ||
5864 | return bc_program_assignStr(right, v, false); | 5903 | return bc_program_assignStr(right, v, false); |
@@ -5952,7 +5991,7 @@ static BcStatus bc_program_pushVar(char *code, size_t *bgn, | |||
5952 | 5991 | ||
5953 | if (!BC_PROG_STACK(v, 2 - copy)) { | 5992 | if (!BC_PROG_STACK(v, 2 - copy)) { |
5954 | free(name); | 5993 | free(name); |
5955 | return bc_error("stack has too few elements"); | 5994 | return bc_error_stack_has_too_few_elements(); |
5956 | } | 5995 | } |
5957 | 5996 | ||
5958 | free(name); | 5997 | free(name); |
@@ -6068,7 +6107,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) | |||
6068 | return bc_error("undefined function"); | 6107 | return bc_error("undefined function"); |
6069 | } | 6108 | } |
6070 | if (nparams != func->nparams) { | 6109 | if (nparams != func->nparams) { |
6071 | return bc_error("function has %u parameters, but called with %u", func->nparams, nparams); | 6110 | return bc_error_fmt("function has %u parameters, but called with %u", func->nparams, nparams); |
6072 | } | 6111 | } |
6073 | ip.len = G.prog.results.len - nparams; | 6112 | ip.len = G.prog.results.len - nparams; |
6074 | 6113 | ||
@@ -6078,7 +6117,7 @@ static BcStatus bc_program_call(char *code, size_t *idx) | |||
6078 | arg = bc_vec_top(&G.prog.results); | 6117 | arg = bc_vec_top(&G.prog.results); |
6079 | 6118 | ||
6080 | if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) | 6119 | if ((!a->idx) != (arg->t == BC_RESULT_ARRAY) || arg->t == BC_RESULT_STR) |
6081 | return bc_error("variable is wrong type"); | 6120 | return bc_error_variable_is_wrong_type(); |
6082 | 6121 | ||
6083 | s = bc_program_copyToVar(a->name, a->idx); | 6122 | s = bc_program_copyToVar(a->name, a->idx); |
6084 | if (s) return s; | 6123 | if (s) return s; |
@@ -6114,7 +6153,7 @@ static BcStatus bc_program_return(char inst) | |||
6114 | BcInstPtr *ip = bc_vec_top(&G.prog.stack); | 6153 | BcInstPtr *ip = bc_vec_top(&G.prog.stack); |
6115 | 6154 | ||
6116 | if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) | 6155 | if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) |
6117 | return bc_error("stack has too few elements"); | 6156 | return bc_error_stack_has_too_few_elements(); |
6118 | 6157 | ||
6119 | f = bc_vec_item(&G.prog.fns, ip->func); | 6158 | f = bc_vec_item(&G.prog.fns, ip->func); |
6120 | res.t = BC_RESULT_TEMP; | 6159 | res.t = BC_RESULT_TEMP; |
@@ -6177,7 +6216,7 @@ static BcStatus bc_program_builtin(char inst) | |||
6177 | bool len = inst == BC_INST_LENGTH; | 6216 | bool len = inst == BC_INST_LENGTH; |
6178 | 6217 | ||
6179 | if (!BC_PROG_STACK(&G.prog.results, 1)) | 6218 | if (!BC_PROG_STACK(&G.prog.results, 1)) |
6180 | return bc_error("stack has too few elements"); | 6219 | return bc_error_stack_has_too_few_elements(); |
6181 | opnd = bc_vec_top(&G.prog.results); | 6220 | opnd = bc_vec_top(&G.prog.results); |
6182 | 6221 | ||
6183 | s = bc_program_num(opnd, &num, false); | 6222 | s = bc_program_num(opnd, &num, false); |
@@ -6185,7 +6224,7 @@ static BcStatus bc_program_builtin(char inst) | |||
6185 | 6224 | ||
6186 | #if ENABLE_DC | 6225 | #if ENABLE_DC |
6187 | if (!BC_PROG_NUM(opnd, num) && !len) | 6226 | if (!BC_PROG_NUM(opnd, num) && !len) |
6188 | return bc_error("variable is wrong type"); | 6227 | return bc_error_variable_is_wrong_type(); |
6189 | #endif | 6228 | #endif |
6190 | 6229 | ||
6191 | bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); | 6230 | bc_num_init(&res.d.n, BC_NUM_DEF_SIZE); |
@@ -6251,7 +6290,7 @@ static BcStatus bc_program_modexp(void) | |||
6251 | BcNum *n1, *n2, *n3; | 6290 | BcNum *n1, *n2, *n3; |
6252 | 6291 | ||
6253 | if (!BC_PROG_STACK(&G.prog.results, 3)) | 6292 | if (!BC_PROG_STACK(&G.prog.results, 3)) |
6254 | return bc_error("stack has too few elements"); | 6293 | return bc_error_stack_has_too_few_elements(); |
6255 | s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false); | 6294 | s = bc_program_binOpPrep(&r2, &n2, &r3, &n3, false); |
6256 | if (s) return s; | 6295 | if (s) return s; |
6257 | 6296 | ||
@@ -6259,7 +6298,7 @@ static BcStatus bc_program_modexp(void) | |||
6259 | s = bc_program_num(r1, &n1, false); | 6298 | s = bc_program_num(r1, &n1, false); |
6260 | if (s) return s; | 6299 | if (s) return s; |
6261 | if (!BC_PROG_NUM(r1, n1)) | 6300 | if (!BC_PROG_NUM(r1, n1)) |
6262 | return bc_error("variable is wrong type"); | 6301 | return bc_error_variable_is_wrong_type(); |
6263 | 6302 | ||
6264 | // Make sure that the values have their pointers updated, if necessary. | 6303 | // Make sure that the values have their pointers updated, if necessary. |
6265 | if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { | 6304 | if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) { |
@@ -6311,7 +6350,7 @@ static BcStatus bc_program_asciify(void) | |||
6311 | unsigned long val; | 6350 | unsigned long val; |
6312 | 6351 | ||
6313 | if (!BC_PROG_STACK(&G.prog.results, 1)) | 6352 | if (!BC_PROG_STACK(&G.prog.results, 1)) |
6314 | return bc_error("stack has too few elements"); | 6353 | return bc_error_stack_has_too_few_elements(); |
6315 | r = bc_vec_top(&G.prog.results); | 6354 | r = bc_vec_top(&G.prog.results); |
6316 | 6355 | ||
6317 | s = bc_program_num(r, &num, false); | 6356 | s = bc_program_num(r, &num, false); |
@@ -6380,7 +6419,7 @@ static BcStatus bc_program_printStream(void) | |||
6380 | char *str; | 6419 | char *str; |
6381 | 6420 | ||
6382 | if (!BC_PROG_STACK(&G.prog.results, 1)) | 6421 | if (!BC_PROG_STACK(&G.prog.results, 1)) |
6383 | return bc_error("stack has too few elements"); | 6422 | return bc_error_stack_has_too_few_elements(); |
6384 | r = bc_vec_top(&G.prog.results); | 6423 | r = bc_vec_top(&G.prog.results); |
6385 | 6424 | ||
6386 | s = bc_program_num(r, &n, false); | 6425 | s = bc_program_num(r, &n, false); |
@@ -6412,7 +6451,7 @@ static BcStatus bc_program_nquit(void) | |||
6412 | bc_vec_pop(&G.prog.results); | 6451 | bc_vec_pop(&G.prog.results); |
6413 | 6452 | ||
6414 | if (G.prog.stack.len < val) | 6453 | if (G.prog.stack.len < val) |
6415 | return bc_error("stack has too few elements"); | 6454 | return bc_error_stack_has_too_few_elements(); |
6416 | if (G.prog.stack.len == val) | 6455 | if (G.prog.stack.len == val) |
6417 | quit(); | 6456 | quit(); |
6418 | 6457 | ||
@@ -6435,7 +6474,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, | |||
6435 | bool exec; | 6474 | bool exec; |
6436 | 6475 | ||
6437 | if (!BC_PROG_STACK(&G.prog.results, 1)) | 6476 | if (!BC_PROG_STACK(&G.prog.results, 1)) |
6438 | return bc_error("stack has too few elements"); | 6477 | return bc_error_stack_has_too_few_elements(); |
6439 | 6478 | ||
6440 | r = bc_vec_top(&G.prog.results); | 6479 | r = bc_vec_top(&G.prog.results); |
6441 | 6480 | ||
@@ -6468,7 +6507,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, | |||
6468 | 6507 | ||
6469 | if (!exec) goto exit; | 6508 | if (!exec) goto exit; |
6470 | if (!BC_PROG_STR(n)) { | 6509 | if (!BC_PROG_STR(n)) { |
6471 | s = bc_error("variable is wrong type"); | 6510 | s = bc_error_variable_is_wrong_type(); |
6472 | goto exit; | 6511 | goto exit; |
6473 | } | 6512 | } |
6474 | 6513 | ||
@@ -6500,7 +6539,7 @@ static BcStatus bc_program_execStr(char *code, size_t *bgn, | |||
6500 | if (s) goto err; | 6539 | if (s) goto err; |
6501 | 6540 | ||
6502 | if (prs.l.t.t != BC_LEX_EOF) { | 6541 | if (prs.l.t.t != BC_LEX_EOF) { |
6503 | s = bc_error("bad expression"); | 6542 | s = bc_error_bad_expression(); |
6504 | goto err; | 6543 | goto err; |
6505 | } | 6544 | } |
6506 | 6545 | ||
@@ -6723,7 +6762,7 @@ static BcStatus bc_program_exec(void) | |||
6723 | case BC_INST_POP: | 6762 | case BC_INST_POP: |
6724 | { | 6763 | { |
6725 | if (!BC_PROG_STACK(&G.prog.results, 1)) | 6764 | if (!BC_PROG_STACK(&G.prog.results, 1)) |
6726 | s = bc_error("stack has too few elements"); | 6765 | s = bc_error_stack_has_too_few_elements(); |
6727 | else | 6766 | else |
6728 | bc_vec_pop(&G.prog.results); | 6767 | bc_vec_pop(&G.prog.results); |
6729 | break; | 6768 | break; |
@@ -6836,7 +6875,7 @@ static BcStatus bc_program_exec(void) | |||
6836 | case BC_INST_DUPLICATE: | 6875 | case BC_INST_DUPLICATE: |
6837 | { | 6876 | { |
6838 | if (!BC_PROG_STACK(&G.prog.results, 1)) | 6877 | if (!BC_PROG_STACK(&G.prog.results, 1)) |
6839 | return bc_error("stack has too few elements"); | 6878 | return bc_error_stack_has_too_few_elements(); |
6840 | ptr = bc_vec_top(&G.prog.results); | 6879 | ptr = bc_vec_top(&G.prog.results); |
6841 | bc_result_copy(&r, ptr); | 6880 | bc_result_copy(&r, ptr); |
6842 | bc_vec_push(&G.prog.results, &r); | 6881 | bc_vec_push(&G.prog.results, &r); |
@@ -6848,7 +6887,7 @@ static BcStatus bc_program_exec(void) | |||
6848 | BcResult *ptr2; | 6887 | BcResult *ptr2; |
6849 | 6888 | ||
6850 | if (!BC_PROG_STACK(&G.prog.results, 2)) | 6889 | if (!BC_PROG_STACK(&G.prog.results, 2)) |
6851 | return bc_error("stack has too few elements"); | 6890 | return bc_error_stack_has_too_few_elements(); |
6852 | 6891 | ||
6853 | ptr = bc_vec_item_rev(&G.prog.results, 0); | 6892 | ptr = bc_vec_item_rev(&G.prog.results, 0); |
6854 | ptr2 = bc_vec_item_rev(&G.prog.results, 1); | 6893 | ptr2 = bc_vec_item_rev(&G.prog.results, 1); |
@@ -7009,7 +7048,7 @@ static BcStatus bc_vm_file(const char *file) | |||
7009 | 7048 | ||
7010 | G.prog.file = file; | 7049 | G.prog.file = file; |
7011 | data = bc_read_file(file); | 7050 | data = bc_read_file(file); |
7012 | if (!data) return bc_error("file '%s' is not text", file); | 7051 | if (!data) return bc_error_fmt("file '%s' is not text", file); |
7013 | 7052 | ||
7014 | bc_lex_file(&G.prs.l, file); | 7053 | bc_lex_file(&G.prs.l, file); |
7015 | s = bc_vm_process(data); | 7054 | s = bc_vm_process(data); |
@@ -7019,7 +7058,7 @@ static BcStatus bc_vm_file(const char *file) | |||
7019 | ip = bc_vec_item(&G.prog.stack, 0); | 7058 | ip = bc_vec_item(&G.prog.stack, 0); |
7020 | 7059 | ||
7021 | if (main_func->code.len < ip->idx) | 7060 | if (main_func->code.len < ip->idx) |
7022 | s = bc_error("file '%s' is not executable", file); | 7061 | s = bc_error_fmt("file '%s' is not executable", file); |
7023 | 7062 | ||
7024 | err: | 7063 | err: |
7025 | free(data); | 7064 | free(data); |