aboutsummaryrefslogtreecommitdiff
path: root/miscutils/bc.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-29 02:24:19 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-29 02:24:19 +0100
commite16a5223d20e5715b98e1fd21fa8d59e75e4e793 (patch)
tree6f5546a00e30296c557c26036d0363ce9e9369e6 /miscutils/bc.c
parentf9b4cc114cb4eb2a997f08daa43af30ad598322c (diff)
downloadbusybox-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.c82
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
2558static 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."
2565static 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
2693static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) 2707static 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}