Watson1978
2/3/2012 - 1:35 AM

require_relative.patch

diff --git a/load.c b/load.c
index b070a120ac25cc07bcca478f8b584f885c593566..d53e06ef5e243ac5577756285997e051314248c8 100644
--- a/load.c
+++ b/load.c
@@ -298,6 +298,23 @@ rb_f_require_imp(VALUE obj, SEL sel, VALUE fname)
     return rb_f_require(obj, fname);
 }
 
+VALUE
+rb_f_require_relative(VALUE obj, VALUE fname)
+{
+    VALUE rb_current_realfilepath(void);
+    VALUE base = rb_current_realfilepath();
+    if (NIL_P(base)) {
+	rb_raise(rb_eLoadError, "cannot infer basepath");
+    }
+    base = rb_file_dirname(base);
+    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
+}
+
+VALUE
+rb_f_require_relative_imp(VALUE obj, SEL sel, VALUE fname)
+{
+    return rb_f_require_relative(obj, fname);
+}
 #if !defined(MACRUBY_STATIC)
 
 static bool
@@ -570,6 +587,7 @@ Init_load()
 
     rb_objc_define_module_function(rb_mKernel, "load", rb_f_load, -1);
     rb_objc_define_module_function(rb_mKernel, "require", rb_f_require_imp, 1);
+    rb_objc_define_module_function(rb_mKernel, "require_relative", rb_f_require_relative_imp, 1);
     rb_objc_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
     rb_objc_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
     rb_objc_define_module_function(rb_mKernel, "autoload", rb_f_autoload, 2);
diff --git a/vm.cpp b/vm.cpp
index af12f8696ce3454c82744f4ca1943016b47fef8b..140ef94dbe45115565deac7573ef568149b8a77b 100644
--- a/vm.cpp
+++ b/vm.cpp
@@ -3883,6 +3883,28 @@ rb_vm_backtrace(int skip)
     return ary;
 }
 
+extern VALUE rb_progname;
+
+extern "C"
+VALUE
+rb_current_realfilepath(void)
+{
+    void *callstack[10];
+    int callstack_n = backtrace(callstack, 10);
+    char path[PATH_MAX];
+    unsigned int interpreter_frame_idx = 0;
+
+    for (int i = 0; i < callstack_n; i++) {
+	path[0] = '\0';
+	GET_CORE()->symbolize_call_address(callstack[i], path, sizeof path,
+					   NULL, NULL, 0, &interpreter_frame_idx);
+	if (path[0] != '\0' && path[0] != '-') { // ignore '-e'
+	    return rb_str_new_cstr(path);
+	}
+    }
+    return rb_progname;
+}
+
 extern "C"
 unsigned char
 rb_vm_is_eh_active(int argc, ...)