diff options
Diffstat (limited to 'miscutils')
| -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 | } |
