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>
This commit is contained in:
parent
2747f6195b
commit
680ccd3573
@ -5,7 +5,6 @@
|
|||||||
* Original code copyright (c) 2018 Gavin D. Howard and contributors.
|
* Original code copyright (c) 2018 Gavin D. Howard and contributors.
|
||||||
*/
|
*/
|
||||||
//TODO: GNU extensions:
|
//TODO: GNU extensions:
|
||||||
// support ibase up to 36
|
|
||||||
// support "define void f()..."
|
// support "define void f()..."
|
||||||
// support "define f(*param[])" - "pass array by reference" syntax
|
// support "define f(*param[])" - "pass array by reference" syntax
|
||||||
|
|
||||||
@ -231,7 +230,7 @@ typedef struct BcNum {
|
|||||||
bool neg;
|
bool neg;
|
||||||
} BcNum;
|
} BcNum;
|
||||||
|
|
||||||
#define BC_NUM_MAX_IBASE ((unsigned long) 16)
|
#define BC_NUM_MAX_IBASE 36
|
||||||
// larger value might speed up BIGNUM calculations a bit:
|
// larger value might speed up BIGNUM calculations a bit:
|
||||||
#define BC_NUM_DEF_SIZE 16
|
#define BC_NUM_DEF_SIZE 16
|
||||||
#define BC_NUM_PRINT_WIDTH 69
|
#define BC_NUM_PRINT_WIDTH 69
|
||||||
@ -2638,32 +2637,33 @@ static void bc_num_parseDecimal(BcNum *n, const char *val)
|
|||||||
static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t)
|
static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t)
|
||||||
{
|
{
|
||||||
BcStatus s;
|
BcStatus s;
|
||||||
BcNum temp, mult, result;
|
BcNum mult, result;
|
||||||
|
BcNum temp;
|
||||||
BcNum base;
|
BcNum base;
|
||||||
|
BcDig temp_digs[ULONG_NUM_BUFSIZE];
|
||||||
BcDig base_digs[ULONG_NUM_BUFSIZE];
|
BcDig base_digs[ULONG_NUM_BUFSIZE];
|
||||||
BcDig c = '\0';
|
BcDig c = '\0';
|
||||||
unsigned long v;
|
size_t digits;
|
||||||
size_t i, digits;
|
|
||||||
|
|
||||||
for (i = 0; ; ++i) {
|
|
||||||
if (val[i] == '\0')
|
|
||||||
return;
|
|
||||||
if (val[i] != '.' && val[i] != '0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bc_num_init_DEF_SIZE(&temp);
|
|
||||||
bc_num_init_DEF_SIZE(&mult);
|
bc_num_init_DEF_SIZE(&mult);
|
||||||
|
|
||||||
|
temp.cap = ARRAY_SIZE(temp_digs);
|
||||||
|
temp.num = temp_digs;
|
||||||
|
|
||||||
base.cap = ARRAY_SIZE(base_digs);
|
base.cap = ARRAY_SIZE(base_digs);
|
||||||
base.num = base_digs;
|
base.num = base_digs;
|
||||||
bc_num_ulong2num(&base, base_t);
|
bc_num_ulong2num(&base, base_t);
|
||||||
|
base_t--;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
unsigned v;
|
||||||
|
|
||||||
c = *val++;
|
c = *val++;
|
||||||
if (c == '\0') goto int_err;
|
if (c == '\0') goto int_err;
|
||||||
if (c == '.') break;
|
if (c == '.') break;
|
||||||
|
|
||||||
v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
|
v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10);
|
||||||
|
if (v > base_t) v = base_t;
|
||||||
|
|
||||||
s = zbc_num_mul(n, &base, &mult, 0);
|
s = zbc_num_mul(n, &base, &mult, 0);
|
||||||
if (s) goto int_err;
|
if (s) goto int_err;
|
||||||
@ -2678,11 +2678,14 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t)
|
|||||||
|
|
||||||
digits = 0;
|
digits = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
unsigned v;
|
||||||
|
|
||||||
c = *val++;
|
c = *val++;
|
||||||
if (c == '\0') break;
|
if (c == '\0') break;
|
||||||
digits++;
|
digits++;
|
||||||
|
|
||||||
v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10);
|
v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10);
|
||||||
|
if (v > base_t) v = base_t;
|
||||||
|
|
||||||
s = zbc_num_mul(&result, &base, &result, 0);
|
s = zbc_num_mul(&result, &base, &result, 0);
|
||||||
if (s) goto err;
|
if (s) goto err;
|
||||||
@ -2707,18 +2710,27 @@ static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t)
|
|||||||
bc_num_free(&result);
|
bc_num_free(&result);
|
||||||
int_err:
|
int_err:
|
||||||
bc_num_free(&mult);
|
bc_num_free(&mult);
|
||||||
bc_num_free(&temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t)
|
static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (!xc_num_strValid(val))
|
if (!xc_num_strValid(val))
|
||||||
RETURN_STATUS(bc_error("bad number string"));
|
RETURN_STATUS(bc_error("bad number string"));
|
||||||
|
|
||||||
bc_num_zero(n);
|
bc_num_zero(n);
|
||||||
while (*val == '0') val++;
|
while (*val == '0')
|
||||||
|
val++;
|
||||||
|
for (i = 0; ; ++i) {
|
||||||
|
if (val[i] == '\0')
|
||||||
|
RETURN_STATUS(BC_STATUS_SUCCESS);
|
||||||
|
if (val[i] != '.' && val[i] != '0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (base_t == 10)
|
if (base_t == 10 || val[1] == '\0')
|
||||||
|
// Decimal, or single-digit number
|
||||||
bc_num_parseDecimal(n, val);
|
bc_num_parseDecimal(n, val);
|
||||||
else
|
else
|
||||||
bc_num_parseBase(n, val, base_t);
|
bc_num_parseBase(n, val, base_t);
|
||||||
@ -5526,7 +5538,7 @@ static BC_STATUS zxc_num_printBase(BcNum *n)
|
|||||||
|
|
||||||
n->neg = false;
|
n->neg = false;
|
||||||
|
|
||||||
if (G.prog.ob_t <= BC_NUM_MAX_IBASE) {
|
if (G.prog.ob_t <= 16) {
|
||||||
width = 1;
|
width = 1;
|
||||||
print = bc_num_printHex;
|
print = bc_num_printHex;
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,6 +218,11 @@ for(i=1; i<3; i++) {
|
|||||||
99
|
99
|
||||||
"
|
"
|
||||||
|
|
||||||
|
testing "bc ibase" \
|
||||||
|
"bc" \
|
||||||
|
"99\n1295\n1224\n" \
|
||||||
|
"" "a=ZZ;a;ibase=36;a=ZZ;a;ibase=Z;a=ZZ;a"
|
||||||
|
|
||||||
tar xJf bc_large.tar.xz
|
tar xJf bc_large.tar.xz
|
||||||
|
|
||||||
for f in bc*.bc; do
|
for f in bc*.bc; do
|
||||||
|
Loading…
x
Reference in New Issue
Block a user