bc: convert arithmetic calc functions to "z" logic
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 11 Dec 2018 18:04:44 +0000 (19:04 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 11 Dec 2018 18:22:04 +0000 (19:22 +0100)
In order for magic macros to work, a bit of reordering was necessary.

function                                             old     new   delta
zbc_program_modexp                                     -     558    +558
zbc_program_assign                                     -     448    +448
zbc_program_pushArray                                  -     111    +111
zbc_num_s                                            239     237      -2
zbc_num_d                                            543     541      -2
zbc_num_binary                                       145     143      -2
zbc_num_a                                            443     441      -2
zbc_num_rem                                           95      91      -4
zbc_num_divmod                                       150     146      -4
zbc_num_m                                            269     257     -12
zbc_num_r                                            230     208     -22
zbc_num_printNum                                     447     417     -30
bc_program_exec                                     3960    3928     -32
zbc_num_p                                            434     399     -35
zbc_program_num                                      880     840     -40
zbc_num_k                                            913     852     -61
zbc_program_printStream                              141       -    -141
bc_program_assign                                    455       -    -455
bc_program_modexp                                    668       -    -668
------------------------------------------------------------------------------
(add/remove: 3/3 grow/shrink: 0/13 up/down: 1117/-1512)      Total: -395 bytes
   text    data     bss     dec     hex filename
 982632     485    7296  990413   f1ccd busybox_old
 982237     485    7296  990018   f1b42 busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
miscutils/bc.c

index 3ab0bf3b78c2fa7bc7abf992edfd69bf7046301b..5ede8598df0828a8edfaf5722475fde207e00ec3 100644 (file)
@@ -929,35 +929,94 @@ dc_parse_insts[] = {
 // ("always returning zero") prefix, i.e. zbc_foo or zdc_foo.
 //
 #if ENABLE_FEATURE_BC_SIGNALS || ENABLE_FEATURE_CLEAN_UP
+# define ERRORS_ARE_FATAL 0
 # define ERRORFUNC        /*nothing*/
 # define ERROR_RETURN(a)  a
-# define ERRORS_ARE_FATAL 0
 # define BC_STATUS        BcStatus
 # define RETURN_STATUS(v) return (v)
 #else
+# define ERRORS_ARE_FATAL 1
 # define ERRORFUNC        NORETURN
 # define ERROR_RETURN(a)  /*nothing*/
-# define ERRORS_ARE_FATAL 1
 # define BC_STATUS        void
 # define RETURN_STATUS(v) do { ((void)(v)); return; } while (0)
 #endif
 
+#define BC_NUM_NEG(n, neg)      ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
+#define BC_NUM_ONE(n)           ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
+#define BC_NUM_INT(n)           ((n)->len - (n)->rdx)
+//#define BC_NUM_AREQ(a, b)       (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1)
+static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b)
+{
+       return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1;
+}
+//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1)
+static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale)
+{
+       return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1;
+}
+
 typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC;
 
-typedef BcStatus (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC;
+typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC;
 
-static BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC;
-static BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC;
-static BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC;
-static BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC;
-static BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC;
-static BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) FAST_FUNC;
-static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
-                              size_t scale);
+static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
+                       BcNumBinaryOp op, size_t req);
+static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
+static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
+static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
+static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
+static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
+static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
+
+static FAST_FUNC BC_STATUS zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
+{
+       BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s;
+       (void) scale;
+       RETURN_STATUS(zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b)));
+}
+
+static FAST_FUNC BC_STATUS zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale)
+{
+       BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a;
+       (void) scale;
+       RETURN_STATUS(zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b)));
+}
+
+static FAST_FUNC BC_STATUS zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale)
+{
+       size_t req = BC_NUM_MREQ(a, b, scale);
+       RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_m, req));
+}
+
+static FAST_FUNC BC_STATUS zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale)
+{
+       size_t req = BC_NUM_MREQ(a, b, scale);
+       RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_d, req));
+}
+
+static FAST_FUNC BC_STATUS zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale)
+{
+       size_t req = BC_NUM_MREQ(a, b, scale);
+       RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_rem, req));
+}
+
+static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale)
+{
+       RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1));
+}
 
 static const BcNumBinaryOp zbc_program_ops[] = {
        zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub,
 };
+#if ERRORS_ARE_FATAL
+# define zbc_num_add(...) (zbc_num_add(__VA_ARGS__), BC_STATUS_SUCCESS)
+# define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__), BC_STATUS_SUCCESS)
+# define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__), BC_STATUS_SUCCESS)
+# define zbc_num_div(...) (zbc_num_div(__VA_ARGS__), BC_STATUS_SUCCESS)
+# define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__), BC_STATUS_SUCCESS)
+# define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
 static void fflush_and_check(void)
 {
@@ -1527,20 +1586,6 @@ static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b,
        }
 }
 
