diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-24 05:00:36 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-24 05:00:36 +0100 |
| commit | 2097ac8d9e07320ff0f087bd6b3f6987aa02eb69 (patch) | |
| tree | f3ceccdc48fff7ea71263d0e05c060e2f126749e | |
| parent | a7732d11204d04f14ec69103128a3a6bec7d525d (diff) | |
| download | busybox-w32-2097ac8d9e07320ff0f087bd6b3f6987aa02eb69.tar.gz busybox-w32-2097ac8d9e07320ff0f087bd6b3f6987aa02eb69.tar.bz2 busybox-w32-2097ac8d9e07320ff0f087bd6b3f6987aa02eb69.zip | |
bc: move functions/macros around, no code changes
Order now is:
enums/structures/defines,
utility/common functions,
parsing,
execution,
main loop,
main()
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | miscutils/bc.c | 776 |
1 files changed, 392 insertions, 384 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 7d3b6b7ed..7a69a0816 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
| @@ -877,82 +877,9 @@ struct globals { | |||
| 877 | # define COMMA_SUCCESS ,BC_STATUS_SUCCESS | 877 | # define COMMA_SUCCESS ,BC_STATUS_SUCCESS |
| 878 | #endif | 878 | #endif |
| 879 | 879 | ||
| 880 | #define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) | 880 | // |
| 881 | #define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) | 881 | // Utility routines |
| 882 | 882 | // | |
| 883 | #define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) | ||
| 884 | #define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) | ||
| 885 | #define BC_NUM_INT(n) ((n)->len - (n)->rdx) | ||
| 886 | //#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) | ||
| 887 | static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b) | ||
| 888 | { | ||
| 889 | return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1; | ||
| 890 | } | ||
| 891 | //#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) | ||
| 892 | static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale) | ||
| 893 | { | ||
| 894 | return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1; | ||
| 895 | } | ||
| 896 | |||
| 897 | typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; | ||
| 898 | |||
| 899 | typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; | ||
| 900 | |||
| 901 | static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, | ||
| 902 | BcNumBinaryOp op, size_t req); | ||
| 903 | static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 904 | static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 905 | static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 906 | static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 907 | static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 908 | static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 909 | |||
| 910 | static FAST_FUNC BC_STATUS zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 911 | { | ||
| 912 | BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s; | ||
| 913 | (void) scale; | ||
| 914 | RETURN_STATUS(zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b))); | ||
| 915 | } | ||
| 916 | |||
| 917 | static FAST_FUNC BC_STATUS zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 918 | { | ||
| 919 | BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a; | ||
| 920 | (void) scale; | ||
| 921 | RETURN_STATUS(zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b))); | ||
| 922 | } | ||
| 923 | |||
| 924 | static FAST_FUNC BC_STATUS zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 925 | { | ||
| 926 | size_t req = BC_NUM_MREQ(a, b, scale); | ||
| 927 | RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_m, req)); | ||
| 928 | } | ||
| 929 | |||
| 930 | static FAST_FUNC BC_STATUS zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 931 | { | ||
| 932 | size_t req = BC_NUM_MREQ(a, b, scale); | ||
| 933 | RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_d, req)); | ||
| 934 | } | ||
| 935 | |||
| 936 | static FAST_FUNC BC_STATUS zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 937 | { | ||
| 938 | size_t req = BC_NUM_MREQ(a, b, scale); | ||
| 939 | RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_rem, req)); | ||
| 940 | } | ||
| 941 | |||
| 942 | static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 943 | { | ||
| 944 | RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1)); | ||
| 945 | } | ||
| 946 | |||
| 947 | static const BcNumBinaryOp zbc_program_ops[] = { | ||
| 948 | zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, | ||
| 949 | }; | ||
| 950 | #define zbc_num_add(...) (zbc_num_add(__VA_ARGS__) COMMA_SUCCESS) | ||
| 951 | #define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__) COMMA_SUCCESS) | ||
| 952 | #define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__) COMMA_SUCCESS) | ||
| 953 | #define zbc_num_div(...) (zbc_num_div(__VA_ARGS__) COMMA_SUCCESS) | ||
| 954 | #define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__) COMMA_SUCCESS) | ||
| 955 | #define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__) COMMA_SUCCESS) | ||
| 956 | 883 | ||
| 957 | static void fflush_and_check(void) | 884 | static void fflush_and_check(void) |
| 958 | { | 885 | { |
| @@ -1324,102 +1251,6 @@ static size_t bc_map_find_exact(const BcVec *v, const void *ptr) | |||
| 1324 | } | 1251 | } |
| 1325 | #endif | 1252 | #endif |
| 1326 | 1253 | ||
| 1327 | static int bad_input_byte(char c) | ||
| 1328 | { | ||
| 1329 | if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? | ||
| 1330 | || c > 0x7e | ||
| 1331 | ) { | ||
| 1332 | bc_error_fmt("illegal character 0x%02x", c); | ||
| 1333 | return 1; | ||
| 1334 | } | ||
| 1335 | return 0; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | // Note: it _appends_ data from fp to vec. | ||
| 1339 | static void bc_read_line(BcVec *vec, FILE *fp) | ||
| 1340 | { | ||
| 1341 | again: | ||
| 1342 | fflush_and_check(); | ||
| 1343 | |||
| 1344 | #if ENABLE_FEATURE_BC_SIGNALS | ||
| 1345 | if (G_interrupt) { // ^C was pressed | ||
| 1346 | intr: | ||
| 1347 | if (fp != stdin) { | ||
| 1348 | // ^C while running a script (bc SCRIPT): die. | ||
| 1349 | // We do not return to interactive prompt: | ||
| 1350 | // user might be running us from a shell, | ||
| 1351 | // and SCRIPT might be intended to terminate | ||
| 1352 | // (e.g. contain a "halt" stmt). | ||
| 1353 | // ^C dropping user into a bc prompt instead of | ||
| 1354 | // the shell would be unexpected. | ||
| 1355 | xfunc_die(); | ||
| 1356 | } | ||
| 1357 | // ^C while interactive input | ||
| 1358 | G_interrupt = 0; | ||
| 1359 | // GNU bc says "interrupted execution." | ||
| 1360 | // GNU dc says "Interrupt!" | ||
| 1361 | fputs("\ninterrupted execution\n", stderr); | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | # if ENABLE_FEATURE_EDITING | ||
| 1365 | if (G_ttyin && fp == stdin) { | ||
| 1366 | int n, i; | ||
| 1367 | # define line_buf bb_common_bufsiz1 | ||
| 1368 | n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); | ||
| 1369 | if (n <= 0) { // read errors or EOF, or ^D, or ^C | ||
| 1370 | if (n == 0) // ^C | ||
| 1371 | goto intr; | ||
| 1372 | bc_vec_pushZeroByte(vec); // ^D or EOF (or error) | ||
| 1373 | return; | ||
| 1374 | } | ||
| 1375 | i = 0; | ||
| 1376 | for (;;) { | ||
| 1377 | char c = line_buf[i++]; | ||
| 1378 | if (!c) break; | ||
| 1379 | if (bad_input_byte(c)) goto again; | ||
| 1380 | } | ||
| 1381 | bc_vec_concat(vec, line_buf); | ||
| 1382 | # undef line_buf | ||
| 1383 | } else | ||
| 1384 | # endif | ||
| 1385 | #endif | ||
| 1386 | { | ||
| 1387 | int c; | ||
| 1388 | bool bad_chars = 0; | ||
| 1389 | size_t len = vec->len; | ||
| 1390 | |||
| 1391 | do { | ||
| 1392 | #if ENABLE_FEATURE_BC_SIGNALS | ||
| 1393 | if (G_interrupt) { | ||
| 1394 | // ^C was pressed: ignore entire line, get another one | ||
| 1395 | vec->len = len; | ||
| 1396 | goto intr; | ||
| 1397 | } | ||
| 1398 | #endif | ||
| 1399 | do c = fgetc(fp); while (c == '\0'); | ||
| 1400 | if (c == EOF) { | ||
| 1401 | if (ferror(fp)) | ||
| 1402 | bb_perror_msg_and_die("input error"); | ||
| 1403 | // Note: EOF does not append '\n' | ||
| 1404 | break; | ||
| 1405 | } | ||
| 1406 | bad_chars |= bad_input_byte(c); | ||
| 1407 | bc_vec_pushByte(vec, (char)c); | ||
| 1408 | } while (c != '\n'); | ||
| 1409 | |||
| 1410 | if (bad_chars) { | ||
| 1411 | // Bad chars on this line | ||
| 1412 | if (!G.prog.file) { // stdin | ||
| 1413 | // ignore entire line, get another one | ||
| 1414 | vec->len = len; | ||
| 1415 | goto again; | ||
| 1416 | } | ||
| 1417 | bb_perror_msg_and_die("file '%s' is not text", G.prog.file); | ||
| 1418 | } | ||
| 1419 | bc_vec_pushZeroByte(vec); | ||
| 1420 | } | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | static void bc_num_setToZero(BcNum *n, size_t scale) | 1254 | static void bc_num_setToZero(BcNum *n, size_t scale) |
| 1424 | { | 1255 | { |
| 1425 | n->len = 0; | 1256 | n->len = 0; |
| @@ -1569,6 +1400,20 @@ static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len) | |||
| 1569 | } | 1400 | } |
| 1570 | } | 1401 | } |
| 1571 | 1402 | ||
| 1403 | #define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg)) | ||
| 1404 | #define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1) | ||
| 1405 | #define BC_NUM_INT(n) ((n)->len - (n)->rdx) | ||
| 1406 | //#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1) | ||
| 1407 | static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b) | ||
| 1408 | { | ||
| 1409 | return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1; | ||
| 1410 | } | ||
| 1411 | //#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1) | ||
| 1412 | static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale) | ||
| 1413 | { | ||
| 1414 | return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1; | ||
| 1415 | } | ||
| 1416 | |||
| 1572 | static ssize_t bc_num_cmp(BcNum *a, BcNum *b) | 1417 | static ssize_t bc_num_cmp(BcNum *a, BcNum *b) |
| 1573 | { | 1418 | { |
| 1574 | size_t i, min, a_int, b_int, diff; | 1419 | size_t i, min, a_int, b_int, diff; |
| @@ -1705,6 +1550,99 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places) | |||
| 1705 | } | 1550 | } |
| 1706 | #define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__) COMMA_SUCCESS) | 1551 | #define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__) COMMA_SUCCESS) |
| 1707 | 1552 | ||
| 1553 | typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC; | ||
| 1554 | |||
| 1555 | static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, | ||
| 1556 | BcNumBinaryOp op, size_t req) | ||
| 1557 | { | ||
| 1558 | BcStatus s; | ||
| 1559 | BcNum num2, *ptr_a, *ptr_b; | ||
| 1560 | bool init = false; | ||
| 1561 | |||
| 1562 | if (c == a) { | ||
| 1563 | ptr_a = &num2; | ||
| 1564 | memcpy(ptr_a, c, sizeof(BcNum)); | ||
| 1565 | init = true; | ||
| 1566 | } else | ||
| 1567 | ptr_a = a; | ||
| 1568 | |||
| 1569 | if (c == b) { | ||
| 1570 | ptr_b = &num2; | ||
| 1571 | if (c != a) { | ||
| 1572 | memcpy(ptr_b, c, sizeof(BcNum)); | ||
| 1573 | init = true; | ||
| 1574 | } | ||
| 1575 | } else | ||
| 1576 | ptr_b = b; | ||
| 1577 | |||
| 1578 | if (init) | ||
| 1579 | bc_num_init(c, req); | ||
| 1580 | else | ||
| 1581 | bc_num_expand(c, req); | ||
| 1582 | |||
| 1583 | s = BC_STATUS_SUCCESS; | ||
| 1584 | IF_ERROR_RETURN_POSSIBLE(s =) op(ptr_a, ptr_b, c, scale); | ||
| 1585 | |||
| 1586 | if (init) bc_num_free(&num2); | ||
| 1587 | |||
| 1588 | RETURN_STATUS(s); | ||
| 1589 | } | ||
| 1590 | #define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__) COMMA_SUCCESS) | ||
| 1591 | |||
| 1592 | static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 1593 | static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 1594 | static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 1595 | static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 1596 | static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 1597 | static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale); | ||
| 1598 | |||
| 1599 | static FAST_FUNC BC_STATUS zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 1600 | { | ||
| 1601 | BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s; | ||
| 1602 | (void) scale; | ||
| 1603 | RETURN_STATUS(zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b))); | ||
| 1604 | } | ||
| 1605 | |||
| 1606 | static FAST_FUNC BC_STATUS zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 1607 | { | ||
| 1608 | BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a; | ||
| 1609 | (void) scale; | ||
| 1610 | RETURN_STATUS(zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b))); | ||
| 1611 | } | ||
| 1612 | |||
| 1613 | static FAST_FUNC BC_STATUS zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 1614 | { | ||
| 1615 | size_t req = BC_NUM_MREQ(a, b, scale); | ||
| 1616 | RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_m, req)); | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | static FAST_FUNC BC_STATUS zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 1620 | { | ||
| 1621 | size_t req = BC_NUM_MREQ(a, b, scale); | ||
| 1622 | RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_d, req)); | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | static FAST_FUNC BC_STATUS zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 1626 | { | ||
| 1627 | size_t req = BC_NUM_MREQ(a, b, scale); | ||
| 1628 | RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_rem, req)); | ||
| 1629 | } | ||
| 1630 | |||
| 1631 | static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) | ||
| 1632 | { | ||
| 1633 | RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1)); | ||
| 1634 | } | ||
| 1635 | |||
| 1636 | static const BcNumBinaryOp zbc_program_ops[] = { | ||
| 1637 | zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub, | ||
| 1638 | }; | ||
| 1639 | #define zbc_num_add(...) (zbc_num_add(__VA_ARGS__) COMMA_SUCCESS) | ||
| 1640 | #define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__) COMMA_SUCCESS) | ||
| 1641 | #define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__) COMMA_SUCCESS) | ||
| 1642 | #define zbc_num_div(...) (zbc_num_div(__VA_ARGS__) COMMA_SUCCESS) | ||
| 1643 | #define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__) COMMA_SUCCESS) | ||
| 1644 | #define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__) COMMA_SUCCESS) | ||
| 1645 | |||
| 1708 | static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) | 1646 | static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale) |
| 1709 | { | 1647 | { |
| 1710 | BcNum one; | 1648 | BcNum one; |
| @@ -2224,195 +2162,6 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size | |||
| 2224 | } | 2162 | } |
| 2225 | #define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS) | 2163 | #define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS) |
| 2226 | 2164 | ||
| 2227 | static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, | ||
| 2228 | BcNumBinaryOp op, size_t req) | ||
| 2229 | { | ||
| 2230 | BcStatus s; | ||
| 2231 | BcNum num2, *ptr_a, *ptr_b; | ||
| 2232 | bool init = false; | ||
| 2233 | |||
| 2234 | if (c == a) { | ||
| 2235 | ptr_a = &num2; | ||
| 2236 | memcpy(ptr_a, c, sizeof(BcNum)); | ||
| 2237 | init = true; | ||
| 2238 | } else | ||
| 2239 | ptr_a = a; | ||
| 2240 | |||
| 2241 | if (c == b) { | ||
| 2242 | ptr_b = &num2; | ||
| 2243 | if (c != a) { | ||
| 2244 | memcpy(ptr_b, c, sizeof(BcNum)); | ||
| 2245 | init = true; | ||
| 2246 | } | ||
| 2247 | } else | ||
| 2248 | ptr_b = b; | ||
| 2249 | |||
| 2250 | if (init) | ||
| 2251 | bc_num_init(c, req); | ||
| 2252 | else | ||
| 2253 | bc_num_expand(c, req); | ||
| 2254 | |||
| 2255 | s = BC_STATUS_SUCCESS; | ||
| 2256 | IF_ERROR_RETURN_POSSIBLE(s =) op(ptr_a, ptr_b, c, scale); | ||
| 2257 | |||
| 2258 | if (init) bc_num_free(&num2); | ||
| 2259 | |||
| 2260 | RETURN_STATUS(s); | ||
| 2261 | } | ||
| 2262 | #define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__) COMMA_SUCCESS) | ||
| 2263 | |||
| 2264 | static bool bc_num_strValid(const char *val, size_t base) | ||
| 2265 | { | ||
| 2266 | BcDig b; | ||
| 2267 | bool radix; | ||
| 2268 | |||
| 2269 | b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); | ||
| 2270 | radix = false; | ||
| 2271 | for (;;) { | ||
| 2272 | BcDig c = *val++; | ||
| 2273 | if (c == '\0') | ||
| 2274 | break; | ||
| 2275 | if (c == '.') { | ||
| 2276 | if (radix) return false; | ||
| 2277 | radix = true; | ||
| 2278 | continue; | ||
| 2279 | } | ||
| 2280 | if (c < '0' || c >= b || (c > '9' && c < 'A')) | ||
| 2281 | return false; | ||
| 2282 | } | ||
| 2283 | return true; | ||
| 2284 | } | ||
| 2285 | |||
| 2286 | // Note: n is already "bc_num_zero()"ed, | ||
| 2287 | // leading zeroes in "val" are removed | ||
| 2288 | static void bc_num_parseDecimal(BcNum *n, const char *val) | ||
| 2289 | { | ||
| 2290 | size_t len, i; | ||
| 2291 | const char *ptr; | ||
| 2292 | |||
| 2293 | len = strlen(val); | ||
| 2294 | if (len == 0) | ||
| 2295 | return; | ||
| 2296 | |||
| 2297 | bc_num_expand(n, len); | ||
| 2298 | |||
| 2299 | ptr = strchr(val, '.'); | ||
| 2300 | |||
| 2301 | n->rdx = 0; | ||
| 2302 | if (ptr != NULL) | ||
| 2303 | n->rdx = (size_t)((val + len) - (ptr + 1)); | ||
| 2304 | |||
| 2305 | for (i = 0; val[i]; ++i) { | ||
| 2306 | if (val[i] != '0' && val[i] != '.') { | ||
| 2307 | // Not entirely zero value - convert it, and exit | ||
| 2308 | i = len - 1; | ||
| 2309 | for (;;) { | ||
| 2310 | n->num[n->len] = val[i] - '0'; | ||
| 2311 | ++n->len; | ||
| 2312 | skip_dot: | ||
| 2313 | if (i == 0) break; | ||
| 2314 | if (val[--i] == '.') goto skip_dot; | ||
| 2315 | } | ||
| 2316 | break; | ||
| 2317 | } | ||
| 2318 | } | ||
| 2319 | // if for() exits without hitting if(), the value is entirely zero | ||
| 2320 | } | ||
| 2321 | |||
| 2322 | // Note: n is already "bc_num_zero()"ed, | ||
| 2323 | // leading zeroes in "val" are removed | ||
| 2324 | static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) | ||
| 2325 | { | ||
| 2326 | BcStatus s; | ||
| 2327 | BcNum temp, mult, result; | ||
| 2328 | BcNum base; | ||
| 2329 | BcDig base_digs[ULONG_NUM_BUFSIZE]; | ||
| 2330 | BcDig c = '\0'; | ||
| 2331 | unsigned long v; | ||
| 2332 | size_t i, digits; | ||
| 2333 | |||
| 2334 | for (i = 0; ; ++i) { | ||
| 2335 | if (val[i] == '\0') | ||
| 2336 | return; | ||
| 2337 | if (val[i] != '.' && val[i] != '0') | ||
| 2338 | break; | ||
| 2339 | } | ||
| 2340 | |||
| 2341 | bc_num_init_DEF_SIZE(&temp); | ||
| 2342 | bc_num_init_DEF_SIZE(&mult); | ||
| 2343 | base.cap = ARRAY_SIZE(base_digs); | ||
| 2344 | base.num = base_digs; | ||
| 2345 | bc_num_ulong2num(&base, base_t); | ||
| 2346 | |||
| 2347 | for (;;) { | ||
| 2348 | c = *val++; | ||
| 2349 | if (c == '\0') goto int_err; | ||
| 2350 | if (c == '.') break; | ||
| 2351 | |||
| 2352 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | ||
| 2353 | |||
| 2354 | s = zbc_num_mul(n, &base, &mult, 0); | ||
| 2355 | if (s) goto int_err; | ||
| 2356 | bc_num_ulong2num(&temp, v); | ||
| 2357 | s = zbc_num_add(&mult, &temp, n, 0); | ||
| 2358 | if (s) goto int_err; | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | bc_num_init(&result, base.len); | ||
| 2362 | //bc_num_zero(&result); - already is | ||
| 2363 | bc_num_one(&mult); | ||
| 2364 | |||
| 2365 | digits = 0; | ||
| 2366 | for (;;) { | ||
| 2367 | c = *val++; | ||
| 2368 | if (c == '\0') break; | ||
| 2369 | digits++; | ||
| 2370 | |||
| 2371 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | ||
| 2372 | |||
| 2373 | s = zbc_num_mul(&result, &base, &result, 0); | ||
| 2374 | if (s) goto err; | ||
| 2375 | bc_num_ulong2num(&temp, v); | ||
| 2376 | s = zbc_num_add(&result, &temp, &result, 0); | ||
| 2377 | if (s) goto err; | ||
| 2378 | s = zbc_num_mul(&mult, &base, &mult, 0); | ||
| 2379 | if (s) goto err; | ||
| 2380 | } | ||
| 2381 | |||
| 2382 | s = zbc_num_div(&result, &mult, &result, digits); | ||
| 2383 | if (s) goto err; | ||
| 2384 | s = zbc_num_add(n, &result, n, digits); | ||
| 2385 | if (s) goto err; | ||
| 2386 | |||
| 2387 | if (n->len != 0) { | ||
| 2388 | if (n->rdx < digits) | ||
| 2389 | bc_num_extend(n, digits - n->rdx); | ||
| 2390 | } else | ||
| 2391 | bc_num_zero(n); | ||
| 2392 | err: | ||
| 2393 | bc_num_free(&result); | ||
| 2394 | int_err: | ||
| 2395 | bc_num_free(&mult); | ||
| 2396 | bc_num_free(&temp); | ||
| 2397 | } | ||
| 2398 | |||
| 2399 | static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) | ||
| 2400 | { | ||
| 2401 | if (!bc_num_strValid(val, base_t)) | ||
| 2402 | RETURN_STATUS(bc_error("bad number string")); | ||
| 2403 | |||
| 2404 | bc_num_zero(n); | ||
| 2405 | while (*val == '0') val++; | ||
| 2406 | |||
| 2407 | if (base_t == 10) | ||
| 2408 | bc_num_parseDecimal(n, val); | ||
| 2409 | else | ||
| 2410 | bc_num_parseBase(n, val, base_t); | ||
| 2411 | |||
| 2412 | RETURN_STATUS(BC_STATUS_SUCCESS); | ||
| 2413 | } | ||
| 2414 | #define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) | ||
| 2415 | |||
| 2416 | static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) | 2165 | static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) |
| 2417 | { | 2166 | { |
| 2418 | BcStatus s; | 2167 | BcStatus s; |
| @@ -2595,29 +2344,6 @@ static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) | |||
| 2595 | #define zdc_num_modexp(...) (zdc_num_modexp(__VA_ARGS__) COMMA_SUCCESS) | 2344 | #define zdc_num_modexp(...) (zdc_num_modexp(__VA_ARGS__) COMMA_SUCCESS) |
| 2596 | #endif // ENABLE_DC | 2345 | #endif // ENABLE_DC |
| 2597 | 2346 | ||
| 2598 | #if ENABLE_BC | ||
| 2599 | static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) | ||
| 2600 | { | ||
| 2601 | BcId *autoid; | ||
| 2602 | BcId a; | ||
| 2603 | size_t i; | ||
| 2604 | |||
| 2605 | autoid = (void*)f->autos.v; | ||
| 2606 | for (i = 0; i < f->autos.len; i++, autoid++) { | ||
| 2607 | if (strcmp(name, autoid->name) == 0) | ||
| 2608 | RETURN_STATUS(bc_error("function parameter or auto var has the same name as another")); | ||
| 2609 | } | ||
| 2610 | |||
| 2611 | a.idx = var; | ||
| 2612 | a.name = name; | ||
| 2613 | |||
| 2614 | bc_vec_push(&f->autos, &a); | ||
| 2615 | |||
| 2616 | RETURN_STATUS(BC_STATUS_SUCCESS); | ||
| 2617 | } | ||
| 2618 | #define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) | ||
| 2619 | #endif | ||
| 2620 | |||
| 2621 | static FAST_FUNC void bc_string_free(void *string) | 2347 | static FAST_FUNC void bc_string_free(void *string) |
| 2622 | { | 2348 | { |
| 2623 | free(*(char**)string); | 2349 | free(*(char**)string); |
| @@ -2740,6 +2466,258 @@ static FAST_FUNC void bc_result_free(void *result) | |||
| 2740 | } | 2466 | } |
| 2741 | } | 2467 | } |
| 2742 | 2468 | ||
| 2469 | static int bad_input_byte(char c) | ||
| 2470 | { | ||
| 2471 | if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? | ||
| 2472 | || c > 0x7e | ||
| 2473 | ) { | ||
| 2474 | bc_error_fmt("illegal character 0x%02x", c); | ||
| 2475 | return 1; | ||
| 2476 | } | ||
| 2477 | return 0; | ||
| 2478 | } | ||
| 2479 | |||
| 2480 | // Note: it _appends_ data from fp to vec. | ||
| 2481 | static void bc_read_line(BcVec *vec, FILE *fp) | ||
| 2482 | { | ||
| 2483 | again: | ||
| 2484 | fflush_and_check(); | ||
| 2485 | |||
| 2486 | #if ENABLE_FEATURE_BC_SIGNALS | ||
| 2487 | if (G_interrupt) { // ^C was pressed | ||
| 2488 | intr: | ||
| 2489 | if (fp != stdin) { | ||
| 2490 | // ^C while running a script (bc SCRIPT): die. | ||
| 2491 | // We do not return to interactive prompt: | ||
| 2492 | // user might be running us from a shell, | ||
| 2493 | // and SCRIPT might be intended to terminate | ||
| 2494 | // (e.g. contain a "halt" stmt). | ||
| 2495 | // ^C dropping user into a bc prompt instead of | ||
| 2496 | // the shell would be unexpected. | ||
| 2497 | xfunc_die(); | ||
| 2498 | } | ||
| 2499 | // ^C while interactive input | ||
| 2500 | G_interrupt = 0; | ||
| 2501 | // GNU bc says "interrupted execution." | ||
| 2502 | // GNU dc says "Interrupt!" | ||
| 2503 | fputs("\ninterrupted execution\n", stderr); | ||
| 2504 | } | ||
| 2505 | |||
| 2506 | # if ENABLE_FEATURE_EDITING | ||
| 2507 | if (G_ttyin && fp == stdin) { | ||
| 2508 | int n, i; | ||
| 2509 | # define line_buf bb_common_bufsiz1 | ||
| 2510 | n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); | ||
| 2511 | if (n <= 0) { // read errors or EOF, or ^D, or ^C | ||
| 2512 | if (n == 0) // ^C | ||
| 2513 | goto intr; | ||
| 2514 | bc_vec_pushZeroByte(vec); // ^D or EOF (or error) | ||
| 2515 | return; | ||
| 2516 | } | ||
| 2517 | i = 0; | ||
| 2518 | for (;;) { | ||
| 2519 | char c = line_buf[i++]; | ||
| 2520 | if (!c) break; | ||
| 2521 | if (bad_input_byte(c)) goto again; | ||
| 2522 | } | ||
| 2523 | bc_vec_concat(vec, line_buf); | ||
| 2524 | # undef line_buf | ||
| 2525 | } else | ||
| 2526 | # endif | ||
| 2527 | #endif | ||
| 2528 | { | ||
| 2529 | int c; | ||
| 2530 | bool bad_chars = 0; | ||
| 2531 | size_t len = vec->len; | ||
| 2532 | |||
| 2533 | do { | ||
| 2534 | #if ENABLE_FEATURE_BC_SIGNALS | ||
| 2535 | if (G_interrupt) { | ||
| 2536 | // ^C was pressed: ignore entire line, get another one | ||
| 2537 | vec->len = len; | ||
| 2538 | goto intr; | ||
| 2539 | } | ||
| 2540 | #endif | ||
| 2541 | do c = fgetc(fp); while (c == '\0'); | ||
| 2542 | if (c == EOF) { | ||
| 2543 | if (ferror(fp)) | ||
| 2544 | bb_perror_msg_and_die("input error"); | ||
| 2545 | // Note: EOF does not append '\n' | ||
| 2546 | break; | ||
| 2547 | } | ||
| 2548 | bad_chars |= bad_input_byte(c); | ||
| 2549 | bc_vec_pushByte(vec, (char)c); | ||
| 2550 | } while (c != '\n'); | ||
| 2551 | |||
| 2552 | if (bad_chars) { | ||
| 2553 | // Bad chars on this line | ||
| 2554 | if (!G.prog.file) { // stdin | ||
| 2555 | // ignore entire line, get another one | ||
| 2556 | vec->len = len; | ||
| 2557 | goto again; | ||
| 2558 | } | ||
| 2559 | bb_perror_msg_and_die("file '%s' is not text", G.prog.file); | ||
| 2560 | } | ||
| 2561 | bc_vec_pushZeroByte(vec); | ||
| 2562 | } | ||
| 2563 | } | ||
| 2564 | |||
| 2565 | // | ||
| 2566 | // Parsing routines | ||
| 2567 | // | ||
| 2568 | |||
| 2569 | static bool bc_num_strValid(const char *val, size_t base) | ||
| 2570 | { | ||
| 2571 | BcDig b; | ||
| 2572 | bool radix; | ||
| 2573 | |||
| 2574 | b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); | ||
| 2575 | radix = false; | ||
| 2576 | for (;;) { | ||
| 2577 | BcDig c = *val++; | ||
| 2578 | if (c == '\0') | ||
| 2579 | break; | ||
| 2580 | if (c == '.') { | ||
| 2581 | if (radix) return false; | ||
| 2582 | radix = true; | ||
| 2583 | continue; | ||
| 2584 | } | ||
| 2585 | if (c < '0' || c >= b || (c > '9' && c < 'A')) | ||
| 2586 | return false; | ||
| 2587 | } | ||
| 2588 | return true; | ||
| 2589 | } | ||
| 2590 | |||
| 2591 | // Note: n is already "bc_num_zero()"ed, | ||
| 2592 | // leading zeroes in "val" are removed | ||
| 2593 | static void bc_num_parseDecimal(BcNum *n, const char *val) | ||
| 2594 | { | ||
| 2595 | size_t len, i; | ||
| 2596 | const char *ptr; | ||
| 2597 | |||
| 2598 | len = strlen(val); | ||
| 2599 | if (len == 0) | ||
| 2600 | return; | ||
| 2601 | |||
| 2602 | bc_num_expand(n, len); | ||
| 2603 | |||
| 2604 | ptr = strchr(val, '.'); | ||
| 2605 | |||
| 2606 | n->rdx = 0; | ||
| 2607 | if (ptr != NULL) | ||
| 2608 | n->rdx = (size_t)((val + len) - (ptr + 1)); | ||
| 2609 | |||
| 2610 | for (i = 0; val[i]; ++i) { | ||
| 2611 | if (val[i] != '0' && val[i] != '.') { | ||
| 2612 | // Not entirely zero value - convert it, and exit | ||
| 2613 | i = len - 1; | ||
| 2614 | for (;;) { | ||
| 2615 | n->num[n->len] = val[i] - '0'; | ||
| 2616 | ++n->len; | ||
| 2617 | skip_dot: | ||
| 2618 | if (i == 0) break; | ||
| 2619 | if (val[--i] == '.') goto skip_dot; | ||
| 2620 | } | ||
| 2621 | break; | ||
| 2622 | } | ||
| 2623 | } | ||
| 2624 | // if for() exits without hitting if(), the value is entirely zero | ||
| 2625 | } | ||
| 2626 | |||
| 2627 | // Note: n is already "bc_num_zero()"ed, | ||
| 2628 | // leading zeroes in "val" are removed | ||
| 2629 | static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t) | ||
| 2630 | { | ||
| 2631 | BcStatus s; | ||
| 2632 | BcNum temp, mult, result; | ||
| 2633 | BcNum base; | ||
| 2634 | BcDig base_digs[ULONG_NUM_BUFSIZE]; | ||
| 2635 | BcDig c = '\0'; | ||
| 2636 | unsigned long v; | ||
| 2637 | size_t i, digits; | ||
| 2638 | |||
| 2639 | for (i = 0; ; ++i) { | ||
| 2640 | if (val[i] == '\0') | ||
| 2641 | return; | ||
| 2642 | if (val[i] != '.' && val[i] != '0') | ||
| 2643 | break; | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | bc_num_init_DEF_SIZE(&temp); | ||
| 2647 | bc_num_init_DEF_SIZE(&mult); | ||
| 2648 | base.cap = ARRAY_SIZE(base_digs); | ||
| 2649 | base.num = base_digs; | ||
| 2650 | bc_num_ulong2num(&base, base_t); | ||
| 2651 | |||
| 2652 | for (;;) { | ||
| 2653 | c = *val++; | ||
| 2654 | if (c == '\0') goto int_err; | ||
| 2655 | if (c == '.') break; | ||
| 2656 | |||
| 2657 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | ||
| 2658 | |||
| 2659 | s = zbc_num_mul(n, &base, &mult, 0); | ||
| 2660 | if (s) goto int_err; | ||
| 2661 | bc_num_ulong2num(&temp, v); | ||
| 2662 | s = zbc_num_add(&mult, &temp, n, 0); | ||
| 2663 | if (s) goto int_err; | ||
| 2664 | } | ||
| 2665 | |||
| 2666 | bc_num_init(&result, base.len); | ||
| 2667 | //bc_num_zero(&result); - already is | ||
| 2668 | bc_num_one(&mult); | ||
| 2669 | |||
| 2670 | digits = 0; | ||
| 2671 | for (;;) { | ||
| 2672 | c = *val++; | ||
| 2673 | if (c == '\0') break; | ||
| 2674 | digits++; | ||
| 2675 | |||
| 2676 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | ||
| 2677 | |||
| 2678 | s = zbc_num_mul(&result, &base, &result, 0); | ||
| 2679 | if (s) goto err; | ||
| 2680 | bc_num_ulong2num(&temp, v); | ||
| 2681 | s = zbc_num_add(&result, &temp, &result, 0); | ||
| 2682 | if (s) goto err; | ||
| 2683 | s = zbc_num_mul(&mult, &base, &mult, 0); | ||
| 2684 | if (s) goto err; | ||
| 2685 | } | ||
| 2686 | |||
| 2687 | s = zbc_num_div(&result, &mult, &result, digits); | ||
| 2688 | if (s) goto err; | ||
| 2689 | s = zbc_num_add(n, &result, n, digits); | ||
| 2690 | if (s) goto err; | ||
| 2691 | |||
| 2692 | if (n->len != 0) { | ||
| 2693 | if (n->rdx < digits) | ||
| 2694 | bc_num_extend(n, digits - n->rdx); | ||
| 2695 | } else | ||
| 2696 | bc_num_zero(n); | ||
| 2697 | err: | ||
| 2698 | bc_num_free(&result); | ||
| 2699 | int_err: | ||
| 2700 | bc_num_free(&mult); | ||
| 2701 | bc_num_free(&temp); | ||
| 2702 | } | ||
| 2703 | |||
| 2704 | static BC_STATUS zbc_num_parse(BcNum *n, const char *val, unsigned base_t) | ||
| 2705 | { | ||
| 2706 | if (!bc_num_strValid(val, base_t)) | ||
| 2707 | RETURN_STATUS(bc_error("bad number string")); | ||
| 2708 | |||
| 2709 | bc_num_zero(n); | ||
| 2710 | while (*val == '0') val++; | ||
| 2711 | |||
| 2712 | if (base_t == 10) | ||
| 2713 | bc_num_parseDecimal(n, val); | ||
| 2714 | else | ||
| 2715 | bc_num_parseBase(n, val, base_t); | ||
| 2716 | |||
| 2717 | RETURN_STATUS(BC_STATUS_SUCCESS); | ||
| 2718 | } | ||
| 2719 | #define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__) COMMA_SUCCESS) | ||
| 2720 | |||
| 2743 | static void bc_lex_lineComment(BcLex *l) | 2721 | static void bc_lex_lineComment(BcLex *l) |
| 2744 | { | 2722 | { |
| 2745 | // Try: echo -n '#foo' | bc | 2723 | // Try: echo -n '#foo' | bc |
| @@ -4333,6 +4311,27 @@ static BC_STATUS zbc_parse_break_or_continue(BcParse *p, BcLexType type) | |||
| 4333 | } | 4311 | } |
| 4334 | #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) | 4312 | #define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS) |
| 4335 | 4313 | ||
| 4314 | static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var) | ||
| 4315 | { | ||
| 4316 | BcId *autoid; | ||
| 4317 | BcId a; | ||
| 4318 | size_t i; | ||
| 4319 | |||
| 4320 | autoid = (void*)f->autos.v; | ||
| 4321 | for (i = 0; i < f->autos.len; i++, autoid++) { | ||
| 4322 | if (strcmp(name, autoid->name) == 0) | ||
| 4323 | RETURN_STATUS(bc_error("function parameter or auto var has the same name as another")); | ||
| 4324 | } | ||
| 4325 | |||
| 4326 | a.idx = var; | ||
| 4327 | a.name = name; | ||
| 4328 | |||
| 4329 | bc_vec_push(&f->autos, &a); | ||
| 4330 | |||
| 4331 | RETURN_STATUS(BC_STATUS_SUCCESS); | ||
| 4332 | } | ||
| 4333 | #define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS) | ||
| 4334 | |||
| 4336 | static BC_STATUS zbc_parse_funcdef(BcParse *p) | 4335 | static BC_STATUS zbc_parse_funcdef(BcParse *p) |
| 4337 | { | 4336 | { |
| 4338 | BcStatus s; | 4337 | BcStatus s; |
| @@ -5010,6 +5009,13 @@ static BC_STATUS zdc_parse_exprs_until_eof(BcParse *p) | |||
| 5010 | 5009 | ||
| 5011 | #endif // ENABLE_DC | 5010 | #endif // ENABLE_DC |
| 5012 | 5011 | ||
| 5012 | // | ||
| 5013 | // Execution engine | ||
| 5014 | // | ||
| 5015 | |||
| 5016 | #define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n))) | ||
| 5017 | #define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n))) | ||
| 5018 | |||
| 5013 | static BcVec* bc_program_search(char *id, bool var) | 5019 | static BcVec* bc_program_search(char *id, bool var) |
| 5014 | { | 5020 | { |
| 5015 | BcId e, *ptr; | 5021 | BcId e, *ptr; |
| @@ -5400,6 +5406,8 @@ static void bc_num_printDecimal(BcNum *n) | |||
| 5400 | bc_num_printHex((size_t) n->num[i], 1, i == rdx); | 5406 | bc_num_printHex((size_t) n->num[i], 1, i == rdx); |
| 5401 | } | 5407 | } |
| 5402 | 5408 | ||
| 5409 | typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC; | ||
| 5410 | |||
| 5403 | static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNumDigitOp print) | 5411 | static BC_STATUS zbc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNumDigitOp print) |
| 5404 | { | 5412 | { |
| 5405 | BcStatus s; | 5413 | BcStatus s; |
