diff options
-rw-r--r-- | lib.c | 7 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | types.h | 3 | ||||
-rw-r--r-- | vm.c | 11 | ||||
-rw-r--r-- | vm.h | 1 |
5 files changed, 23 insertions, 3 deletions
@@ -502,12 +502,15 @@ uc_exists(uc_vm *vm, size_t nargs) return ucv_boolean_new(found); } -__attribute__((noreturn)) static uc_value_t * +static uc_value_t * uc_exit(uc_vm *vm, size_t nargs) { int64_t n = uc_cast_int64(uc_get_arg(0)); - exit(n); + vm->arg.s32 = (int32_t)n; + uc_vm_raise_exception(vm, EXCEPTION_EXIT, "Terminated"); + + return NULL; } static uc_value_t * @@ -132,6 +132,10 @@ parse(uc_parse_config *config, uc_source *src, rc = 0; break; + case STATUS_EXIT: + rc = (int)ucv_int64_get(res); + break; + case ERROR_COMPILE: rc = -1; break; @@ -217,7 +217,8 @@ typedef enum { EXCEPTION_RUNTIME, EXCEPTION_TYPE, EXCEPTION_REFERENCE, - EXCEPTION_USER + EXCEPTION_USER, + EXCEPTION_EXIT } uc_exception_type_t; typedef struct { @@ -77,6 +77,7 @@ static const char *exception_type_strings[] = { [EXCEPTION_TYPE] = "Type error", [EXCEPTION_REFERENCE] = "Reference error", [EXCEPTION_USER] = "Error", + [EXCEPTION_EXIT] = "Exit" }; @@ -2256,6 +2257,16 @@ uc_vm_execute_chunk(uc_vm *vm, uc_value_t **retvalp) /* previous instruction raised exception */ if (vm->exception.type != EXCEPTION_NONE) { + /* VM termination was requested */ + if (vm->exception.type == EXCEPTION_EXIT) { + uc_vm_reset_callframes(vm); + + if (retvalp) + *retvalp = ucv_int64_new(vm->arg.s32); + + return STATUS_EXIT; + } + /* walk up callframes until something handles the exception or the root is reached */ while (!uc_vm_handle_exception(vm)) { /* no further callframe to pop, report unhandled exception and terminate */ @@ -103,6 +103,7 @@ enum insn_type { typedef enum { STATUS_OK, + STATUS_EXIT, ERROR_COMPILE, ERROR_RUNTIME } uc_vm_status_t; |