diff options
Diffstat (limited to 'miscutils')
-rw-r--r-- | miscutils/bc.c | 151 |
1 files changed, 16 insertions, 135 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index e3e8198b7..70db2ce3d 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -2994,7 +2994,7 @@ static BcStatus bc_lex_identifier(BcLex *l) | |||
2994 | l->t.t = BC_LEX_KEY_1st_keyword + i; | 2994 | l->t.t = BC_LEX_KEY_1st_keyword + i; |
2995 | if (!bc_lex_kws_POSIX(i)) { | 2995 | if (!bc_lex_kws_POSIX(i)) { |
2996 | s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); | 2996 | s = bc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8); |
2997 | if (s) return s; | 2997 | ERROR_RETURN(if (s) return s;) |
2998 | } | 2998 | } |
2999 | 2999 | ||
3000 | // We minus 1 because the index has already been incremented. | 3000 | // We minus 1 because the index has already been incremented. |
@@ -3096,123 +3096,75 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) | |||
3096 | 3096 | ||
3097 | // This is the workhorse of the lexer. | 3097 | // This is the workhorse of the lexer. |
3098 | switch (c) { | 3098 | switch (c) { |
3099 | |||
3100 | case '\0': | 3099 | case '\0': |
3101 | case '\n': | 3100 | case '\n': |
3102 | { | ||
3103 | l->newline = true; | 3101 | l->newline = true; |
3104 | l->t.t = !c ? BC_LEX_EOF : BC_LEX_NLINE; | 3102 | l->t.t = !c ? BC_LEX_EOF : BC_LEX_NLINE; |
3105 | break; | 3103 | break; |
3106 | } | ||
3107 | |||
3108 | case '\t': | 3104 | case '\t': |
3109 | case '\v': | 3105 | case '\v': |
3110 | case '\f': | 3106 | case '\f': |
3111 | case '\r': | 3107 | case '\r': |
3112 | case ' ': | 3108 | case ' ': |
3113 | { | ||
3114 | bc_lex_whitespace(l); | 3109 | bc_lex_whitespace(l); |
3115 | break; | 3110 | break; |
3116 | } | ||
3117 | |||
3118 | case '!': | 3111 | case '!': |
3119 | { | ||
3120 | bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); | 3112 | bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT); |
3121 | |||
3122 | if (l->t.t == BC_LEX_OP_BOOL_NOT) { | 3113 | if (l->t.t == BC_LEX_OP_BOOL_NOT) { |
3123 | s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); | 3114 | s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("!"); |
3124 | if (s) return s; | 3115 | ERROR_RETURN(if (s) return s;) |
3125 | } | 3116 | } |
3126 | |||
3127 | break; | 3117 | break; |
3128 | } | ||
3129 | |||
3130 | case '"': | 3118 | case '"': |
3131 | { | ||
3132 | s = bc_lex_string(l); | 3119 | s = bc_lex_string(l); |
3133 | break; | 3120 | break; |
3134 | } | ||
3135 | |||
3136 | case '#': | 3121 | case '#': |
3137 | { | ||
3138 | s = bc_POSIX_does_not_allow("'#' script comments"); | 3122 | s = bc_POSIX_does_not_allow("'#' script comments"); |
3139 | if (s) return s; | 3123 | ERROR_RETURN(if (s) return s;) |
3140 | |||
3141 | bc_lex_lineComment(l); | 3124 | bc_lex_lineComment(l); |
3142 | |||
3143 | break; | 3125 | break; |
3144 | } | ||
3145 | |||
3146 | case '%': | 3126 | case '%': |
3147 | { | ||
3148 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, BC_LEX_OP_MODULUS); | 3127 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MODULUS, BC_LEX_OP_MODULUS); |
3149 | break; | 3128 | break; |
3150 | } | ||
3151 | |||
3152 | case '&': | 3129 | case '&': |
3153 | { | ||
3154 | c2 = l->buf[l->i]; | 3130 | c2 = l->buf[l->i]; |
3155 | if (c2 == '&') { | 3131 | if (c2 == '&') { |
3156 | |||
3157 | s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); | 3132 | s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("&&"); |
3158 | if (s) return s; | 3133 | ERROR_RETURN(if (s) return s;) |
3159 | |||
3160 | ++l->i; | 3134 | ++l->i; |
3161 | l->t.t = BC_LEX_OP_BOOL_AND; | 3135 | l->t.t = BC_LEX_OP_BOOL_AND; |
3162 | } | 3136 | } else { |
3163 | else { | ||
3164 | l->t.t = BC_LEX_INVALID; | 3137 | l->t.t = BC_LEX_INVALID; |
3165 | s = bc_error_bad_character('&'); | 3138 | s = bc_error_bad_character('&'); |
3166 | } | 3139 | } |
3167 | |||
3168 | break; | 3140 | break; |
3169 | } | ||
3170 | |||
3171 | case '(': | 3141 | case '(': |
3172 | case ')': | 3142 | case ')': |
3173 | { | ||
3174 | l->t.t = (BcLexType)(c - '(' + BC_LEX_LPAREN); | 3143 | l->t.t = (BcLexType)(c - '(' + BC_LEX_LPAREN); |
3175 | break; | 3144 | break; |
3176 | } | ||
3177 | |||
3178 | case '*': | 3145 | case '*': |
3179 | { | ||
3180 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, BC_LEX_OP_MULTIPLY); | 3146 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MULTIPLY, BC_LEX_OP_MULTIPLY); |
3181 | break; | 3147 | break; |
3182 | } | ||
3183 | |||
3184 | case '+': | 3148 | case '+': |
3185 | { | ||
3186 | c2 = l->buf[l->i]; | 3149 | c2 = l->buf[l->i]; |
3187 | if (c2 == '+') { | 3150 | if (c2 == '+') { |
3188 | ++l->i; | 3151 | ++l->i; |
3189 | l->t.t = BC_LEX_OP_INC; | 3152 | l->t.t = BC_LEX_OP_INC; |
3190 | } | 3153 | } else |
3191 | else | ||
3192 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, BC_LEX_OP_PLUS); | 3154 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_PLUS, BC_LEX_OP_PLUS); |
3193 | break; | 3155 | break; |
3194 | } | ||
3195 | |||
3196 | case ',': | 3156 | case ',': |
3197 | { | ||
3198 | l->t.t = BC_LEX_COMMA; | 3157 | l->t.t = BC_LEX_COMMA; |
3199 | break; | 3158 | break; |
3200 | } | ||
3201 | |||
3202 | case '-': | 3159 | case '-': |
3203 | { | ||
3204 | c2 = l->buf[l->i]; | 3160 | c2 = l->buf[l->i]; |
3205 | if (c2 == '-') { | 3161 | if (c2 == '-') { |
3206 | ++l->i; | 3162 | ++l->i; |
3207 | l->t.t = BC_LEX_OP_DEC; | 3163 | l->t.t = BC_LEX_OP_DEC; |
3208 | } | 3164 | } else |
3209 | else | ||
3210 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, BC_LEX_OP_MINUS); | 3165 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_MINUS, BC_LEX_OP_MINUS); |
3211 | break; | 3166 | break; |
3212 | } | ||
3213 | |||
3214 | case '.': | 3167 | case '.': |
3215 | { | ||
3216 | if (isdigit(l->buf[l->i])) | 3168 | if (isdigit(l->buf[l->i])) |
3217 | s = zbc_lex_number(l, c); | 3169 | s = zbc_lex_number(l, c); |
3218 | else { | 3170 | else { |
@@ -3220,18 +3172,13 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) | |||
3220 | s = bc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); | 3172 | s = bc_POSIX_does_not_allow("a period ('.') as a shortcut for the last result"); |
3221 | } | 3173 | } |
3222 | break; | 3174 | break; |
3223 | } | ||
3224 | |||
3225 | case '/': | 3175 | case '/': |
3226 | { | ||
3227 | c2 = l->buf[l->i]; | 3176 | c2 = l->buf[l->i]; |
3228 | if (c2 == '*') | 3177 | if (c2 == '*') |
3229 | s = zbc_lex_comment(l); | 3178 | s = zbc_lex_comment(l); |
3230 | else | 3179 | else |
3231 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE); | 3180 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_DIVIDE, BC_LEX_OP_DIVIDE); |
3232 | break; | 3181 | break; |
3233 | } | ||
3234 | |||
3235 | case '0': | 3182 | case '0': |
3236 | case '1': | 3183 | case '1': |
3237 | case '2': | 3184 | case '2': |
@@ -3248,59 +3195,34 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) | |||
3248 | case 'D': | 3195 | case 'D': |
3249 | case 'E': | 3196 | case 'E': |
3250 | case 'F': | 3197 | case 'F': |
3251 | { | ||
3252 | s = zbc_lex_number(l, c); | 3198 | s = zbc_lex_number(l, c); |
3253 | break; | 3199 | break; |
3254 | } | ||
3255 | |||
3256 | case ';': | 3200 | case ';': |
3257 | { | ||
3258 | l->t.t = BC_LEX_SCOLON; | 3201 | l->t.t = BC_LEX_SCOLON; |
3259 | break; | 3202 | break; |
3260 | } | ||
3261 | |||
3262 | case '<': | 3203 | case '<': |
3263 | { | ||
3264 | bc_lex_assign(l, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_LT); | 3204 | bc_lex_assign(l, BC_LEX_OP_REL_LE, BC_LEX_OP_REL_LT); |
3265 | break; | 3205 | break; |
3266 | } | ||
3267 | |||
3268 | case '=': | 3206 | case '=': |
3269 | { | ||
3270 | bc_lex_assign(l, BC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); | 3207 | bc_lex_assign(l, BC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN); |
3271 | break; | 3208 | break; |
3272 | } | ||
3273 | |||
3274 | case '>': | 3209 | case '>': |
3275 | { | ||
3276 | bc_lex_assign(l, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_GT); | 3210 | bc_lex_assign(l, BC_LEX_OP_REL_GE, BC_LEX_OP_REL_GT); |
3277 | break; | 3211 | break; |
3278 | } | ||
3279 | |||
3280 | case '[': | 3212 | case '[': |
3281 | case ']': | 3213 | case ']': |
3282 | { | ||
3283 | l->t.t = (BcLexType)(c - '[' + BC_LEX_LBRACKET); | 3214 | l->t.t = (BcLexType)(c - '[' + BC_LEX_LBRACKET); |
3284 | break; | 3215 | break; |
3285 | } | ||
3286 | |||
3287 | case '\\': | 3216 | case '\\': |
3288 | { | ||
3289 | if (l->buf[l->i] == '\n') { | 3217 | if (l->buf[l->i] == '\n') { |
3290 | l->t.t = BC_LEX_WHITESPACE; | 3218 | l->t.t = BC_LEX_WHITESPACE; |
3291 | ++l->i; | 3219 | ++l->i; |
3292 | } | 3220 | } else |
3293 | else | ||
3294 | s = bc_error_bad_character(c); | 3221 | s = bc_error_bad_character(c); |
3295 | break; | 3222 | break; |
3296 | } | ||
3297 | |||
3298 | case '^': | 3223 | case '^': |
3299 | { | ||
3300 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, BC_LEX_OP_POWER); | 3224 | bc_lex_assign(l, BC_LEX_OP_ASSIGN_POWER, BC_LEX_OP_POWER); |
3301 | break; | 3225 | break; |
3302 | } | ||
3303 | |||
3304 | case 'a': | 3226 | case 'a': |
3305 | case 'b': | 3227 | case 'b': |
3306 | case 'c': | 3228 | case 'c': |
@@ -3327,43 +3249,28 @@ static FAST_FUNC BcStatus bc_lex_token(BcLex *l) | |||
3327 | case 'x': | 3249 | case 'x': |
3328 | case 'y': | 3250 | case 'y': |
3329 | case 'z': | 3251 | case 'z': |
3330 | { | ||
3331 | s = bc_lex_identifier(l); | 3252 | s = bc_lex_identifier(l); |
3332 | break; | 3253 | break; |
3333 | } | ||
3334 | |||
3335 | case '{': | 3254 | case '{': |
3336 | case '}': | 3255 | case '}': |
3337 | { | ||
3338 | l->t.t = (BcLexType)(c - '{' + BC_LEX_LBRACE); | 3256 | l->t.t = (BcLexType)(c - '{' + BC_LEX_LBRACE); |
3339 | break; | 3257 | break; |
3340 | } | ||
3341 | |||
3342 | case '|': | 3258 | case '|': |
3343 | { | ||
3344 | c2 = l->buf[l->i]; | 3259 | c2 = l->buf[l->i]; |
3345 | |||
3346 | if (c2 == '|') { | 3260 | if (c2 == '|') { |
3347 | s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); | 3261 | s = bc_POSIX_does_not_allow_bool_ops_this_is_bad("||"); |
3348 | if (s) return s; | 3262 | ERROR_RETURN(if (s) return s;) |
3349 | |||
3350 | ++l->i; | 3263 | ++l->i; |
3351 | l->t.t = BC_LEX_OP_BOOL_OR; | 3264 | l->t.t = BC_LEX_OP_BOOL_OR; |
3352 | } | 3265 | } else { |
3353 | else { | ||
3354 | l->t.t = BC_LEX_INVALID; | 3266 | l->t.t = BC_LEX_INVALID; |
3355 | s = bc_error_bad_character(c); | 3267 | s = bc_error_bad_character(c); |
3356 | } | 3268 | } |
3357 | |||
3358 | break; | 3269 | break; |
3359 | } | ||
3360 | |||
3361 | default: | 3270 | default: |
3362 | { | ||
3363 | l->t.t = BC_LEX_INVALID; | 3271 | l->t.t = BC_LEX_INVALID; |
3364 | s = bc_error_bad_character(c); | 3272 | s = bc_error_bad_character(c); |
3365 | break; | 3273 | break; |
3366 | } | ||
3367 | } | 3274 | } |
3368 | 3275 | ||
3369 | return s; | 3276 | return s; |
@@ -3443,37 +3350,28 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) | |||
3443 | return zdc_lex_register(l); | 3350 | return zdc_lex_register(l); |
3444 | } | 3351 | } |
3445 | 3352 | ||
3446 | if (c >= '%' && c <= '~' && | 3353 | if (c >= '%' && c <= '~' |
3447 | (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID) | 3354 | && (l->t.t = dc_lex_tokens[(c - '%')]) != BC_LEX_INVALID |
3448 | { | 3355 | ) { |
3449 | return s; | 3356 | return s; |
3450 | } | 3357 | } |
3451 | 3358 | ||
3452 | // This is the workhorse of the lexer. | 3359 | // This is the workhorse of the lexer. |
3453 | switch (c) { | 3360 | switch (c) { |
3454 | |||
3455 | case '\0': | 3361 | case '\0': |
3456 | { | ||
3457 | l->t.t = BC_LEX_EOF; | 3362 | l->t.t = BC_LEX_EOF; |
3458 | break; | 3363 | break; |
3459 | } | ||
3460 | |||
3461 | case '\n': | 3364 | case '\n': |
3462 | case '\t': | 3365 | case '\t': |
3463 | case '\v': | 3366 | case '\v': |
3464 | case '\f': | 3367 | case '\f': |
3465 | case '\r': | 3368 | case '\r': |
3466 | case ' ': | 3369 | case ' ': |
3467 | { | ||
3468 | l->newline = (c == '\n'); | 3370 | l->newline = (c == '\n'); |
3469 | bc_lex_whitespace(l); | 3371 | bc_lex_whitespace(l); |
3470 | break; | 3372 | break; |
3471 | } | ||
3472 | |||
3473 | case '!': | 3373 | case '!': |
3474 | { | ||
3475 | c2 = l->buf[l->i]; | 3374 | c2 = l->buf[l->i]; |
3476 | |||
3477 | if (c2 == '=') | 3375 | if (c2 == '=') |
3478 | l->t.t = BC_LEX_OP_REL_NE; | 3376 | l->t.t = BC_LEX_OP_REL_NE; |
3479 | else if (c2 == '<') | 3377 | else if (c2 == '<') |
@@ -3482,26 +3380,17 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) | |||
3482 | l->t.t = BC_LEX_OP_REL_GE; | 3380 | l->t.t = BC_LEX_OP_REL_GE; |
3483 | else | 3381 | else |
3484 | return bc_error_bad_character(c); | 3382 | return bc_error_bad_character(c); |
3485 | |||
3486 | ++l->i; | 3383 | ++l->i; |
3487 | break; | 3384 | break; |
3488 | } | ||
3489 | |||
3490 | case '#': | 3385 | case '#': |
3491 | { | ||
3492 | bc_lex_lineComment(l); | 3386 | bc_lex_lineComment(l); |
3493 | break; | 3387 | break; |
3494 | } | ||
3495 | |||
3496 | case '.': | 3388 | case '.': |
3497 | { | ||
3498 | if (isdigit(l->buf[l->i])) | 3389 | if (isdigit(l->buf[l->i])) |
3499 | s = zbc_lex_number(l, c); | 3390 | s = zbc_lex_number(l, c); |
3500 | else | 3391 | else |
3501 | s = bc_error_bad_character(c); | 3392 | s = bc_error_bad_character(c); |
3502 | break; | 3393 | break; |
3503 | } | ||
3504 | |||
3505 | case '0': | 3394 | case '0': |
3506 | case '1': | 3395 | case '1': |
3507 | case '2': | 3396 | case '2': |
@@ -3518,23 +3407,15 @@ static FAST_FUNC BcStatus dc_lex_token(BcLex *l) | |||
3518 | case 'D': | 3407 | case 'D': |
3519 | case 'E': | 3408 | case 'E': |
3520 | case 'F': | 3409 | case 'F': |
3521 | { | ||
3522 | s = zbc_lex_number(l, c); | 3410 | s = zbc_lex_number(l, c); |
3523 | break; | 3411 | break; |
3524 | } | ||
3525 | |||
3526 | case '[': | 3412 | case '[': |
3527 | { | ||
3528 | s = zdc_lex_string(l); | 3413 | s = zdc_lex_string(l); |
3529 | break; | 3414 | break; |
3530 | } | ||
3531 | |||
3532 | default: | 3415 | default: |
3533 | { | ||
3534 | l->t.t = BC_LEX_INVALID; | 3416 | l->t.t = BC_LEX_INVALID; |
3535 | s = bc_error_bad_character(c); | 3417 | s = bc_error_bad_character(c); |
3536 | break; | 3418 | break; |
3537 | } | ||
3538 | } | 3419 | } |
3539 | 3420 | ||
3540 | return s; | 3421 | return s; |
@@ -4112,7 +3993,7 @@ static BcStatus bc_parse_return(BcParse *p) | |||
4112 | 3993 | ||
4113 | if (!paren || p->l.t.last != BC_LEX_RPAREN) { | 3994 | if (!paren || p->l.t.last != BC_LEX_RPAREN) { |
4114 | s = bc_POSIX_requires("parentheses around return expressions"); | 3995 | s = bc_POSIX_requires("parentheses around return expressions"); |
4115 | if (s) return s; | 3996 | ERROR_RETURN(if (s) return s;) |
4116 | } | 3997 | } |
4117 | 3998 | ||
4118 | bc_parse_push(p, BC_INST_RET); | 3999 | bc_parse_push(p, BC_INST_RET); |
@@ -5013,11 +4894,11 @@ static BcStatus bc_parse_expr_empty_ok(BcParse *p, uint8_t flags, BcParseNext ne | |||
5013 | 4894 | ||
5014 | if (!(flags & BC_PARSE_REL) && nrelops) { | 4895 | if (!(flags & BC_PARSE_REL) && nrelops) { |
5015 | s = bc_POSIX_does_not_allow("comparison operators outside if or loops"); | 4896 | s = bc_POSIX_does_not_allow("comparison operators outside if or loops"); |
5016 | if (s) return s; | 4897 | ERROR_RETURN(if (s) return s;) |
5017 | } | 4898 | } |
5018 | else if ((flags & BC_PARSE_REL) && nrelops > 1) { | 4899 | else if ((flags & BC_PARSE_REL) && nrelops > 1) { |
5019 | s = bc_POSIX_requires("exactly one comparison operator per condition"); | 4900 | s = bc_POSIX_requires("exactly one comparison operator per condition"); |
5020 | if (s) return s; | 4901 | ERROR_RETURN(if (s) return s;) |
5021 | } | 4902 | } |
5022 | 4903 | ||
5023 | if (flags & BC_PARSE_PRINT) { | 4904 | if (flags & BC_PARSE_PRINT) { |