-#define BC_NUM_NEG(n, neg)      ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
-#define BC_NUM_ONE(n)           ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
-#define BC_NUM_INT(n)           ((n)->len - (n)->rdx)
-//#define BC_NUM_AREQ(a, b)       (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1)
-static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b)
-{
-       return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1;
-}
-//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1)
-static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale)
-{
-       return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1;
-}
-
 static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len)
 {
        size_t i;
@@ -1692,7 +1737,7 @@ static BC_STATUS zbc_num_shift(BcNum *n, size_t places)
 # define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__), BC_STATUS_SUCCESS)
 #endif
 
-static BcStatus zbc_num_inv(BcNum *a, BcNum *b, size_t scale)
+static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale)
 {
        BcNum one;
        BcDig num[2];
@@ -1701,10 +1746,13 @@ static BcStatus zbc_num_inv(BcNum *a, BcNum *b, size_t scale)
        one.num = num;
        bc_num_one(&one);
 
-       return zbc_num_div(&one, a, b, scale);
+       RETURN_STATUS(zbc_num_div(&one, a, b, scale));
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_inv(...) (zbc_num_inv(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
-static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
+static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
 {
        BcDig *ptr, *ptr_a, *ptr_b, *ptr_c;
        size_t i, max, min_rdx, min_int, diff, a_int, b_int;
@@ -1716,11 +1764,11 @@ static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_
        if (a->len == 0) {
                bc_num_copy(c, b);
                if (sub && c->len) c->neg = !c->neg;
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
-       else if (b->len == 0) {
+       if (b->len == 0) {
                bc_num_copy(c, a);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
 
        c->neg = a->neg;
@@ -1772,10 +1820,10 @@ static FAST_FUNC BcStatus zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_
 
        if (carry != 0) c->num[c->len++] = (BcDig) carry;
 
-       return BC_STATUS_SUCCESS; // can't make void, see zbc_num_binary()
+       RETURN_STATUS(BC_STATUS_SUCCESS); // can't make void, see zbc_num_binary()
 }
 
-static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
+static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
 {
        ssize_t cmp;
        BcNum *minuend, *subtrahend;
@@ -1788,11 +1836,11 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_
        if (a->len == 0) {
                bc_num_copy(c, b);
                if (sub && c->len) c->neg = !c->neg;
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
-       else if (b->len == 0) {
+       if (b->len == 0) {
                bc_num_copy(c, a);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
 
        aneg = a->neg;
@@ -1806,9 +1854,9 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_
 
        if (cmp == 0) {
                bc_num_setToZero(c, BC_MAX(a->rdx, b->rdx));
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
-       else if (cmp > 0) {
+       if (cmp > 0) {
                neg = a->neg;
                minuend = a;
                subtrahend = b;
@@ -1834,11 +1882,14 @@ static FAST_FUNC BcStatus zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_
 
        bc_num_clean(c);
 
-       return BC_STATUS_SUCCESS; // can't make void, see zbc_num_binary()
+       RETURN_STATUS(BC_STATUS_SUCCESS); // can't make void, see zbc_num_binary()
 }
 
-static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b,
+static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b,
                          BcNum *restrict c)
+#if ERRORS_ARE_FATAL
+# define zbc_num_k(...) (zbc_num_k(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 {
        BcStatus s;
        size_t max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2;
@@ -1847,12 +1898,12 @@ static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b,
 
        if (a->len == 0 || b->len == 0) {
                bc_num_zero(c);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
        aone = BC_NUM_ONE(a);
        if (aone || BC_NUM_ONE(b)) {
                bc_num_copy(c, aone ? b : a);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
 
        if (a->len + b->len < BC_NUM_KARATSUBA_LEN ||
@@ -1880,14 +1931,16 @@ static FAST_FUNC BcStatus zbc_num_k(BcNum *restrict a, BcNum *restrict b,
                        c->num[i + j] += (BcDig) carry;
                        len = BC_MAX(len, i + j + !!carry);
 
+#if ENABLE_FEATURE_BC_SIGNALS
                        // a=2^1000000
                        // a*a <- without check below, this will not be interruptible
                        if (G_interrupt) return BC_STATUS_FAILURE;
+#endif
                }
 
                c->len = len;
 
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
 
        bc_num_init(&l1, max);
@@ -1940,10 +1993,10 @@ err:
        bc_num_free(&l2);
        bc_num_free(&h1);
        bc_num_free(&l1);
-       return s;
+       RETURN_STATUS(s);
 }
 
-static FAST_FUNC BcStatus zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
+static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
 {
        BcStatus s;
        BcNum cpa, cpb;
@@ -1982,10 +2035,13 @@ static FAST_FUNC BcStatus zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_
 err:
        bc_num_free(&cpb);
        bc_num_free(&cpa);
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_m(...) (zbc_num_m(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
-static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
+static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
 {
        BcStatus s = BC_STATUS_SUCCESS;
        BcDig *n, *p, q;
@@ -1994,15 +2050,15 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_
        bool zero = true;
 
        if (b->len == 0)
-               return bc_error("divide by zero");
-       else if (a->len == 0) {
+               RETURN_STATUS(bc_error("divide by zero"));
+       if (a->len == 0) {
                bc_num_setToZero(c, scale);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
-       else if (BC_NUM_ONE(b)) {
+       if (BC_NUM_ONE(b)) {
                bc_num_copy(c, a);
                bc_num_retireMul(c, scale, a->neg, b->neg);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
 
        bc_num_init(&cp, BC_NUM_MREQ(a, b, scale));
@@ -2042,6 +2098,7 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_
                for (q = 0; (!s && n[len] != 0) || bc_num_compare(n, p, len) >= 0; ++q)
                        bc_num_subArrays(n, p, len);
                c->num[i] = q;
+#if ENABLE_FEATURE_BC_SIGNALS
                // a=2^100000
                // scale=40000
                // 1/a <- without check below, this will not be interruptible
@@ -2049,15 +2106,19 @@ static FAST_FUNC BcStatus zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_
                        s = BC_STATUS_FAILURE;
                        break;
                }
+#endif
        }
 
        bc_num_retireMul(c, scale, a->neg, b->neg);
        bc_num_free(&cp);
 
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_d(...) (zbc_num_d(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
-static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
+static FAST_FUNC BC_STATUS zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
                          BcNum *restrict d, size_t scale, size_t ts)
 {
        BcStatus s;
@@ -2065,11 +2126,11 @@ static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
        bool neg;
 
        if (b->len == 0)
-               return bc_error("divide by zero");
+               RETURN_STATUS(bc_error("divide by zero"));
 
        if (a->len == 0) {
                bc_num_setToZero(d, ts);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
 
        bc_num_init(&temp, d->cap);
@@ -2091,10 +2152,13 @@ static FAST_FUNC BcStatus zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
 
 err:
        bc_num_free(&temp);
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_r(...) (zbc_num_r(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
-static FAST_FUNC BcStatus zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
+static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
 {
        BcStatus s;
        BcNum c1;
@@ -2104,10 +2168,13 @@ static FAST_FUNC BcStatus zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, siz
        s = zbc_num_r(a, b, &c1, c, scale, ts);
        bc_num_free(&c1);
 
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_rem(...) (zbc_num_rem(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
-static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
+static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
 {
        BcStatus s = BC_STATUS_SUCCESS;
        BcNum copy;
@@ -2115,29 +2182,29 @@ static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_
        size_t i, powrdx, resrdx;
        bool neg, zero;
 
-       if (b->rdx) return bc_error("non integer number");
+       if (b->rdx) RETURN_STATUS(bc_error("non integer number"));
 
        if (b->len == 0) {
                bc_num_one(c);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
-       else if (a->len == 0) {
+       if (a->len == 0) {
                bc_num_setToZero(c, scale);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
-       else if (BC_NUM_ONE(b)) {
+       if (BC_NUM_ONE(b)) {
                if (!b->neg)
                        bc_num_copy(c, a);
                else
                        s = zbc_num_inv(a, c, scale);
-               return s;
+               RETURN_STATUS(s);
        }
 
        neg = b->neg;
        b->neg = false;
 
        s = zbc_num_ulong(b, &pow);
-       if (s) return s;
+       if (s) RETURN_STATUS(s);
 
        bc_num_init(&copy, a->len);
        bc_num_copy(&copy, a);
@@ -2195,10 +2262,13 @@ static FAST_FUNC BcStatus zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_
 
 err:
        bc_num_free(&copy);
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_p(...) (zbc_num_p(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
-static BcStatus zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
+static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
                               BcNumBinaryOp op, size_t req)
 {
        BcStatus s;
@@ -2228,183 +2298,19 @@ static BcStatus zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
        else
                bc_num_expand(c, req);
 
+#if !ERRORS_ARE_FATAL
        s = op(ptr_a, ptr_b, c, scale);
-
-       if (init) bc_num_free(&num2);
-
-       return s;
-}
-
-static void bc_num_printNewline(void)
-{
-       if (G.prog.nchars == G.prog.len - 1) {
-               bb_putchar('\\');
-               bb_putchar('\n');
-               G.prog.nchars = 0;
-       }
-}
-
-#if ENABLE_DC
-static FAST_FUNC void bc_num_printChar(size_t num, size_t width, bool radix)
-{
-       (void) radix;
-       bb_putchar((char) num);
-       G.prog.nchars += width;
-}
-#endif
-
-static FAST_FUNC void bc_num_printDigits(size_t num, size_t width, bool radix)
-{
-       size_t exp, pow;
-
-       bc_num_printNewline();
-       bb_putchar(radix ? '.' : ' ');
-       ++G.prog.nchars;
-
-       bc_num_printNewline();
-       for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10)
-               continue;
-
-       for (exp = 0; exp < width; pow /= 10, ++G.prog.nchars, ++exp) {
-               size_t dig;
-               bc_num_printNewline();
-               dig = num / pow;
-               num -= dig * pow;
-               bb_putchar(((char) dig) + '0');
-       }
-}
-
-static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix)
-{
-       if (radix) {
-               bc_num_printNewline();
-               bb_putchar('.');
-               G.prog.nchars += 1;
-       }
-
-       bc_num_printNewline();
-       bb_putchar(bb_hexdigits_upcase[num]);
-       G.prog.nchars += width;
-}
-
-static void bc_num_printDecimal(BcNum *n)
-{
-       size_t i, rdx = n->rdx - 1;
-
-       if (n->neg) bb_putchar('-');
-       G.prog.nchars += n->neg;
-
-       for (i = n->len - 1; i < n->len; --i)
-               bc_num_printHex((size_t) n->num[i], 1, i == rdx);
-}
-
-static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print)
-{
-       BcStatus s;
-       BcVec stack;
-       BcNum intp, fracp, digit, frac_len;
-       unsigned long dig, *ptr;
-       size_t i;
-       bool radix;
-
-       if (n->len == 0) {
-               print(0, width, false);
-               RETURN_STATUS(BC_STATUS_SUCCESS);
-       }
-
-       bc_vec_init(&stack, sizeof(long), NULL);
-       bc_num_init(&intp, n->len);
-       bc_num_init(&fracp, n->rdx);
-       bc_num_init(&digit, width);
-       bc_num_init(&frac_len, BC_NUM_INT(n));
-       bc_num_copy(&intp, n);
-       bc_num_one(&frac_len);
-
-       bc_num_truncate(&intp, intp.rdx);
-       s = zbc_num_sub(n, &intp, &fracp, 0);
-       if (s) goto err;
-
-       while (intp.len != 0) {
-               s = zbc_num_divmod(&intp, base, &intp, &digit, 0);
-               if (s) goto err;
-               s = zbc_num_ulong(&digit, &dig);
-               if (s) goto err;
-               bc_vec_push(&stack, &dig);
-       }
-
-       for (i = 0; i < stack.len; ++i) {
-               ptr = bc_vec_item_rev(&stack, i);
-               print(*ptr, width, false);
-       }
-
-       if (!n->rdx) goto err;
-
-       for (radix = true; frac_len.len <= n->rdx; radix = false) {
-               s = zbc_num_mul(&fracp, base, &fracp, n->rdx);
-               if (s) goto err;
-               s = zbc_num_ulong(&fracp, &dig);
-               if (s) goto err;
-               bc_num_ulong2num(&intp, dig);
-               s = zbc_num_sub(&fracp, &intp, &fracp, 0);
-               if (s) goto err;
-               print(dig, width, radix);
-               s = zbc_num_mul(&frac_len, base, &frac_len, 0);
-               if (s) goto err;
-       }
-
-err:
-       bc_num_free(&frac_len);
-       bc_num_free(&digit);
-       bc_num_free(&fracp);
-       bc_num_free(&intp);
-       bc_vec_free(&stack);
-       RETURN_STATUS(s);
-}
-#if ERRORS_ARE_FATAL
-# define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS)
+#else
+       op(ptr_a, ptr_b, c, scale);
+       s = BC_STATUS_SUCCESS;
 #endif
 
-static BC_STATUS zbc_num_printBase(BcNum *n)
-{
-       BcStatus s;
-       size_t width, i;
-       BcNumDigitOp print;
-       bool neg = n->neg;
-
-       if (neg) {
-               bb_putchar('-');
-               G.prog.nchars++;
-       }
-
-       n->neg = false;
-
-       if (G.prog.ob_t <= BC_NUM_MAX_IBASE) {
-               width = 1;
-               print = bc_num_printHex;
-       }
-       else {
-               for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width)
-                       continue;
-               print = bc_num_printDigits;
-       }
-
-       s = zbc_num_printNum(n, &G.prog.ob, width, print);
-       n->neg = neg;
+       if (init) bc_num_free(&num2);
 
        RETURN_STATUS(s);
 }
 #if ERRORS_ARE_FATAL
-# define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS)
-#endif
-
-#if ENABLE_DC
-static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base)
-{
-       RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar));
-}
-#if ERRORS_ARE_FATAL
-# define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS)
-#endif
+# define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__), BC_STATUS_SUCCESS)
 #endif
 
 static bool bc_num_strValid(const char *val, size_t base)
@@ -2557,70 +2463,7 @@ static BC_STATUS zbc_num_parse(BcNum *n, const char *val, BcNum *base,
 # define zbc_num_parse(...) (zbc_num_parse(__VA_ARGS__), BC_STATUS_SUCCESS)
 #endif
 
-static BC_STATUS zbc_num_print(BcNum *n, bool newline)
-{
-       BcStatus s = BC_STATUS_SUCCESS;
-
-       bc_num_printNewline();
-
-       if (n->len == 0) {
-               bb_putchar('0');
-               ++G.prog.nchars;
-       }
-       else if (G.prog.ob_t == 10)
-               bc_num_printDecimal(n);
-       else
-               s = zbc_num_printBase(n);
-
-       if (newline) {
-               bb_putchar('\n');
-               G.prog.nchars = 0;
-       }
-
-       RETURN_STATUS(s);
-}
-#if ERRORS_ARE_FATAL
-# define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS)
-#endif
-
-static FAST_FUNC BcStatus zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
-{
-       BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s;
-       (void) scale;
-       return zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b));
-}
-
-static FAST_FUNC BcStatus zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale)
-{
-       BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a;
-       (void) scale;
-       return zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b));
-}
-
-static FAST_FUNC BcStatus zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale)
-{
-       size_t req = BC_NUM_MREQ(a, b, scale);
-       return zbc_num_binary(a, b, c, scale, zbc_num_m, req);
-}
-
-static FAST_FUNC BcStatus zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale)
-{
-       size_t req = BC_NUM_MREQ(a, b, scale);
-       return zbc_num_binary(a, b, c, scale, zbc_num_d, req);
-}
-
-static FAST_FUNC BcStatus zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale)
-{
-       size_t req = BC_NUM_MREQ(a, b, scale);
-       return zbc_num_binary(a, b, c, scale, zbc_num_rem, req);
-}
-
-static FAST_FUNC BcStatus zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale)
-{
-       return zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1);
-}
-
-static BcStatus zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
+static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
 {
        BcStatus s;
        BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
@@ -2632,14 +2475,14 @@ static BcStatus zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
 
        if (a->len == 0) {
                bc_num_setToZero(b, scale);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
        else if (a->neg)
-               return bc_error("negative number");
+               RETURN_STATUS(bc_error("negative number"));
        else if (BC_NUM_ONE(a)) {
                bc_num_one(b);
                bc_num_extend(b, scale);
-               return BC_STATUS_SUCCESS;
+               RETURN_STATUS(BC_STATUS_SUCCESS);
        }
 
        scale = BC_MAX(scale, a->rdx) + 1;
@@ -2719,10 +2562,13 @@ err:
        bc_num_free(&half);
        bc_num_free(&num2);
        bc_num_free(&num1);
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_sqrt(...) (zbc_num_sqrt(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
-static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
+static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
                               size_t scale)
 {
        BcStatus s;
@@ -2745,21 +2591,24 @@ static BcStatus zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
 
        if (init) bc_num_free(&num2);
 
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_divmod(...) (zbc_num_divmod(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
 #if ENABLE_DC
-static BcStatus zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d)
+static BC_STATUS zbc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d)
 {
        BcStatus s;
        BcNum base, exp, two, temp;
 
        if (c->len == 0)
-               return bc_error("divide by zero");
+               RETURN_STATUS(bc_error("divide by zero"));
        if (a->rdx || b->rdx || c->rdx)
-               return bc_error("non integer number");
+               RETURN_STATUS(bc_error("non integer number"));
        if (b->neg)
-               return bc_error("negative number");
+               RETURN_STATUS(bc_error("negative number"));
 
        bc_num_expand(d, c->len);
        bc_num_init(&base, c->len);
@@ -2798,8 +2647,11 @@ err:
        bc_num_free(&two);
        bc_num_free(&exp);
        bc_num_free(&base);
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_num_modexp(...) (zbc_num_modexp(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 #endif // ENABLE_DC
 
 #if ENABLE_BC
@@ -5630,7 +5482,11 @@ static BcStatus bc_program_op(char inst)
        if (s) return s;
        bc_num_init_DEF_SIZE(&res.d.n);
 
-       s = zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale);
+       s = BC_STATUS_SUCCESS;
+#if !ERRORS_ARE_FATAL
+       s =
+#endif
+       zbc_program_ops[inst - BC_INST_POWER](n1, n2, &res.d.n, G.prog.scale);
        if (s) goto err;
        bc_program_binOpRetire(&res);
 
@@ -5810,6 +5666,204 @@ static void bc_program_printString(const char *str)
        }
 }
 
+static void bc_num_printNewline(void)
+{
+       if (G.prog.nchars == G.prog.len - 1) {
+               bb_putchar('\\');
+               bb_putchar('\n');
+               G.prog.nchars = 0;
+       }
+}
+
+#if ENABLE_DC
+static FAST_FUNC void bc_num_printChar(size_t num, size_t width, bool radix)
+{
+       (void) radix;
+       bb_putchar((char) num);
+       G.prog.nchars += width;
+}
+#endif
+
+static FAST_FUNC void bc_num_printDigits(size_t num, size_t width, bool radix)
+{
+       size_t exp, pow;
+
+       bc_num_printNewline();
+       bb_putchar(radix ? '.' : ' ');
+       ++G.prog.nchars;
+
+       bc_num_printNewline();
+       for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10)
+               continue;
+
+       for (exp = 0; exp < width; pow /= 10, ++G.prog.nchars, ++exp) {
+               size_t dig;
+               bc_num_printNewline();
+               dig = num / pow;
+               num -= dig * pow;
+               bb_putchar(((char) dig) + '0');
+       }
+}
+
+static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix)
+{
+       if (radix) {
+               bc_num_printNewline();
+               bb_putchar('.');
+               G.prog.nchars += 1;
+       }
+
+       bc_num_printNewline();
+       bb_putchar(bb_hexdigits_upcase[num]);
+       G.prog.nchars += width;
+}
+
+static void bc_num_printDecimal(BcNum *n)
+{
+       size_t i, rdx = n->rdx - 1;
+
+       if (n->neg) bb_putchar('-');
+       G.prog.nchars += n->neg;
+
+       for (i = n->len - 1; i < n->len; --i)
+               bc_num_printHex((size_t) n->num[i], 1, i == rdx);
+}
+
+static BC_STATUS zbc_num_printNum(BcNum *n, BcNum *base, size_t width, BcNumDigitOp print)
+{
+       BcStatus s;
+       BcVec stack;
+       BcNum intp, fracp, digit, frac_len;
+       unsigned long dig, *ptr;
+       size_t i;
+       bool radix;
+
+       if (n->len == 0) {
+               print(0, width, false);
+               RETURN_STATUS(BC_STATUS_SUCCESS);
+       }
+
+       bc_vec_init(&stack, sizeof(long), NULL);
+       bc_num_init(&intp, n->len);
+       bc_num_init(&fracp, n->rdx);
+       bc_num_init(&digit, width);
+       bc_num_init(&frac_len, BC_NUM_INT(n));
+       bc_num_copy(&intp, n);
+       bc_num_one(&frac_len);
+
+       bc_num_truncate(&intp, intp.rdx);
+       s = zbc_num_sub(n, &intp, &fracp, 0);
+       if (s) goto err;
+
+       while (intp.len != 0) {
+               s = zbc_num_divmod(&intp, base, &intp, &digit, 0);
+               if (s) goto err;
+               s = zbc_num_ulong(&digit, &dig);
+               if (s) goto err;
+               bc_vec_push(&stack, &dig);
+       }
+
+       for (i = 0; i < stack.len; ++i) {
+               ptr = bc_vec_item_rev(&stack, i);
+               print(*ptr, width, false);
+       }
+
+       if (!n->rdx) goto err;
+
+       for (radix = true; frac_len.len <= n->rdx; radix = false) {
+               s = zbc_num_mul(&fracp, base, &fracp, n->rdx);
+               if (s) goto err;
+               s = zbc_num_ulong(&fracp, &dig);
+               if (s) goto err;
+               bc_num_ulong2num(&intp, dig);
+               s = zbc_num_sub(&fracp, &intp, &fracp, 0);
+               if (s) goto err;
+               print(dig, width, radix);
+               s = zbc_num_mul(&frac_len, base, &frac_len, 0);
+               if (s) goto err;
+       }
+
+err:
+       bc_num_free(&frac_len);
+       bc_num_free(&digit);
+       bc_num_free(&fracp);
+       bc_num_free(&intp);
+       bc_vec_free(&stack);
+       RETURN_STATUS(s);
+}
+#if ERRORS_ARE_FATAL
+# define zbc_num_printNum(...) (zbc_num_printNum(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
+
+static BC_STATUS zbc_num_printBase(BcNum *n)
+{
+       BcStatus s;
+       size_t width, i;
+       BcNumDigitOp print;
+       bool neg = n->neg;
+
+       if (neg) {
+               bb_putchar('-');
+               G.prog.nchars++;
+       }
+
+       n->neg = false;
+
+       if (G.prog.ob_t <= BC_NUM_MAX_IBASE) {
+               width = 1;
+               print = bc_num_printHex;
+       }
+       else {
+               for (i = G.prog.ob_t - 1, width = 0; i != 0; i /= 10, ++width)
+                       continue;
+               print = bc_num_printDigits;
+       }
+
+       s = zbc_num_printNum(n, &G.prog.ob, width, print);
+       n->neg = neg;
+
+       RETURN_STATUS(s);
+}
+#if ERRORS_ARE_FATAL
+# define zbc_num_printBase(...) (zbc_num_printBase(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
+
+#if ENABLE_DC
+static BC_STATUS zbc_num_stream(BcNum *n, BcNum *base)
+{
+       RETURN_STATUS(zbc_num_printNum(n, base, 1, bc_num_printChar));
+}
+#if ERRORS_ARE_FATAL
+# define zbc_num_stream(...) (zbc_num_stream(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
+#endif
+
+static BC_STATUS zbc_num_print(BcNum *n, bool newline)
+{
+       BcStatus s = BC_STATUS_SUCCESS;
+
+       bc_num_printNewline();
+
+       if (n->len == 0) {
+               bb_putchar('0');
+               ++G.prog.nchars;
+       }
+       else if (G.prog.ob_t == 10)
+               bc_num_printDecimal(n);
+       else
+               s = zbc_num_printBase(n);
+
+       if (newline) {
+               bb_putchar('\n');
+               G.prog.nchars = 0;
+       }
+
+       RETURN_STATUS(s);
+}
+#if ERRORS_ARE_FATAL
+# define zbc_num_print(...) (zbc_num_print(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
+
 static BC_STATUS zbc_program_print(char inst, size_t idx)
 {
        BcStatus s;
@@ -6022,7 +6076,7 @@ static BC_STATUS zbc_program_copyToVar(char *name, bool var)
 # define zbc_program_copyToVar(...) (zbc_program_copyToVar(__VA_ARGS__), BC_STATUS_SUCCESS)
 #endif
 
-static BcStatus bc_program_assign(char inst)
+static BC_STATUS zbc_program_assign(char inst)
 {
        BcStatus s;
        BcResult *left, *right, res;
@@ -6030,7 +6084,7 @@ static BcStatus bc_program_assign(char inst)
        bool assign = inst == BC_INST_ASSIGN, ib, sc;
 
        s = zbc_program_binOpPrep(&left, &l, &right, &r, assign);
-       if (s) return s;
+       if (s) RETURN_STATUS(s);
 
        ib = left->t == BC_RESULT_IBASE;
        sc = left->t == BC_RESULT_SCALE;
@@ -6042,30 +6096,34 @@ static BcStatus bc_program_assign(char inst)
                BcVec *v;
 
                if (left->t != BC_RESULT_VAR)
-                       return bc_error_variable_is_wrong_type();
+                       RETURN_STATUS(bc_error_variable_is_wrong_type());
                v = bc_program_search(left->d.id.name, true);
 
-               return zbc_program_assignStr(right, v, false);
+               RETURN_STATUS(zbc_program_assignStr(right, v, false));
        }
 #endif
 
        if (left->t == BC_RESULT_CONSTANT || left->t == BC_RESULT_TEMP)
-               return bc_error("bad assignment:"
+               RETURN_STATUS(("bad assignment:"
                                " left side must be scale,"
                                " ibase, obase, last, var,"
                                " or array element"
-               );
+               ));
 
 #if ENABLE_BC
        if (inst == BC_INST_ASSIGN_DIVIDE && !bc_num_cmp(r, &G.prog.zero))
-               return bc_error("divide by zero");
+               RETURN_STATUS(bc_error("divide by zero"));
 
        if (assign)
                bc_num_copy(l, r);
-       else
-               s = zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale);
-
-       if (s) return s;
+       else {
+               s = BC_STATUS_SUCCESS;
+#if !ERRORS_ARE_FATAL
+               s =
+#endif
+               zbc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale);
+       }
+       if (s) RETURN_STATUS(s);
 #else
        bc_num_copy(l, r);
 #endif
@@ -6083,8 +6141,7 @@ static BcStatus bc_program_assign(char inst)
                unsigned long val, max;
 
                s = zbc_num_ulong(l, &val);
-               if (s)
-                       return s;
+               if (s) RETURN_STATUS(s);
                s = left->t - BC_RESULT_IBASE;
                if (sc) {
                        max = BC_MAX_SCALE;
@@ -6092,13 +6149,13 @@ static BcStatus bc_program_assign(char inst)
                }
                else {
                        if (val < BC_NUM_MIN_BASE)
-                               return bc_error(msg[s]);
+                               RETURN_STATUS(bc_error(msg[s]));
                        max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE;
                        ptr = ib ? &G.prog.ib_t : &G.prog.ob_t;
                }
 
                if (val > max)
-                       return bc_error(msg[s]);
+                       RETURN_STATUS(bc_error(msg[s]));
                if (!sc)
                        bc_num_copy(ib ? &G.prog.ib : &G.prog.ob, l);
 
@@ -6110,8 +6167,11 @@ static BcStatus bc_program_assign(char inst)
        bc_num_copy(&res.d.n, l);
        bc_program_binOpRetire(&res);
 
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_program_assign(...) (zbc_program_assign(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
 #if !ENABLE_DC
 #define bc_program_pushVar(code, bgn, pop, copy) \
@@ -6232,7 +6292,8 @@ static BC_STATUS zbc_program_incdec(char inst)
                   BC_INST_ASSIGN_MINUS;
 
        bc_vec_push(&G.prog.results, &res);
-       bc_program_assign(inst);
+       s = zbc_program_assign(inst);
+       if (s) RETURN_STATUS(s);
 
        if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) {
                bc_vec_pop(&G.prog.results);
@@ -6369,7 +6430,7 @@ static unsigned long bc_program_len(BcNum *n)
        return len;
 }
 
-static BcStatus bc_program_builtin(char inst)
+static BC_STATUS zbc_program_builtin(char inst)
 {
        BcStatus s;
        BcResult *opnd;
@@ -6378,15 +6439,15 @@ static BcStatus bc_program_builtin(char inst)
        bool len = inst == BC_INST_LENGTH;
 
        if (!BC_PROG_STACK(&G.prog.results, 1))
-               return bc_error_stack_has_too_few_elements();
+               RETURN_STATUS(bc_error_stack_has_too_few_elements());
        opnd = bc_vec_top(&G.prog.results);
 
        s = zbc_program_num(opnd, &num, false);
-       if (s) return s;
+       if (s) RETURN_STATUS(s);
 
 #if ENABLE_DC
        if (!BC_PROG_NUM(opnd, num) && !len)
-               return bc_error_variable_is_wrong_type();
+               RETURN_STATUS(bc_error_variable_is_wrong_type());
 #endif
 
        bc_num_init_DEF_SIZE(&res.d.n);
@@ -6399,7 +6460,6 @@ static BcStatus bc_program_builtin(char inst)
 #endif
 #if ENABLE_DC
        else if (len != 0 && !BC_PROG_NUM(opnd, num)) {
-
                char **str;
                size_t idx = opnd->t == BC_RESULT_STR ? opnd->d.id.idx : num->rdx;
 
@@ -6413,18 +6473,21 @@ static BcStatus bc_program_builtin(char inst)
 
        bc_program_retire(&res, BC_RESULT_TEMP);
 
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_program_builtin(...) (zbc_program_builtin(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
 #if ENABLE_DC
-static BcStatus bc_program_divmod(void)
+static BC_STATUS zbc_program_divmod(void)
 {
        BcStatus s;
        BcResult *opd1, *opd2, res, res2;
        BcNum *n1, *n2 = NULL;
 
        s = zbc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
-       if (s) return s;
+       if (s) RETURN_STATUS(s);
 
        bc_num_init_DEF_SIZE(&res.d.n);
        bc_num_init(&res2.d.n, n2->len);
@@ -6436,42 +6499,45 @@ static BcStatus bc_program_divmod(void)
        res.t = BC_RESULT_TEMP;
        bc_vec_push(&G.prog.results, &res);
 
-       return s;
+       RETURN_STATUS(s);
 
 err:
        bc_num_free(&res2.d.n);
        bc_num_free(&res.d.n);
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_program_divmod(...) (zbc_program_divmod(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
-static BcStatus bc_program_modexp(void)
+static BC_STATUS zbc_program_modexp(void)
 {
        BcStatus s;
        BcResult *r1, *r2, *r3, res;
        BcNum *n1, *n2, *n3;
 
        if (!BC_PROG_STACK(&G.prog.results, 3))
-               return bc_error_stack_has_too_few_elements();
+               RETURN_STATUS(bc_error_stack_has_too_few_elements());
        s = zbc_program_binOpPrep(&r2, &n2, &r3, &n3, false);
-       if (s) return s;
+       if (s) RETURN_STATUS(s);
 
        r1 = bc_vec_item_rev(&G.prog.results, 2);
        s = zbc_program_num(r1, &n1, false);
-       if (s) return s;
+       if (s) RETURN_STATUS(s);
        if (!BC_PROG_NUM(r1, n1))
-               return bc_error_variable_is_wrong_type();
+               RETURN_STATUS(bc_error_variable_is_wrong_type());
 
        // Make sure that the values have their pointers updated, if necessary.
        if (r1->t == BC_RESULT_VAR || r1->t == BC_RESULT_ARRAY_ELEM) {
 
                if (r1->t == r2->t) {
                        s = zbc_program_num(r2, &n2, false);
-                       if (s) return s;
+                       if (s) RETURN_STATUS(s);
                }
 
                if (r1->t == r3->t) {
                        s = zbc_program_num(r3, &n3, false);
-                       if (s) return s;
+                       if (s) RETURN_STATUS(s);
                }
        }
 
@@ -6482,12 +6548,15 @@ static BcStatus bc_program_modexp(void)
        bc_vec_pop(&G.prog.results);
        bc_program_binOpRetire(&res);
 
-       return s;
+       RETURN_STATUS(s);
 
 err:
        bc_num_free(&res.d.n);
-       return s;
+       RETURN_STATUS(s);
 }
+#if ERRORS_ARE_FATAL
+# define zbc_program_modexp(...) (zbc_program_modexp(__VA_ARGS__), BC_STATUS_SUCCESS)
+#endif
 
 static void bc_program_stackLen(void)
 {
@@ -6857,7 +6926,7 @@ static BcStatus bc_program_exec(void)
                        case BC_INST_SCALE_FUNC:
                        case BC_INST_LENGTH:
                        case BC_INST_SQRT:
-                               s = bc_program_builtin(inst);
+                               s = zbc_program_builtin(inst);
                                break;
                        case BC_INST_NUM:
                                r.t = BC_RESULT_CONSTANT;
@@ -6912,14 +6981,14 @@ static BcStatus bc_program_exec(void)
                        case BC_INST_ASSIGN_MINUS:
 #endif
                        case BC_INST_ASSIGN:
-                               s = bc_program_assign(inst);
+                               s = zbc_program_assign(inst);
                                break;
 #if ENABLE_DC
                        case BC_INST_MODEXP:
-                               s = bc_program_modexp();
+                               s = zbc_program_modexp();
                                break;
                        case BC_INST_DIVMOD:
-                               s = bc_program_divmod();
+                               s = zbc_program_divmod();
                                break;
                        case BC_INST_EXECUTE:
                        case BC_INST_EXEC_COND: