diff options
| author | mimaki <[email protected]> | 2012-04-20 09:39:03 +0900 |
|---|---|---|
| committer | mimaki <[email protected]> | 2012-04-20 09:39:03 +0900 |
| commit | e0d6430f63c4cbe0c71ce82ee23284671389a818 (patch) | |
| tree | 41abad7f12eced98d9ac14d141cea62464c3332f /src/error.c | |
| parent | 54ad561098ed353ada70205c39b2c42a2a2eb9e5 (diff) | |
| download | mruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.tar.gz mruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.zip | |
add mruby sources
Diffstat (limited to 'src/error.c')
| -rw-r--r-- | src/error.c | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/src/error.c b/src/error.c new file mode 100644 index 000000000..9dbfc972f --- /dev/null +++ b/src/error.c @@ -0,0 +1,479 @@ +#include "mruby.h" +#include <stdarg.h> +#include <string.h> +#include <stdio.h> +#include <setjmp.h> +#include "error.h" +#include "opcode.h" +#include "irep.h" +#include "mruby/proc.h" +#include "mruby/numeric.h" +#include "variable.h" +#include "mruby/string.h" +#include "eval_intern.h" +#include "mruby/class.h" + +#define warn_printf printf + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +mrb_value +mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len) +{ + return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, mrb_str_new(mrb, ptr, len)); +} + +mrb_value +mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str) +{ + //StringValue(str); + mrb_string_value(mrb, &str); + return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, str); +} + +//mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr); +/* + * call-seq: + * Exception.new(msg = nil) -> exception + * + * Construct a new Exception object, optionally passing in + * a message. + */ + +static mrb_value +exc_initialize(mrb_state *mrb, mrb_value exc) +{ + mrb_value mesg; + + mrb_get_args(mrb, "o", &mesg); + mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), mesg); + + return exc; +} + +/* + * Document-method: exception + * + * call-seq: + * exc.exception(string) -> an_exception or exc + * + * With no argument, or if the argument is the same as the receiver, + * return the receiver. Otherwise, create a new + * exception object of the same class as the receiver, but with a + * message equal to <code>string.to_str</code>. + * + */ + +static mrb_value +exc_exception(mrb_state *mrb, mrb_value self) +{ + mrb_value exc; + mrb_value *argv; + int argc; + + mrb_get_args(mrb, "*", &argv, &argc); + + if (argc == 0) return self; + if (argc == 1 && mrb_obj_equal(mrb, self, argv[0])) return self; + exc = mrb_obj_clone(mrb, self); + exc_initialize(mrb, exc); + + return exc; +} + +/* + * call-seq: + * exception.to_s -> string + * + * Returns exception's message (or the name of the exception if + * no message is set). + */ + +static mrb_value +exc_to_s(mrb_state *mrb, mrb_value exc) +{ + mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg")); + + if (mrb_nil_p(mesg)) return mrb_str_new2(mrb, mrb_obj_classname(mrb, exc)); + return mesg; +} + +/* + * call-seq: + * exception.message -> string + * + * Returns the result of invoking <code>exception.to_s</code>. + * Normally this returns the exception's message or name. By + * supplying a to_str method, exceptions are agreeing to + * be used where Strings are expected. + */ + +static mrb_value +exc_message(mrb_state *mrb, mrb_value exc) +{ + return mrb_funcall(mrb, exc, "to_s", 0); +} + +/* + * call-seq: + * exception.inspect -> string + * + * Return this exception's class name an message + */ + +static mrb_value +exc_inspect(mrb_state *mrb, mrb_value exc) +{ + mrb_value str, klass; + + klass = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc)); + exc = mrb_obj_as_string(mrb, exc); + if (RSTRING_LEN(exc) == 0) { + return klass; + } + + str = mrb_str_new2(mrb, "#<"); + mrb_str_append(mrb, str, klass); + mrb_str_cat2(mrb, str, ": "); + mrb_str_append(mrb, str, exc); + mrb_str_cat2(mrb, str, ">"); + + return str; +} + + +static mrb_value +exc_equal(mrb_state *mrb, mrb_value exc) +{ + mrb_value obj; + mrb_value mesg; + mrb_sym id_mesg = mrb_intern(mrb, "mesg"); + + mrb_get_args(mrb, "o", &obj); + + if (mrb_obj_equal(mrb, exc, obj)) return mrb_true_value(); + + if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { + if ( mrb_respond_to(mrb, obj, mrb_intern(mrb, "message")) ) { + mesg = mrb_funcall(mrb, obj, "message", 0); + } + else + return mrb_false_value(); + } + else { + mesg = mrb_attr_get(mrb, obj, id_mesg); + } + + if (!mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg)) + return mrb_false_value(); + return mrb_true_value(); +} + +void +mrb_exc_raise(mrb_state *mrb, mrb_value exc) +{ + mrb->exc = mrb_object(exc); + longjmp(*(jmp_buf*)mrb->jmp, 1); +} + +void +mrb_raise_va(mrb_state *mrb, struct RClass *c, const char *fmt, va_list args) +{ + char buf[256]; + + vsnprintf(buf, 256, fmt, args); + mrb_exc_raise(mrb, mrb_exc_new(mrb, c, buf, strlen(buf))); +} + +void +mrb_raise(mrb_state *mrb, struct RClass *c, const char *fmt, ...) +{ + va_list args; + char buf[256]; + + va_start(args, fmt); + vsnprintf(buf, 256, fmt, args); + mrb_raise_va(mrb, c, fmt, args); + va_end(args); +} + +void +mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...) +{ + mrb_value exc, argv[2]; + va_list args; + char buf[256]; + + va_start(args, fmt); + //argv[0] = mrb_vsprintf(fmt, args); + vsnprintf(buf, 256, fmt, args); + argv[0] = mrb_str_new(mrb, buf, strlen(buf)); + va_end(args); + + argv[1] = mrb_str_new_cstr(mrb, mrb_sym2name(mrb, id)); + exc = mrb_class_new_instance(mrb, 2, argv, E_NAME_ERROR); + mrb_exc_raise(mrb, exc); +} +mrb_value +mrb_sprintf(mrb_state *mrb, const char *fmt, ...) +{ + va_list args; + char buf[256]; + + va_start(args, fmt); + vsnprintf(buf, 256, fmt, args); + va_end(args); + return mrb_str_new(mrb, buf, strlen(buf)); +} + +void +mrb_warn(const char *fmt, ...) +{ + va_list args; + char buf[256]; + + va_start(args, fmt); + snprintf(buf, 256, "warning: %s", fmt); + printf(buf, args); + va_end(args); +} + + +void +mrb_warning(const char *fmt, ...) +{ + va_list args; + char buf[256]; + + va_start(args, fmt); + snprintf(buf, 256, "warning: %s", fmt); + printf(buf, args); + va_end(args); +} + +void +mrb_bug(const char *fmt, ...) +{ + va_list args; + char buf[256]; + + va_start(args, fmt); + snprintf(buf, 256, "bug: %s", fmt); + printf(buf, args); + va_end(args); +} + +static const char * +mrb_strerrno(int err) +{ +#define defined_error(name, num) if (err == num) return name; +#define undefined_error(name) +//#include "known_errors.inc" +#undef defined_error +#undef undefined_error + return NULL; +} + +void +mrb_bug_errno(const char *mesg, int errno_arg) +{ + if (errno_arg == 0) + mrb_bug("%s: errno == 0 (NOERROR)", mesg); + else { + const char *errno_str = mrb_strerrno(errno_arg); + if (errno_str) + mrb_bug("%s: %s (%s)", mesg, strerror(errno_arg), errno_str); + else + mrb_bug("%s: %s (%d)", mesg, strerror(errno_arg), errno_arg); + } +} + +int +sysexit_status(mrb_state *mrb, mrb_value err) +{ + mrb_value st = mrb_iv_get(mrb, err, mrb_intern(mrb, "status")); + return mrb_fixnum(st); +} + +void +error_pos(void) +{ +#if 0 + const char *sourcefile = mrb_sourcefile(); + int sourceline = mrb_sourceline(); + + if (sourcefile) { + if (sourceline == 0) { + warn_printf("%s", sourcefile); + } + else if (mrb_frame_callee()) { + warn_printf("%s:%d:in `%s'", sourcefile, sourceline, + mrb_sym2name(mrb, mrb_frame_callee())); + } + else { + warn_printf("%s:%d", sourcefile, sourceline); + } + } +#endif +} + +static void +set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt) +{ + mrb_funcall(mrb, info, "set_backtrace", 1, bt); +} + +mrb_value +make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) +{ + mrb_value mesg; + int n; + + mesg = mrb_nil_value(); + switch (argc) { + case 0: + break; + case 1: + if (mrb_nil_p(argv[0])) + break; + if (isstr) { + mesg = mrb_check_string_type(mrb, argv[0]); + if (!mrb_nil_p(mesg)) { + mesg = mrb_exc_new3(mrb, mrb->eRuntimeError_class, mesg); + break; + } + } + n = 0; + goto exception_call; + + case 2: + case 3: + n = 1; +exception_call: + //if (argv[0] == sysstack_error) return argv[0]; + + //CONST_ID(mrb, exception, "exception"); + //mesg = mrb_check_funcall(mrb, argv[0], exception, n, argv+1); + //if (mrb_nil_p(mesg)) { + // /* undef */ + // mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); + //} + if (mrb_respond_to(mrb, argv[0], mrb_intern(mrb, "exception"))) { + mesg = mrb_funcall(mrb, argv[0], "exception", n, argv+1); + } + else { + /* undef */ + mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); + } + + break; + default: + mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%d for 0..3)", argc); + break; + } + if (argc > 0) { + if (!mrb_obj_is_kind_of(mrb, mesg, mrb->eException_class)) + mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); + if (argc > 2) + set_backtrace(mrb, mesg, argv[2]); + } + + return mesg; +} + +mrb_value +mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv) +{ + return make_exception(mrb, argc, argv, TRUE); +} + +void +mrb_sys_fail(mrb_state *mrb, const char *mesg) +{ + mrb_raise(mrb, mrb->eRuntimeError_class, "%s", mesg); +} + +static mrb_value +mrb_exc_c_exception(mrb_state *mrb, mrb_value exc) +{ + mrb_value *argv; + int argc; + + mrb_get_args(mrb, "*", &argv, &argc); + return mrb_make_exception(mrb, argc, argv); +} + +static mrb_value +mrb_exc_exception(mrb_state *mrb, mrb_value exc) +{ + mrb_value *argv; + int argc; + mrb_value exclass; + + mrb_get_args(mrb, "*", &argv, &argc); + if (argc == 0) return exc; + exclass = mrb_obj_value(mrb_class(mrb, exc)); + return mrb_funcall(mrb, exclass, mrb_intern(mrb, "exception"), argc, argv); +} + +void +mrb_init_exception(mrb_state *mrb) +{ + struct RClass *e; + struct RClass *eTypeError_class; + struct RClass *eArgumentError_class; + struct RClass *eIndexError_class; + struct RClass *eRangeError_class; + struct RClass *eNameError_class; + struct RClass *eNoMethodError_class; + struct RClass *eScriptError_class; + struct RClass *eSyntaxError_class; + struct RClass *eLoadError_class; + struct RClass *eSystemCallError_class; + struct RClass *eLocalJumpError_class; + struct RClass *eRegexpError_class; + struct RClass *eZeroDivisionError_class; + struct RClass *eEncodingError_class; + struct RClass *eNotImpError_class; + struct RClass *eFloatDomainError_class; + struct RClass *eKeyError_class; + + mrb->eException_class = e = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */ + mrb_define_class_method(mrb, e, "exception", mrb_instance_new, ARGS_ANY()); + mrb_define_method(mrb, e, "exception", exc_exception, ARGS_ANY()); + mrb_define_method(mrb, e, "initialize", exc_initialize, ARGS_ANY()); + mrb_define_method(mrb, e, "==", exc_equal, ARGS_REQ(1)); + mrb_define_method(mrb, e, "to_s", exc_to_s, ARGS_NONE()); + mrb_define_method(mrb, e, "message", exc_message, ARGS_NONE()); + mrb_define_method(mrb, e, "inspect", exc_inspect, ARGS_NONE()); + + mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ + mrb->eRuntimeError_class = mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ + + eTypeError_class = mrb_define_class(mrb, "TypeError", mrb->eStandardError_class); /* 15.2.29 */ + eArgumentError_class = mrb_define_class(mrb, "ArgumentError", mrb->eStandardError_class); /* 15.2.24 */ + eIndexError_class = mrb_define_class(mrb, "IndexError", mrb->eStandardError_class); /* 15.2.33 */ + eRangeError_class = mrb_define_class(mrb, "RangeError", mrb->eStandardError_class); /* 15.2.26 */ + eNameError_class = mrb_define_class(mrb, "NameError", mrb->eStandardError_class); /* 15.2.31 */ + + eNoMethodError_class = mrb_define_class(mrb, "NoMethodError", eNameError_class); /* 15.2.32 */ + eScriptError_class = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */ + eSyntaxError_class = mrb_define_class(mrb, "SyntaxError", eScriptError_class); /* 15.2.38 */ + eLoadError_class = mrb_define_class(mrb, "LoadError", eScriptError_class); /* 15.2.39 */ + eSystemCallError_class = mrb_define_class(mrb, "SystemCallError", mrb->eStandardError_class); /* 15.2.36 */ + eLocalJumpError_class = mrb_define_class(mrb, "LocalJumpError", mrb->eStandardError_class); /* 15.2.25 */ + eRegexpError_class = mrb_define_class(mrb, "RegexpError", mrb->eStandardError_class); /* 15.2.27 */ + eZeroDivisionError_class = mrb_define_class(mrb, "ZeroDivisionError", mrb->eStandardError_class); /* 15.2.30 */ + + eEncodingError_class = mrb_define_class(mrb, "EncodingError", mrb->eStandardError_class); + eNotImpError_class = mrb_define_class(mrb, "NotImplementedError", eScriptError_class); + + eFloatDomainError_class = mrb_define_class(mrb, "FloatDomainError", eRangeError_class); + eKeyError_class = mrb_define_class(mrb, "KeyError", eIndexError_class); +} |
