diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-29 02:40:03 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-29 03:08:12 +0100 |
commit | d5b0fa6abf725cc9281f3b11fc2a4c0f12df0793 (patch) | |
tree | 695632ded5b8e73a7eb53cc3b426ea6d2d5f2ab0 | |
parent | e16a5223d20e5715b98e1fd21fa8d59e75e4e793 (diff) | |
download | busybox-w32-d5b0fa6abf725cc9281f3b11fc2a4c0f12df0793.tar.gz busybox-w32-d5b0fa6abf725cc9281f3b11fc2a4c0f12df0793.tar.bz2 busybox-w32-d5b0fa6abf725cc9281f3b11fc2a4c0f12df0793.zip |
bc: more fixes for unusual input bases
function old new delta
zxc_program_num 990 1020 +30
zxc_lex_number 172 202 +30
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 60/0) Total: 60 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | miscutils/bc.c | 19 | ||||
-rw-r--r-- | testsuite/bc_numbers2.bc | 18 | ||||
-rw-r--r-- | testsuite/bc_numbers2_results.txt | 50 |
3 files changed, 81 insertions, 6 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 07327af6f..cc15a8dd2 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -2591,7 +2591,7 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) | |||
2591 | if (len == 0) | 2591 | if (len == 0) |
2592 | return; | 2592 | return; |
2593 | 2593 | ||
2594 | bc_num_expand(n, len); | 2594 | bc_num_expand(n, len + 1); // +1 for e.g. "A" converting into 10 |
2595 | 2595 | ||
2596 | ptr = strchr(val, '.'); | 2596 | ptr = strchr(val, '.'); |
2597 | 2597 | ||
@@ -2603,11 +2603,15 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) | |||
2603 | if (val[i] != '0' && val[i] != '.') { | 2603 | if (val[i] != '0' && val[i] != '.') { |
2604 | // Not entirely zero value - convert it, and exit | 2604 | // Not entirely zero value - convert it, and exit |
2605 | if (len == 1) { | 2605 | if (len == 1) { |
2606 | char c = val[0] - '0'; | 2606 | unsigned c = val[0] - '0'; |
2607 | if (c > 9) // A-Z => 10-36 | 2607 | n->len = 1; |
2608 | if (c > 9) { // A-Z => 10-36 | ||
2609 | n->len = 2; | ||
2608 | c -= ('A' - '9' - 1); | 2610 | c -= ('A' - '9' - 1); |
2611 | n->num[1] = c/10; | ||
2612 | c = c%10; | ||
2613 | } | ||
2609 | n->num[0] = c; | 2614 | n->num[0] = c; |
2610 | n->len = 1; | ||
2611 | break; | 2615 | break; |
2612 | } | 2616 | } |
2613 | i = len - 1; | 2617 | i = len - 1; |
@@ -2817,17 +2821,20 @@ static BC_STATUS zxc_lex_number(char last) | |||
2817 | { | 2821 | { |
2818 | BcParse *p = &G.prs; | 2822 | BcParse *p = &G.prs; |
2819 | bool pt; | 2823 | bool pt; |
2824 | char last_valid_ch; | ||
2820 | 2825 | ||
2821 | bc_vec_pop_all(&p->lex_strnumbuf); | 2826 | bc_vec_pop_all(&p->lex_strnumbuf); |
2822 | bc_vec_pushByte(&p->lex_strnumbuf, last); | 2827 | bc_vec_pushByte(&p->lex_strnumbuf, last); |
2823 | 2828 | ||
2824 | // "Input numbers may contain the characters 0-9 and A-Z. | 2829 | // bc: "Input numbers may contain the characters 0-9 and A-Z. |
2825 | // (Note: They must be capitals. Lower case letters are variable names.) | 2830 | // (Note: They must be capitals. Lower case letters are variable names.) |
2826 | // Single digit numbers always have the value of the digit regardless of | 2831 | // 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 | 2832 | // 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. | 2833 | // 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 | 2834 | // This makes the number ZZZ always be the largest 3 digit number of the |
2830 | // input base." | 2835 | // input base." |
2836 | // dc only allows A-F, the rules about single-char and multi-char are the same. | ||
2837 | last_valid_ch = (IS_BC ? 'Z' : 'F'); | ||
2831 | pt = (last == '.'); | 2838 | pt = (last == '.'); |
2832 | p->lex = XC_LEX_NUMBER; | 2839 | p->lex = XC_LEX_NUMBER; |
2833 | for (;;) { | 2840 | for (;;) { |
@@ -2843,7 +2850,7 @@ static BC_STATUS zxc_lex_number(char last) | |||
2843 | c = peek_inbuf(); // force next line to be read | 2850 | c = peek_inbuf(); // force next line to be read |
2844 | goto check_c; | 2851 | goto check_c; |
2845 | } | 2852 | } |
2846 | if (!isdigit(c) && (c < 'A' || c > 'Z')) { | 2853 | if (!isdigit(c) && (c < 'A' || c > last_valid_ch)) { |
2847 | if (c != '.') break; | 2854 | if (c != '.') break; |
2848 | // if '.' was already seen, stop on second one: | 2855 | // if '.' was already seen, stop on second one: |
2849 | if (pt) break; | 2856 | if (pt) break; |
diff --git a/testsuite/bc_numbers2.bc b/testsuite/bc_numbers2.bc new file mode 100644 index 000000000..208fe0d4d --- /dev/null +++ b/testsuite/bc_numbers2.bc | |||
@@ -0,0 +1,18 @@ | |||
1 | define f() { | ||
2 | "ibase:";ibase | ||
3 | a=A;a | ||
4 | a=F;a | ||
5 | a=G;a | ||
6 | a=Z;a | ||
7 | a=0A;a | ||
8 | a=0F;a | ||
9 | a=0G;a | ||
10 | a=0Z;a | ||
11 | } | ||
12 | f() | ||
13 | ibase=9;f() | ||
14 | ibase=A;f() | ||
15 | ibase=F;f() | ||
16 | ibase=G;f() | ||
17 | #ibase=Z;f() | ||
18 | halt | ||
diff --git a/testsuite/bc_numbers2_results.txt b/testsuite/bc_numbers2_results.txt new file mode 100644 index 000000000..e3400bd92 --- /dev/null +++ b/testsuite/bc_numbers2_results.txt | |||
@@ -0,0 +1,50 @@ | |||
1 | ibase:10 | ||
2 | 10 | ||
3 | 15 | ||
4 | 16 | ||
5 | 35 | ||
6 | 10 | ||
7 | 15 | ||
8 | 16 | ||
9 | 35 | ||
10 | 0 | ||
11 | ibase:9 | ||
12 | 10 | ||
13 | 15 | ||
14 | 16 | ||
15 | 35 | ||
16 | 10 | ||
17 | 15 | ||
18 | 16 | ||
19 | 35 | ||
20 | 0 | ||
21 | ibase:10 | ||
22 | 10 | ||
23 | 15 | ||
24 | 16 | ||
25 | 35 | ||
26 | 10 | ||
27 | 15 | ||
28 | 16 | ||
29 | 35 | ||
30 | 0 | ||
31 | ibase:15 | ||
32 | 10 | ||
33 | 15 | ||
34 | 16 | ||
35 | 35 | ||
36 | 10 | ||
37 | 15 | ||
38 | 16 | ||
39 | 35 | ||
40 | 0 | ||
41 | ibase:16 | ||
42 | 10 | ||
43 | 15 | ||
44 | 16 | ||
45 | 35 | ||
46 | 10 | ||
47 | 15 | ||
48 | 16 | ||
49 | 35 | ||
50 | 0 | ||