From d576a25c26ea6765254e7ec247f951d6bb944703 Mon Sep 17 00:00:00 2001 From: tenderlove Date: Tue, 6 Mar 2012 23:38:33 +0000 Subject: * error.c (rb_loaderror_with_path): Adding the missing file as an instance variable to the LoadError exception. * load.c: call rb_loaderror_with_path so that the missing path is added to the exception. * ruby.c: call rb_loaderror rather than raising our own LoadError exception. * include/ruby/intern.h: add declaration for rb_loaderror_with_path. * test/ruby/test_require.rb: add supporting test for LoadError#path method. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34938 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 16 ++++++++++++++++ NEWS | 5 +++++ error.c | 25 +++++++++++++++++++++++-- include/ruby/intern.h | 1 + load.c | 9 +++++---- ruby.c | 2 +- test/ruby/test_require.rb | 8 ++++++++ 7 files changed, 59 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 742a5c4c62..b7c8a2c70a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +Wed Mar 7 08:32:43 2012 Aaron Patterson + + * error.c (rb_loaderror_with_path): Adding the missing file as an + instance variable to the LoadError exception. + + * load.c: call rb_loaderror_with_path so that the missing path is + added to the exception. + + * ruby.c: call rb_loaderror rather than raising our own LoadError + exception. + + * include/ruby/intern.h: add declaration for rb_loaderror_with_path. + + * test/ruby/test_require.rb: add supporting test for LoadError#path + method. + Wed Mar 7 08:28:00 2012 Aaron Patterson * lib/xmlrpc/parser.rb: support i8 types. Thanks Stas Kelvich! diff --git a/NEWS b/NEWS index 8698195afc..be17902b0d 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,11 @@ with all sufficient information, see the ChangeLog file. * respond_to? against a protected method now returns false unless the second argument is true. + * LoadError + * added method: + * added LoadError#path method to return the file name that could not be + loaded. + * Signal * incompatible changes: * Signal.trap raises ArgumentError when :SEGV, :BUS, :ILL, :FPE, :VTALRM diff --git a/error.c b/error.c index bea4d50909..e0c6a44b2f 100644 --- a/error.c +++ b/error.c @@ -1691,7 +1691,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); @@ -1742,11 +1745,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 @@ -1889,7 +1910,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 6f632973f2..42f9e48c55 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 cddd7255ac..67020a1ecd 100644 --- a/load.c +++ b/load.c @@ -495,7 +495,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()); @@ -588,12 +588,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 1ad68caeb1..16e66c8f9c 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 379efec58a..e0e885dce6 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" -- cgit v1.2.3