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 /miscutils | |
| 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>
Diffstat (limited to 'miscutils')
| -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); |
