From cd9124f9b7d2ac86f024eecc1e142ca2338a14e1 Mon Sep 17 00:00:00 2001 From: akr Date: Thu, 16 Apr 2009 14:17:14 +0000 Subject: * class.c (rb_define_method_id): use rb_define_notimplement_method_id if rb_f_notimplement is given. (rb_define_protected_method): ditto. (rb_define_private_method): ditto. (rb_define_method): use rb_define_method_id. * include/ruby/intern.h (rb_f_notimplement): declared. (rb_define_notimplement_method_id): declared. * proc.c (method_inspect): show not-implemented. * vm_method.c (notimplement_body): new variable. (rb_notimplement_body_p): new function. (rb_method_boundp): return false if not implemented. (rb_f_notimplement): new function. (rb_define_notimplement_method_id): new function. * process.c (rb_f_fork): use rb_f_notimplement if not implemented. * file.c (rb_file_s_lchmod): use rb_f_notimplement if not implemented. git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@23192 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 23 +++++++++++++++++ NEWS | 5 ++++ class.c | 19 +++++++++++--- file.c | 7 +----- include/ruby/intern.h | 2 ++ proc.c | 3 +++ process.c | 7 +++--- test/ruby/test_notimp.rb | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ vm_method.c | 25 +++++++++++++++++++ 9 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 test/ruby/test_notimp.rb diff --git a/ChangeLog b/ChangeLog index 09c310310..acb469bb5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +Thu Apr 16 23:09:03 2009 Tanaka Akira + + * class.c (rb_define_method_id): use rb_define_notimplement_method_id + if rb_f_notimplement is given. + (rb_define_protected_method): ditto. + (rb_define_private_method): ditto. + (rb_define_method): use rb_define_method_id. + + * include/ruby/intern.h (rb_f_notimplement): declared. + (rb_define_notimplement_method_id): declared. + + * proc.c (method_inspect): show not-implemented. + + * vm_method.c (notimplement_body): new variable. + (rb_notimplement_body_p): new function. + (rb_method_boundp): return false if not implemented. + (rb_f_notimplement): new function. + (rb_define_notimplement_method_id): new function. + + * process.c (rb_f_fork): use rb_f_notimplement if not implemented. + + * file.c (rb_file_s_lchmod): use rb_f_notimplement if not implemented. + Wed Apr 15 20:24:49 2009 Yusuke Endoh * array.c (rb_ary_flatten): flatten(0) works as Array#dup. diff --git a/NEWS b/NEWS index 06eb4e7c3..383317792 100644 --- a/NEWS +++ b/NEWS @@ -47,6 +47,11 @@ with all sufficient information, see the ChangeLog file. * extended methods: * string[regexp, name] is supported for named capture. + * Kernel + * extended methods: + * respond_to? returns false for not-implemented methods + such as fork on Windows. + * rss * 0.2.4 -> 0.2.5 diff --git a/class.c b/class.c index 18d5f0d70..2a5dc6179 100644 --- a/class.c +++ b/class.c @@ -807,25 +807,36 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) void rb_define_method_id(VALUE klass, ID name, VALUE (*func)(ANYARGS), int argc) { - rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC); + if (func == rb_f_notimplement) + rb_define_notimplement_method_id(klass, name, NOEX_PUBLIC); + else + rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC); } void rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) { - rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC); + rb_define_method_id(klass, rb_intern(name), func, argc); } void rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) { - rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PROTECTED); + ID id = rb_intern(name); + if (func == rb_f_notimplement) + rb_define_notimplement_method_id(klass, id, NOEX_PROTECTED); + else + rb_add_method(klass, id, NEW_CFUNC(func, argc), NOEX_PROTECTED); } void rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) { - rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE); + ID id = rb_intern(name); + if (func == rb_f_notimplement) + rb_define_notimplement_method_id(klass, id, NOEX_PRIVATE); + else + rb_add_method(klass, id, NEW_CFUNC(func, argc), NOEX_PRIVATE); } void diff --git a/file.c b/file.c index a1b38f109..5a9d04f92 100644 --- a/file.c +++ b/file.c @@ -1926,12 +1926,7 @@ rb_file_s_lchmod(int argc, VALUE *argv) return LONG2FIX(n); } #else -static VALUE -rb_file_s_lchmod(int argc, VALUE *argv) -{ - rb_notimplement(); - return Qnil; /* not reached */ -} +#define rb_file_s_lchmod rb_f_notimplement #endif struct chown_args { diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 285981b4a..899a7b3ca 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -275,6 +275,8 @@ int rb_method_basic_definition_p(VALUE, ID); VALUE rb_eval_cmd(VALUE, VALUE, int); int rb_obj_respond_to(VALUE, ID, int); int rb_respond_to(VALUE, ID); +void rb_define_notimplement_method_id(VALUE mod, ID id, int noex); +VALUE rb_f_notimplement(int argc, VALUE *argv, VALUE obj); void rb_interrupt(void); VALUE rb_apply(VALUE, ID, VALUE); void rb_backtrace(void); diff --git a/proc.c b/proc.c index 9f2a46416..5ee01f76b 100644 --- a/proc.c +++ b/proc.c @@ -1616,6 +1616,9 @@ method_inspect(VALUE method) } rb_str_buf_cat2(str, sharp); rb_str_append(str, rb_id2str(data->oid)); + if (rb_notimplement_body_p(data->body)) { + rb_str_buf_cat2(str, " (not-implemented)"); + } rb_str_buf_cat2(str, ">"); return str; diff --git a/process.c b/process.c index f86ee199a..db9158e68 100644 --- a/process.c +++ b/process.c @@ -2601,10 +2601,10 @@ rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds) * fork doesn't copy other threads. */ +#if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD) static VALUE rb_f_fork(VALUE obj) { -#if defined(HAVE_FORK) && !defined(CANNOT_FORK_WITH_PTHREAD) rb_pid_t pid; rb_secure(2); @@ -2630,11 +2630,10 @@ rb_f_fork(VALUE obj) default: return PIDT2NUM(pid); } +} #else - rb_notimplement(); +#define rb_f_fork rb_f_notimplement #endif -} - /* * call-seq: diff --git a/test/ruby/test_notimp.rb b/test/ruby/test_notimp.rb new file mode 100644 index 000000000..dfe51683c --- /dev/null +++ b/test/ruby/test_notimp.rb @@ -0,0 +1,64 @@ +require 'test/unit' +require 'tmpdir' + +class TestNotImplement < Test::Unit::TestCase + def test_respond_to_fork + assert_includes(Process.methods, :fork) + if /linux/ =~ RUBY_PLATFORM + assert_equal(true, Process.respond_to?(:fork)) + end + end + + def test_respond_to_lchmod + assert_includes(File.methods, :lchmod) + if /linux/ =~ RUBY_PLATFORM + assert_equal(false, File.respond_to?(:lchmod)) + end + if /freebsd/ =~ RUBY_PLATFORM + assert_equal(true, File.respond_to?(:lchmod)) + end + end + + def test_call_fork + if Process.respond_to?(:fork) + assert_nothing_raised { + pid = fork {} + Process.wait pid + } + end + end + + def test_call_lchmod + if File.respond_to?(:lchmod) + Dir.mktmpdir {|d| + f = "#{d}/f" + g = "#{d}/g" + File.open(f, "w") {} + File.symlink f, g + newmode = 0444 + File.lchmod newmode, "#{d}/g" + snew = File.lstat(g) + assert_equal(newmode, snew.mode & 0777) + } + end + end + + def test_method_inspect_fork + m = Process.method(:fork) + if Process.respond_to?(:fork) + assert_not_match(/not-implemented/, m.inspect) + else + assert_match(/not-implemented/, m.inspect) + end + end + + def test_method_inspect_lchmod + m = File.method(:lchmod) + if File.respond_to?(:lchmod) + assert_not_match(/not-implemented/, m.inspect) + else + assert_match(/not-implemented/, m.inspect) + end + end + +end diff --git a/vm_method.c b/vm_method.c index 774fa1eda..307471d3d 100644 --- a/vm_method.c +++ b/vm_method.c @@ -24,6 +24,8 @@ static struct cache_entry cache[CACHE_SIZE]; #define ruby_running (GET_VM()->running) /* int ruby_running = 0; */ +static NODE *notimplement_body = 0; + void rb_clear_cache(void) { @@ -413,6 +415,12 @@ rb_export_method(VALUE klass, ID name, ID noex) } } +int +rb_notimplement_body_p(NODE *method) +{ + return method == notimplement_body ? Qtrue : Qfalse; +} + int rb_method_boundp(VALUE klass, ID id, int ex) { @@ -422,6 +430,8 @@ rb_method_boundp(VALUE klass, ID id, int ex) if (ex && (method->nd_noex & NOEX_PRIVATE)) { return Qfalse; } + if (rb_notimplement_body_p(method->nd_body)) + return Qfalse; return Qtrue; } return Qfalse; @@ -811,6 +821,18 @@ rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname) return mod; } +VALUE +rb_f_notimplement(int argc, VALUE *argv, VALUE obj) +{ + rb_notimplement(); +} + +void +rb_define_notimplement_method_id(VALUE mod, ID id, int noex) +{ + rb_add_method(mod, id, notimplement_body, noex); +} + static void secure_visibility(VALUE self) { @@ -1137,5 +1159,8 @@ Init_eval_method(void) singleton_removed = rb_intern("singleton_method_removed"); undefined = rb_intern("method_undefined"); singleton_undefined = rb_intern("singleton_method_undefined"); + + rb_global_variable(¬implement_body); + notimplement_body = NEW_CFUNC(rb_f_notimplement, -1); } -- cgit