diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-25 20:40:55 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-25 20:40:55 +0100 |
commit | a2e62e3e505aad4af81018f385d86d35e6485641 (patch) | |
tree | ac442a36d273090e34ee8e9f99c519a7d9d04419 | |
parent | 1fbe35a7d8579d53df0f4f70b31ba8b272099b7c (diff) | |
download | busybox-w32-a2e62e3e505aad4af81018f385d86d35e6485641.tar.gz busybox-w32-a2e62e3e505aad4af81018f385d86d35e6485641.tar.bz2 busybox-w32-a2e62e3e505aad4af81018f385d86d35e6485641.zip |
bc: stop passing a pointer to G.prs down the call chain
function old new delta
rewrite_label_to_current 19 26 +7
bc_lex_assign 28 35 +7
zbc_lex_skip_if_at_NLINE 14 19 +5
bc_parse_push 11 16 +5
bc_parse_operator 147 152 +5
bc_parse_create 92 97 +5
bc_lex_whitespace 38 43 +5
bc_lex_name 66 71 +5
bc_lex_lineComment 33 38 +5
zbc_lex_number 174 178 +4
zbc_parse_text_init 53 56 +3
zdc_parse_register 43 45 +2
zdc_parse_exprs_until_eof 26 28 +2
bc_parse_free 38 40 +2
bc_lex_file 28 27 -1
zbc_parse_pushSTR 65 63 -2
bc_parse_expr_empty_ok 1778 1776 -2
zbc_vm_execute_FILE 55 52 -3
bc_vm_init 678 675 -3
zbc_parse_stmt_allow_NLINE_before 59 55 -4
bc_parse_pushNUM 80 74 -6
bc_parse_pushJUMP_ZERO 27 21 -6
bc_parse_pushJUMP 27 21 -6
bc_vm_run 112 104 -8
bc_parse_pushName 39 31 -8
bc_parse_pushIndex 60 52 -8
zbc_parse_name 468 453 -15
zdc_program_execStr 524 501 -23
zdc_parse_mem 93 70 -23
zbc_program_exec 4003 3967 -36
zdc_parse_expr 518 476 -42
zbc_vm_process 923 878 -45
zbc_lex_next 2158 2070 -88
zbc_parse_stmt_possibly_auto 1560 1451 -109
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 14/20 up/down: 62/-438) Total: -376 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/bc.c | 701 |
1 files changed, 374 insertions, 327 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 0fdb2963c..75201f5f0 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -2748,8 +2748,9 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) | |||
2748 | } | 2748 | } |
2749 | #define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) | 2749 | #define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) |
2750 | 2750 | ||
2751 | static void bc_lex_lineComment(BcLex *l) | 2751 | static void bc_lex_lineComment(void) |
2752 | { | 2752 | { |
2753 | BcLex *l = &G.prs.l; | ||
2753 | // Try: echo -n '#foo' | bc | 2754 | // Try: echo -n '#foo' | bc |
2754 | size_t i; | 2755 | size_t i; |
2755 | l->lex = XC_LEX_WHITESPACE; | 2756 | l->lex = XC_LEX_WHITESPACE; |
@@ -2759,8 +2760,9 @@ static void bc_lex_lineComment(BcLex *l) | |||
2759 | l->i = i; | 2760 | l->i = i; |
2760 | } | 2761 | } |
2761 | 2762 | ||
2762 | static void bc_lex_whitespace(BcLex *l) | 2763 | static void bc_lex_whitespace(void) |
2763 | { | 2764 | { |
2765 | BcLex *l = &G.prs.l; | ||
2764 | l->lex = XC_LEX_WHITESPACE; | 2766 | l->lex = XC_LEX_WHITESPACE; |
2765 | for (;;) { | 2767 | for (;;) { |
2766 | char c = l->buf[l->i]; | 2768 | char c = l->buf[l->i]; |
@@ -2772,8 +2774,9 @@ static void bc_lex_whitespace(BcLex *l) | |||
2772 | } | 2774 | } |
2773 | } | 2775 | } |
2774 | 2776 | ||
2775 | static BC_STATUS zbc_lex_number(BcLex *l, char start) | 2777 | static BC_STATUS zbc_lex_number(char start) |
2776 | { | 2778 | { |
2779 | BcLex *l = &G.prs.l; | ||
2777 | const char *buf = l->buf + l->i; | 2780 | const char *buf = l->buf + l->i; |
2778 | size_t len, i, ccnt; | 2781 | size_t len, i, ccnt; |
2779 | bool pt; | 2782 | bool pt; |
@@ -2842,8 +2845,9 @@ static BC_STATUS zbc_lex_number(BcLex *l, char start) | |||
2842 | } | 2845 | } |
2843 | #define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__) COMMA_SUCCESS) | 2846 | #define zbc_lex_number(...) (zbc_lex_number(__VA_ARGS__) COMMA_SUCCESS) |
2844 | 2847 | ||
2845 | static void bc_lex_name(BcLex *l) | 2848 | static void bc_lex_name(void) |
2846 | { | 2849 | { |
2850 | BcLex *l = &G.prs.l; | ||
2847 | size_t i; | 2851 | size_t i; |
2848 | const char *buf; | 2852 | const char *buf; |
2849 | 2853 | ||
@@ -2872,24 +2876,25 @@ static void bc_lex_name(BcLex *l) | |||
2872 | //return BC_STATUS_SUCCESS; | 2876 | //return BC_STATUS_SUCCESS; |
2873 | } | 2877 | } |
2874 | 2878 | ||
2875 | static void bc_lex_init(BcLex *l) | 2879 | static void bc_lex_init(void) |
2876 | { | 2880 | { |
2877 | bc_char_vec_init(&l->lex_buf); | 2881 | bc_char_vec_init(&G.prs.l.lex_buf); |
2878 | } | 2882 | } |
2879 | 2883 | ||
2880 | static void bc_lex_free(BcLex *l) | 2884 | static void bc_lex_free(void) |
2881 | { | 2885 | { |
2882 | bc_vec_free(&l->lex_buf); | 2886 | bc_vec_free(&G.prs.l.lex_buf); |
2883 | } | 2887 | } |
2884 | 2888 | ||
2885 | static void bc_lex_file(BcLex *l) | 2889 | static void bc_lex_file(void) |
2886 | { | 2890 | { |
2887 | G.err_line = l->line = 1; | 2891 | G.err_line = G.prs.l.line = 1; |
2888 | l->newline = false; | 2892 | G.prs.l.newline = false; |
2889 | } | 2893 | } |
2890 | 2894 | ||
2891 | static bool bc_lex_more_input(BcLex *l) | 2895 | static bool bc_lex_more_input(void) |
2892 | { | 2896 | { |
2897 | BcLex *l = &G.prs.l; | ||
2893 | size_t str; | 2898 | size_t str; |
2894 | bool comment; | 2899 | bool comment; |
2895 | 2900 | ||
@@ -2960,13 +2965,14 @@ static bool bc_lex_more_input(BcLex *l) | |||
2960 | return l->len != 0; | 2965 | return l->len != 0; |
2961 | } | 2966 | } |
2962 | 2967 | ||
2963 | IF_BC(static BC_STATUS zbc_lex_token(BcLex *l);) | 2968 | IF_BC(static BC_STATUS zbc_lex_token(void);) |
2964 | IF_DC(static BC_STATUS zdc_lex_token(BcLex *l);) | 2969 | IF_DC(static BC_STATUS zdc_lex_token(void);) |
2965 | #define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS) | 2970 | #define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS) |
2966 | #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) | 2971 | #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) |
2967 | 2972 | ||
2968 | static BC_STATUS zbc_lex_next(BcLex *l) | 2973 | static BC_STATUS zbc_lex_next(void) |
2969 | { | 2974 | { |
2975 | BcLex *l = &G.prs.l; | ||
2970 | BcStatus s; | 2976 | BcStatus s; |
2971 | 2977 | ||
2972 | l->lex_last = l->lex; | 2978 | l->lex_last = l->lex; |
@@ -2985,7 +2991,7 @@ static BC_STATUS zbc_lex_next(BcLex *l) | |||
2985 | l->lex = XC_LEX_EOF; | 2991 | l->lex = XC_LEX_EOF; |
2986 | if (!G.prs.input_fp) | 2992 | if (!G.prs.input_fp) |
2987 | RETURN_STATUS(BC_STATUS_SUCCESS); | 2993 | RETURN_STATUS(BC_STATUS_SUCCESS); |
2988 | if (!bc_lex_more_input(l)) { | 2994 | if (!bc_lex_more_input()) { |
2989 | G.prs.input_fp = NULL; | 2995 | G.prs.input_fp = NULL; |
2990 | RETURN_STATUS(BC_STATUS_SUCCESS); | 2996 | RETURN_STATUS(BC_STATUS_SUCCESS); |
2991 | } | 2997 | } |
@@ -2997,9 +3003,9 @@ static BC_STATUS zbc_lex_next(BcLex *l) | |||
2997 | l->lex_next_at | 3003 | l->lex_next_at |
2998 | ); | 3004 | ); |
2999 | if (IS_BC) { | 3005 | if (IS_BC) { |
3000 | IF_BC(s = zbc_lex_token(l)); | 3006 | IF_BC(s = zbc_lex_token()); |
3001 | } else { | 3007 | } else { |
3002 | IF_DC(s = zdc_lex_token(l)); | 3008 | IF_DC(s = zdc_lex_token()); |
3003 | } | 3009 | } |
3004 | } while (!s && l->lex == XC_LEX_WHITESPACE); | 3010 | } while (!s && l->lex == XC_LEX_WHITESPACE); |
3005 | dbg_lex("l->lex from string:%d", l->lex); | 3011 | dbg_lex("l->lex from string:%d", l->lex); |
@@ -3009,39 +3015,40 @@ static BC_STATUS zbc_lex_next(BcLex *l) | |||
3009 | #define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__) COMMA_SUCCESS) | 3015 | #define zbc_lex_next(...) (zbc_lex_next(__VA_ARGS__) COMMA_SUCCESS) |
3010 | 3016 | ||
3011 | #if ENABLE_BC | 3017 | #if ENABLE_BC |
3012 | static BC_STATUS zbc_lex_skip_if_at_NLINE(BcLex *l) | 3018 | static BC_STATUS zbc_lex_skip_if_at_NLINE(void) |
3013 | { | 3019 | { |
3014 | if (l->lex == XC_LEX_NLINE) | 3020 | if (G.prs.l.lex == XC_LEX_NLINE) |
3015 | RETURN_STATUS(zbc_lex_next(l)); | 3021 | RETURN_STATUS(zbc_lex_next()); |
3016 | RETURN_STATUS(BC_STATUS_SUCCESS); | 3022 | RETURN_STATUS(BC_STATUS_SUCCESS); |
3017 | } | 3023 | } |
3018 | #define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__) COMMA_SUCCESS) | 3024 | #define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__) COMMA_SUCCESS) |
3019 | 3025 | ||
3020 | static BC_STATUS zbc_lex_next_and_skip_NLINE(BcLex *l) | 3026 | static BC_STATUS zbc_lex_next_and_skip_NLINE(void) |
3021 | { | 3027 | { |
3022 | BcStatus s; | 3028 | BcStatus s; |
3023 | s = zbc_lex_next(l); | 3029 | s = zbc_lex_next(); |
3024 | if (s) RETURN_STATUS(s); | 3030 | if (s) RETURN_STATUS(s); |
3025 | // if(cond)<newline>stmt is accepted too (but not 2+ newlines) | 3031 | // if(cond)<newline>stmt is accepted too (but not 2+ newlines) |
3026 | s = zbc_lex_skip_if_at_NLINE(l); | 3032 | s = zbc_lex_skip_if_at_NLINE(); |
3027 | RETURN_STATUS(s); | 3033 | RETURN_STATUS(s); |
3028 | } | 3034 | } |
3029 | #define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__) COMMA_SUCCESS) | 3035 | #define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__) COMMA_SUCCESS) |
3030 | #endif | 3036 | #endif |
3031 | 3037 | ||
3032 | static BC_STATUS zbc_lex_text_init(BcLex *l, const char *text) | 3038 | static BC_STATUS zbc_lex_text_init(const char *text) |
3033 | { | 3039 | { |
3034 | l->buf = text; | 3040 | G.prs.l.buf = text; |
3035 | l->i = 0; | 3041 | G.prs.l.i = 0; |
3036 | l->len = strlen(text); | 3042 | G.prs.l.len = strlen(text); |
3037 | l->lex = l->lex_last = XC_LEX_INVALID; | 3043 | G.prs.l.lex = G.prs.l.lex_last = XC_LEX_INVALID; |
3038 | RETURN_STATUS(zbc_lex_next(l)); | 3044 | RETURN_STATUS(zbc_lex_next()); |
3039 | } | 3045 | } |
3040 | #define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__) COMMA_SUCCESS) | 3046 | #define zbc_lex_text_init(...) (zbc_lex_text_init(__VA_ARGS__) COMMA_SUCCESS) |
3041 | 3047 | ||
3042 | #if ENABLE_BC | 3048 | #if ENABLE_BC |
3043 | static BC_STATUS zbc_lex_identifier(BcLex *l) | 3049 | static BC_STATUS zbc_lex_identifier(void) |
3044 | { | 3050 | { |
3051 | BcLex *l = &G.prs.l; | ||
3045 | BcStatus s; | 3052 | BcStatus s; |
3046 | unsigned i; | 3053 | unsigned i; |
3047 | const char *buf = l->buf + l->i - 1; | 3054 | const char *buf = l->buf + l->i - 1; |
@@ -3070,7 +3077,7 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) | |||
3070 | RETURN_STATUS(BC_STATUS_SUCCESS); | 3077 | RETURN_STATUS(BC_STATUS_SUCCESS); |
3071 | } | 3078 | } |
3072 | 3079 | ||
3073 | bc_lex_name(l); | 3080 | bc_lex_name(); |
3074 | s = BC_STATUS_SUCCESS; | 3081 | s = BC_STATUS_SUCCESS; |
3075 | 3082 | ||
3076 | if (l->lex_buf.len > 2) { | 3083 | if (l->lex_buf.len > 2) { |
@@ -3086,8 +3093,9 @@ static BC_STATUS zbc_lex_identifier(BcLex *l) | |||
3086 | } | 3093 | } |
3087 | #define zbc_lex_identifier(...) (zbc_lex_identifier(__VA_ARGS__) COMMA_SUCCESS) | 3094 | #define zbc_lex_identifier(...) (zbc_lex_identifier(__VA_ARGS__) COMMA_SUCCESS) |
3088 | 3095 | ||
3089 | static BC_STATUS zbc_lex_string(BcLex *l) | 3096 | static BC_STATUS zbc_lex_string(void) |
3090 | { | 3097 | { |
3098 | BcLex *l = &G.prs.l; | ||
3091 | size_t len, nls, i; | 3099 | size_t len, nls, i; |
3092 | 3100 | ||
3093 | l->lex = XC_LEX_STR; | 3101 | l->lex = XC_LEX_STR; |
@@ -3122,19 +3130,21 @@ static BC_STATUS zbc_lex_string(BcLex *l) | |||
3122 | } | 3130 | } |
3123 | #define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__) COMMA_SUCCESS) | 3131 | #define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__) COMMA_SUCCESS) |
3124 | 3132 | ||
3125 | static void bc_lex_assign(BcLex *l, unsigned with_and_without) | 3133 | static void bc_lex_assign(unsigned with_and_without) |
3126 | { | 3134 | { |
3135 | BcLex *l = &G.prs.l; | ||
3127 | if (l->buf[l->i] == '=') { | 3136 | if (l->buf[l->i] == '=') { |
3128 | ++l->i; | 3137 | ++l->i; |
3129 | with_and_without >>= 8; // store "with" value | 3138 | with_and_without >>= 8; // store "with" value |
3130 | } // else store "without" value | 3139 | } // else store "without" value |
3131 | l->lex = (with_and_without & 0xff); | 3140 | l->lex = (with_and_without & 0xff); |
3132 | } | 3141 | } |
3133 | #define bc_lex_assign(l, with, without) \ | 3142 | #define bc_lex_assign(with, without) \ |
3134 | bc_lex_assign(l, ((with)<<8)|(without)) | 3143 | bc_lex_assign(((with)<<8)|(without)) |
3135 | 3144 | ||
3136 | static BC_STATUS zbc_lex_comment(BcLex *l) | 3145 | static BC_STATUS zbc_lex_comment(void) |
3137 | { | 3146 | { |
3147 | BcLex *l = &G.prs.l; | ||
3138 | size_t i, nls = 0; | 3148 | size_t i, nls = 0; |
3139 | const char *buf = l->buf; | 3149 | const char *buf = l->buf; |
3140 | 3150 | ||
@@ -3165,8 +3175,9 @@ static BC_STATUS zbc_lex_comment(BcLex *l) | |||
3165 | #define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__) COMMA_SUCCESS) | 3175 | #define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__) COMMA_SUCCESS) |
3166 | 3176 | ||
3167 | #undef zbc_lex_token | 3177 | #undef zbc_lex_token |
3168 | static BC_STATUS zbc_lex_token(BcLex *l) | 3178 | static BC_STATUS zbc_lex_token(void) |
3169 | { | 3179 | { |
3180 | BcLex *l = &G.prs.l; | ||
3170 | BcStatus s = BC_STATUS_SUCCESS; | 3181 | BcStatus s = BC_STATUS_SUCCESS; |
3171 | char c = l->buf[l->i++], c2; | 3182 | char c = l->buf[l->i++], c2; |
3172 | 3183 | ||
@@ -3186,25 +3197,25 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3186 | case '\f': | 3197 | case '\f': |
3187 | case '\r': | 3198 | case '\r': |
3188 | case ' ': | 3199 | case ' ': |
3189 | bc_lex_whitespace(l); | 3200 | bc_lex_whitespace(); |
3190 | break; | 3201 | break; |
3191 | case '!': | 3202 | case '!': |
3192 | bc_lex_assign(l, XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); | 3203 | bc_lex_assign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); |
3193 | if (l->lex == BC_LEX_OP_BOOL_NOT) { | 3204 | if (l->lex == BC_LEX_OP_BOOL_NOT) { |
3194 | s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); | 3205 | s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); |
3195 | if (s) RETURN_STATUS(s); | 3206 | if (s) RETURN_STATUS(s); |
3196 | } | 3207 | } |
3197 | break; | 3208 | break; |
3198 | case '"': | 3209 | case '"': |
3199 | s = zbc_lex_string(l); | 3210 | s = zbc_lex_string(); |
3200 | break; | 3211 | break; |
3201 | case '#': | 3212 | case '#': |
3202 | s = zbc_POSIX_does_not_allow("'#' script comments"); | 3213 | s = zbc_POSIX_does_not_allow("'#' script comments"); |
3203 | if (s) RETURN_STATUS(s); | 3214 | if (s) RETURN_STATUS(s); |
3204 | bc_lex_lineComment(l); | 3215 | bc_lex_lineComment(); |
3205 | break; | 3216 | break; |
3206 | case '%': | 3217 | case '%': |
3207 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); | 3218 | bc_lex_assign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS); |
3208 | break; | 3219 | break; |
3209 | case '&': | 3220 | case '&': |
3210 | c2 = l->buf[l->i]; | 3221 | c2 = l->buf[l->i]; |
@@ -3223,7 +3234,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3223 | l->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); | 3234 | l->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN); |
3224 | break; | 3235 | break; |
3225 | case '*': | 3236 | case '*': |
3226 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); | 3237 | bc_lex_assign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY); |
3227 | break; | 3238 | break; |
3228 | case '+': | 3239 | case '+': |
3229 | c2 = l->buf[l->i]; | 3240 | c2 = l->buf[l->i]; |
@@ -3231,7 +3242,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3231 | ++l->i; | 3242 | ++l->i; |
3232 | l->lex = BC_LEX_OP_INC; | 3243 | l->lex = BC_LEX_OP_INC; |
3233 | } else | 3244 | } else |
3234 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); | 3245 | bc_lex_assign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS); |
3235 | break; | 3246 | break; |
3236 | case ',': | 3247 | case ',': |
3237 | l->lex = BC_LEX_COMMA; | 3248 | l->lex = BC_LEX_COMMA; |
@@ -3242,11 +3253,11 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3242 | ++l->i; | 3253 | ++l->i; |
3243 | l->lex = BC_LEX_OP_DEC; | 3254 | l->lex = BC_LEX_OP_DEC; |
3244 | } else | 3255 | } else |
3245 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); | 3256 | bc_lex_assign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS); |
3246 | break; | 3257 | break; |
3247 | case '.': | 3258 | case '.': |
3248 | if (isdigit(l->buf[l->i])) | 3259 | if (isdigit(l->buf[l->i])) |
3249 | s = zbc_lex_number(l, c); | 3260 | s = zbc_lex_number(c); |
3250 | else { | 3261 | else { |
3251 | l->lex = BC_LEX_KEY_LAST; | 3262 | l->lex = BC_LEX_KEY_LAST; |
3252 | s = zbc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); | 3263 | s = zbc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); |
@@ -3255,9 +3266,9 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3255 | case '/': | 3266 | case '/': |
3256 | c2 = l->buf[l->i]; | 3267 | c2 = l->buf[l->i]; |
3257 | if (c2 == '*') | 3268 | if (c2 == '*') |
3258 | s = zbc_lex_comment(l); | 3269 | s = zbc_lex_comment(); |
3259 | else | 3270 | else |
3260 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); | 3271 | bc_lex_assign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE); |
3261 | break; | 3272 | break; |
3262 | case '0': | 3273 | case '0': |
3263 | case '1': | 3274 | case '1': |
@@ -3275,19 +3286,19 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3275 | case 'D': | 3286 | case 'D': |
3276 | case 'E': | 3287 | case 'E': |
3277 | case 'F': | 3288 | case 'F': |
3278 | s = zbc_lex_number(l, c); | 3289 | s = zbc_lex_number(c); |
3279 | break; | 3290 | break; |
3280 | case ';': | 3291 | case ';': |
3281 | l->lex = BC_LEX_SCOLON; | 3292 | l->lex = BC_LEX_SCOLON; |
3282 | break; | 3293 | break; |
3283 | case '<': | 3294 | case '<': |
3284 | bc_lex_assign(l, XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); | 3295 | bc_lex_assign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT); |
3285 | break; | 3296 | break; |
3286 | case '=': | 3297 | case '=': |
3287 | bc_lex_assign(l, XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); | 3298 | bc_lex_assign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); |
3288 | break; | 3299 | break; |
3289 | case '>': | 3300 | case '>': |
3290 | bc_lex_assign(l, XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); | 3301 | bc_lex_assign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT); |
3291 | break; | 3302 | break; |
3292 | case '[': | 3303 | case '[': |
3293 | case ']': | 3304 | case ']': |
@@ -3301,7 +3312,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3301 | s = bc_error_bad_character(c); | 3312 | s = bc_error_bad_character(c); |
3302 | break; | 3313 | break; |
3303 | case '^': | 3314 | case '^': |
3304 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); | 3315 | bc_lex_assign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER); |
3305 | break; | 3316 | break; |
3306 | case 'a': | 3317 | case 'a': |
3307 | case 'b': | 3318 | case 'b': |
@@ -3329,7 +3340,7 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3329 | case 'x': | 3340 | case 'x': |
3330 | case 'y': | 3341 | case 'y': |
3331 | case 'z': | 3342 | case 'z': |
3332 | s = zbc_lex_identifier(l); | 3343 | s = zbc_lex_identifier(); |
3333 | break; | 3344 | break; |
3334 | case '{': | 3345 | case '{': |
3335 | case '}': | 3346 | case '}': |
@@ -3359,12 +3370,13 @@ static BC_STATUS zbc_lex_token(BcLex *l) | |||
3359 | #endif // ENABLE_BC | 3370 | #endif // ENABLE_BC |
3360 | 3371 | ||
3361 | #if ENABLE_DC | 3372 | #if ENABLE_DC |
3362 | static BC_STATUS zdc_lex_register(BcLex *l) | 3373 | static BC_STATUS zdc_lex_register(void) |
3363 | { | 3374 | { |
3375 | BcLex *l = &G.prs.l; | ||
3364 | if (G_exreg && isspace(l->buf[l->i])) { | 3376 | if (G_exreg && isspace(l->buf[l->i])) { |
3365 | bc_lex_whitespace(l); // eats whitespace (but not newline) | 3377 | bc_lex_whitespace(); // eats whitespace (but not newline) |
3366 | l->i++; // bc_lex_name() expects this | 3378 | l->i++; // bc_lex_name() expects this |
3367 | bc_lex_name(l); | 3379 | bc_lex_name(); |
3368 | } else { | 3380 | } else { |
3369 | bc_vec_pop_all(&l->lex_buf); | 3381 | bc_vec_pop_all(&l->lex_buf); |
3370 | bc_vec_push(&l->lex_buf, &l->buf[l->i++]); | 3382 | bc_vec_push(&l->lex_buf, &l->buf[l->i++]); |
@@ -3376,8 +3388,9 @@ static BC_STATUS zdc_lex_register(BcLex *l) | |||
3376 | } | 3388 | } |
3377 | #define zdc_lex_register(...) (zdc_lex_register(__VA_ARGS__) COMMA_SUCCESS) | 3389 | #define zdc_lex_register(...) (zdc_lex_register(__VA_ARGS__) COMMA_SUCCESS) |
3378 | 3390 | ||
3379 | static BC_STATUS zdc_lex_string(BcLex *l) | 3391 | static BC_STATUS zdc_lex_string(void) |
3380 | { | 3392 | { |
3393 | BcLex *l = &G.prs.l; | ||
3381 | size_t depth, nls, i; | 3394 | size_t depth, nls, i; |
3382 | 3395 | ||
3383 | l->lex = XC_LEX_STR; | 3396 | l->lex = XC_LEX_STR; |
@@ -3420,8 +3433,9 @@ static BC_STATUS zdc_lex_string(BcLex *l) | |||
3420 | #define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__) COMMA_SUCCESS) | 3433 | #define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__) COMMA_SUCCESS) |
3421 | 3434 | ||
3422 | #undef zdc_lex_token | 3435 | #undef zdc_lex_token |
3423 | static BC_STATUS zdc_lex_token(BcLex *l) | 3436 | static BC_STATUS zdc_lex_token(void) |
3424 | { | 3437 | { |
3438 | BcLex *l = &G.prs.l; | ||
3425 | static const //BcLexType - should be this type, but narrower type saves size: | 3439 | static const //BcLexType - should be this type, but narrower type saves size: |
3426 | uint8_t | 3440 | uint8_t |
3427 | dc_lex_regs[] = { | 3441 | dc_lex_regs[] = { |
@@ -3437,7 +3451,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) | |||
3437 | 3451 | ||
3438 | for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { | 3452 | for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) { |
3439 | if (l->lex_last == dc_lex_regs[i]) | 3453 | if (l->lex_last == dc_lex_regs[i]) |
3440 | RETURN_STATUS(zdc_lex_register(l)); | 3454 | RETURN_STATUS(zdc_lex_register()); |
3441 | } | 3455 | } |
3442 | 3456 | ||
3443 | s = BC_STATUS_SUCCESS; | 3457 | s = BC_STATUS_SUCCESS; |
@@ -3471,7 +3485,7 @@ static BC_STATUS zdc_lex_token(BcLex *l) | |||
3471 | case '\r': | 3485 | case '\r': |
3472 | case ' ': | 3486 | case ' ': |
3473 | l->newline = 0; // was (c == '\n') | 3487 | l->newline = 0; // was (c == '\n') |
3474 | bc_lex_whitespace(l); | 3488 | bc_lex_whitespace(); |
3475 | break; | 3489 | break; |
3476 | case '!': | 3490 | case '!': |
3477 | c2 = l->buf[l->i]; | 3491 | c2 = l->buf[l->i]; |
@@ -3486,11 +3500,11 @@ static BC_STATUS zdc_lex_token(BcLex *l) | |||
3486 | ++l->i; | 3500 | ++l->i; |
3487 | break; | 3501 | break; |
3488 | case '#': | 3502 | case '#': |
3489 | bc_lex_lineComment(l); | 3503 | bc_lex_lineComment(); |
3490 | break; | 3504 | break; |
3491 | case '.': | 3505 | case '.': |
3492 | if (isdigit(l->buf[l->i])) | 3506 | if (isdigit(l->buf[l->i])) |
3493 | s = zbc_lex_number(l, c); | 3507 | s = zbc_lex_number(c); |
3494 | else | 3508 | else |
3495 | s = bc_error_bad_character(c); | 3509 | s = bc_error_bad_character(c); |
3496 | break; | 3510 | break; |
@@ -3510,10 +3524,10 @@ static BC_STATUS zdc_lex_token(BcLex *l) | |||
3510 | case 'D': | 3524 | case 'D': |
3511 | case 'E': | 3525 | case 'E': |
3512 | case 'F': | 3526 | case 'F': |
3513 | s = zbc_lex_number(l, c); | 3527 | s = zbc_lex_number(c); |
3514 | break; | 3528 | break; |
3515 | case '[': | 3529 | case '[': |
3516 | s = zdc_lex_string(l); | 3530 | s = zdc_lex_string(); |
3517 | break; | 3531 | break; |
3518 | default: | 3532 | default: |
3519 | l->lex = XC_LEX_INVALID; | 3533 | l->lex = XC_LEX_INVALID; |
@@ -3526,20 +3540,21 @@ static BC_STATUS zdc_lex_token(BcLex *l) | |||
3526 | #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) | 3540 | #define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS) |
3527 | #endif // ENABLE_DC | 3541 | #endif // ENABLE_DC |
3528 | 3542 | ||
3529 | static void bc_parse_push(BcParse *p, char i) | 3543 | static void bc_parse_push(char i) |
3530 | { | 3544 | { |
3545 | BcParse *p = &G.prs; | ||
3531 | dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, p->func->code.len, i); | 3546 | dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, p->func->code.len, i); |
3532 | bc_vec_pushByte(&p->func->code, i); | 3547 | bc_vec_pushByte(&p->func->code, i); |
3533 | } | 3548 | } |
3534 | 3549 | ||
3535 | static void bc_parse_pushName(BcParse *p, char *name) | 3550 | static void bc_parse_pushName(char *name) |
3536 | { | 3551 | { |
3537 | while (*name) | 3552 | while (*name) |
3538 | bc_parse_push(p, *name++); | 3553 | bc_parse_push(*name++); |
3539 | bc_parse_push(p, BC_PARSE_STREND); | 3554 | bc_parse_push(BC_PARSE_STREND); |
3540 | } | 3555 | } |
3541 | 3556 | ||
3542 | static void bc_parse_pushIndex(BcParse *p, size_t idx) | 3557 | static void bc_parse_pushIndex(size_t idx) |
3543 | { | 3558 | { |
3544 | size_t mask; | 3559 | size_t mask; |
3545 | unsigned amt; | 3560 | unsigned amt; |
@@ -3553,42 +3568,44 @@ static void bc_parse_pushIndex(BcParse *p, size_t idx) | |||
3553 | amt--; | 3568 | amt--; |
3554 | } while (amt != 0); | 3569 | } while (amt != 0); |
3555 | 3570 | ||
3556 | bc_parse_push(p, amt); | 3571 | bc_parse_push(amt); |
3557 | 3572 | ||
3558 | while (idx != 0) { | 3573 | while (idx != 0) { |
3559 | bc_parse_push(p, (unsigned char)idx); | 3574 | bc_parse_push((unsigned char)idx); |
3560 | idx >>= 8; | 3575 | idx >>= 8; |
3561 | } | 3576 | } |
3562 | } | 3577 | } |
3563 | 3578 | ||
3564 | #if ENABLE_BC | 3579 | #if ENABLE_BC |
3565 | static void bc_parse_pushJUMP(BcParse *p, size_t idx) | 3580 | static void bc_parse_pushJUMP(size_t idx) |
3566 | { | 3581 | { |
3567 | bc_parse_push(p, BC_INST_JUMP); | 3582 | bc_parse_push(BC_INST_JUMP); |
3568 | bc_parse_pushIndex(p, idx); | 3583 | bc_parse_pushIndex(idx); |
3569 | } | 3584 | } |
3570 | 3585 | ||
3571 | static void bc_parse_pushJUMP_ZERO(BcParse *p, size_t idx) | 3586 | static void bc_parse_pushJUMP_ZERO(size_t idx) |
3572 | { | 3587 | { |
3573 | bc_parse_push(p, BC_INST_JUMP_ZERO); | 3588 | bc_parse_push(BC_INST_JUMP_ZERO); |
3574 | bc_parse_pushIndex(p, idx); | 3589 | bc_parse_pushIndex(idx); |
3575 | } | 3590 | } |
3576 | 3591 | ||
3577 | static BC_STATUS zbc_parse_pushSTR(BcParse *p) | 3592 | static BC_STATUS zbc_parse_pushSTR(void) |
3578 | { | 3593 | { |
3594 | BcParse *p = &G.prs; | ||
3579 | char *str = xstrdup(p->l.lex_buf.v); | 3595 | char *str = xstrdup(p->l.lex_buf.v); |
3580 | 3596 | ||
3581 | bc_parse_push(p, XC_INST_STR); | 3597 | bc_parse_push(XC_INST_STR); |
3582 | bc_parse_pushIndex(p, p->func->strs.len); | 3598 | bc_parse_pushIndex(p->func->strs.len); |
3583 | bc_vec_push(&p->func->strs, &str); | 3599 | bc_vec_push(&p->func->strs, &str); |
3584 | 3600 | ||
3585 | RETURN_STATUS(zbc_lex_next(&p->l)); | 3601 | RETURN_STATUS(zbc_lex_next()); |
3586 | } | 3602 | } |
3587 | #define zbc_parse_pushSTR(...) (zbc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) | 3603 | #define zbc_parse_pushSTR(...) (zbc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS) |
3588 | #endif | 3604 | #endif |
3589 | 3605 | ||
3590 | static void bc_parse_pushNUM(BcParse *p) | 3606 | static void bc_parse_pushNUM(void) |
3591 | { | 3607 | { |
3608 | BcParse *p = &G.prs; | ||
3592 | char *num = xstrdup(p->l.lex_buf.v); | 3609 | char *num = xstrdup(p->l.lex_buf.v); |
3593 | #if ENABLE_BC && ENABLE_DC | 3610 | #if ENABLE_BC && ENABLE_DC |
3594 | size_t idx = bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); | 3611 | size_t idx = bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num); |
@@ -3597,15 +3614,16 @@ static void bc_parse_pushNUM(BcParse *p) | |||
3597 | #else // DC | 3614 | #else // DC |
3598 | size_t idx = bc_vec_push(&G.prog.consts, &num); | 3615 | size_t idx = bc_vec_push(&G.prog.consts, &num); |
3599 | #endif | 3616 | #endif |
3600 | bc_parse_push(p, XC_INST_NUM); | 3617 | bc_parse_push(XC_INST_NUM); |
3601 | bc_parse_pushIndex(p, idx); | 3618 | bc_parse_pushIndex(idx); |
3602 | } | 3619 | } |
3603 | 3620 | ||
3604 | static BC_STATUS zbc_parse_text_init(BcParse *p, const char *text) | 3621 | static BC_STATUS zbc_parse_text_init(const char *text) |
3605 | { | 3622 | { |
3623 | BcParse *p = &G.prs; | ||
3606 | p->func = bc_program_func(p->fidx); | 3624 | p->func = bc_program_func(p->fidx); |
3607 | 3625 | ||
3608 | RETURN_STATUS(zbc_lex_text_init(&p->l, text)); | 3626 | RETURN_STATUS(zbc_lex_text_init(text)); |
3609 | } | 3627 | } |
3610 | #define zbc_parse_text_init(...) (zbc_parse_text_init(__VA_ARGS__) COMMA_SUCCESS) | 3628 | #define zbc_parse_text_init(...) (zbc_parse_text_init(__VA_ARGS__) COMMA_SUCCESS) |
3611 | 3629 | ||
@@ -3626,8 +3644,9 @@ static void bc_program_reset(void) | |||
3626 | 3644 | ||
3627 | // Called when parsing code detects a failure, | 3645 | // Called when parsing code detects a failure, |
3628 | // resets parsing structures. | 3646 | // resets parsing structures. |
3629 | static void bc_parse_reset(BcParse *p) | 3647 | static void bc_parse_reset(void) |
3630 | { | 3648 | { |
3649 | BcParse *p = &G.prs; | ||
3631 | if (p->fidx != BC_PROG_MAIN) { | 3650 | if (p->fidx != BC_PROG_MAIN) { |
3632 | bc_func_free(p->func); | 3651 | bc_func_free(p->func); |
3633 | bc_func_init(p->func); | 3652 | bc_func_init(p->func); |
@@ -3646,19 +3665,21 @@ static void bc_parse_reset(BcParse *p) | |||
3646 | bc_program_reset(); | 3665 | bc_program_reset(); |
3647 | } | 3666 | } |
3648 | 3667 | ||
3649 | static void bc_parse_free(BcParse *p) | 3668 | static void bc_parse_free(void) |
3650 | { | 3669 | { |
3670 | BcParse *p = &G.prs; | ||
3651 | IF_BC(bc_vec_free(&p->exits);) | 3671 | IF_BC(bc_vec_free(&p->exits);) |
3652 | IF_BC(bc_vec_free(&p->conds);) | 3672 | IF_BC(bc_vec_free(&p->conds);) |
3653 | IF_BC(bc_vec_free(&p->ops);) | 3673 | IF_BC(bc_vec_free(&p->ops);) |
3654 | bc_lex_free(&p->l); | 3674 | bc_lex_free(); |
3655 | } | 3675 | } |
3656 | 3676 | ||
3657 | static void bc_parse_create(BcParse *p, size_t fidx) | 3677 | static void bc_parse_create(size_t fidx) |
3658 | { | 3678 | { |
3679 | BcParse *p = &G.prs; | ||
3659 | memset(p, 0, sizeof(BcParse)); | 3680 | memset(p, 0, sizeof(BcParse)); |
3660 | 3681 | ||
3661 | bc_lex_init(&p->l); | 3682 | bc_lex_init(); |
3662 | IF_BC(bc_vec_init(&p->exits, sizeof(size_t), NULL);) | 3683 | IF_BC(bc_vec_init(&p->exits, sizeof(size_t), NULL);) |
3663 | IF_BC(bc_vec_init(&p->conds, sizeof(size_t), NULL);) | 3684 | IF_BC(bc_vec_init(&p->conds, sizeof(size_t), NULL);) |
3664 | IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);) | 3685 | IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);) |
@@ -3714,44 +3735,45 @@ static size_t bc_program_addFunc(char *name) | |||
3714 | // first in the expr enum. Note: This only works for binary operators. | 3735 | // first in the expr enum. Note: This only works for binary operators. |
3715 | #define BC_TOKEN_2_INST(t) ((char) ((t) - XC_LEX_OP_POWER + XC_INST_POWER)) | 3736 | #define BC_TOKEN_2_INST(t) ((char) ((t) - XC_LEX_OP_POWER + XC_INST_POWER)) |
3716 | 3737 | ||
3717 | static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags); | 3738 | static BcStatus bc_parse_expr_empty_ok(uint8_t flags); |
3718 | 3739 | ||
3719 | static BC_STATUS zbc_parse_expr(BcParse *p, uint8_t flags) | 3740 | static BC_STATUS zbc_parse_expr(uint8_t flags) |
3720 | { | 3741 | { |
3721 | BcStatus s; | 3742 | BcStatus s; |
3722 | 3743 | ||
3723 | s = bc_parse_expr_empty_ok(p, flags); | 3744 | s = bc_parse_expr_empty_ok(flags); |
3724 | if (s == BC_STATUS_PARSE_EMPTY_EXP) | 3745 | if (s == BC_STATUS_PARSE_EMPTY_EXP) |
3725 | RETURN_STATUS(bc_error("empty expression")); | 3746 | RETURN_STATUS(bc_error("empty expression")); |
3726 | RETURN_STATUS(s); | 3747 | RETURN_STATUS(s); |
3727 | } | 3748 | } |
3728 | #define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) | 3749 | #define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) |
3729 | 3750 | ||
3730 | static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed); | 3751 | static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed); |
3731 | #define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) | 3752 | #define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) |
3732 | 3753 | ||
3733 | static BC_STATUS zbc_parse_stmt(BcParse *p) | 3754 | static BC_STATUS zbc_parse_stmt(void) |
3734 | { | 3755 | { |
3735 | RETURN_STATUS(zbc_parse_stmt_possibly_auto(p, false)); | 3756 | RETURN_STATUS(zbc_parse_stmt_possibly_auto(false)); |
3736 | } | 3757 | } |
3737 | #define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__) COMMA_SUCCESS) | 3758 | #define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__) COMMA_SUCCESS) |
3738 | 3759 | ||
3739 | static BC_STATUS zbc_parse_stmt_allow_NLINE_before(BcParse *p, const char *after_X) | 3760 | static BC_STATUS zbc_parse_stmt_allow_NLINE_before(const char *after_X) |
3740 | { | 3761 | { |
3762 | BcParse *p = &G.prs; | ||
3741 | // "if(cond)<newline>stmt" is accepted too, but not 2+ newlines. | 3763 | // "if(cond)<newline>stmt" is accepted too, but not 2+ newlines. |
3742 | // Same for "else", "while()", "for()". | 3764 | // Same for "else", "while()", "for()". |
3743 | BcStatus s = zbc_lex_next_and_skip_NLINE(&p->l); | 3765 | BcStatus s = zbc_lex_next_and_skip_NLINE(); |
3744 | if (s) RETURN_STATUS(s); | 3766 | if (s) RETURN_STATUS(s); |
3745 | if (p->l.lex == XC_LEX_NLINE) | 3767 | if (p->l.lex == XC_LEX_NLINE) |
3746 | RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); | 3768 | RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X)); |
3747 | 3769 | ||
3748 | RETURN_STATUS(zbc_parse_stmt(p)); | 3770 | RETURN_STATUS(zbc_parse_stmt()); |
3749 | } | 3771 | } |
3750 | #define zbc_parse_stmt_allow_NLINE_before(...) (zbc_parse_stmt_allow_NLINE_before(__VA_ARGS__) COMMA_SUCCESS) | 3772 | #define zbc_parse_stmt_allow_NLINE_before(...) (zbc_parse_stmt_allow_NLINE_before(__VA_ARGS__) COMMA_SUCCESS) |
3751 | 3773 | ||
3752 | static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, | 3774 | static void bc_parse_operator(BcLexType type, size_t start, size_t *nexprs) |
3753 | size_t *nexprs) | ||
3754 | { | 3775 | { |
3776 | BcParse *p = &G.prs; | ||
3755 | char l, r = bc_parse_op_PREC(type - XC_LEX_1st_op); | 3777 | char l, r = bc_parse_op_PREC(type - XC_LEX_1st_op); |
3756 | bool left = bc_parse_op_LEFT(type - XC_LEX_1st_op); | 3778 | bool left = bc_parse_op_LEFT(type - XC_LEX_1st_op); |
3757 | 3779 | ||
@@ -3762,7 +3784,7 @@ static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, | |||
3762 | l = bc_parse_op_PREC(t - XC_LEX_1st_op); | 3784 | l = bc_parse_op_PREC(t - XC_LEX_1st_op); |
3763 | if (l >= r && (l != r || !left)) break; | 3785 | if (l >= r && (l != r || !left)) break; |
3764 | 3786 | ||
3765 | bc_parse_push(p, BC_TOKEN_2_INST(t)); | 3787 | bc_parse_push(BC_TOKEN_2_INST(t)); |
3766 | bc_vec_pop(&p->ops); | 3788 | bc_vec_pop(&p->ops); |
3767 | *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != XC_LEX_NEG); | 3789 | *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != XC_LEX_NEG); |
3768 | } | 3790 | } |
@@ -3770,8 +3792,9 @@ static void bc_parse_operator(BcParse *p, BcLexType type, size_t start, | |||
3770 | bc_vec_push(&p->ops, &type); | 3792 | bc_vec_push(&p->ops, &type); |
3771 | } | 3793 | } |
3772 | 3794 | ||
3773 | static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) | 3795 | static BC_STATUS zbc_parse_rightParen(size_t ops_bgn, size_t *nexs) |
3774 | { | 3796 | { |
3797 | BcParse *p = &G.prs; | ||
3775 | BcLexType top; | 3798 | BcLexType top; |
3776 | 3799 | ||
3777 | if (p->ops.len <= ops_bgn) | 3800 | if (p->ops.len <= ops_bgn) |
@@ -3779,7 +3802,7 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) | |||
3779 | top = BC_PARSE_TOP_OP(p); | 3802 | top = BC_PARSE_TOP_OP(p); |
3780 | 3803 | ||
3781 | while (top != BC_LEX_LPAREN) { | 3804 | while (top != BC_LEX_LPAREN) { |
3782 | bc_parse_push(p, BC_TOKEN_2_INST(top)); | 3805 | bc_parse_push(BC_TOKEN_2_INST(top)); |
3783 | 3806 | ||
3784 | bc_vec_pop(&p->ops); | 3807 | bc_vec_pop(&p->ops); |
3785 | *nexs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); | 3808 | *nexs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); |
@@ -3795,21 +3818,22 @@ static BC_STATUS zbc_parse_rightParen(BcParse *p, size_t ops_bgn, size_t *nexs) | |||
3795 | } | 3818 | } |
3796 | #define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__) COMMA_SUCCESS) | 3819 | #define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__) COMMA_SUCCESS) |
3797 | 3820 | ||
3798 | static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) | 3821 | static BC_STATUS zbc_parse_params(uint8_t flags) |
3799 | { | 3822 | { |
3823 | BcParse *p = &G.prs; | ||
3800 | BcStatus s; | 3824 | BcStatus s; |
3801 | size_t nparams; | 3825 | size_t nparams; |
3802 | 3826 | ||
3803 | dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); | 3827 | dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); |
3804 | flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; | 3828 | flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; |
3805 | 3829 | ||
3806 | s = zbc_lex_next(&p->l); | 3830 | s = zbc_lex_next(); |
3807 | if (s) RETURN_STATUS(s); | 3831 | if (s) RETURN_STATUS(s); |
3808 | 3832 | ||
3809 | nparams = 0; | 3833 | nparams = 0; |
3810 | if (p->l.lex != BC_LEX_RPAREN) { | 3834 | if (p->l.lex != BC_LEX_RPAREN) { |
3811 | for (;;) { | 3835 | for (;;) { |
3812 | s = zbc_parse_expr(p, flags); | 3836 | s = zbc_parse_expr(flags); |
3813 | if (s) RETURN_STATUS(s); | 3837 | if (s) RETURN_STATUS(s); |
3814 | nparams++; | 3838 | nparams++; |
3815 | if (p->l.lex != BC_LEX_COMMA) { | 3839 | if (p->l.lex != BC_LEX_COMMA) { |
@@ -3817,28 +3841,29 @@ static BC_STATUS zbc_parse_params(BcParse *p, uint8_t flags) | |||
3817 | break; | 3841 | break; |
3818 | RETURN_STATUS(bc_error_bad_token()); | 3842 | RETURN_STATUS(bc_error_bad_token()); |
3819 | } | 3843 | } |
3820 | s = zbc_lex_next(&p->l); | 3844 | s = zbc_lex_next(); |
3821 | if (s) RETURN_STATUS(s); | 3845 | if (s) RETURN_STATUS(s); |
3822 | } | 3846 | } |
3823 | } | 3847 | } |
3824 | 3848 | ||
3825 | bc_parse_push(p, BC_INST_CALL); | 3849 | bc_parse_push(BC_INST_CALL); |
3826 | bc_parse_pushIndex(p, nparams); | 3850 | bc_parse_pushIndex(nparams); |
3827 | 3851 | ||
3828 | RETURN_STATUS(BC_STATUS_SUCCESS); | 3852 | RETURN_STATUS(BC_STATUS_SUCCESS); |
3829 | } | 3853 | } |
3830 | #define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__) COMMA_SUCCESS) | 3854 | #define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__) COMMA_SUCCESS) |
3831 | 3855 | ||
3832 | // Note: takes ownership of 'name' (must be malloced) | 3856 | // Note: takes ownership of 'name' (must be malloced) |
3833 | static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) | 3857 | static BC_STATUS zbc_parse_call(char *name, uint8_t flags) |
3834 | { | 3858 | { |
3859 | BcParse *p = &G.prs; | ||
3835 | BcStatus s; | 3860 | BcStatus s; |
3836 | BcId entry, *entry_ptr; | 3861 | BcId entry, *entry_ptr; |
3837 | size_t idx; | 3862 | size_t idx; |
3838 | 3863 | ||
3839 | entry.name = name; | 3864 | entry.name = name; |
3840 | 3865 | ||
3841 | s = zbc_parse_params(p, flags); | 3866 | s = zbc_parse_params(flags); |
3842 | if (s) goto err; | 3867 | if (s) goto err; |
3843 | 3868 | ||
3844 | if (p->l.lex != BC_LEX_RPAREN) { | 3869 | if (p->l.lex != BC_LEX_RPAREN) { |
@@ -3856,26 +3881,27 @@ static BC_STATUS zbc_parse_call(BcParse *p, char *name, uint8_t flags) | |||
3856 | free(name); | 3881 | free(name); |
3857 | 3882 | ||
3858 | entry_ptr = bc_vec_item(&G.prog.fn_map, idx); | 3883 | entry_ptr = bc_vec_item(&G.prog.fn_map, idx); |
3859 | bc_parse_pushIndex(p, entry_ptr->idx); | 3884 | bc_parse_pushIndex(entry_ptr->idx); |
3860 | 3885 | ||
3861 | RETURN_STATUS(zbc_lex_next(&p->l)); | 3886 | RETURN_STATUS(zbc_lex_next()); |
3862 | err: | 3887 | err: |
3863 | free(name); | 3888 | free(name); |
3864 | RETURN_STATUS(s); | 3889 | RETURN_STATUS(s); |
3865 | } | 3890 | } |
3866 | #define zbc_parse_call(...) (zbc_parse_call(__VA_ARGS__) COMMA_SUCCESS) | 3891 | #define zbc_parse_call(...) (zbc_parse_call(__VA_ARGS__) COMMA_SUCCESS) |
3867 | 3892 | ||
3868 | static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) | 3893 | static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags) |
3869 | { | 3894 | { |
3895 | BcParse *p = &G.prs; | ||
3870 | BcStatus s; | 3896 | BcStatus s; |
3871 | char *name; | 3897 | char *name; |
3872 | 3898 | ||
3873 | name = xstrdup(p->l.lex_buf.v); | 3899 | name = xstrdup(p->l.lex_buf.v); |
3874 | s = zbc_lex_next(&p->l); | 3900 | s = zbc_lex_next(); |
3875 | if (s) goto err; | 3901 | if (s) goto err; |
3876 | 3902 | ||
3877 | if (p->l.lex == BC_LEX_LBRACKET) { | 3903 | if (p->l.lex == BC_LEX_LBRACKET) { |
3878 | s = zbc_lex_next(&p->l); | 3904 | s = zbc_lex_next(); |
3879 | if (s) goto err; | 3905 | if (s) goto err; |
3880 | 3906 | ||
3881 | if (p->l.lex == BC_LEX_RBRACKET) { | 3907 | if (p->l.lex == BC_LEX_RBRACKET) { |
@@ -3887,13 +3913,13 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) | |||
3887 | } else { | 3913 | } else { |
3888 | *type = XC_INST_ARRAY_ELEM; | 3914 | *type = XC_INST_ARRAY_ELEM; |
3889 | flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); | 3915 | flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); |
3890 | s = zbc_parse_expr(p, flags); | 3916 | s = zbc_parse_expr(flags); |
3891 | if (s) goto err; | 3917 | if (s) goto err; |
3892 | } | 3918 | } |
3893 | s = zbc_lex_next(&p->l); | 3919 | s = zbc_lex_next(); |
3894 | if (s) goto err; | 3920 | if (s) goto err; |
3895 | bc_parse_push(p, *type); | 3921 | bc_parse_push(*type); |
3896 | bc_parse_pushName(p, name); | 3922 | bc_parse_pushName(name); |
3897 | free(name); | 3923 | free(name); |
3898 | } else if (p->l.lex == BC_LEX_LPAREN) { | 3924 | } else if (p->l.lex == BC_LEX_LPAREN) { |
3899 | if (flags & BC_PARSE_NOCALL) { | 3925 | if (flags & BC_PARSE_NOCALL) { |
@@ -3901,11 +3927,11 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) | |||
3901 | goto err; | 3927 | goto err; |
3902 | } | 3928 | } |
3903 | *type = BC_INST_CALL; | 3929 | *type = BC_INST_CALL; |
3904 | s = zbc_parse_call(p, name, flags); | 3930 | s = zbc_parse_call(name, flags); |
3905 | } else { | 3931 | } else { |
3906 | *type = XC_INST_VAR; | 3932 | *type = XC_INST_VAR; |
3907 | bc_parse_push(p, XC_INST_VAR); | 3933 | bc_parse_push(XC_INST_VAR); |
3908 | bc_parse_pushName(p, name); | 3934 | bc_parse_pushName(name); |
3909 | free(name); | 3935 | free(name); |
3910 | } | 3936 | } |
3911 | 3937 | ||
@@ -3916,82 +3942,85 @@ static BC_STATUS zbc_parse_name(BcParse *p, BcInst *type, uint8_t flags) | |||
3916 | } | 3942 | } |
3917 | #define zbc_parse_name(...) (zbc_parse_name(__VA_ARGS__) COMMA_SUCCESS) | 3943 | #define zbc_parse_name(...) (zbc_parse_name(__VA_ARGS__) COMMA_SUCCESS) |
3918 | 3944 | ||
3919 | static BC_STATUS zbc_parse_read(BcParse *p) | 3945 | static BC_STATUS zbc_parse_read(void) |
3920 | { | 3946 | { |
3947 | BcParse *p = &G.prs; | ||
3921 | BcStatus s; | 3948 | BcStatus s; |
3922 | 3949 | ||
3923 | s = zbc_lex_next(&p->l); | 3950 | s = zbc_lex_next(); |
3924 | if (s) RETURN_STATUS(s); | 3951 | if (s) RETURN_STATUS(s); |
3925 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); | 3952 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); |
3926 | 3953 | ||
3927 | s = zbc_lex_next(&p->l); | 3954 | s = zbc_lex_next(); |
3928 | if (s) RETURN_STATUS(s); | 3955 | if (s) RETURN_STATUS(s); |
3929 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); | 3956 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
3930 | 3957 | ||
3931 | bc_parse_push(p, XC_INST_READ); | 3958 | bc_parse_push(XC_INST_READ); |
3932 | 3959 | ||
3933 | RETURN_STATUS(s); | 3960 | RETURN_STATUS(s); |
3934 | } | 3961 | } |
3935 | #define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__) COMMA_SUCCESS) | 3962 | #define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__) COMMA_SUCCESS) |
3936 | 3963 | ||
3937 | static BC_STATUS zbc_parse_builtin(BcParse *p, BcLexType type, uint8_t flags, | 3964 | static BC_STATUS zbc_parse_builtin(BcLexType type, uint8_t flags, BcInst *prev) |
3938 | BcInst *prev) | ||
3939 | { | 3965 | { |
3966 | BcParse *p = &G.prs; | ||
3940 | BcStatus s; | 3967 | BcStatus s; |
3941 | 3968 | ||
3942 | s = zbc_lex_next(&p->l); | 3969 | s = zbc_lex_next(); |
3943 | if (s) RETURN_STATUS(s); | 3970 | if (s) RETURN_STATUS(s); |
3944 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); | 3971 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); |
3945 | 3972 | ||
3946 | flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; | 3973 | flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY; |
3947 | 3974 | ||
3948 | s = zbc_lex_next(&p->l); | 3975 | s = zbc_lex_next(); |
3949 | if (s) RETURN_STATUS(s); | 3976 | if (s) RETURN_STATUS(s); |
3950 | 3977 | ||
3951 | s = zbc_parse_expr(p, flags); | 3978 | s = zbc_parse_expr(flags); |
3952 | if (s) RETURN_STATUS(s); | 3979 | if (s) RETURN_STATUS(s); |
3953 | 3980 | ||
3954 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); | 3981 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
3955 | 3982 | ||
3956 | *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT; | 3983 | *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT; |
3957 | bc_parse_push(p, *prev); | 3984 | bc_parse_push(*prev); |
3958 | 3985 | ||
3959 | RETURN_STATUS(s); | 3986 | RETURN_STATUS(s); |
3960 | } | 3987 | } |
3961 | #define zbc_parse_builtin(...) (zbc_parse_builtin(__VA_ARGS__) COMMA_SUCCESS) | 3988 | #define zbc_parse_builtin(...) (zbc_parse_builtin(__VA_ARGS__) COMMA_SUCCESS) |
3962 | 3989 | ||
3963 | static BC_STATUS zbc_parse_scale(BcParse *p, BcInst *type, uint8_t flags) | 3990 | static BC_STATUS zbc_parse_scale(BcInst *type, uint8_t flags) |
3964 | { | 3991 | { |
3992 | BcParse *p = &G.prs; | ||
3965 | BcStatus s; | 3993 | BcStatus s; |
3966 | 3994 | ||
3967 | s = zbc_lex_next(&p->l); | 3995 | s = zbc_lex_next(); |
3968 | if (s) RETURN_STATUS(s); | 3996 | if (s) RETURN_STATUS(s); |
3969 | 3997 | ||
3970 | if (p->l.lex != BC_LEX_LPAREN) { | 3998 | if (p->l.lex != BC_LEX_LPAREN) { |
3971 | *type = XC_INST_SCALE; | 3999 | *type = XC_INST_SCALE; |
3972 | bc_parse_push(p, XC_INST_SCALE); | 4000 | bc_parse_push(XC_INST_SCALE); |
3973 | RETURN_STATUS(BC_STATUS_SUCCESS); | 4001 | RETURN_STATUS(BC_STATUS_SUCCESS); |
3974 | } | 4002 | } |
3975 | 4003 | ||
3976 | *type = XC_INST_SCALE_FUNC; | 4004 | *type = XC_INST_SCALE_FUNC; |
3977 | flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); | 4005 | flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL); |
3978 | 4006 | ||
3979 | s = zbc_lex_next(&p->l); | 4007 | s = zbc_lex_next(); |
3980 | if (s) RETURN_STATUS(s); | 4008 | if (s) RETURN_STATUS(s); |
3981 | 4009 | ||
3982 | s = zbc_parse_expr(p, flags); | 4010 | s = zbc_parse_expr(flags); |
3983 | if (s) RETURN_STATUS(s); | 4011 | if (s) RETURN_STATUS(s); |
3984 | if (p->l.lex != BC_LEX_RPAREN) | 4012 | if (p->l.lex != BC_LEX_RPAREN) |
3985 | RETURN_STATUS(bc_error_bad_token()); | 4013 | RETURN_STATUS(bc_error_bad_token()); |
3986 | bc_parse_push(p, XC_INST_SCALE_FUNC); | 4014 | bc_parse_push(XC_INST_SCALE_FUNC); |
3987 | 4015 | ||
3988 | RETURN_STATUS(zbc_lex_next(&p->l)); | 4016 | RETURN_STATUS(zbc_lex_next()); |
3989 | } | 4017 | } |
3990 | #define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS) | 4018 | #define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS) |
3991 | 4019 | ||
3992 | static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, | 4020 | static BC_STATUS zbc_parse_incdec(BcInst *prev, bool *paren_expr, |
3993 | size_t *nexprs, uint8_t flags) | 4021 | size_t *nexprs, uint8_t flags) |
3994 | { | 4022 | { |
4023 | BcParse *p = &G.prs; | ||
3995 | BcStatus s; | 4024 | BcStatus s; |
3996 | BcLexType type; | 4025 | BcLexType type; |
3997 | char inst; | 4026 | char inst; |
@@ -4002,13 +4031,13 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, | |||
4002 | || etype == XC_INST_IBASE || etype == XC_INST_OBASE | 4031 | || etype == XC_INST_IBASE || etype == XC_INST_OBASE |
4003 | ) { | 4032 | ) { |
4004 | *prev = inst = BC_INST_INC_POST + (p->l.lex != BC_LEX_OP_INC); | 4033 | *prev = inst = BC_INST_INC_POST + (p->l.lex != BC_LEX_OP_INC); |
4005 | bc_parse_push(p, inst); | 4034 | bc_parse_push(inst); |
4006 | s = zbc_lex_next(&p->l); | 4035 | s = zbc_lex_next(); |
4007 | } else { | 4036 | } else { |
4008 | *prev = inst = BC_INST_INC_PRE + (p->l.lex != BC_LEX_OP_INC); | 4037 | *prev = inst = BC_INST_INC_PRE + (p->l.lex != BC_LEX_OP_INC); |
4009 | *paren_expr = true; | 4038 | *paren_expr = true; |
4010 | 4039 | ||
4011 | s = zbc_lex_next(&p->l); | 4040 | s = zbc_lex_next(); |
4012 | if (s) RETURN_STATUS(s); | 4041 | if (s) RETURN_STATUS(s); |
4013 | type = p->l.lex; | 4042 | type = p->l.lex; |
4014 | 4043 | ||
@@ -4018,28 +4047,28 @@ static BC_STATUS zbc_parse_incdec(BcParse *p, BcInst *prev, bool *paren_expr, | |||
4018 | 4047 | ||
4019 | switch (type) { | 4048 | switch (type) { |
4020 | case XC_LEX_NAME: | 4049 | case XC_LEX_NAME: |
4021 | s = zbc_parse_name(p, prev, flags | BC_PARSE_NOCALL); | 4050 | s = zbc_parse_name(prev, flags | BC_PARSE_NOCALL); |
4022 | break; | 4051 | break; |
4023 | case BC_LEX_KEY_IBASE: | 4052 | case BC_LEX_KEY_IBASE: |
4024 | case BC_LEX_KEY_LAST: | 4053 | case BC_LEX_KEY_LAST: |
4025 | case BC_LEX_KEY_OBASE: | 4054 | case BC_LEX_KEY_OBASE: |
4026 | bc_parse_push(p, type - BC_LEX_KEY_IBASE + XC_INST_IBASE); | 4055 | bc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE); |
4027 | s = zbc_lex_next(&p->l); | 4056 | s = zbc_lex_next(); |
4028 | break; | 4057 | break; |
4029 | case BC_LEX_KEY_SCALE: | 4058 | case BC_LEX_KEY_SCALE: |
4030 | s = zbc_lex_next(&p->l); | 4059 | s = zbc_lex_next(); |
4031 | if (s) RETURN_STATUS(s); | 4060 | if (s) RETURN_STATUS(s); |
4032 | if (p->l.lex == BC_LEX_LPAREN) | 4061 | if (p->l.lex == BC_LEX_LPAREN) |
4033 | s = bc_error_bad_token(); | 4062 | s = bc_error_bad_token(); |
4034 | else | 4063 | else |
4035 | bc_parse_push(p, XC_INST_SCALE); | 4064 | bc_parse_push(XC_INST_SCALE); |
4036 | break; | 4065 | break; |
4037 | default: | 4066 | default: |
4038 | s = bc_error_bad_token(); | 4067 | s = bc_error_bad_token(); |
4039 | break; | 4068 | break; |
4040 | } | 4069 | } |
4041 | 4070 | ||
4042 | if (!s) bc_parse_push(p, inst); | 4071 | if (!s) bc_parse_push(inst); |
4043 | } | 4072 | } |
4044 | 4073 | ||
4045 | RETURN_STATUS(s); | 4074 | RETURN_STATUS(s); |
@@ -4064,14 +4093,15 @@ static int ok_in_expr(BcInst p) | |||
4064 | #define BC_PARSE_LEAF(p, rparen) ((rparen) || ok_in_expr(p)) | 4093 | #define BC_PARSE_LEAF(p, rparen) ((rparen) || ok_in_expr(p)) |
4065 | #endif | 4094 | #endif |
4066 | 4095 | ||
4067 | static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, | 4096 | static BC_STATUS zbc_parse_minus(BcInst *prev, size_t ops_bgn, |
4068 | bool rparen, size_t *nexprs) | 4097 | bool rparen, size_t *nexprs) |
4069 | { | 4098 | { |
4099 | BcParse *p = &G.prs; | ||
4070 | BcStatus s; | 4100 | BcStatus s; |
4071 | BcLexType type; | 4101 | BcLexType type; |
4072 | BcInst etype = *prev; | 4102 | BcInst etype = *prev; |
4073 | 4103 | ||
4074 | s = zbc_lex_next(&p->l); | 4104 | s = zbc_lex_next(); |
4075 | if (s) RETURN_STATUS(s); | 4105 | if (s) RETURN_STATUS(s); |
4076 | 4106 | ||
4077 | type = BC_PARSE_LEAF(etype, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG; | 4107 | type = BC_PARSE_LEAF(etype, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG; |
@@ -4082,28 +4112,29 @@ static BC_STATUS zbc_parse_minus(BcParse *p, BcInst *prev, size_t ops_bgn, | |||
4082 | if (type != XC_LEX_OP_MINUS) | 4112 | if (type != XC_LEX_OP_MINUS) |
4083 | bc_vec_push(&p->ops, &type); | 4113 | bc_vec_push(&p->ops, &type); |
4084 | else | 4114 | else |
4085 | bc_parse_operator(p, type, ops_bgn, nexprs); | 4115 | bc_parse_operator(type, ops_bgn, nexprs); |
4086 | 4116 | ||
4087 | RETURN_STATUS(s); | 4117 | RETURN_STATUS(s); |
4088 | } | 4118 | } |
4089 | #define zbc_parse_minus(...) (zbc_parse_minus(__VA_ARGS__) COMMA_SUCCESS) | 4119 | #define zbc_parse_minus(...) (zbc_parse_minus(__VA_ARGS__) COMMA_SUCCESS) |
4090 | 4120 | ||
4091 | static BC_STATUS zbc_parse_print(BcParse *p) | 4121 | static BC_STATUS zbc_parse_print(void) |
4092 | { | 4122 | { |
4123 | BcParse *p = &G.prs; | ||
4093 | BcStatus s; | 4124 | BcStatus s; |
4094 | BcLexType type; | 4125 | BcLexType type; |
4095 | 4126 | ||
4096 | for (;;) { | 4127 | for (;;) { |
4097 | s = zbc_lex_next(&p->l); | 4128 | s = zbc_lex_next(); |
4098 | if (s) RETURN_STATUS(s); | 4129 | if (s) RETURN_STATUS(s); |
4099 | type = p->l.lex; | 4130 | type = p->l.lex; |
4100 | if (type == XC_LEX_STR) { | 4131 | if (type == XC_LEX_STR) { |
4101 | s = zbc_parse_pushSTR(p); | 4132 | s = zbc_parse_pushSTR(); |
4102 | } else { | 4133 | } else { |
4103 | s = zbc_parse_expr(p, 0); | 4134 | s = zbc_parse_expr(0); |
4104 | } | 4135 | } |
4105 | if (s) RETURN_STATUS(s); | 4136 | if (s) RETURN_STATUS(s); |
4106 | bc_parse_push(p, XC_INST_PRINT_POP); | 4137 | bc_parse_push(XC_INST_PRINT_POP); |
4107 | if (p->l.lex != BC_LEX_COMMA) | 4138 | if (p->l.lex != BC_LEX_COMMA) |
4108 | break; | 4139 | break; |
4109 | } | 4140 | } |
@@ -4112,24 +4143,25 @@ static BC_STATUS zbc_parse_print(BcParse *p) | |||
4112 | } | 4143 | } |
4113 | #define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__) COMMA_SUCCESS) | 4144 | #define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__) COMMA_SUCCESS) |
4114 | 4145 | ||
4115 | static BC_STATUS zbc_parse_return(BcParse *p) | 4146 | static BC_STATUS zbc_parse_return(void) |
4116 | { | 4147 | { |
4148 | BcParse *p = &G.prs; | ||
4117 | BcStatus s; | 4149 | BcStatus s; |
4118 | BcLexType t; | 4150 | BcLexType t; |
4119 | 4151 | ||
4120 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 4152 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
4121 | s = zbc_lex_next(&p->l); | 4153 | s = zbc_lex_next(); |
4122 | if (s) RETURN_STATUS(s); | 4154 | if (s) RETURN_STATUS(s); |
4123 | 4155 | ||
4124 | t = p->l.lex; | 4156 | t = p->l.lex; |
4125 | if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON) | 4157 | if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON) |
4126 | bc_parse_push(p, BC_INST_RET0); | 4158 | bc_parse_push(BC_INST_RET0); |
4127 | else { | 4159 | else { |
4128 | bool paren = (t == BC_LEX_LPAREN); | 4160 | bool paren = (t == BC_LEX_LPAREN); |
4129 | s = bc_parse_expr_empty_ok(p, 0); | 4161 | s = bc_parse_expr_empty_ok(0); |
4130 | if (s == BC_STATUS_PARSE_EMPTY_EXP) { | 4162 | if (s == BC_STATUS_PARSE_EMPTY_EXP) { |
4131 | bc_parse_push(p, BC_INST_RET0); | 4163 | bc_parse_push(BC_INST_RET0); |
4132 | s = zbc_lex_next(&p->l); | 4164 | s = zbc_lex_next(); |
4133 | } | 4165 | } |
4134 | if (s) RETURN_STATUS(s); | 4166 | if (s) RETURN_STATUS(s); |
4135 | 4167 | ||
@@ -4138,7 +4170,7 @@ static BC_STATUS zbc_parse_return(BcParse *p) | |||
4138 | if (s) RETURN_STATUS(s); | 4170 | if (s) RETURN_STATUS(s); |
4139 | } | 4171 | } |
4140 | 4172 | ||
4141 | bc_parse_push(p, XC_INST_RET); | 4173 | bc_parse_push(XC_INST_RET); |
4142 | } | 4174 | } |
4143 | 4175 | ||
4144 | dbg_lex_done("%s:%d done", __func__, __LINE__); | 4176 | dbg_lex_done("%s:%d done", __func__, __LINE__); |
@@ -4146,25 +4178,27 @@ static BC_STATUS zbc_parse_return(BcParse *p) | |||
4146 | } | 4178 | } |
4147 | #define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__) COMMA_SUCCESS) | 4179 | #define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__) COMMA_SUCCESS) |
4148 | 4180 | ||
4149 | static void rewrite_label_to_current(BcParse *p, size_t idx) | 4181 | static void rewrite_label_to_current(size_t idx) |
4150 | { | 4182 | { |
4183 | BcParse *p = &G.prs; | ||
4151 | size_t *label = bc_vec_item(&p->func->labels, idx); | 4184 | size_t *label = bc_vec_item(&p->func->labels, idx); |
4152 | *label = p->func->code.len; | 4185 | *label = p->func->code.len; |
4153 | } | 4186 | } |
4154 | 4187 | ||
4155 | static BC_STATUS zbc_parse_if(BcParse *p) | 4188 | static BC_STATUS zbc_parse_if(void) |
4156 | { | 4189 | { |
4190 | BcParse *p = &G.prs; | ||
4157 | BcStatus s; | 4191 | BcStatus s; |
4158 | size_t ip_idx; | 4192 | size_t ip_idx; |
4159 | 4193 | ||
4160 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 4194 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
4161 | s = zbc_lex_next(&p->l); | 4195 | s = zbc_lex_next(); |
4162 | if (s) RETURN_STATUS(s); | 4196 | if (s) RETURN_STATUS(s); |
4163 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); | 4197 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); |
4164 | 4198 | ||
4165 | s = zbc_lex_next(&p->l); | 4199 | s = zbc_lex_next(); |
4166 | if (s) RETURN_STATUS(s); | 4200 | if (s) RETURN_STATUS(s); |
4167 | s = zbc_parse_expr(p, BC_PARSE_REL); | 4201 | s = zbc_parse_expr(BC_PARSE_REL); |
4168 | if (s) RETURN_STATUS(s); | 4202 | if (s) RETURN_STATUS(s); |
4169 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); | 4203 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
4170 | 4204 | ||
@@ -4172,9 +4206,9 @@ static BC_STATUS zbc_parse_if(BcParse *p) | |||
4172 | // Pushed value (destination of the jump) is uninitialized, | 4206 | // Pushed value (destination of the jump) is uninitialized, |
4173 | // will be rewritten to be address of "end of if()" or of "else". | 4207 | // will be rewritten to be address of "end of if()" or of "else". |
4174 | ip_idx = bc_vec_push(&p->func->labels, &ip_idx); | 4208 | ip_idx = bc_vec_push(&p->func->labels, &ip_idx); |
4175 | bc_parse_pushJUMP_ZERO(p, ip_idx); | 4209 | bc_parse_pushJUMP_ZERO(ip_idx); |
4176 | 4210 | ||
4177 | s = zbc_parse_stmt_allow_NLINE_before(p, STRING_if); | 4211 | s = zbc_parse_stmt_allow_NLINE_before(STRING_if); |
4178 | if (s) RETURN_STATUS(s); | 4212 | if (s) RETURN_STATUS(s); |
4179 | 4213 | ||
4180 | dbg_lex("%s:%d in if after stmt: p->l.lex:%d", __func__, __LINE__, p->l.lex); | 4214 | dbg_lex("%s:%d in if after stmt: p->l.lex:%d", __func__, __LINE__, p->l.lex); |
@@ -4184,35 +4218,36 @@ static BC_STATUS zbc_parse_if(BcParse *p) | |||
4184 | // Encode "after then_stmt, jump to end of if()" | 4218 | // Encode "after then_stmt, jump to end of if()" |
4185 | ip2_idx = bc_vec_push(&p->func->labels, &ip2_idx); | 4219 | ip2_idx = bc_vec_push(&p->func->labels, &ip2_idx); |
4186 | dbg_lex("%s:%d after if() then_stmt: BC_INST_JUMP to %zd", __func__, __LINE__, ip2_idx); | 4220 | dbg_lex("%s:%d after if() then_stmt: BC_INST_JUMP to %zd", __func__, __LINE__, ip2_idx); |
4187 | bc_parse_pushJUMP(p, ip2_idx); | 4221 | bc_parse_pushJUMP(ip2_idx); |
4188 | 4222 | ||
4189 | dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else'-> %zd", __func__, __LINE__, p->func->code.len); | 4223 | dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else'-> %zd", __func__, __LINE__, p->func->code.len); |
4190 | rewrite_label_to_current(p, ip_idx); | 4224 | rewrite_label_to_current(ip_idx); |
4191 | 4225 | ||
4192 | ip_idx = ip2_idx; | 4226 | ip_idx = ip2_idx; |
4193 | 4227 | ||
4194 | s = zbc_parse_stmt_allow_NLINE_before(p, STRING_else); | 4228 | s = zbc_parse_stmt_allow_NLINE_before(STRING_else); |
4195 | if (s) RETURN_STATUS(s); | 4229 | if (s) RETURN_STATUS(s); |
4196 | } | 4230 | } |
4197 | 4231 | ||
4198 | dbg_lex("%s:%d rewriting label to jump after 'if' body-> %zd", __func__, __LINE__, p->func->code.len); | 4232 | dbg_lex("%s:%d rewriting label to jump after 'if' body-> %zd", __func__, __LINE__, p->func->code.len); |
4199 | rewrite_label_to_current(p, ip_idx); | 4233 | rewrite_label_to_current(ip_idx); |
4200 | 4234 | ||
4201 | dbg_lex_done("%s:%d done", __func__, __LINE__); | 4235 | dbg_lex_done("%s:%d done", __func__, __LINE__); |
4202 | RETURN_STATUS(s); | 4236 | RETURN_STATUS(s); |
4203 | } | 4237 | } |
4204 | #define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__) COMMA_SUCCESS) | 4238 | #define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__) COMMA_SUCCESS) |
4205 | 4239 | ||
4206 | static BC_STATUS zbc_parse_while(BcParse *p) | 4240 | static BC_STATUS zbc_parse_while(void) |
4207 | { | 4241 | { |
4242 | BcParse *p = &G.prs; | ||
4208 | BcStatus s; | 4243 | BcStatus s; |
4209 | size_t cond_idx; | 4244 | size_t cond_idx; |
4210 | size_t ip_idx; | 4245 | size_t ip_idx; |
4211 | 4246 | ||
4212 | s = zbc_lex_next(&p->l); | 4247 | s = zbc_lex_next(); |
4213 | if (s) RETURN_STATUS(s); | 4248 | if (s) RETURN_STATUS(s); |
4214 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); | 4249 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); |
4215 | s = zbc_lex_next(&p->l); | 4250 | s = zbc_lex_next(); |
4216 | if (s) RETURN_STATUS(s); | 4251 | if (s) RETURN_STATUS(s); |
4217 | 4252 | ||
4218 | cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); | 4253 | cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); |
@@ -4222,20 +4257,20 @@ static BC_STATUS zbc_parse_while(BcParse *p) | |||
4222 | bc_vec_push(&p->exits, &ip_idx); | 4257 | bc_vec_push(&p->exits, &ip_idx); |
4223 | bc_vec_push(&p->func->labels, &ip_idx); | 4258 | bc_vec_push(&p->func->labels, &ip_idx); |
4224 | 4259 | ||
4225 | s = zbc_parse_expr(p, BC_PARSE_REL); | 4260 | s = zbc_parse_expr(BC_PARSE_REL); |
4226 | if (s) RETURN_STATUS(s); | 4261 | if (s) RETURN_STATUS(s); |
4227 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); | 4262 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
4228 | 4263 | ||
4229 | bc_parse_pushJUMP_ZERO(p, ip_idx); | 4264 | bc_parse_pushJUMP_ZERO(ip_idx); |
4230 | 4265 | ||
4231 | s = zbc_parse_stmt_allow_NLINE_before(p, STRING_while); | 4266 | s = zbc_parse_stmt_allow_NLINE_before(STRING_while); |
4232 | if (s) RETURN_STATUS(s); | 4267 | if (s) RETURN_STATUS(s); |
4233 | 4268 | ||
4234 | dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, cond_idx); | 4269 | dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, cond_idx); |
4235 | bc_parse_pushJUMP(p, cond_idx); | 4270 | bc_parse_pushJUMP(cond_idx); |
4236 | 4271 | ||
4237 | dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len); | 4272 | dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len); |
4238 | rewrite_label_to_current(p, ip_idx); | 4273 | rewrite_label_to_current(ip_idx); |
4239 | 4274 | ||
4240 | bc_vec_pop(&p->exits); | 4275 | bc_vec_pop(&p->exits); |
4241 | bc_vec_pop(&p->conds); | 4276 | bc_vec_pop(&p->conds); |
@@ -4244,21 +4279,22 @@ static BC_STATUS zbc_parse_while(BcParse *p) | |||
4244 | } | 4279 | } |
4245 | #define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__) COMMA_SUCCESS) | 4280 | #define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__) COMMA_SUCCESS) |
4246 | 4281 | ||
4247 | static BC_STATUS zbc_parse_for(BcParse *p) | 4282 | static BC_STATUS zbc_parse_for(void) |
4248 | { | 4283 | { |
4284 | BcParse *p = &G.prs; | ||
4249 | BcStatus s; | 4285 | BcStatus s; |
4250 | size_t cond_idx, exit_idx, body_idx, update_idx; | 4286 | size_t cond_idx, exit_idx, body_idx, update_idx; |
4251 | 4287 | ||
4252 | dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); | 4288 | dbg_lex("%s:%d p->l.lex:%d", __func__, __LINE__, p->l.lex); |
4253 | s = zbc_lex_next(&p->l); | 4289 | s = zbc_lex_next(); |
4254 | if (s) RETURN_STATUS(s); | 4290 | if (s) RETURN_STATUS(s); |
4255 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); | 4291 | if (p->l.lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token()); |
4256 | s = zbc_lex_next(&p->l); | 4292 | s = zbc_lex_next(); |
4257 | if (s) RETURN_STATUS(s); | 4293 | if (s) RETURN_STATUS(s); |
4258 | 4294 | ||
4259 | if (p->l.lex != BC_LEX_SCOLON) { | 4295 | if (p->l.lex != BC_LEX_SCOLON) { |
4260 | s = zbc_parse_expr(p, 0); | 4296 | s = zbc_parse_expr(0); |
4261 | bc_parse_push(p, XC_INST_POP); | 4297 | bc_parse_push(XC_INST_POP); |
4262 | if (s) RETURN_STATUS(s); | 4298 | if (s) RETURN_STATUS(s); |
4263 | } else { | 4299 | } else { |
4264 | s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("init"); | 4300 | s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("init"); |
@@ -4266,7 +4302,7 @@ static BC_STATUS zbc_parse_for(BcParse *p) | |||
4266 | } | 4302 | } |
4267 | 4303 | ||
4268 | if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); | 4304 | if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); |
4269 | s = zbc_lex_next(&p->l); | 4305 | s = zbc_lex_next(); |
4270 | if (s) RETURN_STATUS(s); | 4306 | if (s) RETURN_STATUS(s); |
4271 | 4307 | ||
4272 | cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); | 4308 | cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len); |
@@ -4275,52 +4311,52 @@ static BC_STATUS zbc_parse_for(BcParse *p) | |||
4275 | exit_idx = body_idx + 1; | 4311 | exit_idx = body_idx + 1; |
4276 | 4312 | ||
4277 | if (p->l.lex != BC_LEX_SCOLON) | 4313 | if (p->l.lex != BC_LEX_SCOLON) |
4278 | s = zbc_parse_expr(p, BC_PARSE_REL); | 4314 | s = zbc_parse_expr(BC_PARSE_REL); |
4279 | else { | 4315 | else { |
4280 | // Set this for the next call to bc_parse_pushNUM(). | 4316 | // Set this for the next call to bc_parse_pushNUM(). |
4281 | // This is safe to set because the current token is a semicolon, | 4317 | // This is safe to set because the current token is a semicolon, |
4282 | // which has no string requirement. | 4318 | // which has no string requirement. |
4283 | bc_vec_string(&p->l.lex_buf, 1, "1"); | 4319 | bc_vec_string(&p->l.lex_buf, 1, "1"); |
4284 | bc_parse_pushNUM(p); | 4320 | bc_parse_pushNUM(); |
4285 | s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); | 4321 | s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); |
4286 | } | 4322 | } |
4287 | if (s) RETURN_STATUS(s); | 4323 | if (s) RETURN_STATUS(s); |
4288 | 4324 | ||
4289 | if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); | 4325 | if (p->l.lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); |
4290 | 4326 | ||
4291 | s = zbc_lex_next(&p->l); | 4327 | s = zbc_lex_next(); |
4292 | if (s) RETURN_STATUS(s); | 4328 | if (s) RETURN_STATUS(s); |
4293 | 4329 | ||
4294 | bc_parse_pushJUMP_ZERO(p, exit_idx); | 4330 | bc_parse_pushJUMP_ZERO(exit_idx); |
4295 | bc_parse_pushJUMP(p, body_idx); | 4331 | bc_parse_pushJUMP(body_idx); |
4296 | 4332 | ||
4297 | bc_vec_push(&p->conds, &update_idx); | 4333 | bc_vec_push(&p->conds, &update_idx); |
4298 | bc_vec_push(&p->func->labels, &p->func->code.len); | 4334 | bc_vec_push(&p->func->labels, &p->func->code.len); |
4299 | 4335 | ||
4300 | if (p->l.lex != BC_LEX_RPAREN) { | 4336 | if (p->l.lex != BC_LEX_RPAREN) { |
4301 | s = zbc_parse_expr(p, 0); | 4337 | s = zbc_parse_expr(0); |
4302 | if (s) RETURN_STATUS(s); | 4338 | if (s) RETURN_STATUS(s); |
4303 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); | 4339 | if (p->l.lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); |
4304 | bc_parse_push(p, XC_INST_POP); | 4340 | bc_parse_push(XC_INST_POP); |
4305 | } else { | 4341 | } else { |
4306 | s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("update"); | 4342 | s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("update"); |
4307 | if (s) RETURN_STATUS(s); | 4343 | if (s) RETURN_STATUS(s); |
4308 | } | 4344 | } |
4309 | 4345 | ||
4310 | bc_parse_pushJUMP(p, cond_idx); | 4346 | bc_parse_pushJUMP(cond_idx); |
4311 | bc_vec_push(&p->func->labels, &p->func->code.len); | 4347 | bc_vec_push(&p->func->labels, &p->func->code.len); |
4312 | 4348 | ||
4313 | bc_vec_push(&p->exits, &exit_idx); | 4349 | bc_vec_push(&p->exits, &exit_idx); |
4314 | bc_vec_push(&p->func->labels, &exit_idx); | 4350 | bc_vec_push(&p->func->labels, &exit_idx); |
4315 | 4351 | ||
4316 | s = zbc_parse_stmt_allow_NLINE_before(p, STRING_for); | 4352 | s = zbc_parse_stmt_allow_NLINE_before(STRING_for); |
4317 | if (s) RETURN_STATUS(s); | 4353 | if (s) RETURN_STATUS(s); |
4318 | 4354 | ||
4319 | dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, update_idx); | 4355 | dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, update_idx); |
4320 | bc_parse_pushJUMP(p, update_idx); | 4356 | bc_parse_pushJUMP(update_idx); |
4321 | 4357 | ||
4322 | dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len); | 4358 | dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len); |
4323 | rewrite_label_to_current(p, exit_idx); | 4359 | rewrite_label_to_current(exit_idx); |
4324 | 4360 | ||
4325 | bc_vec_pop(&p->exits); | 4361 | bc_vec_pop(&p->exits); |
4326 | bc_vec_pop(&p->conds); | 4362 | bc_vec_pop(&p->conds); |
@@ -4329,8 +4365,9 @@ static BC_STATUS zbc_parse_for(BcParse *p) | |||
4329 | } | 4365 | } |
4330 | #define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__) COMMA_SUCCESS) | 4366 | #define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__) COMMA_SUCCESS) |
4331 | 4367 | ||
4332 | static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) | 4368 | static BC_STATUS zbc_parse_break_or_continue(BcLexType type) |
4333 | { | 4369 | { |
4370 | BcParse *p = &G.prs; | ||
4334 | size_t i; | 4371 | size_t i; |
4335 | 4372 | ||
4336 | if (type == BC_LEX_KEY_BREAK) { | 4373 | if (type == BC_LEX_KEY_BREAK) { |
@@ -4340,9 +4377,9 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) | |||
4340 | } else { | 4377 | } else { |
4341 | i = *(size_t*)bc_vec_top(&p->conds); | 4378 | i = *(size_t*)bc_vec_top(&p->conds); |
4342 | } | 4379 | } |
4343 | bc_parse_pushJUMP(p, i); | 4380 | bc_parse_pushJUMP(i); |
4344 | 4381 | ||
4345 | RETURN_STATUS(zbc_lex_next(&p->l)); | 4382 | RETURN_STATUS(zbc_lex_next()); |
4346 | } | 4383 | } |
4347 | #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) | 4384 | #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) |
4348 | 4385 | ||
@@ -4367,14 +4404,15 @@ static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) | |||
4367 | } | 4404 | } |
4368 | #define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) | 4405 | #define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) |
4369 | 4406 | ||
4370 | static BC_STATUS zbc_parse_funcdef(BcParse *p) | 4407 | static BC_STATUS zbc_parse_funcdef(void) |
4371 | { | 4408 | { |
4409 | BcParse *p = &G.prs; | ||
4372 | BcStatus s; | 4410 | BcStatus s; |
4373 | bool var, comma = false; | 4411 | bool var, comma = false; |
4374 | char *name; | 4412 | char *name; |
4375 | 4413 | ||
4376 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 4414 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
4377 | s = zbc_lex_next(&p->l); | 4415 | s = zbc_lex_next(); |
4378 | if (s) RETURN_STATUS(s); | 4416 | if (s) RETURN_STATUS(s); |
4379 | if (p->l.lex != XC_LEX_NAME) | 4417 | if (p->l.lex != XC_LEX_NAME) |
4380 | RETURN_STATUS(bc_error("bad function definition")); | 4418 | RETURN_STATUS(bc_error("bad function definition")); |
@@ -4383,11 +4421,11 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) | |||
4383 | p->fidx = bc_program_addFunc(name); | 4421 | p->fidx = bc_program_addFunc(name); |
4384 | p->func = bc_program_func(p->fidx); | 4422 | p->func = bc_program_func(p->fidx); |
4385 | 4423 | ||
4386 | s = zbc_lex_next(&p->l); | 4424 | s = zbc_lex_next(); |
4387 | if (s) RETURN_STATUS(s); | 4425 | if (s) RETURN_STATUS(s); |
4388 | if (p->l.lex != BC_LEX_LPAREN) | 4426 | if (p->l.lex != BC_LEX_LPAREN) |
4389 | RETURN_STATUS(bc_error("bad function definition")); | 4427 | RETURN_STATUS(bc_error("bad function definition")); |
4390 | s = zbc_lex_next(&p->l); | 4428 | s = zbc_lex_next(); |
4391 | if (s) RETURN_STATUS(s); | 4429 | if (s) RETURN_STATUS(s); |
4392 | 4430 | ||
4393 | while (p->l.lex != BC_LEX_RPAREN) { | 4431 | while (p->l.lex != BC_LEX_RPAREN) { |
@@ -4397,13 +4435,13 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) | |||
4397 | ++p->func->nparams; | 4435 | ++p->func->nparams; |
4398 | 4436 | ||
4399 | name = xstrdup(p->l.lex_buf.v); | 4437 | name = xstrdup(p->l.lex_buf.v); |
4400 | s = zbc_lex_next(&p->l); | 4438 | s = zbc_lex_next(); |
4401 | if (s) goto err; | 4439 | if (s) goto err; |
4402 | 4440 | ||
4403 | var = p->l.lex != BC_LEX_LBRACKET; | 4441 | var = p->l.lex != BC_LEX_LBRACKET; |
4404 | 4442 | ||
4405 | if (!var) { | 4443 | if (!var) { |
4406 | s = zbc_lex_next(&p->l); | 4444 | s = zbc_lex_next(); |
4407 | if (s) goto err; | 4445 | if (s) goto err; |
4408 | 4446 | ||
4409 | if (p->l.lex != BC_LEX_RBRACKET) { | 4447 | if (p->l.lex != BC_LEX_RBRACKET) { |
@@ -4411,13 +4449,13 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) | |||
4411 | goto err; | 4449 | goto err; |
4412 | } | 4450 | } |
4413 | 4451 | ||
4414 | s = zbc_lex_next(&p->l); | 4452 | s = zbc_lex_next(); |
4415 | if (s) goto err; | 4453 | if (s) goto err; |
4416 | } | 4454 | } |
4417 | 4455 | ||
4418 | comma = p->l.lex == BC_LEX_COMMA; | 4456 | comma = p->l.lex == BC_LEX_COMMA; |
4419 | if (comma) { | 4457 | if (comma) { |
4420 | s = zbc_lex_next(&p->l); | 4458 | s = zbc_lex_next(); |
4421 | if (s) goto err; | 4459 | if (s) goto err; |
4422 | } | 4460 | } |
4423 | 4461 | ||
@@ -4427,7 +4465,7 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) | |||
4427 | 4465 | ||
4428 | if (comma) RETURN_STATUS(bc_error("bad function definition")); | 4466 | if (comma) RETURN_STATUS(bc_error("bad function definition")); |
4429 | 4467 | ||
4430 | s = zbc_lex_next(&p->l); | 4468 | s = zbc_lex_next(); |
4431 | if (s) RETURN_STATUS(s); | 4469 | if (s) RETURN_STATUS(s); |
4432 | 4470 | ||
4433 | if (p->l.lex != BC_LEX_LBRACE) { | 4471 | if (p->l.lex != BC_LEX_LBRACE) { |
@@ -4436,18 +4474,18 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) | |||
4436 | } | 4474 | } |
4437 | 4475 | ||
4438 | // Prevent "define z()<newline>" from being interpreted as function with empty stmt as body | 4476 | // Prevent "define z()<newline>" from being interpreted as function with empty stmt as body |
4439 | s = zbc_lex_skip_if_at_NLINE(&p->l); | 4477 | s = zbc_lex_skip_if_at_NLINE(); |
4440 | if (s) RETURN_STATUS(s); | 4478 | if (s) RETURN_STATUS(s); |
4441 | //GNU bc requires a {} block even if function body has single stmt, enforce this? | 4479 | //GNU bc requires a {} block even if function body has single stmt, enforce this? |
4442 | if (p->l.lex != BC_LEX_LBRACE) | 4480 | if (p->l.lex != BC_LEX_LBRACE) |
4443 | RETURN_STATUS(bc_error("function { body } expected")); | 4481 | RETURN_STATUS(bc_error("function { body } expected")); |
4444 | 4482 | ||
4445 | p->in_funcdef++; // to determine whether "return" stmt is allowed, and such | 4483 | p->in_funcdef++; // to determine whether "return" stmt is allowed, and such |
4446 | s = zbc_parse_stmt_possibly_auto(p, true); | 4484 | s = zbc_parse_stmt_possibly_auto(true); |
4447 | p->in_funcdef--; | 4485 | p->in_funcdef--; |
4448 | if (s) RETURN_STATUS(s); | 4486 | if (s) RETURN_STATUS(s); |
4449 | 4487 | ||
4450 | bc_parse_push(p, BC_INST_RET0); | 4488 | bc_parse_push(BC_INST_RET0); |
4451 | 4489 | ||
4452 | // Subsequent code generation is into main program | 4490 | // Subsequent code generation is into main program |
4453 | p->fidx = BC_PROG_MAIN; | 4491 | p->fidx = BC_PROG_MAIN; |
@@ -4462,13 +4500,14 @@ static BC_STATUS zbc_parse_funcdef(BcParse *p) | |||
4462 | } | 4500 | } |
4463 | #define zbc_parse_funcdef(...) (zbc_parse_funcdef(__VA_ARGS__) COMMA_SUCCESS) | 4501 | #define zbc_parse_funcdef(...) (zbc_parse_funcdef(__VA_ARGS__) COMMA_SUCCESS) |
4464 | 4502 | ||
4465 | static BC_STATUS zbc_parse_auto(BcParse *p) | 4503 | static BC_STATUS zbc_parse_auto(void) |
4466 | { | 4504 | { |
4505 | BcParse *p = &G.prs; | ||
4467 | BcStatus s; | 4506 | BcStatus s; |
4468 | char *name; | 4507 | char *name; |
4469 | 4508 | ||
4470 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 4509 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
4471 | s = zbc_lex_next(&p->l); | 4510 | s = zbc_lex_next(); |
4472 | if (s) RETURN_STATUS(s); | 4511 | if (s) RETURN_STATUS(s); |
4473 | 4512 | ||
4474 | for (;;) { | 4513 | for (;;) { |
@@ -4478,19 +4517,19 @@ static BC_STATUS zbc_parse_auto(BcParse *p) | |||
4478 | RETURN_STATUS(bc_error("bad 'auto' syntax")); | 4517 | RETURN_STATUS(bc_error("bad 'auto' syntax")); |
4479 | 4518 | ||
4480 | name = xstrdup(p->l.lex_buf.v); | 4519 | name = xstrdup(p->l.lex_buf.v); |
4481 | s = zbc_lex_next(&p->l); | 4520 | s = zbc_lex_next(); |
4482 | if (s) goto err; | 4521 | if (s) goto err; |
4483 | 4522 | ||
4484 | var = (p->l.lex != BC_LEX_LBRACKET); | 4523 | var = (p->l.lex != BC_LEX_LBRACKET); |
4485 | if (!var) { | 4524 | if (!var) { |
4486 | s = zbc_lex_next(&p->l); | 4525 | s = zbc_lex_next(); |
4487 | if (s) goto err; | 4526 | if (s) goto err; |
4488 | 4527 | ||
4489 | if (p->l.lex != BC_LEX_RBRACKET) { | 4528 | if (p->l.lex != BC_LEX_RBRACKET) { |
4490 | s = bc_error("bad 'auto' syntax"); | 4529 | s = bc_error("bad 'auto' syntax"); |
4491 | goto err; | 4530 | goto err; |
4492 | } | 4531 | } |
4493 | s = zbc_lex_next(&p->l); | 4532 | s = zbc_lex_next(); |
4494 | if (s) goto err; | 4533 | if (s) goto err; |
4495 | } | 4534 | } |
4496 | 4535 | ||
@@ -4505,7 +4544,7 @@ static BC_STATUS zbc_parse_auto(BcParse *p) | |||
4505 | } | 4544 | } |
4506 | if (p->l.lex != BC_LEX_COMMA) | 4545 | if (p->l.lex != BC_LEX_COMMA) |
4507 | RETURN_STATUS(bc_error("bad 'auto' syntax")); | 4546 | RETURN_STATUS(bc_error("bad 'auto' syntax")); |
4508 | s = zbc_lex_next(&p->l); // skip comma | 4547 | s = zbc_lex_next(); // skip comma |
4509 | if (s) RETURN_STATUS(s); | 4548 | if (s) RETURN_STATUS(s); |
4510 | } | 4549 | } |
4511 | 4550 | ||
@@ -4519,38 +4558,39 @@ static BC_STATUS zbc_parse_auto(BcParse *p) | |||
4519 | #define zbc_parse_auto(...) (zbc_parse_auto(__VA_ARGS__) COMMA_SUCCESS) | 4558 | #define zbc_parse_auto(...) (zbc_parse_auto(__VA_ARGS__) COMMA_SUCCESS) |
4520 | 4559 | ||
4521 | #undef zbc_parse_stmt_possibly_auto | 4560 | #undef zbc_parse_stmt_possibly_auto |
4522 | static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) | 4561 | static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed) |
4523 | { | 4562 | { |
4563 | BcParse *p = &G.prs; | ||
4524 | BcStatus s = BC_STATUS_SUCCESS; | 4564 | BcStatus s = BC_STATUS_SUCCESS; |
4525 | 4565 | ||
4526 | dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); | 4566 | dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); |
4527 | 4567 | ||
4528 | if (p->l.lex == XC_LEX_NLINE) { | 4568 | if (p->l.lex == XC_LEX_NLINE) { |
4529 | dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__); | 4569 | dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__); |
4530 | RETURN_STATUS(zbc_lex_next(&p->l)); | 4570 | RETURN_STATUS(zbc_lex_next()); |
4531 | } | 4571 | } |
4532 | if (p->l.lex == BC_LEX_SCOLON) { | 4572 | if (p->l.lex == BC_LEX_SCOLON) { |
4533 | dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__); | 4573 | dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__); |
4534 | RETURN_STATUS(zbc_lex_next(&p->l)); | 4574 | RETURN_STATUS(zbc_lex_next()); |
4535 | } | 4575 | } |
4536 | 4576 | ||
4537 | if (p->l.lex == BC_LEX_LBRACE) { | 4577 | if (p->l.lex == BC_LEX_LBRACE) { |
4538 | dbg_lex("%s:%d BC_LEX_LBRACE: (auto_allowed:%d)", __func__, __LINE__, auto_allowed); | 4578 | dbg_lex("%s:%d BC_LEX_LBRACE: (auto_allowed:%d)", __func__, __LINE__, auto_allowed); |
4539 | do { | 4579 | do { |
4540 | s = zbc_lex_next(&p->l); | 4580 | s = zbc_lex_next(); |
4541 | if (s) RETURN_STATUS(s); | 4581 | if (s) RETURN_STATUS(s); |
4542 | } while (p->l.lex == XC_LEX_NLINE); | 4582 | } while (p->l.lex == XC_LEX_NLINE); |
4543 | if (auto_allowed && p->l.lex == BC_LEX_KEY_AUTO) { | 4583 | if (auto_allowed && p->l.lex == BC_LEX_KEY_AUTO) { |
4544 | dbg_lex("%s:%d calling zbc_parse_auto()", __func__, __LINE__); | 4584 | dbg_lex("%s:%d calling zbc_parse_auto()", __func__, __LINE__); |
4545 | s = zbc_parse_auto(p); | 4585 | s = zbc_parse_auto(); |
4546 | if (s) RETURN_STATUS(s); | 4586 | if (s) RETURN_STATUS(s); |
4547 | } | 4587 | } |
4548 | while (p->l.lex != BC_LEX_RBRACE) { | 4588 | while (p->l.lex != BC_LEX_RBRACE) { |
4549 | dbg_lex("%s:%d block parsing loop", __func__, __LINE__); | 4589 | dbg_lex("%s:%d block parsing loop", __func__, __LINE__); |
4550 | s = zbc_parse_stmt(p); | 4590 | s = zbc_parse_stmt(); |
4551 | if (s) RETURN_STATUS(s); | 4591 | if (s) RETURN_STATUS(s); |
4552 | } | 4592 | } |
4553 | s = zbc_lex_next(&p->l); | 4593 | s = zbc_lex_next(); |
4554 | dbg_lex_done("%s:%d done (seen BC_LEX_RBRACE)", __func__, __LINE__); | 4594 | dbg_lex_done("%s:%d done (seen BC_LEX_RBRACE)", __func__, __LINE__); |
4555 | RETURN_STATUS(s); | 4595 | RETURN_STATUS(s); |
4556 | } | 4596 | } |
@@ -4571,25 +4611,25 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) | |||
4571 | case BC_LEX_KEY_READ: | 4611 | case BC_LEX_KEY_READ: |
4572 | case BC_LEX_KEY_SCALE: | 4612 | case BC_LEX_KEY_SCALE: |
4573 | case BC_LEX_KEY_SQRT: | 4613 | case BC_LEX_KEY_SQRT: |
4574 | s = zbc_parse_expr(p, BC_PARSE_PRINT); | 4614 | s = zbc_parse_expr(BC_PARSE_PRINT); |
4575 | break; | 4615 | break; |
4576 | case XC_LEX_STR: | 4616 | case XC_LEX_STR: |
4577 | s = zbc_parse_pushSTR(p); | 4617 | s = zbc_parse_pushSTR(); |
4578 | bc_parse_push(p, XC_INST_PRINT_STR); | 4618 | bc_parse_push(XC_INST_PRINT_STR); |
4579 | break; | 4619 | break; |
4580 | case BC_LEX_KEY_BREAK: | 4620 | case BC_LEX_KEY_BREAK: |
4581 | case BC_LEX_KEY_CONTINUE: | 4621 | case BC_LEX_KEY_CONTINUE: |
4582 | s = zbc_parse_break_or_continue(p, p->l.lex); | 4622 | s = zbc_parse_break_or_continue(p->l.lex); |
4583 | break; | 4623 | break; |
4584 | case BC_LEX_KEY_FOR: | 4624 | case BC_LEX_KEY_FOR: |
4585 | s = zbc_parse_for(p); | 4625 | s = zbc_parse_for(); |
4586 | break; | 4626 | break; |
4587 | case BC_LEX_KEY_HALT: | 4627 | case BC_LEX_KEY_HALT: |
4588 | bc_parse_push(p, BC_INST_HALT); | 4628 | bc_parse_push(BC_INST_HALT); |
4589 | s = zbc_lex_next(&p->l); | 4629 | s = zbc_lex_next(); |
4590 | break; | 4630 | break; |
4591 | case BC_LEX_KEY_IF: | 4631 | case BC_LEX_KEY_IF: |
4592 | s = zbc_parse_if(p); | 4632 | s = zbc_parse_if(); |
4593 | break; | 4633 | break; |
4594 | case BC_LEX_KEY_LIMITS: | 4634 | case BC_LEX_KEY_LIMITS: |
4595 | // "limits" is a compile-time command, | 4635 | // "limits" is a compile-time command, |
@@ -4604,10 +4644,10 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) | |||
4604 | "MAX Exponent = "BC_MAX_EXP_STR "\n" | 4644 | "MAX Exponent = "BC_MAX_EXP_STR "\n" |
4605 | "Number of vars = "BC_MAX_VARS_STR "\n" | 4645 | "Number of vars = "BC_MAX_VARS_STR "\n" |
4606 | ); | 4646 | ); |
4607 | s = zbc_lex_next(&p->l); | 4647 | s = zbc_lex_next(); |
4608 | break; | 4648 | break; |
4609 | case BC_LEX_KEY_PRINT: | 4649 | case BC_LEX_KEY_PRINT: |
4610 | s = zbc_parse_print(p); | 4650 | s = zbc_parse_print(); |
4611 | break; | 4651 | break; |
4612 | case BC_LEX_KEY_QUIT: | 4652 | case BC_LEX_KEY_QUIT: |
4613 | // "quit" is a compile-time command. For example, | 4653 | // "quit" is a compile-time command. For example, |
@@ -4617,10 +4657,10 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) | |||
4617 | case BC_LEX_KEY_RETURN: | 4657 | case BC_LEX_KEY_RETURN: |
4618 | if (!p->in_funcdef) | 4658 | if (!p->in_funcdef) |
4619 | RETURN_STATUS(bc_error("'return' not in a function")); | 4659 | RETURN_STATUS(bc_error("'return' not in a function")); |
4620 | s = zbc_parse_return(p); | 4660 | s = zbc_parse_return(); |
4621 | break; | 4661 | break; |
4622 | case BC_LEX_KEY_WHILE: | 4662 | case BC_LEX_KEY_WHILE: |
4623 | s = zbc_parse_while(p); | 4663 | s = zbc_parse_while(); |
4624 | break; | 4664 | break; |
4625 | default: | 4665 | default: |
4626 | s = bc_error_bad_token(); | 4666 | s = bc_error_bad_token(); |
@@ -4632,8 +4672,9 @@ static BC_STATUS zbc_parse_stmt_possibly_auto(BcParse *p, bool auto_allowed) | |||
4632 | } | 4672 | } |
4633 | #define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) | 4673 | #define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS) |
4634 | 4674 | ||
4635 | static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) | 4675 | static BC_STATUS zbc_parse_stmt_or_funcdef(void) |
4636 | { | 4676 | { |
4677 | BcParse *p = &G.prs; | ||
4637 | BcStatus s; | 4678 | BcStatus s; |
4638 | 4679 | ||
4639 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 4680 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
@@ -4641,10 +4682,10 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) | |||
4641 | s = bc_error("end of file"); | 4682 | s = bc_error("end of file"); |
4642 | else if (p->l.lex == BC_LEX_KEY_DEFINE) { | 4683 | else if (p->l.lex == BC_LEX_KEY_DEFINE) { |
4643 | dbg_lex("%s:%d p->l.lex:BC_LEX_KEY_DEFINE", __func__, __LINE__); | 4684 | dbg_lex("%s:%d p->l.lex:BC_LEX_KEY_DEFINE", __func__, __LINE__); |
4644 | s = zbc_parse_funcdef(p); | 4685 | s = zbc_parse_funcdef(); |
4645 | } else { | 4686 | } else { |
4646 | dbg_lex("%s:%d p->l.lex:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.lex); | 4687 | dbg_lex("%s:%d p->l.lex:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->l.lex); |
4647 | s = zbc_parse_stmt(p); | 4688 | s = zbc_parse_stmt(); |
4648 | } | 4689 | } |
4649 | 4690 | ||
4650 | dbg_lex_done("%s:%d done", __func__, __LINE__); | 4691 | dbg_lex_done("%s:%d done", __func__, __LINE__); |
@@ -4653,8 +4694,9 @@ static BC_STATUS zbc_parse_stmt_or_funcdef(BcParse *p) | |||
4653 | #define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__) COMMA_SUCCESS) | 4694 | #define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__) COMMA_SUCCESS) |
4654 | 4695 | ||
4655 | // This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP | 4696 | // This is not a "z" function: can also return BC_STATUS_PARSE_EMPTY_EXP |
4656 | static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | 4697 | static BcStatus bc_parse_expr_empty_ok(uint8_t flags) |
4657 | { | 4698 | { |
4699 | BcParse *p = &G.prs; | ||
4658 | BcInst prev = XC_INST_PRINT; | 4700 | BcInst prev = XC_INST_PRINT; |
4659 | size_t nexprs = 0, ops_bgn = p->ops.len; | 4701 | size_t nexprs = 0, ops_bgn = p->ops.len; |
4660 | unsigned nparens, nrelops; | 4702 | unsigned nparens, nrelops; |
@@ -4680,12 +4722,12 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4680 | switch (t) { | 4722 | switch (t) { |
4681 | case BC_LEX_OP_INC: | 4723 | case BC_LEX_OP_INC: |
4682 | case BC_LEX_OP_DEC: | 4724 | case BC_LEX_OP_DEC: |
4683 | s = zbc_parse_incdec(p, &prev, &paren_expr, &nexprs, flags); | 4725 | s = zbc_parse_incdec(&prev, &paren_expr, &nexprs, flags); |
4684 | rprn = bin_last = false; | 4726 | rprn = bin_last = false; |
4685 | //get_token = false; - already is | 4727 | //get_token = false; - already is |
4686 | break; | 4728 | break; |
4687 | case XC_LEX_OP_MINUS: | 4729 | case XC_LEX_OP_MINUS: |
4688 | s = zbc_parse_minus(p, &prev, ops_bgn, rprn, &nexprs); | 4730 | s = zbc_parse_minus(&prev, ops_bgn, rprn, &nexprs); |
4689 | rprn = false; | 4731 | rprn = false; |
4690 | //get_token = false; - already is | 4732 | //get_token = false; - already is |
4691 | bin_last = (prev == XC_INST_MINUS); | 4733 | bin_last = (prev == XC_INST_MINUS); |
@@ -4728,8 +4770,8 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4728 | } | 4770 | } |
4729 | nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); | 4771 | nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT); |
4730 | prev = BC_TOKEN_2_INST(t); | 4772 | prev = BC_TOKEN_2_INST(t); |
4731 | bc_parse_operator(p, t, ops_bgn, &nexprs); | 4773 | bc_parse_operator(t, ops_bgn, &nexprs); |
4732 | s = zbc_lex_next(&p->l); | 4774 | s = zbc_lex_next(); |
4733 | rprn = false; | 4775 | rprn = false; |
4734 | //get_token = false; - already is | 4776 | //get_token = false; - already is |
4735 | bin_last = (t != BC_LEX_OP_BOOL_NOT); | 4777 | bin_last = (t != BC_LEX_OP_BOOL_NOT); |
@@ -4753,7 +4795,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4753 | dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); | 4795 | dbg_lex_done("%s:%d done (returning EMPTY_EXP)", __func__, __LINE__); |
4754 | return BC_STATUS_PARSE_EMPTY_EXP; | 4796 | return BC_STATUS_PARSE_EMPTY_EXP; |
4755 | } | 4797 | } |
4756 | s = zbc_parse_rightParen(p, ops_bgn, &nexprs); | 4798 | s = zbc_parse_rightParen(ops_bgn, &nexprs); |
4757 | nparens--; | 4799 | nparens--; |
4758 | get_token = true; | 4800 | get_token = true; |
4759 | paren_expr = rprn = true; | 4801 | paren_expr = rprn = true; |
@@ -4762,7 +4804,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4762 | case XC_LEX_NAME: | 4804 | case XC_LEX_NAME: |
4763 | if (BC_PARSE_LEAF(prev, rprn)) | 4805 | if (BC_PARSE_LEAF(prev, rprn)) |
4764 | return bc_error_bad_expression(); | 4806 | return bc_error_bad_expression(); |
4765 | s = zbc_parse_name(p, &prev, flags & ~BC_PARSE_NOCALL); | 4807 | s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL); |
4766 | paren_expr = true; | 4808 | paren_expr = true; |
4767 | rprn = bin_last = false; | 4809 | rprn = bin_last = false; |
4768 | //get_token = false; - already is | 4810 | //get_token = false; - already is |
@@ -4771,7 +4813,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4771 | case XC_LEX_NUMBER: | 4813 | case XC_LEX_NUMBER: |
4772 | if (BC_PARSE_LEAF(prev, rprn)) | 4814 | if (BC_PARSE_LEAF(prev, rprn)) |
4773 | return bc_error_bad_expression(); | 4815 | return bc_error_bad_expression(); |
4774 | bc_parse_pushNUM(p); | 4816 | bc_parse_pushNUM(); |
4775 | prev = XC_INST_NUM; | 4817 | prev = XC_INST_NUM; |
4776 | get_token = true; | 4818 | get_token = true; |
4777 | paren_expr = true; | 4819 | paren_expr = true; |
@@ -4784,7 +4826,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4784 | if (BC_PARSE_LEAF(prev, rprn)) | 4826 | if (BC_PARSE_LEAF(prev, rprn)) |
4785 | return bc_error_bad_expression(); | 4827 | return bc_error_bad_expression(); |
4786 | prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); | 4828 | prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE); |
4787 | bc_parse_push(p, (char) prev); | 4829 | bc_parse_push((char) prev); |
4788 | get_token = true; | 4830 | get_token = true; |
4789 | paren_expr = true; | 4831 | paren_expr = true; |
4790 | rprn = bin_last = false; | 4832 | rprn = bin_last = false; |
@@ -4794,7 +4836,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4794 | case BC_LEX_KEY_SQRT: | 4836 | case BC_LEX_KEY_SQRT: |
4795 | if (BC_PARSE_LEAF(prev, rprn)) | 4837 | if (BC_PARSE_LEAF(prev, rprn)) |
4796 | return bc_error_bad_expression(); | 4838 | return bc_error_bad_expression(); |
4797 | s = zbc_parse_builtin(p, t, flags, &prev); | 4839 | s = zbc_parse_builtin(t, flags, &prev); |
4798 | get_token = true; | 4840 | get_token = true; |
4799 | paren_expr = true; | 4841 | paren_expr = true; |
4800 | rprn = bin_last = false; | 4842 | rprn = bin_last = false; |
@@ -4803,7 +4845,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4803 | case BC_LEX_KEY_READ: | 4845 | case BC_LEX_KEY_READ: |
4804 | if (BC_PARSE_LEAF(prev, rprn)) | 4846 | if (BC_PARSE_LEAF(prev, rprn)) |
4805 | return bc_error_bad_expression(); | 4847 | return bc_error_bad_expression(); |
4806 | s = zbc_parse_read(p); | 4848 | s = zbc_parse_read(); |
4807 | prev = XC_INST_READ; | 4849 | prev = XC_INST_READ; |
4808 | get_token = true; | 4850 | get_token = true; |
4809 | paren_expr = true; | 4851 | paren_expr = true; |
@@ -4813,7 +4855,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4813 | case BC_LEX_KEY_SCALE: | 4855 | case BC_LEX_KEY_SCALE: |
4814 | if (BC_PARSE_LEAF(prev, rprn)) | 4856 | if (BC_PARSE_LEAF(prev, rprn)) |
4815 | return bc_error_bad_expression(); | 4857 | return bc_error_bad_expression(); |
4816 | s = zbc_parse_scale(p, &prev, flags); | 4858 | s = zbc_parse_scale(&prev, flags); |
4817 | prev = XC_INST_SCALE; | 4859 | prev = XC_INST_SCALE; |
4818 | //get_token = false; - already is | 4860 | //get_token = false; - already is |
4819 | paren_expr = true; | 4861 | paren_expr = true; |
@@ -4827,7 +4869,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4827 | if (s || G_interrupt) // error, or ^C: stop parsing | 4869 | if (s || G_interrupt) // error, or ^C: stop parsing |
4828 | return BC_STATUS_FAILURE; | 4870 | return BC_STATUS_FAILURE; |
4829 | if (get_token) { | 4871 | if (get_token) { |
4830 | s = zbc_lex_next(&p->l); | 4872 | s = zbc_lex_next(); |
4831 | if (s) return s; | 4873 | if (s) return s; |
4832 | } | 4874 | } |
4833 | } | 4875 | } |
@@ -4840,7 +4882,7 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4840 | if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) | 4882 | if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN) |
4841 | return bc_error_bad_expression(); | 4883 | return bc_error_bad_expression(); |
4842 | 4884 | ||
4843 | bc_parse_push(p, BC_TOKEN_2_INST(top)); | 4885 | bc_parse_push(BC_TOKEN_2_INST(top)); |
4844 | 4886 | ||
4845 | nexprs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); | 4887 | nexprs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG); |
4846 | bc_vec_pop(&p->ops); | 4888 | bc_vec_pop(&p->ops); |
@@ -4861,8 +4903,8 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4861 | 4903 | ||
4862 | if (flags & BC_PARSE_PRINT) { | 4904 | if (flags & BC_PARSE_PRINT) { |
4863 | if (paren_first || !assign) | 4905 | if (paren_first || !assign) |
4864 | bc_parse_push(p, XC_INST_PRINT); | 4906 | bc_parse_push(XC_INST_PRINT); |
4865 | bc_parse_push(p, XC_INST_POP); | 4907 | bc_parse_push(XC_INST_POP); |
4866 | } | 4908 | } |
4867 | 4909 | ||
4868 | dbg_lex_done("%s:%d done", __func__, __LINE__); | 4910 | dbg_lex_done("%s:%d done", __func__, __LINE__); |
@@ -4873,30 +4915,32 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags) | |||
4873 | 4915 | ||
4874 | #if ENABLE_DC | 4916 | #if ENABLE_DC |
4875 | 4917 | ||
4876 | static BC_STATUS zdc_parse_register(BcParse *p) | 4918 | static BC_STATUS zdc_parse_register(void) |
4877 | { | 4919 | { |
4920 | BcParse *p = &G.prs; | ||
4878 | BcStatus s; | 4921 | BcStatus s; |
4879 | 4922 | ||
4880 | s = zbc_lex_next(&p->l); | 4923 | s = zbc_lex_next(); |
4881 | if (s) RETURN_STATUS(s); | 4924 | if (s) RETURN_STATUS(s); |
4882 | if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); | 4925 | if (p->l.lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token()); |
4883 | 4926 | ||
4884 | bc_parse_pushName(p, p->l.lex_buf.v); | 4927 | bc_parse_pushName(p->l.lex_buf.v); |
4885 | 4928 | ||
4886 | RETURN_STATUS(s); | 4929 | RETURN_STATUS(s); |
4887 | } | 4930 | } |
4888 | #define zdc_parse_register(...) (zdc_parse_register(__VA_ARGS__) COMMA_SUCCESS) | 4931 | #define zdc_parse_register(...) (zdc_parse_register(__VA_ARGS__) COMMA_SUCCESS) |
4889 | 4932 | ||
4890 | static void dc_parse_string(BcParse *p) | 4933 | static void dc_parse_string(void) |
4891 | { | 4934 | { |
4935 | BcParse *p = &G.prs; | ||
4892 | char *str; | 4936 | char *str; |
4893 | size_t len = G.prog.strs.len; | 4937 | size_t len = G.prog.strs.len; |
4894 | 4938 | ||
4895 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 4939 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
4896 | 4940 | ||
4897 | str = xstrdup(p->l.lex_buf.v); | 4941 | str = xstrdup(p->l.lex_buf.v); |
4898 | bc_parse_push(p, XC_INST_STR); | 4942 | bc_parse_push(XC_INST_STR); |
4899 | bc_parse_pushIndex(p, len); | 4943 | bc_parse_pushIndex(len); |
4900 | bc_vec_push(&G.prog.strs, &str); | 4944 | bc_vec_push(&G.prog.strs, &str); |
4901 | 4945 | ||
4902 | // Explanation needed here | 4946 | // Explanation needed here |
@@ -4906,55 +4950,56 @@ static void dc_parse_string(BcParse *p) | |||
4906 | dbg_lex_done("%s:%d done", __func__, __LINE__); | 4950 | dbg_lex_done("%s:%d done", __func__, __LINE__); |
4907 | } | 4951 | } |
4908 | 4952 | ||
4909 | static BC_STATUS zdc_parse_mem(BcParse *p, uint8_t inst, bool name, bool store) | 4953 | static BC_STATUS zdc_parse_mem(uint8_t inst, bool name, bool store) |
4910 | { | 4954 | { |
4911 | BcStatus s; | 4955 | BcStatus s; |
4912 | 4956 | ||
4913 | bc_parse_push(p, inst); | 4957 | bc_parse_push(inst); |
4914 | if (name) { | 4958 | if (name) { |
4915 | s = zdc_parse_register(p); | 4959 | s = zdc_parse_register(); |
4916 | if (s) RETURN_STATUS(s); | 4960 | if (s) RETURN_STATUS(s); |
4917 | } | 4961 | } |
4918 | 4962 | ||
4919 | if (store) { | 4963 | if (store) { |
4920 | bc_parse_push(p, DC_INST_SWAP); | 4964 | bc_parse_push(DC_INST_SWAP); |
4921 | bc_parse_push(p, XC_INST_ASSIGN); | 4965 | bc_parse_push(XC_INST_ASSIGN); |
4922 | bc_parse_push(p, XC_INST_POP); | 4966 | bc_parse_push(XC_INST_POP); |
4923 | } | 4967 | } |
4924 | 4968 | ||
4925 | RETURN_STATUS(BC_STATUS_SUCCESS); | 4969 | RETURN_STATUS(BC_STATUS_SUCCESS); |
4926 | } | 4970 | } |
4927 | #define zdc_parse_mem(...) (zdc_parse_mem(__VA_ARGS__) COMMA_SUCCESS) | 4971 | #define zdc_parse_mem(...) (zdc_parse_mem(__VA_ARGS__) COMMA_SUCCESS) |
4928 | 4972 | ||
4929 | static BC_STATUS zdc_parse_cond(BcParse *p, uint8_t inst) | 4973 | static BC_STATUS zdc_parse_cond(uint8_t inst) |
4930 | { | 4974 | { |
4975 | BcParse *p = &G.prs; | ||
4931 | BcStatus s; | 4976 | BcStatus s; |
4932 | 4977 | ||
4933 | bc_parse_push(p, inst); | 4978 | bc_parse_push(inst); |
4934 | bc_parse_push(p, DC_INST_EXEC_COND); | 4979 | bc_parse_push(DC_INST_EXEC_COND); |
4935 | 4980 | ||
4936 | s = zdc_parse_register(p); | 4981 | s = zdc_parse_register(); |
4937 | if (s) RETURN_STATUS(s); | 4982 | if (s) RETURN_STATUS(s); |
4938 | 4983 | ||
4939 | s = zbc_lex_next(&p->l); | 4984 | s = zbc_lex_next(); |
4940 | if (s) RETURN_STATUS(s); | 4985 | if (s) RETURN_STATUS(s); |
4941 | 4986 | ||
4942 | // Note that 'else' part can not be on the next line: | 4987 | // Note that 'else' part can not be on the next line: |
4943 | // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2" | 4988 | // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2" |
4944 | // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error | 4989 | // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error |
4945 | if (p->l.lex == DC_LEX_ELSE) { | 4990 | if (p->l.lex == DC_LEX_ELSE) { |
4946 | s = zdc_parse_register(p); | 4991 | s = zdc_parse_register(); |
4947 | if (s) RETURN_STATUS(s); | 4992 | if (s) RETURN_STATUS(s); |
4948 | s = zbc_lex_next(&p->l); | 4993 | s = zbc_lex_next(); |
4949 | } else { | 4994 | } else { |
4950 | bc_parse_push(p, BC_PARSE_STREND); | 4995 | bc_parse_push(BC_PARSE_STREND); |
4951 | } | 4996 | } |
4952 | 4997 | ||
4953 | RETURN_STATUS(s); | 4998 | RETURN_STATUS(s); |
4954 | } | 4999 | } |
4955 | #define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__) COMMA_SUCCESS) | 5000 | #define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__) COMMA_SUCCESS) |
4956 | 5001 | ||
4957 | static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) | 5002 | static BC_STATUS zdc_parse_token(BcLexType t) |
4958 | { | 5003 | { |
4959 | BcStatus s; | 5004 | BcStatus s; |
4960 | uint8_t inst; | 5005 | uint8_t inst; |
@@ -4971,88 +5016,90 @@ static BC_STATUS zdc_parse_token(BcParse *p, BcLexType t) | |||
4971 | case XC_LEX_OP_REL_LT: | 5016 | case XC_LEX_OP_REL_LT: |
4972 | case XC_LEX_OP_REL_GT: | 5017 | case XC_LEX_OP_REL_GT: |
4973 | dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__); | 5018 | dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__); |
4974 | s = zdc_parse_cond(p, t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ); | 5019 | s = zdc_parse_cond(t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ); |
4975 | get_token = false; | 5020 | get_token = false; |
4976 | break; | 5021 | break; |
4977 | case DC_LEX_SCOLON: | 5022 | case DC_LEX_SCOLON: |
4978 | case DC_LEX_COLON: | 5023 | case DC_LEX_COLON: |
4979 | dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); | 5024 | dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__); |
4980 | s = zdc_parse_mem(p, XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); | 5025 | s = zdc_parse_mem(XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON); |
4981 | break; | 5026 | break; |
4982 | case XC_LEX_STR: | 5027 | case XC_LEX_STR: |
4983 | dbg_lex("%s:%d LEX_STR", __func__, __LINE__); | 5028 | dbg_lex("%s:%d LEX_STR", __func__, __LINE__); |
4984 | dc_parse_string(p); | 5029 | dc_parse_string(); |
4985 | break; | 5030 | break; |
4986 | case XC_LEX_NEG: | 5031 | case XC_LEX_NEG: |
4987 | dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); | 5032 | dbg_lex("%s:%d LEX_NEG", __func__, __LINE__); |
4988 | s = zbc_lex_next(&p->l); | 5033 | s = zbc_lex_next(); |
4989 | if (s) RETURN_STATUS(s); | 5034 | if (s) RETURN_STATUS(s); |
4990 | if (p->l.lex != XC_LEX_NUMBER) | 5035 | if (G.prs.l.lex != XC_LEX_NUMBER) |
4991 | RETURN_STATUS(bc_error_bad_token()); | 5036 | RETURN_STATUS(bc_error_bad_token()); |
4992 | bc_parse_pushNUM(p); | 5037 | bc_parse_pushNUM(); |
4993 | bc_parse_push(p, XC_INST_NEG); | 5038 | bc_parse_push(XC_INST_NEG); |
4994 | break; | 5039 | break; |
4995 | case XC_LEX_NUMBER: | 5040 | case XC_LEX_NUMBER: |
4996 | dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); | 5041 | dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__); |
4997 | bc_parse_pushNUM(p); | 5042 | bc_parse_pushNUM(); |
4998 | break; | 5043 | break; |
4999 | case DC_LEX_READ: | 5044 | case DC_LEX_READ: |
5000 | dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); | 5045 | dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__); |
5001 | bc_parse_push(p, XC_INST_READ); | 5046 | bc_parse_push(XC_INST_READ); |
5002 | break; | 5047 | break; |
5003 | case DC_LEX_OP_ASSIGN: | 5048 | case DC_LEX_OP_ASSIGN: |
5004 | case DC_LEX_STORE_PUSH: | 5049 | case DC_LEX_STORE_PUSH: |
5005 | dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); | 5050 | dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__); |
5006 | assign = (t == DC_LEX_OP_ASSIGN); | 5051 | assign = (t == DC_LEX_OP_ASSIGN); |
5007 | inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR; | 5052 | inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR; |
5008 | s = zdc_parse_mem(p, inst, true, assign); | 5053 | s = zdc_parse_mem(inst, true, assign); |
5009 | break; | 5054 | break; |
5010 | case DC_LEX_LOAD: | 5055 | case DC_LEX_LOAD: |
5011 | case DC_LEX_LOAD_POP: | 5056 | case DC_LEX_LOAD_POP: |
5012 | dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__); | 5057 | dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__); |
5013 | inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD; | 5058 | inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD; |
5014 | s = zdc_parse_mem(p, inst, true, false); | 5059 | s = zdc_parse_mem(inst, true, false); |
5015 | break; | 5060 | break; |
5016 | case DC_LEX_STORE_IBASE: | 5061 | case DC_LEX_STORE_IBASE: |
5017 | case DC_LEX_STORE_SCALE: | 5062 | case DC_LEX_STORE_SCALE: |
5018 | case DC_LEX_STORE_OBASE: | 5063 | case DC_LEX_STORE_OBASE: |
5019 | dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__); | 5064 | dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__); |
5020 | inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE; | 5065 | inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE; |
5021 | s = zdc_parse_mem(p, inst, false, true); | 5066 | s = zdc_parse_mem(inst, false, true); |
5022 | break; | 5067 | break; |
5023 | default: | 5068 | default: |
5024 | dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__); | 5069 | dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__); |
5025 | RETURN_STATUS(bc_error_bad_token()); | 5070 | RETURN_STATUS(bc_error_bad_token()); |
5026 | } | 5071 | } |
5027 | 5072 | ||
5028 | if (!s && get_token) s = zbc_lex_next(&p->l); | 5073 | if (!s && get_token) s = zbc_lex_next(); |
5029 | 5074 | ||
5030 | dbg_lex_done("%s:%d done", __func__, __LINE__); | 5075 | dbg_lex_done("%s:%d done", __func__, __LINE__); |
5031 | RETURN_STATUS(s); | 5076 | RETURN_STATUS(s); |
5032 | } | 5077 | } |
5033 | #define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__) COMMA_SUCCESS) | 5078 | #define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__) COMMA_SUCCESS) |
5034 | 5079 | ||
5035 | static BC_STATUS zdc_parse_expr(BcParse *p) | 5080 | static BC_STATUS zdc_parse_expr(void) |
5036 | { | 5081 | { |
5082 | BcParse *p = &G.prs; | ||
5037 | int i; | 5083 | int i; |
5038 | 5084 | ||
5039 | i = (int)p->l.lex - (int)XC_LEX_OP_POWER; | 5085 | i = (int)p->l.lex - (int)XC_LEX_OP_POWER; |
5040 | if (i >= 0) { | 5086 | if (i >= 0) { |
5041 | BcInst inst = dc_LEX_to_INST[i]; | 5087 | BcInst inst = dc_LEX_to_INST[i]; |
5042 | if (inst != DC_INST_INVALID) { | 5088 | if (inst != DC_INST_INVALID) { |
5043 | bc_parse_push(p, inst); | 5089 | bc_parse_push(inst); |
5044 | RETURN_STATUS(zbc_lex_next(&p->l)); | 5090 | RETURN_STATUS(zbc_lex_next()); |
5045 | } | 5091 | } |
5046 | } | 5092 | } |
5047 | RETURN_STATUS(zdc_parse_token(p, p->l.lex)); | 5093 | RETURN_STATUS(zdc_parse_token(p->l.lex)); |
5048 | } | 5094 | } |
5049 | #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) | 5095 | #define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS) |
5050 | 5096 | ||
5051 | static BC_STATUS zdc_parse_exprs_until_eof(BcParse *p) | 5097 | static BC_STATUS zdc_parse_exprs_until_eof(void) |
5052 | { | 5098 | { |
5099 | BcParse *p = &G.prs; | ||
5053 | dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); | 5100 | dbg_lex_enter("%s:%d entered, p->l.lex:%d", __func__, __LINE__, p->l.lex); |
5054 | while (p->l.lex != XC_LEX_EOF) { | 5101 | while (p->l.lex != XC_LEX_EOF) { |
5055 | BcStatus s = zdc_parse_expr(p); | 5102 | BcStatus s = zdc_parse_expr(); |
5056 | if (s) RETURN_STATUS(s); | 5103 | if (s) RETURN_STATUS(s); |
5057 | } | 5104 | } |
5058 | 5105 | ||
@@ -5269,15 +5316,15 @@ static BC_STATUS zbc_program_read(void) | |||
5269 | bc_vec_pop_all(&f->code); | 5316 | bc_vec_pop_all(&f->code); |
5270 | 5317 | ||
5271 | sv_parse = G.prs; // struct copy | 5318 | sv_parse = G.prs; // struct copy |
5272 | bc_parse_create(&G.prs, BC_PROG_READ); | 5319 | bc_parse_create(BC_PROG_READ); |
5273 | //bc_lex_file(&G.prs.l); - not needed, error line info is not printed for read() | 5320 | //bc_lex_file(&G.prs.l); - not needed, error line info is not printed for read() |
5274 | 5321 | ||
5275 | s = zbc_parse_text_init(&G.prs, buf.v); | 5322 | s = zbc_parse_text_init(buf.v); |
5276 | if (s) goto exec_err; | 5323 | if (s) goto exec_err; |
5277 | if (IS_BC) { | 5324 | if (IS_BC) { |
5278 | IF_BC(s = zbc_parse_expr(&G.prs, 0)); | 5325 | IF_BC(s = zbc_parse_expr(0)); |
5279 | } else { | 5326 | } else { |
5280 | IF_DC(s = zdc_parse_exprs_until_eof(&G.prs)); | 5327 | IF_DC(s = zdc_parse_exprs_until_eof()); |
5281 | } | 5328 | } |
5282 | if (s) goto exec_err; | 5329 | if (s) goto exec_err; |
5283 | 5330 | ||
@@ -5290,11 +5337,11 @@ static BC_STATUS zbc_program_read(void) | |||
5290 | ip.inst_idx = 0; | 5337 | ip.inst_idx = 0; |
5291 | IF_BC(ip.results_len_before_call = G.prog.results.len;) | 5338 | IF_BC(ip.results_len_before_call = G.prog.results.len;) |
5292 | 5339 | ||
5293 | bc_parse_push(&G.prs, XC_INST_RET); | 5340 | bc_parse_push(XC_INST_RET); |
5294 | bc_vec_push(&G.prog.exestack, &ip); | 5341 | bc_vec_push(&G.prog.exestack, &ip); |
5295 | 5342 | ||
5296 | exec_err: | 5343 | exec_err: |
5297 | bc_parse_free(&G.prs); | 5344 | bc_parse_free(); |
5298 | G.prs = sv_parse; // struct copy | 5345 | G.prs = sv_parse; // struct copy |
5299 | bc_vec_free(&buf); | 5346 | bc_vec_free(&buf); |
5300 | RETURN_STATUS(s); | 5347 | RETURN_STATUS(s); |
@@ -6404,17 +6451,17 @@ static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond) | |||
6404 | char *str; | 6451 | char *str; |
6405 | 6452 | ||
6406 | sv_parse = G.prs; // struct copy | 6453 | sv_parse = G.prs; // struct copy |
6407 | bc_parse_create(&G.prs, fidx); | 6454 | bc_parse_create(fidx); |
6408 | str = *bc_program_str(sidx); | 6455 | str = *bc_program_str(sidx); |
6409 | s = zbc_parse_text_init(&G.prs, str); | 6456 | s = zbc_parse_text_init(str); |
6410 | if (s) goto err; | 6457 | if (s) goto err; |
6411 | 6458 | ||
6412 | s = zdc_parse_exprs_until_eof(&G.prs); | 6459 | s = zdc_parse_exprs_until_eof(); |
6413 | if (s) goto err; | 6460 | if (s) goto err; |
6414 | bc_parse_push(&G.prs, DC_INST_POP_EXEC); | 6461 | bc_parse_push(DC_INST_POP_EXEC); |
6415 | if (G.prs.l.lex != XC_LEX_EOF) | 6462 | if (G.prs.l.lex != XC_LEX_EOF) |
6416 | s = bc_error_bad_expression(); | 6463 | s = bc_error_bad_expression(); |
6417 | bc_parse_free(&G.prs); | 6464 | bc_parse_free(); |
6418 | G.prs = sv_parse; // struct copy | 6465 | G.prs = sv_parse; // struct copy |
6419 | if (s) { | 6466 | if (s) { |
6420 | err: | 6467 | err: |
@@ -6745,7 +6792,7 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
6745 | BcStatus s; | 6792 | BcStatus s; |
6746 | 6793 | ||
6747 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); | 6794 | dbg_lex_enter("%s:%d entered", __func__, __LINE__); |
6748 | s = zbc_parse_text_init(&G.prs, text); // does the first zbc_lex_next() | 6795 | s = zbc_parse_text_init(text); // does the first zbc_lex_next() |
6749 | if (s) RETURN_STATUS(s); | 6796 | if (s) RETURN_STATUS(s); |
6750 | 6797 | ||
6751 | IF_BC(check_eof:) | 6798 | IF_BC(check_eof:) |
@@ -6759,12 +6806,12 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
6759 | if (G.prs.l.lex == BC_LEX_SCOLON | 6806 | if (G.prs.l.lex == BC_LEX_SCOLON |
6760 | || G.prs.l.lex == XC_LEX_NLINE | 6807 | || G.prs.l.lex == XC_LEX_NLINE |
6761 | ) { | 6808 | ) { |
6762 | s = zbc_lex_next(&G.prs.l); | 6809 | s = zbc_lex_next(); |
6763 | if (s) goto err; | 6810 | if (s) goto err; |
6764 | goto check_eof; | 6811 | goto check_eof; |
6765 | } | 6812 | } |
6766 | 6813 | ||
6767 | s = zbc_parse_stmt_or_funcdef(&G.prs); | 6814 | s = zbc_parse_stmt_or_funcdef(); |
6768 | if (s) goto err; | 6815 | if (s) goto err; |
6769 | 6816 | ||
6770 | // Check that next token is a correct stmt delimiter - | 6817 | // Check that next token is a correct stmt delimiter - |
@@ -6790,17 +6837,17 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
6790 | // Most of dc parsing assumes all whitespace, | 6837 | // Most of dc parsing assumes all whitespace, |
6791 | // including '\n', is eaten. | 6838 | // including '\n', is eaten. |
6792 | while (G.prs.l.lex == XC_LEX_NLINE) { | 6839 | while (G.prs.l.lex == XC_LEX_NLINE) { |
6793 | s = zbc_lex_next(&G.prs.l); | 6840 | s = zbc_lex_next(); |
6794 | if (s) goto err; | 6841 | if (s) goto err; |
6795 | if (G.prs.l.lex == XC_LEX_EOF) | 6842 | if (G.prs.l.lex == XC_LEX_EOF) |
6796 | goto done; | 6843 | goto done; |
6797 | } | 6844 | } |
6798 | s = zdc_parse_expr(&G.prs); | 6845 | s = zdc_parse_expr(); |
6799 | #endif | 6846 | #endif |
6800 | } | 6847 | } |
6801 | if (s || G_interrupt) { | 6848 | if (s || G_interrupt) { |
6802 | err: | 6849 | err: |
6803 | bc_parse_reset(&G.prs); // includes bc_program_reset() | 6850 | bc_parse_reset(); // includes bc_program_reset() |
6804 | RETURN_STATUS(BC_STATUS_FAILURE); | 6851 | RETURN_STATUS(BC_STATUS_FAILURE); |
6805 | } | 6852 | } |
6806 | 6853 | ||
@@ -6872,7 +6919,7 @@ static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) | |||
6872 | 6919 | ||
6873 | G.prs.filename = filename; | 6920 | G.prs.filename = filename; |
6874 | G.prs.input_fp = fp; | 6921 | G.prs.input_fp = fp; |
6875 | bc_lex_file(&G.prs.l); | 6922 | bc_lex_file(); |
6876 | 6923 | ||
6877 | do { | 6924 | do { |
6878 | s = zbc_vm_process(""); | 6925 | s = zbc_vm_process(""); |
@@ -7153,7 +7200,7 @@ static BC_STATUS zbc_vm_exec(void) | |||
7153 | // We know that internal library is not buggy, | 7200 | // We know that internal library is not buggy, |
7154 | // thus error checking is normally disabled. | 7201 | // thus error checking is normally disabled. |
7155 | # define DEBUG_LIB 0 | 7202 | # define DEBUG_LIB 0 |
7156 | bc_lex_file(&G.prs.l); | 7203 | bc_lex_file(); |
7157 | s = zbc_vm_process(bc_lib); | 7204 | s = zbc_vm_process(bc_lib); |
7158 | if (DEBUG_LIB && s) RETURN_STATUS(s); | 7205 | if (DEBUG_LIB && s) RETURN_STATUS(s); |
7159 | } | 7206 | } |
@@ -7202,7 +7249,7 @@ static void bc_vm_free(void) | |||
7202 | { | 7249 | { |
7203 | bc_vec_free(&G.files); | 7250 | bc_vec_free(&G.files); |
7204 | bc_program_free(); | 7251 | bc_program_free(); |
7205 | bc_parse_free(&G.prs); | 7252 | bc_parse_free(); |
7206 | free(G.env_args); | 7253 | free(G.env_args); |
7207 | } | 7254 | } |
7208 | #endif | 7255 | #endif |
@@ -7266,7 +7313,7 @@ static int bc_vm_init(const char *env_len) | |||
7266 | bc_vec_init(&G.files, sizeof(char *), NULL); | 7313 | bc_vec_init(&G.files, sizeof(char *), NULL); |
7267 | IF_BC(if (IS_BC) bc_vm_envArgs();) | 7314 | IF_BC(if (IS_BC) bc_vm_envArgs();) |
7268 | bc_program_init(); | 7315 | bc_program_init(); |
7269 | bc_parse_create(&G.prs, BC_PROG_MAIN); | 7316 | bc_parse_create(BC_PROG_MAIN); |
7270 | 7317 | ||
7271 | //TODO: in GNU bc, the check is (isatty(0) && isatty(1)), | 7318 | //TODO: in GNU bc, the check is (isatty(0) && isatty(1)), |
7272 | //-i option unconditionally enables this regardless of isatty(): | 7319 | //-i option unconditionally enables this regardless of isatty(): |