diff --git a/Makefile b/Makefile index ab36a943..752f450a 100644 --- a/Makefile +++ b/Makefile @@ -42,11 +42,14 @@ lib/mini-picrin: FORCE lib/libpicrin.a: FORCE $(MAKE) -C lib libpicrin.a -ext: lib/ext/eval.c +ext: lib/ext/eval.c lib/ext/error.c lib/ext/eval.c: piclib/eval.scm bin/picrin-bootstrap -c eval_rom piclib/eval.scm | bin/picrin-bootstrap tools/mkeval.scm > lib/ext/eval.c +lib/ext/error.c: piclib/error.scm + bin/picrin-bootstrap -c error_rom piclib/error.scm | bin/picrin-bootstrap tools/mkerror.scm > lib/ext/error.c + picrin: $(PICRIN_OBJS) $(CONTRIB_OBJS) ext lib/libpicrin.a $(CC) $(CFLAGS) -o $@ $(PICRIN_OBJS) $(CONTRIB_OBJS) lib/libpicrin.a $(LDFLAGS) diff --git a/lib/Makefile b/lib/Makefile index 94e78ae7..3f0972ce 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -5,7 +5,6 @@ LIBPICRIN_SRCS = \ char.c\ data.c\ dict.c\ - error.c\ gc.c\ number.c\ pair.c\ @@ -22,7 +21,8 @@ LIBPICRIN_SRCS = \ ext/eval.c\ ext/read.c\ ext/write.c\ - ext/file.c + ext/file.c\ + ext/error.c LIBPICRIN_OBJS = \ $(LIBPICRIN_SRCS:.c=.o) diff --git a/lib/error.c b/lib/error.c deleted file mode 100644 index c76d59a0..00000000 --- a/lib/error.c +++ /dev/null @@ -1,311 +0,0 @@ -/** - * See Copyright Notice in picrin.h - */ - -#include "picrin.h" -#include "object.h" -#include "state.h" - -void -pic_panic(pic_state *pic, const char *msg) -{ - if (pic->panicf) { - pic->panicf(pic, msg); - } -#if PIC_USE_LIBC - abort(); -#endif - PIC_UNREACHABLE(); -} - -void -pic_warnf(pic_state *pic, const char *fmt, ...) -{ - va_list ap; - pic_value err; - - va_start(ap, fmt); - err = pic_vstrf_value(pic, fmt, ap); - va_end(ap); - pic_fprintf(pic, pic_stderr(pic), "warn: %s\n", pic_str(pic, err, NULL)); -} - -#define pic_exc(pic) pic_ref(pic, "current-exception-handlers") - -#if PIC_USE_CALLCC - -PIC_JMPBUF * -pic_prepare_try(pic_state *pic) -{ - struct context *cxt = pic_malloc(pic, sizeof(struct context)); - - cxt->pc = NULL; - cxt->fp = NULL; - cxt->sp = NULL; - cxt->irep = NULL; - cxt->conts = pic_nil_value(pic); - cxt->prev = pic->cxt; - pic->cxt = cxt; - return &cxt->jmp; -} - -static pic_value -native_exception_handler(pic_state *pic) -{ - pic_value err; - - pic_get_args(pic, "o", &err); - - pic_call(pic, pic_closure_ref(pic, 0), 1, err); - PIC_UNREACHABLE(); -} - -void -pic_enter_try(pic_state *pic) -{ - pic_value cont, handler; - pic_value var, env; - - pic->cxt->ai = pic->ai; - - /* call/cc */ - cont = pic_make_cont(pic, pic_invalid_value(pic)); - handler = pic_lambda(pic, native_exception_handler, 1, cont); - /* with-exception-handler */ - var = pic_exc(pic); - env = pic_make_attr(pic); - pic_attr_set(pic, env, var, pic_cons(pic, handler, pic_call(pic, var, 0))); - pic->dyn_env = pic_cons(pic, env, pic->dyn_env); - - pic_leave(pic, pic->cxt->ai); -} - -void -pic_exit_try(pic_state *pic) -{ - struct context *cxt = pic->cxt; - pic_value c, it; - pic->dyn_env = pic_cdr(pic, pic->dyn_env); - pic_for_each (c, cxt->conts, it) { - proc_ptr(pic, c)->env->regs[0] = pic_false_value(pic); - } - pic->cxt = cxt->prev; - pic_free(pic, cxt); - /* don't rewind ai here */ -} - -pic_value -pic_abort_try(pic_state *pic) -{ - struct context *cxt = pic->cxt; - pic_value c, it; - pic_value err = cxt->sp->regs[1]; - pic_for_each (c, cxt->conts, it) { - proc_ptr(pic, c)->env->regs[0] = pic_false_value(pic); - } - pic->cxt = cxt->prev; - pic_free(pic, cxt); - pic_protect(pic, err); - return err; -} - -#else - -PIC_JMPBUF *pic_prepare_try(pic_state *PIC_UNUSED(pic)) { return NULL; } -void pic_enter_try(pic_state *PIC_UNUSED(pic)) { } -void pic_exit_try(pic_state *PIC_UNUSED(pic)) { } -pic_value pic_abort_try(pic_state *PIC_UNUSED(pic)) { PIC_UNREACHABLE(); } - -#endif - -pic_value -pic_make_error(pic_state *pic, const char *type, const char *msg, pic_value irrs) -{ - struct error *e; - pic_value ty = pic_intern_cstr(pic, type); - - e = (struct error *)pic_obj_alloc(pic, PIC_TYPE_ERROR); - e->type = sym_ptr(pic, ty); - e->msg = str_ptr(pic, pic_cstr_value(pic, msg)); - e->irrs = irrs; - - return obj_value(pic, e); -} - -static pic_value -with_exception_handlers(pic_state *pic, pic_value handlers, pic_value thunk) -{ - pic_value var, env, r; - var = pic_exc(pic); - env = pic_make_attr(pic); - pic_attr_set(pic, env, var, handlers); - pic->dyn_env = pic_cons(pic, env, pic->dyn_env); - r = pic_call(pic, thunk, 0); - pic->dyn_env = pic_cdr(pic, pic->dyn_env); - return r; -} - -static pic_value -on_raise(pic_state *pic) -{ - pic_value handler, err, val; - bool continuable; - - pic_get_args(pic, ""); - - handler = pic_closure_ref(pic, 0); - err = pic_closure_ref(pic, 1); - continuable = pic_bool(pic, pic_closure_ref(pic, 2)); - - val = pic_call(pic, handler, 1, err); - if (! continuable) { - pic_error(pic, "handler returned", 2, handler, err); - } - return val; -} - -pic_value -pic_raise_continuable(pic_state *pic, pic_value err) -{ - pic_value handlers, var = pic_exc(pic), thunk; - - handlers = pic_call(pic, var, 0); - - if (pic_nil_p(pic, handlers)) { - pic_panic(pic, "no exception handler"); - } - thunk = pic_lambda(pic, on_raise, 3, pic_car(pic, handlers), err, pic_true_value(pic)); - return with_exception_handlers(pic, pic_cdr(pic, handlers), thunk); -} - -void -pic_raise(pic_state *pic, pic_value err) -{ - pic_value handlers, var = pic_exc(pic), thunk; - - handlers = pic_call(pic, var, 0); - - if (pic_nil_p(pic, handlers)) { - pic_panic(pic, "no exception handler"); - } - thunk = pic_lambda(pic, on_raise, 3, pic_car(pic, handlers), err, pic_false_value(pic)); - with_exception_handlers(pic, pic_cdr(pic, handlers), thunk); - PIC_UNREACHABLE(); -} - -void -pic_error(pic_state *pic, const char *msg, int n, ...) -{ - va_list ap; - pic_value irrs; - - va_start(ap, n); - irrs = pic_vlist(pic, n, ap); - va_end(ap); - pic_raise(pic, pic_make_error(pic, "", msg, irrs)); -} - -static pic_value -pic_error_with_exception_handler(pic_state *pic) -{ - pic_value handler, thunk; - pic_value handlers, exc = pic_exc(pic); - - pic_get_args(pic, "ll", &handler, &thunk); - - handlers = pic_call(pic, exc, 0); - - return with_exception_handlers(pic, pic_cons(pic, handler, handlers), thunk); -} - -static pic_value -pic_error_raise(pic_state *pic) -{ - pic_value v; - - pic_get_args(pic, "o", &v); - - pic_raise(pic, v); -} - -static pic_value -pic_error_raise_continuable(pic_state *pic) -{ - pic_value v; - - pic_get_args(pic, "o", &v); - - return pic_raise_continuable(pic, v); -} - -static pic_value -pic_error_error(pic_state *pic) -{ - const char *cstr; - int argc; - pic_value *argv; - - pic_get_args(pic, "z*", &cstr, &argc, &argv); - - pic_raise(pic, pic_make_error(pic, "", cstr, pic_make_list(pic, argc, argv))); -} - -static pic_value -pic_error_error_object_p(pic_state *pic) -{ - pic_value v; - - pic_get_args(pic, "o", &v); - - return pic_bool_value(pic, pic_error_p(pic, v)); -} - -static pic_value -pic_error_error_object_message(pic_state *pic) -{ - pic_value e; - - pic_get_args(pic, "o", &e); - - TYPE_CHECK(pic, e, error); - - return obj_value(pic, error_ptr(pic, e)->msg); -} - -static pic_value -pic_error_error_object_irritants(pic_state *pic) -{ - pic_value e; - - pic_get_args(pic, "o", &e); - - TYPE_CHECK(pic, e, error); - - return error_ptr(pic, e)->irrs; -} - -static pic_value -pic_error_error_object_type(pic_state *pic) -{ - pic_value e; - - pic_get_args(pic, "o", &e); - - TYPE_CHECK(pic, e, error); - - return obj_value(pic, error_ptr(pic, e)->type); -} - -void -pic_init_error(pic_state *pic) -{ - pic_defvar(pic, "current-exception-handlers", pic_nil_value(pic)); - pic_defun(pic, "with-exception-handler", pic_error_with_exception_handler); - pic_defun(pic, "raise", pic_error_raise); - pic_defun(pic, "raise-continuable", pic_error_raise_continuable); - pic_defun(pic, "error", pic_error_error); - pic_defun(pic, "error-object?", pic_error_error_object_p); - pic_defun(pic, "error-object-message", pic_error_error_object_message); - pic_defun(pic, "error-object-irritants", pic_error_error_object_irritants); - pic_defun(pic, "error-object-type", pic_error_error_object_type); -} diff --git a/lib/ext/error.c b/lib/ext/error.c new file mode 100644 index 00000000..02b4adac --- /dev/null +++ b/lib/ext/error.c @@ -0,0 +1,409 @@ +/** + * See Copyright Notice in picrin.h + */ + +#include "picrin.h" +#include "../object.h" +#include "../state.h" + +#if PIC_USE_ERROR + +# define pic_exc(pic) pic_ref(pic, "current-exception-handlers") + +PIC_JMPBUF * +pic_prepare_try(pic_state *pic) +{ + struct context *cxt = pic_malloc(pic, sizeof(struct context)); + + cxt->pc = NULL; + cxt->fp = NULL; + cxt->sp = NULL; + cxt->irep = NULL; + cxt->conts = pic_nil_value(pic); + cxt->prev = pic->cxt; + pic->cxt = cxt; + return &cxt->jmp; +} + +static pic_value +native_exception_handler(pic_state *pic) +{ + pic_value err; + + pic_get_args(pic, "o", &err); + + pic_call(pic, pic_closure_ref(pic, 0), 1, err); + PIC_UNREACHABLE(); +} + +void +pic_enter_try(pic_state *pic) +{ + pic_value cont, handler; + pic_value var, env; + + pic->cxt->ai = pic->ai; + + /* call/cc */ + cont = pic_make_cont(pic, pic_invalid_value(pic)); + handler = pic_lambda(pic, native_exception_handler, 1, cont); + /* with-exception-handler */ + var = pic_exc(pic); + env = pic_make_attr(pic); + pic_attr_set(pic, env, var, pic_cons(pic, handler, pic_call(pic, var, 0))); + pic->dyn_env = pic_cons(pic, env, pic->dyn_env); + + pic_leave(pic, pic->cxt->ai); +} + +void +pic_exit_try(pic_state *pic) +{ + struct context *cxt = pic->cxt; + pic_value c, it; + pic->dyn_env = pic_cdr(pic, pic->dyn_env); + pic_for_each (c, cxt->conts, it) { + proc_ptr(pic, c)->env->regs[0] = pic_false_value(pic); + } + pic->cxt = cxt->prev; + pic_free(pic, cxt); + /* don't rewind ai here */ +} + +pic_value +pic_abort_try(pic_state *pic) +{ + struct context *cxt = pic->cxt; + pic_value c, it; + pic_value err = cxt->sp->regs[1]; + pic_for_each (c, cxt->conts, it) { + proc_ptr(pic, c)->env->regs[0] = pic_false_value(pic); + } + pic->cxt = cxt->prev; + pic_free(pic, cxt); + pic_protect(pic, err); + return err; +} + +#endif + +#if PIC_USE_ERROR +static const unsigned char error_rom[] = { +0x03, 0x01, 0x00, 0x04, 0x02, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x05, +0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x02, 0x00, 0x00, +0x02, 0x01, 0x01, 0x06, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x04, 0x01, +0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x6c, 0x69, +0x73, 0x74, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x00, +0x02, 0x01, 0x02, 0x01, 0x00, 0x04, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x00, +0x02, 0x0e, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x6b, 0x65, 0x2d, 0x70, 0x61, +0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x00, 0x06, 0x00, 0x00, 0x04, +0x01, 0x01, 0x01, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x00, 0x04, +0x0b, 0x0b, 0x48, 0x00, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x00, 0x63, +0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x78, 0x63, 0x65, 0x70, +0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, +0x73, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x72, 0x61, 0x69, 0x73, 0x65, +0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x72, 0x61, 0x69, 0x73, 0x65, 0x2d, +0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x62, 0x6c, 0x65, 0x00, +0x02, 0x16, 0x00, 0x00, 0x00, 0x77, 0x69, 0x74, 0x68, 0x2d, 0x65, 0x78, +0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x68, 0x61, 0x6e, 0x64, +0x6c, 0x65, 0x72, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x6b, +0x65, 0x2d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, 0x65, +0x63, 0x74, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, +0x72, 0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3f, 0x00, 0x02, 0x16, +0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, +0x65, 0x63, 0x74, 0x2d, 0x69, 0x72, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x74, +0x73, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, +0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x65, 0x73, 0x73, +0x61, 0x67, 0x65, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, +0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x74, 0x79, +0x70, 0x65, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, +0x72, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x70, 0x6c, +0x61, 0x79, 0x00, 0x04, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x00, +0x00, 0x07, 0x00, 0x01, 0x02, 0x00, 0x01, 0x07, 0x00, 0x02, 0x02, 0x00, +0x02, 0x07, 0x00, 0x03, 0x02, 0x00, 0x03, 0x07, 0x00, 0x04, 0x02, 0x00, +0x04, 0x07, 0x00, 0x05, 0x02, 0x00, 0x05, 0x07, 0x00, 0x06, 0x02, 0x00, +0x06, 0x07, 0x00, 0x07, 0x02, 0x00, 0x07, 0x07, 0x00, 0x08, 0x02, 0x00, +0x08, 0x07, 0x00, 0x09, 0x02, 0x00, 0x09, 0x02, 0x01, 0x0a, 0x06, 0x02, +0x0a, 0x01, 0x02, 0x02, 0x00, 0x03, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, +0x02, 0x1a, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, +0x2d, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x68, +0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x00, 0x06, 0x00, 0x00, 0x02, +0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, +0x00, 0x02, 0x00, 0x00, 0x04, 0x01, 0x01, 0x01, 0x04, 0x02, 0x00, 0x01, +0x01, 0x02, 0x02, 0x00, 0x03, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, +0x0e, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x6b, 0x65, 0x2d, 0x61, 0x74, 0x74, +0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, +0x00, 0x01, 0x01, 0x01, 0x00, 0x03, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, +0x02, 0x1b, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, +0x2d, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x2d, 0x65, 0x6e, 0x76, +0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x06, 0x00, 0x00, +0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x05, 0x01, 0x00, 0x11, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x01, 0x02, 0x01, 0x04, 0x02, 0x01, +0x01, 0x04, 0x03, 0x00, 0x01, 0x01, 0x03, 0x03, 0x00, 0x05, 0x01, 0x01, +0x10, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, +0x73, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x00, 0x02, +0x04, 0x03, 0x00, 0x03, 0x01, 0x03, 0x01, 0x00, 0x04, 0x01, 0x01, 0x0c, +0x00, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, +0x65, 0x6e, 0x74, 0x2d, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x2d, +0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x00, +0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, +0x01, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, +0x00, 0x00, 0x63, 0x64, 0x72, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, +0x04, 0x02, 0x05, 0x02, 0x01, 0x02, 0x01, 0x00, 0x04, 0x01, 0x01, 0x0c, +0x00, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, +0x65, 0x6e, 0x74, 0x2d, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, +0x6e, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x00, 0x06, +0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, +0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, +0x00, 0x63, 0x61, 0x72, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, +0x02, 0x07, 0x02, 0x01, 0x02, 0x01, 0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, +0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x04, 0x02, 0x0a, +0x02, 0x01, 0x02, 0x01, 0x00, 0x05, 0x01, 0x02, 0x0f, 0x00, 0x00, 0x00, +0x02, 0x05, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x01, +0x10, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x20, +0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x00, 0x06, 0x00, 0x00, +0x02, 0x01, 0x00, 0x03, 0x02, 0x01, 0x04, 0x03, 0x0b, 0x02, 0x01, 0x03, +0x01, 0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +0x04, 0x01, 0x07, 0x01, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, +0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x00, +0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x79, 0x6e, 0x61, +0x6d, 0x69, 0x63, 0x2d, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, +0x65, 0x6e, 0x74, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, +0x08, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x00, 0x00, 0x0a, 0x00, 0x00, +0x00, 0x04, 0x00, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, +0x00, 0x03, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, +0x00, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x78, 0x63, +0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, +0x65, 0x72, 0x73, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, +0x01, 0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +0x04, 0x01, 0x01, 0x01, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, +0x03, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x00, +0x6d, 0x61, 0x6b, 0x65, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, +0x74, 0x65, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, +0x00, 0x03, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, +0x00, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x79, 0x6e, +0x61, 0x6d, 0x69, 0x63, 0x2d, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, +0x6d, 0x65, 0x6e, 0x74, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, +0x01, 0x01, 0x00, 0x05, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, +0x00, 0x04, 0x01, 0x02, 0x01, 0x04, 0x02, 0x01, 0x01, 0x04, 0x03, 0x00, +0x01, 0x01, 0x03, 0x03, 0x00, 0x05, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, +0x02, 0x04, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x73, 0x00, 0x06, 0x00, +0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, 0x03, 0x00, 0x03, +0x01, 0x03, 0x01, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, +0x1b, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, +0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x2d, 0x65, 0x6e, 0x76, 0x69, +0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x06, 0x00, 0x00, 0x02, +0x01, 0x00, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x00, 0x04, 0x01, +0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x63, 0x64, +0x72, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x05, 0x02, +0x01, 0x02, 0x01, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, +0x1a, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, +0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x68, 0x61, +0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, +0x00, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x00, 0x04, 0x01, 0x01, +0x0c, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x63, 0x61, 0x72, +0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x07, 0x02, 0x01, +0x02, 0x01, 0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, +0x00, 0x01, 0x02, 0x01, 0x00, 0x04, 0x02, 0x0a, 0x02, 0x01, 0x02, 0x01, +0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, +0x01, 0x06, 0x01, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x04, +0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x00, 0x63, +0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x79, 0x6e, 0x61, 0x6d, +0x69, 0x63, 0x2d, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, +0x6e, 0x74, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x07, +0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, +0x04, 0x00, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, +0x03, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x00, +0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x78, 0x63, 0x65, +0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, +0x72, 0x73, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, +0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, +0x01, 0x01, 0x01, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x03, +0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x6d, +0x61, 0x6b, 0x65, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, +0x65, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, +0x03, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x00, +0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x79, 0x6e, 0x61, +0x6d, 0x69, 0x63, 0x2d, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, +0x65, 0x6e, 0x74, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, +0x01, 0x00, 0x05, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +0x04, 0x01, 0x02, 0x01, 0x04, 0x02, 0x01, 0x01, 0x04, 0x03, 0x00, 0x01, +0x01, 0x03, 0x03, 0x00, 0x05, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x02, +0x04, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x73, 0x00, 0x06, 0x00, 0x00, +0x02, 0x01, 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, 0x03, 0x00, 0x03, 0x01, +0x03, 0x01, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x1b, +0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2d, 0x64, +0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x2d, 0x65, 0x6e, 0x76, 0x69, 0x72, +0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, +0x00, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x00, 0x05, 0x01, 0x01, +0x10, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, +0x73, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x07, 0x02, +0x04, 0x03, 0x05, 0x02, 0x01, 0x03, 0x01, 0x00, 0x04, 0x01, 0x01, 0x0c, +0x00, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, +0x65, 0x6e, 0x74, 0x2d, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, +0x6e, 0x2d, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x00, 0x06, +0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, +0x00, 0x03, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x09, 0x03, +0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x01, 0x05, 0x01, 0x04, 0x02, 0x00, +0x01, 0x01, 0x02, 0x02, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, +0x02, 0x1b, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, +0x2d, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x2d, 0x65, 0x6e, 0x76, +0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x06, 0x00, 0x00, +0x02, 0x01, 0x00, 0x04, 0x02, 0x06, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, +0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x01, 0x04, 0x01, +0x01, 0x02, 0x01, 0x01, 0x04, 0x00, 0x06, 0x01, 0x01, 0x14, 0x00, 0x00, +0x00, 0x02, 0x06, 0x00, 0x00, 0x00, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, +0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, +0x03, 0x00, 0x03, 0x04, 0x04, 0x00, 0x04, 0x01, 0x04, 0x01, 0x00, 0x05, +0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x00, 0x6d, +0x61, 0x6b, 0x65, 0x2d, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x00, 0x02, +0x0c, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, +0x6a, 0x65, 0x63, 0x74, 0x00, 0x06, 0x00, 0x00, 0x04, 0x01, 0x01, 0x01, +0x03, 0x02, 0x01, 0x04, 0x03, 0x00, 0x01, 0x01, 0x03, 0x02, 0x00, 0x04, +0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x72, +0x65, 0x63, 0x6f, 0x72, 0x64, 0x3f, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, +0x00, 0x04, 0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x00, 0x04, 0x01, 0x01, +0x1c, 0x00, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x00, 0x72, 0x65, 0x63, +0x6f, 0x72, 0x64, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x04, 0x00, 0x00, +0x01, 0x08, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, +0x02, 0x01, 0x02, 0x01, 0x02, 0x04, 0x00, 0x01, 0x01, 0x0a, 0x01, 0x01, +0x01, 0x01, 0x00, 0x05, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x02, 0x03, +0x00, 0x00, 0x00, 0x65, 0x71, 0x3f, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, +0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, +0x00, 0x06, 0x00, 0x00, 0x04, 0x01, 0x02, 0x01, 0x04, 0x02, 0x00, 0x01, +0x03, 0x03, 0x01, 0x01, 0x03, 0x02, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, +0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, +0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3f, 0x00, 0x06, 0x00, 0x00, +0x02, 0x01, 0x00, 0x04, 0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x00, 0x06, +0x01, 0x04, 0x27, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x72, +0x65, 0x63, 0x6f, 0x72, 0x64, 0x2d, 0x64, 0x61, 0x74, 0x75, 0x6d, 0x00, +0x02, 0x05, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x01, +0x14, 0x00, 0x00, 0x00, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20, 0x74, +0x79, 0x70, 0x65, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, +0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, +0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x00, 0x04, 0x00, 0x00, 0x01, 0x08, +0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x01, +0x02, 0x01, 0x02, 0x06, 0x00, 0x01, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, +0x02, 0x04, 0x03, 0x01, 0x02, 0x03, 0x04, 0x03, 0x01, 0x04, 0x01, 0x00, +0x05, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, +0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2d, 0x72, 0x65, 0x66, 0x00, 0x06, +0x00, 0x00, 0x04, 0x01, 0x02, 0x01, 0x04, 0x02, 0x00, 0x01, 0x0d, 0x03, +0x02, 0x01, 0x03, 0x02, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, +0x02, 0x0d, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, +0x62, 0x6a, 0x65, 0x63, 0x74, 0x3f, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, +0x00, 0x04, 0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x00, 0x06, 0x01, 0x04, +0x27, 0x00, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x72, 0x65, 0x63, +0x6f, 0x72, 0x64, 0x2d, 0x64, 0x61, 0x74, 0x75, 0x6d, 0x00, 0x02, 0x05, +0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x01, 0x14, 0x00, +0x00, 0x00, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20, 0x74, 0x79, 0x70, +0x65, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x02, +0x0c, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, +0x6a, 0x65, 0x63, 0x74, 0x00, 0x04, 0x00, 0x00, 0x01, 0x08, 0x00, 0x10, +0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x01, 0x02, 0x01, +0x02, 0x06, 0x00, 0x01, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x04, +0x03, 0x01, 0x02, 0x03, 0x04, 0x03, 0x01, 0x04, 0x01, 0x00, 0x05, 0x00, +0x01, 0x10, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x76, 0x65, +0x63, 0x74, 0x6f, 0x72, 0x2d, 0x72, 0x65, 0x66, 0x00, 0x06, 0x00, 0x00, +0x04, 0x01, 0x02, 0x01, 0x04, 0x02, 0x00, 0x01, 0x0d, 0x03, 0x01, 0x01, +0x03, 0x02, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x0d, +0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, +0x65, 0x63, 0x74, 0x3f, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, +0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x00, 0x06, 0x01, 0x04, 0x27, 0x00, +0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x72, 0x65, 0x63, 0x6f, 0x72, +0x64, 0x2d, 0x64, 0x61, 0x74, 0x75, 0x6d, 0x00, 0x02, 0x05, 0x00, 0x00, +0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, +0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, +0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x02, 0x0c, 0x00, +0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, 0x65, +0x63, 0x74, 0x00, 0x04, 0x00, 0x00, 0x01, 0x08, 0x00, 0x10, 0x00, 0x06, +0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x06, +0x00, 0x01, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x02, 0x04, 0x03, 0x01, +0x02, 0x03, 0x04, 0x03, 0x01, 0x04, 0x01, 0x00, 0x05, 0x00, 0x01, 0x10, +0x00, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x76, 0x65, 0x63, 0x74, +0x6f, 0x72, 0x2d, 0x72, 0x65, 0x66, 0x00, 0x06, 0x00, 0x00, 0x04, 0x01, +0x02, 0x01, 0x04, 0x02, 0x00, 0x01, 0x0d, 0x03, 0x00, 0x01, 0x03, 0x02, +0x01, 0x06, 0x01, 0x01, 0x12, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, +0x00, 0x6d, 0x61, 0x6b, 0x65, 0x2d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, +0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, +0x00, 0x0a, 0x02, 0x04, 0x03, 0x00, 0x02, 0x04, 0x04, 0x00, 0x03, 0x01, +0x04, 0x01, 0x00, 0x04, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x05, +0x00, 0x00, 0x00, 0x72, 0x61, 0x69, 0x73, 0x65, 0x00, 0x06, 0x00, 0x00, +0x04, 0x01, 0x01, 0x01, 0x04, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, +0x03, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x02, +0x01, 0x00, 0x01, 0x01, 0x02, 0x01, 0x03, 0x02, 0x00, 0x08, 0x00, 0x00, +0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x04, +0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x6e, +0x75, 0x6c, 0x6c, 0x3f, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, +0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x04, 0x00, 0x02, 0x1e, 0x00, +0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, 0x65, +0x6e, 0x74, 0x2d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x70, 0x6f, 0x72, +0x74, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x63, 0x61, 0x72, 0x00, 0x04, +0x00, 0x00, 0x01, 0x08, 0x00, 0x0d, 0x00, 0x06, 0x00, 0x00, 0x04, 0x01, +0x01, 0x01, 0x01, 0x01, 0x06, 0x00, 0x01, 0x04, 0x01, 0x01, 0x01, 0x04, +0x02, 0x02, 0x03, 0x01, 0x02, 0x01, 0x00, 0x04, 0x01, 0x00, 0x0d, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x01, 0x01, 0x01, 0x04, 0x02, 0x00, +0x01, 0x01, 0x02, 0x02, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, +0x02, 0x0d, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, +0x62, 0x6a, 0x65, 0x63, 0x74, 0x3f, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, +0x00, 0x04, 0x02, 0x02, 0x02, 0x01, 0x02, 0x01, 0x00, 0x06, 0x01, 0x01, +0x26, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x61, 0x70, 0x70, +0x6c, 0x79, 0x00, 0x04, 0x00, 0x00, 0x01, 0x08, 0x00, 0x0d, 0x00, 0x02, +0x00, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x00, 0x00, 0x04, +0x01, 0x01, 0x01, 0x04, 0x02, 0x04, 0x02, 0x04, 0x03, 0x03, 0x02, 0x04, +0x04, 0x01, 0x02, 0x01, 0x04, 0x01, 0x00, 0x03, 0x02, 0x00, 0x08, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, +0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, +0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, +0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, +0x04, 0x02, 0x05, 0x02, 0x01, 0x02, 0x01, 0x00, 0x04, 0x01, 0x01, 0x1c, +0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, +0x72, 0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x74, 0x79, 0x70, +0x65, 0x00, 0x04, 0x00, 0x00, 0x01, 0x08, 0x00, 0x10, 0x00, 0x06, 0x00, +0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x06, 0x02, 0x01, 0x02, 0x04, 0x00, +0x01, 0x01, 0x0c, 0x01, 0x01, 0x01, 0x01, 0x00, 0x05, 0x01, 0x00, 0x11, +0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x02, 0x02, 0x01, 0x00, 0x04, 0x02, +0x00, 0x01, 0x04, 0x03, 0x05, 0x02, 0x01, 0x03, 0x01, 0x00, 0x05, 0x00, +0x01, 0x11, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x2d, 0x00, +0x04, 0x00, 0x09, 0x02, 0x04, 0x01, 0x03, 0x01, 0x03, 0x02, 0x00, 0x04, +0x03, 0x06, 0x02, 0x01, 0x03, 0x01, 0x00, 0x05, 0x01, 0x01, 0x10, 0x00, +0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, +0x3a, 0x20, 0x22, 0x00, 0x04, 0x00, 0x06, 0x02, 0x02, 0x01, 0x00, 0x03, +0x02, 0x00, 0x04, 0x03, 0x03, 0x02, 0x01, 0x03, 0x01, 0x00, 0x04, 0x01, +0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x65, 0x72, +0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2d, 0x6d, +0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, +0x00, 0x04, 0x02, 0x06, 0x02, 0x01, 0x02, 0x01, 0x00, 0x05, 0x01, 0x00, +0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x02, 0x02, 0x01, 0x00, 0x04, +0x02, 0x00, 0x01, 0x04, 0x03, 0x05, 0x02, 0x01, 0x03, 0x01, 0x00, 0x04, +0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x22, +0x00, 0x04, 0x00, 0x09, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x00, 0x01, +0x02, 0x01, 0x00, 0x04, 0x01, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x16, +0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, 0x6f, 0x62, 0x6a, +0x65, 0x63, 0x74, 0x2d, 0x69, 0x72, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x74, +0x73, 0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x02, 0x09, 0x02, +0x01, 0x02, 0x01, 0x00, 0x05, 0x02, 0x01, 0x0f, 0x00, 0x00, 0x00, 0x02, +0x08, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x72, 0x2d, 0x65, 0x61, 0x63, 0x68, +0x00, 0x06, 0x00, 0x00, 0x02, 0x01, 0x00, 0x02, 0x02, 0x01, 0x04, 0x03, +0x00, 0x01, 0x01, 0x03, 0x01, 0x00, 0x05, 0x00, 0x01, 0x11, 0x00, 0x00, +0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x0c, 0x02, +0x04, 0x01, 0x07, 0x01, 0x03, 0x02, 0x00, 0x04, 0x03, 0x09, 0x02, 0x01, +0x03, 0x02, 0x00, 0x05, 0x01, 0x01, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, +0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x02, 0x02, 0x01, 0x00, +0x03, 0x02, 0x00, 0x04, 0x03, 0x09, 0x02, 0x01, 0x03, 0x01, 0x00, 0x05, +0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x77, +0x72, 0x69, 0x74, 0x65, 0x00, 0x06, 0x00, 0x00, 0x04, 0x01, 0x01, 0x01, +0x04, 0x02, 0x01, 0x02, 0x04, 0x03, 0x0a, 0x02, 0x01, 0x03, 0x01, 0x00, +0x03, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, +0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x04, 0x00, 0x00, 0x01, +0x07, 0x00, 0x00, 0x04, 0x00, 0x02, 0x01, 0x0c, 0x01, 0x01, 0x01, +}; +#endif + +void +pic_init_error(pic_state *PIC_UNUSED(pic)) +{ +#if PIC_USE_ERROR + pic_call(pic, pic_deserialize(pic, pic_blob_value(pic, error_rom, sizeof error_rom)), 0); +#endif +} diff --git a/lib/ext/file.c b/lib/ext/file.c index 33bc5440..d2b5b5c3 100644 --- a/lib/ext/file.c +++ b/lib/ext/file.c @@ -75,13 +75,24 @@ pic_fopen(pic_state *pic, FILE *fp, const char *mode) { } } +#if !PIC_USE_ERROR +# define file_error pic_error +#else PIC_NORETURN static void -file_error(pic_state *pic, const char *msg, const char *fname) +file_error(pic_state *pic, const char *msg, int n, ...) { - pic_value fn = pic_cstr_value(pic, fname); + va_list ap; + pic_value e, irrs; - pic_raise(pic, pic_make_error(pic, "file", msg, pic_list(pic, 1, fn))); + va_start(ap, n); + irrs = pic_vlist(pic, n, ap); + va_end(ap); + + e = pic_funcall(pic, "make-error-object", 3, pic_intern_lit(pic, "file"), pic_cstr_value(pic, msg), irrs); + pic_funcall(pic, "raise", 1, e); + PIC_UNREACHABLE(); } +#endif pic_value pic_file_open_input_file(pic_state *pic) @@ -92,7 +103,7 @@ pic_file_open_input_file(pic_state *pic) pic_get_args(pic, "z", &fname); if ((fp = fopen(fname, "r")) == NULL) { - file_error(pic, "could not open file", fname); + file_error(pic, "could not open file", 1, pic_cstr_value(pic, fname)); } return pic_fopen(pic, fp, "r"); } @@ -106,7 +117,7 @@ pic_file_open_output_file(pic_state *pic) pic_get_args(pic, "z", &fname); if ((fp = fopen(fname, "w")) == NULL) { - file_error(pic, "could not open file", fname); + file_error(pic, "could not open file", 1, pic_cstr_value(pic, fname)); } return pic_fopen(pic, fp, "w"); } @@ -134,7 +145,7 @@ pic_file_delete(pic_state *pic) pic_get_args(pic, "z", &fname); if (remove(fname) != 0) { - file_error(pic, "file cannot be deleted", fname); + file_error(pic, "file cannot be deleted", 1, pic_cstr_value(pic, fname)); } return pic_undef_value(pic); } diff --git a/lib/ext/main.c b/lib/ext/main.c index 12c04de3..acb17dda 100644 --- a/lib/ext/main.c +++ b/lib/ext/main.c @@ -11,7 +11,7 @@ main(int argc, char *argv[]) pic_state *pic; pic_value e, port; - pic = pic_open(pic_default_allocf, NULL); + pic = pic_open(pic_default_allocf, NULL, pic_default_panicf); pic_try { if (argc == 1) { /* repl */ diff --git a/lib/ext/read.c b/lib/ext/read.c index 23e9e19f..b374e3d8 100644 --- a/lib/ext/read.c +++ b/lib/ext/read.c @@ -30,11 +30,24 @@ static pic_reader_t reader_dispatch[256]; static pic_value read_core(pic_state *pic, pic_value port, int c, struct reader_control *p); static pic_value read_nullable(pic_state *pic, pic_value port, int c, struct reader_control *p); +#if !PIC_USE_ERROR +# define read_error pic_error +#else PIC_NORETURN static void -read_error(pic_state *pic, const char *msg, pic_value irritants) +read_error(pic_state *pic, const char *msg, int n, ...) { - pic_raise(pic, pic_make_error(pic, "read", msg, irritants)); + va_list ap; + pic_value e, irrs; + + va_start(ap, n); + irrs = pic_vlist(pic, n, ap); + va_end(ap); + + e = pic_funcall(pic, "make-error-object", 3, pic_intern_lit(pic, "read"), pic_cstr_value(pic, msg), irrs); + pic_funcall(pic, "raise", 1, e); + PIC_UNREACHABLE(); } +#endif static int skip(pic_state *pic, pic_value port, int c) @@ -252,7 +265,7 @@ read_uinteger(pic_state *pic, pic_value port, int c, struct reader_control *PIC_ unsigned u = 0; if (! isdigit(c)) { - read_error(pic, "expected one or more digits", pic_list(pic, 1, pic_char_value(pic, c))); + read_error(pic, "expected one or more digits", 1, pic_char_value(pic, c)); } u = c - '0'; @@ -268,10 +281,10 @@ read_true(pic_state *pic, pic_value port, int c, struct reader_control *PIC_UNUS { if ((c = peek(pic, port)) == 'r') { if (! expect(pic, port, "rue")) { - read_error(pic, "unexpected character while reading #true", pic_nil_value(pic)); + read_error(pic, "unexpected character while reading #true", 0); } } else if (! isdelim(c)) { - read_error(pic, "non-delimiter character given after #t", pic_list(pic, 1, pic_char_value(pic, c))); + read_error(pic, "non-delimiter character given after #t", 1, pic_char_value(pic, c)); } return pic_true_value(pic); @@ -282,10 +295,10 @@ read_false(pic_state *pic, pic_value port, int c, struct reader_control *PIC_UNU { if ((c = peek(pic, port)) == 'a') { if (! expect(pic, port, "alse")) { - read_error(pic, "unexpected character while reading #false", pic_nil_value(pic)); + read_error(pic, "unexpected character while reading #false", 0); } } else if (! isdelim(c)) { - read_error(pic, "non-delimiter character given after #f", pic_list(pic, 1, pic_char_value(pic, c))); + read_error(pic, "non-delimiter character given after #f", 1, pic_char_value(pic, c)); } return pic_false_value(pic); @@ -298,7 +311,7 @@ read_char(pic_state *pic, pic_value port, int c, struct reader_control *PIC_UNUS if (! isdelim(peek(pic, port))) { switch (c) { - default: read_error(pic, "unexpected character after char literal", pic_list(pic, 1, pic_char_value(pic, c))); + default: read_error(pic, "unexpected character after char literal", 1, pic_char_value(pic, c)); case 'a': c = '\a'; if (! expect(pic, port, "larm")) goto fail; break; case 'b': c = '\b'; if (! expect(pic, port, "ackspace")) goto fail; break; case 'd': c = 0x7F; if (! expect(pic, port, "elete")) goto fail; break; @@ -323,7 +336,7 @@ read_char(pic_state *pic, pic_value port, int c, struct reader_control *PIC_UNUS return pic_char_value(pic, (char)c); fail: - read_error(pic, "unexpected character while reading character literal", pic_list(pic, 1, pic_char_value(pic, c))); + read_error(pic, "unexpected character while reading character literal", 1, pic_char_value(pic, c)); } static pic_value @@ -386,7 +399,7 @@ read_pipe(pic_state *pic, pic_value port, int c, struct reader_control *PIC_UNUS i = 0; while ((HEX_BUF[i++] = (char)next(pic, port)) != ';') { if (i >= sizeof HEX_BUF) - read_error(pic, "expected ';'", pic_list(pic, 1, pic_char_value(pic, HEX_BUF[sizeof(HEX_BUF) - 1]))); + read_error(pic, "expected ';'", 1, pic_char_value(pic, HEX_BUF[sizeof(HEX_BUF) - 1])); } c = (char)strtol(HEX_BUF, NULL, 16); break; @@ -420,11 +433,11 @@ read_blob(pic_state *pic, pic_value port, int c, struct reader_control *p) } if (nbits != 8) { - read_error(pic, "unsupported bytevector bit width", pic_list(pic, 1, pic_int_value(pic, nbits))); + read_error(pic, "unsupported bytevector bit width", 1, pic_int_value(pic, nbits)); } if (c != '(') { - read_error(pic, "expected '(' character", pic_list(pic, 1, pic_char_value(pic, c))); + read_error(pic, "expected '(' character", 1, pic_char_value(pic, c)); } len = 0; @@ -433,7 +446,7 @@ read_blob(pic_state *pic, pic_value port, int c, struct reader_control *p) while ((c = skip(pic, port, c)) != ')') { n = read_uinteger(pic, port, c, p); if (n < 0 || (1 << nbits) <= n) { - read_error(pic, "invalid element in bytevector literal", pic_list(pic, 1, pic_int_value(pic, n))); + read_error(pic, "invalid element in bytevector literal", 1, pic_int_value(pic, n)); } len += 1; dat = pic_realloc(pic, dat, len); @@ -452,12 +465,12 @@ read_undef_or_blob(pic_state *pic, pic_value port, int c, struct reader_control { if ((c = peek(pic, port)) == 'n') { if (! expect(pic, port, "ndefined")) { - read_error(pic, "unexpected character while reading #undefined", pic_nil_value(pic)); + read_error(pic, "unexpected character while reading #undefined", 0); } return pic_undef_value(pic); } if (! isdigit(c)) { - read_error(pic, "expect #undefined or #u8(...), but illegal character given", pic_list(pic, 1, pic_char_value(pic, c))); + read_error(pic, "expect #undefined or #u8(...), but illegal character given", 1, pic_char_value(pic, c)); } return read_blob(pic, port, 'u', p); } @@ -483,7 +496,7 @@ read_pair(pic_state *pic, pic_value port, int c, struct reader_control *p) if (pic_invalid_p(pic, read_nullable(pic, port, c, p))) { goto closing; } - read_error(pic, "unmatched parenthesis", pic_nil_value(pic)); + read_error(pic, "unmatched parenthesis", 0); } return cdr; } @@ -579,7 +592,7 @@ read_label_ref(pic_state *pic, pic_value PIC_UNUSED(port), int i, struct reader_ it = kh_get(read, h, i); if (it == kh_end(h)) { - read_error(pic, "label of given index not defined", pic_list(pic, 1, pic_int_value(pic, i))); + read_error(pic, "label of given index not defined", 1, pic_int_value(pic, i)); } return kh_val(h, it); } @@ -600,13 +613,13 @@ read_label(pic_state *pic, pic_value port, int c, struct reader_control *p) if (c == '#') { return read_label_ref(pic, port, i, p); } - read_error(pic, "broken label expression", pic_nil_value(pic)); + read_error(pic, "broken label expression", 0); } static pic_value read_unmatch(pic_state *pic, pic_value PIC_UNUSED(port), int PIC_UNUSED(c), struct reader_control *PIC_UNUSED(p)) { - read_error(pic, "unmatched parenthesis", pic_nil_value(pic)); + read_error(pic, "unmatched parenthesis", 0); } static pic_value @@ -615,11 +628,11 @@ read_dispatch(pic_state *pic, pic_value port, int c, struct reader_control *p) c = next(pic, port); if (c == EOF) { - read_error(pic, "unexpected EOF", pic_nil_value(pic)); + read_error(pic, "unexpected EOF", 0); } if (reader_dispatch[c] == NULL) { - read_error(pic, "invalid character at the seeker head", pic_list(pic, 1, pic_char_value(pic, c))); + read_error(pic, "invalid character at the seeker head", 1, pic_char_value(pic, c)); } return reader_dispatch[c](pic, port, c, p); @@ -631,11 +644,11 @@ read_nullable(pic_state *pic, pic_value port, int c, struct reader_control *p) c = skip(pic, port, c); if (c == EOF) { - read_error(pic, "unexpected EOF", pic_nil_value(pic)); + read_error(pic, "unexpected EOF", 0); } if (reader_table[c] == NULL) { - read_error(pic, "invalid character at the seeker head", pic_list(pic, 1, pic_char_value(pic, c))); + read_error(pic, "invalid character at the seeker head", 1, pic_char_value(pic, c)); } return reader_table[c](pic, port, c, p); @@ -708,46 +721,48 @@ reader_table_init(void) } static void -reader_init(pic_state *PIC_UNUSED(pic), struct reader_control *p) +destroy_reader_control(pic_state *pic, void *ptr) { - p->typecase = CASE_DEFAULT; - kh_init(read, &p->labels); + struct reader_control *p = ptr; + + kh_destroy(read, &p->labels); + pic_free(pic, ptr); } -static void -reader_destroy(pic_state *pic, struct reader_control *p) +static struct reader_control * +make_reader_control(pic_state *pic) { - kh_destroy(read, &p->labels); + struct reader_control *p; + static const pic_data_type t = { "pic_reader_control", destroy_reader_control }; + + p = pic_malloc(pic, sizeof *p); + p->typecase = CASE_DEFAULT; + kh_init(read, &p->labels); + + pic_data_value(pic, p, &t); + + return p; } static pic_value read_value(pic_state *pic, pic_value port) { - struct reader_control p; - size_t ai = pic_enter(pic); + struct reader_control *p = make_reader_control(pic); + size_t ai; pic_value val; int c; - pic_value e; - reader_init(pic, &p); + ai = pic_enter(pic); + while ((c = skip(pic, port, next(pic, port))) != EOF) { + val = read_nullable(pic, port, c, p); - pic_try { - size_t ai = pic_enter(pic); - while ((c = skip(pic, port, next(pic, port))) != EOF) { - val = read_nullable(pic, port, c, &p); - - if (! pic_invalid_p(pic, val)) { - break; - } - pic_leave(pic, ai); - } - if (c == EOF) { - val = pic_eof_object(pic); + if (! pic_invalid_p(pic, val)) { + break; } + pic_leave(pic, ai); } - pic_catch(e) { - reader_destroy(pic, &p); - pic_raise(pic, e); + if (c == EOF) { + val = pic_eof_object(pic); } pic_leave(pic, ai); diff --git a/lib/ext/write.c b/lib/ext/write.c index bc960963..de54b788 100644 --- a/lib/ext/write.c +++ b/lib/ext/write.c @@ -296,33 +296,6 @@ write_record(pic_state *pic, pic_value obj, pic_value port, struct writer_contro pic_fprintf(pic, port, ">"); } -static void -write_error(pic_state *pic, pic_value err, pic_value port, struct writer_control *p) -{ - if (p->mode == WRITE_MODE) { - pic_fprintf(pic, port, "#", obj_ptr(pic, err)); - return; - } - - if (! pic_error_p(pic, err)) { - pic_fprintf(pic, port, "raise: ~s", err); - } else { - struct error *e; - pic_value elem, it; - - e = error_ptr(pic, err); - if (! pic_eq_p(pic, obj_value(pic, e->type), pic_intern_lit(pic, ""))) { - pic_fprintf(pic, port, "~s-", obj_value(pic, e->type)); - } - pic_fprintf(pic, port, "error: \"~a\"", obj_value(pic, e->msg)); - - pic_for_each (elem, e->irrs, it) { /* print error irritants */ - pic_fprintf(pic, port, " ~s", elem); - } - pic_fprintf(pic, port, "\n"); - } -} - static const char * typename(pic_state *pic, pic_value obj) { @@ -356,8 +329,6 @@ typename(pic_state *pic, pic_value obj) return "bytevector"; case PIC_TYPE_PORT: return "port"; - case PIC_TYPE_ERROR: - return "error"; case PIC_TYPE_FRAME: return "frame"; case PIC_TYPE_IREP: @@ -441,9 +412,6 @@ write_core(pic_state *pic, pic_value obj, pic_value port, struct writer_control case PIC_TYPE_RECORD: write_record(pic, obj, port, p); break; - case PIC_TYPE_ERROR: - write_error(pic, obj, port, p); - break; default: pic_fprintf(pic, port, "#<%s %p>", typename(pic, obj), obj_ptr(pic, obj)); break; diff --git a/lib/gc.c b/lib/gc.c index 9a56623a..ea9493f5 100644 --- a/lib/gc.c +++ b/lib/gc.c @@ -26,7 +26,6 @@ struct object { struct proc proc; struct frame frame; struct port port; - struct error err; struct irep irep; } u; }; @@ -104,9 +103,11 @@ pic_malloc(pic_state *pic, size_t size) { void *ptr; + retry: ptr = pic->allocf(pic->userdata, NULL, size); if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); + pic->panicf(pic, "out of memory", 0, NULL); + goto retry; } return ptr; } @@ -114,9 +115,11 @@ pic_malloc(pic_state *pic, size_t size) void * pic_realloc(pic_state *pic, void *ptr, size_t size) { + retry: ptr = pic->allocf(pic->userdata, ptr, size); if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); + pic->panicf(pic, "out of memory", 0, NULL); + goto retry; } return ptr; } @@ -127,9 +130,11 @@ pic_calloc(pic_state *pic, size_t count, size_t size) void *ptr; size *= count; + retry: ptr = pic->allocf(pic->userdata, NULL, size); if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); + pic->panicf(pic, "out of memory", 0, NULL); + goto retry; } memset(ptr, 0, size); return ptr; @@ -263,12 +268,6 @@ gc_mark_object(pic_state *pic, struct object *obj) case PIC_TYPE_PORT: { break; } - case PIC_TYPE_ERROR: { - gc_mark_object(pic, (struct object *)obj->u.err.type); - gc_mark(pic, obj->u.err.irrs); - LOOP(obj->u.err.msg); - break; - } case PIC_TYPE_STRING: { break; } @@ -434,7 +433,6 @@ gc_finalize_object(pic_state *pic, struct object *obj) } case PIC_TYPE_PAIR: - case PIC_TYPE_ERROR: case PIC_TYPE_RECORD: case PIC_TYPE_PROC_FUNC: case PIC_TYPE_PROC_IREP: @@ -460,7 +458,6 @@ type2size(int type) case PIC_TYPE_PORT: return sizeof(struct port); case PIC_TYPE_PAIR: return sizeof(struct pair); case PIC_TYPE_FRAME: return sizeof(struct frame); - case PIC_TYPE_ERROR: return sizeof(struct error); case PIC_TYPE_RECORD: return sizeof(struct record); case PIC_TYPE_PROC_FUNC: return sizeof(struct proc); case PIC_TYPE_PROC_IREP: return sizeof(struct proc); @@ -669,9 +666,12 @@ pic_obj_alloc_unsafe(pic_state *pic, int type) obj = obj_alloc(pic, type); if (obj == NULL) { pic_gc(pic); + retry: obj = obj_alloc(pic, type); - if (obj == NULL) - pic_panic(pic, "GC memory exhausted"); + if (obj == NULL) { + pic->panicf(pic, "out of memory", 0, NULL); + goto retry; + } } return obj; diff --git a/lib/include/picconf.h b/lib/include/picconf.h index 48311f90..3df8bd72 100644 --- a/lib/include/picconf.h +++ b/lib/include/picconf.h @@ -18,6 +18,7 @@ /* #define PIC_USE_WRITE 1 */ /* #define PIC_USE_EVAL 1 */ /* #define PIC_USE_FILE 1 */ +/* #define PIC_USE_ERROR 1 */ /** * I/O configuration diff --git a/lib/include/picrin.h b/lib/include/picrin.h index d9f4a96a..0e81485c 100644 --- a/lib/include/picrin.h +++ b/lib/include/picrin.h @@ -59,7 +59,8 @@ typedef struct { */ typedef void *(*pic_allocf)(void *userdata, void *ptr, size_t n); -pic_state *pic_open(pic_allocf f, void *userdata); +typedef void (*pic_panicf)(pic_state *, const char *msg, int n, pic_value *args); +pic_state *pic_open(pic_allocf allocf, void *userdata, pic_panicf panicf); void pic_close(pic_state *); @@ -291,39 +292,6 @@ pic_value pic_fmemopen(pic_state *, const char *buf, int len, const char *mode); int pic_fgetbuf(pic_state *, pic_value port, const char **buf, int *len); /* deprecated */ -/* - * error handling - */ - -typedef void (*pic_panicf)(pic_state *, const char *msg); -pic_panicf pic_atpanic(pic_state *, pic_panicf f); -PIC_NORETURN void pic_panic(pic_state *, const char *msg); -pic_value pic_raise_continuable(pic_state *pic, pic_value err); -PIC_NORETURN void pic_raise(pic_state *, pic_value v); -PIC_NORETURN void pic_error(pic_state *, const char *msg, int n, ...); - -#define pic_try pic_try_(PIC_GENSYM(jmp)) -#define pic_try_(jmp) \ - do { \ - extern PIC_JMPBUF *pic_prepare_try(pic_state *); \ - extern void pic_enter_try(pic_state *); \ - extern void pic_exit_try(pic_state *); \ - extern pic_value pic_abort_try(pic_state *); \ - PIC_JMPBUF *jmp = pic_prepare_try(pic); \ - if (PIC_SETJMP(*jmp) == 0) { \ - pic_enter_try(pic); -#define pic_catch(e) pic_catch_(e, PIC_GENSYM(label)) -#define pic_catch_(e, label) \ - pic_exit_try(pic); \ - } else { \ - e = pic_abort_try(pic); \ - goto label; \ - } \ - } while (0); \ - if (0) \ - label: - - /* * core language features */ @@ -338,6 +306,8 @@ void pic_defvar(pic_state *, const char *name, pic_value v); pic_value pic_funcall(pic_state *, const char *name, int n, ...); pic_value pic_values(pic_state *, int n, ...); pic_value pic_vvalues(pic_state *, int n, va_list); +PIC_NORETURN void pic_error(pic_state *, const char *msg, int n, ...); +PIC_NORETURN void pic_verror(pic_state *pic, const char *msg, int n, va_list ap); /* diff --git a/lib/include/picrin/extra.h b/lib/include/picrin/extra.h index 7e1d481a..43d2e6a1 100644 --- a/lib/include/picrin/extra.h +++ b/lib/include/picrin/extra.h @@ -11,12 +11,36 @@ extern "C" { #if PIC_USE_LIBC void *pic_default_allocf(void *, void *, size_t); +void pic_default_panicf(pic_state *, const char *, int, pic_value *); #endif #if PIC_USE_FILE pic_value pic_fopen(pic_state *, FILE *, const char *mode); #endif +#if PIC_USE_ERROR +# define pic_try pic_try_(PIC_GENSYM(jmp)) +# define pic_try_(jmp) \ + do { \ + extern PIC_JMPBUF *pic_prepare_try(pic_state *); \ + extern void pic_enter_try(pic_state *); \ + extern void pic_exit_try(pic_state *); \ + extern pic_value pic_abort_try(pic_state *); \ + PIC_JMPBUF *jmp = pic_prepare_try(pic); \ + if (PIC_SETJMP(*jmp) == 0) { \ + pic_enter_try(pic); +# define pic_catch(e) pic_catch_(e, PIC_GENSYM(label)) +# define pic_catch_(e, label) \ + pic_exit_try(pic); \ + } else { \ + e = pic_abort_try(pic); \ + goto label; \ + } \ + } while (0); \ + if (0) \ + label: +#endif + #if defined(__cplusplus) } #endif diff --git a/lib/include/picrin/setup.h b/lib/include/picrin/setup.h index 0f4fd3d1..765987cc 100644 --- a/lib/include/picrin/setup.h +++ b/lib/include/picrin/setup.h @@ -28,12 +28,19 @@ # define PIC_USE_FILE 1 #endif +#ifndef PIC_USE_ERROR +# define PIC_USE_ERROR 1 +#endif + #if !PIC_USE_LIBC && PIC_USE_FILE # error PIC_USE_FILE requires PIC_USE_LIBC #endif #if !PIC_USE_LIBC && PIC_USE_CALLCC # error PIC_USE_CALLCC requires PIC_USE_LIBC #endif +#if !PIC_USE_CALLCC && PIC_USE_ERROR +# error PIC_USE_ERROR requires PIC_USE_CALLCC +#endif #if PIC_USE_CALLCC # include diff --git a/lib/include/picrin/value.h b/lib/include/picrin/value.h index a855d7d8..56fa45c7 100644 --- a/lib/include/picrin/value.h +++ b/lib/include/picrin/value.h @@ -31,7 +31,6 @@ enum { PIC_TYPE_RECORD = 23, PIC_TYPE_ATTR = 24, PIC_TYPE_PORT = 25, - PIC_TYPE_ERROR = 26, PIC_TYPE_IREP = 27, PIC_TYPE_FRAME = 28, PIC_TYPE_PROC_FUNC = 29, @@ -222,7 +221,6 @@ DEFPRED(pic_false_p, PIC_TYPE_FALSE) DEFPRED(pic_str_p, PIC_TYPE_STRING) DEFPRED(pic_vec_p, PIC_TYPE_VECTOR) DEFPRED(pic_blob_p, PIC_TYPE_BLOB) -DEFPRED(pic_error_p, PIC_TYPE_ERROR) DEFPRED(pic_dict_p, PIC_TYPE_DICT) DEFPRED(pic_attr_p, PIC_TYPE_ATTR) DEFPRED(pic_rec_p, PIC_TYPE_RECORD) diff --git a/lib/object.h b/lib/object.h index b85f669d..7a741306 100644 --- a/lib/object.h +++ b/lib/object.h @@ -152,18 +152,10 @@ struct port { } file; }; -struct error { - OBJECT_HEADER - struct symbol *type; - struct string *msg; - pic_value irrs; -}; - #define TYPENAME_int "integer" #define TYPENAME_blob "bytevector" #define TYPENAME_char "character" #define TYPENAME_sym "symbol" -#define TYPENAME_error "error" #define TYPENAME_proc "procedure" #define TYPENAME_str "string" #define TYPENAME_vec "vector" @@ -257,7 +249,6 @@ DEFPTR(attr, struct attr) DEFPTR(data, struct data) DEFPTR(proc, struct proc) DEFPTR(port, struct port) -DEFPTR(error, struct error) DEFPTR(rec, struct record) DEFPTR(irep, struct irep) #undef pic_data_p @@ -273,7 +264,6 @@ pic_value pic_make_record(pic_state *, pic_value type, pic_value datum); pic_value pic_record_type(pic_state *pic, pic_value record); pic_value pic_record_datum(pic_state *pic, pic_value record); pic_value pic_make_cont(pic_state *pic, pic_value k); -pic_value pic_make_error(pic_state *, const char *type, const char *msg, pic_value irrs); struct rope *pic_rope_incref(struct rope *); void pic_rope_decref(pic_state *, struct rope *); diff --git a/lib/state.c b/lib/state.c index dd19bdf2..926a2d5a 100644 --- a/lib/state.c +++ b/lib/state.c @@ -29,11 +29,25 @@ pic_state_global_objects(pic_state *pic) return pic->globals; } +static pic_value +pic_state_error(pic_state *pic) +{ + const char *msg; + int argc; + pic_value *args; + + pic_get_args(pic, "z*", &msg, &argc, &args); + + pic->panicf(pic, msg, argc, args); + PIC_UNREACHABLE(); +} + static void pic_init_state(pic_state *pic) { pic_defun(pic, "features", pic_state_features); pic_defun(pic, "global-objects", pic_state_global_objects); + pic_defun(pic, "error", pic_state_error); pic_add_feature(pic, "picrin"); @@ -128,7 +142,6 @@ pic_init_core(pic_state *pic) pic_init_vector(pic); DONE; pic_init_blob(pic); DONE; pic_init_char(pic); DONE; - pic_init_error(pic); DONE; pic_init_str(pic); DONE; pic_init_var(pic); DONE; pic_init_dict(pic); DONE; @@ -151,10 +164,13 @@ pic_init_core(pic_state *pic) #if PIC_USE_EVAL pic_init_eval(pic); DONE; #endif +#if PIC_USE_ERROR + pic_init_error(pic); DONE; +#endif } pic_state * -pic_open(pic_allocf allocf, void *userdata) +pic_open(pic_allocf allocf, void *userdata, pic_panicf panicf) { pic_state *pic; @@ -170,6 +186,9 @@ pic_open(pic_allocf allocf, void *userdata) /* user data */ pic->userdata = userdata; + /* panic handler */ + pic->panicf = panicf; + /* context */ pic->default_cxt.ai = 0; pic->default_cxt.pc = NULL; @@ -280,6 +299,20 @@ pic_close(pic_state *pic) allocf(pic->userdata, pic, 0); } +void +pic_warnf(pic_state *PIC_UNUSED(pic), const char *PIC_UNUSED(fmt), ...) +{ +#if PIC_USE_FILE + va_list ap; + pic_value err; + + va_start(ap, fmt); + err = pic_vstrf_value(pic, fmt, ap); + va_end(ap); + pic_fprintf(pic, pic_stderr(pic), "warn: %s\n", pic_str(pic, err, NULL)); +#endif +} + pic_value pic_global_ref(pic_state *pic, pic_value sym) { @@ -353,3 +386,40 @@ pic_funcall(pic_state *pic, const char *name, int n, ...) pic_leave(pic, ai); return pic_protect(pic, r); } + +#if PIC_USE_LIBC +void +pic_default_panicf(pic_state *pic, const char *msg, int PIC_UNUSED(n), pic_value *PIC_UNUSED(args)) +{ + fprintf(stderr, "panic!: %s\n", msg); + abort(); +} +#endif + +void +pic_error(pic_state *pic, const char *msg, int n, ...) +{ + va_list ap; + + va_start(ap, n); + pic_verror(pic, msg, n, ap); + va_end(ap); + PIC_UNREACHABLE(); +} + +void +pic_verror(pic_state *pic, const char *msg, int n, va_list ap) +{ + pic_value error = pic_ref(pic, "error"); + int i; + pic_value *args; + + args = pic_alloca(pic, sizeof(pic_value) * (n + 1)); + args[0] = pic_cstr_value(pic, msg); + for (i = 0; i < n; ++i) { + args[i + 1] = va_arg(ap, pic_value); + } + + pic_apply(pic, error, n + 1, args); + PIC_UNREACHABLE(); +} diff --git a/piclib/error.c b/piclib/error.c new file mode 100644 index 00000000..96f85d62 --- /dev/null +++ b/piclib/error.c @@ -0,0 +1,88 @@ +/** + * See Copyright Notice in picrin.h + */ + +#include "picrin.h" +#include "../object.h" +#include "../state.h" + +#if PIC_USE_ERROR + +# define pic_exc(pic) pic_ref(pic, "current-exception-handlers") + +PIC_JMPBUF * +pic_prepare_try(pic_state *pic) +{ + struct context *cxt = pic_malloc(pic, sizeof(struct context)); + + cxt->pc = NULL; + cxt->fp = NULL; + cxt->sp = NULL; + cxt->irep = NULL; + cxt->conts = pic_nil_value(pic); + cxt->prev = pic->cxt; + pic->cxt = cxt; + return &cxt->jmp; +} + +static pic_value +native_exception_handler(pic_state *pic) +{ + pic_value err; + + pic_get_args(pic, "o", &err); + + pic_call(pic, pic_closure_ref(pic, 0), 1, err); + PIC_UNREACHABLE(); +} + +void +pic_enter_try(pic_state *pic) +{ + pic_value cont, handler; + pic_value var, env; + + pic->cxt->ai = pic->ai; + + /* call/cc */ + cont = pic_make_cont(pic, pic_invalid_value(pic)); + handler = pic_lambda(pic, native_exception_handler, 1, cont); + /* with-exception-handler */ + var = pic_exc(pic); + env = pic_make_attr(pic); + pic_attr_set(pic, env, var, pic_cons(pic, handler, pic_call(pic, var, 0))); + pic->dyn_env = pic_cons(pic, env, pic->dyn_env); + + pic_leave(pic, pic->cxt->ai); +} + +void +pic_exit_try(pic_state *pic) +{ + struct context *cxt = pic->cxt; + pic_value c, it; + pic->dyn_env = pic_cdr(pic, pic->dyn_env); + pic_for_each (c, cxt->conts, it) { + proc_ptr(pic, c)->env->regs[0] = pic_false_value(pic); + } + pic->cxt = cxt->prev; + pic_free(pic, cxt); + /* don't rewind ai here */ +} + +pic_value +pic_abort_try(pic_state *pic) +{ + struct context *cxt = pic->cxt; + pic_value c, it; + pic_value err = cxt->sp->regs[1]; + pic_for_each (c, cxt->conts, it) { + proc_ptr(pic, c)->env->regs[0] = pic_false_value(pic); + } + pic->cxt = cxt->prev; + pic_free(pic, cxt); + pic_protect(pic, err); + return err; +} + +#endif diff --git a/piclib/error.scm b/piclib/error.scm new file mode 100644 index 00000000..ad2b677d --- /dev/null +++ b/piclib/error.scm @@ -0,0 +1,52 @@ +(begin + + (define current-exception-handlers + (let ((e error)) + (make-parameter (list e)))) + + (define (raise x) + (let ((handlers (current-exception-handlers))) + (parameterize ((current-exception-handlers (cdr handlers))) + ((car handlers) x) + (error "handler returned" x)))) + + (define (raise-continuable x) + (let ((handlers (current-exception-handlers))) + (parameterize ((current-exception-handlers (cdr handlers))) + ((car handlers) x)))) + + (define (with-exception-handler handler thunk) + (let ((handlers (current-exception-handlers))) + (parameterize ((current-exception-handlers (cons handler handlers))) + (thunk)))) + + (define-record-type error-object + (make-error-object type message irritants) + error-object? + (type error-object-type) + (message error-object-message) + (irritants error-object-irritants)) + + (set! error + (lambda (message . irritants) + (raise (make-error-object #f message irritants)))) + + (set! display + (let ((d display)) + (lambda (x . port) + (let ((port (if (null? port) (current-error-port) (car port)))) + (if (error-object? x) + (let () + (when (error-object-type x) + (d (error-object-type x) port) + (d "-" port)) + (d "error: \"" port) + (d (error-object-message x) port) + (d "\"") + (for-each + (lambda (x) + (d " " port) + (write x port)) + (error-object-irritants x)) + (d "\n" port)) + (apply d x port))))))) diff --git a/src/main.c b/src/main.c index 52dae7ca..62c6ae76 100644 --- a/src/main.c +++ b/src/main.c @@ -28,7 +28,7 @@ main(int argc, char *argv[], char **envp) pic_value e; int status; - pic = pic_open(pic_default_allocf, NULL); + pic = pic_open(pic_default_allocf, NULL, pic_default_panicf); picrin_argc = argc; picrin_argv = argv; diff --git a/tools/mkerror.scm b/tools/mkerror.scm new file mode 100644 index 00000000..782bfcd1 --- /dev/null +++ b/tools/mkerror.scm @@ -0,0 +1,30 @@ +(let ((port (open-input-file "piclib/error.c"))) + (let loop () + (let ((c (read-u8 port))) + (unless (eof-object? c) + (write-u8 c) + (loop))))) + +(for-each + display + `("\n" + "#if PIC_USE_ERROR\n" + "static ")) + +(let loop () + (let ((c (read-u8))) + (unless (eof-object? c) + (write-u8 c) + (loop)))) + +(for-each + display + `("#endif\n" + "\n" + "void\n" + "pic_init_error(pic_state *PIC_UNUSED(pic))\n" + "{\n" + "#if PIC_USE_ERROR\n" + " pic_call(pic, pic_deserialize(pic, pic_blob_value(pic, error_rom, sizeof error_rom)), 0);\n" + "#endif\n" + "}\n"))