Created
March 27, 2012 08:01
-
-
Save aarvay/2213865 to your computer and use it in GitHub Desktop.
Require Hack Patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- load-head.c 2012-03-27 11:29:29.000000000 +0530 | |
+++ load.c 2012-03-27 11:26:22.000000000 +0530 | |
@@ -4,21 +4,19 @@ | |
#include "ruby/ruby.h" | |
#include "ruby/util.h" | |
-#include "internal.h" | |
#include "dln.h" | |
#include "eval_intern.h" | |
- | |
+#include "assert.h" | |
VALUE ruby_dln_librefs; | |
-#define IS_RBEXT(e) (strcmp((e), ".rb") == 0) | |
-#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0) | |
+#define IS_RBEXT(e) (strcmp(e, ".rb") == 0) | |
+#define IS_SOEXT(e) (strcmp(e, ".so") == 0 || strcmp(e, ".o") == 0) | |
#ifdef DLEXT2 | |
-#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0 || strcmp((e), DLEXT2) == 0) | |
+#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0 || strcmp(e, DLEXT2) == 0) | |
#else | |
-#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0) | |
+#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0) | |
#endif | |
- | |
static const char *const loadable_ext[] = { | |
".rb", DLEXT, | |
#ifdef DLEXT2 | |
@@ -27,6 +25,26 @@ | |
0 | |
}; | |
+static void | |
+print_str_ary(VALUE ary) | |
+{ | |
+ long n = RARRAY_LEN(ary); | |
+ long i; | |
+ printf("\n{\n"); | |
+ | |
+ for(i =0; i < n; i++) | |
+ { | |
+ printf("%s,\n", RSTRING_PTR( RARRAY_PTR(ary)[i])); | |
+ } | |
+ printf("}\n"); | |
+} | |
+ | |
+static void | |
+print_str(VALUE ary) | |
+{ | |
+ printf("%s\n" , RSTRING_PTR( ary)); | |
+} | |
+ | |
VALUE | |
rb_get_load_path(void) | |
{ | |
@@ -64,47 +82,41 @@ | |
} | |
static st_table * | |
+get_dollar_quote(void) | |
+{ | |
+ return GET_VM()-> dollar_quote; | |
+} | |
+static st_table * | |
get_loading_table(void) | |
{ | |
return GET_VM()->loading_table; | |
} | |
static VALUE | |
-loaded_feature_path(const char *name, long vlen, const char *feature, long len, | |
- int type, VALUE load_path) | |
+loaded_feature_path(const char *name, long vlen, const char *feature, long len, int type, VALUE load_path) | |
{ | |
long i; | |
- long plen; | |
- const char *e; | |
- | |
- if(vlen < len) return 0; | |
- if (!strncmp(name+(vlen-len),feature,len)){ | |
- plen = vlen - len - 1; | |
- } else { | |
- for (e = name + vlen; name != e && *e != '.' && *e != '/'; --e); | |
- if (*e!='.' || | |
- e-name < len || | |
- strncmp(e-len,feature,len) ) | |
- return 0; | |
- plen = e - name - len - 1; | |
- } | |
+ | |
for (i = 0; i < RARRAY_LEN(load_path); ++i) { | |
- VALUE p = RARRAY_PTR(load_path)[i]; | |
- const char *s = StringValuePtr(p); | |
- long n = RSTRING_LEN(p); | |
- | |
- if (n != plen ) continue; | |
- if (n && (strncmp(name, s, n) || name[n] != '/')) continue; | |
- switch (type) { | |
- case 's': | |
- if (IS_DLEXT(&name[n+len+1])) return p; | |
- break; | |
- case 'r': | |
- if (IS_RBEXT(&name[n+len+1])) return p; | |
- break; | |
- default: | |
- return p; | |
- } | |
+ VALUE p = RARRAY_PTR(load_path)[i]; | |
+ const char *s = StringValuePtr(p); | |
+ long n = RSTRING_LEN(p); | |
+ if (vlen < n + len + 1) continue; | |
+ if (n && (strncmp(name, s, n) || name[n] != '/')) continue; | |
+ if (strncmp(name + n + 1, feature, len)) continue; | |
+ if (name[n+len+1] && name[n+len+1] != '.') continue; | |
+ switch (type) { | |
+ case 's': | |
+ if (IS_DLEXT(&name[n+len+1])) return p; | |
+ break; | |
+ case 'r': | |
+ if (IS_RBEXT(&name[n+len+1])){ | |
+ return p; | |
+ } | |
+ break; | |
+ default: | |
+ return p; | |
+ } | |
} | |
return 0; | |
} | |
@@ -134,87 +146,144 @@ | |
{ | |
VALUE v, features, p, load_path = 0; | |
const char *f, *e; | |
- long i, len, elen, n; | |
+ long i, j, len, elen, n; | |
st_table *loading_tbl; | |
st_data_t data; | |
int type; | |
+ int already_found = 0; | |
if (fn) *fn = 0; | |
if (ext) { | |
- elen = strlen(ext); | |
- len = strlen(feature) - elen; | |
- type = rb ? 'r' : 's'; | |
+ elen= strlen(ext); | |
+ len = strlen(feature) - elen; | |
+ type = rb ? 'r' : 's'; | |
} | |
else { | |
- len = strlen(feature); | |
- elen = 0; | |
- type = 0; | |
+ len = strlen(feature); | |
+ elen = 0; | |
+ type = 0; | |
} | |
+ | |
features = get_loaded_features(); | |
- for (i = 0; i < RARRAY_LEN(features); ++i) { | |
- v = RARRAY_PTR(features)[i]; | |
- f = StringValuePtr(v); | |
- if ((n = RSTRING_LEN(v)) < len) continue; | |
- if (strncmp(f, feature, len) != 0) { | |
- if (expanded) continue; | |
- if (!load_path) load_path = rb_get_expanded_load_path(); | |
- if (!(p = loaded_feature_path(f, n, feature, len, type, load_path))) | |
- continue; | |
- expanded = 1; | |
- f += RSTRING_LEN(p) + 1; | |
- } | |
- if (!*(e = f + len)) { | |
- if (ext) continue; | |
- return 'u'; | |
- } | |
- if (*e != '.') continue; | |
- if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) { | |
- return 's'; | |
- } | |
- if ((rb || !ext) && (IS_RBEXT(e))) { | |
- return 'r'; | |
- } | |
+ char *which = feature ; | |
+ int found = 0 ; | |
+ found = st_lookup( get_dollar_quote() , feature , &found ) ; | |
+ if ( !ext && !found ){ | |
+ for ( i = 0 ; loadable_ext[i] ; i ++ ) { | |
+ | |
+ char *t = (char *) malloc( strlen(feature) + strlen(loadable_ext[i]) + 1 ); | |
+ strcpy(t,feature); | |
+ strcat(t,loadable_ext[i]); | |
+ int temp; | |
+ temp = st_lookup( get_dollar_quote() , t , &temp ); | |
+ if ( temp ) { | |
+ found = 1 ; | |
+ expanded = 1 ; | |
+ which = t ; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if ( !expanded && !found ) { | |
+ load_path = rb_get_expanded_load_path(); | |
+ for (i = 0; i < RARRAY_LEN(load_path) && !found; ++i) { | |
+ VALUE path = RARRAY_PTR(load_path)[i]; | |
+ char *s = StringValuePtr(path); | |
+ strcat(s,"/"); | |
+ strcat(s,feature); | |
+ if (ext) { | |
+ int temp = 0 ; | |
+ temp = st_lookup( get_dollar_quote() , s , &temp ); | |
+ if (temp) { | |
+ found = 1 ; | |
+ which = s ; | |
+ expanded = 1 ; | |
+ break; | |
+ } | |
+ } | |
+ else { | |
+ for ( j = 0 ; loadable_ext[j] ; j++ ) { | |
+ | |
+ char *t = (char *) malloc( strlen(s) + strlen(loadable_ext[j]) + 1 ); | |
+ strcpy(t,s); | |
+ strcat(t,loadable_ext[j] ); | |
+ int temp; | |
+ temp = st_lookup( get_dollar_quote() , t , &temp ); | |
+ if (temp) { | |
+ found = 1 ; | |
+ expanded = 1 ; | |
+ which = t ; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ char ret = 0 ; | |
+ if ( found ){ | |
+ e = strrchr( which , '.'); | |
+ if ( !*e ){ | |
+ if ( !ext ){ | |
+ ret = 'u'; | |
+ return 'u'; | |
+ } | |
+ } | |
+ if ( *e == '.' ){ | |
+ if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) { | |
+ ret = 's'; | |
+ return 's'; | |
+ } | |
+ if ((rb || !ext) && (IS_RBEXT(e))) { | |
+ ret ='r'; | |
+ return 'r'; | |
+ } | |
+ } | |
} | |
+ | |
loading_tbl = get_loading_table(); | |
if (loading_tbl) { | |
- f = 0; | |
- if (!expanded) { | |
- struct loaded_feature_searching fs; | |
- fs.name = feature; | |
- fs.len = len; | |
- fs.type = type; | |
- fs.load_path = load_path ? load_path : rb_get_expanded_load_path(); | |
- fs.result = 0; | |
- st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); | |
- if ((f = fs.result) != 0) { | |
- if (fn) *fn = f; | |
- goto loading; | |
- } | |
- } | |
- if (st_get_key(loading_tbl, (st_data_t)feature, &data)) { | |
- if (fn) *fn = (const char*)data; | |
- loading: | |
- if (!ext) return 'u'; | |
- return !IS_RBEXT(ext) ? 's' : 'r'; | |
- } | |
- else { | |
- VALUE bufstr; | |
- char *buf; | |
- | |
- if (ext && *ext) return 0; | |
- bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN); | |
- buf = RSTRING_PTR(bufstr); | |
- MEMCPY(buf, feature, char, len); | |
- for (i = 0; (e = loadable_ext[i]) != 0; i++) { | |
- strlcpy(buf + len, e, DLEXT_MAXLEN + 1); | |
- if (st_get_key(loading_tbl, (st_data_t)buf, &data)) { | |
- rb_str_resize(bufstr, 0); | |
- if (fn) *fn = (const char*)data; | |
- return i ? 's' : 'r'; | |
- } | |
- } | |
- rb_str_resize(bufstr, 0); | |
- } | |
+ f = 0; | |
+ if (!expanded) { | |
+ struct loaded_feature_searching fs; | |
+ fs.name = feature; | |
+ fs.len = len; | |
+ fs.type = type; | |
+ fs.load_path = load_path ? load_path : rb_get_load_path(); | |
+ fs.result = 0; | |
+ st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs); | |
+ if ((f = fs.result) != 0) { | |
+ if (fn) *fn = f; | |
+ if (!ext) return 'u'; | |
+ return !IS_RBEXT(ext) ? 's' : 'r'; | |
+ } | |
+ } | |
+ if (st_get_key(loading_tbl, (st_data_t)feature, &data)) { | |
+ if (fn) *fn = (const char*)data; | |
+ if (!ext) return 'u'; | |
+ return !IS_RBEXT(ext) ? 's' : 'r'; | |
+ } | |
+ else { | |
+ VALUE bufstr; | |
+ char *buf; | |
+ | |
+ if (ext && *ext){ | |
+ return 0; | |
+ } | |
+ bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN); | |
+ buf = RSTRING_PTR(bufstr); | |
+ MEMCPY(buf, feature, char, len); | |
+ for (i = 0; (e = loadable_ext[i]) != 0; i++) { | |
+ strlcpy(buf + len, e, DLEXT_MAXLEN + 1); | |
+ if (st_get_key(loading_tbl, (st_data_t)buf, &data)) { | |
+ rb_str_resize(bufstr, 0); | |
+ if (fn) *fn = (const char*)data; | |
+ return i ? 's' : 'r'; | |
+ } | |
+ } | |
+ rb_str_resize(bufstr, 0); | |
+ } | |
} | |
return 0; | |
} | |
@@ -230,35 +299,30 @@ | |
{ | |
const char *ext = strrchr(feature, '.'); | |
volatile VALUE fullpath = 0; | |
- | |
if (*feature == '.' && | |
- (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { | |
- fullpath = rb_file_expand_path(rb_str_new2(feature), Qnil); | |
- feature = RSTRING_PTR(fullpath); | |
+ (feature[1] == '/' || strncmp(feature+1, "./", 2) == 0)) { | |
+ fullpath = rb_file_expand_path(rb_str_new2(feature), Qnil); | |
+ feature = RSTRING_PTR(fullpath); | |
} | |
if (ext && !strchr(ext, '/')) { | |
- if (IS_RBEXT(ext)) { | |
- if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE; | |
- return FALSE; | |
- } | |
- else if (IS_SOEXT(ext) || IS_DLEXT(ext)) { | |
- if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE; | |
- return FALSE; | |
- } | |
+ if (IS_RBEXT(ext)) { | |
+ if (rb_feature_p(feature, ext, TRUE, FALSE, loading)) return TRUE; | |
+ return FALSE; | |
+ } | |
+ else if (IS_SOEXT(ext) || IS_DLEXT(ext)) { | |
+ if (rb_feature_p(feature, ext, FALSE, FALSE, loading)) return TRUE; | |
+ return FALSE; | |
+ } | |
} | |
if (rb_feature_p(feature, 0, TRUE, FALSE, loading)) | |
- return TRUE; | |
+ return TRUE; | |
return FALSE; | |
} | |
static void | |
rb_provide_feature(VALUE feature) | |
{ | |
- if (OBJ_FROZEN(get_loaded_features())) { | |
- rb_raise(rb_eRuntimeError, | |
- "$LOADED_FEATURES is frozen; cannot append feature"); | |
- } | |
- rb_ary_push(get_loaded_features(), feature); | |
+ st_add_direct( get_dollar_quote() , StringValuePtr(feature) , 42 ); | |
} | |
void | |
@@ -305,7 +369,7 @@ | |
th->mild_compile_error++; | |
node = (NODE *)rb_load_file(RSTRING_PTR(fname)); | |
loaded = TRUE; | |
- iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), Qfalse); | |
+ iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, fname, Qfalse); | |
th->mild_compile_error--; | |
rb_iseq_eval(iseq); | |
} | |
@@ -405,27 +469,7 @@ | |
rb_warning("loading in progress, circular require considered harmful - %s", ftptr); | |
rb_backtrace(); | |
} | |
- switch (rb_barrier_wait((VALUE)data)) { | |
- case Qfalse: | |
- data = (st_data_t)ftptr; | |
- st_delete(loading_tbl, &data, 0); | |
- return 0; | |
- case Qnil: | |
- return 0; | |
- } | |
- return (char *)ftptr; | |
-} | |
- | |
-static int | |
-release_barrier(st_data_t key, st_data_t *value, st_data_t done) | |
-{ | |
- VALUE barrier = (VALUE)*value; | |
- if (done ? rb_barrier_destroy(barrier) : rb_barrier_release(barrier)) { | |
- /* still in-use */ | |
- return ST_CONTINUE; | |
- } | |
- xfree((char *)key); | |
- return ST_DELETE; | |
+ return RTEST(rb_barrier_wait((VALUE)data)) ? (char *)ftptr : 0; | |
} | |
static void | |
@@ -433,47 +477,41 @@ | |
{ | |
if (ftptr) { | |
st_data_t key = (st_data_t)ftptr; | |
+ st_data_t data; | |
st_table *loading_tbl = get_loading_table(); | |
- st_update(loading_tbl, key, release_barrier, done); | |
+ if (st_delete(loading_tbl, &key, &data)) { | |
+ VALUE barrier = (VALUE)data; | |
+ xfree((char *)key); | |
+ if (done) | |
+ rb_barrier_destroy(barrier); | |
+ else | |
+ rb_barrier_release(barrier); | |
+ } | |
} | |
} | |
/* | |
* call-seq: | |
- * require(name) -> true or false | |
+ * require(string) -> true or false | |
* | |
- * Loads the given +name+, returning +true+ if successful and +false+ if the | |
- * feature is already loaded. | |
- * | |
- * If the filename does not resolve to an absolute path, it will be searched | |
- * for in the directories listed in <code>$LOAD_PATH</code> (<code>$:</code>). | |
- * | |
- * If the filename has the extension ".rb", it is loaded as a source file; if | |
- * the extension is ".so", ".o", or ".dll", or the default shared library | |
- * extension on the current platform, Ruby loads the shared library as a | |
- * Ruby extension. Otherwise, Ruby tries adding ".rb", ".so", and so on | |
- * to the name until found. If the file named cannot be found, a LoadError | |
- * will be raised. | |
- * | |
- * For Ruby extensions the filename given may use any shared library | |
- * extension. For example, on Linux the socket extension is "socket.so" and | |
- * <code>require 'socket.dll'</code> will load the socket extension. | |
- * | |
- * The absolute path of the loaded file is added to | |
- * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be | |
- * loaded again if its path already appears in <code>$"</code>. For example, | |
- * <code>require 'a'; require './a'</code> will not load <code>a.rb</code> | |
- * again. | |
- * | |
- * require "my-library.rb" | |
- * require "db-driver" | |
- * | |
- * Any constants or globals within the loaded source file will be available | |
- * in the calling program's global namespace. However, local variables will | |
- * not be propagated to the loading environment. | |
+ * Ruby tries to load the library named _string_, returning | |
+ * +true+ if successful. If the filename does not resolve to | |
+ * an absolute path, it will be searched for in the directories listed | |
+ * in <code>$:</code>. If the file has the extension ``.rb'', it is | |
+ * loaded as a source file; if the extension is ``.so'', ``.o'', or | |
+ * ``.dll'', or whatever the default shared library extension is on | |
+ * the current platform, Ruby loads the shared library as a Ruby | |
+ * extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on | |
+ * to the name. The name of the loaded feature is added to the array in | |
+ * <code>$"</code>. A feature will not be loaded if its name already | |
+ * appears in <code>$"</code>. The file name is converted to an absolute | |
+ * path, so ``<code>require 'a'; require './a'</code>'' will not load | |
+ * <code>a.rb</code> twice. | |
* | |
+ * require "my-library.rb" | |
+ * require "db-driver" | |
*/ | |
VALUE | |
@@ -482,20 +520,13 @@ | |
return rb_require_safe(fname, rb_safe_level()); | |
} | |
-/* | |
- * call-seq: | |
- * require_relative(string) -> true or false | |
- * | |
- * Ruby tries to load the library named _string_ relative to the requiring | |
- * file's path. If the file's path cannot be determined a LoadError is raised. | |
- * If a file is loaded +true+ is returned and false otherwise. | |
- */ | |
VALUE | |
rb_f_require_relative(VALUE obj, VALUE fname) | |
{ | |
+ VALUE rb_current_realfilepath(void); | |
VALUE base = rb_current_realfilepath(); | |
if (NIL_P(base)) { | |
- rb_loaderror("cannot infer basepath"); | |
+ 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()); | |
@@ -512,78 +543,80 @@ | |
*path = 0; | |
ext = strrchr(ftptr = RSTRING_PTR(fname), '.'); | |
if (ext && !strchr(ext, '/')) { | |
- if (IS_RBEXT(ext)) { | |
- if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) { | |
- if (loading) *path = rb_str_new2(loading); | |
- return 'r'; | |
- } | |
- if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { | |
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
- if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading) | |
- *path = tmp; | |
- return 'r'; | |
- } | |
- return 0; | |
- } | |
- else if (IS_SOEXT(ext)) { | |
- if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { | |
- if (loading) *path = rb_str_new2(loading); | |
- return 's'; | |
- } | |
- tmp = rb_str_new(RSTRING_PTR(fname), ext - RSTRING_PTR(fname)); | |
+ if (IS_RBEXT(ext)) { | |
+ if (rb_feature_p(ftptr, ext, TRUE, FALSE, &loading)) { | |
+ if (loading) | |
+ *path = rb_str_new2(loading); | |
+ return 'r'; | |
+ } | |
+ if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { | |
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
+ if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading) | |
+ *path = tmp; | |
+ return 'r'; | |
+ } | |
+ return 0; | |
+ } | |
+ else if (IS_SOEXT(ext)) { | |
+ if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { | |
+ if (loading) *path = rb_str_new2(loading); | |
+ return 's'; | |
+ } | |
+ tmp = rb_str_new(RSTRING_PTR(fname), ext - RSTRING_PTR(fname)); | |
#ifdef DLEXT2 | |
- OBJ_FREEZE(tmp); | |
- if (rb_find_file_ext_safe(&tmp, loadable_ext + 1, safe_level)) { | |
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
- if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) | |
- *path = tmp; | |
- return 's'; | |
- } | |
+ OBJ_FREEZE(tmp); | |
+ if (rb_find_file_ext_safe(&tmp, loadable_ext + 1, safe_level)) { | |
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
+ if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) | |
+ *path = tmp; | |
+ return 's'; | |
+ } | |
#else | |
- rb_str_cat2(tmp, DLEXT); | |
- OBJ_FREEZE(tmp); | |
- if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) { | |
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
- if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) | |
- *path = tmp; | |
- return 's'; | |
- } | |
+ rb_str_cat2(tmp, DLEXT); | |
+ OBJ_FREEZE(tmp); | |
+ if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) { | |
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
+ if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) | |
+ *path = tmp; | |
+ return 's'; | |
+ } | |
#endif | |
- } | |
- else if (IS_DLEXT(ext)) { | |
- if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { | |
- if (loading) *path = rb_str_new2(loading); | |
- return 's'; | |
- } | |
- if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { | |
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
- if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) | |
- *path = tmp; | |
- return 's'; | |
- } | |
- } | |
+ } | |
+ else if (IS_DLEXT(ext)) { | |
+ if (rb_feature_p(ftptr, ext, FALSE, FALSE, &loading)) { | |
+ if (loading) *path = rb_str_new2(loading); | |
+ return 's'; | |
+ } | |
+ if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { | |
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
+ if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) | |
+ *path = tmp; | |
+ return 's'; | |
+ } | |
+ } | |
} | |
else if ((ft = rb_feature_p(ftptr, 0, FALSE, FALSE, &loading)) == 'r') { | |
- if (loading) *path = rb_str_new2(loading); | |
- return 'r'; | |
+ if (loading) *path = rb_str_new2(loading); | |
+ return 'r'; | |
} | |
+ | |
tmp = fname; | |
type = rb_find_file_ext_safe(&tmp, loadable_ext, safe_level); | |
switch (type) { | |
- case 0: | |
- if (ft) | |
- break; | |
- ftptr = RSTRING_PTR(tmp); | |
- return rb_feature_p(ftptr, 0, FALSE, TRUE, 0); | |
- | |
- default: | |
- if (ft) | |
- break; | |
- case 1: | |
- ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
- if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading) | |
- break; | |
- *path = tmp; | |
+ case 0: | |
+ if (ft) | |
+ break; | |
+ ftptr = RSTRING_PTR(tmp); | |
+ return rb_feature_p(ftptr, 0, FALSE, TRUE, 0); | |
+ | |
+ default: | |
+ if (ft) | |
+ break; | |
+ case 1: | |
+ ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); | |
+ if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading) | |
+ break; | |
+ *path = tmp; | |
} | |
return type ? 's' : 'r'; | |
} | |
@@ -591,7 +624,9 @@ | |
static void | |
load_failed(VALUE fname) | |
{ | |
- rb_load_fail(fname, "cannot load such file"); | |
+ VALUE mesg = rb_str_buf_new_cstr("no such file to load -- "); | |
+ rb_str_append(mesg, fname); /* should be ASCII compatible */ | |
+ rb_exc_raise(rb_exc_new3(rb_eLoadError, mesg)); | |
} | |
static VALUE | |
@@ -609,52 +644,52 @@ | |
volatile VALUE errinfo = th->errinfo; | |
int state; | |
struct { | |
- int safe; | |
+ int safe; | |
} volatile saved; | |
char *volatile ftptr = 0; | |
PUSH_TAG(); | |
saved.safe = rb_safe_level(); | |
if ((state = EXEC_TAG()) == 0) { | |
- VALUE path; | |
- long handle; | |
- int found; | |
- | |
- rb_set_safe_level_force(safe); | |
- FilePathValue(fname); | |
- rb_set_safe_level_force(0); | |
- found = search_required(fname, &path, safe); | |
- if (found) { | |
- if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) { | |
- result = Qfalse; | |
- } | |
- else { | |
- switch (found) { | |
- case 'r': | |
- rb_load_internal(path, 0); | |
- break; | |
- | |
- case 's': | |
- handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext, | |
- path, 0, path); | |
- rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); | |
- break; | |
- } | |
- rb_provide_feature(path); | |
- result = Qtrue; | |
- } | |
- } | |
+ VALUE path; | |
+ long handle; | |
+ int found; | |
+ | |
+ rb_set_safe_level_force(safe); | |
+ FilePathValue(fname); | |
+ rb_set_safe_level_force(0); | |
+ found = search_required(fname, &path, safe); | |
+ if (found) { | |
+ if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) { | |
+ result = Qfalse; | |
+ } | |
+ else { | |
+ switch (found) { | |
+ case 'r': | |
+ rb_load_internal(path, 0); | |
+ break; | |
+ | |
+ case 's': | |
+ handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext, | |
+ path, 0, path, path); | |
+ rb_ary_push(ruby_dln_librefs, LONG2NUM(handle)); | |
+ break; | |
+ } | |
+ rb_provide_feature(path); | |
+ result = Qtrue; | |
+ } | |
+ } | |
} | |
POP_TAG(); | |
load_unlock(ftptr, !state); | |
rb_set_safe_level_force(saved.safe); | |
if (state) { | |
- JUMP_TAG(state); | |
+ JUMP_TAG(state); | |
} | |
if (NIL_P(result)) { | |
- load_failed(fname); | |
+ load_failed(fname); | |
} | |
th->errinfo = errinfo; | |
@@ -678,15 +713,14 @@ | |
return Qnil; | |
} | |
-RUBY_FUNC_EXPORTED void | |
+void | |
ruby_init_ext(const char *name, void (*init)(void)) | |
{ | |
- char* const lock_key = load_lock(name); | |
- if (lock_key) { | |
+ if (load_lock(name)) { | |
rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call, (VALUE)init, | |
- 0, rb_str_new2(name)); | |
+ 0, rb_str_new2(name), Qnil); | |
rb_provide(name); | |
- load_unlock(lock_key, 1); | |
+ load_unlock(name, 1); | |
} | |
} | |
@@ -730,11 +764,7 @@ | |
static VALUE | |
rb_mod_autoload_p(VALUE mod, VALUE sym) | |
{ | |
- ID id = rb_check_id(&sym); | |
- if (!id) { | |
- return Qnil; | |
- } | |
- return rb_autoload_p(mod, id); | |
+ return rb_autoload_p(mod, rb_to_id(sym)); | |
} | |
/* | |
@@ -751,7 +781,7 @@ | |
static VALUE | |
rb_f_autoload(VALUE obj, VALUE sym, VALUE file) | |
{ | |
- VALUE klass = rb_class_real(rb_vm_cbase()); | |
+ VALUE klass = rb_vm_cbase(); | |
if (NIL_P(klass)) { | |
rb_raise(rb_eTypeError, "Can not set autoload on singleton class"); | |
} | |
@@ -780,12 +810,19 @@ | |
return rb_mod_autoload_p(klass, sym); | |
} | |
+VALUE | |
+append_load_path(VALUE ary, VALUE path) | |
+{ | |
+ return rb_ary_push(ary, path); | |
+} | |
+ | |
void | |
Init_load() | |
{ | |
#undef rb_intern | |
-#define rb_intern(str) rb_intern2((str), strlen(str)) | |
+#define rb_intern(str) rb_intern2(str, strlen(str)) | |
rb_vm_t *vm = GET_VM(); | |
+ | |
static const char var_load_path[] = "$:"; | |
ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1); | |
@@ -796,7 +833,11 @@ | |
rb_define_virtual_variable("$\"", get_loaded_features, 0); | |
rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0); | |
- vm->loaded_features = rb_ary_new(); | |
+ vm->loaded_features = rb_ary_new(); | |
+ rb_define_singleton_method(vm->load_path, "<<", append_load_path, 1); | |
+ rb_define_singleton_method(vm->load_path, "unshift", append_load_path, 1); | |
+ vm -> dollar_quote = st_init_strtable(); | |
+ | |
rb_define_global_function("load", rb_f_load, -1); | |
rb_define_global_function("require", rb_f_require, 1); | |
@@ -808,4 +849,5 @@ | |
ruby_dln_librefs = rb_ary_new(); | |
rb_gc_register_mark_object(ruby_dln_librefs); | |
-} | |
\ No newline at end of file | |
+ | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment