diff options
| author | Yukihiro Matsumoto <[email protected]> | 2012-08-13 21:03:08 +0900 |
|---|---|---|
| committer | Yukihiro Matsumoto <[email protected]> | 2012-08-13 21:03:08 +0900 |
| commit | cda1709a35ad7d495ec1a08793cd88b78e20c444 (patch) | |
| tree | 8934fa5e65c5be86f2adcbe5bf9f7282bb137204 /src/vm.c | |
| parent | 59bf47e7f887ee987477d3c926d46dde87c1e15f (diff) | |
| download | mruby-cda1709a35ad7d495ec1a08793cd88b78e20c444.tar.gz mruby-cda1709a35ad7d495ec1a08793cd88b78e20c444.zip | |
setjmp in mrb_funcall_with_block if mrb->jmp is empty
Diffstat (limited to 'src/vm.c')
| -rw-r--r-- | src/vm.c | 53 |
1 files changed, 53 insertions, 0 deletions
@@ -21,6 +21,7 @@ #include <string.h> #include <setjmp.h> #include <stddef.h> +#include <stdarg.h> #define STACK_INIT_SIZE 128 #define CALLINFO_INIT_SIZE 32 @@ -179,6 +180,44 @@ ecall(mrb_state *mrb, int i) if (!mrb->exc) mrb->exc = exc; } +#ifndef MRB_FUNCALL_ARGC_MAX +#define MRB_FUNCALL_ARGC_MAX 16 +#endif + +mrb_value +mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) +{ + mrb_sym mid = mrb_intern(mrb, name); + va_list ap; + int i; + + if (argc == 0) { + return mrb_funcall_argv(mrb, self, mid, 0, 0); + } + else if (argc == 1) { + mrb_value v; + + va_start(ap, argc); + v = va_arg(ap, mrb_value); + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, 1, &v); + } + else { + mrb_value argv[MRB_FUNCALL_ARGC_MAX]; + + if (argc > MRB_FUNCALL_ARGC_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); + } + + va_start(ap, argc); + for (i = 0; i < argc; i++) { + argv[i] = va_arg(ap, mrb_value); + } + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, argc, argv); + } +} + mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk) { @@ -189,6 +228,20 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr int n = mrb->ci->nregs; mrb_value val; + if (!mrb->jmp) { + jmp_buf c_jmp; + + if (setjmp(c_jmp) != 0) { /* error */ + mrb->jmp = 0; + return mrb_nil_value(); + } + mrb->jmp = &c_jmp; + /* recursive call */ + val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); + mrb->jmp = 0; + return val; + } + if (argc < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); } |
