1
From 680ccd357395ad081afe821ffbeef1ff338fe41d Mon Sep 17 00:00:00 2001
2
From: Denys Vlasenko <vda.linux@googlemail.com>
3
Date: Mon, 31 Dec 2018 19:42:13 +0100
4
Subject: [PATCH 05/84] bc: support ibase up to 36 (GNU compat)
7
zxc_program_num 995 1018 +23
9
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
11
miscutils/bc.c | 50 +++++++++++++++++++++++++++++++-------------------
12
testsuite/bc.tests | 5 +++++
13
2 files changed, 36 insertions(+), 19 deletions(-)
15
diff --git a/miscutils/bc.c b/miscutils/bc.c
16
index 72c23542c..798bc0a3e 100644
20
* Original code copyright (c) 2018 Gavin D. Howard and contributors.
22
//TODO: GNU extensions:
23
-// support ibase up to 36
24
// support "define void f()..."
25
// support "define f(*param[])" - "pass array by reference" syntax
27
@@ -231,7 +230,7 @@ typedef struct BcNum {
31
-#define BC_NUM_MAX_IBASE ((unsigned long) 16)
32
+#define BC_NUM_MAX_IBASE 36
33
// larger value might speed up BIGNUM calculations a bit:
34
#define BC_NUM_DEF_SIZE 16
35
#define BC_NUM_PRINT_WIDTH 69
36
@@ -2638,32 +2637,33 @@ static void bc_num_parseDecimal(BcNum *n, const char *val)
37
static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t)
40
- BcNum temp, mult, result;
44
+ BcDig temp_digs[ULONG_NUM_BUFSIZE];
45
BcDig base_digs[ULONG_NUM_BUFSIZE];
50
- for (i = 0; ; ++i) {
53
- if (val[i] != '.' && val[i] != '0')
58
- bc_num_init_DEF_SIZE(&temp);
59
bc_num_init_DEF_SIZE(&mult);
61
+ temp.cap = ARRAY_SIZE(temp_digs);
62
+ temp.num = temp_digs;
64
base.cap = ARRAY_SIZE(base_digs);
66
bc_num_ulong2num(&base, base_t);
73
if (c == '\0') goto int_err;
76
- v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
77
+ v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10);
78
+ if (v > base_t) v = base_t;
80
s = zbc_num_mul(n, &base, &mult, 0);
82
@@ -2678,11 +2678,14 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t)
92
- v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
93
+ v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10);
94
+ if (v > base_t) v = base_t;
96
s = zbc_num_mul(&result, &base, &result, 0);
98
@@ -2707,18 +2710,27 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t)
102
- bc_num_free(&temp);
105
static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t)
109
if (!xc_num_strValid(val))
110
RETURN_STATUS(bc_error("bad number string"));
113
- while (*val == '0') val++;
114
+ while (*val == '0')
116
+ for (i = 0; ; ++i) {
117
+ if (val[i] == '\0')
118
+ RETURN_STATUS(BC_STATUS_SUCCESS);
119
+ if (val[i] != '.' && val[i] != '0')
124
+ if (base_t == 10 || val[1] == '\0')
125
+ // Decimal, or single-digit number
126
bc_num_parseDecimal(n, val);
128
bc_num_parseBase(n, val, base_t);
129
@@ -5526,7 +5538,7 @@ static BC_STATUS zxc_num_printBase(BcNum *n)
133
- if (G.prog.ob_t <= BC_NUM_MAX_IBASE) {
134
+ if (G.prog.ob_t <= 16) {
136
print = bc_num_printHex;
138
diff --git a/testsuite/bc.tests b/testsuite/bc.tests
139
index 3fbb49996..1d4545559 100755
140
--- a/testsuite/bc.tests
141
+++ b/testsuite/bc.tests
142
@@ -218,6 +218,11 @@ for(i=1; i<3; i++) {
146
+testing "bc ibase" \
148
+ "99\n1295\n1224\n" \
149
+ "" "a=ZZ;a;ibase=36;a=ZZ;a;ibase=Z;a=ZZ;a"
151
tar xJf bc_large.tar.xz