diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-29 02:24:19 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-29 02:24:19 +0100 |
commit | e16a5223d20e5715b98e1fd21fa8d59e75e4e793 (patch) | |
tree | 6f5546a00e30296c557c26036d0363ce9e9369e6 /miscutils/bc.c | |
parent | f9b4cc114cb4eb2a997f08daa43af30ad598322c (diff) | |
download | busybox-w32-e16a5223d20e5715b98e1fd21fa8d59e75e4e793.tar.gz busybox-w32-e16a5223d20e5715b98e1fd21fa8d59e75e4e793.tar.bz2 busybox-w32-e16a5223d20e5715b98e1fd21fa8d59e75e4e793.zip |
bc: fix handling of "digits" above 9
function old new delta
zxc_lex_next 1573 1608 +35
xc_parse_pushIndex 58 56 -2
xc_program_index 71 63 -8
zxc_program_num 1022 990 -32
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 35/-42) Total: -7 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils/bc.c')
-rw-r--r-- | miscutils/bc.c | 82 |
1 files changed, 63 insertions, 19 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index c10cd73fa..07327af6f 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -2555,13 +2555,16 @@ static void xc_read_line(BcVec *vec, FILE *fp) | |||
2555 | // Parsing routines | 2555 | // Parsing routines |
2556 | // | 2556 | // |
2557 | 2557 | ||
2558 | static bool xc_num_strValid(const char *val, size_t base) | 2558 | // "Input numbers may contain the characters 0-9 and A-Z. |
2559 | { | 2559 | // (Note: They must be capitals. Lower case letters are variable names.) |
2560 | BcDig b; | 2560 | // Single digit numbers always have the value of the digit regardless of |
2561 | bool radix; | 2561 | // the value of ibase. (i.e. A = 10.) For multi-digit numbers, bc changes |
2562 | 2562 | // all input digits greater or equal to ibase to the value of ibase-1. | |
2563 | b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); | 2563 | // This makes the number ZZZ always be the largest 3 digit number of the |
2564 | radix = false; | 2564 | // input base." |
2565 | static bool xc_num_strValid(const char *val) | ||
2566 | { | ||
2567 | bool radix = false; | ||
2565 | for (;;) { | 2568 | for (;;) { |
2566 | BcDig c = *val++; | 2569 | BcDig c = *val++; |
2567 | if (c == '\0') | 2570 | if (c == '\0') |
@@ -2571,7 +2574,7 @@ static bool xc_num_strValid(const char *val, size_t base) | |||
2571 | radix = true; | 2574 | radix = true; |
2572 | continue; | 2575 | continue; |
2573 | } | 2576 | } |
2574 | if (c < '0' || c >= b || (c > '9' && c < 'A')) | 2577 | if ((c < '0' || c > '9') && (c < 'A' || c > 'Z')) |
2575 | return false; | 2578 | return false; |
2576 | } | 2579 | } |
2577 | return true; | 2580 | return true; |
@@ -2599,10 +2602,21 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) | |||
2599 | for (i = 0; val[i]; ++i) { | 2602 | for (i = 0; val[i]; ++i) { |
2600 | if (val[i] != '0' && val[i] != '.') { | 2603 | if (val[i] != '0' && val[i] != '.') { |
2601 | // Not entirely zero value - convert it, and exit | 2604 | // Not entirely zero value - convert it, and exit |
2605 | if (len == 1) { | ||
2606 | char c = val[0] - '0'; | ||
2607 | if (c > 9) // A-Z => 10-36 | ||
2608 | c -= ('A' - '9' - 1); | ||
2609 | n->num[0] = c; | ||
2610 | n->len = 1; | ||
2611 | break; | ||
2612 | } | ||
2602 | i = len - 1; | 2613 | i = len - 1; |
2603 | for (;;) { | 2614 | for (;;) { |
2604 | n->num[n->len] = val[i] - '0'; | 2615 | char c = val[i] - '0'; |
2605 | ++n->len; | 2616 | if (c > 9) // A-Z => 9 |
2617 | c = 9; | ||
2618 | n->num[n->len] = c; | ||
2619 | n->len++; | ||
2606 | skip_dot: | 2620 | skip_dot: |
2607 | if (i == 0) break; | 2621 | if (i == 0) break; |
2608 | if (val[--i] == '.') goto skip_dot; | 2622 | if (val[--i] == '.') goto skip_dot; |
@@ -2692,7 +2706,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) | |||
2692 | 2706 | ||
2693 | static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) | 2707 | static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) |
2694 | { | 2708 | { |
2695 | if (!xc_num_strValid(val, base_t)) | 2709 | if (!xc_num_strValid(val)) |
2696 | RETURN_STATUS(bc_error("bad number string")); | 2710 | RETURN_STATUS(bc_error("bad number string")); |
2697 | 2711 | ||
2698 | bc_num_zero(n); | 2712 | bc_num_zero(n); |
@@ -2807,6 +2821,13 @@ static BC_STATUS zxc_lex_number(char last) | |||
2807 | bc_vec_pop_all(&p->lex_strnumbuf); | 2821 | bc_vec_pop_all(&p->lex_strnumbuf); |
2808 | bc_vec_pushByte(&p->lex_strnumbuf, last); | 2822 | bc_vec_pushByte(&p->lex_strnumbuf, last); |
2809 | 2823 | ||
2824 | // "Input numbers may contain the characters 0-9 and A-Z. | ||
2825 | // (Note: They must be capitals. Lower case letters are variable names.) | ||
2826 | // Single digit numbers always have the value of the digit regardless of | ||
2827 | // the value of ibase. (i.e. A = 10.) For multi-digit numbers, bc changes | ||
2828 | // all input digits greater or equal to ibase to the value of ibase-1. | ||
2829 | // This makes the number ZZZ always be the largest 3 digit number of the | ||
2830 | // input base." | ||
2810 | pt = (last == '.'); | 2831 | pt = (last == '.'); |
2811 | p->lex = XC_LEX_NUMBER; | 2832 | p->lex = XC_LEX_NUMBER; |
2812 | for (;;) { | 2833 | for (;;) { |
@@ -2822,13 +2843,13 @@ static BC_STATUS zxc_lex_number(char last) | |||
2822 | c = peek_inbuf(); // force next line to be read | 2843 | c = peek_inbuf(); // force next line to be read |
2823 | goto check_c; | 2844 | goto check_c; |
2824 | } | 2845 | } |
2825 | if (!isdigit(c) && (c < 'A' || c > 'F')) { | 2846 | if (!isdigit(c) && (c < 'A' || c > 'Z')) { |
2826 | if (c != '.') break; | 2847 | if (c != '.') break; |
2827 | // if '.' was already seen, stop on second one: | 2848 | // if '.' was already seen, stop on second one: |
2828 | if (pt) break; | 2849 | if (pt) break; |
2829 | pt = true; | 2850 | pt = true; |
2830 | } | 2851 | } |
2831 | // c is one of "0-9A-F." | 2852 | // c is one of "0-9A-Z." |
2832 | last = c; | 2853 | last = c; |
2833 | bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf); | 2854 | bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf); |
2834 | p->lex_inbuf++; | 2855 | p->lex_inbuf++; |
@@ -3167,6 +3188,26 @@ static BC_STATUS zbc_lex_token(void) | |||
3167 | case 'D': | 3188 | case 'D': |
3168 | case 'E': | 3189 | case 'E': |
3169 | case 'F': | 3190 | case 'F': |
3191 | case 'G': | ||
3192 | case 'H': | ||
3193 | case 'I': | ||
3194 | case 'J': | ||
3195 | case 'K': | ||
3196 | case 'L': | ||
3197 | case 'M': | ||
3198 | case 'N': | ||
3199 | case 'O': | ||
3200 | case 'P': | ||
3201 | case 'Q': | ||
3202 | case 'R': | ||
3203 | case 'S': | ||
3204 | case 'T': | ||
3205 | case 'U': | ||
3206 | case 'V': | ||
3207 | case 'W': | ||
3208 | case 'X': | ||
3209 | case 'Y': | ||
3210 | case 'Z': | ||
3170 | s = zxc_lex_number(c); | 3211 | s = zxc_lex_number(c); |
3171 | break; | 3212 | break; |
3172 | case ';': | 3213 | case ';': |
@@ -3450,13 +3491,14 @@ static void xc_parse_pushIndex(size_t idx) | |||
3450 | 3491 | ||
3451 | mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8); | 3492 | mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8); |
3452 | amt = sizeof(idx); | 3493 | amt = sizeof(idx); |
3453 | do { | 3494 | for (;;) { |
3454 | if (idx & mask) break; | 3495 | if (idx & mask) break; |
3455 | mask >>= 8; | 3496 | mask >>= 8; |
3456 | amt--; | 3497 | amt--; |
3457 | } while (amt != 0); | 3498 | } |
3499 | // amt is at least 1 here - "one byte of length data follows" | ||
3458 | 3500 | ||
3459 | xc_parse_push(SMALL_INDEX_LIMIT + amt); | 3501 | xc_parse_push((SMALL_INDEX_LIMIT - 1) + amt); |
3460 | 3502 | ||
3461 | while (idx != 0) { | 3503 | while (idx != 0) { |
3462 | push_idx: | 3504 | push_idx: |
@@ -5260,13 +5302,15 @@ static size_t xc_program_index(char *code, size_t *bgn) | |||
5260 | *bgn += 1; | 5302 | *bgn += 1; |
5261 | return amt; | 5303 | return amt; |
5262 | } | 5304 | } |
5263 | amt -= SMALL_INDEX_LIMIT; | 5305 | amt -= (SMALL_INDEX_LIMIT - 1); // amt is 1 or more here |
5264 | *bgn += amt + 1; | 5306 | *bgn += amt + 1; |
5265 | 5307 | ||
5266 | amt *= 8; | ||
5267 | res = 0; | 5308 | res = 0; |
5268 | for (i = 0; i < amt; i += 8) | 5309 | i = 0; |
5310 | do { | ||
5269 | res |= (size_t)(*bytes++) << i; | 5311 | res |= (size_t)(*bytes++) << i; |
5312 | i += 8; | ||
5313 | } while (--amt != 0); | ||
5270 | 5314 | ||
5271 | return res; | 5315 | return res; |
5272 | } | 5316 | } |