diff options
-rw-r--r-- | miscutils/bc.c | 82 | ||||
-rw-r--r-- | testsuite/bc_numbers1.bc | 23 | ||||
-rw-r--r-- | testsuite/bc_numbers1_results.txt | 17 |
3 files changed, 103 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 | } |
diff --git a/testsuite/bc_numbers1.bc b/testsuite/bc_numbers1.bc new file mode 100644 index 000000000..fd4e225ee --- /dev/null +++ b/testsuite/bc_numbers1.bc | |||
@@ -0,0 +1,23 @@ | |||
1 | ibase=G | ||
2 | define f() { | ||
3 | a00=00;a01=01;a02=02;a03=03;a04=04;a05=05;a06=06;a07=07;a08=08;a09=09;a0a=0A;a0b=0B;a0c=0C;a0d=0D;a0e=0E;a0f=0F | ||
4 | a10=10;a11=11;a12=12;a13=13;a14=14;a15=15;a16=16;a17=17;a18=18;a19=19;a1a=1A;a1b=1B;a1c=1C;a1d=1D;a1e=1E;a1f=1F | ||
5 | a20=20;a21=21;a22=22;a23=23;a24=24;a25=25;a26=26;a27=27;a28=28;a29=29;a2a=2A;a2b=2B;a2c=2C;a2d=2D;a2e=2E;a2f=2F | ||
6 | a30=30;a31=31;a32=32;a33=33;a34=34;a35=35;a36=36;a37=37;a38=38;a39=39;a3a=3A;a3b=3B;a3c=3C;a3d=3D;a3e=3E;a3f=3F | ||
7 | a40=40;a41=41;a42=42;a43=43;a44=44;a45=45;a46=46;a47=47;a48=48;a49=49;a4a=4A;a4b=4B;a4c=4C;a4d=4D;a4e=4E;a4f=4F | ||
8 | a50=50;a51=51;a52=52;a53=53;a54=54;a55=55;a56=56;a57=57;a58=58;a59=59;a5a=5A;a5b=5B;a5c=5C;a5d=5D;a5e=5E;a5f=5F | ||
9 | a60=60;a61=61;a62=62;a63=63;a64=64;a65=65;a66=66;a67=67;a68=68;a69=69;a6a=6A;a6b=6B;a6c=6C;a6d=6D;a6e=6E;a6f=6F | ||
10 | a70=70;a71=71;a72=72;a73=73;a74=74;a75=75;a76=76;a77=77;a78=78;a79=79;a7a=7A;a7b=7B;a7c=7C;a7d=7D;a7e=7E;a7f=7F | ||
11 | a80=80;a81=81;a82=82;a83=83;a84=84;a85=85;a86=86;a87=87;a88=88;a89=89;a8a=8A;a8b=8B;a8c=8C;a8d=8D;a8e=8E;a8f=8F | ||
12 | a90=90;a91=91;a92=92;a93=93;a94=94;a95=95;a96=96;a97=97;a98=98;a99=99;a9a=9A;a9b=9B;a9c=9C;a9d=9D;a9e=9E;a9f=9F | ||
13 | aa0=A0;aa1=A1;aa2=A2;aa3=A3;aa4=A4;aa5=A5;aa6=A6;aa7=A7;aa8=A8;aa9=A9;aaa=AA;aab=AB;aac=AC;aad=AD;aae=AE;aaf=AF | ||
14 | ab0=B0;ab1=B1;ab2=B2;ab3=B3;ab4=B4;ab5=B5;ab6=B6;ab7=B7;ab8=B8;ab9=B9;aba=BA;abb=BB;abc=BC;abd=BD;abe=BE;abf=BF | ||
15 | ac0=C0;ac1=C1;ac2=C2;ac3=C3;ac4=C4;ac5=C5;ac6=C6;ac7=C7;ac8=C8;ac9=C9;aca=CA;acb=CB;acc=CC;acd=CD;ace=CE;acf=CF | ||
16 | ad0=D0;ad1=D1;ad2=D2;ad3=D3;ad4=D4;ad5=D5;ad6=D6;ad7=D7;ad8=D8;ad9=D9;ada=DA;adb=DB;adc=DC;add=DD;ade=DE;adf=DF | ||
17 | ae0=E0;ae1=E1;ae2=E2;ae3=E3;ae4=E4;ae5=E5;ae6=E6;ae7=E7;ae8=E8;ae9=E9;aea=EA;aeb=EB;aec=EC;aed=ED;aee=EE;aef=EF | ||
18 | af0=F0;af1=F1;af2=F2;af3=F3;af4=F4;af5=F5;af6=F6;af7=F7;af8=F8;af9=F9;afa=FA;afb=FB;afc=FC;afd=FD;afe=FE;aff=FF | ||
19 | # this tests "index encoding" in bc.c: are numbers after 0xfc encoded correctly? | ||
20 | af0;af1;af2;af3;af4;af5;af6;af7;af8;af9;afa;afb;afc;afd;afe;aff | ||
21 | } | ||
22 | f() | ||
23 | halt | ||
diff --git a/testsuite/bc_numbers1_results.txt b/testsuite/bc_numbers1_results.txt new file mode 100644 index 000000000..e0ace1049 --- /dev/null +++ b/testsuite/bc_numbers1_results.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | 240 | ||
2 | 241 | ||
3 | 242 | ||
4 | 243 | ||
5 | 244 | ||
6 | 245 | ||
7 | 246 | ||
8 | 247 | ||
9 | 248 | ||
10 | 249 | ||
11 | 250 | ||
12 | 251 | ||
13 | 252 | ||
14 | 253 | ||
15 | 254 | ||
16 | 255 | ||
17 | 0 | ||