diff options
author | Stefan Eßer <se@FreeBSD.org> | 2020-11-26 17:27:07 +0000 |
---|---|---|
committer | Stefan Eßer <se@FreeBSD.org> | 2020-11-26 17:27:07 +0000 |
commit | 2e4772e82335c32e07d0605e5edefb0ac6ea857b (patch) | |
tree | d7a054971d1ea18056d0ddb9e0bf0aeb93fb274f /src | |
parent | 907a6834f73ccf2839853eb67a29726275ed04b4 (diff) |
Notes
Diffstat (limited to 'src')
-rw-r--r-- | src/args.c | 6 | ||||
-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.c | 45 | ||||
-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.c | 6 | ||||
-rw-r--r-- | src/history.c (renamed from src/history/history.c) | 15 | ||||
-rw-r--r-- | src/lang.c | 2 | ||||
-rw-r--r-- | src/lex.c | 11 | ||||
-rw-r--r-- | src/library.c | 1183 | ||||
-rw-r--r-- | src/main.c | 3 | ||||
-rw-r--r-- | src/num.c | 562 | ||||
-rw-r--r-- | src/opt.c | 18 | ||||
-rw-r--r-- | src/parse.c | 3 | ||||
-rw-r--r-- | src/program.c | 83 | ||||
-rw-r--r-- | src/rand.c (renamed from src/rand/rand.c) | 5 | ||||
-rw-r--r-- | src/read.c | 12 | ||||
-rw-r--r-- | src/vector.c | 3 | ||||
-rw-r--r-- | src/vm.c | 126 |
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(©, 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(©, ©, ©, 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(©, ©, ©, powrdx); if (pow & 1) { resrdx += powrdx; + assert(BC_NUM_RDX_VALID(c)); + assert(BC_NUM_RDX_VALID_NP(copy)); bc_num_mul(c, ©, 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; @@ -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(); } |