Skip to content

Instantly share code, notes, and snippets.

@tenderlove
Created February 17, 2012 19:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tenderlove/1855072 to your computer and use it in GitHub Desktop.
Save tenderlove/1855072 to your computer and use it in GitHub Desktop.
diff --git a/error.c b/error.c
index f83cf3d..e119831 100644
--- a/error.c
+++ b/error.c
@@ -1454,6 +1454,12 @@ syserr_eqq(VALUE self, VALUE exc)
* LoadError: no such file to load -- this/file/does/not/exist
*/
+VALUE
+load_error_new(VALUE file)
+{
+
+}
+
/*
* Document-class: NotImplementedError
*
@@ -1690,7 +1696,10 @@ Init_Exception(void)
rb_eScriptError = rb_define_class("ScriptError", rb_eException);
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
+
rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
+ rb_attr(rb_eLoadError, rb_intern("path"), 1, 0, Qfalse);
+
rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
rb_eNameError = rb_define_class("NameError", rb_eStandardError);
@@ -1741,11 +1750,29 @@ rb_loaderror(const char *fmt, ...)
{
va_list args;
VALUE mesg;
+ VALUE err;
+
+ va_start(args, fmt);
+ mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
+ va_end(args);
+ err = rb_exc_new3(rb_eLoadError, mesg);
+ rb_ivar_set(err, rb_intern("@path"), Qnil);
+ rb_exc_raise(err);
+}
+
+void
+rb_loaderror_with_path(VALUE path, const char *fmt, ...)
+{
+ va_list args;
+ VALUE mesg;
+ VALUE err;
va_start(args, fmt);
mesg = rb_enc_vsprintf(rb_locale_encoding(), fmt, args);
va_end(args);
- rb_exc_raise(rb_exc_new3(rb_eLoadError, mesg));
+ err = rb_exc_new3(rb_eLoadError, mesg);
+ rb_ivar_set(err, rb_intern("@path"), path);
+ rb_exc_raise(err);
}
void
@@ -1840,7 +1867,7 @@ rb_sys_warning(const char *fmt, ...)
void
rb_load_fail(const char *path)
{
- rb_loaderror("%s -- %s", strerror(errno), path);
+ rb_loaderror_with_path(rb_str_new2(path), "%s -- %s", strerror(errno), path);
}
void
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index e0c4710..13ccf5b 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -209,6 +209,7 @@ VALUE rb_exc_new(VALUE, const char*, long);
VALUE rb_exc_new2(VALUE, const char*);
VALUE rb_exc_new3(VALUE, VALUE);
PRINTF_ARGS(NORETURN(void rb_loaderror(const char*, ...)), 1, 2);
+PRINTF_ARGS(NORETURN(void rb_loaderror_with_path(VALUE path, const char*, ...)), 2, 3);
PRINTF_ARGS(NORETURN(void rb_name_error(ID, const char*, ...)), 2, 3);
PRINTF_ARGS(NORETURN(void rb_name_error_str(VALUE, const char*, ...)), 2, 3);
NORETURN(void rb_invalid_str(const char*, const char*));
diff --git a/load.c b/load.c
index d36285f..94023d0 100644
--- a/load.c
+++ b/load.c
@@ -490,7 +490,7 @@ rb_f_require_relative(VALUE obj, VALUE fname)
{
VALUE base = rb_current_realfilepath();
if (NIL_P(base)) {
- rb_raise(rb_eLoadError, "cannot infer basepath");
+ rb_loaderror("cannot infer basepath");
}
base = rb_file_dirname(base);
return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
@@ -583,12 +583,13 @@ search_required(VALUE fname, volatile VALUE *path, int safe_level)
return type ? 's' : 'r';
}
+void rb_loaderror_with_path(VALUE path, const char *fmt, ...);
+
static void
load_failed(VALUE fname)
{
- VALUE mesg = rb_str_buf_new_cstr("cannot load such file -- ");
- rb_str_append(mesg, fname); /* should be ASCII compatible */
- rb_exc_raise(rb_exc_new3(rb_eLoadError, mesg));
+ rb_loaderror_with_path(fname, "cannot load such file -- %s", RSTRING_PTR(fname));
+ RB_GC_GUARD(fname);
}
static VALUE
diff --git a/ruby.c b/ruby.c
index 1ad68ca..16e66c8 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1560,7 +1560,7 @@ load_file_internal(VALUE arg)
}
}
}
- rb_raise(rb_eLoadError, "no Ruby script found in input");
+ rb_loaderror("no Ruby script found in input");
}
c = rb_io_getbyte(f);
diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb
index 379efec..e0e885d 100644
--- a/test/ruby/test_require.rb
+++ b/test/ruby/test_require.rb
@@ -5,6 +5,14 @@ require_relative 'envutil'
require 'tmpdir'
class TestRequire < Test::Unit::TestCase
+ def test_load_error_path
+ filename = "should_not_exist"
+ error = assert_raises(LoadError) do
+ require filename
+ end
+ assert_equal filename, error.path
+ end
+
def test_require_invalid_shared_object
t = Tempfile.new(["test_ruby_test_require", ".so"])
t.puts "dummy"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment