summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStefan Eßer <se@FreeBSD.org>2020-11-26 17:27:07 +0000
committerStefan Eßer <se@FreeBSD.org>2020-11-26 17:27:07 +0000
commit2e4772e82335c32e07d0605e5edefb0ac6ea857b (patch)
treed7a054971d1ea18056d0ddb9e0bf0aeb93fb274f /src
parent907a6834f73ccf2839853eb67a29726275ed04b4 (diff)
Notes
Diffstat (limited to 'src')
-rw-r--r--src/args.c6
-rw-r--r--src/bc.c (renamed from src/bc/bc.c)1
-rw-r--r--src/bc_lex.c (renamed from src/bc/lex.c)17
-rw-r--r--src/bc_parse.c (renamed from src/bc/parse.c)160
-rw-r--r--src/data.c45
-rw-r--r--src/dc.c (renamed from src/dc/dc.c)1
-rw-r--r--src/dc_lex.c (renamed from src/dc/lex.c)6
-rw-r--r--src/dc_parse.c (renamed from src/dc/parse.c)14
-rw-r--r--src/file.c6
-rw-r--r--src/history.c (renamed from src/history/history.c)15
-rw-r--r--src/lang.c2
-rw-r--r--src/lex.c11
-rw-r--r--src/library.c1183
-rw-r--r--src/main.c3
-rw-r--r--src/num.c562
-rw-r--r--src/opt.c18
-rw-r--r--src/parse.c3
-rw-r--r--src/program.c83
-rw-r--r--src/rand.c (renamed from src/rand/rand.c)5
-rw-r--r--src/read.c12
-rw-r--r--src/vector.c3
-rw-r--r--src/vm.c126
22 files changed, 1838 insertions, 444 deletions
diff --git a/src/args.c b/src/args.c
index 029237627786..4c9ad3b95549 100644
--- a/src/args.c
+++ b/src/args.c
@@ -41,10 +41,8 @@
#include <unistd.h>
-#include <status.h>
#include <vector.h>
#include <read.h>
-#include <vm.h>
#include <args.h>
#include <opt.h>
@@ -109,7 +107,7 @@ void bc_args(int argc, char *argv[]) {
case 'e':
{
if (vm.no_exit_exprs)
- bc_vm_verr(BC_ERROR_FATAL_OPTION, "-e (--expression)");
+ bc_vm_verr(BC_ERR_FATAL_OPTION, "-e (--expression)");
bc_args_exprs(opts.optarg);
break;
}
@@ -119,7 +117,7 @@ void bc_args(int argc, char *argv[]) {
if (!strcmp(opts.optarg, "-")) vm.no_exit_exprs = true;
else {
if (vm.no_exit_exprs)
- bc_vm_verr(BC_ERROR_FATAL_OPTION, "-f (--file)");
+ bc_vm_verr(BC_ERR_FATAL_OPTION, "-f (--file)");
bc_args_file(opts.optarg);
}
break;
diff --git a/src/bc/bc.c b/src/bc.c
index 3d488b5640c8..cdf3cc9c3a28 100644
--- a/src/bc/bc.c
+++ b/src/bc.c
@@ -37,7 +37,6 @@
#include <string.h>
-#include <status.h>
#include <bc.h>
#include <vm.h>
diff --git a/src/bc/lex.c b/src/bc_lex.c
index cc780e0d6278..87475385fe70 100644
--- a/src/bc/lex.c
+++ b/src/bc_lex.c
@@ -39,7 +39,6 @@
#include <ctype.h>
#include <string.h>
-#include <lex.h>
#include <bc.h>
#include <vm.h>
@@ -58,7 +57,7 @@ static void bc_lex_identifier(BcLex *l) {
l->t = BC_LEX_KW_AUTO + (BcLexType) i;
if (!BC_LEX_KW_POSIX(kw))
- bc_lex_verr(l, BC_ERROR_POSIX_KW, kw->name);
+ bc_lex_verr(l, BC_ERR_POSIX_KW, kw->name);
// We minus 1 because the index has already been incremented.
l->i += n - 1;
@@ -69,7 +68,7 @@ static void bc_lex_identifier(BcLex *l) {
bc_lex_name(l);
if (BC_ERR(l->str.len - 1 > 1))
- bc_lex_verr(l, BC_ERROR_POSIX_NAME_LEN, l->str.v);
+ bc_lex_verr(l, BC_ERR_POSIX_NAME_LEN, l->str.v);
}
static void bc_lex_string(BcLex *l) {
@@ -84,7 +83,7 @@ static void bc_lex_string(BcLex *l) {
if (BC_ERR(c == '\0')) {
l->i = i;
- bc_lex_err(l, BC_ERROR_PARSE_STRING);
+ bc_lex_err(l, BC_ERR_PARSE_STRING);
}
len = i - l->i;
@@ -126,7 +125,7 @@ void bc_lex_token(BcLex *l) {
bc_lex_assign(l, BC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT);
if (l->t == BC_LEX_OP_BOOL_NOT)
- bc_lex_verr(l, BC_ERROR_POSIX_BOOL, "!");
+ bc_lex_verr(l, BC_ERR_POSIX_BOOL, "!");
break;
}
@@ -139,7 +138,7 @@ void bc_lex_token(BcLex *l) {
case '#':
{
- bc_lex_err(l, BC_ERROR_POSIX_COMMENT);
+ bc_lex_err(l, BC_ERR_POSIX_COMMENT);
bc_lex_lineComment(l);
break;
}
@@ -155,7 +154,7 @@ void bc_lex_token(BcLex *l) {
c2 = l->buf[l->i];
if (BC_NO_ERR(c2 == '&')) {
- bc_lex_verr(l, BC_ERROR_POSIX_BOOL, "&&");
+ bc_lex_verr(l, BC_ERR_POSIX_BOOL, "&&");
l->i += 1;
l->t = BC_LEX_OP_BOOL_AND;
@@ -224,7 +223,7 @@ void bc_lex_token(BcLex *l) {
if (BC_LEX_NUM_CHAR(c2, true, false)) bc_lex_number(l, c);
else {
l->t = BC_LEX_KW_LAST;
- bc_lex_err(l, BC_ERROR_POSIX_DOT);
+ bc_lex_err(l, BC_ERR_POSIX_DOT);
}
break;
}
@@ -391,7 +390,7 @@ void bc_lex_token(BcLex *l) {
if (BC_NO_ERR(c2 == '|')) {
- bc_lex_verr(l, BC_ERROR_POSIX_BOOL, "||");
+ bc_lex_verr(l, BC_ERR_POSIX_BOOL, "||");
l->i += 1;
l->t = BC_LEX_OP_BOOL_OR;
diff --git a/src/bc/parse.c b/src/bc_parse.c
index 329c1a84b419..35d3e45c581c 100644
--- a/src/bc/parse.c
+++ b/src/bc_parse.c
@@ -42,8 +42,6 @@
#include <setjmp.h>
-#include <lex.h>
-#include <parse.h>
#include <bc.h>
#include <num.h>
#include <vm.h>
@@ -190,7 +188,7 @@ static void bc_parse_params(BcParse *p, uint8_t flags) {
if (comma) bc_lex_next(&p->l);
}
- if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_parse_push(p, BC_INST_CALL);
bc_parse_pushIndex(p, nparams);
}
@@ -251,7 +249,7 @@ static void bc_parse_name(BcParse *p, BcInst *type,
if (p->l.t == BC_LEX_RBRACKET) {
if (BC_ERR(!(flags & BC_PARSE_ARRAY)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
*type = BC_INST_ARRAY;
*can_assign = false;
@@ -264,7 +262,7 @@ static void bc_parse_name(BcParse *p, BcInst *type,
bc_parse_expr_status(p, flags2, bc_parse_next_elem);
if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
*type = BC_INST_ARRAY_ELEM;
*can_assign = true;
@@ -278,7 +276,7 @@ static void bc_parse_name(BcParse *p, BcInst *type,
else if (p->l.t == BC_LEX_LPAREN) {
if (BC_ERR(flags & BC_PARSE_NOCALL))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
*type = BC_INST_CALL;
*can_assign = false;
@@ -301,10 +299,10 @@ err:
static void bc_parse_noArgBuiltin(BcParse *p, BcInst inst) {
bc_lex_next(&p->l);
- if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(p->l.t != BC_LEX_LPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
- if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if ((p->l.t != BC_LEX_RPAREN)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_parse_push(p, inst);
@@ -316,7 +314,7 @@ static void bc_parse_builtin(BcParse *p, BcLexType type,
{
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_LPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
@@ -327,7 +325,7 @@ static void bc_parse_builtin(BcParse *p, BcLexType type,
bc_parse_expr_status(p, flags, bc_parse_next_rel);
if (BC_ERR(p->l.t != BC_LEX_RPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
*prev = type - BC_LEX_KW_LENGTH + BC_INST_LENGTH;
bc_parse_push(p, *prev);
@@ -356,7 +354,7 @@ static void bc_parse_scale(BcParse *p, BcInst *type,
bc_parse_expr_status(p, flags, bc_parse_next_rel);
if (BC_ERR(p->l.t != BC_LEX_RPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_parse_push(p, BC_INST_SCALE_FUNC);
@@ -376,12 +374,12 @@ static void bc_parse_incdec(BcParse *p, BcInst *prev, bool *can_assign,
if (BC_ERR(last == BC_LEX_OP_INC || last == BC_LEX_OP_DEC ||
last == BC_LEX_RPAREN))
{
- bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
+ bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
}
if (BC_PARSE_INST_VAR(etype)) {
- if (!*can_assign) bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
+ if (!*can_assign) bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
*prev = inst = BC_INST_INC + (p->l.t != BC_LEX_OP_INC);
bc_parse_push(p, inst);
@@ -412,10 +410,10 @@ static void bc_parse_incdec(BcParse *p, BcInst *prev, bool *can_assign,
bc_lex_next(&p->l);
if (BC_ERR(p->l.t == BC_LEX_LPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
else bc_parse_push(p, BC_INST_SCALE);
}
- else bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ else bc_parse_err(p, BC_ERR_PARSE_TOKEN);
*can_assign = false;
@@ -455,7 +453,7 @@ static void bc_parse_print(BcParse *p) {
t = p->l.t;
- if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERROR_PARSE_PRINT);
+ if (bc_parse_isDelimiter(p)) bc_parse_err(p, BC_ERR_PARSE_PRINT);
do {
if (t == BC_LEX_STR) bc_parse_str(p, BC_INST_PRINT_POP);
@@ -469,14 +467,14 @@ static void bc_parse_print(BcParse *p) {
if (comma) bc_lex_next(&p->l);
else {
if (!bc_parse_isDelimiter(p))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
else break;
}
t = p->l.t;
} while (true);
- if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
}
static void bc_parse_return(BcParse *p) {
@@ -485,7 +483,7 @@ static void bc_parse_return(BcParse *p) {
bool paren;
uchar inst = BC_INST_RET0;
- if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(!BC_PARSE_FUNC(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
if (p->func->voidfn) inst = BC_INST_RET_VOID;
@@ -507,10 +505,10 @@ static void bc_parse_return(BcParse *p) {
}
if (!paren || p->l.last != BC_LEX_RPAREN) {
- bc_parse_err(p, BC_ERROR_POSIX_RET);
+ bc_parse_err(p, BC_ERR_POSIX_RET);
}
else if (BC_ERR(p->func->voidfn))
- bc_parse_verr(p, BC_ERROR_PARSE_RET_VOID, p->func->name);
+ bc_parse_verr(p, BC_ERR_PARSE_RET_VOID, p->func->name);
bc_parse_push(p, BC_INST_RET);
}
@@ -526,7 +524,7 @@ static void bc_parse_endBody(BcParse *p, bool brace) {
bool has_brace, new_else = false;
- if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(p->flags.len <= 1)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
if (brace) {
@@ -534,7 +532,7 @@ static void bc_parse_endBody(BcParse *p, bool brace) {
bc_lex_next(&p->l);
if (BC_ERR(!bc_parse_isDelimiter(p)))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
}
has_brace = (BC_PARSE_BRACE(p) != 0);
@@ -543,7 +541,7 @@ static void bc_parse_endBody(BcParse *p, bool brace) {
size_t len = p->flags.len;
bool loop;
- if (has_brace && !brace) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (has_brace && !brace) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
loop = (BC_PARSE_LOOP_INNER(p) != 0);
@@ -595,7 +593,7 @@ static void bc_parse_endBody(BcParse *p, bool brace) {
!(has_brace = (BC_PARSE_BRACE(p) != 0)));
if (BC_ERR(p->flags.len == 1 && brace))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
else if (brace && BC_PARSE_BRACE(p)) {
uint16_t flags = BC_PARSE_TOP_FLAG(p);
@@ -623,12 +621,12 @@ static void bc_parse_if(BcParse *p) {
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_LPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
bc_parse_expr_status(p, flags, bc_parse_next_rel);
if (BC_ERR(p->l.t != BC_LEX_RPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
bc_parse_push(p, BC_INST_JUMP_ZERO);
@@ -645,7 +643,7 @@ static void bc_parse_else(BcParse *p) {
size_t idx = p->func->labels.len;
if (BC_ERR(!BC_PARSE_IF_END(p)))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_parse_push(p, BC_INST_JUMP);
bc_parse_pushIndex(p, idx);
@@ -665,7 +663,7 @@ static void bc_parse_while(BcParse *p) {
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_LPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
bc_parse_createCondLabel(p, p->func->labels.len);
@@ -674,7 +672,7 @@ static void bc_parse_while(BcParse *p) {
bc_parse_expr_status(p, flags, bc_parse_next_rel);
if (BC_ERR(p->l.t != BC_LEX_RPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
bc_parse_push(p, BC_INST_JUMP_ZERO);
@@ -688,15 +686,15 @@ static void bc_parse_for(BcParse *p) {
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_LPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
if (p->l.t != BC_LEX_SCOLON)
bc_parse_expr_status(p, 0, bc_parse_next_for);
- else bc_parse_err(p, BC_ERROR_POSIX_FOR);
+ else bc_parse_err(p, BC_ERR_POSIX_FOR);
if (BC_ERR(p->l.t != BC_LEX_SCOLON))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
cond_idx = p->func->labels.len;
@@ -715,14 +713,14 @@ static void bc_parse_for(BcParse *p) {
// Set this for the next call to bc_parse_number.
// This is safe to set because the current token
// is a semicolon, which has no string requirement.
- bc_vec_string(&p->l.str, strlen(bc_parse_const1), bc_parse_const1);
+ bc_vec_string(&p->l.str, sizeof(bc_parse_one) - 1, bc_parse_one);
bc_parse_number(p);
- bc_parse_err(p, BC_ERROR_POSIX_FOR);
+ bc_parse_err(p, BC_ERR_POSIX_FOR);
}
if (BC_ERR(p->l.t != BC_LEX_SCOLON))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
@@ -735,10 +733,10 @@ static void bc_parse_for(BcParse *p) {
if (p->l.t != BC_LEX_RPAREN)
bc_parse_expr_status(p, 0, bc_parse_next_rel);
- else bc_parse_err(p, BC_ERROR_POSIX_FOR);
+ else bc_parse_err(p, BC_ERR_POSIX_FOR);
if (BC_ERR(p->l.t != BC_LEX_RPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_parse_push(p, BC_INST_JUMP);
bc_parse_pushIndex(p, cond_idx);
bc_parse_createLabel(p, p->func->code.len);
@@ -753,11 +751,11 @@ static void bc_parse_loopExit(BcParse *p, BcLexType type) {
size_t i;
BcInstPtr *ip;
- if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(!BC_PARSE_LOOP(p))) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
if (type == BC_LEX_KW_BREAK) {
- if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(!p->exits.len)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
i = p->exits.len - 1;
ip = bc_vec_item(&p->exits, i);
@@ -783,7 +781,7 @@ static void bc_parse_func(BcParse *p) {
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_NAME))
- bc_parse_err(p, BC_ERROR_PARSE_FUNC);
+ bc_parse_err(p, BC_ERR_PARSE_FUNC);
voidfn = (!BC_IS_POSIX && p->l.t == BC_LEX_NAME &&
!strcmp(p->l.str.v, "void"));
@@ -793,12 +791,12 @@ static void bc_parse_func(BcParse *p) {
voidfn = (voidfn && p->l.t == BC_LEX_NAME);
if (voidfn) {
- bc_parse_err(p, BC_ERROR_POSIX_VOID);
+ bc_parse_err(p, BC_ERR_POSIX_VOID);
bc_lex_next(&p->l);
}
if (BC_ERR(p->l.t != BC_LEX_LPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_FUNC);
+ bc_parse_err(p, BC_ERR_PARSE_FUNC);
assert(p->prog->fns.len == p->prog->fn_map.len);
@@ -821,11 +819,11 @@ static void bc_parse_func(BcParse *p) {
if (p->l.t == BC_LEX_OP_MULTIPLY) {
t = BC_TYPE_REF;
bc_lex_next(&p->l);
- bc_parse_err(p, BC_ERROR_POSIX_REF);
+ bc_parse_err(p, BC_ERR_POSIX_REF);
}
if (BC_ERR(p->l.t != BC_LEX_NAME))
- bc_parse_err(p, BC_ERROR_PARSE_FUNC);
+ bc_parse_err(p, BC_ERR_PARSE_FUNC);
p->func->nparams += 1;
@@ -840,12 +838,12 @@ static void bc_parse_func(BcParse *p) {
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
- bc_parse_err(p, BC_ERROR_PARSE_FUNC);
+ bc_parse_err(p, BC_ERR_PARSE_FUNC);
bc_lex_next(&p->l);
}
else if (BC_ERR(t == BC_TYPE_REF))
- bc_parse_verr(p, BC_ERROR_PARSE_REF_VAR, p->buf.v);
+ bc_parse_verr(p, BC_ERR_PARSE_REF_VAR, p->buf.v);
comma = (p->l.t == BC_LEX_COMMA);
if (comma) {
@@ -855,21 +853,21 @@ static void bc_parse_func(BcParse *p) {
bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
}
- if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_FUNC);
+ if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
flags = BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_FUNC_INNER;
bc_parse_startBody(p, flags);
bc_lex_next(&p->l);
- if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERROR_POSIX_BRACE);
+ if (p->l.t != BC_LEX_LBRACE) bc_parse_err(p, BC_ERR_POSIX_BRACE);
}
static void bc_parse_auto(BcParse *p) {
bool comma, one;
- if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(!p->auto_part)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_lex_next(&p->l);
p->auto_part = comma = false;
@@ -890,7 +888,7 @@ static void bc_parse_auto(BcParse *p) {
bc_lex_next(&p->l);
if (BC_ERR(p->l.t != BC_LEX_RBRACKET))
- bc_parse_err(p, BC_ERROR_PARSE_FUNC);
+ bc_parse_err(p, BC_ERR_PARSE_FUNC);
bc_lex_next(&p->l);
}
@@ -902,10 +900,10 @@ static void bc_parse_auto(BcParse *p) {
bc_func_insert(p->func, p->prog, p->buf.v, t, p->l.line);
}
- if (BC_ERR(comma)) bc_parse_err(p, BC_ERROR_PARSE_FUNC);
- if (BC_ERR(!one)) bc_parse_err(p, BC_ERROR_PARSE_NO_AUTO);
+ if (BC_ERR(comma)) bc_parse_err(p, BC_ERR_PARSE_FUNC);
+ if (BC_ERR(!one)) bc_parse_err(p, BC_ERR_PARSE_NO_AUTO);
if (BC_ERR(!bc_parse_isDelimiter(p)))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
}
static void bc_parse_body(BcParse *p, bool brace) {
@@ -919,7 +917,7 @@ static void bc_parse_body(BcParse *p, bool brace) {
if (*flag_ptr & BC_PARSE_FLAG_FUNC_INNER) {
- if (BC_ERR(!brace)) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (BC_ERR(!brace)) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
p->auto_part = (p->l.t != BC_LEX_KW_AUTO);
@@ -1134,13 +1132,13 @@ static void bc_parse_stmt(BcParse *p) {
default:
{
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
}
}
if (len == p->flags.len && flags == BC_PARSE_TOP_FLAG(p)) {
if (BC_ERR(!bc_parse_isDelimiter(p)))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
}
// Make sure semicolons are eaten.
@@ -1153,10 +1151,10 @@ void bc_parse_parse(BcParse *p) {
BC_SETJMP(exit);
- if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERROR_PARSE_EOF);
+ if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERR_PARSE_EOF);
else if (p->l.t == BC_LEX_KW_DEFINE) {
if (BC_ERR(BC_PARSE_NO_EXEC(p)))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_parse_func(p);
}
else bc_parse_stmt(p);
@@ -1198,7 +1196,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_OP_INC:
case BC_LEX_OP_DEC:
{
- if (BC_ERR(incdec)) bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
+ if (BC_ERR(incdec)) bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
bc_parse_incdec(p, &prev, &can_assign, &nexprs, flags);
rprn = get_token = bin_last = false;
incdec = true;
@@ -1210,7 +1208,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_OP_TRUNC:
{
if (BC_ERR(!BC_PARSE_LEAF(prev, bin_last, rprn)))
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
// I can just add the instruction because
// negative will already be taken care of.
@@ -1246,9 +1244,11 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_OP_ASSIGN:
{
if (!BC_PARSE_INST_VAR(prev))
- bc_parse_err(p, BC_ERROR_PARSE_ASSIGN);
+ bc_parse_err(p, BC_ERR_PARSE_ASSIGN);
}
// Fallthrough.
+ BC_FALLTHROUGH
+
case BC_LEX_OP_POWER:
case BC_LEX_OP_MULTIPLY:
case BC_LEX_OP_DIVIDE:
@@ -1271,10 +1271,10 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
{
if (BC_PARSE_OP_PREFIX(t)) {
if (BC_ERR(!bin_last && !BC_PARSE_OP_PREFIX(p->l.last)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
}
else if (BC_ERR(BC_PARSE_PREV_PREFIX(prev) || bin_last))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
nrelops += (t >= BC_LEX_OP_REL_EQ && t <= BC_LEX_OP_REL_GT);
prev = BC_PARSE_TOKEN_INST(t);
@@ -1290,7 +1290,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_LPAREN:
{
if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
nparens += 1;
rprn = incdec = can_assign = false;
@@ -1308,7 +1308,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
return BC_PARSE_STATUS_EMPTY_EXPR;
if (BC_ERR(bin_last || BC_PARSE_PREV_PREFIX(prev)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
if (!nparens) {
done = true;
@@ -1328,7 +1328,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_NAME:
{
if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
get_token = bin_last = false;
bc_parse_name(p, &prev, &can_assign,
@@ -1343,7 +1343,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_NUMBER:
{
if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
bc_parse_number(p);
nexprs += 1;
@@ -1363,7 +1363,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
{
if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
prev = t - BC_LEX_KW_LAST + BC_INST_LAST;
bc_parse_push(p, prev);
@@ -1384,7 +1384,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
{
if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
bc_parse_builtin(p, t, flags, &prev);
rprn = get_token = bin_last = incdec = can_assign = false;
@@ -1406,9 +1406,9 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
{
if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
else if (t == BC_LEX_KW_READ && BC_ERR(flags & BC_PARSE_NOREAD))
- bc_parse_err(p, BC_ERROR_EXEC_REC_READ);
+ bc_parse_err(p, BC_ERR_EXEC_REC_READ);
else {
prev = t - BC_LEX_KW_READ + BC_INST_READ;
bc_parse_noArgBuiltin(p, prev);
@@ -1424,7 +1424,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_KW_SCALE:
{
if (BC_ERR(BC_PARSE_LEAF(prev, bin_last, rprn)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
bc_parse_scale(p, &prev, &can_assign, flags);
rprn = get_token = bin_last = false;
@@ -1437,7 +1437,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
default:
{
#ifndef NDEBUG
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
break;
#endif // NDEBUG
}
@@ -1452,7 +1452,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
assign = top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN;
if (BC_ERR(top == BC_LEX_LPAREN || top == BC_LEX_RPAREN))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
bc_parse_push(p, BC_PARSE_TOKEN_INST(top));
@@ -1462,16 +1462,16 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
incdec = false;
}
- if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERR_PARSE_EXPR);
for (i = 0; i < next.len && t != next.tokens[i]; ++i);
if (BC_ERR(i == next.len && !bc_parse_isDelimiter(p)))
- bc_parse_err(p, BC_ERROR_PARSE_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EXPR);
if (!(flags & BC_PARSE_REL) && nrelops)
- bc_parse_err(p, BC_ERROR_POSIX_REL_POS);
+ bc_parse_err(p, BC_ERR_POSIX_REL_POS);
else if ((flags & BC_PARSE_REL) && nrelops > 1)
- bc_parse_err(p, BC_ERROR_POSIX_MULTIREL);
+ bc_parse_err(p, BC_ERR_POSIX_MULTIREL);
if (!(flags & BC_PARSE_NEEDVAL) && !pfirst) {
@@ -1522,7 +1522,7 @@ void bc_parse_expr_status(BcParse *p, uint8_t flags, BcParseNext next) {
BcParseStatus s = bc_parse_expr_err(p, flags, next);
if (BC_ERR(s == BC_PARSE_STATUS_EMPTY_EXPR))
- bc_parse_err(p, BC_ERROR_PARSE_EMPTY_EXPR);
+ bc_parse_err(p, BC_ERR_PARSE_EMPTY_EXPR);
}
void bc_parse_expr(BcParse *p, uint8_t flags) {
diff --git a/src/data.c b/src/data.c
index 039c83e1cac1..a3cf4dbda293 100644
--- a/src/data.c
+++ b/src/data.c
@@ -43,6 +43,8 @@
#include <program.h>
#include <vm.h>
+#if !BC_ENABLE_LIBRARY
+
#if BC_ENABLED
const char bc_sig_msg[] = "\ninterrupt (type \"quit\" to exit)\n";
const uchar bc_sig_msg_len = (uchar) (sizeof(bc_sig_msg) - 1);
@@ -664,11 +666,8 @@ const char* bc_inst_names[] = {
};
#endif // BC_DEBUG_CODE
-#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
-
-const BcRandState bc_rand_multiplier = BC_RAND_MULTIPLIER;
-
-#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
+const char bc_parse_zero[2] = "0";
+const char bc_parse_one[2] = "1";
#if BC_ENABLED
const BcLexKeyword bc_lex_kws[] = {
@@ -712,8 +711,6 @@ const BcLexKeyword bc_lex_kws[] = {
const size_t bc_lex_kws_len = sizeof(bc_lex_kws) / sizeof(BcLexKeyword);
-const char* const bc_parse_const1 = "1";
-
// This is an array that corresponds to token types. An entry is
// true if the token is valid in an expression, false otherwise.
const uint8_t bc_parse_exprs[] = {
@@ -937,11 +934,26 @@ const uchar dc_parse_insts[] = {
};
#endif // DC_ENABLED
+#endif // !BC_ENABLE_LIBRARY
+
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
+
+const BcRandState bc_rand_multiplier = BC_RAND_MULTIPLIER;
+
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
+
#if BC_LONG_BIT >= 64
const BcDig bc_num_bigdigMax[] = {
709551616U,
446744073U,
- 18U
+ 18U,
+};
+const BcDig bc_num_bigdigMax2[] = {
+ 768211456U,
+ 374607431U,
+ 938463463U,
+ 282366920U,
+ 340U,
};
#else // BC_LONG_BIT >= 64
const BcDig bc_num_bigdigMax[] = {
@@ -949,12 +961,17 @@ const BcDig bc_num_bigdigMax[] = {
9496U,
42U,
};
+const BcDig bc_num_bigdigMax2[] = {
+ 1616U,
+ 955U,
+ 737U,
+ 6744U,
+ 1844U,
+};
#endif // BC_LONG_BIT >= 64
const size_t bc_num_bigdigMax_size = sizeof(bc_num_bigdigMax) / sizeof(BcDig);
-
-const char bc_parse_zero[] = "0";
-const char bc_parse_one[] = "1";
+const size_t bc_num_bigdigMax2_size = sizeof(bc_num_bigdigMax2) / sizeof(BcDig);
const char bc_num_hex_digits[] = "0123456789ABCDEF";
@@ -973,6 +990,8 @@ const BcBigDig bc_num_pow10[BC_BASE_DIGS + 1] = {
#endif // BC_BASE_DIGS > 4
};
+#if !BC_ENABLE_LIBRARY
+
const BcNumBinaryOp bc_program_ops[] = {
bc_num_pow, bc_num_mul, bc_num_div, bc_num_mod, bc_num_add, bc_num_sub,
#if BC_ENABLE_EXTRA_MATH
@@ -981,7 +1000,7 @@ const BcNumBinaryOp bc_program_ops[] = {
};
const BcNumBinaryOpReq bc_program_opReqs[] = {
- bc_num_powReq, bc_num_mulReq, bc_num_mulReq, bc_num_mulReq,
+ bc_num_powReq, bc_num_mulReq, bc_num_divReq, bc_num_divReq,
bc_num_addReq, bc_num_addReq,
#if BC_ENABLE_EXTRA_MATH
bc_num_placesReq, bc_num_placesReq, bc_num_placesReq,
@@ -1002,3 +1021,5 @@ const char bc_program_ready_msg[] = "ready for more input\n";
const size_t bc_program_ready_msg_len = sizeof(bc_program_ready_msg) - 1;
const char bc_program_esc_chars[] = "ab\\efnqrt";
const char bc_program_esc_seqs[] = "\a\b\\\\\f\n\"\r\t";
+
+#endif // !BC_ENABLE_LIBRARY
diff --git a/src/dc/dc.c b/src/dc.c
index 8c03ccf0e414..41c49a08b367 100644
--- a/src/dc/dc.c
+++ b/src/dc.c
@@ -37,7 +37,6 @@
#include <string.h>
-#include <status.h>
#include <dc.h>
#include <vm.h>
diff --git a/src/dc/lex.c b/src/dc_lex.c
index b17f01bc990d..e9a7d2ca1e4b 100644
--- a/src/dc/lex.c
+++ b/src/dc_lex.c
@@ -37,8 +37,6 @@
#include <ctype.h>
-#include <status.h>
-#include <lex.h>
#include <dc.h>
#include <vm.h>
@@ -57,7 +55,7 @@ static void dc_lex_register(BcLex *l) {
c = l->buf[l->i];
if (!isalnum(c) && c != '_')
- bc_lex_verr(l, BC_ERROR_PARSE_CHAR, c);
+ bc_lex_verr(l, BC_ERR_PARSE_CHAR, c);
l->i += 1;
bc_lex_name(l);
@@ -96,7 +94,7 @@ static void dc_lex_string(BcLex *l) {
if (BC_ERR(c == '\0' && depth)) {
l->i = i;
- bc_lex_err(l, BC_ERROR_PARSE_STRING);
+ bc_lex_err(l, BC_ERR_PARSE_STRING);
}
bc_vec_pushByte(&l->str, '\0');
diff --git a/src/dc/parse.c b/src/dc_parse.c
index 86edc5f66505..81191541fa83 100644
--- a/src/dc/parse.c
+++ b/src/dc_parse.c
@@ -40,8 +40,6 @@
#include <string.h>
#include <setjmp.h>
-#include <status.h>
-#include <parse.h>
#include <dc.h>
#include <program.h>
#include <vm.h>
@@ -49,7 +47,7 @@
static void dc_parse_register(BcParse *p, bool var) {
bc_lex_next(&p->l);
- if (p->l.t != BC_LEX_NAME) bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ if (p->l.t != BC_LEX_NAME) bc_parse_err(p, BC_ERR_PARSE_TOKEN);
bc_parse_pushName(p, p->l.str.v, var);
}
@@ -132,6 +130,8 @@ static void dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) {
bc_lex_next(&p->l);
}
// Fallthrough.
+ BC_FALLTHROUGH
+
case BC_LEX_NUMBER:
{
bc_parse_number(p);
@@ -145,7 +145,7 @@ static void dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) {
case BC_LEX_KW_READ:
{
if (BC_ERR(flags & BC_PARSE_NOREAD))
- bc_parse_err(p, BC_ERROR_EXEC_REC_READ);
+ bc_parse_err(p, BC_ERR_EXEC_REC_READ);
else bc_parse_push(p, BC_INST_READ);
get_token = true;
break;
@@ -182,7 +182,7 @@ static void dc_parse_token(BcParse *p, BcLexType t, uint8_t flags) {
default:
{
- bc_parse_err(p, BC_ERROR_PARSE_TOKEN);
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
}
}
@@ -214,7 +214,7 @@ void dc_parse_expr(BcParse *p, uint8_t flags) {
}
if (BC_ERR(need_expr && !have_expr))
- bc_vm_err(BC_ERROR_EXEC_READ_EXPR);
+ bc_vm_err(BC_ERR_EXEC_READ_EXPR);
else if (p->l.t == BC_LEX_EOF && (flags & BC_PARSE_NOCALL))
bc_parse_push(p, BC_INST_POP_EXEC);
}
@@ -225,7 +225,7 @@ void dc_parse_parse(BcParse *p) {
BC_SETJMP(exit);
- if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERROR_PARSE_EOF);
+ if (BC_ERR(p->l.t == BC_LEX_EOF)) bc_parse_err(p, BC_ERR_PARSE_EOF);
else dc_parse_expr(p, 0);
exit:
diff --git a/src/file.c b/src/file.c
index 01997399f452..1d4d390f89a4 100644
--- a/src/file.c
+++ b/src/file.c
@@ -41,8 +41,8 @@
#include <file.h>
#include <vm.h>
-void bc_file_ultoa(unsigned long long val, char buf[BC_FILE_ULL_LENGTH]) {
-
+static void bc_file_ultoa(unsigned long long val, char buf[BC_FILE_ULL_LENGTH])
+{
char buf2[BC_FILE_ULL_LENGTH];
size_t i, len;
@@ -105,7 +105,7 @@ void bc_file_flush(BcFile *restrict f) {
vm.status = (sig_atomic_t) s;
BC_VM_JMP;
}
- else bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ else bc_vm_err(BC_ERR_FATAL_IO_ERR);
}
}
diff --git a/src/history/history.c b/src/history.c
index b94fbb7b3fdf..ae4b42d326c0 100644
--- a/src/history/history.c
+++ b/src/history.c
@@ -383,7 +383,7 @@ static BcStatus bc_history_readCode(char *buf, size_t buf_len,
return BC_STATUS_SUCCESS;
err:
- if (BC_ERR(n < 0)) bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ if (BC_ERR(n < 0)) bc_vm_err(BC_ERR_FATAL_IO_ERR);
else *nread = (size_t) n;
return BC_STATUS_EOF;
}
@@ -441,7 +441,7 @@ static void bc_history_enableRaw(BcHistory *h) {
BC_SIG_LOCK;
if (BC_ERR(tcgetattr(STDIN_FILENO, &h->orig_termios) == -1))
- bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ bc_vm_err(BC_ERR_FATAL_IO_ERR);
BC_SIG_UNLOCK;
@@ -473,7 +473,7 @@ static void bc_history_enableRaw(BcHistory *h) {
BC_SIG_UNLOCK;
- if (BC_ERR(err < 0)) bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ if (BC_ERR(err < 0)) bc_vm_err(BC_ERR_FATAL_IO_ERR);
h->rawMode = true;
}
@@ -672,7 +672,7 @@ static void bc_history_refresh(BcHistory *h) {
*/
static void bc_history_edit_insert(BcHistory *h, const char *cbuf, size_t clen)
{
- bc_vec_expand(&h->buf, bc_vm_growSize(h->buf.len, clen));
+ bc_vec_grow(&h->buf, clen);
if (h->pos == BC_HIST_BUF_LEN(h)) {
@@ -948,8 +948,7 @@ static void bc_history_escape(BcHistory *h) {
}
else {
- if (BC_ERR(BC_HIST_READ(seq + 1, 1)))
- bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ if (BC_ERR(BC_HIST_READ(seq + 1, 1))) bc_vm_err(BC_ERR_FATAL_IO_ERR);
// ESC [ sequences.
if (c == '[') {
@@ -960,13 +959,13 @@ static void bc_history_escape(BcHistory *h) {
// Extended escape, read additional byte.
if (BC_ERR(BC_HIST_READ(seq + 2, 1)))
- bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ bc_vm_err(BC_ERR_FATAL_IO_ERR);
if (seq[2] == '~' && c == '3') bc_history_edit_delete(h);
else if(seq[2] == ';') {
if (BC_ERR(BC_HIST_READ(seq, 2)))
- bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ bc_vm_err(BC_ERR_FATAL_IO_ERR);
if (seq[0] != '5') return;
else if (seq[1] == 'C') bc_history_edit_wordEnd(h);
diff --git a/src/lang.c b/src/lang.c
index bd287c75ee78..bc34e7c269f8 100644
--- a/src/lang.c
+++ b/src/lang.c
@@ -77,7 +77,7 @@ void bc_func_insert(BcFunc *f, BcProgram *p, char *name,
BcLoc *id = bc_vec_item(&f->autos, i);
if (BC_ERR(idx == id->loc && type == (BcType) id->idx)) {
const char *array = type == BC_TYPE_ARRAY ? "[]" : "";
- bc_vm_error(BC_ERROR_PARSE_DUP_LOCAL, line, name, array);
+ bc_vm_error(BC_ERR_PARSE_DUP_LOCAL, line, name, array);
}
}
diff --git a/src/lex.c b/src/lex.c
index 2b705c8bc71b..d6f09f995a6a 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -38,14 +38,13 @@
#include <stdbool.h>
#include <string.h>
-#include <status.h>
#include <lex.h>
#include <vm.h>
#include <bc.h>
void bc_lex_invalidChar(BcLex *l, char c) {
l->t = BC_LEX_INVALID;
- bc_lex_verr(l, BC_ERROR_PARSE_CHAR, c);
+ bc_lex_verr(l, BC_ERR_PARSE_CHAR, c);
}
void bc_lex_lineComment(BcLex *l) {
@@ -69,7 +68,7 @@ void bc_lex_comment(BcLex *l) {
if (BC_ERR(!c || buf[i + 1] == '\0')) {
l->i = i;
- bc_lex_err(l, BC_ERROR_PARSE_COMMENT);
+ bc_lex_err(l, BC_ERR_PARSE_COMMENT);
}
end = buf[i + 1] == '/';
@@ -143,7 +142,7 @@ void bc_lex_number(BcLex *l, char start) {
if (c == 'e') {
#if BC_ENABLED
- if (BC_IS_POSIX) bc_lex_err(l, BC_ERROR_POSIX_EXP_NUM);
+ if (BC_IS_POSIX) bc_lex_err(l, BC_ERR_POSIX_EXP_NUM);
#endif // BC_ENABLED
bc_vec_push(&l->str, &c);
@@ -157,7 +156,7 @@ void bc_lex_number(BcLex *l, char start) {
}
if (BC_ERR(!BC_LEX_NUM_CHAR(c, false, true)))
- bc_lex_verr(l, BC_ERROR_PARSE_CHAR, c);
+ bc_lex_verr(l, BC_ERR_PARSE_CHAR, c);
l->i += bc_lex_num(l, 0, true);
}
@@ -208,7 +207,7 @@ void bc_lex_next(BcLex *l) {
l->last = l->t;
l->line += (l->i != 0 && l->buf[l->i - 1] == '\n');
- if (BC_ERR(l->last == BC_LEX_EOF)) bc_lex_err(l, BC_ERROR_PARSE_EOF);
+ if (BC_ERR(l->last == BC_LEX_EOF)) bc_lex_err(l, BC_ERR_PARSE_EOF);
l->t = BC_LEX_EOF;
diff --git a/src/library.c b/src/library.c
new file mode 100644
index 000000000000..278b0f55a950
--- /dev/null
+++ b/src/library.c
@@ -0,0 +1,1183 @@
+/*
+ * *****************************************************************************
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * *****************************************************************************
+ *
+ * The public functions for libbc.
+ *
+ */
+
+#if BC_ENABLE_LIBRARY
+
+#include <setjmp.h>
+#include <string.h>
+#include <time.h>
+
+#include <bcl.h>
+
+#include <library.h>
+#include <num.h>
+#include <vm.h>
+
+static void bcl_num_destruct(void *num);
+
+void bcl_handleSignal(void) {
+
+ // Signal already in flight, or bc is not executing.
+ if (vm.sig || !vm.running) return;
+
+ vm.sig = 1;
+
+ assert(vm.jmp_bufs.len);
+
+ if (!vm.sig_lock) BC_VM_JMP;
+}
+
+bool bcl_running(void) {
+ return vm.running != 0;
+}
+
+BclError bcl_init(void) {
+
+ BclError e = BCL_ERROR_NONE;
+
+ vm.refs += 1;
+
+ if (vm.refs > 1) return e;
+
+ vm.ctxts.v = NULL;
+ vm.jmp_bufs.v = NULL;
+ vm.out.v = NULL;
+
+ vm.abrt = false;
+
+ BC_SIG_LOCK;
+
+ bc_vec_init(&vm.jmp_bufs, sizeof(sigjmp_buf), NULL);
+
+ BC_FUNC_HEADER_INIT(err);
+
+ bc_vm_init();
+
+ bc_vec_init(&vm.ctxts, sizeof(BclContext), NULL);
+ bc_vec_init(&vm.out, sizeof(uchar), NULL);
+
+ srand((unsigned int) time(NULL));
+ bc_rand_init(&vm.rng);
+
+err:
+ if (BC_ERR(vm.err)) {
+ if (vm.out.v != NULL) bc_vec_free(&vm.out);
+ if (vm.jmp_bufs.v != NULL) bc_vec_free(&vm.jmp_bufs);
+ if (vm.ctxts.v != NULL) bc_vec_free(&vm.ctxts);
+ }
+
+ BC_FUNC_FOOTER_UNLOCK(e);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return e;
+}
+
+BclError bcl_pushContext(BclContext ctxt) {
+
+ BclError e = BCL_ERROR_NONE;
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_push(&vm.ctxts, &ctxt);
+
+err:
+ BC_FUNC_FOOTER_UNLOCK(e);
+ return e;
+}
+
+void bcl_popContext(void) {
+ if (vm.ctxts.len) bc_vec_pop(&vm.ctxts);
+}
+
+BclContext bcl_context(void) {
+ if (!vm.ctxts.len) return NULL;
+ return *((BclContext*) bc_vec_top(&vm.ctxts));
+}
+
+void bcl_free(void) {
+
+ vm.refs -= 1;
+
+ if (vm.refs) return;
+
+ BC_SIG_LOCK;
+
+#ifndef NDEBUG
+ bc_rand_free(&vm.rng);
+ bc_vec_free(&vm.out);
+
+ {
+ size_t i;
+
+ for (i = 0; i < vm.ctxts.len; ++i) {
+ BclContext ctxt = *((BclContext*) bc_vec_item(&vm.ctxts, i));
+ bcl_ctxt_free(ctxt);
+ }
+ }
+
+ bc_vec_free(&vm.ctxts);
+#endif // NDEBUG
+
+ bc_vm_shutdown();
+
+ bc_vec_free(&vm.jmp_bufs);
+
+ BC_SIG_UNLOCK;
+
+ memset(&vm, 0, sizeof(BcVm));
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+}
+
+void bcl_gc(void) {
+ bc_vm_freeTemps();
+ vm.temps.len = 0;
+}
+
+bool bcl_abortOnFatalError(void) {
+ return vm.abrt;
+}
+
+void bcl_setAbortOnFatalError(bool abrt) {
+ vm.abrt = abrt;
+}
+
+BclContext bcl_ctxt_create(void) {
+
+ BclContext ctxt = NULL;
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ ctxt = bc_vm_malloc(sizeof(BclCtxt));
+
+ bc_vec_init(&ctxt->nums, sizeof(BcNum), bcl_num_destruct);
+ bc_vec_init(&ctxt->free_nums, sizeof(BclNumber), NULL);
+
+ ctxt->scale = 0;
+ ctxt->ibase = 10;
+ ctxt->obase= 10;
+
+err:
+ if (BC_ERR(vm.err && ctxt != NULL)) {
+ if (ctxt->nums.v != NULL) bc_vec_free(&ctxt->nums);
+ free(ctxt);
+ ctxt = NULL;
+ }
+
+ BC_FUNC_FOOTER_NO_ERR;
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return ctxt;
+}
+
+void bcl_ctxt_free(BclContext ctxt) {
+ BC_SIG_LOCK;
+ bc_vec_free(&ctxt->free_nums);
+ bc_vec_free(&ctxt->nums);
+ free(ctxt);
+ BC_SIG_UNLOCK;
+}
+
+void bcl_ctxt_freeNums(BclContext ctxt) {
+ bc_vec_npop(&ctxt->nums, ctxt->nums.len);
+ bc_vec_npop(&ctxt->free_nums, ctxt->free_nums.len);
+}
+
+size_t bcl_ctxt_scale(BclContext ctxt) {
+ return ctxt->scale;
+}
+
+void bcl_ctxt_setScale(BclContext ctxt, size_t scale) {
+ ctxt->scale = scale;
+}
+
+size_t bcl_ctxt_ibase(BclContext ctxt) {
+ return ctxt->ibase;
+}
+
+void bcl_ctxt_setIbase(BclContext ctxt, size_t ibase) {
+ if (ibase < BC_NUM_MIN_BASE) ibase = BC_NUM_MIN_BASE;
+ else if (ibase > BC_NUM_MAX_IBASE) ibase = BC_NUM_MAX_IBASE;
+ ctxt->ibase = ibase;
+}
+
+size_t bcl_ctxt_obase(BclContext ctxt) {
+ return ctxt->obase;
+}
+
+void bcl_ctxt_setObase(BclContext ctxt, size_t obase) {
+ ctxt->obase = obase;
+}
+
+BclError bcl_err(BclNumber n) {
+
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ERR(ctxt);
+
+ if (n.i >= ctxt->nums.len) {
+ if (n.i > 0 - (size_t) BCL_ERROR_NELEMS) return (BclError) (0 - n.i);
+ else return BCL_ERROR_INVALID_NUM;
+ }
+ else return BCL_ERROR_NONE;
+}
+
+static BclNumber bcl_num_insert(BclContext ctxt, BcNum *restrict n) {
+
+ BclNumber idx;
+
+ if (ctxt->free_nums.len) {
+
+ BcNum *ptr;
+
+ idx = *((BclNumber*) bc_vec_top(&ctxt->free_nums));
+
+ bc_vec_pop(&ctxt->free_nums);
+
+ ptr = bc_vec_item(&ctxt->nums, idx.i);
+ memcpy(ptr, n, sizeof(BcNum));
+ }
+ else {
+ idx.i = ctxt->nums.len;
+ bc_vec_push(&ctxt->nums, n);
+ }
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+BclNumber bcl_num_create(void) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum n;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ bc_num_init(&n, BC_NUM_DEF_SIZE);
+
+err:
+ BC_FUNC_FOOTER_UNLOCK(e);
+ BC_MAYBE_SETUP(ctxt, e, n, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+static void bcl_num_dtor(BclContext ctxt, BclNumber n, BcNum *restrict num) {
+
+ BC_SIG_ASSERT_LOCKED;
+
+ assert(num != NULL && num->num != NULL);
+
+ bcl_num_destruct(num);
+ bc_vec_push(&ctxt->free_nums, &n);
+}
+
+void bcl_num_free(BclNumber n) {
+
+ BcNum *num;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ BC_SIG_LOCK;
+
+ assert(n.i < ctxt->nums.len);
+
+ num = BC_NUM(ctxt, n);
+
+ bcl_num_dtor(ctxt, n, num);
+
+ BC_SIG_UNLOCK;
+}
+
+BclError bcl_copy(BclNumber d, BclNumber s) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum *dest, *src;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ERR(ctxt);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ assert(d.i < ctxt->nums.len && s.i < ctxt->nums.len);
+
+ dest = BC_NUM(ctxt, d);
+ src = BC_NUM(ctxt, s);
+
+ assert(dest != NULL && src != NULL);
+ assert(dest->num != NULL && src->num != NULL);
+
+ bc_num_copy(dest, src);
+
+err:
+ BC_FUNC_FOOTER_UNLOCK(e);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return e;
+}
+
+BclNumber bcl_dup(BclNumber s) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum *src, dest;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ assert(s.i < ctxt->nums.len);
+
+ src = BC_NUM(ctxt, s);
+
+ assert(src != NULL && src->num != NULL);
+
+ bc_num_clear(&dest);
+
+ bc_num_createCopy(&dest, src);
+
+err:
+ BC_FUNC_FOOTER_UNLOCK(e);
+ BC_MAYBE_SETUP(ctxt, e, dest, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+static void bcl_num_destruct(void *num) {
+
+ BcNum *n = (BcNum*) num;
+
+ assert(n != NULL);
+
+ if (n->num == NULL) return;
+
+ bc_num_free(num);
+ bc_num_clear(num);
+}
+
+bool bcl_num_neg(BclNumber n) {
+
+ BcNum *num;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ assert(n.i < ctxt->nums.len);
+
+ num = BC_NUM(ctxt, n);
+
+ assert(num != NULL && num->num != NULL);
+
+ return BC_NUM_NEG(num) != 0;
+}
+
+void bcl_num_setNeg(BclNumber n, bool neg) {
+
+ BcNum *num;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ assert(n.i < ctxt->nums.len);
+
+ num = BC_NUM(ctxt, n);
+
+ assert(num != NULL && num->num != NULL);
+
+ num->rdx = BC_NUM_NEG_VAL(num, neg);
+}
+
+size_t bcl_num_scale(BclNumber n) {
+
+ BcNum *num;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ assert(n.i < ctxt->nums.len);
+
+ num = BC_NUM(ctxt, n);
+
+ assert(num != NULL && num->num != NULL);
+
+ return bc_num_scale(num);
+}
+
+BclError bcl_num_setScale(BclNumber n, size_t scale) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum *nptr;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ERR(ctxt);
+
+ BC_CHECK_NUM_ERR(ctxt, n);
+
+ BC_FUNC_HEADER(err);
+
+ assert(n.i < ctxt->nums.len);
+
+ nptr = BC_NUM(ctxt, n);
+
+ assert(nptr != NULL && nptr->num != NULL);
+
+ if (scale > nptr->scale) bc_num_extend(nptr, scale - nptr->scale);
+ else if (scale < nptr->scale) bc_num_truncate(nptr, nptr->scale - scale);
+
+err:
+ BC_SIG_MAYLOCK;
+ BC_FUNC_FOOTER(e);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return e;
+}
+
+size_t bcl_num_len(BclNumber n) {
+
+ BcNum *num;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ assert(n.i < ctxt->nums.len);
+
+ num = BC_NUM(ctxt, n);
+
+ assert(num != NULL && num->num != NULL);
+
+ return bc_num_len(num);
+}
+
+BclError bcl_bigdig(BclNumber n, BclBigDig *result) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum *num;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ERR(ctxt);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ assert(n.i < ctxt->nums.len);
+ assert(result != NULL);
+
+ num = BC_NUM(ctxt, n);
+
+ assert(num != NULL && num->num != NULL);
+
+ bc_num_bigdig(num, result);
+
+err:
+ bcl_num_dtor(ctxt, n, num);
+ BC_FUNC_FOOTER_UNLOCK(e);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return e;
+}
+
+BclNumber bcl_bigdig2num(BclBigDig val) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum n;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ bc_num_createFromBigdig(&n, val);
+
+err:
+ BC_FUNC_FOOTER_UNLOCK(e);
+ BC_MAYBE_SETUP(ctxt, e, n, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+static BclNumber bcl_binary(BclNumber a, BclNumber b,
+ const BcNumBinaryOp op,
+ const BcNumBinaryOpReq req)
+{
+ BclError e = BCL_ERROR_NONE;
+ BcNum *aptr, *bptr;
+ BcNum c;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_CHECK_NUM(ctxt, a);
+ BC_CHECK_NUM(ctxt, b);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
+
+ aptr = BC_NUM(ctxt, a);
+ bptr = BC_NUM(ctxt, b);
+
+ assert(aptr != NULL && bptr != NULL);
+ assert(aptr->num != NULL && bptr->num != NULL);
+
+ bc_num_clear(&c);
+
+ bc_num_init(&c, req(aptr, bptr, ctxt->scale));
+
+ BC_SIG_UNLOCK;
+
+ op(aptr, bptr, &c, ctxt->scale);
+
+err:
+ BC_SIG_MAYLOCK;
+ bcl_num_dtor(ctxt, a, aptr);
+ if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
+ BC_FUNC_FOOTER(e);
+ BC_MAYBE_SETUP(ctxt, e, c, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+BclNumber bcl_add(BclNumber a, BclNumber b) {
+ return bcl_binary(a, b, bc_num_add, bc_num_addReq);
+}
+
+BclNumber bcl_sub(BclNumber a, BclNumber b) {
+ return bcl_binary(a, b, bc_num_sub, bc_num_addReq);
+}
+
+BclNumber bcl_mul(BclNumber a, BclNumber b) {
+ return bcl_binary(a, b, bc_num_mul, bc_num_mulReq);
+}
+
+BclNumber bcl_div(BclNumber a, BclNumber b) {
+ return bcl_binary(a, b, bc_num_div, bc_num_divReq);
+}
+
+BclNumber bcl_mod(BclNumber a, BclNumber b) {
+ return bcl_binary(a, b, bc_num_mod, bc_num_divReq);
+}
+
+BclNumber bcl_pow(BclNumber a, BclNumber b) {
+ return bcl_binary(a, b, bc_num_pow, bc_num_powReq);
+}
+
+BclNumber bcl_lshift(BclNumber a, BclNumber b) {
+ return bcl_binary(a, b, bc_num_lshift, bc_num_placesReq);
+}
+
+BclNumber bcl_rshift(BclNumber a, BclNumber b) {
+ return bcl_binary(a, b, bc_num_rshift, bc_num_placesReq);
+}
+
+BclNumber bcl_sqrt(BclNumber a) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum *aptr;
+ BcNum b;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_CHECK_NUM(ctxt, a);
+
+ BC_FUNC_HEADER(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ assert(a.i < ctxt->nums.len);
+
+ aptr = BC_NUM(ctxt, a);
+
+ bc_num_sqrt(aptr, &b, ctxt->scale);
+
+err:
+ BC_SIG_MAYLOCK;
+ bcl_num_dtor(ctxt, a, aptr);
+ BC_FUNC_FOOTER(e);
+ BC_MAYBE_SETUP(ctxt, e, b, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+BclError bcl_divmod(BclNumber a, BclNumber b, BclNumber *c, BclNumber *d) {
+
+ BclError e = BCL_ERROR_NONE;
+ size_t req;
+ BcNum *aptr, *bptr;
+ BcNum cnum, dnum;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ERR(ctxt);
+
+ BC_CHECK_NUM_ERR(ctxt, a);
+ BC_CHECK_NUM_ERR(ctxt, b);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 2);
+
+ assert(c != NULL && d != NULL);
+
+ aptr = BC_NUM(ctxt, a);
+ bptr = BC_NUM(ctxt, b);
+
+ assert(aptr != NULL && bptr != NULL);
+ assert(aptr->num != NULL && bptr->num != NULL);
+
+ bc_num_clear(&cnum);
+ bc_num_clear(&dnum);
+
+ req = bc_num_divReq(aptr, bptr, ctxt->scale);
+
+ bc_num_init(&cnum, req);
+ bc_num_init(&dnum, req);
+
+ BC_SIG_UNLOCK;
+
+ bc_num_divmod(aptr, bptr, &cnum, &dnum, ctxt->scale);
+
+err:
+ BC_SIG_MAYLOCK;
+
+ bcl_num_dtor(ctxt, a, aptr);
+ if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
+
+ if (BC_ERR(vm.err)) {
+ if (cnum.num != NULL) bc_num_free(&cnum);
+ if (dnum.num != NULL) bc_num_free(&dnum);
+ c->i = 0 - (size_t) BCL_ERROR_INVALID_NUM;
+ d->i = c->i;
+ BC_FUNC_FOOTER(e);
+ }
+ else {
+ BC_FUNC_FOOTER(e);
+ *c = bcl_num_insert(ctxt, &cnum);
+ *d = bcl_num_insert(ctxt, &dnum);
+ }
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return e;
+}
+
+BclNumber bcl_modexp(BclNumber a, BclNumber b, BclNumber c) {
+
+ BclError e = BCL_ERROR_NONE;
+ size_t req;
+ BcNum *aptr, *bptr, *cptr;
+ BcNum d;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_CHECK_NUM(ctxt, a);
+ BC_CHECK_NUM(ctxt, b);
+ BC_CHECK_NUM(ctxt, c);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
+ assert(c.i < ctxt->nums.len);
+
+ aptr = BC_NUM(ctxt, a);
+ bptr = BC_NUM(ctxt, b);
+ cptr = BC_NUM(ctxt, c);
+
+ assert(aptr != NULL && bptr != NULL && cptr != NULL);
+ assert(aptr->num != NULL && bptr->num != NULL && cptr->num != NULL);
+
+ bc_num_clear(&d);
+
+ req = bc_num_divReq(aptr, cptr, 0);
+
+ bc_num_init(&d, req);
+
+ BC_SIG_UNLOCK;
+
+ bc_num_modexp(aptr, bptr, cptr, &d);
+
+err:
+ BC_SIG_MAYLOCK;
+
+ bcl_num_dtor(ctxt, a, aptr);
+ if (b.i != a.i) bcl_num_dtor(ctxt, b, bptr);
+ if (c.i != a.i && c.i != b.i) bcl_num_dtor(ctxt, c, cptr);
+
+ BC_FUNC_FOOTER(e);
+ BC_MAYBE_SETUP(ctxt, e, d, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+ssize_t bcl_cmp(BclNumber a, BclNumber b) {
+
+ BcNum *aptr, *bptr;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ assert(a.i < ctxt->nums.len && b.i < ctxt->nums.len);
+
+ aptr = BC_NUM(ctxt, a);
+ bptr = BC_NUM(ctxt, b);
+
+ assert(aptr != NULL && bptr != NULL);
+ assert(aptr->num != NULL && bptr->num != NULL);
+
+ return bc_num_cmp(aptr, bptr);
+}
+
+void bcl_zero(BclNumber n) {
+
+ BcNum *nptr;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ assert(n.i < ctxt->nums.len);
+
+ nptr = BC_NUM(ctxt, n);
+
+ assert(nptr != NULL && nptr->num != NULL);
+
+ bc_num_zero(nptr);
+}
+
+void bcl_one(BclNumber n) {
+
+ BcNum *nptr;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ assert(n.i < ctxt->nums.len);
+
+ nptr = BC_NUM(ctxt, n);
+
+ assert(nptr != NULL && nptr->num != NULL);
+
+ bc_num_one(nptr);
+}
+
+BclNumber bcl_parse(const char *restrict val) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum n;
+ BclNumber idx;
+ BclContext ctxt;
+ bool neg;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ assert(val != NULL);
+
+ neg = (val[0] == '-');
+
+ if (neg) val += 1;
+
+ if (!bc_num_strValid(val)) {
+ vm.err = BCL_ERROR_PARSE_INVALID_STR;
+ goto err;
+ }
+
+ bc_num_clear(&n);
+
+ bc_num_init(&n, BC_NUM_DEF_SIZE);
+
+ BC_SIG_UNLOCK;
+
+ bc_num_parse(&n, val, (BcBigDig) ctxt->ibase);
+
+ n.rdx = BC_NUM_NEG_VAL_NP(n, neg);
+
+err:
+ BC_SIG_MAYLOCK;
+ BC_FUNC_FOOTER(e);
+ BC_MAYBE_SETUP(ctxt, e, n, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+char* bcl_string(BclNumber n) {
+
+ BcNum *nptr;
+ char *str = NULL;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ASSERT(ctxt);
+
+ if (BC_ERR(n.i >= ctxt->nums.len)) return str;
+
+ BC_FUNC_HEADER(err);
+
+ assert(n.i < ctxt->nums.len);
+
+ nptr = BC_NUM(ctxt, n);
+
+ assert(nptr != NULL && nptr->num != NULL);
+
+ bc_vec_npop(&vm.out, vm.out.len);
+
+ bc_num_print(nptr, (BcBigDig) ctxt->obase, false);
+ bc_vec_pushByte(&vm.out, '\0');
+
+ BC_SIG_LOCK;
+ str = bc_vm_strdup(vm.out.v);
+
+err:
+ bcl_num_dtor(ctxt, n, nptr);
+
+ BC_FUNC_FOOTER_NO_ERR;
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return str;
+}
+
+BclNumber bcl_irand(BclNumber a) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum *aptr;
+ BcNum b;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_CHECK_NUM(ctxt, a);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ assert(a.i < ctxt->nums.len);
+
+ aptr = BC_NUM(ctxt, a);
+
+ assert(aptr != NULL && aptr->num != NULL);
+
+ bc_num_clear(&b);
+
+ bc_num_init(&b, BC_NUM_DEF_SIZE);
+
+ BC_SIG_UNLOCK;
+
+ bc_num_irand(aptr, &b, &vm.rng);
+
+err:
+ BC_SIG_MAYLOCK;
+ bcl_num_dtor(ctxt, a, aptr);
+ BC_FUNC_FOOTER(e);
+ BC_MAYBE_SETUP(ctxt, e, b, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+static void bcl_frandHelper(BcNum *restrict b, size_t places) {
+
+ BcNum exp, pow, ten;
+ BcDig exp_digs[BC_NUM_BIGDIG_LOG10];
+ BcDig ten_digs[BC_NUM_BIGDIG_LOG10];
+
+ bc_num_setup(&exp, exp_digs, BC_NUM_BIGDIG_LOG10);
+ bc_num_setup(&ten, ten_digs, BC_NUM_BIGDIG_LOG10);
+
+ ten.num[0] = 10;
+ ten.len = 1;
+
+ bc_num_bigdig2num(&exp, (BcBigDig) places);
+
+ bc_num_clear(&pow);
+
+ BC_SIG_LOCK;
+
+ BC_SETJMP_LOCKED(err);
+
+ bc_num_init(&pow, bc_num_powReq(&ten, &exp, 0));
+
+ BC_SIG_UNLOCK;
+
+ bc_num_pow(&ten, &exp, &pow, 0);
+
+ bc_num_irand(&pow, b, &vm.rng);
+
+ bc_num_shiftRight(b, places);
+
+err:
+ BC_SIG_MAYLOCK;
+ bc_num_free(&pow);
+ BC_LONGJMP_CONT;
+}
+
+BclNumber bcl_frand(size_t places) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum n;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ bc_num_clear(&n);
+
+ bc_num_init(&n, BC_NUM_DEF_SIZE);
+
+ BC_SIG_UNLOCK;
+
+ bcl_frandHelper(&n, places);
+
+err:
+ BC_SIG_MAYLOCK;
+ BC_FUNC_FOOTER(e);
+ BC_MAYBE_SETUP(ctxt, e, n, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+static void bcl_ifrandHelper(BcNum *restrict a, BcNum *restrict b,
+ size_t places)
+{
+ BcNum ir, fr;
+
+ bc_num_clear(&ir);
+ bc_num_clear(&fr);
+
+ BC_SIG_LOCK;
+
+ BC_SETJMP_LOCKED(err);
+
+ bc_num_init(&ir, BC_NUM_DEF_SIZE);
+ bc_num_init(&fr, BC_NUM_DEF_SIZE);
+
+ BC_SIG_UNLOCK;
+
+ bc_num_irand(a, &ir, &vm.rng);
+ bcl_frandHelper(&fr, places);
+
+ bc_num_add(&ir, &fr, b, 0);
+
+err:
+ BC_SIG_MAYLOCK;
+ bc_num_free(&fr);
+ bc_num_free(&ir);
+ BC_LONGJMP_CONT;
+}
+
+BclNumber bcl_ifrand(BclNumber a, size_t places) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum *aptr;
+ BcNum b;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_CHECK_NUM(ctxt, a);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_vec_grow(&ctxt->nums, 1);
+
+ assert(a.i < ctxt->nums.len);
+
+ aptr = BC_NUM(ctxt, a);
+
+ assert(aptr != NULL && aptr->num != NULL);
+
+ bc_num_clear(&b);
+
+ bc_num_init(&b, BC_NUM_DEF_SIZE);
+
+ BC_SIG_UNLOCK;
+
+ bcl_ifrandHelper(aptr, &b, places);
+
+err:
+ BC_SIG_MAYLOCK;
+ bcl_num_dtor(ctxt, a, aptr);
+ BC_FUNC_FOOTER(e);
+ BC_MAYBE_SETUP(ctxt, e, b, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+BclError bcl_rand_seedWithNum(BclNumber n) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum *nptr;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT_ERR(ctxt);
+
+ BC_CHECK_NUM_ERR(ctxt, n);
+
+ BC_FUNC_HEADER(err);
+
+ assert(n.i < ctxt->nums.len);
+
+ nptr = BC_NUM(ctxt, n);
+
+ assert(nptr != NULL && nptr->num != NULL);
+
+ bc_num_rng(nptr, &vm.rng);
+
+err:
+ BC_SIG_MAYLOCK;
+ BC_FUNC_FOOTER(e);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return e;
+}
+
+BclError bcl_rand_seed(unsigned char seed[BC_SEED_SIZE]) {
+
+ BclError e = BCL_ERROR_NONE;
+ size_t i;
+ ulong vals[BC_SEED_ULONGS];
+
+ BC_FUNC_HEADER(err);
+
+ for (i = 0; i < BC_SEED_SIZE; ++i) {
+ ulong val = ((ulong) seed[i]) << (((ulong) CHAR_BIT) *
+ (i % sizeof(ulong)));
+ vals[i / sizeof(long)] |= val;
+ }
+
+ bc_rand_seed(&vm.rng, vals[0], vals[1], vals[2], vals[3]);
+
+err:
+ BC_SIG_MAYLOCK;
+ BC_FUNC_FOOTER(e);
+ return e;
+}
+
+void bcl_rand_reseed(void) {
+ bc_rand_srand(bc_vec_top(&vm.rng.v));
+}
+
+BclNumber bcl_rand_seed2num(void) {
+
+ BclError e = BCL_ERROR_NONE;
+ BcNum n;
+ BclNumber idx;
+ BclContext ctxt;
+
+ BC_CHECK_CTXT(ctxt);
+
+ BC_FUNC_HEADER_LOCK(err);
+
+ bc_num_clear(&n);
+
+ bc_num_init(&n, BC_NUM_DEF_SIZE);
+
+ BC_SIG_UNLOCK;
+
+ bc_num_createFromRNG(&n, &vm.rng);
+
+err:
+ BC_SIG_MAYLOCK;
+ BC_FUNC_FOOTER(e);
+ BC_MAYBE_SETUP(ctxt, e, n, idx);
+
+ assert(!vm.running && !vm.sig && !vm.sig_lock);
+
+ return idx;
+}
+
+BclRandInt bcl_rand_int(void) {
+ return (BclRandInt) bc_rand_int(&vm.rng);
+}
+
+BclRandInt bcl_rand_bounded(BclRandInt bound) {
+ if (bound <= 1) return 0;
+ return (BclRandInt) bc_rand_bounded(&vm.rng, (BcRand) bound);
+}
+
+#endif // BC_ENABLE_LIBRARY
diff --git a/src/main.c b/src/main.c
index 7e5e2905cf75..9c16e766e798 100644
--- a/src/main.c
+++ b/src/main.c
@@ -47,9 +47,6 @@
#include <bc.h>
#include <dc.h>
-char output_bufs[BC_VM_BUF_SIZE];
-BcVm vm;
-
int main(int argc, char *argv[]) {
int s;
diff --git a/src/num.c b/src/num.c
index de5fa5c566fb..0b8823a3fec2 100644
--- a/src/num.c
+++ b/src/num.c
@@ -41,7 +41,6 @@
#include <setjmp.h>
#include <limits.h>
-#include <status.h>
#include <num.h>
#include <rand.h>
#include <vm.h>
@@ -53,11 +52,11 @@ static inline ssize_t bc_num_neg(size_t n, bool neg) {
}
ssize_t bc_num_cmpZero(const BcNum *n) {
- return bc_num_neg((n)->len != 0, (n)->neg);
+ return bc_num_neg((n)->len != 0, BC_NUM_NEG(n));
}
static inline size_t bc_num_int(const BcNum *n) {
- return n->len ? n->len - n->rdx : 0;
+ return n->len ? n->len - BC_NUM_RDX_VAL(n) : 0;
}
static void bc_num_expand(BcNum *restrict n, size_t req) {
@@ -81,10 +80,9 @@ static void bc_num_setToZero(BcNum *restrict n, size_t scale) {
assert(n != NULL);
n->scale = scale;
n->len = n->rdx = 0;
- n->neg = false;
}
-static inline void bc_num_zero(BcNum *restrict n) {
+void bc_num_zero(BcNum *restrict n) {
bc_num_setToZero(n, 0);
}
@@ -98,11 +96,11 @@ static void bc_num_clean(BcNum *restrict n) {
while (BC_NUM_NONZERO(n) && !n->num[n->len - 1]) n->len -= 1;
- if (BC_NUM_ZERO(n)) {
- n->neg = false;
- n->rdx = 0;
+ if (BC_NUM_ZERO(n)) n->rdx = 0;
+ else {
+ size_t rdx = BC_NUM_RDX_VAL(n);
+ if (n->len < rdx) n->len = rdx;
}
- else if (n->len < n->rdx) n->len = n->rdx;
}
static size_t bc_num_log10(size_t i) {
@@ -126,7 +124,7 @@ static size_t bc_num_intDigits(const BcNum *n) {
static size_t bc_num_nonzeroLen(const BcNum *restrict n) {
size_t i, len = n->len;
- assert(len == n->rdx);
+ assert(len == BC_NUM_RDX_VAL(n));
for (i = len - 1; i < len && !n->num[i]; --i);
assert(i + 1 > 0);
return i + 1;
@@ -210,9 +208,9 @@ static void bc_num_mulArray(const BcNum *restrict a, BcBigDig b,
bc_num_clean(c);
- assert(!c->neg || BC_NUM_NONZERO(c));
- assert(c->rdx <= c->len || !c->len);
- assert(!c->len || c->num[c->len - 1] || c->rdx == c->len);
+ assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
+ assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
+ assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
}
static void bc_num_divArray(const BcNum *restrict a, BcBigDig b,
@@ -234,9 +232,9 @@ static void bc_num_divArray(const BcNum *restrict a, BcBigDig b,
bc_num_clean(c);
*rem = carry;
- assert(!c->neg || BC_NUM_NONZERO(c));
- assert(c->rdx <= c->len || !c->len);
- assert(!c->len || c->num[c->len - 1] || c->rdx == c->len);
+ assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
+ assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
+ assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
}
static ssize_t bc_num_compare(const BcDig *restrict a, const BcDig *restrict b,
@@ -250,7 +248,7 @@ static ssize_t bc_num_compare(const BcDig *restrict a, const BcDig *restrict b,
ssize_t bc_num_cmp(const BcNum *a, const BcNum *b) {
- size_t i, min, a_int, b_int, diff;
+ size_t i, min, a_int, b_int, diff, ardx, brdx;
BcDig *max_num, *min_num;
bool a_max, neg = false;
ssize_t cmp;
@@ -258,13 +256,13 @@ ssize_t bc_num_cmp(const BcNum *a, const BcNum *b) {
assert(a != NULL && b != NULL);
if (a == b) return 0;
- if (BC_NUM_ZERO(a)) return bc_num_neg(b->len != 0, !b->neg);
+ if (BC_NUM_ZERO(a)) return bc_num_neg(b->len != 0, !BC_NUM_NEG(b));
if (BC_NUM_ZERO(b)) return bc_num_cmpZero(a);
- if (a->neg) {
- if (b->neg) neg = true;
+ if (BC_NUM_NEG(a)) {
+ if (BC_NUM_NEG(b)) neg = true;
else return -1;
}
- else if (b->neg) return 1;
+ else if (BC_NUM_NEG(b)) return 1;
a_int = bc_num_int(a);
b_int = bc_num_int(b);
@@ -272,17 +270,19 @@ ssize_t bc_num_cmp(const BcNum *a, const BcNum *b) {
if (a_int) return neg ? -((ssize_t) a_int) : (ssize_t) a_int;
- a_max = (a->rdx > b->rdx);
+ ardx = BC_NUM_RDX_VAL(a);
+ brdx = BC_NUM_RDX_VAL(b);
+ a_max = (ardx > brdx);
if (a_max) {
- min = b->rdx;
- diff = a->rdx - b->rdx;
+ min = brdx;
+ diff = ardx - brdx;
max_num = a->num + diff;
min_num = b->num;
}
else {
- min = a->rdx;
- diff = b->rdx - a->rdx;
+ min = ardx;
+ diff = brdx - ardx;
max_num = b->num + diff;
min_num = a->num;
}
@@ -300,15 +300,16 @@ ssize_t bc_num_cmp(const BcNum *a, const BcNum *b) {
void bc_num_truncate(BcNum *restrict n, size_t places) {
- size_t places_rdx;
+ size_t nrdx, places_rdx;
if (!places) return;
- places_rdx = n->rdx ? n->rdx - BC_NUM_RDX(n->scale - places) : 0;
+ nrdx = BC_NUM_RDX_VAL(n);
+ places_rdx = nrdx ? nrdx - BC_NUM_RDX(n->scale - places) : 0;
assert(places <= n->scale && (BC_NUM_ZERO(n) || places_rdx <= n->len));
n->scale -= places;
- n->rdx -= places_rdx;
+ BC_NUM_RDX_SET(n, nrdx - places_rdx);
if (BC_NUM_NONZERO(n)) {
@@ -328,9 +329,9 @@ void bc_num_truncate(BcNum *restrict n, size_t places) {
}
}
-static void bc_num_extend(BcNum *restrict n, size_t places) {
+void bc_num_extend(BcNum *restrict n, size_t places) {
- size_t places_rdx;
+ size_t nrdx, places_rdx;
if (!places) return;
if (BC_NUM_ZERO(n)) {
@@ -338,7 +339,8 @@ static void bc_num_extend(BcNum *restrict n, size_t places) {
return;
}
- places_rdx = BC_NUM_RDX(places + n->scale) - n->rdx;
+ nrdx = BC_NUM_RDX_VAL(n);
+ places_rdx = BC_NUM_RDX(places + n->scale) - nrdx;
if (places_rdx) {
bc_num_expand(n, bc_vm_growSize(n->len, places_rdx));
@@ -346,11 +348,11 @@ static void bc_num_extend(BcNum *restrict n, size_t places) {
memset(n->num, 0, BC_NUM_SIZE(places_rdx));
}
- n->rdx += places_rdx;
+ BC_NUM_RDX_SET(n, nrdx + places_rdx);
n->scale += places;
n->len += places_rdx;
- assert(n->rdx == BC_NUM_RDX(n->scale));
+ assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale));
}
static void bc_num_retireMul(BcNum *restrict n, size_t scale,
@@ -360,7 +362,7 @@ static void bc_num_retireMul(BcNum *restrict n, size_t scale,
else bc_num_truncate(n, n->scale - scale);
bc_num_clean(n);
- if (BC_NUM_NONZERO(n)) n->neg = (!neg1 != !neg2);
+ if (BC_NUM_NONZERO(n)) n->rdx = BC_NUM_NEG_VAL(n, !neg1 != !neg2);
}
static void bc_num_split(const BcNum *restrict n, size_t idx,
@@ -373,7 +375,9 @@ static void bc_num_split(const BcNum *restrict n, size_t idx,
b->len = n->len - idx;
a->len = idx;
- a->scale = a->rdx = b->scale = b->rdx = 0;
+ a->scale = b->scale = 0;
+ BC_NUM_RDX_SET(a, 0);
+ BC_NUM_RDX_SET(b, 0);
assert(a->cap >= a->len);
assert(b->cap >= b->len);
@@ -392,7 +396,7 @@ static size_t bc_num_shiftZero(BcNum *restrict n) {
size_t i;
- assert(!n->rdx || BC_NUM_ZERO(n));
+ assert(!BC_NUM_RDX_VAL(n) || BC_NUM_ZERO(n));
for (i = 0; i < n->len && !n->num[i]; ++i);
@@ -438,7 +442,7 @@ static void bc_num_shiftLeft(BcNum *restrict n, size_t places) {
if (!places) return;
if (places > n->scale) {
size_t size = bc_vm_growSize(BC_NUM_RDX(places - n->scale), n->len);
- if (size > SIZE_MAX - 1) bc_vm_err(BC_ERROR_MATH_OVERFLOW);
+ if (size > SIZE_MAX - 1) bc_vm_err(BC_ERR_MATH_OVERFLOW);
}
if (BC_NUM_ZERO(n)) {
if (n->scale >= places) n->scale -= places;
@@ -452,7 +456,9 @@ static void bc_num_shiftLeft(BcNum *restrict n, size_t places) {
if (n->scale) {
- if (n->rdx >= places_rdx) {
+ size_t nrdx = BC_NUM_RDX_VAL(n);
+
+ if (nrdx >= places_rdx) {
size_t mod = n->scale % BC_BASE_DIGS, revdig;
@@ -462,7 +468,7 @@ static void bc_num_shiftLeft(BcNum *restrict n, size_t places) {
if (mod + revdig > BC_BASE_DIGS) places_rdx = 1;
else places_rdx = 0;
}
- else places_rdx -= n->rdx;
+ else places_rdx -= nrdx;
}
if (places_rdx) {
@@ -472,10 +478,13 @@ static void bc_num_shiftLeft(BcNum *restrict n, size_t places) {
n->len += places_rdx;
}
- if (places > n->scale) n->scale = n->rdx = 0;
+ if (places > n->scale) {
+ n->scale = 0;
+ BC_NUM_RDX_SET(n, 0);
+ }
else {
n->scale -= places;
- n->rdx = BC_NUM_RDX(n->scale);
+ BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
}
if (shift) bc_num_shift(n, BC_BASE_DIGS - dig);
@@ -483,7 +492,7 @@ static void bc_num_shiftLeft(BcNum *restrict n, size_t places) {
bc_num_clean(n);
}
-static void bc_num_shiftRight(BcNum *restrict n, size_t places) {
+void bc_num_shiftRight(BcNum *restrict n, size_t places) {
BcBigDig dig;
size_t places_rdx, scale, scale_mod, int_len, expand;
@@ -520,17 +529,18 @@ static void bc_num_shiftRight(BcNum *restrict n, size_t places) {
bc_num_expand(n, bc_vm_growSize(expand, n->len));
memset(n->num + n->len, 0, BC_NUM_SIZE(expand));
n->len += expand;
- n->scale = n->rdx = 0;
+ n->scale = 0;
+ BC_NUM_RDX_SET(n, 0);
if (shift) bc_num_shift(n, dig);
n->scale = scale + places;
- n->rdx = BC_NUM_RDX(n->scale);
+ BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
bc_num_clean(n);
- assert(n->rdx <= n->len && n->len <= n->cap);
- assert(n->rdx == BC_NUM_RDX(n->scale));
+ assert(BC_NUM_RDX_VAL(n) <= n->len && n->len <= n->cap);
+ assert(BC_NUM_RDX_VAL(n) == BC_NUM_RDX(n->scale));
}
static void bc_num_inv(BcNum *a, BcNum *b, size_t scale) {
@@ -550,7 +560,7 @@ static void bc_num_inv(BcNum *a, BcNum *b, size_t scale) {
static void bc_num_intop(const BcNum *a, const BcNum *b, BcNum *restrict c,
BcBigDig *v)
{
- if (BC_ERR(b->rdx)) bc_vm_err(BC_ERROR_MATH_NON_INTEGER);
+ if (BC_ERR(BC_NUM_RDX_VAL(b))) bc_vm_err(BC_ERR_MATH_NON_INTEGER);
bc_num_copy(c, a);
bc_num_bigdig(b, v);
}
@@ -560,8 +570,8 @@ static void bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) {
BcDig *ptr_c, *ptr_l, *ptr_r;
size_t i, min_rdx, max_rdx, diff, a_int, b_int, min_len, max_len, max_int;
- size_t len_l, len_r;
- bool b_neg, do_sub, do_rev_sub, carry;
+ size_t len_l, len_r, ardx, brdx;
+ bool b_neg, do_sub, do_rev_sub, carry, c_neg;
// Because this function doesn't need to use scale (per the bc spec),
// I am hijacking it to say whether it's doing an add or a subtract.
@@ -573,23 +583,25 @@ static void bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) {
}
if (BC_NUM_ZERO(a)) {
bc_num_copy(c, b);
- c->neg = (b->neg != sub);
+ c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(b) != sub);
return;
}
// Invert sign of b if it is to be subtracted. This operation must
// preced the tests for any of the operands being zero.
- b_neg = (b->neg != sub);
+ b_neg = (BC_NUM_NEG(b) != sub);
// Actually add the numbers if their signs are equal, else subtract.
- do_sub = (a->neg != b_neg);
+ do_sub = (BC_NUM_NEG(a) != b_neg);
a_int = bc_num_int(a);
b_int = bc_num_int(b);
max_int = BC_MAX(a_int, b_int);
- min_rdx = BC_MIN(a->rdx, b->rdx);
- max_rdx = BC_MAX(a->rdx, b->rdx);
+ ardx = BC_NUM_RDX_VAL(a);
+ brdx = BC_NUM_RDX_VAL(b);
+ min_rdx = BC_MIN(ardx, brdx);
+ max_rdx = BC_MAX(ardx, brdx);
diff = max_rdx - min_rdx;
max_len = max_int + max_rdx;
@@ -598,7 +610,7 @@ static void bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) {
// Check whether b has to be subtracted from a or a from b.
if (a_int != b_int) do_rev_sub = (a_int < b_int);
- else if (a->rdx > b->rdx)
+ else if (ardx > brdx)
do_rev_sub = (bc_num_compare(a->num + diff, b->num, b->len) < 0);
else
do_rev_sub = (bc_num_compare(a->num, b->num + diff, a->len) <= 0);
@@ -634,9 +646,9 @@ static void bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) {
// If the rdx values of the operands do not match, the result will
// have low end elements that are the positive or negative trailing
// elements of the operand with higher rdx value.
- if ((a->rdx > b->rdx) != do_rev_sub) {
+ if ((ardx > brdx) != do_rev_sub) {
- // !do_rev_sub && a->rdx > b->rdx || do_rev_sub && b->rdx > a->rdx
+ // !do_rev_sub && ardx > brdx || do_rev_sub && brdx > ardx
// The left operand has BcDig values that need to be copied,
// either from a or from b (in case of a reversed subtraction).
memcpy(ptr_c, ptr_l, BC_NUM_SIZE(diff));
@@ -649,14 +661,14 @@ static void bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) {
// or subtracted from zero (in case of a subtraction).
if (do_sub) {
- // do_sub (do_rev_sub && a->rdx > b->rdx ||
- // !do_rev_sub && b->rdx > a->rdx)
+ // do_sub (do_rev_sub && ardx > brdx ||
+ // !do_rev_sub && brdx > ardx)
for (i = 0; i < diff; i++)
ptr_c[i] = bc_num_subDigits(0, ptr_r[i], &carry);
}
else {
- // !do_sub && b->rdx > a->rdx
+ // !do_sub && brdx > ardx
memcpy(ptr_c, ptr_r, BC_NUM_SIZE(diff));
}
@@ -691,9 +703,9 @@ static void bc_num_as(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub) {
// The result has the same sign as a, unless the operation was a
// reverse subtraction (b - a).
- c->neg = (a->neg != (do_sub && do_rev_sub));
+ c_neg = BC_NUM_NEG(a) != (do_sub && do_rev_sub);
+ BC_NUM_RDX_SET_NEG(c, max_rdx, c_neg);
c->len = max_len;
- c->rdx = max_rdx;
c->scale = BC_MAX(a->scale, b->scale);
bc_num_clean(c);
@@ -706,7 +718,7 @@ static void bc_num_m_simp(const BcNum *a, const BcNum *b, BcNum *restrict c)
BcBigDig sum = 0, carry = 0;
assert(sizeof(sum) >= sizeof(BcDig) * 2);
- assert(!a->rdx && !b->rdx);
+ assert(!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b));
clen = bc_vm_growSize(alen, blen);
bc_num_expand(c, bc_vm_growSize(clen, 1));
@@ -751,7 +763,7 @@ static void bc_num_shiftAddSub(BcNum *restrict n, const BcNum *restrict a,
size_t shift, BcNumShiftAddOp op)
{
assert(n->len >= shift + a->len);
- assert(!n->rdx && !a->rdx);
+ assert(!BC_NUM_RDX_VAL(n) && !BC_NUM_RDX_VAL(a));
op(n->num + shift, a->num, a->len);
}
@@ -768,7 +780,7 @@ static void bc_num_k(BcNum *a, BcNum *b, BcNum *restrict c) {
if (BC_NUM_ZERO(a) || BC_NUM_ZERO(b)) return;
if (aone || BC_NUM_ONE(b)) {
bc_num_copy(c, aone ? b : a);
- if ((aone && a->neg) || b->neg) c->neg = !c->neg;
+ if ((aone && BC_NUM_NEG(a)) || BC_NUM_NEG(b)) BC_NUM_NEG_TGL(c);
return;
}
if (a->len < BC_NUM_KARATSUBA_LEN || b->len < BC_NUM_KARATSUBA_LEN) {
@@ -820,6 +832,9 @@ static void bc_num_k(BcNum *a, BcNum *b, BcNum *restrict c) {
if (BC_NUM_NONZERO(&h1) && BC_NUM_NONZERO(&h2)) {
+ assert(BC_NUM_RDX_VALID_NP(h1));
+ assert(BC_NUM_RDX_VALID_NP(h2));
+
bc_num_m(&h1, &h2, &z2, 0);
bc_num_clean(&z2);
@@ -829,6 +844,9 @@ static void bc_num_k(BcNum *a, BcNum *b, BcNum *restrict c) {
if (BC_NUM_NONZERO(&l1) && BC_NUM_NONZERO(&l2)) {
+ assert(BC_NUM_RDX_VALID_NP(l1));
+ assert(BC_NUM_RDX_VALID_NP(l2));
+
bc_num_m(&l1, &l2, &z0, 0);
bc_num_clean(&z0);
@@ -838,10 +856,14 @@ static void bc_num_k(BcNum *a, BcNum *b, BcNum *restrict c) {
if (BC_NUM_NONZERO(&m1) && BC_NUM_NONZERO(&m2)) {
+ assert(BC_NUM_RDX_VALID_NP(m1));
+ assert(BC_NUM_RDX_VALID_NP(m1));
+
bc_num_m(&m1, &m2, &z1, 0);
bc_num_clean(&z1);
- op = (m1.neg != m2.neg) ? bc_num_subArrays : bc_num_addArrays;
+ op = (BC_NUM_NEG_NP(m1) != BC_NUM_NEG_NP(m2)) ?
+ bc_num_subArrays : bc_num_addArrays;
bc_num_shiftAddSub(c, &z1, max2, op);
}
@@ -860,6 +882,9 @@ static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
BcNum cpa, cpb;
size_t ascale, bscale, ardx, brdx, azero = 0, bzero = 0, zero, len, rscale;
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
+
bc_num_zero(c);
ascale = a->scale;
bscale = b->scale;
@@ -885,15 +910,19 @@ static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
bc_num_mulArray(operand, dig, c);
- if (BC_NUM_NONZERO(c)) c->neg = (a->neg != b->neg);
+ if (BC_NUM_NONZERO(c))
+ c->rdx = BC_NUM_NEG_VAL(c, BC_NUM_NEG(a) != BC_NUM_NEG(b));
return;
}
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
+
BC_SIG_LOCK;
- bc_num_init(&cpa, a->len + a->rdx);
- bc_num_init(&cpb, b->len + b->rdx);
+ bc_num_init(&cpa, a->len + BC_NUM_RDX_VAL(a));
+ bc_num_init(&cpb, b->len + BC_NUM_RDX_VAL(b));
BC_SETJMP_LOCKED(err);
@@ -902,12 +931,19 @@ static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
bc_num_copy(&cpa, a);
bc_num_copy(&cpb, b);
- cpa.neg = cpb.neg = false;
+ assert(BC_NUM_RDX_VALID_NP(cpa));
+ assert(BC_NUM_RDX_VALID_NP(cpb));
+
+ BC_NUM_NEG_CLR_NP(cpa);
+ BC_NUM_NEG_CLR_NP(cpb);
- ardx = cpa.rdx * BC_BASE_DIGS;
+ assert(BC_NUM_RDX_VALID_NP(cpa));
+ assert(BC_NUM_RDX_VALID_NP(cpb));
+
+ ardx = BC_NUM_RDX_VAL_NP(cpa) * BC_BASE_DIGS;
bc_num_shiftLeft(&cpa, ardx);
- brdx = cpb.rdx * BC_BASE_DIGS;
+ brdx = BC_NUM_RDX_VAL_NP(cpb) * BC_BASE_DIGS;
bc_num_shiftLeft(&cpb, brdx);
// We need to reset the jump here because azero and bzero are used in the
@@ -936,7 +972,7 @@ static void bc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
bc_num_shiftLeft(c, (len - c->len) * BC_BASE_DIGS);
bc_num_shiftRight(c, ardx + brdx);
- bc_num_retireMul(c, scale, a->neg, b->neg);
+ bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
err:
BC_SIG_MAYLOCK;
@@ -997,7 +1033,7 @@ static void bc_num_d_long(BcNum *restrict a, BcNum *restrict b,
bc_num_expand(c, a->len);
memset(c->num, 0, c->cap * sizeof(BcDig));
- c->rdx = a->rdx;
+ BC_NUM_RDX_SET(c, BC_NUM_RDX_VAL(a));
c->scale = a->scale;
c->len = a->len;
@@ -1030,7 +1066,7 @@ static void bc_num_d_long(BcNum *restrict a, BcNum *restrict b,
memset(c->num, 0, BC_NUM_SIZE(c->cap));
assert(c->scale >= scale);
- rdx = c->rdx - BC_NUM_RDX(scale);
+ rdx = BC_NUM_RDX_VAL(c) - BC_NUM_RDX(scale);
BC_SIG_LOCK;
@@ -1094,27 +1130,27 @@ err:
static void bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
- size_t len;
+ size_t len, cpardx;
BcNum cpa, cpb;
- if (BC_NUM_ZERO(b)) bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
+ if (BC_NUM_ZERO(b)) bc_vm_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
if (BC_NUM_ZERO(a)) {
bc_num_setToZero(c, scale);
return;
}
if (BC_NUM_ONE(b)) {
bc_num_copy(c, a);
- bc_num_retireMul(c, scale, a->neg, b->neg);
+ bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
return;
}
- if (!a->rdx && !b->rdx && b->len == 1 && !scale) {
+ if (!BC_NUM_RDX_VAL(a) && !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale) {
BcBigDig rem;
bc_num_divArray(a, (BcBigDig) b->num[0], c, &rem);
- bc_num_retireMul(c, scale, a->neg, b->neg);
+ bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
return;
}
- len = bc_num_mulReq(a, b, scale);
+ len = bc_num_divReq(a, b, scale);
BC_SIG_LOCK;
@@ -1133,15 +1169,18 @@ static void bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
bc_num_extend(&cpa, (len - cpa.len) * BC_BASE_DIGS);
}
- cpa.scale = cpa.rdx * BC_BASE_DIGS;
+ cpardx = BC_NUM_RDX_VAL_NP(cpa);
+ cpa.scale = cpardx * BC_BASE_DIGS;
bc_num_extend(&cpa, b->scale);
- cpa.rdx -= BC_NUM_RDX(b->scale);
- cpa.scale = cpa.rdx * BC_BASE_DIGS;
+ cpardx = BC_NUM_RDX_VAL_NP(cpa) - BC_NUM_RDX(b->scale);
+ BC_NUM_RDX_SET_NP(cpa, cpardx);
+ cpa.scale = cpardx * BC_BASE_DIGS;
if (scale > cpa.scale) {
bc_num_extend(&cpa, scale);
- cpa.scale = cpa.rdx * BC_BASE_DIGS;
+ cpardx = BC_NUM_RDX_VAL_NP(cpa);
+ cpa.scale = cpardx * BC_BASE_DIGS;
}
if (cpa.cap == cpa.len) bc_num_expand(&cpa, bc_vm_growSize(cpa.len, 1));
@@ -1149,13 +1188,14 @@ static void bc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
// We want an extra zero in front to make things simpler.
cpa.num[cpa.len++] = 0;
- if (cpa.rdx == cpa.len) cpa.len = bc_num_nonzeroLen(&cpa);
- if (cpb.rdx == cpb.len) cpb.len = bc_num_nonzeroLen(&cpb);
- cpb.scale = cpb.rdx = 0;
+ if (cpardx == cpa.len) cpa.len = bc_num_nonzeroLen(&cpa);
+ if (BC_NUM_RDX_VAL_NP(cpb) == cpb.len) cpb.len = bc_num_nonzeroLen(&cpb);
+ cpb.scale = 0;
+ BC_NUM_RDX_SET_NP(cpb, 0);
bc_num_d_long(&cpa, &cpb, c, scale);
- bc_num_retireMul(c, scale, a->neg, b->neg);
+ bc_num_retireMul(c, scale, BC_NUM_NEG(a), BC_NUM_NEG(b));
err:
BC_SIG_MAYLOCK;
@@ -1170,7 +1210,7 @@ static void bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
BcNum temp;
bool neg;
- if (BC_NUM_ZERO(b)) bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
+ if (BC_NUM_ZERO(b)) bc_vm_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
if (BC_NUM_ZERO(a)) {
bc_num_setToZero(c, ts);
bc_num_setToZero(d, ts);
@@ -1189,14 +1229,17 @@ static void bc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
if (scale) scale = ts + 1;
+ assert(BC_NUM_RDX_VALID(c));
+ assert(BC_NUM_RDX_VALID(b));
+
bc_num_m(c, b, &temp, scale);
bc_num_sub(a, &temp, d, scale);
if (ts > d->scale && BC_NUM_NONZERO(d)) bc_num_extend(d, ts - d->scale);
- neg = d->neg;
- bc_num_retireMul(d, ts, a->neg, b->neg);
- d->neg = BC_NUM_NONZERO(d) ? neg : false;
+ neg = BC_NUM_NEG(d);
+ bc_num_retireMul(d, ts, BC_NUM_NEG(a), BC_NUM_NEG(b));
+ d->rdx = BC_NUM_NEG_VAL(d, BC_NUM_NONZERO(d) ? neg : false);
err:
BC_SIG_MAYLOCK;
@@ -1235,29 +1278,29 @@ static void bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
size_t i, powrdx, resrdx;
bool neg, zero;
- if (BC_ERR(b->rdx)) bc_vm_err(BC_ERROR_MATH_NON_INTEGER);
+ if (BC_ERR(BC_NUM_RDX_VAL(b))) bc_vm_err(BC_ERR_MATH_NON_INTEGER);
if (BC_NUM_ZERO(b)) {
bc_num_one(c);
return;
}
if (BC_NUM_ZERO(a)) {
- if (b->neg) bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
+ if (BC_NUM_NEG(b)) bc_vm_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
bc_num_setToZero(c, scale);
return;
}
if (BC_NUM_ONE(b)) {
- if (!b->neg) bc_num_copy(c, a);
+ if (!BC_NUM_NEG(b)) bc_num_copy(c, a);
else bc_num_inv(a, c, scale);
return;
}
BC_SIG_LOCK;
- neg = b->neg;
- b->neg = false;
+ neg = BC_NUM_NEG(b);
+ BC_NUM_NEG_CLR(b);
bc_num_bigdig(b, &pow);
- b->neg = neg;
+ b->rdx = BC_NUM_NEG_VAL(b, neg);
bc_num_createCopy(&copy, a);
@@ -1272,6 +1315,7 @@ static void bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
for (powrdx = a->scale; !(pow & 1); pow >>= 1) {
powrdx <<= 1;
+ assert(BC_NUM_RDX_VALID_NP(copy));
bc_num_mul(&copy, &copy, &copy, powrdx);
}
@@ -1281,10 +1325,13 @@ static void bc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
while (pow >>= 1) {
powrdx <<= 1;
+ assert(BC_NUM_RDX_VALID_NP(copy));
bc_num_mul(&copy, &copy, &copy, powrdx);
if (pow & 1) {
resrdx += powrdx;
+ assert(BC_NUM_RDX_VALID(c));
+ assert(BC_NUM_RDX_VALID_NP(copy));
bc_num_mul(c, &copy, c, resrdx);
}
}
@@ -1344,11 +1391,14 @@ static void bc_num_right(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale) {
static void bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
BcNumBinaryOp op, size_t req)
{
- BcNum num2, *ptr_a, *ptr_b;
+ BcNum *ptr_a, *ptr_b, num2;
bool init = false;
assert(a != NULL && b != NULL && c != NULL && op != NULL);
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
+
BC_SIG_LOCK;
if (c == a) {
@@ -1358,7 +1408,9 @@ static void bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
memcpy(ptr_a, c, sizeof(BcNum));
init = true;
}
- else ptr_a = a;
+ else {
+ ptr_a = a;
+ }
if (c == b) {
@@ -1369,7 +1421,9 @@ static void bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
init = true;
}
}
- else ptr_b = b;
+ else {
+ ptr_b = b;
+ }
if (init) {
@@ -1385,9 +1439,10 @@ static void bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
op(ptr_a, ptr_b, c, scale);
- assert(!c->neg || BC_NUM_NONZERO(c));
- assert(c->rdx <= c->len || !c->len);
- assert(!c->len || c->num[c->len - 1] || c->rdx == c->len);
+ assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
+ assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
+ assert(BC_NUM_RDX_VALID(c));
+ assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
err:
if (init) {
@@ -1397,8 +1452,8 @@ err:
}
}
-#ifndef NDEBUG
-static bool bc_num_strValid(const char *val) {
+#if !defined(NDEBUG) || BC_ENABLE_LIBRARY
+bool bc_num_strValid(const char *restrict val) {
bool radix = false;
size_t i, len = strlen(val);
@@ -1422,7 +1477,7 @@ static bool bc_num_strValid(const char *val) {
return true;
}
-#endif // NDEBUG
+#endif // !defined(NDEBUG) || BC_ENABLE_LIBRARY
static BcBigDig bc_num_parseChar(char c, size_t base_t) {
@@ -1459,8 +1514,8 @@ static void bc_num_parseDecimal(BcNum *restrict n, const char *restrict val) {
n->scale = (size_t) (rdx * (((uintptr_t) (val + len)) -
(((uintptr_t) ptr) + 1)));
- n->rdx = BC_NUM_RDX(n->scale);
+ BC_NUM_RDX_SET(n, BC_NUM_RDX(n->scale));
i = len - (ptr == val ? 0 : i) - rdx;
temp = BC_NUM_ROUND_POW(i);
mod = n->scale % BC_BASE_DIGS;
@@ -1470,7 +1525,11 @@ static void bc_num_parseDecimal(BcNum *restrict n, const char *restrict val) {
bc_num_expand(n, n->len);
memset(n->num, 0, BC_NUM_SIZE(n->len));
- if (zero) n->len = n->rdx = 0;
+ if (zero) {
+ // I think I can set rdx directly to zero here because n should be a
+ // new number with sign set to false.
+ n->len = n->rdx = 0;
+ }
else {
BcBigDig exp, pow;
@@ -1551,6 +1610,8 @@ static void bc_num_parseBase(BcNum *restrict n, const char *restrict val,
for (i += 1, digs = 0; i < len && (c = val[i]); ++i, ++digs) {
+ size_t rdx;
+
v = bc_num_parseChar(c, base);
bc_num_mulArray(&result1, base, &result2);
@@ -1559,7 +1620,9 @@ static void bc_num_parseBase(BcNum *restrict n, const char *restrict val,
bc_num_add(&result2, &temp, &result1, 0);
bc_num_mulArray(m1, base, m2);
- if (m2->len < m2->rdx) m2->len = m2->rdx;
+ rdx = BC_NUM_RDX_VAL(m2);
+
+ if (m2->len < rdx) m2->len = rdx;
ptr = m1;
m1 = m2;
@@ -1589,11 +1652,13 @@ int_err:
BC_LONGJMP_CONT;
}
-static void bc_num_printNewline(void) {
+static inline void bc_num_printNewline(void) {
+#if !BC_ENABLE_LIBRARY
if (vm.nchars >= vm.line_len - 1) {
bc_vm_putchar('\\');
bc_vm_putchar('\n');
}
+#endif // !BC_ENABLE_LIBRARY
}
static void bc_num_putchar(int c) {
@@ -1601,14 +1666,14 @@ static void bc_num_putchar(int c) {
bc_vm_putchar(c);
}
-#if DC_ENABLED
+#if DC_ENABLED && !BC_ENABLE_LIBRARY
static void bc_num_printChar(size_t n, size_t len, bool rdx) {
BC_UNUSED(rdx);
BC_UNUSED(len);
assert(len == 1);
bc_vm_putchar((uchar) n);
}
-#endif // DC_ENABLED
+#endif // DC_ENABLED && !BC_ENABLE_LIBRARY
static void bc_num_printDigits(size_t n, size_t len, bool rdx) {
@@ -1638,11 +1703,11 @@ static void bc_num_printHex(size_t n, size_t len, bool rdx) {
static void bc_num_printDecimal(const BcNum *restrict n) {
- size_t i, j, rdx = n->rdx;
+ size_t i, j, rdx = BC_NUM_RDX_VAL(n);
bool zero = true;
size_t buffer[BC_BASE_DIGS];
- if (n->neg) bc_num_putchar('-');
+ if (BC_NUM_NEG(n)) bc_num_putchar('-');
for (i = n->len - 1; i < n->len; --i) {
@@ -1672,9 +1737,9 @@ static void bc_num_printDecimal(const BcNum *restrict n) {
#if BC_ENABLE_EXTRA_MATH
static void bc_num_printExponent(const BcNum *restrict n, bool eng) {
- bool neg = (n->len <= n->rdx);
+ size_t places, mod, nrdx = BC_NUM_RDX_VAL(n);
+ bool neg = (n->len <= nrdx);
BcNum temp, exp;
- size_t places, mod;
BcDig digs[BC_NUM_BIGDIG_LOG10];
BC_SIG_LOCK;
@@ -1696,7 +1761,7 @@ static void bc_num_printExponent(const BcNum *restrict n, bool eng) {
else break;
}
- places += (n->rdx - (idx + 1)) * BC_BASE_DIGS;
+ places += (nrdx - (idx + 1)) * BC_BASE_DIGS;
mod = places % 3;
if (eng && mod != 0) places += 3 - mod;
@@ -1799,7 +1864,7 @@ static void bc_num_printNum(BcNum *restrict n, BcBigDig base,
BcVec stack;
BcNum intp, fracp1, fracp2, digit, flen1, flen2, *n1, *n2, *temp;
BcBigDig dig = 0, *ptr, acc, exp;
- size_t i, j;
+ size_t i, j, nrdx;
bool radix;
BcDig digit_digs[BC_NUM_BIGDIG_LOG10 + 1];
@@ -1843,10 +1908,12 @@ static void bc_num_printNum(BcNum *restrict n, BcBigDig base,
// happens and bc_num_printFixup() where the inner loop, or actual
// conversion, happens.
+ nrdx = BC_NUM_RDX_VAL(n);
+
BC_SIG_LOCK;
bc_vec_init(&stack, sizeof(BcBigDig), NULL);
- bc_num_init(&fracp1, n->rdx);
+ bc_num_init(&fracp1, nrdx);
bc_num_createCopy(&intp, n);
@@ -1911,7 +1978,7 @@ static void bc_num_printNum(BcNum *restrict n, BcBigDig base,
BC_UNSETJMP;
- bc_num_init(&fracp2, n->rdx);
+ bc_num_init(&fracp2, nrdx);
bc_num_setup(&digit, digit_digs, sizeof(digit_digs) / sizeof(BcDig));
bc_num_init(&flen1, BC_NUM_BIGDIG_LOG10);
bc_num_init(&flen2, BC_NUM_BIGDIG_LOG10);
@@ -1927,13 +1994,16 @@ static void bc_num_printNum(BcNum *restrict n, BcBigDig base,
n2 = &flen2;
fracp2.scale = n->scale;
- fracp2.rdx = BC_NUM_RDX(fracp2.scale);
+ BC_NUM_RDX_SET_NP(fracp2, BC_NUM_RDX(fracp2.scale));
while (bc_num_intDigits(n1) < n->scale + 1) {
bc_num_expand(&fracp2, fracp1.len + 1);
bc_num_mulArray(&fracp1, base, &fracp2);
- if (fracp2.len < fracp2.rdx) fracp2.len = fracp2.rdx;
+
+ nrdx = BC_NUM_RDX_VAL_NP(fracp2);
+
+ if (fracp2.len < nrdx) fracp2.len = nrdx;
// fracp is guaranteed to be non-negative and small enough.
bc_num_bigdig2(&fracp2, &dig);
@@ -1967,11 +2037,11 @@ static void bc_num_printBase(BcNum *restrict n, BcBigDig base) {
size_t width;
BcNumDigitOp print;
- bool neg = n->neg;
+ bool neg = BC_NUM_NEG(n);
if (neg) bc_num_putchar('-');
- n->neg = false;
+ BC_NUM_NEG_CLR(n);
if (base <= BC_NUM_MAX_POSIX_IBASE) {
width = 1;
@@ -1984,14 +2054,14 @@ static void bc_num_printBase(BcNum *restrict n, BcBigDig base) {
}
bc_num_printNum(n, base, width, print);
- n->neg = neg;
+ n->rdx = BC_NUM_NEG_VAL(n, neg);
}
-#if DC_ENABLED
+#if DC_ENABLED && !BC_ENABLE_LIBRARY
void bc_num_stream(BcNum *restrict n, BcBigDig base) {
bc_num_printNum(n, base, 1, bc_num_printChar);
}
-#endif // DC_ENABLED
+#endif // DC_ENABLED && !BC_ENABLE_LIBRARY
void bc_num_setup(BcNum *restrict n, BcDig *restrict num, size_t cap) {
assert(n != NULL);
@@ -2042,7 +2112,7 @@ void bc_num_copy(BcNum *d, const BcNum *s) {
if (d == s) return;
bc_num_expand(d, s->len);
d->len = s->len;
- d->neg = s->neg;
+ // I can just copy directly here.
d->rdx = s->rdx;
d->scale = s->scale;
memcpy(d->num, s->num, BC_NUM_SIZE(d->len));
@@ -2056,7 +2126,7 @@ void bc_num_createCopy(BcNum *d, const BcNum *s) {
void bc_num_createFromBigdig(BcNum *n, BcBigDig val) {
BC_SIG_ASSERT_LOCKED;
- bc_num_init(n, (BC_NUM_BIGDIG_LOG10 - 1) / BC_BASE_DIGS + 1);
+ bc_num_init(n, BC_NUM_BIGDIG_LOG10);
bc_num_bigdig2num(n, val);
}
@@ -2070,7 +2140,7 @@ size_t bc_num_len(const BcNum *restrict n) {
if (BC_NUM_ZERO(n)) return 0;
- if (n->rdx == len) {
+ if (BC_NUM_RDX_VAL(n) == len) {
size_t zero, scale;
@@ -2088,19 +2158,20 @@ size_t bc_num_len(const BcNum *restrict n) {
return len;
}
-void bc_num_parse(BcNum *restrict n, const char *restrict val,
- BcBigDig base, bool letter)
-{
+void bc_num_parse(BcNum *restrict n, const char *restrict val, BcBigDig base) {
+
assert(n != NULL && val != NULL && base);
assert(base >= BC_NUM_MIN_BASE && base <= vm.maxes[BC_PROG_GLOBALS_IBASE]);
assert(bc_num_strValid(val));
- if (letter) {
+ if (!val[1]) {
BcBigDig dig = bc_num_parseChar(val[0], BC_NUM_MAX_LBASE);
bc_num_bigdig2num(n, dig);
}
else if (base == BC_BASE) bc_num_parseDecimal(n, val);
else bc_num_parseBase(n, val, base);
+
+ assert(BC_NUM_RDX_VALID(n));
}
void bc_num_print(BcNum *restrict n, BcBigDig base, bool newline) {
@@ -2113,8 +2184,7 @@ void bc_num_print(BcNum *restrict n, BcBigDig base, bool newline) {
if (BC_NUM_ZERO(n)) bc_num_printHex(0, 1, false);
else if (base == BC_BASE) bc_num_printDecimal(n);
#if BC_ENABLE_EXTRA_MATH
- else if (base == 0 || base == 1)
- bc_num_printExponent(n, base != 0);
+ else if (base == 0 || base == 1) bc_num_printExponent(n, base != 0);
#endif // BC_ENABLE_EXTRA_MATH
else bc_num_printBase(n, base);
@@ -2127,28 +2197,38 @@ void bc_num_bigdig2(const BcNum *restrict n, BcBigDig *result) {
// its preconditions are met. Those preconditions include both parameters
// being non-NULL, n being non-negative, and n being less than vm.max. If
// all of that is true, then we can just convert without worrying about
- // negative errors or overflow. We also don't care about signals because
- // this function should execute in only a few iterations, meaning that
- // ignoring signals here should be fine.
+ // negative errors or overflow.
BcBigDig r = 0;
+ size_t nrdx = BC_NUM_RDX_VAL(n);
assert(n != NULL && result != NULL);
- assert(!n->neg);
+ assert(!BC_NUM_NEG(n));
assert(bc_num_cmp(n, &vm.max) < 0);
- assert(n->len - n->rdx <= 3);
+ assert(n->len - nrdx <= 3);
// There is a small speed win from unrolling the loop here, and since it
// only adds 53 bytes, I decided that it was worth it.
- switch (n->len - n->rdx) {
+ switch (n->len - nrdx) {
+
case 3:
- r = (BcBigDig) n->num[n->rdx + 2];
- // Fallthrough.
+ {
+ r = (BcBigDig) n->num[nrdx + 2];
+ }
+ // Fallthrough.
+ BC_FALLTHROUGH
+
case 2:
- r = r * BC_BASE_POW + (BcBigDig) n->num[n->rdx + 1];
- // Fallthrough.
+ {
+ r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx + 1];
+ }
+ // Fallthrough.
+ BC_FALLTHROUGH
+
case 1:
- r = r * BC_BASE_POW + (BcBigDig) n->num[n->rdx];
+ {
+ r = r * BC_BASE_POW + (BcBigDig) n->num[nrdx];
+ }
}
*result = r;
@@ -2158,9 +2238,9 @@ void bc_num_bigdig(const BcNum *restrict n, BcBigDig *result) {
assert(n != NULL && result != NULL);
- if (BC_ERR(n->neg)) bc_vm_err(BC_ERROR_MATH_NEGATIVE);
+ if (BC_ERR(BC_NUM_NEG(n))) bc_vm_err(BC_ERR_MATH_NEGATIVE);
if (BC_ERR(bc_num_cmp(n, &vm.max) >= 0))
- bc_vm_err(BC_ERROR_MATH_OVERFLOW);
+ bc_vm_err(BC_ERR_MATH_OVERFLOW);
bc_num_bigdig2(n, result);
}
@@ -2187,41 +2267,41 @@ void bc_num_bigdig2num(BcNum *restrict n, BcBigDig val) {
#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
void bc_num_rng(const BcNum *restrict n, BcRNG *rng) {
- BcNum pow, temp, temp2, intn, frac;
+ BcNum temp, temp2, intn, frac;
BcRand state1, state2, inc1, inc2;
- BcDig pow_num[BC_RAND_NUM_SIZE];
-
- bc_num_setup(&pow, pow_num, sizeof(pow_num) / sizeof(BcDig));
+ size_t nrdx = BC_NUM_RDX_VAL(n);
BC_SIG_LOCK;
bc_num_init(&temp, n->len);
bc_num_init(&temp2, n->len);
- bc_num_init(&frac, n->rdx);
+ bc_num_init(&frac, nrdx);
bc_num_init(&intn, bc_num_int(n));
BC_SETJMP_LOCKED(err);
BC_SIG_UNLOCK;
- bc_num_mul(&vm.max, &vm.max, &pow, 0);
+ assert(BC_NUM_RDX_VALID_NP(vm.max));
- memcpy(frac.num, n->num, BC_NUM_SIZE(n->rdx));
- frac.len = n->rdx;
- frac.rdx = n->rdx;
+ memcpy(frac.num, n->num, BC_NUM_SIZE(nrdx));
+ frac.len = nrdx;
+ BC_NUM_RDX_SET_NP(frac, nrdx);
frac.scale = n->scale;
- bc_num_mul(&frac, &pow, &temp, 0);
+ assert(BC_NUM_RDX_VALID_NP(frac));
+ assert(BC_NUM_RDX_VALID_NP(vm.max2));
+
+ bc_num_mul(&frac, &vm.max2, &temp, 0);
bc_num_truncate(&temp, temp.scale);
bc_num_copy(&frac, &temp);
- memcpy(intn.num, n->num + n->rdx, BC_NUM_SIZE(bc_num_int(n)));
+ memcpy(intn.num, n->num + nrdx, BC_NUM_SIZE(bc_num_int(n)));
intn.len = bc_num_int(n);
// This assert is here because it has to be true. It is also here to justify
- // the use of BC_ERROR_SIGNAL_ONLY() on each of the divmod's and mod's
- // below.
+ // the use of BC_ERR_SIGNAL_ONLY() on each of the divmod's and mod's below.
assert(BC_NUM_NONZERO(&vm.max));
if (BC_NUM_NONZERO(&frac)) {
@@ -2271,8 +2351,7 @@ err:
void bc_num_createFromRNG(BcNum *restrict n, BcRNG *rng) {
BcRand s1, s2, i1, i2;
- BcNum pow, conv, temp1, temp2, temp3;
- BcDig pow_num[BC_RAND_NUM_SIZE];
+ BcNum conv, temp1, temp2, temp3;
BcDig temp1_num[BC_RAND_NUM_SIZE], temp2_num[BC_RAND_NUM_SIZE];
BcDig conv_num[BC_NUM_BIGDIG_LOG10];
@@ -2284,35 +2363,36 @@ void bc_num_createFromRNG(BcNum *restrict n, BcRNG *rng) {
BC_SIG_UNLOCK;
- bc_num_setup(&pow, pow_num, sizeof(pow_num) / sizeof(BcDig));
bc_num_setup(&temp1, temp1_num, sizeof(temp1_num) / sizeof(BcDig));
bc_num_setup(&temp2, temp2_num, sizeof(temp2_num) / sizeof(BcDig));
bc_num_setup(&conv, conv_num, sizeof(conv_num) / sizeof(BcDig));
// This assert is here because it has to be true. It is also here to justify
- // the assumption that pow is not zero.
+ // the assumption that vm.max2 is not zero.
assert(BC_NUM_NONZERO(&vm.max));
- bc_num_mul(&vm.max, &vm.max, &pow, 0);
-
- // Because this is true, we can just use BC_ERROR_SIGNAL_ONLY() below when
- // dividing by pow.
- assert(BC_NUM_NONZERO(&pow));
+ // Because this is true, we can just use BC_ERR_SIGNAL_ONLY() below when
+ // dividing by vm.max2.
+ assert(BC_NUM_NONZERO(&vm.max2));
bc_rand_getRands(rng, &s1, &s2, &i1, &i2);
bc_num_bigdig2num(&conv, (BcBigDig) s2);
+ assert(BC_NUM_RDX_VALID_NP(conv));
+
bc_num_mul(&conv, &vm.max, &temp1, 0);
bc_num_bigdig2num(&conv, (BcBigDig) s1);
bc_num_add(&conv, &temp1, &temp2, 0);
- bc_num_div(&temp2, &pow, &temp3, BC_RAND_STATE_BITS);
+ bc_num_div(&temp2, &vm.max2, &temp3, BC_RAND_STATE_BITS);
bc_num_bigdig2num(&conv, (BcBigDig) i2);
+ assert(BC_NUM_RDX_VALID_NP(conv));
+
bc_num_mul(&conv, &vm.max, &temp1, 0);
bc_num_bigdig2num(&conv, (BcBigDig) i1);
@@ -2321,6 +2401,8 @@ void bc_num_createFromRNG(BcNum *restrict n, BcRNG *rng) {
bc_num_add(&temp2, &temp3, n, 0);
+ assert(BC_NUM_RDX_VALID(n));
+
err:
BC_SIG_MAYLOCK;
bc_num_free(&temp3);
@@ -2340,8 +2422,8 @@ void bc_num_irand(const BcNum *restrict a, BcNum *restrict b,
assert(a != b);
- if (BC_ERR(a->neg)) bc_vm_err(BC_ERROR_MATH_NEGATIVE);
- if (BC_ERR(a->rdx)) bc_vm_err(BC_ERROR_MATH_NON_INTEGER);
+ if (BC_ERR(BC_NUM_NEG(a))) bc_vm_err(BC_ERR_MATH_NEGATIVE);
+ if (BC_ERR(BC_NUM_RDX_VAL(a))) bc_vm_err(BC_ERR_MATH_NON_INTEGER);
if (BC_NUM_ZERO(a) || BC_NUM_ONE(a)) return;
cmp = bc_num_cmp(a, &vm.max);
@@ -2396,8 +2478,7 @@ void bc_num_irand(const BcNum *restrict a, BcNum *restrict b,
c2 = &cp2;
// This assert is here because it has to be true. It is also here to justify
- // the use of BC_ERROR_SIGNAL_ONLY() on each of the divmod's and mod's
- // below.
+ // the use of BC_ERR_SIGNAL_ONLY() on each of the divmod's and mod's below.
assert(BC_NUM_NONZERO(&vm.max));
while (BC_NUM_NONZERO(c1)) {
@@ -2429,11 +2510,17 @@ void bc_num_irand(const BcNum *restrict a, BcNum *restrict b,
bc_num_bigdig2num(&rand, r);
+ assert(BC_NUM_RDX_VALID_NP(rand));
+ assert(BC_NUM_RDX_VALID(p1));
+
bc_num_mul(&rand, p1, p2, 0);
bc_num_add(p2, t1, t2, 0);
if (BC_NUM_NONZERO(c2)) {
+ assert(BC_NUM_RDX_VALID_NP(vm.max));
+ assert(BC_NUM_RDX_VALID(p1));
+
bc_num_mul(&vm.max, p1, p2, 0);
tmp = p1;
@@ -2454,6 +2541,8 @@ void bc_num_irand(const BcNum *restrict a, BcNum *restrict b,
bc_num_copy(b, t1);
bc_num_clean(b);
+ assert(BC_NUM_RDX_VALID(b));
+
err:
BC_SIG_MAYLOCK;
bc_num_free(&pow);
@@ -2473,11 +2562,11 @@ size_t bc_num_addReq(const BcNum *a, const BcNum *b, size_t scale) {
BC_UNUSED(scale);
- ardx = a->rdx;
+ ardx = BC_NUM_RDX_VAL(a);
aint = bc_num_int(a);
assert(aint <= a->len && ardx <= a->len);
- brdx = b->rdx;
+ brdx = BC_NUM_RDX_VAL(b);
bint = bc_num_int(b);
assert(bint <= b->len && brdx <= b->len);
@@ -2489,13 +2578,22 @@ size_t bc_num_addReq(const BcNum *a, const BcNum *b, size_t scale) {
size_t bc_num_mulReq(const BcNum *a, const BcNum *b, size_t scale) {
size_t max, rdx;
- rdx = bc_vm_growSize(a->rdx, b->rdx);
+ rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));
max = BC_NUM_RDX(scale);
max = bc_vm_growSize(BC_MAX(max, rdx), 1);
rdx = bc_vm_growSize(bc_vm_growSize(bc_num_int(a), bc_num_int(b)), max);
return rdx;
}
+size_t bc_num_divReq(const BcNum *a, const BcNum *b, size_t scale) {
+ size_t max, rdx;
+ rdx = bc_vm_growSize(BC_NUM_RDX_VAL(a), BC_NUM_RDX_VAL(b));
+ max = BC_NUM_RDX(scale);
+ max = bc_vm_growSize(BC_MAX(max, rdx), 1);
+ rdx = bc_vm_growSize(bc_num_int(a), max);
+ return rdx;
+}
+
size_t bc_num_powReq(const BcNum *a, const BcNum *b, size_t scale) {
BC_UNUSED(scale);
return bc_vm_growSize(bc_vm_growSize(a->len, b->len), 1);
@@ -2504,44 +2602,62 @@ size_t bc_num_powReq(const BcNum *a, const BcNum *b, size_t scale) {
#if BC_ENABLE_EXTRA_MATH
size_t bc_num_placesReq(const BcNum *a, const BcNum *b, size_t scale) {
BC_UNUSED(scale);
- return a->len + b->len - a->rdx - b->rdx;
+ return a->len + b->len - BC_NUM_RDX_VAL(a) - BC_NUM_RDX_VAL(b);
}
#endif // BC_ENABLE_EXTRA_MATH
void bc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
bc_num_binary(a, b, c, false, bc_num_as, bc_num_addReq(a, b, scale));
}
void bc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
bc_num_binary(a, b, c, true, bc_num_as, bc_num_addReq(a, b, scale));
}
void bc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
bc_num_binary(a, b, c, scale, bc_num_m, bc_num_mulReq(a, b, scale));
}
void bc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
- bc_num_binary(a, b, c, scale, bc_num_d, bc_num_mulReq(a, b, scale));
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
+ bc_num_binary(a, b, c, scale, bc_num_d, bc_num_divReq(a, b, scale));
}
void bc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
- bc_num_binary(a, b, c, scale, bc_num_rem, bc_num_mulReq(a, b, scale));
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
+ bc_num_binary(a, b, c, scale, bc_num_rem, bc_num_divReq(a, b, scale));
}
void bc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
bc_num_binary(a, b, c, scale, bc_num_p, bc_num_powReq(a, b, scale));
}
#if BC_ENABLE_EXTRA_MATH
void bc_num_places(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
bc_num_binary(a, b, c, scale, bc_num_place, bc_num_placesReq(a, b, scale));
}
void bc_num_lshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
bc_num_binary(a, b, c, scale, bc_num_left, bc_num_placesReq(a, b, scale));
}
void bc_num_rshift(BcNum *a, BcNum *b, BcNum *c, size_t scale) {
+ assert(BC_NUM_RDX_VALID(a));
+ assert(BC_NUM_RDX_VALID(b));
bc_num_binary(a, b, c, scale, bc_num_right, bc_num_placesReq(a, b, scale));
}
#endif // BC_ENABLE_EXTRA_MATH
@@ -2554,13 +2670,13 @@ void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
assert(a != NULL && b != NULL && a != b);
- if (BC_ERR(a->neg)) bc_vm_err(BC_ERROR_MATH_NEGATIVE);
+ if (BC_ERR(BC_NUM_NEG(a))) bc_vm_err(BC_ERR_MATH_NEGATIVE);
if (a->scale > scale) scale = a->scale;
len = bc_vm_growSize(bc_num_intDigits(a), 1);
rdx = BC_NUM_RDX(scale);
- req = bc_vm_growSize(BC_MAX(rdx, a->rdx), len >> 1);
+ req = bc_vm_growSize(BC_MAX(rdx, BC_NUM_RDX_VAL(a)), len >> 1);
BC_SIG_LOCK;
@@ -2568,6 +2684,9 @@ void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
BC_SIG_UNLOCK;
+ assert(a != NULL && b != NULL && a != b);
+ assert(a->num != NULL && b->num != NULL);
+
if (BC_NUM_ZERO(a)) {
bc_num_setToZero(b, scale);
return;
@@ -2579,7 +2698,7 @@ void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
}
rdx = BC_NUM_RDX(scale);
- rdx = BC_MAX(rdx, a->rdx);
+ rdx = BC_MAX(rdx, BC_NUM_RDX_VAL(a));
len = bc_vm_growSize(a->len, rdx);
BC_SIG_LOCK;
@@ -2591,7 +2710,7 @@ void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
bc_num_one(&half);
half.num[0] = BC_BASE_POW / 2;
half.len = 1;
- half.rdx = 1;
+ BC_NUM_RDX_SET_NP(half, 1);
half.scale = 1;
bc_num_init(&f, len);
@@ -2616,6 +2735,7 @@ void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
bc_num_shiftLeft(x0, pow / 2);
}
+ // I can set the rdx here directly because neg should be false.
x0->scale = x0->rdx = digs = digs1 = digs2 = 0;
resscale = (scale + BC_BASE_DIGS) + 2;
@@ -2625,6 +2745,10 @@ void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
bc_num_div(a, x0, &f, resscale);
bc_num_add(x0, &f, &fprime, resscale);
+
+ assert(BC_NUM_RDX_VALID_NP(fprime));
+ assert(BC_NUM_RDX_VALID_NP(half));
+
bc_num_mul(&fprime, &half, x1, resscale);
temp = x0;
@@ -2635,9 +2759,10 @@ void bc_num_sqrt(BcNum *restrict a, BcNum *restrict b, size_t scale) {
bc_num_copy(b, x0);
if (b->scale > scale) bc_num_truncate(b, b->scale - scale);
- assert(!b->neg || BC_NUM_NONZERO(b));
- assert(b->rdx <= b->len || !b->len);
- assert(!b->len || b->num[b->len - 1] || b->rdx == b->len);
+ assert(!BC_NUM_NEG(b) || BC_NUM_NONZERO(b));
+ assert(BC_NUM_RDX_VALID(b));
+ assert(BC_NUM_RDX_VAL(b) <= b->len || !b->len);
+ assert(!b->len || b->num[b->len - 1] || BC_NUM_RDX_VAL(b) == b->len);
err:
BC_SIG_MAYLOCK;
@@ -2650,9 +2775,9 @@ err:
void bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) {
- BcNum num2, *ptr_a;
- bool init = false;
size_t ts, len;
+ BcNum *ptr_a, num2;
+ bool init = false;
ts = BC_MAX(scale + b->scale, a->scale);
len = bc_num_mulReq(a, b, ts);
@@ -2680,8 +2805,9 @@ void bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) {
bc_num_expand(c, len);
}
- if (BC_NUM_NONZERO(a) && !a->rdx && !b->rdx && b->len == 1 && !scale) {
-
+ if (BC_NUM_NONZERO(a) && !BC_NUM_RDX_VAL(a) &&
+ !BC_NUM_RDX_VAL(b) && b->len == 1 && !scale)
+ {
BcBigDig rem;
bc_num_divArray(ptr_a, (BcBigDig) b->num[0], c, &rem);
@@ -2693,12 +2819,14 @@ void bc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d, size_t scale) {
}
else bc_num_r(ptr_a, b, c, d, scale, ts);
- assert(!c->neg || BC_NUM_NONZERO(c));
- assert(c->rdx <= c->len || !c->len);
- assert(!c->len || c->num[c->len - 1] || c->rdx == c->len);
- assert(!d->neg || BC_NUM_NONZERO(d));
- assert(d->rdx <= d->len || !d->len);
- assert(!d->len || d->num[d->len - 1] || d->rdx == d->len);
+ assert(!BC_NUM_NEG(c) || BC_NUM_NONZERO(c));
+ assert(BC_NUM_RDX_VALID(c));
+ assert(BC_NUM_RDX_VAL(c) <= c->len || !c->len);
+ assert(!c->len || c->num[c->len - 1] || BC_NUM_RDX_VAL(c) == c->len);
+ assert(!BC_NUM_NEG(d) || BC_NUM_NONZERO(d));
+ assert(BC_NUM_RDX_VALID(d));
+ assert(BC_NUM_RDX_VAL(d) <= d->len || !d->len);
+ assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
err:
if (init) {
@@ -2717,10 +2845,10 @@ void bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) {
assert(a != NULL && b != NULL && c != NULL && d != NULL);
assert(a != d && b != d && c != d);
- if (BC_ERR(BC_NUM_ZERO(c))) bc_vm_err(BC_ERROR_MATH_DIVIDE_BY_ZERO);
- if (BC_ERR(b->neg)) bc_vm_err(BC_ERROR_MATH_NEGATIVE);
- if (BC_ERR(a->rdx || b->rdx || c->rdx))
- bc_vm_err(BC_ERROR_MATH_NON_INTEGER);
+ if (BC_ERR(BC_NUM_ZERO(c))) bc_vm_err(BC_ERR_MATH_DIVIDE_BY_ZERO);
+ if (BC_ERR(BC_NUM_NEG(b))) bc_vm_err(BC_ERR_MATH_NEGATIVE);
+ if (BC_ERR(BC_NUM_RDX_VAL(a) || BC_NUM_RDX_VAL(b) || BC_NUM_RDX_VAL(c)))
+ bc_vm_err(BC_ERR_MATH_NON_INTEGER);
bc_num_expand(d, c->len);
@@ -2747,7 +2875,10 @@ void bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) {
// Num two cannot be 0, so no errors.
bc_num_divmod(&exp, &two, &exp, &temp, 0);
- if (BC_NUM_ONE(&temp) && !temp.neg) {
+ if (BC_NUM_ONE(&temp) && !BC_NUM_NEG_NP(temp)) {
+
+ assert(BC_NUM_RDX_VALID(d));
+ assert(BC_NUM_RDX_VALID_NP(base));
bc_num_mul(d, &base, &temp, 0);
@@ -2755,6 +2886,8 @@ void bc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d) {
bc_num_rem(&temp, c, d, 0);
}
+ assert(BC_NUM_RDX_VALID_NP(base));
+
bc_num_mul(&base, &base, &temp, 0);
// We already checked for 0.
@@ -2767,8 +2900,9 @@ err:
bc_num_free(&temp);
bc_num_free(&base);
BC_LONGJMP_CONT;
- assert(!d->neg || d->len);
- assert(!d->len || d->num[d->len - 1] || d->rdx == d->len);
+ assert(!BC_NUM_NEG(d) || d->len);
+ assert(BC_NUM_RDX_VALID(d));
+ assert(!d->len || d->num[d->len - 1] || BC_NUM_RDX_VAL(d) == d->len);
}
#endif // DC_ENABLED
@@ -2797,7 +2931,7 @@ void bc_num_printDigs(const BcDig *n, size_t len, bool emptyline) {
void bc_num_printWithDigs(const BcNum *n, const char *name, bool emptyline) {
bc_file_puts(&vm.fout, name);
bc_file_printf(&vm.fout, " len: %zu, rdx: %zu, scale: %zu\n",
- name, n->len, n->rdx, n->scale);
+ name, n->len, BC_NUM_RDX_VAL(n), n->scale);
bc_num_printDigs(n->num, n->len, emptyline);
}
@@ -2806,13 +2940,13 @@ void bc_num_dump(const char *varname, const BcNum *n) {
ulong i, scale = n->scale;
bc_file_printf(&vm.ferr, "\n%s = %s", varname,
- n->len ? (n->neg ? "-" : "+") : "0 ");
+ n->len ? (BC_NUM_NEG(n) ? "-" : "+") : "0 ");
for (i = n->len - 1; i < n->len; --i) {
- if (i + 1 == n->rdx) bc_file_puts(&vm.ferr, ". ");
+ if (i + 1 == BC_NUM_RDX_VAL(n)) bc_file_puts(&vm.ferr, ". ");
- if (scale / BC_BASE_DIGS != n->rdx - i - 1)
+ if (scale / BC_BASE_DIGS != BC_NUM_RDX_VAL(n) - i - 1)
bc_file_printf(&vm.ferr, "%lu ", (unsigned long) n->num[i]);
else {
@@ -2831,7 +2965,7 @@ void bc_num_dump(const char *varname, const BcNum *n) {
}
bc_file_printf(&vm.ferr, "(%zu | %zu.%zu / %zu) %lu\n",
- n->scale, n->len, n->rdx, n->cap,
+ n->scale, n->len, BC_NUM_RDX_VAL(n), n->cap,
(unsigned long) (void*) n->num);
}
#endif // BC_DEBUG_CODE
diff --git a/src/opt.c b/src/opt.c
index 3a01a2657f15..57cee759af5e 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -62,8 +62,8 @@ static const char* bc_opt_longopt(const BcOptLong *longopts, int c) {
return "NULL";
}
-static void bc_opt_error(BcError err, int c, const char *str) {
- if (err == BC_ERROR_FATAL_OPTION) bc_vm_error(err, 0, str);
+static void bc_opt_error(BcErr err, int c, const char *str) {
+ if (err == BC_ERR_FATAL_OPTION) bc_vm_error(err, 0, str);
else bc_vm_error(err, 0, (int) c, str);
}
@@ -110,10 +110,12 @@ static int bc_opt_parseShort(BcOpt *o, const BcOptLong *longopts) {
str[0] = option[0];
o->optind += 1;
- bc_opt_error(BC_ERROR_FATAL_OPTION, option[0], str);
+ bc_opt_error(BC_ERR_FATAL_OPTION, option[0], str);
}
}
// Fallthrough.
+ BC_FALLTHROUGH
+
case BC_OPT_NONE:
{
if (option[1]) o->subopt += 1;
@@ -136,7 +138,7 @@ static int bc_opt_parseShort(BcOpt *o, const BcOptLong *longopts) {
o->optarg = next;
o->optind += 1;
}
- else bc_opt_error(BC_ERROR_FATAL_OPTION_NO_ARG, option[0],
+ else bc_opt_error(BC_ERR_FATAL_OPTION_NO_ARG, option[0],
bc_opt_longopt(longopts, option[0]));
@@ -215,12 +217,12 @@ int bc_opt_parse(BcOpt *o, const BcOptLong *longopts) {
if ((longopts[i].type == BC_OPT_BC_ONLY && BC_IS_DC) ||
(longopts[i].type == BC_OPT_DC_ONLY && BC_IS_BC))
{
- bc_opt_error(BC_ERROR_FATAL_OPTION, o->optopt, name);
+ bc_opt_error(BC_ERR_FATAL_OPTION, o->optopt, name);
}
if (longopts[i].type == BC_OPT_NONE && arg != NULL)
{
- bc_opt_error(BC_ERROR_FATAL_OPTION_ARG, o->optopt, name);
+ bc_opt_error(BC_ERR_FATAL_OPTION_ARG, o->optopt, name);
}
if (arg != NULL) o->optarg = arg;
@@ -229,7 +231,7 @@ int bc_opt_parse(BcOpt *o, const BcOptLong *longopts) {
o->optarg = o->argv[o->optind];
if (o->optarg != NULL) o->optind += 1;
- else bc_opt_error(BC_ERROR_FATAL_OPTION_NO_ARG,
+ else bc_opt_error(BC_ERR_FATAL_OPTION_NO_ARG,
o->optopt, name);
}
@@ -237,7 +239,7 @@ int bc_opt_parse(BcOpt *o, const BcOptLong *longopts) {
}
}
- bc_opt_error(BC_ERROR_FATAL_OPTION, 0, option);
+ bc_opt_error(BC_ERR_FATAL_OPTION, 0, option);
return -1;
}
diff --git a/src/parse.c b/src/parse.c
index a48f5807e9ce..39b79efdd02f 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -40,9 +40,6 @@
#include <limits.h>
-#include <status.h>
-#include <vector.h>
-#include <lex.h>
#include <parse.h>
#include <program.h>
#include <vm.h>
diff --git a/src/program.c b/src/program.c
index 3c2544f8a61f..f0a67ee194c1 100644
--- a/src/program.c
+++ b/src/program.c
@@ -61,7 +61,7 @@ static inline void bc_program_type_num(BcResult *r, BcNum *n) {
assert(r->t != BC_RESULT_VOID);
#endif // BC_ENABLED
- if (BC_ERR(!BC_PROG_NUM(r, n))) bc_vm_err(BC_ERROR_EXEC_TYPE);
+ if (BC_ERR(!BC_PROG_NUM(r, n))) bc_vm_err(BC_ERR_EXEC_TYPE);
}
#if BC_ENABLED
@@ -72,7 +72,7 @@ static void bc_program_type_match(BcResult *r, BcType t) {
#endif // DC_ENABLED
if (BC_ERR((r->t != BC_RESULT_ARRAY) != (!t)))
- bc_vm_err(BC_ERROR_EXEC_TYPE);
+ bc_vm_err(BC_ERR_EXEC_TYPE);
}
#endif // BC_ENABLED
@@ -270,7 +270,7 @@ static void bc_program_operand(BcProgram *p, BcResult **r,
*r = bc_vec_item_rev(&p->results, idx);
#if BC_ENABLED
- if (BC_ERR((*r)->t == BC_RESULT_VOID)) bc_vm_err(BC_ERROR_EXEC_VOID_VAL);
+ if (BC_ERR((*r)->t == BC_RESULT_VOID)) bc_vm_err(BC_ERR_EXEC_VOID_VAL);
#endif // BC_ENABLED
*n = bc_program_num(p, *r);
@@ -286,7 +286,7 @@ static void bc_program_binPrep(BcProgram *p, BcResult **l, BcNum **ln,
#ifndef BC_PROG_NO_STACK_CHECK
if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 2)))
- bc_vm_err(BC_ERROR_EXEC_STACK);
+ bc_vm_err(BC_ERR_EXEC_STACK);
}
#endif // BC_PROG_NO_STACK_CHECK
@@ -306,7 +306,7 @@ static void bc_program_binPrep(BcProgram *p, BcResult **l, BcNum **ln,
if (lt == (*r)->t && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM))
*ln = bc_program_num(p, *l);
- if (BC_ERR(lt == BC_RESULT_STR)) bc_vm_err(BC_ERROR_EXEC_TYPE);
+ if (BC_ERR(lt == BC_RESULT_STR)) bc_vm_err(BC_ERR_EXEC_TYPE);
}
static void bc_program_binOpPrep(BcProgram *p, BcResult **l, BcNum **ln,
@@ -329,7 +329,7 @@ static void bc_program_assignPrep(BcProgram *p, BcResult **l, BcNum **ln,
lt = (*l)->t;
if (BC_ERR(lt >= min && lt <= BC_RESULT_ONE))
- bc_vm_err(BC_ERROR_EXEC_TYPE);
+ bc_vm_err(BC_ERR_EXEC_TYPE);
#if DC_ENABLED
if(BC_IS_DC) {
@@ -351,7 +351,7 @@ static void bc_program_prep(BcProgram *p, BcResult **r, BcNum **n, size_t idx) {
#ifndef BC_PROG_NO_STACK_CHECK
if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
- bc_vm_err(BC_ERROR_EXEC_STACK);
+ bc_vm_err(BC_ERR_EXEC_STACK);
}
#endif // BC_PROG_NO_STACK_CHECK
@@ -391,7 +391,7 @@ static void bc_program_const(BcProgram *p, const char *code, size_t *bgn) {
}
// bc_num_parse() should only do operations that cannot fail.
- bc_num_parse(&c->num, c->val, base, !c->val[1]);
+ bc_num_parse(&c->num, c->val, base);
c->base = base;
}
@@ -419,6 +419,9 @@ static void bc_program_op(BcProgram *p, uchar inst) {
BC_SIG_UNLOCK;
+ assert(BC_NUM_RDX_VALID(n1));
+ assert(BC_NUM_RDX_VALID(n2));
+
bc_program_ops[idx](n1, n2, &res->d.n, BC_PROG_SCALE(p));
bc_program_retire(p, 1, 2);
@@ -437,7 +440,7 @@ static void bc_program_read(BcProgram *p) {
for (i = 0; i < p->stack.len; ++i) {
BcInstPtr *ip_ptr = bc_vec_item(&p->stack, i);
if (ip_ptr->func == BC_PROG_READ)
- bc_vm_err(BC_ERROR_EXEC_REC_READ);
+ bc_vm_err(BC_ERR_EXEC_REC_READ);
}
BC_SIG_LOCK;
@@ -454,13 +457,13 @@ static void bc_program_read(BcProgram *p) {
bc_vec_npop(&f->code, f->code.len);
s = bc_read_line(&buf, BC_IS_BC ? "read> " : "?> ");
- if (s == BC_STATUS_EOF) bc_vm_err(BC_ERROR_EXEC_READ_EXPR);
+ if (s == BC_STATUS_EOF) bc_vm_err(BC_ERR_EXEC_READ_EXPR);
bc_parse_text(&parse, buf.v);
vm.expr(&parse, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL);
if (BC_ERR(parse.l.t != BC_LEX_NLINE && parse.l.t != BC_LEX_EOF))
- bc_vm_err(BC_ERROR_EXEC_READ_EXPR);
+ bc_vm_err(BC_ERR_EXEC_READ_EXPR);
#if BC_ENABLED
if (BC_G) bc_program_prepGlobals(p);
@@ -495,6 +498,12 @@ exec_err:
static void bc_program_rand(BcProgram *p) {
BcRand rand = bc_rand_int(&p->rng);
bc_program_pushBigdig(p, (BcBigDig) rand, BC_RESULT_TEMP);
+#ifndef NDEBUG
+ {
+ BcResult *r = bc_vec_top(&p->results);
+ assert(BC_NUM_RDX_VALID_NP(r->d.n));
+ }
+#endif // NDEBUG
}
#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
@@ -560,7 +569,7 @@ static void bc_program_print(BcProgram *p, uchar inst, size_t idx) {
#ifndef BC_PROG_NO_STACK_CHECK
if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
- bc_vm_err(BC_ERROR_EXEC_STACK);
+ bc_vm_err(BC_ERR_EXEC_STACK);
}
#endif // BC_PROG_NO_STACK_CHECK
@@ -570,7 +579,7 @@ static void bc_program_print(BcProgram *p, uchar inst, size_t idx) {
#if BC_ENABLED
if (r->t == BC_RESULT_VOID) {
- if (BC_ERR(pop)) bc_vm_err(BC_ERROR_EXEC_VOID_VAL);
+ if (BC_ERR(pop)) bc_vm_err(BC_ERR_EXEC_VOID_VAL);
bc_vec_pop(&p->results);
return;
}
@@ -604,7 +613,7 @@ static void bc_program_print(BcProgram *p, uchar inst, size_t idx) {
void bc_program_negate(BcResult *r, BcNum *n) {
bc_num_copy(&r->d.n, n);
- if (BC_NUM_NONZERO(&r->d.n)) r->d.n.neg = !r->d.n.neg;
+ if (BC_NUM_NONZERO(&r->d.n)) BC_NUM_NEG_TGL_NP(r->d.n);
}
void bc_program_not(BcResult *r, BcNum *n) {
@@ -743,7 +752,7 @@ static void bc_program_copyToVar(BcProgram *p, size_t idx,
if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
- bc_vm_err(BC_ERROR_EXEC_STACK);
+ bc_vm_err(BC_ERR_EXEC_STACK);
assert(BC_PROG_STACK(&p->results, 1));
@@ -768,7 +777,7 @@ static void bc_program_copyToVar(BcProgram *p, size_t idx,
#if DC_ENABLED
if (BC_IS_DC && (ptr->t == BC_RESULT_STR || BC_PROG_STR(n))) {
- if (BC_ERR(!var)) bc_vm_err(BC_ERROR_EXEC_TYPE);
+ if (BC_ERR(!var)) bc_vm_err(BC_ERR_EXEC_TYPE);
bc_program_assignStr(p, ptr, vec, true);
return;
}
@@ -871,6 +880,9 @@ static void bc_program_assign(BcProgram *p, uchar inst) {
if (!use_val)
inst -= (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);
+ assert(BC_NUM_RDX_VALID(l));
+ assert(BC_NUM_RDX_VALID(r));
+
bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, scale);
}
#endif // BC_ENABLED
@@ -882,10 +894,10 @@ static void bc_program_assign(BcProgram *p, uchar inst) {
BcVec *v;
BcBigDig *ptr, *ptr_t, val, max, min;
- BcError e;
+ BcErr e;
bc_num_bigdig(l, &val);
- e = left->t - BC_RESULT_IBASE + BC_ERROR_EXEC_IBASE;
+ e = left->t - BC_RESULT_IBASE + BC_ERR_EXEC_IBASE;
if (sc) {
min = 0;
@@ -940,7 +952,7 @@ static void bc_program_pushVar(BcProgram *p, const char *restrict code,
BcVec *v = bc_program_vec(p, idx, BC_TYPE_VAR);
BcNum *num = bc_vec_top(v);
- if (BC_ERR(!BC_PROG_STACK(v, 2 - copy))) bc_vm_err(BC_ERROR_EXEC_STACK);
+ if (BC_ERR(!BC_PROG_STACK(v, 2 - copy))) bc_vm_err(BC_ERR_EXEC_STACK);
assert(BC_PROG_STACK(v, 2 - copy));
@@ -1058,9 +1070,9 @@ static void bc_program_call(BcProgram *p, const char *restrict code,
ip.func = bc_program_index(code, idx);
f = bc_vec_item(&p->fns, ip.func);
- if (BC_ERR(!f->code.len)) bc_vm_verr(BC_ERROR_EXEC_UNDEF_FUNC, f->name);
+ if (BC_ERR(!f->code.len)) bc_vm_verr(BC_ERR_EXEC_UNDEF_FUNC, f->name);
if (BC_ERR(nparams != f->nparams))
- bc_vm_verr(BC_ERROR_EXEC_PARAMS, f->nparams, nparams);
+ bc_vm_verr(BC_ERR_EXEC_PARAMS, f->nparams, nparams);
ip.len = p->results.len - nparams;
assert(BC_PROG_STACK(&p->results, nparams));
@@ -1073,8 +1085,7 @@ static void bc_program_call(BcProgram *p, const char *restrict code,
bool last = true;
arg = bc_vec_top(&p->results);
- if (BC_ERR(arg->t == BC_RESULT_VOID))
- bc_vm_err(BC_ERROR_EXEC_VOID_VAL);
+ if (BC_ERR(arg->t == BC_RESULT_VOID)) bc_vm_err(BC_ERR_EXEC_VOID_VAL);
a = bc_vec_item(&f->autos, nparams - 1 - i);
@@ -1178,7 +1189,7 @@ static void bc_program_builtin(BcProgram *p, uchar inst) {
#ifndef BC_PROG_NO_STACK_CHECK
if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
- bc_vm_err(BC_ERROR_EXEC_STACK);
+ bc_vm_err(BC_ERR_EXEC_STACK);
}
#endif // BC_PROG_NO_STACK_CHECK
@@ -1203,7 +1214,7 @@ static void bc_program_builtin(BcProgram *p, uchar inst) {
BC_SIG_UNLOCK;
- res->d.n.neg = false;
+ BC_NUM_NEG_CLR_NP(res->d.n);
}
#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
else if (inst == BC_INST_IRAND) {
@@ -1271,7 +1282,7 @@ static void bc_program_divmod(BcProgram *p) {
BcNum *n1, *n2;
size_t req;
- bc_vec_expand(&p->results, p->results.len + 2);
+ bc_vec_grow(&p->results, 2);
// We don't need to update the pointer because
// the capacity is enough due to the line above.
@@ -1299,7 +1310,7 @@ static void bc_program_modexp(BcProgram *p) {
BcResult *r1, *r2, *r3, *res;
BcNum *n1, *n2, *n3;
- if (BC_ERR(!BC_PROG_STACK(&p->results, 3))) bc_vm_err(BC_ERROR_EXEC_STACK);
+ if (BC_ERR(!BC_PROG_STACK(&p->results, 3))) bc_vm_err(BC_ERR_EXEC_STACK);
assert(BC_PROG_STACK(&p->results, 3));
@@ -1346,7 +1357,7 @@ static uchar bc_program_asciifyNum(BcProgram *p, BcNum *n) {
BC_SIG_UNLOCK;
bc_num_truncate(&num, num.scale);
- num.neg = false;
+ BC_NUM_NEG_CLR_NP(num);
// This is guaranteed to not have a divide by 0
// because strmb is equal to UCHAR_MAX + 1.
@@ -1372,7 +1383,7 @@ static void bc_program_asciify(BcProgram *p) {
uchar c;
size_t idx;
- if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_vm_err(BC_ERROR_EXEC_STACK);
+ if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_vm_err(BC_ERR_EXEC_STACK);
assert(BC_PROG_STACK(&p->results, 1));
@@ -1409,7 +1420,7 @@ static void bc_program_printStream(BcProgram *p) {
BcResult *r;
BcNum *n;
- if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_vm_err(BC_ERROR_EXEC_STACK);
+ if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_vm_err(BC_ERR_EXEC_STACK);
assert(BC_PROG_STACK(&p->results, 1));
@@ -1471,7 +1482,7 @@ static void bc_program_execStr(BcProgram *p, const char *restrict code,
assert(p->stack.len == p->tail_calls.len);
- if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_vm_err(BC_ERROR_EXEC_STACK);
+ if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_vm_err(BC_ERR_EXEC_STACK);
assert(BC_PROG_STACK(&p->results, 1));
@@ -1496,7 +1507,7 @@ static void bc_program_execStr(BcProgram *p, const char *restrict code,
n = bc_vec_top(bc_program_vec(p, idx, BC_TYPE_VAR));
else goto exit;
- if (BC_ERR(!BC_PROG_STR(n))) bc_vm_err(BC_ERROR_EXEC_TYPE);
+ if (BC_ERR(!BC_PROG_STR(n))) bc_vm_err(BC_ERR_EXEC_TYPE);
BC_UNSETJMP;
BC_SIG_UNLOCK;
@@ -1832,6 +1843,8 @@ void bc_program_exec(BcProgram *p) {
bc_vec_pop(&p->results);
}
// Fallthrough.
+ BC_FALLTHROUGH
+
case BC_INST_JUMP:
{
idx = bc_program_index(code, &ip->idx);
@@ -2077,7 +2090,7 @@ void bc_program_exec(BcProgram *p) {
#ifndef BC_PROG_NO_STACK_CHECK
if (!BC_IS_BC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
- bc_vm_err(BC_ERROR_EXEC_STACK);
+ bc_vm_err(BC_ERR_EXEC_STACK);
}
#endif // BC_PROG_NO_STACK_CHECK
@@ -2145,7 +2158,7 @@ void bc_program_exec(BcProgram *p) {
case BC_INST_DUPLICATE:
{
if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
- bc_vm_err(BC_ERROR_EXEC_STACK);
+ bc_vm_err(BC_ERR_EXEC_STACK);
assert(BC_PROG_STACK(&p->results, 1));
@@ -2166,7 +2179,7 @@ void bc_program_exec(BcProgram *p) {
BcResult *ptr2;
if (BC_ERR(!BC_PROG_STACK(&p->results, 2)))
- bc_vm_err(BC_ERROR_EXEC_STACK);
+ bc_vm_err(BC_ERR_EXEC_STACK);
assert(BC_PROG_STACK(&p->results, 2));
diff --git a/src/rand/rand.c b/src/rand.c
index b16061d711a1..a66728246fbc 100644
--- a/src/rand/rand.c
+++ b/src/rand.c
@@ -74,7 +74,6 @@
#include <unistd.h>
#include <status.h>
-#include <num.h>
#include <rand.h>
#include <vm.h>
@@ -180,7 +179,7 @@ static ulong bc_rand_frand(void *ptr) {
nread = read(fd, buf, sizeof(ulong));
- if (BC_ERR(nread != sizeof(ulong))) bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ if (BC_ERR(nread != sizeof(ulong))) bc_vm_err(BC_ERR_FATAL_IO_ERR);
return *((ulong*) buf);
}
@@ -278,7 +277,7 @@ static void bc_rand_seedZeroes(BcRNG *r, BcRNGData *rng, size_t idx) {
}
}
-static void bc_rand_srand(BcRNGData *rng) {
+void bc_rand_srand(BcRNGData *rng) {
int fd;
diff --git a/src/read.c b/src/read.c
index 6886a7e13602..45e868c927da 100644
--- a/src/read.c
+++ b/src/read.c
@@ -143,7 +143,7 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) {
BC_SIG_UNLOCK;
- bc_vm_err(BC_ERROR_FATAL_IO_ERR);
+ bc_vm_err(BC_ERR_FATAL_IO_ERR);
}
BC_SIG_UNLOCK;
@@ -177,14 +177,14 @@ BcStatus bc_read_line(BcVec *vec, const char *prompt) {
#endif // BC_ENABLE_HISTORY
if (BC_ERR(bc_read_binary(vec->v, vec->len - 1)))
- bc_vm_verr(BC_ERROR_FATAL_BIN_FILE, bc_program_stdin_name);
+ bc_vm_verr(BC_ERR_FATAL_BIN_FILE, bc_program_stdin_name);
return s;
}
void bc_read_file(const char *path, char **buf) {
- BcError e = BC_ERROR_FATAL_IO_ERR;
+ BcErr e = BC_ERR_FATAL_IO_ERR;
size_t size, r;
struct stat pstat;
int fd;
@@ -194,11 +194,11 @@ void bc_read_file(const char *path, char **buf) {
assert(path != NULL);
fd = open(path, O_RDONLY);
- if (BC_ERR(fd < 0)) bc_vm_verr(BC_ERROR_FATAL_FILE_ERR, path);
+ if (BC_ERR(fd < 0)) bc_vm_verr(BC_ERR_FATAL_FILE_ERR, path);
if (BC_ERR(fstat(fd, &pstat) == -1)) goto malloc_err;
if (BC_ERR(S_ISDIR(pstat.st_mode))) {
- e = BC_ERROR_FATAL_PATH_DIR;
+ e = BC_ERR_FATAL_PATH_DIR;
goto malloc_err;
}
@@ -211,7 +211,7 @@ void bc_read_file(const char *path, char **buf) {
(*buf)[size] = '\0';
if (BC_ERR(bc_read_binary(*buf, size))) {
- e = BC_ERROR_FATAL_BIN_FILE;
+ e = BC_ERR_FATAL_BIN_FILE;
goto read_err;
}
diff --git a/src/vector.c b/src/vector.c
index f45bcb198a25..df6936aaeb76 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -37,12 +37,11 @@
#include <stdlib.h>
#include <string.h>
-#include <status.h>
#include <vector.h>
#include <lang.h>
#include <vm.h>
-static void bc_vec_grow(BcVec *restrict v, size_t n) {
+void bc_vec_grow(BcVec *restrict v, size_t n) {
size_t len, cap = v->cap;
sig_atomic_t lock;
diff --git a/src/vm.c b/src/vm.c
index e15b1398734e..3922b088414f 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -56,13 +56,15 @@
#endif // _WIN32
-#include <status.h>
#include <vector.h>
#include <args.h>
#include <vm.h>
#include <read.h>
#include <bc.h>
+char output_bufs[BC_VM_BUF_SIZE];
+BcVm vm;
+
#if BC_DEBUG_CODE
BC_NORETURN void bc_vm_jmp(const char* f) {
#else // BC_DEBUG_CODE
@@ -84,12 +86,14 @@ BC_NORETURN void bc_vm_jmp(void) {
assert(vm.jmp_bufs.len - (size_t) vm.sig_pop);
#endif // NDEBUG
+ if (vm.jmp_bufs.len == 0) abort();
if (vm.sig_pop) bc_vec_pop(&vm.jmp_bufs);
else vm.sig_pop = 1;
siglongjmp(*((sigjmp_buf*) bc_vec_top(&vm.jmp_bufs)), 1);
}
+#if !BC_ENABLE_LIBRARY
static void bc_vm_sig(int sig) {
// There is already a signal in flight.
@@ -132,8 +136,28 @@ void bc_vm_info(const char* const help) {
bc_file_flush(&vm.fout);
}
+#endif // !BC_ENABLE_LIBRARY
+
+#if BC_ENABLE_LIBRARY
+void bc_vm_handleError(BcErr e) {
+
+ assert(e < BC_ERR_NELEMS);
+ assert(!vm.sig_pop);
+
+ BC_SIG_LOCK;
-void bc_vm_error(BcError e, size_t line, ...) {
+ if (e <= BC_ERR_MATH_DIVIDE_BY_ZERO) {
+ vm.err = (BclError) (e - BC_ERR_MATH_NEGATIVE +
+ BCL_ERROR_MATH_NEGATIVE);
+ }
+ else if (vm.abrt) abort();
+ else if (e == BC_ERR_FATAL_ALLOC_ERR) vm.err = BCL_ERROR_FATAL_ALLOC_ERR;
+ else vm.err = BCL_ERROR_FATAL_UNKNOWN_ERR;
+
+ BC_VM_JMP;
+}
+#else // BC_ENABLE_LIBRARY
+void bc_vm_handleError(BcErr e, size_t line, ...) {
BcStatus s;
va_list args;
@@ -141,11 +165,11 @@ void bc_vm_error(BcError e, size_t line, ...) {
const char* err_type = vm.err_ids[id];
sig_atomic_t lock;
- assert(e < BC_ERROR_NELEMS);
+ assert(e < BC_ERR_NELEMS);
assert(!vm.sig_pop);
#if BC_ENABLED
- if (!BC_S && e >= BC_ERROR_POSIX_START) {
+ if (!BC_S && e >= BC_ERR_POSIX_START) {
if (BC_W) {
// Make sure to not return an error.
id = UCHAR_MAX;
@@ -261,7 +285,7 @@ static void bc_vm_envArgs(const char* const env_args_name) {
buf += 1;
start = buf;
}
- else if (instr) bc_vm_error(BC_ERROR_FATAL_OPTION, 0, start);
+ else if (instr) bc_vm_error(BC_ERR_FATAL_OPTION, 0, start);
}
else buf += 1;
}
@@ -293,6 +317,7 @@ static size_t bc_vm_envLen(const char *var) {
return len;
}
+#endif // BC_ENABLE_LIBRARY
void bc_vm_shutdown(void) {
@@ -308,6 +333,7 @@ void bc_vm_shutdown(void) {
#endif // BC_ENABLE_HISTORY
#ifndef NDEBUG
+#if !BC_ENABLE_LIBRARY
bc_vec_free(&vm.env_args);
free(vm.env_args_buffer);
bc_vec_free(&vm.files);
@@ -315,31 +341,40 @@ void bc_vm_shutdown(void) {
bc_program_free(&vm.prog);
bc_parse_free(&vm.prs);
+#endif // !BC_ENABLE_LIBRARY
- {
- size_t i;
- for (i = 0; i < vm.temps.len; ++i)
- free(((BcNum*) bc_vec_item(&vm.temps, i))->num);
-
- bc_vec_free(&vm.temps);
- }
+ bc_vm_freeTemps();
+ bc_vec_free(&vm.temps);
#endif // NDEBUG
+#if !BC_ENABLE_LIBRARY
bc_file_free(&vm.fout);
bc_file_free(&vm.ferr);
+#endif // !BC_ENABLE_LIBRARY
}
+#if !defined(NDEBUG) || BC_ENABLE_LIBRARY
+void bc_vm_freeTemps(void) {
+
+ size_t i;
+
+ for (i = 0; i < vm.temps.len; ++i) {
+ free(((BcNum*) bc_vec_item(&vm.temps, i))->num);
+ }
+}
+#endif // !defined(NDEBUG) || BC_ENABLE_LIBRARY
+
inline size_t bc_vm_arraySize(size_t n, size_t size) {
size_t res = n * size;
if (BC_ERR(res >= SIZE_MAX || (n != 0 && res / n != size)))
- bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return res;
}
inline size_t bc_vm_growSize(size_t a, size_t b) {
size_t res = a + b;
if (BC_ERR(res >= SIZE_MAX || res < a || res < b))
- bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return res;
}
@@ -351,7 +386,7 @@ void* bc_vm_malloc(size_t n) {
ptr = malloc(n);
- if (BC_ERR(ptr == NULL)) bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ if (BC_ERR(ptr == NULL)) bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return ptr;
}
@@ -364,7 +399,7 @@ void* bc_vm_realloc(void *ptr, size_t n) {
temp = realloc(ptr, n);
- if (BC_ERR(temp == NULL)) bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ if (BC_ERR(temp == NULL)) bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return temp;
}
@@ -377,11 +412,12 @@ char* bc_vm_strdup(const char *str) {
s = strdup(str);
- if (BC_ERR(!s)) bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ if (BC_ERR(!s)) bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return s;
}
+#if !BC_ENABLE_LIBRARY
void bc_vm_printf(const char *fmt, ...) {
va_list args;
@@ -396,12 +432,18 @@ void bc_vm_printf(const char *fmt, ...) {
BC_SIG_UNLOCK;
}
+#endif // !BC_ENABLE_LIBRARY
void bc_vm_putchar(int c) {
+#if BC_ENABLE_LIBRARY
+ bc_vec_pushByte(&vm.out, (uchar) c);
+#else // BC_ENABLE_LIBRARY
bc_file_putchar(&vm.fout, (uchar) c);
vm.nchars = (c == '\n' ? 0 : vm.nchars + 1);
+#endif // BC_ENABLE_LIBRARY
}
+#if !BC_ENABLE_LIBRARY
static void bc_vm_clean(void) {
BcVec *fns = &vm.prog.fns;
@@ -491,7 +533,7 @@ static void bc_vm_endif(void) {
if (good) {
while (BC_PARSE_IF_END(&vm.prs)) bc_vm_process("else {}");
}
- else bc_parse_err(&vm.prs, BC_ERROR_PARSE_BLOCK);
+ else bc_parse_err(&vm.prs, BC_ERR_PARSE_BLOCK);
}
#endif // BC_ENABLED
@@ -604,9 +646,9 @@ restart:
if (!BC_STATUS_IS_ERROR(s)) {
if (BC_ERR(comment))
- bc_parse_err(&vm.prs, BC_ERROR_PARSE_COMMENT);
+ bc_parse_err(&vm.prs, BC_ERR_PARSE_COMMENT);
else if (BC_ERR(string))
- bc_parse_err(&vm.prs, BC_ERROR_PARSE_STRING);
+ bc_parse_err(&vm.prs, BC_ERR_PARSE_STRING);
#if BC_ENABLED
else if (BC_IS_BC) bc_vm_endif();
#endif // BC_ENABLED
@@ -652,7 +694,7 @@ static void bc_vm_defaultMsgs(void) {
for (i = 0; i < BC_ERR_IDX_NELEMS + BC_ENABLED; ++i)
vm.err_ids[i] = bc_errs[i];
- for (i = 0; i < BC_ERROR_NELEMS; ++i) vm.err_msgs[i] = bc_err_msgs[i];
+ for (i = 0; i < BC_ERR_NELEMS; ++i) vm.err_msgs[i] = bc_err_msgs[i];
}
static void bc_vm_gettext(void) {
@@ -683,7 +725,7 @@ static void bc_vm_gettext(void) {
i = 0;
id = bc_err_ids[i];
- for (set = id + 3, msg = 1; i < BC_ERROR_NELEMS; ++i, ++msg) {
+ for (set = id + 3, msg = 1; i < BC_ERR_NELEMS; ++i, ++msg) {
if (id != bc_err_ids[i]) {
msg = 1;
@@ -775,8 +817,8 @@ err:
#endif // NDEBUG
}
-void bc_vm_boot(int argc, char *argv[], const char *env_len,
- const char* const env_args)
+void bc_vm_boot(int argc, char *argv[], const char *env_len,
+ const char* const env_args)
{
int ttyin, ttyout, ttyerr;
struct sigaction sa;
@@ -803,10 +845,7 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
if (BC_TTY) sigaction(SIGHUP, &sa, NULL);
#endif // BC_ENABLE_HISTORY
- memcpy(vm.max_num, bc_num_bigdigMax,
- bc_num_bigdigMax_size * sizeof(BcDig));
- bc_num_setup(&vm.max, vm.max_num, BC_NUM_BIGDIG_LOG10);
- vm.max.len = bc_num_bigdigMax_size;
+ bc_vm_init();
vm.file = NULL;
@@ -822,8 +861,6 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
bc_vec_clear(&vm.files);
bc_vec_clear(&vm.exprs);
- bc_vec_init(&vm.temps, sizeof(BcNum), NULL);
-
bc_program_init(&vm.prog);
bc_parse_init(&vm.prs, &vm.prog, BC_PROG_MAIN);
@@ -842,6 +879,27 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
if (BC_IS_POSIX) vm.flags &= ~(BC_FLAG_G);
#endif // BC_ENABLED
+ BC_SIG_UNLOCK;
+
+ bc_vm_exec();
+}
+#endif // !BC_ENABLE_LIBRARY
+
+void bc_vm_init(void) {
+
+ BC_SIG_ASSERT_LOCKED;
+
+ memcpy(vm.max_num, bc_num_bigdigMax,
+ bc_num_bigdigMax_size * sizeof(BcDig));
+ memcpy(vm.max2_num, bc_num_bigdigMax2,
+ bc_num_bigdigMax2_size * sizeof(BcDig));
+ bc_num_setup(&vm.max, vm.max_num, BC_NUM_BIGDIG_LOG10);
+ bc_num_setup(&vm.max2, vm.max2_num, BC_NUM_BIGDIG_LOG10);
+ vm.max.len = bc_num_bigdigMax_size;
+ vm.max2.len = bc_num_bigdigMax2_size;
+
+ bc_vec_init(&vm.temps, sizeof(BcNum), NULL);
+
vm.maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_POSIX_IBASE;
vm.maxes[BC_PROG_GLOBALS_OBASE] = BC_MAX_OBASE;
vm.maxes[BC_PROG_GLOBALS_SCALE] = BC_MAX_SCALE;
@@ -851,11 +909,11 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
#if BC_ENABLED
+#if !BC_ENABLE_LIBRARY
if (BC_IS_BC && !BC_IS_POSIX)
+#endif // !BC_ENABLE_LIBRARY
+ {
vm.maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_IBASE;
+ }
#endif // BC_ENABLED
-
- BC_SIG_UNLOCK;
-
- bc_vm_exec();
}