#include #include #include #include #include #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif static int get_status(mrb_state *mrb) { mrb_value status = mrb_true_value(); mrb_get_args(mrb, "|o", &status); if (mrb_true_p(status)) return EXIT_SUCCESS; if (mrb_false_p(status)) return EXIT_FAILURE; return (int)mrb_as_int(mrb, status); } /* * call-seq: * exit(status=true) * * Initiates the termination of the Ruby script by raising the * SystemExit exception. This exception may be caught. The * optional parameter is used to return a status code to the invoking * environment. * * `true` and `false` of _status_ means success and failure * respectively. The interpretation of other integer values are * system dependent. * * exit(0) */ static mrb_value f_exit(mrb_state *mrb, mrb_value self) { int status = get_status(mrb); mrb_value exc = mrb_obj_new(mrb, mrb_exc_get_id(mrb, MRB_SYM(SystemExit)), 0, NULL); struct RException *e = mrb_exc_ptr(exc); e->flags |= MRB_EXC_EXIT; mrb_iv_set(mrb, exc, MRB_SYM(status), mrb_int_value(mrb, (mrb_int)status)); mrb_exc_raise(mrb, exc); /* not reached */ return mrb_nil_value(); } /* * call-seq: * exit!(status=true) * * Exits the process immediately. No exit handlers are run. * status is returned to the underlying system as the * exit status. * * exit!(0) */ static mrb_value f_exit_bang(mrb_state *mrb, mrb_value self) { exit(get_status(mrb)); /* not reached */ return mrb_nil_value(); } void mrb_mruby_exit_gem_init(mrb_state* mrb) { mrb_define_class_id(mrb, MRB_SYM(SystemExit), E_EXCEPTION); mrb_define_private_method_id(mrb, mrb->kernel_module, MRB_SYM(exit), f_exit, MRB_ARGS_OPT(1)); mrb_define_private_method_id(mrb, mrb->kernel_module, MRB_SYM_B(exit), f_exit_bang, MRB_ARGS_OPT(1)); } void mrb_mruby_exit_gem_final(mrb_state* mrb) { }