aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miscutils/bc.c198
1 files changed, 94 insertions, 104 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 0908d7cb9..ef21ab063 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -217,14 +217,6 @@ typedef struct BcNum {
217typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t); 217typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t);
218typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *, size_t); 218typedef void (*BcNumDigitOp)(size_t, size_t, bool, size_t *, size_t);
219 219
220static void bc_num_init(BcNum *n, size_t req);
221static void bc_num_expand(BcNum *n, size_t req);
222static void bc_num_copy(BcNum *d, BcNum *s);
223static void bc_num_free(void *num);
224
225static BcStatus bc_num_ulong(BcNum *n, unsigned long *result);
226static void bc_num_ulong2num(BcNum *n, unsigned long val);
227
228static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale); 220static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale);
229static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale); 221static BcStatus bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale);
230static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale); 222static BcStatus bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale);
@@ -387,7 +379,6 @@ typedef struct BcInstPtr {
387 size_t len; 379 size_t len;
388} BcInstPtr; 380} BcInstPtr;
389 381
390static void bc_array_expand(BcVec *a, size_t len);
391static int bc_id_cmp(const void *e1, const void *e2); 382static int bc_id_cmp(const void *e1, const void *e2);
392 383
393// BC_LEX_NEG is not used in lexing; it is only for parsing. 384// BC_LEX_NEG is not used in lexing; it is only for parsing.
@@ -798,11 +789,8 @@ struct globals {
798#define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X)) 789#define G_exreg (ENABLE_DC && (option_mask32 & BC_FLAG_X))
799#define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0) 790#define G_interrupt (ENABLE_FEATURE_BC_SIGNALS ? bb_got_signal : 0)
800 791
801
802#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b')) 792#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
803 793
804static void bc_vm_info(void);
805
806#if ENABLE_BC 794#if ENABLE_BC
807 795
808// This is a bit array that corresponds to token types. An entry is 796// This is a bit array that corresponds to token types. An entry is
@@ -1046,6 +1034,15 @@ static int bc_error_nested_read_call(void)
1046 return bc_error("read() call inside of a read() call"); 1034 return bc_error("read() call inside of a read() call");
1047} 1035}
1048 1036
1037static void bc_vm_info(void)
1038{
1039 printf("%s "BB_VER"\n"
1040 "Copyright (c) 2018 Gavin D. Howard and contributors\n"
1041 "Report bugs at: https://github.com/gavinhoward/bc\n"
1042 "This is free software with ABSOLUTELY NO WARRANTY\n"
1043 , applet_name);
1044}
1045
1049static void bc_vec_grow(BcVec *v, size_t n) 1046static void bc_vec_grow(BcVec *v, size_t n)
1050{ 1047{
1051 size_t cap = v->cap * 2; 1048 size_t cap = v->cap * 2;
@@ -1351,6 +1348,74 @@ static void bc_num_ten(BcNum *n)
1351 n->num[1] = 1; 1348 n->num[1] = 1;
1352} 1349}
1353 1350
1351static void bc_num_init(BcNum *n, size_t req)
1352{
1353 req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
1354 memset(n, 0, sizeof(BcNum));
1355 n->num = xmalloc(req);
1356 n->cap = req;
1357}
1358
1359static void bc_num_expand(BcNum *n, size_t req)
1360{
1361 req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
1362 if (req > n->cap) {
1363 n->num = xrealloc(n->num, req);
1364 n->cap = req;
1365 }
1366}
1367
1368static void bc_num_free(void *num)
1369{
1370 free(((BcNum *) num)->num);
1371}
1372
1373static void bc_num_copy(BcNum *d, BcNum *s)
1374{
1375 if (d != s) {
1376 bc_num_expand(d, s->cap);
1377 d->len = s->len;
1378 d->neg = s->neg;
1379 d->rdx = s->rdx;
1380 memcpy(d->num, s->num, sizeof(BcDig) * d->len);
1381 }
1382}
1383
1384static BcStatus bc_num_ulong(BcNum *n, unsigned long *result)
1385{
1386 size_t i;
1387 unsigned long pow;
1388
1389 if (n->neg) return bc_error("negative number");
1390
1391 for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) {
1392
1393 unsigned long prev = *result, powprev = pow;
1394
1395 *result += ((unsigned long) n->num[i]) * pow;
1396 pow *= 10;
1397
1398 if (*result < prev || pow < powprev)
1399 return bc_error("overflow");
1400 }
1401
1402 return BC_STATUS_SUCCESS;
1403}
1404
1405static void bc_num_ulong2num(BcNum *n, unsigned long val)
1406{
1407 size_t len;
1408 BcDig *ptr;
1409 unsigned long i;
1410
1411 bc_num_zero(n);
1412
1413 if (val == 0) return;
1414
1415 for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len);
1416 for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10;
1417}
1418
1354static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, 1419static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b,
1355 size_t len) 1420 size_t len)
1356{ 1421{
@@ -2343,39 +2408,6 @@ static BcStatus bc_num_stream(BcNum *n, BcNum *base, size_t *nchars, size_t len)
2343} 2408}
2344#endif 2409#endif
2345 2410
2346static void bc_num_init(BcNum *n, size_t req)
2347{
2348 req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2349 memset(n, 0, sizeof(BcNum));
2350 n->num = xmalloc(req);
2351 n->cap = req;
2352}
2353
2354static void bc_num_expand(BcNum *n, size_t req)
2355{
2356 req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
2357 if (req > n->cap) {
2358 n->num = xrealloc(n->num, req);
2359 n->cap = req;
2360 }
2361}
2362
2363static void bc_num_free(void *num)
2364{
2365 free(((BcNum *) num)->num);
2366}
2367
2368static void bc_num_copy(BcNum *d, BcNum *s)
2369{
2370 if (d != s) {
2371 bc_num_expand(d, s->cap);
2372 d->len = s->len;
2373 d->neg = s->neg;
2374 d->rdx = s->rdx;
2375 memcpy(d->num, s->num, sizeof(BcDig) * d->len);
2376 }
2377}
2378
2379static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, 2411static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base,
2380 size_t base_t) 2412 size_t base_t)
2381{ 2413{
@@ -2414,41 +2446,6 @@ static BcStatus bc_num_print(BcNum *n, BcNum *base, size_t base_t, bool newline,
2414 return s; 2446 return s;
2415} 2447}
2416 2448
2417static BcStatus bc_num_ulong(BcNum *n, unsigned long *result)
2418{
2419 size_t i;
2420 unsigned long pow;
2421
2422 if (n->neg) return bc_error("negative number");
2423
2424 for (*result = 0, pow = 1, i = n->rdx; i < n->len; ++i) {
2425
2426 unsigned long prev = *result, powprev = pow;
2427
2428 *result += ((unsigned long) n->num[i]) * pow;
2429 pow *= 10;
2430
2431 if (*result < prev || pow < powprev)
2432 return bc_error("overflow");
2433 }
2434
2435 return BC_STATUS_SUCCESS;
2436}
2437
2438static void bc_num_ulong2num(BcNum *n, unsigned long val)
2439{
2440 size_t len;
2441 BcDig *ptr;
2442 unsigned long i;
2443
2444 bc_num_zero(n);
2445
2446 if (val == 0) return;
2447
2448 for (len = 1, i = ULONG_MAX; i != 0; i /= 10, ++len) bc_num_expand(n, len);
2449 for (ptr = n->num, i = 0; val; ++i, ++n->len, val /= 10) ptr[i] = val % 10;
2450}
2451
2452static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) 2449static BcStatus bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
2453{ 2450{
2454 BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s; 2451 BcNumBinaryOp op = (!a->neg == !b->neg) ? bc_num_a : bc_num_s;
@@ -2712,6 +2709,8 @@ static void bc_func_free(void *func)
2712 bc_vec_free(&f->labels); 2709 bc_vec_free(&f->labels);
2713} 2710}
2714 2711
2712static void bc_array_expand(BcVec *a, size_t len);
2713
2715static void bc_array_init(BcVec *a, bool nums) 2714static void bc_array_init(BcVec *a, bool nums)
2716{ 2715{
2717 if (nums) 2716 if (nums)
@@ -2721,21 +2720,6 @@ static void bc_array_init(BcVec *a, bool nums)
2721 bc_array_expand(a, 1); 2720 bc_array_expand(a, 1);
2722} 2721}
2723 2722
2724static void bc_array_copy(BcVec *d, const BcVec *s)
2725{
2726 size_t i;
2727
2728 bc_vec_pop_all(d);
2729 bc_vec_expand(d, s->cap);
2730 d->len = s->len;
2731
2732 for (i = 0; i < s->len; ++i) {
2733 BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
2734 bc_num_init(dnum, snum->len);
2735 bc_num_copy(dnum, snum);
2736 }
2737}
2738
2739static void bc_array_expand(BcVec *a, size_t len) 2723static void bc_array_expand(BcVec *a, size_t len)
2740{ 2724{
2741 BcResultData data; 2725 BcResultData data;
@@ -2754,6 +2738,21 @@ static void bc_array_expand(BcVec *a, size_t len)
2754 } 2738 }
2755} 2739}
2756 2740
2741static void bc_array_copy(BcVec *d, const BcVec *s)
2742{
2743 size_t i;
2744
2745 bc_vec_pop_all(d);
2746 bc_vec_expand(d, s->cap);
2747 d->len = s->len;
2748
2749 for (i = 0; i < s->len; ++i) {
2750 BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
2751 bc_num_init(dnum, snum->len);
2752 bc_num_copy(dnum, snum);
2753 }
2754}
2755
2757static void bc_string_free(void *string) 2756static void bc_string_free(void *string)
2758{ 2757{
2759 free(*((char **) string)); 2758 free(*((char **) string));
@@ -6854,15 +6853,6 @@ static BcStatus bc_program_exec(void)
6854 return s; 6853 return s;
6855} 6854}
6856 6855
6857static void bc_vm_info(void)
6858{
6859 printf("%s "BB_VER"\n"
6860 "Copyright (c) 2018 Gavin D. Howard and contributors\n"
6861 "Report bugs at: https://github.com/gavinhoward/bc\n"
6862 "This is free software with ABSOLUTELY NO WARRANTY\n"
6863 , applet_name);
6864}
6865
6866#if ENABLE_BC 6856#if ENABLE_BC
6867static void bc_vm_envArgs(void) 6857static void bc_vm_envArgs(void)
6868{ 6858{