diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-31 19:42:13 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-31 19:42:13 +0100 |
| commit | 680ccd357395ad081afe821ffbeef1ff338fe41d (patch) | |
| tree | b6c8622f8f221c5691346fe9ec4ff31ecbc74d8d /miscutils | |
| parent | 2747f6195b94db6c1adf2eae243df5c0a01d39f2 (diff) | |
| download | busybox-w32-680ccd357395ad081afe821ffbeef1ff338fe41d.tar.gz busybox-w32-680ccd357395ad081afe821ffbeef1ff338fe41d.tar.bz2 busybox-w32-680ccd357395ad081afe821ffbeef1ff338fe41d.zip | |
bc: support ibase up to 36 (GNU compat)
function old new delta
zxc_program_num 995 1018 +23
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/bc.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 72c23542c..798bc0a3e 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | * Original code copyright (c) 2018 Gavin D. Howard and contributors. | 5 | * Original code copyright (c) 2018 Gavin D. Howard and contributors. |
| 6 | */ | 6 | */ |
| 7 | //TODO: GNU extensions: | 7 | //TODO: GNU extensions: |
| 8 | // support ibase up to 36 | ||
| 9 | // support "define void f()..." | 8 | // support "define void f()..." |
| 10 | // support "define f(*param[])" - "pass array by reference" syntax | 9 | // support "define f(*param[])" - "pass array by reference" syntax |
| 11 | 10 | ||
| @@ -231,7 +230,7 @@ typedef struct BcNum { | |||
| 231 | bool neg; | 230 | bool neg; |
| 232 | } BcNum; | 231 | } BcNum; |
| 233 | 232 | ||
| 234 | #define BC_NUM_MAX_IBASE ((unsigned long) 16) | 233 | #define BC_NUM_MAX_IBASE 36 |
| 235 | // larger value might speed up BIGNUM calculations a bit: | 234 | // larger value might speed up BIGNUM calculations a bit: |
| 236 | #define BC_NUM_DEF_SIZE 16 | 235 | #define BC_NUM_DEF_SIZE 16 |
| 237 | #define BC_NUM_PRINT_WIDTH 69 | 236 | #define BC_NUM_PRINT_WIDTH 69 |
| @@ -2638,32 +2637,33 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) | |||
| 2638 | static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) | 2637 | static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) |
| 2639 | { | 2638 | { |
| 2640 | BcStatus s; | 2639 | BcStatus s; |
| 2641 | BcNum temp, mult, result; | 2640 | BcNum mult, result; |
| 2641 | BcNum temp; | ||
| 2642 | BcNum base; | 2642 | BcNum base; |
| 2643 | BcDig temp_digs[ULONG_NUM_BUFSIZE]; | ||
| 2643 | BcDig base_digs[ULONG_NUM_BUFSIZE]; | 2644 | BcDig base_digs[ULONG_NUM_BUFSIZE]; |
| 2644 | BcDig c = '\0'; | 2645 | BcDig c = '\0'; |
| 2645 | unsigned long v; | 2646 | size_t digits; |
| 2646 | size_t i, digits; | ||
| 2647 | |||
| 2648 | for (i = 0; ; ++i) { | ||
| 2649 | if (val[i] == '\0') | ||
| 2650 | return; | ||
| 2651 | if (val[i] != '.' && val[i] != '0') | ||
| 2652 | break; | ||
| 2653 | } | ||
| 2654 | 2647 | ||
| 2655 | bc_num_init_DEF_SIZE(&temp); | ||
| 2656 | bc_num_init_DEF_SIZE(&mult); | 2648 | bc_num_init_DEF_SIZE(&mult); |
| 2649 | |||
| 2650 | temp.cap = ARRAY_SIZE(temp_digs); | ||
| 2651 | temp.num = temp_digs; | ||
| 2652 | |||
| 2657 | base.cap = ARRAY_SIZE(base_digs); | 2653 | base.cap = ARRAY_SIZE(base_digs); |
| 2658 | base.num = base_digs; | 2654 | base.num = base_digs; |
| 2659 | bc_num_ulong2num(&base, base_t); | 2655 | bc_num_ulong2num(&base, base_t); |
| 2656 | base_t--; | ||
| 2660 | 2657 | ||
| 2661 | for (;;) { | 2658 | for (;;) { |
| 2659 | unsigned v; | ||
| 2660 | |||
| 2662 | c = *val++; | 2661 | c = *val++; |
| 2663 | if (c == '\0') goto int_err; | 2662 | if (c == '\0') goto int_err; |
| 2664 | if (c == '.') break; | 2663 | if (c == '.') break; |
| 2665 | 2664 | ||
| 2666 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | 2665 | v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10); |
| 2666 | if (v > base_t) v = base_t; | ||
| 2667 | 2667 | ||
| 2668 | s = zbc_num_mul(n, &base, &mult, 0); | 2668 | s = zbc_num_mul(n, &base, &mult, 0); |
| 2669 | if (s) goto int_err; | 2669 | if (s) goto int_err; |
| @@ -2678,11 +2678,14 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) | |||
| 2678 | 2678 | ||
| 2679 | digits = 0; | 2679 | digits = 0; |
| 2680 | for (;;) { | 2680 | for (;;) { |
| 2681 | unsigned v; | ||
| 2682 | |||
| 2681 | c = *val++; | 2683 | c = *val++; |
| 2682 | if (c == '\0') break; | 2684 | if (c == '\0') break; |
| 2683 | digits++; | 2685 | digits++; |
| 2684 | 2686 | ||
| 2685 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | 2687 | v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10); |
| 2688 | if (v > base_t) v = base_t; | ||
| 2686 | 2689 | ||
| 2687 | s = zbc_num_mul(&result, &base, &result, 0); | 2690 | s = zbc_num_mul(&result, &base, &result, 0); |
| 2688 | if (s) goto err; | 2691 | if (s) goto err; |
| @@ -2707,18 +2710,27 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) | |||
| 2707 | bc_num_free(&result); | 2710 | bc_num_free(&result); |
| 2708 | int_err: | 2711 | int_err: |
| 2709 | bc_num_free(&mult); | 2712 | bc_num_free(&mult); |
| 2710 | bc_num_free(&temp); | ||
| 2711 | } | 2713 | } |
| 2712 | 2714 | ||
| 2713 | static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) | 2715 | static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t) |
| 2714 | { | 2716 | { |
| 2717 | size_t i; | ||
| 2718 | |||
| 2715 | if (!xc_num_strValid(val)) | 2719 | if (!xc_num_strValid(val)) |
| 2716 | RETURN_STATUS(bc_error("bad number string")); | 2720 | RETURN_STATUS(bc_error("bad number string")); |
| 2717 | 2721 | ||
| 2718 | bc_num_zero(n); | 2722 | bc_num_zero(n); |
| 2719 | while (*val == '0') val++; | 2723 | while (*val == '0') |
| 2724 | val++; | ||
| 2725 | for (i = 0; ; ++i) { | ||
| 2726 | if (val[i] == '\0') | ||
| 2727 | RETURN_STATUS(BC_STATUS_SUCCESS); | ||
| 2728 | if (val[i] != '.' && val[i] != '0') | ||
| 2729 | break; | ||
| 2730 | } | ||
| 2720 | 2731 | ||
| 2721 | if (base_t == 10) | 2732 | if (base_t == 10 || val[1] == '\0') |
| 2733 | // Decimal, or single-digit number | ||
| 2722 | bc_num_parseDecimal(n, val); | 2734 | bc_num_parseDecimal(n, val); |
| 2723 | else | 2735 | else |
| 2724 | bc_num_parseBase(n, val, base_t); | 2736 | bc_num_parseBase(n, val, base_t); |
| @@ -5526,7 +5538,7 @@ static BC_STATUS zxc_num_printBase(BcNum *n) | |||
| 5526 | 5538 | ||
| 5527 | n->neg = false; | 5539 | n->neg = false; |
| 5528 | 5540 | ||
| 5529 | if (G.prog.ob_t <= BC_NUM_MAX_IBASE) { | 5541 | if (G.prog.ob_t <= 16) { |
| 5530 | width = 1; | 5542 | width = 1; |
| 5531 | print = bc_num_printHex; | 5543 | print = bc_num_printHex; |
| 5532 | } else { | 5544 | } else { |
