summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-04-16 14:17:14 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-04-16 14:17:14 +0000
commitcd9124f9b7d2ac86f024eecc1e142ca2338a14e1 (patch)
tree46d2b5cfc923aa18bc9f70405a0e6460252a4196
parent4ca367fed442858b6a22f2009318a0fab35f4646 (diff)
downloadruby-cd9124f9b7d2ac86f024eecc1e142ca2338a14e1.tar.gz
ruby-cd9124f9b7d2ac86f024eecc1e142ca2338a14e1.tar.xz
ruby-cd9124f9b7d2ac86f024eecc1e142ca2338a14e1.zip
* 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
-rw-r--r--ChangeLog23
-rw-r--r--NEWS5
-rw-r--r--class.c19
-rw-r--r--file.c7
-rw-r--r--include/ruby/intern.h2
-rw-r--r--proc.c3
-rw-r--r--process.c7
-rw-r--r--test/ruby/test_notimp.rb64
-rw-r--r--vm_method.c25
9 files changed, 141 insertions, 14 deletions
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 <akr@fsij.org>
+
+ * 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 <mame@tsg.ne.jp>
* 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)
{
@@ -414,6 +416,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)
{
NODE *method;
@@ -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(&notimplement_body);
+ notimplement_body = NEW_CFUNC(rb_f_notimplement, -1);
}