summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/args.c8
-rw-r--r--src/bc/bc.c4
-rw-r--r--src/bc/lex.c4
-rw-r--r--src/bc/parse.c56
-rw-r--r--src/data.c81
-rw-r--r--src/dc/dc.c4
-rw-r--r--src/dc/lex.c4
-rw-r--r--src/dc/parse.c6
-rw-r--r--src/file.c4
-rw-r--r--src/history/history.c12
-rw-r--r--src/lang.c41
-rw-r--r--src/lex.c4
-rw-r--r--src/main.c4
-rw-r--r--src/num.c9
-rw-r--r--src/opt.c8
-rw-r--r--src/parse.c25
-rw-r--r--src/program.c218
-rw-r--r--src/rand/rand.c10
-rw-r--r--src/read.c29
-rw-r--r--src/vector.c74
-rw-r--r--src/vm.c123
21 files changed, 424 insertions, 304 deletions
diff --git a/src/args.c b/src/args.c
index d3735178fc48c..1626ad4944e4e 100644
--- a/src/args.c
+++ b/src/args.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -184,7 +184,7 @@ void bc_args(int argc, char *argv[]) {
#if DC_ENABLED
case 'x':
{
- assert(!BC_IS_BC);
+ assert(BC_IS_DC);
vm.flags |= DC_FLAG_X;
break;
}
@@ -205,7 +205,7 @@ void bc_args(int argc, char *argv[]) {
if (version) bc_vm_info(NULL);
if (do_exit) exit((int) vm.status);
- if (vm.exprs.len > 1 || !BC_IS_BC) vm.flags |= BC_FLAG_Q;
+ if (vm.exprs.len > 1 || BC_IS_DC) vm.flags |= BC_FLAG_Q;
if (opts.optind < (size_t) argc)
bc_vec_init(&vm.files, sizeof(char*), NULL);
diff --git a/src/bc/bc.c b/src/bc/bc.c
index 86d8f81dd4011..ef0fc3d6865dc 100644
--- a/src/bc/bc.c
+++ b/src/bc/bc.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
diff --git a/src/bc/lex.c b/src/bc/lex.c
index d4c6bd4c192e8..cc780e0d6278b 100644
--- a/src/bc/lex.c
+++ b/src/bc/lex.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
diff --git a/src/bc/parse.c b/src/bc/parse.c
index fb00447ee6bca..2aa9d97468ffb 100644
--- a/src/bc/parse.c
+++ b/src/bc/parse.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -399,8 +399,10 @@ static void bc_parse_incdec(BcParse *p, BcInst *prev, bool *can_assign,
// right here, we need to increment this.
*nexs = *nexs + 1;
- if (type == BC_LEX_NAME)
- bc_parse_name(p, prev, can_assign, flags | BC_PARSE_NOCALL);
+ if (type == BC_LEX_NAME) {
+ uint8_t flags2 = flags & ~BC_PARSE_ARRAY;
+ bc_parse_name(p, prev, can_assign, flags2 | BC_PARSE_NOCALL);
+ }
else if (type >= BC_LEX_KW_LAST && type <= BC_LEX_KW_OBASE) {
bc_parse_push(p, type - BC_LEX_KW_LAST + BC_INST_LAST);
bc_lex_next(&p->l);
@@ -1006,24 +1008,24 @@ static void bc_parse_stmt(BcParse *p) {
case BC_LEX_KW_LENGTH:
case BC_LEX_KW_OBASE:
case BC_LEX_KW_SCALE:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_SEED:
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_SQRT:
case BC_LEX_KW_ABS:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_IRAND:
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_READ:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_RAND:
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_MAXIBASE:
case BC_LEX_KW_MAXOBASE:
case BC_LEX_KW_MAXSCALE:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_MAXRAND:
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
{
bc_parse_expr_status(p, BC_PARSE_PRINT, bc_parse_next_expr);
break;
@@ -1092,9 +1094,9 @@ static void bc_parse_stmt(BcParse *p) {
bc_vm_printf("BC_STRING_MAX = %lu\n", BC_MAX_STRING);
bc_vm_printf("BC_NAME_MAX = %lu\n", BC_MAX_NAME);
bc_vm_printf("BC_NUM_MAX = %lu\n", BC_MAX_NUM);
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
bc_vm_printf("BC_RAND_MAX = %lu\n", BC_MAX_RAND);
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
bc_vm_printf("MAX Exponent = %lu\n", BC_MAX_EXP);
bc_vm_printf("Number of vars = %lu\n", BC_MAX_VARS);
@@ -1161,7 +1163,8 @@ void bc_parse_parse(BcParse *p) {
exit:
BC_SIG_MAYLOCK;
- if (BC_ERR((vm.status && vm.status != BC_STATUS_QUIT))) bc_parse_reset(p);
+ if (BC_ERR(((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig)))
+ bc_parse_reset(p);
BC_LONGJMP_CONT;
}
@@ -1212,7 +1215,7 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
// I can just add the instruction because
// negative will already be taken care of.
bc_parse_push(p, BC_INST_TRUNC);
- rprn = can_assign = false;
+ rprn = can_assign = incdec = false;
get_token = true;
flags &= ~(BC_PARSE_ARRAY);
break;
@@ -1355,9 +1358,9 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_KW_IBASE:
case BC_LEX_KW_LAST:
case BC_LEX_KW_OBASE:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_SEED:
-#endif // BC_ENABLE_EXTRA_MATH
+#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);
@@ -1376,9 +1379,9 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
case BC_LEX_KW_LENGTH:
case BC_LEX_KW_SQRT:
case BC_LEX_KW_ABS:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_IRAND:
-#endif // BC_ENABLE_EXTRA_MATH
+#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);
@@ -1392,15 +1395,15 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
}
case BC_LEX_KW_READ:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_RAND:
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_MAXIBASE:
case BC_LEX_KW_MAXOBASE:
case BC_LEX_KW_MAXSCALE:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_LEX_KW_MAXRAND:
-#endif // BC_ENABLE_EXTRA_MATH
+#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);
@@ -1455,6 +1458,8 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
nexprs -= !BC_PARSE_OP_PREFIX(top);
bc_vec_pop(&p->ops);
+
+ incdec = false;
}
if (BC_ERR(nexprs != 1)) bc_parse_err(p, BC_ERROR_PARSE_EXPR);
@@ -1482,7 +1487,8 @@ static BcParseStatus bc_parse_expr_err(BcParse *p, uint8_t flags,
inst != BC_INST_ASSIGN_PLUS);
}
- if (inst >= BC_INST_ASSIGN_PLUS_NO_VAL && inst <= BC_INST_ASSIGN_NO_VAL)
+ if (inst >= BC_INST_ASSIGN_POWER_NO_VAL &&
+ inst <= BC_INST_ASSIGN_NO_VAL)
{
bc_vec_pop(&p->func->code);
if (incdec) bc_parse_push(p, BC_INST_ONE);
diff --git a/src/data.c b/src/data.c
index 3dae137634709..2556f795eed6d 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -588,6 +588,7 @@ const char* bc_inst_names[] = {
"BC_INST_ARRAY",
#endif // BC_ENABLED
+ "BC_INST_ZERO",
"BC_INST_ONE",
#if BC_ENABLED
@@ -663,11 +664,11 @@ const char* bc_inst_names[] = {
};
#endif // BC_DEBUG_CODE
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
const BcRandState bc_rand_multiplier = BC_RAND_MULTIPLIER;
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
#if BC_ENABLED
const BcLexKeyword bc_lex_kws[] = {
@@ -685,27 +686,27 @@ const BcLexKeyword bc_lex_kws[] = {
BC_LEX_KW_ENTRY("ibase", 5, true),
BC_LEX_KW_ENTRY("obase", 5, true),
BC_LEX_KW_ENTRY("scale", 5, true),
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_ENTRY("seed", 4, false),
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_ENTRY("length", 6, true),
BC_LEX_KW_ENTRY("print", 5, false),
BC_LEX_KW_ENTRY("sqrt", 4, true),
BC_LEX_KW_ENTRY("abs", 3, false),
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_ENTRY("irand", 5, false),
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_ENTRY("quit", 4, true),
BC_LEX_KW_ENTRY("read", 4, false),
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_ENTRY("rand", 4, false),
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_ENTRY("maxibase", 8, false),
BC_LEX_KW_ENTRY("maxobase", 8, false),
BC_LEX_KW_ENTRY("maxscale", 8, false),
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_ENTRY("maxrand", 7, false),
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_ENTRY("else", 4, false),
};
@@ -719,7 +720,7 @@ const uint8_t bc_parse_exprs[] = {
BC_PARSE_EXPR_ENTRY(false, false, true, true, true, true, true, true),
BC_PARSE_EXPR_ENTRY(true, true, true, true, true, true, true, true),
BC_PARSE_EXPR_ENTRY(true, true, true, true, true, true, true, true),
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_PARSE_EXPR_ENTRY(true, true, true, true, true, true, true, true),
BC_PARSE_EXPR_ENTRY(true, true, false, false, true, true, false, false),
BC_PARSE_EXPR_ENTRY(false, false, false, false, false, true, true, false),
@@ -727,7 +728,14 @@ const uint8_t bc_parse_exprs[] = {
BC_PARSE_EXPR_ENTRY(false, true, true, true, true, true, true, false),
BC_PARSE_EXPR_ENTRY(true, true, true, false, true, true, true, true),
BC_PARSE_EXPR_ENTRY(true, true, false, 0, 0, 0, 0, 0)
-#else // BC_ENABLE_EXTRA_MATH
+#elif BC_ENABLE_EXTRA_MATH // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
+ BC_PARSE_EXPR_ENTRY(true, true, true, true, true, true, true, true),
+ BC_PARSE_EXPR_ENTRY(true, true, false, false, true, true, false, false),
+ BC_PARSE_EXPR_ENTRY(false, false, false, false, false, true, true, false),
+ BC_PARSE_EXPR_ENTRY(false, false, false, false, false, false, false, false),
+ BC_PARSE_EXPR_ENTRY(false, true, true, true, true, true, false, true),
+ BC_PARSE_EXPR_ENTRY(true, false, true, true, true, true, false, 0),
+#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_PARSE_EXPR_ENTRY(true, true, true, false, false, true, true, false),
BC_PARSE_EXPR_ENTRY(false, false, false, false, false, false, true, true),
BC_PARSE_EXPR_ENTRY(false, false, false, false, false, false, false, false),
@@ -786,11 +794,11 @@ const uint8_t dc_lex_regs[] = {
const size_t dc_lex_regs_len = sizeof(dc_lex_regs) / sizeof(uint8_t);
const uchar dc_lex_tokens[] = {
-#if BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_IRAND,
-#else // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_INVALID,
-#endif // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_INVALID,
#if BC_ENABLE_EXTRA_MATH
BC_LEX_OP_TRUNC,
@@ -798,11 +806,11 @@ const uchar dc_lex_tokens[] = {
BC_LEX_INVALID,
#endif // BC_ENABLE_EXTRA_MATH
BC_LEX_OP_MODULUS, BC_LEX_INVALID,
-#if BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_RAND,
-#else // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_INVALID,
-#endif // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_LPAREN, BC_LEX_RPAREN, BC_LEX_OP_MULTIPLY, BC_LEX_OP_PLUS,
BC_LEX_INVALID, BC_LEX_OP_MINUS, BC_LEX_INVALID, BC_LEX_OP_DIVIDE,
BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID, BC_LEX_INVALID,
@@ -823,20 +831,20 @@ const uchar dc_lex_tokens[] = {
BC_LEX_INVALID,
#endif // BC_ENABLE_EXTRA_MATH
BC_LEX_KW_IBASE,
-#if BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_SEED,
-#else // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_INVALID,
-#endif // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_SCALE, BC_LEX_LOAD_POP, BC_LEX_OP_BOOL_AND, BC_LEX_OP_BOOL_NOT,
BC_LEX_KW_OBASE, BC_LEX_PRINT_STREAM, BC_LEX_NQUIT, BC_LEX_POP,
BC_LEX_STORE_PUSH, BC_LEX_KW_MAXIBASE, BC_LEX_KW_MAXOBASE,
BC_LEX_KW_MAXSCALE,
-#if BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_KW_MAXRAND,
-#else // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_INVALID,
-#endif // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_SCALE_FACTOR,
BC_LEX_INVALID, BC_LEX_KW_LENGTH, BC_LEX_INVALID, BC_LEX_INVALID,
BC_LEX_INVALID, BC_LEX_OP_POWER, BC_LEX_NEG, BC_LEX_INVALID,
@@ -848,11 +856,11 @@ const uchar dc_lex_tokens[] = {
BC_LEX_INVALID,
#endif // BC_ENABLE_EXTRA_MATH
BC_LEX_STORE_IBASE,
-#if BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_STORE_SEED,
-#else // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_INVALID,
-#endif // BC_ENABLE_EXTRA_MATH && DC_ENABLE_RAND
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_LEX_STORE_SCALE, BC_LEX_LOAD,
BC_LEX_OP_BOOL_OR, BC_LEX_PRINT_POP, BC_LEX_STORE_OBASE, BC_LEX_KW_PRINT,
BC_LEX_KW_QUIT, BC_LEX_SWAP, BC_LEX_OP_ASSIGN, BC_LEX_INVALID,
@@ -898,21 +906,21 @@ const uchar dc_parse_insts[] = {
BC_INST_INVALID, BC_INST_INVALID, BC_INST_INVALID,
#endif // BC_ENABLED
BC_INST_IBASE, BC_INST_OBASE, BC_INST_SCALE,
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_INST_SEED,
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_INST_LENGTH, BC_INST_PRINT,
BC_INST_SQRT, BC_INST_ABS,
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_INST_IRAND,
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_INST_QUIT, BC_INST_INVALID,
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_INST_RAND,
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_INST_MAXIBASE,
BC_INST_MAXOBASE, BC_INST_MAXSCALE,
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_INST_MAXRAND,
#endif // BC_ENABLE_EXTRA_MATH
BC_INST_INVALID,
@@ -945,6 +953,7 @@ const BcDig bc_num_bigdigMax[] = {
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 char bc_num_hex_digits[] = "0123456789ABCDEF";
diff --git a/src/dc/dc.c b/src/dc/dc.c
index 0e0774b5322a1..21d7bfbd4385a 100644
--- a/src/dc/dc.c
+++ b/src/dc/dc.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
diff --git a/src/dc/lex.c b/src/dc/lex.c
index 663a828dfe7c3..b17f01bc990dd 100644
--- a/src/dc/lex.c
+++ b/src/dc/lex.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
diff --git a/src/dc/parse.c b/src/dc/parse.c
index 9ec746b96f7f4..86edc5f665059 100644
--- a/src/dc/parse.c
+++ b/src/dc/parse.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -230,7 +230,7 @@ void dc_parse_parse(BcParse *p) {
exit:
BC_SIG_MAYLOCK;
- if (BC_ERR(vm.status)) bc_parse_reset(p);
+ if (BC_ERR(vm.status || vm.sig)) bc_parse_reset(p);
BC_LONGJMP_CONT;
}
#endif // DC_ENABLED
diff --git a/src/file.c b/src/file.c
index ce878a018ca56..01997399f4520 100644
--- a/src/file.c
+++ b/src/file.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
diff --git a/src/history/history.c b/src/history/history.c
index ad917e65ba08d..b94fbb7b3fdfc 100644
--- a/src/history/history.c
+++ b/src/history/history.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -47,8 +47,6 @@
* Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>
* Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
*
- * All rights reserved.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
@@ -482,15 +480,17 @@ static void bc_history_enableRaw(BcHistory *h) {
static void bc_history_disableRaw(BcHistory *h) {
+ sig_atomic_t lock;
+
// Don't even check the return value as it's too late.
if (!h->rawMode) return;
- BC_SIG_LOCK;
+ BC_SIG_TRYLOCK(lock);
if (BC_ERR(tcsetattr(STDIN_FILENO, TCSAFLUSH, &h->orig_termios) != -1))
h->rawMode = false;
- BC_SIG_UNLOCK;
+ BC_SIG_TRYUNLOCK(lock);
}
/**
diff --git a/src/lang.c b/src/lang.c
index 6959af80fbfeb..bd287c75ee78f 100644
--- a/src/lang.c
+++ b/src/lang.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -96,37 +96,41 @@ void bc_func_init(BcFunc *f, const char *name) {
bc_vec_init(&f->code, sizeof(uchar), NULL);
- // This is necessary for not allocating memory where it isn't used.
- // dc does not use strings except in the main function. The else part
- // is necessary to stop uninitiazed data errors in valgrind.
- if (BC_IS_BC || !strcmp(name, bc_func_main))
- bc_vec_init(&f->strs, sizeof(char*), bc_string_free);
-#if BC_ENABLE_FUNC_FREE
- else bc_vec_clear(&f->strs);
-#endif // BC_ENABLE_FUNC_FREE
-
bc_vec_init(&f->consts, sizeof(BcConst), bc_const_free);
+
#if BC_ENABLED
if (BC_IS_BC) {
+
+ bc_vec_init(&f->strs, sizeof(char*), bc_string_free);
+
bc_vec_init(&f->autos, sizeof(BcLoc), NULL);
bc_vec_init(&f->labels, sizeof(size_t), NULL);
+
f->nparams = 0;
f->voidfn = false;
}
#endif // BC_ENABLED
+
f->name = name;
}
void bc_func_reset(BcFunc *f) {
+
BC_SIG_ASSERT_LOCKED;
assert(f != NULL);
+
bc_vec_npop(&f->code, f->code.len);
- bc_vec_npop(&f->strs, f->strs.len);
+
bc_vec_npop(&f->consts, f->consts.len);
+
#if BC_ENABLED
if (BC_IS_BC) {
+
+ bc_vec_npop(&f->strs, f->strs.len);
+
bc_vec_npop(&f->autos, f->autos.len);
bc_vec_npop(&f->labels, f->labels.len);
+
f->nparams = 0;
f->voidfn = false;
}
@@ -134,17 +138,24 @@ void bc_func_reset(BcFunc *f) {
}
void bc_func_free(void *func) {
+
#if BC_ENABLE_FUNC_FREE
BcFunc *f = (BcFunc*) func;
+
BC_SIG_ASSERT_LOCKED;
assert(f != NULL);
+
bc_vec_free(&f->code);
- bc_vec_free(&f->strs);
+
bc_vec_free(&f->consts);
+
#if BC_ENABLED
#ifndef NDEBUG
if (BC_IS_BC) {
+
+ bc_vec_free(&f->strs);
+
bc_vec_free(&f->autos);
bc_vec_free(&f->labels);
}
@@ -245,13 +256,13 @@ void bc_result_copy(BcResult *d, BcResult *src) {
break;
}
- case BC_RESULT_CONSTANT:
case BC_RESULT_STR:
{
memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
break;
}
+ case BC_RESULT_ZERO:
case BC_RESULT_ONE:
{
// Do nothing.
@@ -299,7 +310,7 @@ void bc_result_free(void *result) {
#endif // BC_ENABLED
case BC_RESULT_ARRAY_ELEM:
case BC_RESULT_STR:
- case BC_RESULT_CONSTANT:
+ case BC_RESULT_ZERO:
case BC_RESULT_ONE:
#if BC_ENABLED
case BC_RESULT_VOID:
diff --git a/src/lex.c b/src/lex.c
index 8bbc694c161f3..2b705c8bc71b3 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
diff --git a/src/main.c b/src/main.c
index 68941c5e24a52..7e5e2905cf759 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
diff --git a/src/num.c b/src/num.c
index ac255295e9709..05b4654f21f53 100644
--- a/src/num.c
+++ b/src/num.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -2012,7 +2012,6 @@ void bc_num_init(BcNum *restrict n, size_t req) {
if (req == BC_NUM_DEF_SIZE && vm.temps.len) {
BcNum *nptr = bc_vec_top(&vm.temps);
num = nptr->num;
- req = nptr->cap;
bc_vec_pop(&vm.temps);
}
else num = bc_vm_malloc(BC_NUM_SIZE(req));
@@ -2184,7 +2183,7 @@ void bc_num_bigdig2num(BcNum *restrict n, BcBigDig val) {
n->len = i;
}
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
void bc_num_rng(const BcNum *restrict n, BcRNG *rng) {
BcNum pow, temp, temp2, intn, frac;
@@ -2465,7 +2464,7 @@ err:
bc_num_free(&cp);
BC_LONGJMP_CONT;
}
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
size_t bc_num_addReq(const BcNum *a, const BcNum *b, size_t scale) {
diff --git a/src/opt.c b/src/opt.c
index 730b1cd51f19d..3a01a2657f159 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -102,7 +102,7 @@ static int bc_opt_parseShort(BcOpt *o, const BcOptLong *longopts) {
case BC_OPT_BC_ONLY:
case BC_OPT_DC_ONLY:
{
- if (type == -1 || (type == BC_OPT_BC_ONLY && !BC_IS_BC) ||
+ if (type == -1 || (type == BC_OPT_BC_ONLY && BC_IS_DC) ||
(type == BC_OPT_DC_ONLY && BC_IS_BC))
{
char str[2] = {0, 0};
@@ -212,7 +212,7 @@ int bc_opt_parse(BcOpt *o, const BcOptLong *longopts) {
o->optopt = longopts[i].val;
arg = bc_opt_longoptsArg(option);
- if ((longopts[i].type == BC_OPT_BC_ONLY && !BC_IS_BC) ||
+ 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);
diff --git a/src/parse.c b/src/parse.c
index 5d35fe66d3b63..a48f5807e9cef 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -64,25 +64,20 @@ static void bc_parse_update(BcParse *p, uchar inst, size_t idx) {
void bc_parse_addString(BcParse *p) {
- BcFunc *f = BC_IS_BC ? p->func : bc_vec_item(&p->prog->fns, BC_PROG_MAIN);
+ BcVec *strs = BC_IS_BC ? &p->func->strs : p->prog->strs;
size_t idx;
BC_SIG_LOCK;
if (BC_IS_BC) {
const char *str = bc_vm_strdup(p->l.str.v);
- idx = f->strs.len;
- bc_vec_push(&f->strs, &str);
+ idx = strs->len;
+ bc_vec_push(strs, &str);
}
#if DC_ENABLED
else idx = bc_program_insertFunc(p->prog, p->l.str.v) - BC_PROG_REQ_FUNCS;
#endif // DC_ENABLED
-#ifndef NDEBUG
- f = BC_IS_BC ? p->func : bc_vec_item(&p->prog->fns, BC_PROG_MAIN);
- assert(f->strs.len > idx);
-#endif // NDEBUG
-
bc_parse_update(p, BC_INST_STR, idx);
BC_SIG_UNLOCK;
@@ -90,16 +85,20 @@ void bc_parse_addString(BcParse *p) {
static void bc_parse_addNum(BcParse *p, const char *string) {
- BcFunc *f = BC_IS_BC ? p->func : bc_vec_item(&p->prog->fns, BC_PROG_MAIN);
+ BcVec *consts = &p->func->consts;
size_t idx;
BcConst c;
+ if (bc_parse_zero[0] == string[0] && bc_parse_zero[1] == string[1]) {
+ bc_parse_push(p, BC_INST_ZERO);
+ return;
+ }
if (bc_parse_one[0] == string[0] && bc_parse_one[1] == string[1]) {
bc_parse_push(p, BC_INST_ONE);
return;
}
- idx = f->consts.len;
+ idx = consts->len;
BC_SIG_LOCK;
@@ -107,7 +106,7 @@ static void bc_parse_addNum(BcParse *p, const char *string) {
c.base = BC_NUM_BIGDIG_MAX;
bc_num_clear(&c.num);
- bc_vec_push(&f->consts, &c);
+ bc_vec_push(consts, &c);
bc_parse_update(p, BC_INST_NUM, idx);
diff --git a/src/program.c b/src/program.c
index 8f2270f5e71de..1a8176c76f968 100644
--- a/src/program.c
+++ b/src/program.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -52,10 +52,10 @@ static void bc_program_addFunc(BcProgram *p, BcFunc *f, BcId *id_ptr);
static inline void bc_program_setVecs(BcProgram *p, BcFunc *f) {
p->consts = &f->consts;
- p->strs = &f->strs;
+ if (BC_IS_BC) p->strs = &f->strs;
}
-static void bc_program_type_num(BcResult *r, BcNum *n) {
+static inline void bc_program_type_num(BcResult *r, BcNum *n) {
#if BC_ENABLED
assert(r->t != BC_RESULT_VOID);
@@ -68,7 +68,7 @@ static void bc_program_type_num(BcResult *r, BcNum *n) {
static void bc_program_type_match(BcResult *r, BcType t) {
#if DC_ENABLED
- assert(!BC_IS_BC || BC_NO_ERR(r->t != BC_RESULT_STR));
+ assert(BC_IS_DC || BC_NO_ERR(r->t != BC_RESULT_STR));
#endif // DC_ENABLED
if (BC_ERR((r->t != BC_RESULT_ARRAY) != (!t)))
@@ -89,6 +89,7 @@ static size_t bc_program_index(const char *restrict code, size_t *restrict bgn)
return res;
}
+#if BC_ENABLED
static void bc_program_prepGlobals(BcProgram *p) {
size_t i;
@@ -96,9 +97,9 @@ static void bc_program_prepGlobals(BcProgram *p) {
for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
bc_vec_push(p->globals_v + i, p->globals + i);
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
bc_rand_push(&p->rng);
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
}
static void bc_program_popGlobals(BcProgram *p, bool reset) {
@@ -111,10 +112,11 @@ static void bc_program_popGlobals(BcProgram *p, bool reset) {
p->globals[i] = BC_PROG_GLOBAL(v);
}
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
bc_rand_pop(&p->rng, reset);
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
}
+#endif // BC_ENABLED
static void bc_program_pushBigdig(BcProgram *p, BcBigDig dig, BcResultType type)
{
@@ -182,38 +184,6 @@ static BcNum* bc_program_num(BcProgram *p, BcResult *r) {
switch (r->t) {
- case BC_RESULT_CONSTANT:
- {
- BcConst *c = bc_vec_item(p->consts, r->d.loc.loc);
- BcBigDig base = BC_PROG_IBASE(p);
-
- if (c->base != base) {
-
- if (c->num.num == NULL) {
- BC_SIG_LOCK;
- bc_num_init(&c->num, BC_NUM_RDX(strlen(c->val)));
- BC_SIG_UNLOCK;
- }
-
- // bc_num_parse() should only do operations that cannot fail.
- bc_num_parse(&c->num, c->val, base, !c->val[1]);
-
- c->base = base;
- }
-
- BC_SIG_LOCK;
-
- n = &r->d.n;
-
- r->t = BC_RESULT_TEMP;
-
- bc_num_createCopy(n, &c->num);
-
- BC_SIG_UNLOCK;
-
- break;
- }
-
case BC_RESULT_STR:
case BC_RESULT_TEMP:
case BC_RESULT_IBASE:
@@ -263,6 +233,12 @@ static BcNum* bc_program_num(BcProgram *p, BcResult *r) {
break;
}
+ case BC_RESULT_ZERO:
+ {
+ n = &p->zero;
+ break;
+ }
+
case BC_RESULT_ONE:
{
n = &p->one;
@@ -308,7 +284,7 @@ static void bc_program_binPrep(BcProgram *p, BcResult **l, BcNum **ln,
assert(p != NULL && l != NULL && ln != NULL && r != NULL && rn != NULL);
#ifndef BC_PROG_NO_STACK_CHECK
- if (!BC_IS_BC) {
+ if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 2)))
bc_vm_err(BC_ERROR_EXEC_STACK);
}
@@ -346,7 +322,7 @@ static void bc_program_assignPrep(BcProgram *p, BcResult **l, BcNum **ln,
{
BcResultType lt, min;
- min = BC_RESULT_CONSTANT - ((unsigned int) (BC_IS_BC << 1));
+ min = BC_RESULT_TEMP - ((unsigned int) (BC_IS_BC));
bc_program_binPrep(p, l, ln, r, rn, 0);
@@ -356,7 +332,7 @@ static void bc_program_assignPrep(BcProgram *p, BcResult **l, BcNum **ln,
bc_vm_err(BC_ERROR_EXEC_TYPE);
#if DC_ENABLED
- if(!BC_IS_BC) {
+ if(BC_IS_DC) {
bool good = (((*r)->t == BC_RESULT_STR || BC_PROG_STR(*rn)) &&
lt <= BC_RESULT_ARRAY_ELEM);
@@ -373,7 +349,7 @@ static void bc_program_prep(BcProgram *p, BcResult **r, BcNum **n, size_t idx) {
assert(p != NULL && r != NULL && n != NULL);
#ifndef BC_PROG_NO_STACK_CHECK
- if (!BC_IS_BC) {
+ if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
bc_vm_err(BC_ERROR_EXEC_STACK);
}
@@ -400,6 +376,33 @@ static BcResult* bc_program_prepResult(BcProgram *p) {
return bc_vec_top(&p->results);
}
+static void bc_program_const(BcProgram *p, const char *code, size_t *bgn) {
+
+ BcResult *r = bc_program_prepResult(p);
+ BcConst *c = bc_vec_item(p->consts, bc_program_index(code, bgn));
+ BcBigDig base = BC_PROG_IBASE(p);
+
+ if (c->base != base) {
+
+ if (c->num.num == NULL) {
+ BC_SIG_LOCK;
+ bc_num_init(&c->num, BC_NUM_RDX(strlen(c->val)));
+ BC_SIG_UNLOCK;
+ }
+
+ // bc_num_parse() should only do operations that cannot fail.
+ bc_num_parse(&c->num, c->val, base, !c->val[1]);
+
+ c->base = base;
+ }
+
+ BC_SIG_LOCK;
+
+ bc_num_createCopy(&r->d.n, &c->num);
+
+ BC_SIG_UNLOCK;
+}
+
static void bc_program_op(BcProgram *p, uchar inst) {
BcResult *opd1, *opd2, *res;
@@ -459,7 +462,9 @@ static void bc_program_read(BcProgram *p) {
if (BC_ERR(parse.l.t != BC_LEX_NLINE && parse.l.t != BC_LEX_EOF))
bc_vm_err(BC_ERROR_EXEC_READ_EXPR);
+#if BC_ENABLED
if (BC_G) bc_program_prepGlobals(p);
+#endif // BC_ENABLED
ip.func = BC_PROG_READ;
ip.idx = 0;
@@ -470,8 +475,9 @@ static void bc_program_read(BcProgram *p) {
bc_vec_pushByte(&f->code, vm.read_ret);
bc_vec_push(&p->stack, &ip);
+
#if DC_ENABLED
- if (!BC_IS_BC) {
+ if (BC_IS_DC) {
size_t temp = 0;
bc_vec_push(&p->tail_calls, &temp);
}
@@ -485,12 +491,12 @@ exec_err:
BC_LONGJMP_CONT;
}
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
static void bc_program_rand(BcProgram *p) {
BcRand rand = bc_rand_int(&p->rng);
bc_program_pushBigdig(p, (BcBigDig) rand, BC_RESULT_TEMP);
}
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
static void bc_program_printChars(const char *str) {
@@ -510,7 +516,7 @@ static void bc_program_printString(const char *restrict str) {
size_t i, len = strlen(str);
#if DC_ENABLED
- if (!len && !BC_IS_BC) {
+ if (!len && BC_IS_DC) {
bc_vm_putchar('\0');
return;
}
@@ -552,7 +558,7 @@ static void bc_program_print(BcProgram *p, uchar inst, size_t idx) {
assert(p != NULL);
#ifndef BC_PROG_NO_STACK_CHECK
- if (!BC_IS_BC) {
+ if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
bc_vm_err(BC_ERROR_EXEC_STACK);
}
@@ -560,9 +566,6 @@ static void bc_program_print(BcProgram *p, uchar inst, size_t idx) {
assert(BC_PROG_STACK(&p->results, idx + 1));
- assert(BC_IS_BC ||
- p->strs == &((BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN))->strs);
-
r = bc_vec_item_rev(&p->results, idx);
#if BC_ENABLED
@@ -586,6 +589,7 @@ static void bc_program_print(BcProgram *p, uchar inst, size_t idx) {
size_t i = (r->t == BC_RESULT_STR) ? r->d.loc.loc : n->scale;
+ bc_file_flush(&vm.fout);
str = *((char**) bc_vec_item(p->strs, i));
if (inst == BC_INST_PRINT_STR) bc_program_printChars(str);
@@ -736,7 +740,7 @@ static void bc_program_copyToVar(BcProgram *p, size_t idx,
bool var = (t == BC_TYPE_VAR);
#if DC_ENABLED
- if (!BC_IS_BC) {
+ if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
bc_vm_err(BC_ERROR_EXEC_STACK);
@@ -763,7 +767,7 @@ static void bc_program_copyToVar(BcProgram *p, size_t idx,
vec = bc_program_vec(p, idx, t);
#if DC_ENABLED
- if (ptr->t == BC_RESULT_STR) {
+ if (BC_IS_DC && (ptr->t == BC_RESULT_STR || BC_PROG_STR(n))) {
if (BC_ERR(!var)) bc_vm_err(BC_ERROR_EXEC_TYPE);
bc_program_assignStr(p, ptr, vec, true);
return;
@@ -839,7 +843,7 @@ static void bc_program_assign(BcProgram *p, uchar inst) {
if (right->t == BC_RESULT_STR || BC_PROG_STR(r)) {
- size_t idx = right->d.loc.loc;
+ size_t idx = right->t == BC_RESULT_STR ? right->d.loc.loc : r->scale;
if (left->t == BC_RESULT_ARRAY_ELEM) {
BC_SIG_LOCK;
@@ -891,7 +895,7 @@ static void bc_program_assign(BcProgram *p, uchar inst) {
}
else {
min = BC_NUM_MIN_BASE;
- if (BC_ENABLE_EXTRA_MATH && ob && (!BC_IS_BC || !BC_IS_POSIX))
+ if (BC_ENABLE_EXTRA_MATH && ob && (BC_IS_DC || !BC_IS_POSIX))
min = 0;
max = vm.maxes[ob + BC_PROG_GLOBALS_IBASE];
v = p->globals_v + BC_PROG_GLOBALS_IBASE + ob;
@@ -904,9 +908,9 @@ static void bc_program_assign(BcProgram *p, uchar inst) {
*ptr = val;
*ptr_t = val;
}
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
else if (left->t == BC_RESULT_SEED) bc_num_rng(l, &p->rng);
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
BC_SIG_LOCK;
@@ -931,7 +935,7 @@ static void bc_program_pushVar(BcProgram *p, const char *restrict code,
r.d.loc.loc = idx;
#if DC_ENABLED
- if (!BC_IS_BC && (pop || copy)) {
+ if (BC_IS_DC && (pop || copy)) {
BcVec *v = bc_program_vec(p, idx, BC_TYPE_VAR);
BcNum *num = bc_vec_top(v);
@@ -989,8 +993,13 @@ static void bc_program_pushArray(BcProgram *p, const char *restrict code,
r.t = BC_RESULT_ARRAY_ELEM;
r.d.loc.idx = (size_t) temp;
+
+ BC_SIG_LOCK;
+
bc_vec_pop(&p->results);
bc_vec_push(&p->results, &r);
+
+ BC_SIG_UNLOCK;
}
#if BC_ENABLED
@@ -1160,14 +1169,14 @@ static void bc_program_builtin(BcProgram *p, uchar inst) {
BcNum *num;
bool len = (inst == BC_INST_LENGTH);
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IRAND);
-#else // BC_ENABLE_EXTRA_MATH
+#else // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
assert(inst >= BC_INST_LENGTH && inst <= BC_INST_ABS);
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
#ifndef BC_PROG_NO_STACK_CHECK
- if (!BC_IS_BC) {
+ if (BC_IS_DC) {
if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
bc_vm_err(BC_ERROR_EXEC_STACK);
}
@@ -1196,7 +1205,7 @@ static void bc_program_builtin(BcProgram *p, uchar inst) {
res->d.n.neg = false;
}
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
else if (inst == BC_INST_IRAND) {
BC_SIG_LOCK;
@@ -1207,7 +1216,7 @@ static void bc_program_builtin(BcProgram *p, uchar inst) {
bc_num_irand(num, &res->d.n, &p->rng);
}
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
else {
BcBigDig val = 0;
@@ -1582,7 +1591,7 @@ static void bc_program_pushGlobal(BcProgram *p, uchar inst) {
bc_program_pushBigdig(p, p->globals[inst - BC_INST_IBASE], t);
}
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
static void bc_program_pushSeed(BcProgram *p) {
BcResult *res;
@@ -1598,7 +1607,7 @@ static void bc_program_pushSeed(BcProgram *p) {
bc_num_createFromRNG(&res->d.n, &p->rng);
}
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
static void bc_program_addFunc(BcProgram *p, BcFunc *f, BcId *id_ptr) {
@@ -1610,11 +1619,10 @@ static void bc_program_addFunc(BcProgram *p, BcFunc *f, BcId *id_ptr) {
bc_vec_push(&p->fns, f);
// This is to make sure pointers are updated if the array was moved.
- if (BC_IS_BC && p->stack.len) {
- ip = bc_vec_item_rev(&p->stack, 0);
+ if (p->stack.len) {
+ ip = bc_vec_top(&p->stack);
bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, ip->func));
}
- else bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN));
}
size_t bc_program_insertFunc(BcProgram *p, const char *name) {
@@ -1643,9 +1651,7 @@ size_t bc_program_insertFunc(BcProgram *p, const char *name) {
bc_program_addFunc(p, &f, id_ptr);
#if DC_ENABLED
- if (!BC_IS_BC && strcmp(name, bc_func_main) &&
- strcmp(name, bc_func_read))
- {
+ if (BC_IS_DC && idx >= BC_PROG_REQ_FUNCS) {
bc_vec_push(p->strs, &id_ptr->name);
assert(p->strs->len == p->fns.len - BC_PROG_REQ_FUNCS);
}
@@ -1679,12 +1685,15 @@ void bc_program_free(BcProgram *p) {
if (BC_IS_BC) bc_num_free(&p->last);
#endif // BC_ENABLED
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
bc_rand_free(&p->rng);
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
#if DC_ENABLED
- if (!BC_IS_BC) bc_vec_free(&p->tail_calls);
+ if (BC_IS_DC) {
+ bc_vec_free(&p->tail_calls);
+ bc_vec_free(&p->strs_v);
+ }
#endif // DC_ENABLED
}
#endif // NDEBUG
@@ -1710,7 +1719,10 @@ void bc_program_init(BcProgram *p) {
}
#if DC_ENABLED
- if (!BC_IS_BC) {
+ if (BC_IS_DC) {
+
+ bc_vec_init(&p->strs_v, sizeof(char*), bc_string_free);
+ p->strs = &p->strs_v;
bc_vec_init(&p->tail_calls, sizeof(size_t), NULL);
i = 0;
@@ -1722,10 +1734,12 @@ void bc_program_init(BcProgram *p) {
}
#endif // DC_ENABLED
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
srand((unsigned int) time(NULL));
bc_rand_init(&p->rng);
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
+
+ bc_num_setup(&p->zero, p->zero_num, BC_PROG_ONE_CAP);
bc_num_setup(&p->one, p->one_num, BC_PROG_ONE_CAP);
bc_num_one(&p->one);
@@ -1748,6 +1762,10 @@ void bc_program_init(BcProgram *p) {
bc_vec_init(&p->results, sizeof(BcResult), bc_result_free);
bc_vec_init(&p->stack, sizeof(BcInstPtr), NULL);
bc_vec_push(&p->stack, &ip);
+
+ bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN));
+
+ assert(p->consts != NULL && p->strs != NULL);
}
void bc_program_reset(BcProgram *p) {
@@ -1760,11 +1778,13 @@ void bc_program_reset(BcProgram *p) {
bc_vec_npop(&p->stack, p->stack.len - 1);
bc_vec_npop(&p->results, p->results.len);
+#if BC_ENABLED
if (BC_G) bc_program_popGlobals(p, true);
+#endif // BC_ENABLED
f = bc_vec_item(&p->fns, BC_PROG_MAIN);
ip = bc_vec_top(&p->stack);
- if (BC_IS_BC) bc_program_setVecs(p, f);
+ bc_program_setVecs(p, f);
ip->idx = f->code.len;
if (vm.sig) {
@@ -1779,7 +1799,7 @@ void bc_program_exec(BcProgram *p) {
size_t idx;
BcResult r, *ptr;
BcInstPtr *ip = bc_vec_top(&p->stack);
- BcFunc *func = bc_vec_item(&p->fns, ip->func);
+ BcFunc *func = (BcFunc*) bc_vec_item(&p->fns, ip->func);
char *code = func->code.v;
bool cond = false;
#if BC_ENABLED
@@ -1793,8 +1813,7 @@ void bc_program_exec(BcProgram *p) {
jmp_bufs_len = vm.jmp_bufs.len;
#endif // NDEBUG
- if (BC_IS_BC) bc_program_setVecs(p, func);
- else bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN));
+ bc_program_setVecs(p, func);
while (ip->idx < func->code.len) {
@@ -1867,7 +1886,7 @@ void bc_program_exec(BcProgram *p) {
func = bc_vec_item(&p->fns, ip->func);
code = func->code.v;
- if (BC_IS_BC) bc_program_setVecs(p, func);
+ bc_program_setVecs(p, func);
break;
}
@@ -1894,25 +1913,25 @@ void bc_program_exec(BcProgram *p) {
func = bc_vec_item(&p->fns, ip->func);
code = func->code.v;
- if (BC_IS_BC) bc_program_setVecs(p, func);
+ bc_program_setVecs(p, func);
break;
}
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_INST_RAND:
{
bc_program_rand(p);
break;
}
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_INST_MAXIBASE:
case BC_INST_MAXOBASE:
case BC_INST_MAXSCALE:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_INST_MAXRAND:
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
{
BcBigDig dig = vm.maxes[inst - BC_INST_MAXIBASE];
bc_program_pushBigdig(p, dig, BC_RESULT_TEMP);
@@ -1942,21 +1961,21 @@ void bc_program_exec(BcProgram *p) {
break;
}
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_INST_SEED:
{
bc_program_pushSeed(p);
break;
}
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_INST_LENGTH:
case BC_INST_SCALE_FUNC:
case BC_INST_SQRT:
case BC_INST_ABS:
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
case BC_INST_IRAND:
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
{
bc_program_builtin(p, inst);
break;
@@ -1964,18 +1983,17 @@ void bc_program_exec(BcProgram *p) {
case BC_INST_NUM:
{
- r.t = BC_RESULT_CONSTANT;
- r.d.loc.loc = bc_program_index(code, &ip->idx);
- bc_vec_push(&p->results, &r);
+ bc_program_const(p, code, &ip->idx);
break;
}
+ case BC_INST_ZERO:
case BC_INST_ONE:
#if BC_ENABLED
case BC_INST_LAST:
#endif // BC_ENABLED
{
- r.t = BC_RESULT_ONE + (inst - BC_INST_ONE);
+ r.t = BC_RESULT_ZERO + (inst - BC_INST_ZERO);
bc_vec_push(&p->results, &r);
break;
}
@@ -2077,6 +2095,7 @@ void bc_program_exec(BcProgram *p) {
ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func);
code = func->code.v;
+ bc_program_setVecs(p, func);
break;
}
@@ -2100,6 +2119,7 @@ void bc_program_exec(BcProgram *p) {
ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func);
code = func->code.v;
+ bc_program_setVecs(p, func);
break;
}
@@ -2164,6 +2184,7 @@ void bc_program_exec(BcProgram *p) {
ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func);
code = func->code.v;
+ bc_program_setVecs(p, func);
break;
}
@@ -2195,6 +2216,7 @@ void bc_program_exec(BcProgram *p) {
ip = bc_vec_top(&p->stack);
func = bc_vec_item(&p->fns, ip->func);
code = func->code.v;
+ bc_program_setVecs(p, func);
break;
}
#endif // DC_ENABLED
diff --git a/src/rand/rand.c b/src/rand/rand.c
index aa589bbd533d8..b16061d711a1d 100644
--- a/src/rand/rand.c
+++ b/src/rand/rand.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2019 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * Copyright (c) 2018-2019 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:
@@ -66,8 +66,6 @@
*
*/
-#if BC_ENABLE_EXTRA_MATH
-
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -80,6 +78,8 @@
#include <rand.h>
#include <vm.h>
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
+
#if !BC_RAND_BUILTIN
static BcRandState bc_rand_addition(uint_fast64_t a, uint_fast64_t b) {
@@ -412,4 +412,4 @@ void bc_rand_free(BcRNG *r) {
}
#endif // NDEBUG
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
diff --git a/src/read.c b/src/read.c
index c63952523181f..6886a7e13602b 100644
--- a/src/read.c
+++ b/src/read.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -61,29 +61,29 @@ static bool bc_read_binary(const char *buf, size_t size) {
return false;
}
-static bool bc_read_buf(BcVec *vec) {
+bool bc_read_buf(BcVec *vec, char *buf, size_t *buf_len) {
char *nl;
- if (!vm.buf_len) return false;
+ if (!*buf_len) return false;
- nl = strchr(vm.buf, '\n');
+ nl = strchr(buf, '\n');
if (nl != NULL) {
- size_t nllen = (size_t) ((nl + 1) - vm.buf);
+ size_t nllen = (size_t) ((nl + 1) - buf);
- nllen = vm.buf_len >= nllen ? nllen : vm.buf_len;
+ nllen = *buf_len >= nllen ? nllen : *buf_len;
- bc_vec_npush(vec, nllen, vm.buf);
- vm.buf_len -= nllen;
- memmove(vm.buf, nl + 1, vm.buf_len);
+ bc_vec_npush(vec, nllen, buf);
+ *buf_len -= nllen;
+ memmove(buf, nl + 1, *buf_len + 1);
return true;
}
- bc_vec_npush(vec, vm.buf_len, vm.buf);
- vm.buf_len = 0;
+ bc_vec_npush(vec, *buf_len, buf);
+ *buf_len = 0;
return false;
}
@@ -105,7 +105,7 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) {
}
#endif // BC_ENABLE_PROMPT
- if (bc_read_buf(vec)) {
+ if (bc_read_buf(vec, vm.buf, &vm.buf_len)) {
bc_vec_pushByte(vec, '\0');
return BC_STATUS_SUCCESS;
}
@@ -154,8 +154,9 @@ BcStatus bc_read_chars(BcVec *vec, const char *prompt) {
}
vm.buf_len += (size_t) r;
+ vm.buf[vm.buf_len] = '\0';
- done = bc_read_buf(vec);
+ done = bc_read_buf(vec, vm.buf, &vm.buf_len);
}
bc_vec_pushByte(vec, '\0');
diff --git a/src/vector.c b/src/vector.c
index 28c7440693ebf..f45bcb198a25f 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -86,20 +86,19 @@ void bc_vec_expand(BcVec *restrict v, size_t req) {
void bc_vec_npop(BcVec *restrict v, size_t n) {
+ sig_atomic_t lock;
+
assert(v != NULL && n <= v->len);
+ BC_SIG_TRYLOCK(lock);
+
if (v->dtor == NULL) v->len -= n;
else {
-
- sig_atomic_t lock;
size_t len = v->len - n;
-
- BC_SIG_TRYLOCK(lock);
-
while (v->len > len) v->dtor(v->v + (v->size * --v->len));
-
- BC_SIG_TRYUNLOCK(lock);
}
+
+ BC_SIG_TRYUNLOCK(lock);
}
void bc_vec_npopAt(BcVec *restrict v, size_t n, size_t idx) {
@@ -112,26 +111,35 @@ void bc_vec_npopAt(BcVec *restrict v, size_t n, size_t idx) {
ptr = bc_vec_item(v, idx);
data = bc_vec_item(v, idx + n);
+ BC_SIG_LOCK;
+
if (v->dtor != NULL) {
size_t i;
- BC_SIG_LOCK;
-
for (i = 0; i < n; ++i) v->dtor(bc_vec_item(v, idx + i));
-
- BC_SIG_UNLOCK;
}
v->len -= n;
memmove(ptr, data, (v->len - idx) * v->size);
+
+ BC_SIG_UNLOCK;
}
void bc_vec_npush(BcVec *restrict v, size_t n, const void *data) {
+
+ sig_atomic_t lock;
+
assert(v != NULL && data != NULL);
+
+ BC_SIG_TRYLOCK(lock);
+
if (v->len + n > v->cap) bc_vec_grow(v, n);
+
memcpy(v->v + (v->size * v->len), data, v->size * n);
v->len += n;
+
+ BC_SIG_TRYUNLOCK(lock);
}
inline void bc_vec_push(BcVec *restrict v, const void *data) {
@@ -140,32 +148,35 @@ inline void bc_vec_push(BcVec *restrict v, const void *data) {
void bc_vec_pushByte(BcVec *restrict v, uchar data) {
assert(v != NULL && v->size == sizeof(uchar));
- if (v->len == v->cap) bc_vec_grow(v, 1);
- v->v[v->len] = (char) data;
- v->len += 1;
+ bc_vec_npush(v, 1, &data);
}
void bc_vec_pushIndex(BcVec *restrict v, size_t idx) {
- uchar amt, nums[sizeof(size_t)];
+ uchar amt, nums[sizeof(size_t) + 1];
assert(v != NULL);
assert(v->size == sizeof(uchar));
for (amt = 0; idx; ++amt) {
- nums[amt] = (uchar) idx;
+ nums[amt + 1] = (uchar) idx;
idx &= ((size_t) ~(UCHAR_MAX));
idx >>= sizeof(uchar) * CHAR_BIT;
}
- bc_vec_push(v, &amt);
- bc_vec_npush(v, amt, nums);
+ nums[0] = amt;
+
+ bc_vec_npush(v, amt + 1, nums);
}
static void bc_vec_pushAt(BcVec *restrict v, const void *data, size_t idx) {
+ sig_atomic_t lock;
+
assert(v != NULL && data != NULL && idx <= v->len);
+ BC_SIG_TRYLOCK(lock);
+
if (idx == v->len) bc_vec_push(v, data);
else {
@@ -178,40 +189,62 @@ static void bc_vec_pushAt(BcVec *restrict v, const void *data, size_t idx) {
memmove(ptr + v->size, ptr, v->size * (v->len++ - idx));
memmove(ptr, data, v->size);
}
+
+ BC_SIG_TRYUNLOCK(lock);
}
void bc_vec_string(BcVec *restrict v, size_t len, const char *restrict str) {
+ sig_atomic_t lock;
+
assert(v != NULL && v->size == sizeof(char));
assert(v->dtor == NULL);
assert(!v->len || !v->v[v->len - 1]);
assert(v->v != str);
+ BC_SIG_TRYLOCK(lock);
+
bc_vec_npop(v, v->len);
bc_vec_expand(v, bc_vm_growSize(len, 1));
memcpy(v->v, str, len);
v->len = len;
bc_vec_pushByte(v, '\0');
+
+ BC_SIG_TRYUNLOCK(lock);
}
void bc_vec_concat(BcVec *restrict v, const char *restrict str) {
+ sig_atomic_t lock;
+
assert(v != NULL && v->size == sizeof(char));
assert(v->dtor == NULL);
assert(!v->len || !v->v[v->len - 1]);
assert(v->v != str);
+ BC_SIG_TRYLOCK(lock);
+
if (v->len) v->len -= 1;
bc_vec_npush(v, strlen(str) + 1, str);
+
+ BC_SIG_TRYUNLOCK(lock);
}
void bc_vec_empty(BcVec *restrict v) {
+
+ sig_atomic_t lock;
+
assert(v != NULL && v->size == sizeof(char));
assert(v->dtor == NULL);
+
+ BC_SIG_TRYLOCK(lock);
+
bc_vec_npop(v, v->len);
bc_vec_pushByte(v, '\0');
+
+ BC_SIG_TRYUNLOCK(lock);
}
#if BC_ENABLE_HISTORY
@@ -242,6 +275,7 @@ inline void* bc_vec_item_rev(const BcVec *restrict v, size_t idx) {
}
inline void bc_vec_clear(BcVec *restrict v) {
+ BC_SIG_ASSERT_LOCKED;
v->v = NULL;
v->len = 0;
v->dtor = NULL;
diff --git a/src/vm.c b/src/vm.c
index d569cc70a0086..b3dee16b2e28c 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1,9 +1,9 @@
/*
* *****************************************************************************
*
- * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * All rights reserved.
+ * 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:
@@ -69,7 +69,7 @@ BC_NORETURN void bc_vm_jmp(const char* f) {
BC_NORETURN void bc_vm_jmp(void) {
#endif
- assert(vm.status != BC_STATUS_SUCCESS || vm.sig);
+ assert(BC_SIG_EXC);
BC_SIG_MAYLOCK;
@@ -191,11 +191,13 @@ void bc_vm_error(BcError e, size_t line, ...) {
bc_file_putchar(&vm.ferr, ' ');
bc_file_puts(&vm.ferr, f->name);
+#if BC_ENABLED
if (BC_IS_BC && ip->func != BC_PROG_MAIN &&
ip->func != BC_PROG_READ)
{
bc_file_puts(&vm.ferr, "()");
}
+#endif // BC_ENABLED
}
}
@@ -327,14 +329,14 @@ void bc_vm_shutdown(void) {
bc_file_free(&vm.ferr);
}
-size_t bc_vm_arraySize(size_t n, size_t size) {
+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);
return res;
}
-size_t bc_vm_growSize(size_t a, size_t b) {
+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);
@@ -402,11 +404,10 @@ void bc_vm_putchar(int c) {
static void bc_vm_clean(void) {
- BcProgram *prog = &vm.prog;
- BcVec *fns = &prog->fns;
+ BcVec *fns = &vm.prog.fns;
BcFunc *f = bc_vec_item(fns, BC_PROG_MAIN);
- BcInstPtr *ip = bc_vec_item(&prog->stack, 0);
- bool good = (vm.status && vm.status != BC_STATUS_QUIT);
+ BcInstPtr *ip = bc_vec_item(&vm.prog.stack, 0);
+ bool good = ((vm.status && vm.status != BC_STATUS_QUIT) || vm.sig);
if (good) bc_program_reset(&vm.prog);
@@ -415,53 +416,38 @@ static void bc_vm_clean(void) {
#endif // BC_ENABLED
#if DC_ENABLED
- if (!BC_IS_BC) {
+ if (BC_IS_DC) {
size_t i;
- for (i = 0; i < vm.prog.vars.len; ++i) {
- BcVec *arr = bc_vec_item(&vm.prog.vars, i);
- BcNum *n = bc_vec_top(arr);
- if (arr->len != 1 || BC_PROG_STR(n)) break;
- }
-
- if (i == vm.prog.vars.len) {
-
- for (i = 0; i < vm.prog.arrs.len; ++i) {
-
- BcVec *arr = bc_vec_item(&vm.prog.arrs, i);
- size_t j;
-
- assert(arr->len == 1);
-
- arr = bc_vec_top(arr);
-
- for (j = 0; j < arr->len; ++j) {
- BcNum *n = bc_vec_item(arr, j);
- if (BC_PROG_STR(n)) break;
- }
-
- if (j != arr->len) break;
- }
+ good = true;
- good = (i == vm.prog.arrs.len);
+ for (i = 0; good && i < vm.prog.results.len; ++i) {
+ BcResult *r = (BcResult*) bc_vec_item(&vm.prog.results, i);
+ good = BC_VM_SAFE_RESULT(r);
}
}
#endif // DC_ENABLED
// If this condition is true, we can get rid of strings,
// constants, and code. This is an idea from busybox.
- if (good && prog->stack.len == 1 && !prog->results.len &&
- ip->idx == f->code.len)
- {
+ if (good && vm.prog.stack.len == 1 && ip->idx == f->code.len) {
+
#if BC_ENABLED
if (BC_IS_BC) {
bc_vec_npop(&f->labels, f->labels.len);
bc_vec_npop(&f->strs, f->strs.len);
+ bc_vec_npop(&f->consts, f->consts.len);
}
#endif // BC_ENABLED
- bc_vec_npop(&f->consts, f->consts.len);
+
+#if DC_ENABLED
+ // Note to self: you cannot delete strings and functions. Deal with it.
+ if (BC_IS_DC) bc_vec_npop(vm.prog.consts, vm.prog.consts->len);
+#endif // DC_ENABLED
+
bc_vec_npop(&f->code, f->code.len);
+
ip->idx = 0;
}
}
@@ -494,6 +480,9 @@ static void bc_vm_process(const char *text, bool is_stdin) {
#endif // BC_ENABLED
bc_program_exec(&vm.prog);
+
+ assert(BC_IS_DC || vm.prog.results.len == 0);
+
if (BC_I) bc_file_flush(&vm.fout);
} while (vm.prs.l.t != BC_LEX_EOF);
@@ -604,6 +593,7 @@ restart:
bc_vec_empty(&buffer);
if (vm.eof) break;
+ else bc_vm_clean();
}
if (!BC_STATUS_IS_ERROR(s)) {
@@ -707,6 +697,7 @@ static void bc_vm_exec(const char* env_exp_exit) {
size_t i;
bool has_file = false;
+ BcVec buf;
#if BC_ENABLED
if (BC_IS_BC && (vm.flags & BC_FLAG_L)) {
@@ -720,8 +711,40 @@ static void bc_vm_exec(const char* env_exp_exit) {
#endif // BC_ENABLED
if (vm.exprs.len) {
+
+ size_t len = vm.exprs.len - 1;
+ bool more;
+
+ BC_SIG_LOCK;
+ bc_vec_init(&buf, sizeof(uchar), NULL);
+
+#ifndef NDEBUG
+ BC_SETJMP_LOCKED(err);
+#endif // NDEBUG
+
+ BC_SIG_UNLOCK;
+
bc_lex_file(&vm.prs.l, bc_program_exprs_name);
- bc_vm_process(vm.exprs.v, false);
+
+ do {
+
+ more = bc_read_buf(&buf, vm.exprs.v, &len);
+ bc_vec_pushByte(&buf, '\0');
+ bc_vm_process(buf.v, false);
+
+ bc_vec_npop(&buf, buf.len);
+
+ } while (more);
+
+ BC_SIG_LOCK;
+ bc_vec_free(&buf);
+
+#ifndef NDEBUG
+ BC_UNSETJMP;
+#endif // NDEBUG
+
+ BC_SIG_UNLOCK;
+
if (getenv(env_exp_exit) != NULL) return;
}
@@ -733,6 +756,18 @@ static void bc_vm_exec(const char* env_exp_exit) {
}
if (BC_IS_BC || !has_file) bc_vm_stdin();
+
+// These are all protected by ifndef NDEBUG because if these are needed, bc is
+// goingi to exit anyway, and I see no reason to include this code in a release
+// build when the OS is going to free all of the resources anyway.
+#ifndef NDEBUG
+ return;
+
+err:
+ BC_SIG_MAYLOCK;
+ bc_vec_free(&buf);
+ BC_LONGJMP_CONT;
+#endif // NDEBUG
}
void bc_vm_boot(int argc, char *argv[], const char *env_len,
@@ -798,18 +833,22 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
bc_vm_envArgs(env_args);
bc_args(argc, argv);
+#if BC_ENABLED
if (BC_IS_POSIX) vm.flags &= ~(BC_FLAG_G);
+#endif // BC_ENABLED
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;
-#if BC_ENABLE_EXTRA_MATH
+#if BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
vm.maxes[BC_PROG_MAX_RAND] = ((BcRand) 0) - 1;
-#endif // BC_ENABLE_EXTRA_MATH
+#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
+#if BC_ENABLED
if (BC_IS_BC && !BC_IS_POSIX)
vm.maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_IBASE;
+#endif // BC_ENABLED
if (BC_IS_BC && BC_I && !(vm.flags & BC_FLAG_Q)) bc_vm_info(NULL);