aboutsummaryrefslogtreecommitdiff
path: root/contrib/bc/src/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bc/src/vm.c')
-rw-r--r--contrib/bc/src/vm.c126
1 files changed, 92 insertions, 34 deletions
diff --git a/contrib/bc/src/vm.c b/contrib/bc/src/vm.c
index e15b1398734e..3922b088414f 100644
--- a/contrib/bc/src/vm.c
+++ b/contrib/bc/src/vm.c
@@ -56,13 +56,15 @@
#endif // _WIN32
-#include <status.h>
#include <vector.h>
#include <args.h>
#include <vm.h>
#include <read.h>
#include <bc.h>
+char output_bufs[BC_VM_BUF_SIZE];
+BcVm vm;
+
#if BC_DEBUG_CODE
BC_NORETURN void bc_vm_jmp(const char* f) {
#else // BC_DEBUG_CODE
@@ -84,12 +86,14 @@ BC_NORETURN void bc_vm_jmp(void) {
assert(vm.jmp_bufs.len - (size_t) vm.sig_pop);
#endif // NDEBUG
+ if (vm.jmp_bufs.len == 0) abort();
if (vm.sig_pop) bc_vec_pop(&vm.jmp_bufs);
else vm.sig_pop = 1;
siglongjmp(*((sigjmp_buf*) bc_vec_top(&vm.jmp_bufs)), 1);
}
+#if !BC_ENABLE_LIBRARY
static void bc_vm_sig(int sig) {
// There is already a signal in flight.
@@ -132,8 +136,28 @@ void bc_vm_info(const char* const help) {
bc_file_flush(&vm.fout);
}
+#endif // !BC_ENABLE_LIBRARY
+
+#if BC_ENABLE_LIBRARY
+void bc_vm_handleError(BcErr e) {
+
+ assert(e < BC_ERR_NELEMS);
+ assert(!vm.sig_pop);
+
+ BC_SIG_LOCK;
-void bc_vm_error(BcError e, size_t line, ...) {
+ if (e <= BC_ERR_MATH_DIVIDE_BY_ZERO) {
+ vm.err = (BclError) (e - BC_ERR_MATH_NEGATIVE +
+ BCL_ERROR_MATH_NEGATIVE);
+ }
+ else if (vm.abrt) abort();
+ else if (e == BC_ERR_FATAL_ALLOC_ERR) vm.err = BCL_ERROR_FATAL_ALLOC_ERR;
+ else vm.err = BCL_ERROR_FATAL_UNKNOWN_ERR;
+
+ BC_VM_JMP;
+}
+#else // BC_ENABLE_LIBRARY
+void bc_vm_handleError(BcErr e, size_t line, ...) {
BcStatus s;
va_list args;
@@ -141,11 +165,11 @@ void bc_vm_error(BcError e, size_t line, ...) {
const char* err_type = vm.err_ids[id];
sig_atomic_t lock;
- assert(e < BC_ERROR_NELEMS);
+ assert(e < BC_ERR_NELEMS);
assert(!vm.sig_pop);
#if BC_ENABLED
- if (!BC_S && e >= BC_ERROR_POSIX_START) {
+ if (!BC_S && e >= BC_ERR_POSIX_START) {
if (BC_W) {
// Make sure to not return an error.
id = UCHAR_MAX;
@@ -261,7 +285,7 @@ static void bc_vm_envArgs(const char* const env_args_name) {
buf += 1;
start = buf;
}
- else if (instr) bc_vm_error(BC_ERROR_FATAL_OPTION, 0, start);
+ else if (instr) bc_vm_error(BC_ERR_FATAL_OPTION, 0, start);
}
else buf += 1;
}
@@ -293,6 +317,7 @@ static size_t bc_vm_envLen(const char *var) {
return len;
}
+#endif // BC_ENABLE_LIBRARY
void bc_vm_shutdown(void) {
@@ -308,6 +333,7 @@ void bc_vm_shutdown(void) {
#endif // BC_ENABLE_HISTORY
#ifndef NDEBUG
+#if !BC_ENABLE_LIBRARY
bc_vec_free(&vm.env_args);
free(vm.env_args_buffer);
bc_vec_free(&vm.files);
@@ -315,31 +341,40 @@ void bc_vm_shutdown(void) {
bc_program_free(&vm.prog);
bc_parse_free(&vm.prs);
+#endif // !BC_ENABLE_LIBRARY
- {
- size_t i;
- for (i = 0; i < vm.temps.len; ++i)
- free(((BcNum*) bc_vec_item(&vm.temps, i))->num);
-
- bc_vec_free(&vm.temps);
- }
+ bc_vm_freeTemps();
+ bc_vec_free(&vm.temps);
#endif // NDEBUG
+#if !BC_ENABLE_LIBRARY
bc_file_free(&vm.fout);
bc_file_free(&vm.ferr);
+#endif // !BC_ENABLE_LIBRARY
}
+#if !defined(NDEBUG) || BC_ENABLE_LIBRARY
+void bc_vm_freeTemps(void) {
+
+ size_t i;
+
+ for (i = 0; i < vm.temps.len; ++i) {
+ free(((BcNum*) bc_vec_item(&vm.temps, i))->num);
+ }
+}
+#endif // !defined(NDEBUG) || BC_ENABLE_LIBRARY
+
inline size_t bc_vm_arraySize(size_t n, size_t size) {
size_t res = n * size;
if (BC_ERR(res >= SIZE_MAX || (n != 0 && res / n != size)))
- bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return res;
}
inline size_t bc_vm_growSize(size_t a, size_t b) {
size_t res = a + b;
if (BC_ERR(res >= SIZE_MAX || res < a || res < b))
- bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return res;
}
@@ -351,7 +386,7 @@ void* bc_vm_malloc(size_t n) {
ptr = malloc(n);
- if (BC_ERR(ptr == NULL)) bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ if (BC_ERR(ptr == NULL)) bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return ptr;
}
@@ -364,7 +399,7 @@ void* bc_vm_realloc(void *ptr, size_t n) {
temp = realloc(ptr, n);
- if (BC_ERR(temp == NULL)) bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ if (BC_ERR(temp == NULL)) bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return temp;
}
@@ -377,11 +412,12 @@ char* bc_vm_strdup(const char *str) {
s = strdup(str);
- if (BC_ERR(!s)) bc_vm_err(BC_ERROR_FATAL_ALLOC_ERR);
+ if (BC_ERR(!s)) bc_vm_err(BC_ERR_FATAL_ALLOC_ERR);
return s;
}
+#if !BC_ENABLE_LIBRARY
void bc_vm_printf(const char *fmt, ...) {
va_list args;
@@ -396,12 +432,18 @@ void bc_vm_printf(const char *fmt, ...) {
BC_SIG_UNLOCK;
}
+#endif // !BC_ENABLE_LIBRARY
void bc_vm_putchar(int c) {
+#if BC_ENABLE_LIBRARY
+ bc_vec_pushByte(&vm.out, (uchar) c);
+#else // BC_ENABLE_LIBRARY
bc_file_putchar(&vm.fout, (uchar) c);
vm.nchars = (c == '\n' ? 0 : vm.nchars + 1);
+#endif // BC_ENABLE_LIBRARY
}
+#if !BC_ENABLE_LIBRARY
static void bc_vm_clean(void) {
BcVec *fns = &vm.prog.fns;
@@ -491,7 +533,7 @@ static void bc_vm_endif(void) {
if (good) {
while (BC_PARSE_IF_END(&vm.prs)) bc_vm_process("else {}");
}
- else bc_parse_err(&vm.prs, BC_ERROR_PARSE_BLOCK);
+ else bc_parse_err(&vm.prs, BC_ERR_PARSE_BLOCK);
}
#endif // BC_ENABLED
@@ -604,9 +646,9 @@ restart:
if (!BC_STATUS_IS_ERROR(s)) {
if (BC_ERR(comment))
- bc_parse_err(&vm.prs, BC_ERROR_PARSE_COMMENT);
+ bc_parse_err(&vm.prs, BC_ERR_PARSE_COMMENT);
else if (BC_ERR(string))
- bc_parse_err(&vm.prs, BC_ERROR_PARSE_STRING);
+ bc_parse_err(&vm.prs, BC_ERR_PARSE_STRING);
#if BC_ENABLED
else if (BC_IS_BC) bc_vm_endif();
#endif // BC_ENABLED
@@ -652,7 +694,7 @@ static void bc_vm_defaultMsgs(void) {
for (i = 0; i < BC_ERR_IDX_NELEMS + BC_ENABLED; ++i)
vm.err_ids[i] = bc_errs[i];
- for (i = 0; i < BC_ERROR_NELEMS; ++i) vm.err_msgs[i] = bc_err_msgs[i];
+ for (i = 0; i < BC_ERR_NELEMS; ++i) vm.err_msgs[i] = bc_err_msgs[i];
}
static void bc_vm_gettext(void) {
@@ -683,7 +725,7 @@ static void bc_vm_gettext(void) {
i = 0;
id = bc_err_ids[i];
- for (set = id + 3, msg = 1; i < BC_ERROR_NELEMS; ++i, ++msg) {
+ for (set = id + 3, msg = 1; i < BC_ERR_NELEMS; ++i, ++msg) {
if (id != bc_err_ids[i]) {
msg = 1;
@@ -775,8 +817,8 @@ err:
#endif // NDEBUG
}
-void bc_vm_boot(int argc, char *argv[], const char *env_len,
- const char* const env_args)
+void bc_vm_boot(int argc, char *argv[], const char *env_len,
+ const char* const env_args)
{
int ttyin, ttyout, ttyerr;
struct sigaction sa;
@@ -803,10 +845,7 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
if (BC_TTY) sigaction(SIGHUP, &sa, NULL);
#endif // BC_ENABLE_HISTORY
- memcpy(vm.max_num, bc_num_bigdigMax,
- bc_num_bigdigMax_size * sizeof(BcDig));
- bc_num_setup(&vm.max, vm.max_num, BC_NUM_BIGDIG_LOG10);
- vm.max.len = bc_num_bigdigMax_size;
+ bc_vm_init();
vm.file = NULL;
@@ -822,8 +861,6 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
bc_vec_clear(&vm.files);
bc_vec_clear(&vm.exprs);
- bc_vec_init(&vm.temps, sizeof(BcNum), NULL);
-
bc_program_init(&vm.prog);
bc_parse_init(&vm.prs, &vm.prog, BC_PROG_MAIN);
@@ -842,6 +879,27 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
if (BC_IS_POSIX) vm.flags &= ~(BC_FLAG_G);
#endif // BC_ENABLED
+ BC_SIG_UNLOCK;
+
+ bc_vm_exec();
+}
+#endif // !BC_ENABLE_LIBRARY
+
+void bc_vm_init(void) {
+
+ BC_SIG_ASSERT_LOCKED;
+
+ memcpy(vm.max_num, bc_num_bigdigMax,
+ bc_num_bigdigMax_size * sizeof(BcDig));
+ memcpy(vm.max2_num, bc_num_bigdigMax2,
+ bc_num_bigdigMax2_size * sizeof(BcDig));
+ bc_num_setup(&vm.max, vm.max_num, BC_NUM_BIGDIG_LOG10);
+ bc_num_setup(&vm.max2, vm.max2_num, BC_NUM_BIGDIG_LOG10);
+ vm.max.len = bc_num_bigdigMax_size;
+ vm.max2.len = bc_num_bigdigMax2_size;
+
+ bc_vec_init(&vm.temps, sizeof(BcNum), NULL);
+
vm.maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_POSIX_IBASE;
vm.maxes[BC_PROG_GLOBALS_OBASE] = BC_MAX_OBASE;
vm.maxes[BC_PROG_GLOBALS_SCALE] = BC_MAX_SCALE;
@@ -851,11 +909,11 @@ void bc_vm_boot(int argc, char *argv[], const char *env_len,
#endif // BC_ENABLE_EXTRA_MATH && BC_ENABLE_RAND
#if BC_ENABLED
+#if !BC_ENABLE_LIBRARY
if (BC_IS_BC && !BC_IS_POSIX)
+#endif // !BC_ENABLE_LIBRARY
+ {
vm.maxes[BC_PROG_GLOBALS_IBASE] = BC_NUM_MAX_IBASE;
+ }
#endif // BC_ENABLED
-
- BC_SIG_UNLOCK;
-
- bc_vm_exec();
}