From e56d53e354b6eda96427f13563199e7a076d7983 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sahara Date: Wed, 13 Mar 2013 10:00:22 +0900 Subject: [PATCH] Errno module for mruby. --- README.md | 25 +- mrbgem.rake | 6 + src/errno.c | 163 +++++++++ src/gen.rb | 25 ++ src/known_errors.def | 145 ++++++++ src/known_errors_def.cstub | 725 +++++++++++++++++++++++++++++++++++++ src/known_errors_e2c.cstub | 435 ++++++++++++++++++++++ test/errno.rb | 60 +++ 8 files changed, 1583 insertions(+), 1 deletion(-) create mode 100644 mrbgem.rake create mode 100644 src/errno.c create mode 100755 src/gen.rb create mode 100644 src/known_errors.def create mode 100644 src/known_errors_def.cstub create mode 100644 src/known_errors_e2c.cstub create mode 100644 test/errno.rb diff --git a/README.md b/README.md index e76cddb82..e3c594cb5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,27 @@ mruby-errno =========== -Errno module for mruby \ No newline at end of file +Errno module for mruby + + +## License + +Copyright (c) 2013 Internet Initiative Japan Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/mrbgem.rake b/mrbgem.rake new file mode 100644 index 000000000..ba3d60dae --- /dev/null +++ b/mrbgem.rake @@ -0,0 +1,6 @@ +MRuby::Gem::Specification.new('mruby-errno') do |spec| + spec.license = 'MIT' + spec.authors = 'Internet Initiative Japan Inc.' + + spec.cc.include_paths << "#{build.root}/src" +end diff --git a/src/errno.c b/src/errno.c new file mode 100644 index 000000000..3c7d06693 --- /dev/null +++ b/src/errno.c @@ -0,0 +1,163 @@ +#include "mruby.h" +#include "mruby/array.h" +#include "mruby/class.h" +#include "mruby/hash.h" +#include "mruby/numeric.h" +#include "mruby/string.h" +#include "mruby/variable.h" +#include +#include +#include + +static mrb_value +mrb_sce_init(mrb_state *mrb, mrb_value self) +{ + mrb_value c, e2c, m, str; + mrb_int n; + int argc, no_errno = 0; + char buf[20]; + + argc = mrb_get_args(mrb, "o|i", &m, &n); + if (argc == 1) { + if (mrb_type(m) == MRB_TT_FIXNUM) { + n = mrb_fixnum(m); + m = mrb_nil_value(); + } else { + no_errno = 1; + } + } + if (!no_errno) { + e2c = mrb_const_get(mrb, mrb_obj_value(mrb_class_get(mrb, "Errno")), mrb_intern(mrb, "Errno2class")); + c = mrb_hash_fetch(mrb, e2c, mrb_fixnum_value(n), mrb_nil_value()); + if (!mrb_nil_p(c)) { + mrb_basic(self)->c = mrb_class_ptr(c); + str = mrb_str_new2(mrb, strerror(n)); + } else { + mrb_iv_set(mrb, self, mrb_intern(mrb, "errno"), mrb_fixnum_value(n)); + str = mrb_str_new2(mrb, "Unknown error: "); + snprintf(buf, sizeof(buf), "%d", n); + mrb_str_cat2(mrb, str, buf); + } + } else { + str = mrb_str_new2(mrb, "unknown error"); + } + if (!mrb_nil_p(m)) { + mrb_str_cat2(mrb, str, " - "); + mrb_str_append(mrb, str, m); + } + mrb_iv_set(mrb, self, mrb_intern(mrb, "mesg"), str); + return self; +} + +static mrb_value +mrb_sce_errno(mrb_state *mrb, mrb_value self) +{ + mrb_sym sym; + mrb_value klass; + + klass = mrb_obj_value(mrb_class(mrb, self)); + sym = mrb_intern(mrb, "Errno"); + if (mrb_const_defined(mrb, klass, sym)) + return mrb_const_get(mrb, klass, sym); + else { + sym = mrb_intern(mrb, "errno"); + return mrb_attr_get(mrb, self, sym); + } +} + +static mrb_value +mrb_sce_to_s(mrb_state *mrb, mrb_value self) +{ + return mrb_attr_get(mrb, self, mrb_intern(mrb, "mesg")); +} + +static mrb_value +mrb_sce_sys_fail(mrb_state *mrb, mrb_value cls) +{ + struct RClass *cl, *sce; + mrb_value e, msg; + mrb_int no; + int argc; + char name[8]; + + sce = mrb_class_obj_get(mrb, "SystemCallError"); + argc = mrb_get_args(mrb, "i|S", &no, &msg); + if (argc == 1) { + e = mrb_funcall(mrb, mrb_obj_value(sce), "new", 1, mrb_fixnum_value(no)); + } else { + e = mrb_funcall(mrb, mrb_obj_value(sce), "new", 2, msg, mrb_fixnum_value(no)); + } + if (mrb_obj_class(mrb, e) == sce) { + snprintf(name, sizeof(name), "E%03ld", (long)no); + cl = mrb_define_class_under(mrb, mrb_class_get(mrb, "Errno"), name, sce); + mrb_define_const(mrb, cl, "Errno", mrb_fixnum_value(no)); + mrb_basic(e)->c = cl; + } + mrb_exc_raise(mrb, e); + return mrb_nil_value(); /* NOTREACHED */ +} + +static mrb_value +mrb_exxx_init(mrb_state *mrb, mrb_value self) +{ + mrb_value m, no, str; + + no = mrb_const_get(mrb, mrb_obj_value(mrb_class(mrb, self)), mrb_intern(mrb, "Errno")); + str = mrb_str_new2(mrb, strerror(mrb_fixnum(no))); + + m = mrb_nil_value(); + mrb_get_args(mrb, "|S", &m); + if (!mrb_nil_p(m)) { + mrb_str_cat2(mrb, str, " - "); + mrb_str_append(mrb, str, m); + } + mrb_iv_set(mrb, self, mrb_intern(mrb, "mesg"), str); + return self; +} + +void +mrb_mruby_errno_gem_init(mrb_state *mrb) +{ + struct RClass *e, *eno, *sce, *ste; + mrb_value h, noerror; + + ste = mrb_class_obj_get(mrb, "StandardError"); + + sce = mrb_define_class(mrb, "SystemCallError", ste); + mrb_define_class_method(mrb, sce, "_sys_fail", mrb_sce_sys_fail, ARGS_REQ(1)); + mrb_define_method(mrb, sce, "errno", mrb_sce_errno, ARGS_NONE()); + mrb_define_method(mrb, sce, "to_s", mrb_sce_to_s, ARGS_NONE()); + mrb_define_method(mrb, sce, "initialize", mrb_sce_init, ARGS_REQ(1)|ARGS_OPT(1)); + + eno = mrb_define_module(mrb, "Errno"); + h = mrb_hash_new(mrb); + mrb_define_const(mrb, eno, "Errno2class", h); + + e = mrb_define_class_under(mrb, eno, "NOERROR", sce); + mrb_define_const(mrb, e, "Errno", mrb_fixnum_value(0)); + mrb_define_method(mrb, e, "initialize", mrb_exxx_init, ARGS_OPT(1)); + //mrb_define_method(mrb, e, "===", mrb_exxx_cmp, ARGS_REQ(1)); + noerror = mrb_obj_value(e); + +#define itsdefined(SYM) \ + do { \ + int ai = mrb_gc_arena_save(mrb); \ + e = mrb_define_class_under(mrb, eno, #SYM, sce); \ + mrb_define_const(mrb, e, "Errno", mrb_fixnum_value(SYM)); \ + mrb_define_method(mrb, e, "initialize", mrb_exxx_init, ARGS_OPT(1)); \ + mrb_hash_set(mrb, h, mrb_fixnum_value(SYM), mrb_obj_value(e)); \ + mrb_gc_arena_restore(mrb, ai); \ + } while (0) + +#define itsnotdefined(SYM) \ + do { \ + mrb_define_const(mrb, eno, #SYM, noerror); \ + } while (0) + +#include "known_errors_def.cstub" +} + +void +mrb_mruby_errno_gem_final(mrb_state *mrb) +{ +} diff --git a/src/gen.rb b/src/gen.rb new file mode 100755 index 000000000..12e6b302e --- /dev/null +++ b/src/gen.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby + +Dir.chdir(File.dirname($0)) + +e = File.open("known_errors_e2c.cstub", "w") +d = File.open("known_errors_def.cstub", "w") + +IO.readlines("known_errors.def").each { |name| + next if name =~ /^#/ + name.strip! + + e.write <