aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-29 02:40:03 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-29 03:08:12 +0100
commitd5b0fa6abf725cc9281f3b11fc2a4c0f12df0793 (patch)
tree695632ded5b8e73a7eb53cc3b426ea6d2d5f2ab0
parente16a5223d20e5715b98e1fd21fa8d59e75e4e793 (diff)
downloadbusybox-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.c19
-rw-r--r--testsuite/bc_numbers2.bc18
-rw-r--r--testsuite/bc_numbers2_results.txt50
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 @@
1define 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}
12f()
13ibase=9;f()
14ibase=A;f()
15ibase=F;f()
16ibase=G;f()
17#ibase=Z;f()
18halt
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 @@
1ibase:10
210
315
416
535
610
715
816
935
100
11ibase:9
1210
1315
1416
1535
1610
1715
1816
1935
200
21ibase:10
2210
2315
2416
2535
2610
2715
2816
2935
300
31ibase:15
3210
3315
3416
3535
3610
3715
3816
3935
400
41ibase:16
4210
4315
4416
4535
4610
4715
4816
4935
500